Source code of Windows XP (NT5)
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.

2941 lines
72 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. // Iniatialize
  546. //
  547. {
  548. *ppRootDse = NULL;
  549. *ppDomain = NULL;
  550. VariantInit(&var);
  551. }
  552. do
  553. {
  554. // Get RootDSE
  555. //
  556. hr = DsrDomainGetRootDse(pszDomain, ppRootDse);
  557. DSR_BREAK_ON_FAILED_HR(hr);
  558. // Use RootDSE to figure out the name of the domain object
  559. // to query
  560. hr = (*ppRootDse)->Get((PWCHAR)pszDefaultNamingContext, &var);
  561. DSR_BREAK_ON_FAILED_HR( hr );
  562. // Compute the distinguished name of the root domain object
  563. //
  564. hr = DsrDomainGenLdapPath(pszDomain, V_BSTR(&var), &pszDomainObj);
  565. DSR_BREAK_ON_FAILED_HR(hr);
  566. // Get the objects
  567. //
  568. hr = ADsGetObject(pszDomainObj, IID_IADsContainer, (VOID**)ppDomain);
  569. DSR_BREAK_ON_FAILED_HR( hr );
  570. } while (FALSE);
  571. // Cleanup
  572. //
  573. {
  574. if (FAILED( hr ))
  575. {
  576. DSR_RELEASE(*ppRootDse);
  577. DSR_RELEASE(*ppDomain);
  578. *ppRootDse = NULL;
  579. *ppDomain = NULL;
  580. }
  581. DSR_FREE(pszDomainObj);
  582. VariantClear(&var);
  583. }
  584. return hr;
  585. }
  586. //
  587. // Initializes COM
  588. //
  589. HRESULT
  590. DsrComIntialize()
  591. {
  592. HRESULT hr;
  593. hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
  594. if (hr == RPC_E_CHANGED_MODE)
  595. {
  596. hr = CoInitializeEx (NULL, COINIT_MULTITHREADED);
  597. }
  598. if ((hr != S_FALSE) && (FAILED(hr)))
  599. {
  600. return hr;
  601. }
  602. return NO_ERROR;
  603. }
  604. //
  605. // Unitializes COM
  606. //
  607. VOID
  608. DsrComUninitialize()
  609. {
  610. CoUninitialize();
  611. }
  612. //
  613. // Creates a SID based on the array of bytes
  614. // stored in a variant.
  615. //
  616. DWORD
  617. DsrSidInit (
  618. IN VARIANT * pVar,
  619. OUT PBYTE* ppbSid)
  620. {
  621. SAFEARRAY * pArray = V_ARRAY(pVar);
  622. DWORD dwSize, dwLow, dwHigh, i;
  623. HRESULT hr;
  624. BYTE* pbRet = NULL;
  625. VARIANT var;
  626. DsrTraceEx (0, "DsrSidInit: entered.");
  627. // Get the array of bytes
  628. i = 0;
  629. hr = SafeArrayGetElement(pArray, (LONG*)&i, (VOID*)&var);
  630. if (FAILED (hr))
  631. return hr;
  632. // Initialize the return buffer accordingly
  633. pArray = V_ARRAY(&var);
  634. dwSize = SafeArrayGetDim(pArray);
  635. hr = SafeArrayGetLBound(pArray, 1, (LONG*)&dwLow);
  636. if (FAILED (hr))
  637. return DsrTraceEx(hr, "DsrSidInit: %x unable to get lbound", hr);
  638. hr = SafeArrayGetUBound(pArray, 1, (LONG*)&dwHigh);
  639. if (FAILED (hr))
  640. return DsrTraceEx(hr, "DsrSidInit: %x unable to get ubound", hr);
  641. DsrTraceEx (
  642. 0,
  643. "DsrSidInit: Dim=%d, Low=%d, High=%d",
  644. dwSize,
  645. dwLow,
  646. dwHigh);
  647. // Allocate the sid
  648. if ((pbRet = (BYTE*)DsrAlloc((dwHigh - dwLow) + 2, TRUE)) == NULL) {
  649. return DsrTraceEx (
  650. ERROR_NOT_ENOUGH_MEMORY,
  651. "DsrSidInit: Unable to alloc");
  652. }
  653. // Copy in the bytes of the SID
  654. i = dwLow;
  655. while (TRUE) {
  656. hr = SafeArrayGetElement(pArray, (LONG*)&i, (VOID*)(&(pbRet[i])));
  657. if (FAILED (hr))
  658. break;
  659. i++;
  660. }
  661. DsrTraceEx(0, "DsrSidInit: copied %d bytes", i);
  662. *ppbSid = pbRet;
  663. {
  664. PUCHAR puSA;
  665. DsrTraceEx (0, "DsrSidInit: Sid Length: %d", GetLengthSid(pbRet));
  666. puSA = GetSidSubAuthorityCount(pbRet);
  667. if (puSA)
  668. DsrTraceEx (0, "DsrSidInit: Sid SA Count: %d", *puSA);
  669. }
  670. return NO_ERROR;
  671. }
  672. //
  673. // Generates the ascii equivalent (suitable for submission as part of
  674. // a query against the DS) of a SID based on a base SID and a sub authority
  675. // to be appeneded.
  676. //
  677. HRESULT
  678. DsrSidInitAscii(
  679. IN LPBYTE pBaseSid,
  680. IN DWORD dwSubAuthority,
  681. OUT PWCHAR* ppszSid)
  682. {
  683. DWORD dwLen, dwSidLen, i;
  684. WCHAR* pszRet = NULL;
  685. PUCHAR puCount;
  686. LPBYTE pByte;
  687. // Calculate the length of the returned buffer
  688. dwSidLen = GetLengthSid(pBaseSid);
  689. dwLen = (dwSidLen * 2) + sizeof(DWORD) + 1;
  690. dwLen *= sizeof (WCHAR);
  691. // we put '\' before each byte, so double the size
  692. dwLen *= 2;
  693. // Allocate the return buffer
  694. pszRet = (PWCHAR) DsrAlloc(dwLen, TRUE);
  695. if (pszRet == NULL)
  696. return E_OUTOFMEMORY;
  697. // Increment the sub authority count
  698. puCount = GetSidSubAuthorityCount(pBaseSid);
  699. *puCount = *puCount + 1;
  700. // Copy the bytes
  701. for (i = 0; i < dwSidLen; i++) {
  702. pszRet[i*3] = L'\\';
  703. wsprintfW(&(pszRet[i*3+1]), L"%02x", (DWORD)pBaseSid[i]);
  704. }
  705. // Append the bytes for the new sub authority
  706. pByte = (LPBYTE)&(dwSubAuthority);
  707. for (; i < dwSidLen + sizeof(DWORD); i++) {
  708. pszRet[i*3] = L'\\';
  709. wsprintfW(&(pszRet[i*3+1]), L"%02x", (DWORD)pByte[i-dwSidLen]);
  710. }
  711. // Decrement the sub authority count -- restoring the
  712. // base sid.
  713. *puCount = *puCount - 1;
  714. *ppszSid = pszRet;
  715. return NO_ERROR;
  716. }
  717. //
  718. // Searches given domain for a computer account
  719. // with the given name and returns its ADsPath
  720. // if found.
  721. //
  722. DWORD
  723. DsrFindDomainComputer (
  724. IN PWCHAR pszDomain,
  725. IN PWCHAR pszComputer,
  726. OUT PWCHAR* ppszADsPath)
  727. {
  728. HRESULT hr = S_OK;
  729. DWORD dwLen, dwSrchAttribCount;
  730. IDirectorySearch * pSearch = NULL;
  731. PWCHAR pszDomainPath = NULL, pszFilter = NULL;
  732. PWCHAR pszBase, pszPrefix;
  733. ADS_SEARCH_HANDLE hSearch = NULL;
  734. ADS_SEARCH_COLUMN adsColumn;
  735. PWCHAR ppszSrchAttribs[] =
  736. {
  737. (PWCHAR)pszDn,
  738. NULL
  739. };
  740. BOOL bSearchGC = FALSE;
  741. do {
  742. // Validate parameters
  743. if (!pszDomain || !pszComputer || !ppszADsPath) {
  744. hr = ERROR_INVALID_PARAMETER;
  745. break;
  746. }
  747. // Decide whether to search the GC or the domain
  748. // object
  749. if (bSearchGC) {
  750. pszBase = (PWCHAR)pszGC;
  751. pszPrefix = (PWCHAR)pszGCPrefix;
  752. }
  753. else {
  754. pszBase = (PWCHAR)pszLdap;
  755. pszPrefix = (PWCHAR)pszLdapPrefix;
  756. }
  757. // Allocate the domain path
  758. dwLen = (pszDomain) ? wcslen(pszDomain) : 0;
  759. dwLen += wcslen(pszPrefix) + 1;
  760. dwLen *= sizeof(WCHAR);
  761. pszDomainPath = (PWCHAR) DsrAlloc(dwLen, FALSE);
  762. if (pszDomainPath == NULL) {
  763. hr = ERROR_NOT_ENOUGH_MEMORY;
  764. break;
  765. }
  766. // Format the domain path
  767. if (pszDomain) {
  768. wcscpy(pszDomainPath, pszPrefix);
  769. wcscat(pszDomainPath, pszDomain);
  770. }
  771. else
  772. wcscpy(pszDomainPath, pszBase);
  773. // Get a reference to the object to search
  774. // (either domain object or GC)
  775. hr = ADsGetObject (
  776. pszDomainPath,
  777. IID_IDirectorySearch,
  778. (VOID**)&pSearch);
  779. if (FAILED (hr))
  780. break;
  781. // Prepare the search filter
  782. //
  783. dwLen = wcslen(pszCompFilterFmt) + wcslen(pszComputer) + 1;
  784. dwLen *= sizeof(WCHAR);
  785. pszFilter = (PWCHAR) DsrAlloc(dwLen, FALSE);
  786. if (pszFilter == NULL) {
  787. hr = ERROR_NOT_ENOUGH_MEMORY;
  788. break;
  789. }
  790. wsprintfW(pszFilter, pszCompFilterFmt, pszComputer);
  791. // Count the number of attributes we're searching
  792. // for
  793. if (ppszSrchAttribs == NULL)
  794. dwSrchAttribCount = (DWORD)-1;
  795. else {
  796. for (dwSrchAttribCount = 0;
  797. ppszSrchAttribs[dwSrchAttribCount];
  798. dwSrchAttribCount++);
  799. }
  800. // Search the DS
  801. hr = pSearch->ExecuteSearch(
  802. pszFilter,
  803. ppszSrchAttribs,
  804. dwSrchAttribCount,
  805. &hSearch);
  806. if (FAILED (hr))
  807. break;
  808. // Get the first result
  809. hr = pSearch->GetNextRow(hSearch);
  810. if (hr == S_ADS_NOMORE_ROWS) {
  811. hr = ERROR_NOT_FOUND;
  812. break;
  813. }
  814. // Get the attribute we're interested in
  815. hr = pSearch->GetColumn(hSearch, (PWCHAR)pszDn, &adsColumn);
  816. if (SUCCEEDED (hr)) {
  817. dwLen = wcslen(adsColumn.pADsValues[0].PrintableString) +
  818. wcslen(pszLdapPrefix) +
  819. 1;
  820. dwLen *= 2;
  821. *ppszADsPath = (PWCHAR) DsrAlloc(dwLen, FALSE);
  822. if (*ppszADsPath == NULL)
  823. {
  824. pSearch->FreeColumn(&adsColumn);
  825. hr = ERROR_NOT_ENOUGH_MEMORY;
  826. break;
  827. }
  828. wcscpy(*ppszADsPath, pszLdapPrefix);
  829. wcscat(*ppszADsPath, adsColumn.pADsValues[0].PrintableString);
  830. pSearch->FreeColumn (&adsColumn);
  831. hr = NO_ERROR;
  832. }
  833. } while (FALSE);
  834. // Cleanup
  835. {
  836. if (hSearch)
  837. pSearch->CloseSearchHandle(hSearch);
  838. DSR_FREE (pszDomainPath);
  839. DSR_FREE (pszFilter);
  840. DSR_RELEASE (pSearch);
  841. }
  842. return DSR_ERROR(hr);
  843. }
  844. //
  845. // Searches given domain for the well known
  846. // "RAS and IAS Servers" group and returns
  847. // its ADsPath if found.
  848. //
  849. DWORD
  850. DsrFindRasServersGroup (
  851. IN PWCHAR pszDomain,
  852. OUT PWCHAR* ppszADsPath)
  853. {
  854. HRESULT hr = S_OK;
  855. DWORD dwLen, dwSrchAttribCount, dwErr;
  856. IDirectorySearch * pSearch = NULL;
  857. IADs * pIads = NULL;
  858. PWCHAR pszDomainPath = NULL, pszFilter = NULL;
  859. PWCHAR pszBase, pszPrefix, pszGroupSid = NULL;
  860. ADS_SEARCH_HANDLE hSearch = NULL;
  861. ADS_SEARCH_COLUMN adsColumn;
  862. PWCHAR ppszSrchAttribs[] =
  863. {
  864. (PWCHAR)pszDn,
  865. NULL
  866. };
  867. BOOL bSearchGC = FALSE;
  868. VARIANT var;
  869. LPBYTE pDomainSid = NULL;
  870. BSTR bstrSid = NULL;
  871. do {
  872. // Validate parameters
  873. if (!pszDomain || !ppszADsPath) {
  874. hr = ERROR_INVALID_PARAMETER;
  875. break;
  876. }
  877. // Decide whether to search the GC or the domain
  878. // object
  879. if (bSearchGC) {
  880. pszBase = (PWCHAR)pszGC;
  881. pszPrefix = (PWCHAR)pszGCPrefix;
  882. }
  883. else {
  884. pszBase = (PWCHAR)pszLdap;
  885. pszPrefix = (PWCHAR)pszLdapPrefix;
  886. }
  887. // Allocate the domain path
  888. dwLen = wcslen(pszDomain) + wcslen(pszPrefix) + 1;
  889. dwLen *= sizeof(WCHAR);
  890. pszDomainPath = (PWCHAR) DsrAlloc(dwLen, FALSE);
  891. if (pszDomainPath == NULL) {
  892. hr = ERROR_NOT_ENOUGH_MEMORY;
  893. break;
  894. }
  895. // Format the domain path
  896. wcscpy(pszDomainPath, pszPrefix);
  897. wcscat(pszDomainPath, pszDomain);
  898. // Get a reference to the object to search
  899. // (either domain object or GC)
  900. hr = ADsGetObject (
  901. pszDomainPath,
  902. IID_IDirectorySearch,
  903. (VOID**)&pSearch);
  904. if (FAILED (hr))
  905. break;
  906. // Get IADs reference to domain object
  907. hr = pSearch->QueryInterface(IID_IADs, (VOID**)&pIads);
  908. if (FAILED (hr))
  909. break;
  910. // Get the SID of the domain object
  911. VariantInit(&var);
  912. bstrSid = SysAllocString(pszSid);
  913. if (bstrSid == NULL)
  914. {
  915. hr = ERROR_NOT_ENOUGH_MEMORY;
  916. break;
  917. }
  918. hr = pIads->GetEx(bstrSid, &var);
  919. if (FAILED (hr))
  920. {
  921. break;
  922. }
  923. dwErr = DsrSidInit(&var, &pDomainSid);
  924. if (dwErr != NO_ERROR) {
  925. hr = dwErr;
  926. break;
  927. }
  928. VariantClear(&var);
  929. // Prepare the ascii version of the "RAS and IAS Servers" SID
  930. // for use in querying the DC
  931. hr = DsrSidInitAscii(
  932. pDomainSid,
  933. DOMAIN_ALIAS_RID_RAS_SERVERS,
  934. &pszGroupSid);
  935. if (FAILED (hr))
  936. break;
  937. DsrTraceEx(0, "GroupSid = %ls", pszGroupSid);
  938. // Prepare the search filter
  939. //
  940. dwLen = (wcslen(pszGroupFilterFmt) + wcslen(pszGroupSid) + 1);
  941. dwLen *= sizeof(WCHAR);
  942. pszFilter = (PWCHAR) DsrAlloc(dwLen, FALSE);
  943. if (pszFilter == NULL) {
  944. hr = ERROR_NOT_ENOUGH_MEMORY;
  945. break;
  946. }
  947. wsprintfW(pszFilter, pszGroupFilterFmt, pszGroupSid);
  948. // Count the number of attributes we're searching
  949. // for
  950. if (ppszSrchAttribs == NULL)
  951. dwSrchAttribCount = (DWORD)-1;
  952. else
  953. {
  954. for (dwSrchAttribCount = 0;
  955. ppszSrchAttribs[dwSrchAttribCount];
  956. dwSrchAttribCount++);
  957. }
  958. // Search the DS
  959. hr = pSearch->ExecuteSearch(
  960. pszFilter,
  961. ppszSrchAttribs,
  962. dwSrchAttribCount,
  963. &hSearch);
  964. if (FAILED (hr))
  965. break;
  966. // Get the first result
  967. hr = pSearch->GetNextRow(hSearch);
  968. if (hr == S_ADS_NOMORE_ROWS) {
  969. hr = ERROR_NOT_FOUND;
  970. break;
  971. }
  972. // Get the attribute we're interested in
  973. hr = pSearch->GetColumn(hSearch, (PWCHAR)pszDn, &adsColumn);
  974. if (SUCCEEDED (hr))
  975. {
  976. dwLen = wcslen(adsColumn.pADsValues[0].PrintableString) +
  977. wcslen(pszLdapPrefix) +
  978. 1;
  979. dwLen *= sizeof(WCHAR);
  980. *ppszADsPath = (PWCHAR) DsrAlloc(dwLen, FALSE);
  981. if (*ppszADsPath == NULL)
  982. {
  983. pSearch->FreeColumn(&adsColumn);
  984. hr = ERROR_NOT_ENOUGH_MEMORY;
  985. break;
  986. }
  987. wsprintfW(
  988. *ppszADsPath,
  989. L"%s%s",
  990. pszLdapPrefix,
  991. adsColumn.pADsValues[0].PrintableString);
  992. pSearch->FreeColumn(&adsColumn);
  993. hr = NO_ERROR;
  994. }
  995. } while (FALSE);
  996. // Cleanup
  997. {
  998. if (hSearch)
  999. pSearch->CloseSearchHandle(hSearch);
  1000. DSR_FREE (pszDomainPath);
  1001. DSR_FREE (pszFilter);
  1002. DSR_FREE (pDomainSid);
  1003. DSR_FREE (pszGroupSid);
  1004. DSR_RELEASE (pSearch);
  1005. DSR_RELEASE (pIads);
  1006. if (bstrSid)
  1007. SysFreeString(bstrSid);
  1008. }
  1009. return DSR_ERROR(hr);
  1010. }
  1011. //
  1012. // Adds or removes a given object from a given group.
  1013. //
  1014. DWORD
  1015. DsrGroupAddRemoveMember(
  1016. IN PWCHAR pszGroupDN,
  1017. IN PWCHAR pszNewMemberDN,
  1018. IN BOOL bAdd)
  1019. {
  1020. VARIANT_BOOL vbIsMember = VARIANT_FALSE;
  1021. IADsGroup* pGroup = NULL;
  1022. HRESULT hr = S_OK;
  1023. DsrTraceEx (
  1024. 0,
  1025. "DsrGroupAddRemoveMember entered for [%S] [%S]",
  1026. pszGroupDN,
  1027. pszNewMemberDN);
  1028. do
  1029. {
  1030. // Get a reference to the group
  1031. hr = ADsGetObject (pszGroupDN, IID_IADsGroup, (VOID**)&pGroup);
  1032. if (FAILED (hr))
  1033. {
  1034. DsrTraceEx(
  1035. hr,
  1036. "DsrGroupAddRemoveMember: %x from ADsGetObject(%S)",
  1037. hr,
  1038. pszGroupDN);
  1039. break;
  1040. }
  1041. // Find out if the given new member is in the group
  1042. hr = pGroup->IsMember (pszNewMemberDN, &vbIsMember);
  1043. if (FAILED (hr))
  1044. {
  1045. DsrTraceEx (
  1046. hr,
  1047. "DsrGroupAddRemoveMember: %x from IsMember\n",
  1048. hr);
  1049. break;
  1050. }
  1051. // Add the object to the group and flush the cache
  1052. if (bAdd)
  1053. {
  1054. if (vbIsMember == VARIANT_FALSE)
  1055. {
  1056. hr = pGroup->Add (pszNewMemberDN);
  1057. }
  1058. }
  1059. else
  1060. {
  1061. if (vbIsMember == VARIANT_TRUE)
  1062. {
  1063. hr = pGroup->Remove (pszNewMemberDN);
  1064. }
  1065. }
  1066. // If the new member is already in the group, the error code
  1067. // is ERROR_DS_CONSTRAINT_VIOLATION. I suspect this may change.
  1068. //
  1069. if (hr == ERROR_DS_CONSTRAINT_VIOLATION)
  1070. {
  1071. hr = ERROR_ALREADY_EXISTS;
  1072. break;
  1073. }
  1074. if (FAILED (hr))
  1075. {
  1076. DsrTraceEx(
  1077. hr,
  1078. "DsrGroupAddRemoveMember: %x from Add/Remove",
  1079. hr);
  1080. break;
  1081. }
  1082. } while (FALSE);
  1083. // Cleanup
  1084. {
  1085. DSR_RELEASE(pGroup);
  1086. }
  1087. return DSR_ERROR(hr);
  1088. }
  1089. //
  1090. // Returns whether the given object is a member of
  1091. // the given group.
  1092. //
  1093. DWORD
  1094. DsrGroupIsMember(
  1095. IN PWCHAR pszGroupDN,
  1096. IN PWCHAR pszObjectDN,
  1097. OUT PBOOL pbIsMember)
  1098. {
  1099. IADsGroup * pGroup = NULL;
  1100. HRESULT hr = S_OK;
  1101. VARIANT_BOOL vbIsMember = VARIANT_FALSE;
  1102. DsrTraceEx (
  1103. 0,
  1104. "DsrGroupIsMember: entered [%S] [%S].",
  1105. pszGroupDN,
  1106. pszObjectDN);
  1107. do
  1108. {
  1109. // Get a reference to the group
  1110. hr = ADsGetObject (pszGroupDN, IID_IADsGroup, (VOID**)&pGroup);
  1111. if (FAILED (hr))
  1112. {
  1113. DsrTraceEx (
  1114. hr,
  1115. "DsrGroupIsMember: %x returned when opening %S",
  1116. hr,
  1117. pszGroupDN);
  1118. *pbIsMember = FALSE;
  1119. hr = NO_ERROR;
  1120. break;
  1121. }
  1122. // Find out if the object is a member
  1123. hr = pGroup->IsMember (pszObjectDN, &vbIsMember);
  1124. if (FAILED (hr))
  1125. {
  1126. DsrTraceEx (hr, "DsrGroupIsMember: %x from IsMember\n", hr);
  1127. break;
  1128. }
  1129. *pbIsMember = (vbIsMember == VARIANT_TRUE) ? TRUE : FALSE;
  1130. } while (FALSE);
  1131. // Cleanup
  1132. {
  1133. DSR_RELEASE(pGroup);
  1134. }
  1135. return DSR_ERROR(hr);
  1136. }
  1137. //
  1138. // Applies the aces in the given access settings to the
  1139. // appropriate domain.
  1140. //
  1141. HRESULT
  1142. DsrAceAppAdd(
  1143. IN DWORD dwMode,
  1144. IN PWCHAR pszDC,
  1145. IN DSR_ACE_APPLICATION* pAces,
  1146. IN DWORD dwCount)
  1147. {
  1148. HRESULT hr = S_OK;
  1149. DSR_ACE_APPLICATION* pAceApp = NULL;
  1150. DWORD i, j;
  1151. do
  1152. {
  1153. // Add the ACES to the domain objects
  1154. //
  1155. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1156. {
  1157. for (j = 0; j < pAceApp->dwCount; j++)
  1158. {
  1159. if (pAceApp->pAces[j].dwMode != dwMode)
  1160. {
  1161. continue;
  1162. }
  1163. hr = DsrAceAdd(
  1164. pszDC,
  1165. pAceApp->pObject,
  1166. &(pAceApp->pAces[j]));
  1167. DSR_BREAK_ON_FAILED_HR( hr );
  1168. }
  1169. }
  1170. DSR_BREAK_ON_FAILED_HR( hr );
  1171. // Commit the ACE's to the domain objects.
  1172. //
  1173. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1174. {
  1175. hr = pAceApp->pObject->SetInfo();
  1176. DSR_BREAK_ON_FAILED_HR( hr );
  1177. }
  1178. DSR_BREAK_ON_FAILED_HR( hr );
  1179. } while (FALSE);
  1180. // Cleanup
  1181. {
  1182. }
  1183. return hr;
  1184. }
  1185. //
  1186. // Releases the resources held by an ace application
  1187. //
  1188. HRESULT
  1189. DsrAceAppCleanup(
  1190. IN DSR_ACE_APPLICATION* pAces,
  1191. IN DWORD dwCount)
  1192. {
  1193. DSR_ACE_APPLICATION* pAceApp = NULL;
  1194. DWORD i, j;
  1195. if (pAces)
  1196. {
  1197. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1198. {
  1199. DSR_RELEASE(pAceApp->pObject);
  1200. for (j = 0; j < pAceApp->dwCount; j++)
  1201. {
  1202. DsrAceDescClear(&(pAceApp->pAces[j]));
  1203. }
  1204. }
  1205. DSR_FREE(pAces);
  1206. }
  1207. return NO_ERROR;
  1208. }
  1209. //
  1210. // Generates a list of ace applications based on a list
  1211. // of ace application descriptions
  1212. //
  1213. HRESULT
  1214. DsrAceAppFromAppDesc(
  1215. IN DSR_ACE_APPLICATION_DESC* pDesc,
  1216. IN DWORD dwCount,
  1217. IN IADsContainer* pContainer,
  1218. IN IADs* pDefault,
  1219. OUT DSR_ACE_APPLICATION** ppAceApp,
  1220. OUT LPDWORD lpdwCount)
  1221. {
  1222. DSR_ACE_APPLICATION* pAceApp = NULL, *pCurApp = NULL;
  1223. DSR_ACE_APPLICATION_DESC* pAceAppDesc = NULL;
  1224. IDispatch* pDispatch = NULL;
  1225. HRESULT hr = S_OK;
  1226. DWORD i, j;
  1227. do
  1228. {
  1229. // Allocate and zero the ACE list
  1230. //
  1231. pAceApp = (DSR_ACE_APPLICATION*)
  1232. DsrAlloc(sizeof(DSR_ACE_APPLICATION) * dwCount, TRUE);
  1233. if (pAceApp == NULL)
  1234. {
  1235. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  1236. }
  1237. // Set up the ACE applications
  1238. //
  1239. for (i = 0, pAceAppDesc = pDesc, pCurApp = pAceApp;
  1240. i < dwCount;
  1241. i++, pAceAppDesc++, pCurApp++)
  1242. {
  1243. // Allocate the appropriate number of ace
  1244. // descriptors
  1245. //
  1246. pCurApp->pAces = (DSR_ACE_DESCRIPTOR*)
  1247. DsrAlloc(
  1248. sizeof(DSR_ACE_DESCRIPTOR) * pAceAppDesc->dwCount,
  1249. TRUE);
  1250. if (pCurApp->pAces == NULL)
  1251. {
  1252. hr = E_OUTOFMEMORY;
  1253. break;
  1254. }
  1255. pCurApp->dwCount = pAceAppDesc->dwCount;
  1256. // Get the desired object in the DS
  1257. //
  1258. if (pAceAppDesc->pszObjectCN)
  1259. {
  1260. hr = pContainer->GetObject(
  1261. pAceAppDesc->pszObjectClass,
  1262. pAceAppDesc->pszObjectCN,
  1263. &pDispatch);
  1264. DSR_BREAK_ON_FAILED_HR( hr );
  1265. hr = pDispatch->QueryInterface(
  1266. IID_IADs,
  1267. (VOID**)&(pCurApp->pObject));
  1268. DSR_BREAK_ON_FAILED_HR( hr );
  1269. pDispatch->Release();
  1270. pDispatch = NULL;
  1271. }
  1272. else
  1273. {
  1274. pCurApp->pObject = pDefault;
  1275. pCurApp->pObject->AddRef();
  1276. }
  1277. // Copy over the ACE information
  1278. //
  1279. for (j = 0; j < pCurApp->dwCount; j++)
  1280. {
  1281. hr = DsrAceDescCopy(
  1282. &(pCurApp->pAces[j]),
  1283. &(pAceAppDesc->pAces[j]));
  1284. DSR_BREAK_ON_FAILED_HR( hr );
  1285. }
  1286. DSR_BREAK_ON_FAILED_HR( hr );
  1287. }
  1288. DSR_BREAK_ON_FAILED_HR( hr );
  1289. // Assign the return values
  1290. *ppAceApp = pAceApp;
  1291. *lpdwCount = dwCount;
  1292. } while (FALSE);
  1293. // Cleanup
  1294. {
  1295. if (FAILED(hr))
  1296. {
  1297. DsrAceAppCleanup(pAceApp, i);
  1298. }
  1299. }
  1300. return hr;
  1301. }
  1302. //
  1303. // Discovers whether a set of aces is present in the given
  1304. // domain.
  1305. //
  1306. HRESULT
  1307. DsrAceAppQueryPresence(
  1308. IN PWCHAR pszDC,
  1309. IN DSR_ACE_APPLICATION* pAces,
  1310. IN DWORD dwCount,
  1311. IN DWORD dwMode,
  1312. OUT PBOOL pbPresent)
  1313. {
  1314. DSR_ACE_APPLICATION* pAceApp = NULL;
  1315. IADsSecurityDescriptor* pSD = NULL;
  1316. IADsAccessControlList* pAcl = NULL;
  1317. IDispatch* pAce = NULL;
  1318. VARIANT varSD;
  1319. HRESULT hr = S_OK;
  1320. BOOL bEnabled = FALSE, bOk = TRUE;
  1321. DWORD i, j;
  1322. do
  1323. {
  1324. // Initialize
  1325. *pbPresent = FALSE;
  1326. VariantInit(&varSD);
  1327. // Find out if the ACES are set
  1328. //
  1329. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1330. {
  1331. for (j = 0; j < pAceApp->dwCount; j++)
  1332. {
  1333. // Only validate aces that pertain to the
  1334. // given mode
  1335. //
  1336. if (pAceApp->pAces[j].dwMode != dwMode)
  1337. {
  1338. continue;
  1339. }
  1340. hr = DsrAceFind(
  1341. pszDC,
  1342. pAceApp->pObject,
  1343. &(pAceApp->pAces[j]),
  1344. &varSD,
  1345. &pSD,
  1346. &pAcl,
  1347. &pAce);
  1348. DSR_BREAK_ON_FAILED_HR( hr );
  1349. // We're enabled so long as we don't find
  1350. // a missing ACE
  1351. //
  1352. bOk = (pAce != NULL);
  1353. // Cleanup
  1354. //
  1355. DSR_RELEASE( pAce );
  1356. DSR_RELEASE( pAcl );
  1357. DSR_RELEASE( pSD );
  1358. VariantClear(&varSD);
  1359. pAce = NULL;
  1360. pAcl = NULL;
  1361. pSD = NULL;
  1362. // Break if we find out we're not enabled
  1363. //
  1364. if (bOk == FALSE)
  1365. {
  1366. break;
  1367. }
  1368. }
  1369. // Break if we find out we're not enabled
  1370. //
  1371. if (bOk == FALSE)
  1372. {
  1373. break;
  1374. }
  1375. }
  1376. DSR_BREAK_ON_FAILED_HR( hr );
  1377. *pbPresent = bOk;
  1378. } while (FALSE);
  1379. // Cleanup
  1380. {
  1381. }
  1382. return hr;
  1383. }
  1384. //
  1385. // Applies the aces in the given access settings to the
  1386. // appropriate domain.
  1387. //
  1388. HRESULT
  1389. DsrAceAppRemove(
  1390. IN DWORD dwMode,
  1391. IN PWCHAR pszDC,
  1392. IN DSR_ACE_APPLICATION* pAces,
  1393. IN DWORD dwCount)
  1394. {
  1395. HRESULT hr = S_OK;
  1396. DSR_ACE_APPLICATION* pAceApp = NULL;
  1397. DWORD i, j;
  1398. do
  1399. {
  1400. // Add/Del the ACES to the domain objects
  1401. //
  1402. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1403. {
  1404. for (j = 0; j < pAceApp->dwCount; j++)
  1405. {
  1406. if (pAceApp->pAces[j].dwMode != dwMode)
  1407. {
  1408. continue;
  1409. }
  1410. hr = DsrAceRemove(
  1411. pszDC,
  1412. pAceApp->pObject,
  1413. &(pAceApp->pAces[j]));
  1414. DSR_BREAK_ON_FAILED_HR( hr );
  1415. }
  1416. }
  1417. DSR_BREAK_ON_FAILED_HR( hr );
  1418. // Commit the ACE's to the domain objects.
  1419. //
  1420. for (i = 0, pAceApp = pAces; i < dwCount; i++, pAceApp++)
  1421. {
  1422. hr = pAceApp->pObject->SetInfo();
  1423. DSR_BREAK_ON_FAILED_HR( hr );
  1424. }
  1425. DSR_BREAK_ON_FAILED_HR( hr );
  1426. } while (FALSE);
  1427. // Cleanup
  1428. {
  1429. }
  1430. return hr;
  1431. }
  1432. //
  1433. // Clear the dsr ace parameters
  1434. //
  1435. DWORD
  1436. DsrAceDescClear(
  1437. IN DSR_ACE_DESCRIPTOR* pParams)
  1438. {
  1439. if (pParams)
  1440. {
  1441. if (pParams->bstrTrustee)
  1442. {
  1443. SysFreeString(pParams->bstrTrustee);
  1444. }
  1445. if (pParams->bstrObjectType)
  1446. {
  1447. SysFreeString(pParams->bstrObjectType);
  1448. }
  1449. if (pParams->bstrInheritedObjectType)
  1450. {
  1451. SysFreeString(pParams->bstrInheritedObjectType);
  1452. }
  1453. ZeroMemory(pParams, sizeof(DSR_ACE_DESCRIPTOR));
  1454. }
  1455. return NO_ERROR;
  1456. }
  1457. //
  1458. // Returns 0 if ACE descriptors are describing the same ACE.
  1459. // FALSE, otherwise.
  1460. //
  1461. HRESULT
  1462. DsrAceDescCompare(
  1463. IN DSR_ACE_DESCRIPTOR* pAce1,
  1464. IN DSR_ACE_DESCRIPTOR* pAce2)
  1465. {
  1466. DWORD dw1, dw2;
  1467. // Compare the non-string fields so that we can rule things
  1468. // out w/o string compares if possible
  1469. //
  1470. if (
  1471. (pAce1->dwAccessMask != pAce2->dwAccessMask) ||
  1472. (pAce1->dwAceFlags != pAce2->dwAceFlags) ||
  1473. (pAce1->dwAceType != pAce2->dwAceType) ||
  1474. (pAce1->dwFlags != pAce2->dwFlags)
  1475. )
  1476. {
  1477. return 1;
  1478. }
  1479. // Compare the strings
  1480. //
  1481. if ((DsrStrCompare(pAce1->bstrTrustee, pAce2->bstrTrustee)) ||
  1482. (DsrStrCompare(pAce1->bstrObjectType, pAce2->bstrObjectType)) ||
  1483. (DsrStrCompare(pAce1->bstrInheritedObjectType,
  1484. pAce2->bstrInheritedObjectType))
  1485. )
  1486. {
  1487. return 1;
  1488. }
  1489. // Return success
  1490. //
  1491. return 0;
  1492. }
  1493. //
  1494. // Copy over the ACE information
  1495. //
  1496. HRESULT
  1497. DsrAceDescCopy(
  1498. OUT DSR_ACE_DESCRIPTOR* pDst,
  1499. IN DSR_ACE_DESCRIPTOR* pSrc)
  1500. {
  1501. HRESULT hr = S_OK;
  1502. do
  1503. {
  1504. // Initialize the ACE parameters
  1505. *pDst = *pSrc;
  1506. if (pSrc->bstrTrustee)
  1507. {
  1508. pDst->bstrTrustee =
  1509. SysAllocString(pSrc->bstrTrustee);
  1510. if (pDst->bstrTrustee == NULL)
  1511. {
  1512. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  1513. }
  1514. }
  1515. if (pSrc->bstrObjectType)
  1516. {
  1517. pDst->bstrObjectType =
  1518. SysAllocString(pSrc->bstrObjectType);
  1519. if (pDst->bstrObjectType == NULL)
  1520. {
  1521. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  1522. }
  1523. }
  1524. if (pSrc->bstrInheritedObjectType)
  1525. {
  1526. pDst->bstrInheritedObjectType =
  1527. SysAllocString(pSrc->bstrInheritedObjectType);
  1528. if (pDst->bstrInheritedObjectType == NULL)
  1529. {
  1530. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  1531. }
  1532. }
  1533. } while (FALSE);
  1534. // Cleanup
  1535. {
  1536. if (FAILED( hr ))
  1537. {
  1538. if (pDst->bstrTrustee)
  1539. {
  1540. SysFreeString(pDst->bstrTrustee);
  1541. }
  1542. if (pDst->bstrObjectType)
  1543. {
  1544. SysFreeString(pDst->bstrObjectType);
  1545. }
  1546. if (pDst->bstrInheritedObjectType)
  1547. {
  1548. SysFreeString(pDst->bstrInheritedObjectType);
  1549. }
  1550. }
  1551. }
  1552. return hr;
  1553. }
  1554. //
  1555. // Populates the given ACE descriptor with the values from
  1556. // the given ACE.
  1557. //
  1558. HRESULT
  1559. DsrAceDescFromIadsAce(
  1560. IN PWCHAR pszDC,
  1561. IN IADsAccessControlEntry* pAce,
  1562. IN DSR_ACE_DESCRIPTOR* pAceParams)
  1563. {
  1564. HRESULT hr = S_OK;
  1565. BSTR bstrTrustee = NULL;
  1566. PWCHAR pszSid, pszDomain;
  1567. PBYTE pbSid;
  1568. DWORD dwSidSize, dwDomainSize;
  1569. BOOL bOk;
  1570. SID_NAME_USE SidNameUse;
  1571. pszSid = (PWCHAR) DsrAlloc(sizeof(WCHAR)*1024, FALSE);
  1572. pszDomain = (PWCHAR) DsrAlloc(sizeof(WCHAR)*1024, FALSE);
  1573. pbSid = (PBYTE) DsrAlloc(sizeof(BYTE)*1024, FALSE);
  1574. if (!pszSid || !pszDomain || !pbSid) {
  1575. if (pszSid)
  1576. DsrFree(pszSid);
  1577. if (pszDomain)
  1578. DsrFree(pszDomain);
  1579. if (pbSid)
  1580. DsrFree(pbSid);
  1581. return E_OUTOFMEMORY;
  1582. }
  1583. do
  1584. {
  1585. hr = pAce->get_AccessMask(&(pAceParams->dwAccessMask));
  1586. DSR_BREAK_ON_FAILED_HR( hr );
  1587. hr = pAce->get_AceType(&(pAceParams->dwAceType));
  1588. DSR_BREAK_ON_FAILED_HR( hr );
  1589. hr = pAce->get_AceFlags(&(pAceParams->dwAceFlags));
  1590. DSR_BREAK_ON_FAILED_HR( hr );
  1591. hr = pAce->get_Flags(&(pAceParams->dwFlags));
  1592. DSR_BREAK_ON_FAILED_HR( hr );
  1593. hr = pAce->get_ObjectType(&(pAceParams->bstrObjectType));
  1594. DSR_BREAK_ON_FAILED_HR( hr );
  1595. hr = pAce->get_InheritedObjectType(
  1596. &(pAceParams->bstrInheritedObjectType));
  1597. DSR_BREAK_ON_FAILED_HR( hr );
  1598. hr = pAce->get_Trustee(&bstrTrustee);
  1599. DSR_BREAK_ON_FAILED_HR( hr );
  1600. // Get the SID of the trustee
  1601. //
  1602. dwSidSize = sizeof(pbSid);
  1603. dwDomainSize = sizeof(pszDomain) / sizeof(WCHAR);
  1604. bOk = LookupAccountName(
  1605. pszDC,
  1606. bstrTrustee,
  1607. (PSID)pbSid,
  1608. &dwSidSize,
  1609. pszDomain,
  1610. &dwDomainSize,
  1611. &SidNameUse);
  1612. if (bOk == FALSE)
  1613. {
  1614. hr = GetLastError();
  1615. break;
  1616. }
  1617. // Convert the sid to a string
  1618. //
  1619. hr = DsrStrFromSID((PSID)pbSid, pszSid, sizeof(pszSid));
  1620. if (hr != NO_ERROR)
  1621. {
  1622. break;
  1623. }
  1624. // Create the trustee accordingly
  1625. //
  1626. pAceParams->bstrTrustee = SysAllocString(pszSid);
  1627. if (pAceParams->bstrTrustee == NULL)
  1628. {
  1629. hr = E_OUTOFMEMORY;
  1630. break;
  1631. }
  1632. } while (FALSE);
  1633. // Cleanup
  1634. {
  1635. if (bstrTrustee)
  1636. {
  1637. SysFreeString(bstrTrustee);
  1638. }
  1639. if (FAILED(hr))
  1640. {
  1641. DsrAceDescClear(pAceParams);
  1642. }
  1643. }
  1644. DsrFree(pszSid);
  1645. DsrFree(pszDomain);
  1646. DsrFree(pbSid);
  1647. return hr;
  1648. }
  1649. PWCHAR
  1650. DsrAceAttrToString(
  1651. IN PWCHAR pszObjectType)
  1652. {
  1653. if (pszObjectType == NULL)
  1654. {
  1655. return L"All";
  1656. }
  1657. else if (lstrcmpi(pszObjectType, pszGuidUserParms) == 0)
  1658. {
  1659. return L"UserParms (BF967A6D-0DE6-11D0-A285-00AA003049E2)";
  1660. }
  1661. else if (lstrcmpi(pszObjectType, pszGuidRasPropSet1) == 0)
  1662. {
  1663. return L"Ras user properties (037088F8-0AE1-11D2-B422-00A0C968F939)";
  1664. }
  1665. else if (lstrcmpi(pszObjectType, pszGuidRasPropSet2) == 0)
  1666. {
  1667. return L"Misc user properties (4C164200-20C0-11D0-A768-00AA006E0529)";
  1668. }
  1669. else if (lstrcmpi(pszObjectType, pszGuidLogonHours) == 0)
  1670. {
  1671. return L"Logon-Hours (BF9679AB-0DE6-11D0-A285-00AA003049E2)";
  1672. }
  1673. else if (lstrcmpi(pszObjectType, pszGuidSamAccountName) == 0)
  1674. {
  1675. return L"Sam account name (3E0ABFD0-126A-11D0-A060-00AA006C33ED)";
  1676. }
  1677. return pszObjectType;
  1678. }
  1679. PWCHAR
  1680. DsrAceApplyToString(
  1681. IN PWCHAR pszApply)
  1682. {
  1683. if (pszApply == NULL)
  1684. {
  1685. return L"This object";
  1686. }
  1687. else if (lstrcmpi(pszApply, pszGuidUserClass) == 0)
  1688. {
  1689. return L"User objects (BF967ABA-0DE6-11D0-A285-00aa003049E2)";
  1690. }
  1691. return pszApply;
  1692. }
  1693. PWCHAR
  1694. DsrAceMaskToString(
  1695. IN DWORD dwType,
  1696. IN DWORD dwMask,
  1697. IN PWCHAR pszBuf)
  1698. {
  1699. WCHAR pszTemp[64];
  1700. *pszBuf = L'\0';
  1701. switch (dwType)
  1702. {
  1703. case ADS_ACETYPE_ACCESS_ALLOWED:
  1704. wcscpy(pszBuf, L"Allow: ");
  1705. break;
  1706. case ADS_ACETYPE_ACCESS_DENIED:
  1707. wcscpy(pszBuf, L"Deny: ");
  1708. break;
  1709. case ADS_ACETYPE_SYSTEM_AUDIT:
  1710. wcscpy(pszBuf, L"Audit: ");
  1711. break;
  1712. case ADS_ACETYPE_ACCESS_ALLOWED_OBJECT:
  1713. wcscpy(pszBuf, L"Allow obj: ");
  1714. break;
  1715. case ADS_ACETYPE_ACCESS_DENIED_OBJECT:
  1716. wcscpy(pszBuf, L"Deny obj: ");
  1717. break;
  1718. case ADS_ACETYPE_SYSTEM_AUDIT_OBJECT:
  1719. wcscpy(pszBuf, L"Audit obj: ");
  1720. break;
  1721. }
  1722. wsprintfW(pszTemp, L"(%x): ", dwMask);
  1723. wcscat(pszBuf, pszTemp);
  1724. if (dwMask == DSR_ADS_RIGHT_GENERIC_READ)
  1725. {
  1726. wcscat(pszBuf, L"Generic read");
  1727. }
  1728. else if (dwMask == 0xffffffff)
  1729. {
  1730. wcscat(pszBuf, L"Full control");
  1731. }
  1732. else
  1733. {
  1734. if (dwMask & ADS_RIGHT_READ_CONTROL)
  1735. wcscat(pszBuf, L"R ctrl, ");
  1736. if (dwMask & ADS_RIGHT_WRITE_DAC)
  1737. wcscat(pszBuf, L"R/W dac, ");
  1738. if (dwMask & ADS_RIGHT_WRITE_OWNER)
  1739. wcscat(pszBuf, L"W own, ");
  1740. if (dwMask & ADS_RIGHT_SYNCHRONIZE)
  1741. wcscat(pszBuf, L"Sync, ");
  1742. if (dwMask & ADS_RIGHT_ACCESS_SYSTEM_SECURITY)
  1743. wcscat(pszBuf, L"Sys, ");
  1744. if (dwMask & ADS_RIGHT_GENERIC_READ)
  1745. wcscat(pszBuf, L"R (gen), ");
  1746. if (dwMask & ADS_RIGHT_GENERIC_WRITE)
  1747. wcscat(pszBuf, L"W (gen), ");
  1748. if (dwMask & ADS_RIGHT_GENERIC_EXECUTE)
  1749. wcscat(pszBuf, L"Ex, ");
  1750. if (dwMask & ADS_RIGHT_GENERIC_ALL)
  1751. wcscat(pszBuf, L"All, ");
  1752. if (dwMask & ADS_RIGHT_DS_CREATE_CHILD)
  1753. wcscat(pszBuf, L"Cr cld, ");
  1754. if (dwMask & ADS_RIGHT_DS_DELETE_CHILD)
  1755. wcscat(pszBuf, L"Del cld, ");
  1756. if (dwMask & ADS_RIGHT_ACTRL_DS_LIST)
  1757. wcscat(pszBuf, L"List, ");
  1758. if (dwMask & ADS_RIGHT_DS_SELF)
  1759. wcscat(pszBuf, L"Self, ");
  1760. if (dwMask & ADS_RIGHT_DS_READ_PROP)
  1761. wcscat(pszBuf, L"R prop, ");
  1762. if (dwMask & ADS_RIGHT_DS_WRITE_PROP)
  1763. wcscat(pszBuf, L"W prop, ");
  1764. if (dwMask & ADS_RIGHT_DS_DELETE_TREE)
  1765. wcscat(pszBuf, L"Del tree, ");
  1766. if (dwMask & ADS_RIGHT_DS_LIST_OBJECT)
  1767. wcscat(pszBuf, L"List obj, ");
  1768. if (dwMask & ADS_RIGHT_DS_CONTROL_ACCESS)
  1769. wcscat(pszBuf, L"Ctrl acc, ");
  1770. }
  1771. return pszBuf;
  1772. }
  1773. PWCHAR
  1774. DsrAceFlagsToString(
  1775. IN DWORD dwAceFlags,
  1776. IN PWCHAR pszBuf)
  1777. {
  1778. WCHAR pszTemp[64];
  1779. *pszBuf = L'\0';
  1780. switch (dwAceFlags)
  1781. {
  1782. case 0:
  1783. wcscpy(pszBuf, L"This object only");
  1784. break;
  1785. case ADS_ACEFLAG_INHERIT_ACE:
  1786. wcscpy(pszBuf, L"This object and children");
  1787. break;
  1788. case ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE:
  1789. wcscpy(pszBuf, L"No-prop inherit");
  1790. break;
  1791. case ADS_ACEFLAG_INHERIT_ONLY_ACE:
  1792. wcscpy(pszBuf, L"Inherit-only");
  1793. break;
  1794. case ADS_ACEFLAG_INHERITED_ACE:
  1795. wcscpy(pszBuf, L"Inherited");
  1796. break;
  1797. case ADS_ACEFLAG_VALID_INHERIT_FLAGS:
  1798. wcscpy(pszBuf, L"Valid inherit flags");
  1799. break;
  1800. case ADS_ACEFLAG_SUCCESSFUL_ACCESS:
  1801. wcscpy(pszBuf, L"Successful access");
  1802. break;
  1803. case ADS_ACEFLAG_FAILED_ACCESS:
  1804. wcscpy(pszBuf, L"Failed access");
  1805. break;
  1806. }
  1807. wsprintfW(pszTemp, L" (%x)", dwAceFlags);
  1808. wcscat(pszBuf, pszTemp);
  1809. return pszBuf;
  1810. }
  1811. //
  1812. // Traces out the contents of an ACE
  1813. //
  1814. VOID
  1815. DsrAceDescTrace(
  1816. IN IADs* pIads,
  1817. IN DSR_ACE_DESCRIPTOR* pA)
  1818. {
  1819. VARIANT var;
  1820. BSTR bstrProp = SysAllocString(pszDn);
  1821. HRESULT hr = S_OK;
  1822. WCHAR pszBuf[1024];
  1823. do
  1824. {
  1825. VariantInit(&var);
  1826. if (bstrProp == NULL)
  1827. {
  1828. hr = E_FAIL;
  1829. break;
  1830. }
  1831. hr = pIads->Get(bstrProp, &var);
  1832. DSR_BREAK_ON_FAILED_HR( hr );
  1833. DsrTraceEx(0, "%ls", V_BSTR(&var));
  1834. DsrTraceEx(0, "%ls",
  1835. DsrAceMaskToString(pA->dwAceType, pA->dwAccessMask, pszBuf));
  1836. DsrTraceEx(0, "To: %ls", pA->bstrTrustee);
  1837. DsrTraceEx(0, "Attribute: %ls",
  1838. DsrAceAttrToString(pA->bstrObjectType));
  1839. DsrTraceEx(0, "ApplyTo: %ls",
  1840. DsrAceApplyToString(pA->bstrInheritedObjectType));
  1841. DsrTraceEx(0, "Inheritance: %ls",
  1842. DsrAceFlagsToString(pA->dwAceFlags, pszBuf));
  1843. DsrTraceEx(0, "Flags: %x", pA->dwFlags);
  1844. DsrTraceEx(0, " ");
  1845. } while (FALSE);
  1846. // Cleanup
  1847. //
  1848. {
  1849. SysFreeString(bstrProp);
  1850. VariantClear(&var);
  1851. }
  1852. if (FAILED(hr))
  1853. {
  1854. DsrTraceEx(
  1855. 0,
  1856. "{ %-8x %-2x %-2x %-2x %-40ls %ls %ls }",
  1857. pA->dwAccessMask,
  1858. pA->dwAceType,
  1859. pA->dwAceFlags,
  1860. pA->dwFlags,
  1861. pA->bstrTrustee,
  1862. pA->bstrObjectType,
  1863. pA->bstrInheritedObjectType);
  1864. }
  1865. }
  1866. //
  1867. // Adds the given ace to the given ds object
  1868. //
  1869. HRESULT
  1870. DsrAceAdd(
  1871. IN PWCHAR pszDC,
  1872. IN IADs* pIads,
  1873. IN DSR_ACE_DESCRIPTOR * pAceParams)
  1874. {
  1875. IADsSecurityDescriptor* pSD = NULL;
  1876. IADsAccessControlList* pAcl = NULL;
  1877. IDispatch* pAce = NULL;
  1878. IDispatch* pDispatch = NULL;
  1879. HRESULT hr = S_OK;
  1880. VARIANT var;
  1881. // Initialize
  1882. VariantInit(&var);
  1883. do
  1884. {
  1885. // Get the security descriptor
  1886. //
  1887. pIads->Get((PWCHAR)pszSecurityDesc, &var);
  1888. DSR_BREAK_ON_FAILED_HR( hr );
  1889. // Get the appropriate interface to the sd
  1890. //
  1891. V_DISPATCH(&var)->QueryInterface(
  1892. IID_IADsSecurityDescriptor,
  1893. (VOID**)&pSD);
  1894. DSR_BREAK_ON_FAILED_HR( hr );
  1895. // Get a reference to the discretionary acl
  1896. //
  1897. hr = pSD->get_DiscretionaryAcl(&pDispatch);
  1898. DSR_BREAK_ON_FAILED_HR( hr );
  1899. hr = pDispatch->QueryInterface(
  1900. IID_IADsAccessControlList,
  1901. (VOID**)&pAcl);
  1902. DSR_BREAK_ON_FAILED_HR( hr );
  1903. // Don't add the ACE if it's already there.
  1904. //
  1905. hr = DsrAceFindInAcl(
  1906. pszDC,
  1907. pAcl,
  1908. pAceParams,
  1909. &pAce);
  1910. if (SUCCEEDED(hr) && pAce)
  1911. {
  1912. hr = S_OK;
  1913. break;
  1914. }
  1915. // Trace out the ACE
  1916. DsrAceDescTrace(pIads, pAceParams);
  1917. // Create the ACE
  1918. hr = DsrAceCreate(pAceParams, &pAce);
  1919. DSR_BREAK_ON_FAILED_HR( hr );
  1920. // Add the newly created ACE to the ACL
  1921. //
  1922. hr = pAcl->AddAce(pAce);
  1923. DSR_BREAK_ON_FAILED_HR( hr );
  1924. // Now commit the result in the ACL
  1925. //
  1926. hr = pSD->put_DiscretionaryAcl(pDispatch);
  1927. DSR_BREAK_ON_FAILED_HR( hr );
  1928. // Finally, commit the result in the ds object
  1929. //
  1930. hr = pIads->Put((PWCHAR)pszSecurityDesc, var);
  1931. DSR_BREAK_ON_FAILED_HR( hr );
  1932. } while (FALSE);
  1933. // Cleanup
  1934. {
  1935. DSR_RELEASE( pAce );
  1936. DSR_RELEASE( pAcl );
  1937. DSR_RELEASE( pDispatch );
  1938. DSR_RELEASE( pSD );
  1939. VariantClear(&var);
  1940. }
  1941. return DSR_ERROR(hr);
  1942. }
  1943. //
  1944. // Creates a new ACE object from the given parameters
  1945. //
  1946. HRESULT
  1947. DsrAceCreate(
  1948. IN DSR_ACE_DESCRIPTOR * pAceParams,
  1949. OUT IDispatch** ppAce)
  1950. {
  1951. IADsAccessControlEntry* pAce = NULL;
  1952. IDispatch* pRet = NULL;
  1953. HRESULT hr = S_OK;
  1954. do
  1955. {
  1956. // Create the new ACE
  1957. //
  1958. hr = CoCreateInstance(
  1959. CLSID_AccessControlEntry,
  1960. NULL,
  1961. CLSCTX_INPROC_SERVER,
  1962. IID_IADsAccessControlEntry,
  1963. (VOID**) &pAce);
  1964. DSR_BREAK_ON_FAILED_HR( hr );
  1965. // Initialize the values
  1966. //
  1967. hr = pAce->put_Trustee(pAceParams->bstrTrustee);
  1968. DSR_BREAK_ON_FAILED_HR( hr );
  1969. hr = pAce->put_AceFlags(pAceParams->dwAceFlags);
  1970. DSR_BREAK_ON_FAILED_HR( hr );
  1971. hr = pAce->put_Flags(pAceParams->dwFlags);
  1972. DSR_BREAK_ON_FAILED_HR( hr );
  1973. hr = pAce->put_AceType(pAceParams->dwAceType);
  1974. DSR_BREAK_ON_FAILED_HR( hr );
  1975. hr = pAce->put_AccessMask(pAceParams->dwAccessMask);
  1976. DSR_BREAK_ON_FAILED_HR( hr );
  1977. hr = pAce->put_ObjectType(pAceParams->bstrObjectType);
  1978. DSR_BREAK_ON_FAILED_HR( hr );
  1979. hr = pAce->put_InheritedObjectType(
  1980. pAceParams->bstrInheritedObjectType);
  1981. DSR_BREAK_ON_FAILED_HR( hr );
  1982. // Query the return value
  1983. //
  1984. hr = pAce->QueryInterface(IID_IDispatch, (VOID**)&pRet);
  1985. DSR_BREAK_ON_FAILED_HR( hr );
  1986. // Assign the return value
  1987. *ppAce = pRet;
  1988. } while (FALSE);
  1989. // Cleanup
  1990. {
  1991. if (FAILED (hr))
  1992. {
  1993. DSR_RELEASE(pRet);
  1994. }
  1995. DSR_RELEASE(pAce);
  1996. }
  1997. return hr;
  1998. }
  1999. //
  2000. // Finds the given ace in the given acl
  2001. //
  2002. HRESULT
  2003. DsrAceFind(
  2004. IN PWCHAR pszDC,
  2005. IN IADs* pObject,
  2006. IN DSR_ACE_DESCRIPTOR* pAceParams,
  2007. OUT VARIANT* pVarSD,
  2008. OUT IADsSecurityDescriptor** ppSD,
  2009. OUT IADsAccessControlList** ppAcl,
  2010. OUT IDispatch** ppAce)
  2011. {
  2012. IDispatch* pAcl = NULL;
  2013. HRESULT hr = S_OK;
  2014. do
  2015. {
  2016. // Get the security descriptor
  2017. //
  2018. pObject->Get((PWCHAR)pszSecurityDesc, pVarSD);
  2019. DSR_BREAK_ON_FAILED_HR( hr );
  2020. // Get the appropriate interface to the sd
  2021. //
  2022. V_DISPATCH(pVarSD)->QueryInterface(
  2023. IID_IADsSecurityDescriptor,
  2024. (VOID**)ppSD);
  2025. DSR_BREAK_ON_FAILED_HR( hr );
  2026. // Get a reference to the discretionary acl
  2027. //
  2028. hr = (*ppSD)->get_DiscretionaryAcl(&pAcl);
  2029. DSR_BREAK_ON_FAILED_HR( hr );
  2030. hr = pAcl->QueryInterface(
  2031. IID_IADsAccessControlList,
  2032. (VOID**)ppAcl);
  2033. DSR_BREAK_ON_FAILED_HR( hr );
  2034. hr = DsrAceFindInAcl(
  2035. pszDC,
  2036. *ppAcl,
  2037. pAceParams,
  2038. ppAce);
  2039. DSR_BREAK_ON_FAILED_HR(hr);
  2040. } while (FALSE);
  2041. // Cleanup
  2042. {
  2043. DSR_RELEASE( pAcl );
  2044. if (*ppAce == NULL)
  2045. {
  2046. VariantClear(pVarSD);
  2047. DSR_RELEASE(*ppAcl);
  2048. DSR_RELEASE(*ppSD);
  2049. *ppAcl = NULL;
  2050. *ppSD = NULL;
  2051. }
  2052. }
  2053. return hr;
  2054. }
  2055. //
  2056. // Finds the given ACE in the given ACL
  2057. //
  2058. HRESULT
  2059. DsrAceFindInAcl(
  2060. IN PWCHAR pszDC,
  2061. IN IADsAccessControlList* pAcl,
  2062. IN DSR_ACE_DESCRIPTOR* pAceDesc,
  2063. OUT IDispatch** ppAce)
  2064. {
  2065. DSR_ACE_DESCRIPTOR CurAceParams, *pCurAceDesc = &CurAceParams;
  2066. IADsAccessControlEntry* pCurAce = NULL;
  2067. HRESULT hr = S_OK;
  2068. IUnknown* pUnknown = NULL;
  2069. IEnumVARIANT* pEnumVar = NULL;
  2070. IDispatch* pRet = NULL;
  2071. DWORD dwRetrieved;
  2072. VARIANT var;
  2073. do
  2074. {
  2075. // Get an enumerator of the aces
  2076. //
  2077. hr = pAcl->get__NewEnum(&pUnknown);
  2078. DSR_BREAK_ON_FAILED_HR( hr );
  2079. // Get the right interface to enumerate the aces
  2080. //
  2081. hr = pUnknown->QueryInterface(IID_IEnumVARIANT, (VOID**)&pEnumVar);
  2082. DSR_BREAK_ON_FAILED_HR( hr );
  2083. // Enumerate
  2084. //
  2085. pEnumVar->Reset();
  2086. VariantInit(&var);
  2087. ZeroMemory(pCurAceDesc, sizeof(DSR_ACE_DESCRIPTOR));
  2088. while ((pEnumVar->Next(1, &var, &dwRetrieved) == S_OK) &&
  2089. (dwRetrieved == 1)
  2090. )
  2091. {
  2092. // Get the reference to the ace
  2093. //
  2094. hr = V_DISPATCH(&var)->QueryInterface(
  2095. IID_IADsAccessControlEntry,
  2096. (VOID**)&pCurAce);
  2097. if (SUCCEEDED (hr))
  2098. {
  2099. // Read the ACE parameters
  2100. //
  2101. hr = DsrAceDescFromIadsAce(pszDC, pCurAce, pCurAceDesc);
  2102. if (SUCCEEDED (hr))
  2103. {
  2104. // Assign the ace if we have a match
  2105. //
  2106. if (DsrAceDescCompare(pCurAceDesc, pAceDesc) == 0)
  2107. {
  2108. pRet = V_DISPATCH(&var);
  2109. }
  2110. DsrAceDescClear(pCurAceDesc);
  2111. }
  2112. pCurAce->Release();
  2113. }
  2114. if (pRet == NULL)
  2115. {
  2116. VariantClear(&var);
  2117. }
  2118. else
  2119. {
  2120. break;
  2121. }
  2122. }
  2123. // Assign the return value
  2124. //
  2125. *ppAce = pRet;
  2126. } while (FALSE);
  2127. // Cleanup
  2128. {
  2129. DSR_RELEASE( pEnumVar );
  2130. DSR_RELEASE( pUnknown );
  2131. }
  2132. return hr;
  2133. }
  2134. //
  2135. // Removes the given ace from the given ds object
  2136. //
  2137. HRESULT
  2138. DsrAceRemove(
  2139. IN PWCHAR pszDC,
  2140. IN IADs* pIads,
  2141. IN DSR_ACE_DESCRIPTOR * pAceParams)
  2142. {
  2143. IADsSecurityDescriptor* pSD = NULL;
  2144. IADsAccessControlList* pAcl = NULL;
  2145. IADsAccessControlEntry* pIadsAce = NULL;
  2146. IDispatch* pAce = NULL;
  2147. DSR_ACE_DESCRIPTOR CurAceParams;
  2148. HRESULT hr = S_OK;
  2149. VARIANT varSD;
  2150. do
  2151. {
  2152. VariantInit(&varSD);
  2153. hr = DsrAceFind(pszDC, pIads, pAceParams, &varSD, &pSD, &pAcl, &pAce);
  2154. DSR_BREAK_ON_FAILED_HR( hr );
  2155. if (pAce)
  2156. {
  2157. // Make sure the ace is the same as we think
  2158. //
  2159. hr = pAce->QueryInterface(
  2160. IID_IADsAccessControlEntry,
  2161. (VOID**)&pIadsAce);
  2162. if (SUCCEEDED(hr))
  2163. {
  2164. DsrTraceEx(0, "ACE to be removed!");
  2165. DsrAceDescFromIadsAce(pszDC, pIadsAce, &CurAceParams);
  2166. DsrAceDescTrace(pIads, &CurAceParams);
  2167. DsrAceDescClear(&CurAceParams);
  2168. }
  2169. else
  2170. {
  2171. DsrTraceEx(0, "Unable to trace ACE that will be removed!\n");
  2172. }
  2173. // Remove the ace found if any.
  2174. //
  2175. // Trace out the ACE
  2176. hr = pAcl->RemoveAce(pAce);
  2177. DSR_BREAK_ON_FAILED_HR( hr );
  2178. // Now commit the result in the ACL
  2179. //
  2180. hr = pSD->put_DiscretionaryAcl(pAcl);
  2181. DSR_BREAK_ON_FAILED_HR( hr );
  2182. // Finally, commit the result in the ds object
  2183. //
  2184. hr = pIads->Put((PWCHAR)pszSecurityDesc, varSD);
  2185. DSR_BREAK_ON_FAILED_HR( hr );
  2186. }
  2187. else
  2188. {
  2189. DsrTraceEx(0, "DsrAceRemove: unable to match ACE for removal:");
  2190. DsrAceDescTrace(pIads, pAceParams);
  2191. }
  2192. } while (FALSE);
  2193. // Cleanup
  2194. {
  2195. DSR_RELEASE( pAce );
  2196. DSR_RELEASE( pIadsAce );
  2197. DSR_RELEASE( pAcl );
  2198. DSR_RELEASE( pSD );
  2199. VariantClear(&varSD);
  2200. }
  2201. return DSR_ERROR(hr);
  2202. }
  2203. //
  2204. // Cleans up after DsrAccessInfoInit
  2205. //
  2206. DWORD
  2207. DsrAccessInfoCleanup(
  2208. IN DSR_DOMAIN_ACCESS_INFO* pInfo)
  2209. {
  2210. if (pInfo)
  2211. {
  2212. // Cleanup the name of the DC
  2213. //
  2214. if (pInfo->pszDC)
  2215. {
  2216. DsrFree(pInfo->pszDC);
  2217. }
  2218. // Cleanup the ace applications
  2219. //
  2220. DsrAceAppCleanup(pInfo->pAces, pInfo->dwAceCount);
  2221. // Release the hold on domain objects
  2222. //
  2223. DSR_RELEASE(pInfo->pRootDse);
  2224. DSR_RELEASE(pInfo->pDomain);
  2225. DsrFree(pInfo);
  2226. }
  2227. return NO_ERROR;
  2228. }
  2229. //
  2230. // Generates the information needed to enable nt4 ras
  2231. // servers in a domain
  2232. //
  2233. HRESULT
  2234. DsrAccessInfoInit(
  2235. IN PWCHAR pszDomain,
  2236. OUT DSR_DOMAIN_ACCESS_INFO** ppInfo)
  2237. {
  2238. DSR_DOMAIN_ACCESS_INFO* pInfo = NULL;
  2239. IADsContainer* pDomContainer = NULL;
  2240. IADs* pDomain = NULL;
  2241. IDispatch* pDispatch = NULL;
  2242. PDOMAIN_CONTROLLER_INFO pDomainInfo = NULL;
  2243. HRESULT hr = S_OK;
  2244. do
  2245. {
  2246. // Allocate and zero the return value
  2247. //
  2248. pInfo = (DSR_DOMAIN_ACCESS_INFO*)
  2249. DsrAlloc(sizeof(DSR_DOMAIN_ACCESS_INFO), TRUE);
  2250. if (pInfo == NULL)
  2251. {
  2252. DSR_BREAK_ON_FAILED_HR(hr = E_OUTOFMEMORY);
  2253. }
  2254. // Get the name of a DC to query when needed
  2255. //
  2256. hr = DsGetDcNameW(
  2257. NULL,
  2258. pszDomain,
  2259. NULL,
  2260. NULL,
  2261. DS_DIRECTORY_SERVICE_REQUIRED,
  2262. &pDomainInfo);
  2263. if (hr != NO_ERROR)
  2264. {
  2265. hr = HRESULT_FROM_WIN32(hr);
  2266. break;
  2267. }
  2268. // Copy the string
  2269. //
  2270. pInfo->pszDC = (PWCHAR)
  2271. DsrAlloc(
  2272. (wcslen(pDomainInfo->DomainControllerName) + 1) *
  2273. sizeof(WCHAR),
  2274. FALSE);
  2275. if (pInfo->pszDC == NULL)
  2276. {
  2277. hr = E_OUTOFMEMORY;
  2278. break;
  2279. }
  2280. wcscpy(pInfo->pszDC, pDomainInfo->DomainControllerName);
  2281. // Get the well known domain containers
  2282. //
  2283. hr = DsrDomainGetBaseObjects(
  2284. pszDomain,
  2285. &(pInfo->pRootDse),
  2286. &pDomContainer);
  2287. DSR_BREAK_ON_FAILED_HR( hr );
  2288. // Get the interface to the domain object
  2289. //
  2290. hr = pDomContainer->QueryInterface(
  2291. IID_IADs,
  2292. (VOID**)&pDomain);
  2293. DSR_BREAK_ON_FAILED_HR( hr );
  2294. pInfo->pDomain = pDomain;
  2295. pInfo->pDomain->AddRef();
  2296. // Create ace applications
  2297. hr = DsrAceAppFromAppDesc(
  2298. g_pAces,
  2299. sizeof(g_pAces) / sizeof(*g_pAces),
  2300. pDomContainer,
  2301. pDomain,
  2302. &(pInfo->pAces),
  2303. &(pInfo->dwAceCount));
  2304. DSR_BREAK_ON_FAILED_HR( hr );
  2305. // Assign the return value
  2306. *ppInfo = pInfo;
  2307. } while (FALSE);
  2308. // Cleanup
  2309. //
  2310. {
  2311. DSR_RELEASE(pDomain);
  2312. DSR_RELEASE(pDomContainer);
  2313. DSR_RELEASE(pDispatch);
  2314. if (FAILED (hr))
  2315. {
  2316. DsrAccessInfoCleanup(pInfo);
  2317. }
  2318. if (pDomainInfo)
  2319. {
  2320. NetApiBufferFree(pDomainInfo);
  2321. }
  2322. }
  2323. return hr;
  2324. }
  2325. //
  2326. // Discovers the access mode of the domain currently.
  2327. //
  2328. // Assumes COM is initialized
  2329. //
  2330. HRESULT
  2331. DsrDomainQueryAccessEx(
  2332. IN PWCHAR pszDomain,
  2333. OUT LPDWORD lpdwAccessFlags,
  2334. OUT DSR_DOMAIN_ACCESS_INFO** ppInfo)
  2335. {
  2336. DSR_DOMAIN_ACCESS_INFO* pInfo = NULL;
  2337. HRESULT hr = S_OK;
  2338. BOOL bOk = FALSE;
  2339. if (lpdwAccessFlags == NULL)
  2340. {
  2341. return ERROR_INVALID_PARAMETER;
  2342. }
  2343. do
  2344. {
  2345. // Initialize
  2346. //
  2347. *lpdwAccessFlags = 0;
  2348. // Read in the info that tells us what ACE's
  2349. // need to be set.
  2350. //
  2351. hr = DsrAccessInfoInit(
  2352. pszDomain,
  2353. &pInfo);
  2354. DSR_BREAK_ON_FAILED_HR( hr );
  2355. // Check for nt4 level access
  2356. //
  2357. bOk = FALSE;
  2358. hr = DsrAceAppQueryPresence(
  2359. pInfo->pszDC,
  2360. pInfo->pAces,
  2361. pInfo->dwAceCount,
  2362. MPRFLAG_DOMAIN_ALL,
  2363. &bOk);
  2364. DSR_BREAK_ON_FAILED_HR(hr);
  2365. // If we don't have nt4 access, we have no access
  2366. //
  2367. if (bOk == FALSE)
  2368. {
  2369. *lpdwAccessFlags = 0;
  2370. break;
  2371. }
  2372. *lpdwAccessFlags |= MPRFLAG_DOMAIN_NT4_SERVERS;
  2373. // Check for w2k level access
  2374. //
  2375. bOk = FALSE;
  2376. hr = DsrAceAppQueryPresence(
  2377. pInfo->pszDC,
  2378. pInfo->pAces,
  2379. pInfo->dwAceCount,
  2380. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS,
  2381. &bOk);
  2382. DSR_BREAK_ON_FAILED_HR(hr);
  2383. // If we don't have w2k access, no need to proceed
  2384. //
  2385. if (bOk == FALSE)
  2386. {
  2387. break;
  2388. }
  2389. *lpdwAccessFlags |= MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS;
  2390. } while (FALSE);
  2391. // Cleanup
  2392. {
  2393. if (FAILED(hr))
  2394. {
  2395. if (pInfo)
  2396. {
  2397. DsrAccessInfoCleanup(pInfo);
  2398. }
  2399. }
  2400. else
  2401. {
  2402. *ppInfo = pInfo;
  2403. }
  2404. }
  2405. return hr;
  2406. }
  2407. //
  2408. // Returns the access level of the given domain
  2409. //
  2410. DWORD
  2411. DsrDomainQueryAccess(
  2412. IN PWCHAR pszDomain,
  2413. OUT LPDWORD lpdwAccessFlags)
  2414. {
  2415. DSR_DOMAIN_ACCESS_INFO* pInfo = NULL;
  2416. HRESULT hr = S_OK;
  2417. do
  2418. {
  2419. // Initialize
  2420. hr = DsrComIntialize();
  2421. DSR_BREAK_ON_FAILED_HR( hr );
  2422. // Query the access
  2423. hr = DsrDomainQueryAccessEx(
  2424. pszDomain,
  2425. lpdwAccessFlags,
  2426. &pInfo);
  2427. DSR_BREAK_ON_FAILED_HR(hr);
  2428. } while (FALSE);
  2429. // Cleanup
  2430. {
  2431. if (pInfo)
  2432. {
  2433. DsrAccessInfoCleanup(pInfo);
  2434. }
  2435. DsrComUninitialize();
  2436. }
  2437. return DSR_ERROR(hr);
  2438. }
  2439. //
  2440. // Sets the ACES in the given domain to enable nt4 servers
  2441. //
  2442. DWORD
  2443. DsrDomainSetAccess(
  2444. IN PWCHAR pszDomain,
  2445. IN DWORD dwAccessFlags)
  2446. {
  2447. DSR_DOMAIN_ACCESS_INFO* pInfo = NULL;
  2448. HRESULT hr = S_OK;
  2449. BOOL bClean = TRUE;
  2450. DWORD dwCurAccess = 0;
  2451. do
  2452. {
  2453. // Initialize
  2454. hr = DsrComIntialize();
  2455. DSR_BREAK_ON_FAILED_HR( hr );
  2456. DsrTraceEx(
  2457. 0,
  2458. "DsrDomainSetAccess: Req: %x",
  2459. dwAccessFlags);
  2460. // W2k mode always implies nt4 mode as well
  2461. //
  2462. if (dwAccessFlags & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)
  2463. {
  2464. dwAccessFlags |= MPRFLAG_DOMAIN_NT4_SERVERS;
  2465. }
  2466. // Discover the current access on the domain and
  2467. // initialize the info we need
  2468. //
  2469. hr = DsrDomainQueryAccessEx(
  2470. pszDomain,
  2471. &dwCurAccess,
  2472. &pInfo);
  2473. DSR_BREAK_ON_FAILED_HR(hr);
  2474. DsrTraceEx(
  2475. 0,
  2476. "DsrDomainSetAccess: Cur: %x",
  2477. dwCurAccess);
  2478. // Remove all appropriate aces if the requested access
  2479. // is none.
  2480. if (dwAccessFlags == 0)
  2481. {
  2482. // Remove the nt4 mode aces if needed
  2483. //
  2484. if (dwCurAccess & MPRFLAG_DOMAIN_NT4_SERVERS)
  2485. {
  2486. hr = DsrAceAppRemove(
  2487. MPRFLAG_DOMAIN_ALL,
  2488. pInfo->pszDC,
  2489. pInfo->pAces,
  2490. pInfo->dwAceCount);
  2491. DSR_BREAK_ON_FAILED_HR(hr);
  2492. }
  2493. if (dwCurAccess & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)
  2494. {
  2495. hr = DsrAceAppRemove(
  2496. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS,
  2497. pInfo->pszDC,
  2498. pInfo->pAces,
  2499. pInfo->dwAceCount);
  2500. DSR_BREAK_ON_FAILED_HR(hr);
  2501. }
  2502. }
  2503. // Set nt4 mode if needed
  2504. //
  2505. if (dwAccessFlags & MPRFLAG_DOMAIN_NT4_SERVERS)
  2506. {
  2507. // Remove w2k level access if needed
  2508. //
  2509. if ((!(dwAccessFlags & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)) &&
  2510. (dwCurAccess & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS))
  2511. {
  2512. hr = DsrAceAppRemove(
  2513. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS,
  2514. pInfo->pszDC,
  2515. pInfo->pAces,
  2516. pInfo->dwAceCount);
  2517. DSR_BREAK_ON_FAILED_HR(hr);
  2518. }
  2519. // Add nt4 level access if needed
  2520. //
  2521. if (! (dwCurAccess & MPRFLAG_DOMAIN_NT4_SERVERS))
  2522. {
  2523. hr = DsrAceAppAdd(
  2524. MPRFLAG_DOMAIN_ALL,
  2525. pInfo->pszDC,
  2526. pInfo->pAces,
  2527. pInfo->dwAceCount);
  2528. DSR_BREAK_ON_FAILED_HR(hr);
  2529. }
  2530. }
  2531. // Set w2k mode if needed
  2532. //
  2533. if (dwAccessFlags & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS)
  2534. {
  2535. if (!(dwCurAccess & MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS))
  2536. {
  2537. hr = DsrAceAppAdd(
  2538. MPRFLAG_DOMAIN_W2K_IN_NT4_DOMAINS,
  2539. pInfo->pszDC,
  2540. pInfo->pAces,
  2541. pInfo->dwAceCount);
  2542. DSR_BREAK_ON_FAILED_HR(hr);
  2543. }
  2544. }
  2545. } while (FALSE);
  2546. // Cleanup
  2547. {
  2548. if (pInfo)
  2549. {
  2550. DsrAccessInfoCleanup(pInfo);
  2551. }
  2552. DsrComUninitialize();
  2553. }
  2554. return DSR_ERROR(hr);
  2555. }