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.

2511 lines
55 KiB

  1. /*++
  2. Copyright (c) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. rndsec.cpp
  5. Abstract:
  6. Security utilities for Rendezvous Control.
  7. Author:
  8. KrishnaG (from OLEDS team)
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. 12-Dec-1997 DonRyan
  13. Munged KrishnaG's code to work with Rendezvous Control.
  14. --*/
  15. ///////////////////////////////////////////////////////////////////////////////
  16. // //
  17. // Include files //
  18. // //
  19. ///////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include <security.h>
  22. #include <initguid.h>
  23. #include <iads.h>
  24. #include <ntlsa.h>
  25. #include <stdlib.h>
  26. #include <limits.h>
  27. #include <io.h>
  28. #include <wchar.h>
  29. #include <tchar.h>
  30. #include "rndsec.h"
  31. ///////////////////////////////////////////////////////////////////////////////
  32. // //
  33. // Private macros //
  34. // //
  35. ///////////////////////////////////////////////////////////////////////////////
  36. #define BAIL_ON_FAILURE(hr) \
  37. if (FAILED(hr)) { goto error; }
  38. #define CONTINUE_ON_FAILURE(hr) \
  39. if (FAILED(hr)) { continue; }
  40. ///////////////////////////////////////////////////////////////////////////////
  41. // //
  42. // Private procedures //
  43. // //
  44. ///////////////////////////////////////////////////////////////////////////////
  45. LPWSTR
  46. AllocADsStr(
  47. LPWSTR pStr
  48. )
  49. {
  50. LPWSTR pMem;
  51. if (!pStr)
  52. return NULL;
  53. if (pMem = new WCHAR[wcslen(pStr) + 1])
  54. wcscpy(pMem, pStr);
  55. return pMem;
  56. }
  57. HRESULT
  58. ConvertSidToString(
  59. PSID pSid,
  60. LPWSTR String
  61. )
  62. /*++
  63. Routine Description:
  64. This function generates a printable unicode string representation
  65. of a SID.
  66. The resulting string will take one of two forms. If the
  67. IdentifierAuthority value is not greater than 2^32, then
  68. the SID will be in the form:
  69. S-1-281736-12-72-9-110
  70. ^ ^^ ^^ ^ ^^^
  71. | | | | |
  72. +-----+--+-+--+---- Decimal
  73. Otherwise it will take the form:
  74. S-1-0x173495281736-12-72-9-110
  75. ^^^^^^^^^^^^^^ ^^ ^^ ^ ^^^
  76. Hexidecimal | | | |
  77. +--+-+--+---- Decimal
  78. Arguments:
  79. pSid - opaque pointer that supplies the SID that is to be
  80. converted to Unicode.
  81. Return Value:
  82. If the Sid is successfully converted to a Unicode string, a
  83. pointer to the Unicode string is returned, else NULL is
  84. returned.
  85. --*/
  86. {
  87. WCHAR Buffer[256];
  88. UCHAR i;
  89. ULONG Tmp;
  90. HRESULT hr = S_OK;
  91. SID_IDENTIFIER_AUTHORITY *pSidIdentifierAuthority;
  92. PUCHAR pSidSubAuthorityCount;
  93. //
  94. // IsValidSid fiers an AV is pSid == NULL
  95. //
  96. if( NULL == pSid )
  97. {
  98. *String= L'\0';
  99. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  100. return(hr);
  101. }
  102. if (!IsValidSid( pSid )) {
  103. *String= L'\0';
  104. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  105. return(hr);
  106. }
  107. wsprintf(Buffer, L"S-%u-", (USHORT)(((PISID)pSid)->Revision ));
  108. wcscpy(String, Buffer);
  109. pSidIdentifierAuthority = GetSidIdentifierAuthority(pSid);
  110. if ( (pSidIdentifierAuthority->Value[0] != 0) ||
  111. (pSidIdentifierAuthority->Value[1] != 0) ){
  112. wsprintf(Buffer, L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
  113. (USHORT)pSidIdentifierAuthority->Value[0],
  114. (USHORT)pSidIdentifierAuthority->Value[1],
  115. (USHORT)pSidIdentifierAuthority->Value[2],
  116. (USHORT)pSidIdentifierAuthority->Value[3],
  117. (USHORT)pSidIdentifierAuthority->Value[4],
  118. (USHORT)pSidIdentifierAuthority->Value[5] );
  119. wcscat(String, Buffer);
  120. } else {
  121. Tmp = (ULONG)pSidIdentifierAuthority->Value[5] +
  122. (ULONG)(pSidIdentifierAuthority->Value[4] << 8) +
  123. (ULONG)(pSidIdentifierAuthority->Value[3] << 16) +
  124. (ULONG)(pSidIdentifierAuthority->Value[2] << 24);
  125. wsprintf(Buffer, L"%lu", Tmp);
  126. wcscat(String, Buffer);
  127. }
  128. pSidSubAuthorityCount = GetSidSubAuthorityCount(pSid);
  129. for (i=0;i< *(pSidSubAuthorityCount);i++ ) {
  130. wsprintf(Buffer, L"-%lu", *(GetSidSubAuthority(pSid, i)));
  131. wcscat(String, Buffer);
  132. }
  133. return(S_OK);
  134. }
  135. HRESULT
  136. ConvertSidToFriendlyName(
  137. PSID pSid,
  138. LPWSTR * ppszAccountName
  139. )
  140. {
  141. HRESULT hr = S_OK;
  142. SID_NAME_USE eUse;
  143. WCHAR szAccountName[MAX_PATH];
  144. WCHAR szDomainName[MAX_PATH];
  145. DWORD dwLen = 0;
  146. DWORD dwRet = 0;
  147. LPWSTR pszAccountName = NULL;
  148. DWORD dwAcctLen = 0;
  149. DWORD dwDomainLen = 0;
  150. dwAcctLen = sizeof(szAccountName);
  151. dwDomainLen = sizeof(szDomainName);
  152. dwRet = LookupAccountSid(
  153. NULL,
  154. pSid,
  155. szAccountName,
  156. &dwAcctLen,
  157. szDomainName,
  158. &dwDomainLen,
  159. (PSID_NAME_USE)&eUse
  160. );
  161. if (!dwRet) {
  162. hr = ConvertSidToString(
  163. pSid,
  164. szAccountName
  165. );
  166. BAIL_ON_FAILURE(hr);
  167. pszAccountName = AllocADsStr(szAccountName);
  168. if (!pszAccountName) {
  169. hr = E_OUTOFMEMORY;
  170. BAIL_ON_FAILURE(hr);
  171. }
  172. *ppszAccountName = pszAccountName;
  173. }else {
  174. dwLen = wcslen(szAccountName) + wcslen(szDomainName) + 1 + 1;
  175. pszAccountName = new WCHAR [dwLen];
  176. if (!pszAccountName) {
  177. hr = E_OUTOFMEMORY;
  178. BAIL_ON_FAILURE(hr);
  179. }
  180. if (szDomainName[0] && szAccountName[0]) {
  181. wsprintf(pszAccountName,L"%s\\%s",szDomainName, szAccountName);
  182. }else if (szAccountName[0]) {
  183. wsprintf(pszAccountName,L"%s", szAccountName);
  184. }
  185. *ppszAccountName = pszAccountName;
  186. }
  187. error:
  188. return(hr);
  189. }
  190. //
  191. // Converts an ACE to a variant, but leaves the trustee name unset.
  192. // Instead it returns a pointer to the SID in this ACE, so that
  193. // we can go back and convert all the SIDs to trustee names at once
  194. // and set them on the ACEs later.
  195. //
  196. HRESULT
  197. ConvertAceToVariant(
  198. PBYTE pAce,
  199. LPVARIANT pvarAce,
  200. PSID * ppSid
  201. )
  202. {
  203. IADsAccessControlEntry * pAccessControlEntry = NULL;
  204. IDispatch * pDispatch = NULL;
  205. DWORD dwAceType = 0;
  206. DWORD dwAceFlags = 0;
  207. DWORD dwAccessMask = 0;
  208. PACE_HEADER pAceHeader = NULL;
  209. LPBYTE pSidAddress = NULL;
  210. LPBYTE pOffset = NULL;
  211. DWORD dwFlags = 0;
  212. GUID ObjectGUID;
  213. GUID InheritedObjectGUID;
  214. WCHAR szObjectGUID[MAX_PATH];
  215. WCHAR szInheritedObjectGUID[MAX_PATH];
  216. HRESULT hr = S_OK;
  217. szObjectGUID[0] = L'\0';
  218. szInheritedObjectGUID[0] = L'\0';
  219. VariantInit(pvarAce);
  220. hr = CoCreateInstance(
  221. CLSID_AccessControlEntry,
  222. NULL,
  223. CLSCTX_INPROC_SERVER,
  224. IID_IADsAccessControlEntry,
  225. (void **)&pAccessControlEntry
  226. );
  227. BAIL_ON_FAILURE(hr);
  228. pAceHeader = (ACE_HEADER *)pAce;
  229. dwAceType = pAceHeader->AceType;
  230. dwAceFlags = pAceHeader->AceFlags;
  231. dwAccessMask = *(PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  232. switch (dwAceType) {
  233. case ACCESS_ALLOWED_ACE_TYPE:
  234. case ACCESS_DENIED_ACE_TYPE:
  235. case SYSTEM_AUDIT_ACE_TYPE:
  236. case SYSTEM_ALARM_ACE_TYPE:
  237. pSidAddress = (LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK);
  238. break;
  239. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  240. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  241. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  242. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  243. pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
  244. dwFlags = (DWORD)(*(PDWORD)pOffset);
  245. //
  246. // Now advance by the size of the flags
  247. //
  248. pOffset += sizeof(ULONG);
  249. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  250. memcpy(&ObjectGUID, pOffset, sizeof(GUID));
  251. StringFromGUID2(ObjectGUID, szObjectGUID, MAX_PATH);
  252. pOffset += sizeof (GUID);
  253. }
  254. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  255. memcpy(&InheritedObjectGUID, pOffset, sizeof(GUID));
  256. StringFromGUID2(InheritedObjectGUID, szInheritedObjectGUID, MAX_PATH);
  257. pOffset += sizeof (GUID);
  258. }
  259. pSidAddress = pOffset;
  260. break;
  261. default:
  262. break;
  263. }
  264. //
  265. // return a pointer to the SID for this ACE, rather than converting the
  266. // SID to a trustee name (and taking forever for a large ACL)
  267. //
  268. *ppSid = (PSID) pSidAddress;
  269. //
  270. // Now set all the information in the Access Control Entry
  271. //
  272. hr = pAccessControlEntry->put_AccessMask(dwAccessMask);
  273. hr = pAccessControlEntry->put_AceFlags(dwAceFlags);
  274. hr = pAccessControlEntry->put_AceType(dwAceType);
  275. //
  276. // Extended ACE information
  277. //
  278. hr = pAccessControlEntry->put_Flags(dwFlags);
  279. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  280. //
  281. // Add in the Object Type GUID
  282. //
  283. hr = pAccessControlEntry->put_ObjectType(szObjectGUID);
  284. }
  285. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  286. //
  287. // Add in the Inherited Object Type GUID
  288. //
  289. hr = pAccessControlEntry->put_InheritedObjectType(szInheritedObjectGUID);
  290. }
  291. hr = pAccessControlEntry->QueryInterface(
  292. IID_IDispatch,
  293. (void **)&pDispatch
  294. );
  295. BAIL_ON_FAILURE(hr);
  296. V_DISPATCH(pvarAce) = pDispatch;
  297. V_VT(pvarAce) = VT_DISPATCH;
  298. cleanup:
  299. if (pAccessControlEntry) {
  300. pAccessControlEntry->Release();
  301. }
  302. return(hr);
  303. error:
  304. if (pDispatch) {
  305. pDispatch->Release();
  306. }
  307. goto cleanup;
  308. }
  309. BOOL
  310. APIENTRY
  311. LookupArrayOfSids(
  312. DWORD dwCount,
  313. PSID * ppSids,
  314. LSA_REFERENCED_DOMAIN_LIST ** ppDomains,
  315. LSA_TRANSLATED_NAME ** ppTrustees
  316. )
  317. {
  318. PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains;
  319. PLSA_TRANSLATED_NAME Names;
  320. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  321. OBJECT_ATTRIBUTES ObjectAttributes;
  322. LSA_HANDLE PolicyHandle;
  323. NTSTATUS Status;
  324. NTSTATUS TmpStatus;
  325. SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  326. SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
  327. SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  328. SecurityQualityOfService.EffectiveOnly = FALSE;
  329. //
  330. // Set up the object attributes prior to opening the LSA.
  331. //
  332. InitializeObjectAttributes(
  333. &ObjectAttributes,
  334. NULL,
  335. 0L,
  336. NULL,
  337. NULL
  338. );
  339. //
  340. // The InitializeObjectAttributes macro presently stores NULL for
  341. // the SecurityQualityOfService field, so we must manually copy that
  342. // structure for now.
  343. //
  344. ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;
  345. Status = LsaOpenPolicy(
  346. NULL,
  347. &ObjectAttributes,
  348. POLICY_LOOKUP_NAMES,
  349. &PolicyHandle
  350. );
  351. if ( !NT_SUCCESS( Status )) {
  352. // BaseSetLastNTError( Status );
  353. return( FALSE );
  354. }
  355. Status = LsaLookupSids(
  356. PolicyHandle,
  357. dwCount,
  358. ppSids,
  359. ppDomains,
  360. ppTrustees
  361. );
  362. TmpStatus = LsaClose( PolicyHandle );
  363. //
  364. // If an error was returned, check specifically for STATUS_NONE_MAPPED.
  365. // In this case, we may need to dispose of the returned Referenced Domain
  366. // List and Names structures. For all other errors, LsaLookupSids()
  367. // frees these structures prior to exit.
  368. //
  369. if ( !NT_SUCCESS( Status ))
  370. {
  371. if (Status == STATUS_NONE_MAPPED)
  372. {
  373. if ( *ppDomains != NULL)
  374. {
  375. TmpStatus = LsaFreeMemory( *ppDomains );
  376. _ASSERTE( NT_SUCCESS( TmpStatus ));
  377. *ppDomains = NULL;
  378. }
  379. if ( *ppTrustees != NULL) {
  380. TmpStatus = LsaFreeMemory( *ppTrustees );
  381. _ASSERTE( NT_SUCCESS( TmpStatus ));
  382. *ppTrustees = NULL;
  383. }
  384. }
  385. // BaseSetLastNTError( Status );
  386. return( FALSE );
  387. }
  388. //
  389. // The Sids were successfully translated.
  390. //
  391. return TRUE;
  392. }
  393. //
  394. // ZoltanS
  395. //
  396. HRESULT SetTrusteeOnACE(
  397. VARIANT * pVarAce,
  398. PLSA_REFERENCED_DOMAIN_LIST pDomains,
  399. PLSA_TRANSLATED_NAME pName
  400. )
  401. {
  402. //
  403. // Make sure pName is valid
  404. //
  405. if ((pName->Use == SidTypeInvalid) ||
  406. (pName->Use == SidTypeUnknown))
  407. {
  408. return E_INVALIDARG;
  409. }
  410. //
  411. // Find the domain and account names.
  412. //
  413. DWORD dwAccountNameSize = pName->Name.Length / 2;
  414. WCHAR * szAccountName = pName->Name.Buffer;
  415. DWORD dwDomainNameSize =
  416. (pDomains->Domains + pName->DomainIndex)->Name.Length / 2;
  417. WCHAR * szDomainName =
  418. (pDomains->Domains + pName->DomainIndex)->Name.Buffer;
  419. //
  420. // Allocate space for the compound name
  421. //
  422. DWORD dwLen = dwAccountNameSize + dwDomainNameSize + 1 + 1;
  423. WCHAR * pszAccountName = new WCHAR [dwLen];
  424. if (!pszAccountName)
  425. {
  426. return E_OUTOFMEMORY;
  427. }
  428. //
  429. // Copy in the domain and user name
  430. // to get the trustee name
  431. //
  432. if ( dwDomainNameSize != 0 )
  433. {
  434. // strange +1 needed because it will also put in a NULL terminator
  435. lstrcpynW(pszAccountName, szDomainName, dwDomainNameSize + 1);
  436. lstrcatW(pszAccountName, L"\\");
  437. }
  438. else
  439. {
  440. pszAccountName[0] = L'\0';
  441. }
  442. wcsncat(pszAccountName, szAccountName, dwAccountNameSize);
  443. //
  444. // Set the trustee name on the ACE
  445. //
  446. IDispatch * pDispatch = V_DISPATCH(pVarAce);
  447. IADsAccessControlEntry * pACE;
  448. HRESULT hr;
  449. hr = pDispatch->QueryInterface(IID_IADsAccessControlEntry,
  450. (void **) & pACE);
  451. hr = pACE->put_Trustee(pszAccountName);
  452. pACE->Release();
  453. return hr;
  454. }
  455. //
  456. // ZoltanS optimized version of ConvertACLToVariant
  457. //
  458. HRESULT
  459. ConvertACLToVariant(
  460. PACL pACL,
  461. LPVARIANT pvarACL
  462. )
  463. {
  464. IADsAccessControlList * pAccessControlList = NULL;
  465. IDispatch * pDispatch = NULL;
  466. DWORD dwAclSize = 0;
  467. DWORD dwAclRevision = 0;
  468. DWORD dwAceCount = 0;
  469. ACL_SIZE_INFORMATION AclSize;
  470. ACL_REVISION_INFORMATION AclRevision;
  471. DWORD dwStatus = 0;
  472. DWORD i = 0;
  473. DWORD dwNewAceCount = 0;
  474. HRESULT hr = S_OK;
  475. LPBYTE pAceAddress = NULL;
  476. memset(&AclSize, 0, sizeof(ACL_SIZE_INFORMATION));
  477. memset(&AclRevision, 0, sizeof(ACL_REVISION_INFORMATION));
  478. dwStatus = GetAclInformation(
  479. pACL,
  480. &AclSize,
  481. sizeof(ACL_SIZE_INFORMATION),
  482. AclSizeInformation
  483. );
  484. dwStatus = GetAclInformation(
  485. pACL,
  486. &AclRevision,
  487. sizeof(ACL_REVISION_INFORMATION),
  488. AclRevisionInformation
  489. );
  490. dwAceCount = AclSize.AceCount;
  491. dwAclRevision = AclRevision.AclRevision;
  492. VariantInit(pvarACL);
  493. hr = CoCreateInstance(
  494. CLSID_AccessControlList,
  495. NULL,
  496. CLSCTX_INPROC_SERVER,
  497. IID_IADsAccessControlList,
  498. (void **)&pAccessControlList
  499. );
  500. if ( FAILED(hr) )
  501. {
  502. return hr;
  503. }
  504. PSID * apSids = new PSID[ dwAceCount ];
  505. if ( apSids == NULL )
  506. {
  507. pAccessControlList->Release();
  508. return E_OUTOFMEMORY;
  509. }
  510. VARIANT * aVarAces = new VARIANT[ dwAceCount ];
  511. if ( aVarAces == NULL )
  512. {
  513. pAccessControlList->Release();
  514. delete apSids;
  515. return E_OUTOFMEMORY;
  516. }
  517. for (i = 0; i < dwAceCount; i++)
  518. {
  519. dwStatus = GetAce(pACL, i, (void **)&pAceAddress);
  520. hr = ConvertAceToVariant(
  521. pAceAddress,
  522. aVarAces + i,
  523. apSids + i );
  524. }
  525. //
  526. // Above, ConvertAceToVariant did not set the trustee names on the ACEs.
  527. // Instead we have an array (apSids) of dwNewAceCount valid PSIDs.
  528. // Convert all of these to trustees now.
  529. //
  530. PLSA_REFERENCED_DOMAIN_LIST pDomains = NULL;
  531. PLSA_TRANSLATED_NAME pTrustees = NULL;
  532. BOOL fStatus = LookupArrayOfSids(
  533. dwAceCount, // IN count
  534. apSids, // IN array of sid pointers
  535. &pDomains, // OUT referenced domain list
  536. &pTrustees); // OUT translated name list
  537. delete apSids;
  538. if ( fStatus == FALSE )
  539. {
  540. // LookupArrayOfSids failed
  541. hr = E_FAIL;
  542. }
  543. else
  544. {
  545. //
  546. // Set the trustees on the ACEs here
  547. //
  548. for ( i = 0; i < dwAceCount; i++ )
  549. {
  550. VARIANT * pVarAce = aVarAces + i;
  551. hr = SetTrusteeOnACE(
  552. pVarAce,
  553. pDomains,
  554. pTrustees + i
  555. );
  556. hr = pAccessControlList->AddAce( V_DISPATCH ( pVarAce ) );
  557. VariantClear( pVarAce );
  558. if ( SUCCEEDED(hr) )
  559. {
  560. dwNewAceCount++;
  561. }
  562. }
  563. //
  564. // Free output buffers returned by LsaLookupSids
  565. //
  566. DWORD Status;
  567. Status = LsaFreeMemory( pTrustees );
  568. _ASSERTE( NT_SUCCESS( Status ));
  569. Status = LsaFreeMemory( pDomains );
  570. _ASSERTE( NT_SUCCESS( Status ));
  571. pAccessControlList->put_AclRevision(dwAclRevision);
  572. pAccessControlList->put_AceCount(dwNewAceCount);
  573. hr = pAccessControlList->QueryInterface(
  574. IID_IDispatch,
  575. (void **)&pDispatch
  576. );
  577. V_VT(pvarACL) = VT_DISPATCH;
  578. V_DISPATCH(pvarACL) = pDispatch;
  579. }
  580. pAccessControlList->Release();
  581. //
  582. // aVarAces was dynamic allocated
  583. // aVarAces should be deallocated
  584. //
  585. delete aVarAces;
  586. return(hr);
  587. }
  588. HRESULT
  589. SecCreateSidFromArray (
  590. OUT PSID *PPSid,
  591. IN PSID_IDENTIFIER_AUTHORITY PSidAuthority,
  592. IN UCHAR SubAuthorityCount,
  593. IN ULONG SubAuthorities[],
  594. OUT PDWORD pdwSidSize
  595. )
  596. /*++
  597. Routine Description:
  598. Creates a SID with desired authority and sub authorities.
  599. NOTE: This routine allocates memory for the SID. When finished
  600. the caller should free memory using SEC_FREE (PSid).
  601. Arguments:
  602. PPSid -- addr of ptr to SID to be created
  603. Note: if SID creation fails ptr set to NULL
  604. PSidAuthority -- desired value for SID authority
  605. SubAuthorityCount -- number of sub authorities desired
  606. SubAuthorities -- sub-authority values, MUST SPECIFY contain
  607. at least SubAuthorityCount number of values
  608. Return Value:
  609. STATUS_SUCCESS if SID created.
  610. STATUS_UNSUCCESSFUL otherwise.
  611. --*/
  612. {
  613. USHORT iSub; /* sub-authority index */
  614. DWORD dwSidSize = 0;
  615. HRESULT hr = S_OK;
  616. /* allocate memory for SID */
  617. dwSidSize = RtlLengthRequiredSid(SubAuthorityCount);
  618. *PPSid = (PSID) new BYTE[dwSidSize];
  619. if (! *PPSid){
  620. hr = E_OUTOFMEMORY;
  621. BAIL_ON_FAILURE(hr);
  622. }
  623. *pdwSidSize = dwSidSize;
  624. /* initialize SID with top level SID identifier authority */
  625. RtlInitializeSid( *PPSid, PSidAuthority, SubAuthorityCount);
  626. /* fill in sub authorities */
  627. for (iSub=0; iSub < SubAuthorityCount; iSub++)
  628. * RtlSubAuthoritySid( *PPSid, iSub) = SubAuthorities[iSub];
  629. /* sanity check */
  630. if ( ! RtlValidSid( *PPSid) ) {
  631. delete (*PPSid);
  632. *PPSid = NULL;
  633. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  634. BAIL_ON_FAILURE(hr);
  635. }
  636. error:
  637. return(hr);
  638. }
  639. HRESULT
  640. ConvertStringToSid(
  641. IN PWSTR string,
  642. OUT PSID *sid,
  643. OUT PDWORD pdwSidSize,
  644. OUT PWSTR *end
  645. )
  646. {
  647. HRESULT hr = S_OK;
  648. UCHAR revision;
  649. UCHAR sub_authority_count;
  650. SID_IDENTIFIER_AUTHORITY authority;
  651. ULONG sub_authority[SID_MAX_SUB_AUTHORITIES];
  652. PWSTR end_list;
  653. PWSTR current;
  654. PWSTR next;
  655. ULONG x;
  656. *sid = NULL;
  657. if ( string == NULL )
  658. {
  659. return E_POINTER;
  660. }
  661. if (((*string != L'S') && (*string != L's')) || (*(string + 1) != L'-'))
  662. {
  663. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  664. BAIL_ON_FAILURE(hr);
  665. }
  666. current = string + 2;
  667. revision = (UCHAR)wcstol(current, &end_list, 10);
  668. current = end_list + 1;
  669. //
  670. // Count the number of characters in the indentifer authority...
  671. //
  672. next = wcschr(current, L'-');
  673. if((next != NULL) &&
  674. (next - current == 6))
  675. {
  676. for(x = 0; x < 6; x++)
  677. {
  678. authority.Value[x] = (UCHAR)next[x];
  679. }
  680. current +=6;
  681. }
  682. else
  683. {
  684. ULONG Auto = wcstoul(current, &end_list, 10);
  685. authority.Value[0] = authority.Value[1] = 0;
  686. authority.Value[5] = (UCHAR)Auto & 0xF;
  687. authority.Value[4] = (UCHAR)((Auto >> 8) & 0xFF);
  688. authority.Value[3] = (UCHAR)((Auto >> 16) & 0xFF);
  689. authority.Value[2] = (UCHAR)((Auto >> 24) & 0xFF);
  690. current = end_list;
  691. }
  692. //
  693. // Now, count the number of sub auths
  694. //
  695. sub_authority_count = 0;
  696. //
  697. // Initialize sub_authority array
  698. //
  699. memset( sub_authority, 0, sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES );
  700. next = current;
  701. //
  702. // We'll have to count our sub authoritys one character at a time,
  703. // since there are several deliminators that we can have...
  704. //
  705. while(next)
  706. {
  707. next++;
  708. if(*next == L'-')
  709. {
  710. //
  711. // We've found one!
  712. //
  713. sub_authority_count++;
  714. }
  715. else if(*next == L';' || *next == L'\0')
  716. {
  717. *end = next;
  718. sub_authority_count++;
  719. break;
  720. }
  721. }
  722. if(sub_authority_count != 0)
  723. {
  724. current++;
  725. for(x = 0; x < sub_authority_count; x++)
  726. {
  727. sub_authority[x] = wcstoul(current, &end_list, 10);
  728. current = end_list + 1;
  729. }
  730. }
  731. //
  732. // Now, create the SID
  733. //
  734. hr = SecCreateSidFromArray(
  735. sid,
  736. &authority,
  737. sub_authority_count,
  738. sub_authority,
  739. pdwSidSize
  740. );
  741. if (SUCCEEDED(hr))
  742. {
  743. /* Set the revision to what was specified in the string, in case, our
  744. system creates one with newer revision */
  745. ((SID *)(*sid))->Revision = revision;
  746. }
  747. error:
  748. return(hr);
  749. }
  750. HRESULT
  751. ConvertTrusteeToSid(
  752. BSTR bstrTrustee,
  753. PSID * ppSid,
  754. PDWORD pdwSidSize
  755. )
  756. {
  757. HRESULT hr = S_OK;
  758. BYTE Sid[MAX_PATH];
  759. DWORD dwSidSize = sizeof(Sid);
  760. DWORD dwRet = 0;
  761. WCHAR szDomainName[MAX_PATH];
  762. DWORD dwDomainSize = sizeof(szDomainName)/sizeof(WCHAR);
  763. SID_NAME_USE eUse;
  764. PSID pSid = NULL;
  765. LPWSTR pszEnd = NULL;
  766. BOOL fNTDSType = FALSE;
  767. dwSidSize = sizeof(Sid);
  768. dwRet = LookupAccountName(
  769. NULL,
  770. bstrTrustee,
  771. Sid,
  772. &dwSidSize,
  773. szDomainName,
  774. &dwDomainSize,
  775. (PSID_NAME_USE)&eUse
  776. );
  777. if (!dwRet) {
  778. hr = HRESULT_FROM_WIN32(GetLastError());
  779. }
  780. //
  781. // If neither the NTDS nor the U2 conversion
  782. // worked, then try a textual translation
  783. //
  784. if (FAILED(hr)) {
  785. hr = ConvertStringToSid(
  786. bstrTrustee,
  787. &pSid,
  788. &dwSidSize,
  789. &pszEnd
  790. );
  791. BAIL_ON_FAILURE(hr);
  792. memcpy(Sid,pSid, dwSidSize);
  793. if (pSid) {
  794. delete pSid;
  795. }
  796. }
  797. pSid = (PSID) new BYTE[dwSidSize];
  798. if (!pSid) {
  799. hr = E_OUTOFMEMORY;
  800. BAIL_ON_FAILURE(hr);
  801. }
  802. memcpy(pSid, Sid, dwSidSize);
  803. *pdwSidSize = dwSidSize;
  804. *ppSid = pSid;
  805. error:
  806. return(hr);
  807. }
  808. HRESULT
  809. GetOwnerSecurityIdentifier(
  810. IADsSecurityDescriptor FAR * pSecDes,
  811. PSID * ppSid,
  812. PBOOL pfOwnerDefaulted
  813. )
  814. {
  815. BSTR bstrOwner = NULL;
  816. DWORD dwSidSize = 0;
  817. HRESULT hr = S_OK;
  818. VARIANT_BOOL varBool = VARIANT_FALSE;
  819. hr = pSecDes->get_Owner(
  820. &bstrOwner
  821. );
  822. BAIL_ON_FAILURE(hr);
  823. hr = pSecDes->get_OwnerDefaulted(
  824. &varBool
  825. );
  826. BAIL_ON_FAILURE(hr);
  827. if (varBool == VARIANT_FALSE) {
  828. if (bstrOwner && *bstrOwner) {
  829. hr = ConvertTrusteeToSid(
  830. bstrOwner,
  831. ppSid,
  832. &dwSidSize
  833. );
  834. BAIL_ON_FAILURE(hr);
  835. *pfOwnerDefaulted = FALSE;
  836. }else {
  837. *ppSid = NULL;
  838. *pfOwnerDefaulted = FALSE;
  839. }
  840. }else {
  841. *ppSid = NULL;
  842. dwSidSize = 0;
  843. *pfOwnerDefaulted = TRUE;
  844. }
  845. error:
  846. if (bstrOwner) {
  847. SysFreeString(bstrOwner);
  848. }
  849. return(hr);
  850. }
  851. HRESULT
  852. ComputeTotalAclSize(
  853. PACE_HEADER * ppAceHdr,
  854. DWORD dwAceCount,
  855. PDWORD pdwAclSize
  856. )
  857. {
  858. DWORD i = 0;
  859. PACE_HEADER pAceHdr = NULL;
  860. DWORD dwAceSize = 0;
  861. DWORD dwAclSize = 0;
  862. for (i = 0; i < dwAceCount; i++) {
  863. pAceHdr = *(ppAceHdr + i);
  864. dwAceSize = pAceHdr->AceSize;
  865. dwAclSize += dwAceSize;
  866. }
  867. dwAclSize += sizeof(ACL);
  868. *pdwAclSize = dwAclSize;
  869. return(S_OK);
  870. }
  871. HRESULT
  872. ConvertAccessControlEntryToAce(
  873. IADsAccessControlEntry * pAccessControlEntry,
  874. LPBYTE * ppAce
  875. )
  876. {
  877. DWORD dwAceType = 0;
  878. HRESULT hr = S_OK;
  879. BSTR bstrTrustee = NULL;
  880. PSID pSid = NULL;
  881. DWORD dwSidSize = 0;
  882. DWORD dwAceFlags = 0;
  883. DWORD dwAccessMask = 0;
  884. DWORD dwAceSize = 0;
  885. LPBYTE pAce = NULL;
  886. PACCESS_MASK pAccessMask = NULL;
  887. PSID pSidAddress = NULL;
  888. PUSHORT pCompoundAceType = NULL;
  889. DWORD dwCompoundAceType = 0;
  890. PACE_HEADER pAceHeader = NULL;
  891. LPBYTE pOffset = NULL;
  892. BSTR bstrObjectTypeClsid = NULL;
  893. BSTR bstrInheritedObjectTypeClsid = NULL;
  894. GUID ObjectTypeGUID;
  895. GUID InheritedObjectTypeGUID;
  896. PULONG pFlags;
  897. DWORD dwFlags = 0;
  898. hr = pAccessControlEntry->get_AceType((LONG *)&dwAceType);
  899. BAIL_ON_FAILURE(hr);
  900. hr = pAccessControlEntry->get_Trustee(&bstrTrustee);
  901. BAIL_ON_FAILURE(hr);
  902. hr = ConvertTrusteeToSid(
  903. bstrTrustee,
  904. &pSid,
  905. &dwSidSize
  906. );
  907. BAIL_ON_FAILURE(hr);
  908. hr = pAccessControlEntry->get_AceFlags((long *)&dwAceFlags);
  909. BAIL_ON_FAILURE(hr);
  910. hr = pAccessControlEntry->get_AccessMask((long *)&dwAccessMask);
  911. BAIL_ON_FAILURE(hr);
  912. if( pSid )
  913. {
  914. PSID_IDENTIFIER_AUTHORITY pSIA = GetSidIdentifierAuthority( pSid );
  915. if( pSIA )
  916. {
  917. SID_IDENTIFIER_AUTHORITY sidEveryone = SECURITY_WORLD_SID_AUTHORITY;
  918. if( memcmp(pSIA, &sidEveryone, sizeof(SID_IDENTIFIER_AUTHORITY))== 0)
  919. {
  920. // It is an Everyone user
  921. dwAccessMask |= ADS_RIGHT_READ_CONTROL;
  922. }
  923. }
  924. }
  925. //
  926. // we will compensateby adding the entire ACE size
  927. //
  928. dwAceSize = dwSidSize - sizeof(ULONG);
  929. switch (dwAceType) {
  930. case ACCESS_ALLOWED_ACE_TYPE:
  931. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  932. pAce = new BYTE[dwAceSize];
  933. if (!pAce) {
  934. hr = E_OUTOFMEMORY;
  935. BAIL_ON_FAILURE(hr);
  936. }
  937. pAceHeader = (PACE_HEADER)pAce;
  938. pAceHeader->AceType = (UCHAR)dwAceType;
  939. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  940. pAceHeader->AceSize = (USHORT)dwAceSize;
  941. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  942. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  943. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  944. memcpy(pSidAddress, pSid, dwSidSize);
  945. break;
  946. case ACCESS_DENIED_ACE_TYPE:
  947. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  948. pAce = new BYTE[dwAceSize];
  949. if (!pAce) {
  950. hr = E_OUTOFMEMORY;
  951. BAIL_ON_FAILURE(hr);
  952. }
  953. pAceHeader = (PACE_HEADER)pAce;
  954. pAceHeader->AceType = (UCHAR)dwAceType;
  955. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  956. pAceHeader->AceSize = (USHORT)dwAceSize;
  957. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  958. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  959. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  960. memcpy(pSidAddress, pSid, dwSidSize);
  961. break;
  962. case SYSTEM_AUDIT_ACE_TYPE:
  963. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  964. pAce = new BYTE[dwAceSize];
  965. if (!pAce) {
  966. hr = E_OUTOFMEMORY;
  967. BAIL_ON_FAILURE(hr);
  968. }
  969. pAceHeader = (PACE_HEADER)pAce;
  970. pAceHeader->AceType = (UCHAR)dwAceType;
  971. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  972. pAceHeader->AceSize = (USHORT)dwAceSize;
  973. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  974. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  975. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  976. memcpy(pSidAddress, pSid, dwSidSize);
  977. break;
  978. case SYSTEM_ALARM_ACE_TYPE:
  979. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  980. pAce = new BYTE[dwAceSize];
  981. if (!pAce) {
  982. hr = E_OUTOFMEMORY;
  983. BAIL_ON_FAILURE(hr);
  984. }
  985. pAceHeader = (PACE_HEADER)pAce;
  986. pAceHeader->AceType = (UCHAR)dwAceType;
  987. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  988. pAceHeader->AceSize = (USHORT)dwAceSize;
  989. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  990. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  991. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  992. memcpy(pSidAddress, pSid, dwSidSize);
  993. break;
  994. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  995. dwAceSize += sizeof(COMPOUND_ACCESS_ALLOWED_ACE);
  996. pAce = new BYTE[dwAceSize];
  997. if (!pAce) {
  998. hr = E_OUTOFMEMORY;
  999. BAIL_ON_FAILURE(hr);
  1000. }
  1001. pAceHeader = (PACE_HEADER)pAce;
  1002. pAceHeader->AceType = (UCHAR)dwAceType;
  1003. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  1004. pAceHeader->AceSize = (USHORT)dwAceSize;
  1005. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  1006. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  1007. pCompoundAceType = (PUSHORT)(pAccessMask + sizeof(ACCESS_MASK));
  1008. *pCompoundAceType = (USHORT)dwCompoundAceType;
  1009. //
  1010. // Fill in the reserved field here.
  1011. //
  1012. pSidAddress = (PSID)((LPBYTE)pCompoundAceType + sizeof(DWORD));
  1013. memcpy(pSidAddress, pSid, dwSidSize);
  1014. break;
  1015. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  1016. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  1017. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  1018. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  1019. hr = pAccessControlEntry->get_AceFlags((LONG *)&dwAceFlags);
  1020. BAIL_ON_FAILURE(hr);
  1021. hr = pAccessControlEntry->get_Flags((LONG *)&dwFlags);
  1022. BAIL_ON_FAILURE(hr);
  1023. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  1024. dwAceSize += sizeof(GUID);
  1025. }
  1026. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  1027. dwAceSize += sizeof(GUID);
  1028. }
  1029. hr = pAccessControlEntry->get_ObjectType(&bstrObjectTypeClsid);
  1030. BAIL_ON_FAILURE(hr);
  1031. hr = CLSIDFromString(bstrObjectTypeClsid, &ObjectTypeGUID);
  1032. BAIL_ON_FAILURE(hr);
  1033. hr = pAccessControlEntry->get_InheritedObjectType(&bstrInheritedObjectTypeClsid);
  1034. BAIL_ON_FAILURE(hr);
  1035. hr = CLSIDFromString(bstrInheritedObjectTypeClsid, &InheritedObjectTypeGUID);
  1036. BAIL_ON_FAILURE(hr);
  1037. dwAceSize += sizeof(ACCESS_ALLOWED_OBJECT_ACE);
  1038. pAce = new BYTE[dwAceSize];
  1039. if (!pAce) {
  1040. hr = E_OUTOFMEMORY;
  1041. BAIL_ON_FAILURE(hr);
  1042. }
  1043. pAceHeader = (PACE_HEADER)pAce;
  1044. pAceHeader->AceType = (UCHAR)dwAceType;
  1045. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  1046. pAceHeader->AceSize = (USHORT)dwAceSize;
  1047. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  1048. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  1049. //
  1050. // Fill in Flags
  1051. //
  1052. pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
  1053. pFlags = (PULONG)(pOffset);
  1054. *pFlags = dwFlags;
  1055. pOffset += sizeof(ULONG);
  1056. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  1057. memcpy(pOffset, &ObjectTypeGUID, sizeof(GUID));
  1058. pOffset += sizeof(GUID);
  1059. }
  1060. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  1061. memcpy(pOffset, &InheritedObjectTypeGUID, sizeof(GUID));
  1062. pOffset += sizeof(GUID);
  1063. }
  1064. pSidAddress = (PSID)((LPBYTE)pOffset);
  1065. memcpy(pSidAddress, pSid, dwSidSize);
  1066. break;
  1067. }
  1068. *ppAce = pAce;
  1069. error:
  1070. if (bstrTrustee) {
  1071. SysFreeString(bstrTrustee);
  1072. }
  1073. if (pSid) {
  1074. delete (pSid);
  1075. }
  1076. return(hr);
  1077. }
  1078. HRESULT AddACEEveryone(
  1079. IADsAccessControlList FAR * pAccessList
  1080. )
  1081. {
  1082. // Declarations
  1083. DWORD dwAceCount = 0;
  1084. HRESULT hr = S_OK;
  1085. IUnknown * pUnknown = NULL;
  1086. IEnumVARIANT * pEnumerator = NULL;
  1087. DWORD i = 0;
  1088. DWORD cReturned = 0;
  1089. VARIANT varAce;
  1090. BOOL bEveryone = FALSE;
  1091. IADsAccessControlEntry FAR * pAccessControlEntry = NULL;
  1092. IDispatch* pACEDispatch = NULL;
  1093. PSID pSid = NULL;
  1094. DWORD dwSidSize = 0;
  1095. BSTR bstrTrustee = NULL;
  1096. // Get the ACE count
  1097. hr = pAccessList->get_AceCount((long*)&dwAceCount);
  1098. BAIL_ON_FAILURE(hr);
  1099. // Get the ACE enumeration
  1100. hr = pAccessList->get__NewEnum( &pUnknown );
  1101. BAIL_ON_FAILURE(hr);
  1102. hr = pUnknown->QueryInterface(
  1103. IID_IEnumVARIANT,
  1104. (void FAR * FAR *)&pEnumerator);
  1105. BAIL_ON_FAILURE(hr);
  1106. // Browse the enumeration
  1107. for (i = 0; i < dwAceCount; i++)
  1108. {
  1109. VariantInit(&varAce);
  1110. hr = pEnumerator->Next(
  1111. 1,
  1112. &varAce,
  1113. &cReturned
  1114. );
  1115. CONTINUE_ON_FAILURE(hr);
  1116. hr = (V_DISPATCH(&varAce))->QueryInterface(
  1117. IID_IADsAccessControlEntry,
  1118. (void **)&pAccessControlEntry
  1119. );
  1120. CONTINUE_ON_FAILURE(hr);
  1121. //
  1122. // Get the user
  1123. //
  1124. hr = pAccessControlEntry->get_Trustee(&bstrTrustee);
  1125. if( FAILED(hr) )
  1126. {
  1127. // Clean-up
  1128. VariantClear(&varAce);
  1129. pAccessControlEntry->Release();
  1130. pAccessControlEntry = NULL;
  1131. continue;
  1132. }
  1133. //
  1134. // Get the SID
  1135. //
  1136. hr = ConvertTrusteeToSid(
  1137. bstrTrustee,
  1138. &pSid,
  1139. &dwSidSize
  1140. );
  1141. if( FAILED(hr) )
  1142. {
  1143. // Clean-up
  1144. if( bstrTrustee )
  1145. {
  1146. SysFreeString( bstrTrustee );
  1147. bstrTrustee = NULL;
  1148. }
  1149. VariantClear(&varAce);
  1150. pAccessControlEntry->Release();
  1151. pAccessControlEntry = NULL;
  1152. continue;
  1153. }
  1154. //
  1155. // Validate if is the Everyone SID
  1156. //
  1157. if( pSid )
  1158. {
  1159. PSID_IDENTIFIER_AUTHORITY pSIA = GetSidIdentifierAuthority( pSid );
  1160. if( pSIA )
  1161. {
  1162. SID_IDENTIFIER_AUTHORITY sidEveryone = SECURITY_WORLD_SID_AUTHORITY;
  1163. if( memcmp(pSIA, &sidEveryone, sizeof(SID_IDENTIFIER_AUTHORITY))== 0)
  1164. {
  1165. // It is an Everyone user
  1166. bEveryone = TRUE;
  1167. // Clean-up
  1168. VariantClear(&varAce);
  1169. pAccessControlEntry->Release();
  1170. pAccessControlEntry = NULL;
  1171. // Break the loop
  1172. break;
  1173. }
  1174. }
  1175. }
  1176. VariantClear(&varAce);
  1177. if (pAccessControlEntry)
  1178. {
  1179. pAccessControlEntry->Release();
  1180. pAccessControlEntry = NULL;
  1181. }
  1182. if( bstrTrustee )
  1183. {
  1184. SysFreeString( bstrTrustee );
  1185. bstrTrustee = NULL;
  1186. }
  1187. }
  1188. if( !bEveryone)
  1189. {
  1190. // We have to add an everyone entry
  1191. hr = CoCreateInstance(
  1192. CLSID_AccessControlEntry,
  1193. NULL,
  1194. CLSCTX_INPROC_SERVER,
  1195. IID_IADsAccessControlEntry,
  1196. (void**)&pAccessControlEntry);
  1197. BAIL_ON_FAILURE(hr);
  1198. // Access mask
  1199. hr = pAccessControlEntry->put_AccessMask( ADS_RIGHT_READ_CONTROL );
  1200. BAIL_ON_FAILURE(hr);
  1201. // Ace type
  1202. hr = pAccessControlEntry->put_AceType( 0 );
  1203. BAIL_ON_FAILURE(hr);
  1204. // Ace flags
  1205. hr = pAccessControlEntry->put_AceFlags( 0 );
  1206. BAIL_ON_FAILURE(hr);
  1207. // Get the SID for everyone
  1208. WCHAR Trustee[256];
  1209. PSID pSidEveryone = NULL;
  1210. SID_IDENTIFIER_AUTHORITY siaEveryone = SECURITY_WORLD_SID_AUTHORITY;
  1211. BOOL bAllocate = AllocateAndInitializeSid(
  1212. &siaEveryone,
  1213. 1,0,0,0,0,0,0,0,0,
  1214. &pSidEveryone);
  1215. if( !bAllocate )
  1216. {
  1217. BAIL_ON_FAILURE(E_OUTOFMEMORY);
  1218. }
  1219. // Get the trustee for everyone
  1220. hr = ConvertSidToString( pSidEveryone, Trustee );
  1221. FreeSid( pSidEveryone);
  1222. BAIL_ON_FAILURE(hr);
  1223. bstrTrustee = SysAllocString( Trustee );
  1224. if( bstrTrustee == NULL)
  1225. {
  1226. BAIL_ON_FAILURE(E_OUTOFMEMORY);
  1227. }
  1228. // Add trustee
  1229. hr = pAccessControlEntry->put_Trustee( bstrTrustee );
  1230. BAIL_ON_FAILURE(hr);
  1231. // Get the IDispatch
  1232. hr = pAccessControlEntry->QueryInterface(
  1233. IID_IDispatch,
  1234. (void**)&pACEDispatch);
  1235. BAIL_ON_FAILURE(hr);
  1236. // Add ACE to the ACL
  1237. hr = pAccessList->AddAce( pACEDispatch );
  1238. BAIL_ON_FAILURE(hr);
  1239. }
  1240. error:
  1241. if (pUnknown) {
  1242. pUnknown->Release();
  1243. }
  1244. if (pEnumerator) {
  1245. pEnumerator->Release();
  1246. }
  1247. if( pACEDispatch )
  1248. {
  1249. pACEDispatch->Release();
  1250. }
  1251. if(pAccessControlEntry)
  1252. {
  1253. pAccessControlEntry->Release();
  1254. }
  1255. if( bstrTrustee )
  1256. {
  1257. SysFreeString( bstrTrustee );
  1258. }
  1259. return(hr);
  1260. }
  1261. HRESULT
  1262. ConvertAccessControlListToAcl(
  1263. IADsAccessControlList FAR * pAccessList,
  1264. PACL * ppAcl
  1265. )
  1266. {
  1267. IUnknown * pUnknown = NULL;
  1268. IEnumVARIANT * pEnumerator = NULL;
  1269. HRESULT hr = S_OK;
  1270. DWORD i = 0;
  1271. DWORD cReturned = 0;
  1272. VARIANT varAce;
  1273. DWORD dwAceCount = 0;
  1274. IADsAccessControlEntry FAR * pAccessControlEntry = NULL;
  1275. LPBYTE pTempAce = NULL;
  1276. DWORD dwCount = 0;
  1277. PACL pAcl = NULL;
  1278. DWORD dwAclSize = 0;
  1279. PACE_HEADER * ppAceHdr = NULL;
  1280. DWORD dwRet = 0;
  1281. DWORD dwAclRevision = 0;
  1282. DWORD dwStatus = 0;
  1283. DWORD dwError = 0;
  1284. hr = AddACEEveryone( pAccessList );
  1285. BAIL_ON_FAILURE(hr);
  1286. hr = pAccessList->get_AceCount((long *)&dwAceCount);
  1287. BAIL_ON_FAILURE(hr);
  1288. hr = pAccessList->get__NewEnum(
  1289. &pUnknown
  1290. );
  1291. BAIL_ON_FAILURE(hr);
  1292. hr = pUnknown->QueryInterface(
  1293. IID_IEnumVARIANT,
  1294. (void FAR * FAR *)&pEnumerator
  1295. );
  1296. BAIL_ON_FAILURE(hr);
  1297. ppAceHdr = new PACE_HEADER [dwAceCount];
  1298. if (!ppAceHdr) {
  1299. hr = E_OUTOFMEMORY;
  1300. BAIL_ON_FAILURE(hr);
  1301. }
  1302. for (i = 0; i < dwAceCount; i++) {
  1303. VariantInit(&varAce);
  1304. hr = pEnumerator->Next(
  1305. 1,
  1306. &varAce,
  1307. &cReturned
  1308. );
  1309. CONTINUE_ON_FAILURE(hr);
  1310. hr = (V_DISPATCH(&varAce))->QueryInterface(
  1311. IID_IADsAccessControlEntry,
  1312. (void **)&pAccessControlEntry
  1313. );
  1314. CONTINUE_ON_FAILURE(hr);
  1315. hr = ConvertAccessControlEntryToAce(
  1316. pAccessControlEntry,
  1317. &(pTempAce)
  1318. );
  1319. // ZoltanS: Rather than CONTINUE_ON_FAILURE, let's bail so that we
  1320. // know if the Ace we set is invalid.
  1321. BAIL_ON_FAILURE(hr);
  1322. *(ppAceHdr + dwCount) = (PACE_HEADER)pTempAce;
  1323. VariantClear(&varAce);
  1324. if (pAccessControlEntry) {
  1325. pAccessControlEntry->Release();
  1326. pAccessControlEntry = NULL;
  1327. }
  1328. dwCount++;
  1329. }
  1330. hr = ComputeTotalAclSize(ppAceHdr, dwCount, &dwAclSize);
  1331. BAIL_ON_FAILURE(hr);
  1332. pAcl = (PACL)new BYTE[dwAclSize];
  1333. if (!pAcl) {
  1334. hr = E_OUTOFMEMORY;
  1335. BAIL_ON_FAILURE(hr);
  1336. }
  1337. hr = pAccessList->get_AclRevision((long *)&dwAclRevision);
  1338. //
  1339. // we have to deallocate memory
  1340. //
  1341. if( FAILED(hr) && (NULL != pAcl) )
  1342. delete( pAcl );
  1343. BAIL_ON_FAILURE(hr);
  1344. dwRet = InitializeAcl(
  1345. pAcl,
  1346. dwAclSize,
  1347. dwAclRevision
  1348. );
  1349. if (!dwRet) {
  1350. hr = HRESULT_FROM_WIN32(GetLastError());
  1351. //
  1352. // we have to deallocate memory
  1353. //
  1354. if( FAILED(hr) && (NULL != pAcl) )
  1355. delete( pAcl );
  1356. BAIL_ON_FAILURE(hr);
  1357. }
  1358. for (i = 0; i < dwCount; i++) {
  1359. dwStatus = AddAce(
  1360. pAcl,
  1361. dwAclRevision,
  1362. i,
  1363. (LPBYTE)*(ppAceHdr + i),
  1364. (*(ppAceHdr + i))->AceSize
  1365. );
  1366. if (!dwStatus) {
  1367. dwError = GetLastError();
  1368. }
  1369. }
  1370. *ppAcl = pAcl;
  1371. error:
  1372. if (ppAceHdr) {
  1373. for (i = 0; i < dwCount; i++) {
  1374. if (*(ppAceHdr + i)) {
  1375. delete (*(ppAceHdr + i));
  1376. }
  1377. }
  1378. delete (ppAceHdr);
  1379. }
  1380. if (pUnknown) {
  1381. pUnknown->Release();
  1382. }
  1383. if (pEnumerator) {
  1384. pEnumerator->Release();
  1385. }
  1386. return(hr);
  1387. }
  1388. HRESULT
  1389. GetGroupSecurityIdentifier(
  1390. IADsSecurityDescriptor FAR * pSecDes,
  1391. PSID * ppSid,
  1392. PBOOL pfGroupDefaulted
  1393. )
  1394. {
  1395. BSTR bstrGroup = NULL;
  1396. DWORD dwSidSize = 0;
  1397. HRESULT hr = S_OK;
  1398. VARIANT_BOOL varBool = VARIANT_FALSE;
  1399. hr = pSecDes->get_Group(
  1400. &bstrGroup
  1401. );
  1402. BAIL_ON_FAILURE(hr);
  1403. hr = pSecDes->get_GroupDefaulted(
  1404. &varBool
  1405. );
  1406. BAIL_ON_FAILURE(hr);
  1407. if (varBool == VARIANT_FALSE) {
  1408. if (bstrGroup && *bstrGroup) {
  1409. hr = ConvertTrusteeToSid(
  1410. bstrGroup,
  1411. ppSid,
  1412. &dwSidSize
  1413. );
  1414. BAIL_ON_FAILURE(hr);
  1415. *pfGroupDefaulted = FALSE;
  1416. }else {
  1417. *ppSid = NULL;
  1418. *pfGroupDefaulted = FALSE;
  1419. }
  1420. }else {
  1421. *ppSid = NULL;
  1422. dwSidSize = 0;
  1423. *pfGroupDefaulted = TRUE;
  1424. }
  1425. error:
  1426. if (bstrGroup) {
  1427. SysFreeString(bstrGroup);
  1428. }
  1429. return(hr);
  1430. }
  1431. HRESULT
  1432. GetDacl(
  1433. IADsSecurityDescriptor FAR * pSecDes,
  1434. PACL * ppDacl,
  1435. PBOOL pfDaclDefaulted
  1436. )
  1437. {
  1438. IADsAccessControlList FAR * pDiscAcl = NULL;
  1439. IDispatch FAR * pDispatch = NULL;
  1440. HRESULT hr = S_OK;
  1441. VARIANT_BOOL varBool = VARIANT_FALSE;
  1442. hr = pSecDes->get_DaclDefaulted(
  1443. &varBool
  1444. );
  1445. BAIL_ON_FAILURE(hr);
  1446. if (varBool == VARIANT_FALSE) {
  1447. *pfDaclDefaulted = FALSE;
  1448. }else {
  1449. *pfDaclDefaulted = TRUE;
  1450. }
  1451. hr = pSecDes->get_DiscretionaryAcl(
  1452. &pDispatch
  1453. );
  1454. BAIL_ON_FAILURE(hr);
  1455. if (!pDispatch) {
  1456. *ppDacl = NULL;
  1457. goto error;
  1458. }
  1459. hr = pDispatch->QueryInterface(
  1460. IID_IADsAccessControlList,
  1461. (void **)&pDiscAcl
  1462. );
  1463. BAIL_ON_FAILURE(hr);
  1464. hr = ConvertAccessControlListToAcl(
  1465. pDiscAcl,
  1466. ppDacl
  1467. );
  1468. BAIL_ON_FAILURE(hr);
  1469. error:
  1470. if (pDispatch) {
  1471. pDispatch->Release();
  1472. }
  1473. if (pDiscAcl) {
  1474. pDiscAcl->Release();
  1475. }
  1476. return(hr);
  1477. }
  1478. HRESULT
  1479. GetSacl(
  1480. IADsSecurityDescriptor FAR * pSecDes,
  1481. PACL * ppSacl,
  1482. PBOOL pfSaclDefaulted
  1483. )
  1484. {
  1485. IADsAccessControlList FAR * pSystemAcl = NULL;
  1486. IDispatch FAR * pDispatch = NULL;
  1487. HRESULT hr = S_OK;
  1488. VARIANT_BOOL varBool = VARIANT_FALSE;
  1489. hr = pSecDes->get_SaclDefaulted(
  1490. &varBool
  1491. );
  1492. BAIL_ON_FAILURE(hr);
  1493. if (varBool == VARIANT_FALSE) {
  1494. *pfSaclDefaulted = FALSE;
  1495. }else {
  1496. *pfSaclDefaulted = TRUE;
  1497. }
  1498. hr = pSecDes->get_SystemAcl(
  1499. &pDispatch
  1500. );
  1501. BAIL_ON_FAILURE(hr);
  1502. if (!pDispatch) {
  1503. *ppSacl = NULL;
  1504. goto error;
  1505. }
  1506. hr = pDispatch->QueryInterface(
  1507. IID_IADsAccessControlList,
  1508. (void **)&pSystemAcl
  1509. );
  1510. BAIL_ON_FAILURE(hr);
  1511. hr = ConvertAccessControlListToAcl(
  1512. pSystemAcl,
  1513. ppSacl
  1514. );
  1515. BAIL_ON_FAILURE(hr);
  1516. error:
  1517. if (pDispatch) {
  1518. pDispatch->Release();
  1519. }
  1520. if (pSystemAcl) {
  1521. pSystemAcl->Release();
  1522. }
  1523. return(hr);
  1524. }
  1525. ///////////////////////////////////////////////////////////////////////////////
  1526. // //
  1527. // Public procedures //
  1528. // //
  1529. ///////////////////////////////////////////////////////////////////////////////
  1530. HRESULT
  1531. ConvertSDToIDispatch(
  1532. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1533. OUT IDispatch ** ppIDispatch
  1534. )
  1535. {
  1536. IADsSecurityDescriptor * pSecDes = NULL;
  1537. IDispatch * pDispatch = NULL;
  1538. LPWSTR pszGroup = NULL;
  1539. LPWSTR pszOwner = NULL;
  1540. BOOL fOwnerDefaulted = 0;
  1541. BOOL fGroupDefaulted = 0;
  1542. BOOL fDaclDefaulted = 0;
  1543. BOOL fSaclDefaulted = 0;
  1544. BOOL fSaclPresent = 0;
  1545. BOOL fDaclPresent = 0;
  1546. LPBYTE pOwnerSidAddress = NULL;
  1547. LPBYTE pGroupSidAddress = NULL;
  1548. LPBYTE pDACLAddress = NULL;
  1549. LPBYTE pSACLAddress = NULL;
  1550. DWORD dwRet = 0;
  1551. VARIANT varDACL;
  1552. VARIANT varSACL;
  1553. HRESULT hr = S_OK;
  1554. DWORD dwRevision = 0;
  1555. WORD wControl = 0;
  1556. memset(&varSACL, 0, sizeof(VARIANT));
  1557. memset(&varDACL, 0, sizeof(VARIANT));
  1558. if (!pSecurityDescriptor) {
  1559. return(E_FAIL);
  1560. }
  1561. dwRet = GetSecurityDescriptorControl(
  1562. pSecurityDescriptor,
  1563. &wControl,
  1564. &dwRevision
  1565. );
  1566. if (!dwRet){
  1567. hr = HRESULT_FROM_WIN32(GetLastError());
  1568. BAIL_ON_FAILURE(hr);
  1569. }
  1570. dwRet = GetSecurityDescriptorOwner(
  1571. pSecurityDescriptor,
  1572. (PSID *)&pOwnerSidAddress,
  1573. &fOwnerDefaulted
  1574. );
  1575. if (!dwRet){
  1576. hr = HRESULT_FROM_WIN32(GetLastError());
  1577. BAIL_ON_FAILURE(hr);
  1578. }
  1579. hr = ConvertSidToFriendlyName(
  1580. pOwnerSidAddress,
  1581. &pszOwner
  1582. );
  1583. BAIL_ON_FAILURE(hr);
  1584. dwRet = GetSecurityDescriptorGroup(
  1585. pSecurityDescriptor,
  1586. (PSID *)&pGroupSidAddress,
  1587. &fOwnerDefaulted
  1588. );
  1589. if (!dwRet){
  1590. hr = HRESULT_FROM_WIN32(GetLastError());
  1591. BAIL_ON_FAILURE(hr);
  1592. }
  1593. hr = ConvertSidToFriendlyName(
  1594. pGroupSidAddress,
  1595. &pszGroup
  1596. );
  1597. BAIL_ON_FAILURE(hr);
  1598. dwRet = GetSecurityDescriptorDacl(
  1599. pSecurityDescriptor,
  1600. &fDaclPresent,
  1601. (PACL*)&pDACLAddress,
  1602. &fDaclDefaulted
  1603. );
  1604. if (pDACLAddress) {
  1605. hr = ConvertACLToVariant(
  1606. (PACL)pDACLAddress,
  1607. &varDACL
  1608. );
  1609. BAIL_ON_FAILURE(hr);
  1610. }
  1611. dwRet = GetSecurityDescriptorSacl(
  1612. pSecurityDescriptor,
  1613. &fSaclPresent,
  1614. (PACL *)&pSACLAddress,
  1615. &fSaclDefaulted
  1616. );
  1617. if (!dwRet){
  1618. hr = HRESULT_FROM_WIN32(GetLastError());
  1619. BAIL_ON_FAILURE(hr);
  1620. }
  1621. if (pSACLAddress) {
  1622. hr = ConvertACLToVariant(
  1623. (PACL)pSACLAddress,
  1624. &varSACL
  1625. );
  1626. BAIL_ON_FAILURE(hr);
  1627. }
  1628. hr = CoCreateInstance(
  1629. CLSID_SecurityDescriptor,
  1630. NULL,
  1631. CLSCTX_INPROC_SERVER,
  1632. IID_IADsSecurityDescriptor,
  1633. (void **)&pSecDes
  1634. );
  1635. BAIL_ON_FAILURE(hr);
  1636. hr = pSecDes->put_Owner(pszOwner);
  1637. BAIL_ON_FAILURE(hr);
  1638. hr = pSecDes->put_Group(pszGroup);
  1639. BAIL_ON_FAILURE(hr);
  1640. hr = pSecDes->put_Revision(dwRevision);
  1641. BAIL_ON_FAILURE(hr);
  1642. hr = pSecDes->put_Control((DWORD)wControl);
  1643. BAIL_ON_FAILURE(hr);
  1644. hr = pSecDes->put_DiscretionaryAcl(V_DISPATCH(&varDACL));
  1645. BAIL_ON_FAILURE(hr);
  1646. hr = pSecDes->put_SystemAcl(V_DISPATCH(&varSACL));
  1647. BAIL_ON_FAILURE(hr);
  1648. hr = pSecDes->QueryInterface(IID_IDispatch, (void**)&pDispatch);
  1649. BAIL_ON_FAILURE(hr);
  1650. *ppIDispatch = pDispatch;
  1651. error:
  1652. VariantClear(&varSACL);
  1653. VariantClear(&varDACL);
  1654. if (pszOwner) {
  1655. delete (pszOwner);
  1656. }
  1657. if (pszGroup) {
  1658. delete (pszGroup);
  1659. }
  1660. if (pSecDes) {
  1661. pSecDes->Release();
  1662. }
  1663. return(hr);
  1664. }
  1665. HRESULT
  1666. ConvertSDToVariant(
  1667. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1668. OUT VARIANT * pVarSec
  1669. )
  1670. {
  1671. IDispatch *pIDispatch;
  1672. HRESULT hr = ConvertSDToIDispatch(pSecurityDescriptor, &pIDispatch);
  1673. if (FAILED(hr))
  1674. {
  1675. return hr;
  1676. }
  1677. VariantInit(pVarSec);
  1678. V_VT(pVarSec) = VT_DISPATCH;
  1679. V_DISPATCH(pVarSec) = pIDispatch;
  1680. return S_OK;
  1681. }
  1682. HRESULT
  1683. ConvertObjectToSD(
  1684. IN IADsSecurityDescriptor FAR * pSecDes,
  1685. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor,
  1686. OUT PDWORD pdwSDLength
  1687. )
  1688. {
  1689. HRESULT hr = S_OK;
  1690. SECURITY_DESCRIPTOR AbsoluteSD;
  1691. PSECURITY_DESCRIPTOR pRelative = NULL;
  1692. BOOL Defaulted = FALSE;
  1693. BOOL DaclPresent = FALSE;
  1694. BOOL SaclPresent = FALSE;
  1695. BOOL fDaclDefaulted = FALSE;
  1696. BOOL fSaclDefaulted = FALSE;
  1697. BOOL fOwnerDefaulted = FALSE;
  1698. BOOL fGroupDefaulted = FALSE;
  1699. PSID pOwnerSid = NULL;
  1700. PSID pGroupSid = NULL;
  1701. PACL pDacl = NULL;
  1702. PACL pSacl = NULL;
  1703. DWORD dwSDLength = 0;
  1704. DWORD dwRet = 0;
  1705. BOOL dwStatus = 0;
  1706. //
  1707. // Initialize *pSizeSD = 0;
  1708. //
  1709. dwRet = InitializeSecurityDescriptor (
  1710. &AbsoluteSD,
  1711. SECURITY_DESCRIPTOR_REVISION1
  1712. );
  1713. if (!dwRet) {
  1714. hr = E_FAIL;
  1715. BAIL_ON_FAILURE(hr);
  1716. }
  1717. hr = GetOwnerSecurityIdentifier(
  1718. pSecDes,
  1719. &pOwnerSid,
  1720. &fOwnerDefaulted
  1721. );
  1722. BAIL_ON_FAILURE(hr);
  1723. dwStatus = SetSecurityDescriptorOwner(
  1724. &AbsoluteSD,
  1725. pOwnerSid,
  1726. fOwnerDefaulted
  1727. );
  1728. if (!dwStatus) {
  1729. hr = HRESULT_FROM_WIN32(GetLastError());
  1730. BAIL_ON_FAILURE(hr);
  1731. }
  1732. hr = GetGroupSecurityIdentifier(
  1733. pSecDes,
  1734. &pGroupSid,
  1735. &fGroupDefaulted
  1736. );
  1737. BAIL_ON_FAILURE(hr);
  1738. dwStatus = SetSecurityDescriptorGroup(
  1739. &AbsoluteSD,
  1740. pGroupSid,
  1741. fGroupDefaulted
  1742. );
  1743. if (!dwStatus) {
  1744. hr = HRESULT_FROM_WIN32(GetLastError());
  1745. BAIL_ON_FAILURE(hr);
  1746. }
  1747. hr = GetDacl(
  1748. pSecDes,
  1749. &pDacl,
  1750. &fDaclDefaulted
  1751. );
  1752. BAIL_ON_FAILURE(hr);
  1753. if (pDacl || fDaclDefaulted) {
  1754. DaclPresent = TRUE;
  1755. }
  1756. dwStatus = SetSecurityDescriptorDacl(
  1757. &AbsoluteSD,
  1758. DaclPresent,
  1759. pDacl,
  1760. fDaclDefaulted
  1761. );
  1762. if (!dwStatus) {
  1763. hr = HRESULT_FROM_WIN32(GetLastError());
  1764. BAIL_ON_FAILURE(hr);
  1765. }
  1766. hr = GetSacl(
  1767. pSecDes,
  1768. &pSacl,
  1769. &fSaclDefaulted
  1770. );
  1771. BAIL_ON_FAILURE(hr);
  1772. if (pSacl || fSaclDefaulted) {
  1773. SaclPresent = TRUE;
  1774. }
  1775. dwStatus = SetSecurityDescriptorSacl(
  1776. &AbsoluteSD,
  1777. SaclPresent,
  1778. pSacl,
  1779. fSaclDefaulted
  1780. );
  1781. if (!dwStatus) {
  1782. hr = HRESULT_FROM_WIN32(GetLastError());
  1783. BAIL_ON_FAILURE(hr);
  1784. }
  1785. dwSDLength = GetSecurityDescriptorLength(
  1786. &AbsoluteSD
  1787. );
  1788. pRelative = new BYTE[dwSDLength];
  1789. if (!pRelative) {
  1790. hr = E_OUTOFMEMORY;
  1791. BAIL_ON_FAILURE(hr);
  1792. }
  1793. if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &dwSDLength)) {
  1794. delete (pRelative);
  1795. hr = HRESULT_FROM_WIN32(GetLastError());
  1796. BAIL_ON_FAILURE(hr);
  1797. }
  1798. *ppSecurityDescriptor = pRelative;
  1799. *pdwSDLength = dwSDLength;
  1800. cleanup:
  1801. if (pDacl) {
  1802. delete (pDacl);
  1803. }
  1804. if (pSacl) {
  1805. delete (pSacl);
  1806. }
  1807. if (pOwnerSid) {
  1808. delete (pOwnerSid);
  1809. }
  1810. if (pGroupSid) {
  1811. delete (pGroupSid);
  1812. }
  1813. return(hr);
  1814. error:
  1815. if (pRelative) {
  1816. delete (pRelative);
  1817. }
  1818. *ppSecurityDescriptor = NULL;
  1819. *pdwSDLength = 0;
  1820. goto cleanup;
  1821. }
  1822. HRESULT
  1823. ConvertObjectToSDDispatch(
  1824. IN IDispatch * pDisp,
  1825. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor,
  1826. OUT PDWORD pdwSDLength
  1827. )
  1828. {
  1829. HRESULT hr;
  1830. IADsSecurityDescriptor * pSecDes;
  1831. hr = pDisp->QueryInterface(
  1832. IID_IADsSecurityDescriptor,
  1833. (VOID **)&pSecDes
  1834. );
  1835. if (FAILED(hr))
  1836. {
  1837. return hr;
  1838. }
  1839. hr = ConvertObjectToSD(pSecDes, ppSecurityDescriptor, pdwSDLength);
  1840. return hr;
  1841. }
  1842. // Returns FALSE if these two security descriptors are identical.
  1843. // Returns TRUE if they differ, or if there is any error parsing either of them
  1844. BOOL CheckIfSecurityDescriptorsDiffer(PSECURITY_DESCRIPTOR pSD1,
  1845. DWORD dwSDSize1,
  1846. PSECURITY_DESCRIPTOR pSD2,
  1847. DWORD dwSDSize2)
  1848. {
  1849. //
  1850. // If one of them is null, then they differ. (It should be impossible for them
  1851. // to both be null, but if they are, they had better both have size 0, which
  1852. // would just make us return TRUE below, so that's ok.)
  1853. //
  1854. if ( ( pSD1 == NULL ) || ( pSD2 == NULL ) )
  1855. {
  1856. return TRUE;
  1857. }
  1858. // if they converted to different sized structures then they are different
  1859. if ( dwSDSize1 != dwSDSize2 )
  1860. {
  1861. return TRUE;
  1862. }
  1863. // we know both succeeded conversion and converted to the same sized structures
  1864. // if the structures contain the same bytes then they are identical
  1865. if ( 0 == memcmp(pSD1, pSD2, dwSDSize1) )
  1866. {
  1867. return FALSE;
  1868. }
  1869. // else they differ
  1870. return TRUE;
  1871. }
  1872. // eof