namespace Vanara.PInvoke;
public static partial class NTDSApi
{
///
///
/// The DS_MANGLE_FOR enumeration is used to define whether a relative distinguished name is mangled (encoded) and in what
/// form the mangling occurs.
///
///
// 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
{
/// Indicates that the relative distinguished name is not mangled or that the type of mangling is unknown.
DS_MANGLE_UNKNOWN,
/// Indicates that the relative distinguished name has been mangled for deletion.
DS_MANGLE_OBJECT_RDN_FOR_DELETION,
/// Indicates that the relative distinguished name has been mangled due to a naming conflict.
DS_MANGLE_OBJECT_RDN_FOR_NAME_CONFLICT,
}
///
/// The DsCrackSpn function parses a service principal name (SPN) into its component strings.
///
///
///
/// Pointer to a constant null-terminated string that contains the SPN to parse. The SPN has the following format, in which the
/// <service class> and <instance name> components must be present and the <port number> and <service name>
/// components are optional. The <port number> component must be a numeric string value.
///
///
///
///
/// Pointer to a DWORD value that, on entry, contains the size, in TCHARs, of the ServiceClass buffer, including the
/// terminating null character. On exit, this parameter contains the number of TCHARs in the ServiceClass string, including
/// the terminating null character.
///
/// If this parameter is NULL, contains zero, or ServiceClass is NULL, this parameter and ServiceClass are ignored.
///
/// To obtain the number of characters required for the ServiceClass string, including the null terminator, call this function with a
/// valid SPN, a non- NULL ServiceClass and this parameter set to 1.
///
///
///
///
/// Pointer to a TCHAR buffer that receives a null-terminated string containing the <service class> component of the
/// SPN. This buffer must be at least *pcServiceClass TCHARs in size. This parameter may be NULL if the service class
/// is not required.
///
///
///
///
/// Pointer to a DWORD value that, on entry, contains the size, in TCHARs, of the ServiceName buffer, including the
/// terminating null character. On exit, this parameter contains the number of TCHARs in the ServiceName string, including the
/// terminating null character.
///
/// If this parameter is NULL, contains zero, or ServiceName is NULL, this parameter and ServiceName are ignored.
///
/// To obtain the number of characters required for the ServiceName string, including the null terminator, call this function with a
/// valid SPN, a non- NULL ServiceName and this parameter set to 1.
///
///
///
///
/// Pointer to a TCHAR buffer that receives a null-terminated string containing the <service name> component of the SPN.
/// This buffer must be at least *pcServiceName TCHARs in size. If the <service name> component is not present in the
/// SPN, this buffer receives the <instance name> component. This parameter may be NULL if the service name is not required.
///
///
///
///
/// Pointer to a DWORD value that, on entry, contains the size, in TCHARs, of the InstanceName buffer, including the
/// terminating null character. On exit, this parameter contains the number of TCHARs in the InstanceName string, including
/// the terminating null character.
///
/// If this parameter is NULL, contains zero, or InstanceName is NULL, this parameter and InstanceName are ignored.
///
/// To obtain the number of characters required for the InstanceName string, including the null terminator, call this function with a
/// valid SPN, a non- NULL InstanceName and this parameter set to 1.
///
///
///
///
/// Pointer to a TCHAR buffer that receives a null-terminated string containing the <instance name> component of the
/// SPN. This buffer must be at least *pcInstanceName TCHARs in size. This parameter may be NULL if the instance name
/// is not required.
///
///
///
///
/// Pointer to a DWORD value that receives the integer value of the <port number> component of the SPN. If the SPN does
/// not contain a <port number> component, this parameter receives zero. This parameter may be NULL if the port number
/// is not required.
///
///
///
/// Returns a Win32 error code, including the following.
///
// 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,
[Optional] StringBuilder? ServiceName, ref uint pcInstanceName, [Optional] StringBuilder? InstanceName, out ushort pInstancePort);
///
///
/// The DsCrackUnquotedMangledRdn function unmangles (unencodes) a given relative distinguished name and returns both the
/// decoded GUID and the mangling type used.
///
///
///
///
/// 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.
///
///
///
/// Contains the length, in characters, of the pszRDN string.
///
///
///
/// Pointer to GUID value that receives the GUID of the unmangled relative distinguished name. This parameter can be NULL.
///
///
///
///
/// Pointer to a DS_MANGLE_FOR value that receives the type of mangling used in the mangled relative distinguished name. This
/// parameter can be NULL.
///
///
///
///
/// This function returns TRUE if the relative distinguished name is mangled or FALSE otherwise. If this function
/// returns FALSE, neither pGuid or peDsMangleFor receive any data.
///
///
///
///
/// 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 TRUE and retrieves the GUID and mangle type, if
/// requested. If the relative distinguished name is not mangled, the function returns FALSE.
///
///
// 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);
///
///
/// The DsGetRdnW 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.
///
///
///
///
/// 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".
///
///
///
///
/// Pointer to a DWORD 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.
///
///
///
///
/// Pointer to a LPCWCH 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.
///
///
///
///
/// Pointer to a DWORD 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.
///
///
///
///
/// Pointer to a LPCWCH 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.
///
///
///
///
/// Pointer to a DWORD 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.
///
///
///
///
/// Returns ERROR_SUCCESS if successful or a Win32 error code otherwise. Possible error codes include the following values.
///
///
// 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);
///
/// The DsGetRdnW 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.
///
/// Address of a string that contains the distinguished name string to be parsed.
/// A string that recieves the remainder of the distinguished name exclusive of current relative distinguished name.
/// A string that, if the function succeeds, receives the key in the relative distinguished name string.
/// A string that, if the function is successful, receives the value in the relative distinguished name string.
/// Returns ERROR_SUCCESS if successful or a Win32 error code otherwise.
[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;
}
///
///
/// The DsIsMangledDn function determines if the first relative distinguished name (RDN) in a distinguished name (DN) is a
/// mangled name of a given type.
///
///
///
///
/// 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.
///
///
///
/// Contains one of the DS_MANGLE_FOR values that specifies the type of name mangling to look for.
///
///
///
/// Returns TRUE if the first relative distinguished name in pszDn is mangled in the manner specified by eDsMangleFor or
/// FALSE otherwise.
///
///
// 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);
///
///
/// The DsIsMangledRdnValue function determines if a given relative distinguished name value is a mangled name of the given type.
///
///
///
///
/// 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.
///
///
///
/// Contains the number of characters in the pszRdn string.
///
///
/// Contains one of the DS_MANGLE_FOR values that specifies the type of name mangling to search for.
///
///
///
/// Returns TRUE if the relative distinguished name is mangled and the mangle type is the same as specified. Returns
/// FALSE if the relative distinguished name is not mangled or the mangle type is different than specified.
///
///
///
///
/// 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.
///
///
// 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);
///
/// The DsMakeSpn function constructs a service principal name (SPN) that identifies a service instance.
///
/// 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.
///
///
///
///
/// 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.
///
///
///
///
/// Pointer to a constant null-terminated string that specifies the DNS name, NetBIOS name, or distinguished name (DN). This
/// parameter must be non- NULL.
///
///
/// For more information about how the ServiceName, InstanceName and InstancePort parameters are used to compose an SPN, see the
/// following Remarks section.
///
///
///
///
/// Pointer to a constant null-terminated string that specifies the DNS name or IP address of the host for an instance of the service.
///
/// If ServiceName specifies the DNS or NetBIOS name of the service host computer, the InstanceName parameter must be NULL.
///
/// 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.
///
///
///
///
/// 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.
///
///
///
///
/// 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.
///
///
///
///
/// 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.
///
/// The pcSpnLength parameter also receives the actual length of the SPN created, including the terminating null character.
///
///
///
/// 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 NULL to request the final buffer size in advance.
///
///
///
///
/// If the function returns an SPN, the return value is ERROR_SUCCESS. If the function fails, the return value can be one of
/// the following error codes.
///
///
///
///
/// The format of the SPN produced by the DsMakeSpn 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.
///
/// Note This format is used by host-based services.
/// To produce an SPN with the "<ServiceClass>/<host>" format
///
/// -
///
/// Set the ServiceName parameter to the DNS name of the host computer for the service instance. This is the host component of the SPN.
///
///
/// -
/// Set the InstanceName and Referrer parameters to NULL.
///
/// -
/// Set the InstancePort parameter to zero. If InstancePort is nonzero, the SPN has the following format:
///
///
/// Note This format is used by replicable services.
/// To produce an SPN with the "<ServiceClass>/<host>:<InstancePort>" format
///
/// -
/// Set the InstanceName parameter to the DNS name of the host computer for the service instance. This is the host component.
///
/// -
///
/// 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.
///
///
/// -
/// Set the Referrer parameter to NULL.
///
/// -
/// Set the InstancePort parameter to zero. If InstancePort is nonzero, the SPN has the following format:
///
///
///
/// 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:
///
///
/// where the host component is the InstanceName string or the ServiceName string if InstanceName is NULL, and the
/// InstancePort component is optional.
///
/// String parameters cannot include the forward slash (/) character, as it is used to separate the components of the SPN.
///
// 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, [Optional] string? InstanceName, ushort InstancePort, [Optional] string? Referrer, ref uint pcSpnLength, [Optional] StringBuilder? pszSpn);
///
///
/// The DsQuoteRdnValue 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".
///
///
///
/// The number of characters in the psUnquotedRdnValue string.
///
///
/// The string that specifies the unquoted RDN value.
///
///
/// The maximum number of characters in the psQuotedRdnValue string.
/// The following flags are the output for this parameter.
/// ERROR_SUCCESS
/// Indicates that the correct number of characters were found in psQuotedRdnValue.
/// ERROR_BUFFER_OVERFLOW
/// Indicates that the number of characters in the string do not match psQuotedRdnValue.
///
///
/// The string that receives the converted, and perhaps quoted, RDN value.
///
///
/// The following list contains the possible values returned for the DsQuoteRdnValue function.
///
///
///
/// 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.
///
///
/// 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.
///
/// The input and output RDN values are not NULL-terminated strings.
/// To revert changes made by this call, call the DsUnquoteRdnValue function.
///
// 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);
///
///
/// The DsUnquoteRdnValue 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.
///
///
///
/// The number of characters in the psQuotedRdnValue string.
///
///
/// The RDN value that may be quoted and escaped.
///
///
/// The input value for this argument is the maximum length, in characters, of psQuotedRdnValue.
/// The output value for this argument includes the following flags.
/// ERROR_SUCCESS
/// This is returned if the number of characters match the string used in psQuotedRdnValue.
/// ERROR_BUFFER_OVERFLOW
/// This is returned if the number of characters do not match the string used in psQuotedRdnValue.
///
///
/// The converted, unquoted RDN value.
///
///
/// The following list contains the possible values that are returned for the DsUnquoteRdnValue function.
///
///
/// When psQuotedRdnValue is quoted:
///
/// -
/// The leading and trailing quotes are removed.
///
/// -
/// White space before the first quote is discarded.
///
/// -
/// White space trailing the last quote is discarded.
///
/// -
/// Escapes are removed and the character following the escape is kept.
///
///
/// The following actions are taken when psQuotedRdnValue is unquoted:
///
/// -
/// The leading white space is discarded.
///
/// -
/// The trailing white space is kept.
///
/// -
/// Escaped non-special characters return an error.
///
/// -
/// Unescaped special characters return an error.
///
/// -
///
/// 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.
///
///
/// -
/// Escaped hex digits (\89) are converted into a binary byte (0x89).
///
/// -
/// Escapes are removed from escaped special characters.
///
///
/// The following actions are always taken:
///
/// -
/// Escaped special characters are unescaped.
///
/// -
/// The input and output RDN values are not null-terminated values.
///
///
///
// 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);
}