Vanara/PInvoke/NTDSApi/DsParse.cs

567 lines
30 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class NTDSApi
{
/// <summary>
/// <para>
/// The <c>DS_MANGLE_FOR</c> enumeration is used to define whether a relative distinguished name is mangled (encoded) and in what
/// form the mangling occurs.
/// </para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/ne-dsparse-_ds_mangle_for typedef enum _DS_MANGLE_FOR {
// DS_MANGLE_UNKNOWN , DS_MANGLE_OBJECT_RDN_FOR_DELETION , DS_MANGLE_OBJECT_RDN_FOR_NAME_CONFLICT } DS_MANGLE_FOR;
[PInvokeData("dsparse.h", MSDNShortId = "79a66a54-889e-464e-8199-ad911ea84a86")]
public enum DS_MANGLE_FOR
{
/// <summary>Indicates that the relative distinguished name is not mangled or that the type of mangling is unknown.</summary>
DS_MANGLE_UNKNOWN,
/// <summary>Indicates that the relative distinguished name has been mangled for deletion.</summary>
DS_MANGLE_OBJECT_RDN_FOR_DELETION,
/// <summary>Indicates that the relative distinguished name has been mangled due to a naming conflict.</summary>
DS_MANGLE_OBJECT_RDN_FOR_NAME_CONFLICT,
}
/// <summary>
/// <para>The <c>DsCrackSpn</c> function parses a service principal name (SPN) into its component strings.</para>
/// </summary>
/// <param name="pszSpn">
/// <para>
/// Pointer to a constant null-terminated string that contains the SPN to parse. The SPN has the following format, in which the
/// &lt;service class&gt; and &lt;instance name&gt; components must be present and the &lt;port number&gt; and &lt;service name&gt;
/// components are optional. The &lt;port number&gt; component must be a numeric string value.
/// </para>
/// </param>
/// <param name="pcServiceClass">
/// <para>
/// Pointer to a <c>DWORD</c> value that, on entry, contains the size, in <c>TCHARs</c>, of the ServiceClass buffer, including the
/// terminating null character. On exit, this parameter contains the number of <c>TCHARs</c> in the ServiceClass string, including
/// the terminating null character.
/// </para>
/// <para>If this parameter is <c>NULL</c>, contains zero, or ServiceClass is <c>NULL</c>, this parameter and ServiceClass are ignored.</para>
/// <para>
/// To obtain the number of characters required for the ServiceClass string, including the null terminator, call this function with a
/// valid SPN, a non- <c>NULL</c> ServiceClass and this parameter set to 1.
/// </para>
/// </param>
/// <param name="ServiceClass">
/// <para>
/// Pointer to a <c>TCHAR</c> buffer that receives a null-terminated string containing the &lt;service class&gt; component of the
/// SPN. This buffer must be at least *pcServiceClass <c>TCHARs</c> in size. This parameter may be <c>NULL</c> if the service class
/// is not required.
/// </para>
/// </param>
/// <param name="pcServiceName">
/// <para>
/// Pointer to a <c>DWORD</c> value that, on entry, contains the size, in <c>TCHARs</c>, of the ServiceName buffer, including the
/// terminating null character. On exit, this parameter contains the number of <c>TCHARs</c> in the ServiceName string, including the
/// terminating null character.
/// </para>
/// <para>If this parameter is <c>NULL</c>, contains zero, or ServiceName is <c>NULL</c>, this parameter and ServiceName are ignored.</para>
/// <para>
/// To obtain the number of characters required for the ServiceName string, including the null terminator, call this function with a
/// valid SPN, a non- <c>NULL</c> ServiceName and this parameter set to 1.
/// </para>
/// </param>
/// <param name="ServiceName">
/// <para>
/// Pointer to a <c>TCHAR</c> buffer that receives a null-terminated string containing the &lt;service name&gt; component of the SPN.
/// This buffer must be at least *pcServiceName <c>TCHARs</c> in size. If the &lt;service name&gt; component is not present in the
/// SPN, this buffer receives the &lt;instance name&gt; component. This parameter may be <c>NULL</c> if the service name is not required.
/// </para>
/// </param>
/// <param name="pcInstanceName">
/// <para>
/// Pointer to a <c>DWORD</c> value that, on entry, contains the size, in <c>TCHARs</c>, of the InstanceName buffer, including the
/// terminating null character. On exit, this parameter contains the number of <c>TCHARs</c> in the InstanceName string, including
/// the terminating null character.
/// </para>
/// <para>If this parameter is <c>NULL</c>, contains zero, or InstanceName is <c>NULL</c>, this parameter and InstanceName are ignored.</para>
/// <para>
/// To obtain the number of characters required for the InstanceName string, including the null terminator, call this function with a
/// valid SPN, a non- <c>NULL</c> InstanceName and this parameter set to 1.
/// </para>
/// </param>
/// <param name="InstanceName">
/// <para>
/// Pointer to a <c>TCHAR</c> buffer that receives a null-terminated string containing the &lt;instance name&gt; component of the
/// SPN. This buffer must be at least *pcInstanceName <c>TCHARs</c> in size. This parameter may be <c>NULL</c> if the instance name
/// is not required.
/// </para>
/// </param>
/// <param name="pInstancePort">
/// <para>
/// Pointer to a <c>DWORD</c> value that receives the integer value of the &lt;port number&gt; component of the SPN. If the SPN does
/// not contain a &lt;port number&gt; component, this parameter receives zero. This parameter may be <c>NULL</c> if the port number
/// is not required.
/// </para>
/// </param>
/// <returns>
/// <para>Returns a Win32 error code, including the following.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/nf-dsparse-dscrackspna DSPARSE DWORD DsCrackSpnA( LPCSTR pszSpn,
// LPDWORD pcServiceClass, LPSTR ServiceClass, LPDWORD pcServiceName, LPSTR ServiceName, LPDWORD pcInstanceName, LPSTR InstanceName,
// USHORT *pInstancePort );
[DllImport(Lib.NTDSApi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsparse.h", MSDNShortId = "65c81c23-a259-480c-9c1e-03484d3e89c9")]
public static extern Win32Error DsCrackSpn(string pszSpn, ref uint pcServiceClass, StringBuilder ServiceClass, ref uint pcServiceName, StringBuilder ServiceName, ref uint pcInstanceName,
StringBuilder InstanceName, out ushort pInstancePort);
/// <summary>
/// <para>
/// The <c>DsCrackUnquotedMangledRdn</c> function unmangles (unencodes) a given relative distinguished name and returns both the
/// decoded GUID and the mangling type used.
/// </para>
/// </summary>
/// <param name="pszRDN">
/// <para>
/// Pointer to a string that contains the relative distinguished name (RDN) to translate. This string length is specified by the
/// cchRDN parameter, so this string is not required to be null-terminated. This string must be in unquoted form. For more
/// information about unquoted relative distinguished names, see DsUnquoteRdnValue.
/// </para>
/// </param>
/// <param name="cchRDN">
/// <para>Contains the length, in characters, of the pszRDN string.</para>
/// </param>
/// <param name="pGuid">
/// <para>
/// Pointer to <c>GUID</c> value that receives the GUID of the unmangled relative distinguished name. This parameter can be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="peDsMangleFor">
/// <para>
/// Pointer to a DS_MANGLE_FOR value that receives the type of mangling used in the mangled relative distinguished name. This
/// parameter can be <c>NULL</c>.
/// </para>
/// </param>
/// <returns>
/// <para>
/// This function returns <c>TRUE</c> if the relative distinguished name is mangled or <c>FALSE</c> otherwise. If this function
/// returns <c>FALSE</c>, neither pGuid or peDsMangleFor receive any data.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// This function attempts to decode (unmangle) an RDN that has been previously mangled due to a deletion or a naming conflict. If
/// the relative distinguished name is mangled, the function returns <c>TRUE</c> and retrieves the GUID and mangle type, if
/// requested. If the relative distinguished name is not mangled, the function returns <c>FALSE</c>.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/nf-dsparse-dscrackunquotedmangledrdna DSPARSE BOOL
// DsCrackUnquotedMangledRdnA( LPCSTR pszRDN, DWORD cchRDN, GUID *pGuid, DS_MANGLE_FOR *peDsMangleFor );
[DllImport(Lib.NTDSApi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsparse.h", MSDNShortId = "30711d2d-f541-46b4-a301-a0f9fc7d6676")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DsCrackUnquotedMangledRdn(string pszRDN, uint cchRDN, out Guid pGuid, out DS_MANGLE_FOR peDsMangleFor);
/// <summary>
/// <para>
/// The <c>DsGetRdnW</c> function retrieves the key and value of the first relative distinguished name and a pointer to the next
/// relative distinguished name from a distinguished name string.
/// </para>
/// </summary>
/// <param name="ppDN">
/// <para>
/// Address of a Unicode string pointer that, on entry, contains the distinguished name string to be parsed. The length of this
/// string is specified in the pcDN parameter. If the function succeeds, this parameter is adjusted to point to the remainder of the
/// distinguished name exclusive of current relative distinguished name. For example, if this parameter points to the string
/// "dc=corp,dc=fabrikam,dc=com", after the function is complete this parameter points to the string ",dc=fabrikam,dc=com".
/// </para>
/// </param>
/// <param name="pcDN">
/// <para>
/// Pointer to a <c>DWORD</c> value that, on entry, contains the number of characters in the ppDN string. If the function succeeds,
/// this parameter receives the number of characters in the remainder of the distinguished name. These values do not include the
/// null-terminated character.
/// </para>
/// </param>
/// <param name="ppKey">
/// <para>
/// Pointer to a <c>LPCWCH</c> value that, if the function succeeds, receives a pointer to the key in the relative distinguished name
/// string. This pointer is within the ppDN string and is not null-terminated. The pcKey parameter receives the number of characters
/// in the key. This parameter is undefined if pcKey receives zero.
/// </para>
/// </param>
/// <param name="pcKey">
/// <para>
/// Pointer to a <c>DWORD</c> value that, if the function succeeds, receives the number of characters in the key string represented
/// by the ppKey parameter. If this parameter receives zero, ppKey is undefined.
/// </para>
/// </param>
/// <param name="ppVal">
/// <para>
/// Pointer to a <c>LPCWCH</c> value that, if the function is successful, receives a pointer to the value in the relative
/// distinguished name string. This pointer is within the ppDN string and is not null-terminated. The pcVal parameter receives the
/// number of characters in the value. This parameter is undefined if pcVal receives zero.
/// </para>
/// </param>
/// <param name="pcVal">
/// <para>
/// Pointer to a <c>DWORD</c> value that, if the function succeeds, receives the number of characters in the value string represented
/// by the ppVal parameter. If this parameter receives zero, ppVal is undefined.
/// </para>
/// </param>
/// <returns>
/// <para>
/// Returns <c>ERROR_SUCCESS</c> if successful or a Win32 error code otherwise. Possible error codes include the following values.
/// </para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/nf-dsparse-dsgetrdnw DSPARSE DWORD DsGetRdnW( LPCWCH *ppDN, DWORD
// *pcDN, LPCWCH *ppKey, DWORD *pcKey, LPCWCH *ppVal, DWORD *pcVal );
[DllImport(Lib.NTDSApi, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)]
[PInvokeData("dsparse.h", MSDNShortId = "22627f2e-adfb-49de-bae5-20aaf69830ac")]
public static extern Win32Error DsGetRdnW(ref IntPtr ppDN, ref uint pcDN, ref IntPtr ppKey, out uint pcKey, ref IntPtr ppVal, out uint pcVal);
/// <summary>
/// The <c>DsGetRdnW</c> function retrieves the key and value of the first relative distinguished name and a pointer to the next
/// relative distinguished name from a distinguished name string.
/// </summary>
/// <param name="fullDN">Address of a string that contains the distinguished name string to be parsed.</param>
/// <param name="dn">A string that recieves the remainder of the distinguished name exclusive of current relative distinguished name.</param>
/// <param name="key">A string that, if the function succeeds, receives the key in the relative distinguished name string.</param>
/// <param name="val">A string that, if the function is successful, receives the value in the relative distinguished name string.</param>
/// <returns>Returns <c>ERROR_SUCCESS</c> if successful or a Win32 error code otherwise.</returns>
[PInvokeData("dsparse.h", MSDNShortId = "22627f2e-adfb-49de-bae5-20aaf69830ac")]
public static Win32Error DsGetRdnW(string fullDN, out string dn, out string key, out string val)
{
var s = new SafeCoTaskMemString(fullDN, CharSet.Unicode);
IntPtr ppDN = s.DangerousGetHandle(), ppKey = IntPtr.Zero, ppVal = IntPtr.Zero;
var cDN = (uint)fullDN.Length;
var ret = DsGetRdnW(ref ppDN, ref cDN, ref ppKey, out var cKey, ref ppVal, out var cVal);
if (ret != 0)
{
dn = key = val = null;
}
else
{
dn = StringHelper.GetString(ppDN, (int)cDN, CharSet.Unicode);
key = StringHelper.GetString(ppKey, (int)cKey, CharSet.Unicode);
val = StringHelper.GetString(ppVal, (int)cVal, CharSet.Unicode);
}
return ret;
}
/// <summary>
/// <para>
/// The <c>DsIsMangledDn</c> function determines if the first relative distinguished name (RDN) in a distinguished name (DN) is a
/// mangled name of a given type.
/// </para>
/// </summary>
/// <param name="pszDn">
/// <para>
/// Pointer to a null-terminated string that contains the distinguished name to retrieve the relative distinguished name from. This
/// can also be a quoted distinguished name as returned by other directory service functions.
/// </para>
/// </param>
/// <param name="eDsMangleFor">
/// <para>Contains one of the DS_MANGLE_FOR values that specifies the type of name mangling to look for.</para>
/// </param>
/// <returns>
/// <para>
/// Returns <c>TRUE</c> if the first relative distinguished name in pszDn is mangled in the manner specified by eDsMangleFor or
/// <c>FALSE</c> otherwise.
/// </para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/nf-dsparse-dsismangleddna DSPARSE BOOL DsIsMangledDnA( LPCSTR pszDn,
// DS_MANGLE_FOR eDsMangleFor );
[DllImport(Lib.NTDSApi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsparse.h", MSDNShortId = "e4aaa83c-3bd6-48db-9d34-367b76ba629c")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DsIsMangledDn(string pszDn, DS_MANGLE_FOR eDsMangleFor);
/// <summary>
/// <para>
/// The <c>DsIsMangledRdnValue</c> function determines if a given relative distinguished name value is a mangled name of the given type.
/// </para>
/// </summary>
/// <param name="pszRdn">
/// <para>
/// Pointer to a null-terminated string that contains the relative distinguished name to determine if it is mangled. The cRdn
/// parameter contains the number of characters in this string.
/// </para>
/// </param>
/// <param name="cRdn">
/// <para>Contains the number of characters in the pszRdn string.</para>
/// </param>
/// <param name="eDsMangleForDesired">
/// <para>Contains one of the DS_MANGLE_FOR values that specifies the type of name mangling to search for.</para>
/// </param>
/// <returns>
/// <para>
/// Returns <c>TRUE</c> if the relative distinguished name is mangled and the mangle type is the same as specified. Returns
/// <c>FALSE</c> if the relative distinguished name is not mangled or the mangle type is different than specified.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// This function determines if the given relative distinguished name value is mangled and mangled in the given type. The pszRdn
/// parameter should only contain the value of the relative distinguished name and not the key. The relative distinguished name value
/// may be quoted or unquoted.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/nf-dsparse-dsismangledrdnvaluea DSPARSE BOOL DsIsMangledRdnValueA(
// LPCSTR pszRdn, DWORD cRdn, DS_MANGLE_FOR eDsMangleForDesired );
[DllImport(Lib.NTDSApi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsparse.h", MSDNShortId = "adf5e133-9e48-4e97-af0c-4f8ea9b8bf8f")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DsIsMangledRdnValue(string pszRdn, uint cRdn, DS_MANGLE_FOR eDsMangleForDesired);
/// <summary>
/// <para>The <c>DsMakeSpn</c> function constructs a service principal name (SPN) that identifies a service instance.</para>
/// <para>
/// A client application uses this function to compose an SPN, which it uses to authenticate the service instance. For example, the
/// client can pass an SPN in the pszTargetName parameter of the InitializeSecurityContext function.
/// </para>
/// </summary>
/// <param name="ServiceClass">
/// <para>
/// Pointer to a constant null-terminated string that specifies the class of the service. This parameter can be any string unique to
/// that service; either the protocol name, for example, ldap, or the string form of a GUID are acceptable.
/// </para>
/// </param>
/// <param name="ServiceName">
/// <para>
/// Pointer to a constant null-terminated string that specifies the DNS name, NetBIOS name, or distinguished name (DN). This
/// parameter must be non- <c>NULL</c>.
/// </para>
/// <para>
/// For more information about how the ServiceName, InstanceName and InstancePort parameters are used to compose an SPN, see the
/// following Remarks section.
/// </para>
/// </param>
/// <param name="InstanceName">
/// <para>
/// Pointer to a constant null-terminated string that specifies the DNS name or IP address of the host for an instance of the service.
/// </para>
/// <para>If ServiceName specifies the DNS or NetBIOS name of the service host computer, the InstanceName parameter must be <c>NULL</c>.</para>
/// <para>
/// If ServiceName specifies a DNS domain name, the name of a DNS SRV record, or a distinguished name, such as the DN of a service
/// connection point, the InstanceName parameter must specify the DNS or NetBIOS name of the service host computer.
/// </para>
/// </param>
/// <param name="InstancePort">
/// <para>
/// Port number for an instance of the service. Use 0 for the default port. If this parameter is zero, the SPN does not include a
/// port number.
/// </para>
/// </param>
/// <param name="Referrer">
/// <para>
/// Pointer to a constant null-terminated string that specifies the DNS name of the host that gave an IP address referral. This
/// parameter is ignored unless the ServiceName parameter specifies an IP address.
/// </para>
/// </param>
/// <param name="pcSpnLength">
/// <para>
/// Pointer to a variable that contains the length, in characters, of the buffer that will receive the new constructed SPN. This
/// value may be 0 to request the final buffer size in advance.
/// </para>
/// <para>The pcSpnLength parameter also receives the actual length of the SPN created, including the terminating null character.</para>
/// </param>
/// <param name="pszSpn">
/// <para>
/// Pointer to a null-terminated string that receives the constructed SPN. This buffer should be the length specified by pcSpnLength.
/// The pszSpn parameter may be <c>NULL</c> to request the final buffer size in advance.
/// </para>
/// </param>
/// <returns>
/// <para>
/// If the function returns an SPN, the return value is <c>ERROR_SUCCESS</c>. If the function fails, the return value can be one of
/// the following error codes.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// The format of the SPN produced by the <c>DsMakeSpn</c> function depends on the input parameters. There are two basic formats.
/// Both formats begin with the ServiceClass string followed by a host computer name and an optional InstancePort component.
/// </para>
/// <para><c>Note</c> This format is used by host-based services.</para>
/// <para><c>To produce an SPN with the "&lt;ServiceClass&gt;/&lt;host&gt;" format</c></para>
/// <list type="number">
/// <item>
/// <term>
/// Set the ServiceName parameter to the DNS name of the host computer for the service instance. This is the host component of the SPN.
/// </term>
/// </item>
/// <item>
/// <term>Set the InstanceName and Referrer parameters to <c>NULL</c>.</term>
/// </item>
/// <item>
/// <term>Set the InstancePort parameter to zero. If InstancePort is nonzero, the SPN has the following format:</term>
/// </item>
/// </list>
/// <para><c>Note</c> This format is used by replicable services.</para>
/// <para><c>To produce an SPN with the "&lt;ServiceClass&gt;/&lt;host&gt;:&lt;InstancePort&gt;" format</c></para>
/// <list type="number">
/// <item>
/// <term>Set the InstanceName parameter to the DNS name of the host computer for the service instance. This is the host component.</term>
/// </item>
/// <item>
/// <term>
/// Set the ServiceName parameter to a string that identifies an instance of the service. For example, it could be the distinguished
/// name of the service connection point for this service instance.
/// </term>
/// </item>
/// <item>
/// <term>Set the Referrer parameter to <c>NULL</c>.</term>
/// </item>
/// <item>
/// <term>Set the InstancePort parameter to zero. If InstancePort is nonzero, the SPN has the following format:</term>
/// </item>
/// </list>
/// <para>
/// The Referrer parameter is used only if the ServiceName parameter specifies the IP address of the service's host computer. In this
/// case, Referrer specifies the DNS name of the computer that gave the IP address as a referral. The SPN has the following format:
/// </para>
/// <para>
/// where the host component is the InstanceName string or the ServiceName string if InstanceName is <c>NULL</c>, and the
/// InstancePort component is optional.
/// </para>
/// <para>String parameters cannot include the forward slash (/) character, as it is used to separate the components of the SPN.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/nf-dsparse-dsmakespnw DSPARSE DWORD DsMakeSpnW( LPCWSTR ServiceClass,
// LPCWSTR ServiceName, LPCWSTR InstanceName, USHORT InstancePort, LPCWSTR Referrer, DWORD *pcSpnLength, LPWSTR pszSpn );
[DllImport(Lib.NTDSApi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsparse.h", MSDNShortId = "fca3c59c-bb81-42a0-acd3-2e55c902febe")]
public static extern Win32Error DsMakeSpn(string ServiceClass, string ServiceName, string InstanceName, ushort InstancePort, string Referrer, ref uint pcSpnLength, StringBuilder pszSpn);
/// <summary>
/// <para>
/// The <c>DsQuoteRdnValue</c> function converts an RDN into a quoted RDN value, if the RDN value contains characters that require
/// quotes. The quoted RDN can then be submitted as part of a distinguished name (DN) to the directory service using various APIs
/// such as LDAP. An example of an RDN that would require quotes would be one that has a comma-separated value, such as an RDN for a
/// name that uses the format "last,first".
/// </para>
/// </summary>
/// <param name="cUnquotedRdnValueLength">
/// <para>The number of characters in the psUnquotedRdnValue string.</para>
/// </param>
/// <param name="psUnquotedRdnValue">
/// <para>The string that specifies the unquoted RDN value.</para>
/// </param>
/// <param name="pcQuotedRdnValueLength">
/// <para>The maximum number of characters in the psQuotedRdnValue string.</para>
/// <para>The following flags are the output for this parameter.</para>
/// <para>ERROR_SUCCESS</para>
/// <para>Indicates that the correct number of characters were found in psQuotedRdnValue.</para>
/// <para>ERROR_BUFFER_OVERFLOW</para>
/// <para>Indicates that the number of characters in the string do not match psQuotedRdnValue.</para>
/// </param>
/// <param name="psQuotedRdnValue">
/// <para>The string that receives the converted, and perhaps quoted, RDN value.</para>
/// </param>
/// <returns>
/// <para>The following list contains the possible values returned for the <c>DsQuoteRdnValue</c> function.</para>
/// </returns>
/// <remarks>
/// <para>
/// Quotes are not added to the RDN if none are required. In this case, the output RDN value is the same as the input RDN value.
/// </para>
/// <para>
/// When quoting is required, the RDN is quoted in accordance with the specification "Lightweight Directory Access Protocol (v3):
/// UTF-8 String Representation of Distinguished Names," RFC 2253.
/// </para>
/// <para>The input and output RDN values are not <c>NULL</c>-terminated strings.</para>
/// <para>To revert changes made by this call, call the DsUnquoteRdnValue function.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/nf-dsparse-dsquoterdnvaluea DSPARSE DWORD DsQuoteRdnValueA( DWORD
// cUnquotedRdnValueLength, IN LPCCH psUnquotedRdnValue, DWORD *pcQuotedRdnValueLength, LPCH psQuotedRdnValue );
[DllImport(Lib.NTDSApi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsparse.h", MSDNShortId = "a1e8a4c0-965a-4061-aab3-3e719ec6374d")]
public static extern Win32Error DsQuoteRdnValue(uint cUnquotedRdnValueLength, string psUnquotedRdnValue, ref uint pcQuotedRdnValueLength, StringBuilder psQuotedRdnValue);
/// <summary>
/// <para>
/// The <c>DsUnquoteRdnValue</c> function is a client call that converts a quoted RDN value back to an unquoted RDN value. Because
/// the RDN was originally put into quotes because it contained characters that could be misinterpreted when it was embedded within a
/// distinguished name (DN), the unquoted RDN value should not be submitted as part of a DN to the directory service using various
/// APIs such as LDAP.
/// </para>
/// </summary>
/// <param name="cQuotedRdnValueLength">
/// <para>The number of characters in the psQuotedRdnValue string.</para>
/// </param>
/// <param name="psQuotedRdnValue">
/// <para>The RDN value that may be quoted and escaped.</para>
/// </param>
/// <param name="pcUnquotedRdnValueLength">
/// <para>The input value for this argument is the maximum length, in characters, of psQuotedRdnValue.</para>
/// <para>The output value for this argument includes the following flags.</para>
/// <para>ERROR_SUCCESS</para>
/// <para>This is returned if the number of characters match the string used in psQuotedRdnValue.</para>
/// <para>ERROR_BUFFER_OVERFLOW</para>
/// <para>This is returned if the number of characters do not match the string used in psQuotedRdnValue.</para>
/// </param>
/// <param name="psUnquotedRdnValue">
/// <para>The converted, unquoted RDN value.</para>
/// </param>
/// <returns>
/// <para>The following list contains the possible values that are returned for the <c>DsUnquoteRdnValue</c> function.</para>
/// </returns>
/// <remarks>
/// <para>When psQuotedRdnValue is quoted:</para>
/// <list type="bullet">
/// <item>
/// <term>The leading and trailing quotes are removed.</term>
/// </item>
/// <item>
/// <term>White space before the first quote is discarded.</term>
/// </item>
/// <item>
/// <term>White space trailing the last quote is discarded.</term>
/// </item>
/// <item>
/// <term>Escapes are removed and the character following the escape is kept.</term>
/// </item>
/// </list>
/// <para>The following actions are taken when psQuotedRdnValue is unquoted:</para>
/// <list type="bullet">
/// <item>
/// <term>The leading white space is discarded.</term>
/// </item>
/// <item>
/// <term>The trailing white space is kept.</term>
/// </item>
/// <item>
/// <term>Escaped non-special characters return an error.</term>
/// </item>
/// <item>
/// <term>Unescaped special characters return an error.</term>
/// </item>
/// <item>
/// <term>
/// RDN values beginning with # (ignoring leading white space) are handled as a BER value that has previously been converted to a
/// string, and converted accordingly.
/// </term>
/// </item>
/// <item>
/// <term>Escaped hex digits (\89) are converted into a binary byte (0x89).</term>
/// </item>
/// <item>
/// <term>Escapes are removed from escaped special characters.</term>
/// </item>
/// </list>
/// <para>The following actions are always taken:</para>
/// <list type="bullet">
/// <item>
/// <term>Escaped special characters are unescaped.</term>
/// </item>
/// <item>
/// <term>The input and output RDN values are not null-terminated values.</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/dsparse/nf-dsparse-dsunquoterdnvaluea DSPARSE DWORD DsUnquoteRdnValueA( DWORD
// cQuotedRdnValueLength, LPCCH psQuotedRdnValue, DWORD *pcUnquotedRdnValueLength, LPCH psUnquotedRdnValue );
[DllImport(Lib.NTDSApi, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("dsparse.h", MSDNShortId = "6e3dd220-ba98-46b5-8522-93cbe2029aa4")]
public static extern Win32Error DsUnquoteRdnValue(uint cQuotedRdnValueLength, string psQuotedRdnValue, ref uint pcUnquotedRdnValueLength, StringBuilder psUnquotedRdnValue);
}
}