Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3047 lines
78 KiB

  1. /*
  2. File adsi.cpp
  3. Com interaction with adsi
  4. Paul Mayfield, 4/14/98
  5. */
  6. #include "dsrights.h"
  7. #include "sddl.h"
  8. #include "mprapip.h"
  9. #include "dsgetdc.h"
  10. // Definition for convenience
  11. //
  12. #define DSR_ADS_RIGHT_GENERIC_READ (ADS_RIGHT_READ_CONTROL | \
  13. ADS_RIGHT_DS_LIST_OBJECT | \
  14. ADS_RIGHT_DS_READ_PROP | \
  15. ADS_RIGHT_ACTRL_DS_LIST )
  16. #define DSR_ADS_ACE_INHERITED (ADS_ACEFLAG_INHERIT_ONLY_ACE | \
  17. ADS_ACEFLAG_INHERIT_ACE)
  18. #define DSR_ADS_FLAG_ALL (ADS_FLAG_OBJECT_TYPE_PRESENT | \
  19. ADS_FLAG_INHERITED_OBJECT_TYPE_PRESENT)
  20. #define MPRFLAG_DOMAIN_ALL (MPRFLAG_DOMAIN_NT4_SERVERS | \
  21. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)
  22. //
  23. // Describes an Access control entry
  24. //
  25. typedef struct _DSR_ACE_DESCRIPTOR
  26. {
  27. LONG dwAccessMask;
  28. LONG dwAceType;
  29. LONG dwAceFlags;
  30. LONG dwFlags;
  31. BSTR bstrTrustee;
  32. BSTR bstrObjectType;
  33. BSTR bstrInheritedObjectType;
  34. DWORD dwMode;
  35. } DSR_ACE_DESCRIPTOR;
  36. //
  37. // Structure maps a domain object to the ACES that should be
  38. // added or removed from it in order to enable/disable legacy
  39. // ras servers in the domain
  40. //
  41. typedef struct _DSR_ACE_APPLICATION
  42. {
  43. IADs* pObject;
  44. DWORD dwCount;
  45. DSR_ACE_DESCRIPTOR* pAces;
  46. } DSR_ACE_APPLICATION;
  47. //
  48. // Parameters used to generate a DSR_ACE_APPLICATION
  49. //
  50. typedef struct _DSR_ACE_APPLICATION_DESC
  51. {
  52. PWCHAR pszObjectCN; // NULL means domain root
  53. PWCHAR pszObjectClass;
  54. DWORD dwCount;
  55. DSR_ACE_DESCRIPTOR* pAces;
  56. } DSR_ACE_APPLICATION_DESC;
  57. //
  58. // Structure contains the information needed to have
  59. // ACL's in the AD of a given domain adjusted such that
  60. // the various modes (MPR_DOMAIN_*) of access are granted.
  61. //
  62. typedef struct _DSR_DOMAIN_ACCESS_INFO
  63. {
  64. // The name of a DC in the target domain
  65. //
  66. PWCHAR pszDC;
  67. // Aces
  68. //
  69. DSR_ACE_APPLICATION* pAces;
  70. DWORD dwAceCount;
  71. // Stored here for convenience, pointers
  72. // to common ds objects
  73. //
  74. IADs* pDomain;
  75. IADs* pRootDse;
  76. } DSR_DOMAIN_ACCESS_INFO;
  77. //
  78. // Strings used in DS queries
  79. //
  80. static const WCHAR pszLdapPrefix[] = L"LDAP://";
  81. static const WCHAR pszLdap[] = L"LDAP:";
  82. static const WCHAR pszCN[] = L"CN=";
  83. static const WCHAR pszGCPrefix[] = L"GC://";
  84. static const WCHAR pszGC[] = L"GC:";
  85. static const WCHAR pszRootDse[] = L"RootDSE";
  86. static const WCHAR pszSecurityDesc[] = L"ntSecurityDescriptor";
  87. static const WCHAR pszDn[] = L"distinguishedName";
  88. static const WCHAR pszSid[] = L"objectSid";
  89. static const WCHAR pszEveryone[] = L"S-1-1-0";
  90. static const WCHAR pszDefaultNamingContext[] = L"defaultNamingContext";
  91. static const WCHAR pszSystemClass[] = L"Container";
  92. static const WCHAR pszSystemCN[] = L"CN=System";
  93. static const WCHAR pszBuiltinClass[] = L"builtinDomain";
  94. static const WCHAR pszBuiltinCN[] = L"CN=Builtin";
  95. static const WCHAR pszSamSvrClass[] = L"samServer";
  96. static const WCHAR pszSamSvrCN[] = L"CN=Server,CN=System";
  97. static const WCHAR pszAccessChkClass[] = L"Container";
  98. static const WCHAR pszAccessChkCN[] =
  99. L"CN=RAS and IAS Servers Access Check,CN=System";
  100. static const WCHAR pszGuidUserParms[] =
  101. L"{BF967A6D-0DE6-11D0-A285-00AA003049E2}";
  102. static const WCHAR pszGuidUserClass[] =
  103. L"{BF967ABA-0DE6-11D0-A285-00aa003049E2}";
  104. //
  105. // This GUID is the property set of the following
  106. // attributes needed for w2k level access.
  107. //
  108. // Token-Groups
  109. // msNPAllowDialin
  110. // msNPCallingStationID
  111. // msRADIUSCallbackNumber
  112. // msRADIUSFramedIPAddress
  113. // msRADIUSFramedRoute
  114. // msRADIUSServiceType
  115. //
  116. static const WCHAR pszGuidRasPropSet1[] =
  117. L"{037088F8-0AE1-11D2-B422-00A0C968F939}";
  118. //
  119. // This GUID is the property set of the following
  120. // attributes needed for w2k level access
  121. //
  122. // User-Account-Control
  123. // Account-Expires
  124. //
  125. static const WCHAR pszGuidRasPropSet2[] =
  126. L"{4C164200-20C0-11D0-A768-00AA006E0529}";
  127. //
  128. // This GUID is the property of the following
  129. // attribute needed for w2k level access
  130. //
  131. // Logon-Hours
  132. //
  133. static const WCHAR pszGuidLogonHours[] =
  134. L"{BF9679AB-0DE6-11D0-A285-00AA003049E2}";
  135. //
  136. // This GUID is the value of the samAccountName
  137. // attribute needed for w2k level access.
  138. //
  139. // samAccountName
  140. //
  141. static const WCHAR pszGuidSamAccountName[] =
  142. L"{3E0ABFD0-126A-11D0-A060-00AA006C33ED}";
  143. // The optimal means for searching for a computer
  144. // in a domain is to lookup its sam account name which
  145. // is indexed. The optimal means for searching for a
  146. // group of a given sid is to lookup its SID which is indexed.
  147. //
  148. const WCHAR pszCompFilterFmt[] = L"(samaccountname=%s$)";
  149. const WCHAR pszGroupFilterFmt[] = L"(objectSid=%s)";
  150. const WCHAR pszUserClassFmt[] =
  151. L"(&(objectClass=user)(!(objectClass=computer)))";
  152. //
  153. // Aces to be added to the domain root
  154. //
  155. DSR_ACE_DESCRIPTOR g_pAcesRoot[] =
  156. {
  157. // Grant list options to everyone for the root domain
  158. // object (needed for nt4 servers in this domain)
  159. //
  160. {
  161. ADS_RIGHT_ACTRL_DS_LIST, // dwAccessMask
  162. ADS_ACETYPE_ACCESS_ALLOWED, // dwAceType
  163. 0, // dwAceFlags
  164. 0, // dwFlags
  165. (PWCHAR)pszEveryone, // bstrTrustee
  166. NULL, // bstrObjectType
  167. NULL, // bstrInheritedObjectType
  168. MPRFLAG_DOMAIN_ALL // mode
  169. },
  170. // Allow everyone to read the userparms property enabling
  171. // this inheritable ACE to the root domain object
  172. // (needed for nt4 servers in this domain)
  173. {
  174. ADS_RIGHT_DS_READ_PROP, // dwAccessMask
  175. ADS_ACETYPE_ACCESS_ALLOWED_OBJECT,// dwAceType
  176. DSR_ADS_ACE_INHERITED, // dwAceFlags
  177. DSR_ADS_FLAG_ALL, // dwFlags
  178. (PWCHAR)pszEveryone, // bstrTrustee
  179. (PWCHAR)pszGuidUserParms, // bstrObjectType
  180. (PWCHAR)pszGuidUserClass, // bstrInheritedObjectType
  181. MPRFLAG_DOMAIN_ALL // mode
  182. },
  183. // All users should expose their RAS properties
  184. //
  185. {
  186. ADS_RIGHT_DS_READ_PROP, // dwAccessMask
  187. ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, // dwAceType
  188. DSR_ADS_ACE_INHERITED, // dwAceFlags
  189. DSR_ADS_FLAG_ALL, // dwFlags
  190. (PWCHAR)pszEveryone, // bstrTrustee
  191. (PWCHAR)pszGuidRasPropSet1, // bstrObjectType
  192. (PWCHAR)pszGuidUserClass, // bstrInheritedObjectType
  193. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS // mode
  194. },
  195. // All users should expose their RAS properties
  196. //
  197. {
  198. ADS_RIGHT_DS_READ_PROP, // dwAccessMask
  199. ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, // dwAceType
  200. DSR_ADS_ACE_INHERITED, // dwAceFlags
  201. DSR_ADS_FLAG_ALL, // dwFlags
  202. (PWCHAR)pszEveryone, // bstrTrustee
  203. (PWCHAR)pszGuidRasPropSet2, // bstrObjectType
  204. (PWCHAR)pszGuidUserClass, // bstrInheritedObjectType
  205. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS // mode
  206. },
  207. // All users should expose their logon hours property
  208. //
  209. {
  210. ADS_RIGHT_DS_READ_PROP, // dwAccessMask
  211. ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, // dwAceType
  212. DSR_ADS_ACE_INHERITED, // dwAceFlags
  213. DSR_ADS_FLAG_ALL, // dwFlags
  214. (PWCHAR)pszEveryone, // bstrTrustee
  215. (PWCHAR)pszGuidLogonHours, // bstrObjectType
  216. (PWCHAR)pszGuidUserClass, // bstrInheritedObjectType
  217. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS // mode
  218. },
  219. // All users should expose their samAccountName
  220. //
  221. {
  222. ADS_RIGHT_DS_READ_PROP, // dwAccessMask
  223. ADS_ACETYPE_ACCESS_ALLOWED_OBJECT, // dwAceType
  224. DSR_ADS_ACE_INHERITED, // dwAceFlags
  225. DSR_ADS_FLAG_ALL, // dwFlags
  226. (PWCHAR)pszEveryone, // bstrTrustee
  227. (PWCHAR)pszGuidSamAccountName, // bstrObjectType
  228. (PWCHAR)pszGuidUserClass, // bstrInheritedObjectType
  229. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS // mode
  230. }
  231. };
  232. //
  233. // Aces to be added to the builtin class
  234. //
  235. DSR_ACE_DESCRIPTOR g_pAcesBuiltin[] =
  236. {
  237. {
  238. ADS_RIGHT_ACTRL_DS_LIST, // dwAccessMask
  239. ADS_ACETYPE_ACCESS_ALLOWED, // dwAceType
  240. 0, // dwAceFlags
  241. 0, // dwFlags
  242. (PWCHAR)pszEveryone, // bstrTrustee
  243. NULL, // bstrObjectType
  244. NULL, // bstrInheritedObjectType
  245. MPRFLAG_DOMAIN_ALL // mode
  246. }
  247. };
  248. //
  249. // Aces to be added to the sam server object
  250. //
  251. DSR_ACE_DESCRIPTOR g_pAcesSamSvr[] =
  252. {
  253. {
  254. DSR_ADS_RIGHT_GENERIC_READ, // dwAccessMask
  255. ADS_ACETYPE_ACCESS_ALLOWED, // dwAceType
  256. 0, // dwAceFlags
  257. 0, // dwFlags
  258. (PWCHAR)pszEveryone, // bstrTrustee
  259. NULL, // bstrObjectType
  260. NULL, // bstrInheritedObjectType
  261. MPRFLAG_DOMAIN_ALL // mode
  262. }
  263. };
  264. //
  265. // Aces to be added to the system container
  266. //
  267. DSR_ACE_DESCRIPTOR g_pAcesSystem[] =
  268. {
  269. {
  270. ADS_RIGHT_ACTRL_DS_LIST, // dwAccessMask
  271. ADS_ACETYPE_ACCESS_ALLOWED, // dwAceType
  272. 0, // dwAceFlags
  273. 0, // dwFlags
  274. (PWCHAR)pszEveryone, // bstrTrustee
  275. NULL, // bstrObjectType
  276. NULL, // bstrInheritedObjectType
  277. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS // mode
  278. }
  279. };
  280. //
  281. // Aces to be added to the ras and ias servers access check obj.
  282. //
  283. DSR_ACE_DESCRIPTOR g_pAcesAccessCheck[] =
  284. {
  285. {
  286. DSR_ADS_RIGHT_GENERIC_READ, // dwAccessMask
  287. ADS_ACETYPE_ACCESS_ALLOWED, // dwAceType
  288. 0, // dwAceFlags
  289. 0, // dwFlags
  290. (PWCHAR)pszEveryone, // bstrTrustee
  291. NULL, // bstrObjectType
  292. NULL, // bstrInheritedObjectType
  293. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS // mode
  294. }
  295. };
  296. //
  297. // The table of aces to be applied
  298. //
  299. DSR_ACE_APPLICATION_DESC g_pAces[] =
  300. {
  301. {
  302. NULL, // Object (NULL = root)
  303. NULL, // Object class
  304. sizeof(g_pAcesRoot) / sizeof(*g_pAcesRoot),
  305. g_pAcesRoot
  306. },
  307. // Grant list contents to everyone for the builtin
  308. //
  309. {
  310. (PWCHAR)pszBuiltinCN, // Object
  311. (PWCHAR)pszBuiltinClass, // Object class
  312. sizeof(g_pAcesBuiltin) / sizeof(*g_pAcesBuiltin),
  313. g_pAcesBuiltin
  314. },
  315. // Grant generic read to everyone on the sam server
  316. // object
  317. //
  318. {
  319. (PWCHAR)pszSamSvrCN, // Object
  320. (PWCHAR)pszSamSvrClass, // Object class
  321. sizeof(g_pAcesSamSvr) / sizeof(*g_pAcesSamSvr),
  322. g_pAcesSamSvr
  323. },
  324. // Grant list contents to Everyone for the System
  325. // container
  326. //
  327. {
  328. (PWCHAR)pszSystemCN, // Object
  329. (PWCHAR)pszSystemClass, // Object class
  330. sizeof(g_pAcesSystem) / sizeof(*g_pAcesSystem),
  331. g_pAcesSystem
  332. },
  333. // Grant generic read to Everyone for the 'RAS and IAS Servers
  334. // Access Check' container
  335. //
  336. {
  337. (PWCHAR)pszAccessChkCN, // Object
  338. (PWCHAR)pszAccessChkClass, // Object class
  339. sizeof(g_pAcesAccessCheck) / sizeof(*g_pAcesAccessCheck),
  340. g_pAcesAccessCheck
  341. }
  342. };
  343. DWORD
  344. DsrAccessInfoCleanup(
  345. IN DSR_DOMAIN_ACCESS_INFO* pSecurityInfo);
  346. DWORD
  347. DsrAceDescClear(
  348. IN DSR_ACE_DESCRIPTOR* pParams);
  349. HRESULT
  350. DsrAceDescCopy(
  351. OUT DSR_ACE_DESCRIPTOR* pDst,
  352. IN DSR_ACE_DESCRIPTOR* pSrc);
  353. VOID
  354. DsrAceDescTrace(
  355. IN IADs* pIads,
  356. IN DSR_ACE_DESCRIPTOR* pA);
  357. HRESULT
  358. DsrAceAdd(
  359. IN PWCHAR pszDC,
  360. IN IADs* pIads,
  361. IN DSR_ACE_DESCRIPTOR * pAceParams);
  362. HRESULT
  363. DsrAceCreate(
  364. IN DSR_ACE_DESCRIPTOR * pAceParams,
  365. OUT IDispatch** ppAce);
  366. HRESULT
  367. DsrAceFind(
  368. IN PWCHAR pszDC,
  369. IN IADs* pObject,
  370. IN DSR_ACE_DESCRIPTOR* pAceParams,
  371. OUT VARIANT* pVarSD,
  372. OUT IADsSecurityDescriptor** ppSD,
  373. OUT IADsAccessControlList** ppAcl,
  374. OUT IDispatch** ppAce);
  375. HRESULT
  376. DsrAceFindInAcl(
  377. IN PWCHAR pszDC,
  378. IN IADsAccessControlList* pAcl,
  379. IN DSR_ACE_DESCRIPTOR* pAceDesc,
  380. OUT IDispatch** ppAce);
  381. HRESULT
  382. DsrAceRemove(
  383. IN PWCHAR pszDC,
  384. IN IADs* pIads,
  385. IN DSR_ACE_DESCRIPTOR * pAceParams);
  386. HRESULT
  387. DsrDomainQueryAccessEx(
  388. IN PWCHAR pszDomain,
  389. OUT LPDWORD lpdwAccessFlags,
  390. OUT DSR_DOMAIN_ACCESS_INFO** ppInfo);
  391. //
  392. // Compares to optional strings
  393. //
  394. INT
  395. DsrStrCompare(
  396. IN BSTR bstrS1,
  397. IN BSTR bstrS2)
  398. {
  399. if ((!!bstrS1) != (!!bstrS2))
  400. {
  401. return -1;
  402. }
  403. if (bstrS1 == NULL)
  404. {
  405. return 0;
  406. }
  407. return lstrcmpi(bstrS1, bstrS2);
  408. }
  409. //
  410. // Converts a SID into a buffer
  411. //
  412. DWORD
  413. DsrStrFromSID(
  414. IN PSID pSid,
  415. OUT PWCHAR pszString,
  416. IN DWORD dwSize)
  417. {
  418. NTSTATUS nStatus = STATUS_SUCCESS;
  419. UNICODE_STRING UnicodeString;
  420. // Initialize the unicode string
  421. //
  422. RtlInitUnicodeString(&UnicodeString, NULL);
  423. do
  424. {
  425. // Convert the string
  426. //
  427. nStatus = RtlConvertSidToUnicodeString(
  428. &UnicodeString,
  429. pSid,
  430. TRUE);
  431. if (! NT_SUCCESS(nStatus))
  432. {
  433. break;
  434. }
  435. // Validate the result
  436. //
  437. if (UnicodeString.Buffer == NULL)
  438. {
  439. nStatus = ERROR_CAN_NOT_COMPLETE;
  440. break;
  441. }
  442. if (UnicodeString.Length > dwSize)
  443. {
  444. nStatus = STATUS_BUFFER_OVERFLOW;
  445. break;
  446. }
  447. // Copy the result
  448. //
  449. wcscpy(pszString, UnicodeString.Buffer);
  450. nStatus = STATUS_SUCCESS;
  451. } while (FALSE);
  452. // Cleanup
  453. {
  454. if (UnicodeString.Buffer != NULL)
  455. {
  456. RtlFreeUnicodeString(&UnicodeString);
  457. }
  458. }
  459. return RtlNtStatusToDosError(nStatus);
  460. }
  461. //
  462. // Generates an LDAP path based on a domain and a
  463. // distinguished name
  464. //
  465. // Form of value returned: LDAP://<domain or dc>/dn
  466. //
  467. HRESULT
  468. DsrDomainGenLdapPath(
  469. IN PWCHAR pszDomain,
  470. IN PWCHAR pszDN,
  471. OUT PWCHAR* ppszObject)
  472. {
  473. DWORD dwSize;
  474. // Calculate the size needed
  475. //
  476. dwSize = (wcslen(pszLdapPrefix) + wcslen(pszDN) + 1) * sizeof(WCHAR);
  477. if (pszDomain)
  478. {
  479. dwSize += (wcslen(pszDomain) + 1) * sizeof(WCHAR); // +1 for '/'
  480. }
  481. // Allocate the return value
  482. //
  483. *ppszObject = (PWCHAR) DsrAlloc(dwSize, FALSE);
  484. if (*ppszObject == NULL)
  485. {
  486. return E_OUTOFMEMORY;
  487. }
  488. // Format the return value
  489. if (pszDomain == NULL)
  490. {
  491. wsprintfW(*ppszObject, L"%s%s", pszLdapPrefix, pszDN);
  492. }
  493. else
  494. {
  495. wsprintfW(*ppszObject, L"%s%s/%s", pszLdapPrefix, pszDomain, pszDN);
  496. }
  497. return S_OK;
  498. }
  499. //
  500. // Returns a reference to rootDse of the given
  501. // domain
  502. //
  503. HRESULT
  504. DsrDomainGetRootDse(
  505. IN PWCHAR pszDomain,
  506. OUT IADs** ppRootDse)
  507. {
  508. HRESULT hr = S_OK;
  509. PWCHAR pszPath = NULL;
  510. DWORD dwSize = 0;
  511. do
  512. {
  513. // Get the object path
  514. //
  515. hr = DsrDomainGenLdapPath(pszDomain, (PWCHAR)pszRootDse, &pszPath);
  516. DSR_BREAK_ON_FAILED_HR(hr);
  517. // Get RootDSE
  518. //
  519. hr = ADsGetObject(pszPath, IID_IADs, (VOID**)ppRootDse);
  520. DSR_BREAK_ON_FAILED_HR( hr );
  521. } while (FALSE);
  522. // Cleanup
  523. {
  524. DSR_FREE(pszPath);
  525. if (FAILED (hr))
  526. {
  527. DSR_RELEASE(*ppRootDse);
  528. }
  529. }
  530. return hr;
  531. }
  532. //
  533. // Returns a reference to the root domain object
  534. //
  535. HRESULT
  536. DsrDomainGetBaseObjects(
  537. IN PWCHAR pszDomain,
  538. OUT IADs** ppRootDse,
  539. OUT IADsContainer** ppDomain)
  540. {
  541. PWCHAR pszDomainObj = NULL;
  542. HRESULT hr = S_OK;
  543. DWORD dwSize = 0;
  544. VARIANT var;
  545. BSTR StringTmp = NULL;
  546. // Iniatialize
  547. //
  548. {
  549. *ppRootDse = NULL;
  550. *ppDomain = NULL;
  551. VariantInit(&var);
  552. }
  553. do
  554. {
  555. // Get RootDSE
  556. //
  557. hr = DsrDomainGetRootDse(pszDomain, ppRootDse);
  558. DSR_BREAK_ON_FAILED_HR(hr);
  559. StringTmp = SysAllocString(pszDefaultNamingContext);
  560. if (!StringTmp)
  561. {
  562. hr = E_OUTOFMEMORY;
  563. break;
  564. }
  565. // Use RootDSE to figure out the name of the domain object
  566. // to query
  567. hr = (*ppRootDse)->Get(StringTmp, &var);
  568. DSR_BREAK_ON_FAILED_HR( hr );
  569. // Compute the distinguished name of the root domain object
  570. //
  571. hr = DsrDomainGenLdapPath(pszDomain, V_BSTR(&var), &pszDomainObj);
  572. DSR_BREAK_ON_FAILED_HR(hr);
  573. // Get the objects
  574. //
  575. hr = ADsGetObject(pszDomainObj, IID_IADsContainer, (VOID**)ppDomain);
  576. DSR_BREAK_ON_FAILED_HR( hr );
  577. } while (FALSE);
  578. // Cleanup
  579. //
  580. {
  581. if (FAILED( hr ))
  582. {
  583. DSR_RELEASE(*ppRootDse);
  584. DSR_RELEASE(*ppDomain);
  585. *ppRootDse = NULL;
  586. *ppDomain = NULL;
  587. }
  588. DSR_FREE(pszDomainObj);
  589. VariantClear(&var);
  590. if (StringTmp)
  591. {
  592. SysFreeString(StringTmp);
  593. }
  594. }
  595. return hr;
  596. }
  597. //
  598. // Initializes COM
  599. //
  600. HRESULT
  601. DsrComIntialize()
  602. {
  603. HRESULT hr;
  604. hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
  605. if (hr == RPC_E_CHANGED_MODE)
  606. {
  607. hr = CoInitializeEx (NULL, COINIT_MULTITHREADED);
  608. }
  609. if ((hr != S_FALSE) && (FAILED(hr)))
  610. {
  611. return hr;
  612. }
  613. return NO_ERROR;
  614. }
  615. //
  616. // Unitializes COM
  617. //
  618. VOID
  619. DsrComUninitialize()
  620. {
  621. CoUninitialize();
  622. }
  623. //
  624. // Creates a SID based on the array of bytes
  625. // stored in a variant.
  626. //
  627. DWORD
  628. DsrSidInit (
  629. IN VARIANT * pVar,
  630. OUT PBYTE* ppbSid)
  631. {
  632. SAFEARRAY * pArray = V_ARRAY(pVar);
  633. DWORD dwSize, dwLow, dwHigh, i;
  634. HRESULT hr;
  635. BYTE* pbRet = NULL;
  636. VARIANT var;
  637. DsrTraceEx (0, "DsrSidInit: entered.");
  638. // Get the array of bytes
  639. i = 0;
  640. hr = SafeArrayGetElement(pArray, (LONG*)&i, (VOID*)&var);
  641. if (FAILED (hr))
  642. return hr;
  643. // Initialize the return buffer accordingly
  644. pArray = V_ARRAY(&var);
  645. dwSize = SafeArrayGetDim(pArray);
  646. hr = SafeArrayGetLBound(pArray, 1, (LONG*)&dwLow);
  647. if (FAILED (hr))
  648. return DsrTraceEx(hr, "DsrSidInit: %x unable to get lbound", hr);
  649. hr = SafeArrayGetUBound(pArray, 1, (LONG*)&dwHigh);
  650. if (FAILED (hr))
  651. return DsrTraceEx(hr, "DsrSidInit: %x unable to get ubound", hr);
  652. DsrTraceEx (
  653. 0,
  654. "DsrSidInit: Dim=%d, Low=%d, High=%d",
  655. dwSize,
  656. dwLow,
  657. dwHigh);
  658. // Allocate the sid
  659. if ((pbRet = (BYTE*)DsrAlloc((dwHigh - dwLow) + 2, TRUE)) == NULL) {
  660. return DsrTraceEx (
  661. ERROR_NOT_ENOUGH_MEMORY,
  662. "DsrSidInit: Unable to alloc");
  663. }
  664. // Copy in the bytes of the SID
  665. i = dwLow;
  666. while (TRUE) {
  667. hr = SafeArrayGetElement(pArray, (LONG*)&i, (VOID*)(&(pbRet[i])));
  668. if (FAILED (hr))
  669. break;
  670. i++;
  671. }
  672. DsrTraceEx(0, "DsrSidInit: copied %d bytes", i);
  673. *ppbSid = pbRet;
  674. {
  675. PUCHAR puSA;
  676. DsrTraceEx (0, "DsrSidInit: Sid Length: %d", GetLengthSid(pbRet));
  677. puSA = GetSidSubAuthorityCount(pbRet);
  678. if (puSA)
  679. DsrTraceEx (0, "DsrSidInit: Sid SA Count: %d", *puSA);
  680. }
  681. return NO_ERROR;
  682. }
  683. //
  684. // Generates the ascii equivalent (suitable for submission as part of
  685. // a query against the DS) of a SID based on a base SID and a sub authority
  686. // to be appeneded.
  687. //
  688. HRESULT
  689. DsrSidInitAscii(
  690. IN LPBYTE pBaseSid,
  691. IN DWORD dwSubAuthority,
  692. OUT PWCHAR* ppszSid)
  693. {
  694. DWORD dwLen, dwSidLen, i;
  695. WCHAR* pszRet = NULL;
  696. PUCHAR puCount;
  697. LPBYTE pByte;
  698. // Calculate the length of the returned buffer
  699. dwSidLen = GetLengthSid(pBaseSid);
  700. dwLen = (dwSidLen * 2) + sizeof(DWORD) + 1;
  701. dwLen *= sizeof (WCHAR);
  702. // we put '\' before each byte, so double the size
  703. dwLen *= 2;
  704. // Allocate the return buffer
  705. pszRet = (PWCHAR) DsrAlloc(dwLen, TRUE);
  706. if (pszRet == NULL)
  707. return E_OUTOFMEMORY;
  708. // Increment the sub authority count
  709. puCount = GetSidSubAuthorityCount(pBaseSid);
  710. *puCount = *puCount + 1;
  711. // Copy the bytes
  712. for (i = 0; i < dwSidLen; i++) {
  713. pszRet[i*3] = L'\\';
  714. wsprintfW(&(pszRet[i*3+1]), L"%02x", (DWORD)pBaseSid[i]);
  715. }
  716. // Append the bytes for the new sub authority
  717. pByte = (LPBYTE)&(dwSubAuthority);
  718. for (; i < dwSidLen + sizeof(DWORD); i++) {
  719. pszRet[i*3] = L'\\';
  720. wsprintfW(&(pszRet[i*3+1]), L"%02x", (DWORD)pByte[i-dwSidLen]);
  721. }
  722. // Decrement the sub authority count -- restoring the
  723. // base sid.
  724. *puCount = *puCount - 1;
  725. *ppszSid = pszRet;
  726. return NO_ERROR;
  727. }
  728. //
  729. // Searches given domain for a computer account
  730. // with the given name and returns its ADsPath
  731. // if found.
  732. //
  733. DWORD
  734. DsrFindDomainComputer (
  735. IN PWCHAR pszDomain,
  736. IN PWCHAR pszComputer,
  737. OUT PWCHAR* ppszADsPath)
  738. {
  739. HRESULT hr = S_OK;
  740. DWORD dwLen, dwSrchAttribCount;
  741. IDirectorySearch * pSearch = NULL;
  742. PWCHAR pszDomainPath = NULL, pszFilter = NULL;
  743. PWCHAR pszBase, pszPrefix;
  744. ADS_SEARCH_HANDLE hSearch = NULL;
  745. ADS_SEARCH_COLUMN adsColumn;
  746. PWCHAR ppszSrchAttribs[] =
  747. {
  748. (PWCHAR)pszDn,
  749. NULL
  750. };
  751. BOOL bSearchGC = FALSE;
  752. do {
  753. // Validate parameters
  754. if (!pszDomain || !pszComputer || !ppszADsPath) {
  755. hr = ERROR_INVALID_PARAMETER;
  756. break;
  757. }
  758. // Decide whether to search the GC or the domain
  759. // object
  760. if (bSearchGC) {
  761. pszBase = (PWCHAR)pszGC;
  762. pszPrefix = (PWCHAR)pszGCPrefix;
  763. }
  764. else {
  765. pszBase = (PWCHAR)pszLdap;
  766. pszPrefix = (PWCHAR)pszLdapPrefix;
  767. }
  768. // Allocate the domain path
  769. dwLen = (pszDomain) ? wcslen(pszDomain) : 0;
  770. dwLen += wcslen(pszPrefix) + 1;
  771. dwLen *= sizeof(WCHAR);
  772. pszDomainPath = (PWCHAR) DsrAlloc(dwLen, FALSE);
  773. if (pszDomainPath == NULL) {
  774. hr = ERROR_NOT_ENOUGH_MEMORY;
  775. break;
  776. }
  777. // Format the domain path
  778. if (pszDomain) {
  779. wcscpy(pszDomainPath, pszPrefix);
  780. wcscat(pszDomainPath, pszDomain);
  781. }
  782. else
  783. wcscpy(pszDomainPath, pszBase);
  784. // Get a reference to the object to search
  785. // (either domain object or GC)
  786. hr = ADsGetObject (
  787. pszDomainPath,
  788. IID_IDirectorySearch,
  789. (VOID**)&pSearch);
  790. if (FAILED (hr))
  791. break;
  792. // Prepare the search filter
  793. //
  794. dwLen = wcslen(pszCompFilterFmt) + wcslen(pszComputer) + 1;
  795. dwLen *= sizeof(WCHAR);
  796. pszFilter = (PWCHAR) DsrAlloc(dwLen, FALSE);
  797. if (pszFilter == NULL) {
  798. hr = ERROR_NOT_ENOUGH_MEMORY;
  799. break;
  800. }
  801. wsprintfW(pszFilter, pszCompFilterFmt, pszComputer);
  802. // Count the number of attributes we're searching
  803. // for
  804. if (ppszSrchAttribs == NULL)
  805. dwSrchAttribCount = (DWORD)-1;
  806. else {
  807. for (dwSrchAttribCount = 0;
  808. ppszSrchAttribs[dwSrchAttribCount];
  809. dwSrchAttribCount++);
  810. }
  811. // Search the DS
  812. hr = pSearch->ExecuteSearch(
  813. pszFilter,
  814. ppszSrchAttribs,
  815. dwSrchAttribCount,
  816. &hSearch);
  817. if (FAILED (hr))
  818. break;
  819. // Get the first result
  820. hr = pSearch->GetNextRow(hSearch);
  821. if (hr == S_ADS_NOMORE_ROWS) {
  822. hr = ERROR_NOT_FOUND;
  823. break;
  824. }
  825. // Get the attribute we're interested in
  826. hr = pSearch->GetColumn(hSearch, (PWCHAR)pszDn, &adsColumn);
  827. if (SUCCEEDED (hr)) {
  828. dwLen = wcslen(adsColumn.pADsValues[0].PrintableString) +
  829. wcslen(pszLdapPrefix) +
  830. 1;
  831. dwLen *= 2;
  832. *ppszADsPath = (PWCHAR) DsrAlloc(dwLen, FALSE);
  833. if (*ppszADsPath == NULL)
  834. {
  835. pSearch->FreeColumn(&adsColumn);
  836. hr = ERROR_NOT_ENOUGH_MEMORY;
  837. break;
  838. }
  839. wcscpy(*ppszADsPath, pszLdapPrefix);
  840. wcscat(*ppszADsPath, adsColumn.pADsValues[0].PrintableString);
  841. pSearch->FreeColumn (&adsColumn);
  842. hr = NO_ERROR;
  843. }
  844. } while (FALSE);
  845. // Cleanup
  846. {
  847. if (hSearch)
  848. pSearch->CloseSearchHandle(hSearch);
  849. DSR_FREE (pszDomainPath);
  850. DSR_FREE (pszFilter);
  851. DSR_RELEASE (pSearch);
  852. }
  853. return DSR_ERROR(hr);
  854. }
  855. //
  856. // Searches given domain for the well known
  857. // "RAS and IAS Servers" group and returns
  858. // its ADsPath if found.
  859. //
  860. DWORD
  861. DsrFindRasServersGroup (
  862. IN PWCHAR pszDomain,
  863. OUT PWCHAR* ppszADsPath)
  864. {
  865. HRESULT hr = S_OK;
  866. DWORD dwLen, dwSrchAttribCount, dwErr;
  867. IDirectorySearch * pSearch = NULL;
  868. IADs * pIads = NULL;
  869. PWCHAR pszDomainPath = NULL, pszFilter = NULL;
  870. PWCHAR pszBase, pszPrefix, pszGroupSid = NULL;
  871. ADS_SEARCH_HANDLE hSearch = NULL;
  872. ADS_SEARCH_COLUMN adsColumn;
  873. PWCHAR ppszSrchAttribs[] =
  874. {
  875. (PWCHAR)pszDn,
  876. NULL
  877. };
  878. BOOL bSearchGC = FALSE;
  879. VARIANT var;
  880. LPBYTE pDomainSid = NULL;
  881. BSTR bstrSid = NULL;
  882. do {
  883. // Validate parameters
  884. if (!pszDomain || !ppszADsPath) {
  885. hr = ERROR_INVALID_PARAMETER;
  886. break;
  887. }
  888. // Decide whether to search the GC or the domain
  889. // object
  890. if (bSearchGC) {
  891. pszBase = (PWCHAR)pszGC;
  892. pszPrefix = (PWCHAR)pszGCPrefix;
  893. }
  894. else {
  895. pszBase = (PWCHAR)pszLdap;
  896. pszPrefix = (PWCHAR)pszLdapPrefix;
  897. }
  898. // Allocate the domain path
  899. dwLen = wcslen(pszDomain) + wcslen(pszPrefix) + 1;
  900. dwLen *= sizeof(WCHAR);
  901. pszDomainPath = (PWCHAR) DsrAlloc(dwLen, FALSE);
  902. if (pszDomainPath == NULL) {
  903. hr = ERROR_NOT_ENOUGH_MEMORY;
  904. break;
  905. }
  906. // Format the domain path
  907. wcscpy(pszDomainPath, pszPrefix);
  908. wcscat(pszDomainPath, pszDomain);
  909. // Get a reference to the object to search
  910. // (either domain object or GC)
  911. hr = ADsGetObject (
  912. pszDomainPath,
  913. IID_IDirectorySearch,
  914. (VOID**)&pSearch);
  915. if (FAILED (hr))
  916. break;
  917. // Get IADs reference to domain object
  918. hr = pSearch->QueryInterface(IID_IADs, (VOID**)&pIads);
  919. if (FAILED (hr))
  920. break;
  921. // Get the SID of the domain object
  922. VariantInit(&var);
  923. bstrSid = SysAllocString(pszSid);
  924. if (bstrSid == NULL)
  925. {
  926. hr = ERROR_NOT_ENOUGH_MEMORY;
  927. break;
  928. }
  929. hr = pIads->GetEx(bstrSid, &var);
  930. if (FAILED (hr))
  931. {
  932. break;
  933. }
  934. dwErr = DsrSidInit(&var, &pDomainSid);
  935. if (dwErr != NO_ERROR) {
  936. hr = dwErr;
  937. break;
  938. }
  939. VariantClear(&var);
  940. // Prepare the ascii version of the "RAS and IAS Servers" SID
  941. // for use in querying the DC
  942. hr = DsrSidInitAscii(
  943. pDomainSid,
  944. DOMAIN_ALIAS_RID_RAS_SERVERS,
  945. &pszGroupSid);
  946. if (FAILED (hr))
  947. break;
  948. DsrTraceEx(0, "GroupSid = %ls", pszGroupSid);
  949. // Prepare the search filter
  950. //
  951. dwLen = (wcslen(pszGroupFilterFmt) + wcslen(pszGroupSid) + 1);
  952. dwLen *= sizeof(WCHAR);
  953. pszFilter = (PWCHAR) DsrAlloc(dwLen, FALSE);
  954. if (pszFilter == NULL) {
  955. hr = ERROR_NOT_ENOUGH_MEMORY;
  956. break;
  957. }
  958. wsprintfW(pszFilter, pszGroupFilterFmt, pszGroupSid);
  959. // Count the number of attributes we're searching
  960. // for
  961. if (ppszSrchAttribs == NULL)
  962. dwSrchAttribCount = (DWORD)-1;
  963. else
  964. {
  965. for (dwSrchAttribCount = 0;
  966. ppszSrchAttribs[dwSrchAttribCount];
  967. dwSrchAttribCount++);
  968. }
  969. // Search the DS
  970. hr = pSearch->ExecuteSearch(
  971. pszFilter,
  972. ppszSrchAttribs,
  973. dwSrchAttribCount,
  974. &hSearch);
  975. if (FAILED (hr))
  976. break;
  977. // Get the first result
  978. hr = pSearch->GetNextRow(hSearch);
  979. if (hr == S_ADS_NOMORE_ROWS) {
  980. hr = ERROR_NOT_FOUND;
  981. break;
  982. }
  983. // Get the attribute we're interested in
  984. hr = pSearch->GetColumn(hSearch, (PWCHAR)pszDn, &adsColumn);
  985. if (SUCCEEDED (hr))
  986. {
  987. dwLen = wcslen(adsColumn.pADsValues[0].PrintableString) +
  988. wcslen(pszLdapPrefix) +
  989. 1;
  990. dwLen *= sizeof(WCHAR);
  991. *ppszADsPath = (PWCHAR) DsrAlloc(dwLen, FALSE);
  992. if (*ppszADsPath == NULL)
  993. {
  994. pSearch->FreeColumn(&adsColumn);
  995. hr = ERROR_NOT_ENOUGH_MEMORY;
  996. break;
  997. }
  998. wsprintfW(
  999. *ppszADsPath,
  1000. L"%s%s",
  1001. pszLdapPrefix,
  1002. adsColumn.pADsValues[0].PrintableString);
  1003. pSearch->FreeColumn(&adsColumn);
  1004. hr = NO_ERROR;
  1005. }
  1006. } while (FALSE);
  1007. // Cleanup
  1008. {
  1009. if (hSearch)
  1010. pSearch->CloseSearchHandle(hSearch);
  1011. DSR_FREE (pszDomainPath);
  1012. DSR_FREE (pszFilter);
  1013. DSR_FREE (pDomainSid);
  1014. DSR_FREE (pszGroupSid);
  1015. DSR_RELEASE (pSearch);
  1016. DSR_RELEASE (pIads);
  1017. if (bstrSid)
  1018. SysFreeString(bstrSid);
  1019. }
  1020. return DSR_ERROR(hr);
  1021. }
  1022. //
  1023. // Adds or removes a given object from a given group.
  1024. //
  1025. DWORD
  1026. DsrGroupAddRemoveMember(
  1027. IN PWCHAR pszGroupDN,
  1028. IN PWCHAR pszNewMemberDN,
  1029. IN BOOL bAdd)
  1030. {
  1031. VARIANT_BOOL vbIsMember = VARIANT_FALSE;
  1032. IADsGroup* pGroup = NULL;
  1033. HRESULT hr = S_OK;
  1034. BSTR StringTmp = NULL;
  1035. DsrTraceEx (
  1036. 0,
  1037. "DsrGroupAddRemoveMember entered for [%S] [%S]",
  1038. pszGroupDN,
  1039. pszNewMemberDN);
  1040. do
  1041. {
  1042. // Get a reference to the group
  1043. hr = ADsGetObject (pszGroupDN, IID_IADsGroup, (VOID**)&pGroup);
  1044. if (FAILED (hr))
  1045. {
  1046. DsrTraceEx(
  1047. hr,
  1048. "DsrGroupAddRemoveMember: %x from ADsGetObject(%S)",
  1049. hr,
  1050. pszGroupDN);
  1051. break;
  1052. }
  1053. StringTmp = SysAllocString(pszNewMemberDN);
  1054. if (!StringTmp)
  1055. {
  1056. hr = E_OUTOFMEMORY;
  1057. break;
  1058. }
  1059. // Find out if the given new member is in the group
  1060. hr = pGroup->IsMember (StringTmp, &vbIsMember);
  1061. if (FAILED (hr))
  1062. {
  1063. DsrTraceEx (
  1064. hr,
  1065. "DsrGroupAddRemoveMember: %x from IsMember\n",
  1066. hr);
  1067. break;
  1068. }
  1069. // Add the object to the group and flush the cache
  1070. if (bAdd)
  1071. {
  1072. if (vbIsMember == VARIANT_FALSE)
  1073. {
  1074. hr = pGroup->Add (StringTmp);
  1075. }
  1076. }
  1077. else
  1078. {
  1079. if (vbIsMember == VARIANT_TRUE)
  1080. {
  1081. hr = pGroup->Remove (StringTmp);
  1082. }
  1083. }
  1084. // If the new member is already in the group, the error code
  1085. // is ERROR_DS_CONSTRAINT_VIOLATION. I suspect this may change.
  1086. //
  1087. if (hr == ERROR_DS_CONSTRAINT_VIOLATION)
  1088. {
  1089. hr = ERROR_ALREADY_EXISTS;
  1090. break;
  1091. }
  1092. if (FAILED (hr))
  1093. {
  1094. DsrTraceEx(
  1095. hr,
  1096. "DsrGroupAddRemoveMember: %x from Add/Remove",
  1097. hr);
  1098. break;
  1099. }
  1100. } while (FALSE);
  1101. // Cleanup
  1102. {
  1103. DSR_RELEASE(pGroup);
  1104. if (StringTmp)
  1105. {
  1106. SysFreeString(StringTmp);
  1107. }
  1108. }
  1109. return DSR_ERROR(hr);
  1110. }
  1111. //
  1112. // Returns whether the given object is a member of
  1113. // the given group.
  1114. //
  1115. DWORD
  1116. DsrGroupIsMember(
  1117. IN PWCHAR pszGroupDN,
  1118. IN PWCHAR pszObjectDN,
  1119. OUT PBOOL pbIsMember)
  1120. {
  1121. IADsGroup * pGroup = NULL;
  1122. HRESULT hr = S_OK;
  1123. VARIANT_BOOL vbIsMember = VARIANT_FALSE;
  1124. BSTR StringTmp = NULL;
  1125. DsrTraceEx (
  1126. 0,
  1127. "DsrGroupIsMember: entered [%S] [%S].",
  1128. pszGroupDN,
  1129. pszObjectDN);
  1130. do
  1131. {
  1132. // Get a reference to the group
  1133. hr = ADsGetObject (pszGroupDN, IID_IADsGroup, (VOID**)&pGroup);
  1134. if (FAILED (hr))
  1135. {
  1136. DsrTraceEx (
  1137. hr,
  1138. "DsrGroupIsMember: %x returned when opening %S",
  1139. hr,
  1140. pszGroupDN);
  1141. *pbIsMember = FALSE;
  1142. hr = NO_ERROR;
  1143. break;
  1144. }
  1145. // Find out if the object is a member
  1146. StringTmp = SysAllocString(pszObjectDN);
  1147. if (!StringTmp)
  1148. {
  1149. hr = E_OUTOFMEMORY;
  1150. break;
  1151. }
  1152. hr = pGroup->IsMember (StringTmp, &vbIsMember);
  1153. if (FAILED (hr))
  1154. {
  1155. DsrTraceEx (hr, "DsrGroupIsMember: %x from IsMember\n", hr);
  1156. break;
  1157. }
  1158. *pbIsMember = (vbIsMember == VARIANT_TRUE) ? TRUE : FALSE;
  1159. } while (FALSE);
  1160. // Cleanup
  1161. {
  1162. DSR_RELEASE(pGroup);
  1163. if (StringTmp)
  1164. {
  1165. SysFreeString(StringTmp);
  1166. }
  1167. }
  1168. return DSR_ERROR(hr);
  1169. }
  1170. //
  1171. // Applies the aces in the given access settings to the
  1172. // appropriate domain.
  1173. //
  1174. HRESULT
  1175. DsrAceAppAdd(
  1176. IN DWORD dwMode,
  1177. IN PWCHAR pszDC,
  1178. IN DSR_ACE_APPLICATION* pAces,
  1179. IN DWORD dwCount)
  1180. {
  1181. HRESULT hr = S_OK;
  1182. DSR_ACE_APPLICATION* pAceApp = NULL;
  1183. DWORD i, j;
  1184. do
  1185. {
  1186. // Add the ACES to the domain objects
  1187. //
  1188. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1189. {
  1190. for (j = 0; j < pAceApp->dwCount; j++)
  1191. {
  1192. if (pAceApp->pAces[j].dwMode != dwMode)
  1193. {
  1194. continue;
  1195. }
  1196. hr = DsrAceAdd(
  1197. pszDC,
  1198. pAceApp->pObject,
  1199. &(pAceApp->pAces[j]));
  1200. DSR_BREAK_ON_FAILED_HR( hr );
  1201. }
  1202. }
  1203. DSR_BREAK_ON_FAILED_HR( hr );
  1204. // Commit the ACE's to the domain objects.
  1205. //
  1206. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1207. {
  1208. hr = pAceApp->pObject->SetInfo();
  1209. DSR_BREAK_ON_FAILED_HR( hr );
  1210. }
  1211. DSR_BREAK_ON_FAILED_HR( hr );
  1212. } while (FALSE);
  1213. // Cleanup
  1214. {
  1215. }
  1216. return hr;
  1217. }
  1218. //
  1219. // Releases the resources held by an ace application
  1220. //
  1221. HRESULT
  1222. DsrAceAppCleanup(
  1223. IN DSR_ACE_APPLICATION* pAces,
  1224. IN DWORD dwCount)
  1225. {
  1226. DSR_ACE_APPLICATION* pAceApp = NULL;
  1227. DWORD i, j;
  1228. if (pAces)
  1229. {
  1230. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1231. {
  1232. DSR_RELEASE(pAceApp->pObject);
  1233. for (j = 0; j < pAceApp->dwCount; j++)
  1234. {
  1235. DsrAceDescClear(&(pAceApp->pAces[j]));
  1236. }
  1237. }
  1238. DSR_FREE(pAces);
  1239. }
  1240. return NO_ERROR;
  1241. }
  1242. //
  1243. // Generates a list of ace applications based on a list
  1244. // of ace application descriptions
  1245. //
  1246. HRESULT
  1247. DsrAceAppFromAppDesc(
  1248. IN DSR_ACE_APPLICATION_DESC* pDesc,
  1249. IN DWORD dwCount,
  1250. IN IADsContainer* pContainer,
  1251. IN IADs* pDefault,
  1252. OUT DSR_ACE_APPLICATION** ppAceApp,
  1253. OUT LPDWORD lpdwCount)
  1254. {
  1255. DSR_ACE_APPLICATION* pAceApp = NULL, *pCurApp = NULL;
  1256. DSR_ACE_APPLICATION_DESC* pAceAppDesc = NULL;
  1257. IDispatch* pDispatch = NULL;
  1258. HRESULT hr = S_OK;
  1259. DWORD i=0, j;
  1260. BSTR StringTmp = NULL;
  1261. BSTR StringTmp1 = NULL;
  1262. do
  1263. {
  1264. // Allocate and zero the ACE list
  1265. //
  1266. pAceApp = (DSR_ACE_APPLICATION*)
  1267. DsrAlloc(sizeof(DSR_ACE_APPLICATION) * dwCount, TRUE);
  1268. if (pAceApp == NULL)
  1269. {
  1270. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  1271. break; //to keep prefast happy
  1272. }
  1273. // Set up the ACE applications
  1274. //
  1275. for (i = 0, pAceAppDesc = pDesc, pCurApp = pAceApp;
  1276. i < dwCount;
  1277. i++, pAceAppDesc++, pCurApp++)
  1278. {
  1279. // Allocate the appropriate number of ace
  1280. // descriptors
  1281. //
  1282. pCurApp->pAces = (DSR_ACE_DESCRIPTOR*)
  1283. DsrAlloc(
  1284. sizeof(DSR_ACE_DESCRIPTOR) * pAceAppDesc->dwCount,
  1285. TRUE);
  1286. if (pCurApp->pAces == NULL)
  1287. {
  1288. hr = E_OUTOFMEMORY;
  1289. break;
  1290. }
  1291. pCurApp->dwCount = pAceAppDesc->dwCount;
  1292. // Get the desired object in the DS
  1293. //
  1294. if (pAceAppDesc->pszObjectCN)
  1295. {
  1296. StringTmp = SysAllocString(pAceAppDesc->pszObjectClass);
  1297. StringTmp1 = SysAllocString(pAceAppDesc->pszObjectCN);
  1298. if (!StringTmp || !StringTmp1)
  1299. {
  1300. hr = E_OUTOFMEMORY;
  1301. break;
  1302. }
  1303. hr = pContainer->GetObject(
  1304. StringTmp,
  1305. StringTmp1,
  1306. &pDispatch);
  1307. DSR_BREAK_ON_FAILED_HR( hr );
  1308. hr = pDispatch->QueryInterface(
  1309. IID_IADs,
  1310. (VOID**)&(pCurApp->pObject));
  1311. DSR_BREAK_ON_FAILED_HR( hr );
  1312. pDispatch->Release();
  1313. pDispatch = NULL;
  1314. }
  1315. else
  1316. {
  1317. pCurApp->pObject = pDefault;
  1318. pCurApp->pObject->AddRef();
  1319. }
  1320. // Copy over the ACE information
  1321. //
  1322. for (j = 0; j < pCurApp->dwCount; j++)
  1323. {
  1324. hr = DsrAceDescCopy(
  1325. &(pCurApp->pAces[j]),
  1326. &(pAceAppDesc->pAces[j]));
  1327. DSR_BREAK_ON_FAILED_HR( hr );
  1328. }
  1329. DSR_BREAK_ON_FAILED_HR( hr );
  1330. }
  1331. DSR_BREAK_ON_FAILED_HR( hr );
  1332. // Assign the return values
  1333. *ppAceApp = pAceApp;
  1334. *lpdwCount = dwCount;
  1335. } while (FALSE);
  1336. // Cleanup
  1337. {
  1338. if (FAILED(hr))
  1339. {
  1340. DsrAceAppCleanup(pAceApp, i);
  1341. }
  1342. if (StringTmp)
  1343. {
  1344. SysFreeString(StringTmp);
  1345. }
  1346. if (StringTmp1)
  1347. {
  1348. SysFreeString(StringTmp1);
  1349. }
  1350. }
  1351. return hr;
  1352. }
  1353. //
  1354. // Discovers whether a set of aces is present in the given
  1355. // domain.
  1356. //
  1357. HRESULT
  1358. DsrAceAppQueryPresence(
  1359. IN PWCHAR pszDC,
  1360. IN DSR_ACE_APPLICATION* pAces,
  1361. IN DWORD dwCount,
  1362. IN DWORD dwMode,
  1363. OUT PBOOL pbPresent)
  1364. {
  1365. DSR_ACE_APPLICATION* pAceApp = NULL;
  1366. IADsSecurityDescriptor* pSD = NULL;
  1367. IADsAccessControlList* pAcl = NULL;
  1368. IDispatch* pAce = NULL;
  1369. VARIANT varSD;
  1370. HRESULT hr = S_OK;
  1371. BOOL bEnabled = FALSE, bOk = TRUE;
  1372. DWORD i, j;
  1373. do
  1374. {
  1375. // Initialize
  1376. *pbPresent = FALSE;
  1377. VariantInit(&varSD);
  1378. // Find out if the ACES are set
  1379. //
  1380. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1381. {
  1382. for (j = 0; j < pAceApp->dwCount; j++)
  1383. {
  1384. // Only validate aces that pertain to the
  1385. // given mode
  1386. //
  1387. if (pAceApp->pAces[j].dwMode != dwMode)
  1388. {
  1389. continue;
  1390. }
  1391. hr = DsrAceFind(
  1392. pszDC,
  1393. pAceApp->pObject,
  1394. &(pAceApp->pAces[j]),
  1395. &varSD,
  1396. &pSD,
  1397. &pAcl,
  1398. &pAce);
  1399. DSR_BREAK_ON_FAILED_HR( hr );
  1400. // We're enabled so long as we don't find
  1401. // a missing ACE
  1402. //
  1403. bOk = (pAce != NULL);
  1404. // Cleanup
  1405. //
  1406. DSR_RELEASE( pAce );
  1407. DSR_RELEASE( pAcl );
  1408. DSR_RELEASE( pSD );
  1409. VariantClear(&varSD);
  1410. pAce = NULL;
  1411. pAcl = NULL;
  1412. pSD = NULL;
  1413. // Break if we find out we're not enabled
  1414. //
  1415. if (bOk == FALSE)
  1416. {
  1417. break;
  1418. }
  1419. }
  1420. // Break if we find out we're not enabled
  1421. //
  1422. if (bOk == FALSE)
  1423. {
  1424. break;
  1425. }
  1426. }
  1427. DSR_BREAK_ON_FAILED_HR( hr );
  1428. *pbPresent = bOk;
  1429. } while (FALSE);
  1430. // Cleanup
  1431. {
  1432. }
  1433. return hr;
  1434. }
  1435. //
  1436. // Applies the aces in the given access settings to the
  1437. // appropriate domain.
  1438. //
  1439. HRESULT
  1440. DsrAceAppRemove(
  1441. IN DWORD dwMode,
  1442. IN PWCHAR pszDC,
  1443. IN DSR_ACE_APPLICATION* pAces,
  1444. IN DWORD dwCount)
  1445. {
  1446. HRESULT hr = S_OK;
  1447. DSR_ACE_APPLICATION* pAceApp = NULL;
  1448. DWORD i, j;
  1449. do
  1450. {
  1451. // Add/Del the ACES to the domain objects
  1452. //
  1453. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1454. {
  1455. for (j = 0; j < pAceApp->dwCount; j++)
  1456. {
  1457. if (pAceApp->pAces[j].dwMode != dwMode)
  1458. {
  1459. continue;
  1460. }
  1461. hr = DsrAceRemove(
  1462. pszDC,
  1463. pAceApp->pObject,
  1464. &(pAceApp->pAces[j]));
  1465. DSR_BREAK_ON_FAILED_HR( hr );
  1466. }
  1467. }
  1468. DSR_BREAK_ON_FAILED_HR( hr );
  1469. // Commit the ACE's to the domain objects.
  1470. //
  1471. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1472. {
  1473. hr = pAceApp->pObject->SetInfo();
  1474. DSR_BREAK_ON_FAILED_HR( hr );
  1475. }
  1476. DSR_BREAK_ON_FAILED_HR( hr );
  1477. } while (FALSE);
  1478. // Cleanup
  1479. {
  1480. }
  1481. return hr;
  1482. }
  1483. //
  1484. // Clear the dsr ace parameters
  1485. //
  1486. DWORD
  1487. DsrAceDescClear(
  1488. IN DSR_ACE_DESCRIPTOR* pParams)
  1489. {
  1490. if (pParams)
  1491. {
  1492. if (pParams->bstrTrustee)
  1493. {
  1494. SysFreeString(pParams->bstrTrustee);
  1495. }
  1496. if (pParams->bstrObjectType)
  1497. {
  1498. SysFreeString(pParams->bstrObjectType);
  1499. }
  1500. if (pParams->bstrInheritedObjectType)
  1501. {
  1502. SysFreeString(pParams->bstrInheritedObjectType);
  1503. }
  1504. ZeroMemory(pParams, sizeof(DSR_ACE_DESCRIPTOR));
  1505. }
  1506. return NO_ERROR;
  1507. }
  1508. //
  1509. // Returns 0 if ACE descriptors are describing the same ACE.
  1510. // FALSE, otherwise.
  1511. //
  1512. HRESULT
  1513. DsrAceDescCompare(
  1514. IN DSR_ACE_DESCRIPTOR* pAce1,
  1515. IN DSR_ACE_DESCRIPTOR* pAce2)
  1516. {
  1517. DWORD dw1, dw2;
  1518. // Compare the non-string fields so that we can rule things
  1519. // out w/o string compares if possible
  1520. //
  1521. if (
  1522. (pAce1->dwAccessMask != pAce2->dwAccessMask) ||
  1523. (pAce1->dwAceFlags != pAce2->dwAceFlags) ||
  1524. (pAce1->dwAceType != pAce2->dwAceType) ||
  1525. (pAce1->dwFlags != pAce2->dwFlags)
  1526. )
  1527. {
  1528. return 1;
  1529. }
  1530. // Compare the strings
  1531. //
  1532. if ((DsrStrCompare(pAce1->bstrTrustee, pAce2->bstrTrustee)) ||
  1533. (DsrStrCompare(pAce1->bstrObjectType, pAce2->bstrObjectType)) ||
  1534. (DsrStrCompare(pAce1->bstrInheritedObjectType,
  1535. pAce2->bstrInheritedObjectType))
  1536. )
  1537. {
  1538. return 1;
  1539. }
  1540. // Return success
  1541. //
  1542. return 0;
  1543. }
  1544. //
  1545. // Copy over the ACE information
  1546. //
  1547. HRESULT
  1548. DsrAceDescCopy(
  1549. OUT DSR_ACE_DESCRIPTOR* pDst,
  1550. IN DSR_ACE_DESCRIPTOR* pSrc)
  1551. {
  1552. HRESULT hr = S_OK;
  1553. do
  1554. {
  1555. // Initialize the ACE parameters
  1556. *pDst = *pSrc;
  1557. if (pSrc->bstrTrustee)
  1558. {
  1559. pDst->bstrTrustee =
  1560. SysAllocString(pSrc->bstrTrustee);
  1561. if (pDst->bstrTrustee == NULL)
  1562. {
  1563. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  1564. }
  1565. }
  1566. if (pSrc->bstrObjectType)
  1567. {
  1568. pDst->bstrObjectType =
  1569. SysAllocString(pSrc->bstrObjectType);
  1570. if (pDst->bstrObjectType == NULL)
  1571. {
  1572. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  1573. }
  1574. }
  1575. if (pSrc->bstrInheritedObjectType)
  1576. {
  1577. pDst->bstrInheritedObjectType =
  1578. SysAllocString(pSrc->bstrInheritedObjectType);
  1579. if (pDst->bstrInheritedObjectType == NULL)
  1580. {
  1581. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  1582. }
  1583. }
  1584. } while (FALSE);
  1585. // Cleanup
  1586. {
  1587. if (FAILED( hr ))
  1588. {
  1589. if (pDst->bstrTrustee)
  1590. {
  1591. SysFreeString(pDst->bstrTrustee);
  1592. }
  1593. if (pDst->bstrObjectType)
  1594. {
  1595. SysFreeString(pDst->bstrObjectType);
  1596. }
  1597. if (pDst->bstrInheritedObjectType)
  1598. {
  1599. SysFreeString(pDst->bstrInheritedObjectType);
  1600. }
  1601. }
  1602. }
  1603. return hr;
  1604. }
  1605. //
  1606. // Populates the given ACE descriptor with the values from
  1607. // the given ACE.
  1608. //
  1609. HRESULT
  1610. DsrAceDescFromIadsAce(
  1611. IN PWCHAR pszDC,
  1612. IN IADsAccessControlEntry* pAce,
  1613. IN DSR_ACE_DESCRIPTOR* pAceParams)
  1614. {
  1615. HRESULT hr = S_OK;
  1616. BSTR bstrTrustee = NULL;
  1617. PWCHAR pszSidLocal, pszDomain;
  1618. PBYTE pbSid;
  1619. DWORD dwSidSize, dwDomainSize;
  1620. BOOL bOk;
  1621. SID_NAME_USE SidNameUse;
  1622. pszSidLocal = (PWCHAR) DsrAlloc(sizeof(WCHAR)*1024, FALSE);
  1623. pszDomain = (PWCHAR) DsrAlloc(sizeof(WCHAR)*1024, FALSE);
  1624. pbSid = (PBYTE) DsrAlloc(sizeof(BYTE)*1024, FALSE);
  1625. if (!pszSidLocal || !pszDomain || !pbSid) {
  1626. if (pszSidLocal)
  1627. DsrFree(pszSidLocal);
  1628. if (pszDomain)
  1629. DsrFree(pszDomain);
  1630. if (pbSid)
  1631. DsrFree(pbSid);
  1632. return E_OUTOFMEMORY;
  1633. }
  1634. do
  1635. {
  1636. hr = pAce->get_AccessMask(&(pAceParams->dwAccessMask));
  1637. DSR_BREAK_ON_FAILED_HR( hr );
  1638. hr = pAce->get_AceType(&(pAceParams->dwAceType));
  1639. DSR_BREAK_ON_FAILED_HR( hr );
  1640. hr = pAce->get_AceFlags(&(pAceParams->dwAceFlags));
  1641. DSR_BREAK_ON_FAILED_HR( hr );
  1642. hr = pAce->get_Flags(&(pAceParams->dwFlags));
  1643. DSR_BREAK_ON_FAILED_HR( hr );
  1644. hr = pAce->get_ObjectType(&(pAceParams->bstrObjectType));
  1645. DSR_BREAK_ON_FAILED_HR( hr );
  1646. hr = pAce->get_InheritedObjectType(
  1647. &(pAceParams->bstrInheritedObjectType));
  1648. DSR_BREAK_ON_FAILED_HR( hr );
  1649. hr = pAce->get_Trustee(&bstrTrustee);
  1650. DSR_BREAK_ON_FAILED_HR( hr );
  1651. // Get the SID of the trustee
  1652. //
  1653. dwSidSize = sizeof(pbSid);
  1654. dwDomainSize = sizeof(pszDomain) / sizeof(WCHAR);
  1655. bOk = LookupAccountName(
  1656. pszDC,
  1657. bstrTrustee,
  1658. (PSID)pbSid,
  1659. &dwSidSize,
  1660. pszDomain,
  1661. &dwDomainSize,
  1662. &SidNameUse);
  1663. if (bOk == FALSE)
  1664. {
  1665. hr = GetLastError();
  1666. break;
  1667. }
  1668. // Convert the sid to a string
  1669. //
  1670. hr = DsrStrFromSID((PSID)pbSid, pszSidLocal, sizeof(pszSidLocal));
  1671. if (hr != NO_ERROR)
  1672. {
  1673. break;
  1674. }
  1675. // Create the trustee accordingly
  1676. //
  1677. pAceParams->bstrTrustee = SysAllocString(pszSidLocal);
  1678. if (pAceParams->bstrTrustee == NULL)
  1679. {
  1680. hr = E_OUTOFMEMORY;
  1681. break;
  1682. }
  1683. } while (FALSE);
  1684. // Cleanup
  1685. {
  1686. if (bstrTrustee)
  1687. {
  1688. SysFreeString(bstrTrustee);
  1689. }
  1690. if (FAILED(hr))
  1691. {
  1692. DsrAceDescClear(pAceParams);
  1693. }
  1694. }
  1695. DsrFree(pszSidLocal);
  1696. DsrFree(pszDomain);
  1697. DsrFree(pbSid);
  1698. return hr;
  1699. }
  1700. PWCHAR
  1701. DsrAceAttrToString(
  1702. IN PWCHAR pszObjectType)
  1703. {
  1704. if (pszObjectType == NULL)
  1705. {
  1706. return L"All";
  1707. }
  1708. else if (lstrcmpi(pszObjectType, pszGuidUserParms) == 0)
  1709. {
  1710. return L"UserParms (BF967A6D-0DE6-11D0-A285-00AA003049E2)";
  1711. }
  1712. else if (lstrcmpi(pszObjectType, pszGuidRasPropSet1) == 0)
  1713. {
  1714. return L"Ras user properties (037088F8-0AE1-11D2-B422-00A0C968F939)";
  1715. }
  1716. else if (lstrcmpi(pszObjectType, pszGuidRasPropSet2) == 0)
  1717. {
  1718. return L"Misc user properties (4C164200-20C0-11D0-A768-00AA006E0529)";
  1719. }
  1720. else if (lstrcmpi(pszObjectType, pszGuidLogonHours) == 0)
  1721. {
  1722. return L"Logon-Hours (BF9679AB-0DE6-11D0-A285-00AA003049E2)";
  1723. }
  1724. else if (lstrcmpi(pszObjectType, pszGuidSamAccountName) == 0)
  1725. {
  1726. return L"Sam account name (3E0ABFD0-126A-11D0-A060-00AA006C33ED)";
  1727. }
  1728. return pszObjectType;
  1729. }
  1730. PWCHAR
  1731. DsrAceApplyToString(
  1732. IN PWCHAR pszApply)
  1733. {
  1734. if (pszApply == NULL)
  1735. {
  1736. return L"This object";
  1737. }
  1738. else if (lstrcmpi(pszApply, pszGuidUserClass) == 0)
  1739. {
  1740. return L"User objects (BF967ABA-0DE6-11D0-A285-00aa003049E2)";
  1741. }
  1742. return pszApply;
  1743. }
  1744. PWCHAR
  1745. DsrAceMaskToString(
  1746. IN DWORD dwType,
  1747. IN DWORD dwMask,
  1748. IN PWCHAR pszBuf)
  1749. {
  1750. WCHAR pszTemp[64];
  1751. *pszBuf = L'\0';
  1752. switch (dwType)
  1753. {
  1754. case ADS_ACETYPE_ACCESS_ALLOWED:
  1755. wcscpy(pszBuf, L"Allow: ");
  1756. break;
  1757. case ADS_ACETYPE_ACCESS_DENIED:
  1758. wcscpy(pszBuf, L"Deny: ");
  1759. break;
  1760. case ADS_ACETYPE_SYSTEM_AUDIT:
  1761. wcscpy(pszBuf, L"Audit: ");
  1762. break;
  1763. case ADS_ACETYPE_ACCESS_ALLOWED_OBJECT:
  1764. wcscpy(pszBuf, L"Allow obj: ");
  1765. break;
  1766. case ADS_ACETYPE_ACCESS_DENIED_OBJECT:
  1767. wcscpy(pszBuf, L"Deny obj: ");
  1768. break;
  1769. case ADS_ACETYPE_SYSTEM_AUDIT_OBJECT:
  1770. wcscpy(pszBuf, L"Audit obj: ");
  1771. break;
  1772. }
  1773. wsprintfW(pszTemp, L"(%x): ", dwMask);
  1774. wcscat(pszBuf, pszTemp);
  1775. if (dwMask == DSR_ADS_RIGHT_GENERIC_READ)
  1776. {
  1777. wcscat(pszBuf, L"Generic read");
  1778. }
  1779. else if (dwMask == 0xffffffff)
  1780. {
  1781. wcscat(pszBuf, L"Full control");
  1782. }
  1783. else
  1784. {
  1785. if (dwMask & ADS_RIGHT_READ_CONTROL)
  1786. wcscat(pszBuf, L"R ctrl, ");
  1787. if (dwMask & ADS_RIGHT_WRITE_DAC)
  1788. wcscat(pszBuf, L"R/W dac, ");
  1789. if (dwMask & ADS_RIGHT_WRITE_OWNER)
  1790. wcscat(pszBuf, L"W own, ");
  1791. if (dwMask & ADS_RIGHT_SYNCHRONIZE)
  1792. wcscat(pszBuf, L"Sync, ");
  1793. if (dwMask & ADS_RIGHT_ACCESS_SYSTEM_SECURITY)
  1794. wcscat(pszBuf, L"Sys, ");
  1795. if (dwMask & ADS_RIGHT_GENERIC_READ)
  1796. wcscat(pszBuf, L"R (gen), ");
  1797. if (dwMask & ADS_RIGHT_GENERIC_WRITE)
  1798. wcscat(pszBuf, L"W (gen), ");
  1799. if (dwMask & ADS_RIGHT_GENERIC_EXECUTE)
  1800. wcscat(pszBuf, L"Ex, ");
  1801. if (dwMask & ADS_RIGHT_GENERIC_ALL)
  1802. wcscat(pszBuf, L"All, ");
  1803. if (dwMask & ADS_RIGHT_DS_CREATE_CHILD)
  1804. wcscat(pszBuf, L"Cr cld, ");
  1805. if (dwMask & ADS_RIGHT_DS_DELETE_CHILD)
  1806. wcscat(pszBuf, L"Del cld, ");
  1807. if (dwMask & ADS_RIGHT_ACTRL_DS_LIST)
  1808. wcscat(pszBuf, L"List, ");
  1809. if (dwMask & ADS_RIGHT_DS_SELF)
  1810. wcscat(pszBuf, L"Self, ");
  1811. if (dwMask & ADS_RIGHT_DS_READ_PROP)
  1812. wcscat(pszBuf, L"R prop, ");
  1813. if (dwMask & ADS_RIGHT_DS_WRITE_PROP)
  1814. wcscat(pszBuf, L"W prop, ");
  1815. if (dwMask & ADS_RIGHT_DS_DELETE_TREE)
  1816. wcscat(pszBuf, L"Del tree, ");
  1817. if (dwMask & ADS_RIGHT_DS_LIST_OBJECT)
  1818. wcscat(pszBuf, L"List obj, ");
  1819. if (dwMask & ADS_RIGHT_DS_CONTROL_ACCESS)
  1820. wcscat(pszBuf, L"Ctrl acc, ");
  1821. }
  1822. return pszBuf;
  1823. }
  1824. PWCHAR
  1825. DsrAceFlagsToString(
  1826. IN DWORD dwAceFlags,
  1827. IN PWCHAR pszBuf)
  1828. {
  1829. WCHAR pszTemp[64];
  1830. *pszBuf = L'\0';
  1831. switch (dwAceFlags)
  1832. {
  1833. case 0:
  1834. wcscpy(pszBuf, L"This object only");
  1835. break;
  1836. case ADS_ACEFLAG_INHERIT_ACE:
  1837. wcscpy(pszBuf, L"This object and children");
  1838. break;
  1839. case ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE:
  1840. wcscpy(pszBuf, L"No-prop inherit");
  1841. break;
  1842. case ADS_ACEFLAG_INHERIT_ONLY_ACE:
  1843. wcscpy(pszBuf, L"Inherit-only");
  1844. break;
  1845. case ADS_ACEFLAG_INHERITED_ACE:
  1846. wcscpy(pszBuf, L"Inherited");
  1847. break;
  1848. case ADS_ACEFLAG_VALID_INHERIT_FLAGS:
  1849. wcscpy(pszBuf, L"Valid inherit flags");
  1850. break;
  1851. case ADS_ACEFLAG_SUCCESSFUL_ACCESS:
  1852. wcscpy(pszBuf, L"Successful access");
  1853. break;
  1854. case ADS_ACEFLAG_FAILED_ACCESS:
  1855. wcscpy(pszBuf, L"Failed access");
  1856. break;
  1857. }
  1858. wsprintfW(pszTemp, L" (%x)", dwAceFlags);
  1859. wcscat(pszBuf, pszTemp);
  1860. return pszBuf;
  1861. }
  1862. //
  1863. // Traces out the contents of an ACE
  1864. //
  1865. VOID
  1866. DsrAceDescTrace(
  1867. IN IADs* pIads,
  1868. IN DSR_ACE_DESCRIPTOR* pA)
  1869. {
  1870. VARIANT var;
  1871. BSTR bstrProp = SysAllocString(pszDn);
  1872. HRESULT hr = S_OK;
  1873. WCHAR pszBuf[1024];
  1874. do
  1875. {
  1876. VariantInit(&var);
  1877. if (bstrProp == NULL)
  1878. {
  1879. hr = E_FAIL;
  1880. break;
  1881. }
  1882. hr = pIads->Get(bstrProp, &var);
  1883. DSR_BREAK_ON_FAILED_HR( hr );
  1884. DsrTraceEx(0, "%ls", V_BSTR(&var));
  1885. DsrTraceEx(0, "%ls",
  1886. DsrAceMaskToString(pA->dwAceType, pA->dwAccessMask, pszBuf));
  1887. DsrTraceEx(0, "To: %ls", pA->bstrTrustee);
  1888. DsrTraceEx(0, "Attribute: %ls",
  1889. DsrAceAttrToString(pA->bstrObjectType));
  1890. DsrTraceEx(0, "ApplyTo: %ls",
  1891. DsrAceApplyToString(pA->bstrInheritedObjectType));
  1892. DsrTraceEx(0, "Inheritance: %ls",
  1893. DsrAceFlagsToString(pA->dwAceFlags, pszBuf));
  1894. DsrTraceEx(0, "Flags: %x", pA->dwFlags);
  1895. DsrTraceEx(0, " ");
  1896. } while (FALSE);
  1897. // Cleanup
  1898. //
  1899. {
  1900. SysFreeString(bstrProp);
  1901. VariantClear(&var);
  1902. }
  1903. if (FAILED(hr))
  1904. {
  1905. DsrTraceEx(
  1906. 0,
  1907. "{ %-8x %-2x %-2x %-2x %-40ls %ls %ls }",
  1908. pA->dwAccessMask,
  1909. pA->dwAceType,
  1910. pA->dwAceFlags,
  1911. pA->dwFlags,
  1912. pA->bstrTrustee,
  1913. pA->bstrObjectType,
  1914. pA->bstrInheritedObjectType);
  1915. }
  1916. }
  1917. //
  1918. // Adds the given ace to the given ds object
  1919. //
  1920. HRESULT
  1921. DsrAceAdd(
  1922. IN PWCHAR pszDC,
  1923. IN IADs* pIads,
  1924. IN DSR_ACE_DESCRIPTOR * pAceParams)
  1925. {
  1926. IADsSecurityDescriptor* pSD = NULL;
  1927. IADsAccessControlList* pAcl = NULL;
  1928. IDispatch* pAce = NULL;
  1929. IDispatch* pDispatch = NULL;
  1930. HRESULT hr = S_OK;
  1931. VARIANT var;
  1932. BSTR StringTmp = NULL;
  1933. // Initialize
  1934. VariantInit(&var);
  1935. do
  1936. {
  1937. // Get the security descriptor
  1938. //
  1939. StringTmp = SysAllocString(pszSecurityDesc);
  1940. if (!StringTmp)
  1941. {
  1942. hr = E_OUTOFMEMORY;
  1943. break;
  1944. }
  1945. pIads->Get(StringTmp, &var);
  1946. DSR_BREAK_ON_FAILED_HR( hr );
  1947. SysFreeString(StringTmp);
  1948. StringTmp = NULL;
  1949. // Get the appropriate interface to the sd
  1950. //
  1951. V_DISPATCH(&var)->QueryInterface(
  1952. IID_IADsSecurityDescriptor,
  1953. (VOID**)&pSD);
  1954. DSR_BREAK_ON_FAILED_HR( hr );
  1955. // Get a reference to the discretionary acl
  1956. //
  1957. hr = pSD->get_DiscretionaryAcl(&pDispatch);
  1958. DSR_BREAK_ON_FAILED_HR( hr );
  1959. hr = pDispatch->QueryInterface(
  1960. IID_IADsAccessControlList,
  1961. (VOID**)&pAcl);
  1962. DSR_BREAK_ON_FAILED_HR( hr );
  1963. // Don't add the ACE if it's already there.
  1964. //
  1965. hr = DsrAceFindInAcl(
  1966. pszDC,
  1967. pAcl,
  1968. pAceParams,
  1969. &pAce);
  1970. if (SUCCEEDED(hr) && pAce)
  1971. {
  1972. hr = S_OK;
  1973. break;
  1974. }
  1975. // Trace out the ACE
  1976. DsrAceDescTrace(pIads, pAceParams);
  1977. // Create the ACE
  1978. hr = DsrAceCreate(pAceParams, &pAce);
  1979. DSR_BREAK_ON_FAILED_HR( hr );
  1980. // Add the newly created ACE to the ACL
  1981. //
  1982. hr = pAcl->AddAce(pAce);
  1983. DSR_BREAK_ON_FAILED_HR( hr );
  1984. // Now commit the result in the ACL
  1985. //
  1986. hr = pSD->put_DiscretionaryAcl(pDispatch);
  1987. DSR_BREAK_ON_FAILED_HR( hr );
  1988. // Finally, commit the result in the ds object
  1989. //
  1990. StringTmp = SysAllocString(pszSecurityDesc);
  1991. if (!StringTmp)
  1992. {
  1993. hr = E_OUTOFMEMORY;
  1994. break;
  1995. }
  1996. hr = pIads->Put(StringTmp, var);
  1997. DSR_BREAK_ON_FAILED_HR( hr );
  1998. } while (FALSE);
  1999. // Cleanup
  2000. {
  2001. DSR_RELEASE( pAce );
  2002. DSR_RELEASE( pAcl );
  2003. DSR_RELEASE( pDispatch );
  2004. DSR_RELEASE( pSD );
  2005. VariantClear(&var);
  2006. if (StringTmp)
  2007. {
  2008. SysFreeString(StringTmp);
  2009. }
  2010. }
  2011. return DSR_ERROR(hr);
  2012. }
  2013. //
  2014. // Creates a new ACE object from the given parameters
  2015. //
  2016. HRESULT
  2017. DsrAceCreate(
  2018. IN DSR_ACE_DESCRIPTOR * pAceParams,
  2019. OUT IDispatch** ppAce)
  2020. {
  2021. IADsAccessControlEntry* pAce = NULL;
  2022. IDispatch* pRet = NULL;
  2023. HRESULT hr = S_OK;
  2024. do
  2025. {
  2026. // Create the new ACE
  2027. //
  2028. hr = CoCreateInstance(
  2029. CLSID_AccessControlEntry,
  2030. NULL,
  2031. CLSCTX_INPROC_SERVER,
  2032. IID_IADsAccessControlEntry,
  2033. (VOID**) &pAce);
  2034. DSR_BREAK_ON_FAILED_HR( hr );
  2035. // Initialize the values
  2036. //
  2037. hr = pAce->put_Trustee(pAceParams->bstrTrustee);
  2038. DSR_BREAK_ON_FAILED_HR( hr );
  2039. hr = pAce->put_AceFlags(pAceParams->dwAceFlags);
  2040. DSR_BREAK_ON_FAILED_HR( hr );
  2041. hr = pAce->put_Flags(pAceParams->dwFlags);
  2042. DSR_BREAK_ON_FAILED_HR( hr );
  2043. hr = pAce->put_AceType(pAceParams->dwAceType);
  2044. DSR_BREAK_ON_FAILED_HR( hr );
  2045. hr = pAce->put_AccessMask(pAceParams->dwAccessMask);
  2046. DSR_BREAK_ON_FAILED_HR( hr );
  2047. hr = pAce->put_ObjectType(pAceParams->bstrObjectType);
  2048. DSR_BREAK_ON_FAILED_HR( hr );
  2049. hr = pAce->put_InheritedObjectType(
  2050. pAceParams->bstrInheritedObjectType);
  2051. DSR_BREAK_ON_FAILED_HR( hr );
  2052. // Query the return value
  2053. //
  2054. hr = pAce->QueryInterface(IID_IDispatch, (VOID**)&pRet);
  2055. DSR_BREAK_ON_FAILED_HR( hr );
  2056. // Assign the return value
  2057. *ppAce = pRet;
  2058. } while (FALSE);
  2059. // Cleanup
  2060. {
  2061. if (FAILED (hr))
  2062. {
  2063. DSR_RELEASE(pRet);
  2064. }
  2065. DSR_RELEASE(pAce);
  2066. }
  2067. return hr;
  2068. }
  2069. //
  2070. // Finds the given ace in the given acl
  2071. //
  2072. HRESULT
  2073. DsrAceFind(
  2074. IN PWCHAR pszDC,
  2075. IN IADs* pObject,
  2076. IN DSR_ACE_DESCRIPTOR* pAceParams,
  2077. OUT VARIANT* pVarSD,
  2078. OUT IADsSecurityDescriptor** ppSD,
  2079. OUT IADsAccessControlList** ppAcl,
  2080. OUT IDispatch** ppAce)
  2081. {
  2082. IDispatch* pAcl = NULL;
  2083. HRESULT hr = S_OK;
  2084. BSTR StringTmp = NULL;
  2085. do
  2086. {
  2087. // Get the security descriptor
  2088. //
  2089. StringTmp = SysAllocString(pszSecurityDesc);
  2090. if (!StringTmp)
  2091. {
  2092. hr = E_OUTOFMEMORY;
  2093. DSR_BREAK_ON_FAILED_HR( hr );
  2094. }
  2095. pObject->Get(StringTmp, pVarSD);
  2096. DSR_BREAK_ON_FAILED_HR( hr );
  2097. // Get the appropriate interface to the sd
  2098. //
  2099. V_DISPATCH(pVarSD)->QueryInterface(
  2100. IID_IADsSecurityDescriptor,
  2101. (VOID**)ppSD);
  2102. DSR_BREAK_ON_FAILED_HR( hr );
  2103. // Get a reference to the discretionary acl
  2104. //
  2105. hr = (*ppSD)->get_DiscretionaryAcl(&pAcl);
  2106. DSR_BREAK_ON_FAILED_HR( hr );
  2107. hr = pAcl->QueryInterface(
  2108. IID_IADsAccessControlList,
  2109. (VOID**)ppAcl);
  2110. DSR_BREAK_ON_FAILED_HR( hr );
  2111. hr = DsrAceFindInAcl(
  2112. pszDC,
  2113. *ppAcl,
  2114. pAceParams,
  2115. ppAce);
  2116. DSR_BREAK_ON_FAILED_HR(hr);
  2117. } while (FALSE);
  2118. // Cleanup
  2119. {
  2120. DSR_RELEASE( pAcl );
  2121. if (*ppAce == NULL)
  2122. {
  2123. VariantClear(pVarSD);
  2124. DSR_RELEASE(*ppAcl);
  2125. DSR_RELEASE(*ppSD);
  2126. *ppAcl = NULL;
  2127. *ppSD = NULL;
  2128. }
  2129. if (StringTmp)
  2130. {
  2131. SysFreeString(StringTmp);
  2132. }
  2133. }
  2134. return hr;
  2135. }
  2136. //
  2137. // Finds the given ACE in the given ACL
  2138. //
  2139. HRESULT
  2140. DsrAceFindInAcl(
  2141. IN PWCHAR pszDC,
  2142. IN IADsAccessControlList* pAcl,
  2143. IN DSR_ACE_DESCRIPTOR* pAceDesc,
  2144. OUT IDispatch** ppAce)
  2145. {
  2146. DSR_ACE_DESCRIPTOR CurAceParams, *pCurAceDesc = &CurAceParams;
  2147. IADsAccessControlEntry* pCurAce = NULL;
  2148. HRESULT hr = S_OK;
  2149. IUnknown* pUnknown = NULL;
  2150. IEnumVARIANT* pEnumVar = NULL;
  2151. IDispatch* pRet = NULL;
  2152. DWORD dwRetrieved;
  2153. VARIANT var;
  2154. do
  2155. {
  2156. // Get an enumerator of the aces
  2157. //
  2158. hr = pAcl->get__NewEnum(&pUnknown);
  2159. DSR_BREAK_ON_FAILED_HR( hr );
  2160. // Get the right interface to enumerate the aces
  2161. //
  2162. hr = pUnknown->QueryInterface(IID_IEnumVARIANT, (VOID**)&pEnumVar);
  2163. DSR_BREAK_ON_FAILED_HR( hr );
  2164. // Enumerate
  2165. //
  2166. pEnumVar->Reset();
  2167. VariantInit(&var);
  2168. ZeroMemory(pCurAceDesc, sizeof(DSR_ACE_DESCRIPTOR));
  2169. while ((pEnumVar->Next(1, &var, &dwRetrieved) == S_OK) &&
  2170. (dwRetrieved == 1)
  2171. )
  2172. {
  2173. // Get the reference to the ace
  2174. //
  2175. hr = V_DISPATCH(&var)->QueryInterface(
  2176. IID_IADsAccessControlEntry,
  2177. (VOID**)&pCurAce);
  2178. if (SUCCEEDED (hr))
  2179. {
  2180. // Read the ACE parameters
  2181. //
  2182. hr = DsrAceDescFromIadsAce(pszDC, pCurAce, pCurAceDesc);
  2183. if (SUCCEEDED (hr))
  2184. {
  2185. // Assign the ace if we have a match
  2186. //
  2187. if (DsrAceDescCompare(pCurAceDesc, pAceDesc) == 0)
  2188. {
  2189. pRet = V_DISPATCH(&var);
  2190. }
  2191. DsrAceDescClear(pCurAceDesc);
  2192. }
  2193. pCurAce->Release();
  2194. }
  2195. if (pRet == NULL)
  2196. {
  2197. VariantClear(&var);
  2198. }
  2199. else
  2200. {
  2201. break;
  2202. }
  2203. }
  2204. // Assign the return value
  2205. //
  2206. *ppAce = pRet;
  2207. } while (FALSE);
  2208. // Cleanup
  2209. {
  2210. DSR_RELEASE( pEnumVar );
  2211. DSR_RELEASE( pUnknown );
  2212. }
  2213. return hr;
  2214. }
  2215. //
  2216. // Removes the given ace from the given ds object
  2217. //
  2218. HRESULT
  2219. DsrAceRemove(
  2220. IN PWCHAR pszDC,
  2221. IN IADs* pIads,
  2222. IN DSR_ACE_DESCRIPTOR * pAceParams)
  2223. {
  2224. IADsSecurityDescriptor* pSD = NULL;
  2225. IADsAccessControlList* pAcl = NULL;
  2226. IADsAccessControlEntry* pIadsAce = NULL;
  2227. IDispatch* pAce = NULL;
  2228. DSR_ACE_DESCRIPTOR CurAceParams;
  2229. HRESULT hr = S_OK;
  2230. VARIANT varSD;
  2231. BSTR StringTmp = NULL;
  2232. do
  2233. {
  2234. VariantInit(&varSD);
  2235. hr = DsrAceFind(pszDC, pIads, pAceParams, &varSD, &pSD, &pAcl, &pAce);
  2236. DSR_BREAK_ON_FAILED_HR( hr );
  2237. if (pAce)
  2238. {
  2239. // Make sure the ace is the same as we think
  2240. //
  2241. hr = pAce->QueryInterface(
  2242. IID_IADsAccessControlEntry,
  2243. (VOID**)&pIadsAce);
  2244. if (SUCCEEDED(hr))
  2245. {
  2246. DsrTraceEx(0, "ACE to be removed!");
  2247. DsrAceDescFromIadsAce(pszDC, pIadsAce, &CurAceParams);
  2248. DsrAceDescTrace(pIads, &CurAceParams);
  2249. DsrAceDescClear(&CurAceParams);
  2250. }
  2251. else
  2252. {
  2253. DsrTraceEx(0, "Unable to trace ACE that will be removed!\n");
  2254. }
  2255. // Remove the ace found if any.
  2256. //
  2257. // Trace out the ACE
  2258. hr = pAcl->RemoveAce(pAce);
  2259. DSR_BREAK_ON_FAILED_HR( hr );
  2260. // Now commit the result in the ACL
  2261. //
  2262. hr = pSD->put_DiscretionaryAcl(pAcl);
  2263. DSR_BREAK_ON_FAILED_HR( hr );
  2264. // Finally, commit the result in the ds object
  2265. //
  2266. StringTmp = SysAllocString(pszSecurityDesc);
  2267. if (!StringTmp)
  2268. {
  2269. hr = E_OUTOFMEMORY;
  2270. break;
  2271. }
  2272. hr = pIads->Put(StringTmp, varSD);
  2273. DSR_BREAK_ON_FAILED_HR( hr );
  2274. }
  2275. else
  2276. {
  2277. DsrTraceEx(0, "DsrAceRemove: unable to match ACE for removal:");
  2278. DsrAceDescTrace(pIads, pAceParams);
  2279. }
  2280. } while (FALSE);
  2281. // Cleanup
  2282. {
  2283. DSR_RELEASE( pAce );
  2284. DSR_RELEASE( pIadsAce );
  2285. DSR_RELEASE( pAcl );
  2286. DSR_RELEASE( pSD );
  2287. VariantClear(&varSD);
  2288. if (StringTmp)
  2289. {
  2290. SysFreeString(StringTmp);
  2291. }
  2292. }
  2293. return DSR_ERROR(hr);
  2294. }
  2295. //
  2296. // Cleans up after DsrAccessInfoInit
  2297. //
  2298. DWORD
  2299. DsrAccessInfoCleanup(
  2300. IN DSR_DOMAIN_ACCESS_INFO* pInfo)
  2301. {
  2302. if (pInfo)
  2303. {
  2304. // Cleanup the name of the DC
  2305. //
  2306. if (pInfo->pszDC)
  2307. {
  2308. DsrFree(pInfo->pszDC);
  2309. }
  2310. // Cleanup the ace applications
  2311. //
  2312. DsrAceAppCleanup(pInfo->pAces, pInfo->dwAceCount);
  2313. // Release the hold on domain objects
  2314. //
  2315. DSR_RELEASE(pInfo->pRootDse);
  2316. DSR_RELEASE(pInfo->pDomain);
  2317. DsrFree(pInfo);
  2318. }
  2319. return NO_ERROR;
  2320. }
  2321. //
  2322. // Generates the information needed to enable nt4 ras
  2323. // servers in a domain
  2324. //
  2325. HRESULT
  2326. DsrAccessInfoInit(
  2327. IN PWCHAR pszDomain,
  2328. OUT DSR_DOMAIN_ACCESS_INFO** ppInfo)
  2329. {
  2330. DSR_DOMAIN_ACCESS_INFO* pInfo = NULL;
  2331. IADsContainer* pDomContainer = NULL;
  2332. IADs* pDomain = NULL;
  2333. IDispatch* pDispatch = NULL;
  2334. PDOMAIN_CONTROLLER_INFO pDomainInfo = NULL;
  2335. HRESULT hr = S_OK;
  2336. do
  2337. {
  2338. // Allocate and zero the return value
  2339. //
  2340. pInfo = (DSR_DOMAIN_ACCESS_INFO*)
  2341. DsrAlloc(sizeof(DSR_DOMAIN_ACCESS_INFO), TRUE);
  2342. if (pInfo == NULL)
  2343. {
  2344. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  2345. break; //to make prefast happy
  2346. }
  2347. // Get the name of a DC to query when needed
  2348. //
  2349. hr = DsGetDcNameW(
  2350. NULL,
  2351. pszDomain,
  2352. NULL,
  2353. NULL,
  2354. DS_DIRECTORY_SERVICE_REQUIRED,
  2355. &pDomainInfo);
  2356. if (hr != NO_ERROR)
  2357. {
  2358. hr = HRESULT_FROM_WIN32(hr);
  2359. break;
  2360. }
  2361. // Copy the string
  2362. //
  2363. pInfo->pszDC = (PWCHAR)
  2364. DsrAlloc(
  2365. (wcslen(pDomainInfo->DomainControllerName) + 1) *
  2366. sizeof(WCHAR),
  2367. FALSE);
  2368. if (pInfo->pszDC == NULL)
  2369. {
  2370. hr = E_OUTOFMEMORY;
  2371. break;
  2372. }
  2373. wcscpy(pInfo->pszDC, pDomainInfo->DomainControllerName);
  2374. // Get the well known domain containers
  2375. //
  2376. hr = DsrDomainGetBaseObjects(
  2377. pszDomain,
  2378. &(pInfo->pRootDse),
  2379. &pDomContainer);
  2380. DSR_BREAK_ON_FAILED_HR( hr );
  2381. // Get the interface to the domain object
  2382. //
  2383. hr = pDomContainer->QueryInterface(
  2384. IID_IADs,
  2385. (VOID**)&pDomain);
  2386. DSR_BREAK_ON_FAILED_HR( hr );
  2387. pInfo->pDomain = pDomain;
  2388. pInfo->pDomain->AddRef();
  2389. // Create ace applications
  2390. hr = DsrAceAppFromAppDesc(
  2391. g_pAces,
  2392. sizeof(g_pAces) / sizeof(*g_pAces),
  2393. pDomContainer,
  2394. pDomain,
  2395. &(pInfo->pAces),
  2396. &(pInfo->dwAceCount));
  2397. DSR_BREAK_ON_FAILED_HR( hr );
  2398. // Assign the return value
  2399. *ppInfo = pInfo;
  2400. } while (FALSE);
  2401. // Cleanup
  2402. //
  2403. {
  2404. DSR_RELEASE(pDomain);
  2405. DSR_RELEASE(pDomContainer);
  2406. DSR_RELEASE(pDispatch);
  2407. if (FAILED (hr))
  2408. {
  2409. DsrAccessInfoCleanup(pInfo);
  2410. }
  2411. if (pDomainInfo)
  2412. {
  2413. NetApiBufferFree(pDomainInfo);
  2414. }
  2415. }
  2416. return hr;
  2417. }
  2418. //
  2419. // Discovers the access mode of the domain currently.
  2420. //
  2421. // Assumes COM is initialized
  2422. //
  2423. HRESULT
  2424. DsrDomainQueryAccessEx(
  2425. IN PWCHAR pszDomain,
  2426. OUT LPDWORD lpdwAccessFlags,
  2427. OUT DSR_DOMAIN_ACCESS_INFO** ppInfo)
  2428. {
  2429. DSR_DOMAIN_ACCESS_INFO* pInfo = NULL;
  2430. HRESULT hr = S_OK;
  2431. BOOL bOk = FALSE;
  2432. if (lpdwAccessFlags == NULL)
  2433. {
  2434. return ERROR_INVALID_PARAMETER;
  2435. }
  2436. do
  2437. {
  2438. // Initialize
  2439. //
  2440. *lpdwAccessFlags = 0;
  2441. // Read in the info that tells us what ACE's
  2442. // need to be set.
  2443. //
  2444. hr = DsrAccessInfoInit(
  2445. pszDomain,
  2446. &pInfo);
  2447. DSR_BREAK_ON_FAILED_HR( hr );
  2448. // Check for nt4 level access
  2449. //
  2450. bOk = FALSE;
  2451. hr = DsrAceAppQueryPresence(
  2452. pInfo->pszDC,
  2453. pInfo->pAces,
  2454. pInfo->dwAceCount,
  2455. MPRFLAG_DOMAIN_ALL,
  2456. &bOk);
  2457. DSR_BREAK_ON_FAILED_HR(hr);
  2458. // If we don't have nt4 access, we have no access
  2459. //
  2460. if (bOk == FALSE)
  2461. {
  2462. *lpdwAccessFlags = 0;
  2463. break;
  2464. }
  2465. *lpdwAccessFlags |= MPRFLAG_DOMAIN_NT4_SERVERS;
  2466. // Check for w2k level access
  2467. //
  2468. bOk = FALSE;
  2469. hr = DsrAceAppQueryPresence(
  2470. pInfo->pszDC,
  2471. pInfo->pAces,
  2472. pInfo->dwAceCount,
  2473. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS,
  2474. &bOk);
  2475. DSR_BREAK_ON_FAILED_HR(hr);
  2476. // If we don't have w2k access, no need to proceed
  2477. //
  2478. if (bOk == FALSE)
  2479. {
  2480. break;
  2481. }
  2482. *lpdwAccessFlags |= MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS;
  2483. } while (FALSE);
  2484. // Cleanup
  2485. {
  2486. if (FAILED(hr))
  2487. {
  2488. if (pInfo)
  2489. {
  2490. DsrAccessInfoCleanup(pInfo);
  2491. }
  2492. }
  2493. else
  2494. {
  2495. *ppInfo = pInfo;
  2496. }
  2497. }
  2498. return hr;
  2499. }
  2500. //
  2501. // Returns the access level of the given domain
  2502. //
  2503. DWORD
  2504. DsrDomainQueryAccess(
  2505. IN PWCHAR pszDomain,
  2506. OUT LPDWORD lpdwAccessFlags)
  2507. {
  2508. DSR_DOMAIN_ACCESS_INFO* pInfo = NULL;
  2509. HRESULT hr = S_OK;
  2510. do
  2511. {
  2512. // Initialize
  2513. hr = DsrComIntialize();
  2514. DSR_BREAK_ON_FAILED_HR( hr );
  2515. // Query the access
  2516. hr = DsrDomainQueryAccessEx(
  2517. pszDomain,
  2518. lpdwAccessFlags,
  2519. &pInfo);
  2520. DSR_BREAK_ON_FAILED_HR(hr);
  2521. } while (FALSE);
  2522. // Cleanup
  2523. {
  2524. if (pInfo)
  2525. {
  2526. DsrAccessInfoCleanup(pInfo);
  2527. }
  2528. DsrComUninitialize();
  2529. }
  2530. return DSR_ERROR(hr);
  2531. }
  2532. //
  2533. // Sets the ACES in the given domain to enable nt4 servers
  2534. //
  2535. DWORD
  2536. DsrDomainSetAccess(
  2537. IN PWCHAR pszDomain,
  2538. IN DWORD dwAccessFlags)
  2539. {
  2540. DSR_DOMAIN_ACCESS_INFO* pInfo = NULL;
  2541. HRESULT hr = S_OK;
  2542. BOOL bClean = TRUE;
  2543. DWORD dwCurAccess = 0;
  2544. do
  2545. {
  2546. // Initialize
  2547. hr = DsrComIntialize();
  2548. DSR_BREAK_ON_FAILED_HR( hr );
  2549. DsrTraceEx(
  2550. 0,
  2551. "DsrDomainSetAccess: Req: %x",
  2552. dwAccessFlags);
  2553. // W2k mode always implies nt4 mode as well
  2554. //
  2555. if (dwAccessFlags & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)
  2556. {
  2557. dwAccessFlags |= MPRFLAG_DOMAIN_NT4_SERVERS;
  2558. }
  2559. // Discover the current access on the domain and
  2560. // initialize the info we need
  2561. //
  2562. hr = DsrDomainQueryAccessEx(
  2563. pszDomain,
  2564. &dwCurAccess,
  2565. &pInfo);
  2566. DSR_BREAK_ON_FAILED_HR(hr);
  2567. DsrTraceEx(
  2568. 0,
  2569. "DsrDomainSetAccess: Cur: %x",
  2570. dwCurAccess);
  2571. // Remove all appropriate aces if the requested access
  2572. // is none.
  2573. if (dwAccessFlags == 0)
  2574. {
  2575. // Remove the nt4 mode aces if needed
  2576. //
  2577. if (dwCurAccess & MPRFLAG_DOMAIN_NT4_SERVERS)
  2578. {
  2579. hr = DsrAceAppRemove(
  2580. MPRFLAG_DOMAIN_ALL,
  2581. pInfo->pszDC,
  2582. pInfo->pAces,
  2583. pInfo->dwAceCount);
  2584. DSR_BREAK_ON_FAILED_HR(hr);
  2585. }
  2586. if (dwCurAccess & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)
  2587. {
  2588. hr = DsrAceAppRemove(
  2589. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS,
  2590. pInfo->pszDC,
  2591. pInfo->pAces,
  2592. pInfo->dwAceCount);
  2593. DSR_BREAK_ON_FAILED_HR(hr);
  2594. }
  2595. }
  2596. // Set nt4 mode if needed
  2597. //
  2598. if (dwAccessFlags & MPRFLAG_DOMAIN_NT4_SERVERS)
  2599. {
  2600. // Remove w2k level access if needed
  2601. //
  2602. if ((!(dwAccessFlags & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)) &&
  2603. (dwCurAccess & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS))
  2604. {
  2605. hr = DsrAceAppRemove(
  2606. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS,
  2607. pInfo->pszDC,
  2608. pInfo->pAces,
  2609. pInfo->dwAceCount);
  2610. DSR_BREAK_ON_FAILED_HR(hr);
  2611. }
  2612. // Add nt4 level access if needed
  2613. //
  2614. if (! (dwCurAccess & MPRFLAG_DOMAIN_NT4_SERVERS))
  2615. {
  2616. hr = DsrAceAppAdd(
  2617. MPRFLAG_DOMAIN_ALL,
  2618. pInfo->pszDC,
  2619. pInfo->pAces,
  2620. pInfo->dwAceCount);
  2621. DSR_BREAK_ON_FAILED_HR(hr);
  2622. }
  2623. }
  2624. // Set w2k mode if needed
  2625. //
  2626. if (dwAccessFlags & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)
  2627. {
  2628. if (!(dwCurAccess & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS))
  2629. {
  2630. hr = DsrAceAppAdd(
  2631. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS,
  2632. pInfo->pszDC,
  2633. pInfo->pAces,
  2634. pInfo->dwAceCount);
  2635. DSR_BREAK_ON_FAILED_HR(hr);
  2636. }
  2637. }
  2638. } while (FALSE);
  2639. // Cleanup
  2640. {
  2641. if (pInfo)
  2642. {
  2643. DsrAccessInfoCleanup(pInfo);
  2644. }
  2645. DsrComUninitialize();
  2646. }
  2647. return DSR_ERROR(hr);
  2648. }