1+ using System ;
2+ using System . Runtime . InteropServices ;
3+
4+ namespace MultiFactor . IIS . Adapter . Interop
5+ {
6+ internal static class NativeMethods
7+ {
8+ private const string NTDSAPI = "ntdsapi.dll" ;
9+
10+ [ DllImport ( NTDSAPI , CharSet = CharSet . Auto ) ]
11+ public static extern uint DsBind (
12+ string DomainControllerName , // in, optional
13+ string DnsDomainName , // in, optional
14+ out SafeDsHandle phDS ) ;
15+
16+ [ DllImport ( NTDSAPI , CharSet = CharSet . Auto ) ]
17+ public static extern uint DsCrackNames (
18+ SafeDsHandle hDS ,
19+ DS_NAME_FLAGS flags ,
20+ DS_NAME_FORMAT formatOffered ,
21+ DS_NAME_FORMAT formatDesired ,
22+ uint cNames ,
23+ [ MarshalAs ( UnmanagedType . LPArray , ArraySubType = UnmanagedType . LPTStr , SizeParamIndex = 4 ) ]
24+ string [ ] rpNames ,
25+ out IntPtr ppResult ) ;
26+
27+ [ DllImport ( NTDSAPI , CharSet = CharSet . Auto ) ]
28+ public static extern void DsFreeNameResult ( IntPtr pResult /* DS_NAME_RESULT* */ ) ;
29+
30+ [ DllImport ( NTDSAPI , CharSet = CharSet . Auto ) ]
31+ public static extern uint DsUnBind ( ref IntPtr phDS ) ;
32+
33+ [ StructLayout ( LayoutKind . Sequential , CharSet = CharSet . Auto ) ]
34+ public struct DS_NAME_RESULT
35+ {
36+ public uint cItems ;
37+ internal IntPtr rItems ; // PDS_NAME_RESULT_ITEM
38+ public DS_NAME_RESULT_ITEM [ ] Items
39+ {
40+ get
41+ {
42+ if ( rItems == IntPtr . Zero )
43+ {
44+ return new DS_NAME_RESULT_ITEM [ 0 ] ;
45+ }
46+
47+ var ResultArray = new DS_NAME_RESULT_ITEM [ cItems ] ;
48+ Type strType = typeof ( DS_NAME_RESULT_ITEM ) ;
49+ int stSize = Marshal . SizeOf ( strType ) ;
50+ IntPtr curptr ;
51+
52+ for ( uint i = 0 ; i < cItems ; i ++ )
53+ {
54+ curptr = new IntPtr ( rItems . ToInt64 ( ) + ( i * stSize ) ) ;
55+ ResultArray [ i ] = ( DS_NAME_RESULT_ITEM ) Marshal . PtrToStructure ( curptr , strType ) ;
56+ }
57+ return ResultArray ;
58+ }
59+ }
60+ }
61+
62+ [ StructLayout ( LayoutKind . Sequential , CharSet = CharSet . Auto ) ]
63+ public struct DS_NAME_RESULT_ITEM
64+ {
65+ public DS_NAME_ERROR status ;
66+ public string pDomain ;
67+ public string pName ;
68+ public override string ToString ( )
69+ {
70+ if ( status == DS_NAME_ERROR . DS_NAME_NO_ERROR )
71+ {
72+ return pName ;
73+ }
74+
75+ return null ;
76+ }
77+ }
78+
79+ public enum DS_NAME_ERROR
80+ {
81+ DS_NAME_NO_ERROR = 0 ,
82+ // Generic processing error.
83+ DS_NAME_ERROR_RESOLVING = 1 ,
84+ // Couldn't find the name at all - or perhaps caller doesn't have
85+ // rights to see it.
86+ DS_NAME_ERROR_NOT_FOUND = 2 ,
87+ // Input name mapped to more than one output name.
88+ DS_NAME_ERROR_NOT_UNIQUE = 3 ,
89+ // Input name found, but not the associated output format.
90+ // Can happen if object doesn't have all the required attributes.
91+ DS_NAME_ERROR_NO_MAPPING = 4 ,
92+ // Unable to resolve entire name, but was able to determine which
93+ // domain object resides in. Thus DS_NAME_RESULT_ITEM?.pDomain
94+ // is valid on return.
95+ DS_NAME_ERROR_DOMAIN_ONLY = 5 ,
96+ // Unable to perform a purely syntactical mapping at the client
97+ // without going out on the wire.
98+ DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 6 ,
99+ // The name is from an external trusted forest.
100+ DS_NAME_ERROR_TRUST_REFERRAL = 7
101+ }
102+
103+ [ Flags ]
104+ public enum DS_NAME_FLAGS
105+ {
106+ DS_NAME_NO_FLAGS = 0x0 ,
107+ // Perform a syntactical mapping at the client (if possible) without
108+ // going out on the wire. Returns DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING
109+ // if a purely syntactical mapping is not possible.
110+ DS_NAME_FLAG_SYNTACTICAL_ONLY = 0x1 ,
111+ // Force a trip to the DC for evaluation, even if this could be
112+ // locally cracked syntactically.
113+ DS_NAME_FLAG_EVAL_AT_DC = 0x2 ,
114+ // The call fails if the DC is not a GC
115+ DS_NAME_FLAG_GCVERIFY = 0x4 ,
116+ // Enable cross forest trust referral
117+ DS_NAME_FLAG_TRUST_REFERRAL = 0x8
118+ }
119+
120+ public enum DS_NAME_FORMAT
121+ {
122+ // unknown name type
123+ DS_UNKNOWN_NAME = 0 ,
124+ // eg: CN=User Name,OU=Users,DC=Example,DC=Microsoft,DC=Com
125+ DS_FQDN_1779_NAME = 1 ,
126+ // eg: Example\UserN
127+ // Domain-only version includes trailing '\\'.
128+ DS_NT4_ACCOUNT_NAME = 2 ,
129+ // Probably "User Name" but could be something else. I.e. The
130+ // display name is not necessarily the defining RDN.
131+ DS_DISPLAY_NAME = 3 ,
132+ // obsolete - see #define later
133+ // DS_DOMAIN_SIMPLE_NAME = 4,
134+ // obsolete - see #define later
135+ // DS_ENTERPRISE_SIMPLE_NAME = 5,
136+ // String-ized GUID as returned by IIDFromString().
137+ // eg: {4fa050f0-f561-11cf-bdd9-00aa003a77b6}
138+ DS_UNIQUE_ID_NAME = 6 ,
139+ // eg: example.microsoft.com/software/user name
140+ // Domain-only version includes trailing '/'.
141+ DS_CANONICAL_NAME = 7 ,
142+ // eg: usern@example.microsoft.com
143+ DS_USER_PRINCIPAL_NAME = 8 ,
144+ // Same as DS_CANONICAL_NAME except that rightmost '/' is
145+ // replaced with '\n' - even in domain-only case.
146+ // eg: example.microsoft.com/software\nuser name
147+ DS_CANONICAL_NAME_EX = 9 ,
148+ // eg: www/www.microsoft.com@example.com - generalized service principal
149+ // names.
150+ DS_SERVICE_PRINCIPAL_NAME = 10 ,
151+ // This is the string representation of a SID. Invalid for formatDesired.
152+ // See sddl.h for SID binary <--> text conversion routines.
153+ // eg: S-1-5-21-397955417-626881126-188441444-501
154+ DS_SID_OR_SID_HISTORY_NAME = 11 ,
155+ // Pseudo-name format so GetUserNameEx can return the DNS domain name to
156+ // a caller. This level is not supported by the DS APIs.
157+ DS_DNS_DOMAIN_NAME = 12
158+ }
159+ }
160+ }
0 commit comments