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

2529 lines
58 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. if( (dwLen <= dwAccountNameSize) || (dwLen<=dwDomainNameSize) )
  424. {
  425. return E_FAIL;
  426. }
  427. WCHAR * pszAccountName = new WCHAR [dwLen];
  428. if (!pszAccountName)
  429. {
  430. return E_OUTOFMEMORY;
  431. }
  432. //
  433. // Copy in the domain and user name
  434. // to get the trustee name
  435. //
  436. if ( dwDomainNameSize != 0 )
  437. {
  438. // strange +1 needed because it will also put in a NULL terminator
  439. lstrcpynW(pszAccountName, szDomainName, dwDomainNameSize+1);
  440. lstrcatW(pszAccountName, L"\\");
  441. }
  442. else
  443. {
  444. pszAccountName[0] = L'\0';
  445. }
  446. wcsncat(pszAccountName, szAccountName, dwAccountNameSize);
  447. //
  448. // Set the trustee name on the ACE
  449. //
  450. IDispatch * pDispatch = V_DISPATCH(pVarAce);
  451. IADsAccessControlEntry * pACE;
  452. HRESULT hr;
  453. hr = pDispatch->QueryInterface(IID_IADsAccessControlEntry,
  454. (void **) & pACE);
  455. hr = pACE->put_Trustee(pszAccountName);
  456. pACE->Release();
  457. delete [] pszAccountName;
  458. return hr;
  459. }
  460. //
  461. // ZoltanS optimized version of ConvertACLToVariant
  462. //
  463. HRESULT
  464. ConvertACLToVariant(
  465. PACL pACL,
  466. LPVARIANT pvarACL
  467. )
  468. {
  469. IADsAccessControlList * pAccessControlList = NULL;
  470. IDispatch * pDispatch = NULL;
  471. DWORD dwAclSize = 0;
  472. DWORD dwAclRevision = 0;
  473. DWORD dwAceCount = 0;
  474. ACL_SIZE_INFORMATION AclSize;
  475. ACL_REVISION_INFORMATION AclRevision;
  476. DWORD dwStatus = 0;
  477. DWORD i = 0;
  478. DWORD dwNewAceCount = 0;
  479. HRESULT hr = S_OK;
  480. LPBYTE pAceAddress = NULL;
  481. memset(&AclSize, 0, sizeof(ACL_SIZE_INFORMATION));
  482. memset(&AclRevision, 0, sizeof(ACL_REVISION_INFORMATION));
  483. dwStatus = GetAclInformation(
  484. pACL,
  485. &AclSize,
  486. sizeof(ACL_SIZE_INFORMATION),
  487. AclSizeInformation
  488. );
  489. dwStatus = GetAclInformation(
  490. pACL,
  491. &AclRevision,
  492. sizeof(ACL_REVISION_INFORMATION),
  493. AclRevisionInformation
  494. );
  495. dwAceCount = AclSize.AceCount;
  496. dwAclRevision = AclRevision.AclRevision;
  497. VariantInit(pvarACL);
  498. hr = CoCreateInstance(
  499. CLSID_AccessControlList,
  500. NULL,
  501. CLSCTX_INPROC_SERVER,
  502. IID_IADsAccessControlList,
  503. (void **)&pAccessControlList
  504. );
  505. if ( FAILED(hr) )
  506. {
  507. return hr;
  508. }
  509. PSID * apSids = new PSID[ dwAceCount ];
  510. if ( apSids == NULL )
  511. {
  512. pAccessControlList->Release();
  513. return E_OUTOFMEMORY;
  514. }
  515. VARIANT * aVarAces = new VARIANT[ dwAceCount ];
  516. if ( aVarAces == NULL )
  517. {
  518. pAccessControlList->Release();
  519. delete apSids;
  520. return E_OUTOFMEMORY;
  521. }
  522. for (i = 0; i < dwAceCount; i++)
  523. {
  524. dwStatus = GetAce(pACL, i, (void **)&pAceAddress);
  525. hr = ConvertAceToVariant(
  526. pAceAddress,
  527. aVarAces + i,
  528. apSids + i );
  529. }
  530. //
  531. // Above, ConvertAceToVariant did not set the trustee names on the ACEs.
  532. // Instead we have an array (apSids) of dwNewAceCount valid PSIDs.
  533. // Convert all of these to trustees now.
  534. //
  535. PLSA_REFERENCED_DOMAIN_LIST pDomains = NULL;
  536. PLSA_TRANSLATED_NAME pTrustees = NULL;
  537. BOOL fStatus = LookupArrayOfSids(
  538. dwAceCount, // IN count
  539. apSids, // IN array of sid pointers
  540. &pDomains, // OUT referenced domain list
  541. &pTrustees); // OUT translated name list
  542. delete apSids;
  543. if ( fStatus == FALSE )
  544. {
  545. // LookupArrayOfSids failed
  546. hr = E_FAIL;
  547. }
  548. else
  549. {
  550. //
  551. // Set the trustees on the ACEs here
  552. //
  553. for ( i = 0; i < dwAceCount; i++ )
  554. {
  555. VARIANT * pVarAce = aVarAces + i;
  556. hr = SetTrusteeOnACE(
  557. pVarAce,
  558. pDomains,
  559. pTrustees + i
  560. );
  561. hr = pAccessControlList->AddAce( V_DISPATCH ( pVarAce ) );
  562. VariantClear( pVarAce );
  563. if ( SUCCEEDED(hr) )
  564. {
  565. dwNewAceCount++;
  566. }
  567. }
  568. //
  569. // Free output buffers returned by LsaLookupSids
  570. //
  571. DWORD Status;
  572. Status = LsaFreeMemory( pTrustees );
  573. _ASSERTE( NT_SUCCESS( Status ));
  574. Status = LsaFreeMemory( pDomains );
  575. _ASSERTE( NT_SUCCESS( Status ));
  576. pAccessControlList->put_AclRevision(dwAclRevision);
  577. pAccessControlList->put_AceCount(dwNewAceCount);
  578. hr = pAccessControlList->QueryInterface(
  579. IID_IDispatch,
  580. (void **)&pDispatch
  581. );
  582. V_VT(pvarACL) = VT_DISPATCH;
  583. V_DISPATCH(pvarACL) = pDispatch;
  584. }
  585. pAccessControlList->Release();
  586. //
  587. // aVarAces was dynamic allocated
  588. // aVarAces should be deallocated
  589. //
  590. delete aVarAces;
  591. return(hr);
  592. }
  593. HRESULT
  594. SecCreateSidFromArray (
  595. OUT PSID *PPSid,
  596. IN PSID_IDENTIFIER_AUTHORITY PSidAuthority,
  597. IN UCHAR SubAuthorityCount,
  598. IN ULONG SubAuthorities[],
  599. OUT PDWORD pdwSidSize
  600. )
  601. /*++
  602. Routine Description:
  603. Creates a SID with desired authority and sub authorities.
  604. NOTE: This routine allocates memory for the SID. When finished
  605. the caller should free memory using SEC_FREE (PSid).
  606. Arguments:
  607. PPSid -- addr of ptr to SID to be created
  608. Note: if SID creation fails ptr set to NULL
  609. PSidAuthority -- desired value for SID authority
  610. SubAuthorityCount -- number of sub authorities desired
  611. SubAuthorities -- sub-authority values, MUST SPECIFY contain
  612. at least SubAuthorityCount number of values
  613. Return Value:
  614. STATUS_SUCCESS if SID created.
  615. STATUS_UNSUCCESSFUL otherwise.
  616. --*/
  617. {
  618. USHORT iSub; /* sub-authority index */
  619. DWORD dwSidSize = 0;
  620. HRESULT hr = S_OK;
  621. /* allocate memory for SID */
  622. dwSidSize = RtlLengthRequiredSid(SubAuthorityCount);
  623. *PPSid = (PSID) new BYTE[dwSidSize];
  624. if (! *PPSid){
  625. hr = E_OUTOFMEMORY;
  626. BAIL_ON_FAILURE(hr);
  627. }
  628. *pdwSidSize = dwSidSize;
  629. /* initialize SID with top level SID identifier authority */
  630. RtlInitializeSid( *PPSid, PSidAuthority, SubAuthorityCount);
  631. /* fill in sub authorities */
  632. for (iSub=0; iSub < SubAuthorityCount; iSub++)
  633. * RtlSubAuthoritySid( *PPSid, iSub) = SubAuthorities[iSub];
  634. /* sanity check */
  635. if ( ! RtlValidSid( *PPSid) ) {
  636. delete (*PPSid);
  637. *PPSid = NULL;
  638. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  639. BAIL_ON_FAILURE(hr);
  640. }
  641. error:
  642. return(hr);
  643. }
  644. HRESULT
  645. ConvertStringToSid(
  646. IN PWSTR string,
  647. OUT PSID *sid,
  648. OUT PDWORD pdwSidSize,
  649. OUT PWSTR *end
  650. )
  651. {
  652. HRESULT hr = S_OK;
  653. UCHAR revision;
  654. UCHAR sub_authority_count;
  655. SID_IDENTIFIER_AUTHORITY authority;
  656. ULONG sub_authority[SID_MAX_SUB_AUTHORITIES];
  657. PWSTR end_list;
  658. PWSTR current;
  659. PWSTR next;
  660. ULONG x;
  661. *sid = NULL;
  662. if ( string == NULL )
  663. {
  664. return E_POINTER;
  665. }
  666. if (((*string != L'S') && (*string != L's')) || (*(string + 1) != L'-'))
  667. {
  668. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  669. BAIL_ON_FAILURE(hr);
  670. }
  671. current = string + 2;
  672. revision = (UCHAR)wcstol(current, &end_list, 10);
  673. current = end_list + 1;
  674. //
  675. // Count the number of characters in the indentifer authority...
  676. //
  677. next = wcschr(current, L'-');
  678. if((next != NULL) &&
  679. (next - current == 6))
  680. {
  681. for(x = 0; x < 6; x++)
  682. {
  683. authority.Value[x] = (UCHAR)next[x];
  684. }
  685. current +=6;
  686. }
  687. else
  688. {
  689. ULONG Auto = wcstoul(current, &end_list, 10);
  690. authority.Value[0] = authority.Value[1] = 0;
  691. authority.Value[5] = (UCHAR)Auto & 0xF;
  692. authority.Value[4] = (UCHAR)((Auto >> 8) & 0xFF);
  693. authority.Value[3] = (UCHAR)((Auto >> 16) & 0xFF);
  694. authority.Value[2] = (UCHAR)((Auto >> 24) & 0xFF);
  695. current = end_list;
  696. }
  697. //
  698. // Now, count the number of sub auths
  699. //
  700. sub_authority_count = 0;
  701. //
  702. // Initialize sub_authority array
  703. //
  704. memset( sub_authority, 0, sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES );
  705. next = current;
  706. //
  707. // We'll have to count our sub authoritys one character at a time,
  708. // since there are several deliminators that we can have...
  709. //
  710. while(next)
  711. {
  712. next++;
  713. if(*next == L'-')
  714. {
  715. //
  716. // We've found one!
  717. //
  718. sub_authority_count++;
  719. }
  720. else if(*next == L';' || *next == L'\0')
  721. {
  722. *end = next;
  723. sub_authority_count++;
  724. break;
  725. }
  726. }
  727. if(sub_authority_count != 0)
  728. {
  729. current++;
  730. for(x = 0; x < sub_authority_count; x++)
  731. {
  732. sub_authority[x] = wcstoul(current, &end_list, 10);
  733. current = end_list + 1;
  734. }
  735. }
  736. //
  737. // Now, create the SID
  738. //
  739. hr = SecCreateSidFromArray(
  740. sid,
  741. &authority,
  742. sub_authority_count,
  743. sub_authority,
  744. pdwSidSize
  745. );
  746. if (SUCCEEDED(hr))
  747. {
  748. /* Set the revision to what was specified in the string, in case, our
  749. system creates one with newer revision */
  750. ((SID *)(*sid))->Revision = revision;
  751. }
  752. error:
  753. return(hr);
  754. }
  755. HRESULT
  756. ConvertTrusteeToSid(
  757. BSTR bstrTrustee,
  758. PSID * ppSid,
  759. PDWORD pdwSidSize
  760. )
  761. {
  762. HRESULT hr = S_OK;
  763. BYTE Sid[MAX_PATH];
  764. ZeroMemory(Sid, MAX_PATH*sizeof(BYTE));
  765. DWORD dwSidSize = sizeof(Sid);
  766. DWORD dwRet = 0;
  767. WCHAR szDomainName[MAX_PATH];
  768. DWORD dwDomainSize = sizeof(szDomainName)/sizeof(WCHAR);
  769. SID_NAME_USE eUse;
  770. PSID pSid = NULL;
  771. LPWSTR pszEnd = NULL;
  772. BOOL fNTDSType = FALSE;
  773. dwSidSize = sizeof(Sid);
  774. dwRet = LookupAccountName(
  775. NULL,
  776. bstrTrustee,
  777. Sid,
  778. &dwSidSize,
  779. szDomainName,
  780. &dwDomainSize,
  781. (PSID_NAME_USE)&eUse
  782. );
  783. if (!dwRet) {
  784. hr = HRESULT_FROM_WIN32(GetLastError());
  785. }
  786. //
  787. // If neither the NTDS nor the U2 conversion
  788. // worked, then try a textual translation
  789. //
  790. if (FAILED(hr)) {
  791. hr = ConvertStringToSid(
  792. bstrTrustee,
  793. &pSid,
  794. &dwSidSize,
  795. &pszEnd
  796. );
  797. BAIL_ON_FAILURE(hr);
  798. memcpy(Sid,pSid, dwSidSize);
  799. if (pSid) {
  800. delete pSid;
  801. }
  802. }
  803. pSid = (PSID) new BYTE[dwSidSize];
  804. if (!pSid) {
  805. hr = E_OUTOFMEMORY;
  806. BAIL_ON_FAILURE(hr);
  807. }
  808. memcpy(pSid, Sid, dwSidSize);
  809. *pdwSidSize = dwSidSize;
  810. *ppSid = pSid;
  811. error:
  812. return(hr);
  813. }
  814. HRESULT
  815. GetOwnerSecurityIdentifier(
  816. IADsSecurityDescriptor FAR * pSecDes,
  817. PSID * ppSid,
  818. PBOOL pfOwnerDefaulted
  819. )
  820. {
  821. BSTR bstrOwner = NULL;
  822. DWORD dwSidSize = 0;
  823. HRESULT hr = S_OK;
  824. VARIANT_BOOL varBool = VARIANT_FALSE;
  825. hr = pSecDes->get_Owner(
  826. &bstrOwner
  827. );
  828. BAIL_ON_FAILURE(hr);
  829. hr = pSecDes->get_OwnerDefaulted(
  830. &varBool
  831. );
  832. BAIL_ON_FAILURE(hr);
  833. if (varBool == VARIANT_FALSE) {
  834. if (bstrOwner && *bstrOwner) {
  835. hr = ConvertTrusteeToSid(
  836. bstrOwner,
  837. ppSid,
  838. &dwSidSize
  839. );
  840. BAIL_ON_FAILURE(hr);
  841. *pfOwnerDefaulted = FALSE;
  842. }else {
  843. *ppSid = NULL;
  844. *pfOwnerDefaulted = FALSE;
  845. }
  846. }else {
  847. *ppSid = NULL;
  848. dwSidSize = 0;
  849. *pfOwnerDefaulted = TRUE;
  850. }
  851. error:
  852. if (bstrOwner) {
  853. SysFreeString(bstrOwner);
  854. }
  855. return(hr);
  856. }
  857. HRESULT
  858. ComputeTotalAclSize(
  859. PACE_HEADER * ppAceHdr,
  860. DWORD dwAceCount,
  861. PDWORD pdwAclSize
  862. )
  863. {
  864. DWORD i = 0;
  865. PACE_HEADER pAceHdr = NULL;
  866. DWORD dwAceSize = 0;
  867. DWORD dwAclSize = 0;
  868. for (i = 0; i < dwAceCount; i++) {
  869. pAceHdr = *(ppAceHdr + i);
  870. dwAceSize = pAceHdr->AceSize;
  871. dwAclSize += dwAceSize;
  872. }
  873. dwAclSize += sizeof(ACL);
  874. *pdwAclSize = dwAclSize;
  875. return(S_OK);
  876. }
  877. HRESULT
  878. ConvertAccessControlEntryToAce(
  879. IADsAccessControlEntry * pAccessControlEntry,
  880. LPBYTE * ppAce
  881. )
  882. {
  883. DWORD dwAceType = 0;
  884. HRESULT hr = S_OK;
  885. BSTR bstrTrustee = NULL;
  886. PSID pSid = NULL;
  887. DWORD dwSidSize = 0;
  888. DWORD dwAceFlags = 0;
  889. DWORD dwAccessMask = 0;
  890. DWORD dwAceSize = 0;
  891. LPBYTE pAce = NULL;
  892. PACCESS_MASK pAccessMask = NULL;
  893. PSID pSidAddress = NULL;
  894. PUSHORT pCompoundAceType = NULL;
  895. DWORD dwCompoundAceType = 0;
  896. PACE_HEADER pAceHeader = NULL;
  897. LPBYTE pOffset = NULL;
  898. BSTR bstrObjectTypeClsid = NULL;
  899. BSTR bstrInheritedObjectTypeClsid = NULL;
  900. GUID ObjectTypeGUID;
  901. GUID InheritedObjectTypeGUID;
  902. PULONG pFlags;
  903. DWORD dwFlags = 0;
  904. hr = pAccessControlEntry->get_AceType((LONG *)&dwAceType);
  905. BAIL_ON_FAILURE(hr);
  906. hr = pAccessControlEntry->get_Trustee(&bstrTrustee);
  907. BAIL_ON_FAILURE(hr);
  908. hr = ConvertTrusteeToSid(
  909. bstrTrustee,
  910. &pSid,
  911. &dwSidSize
  912. );
  913. BAIL_ON_FAILURE(hr);
  914. hr = pAccessControlEntry->get_AceFlags((long *)&dwAceFlags);
  915. BAIL_ON_FAILURE(hr);
  916. hr = pAccessControlEntry->get_AccessMask((long *)&dwAccessMask);
  917. BAIL_ON_FAILURE(hr);
  918. if( pSid )
  919. {
  920. PSID_IDENTIFIER_AUTHORITY pSIA = GetSidIdentifierAuthority( pSid );
  921. if( pSIA )
  922. {
  923. SID_IDENTIFIER_AUTHORITY sidEveryone = SECURITY_WORLD_SID_AUTHORITY;
  924. if( memcmp(pSIA, &sidEveryone, sizeof(SID_IDENTIFIER_AUTHORITY))== 0)
  925. {
  926. // It is an Everyone user
  927. dwAccessMask |= ADS_RIGHT_READ_CONTROL;
  928. }
  929. }
  930. }
  931. //
  932. // we will compensateby adding the entire ACE size
  933. //
  934. dwAceSize = dwSidSize - sizeof(ULONG);
  935. switch (dwAceType) {
  936. case ACCESS_ALLOWED_ACE_TYPE:
  937. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  938. pAce = new BYTE[dwAceSize];
  939. if (!pAce) {
  940. hr = E_OUTOFMEMORY;
  941. BAIL_ON_FAILURE(hr);
  942. }
  943. pAceHeader = (PACE_HEADER)pAce;
  944. pAceHeader->AceType = (UCHAR)dwAceType;
  945. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  946. pAceHeader->AceSize = (USHORT)dwAceSize;
  947. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  948. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  949. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  950. memcpy(pSidAddress, pSid, dwSidSize);
  951. break;
  952. case ACCESS_DENIED_ACE_TYPE:
  953. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  954. pAce = new BYTE[dwAceSize];
  955. if (!pAce) {
  956. hr = E_OUTOFMEMORY;
  957. BAIL_ON_FAILURE(hr);
  958. }
  959. pAceHeader = (PACE_HEADER)pAce;
  960. pAceHeader->AceType = (UCHAR)dwAceType;
  961. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  962. pAceHeader->AceSize = (USHORT)dwAceSize;
  963. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  964. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  965. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  966. memcpy(pSidAddress, pSid, dwSidSize);
  967. break;
  968. case SYSTEM_AUDIT_ACE_TYPE:
  969. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  970. pAce = new BYTE[dwAceSize];
  971. if (!pAce) {
  972. hr = E_OUTOFMEMORY;
  973. BAIL_ON_FAILURE(hr);
  974. }
  975. pAceHeader = (PACE_HEADER)pAce;
  976. pAceHeader->AceType = (UCHAR)dwAceType;
  977. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  978. pAceHeader->AceSize = (USHORT)dwAceSize;
  979. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  980. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  981. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  982. memcpy(pSidAddress, pSid, dwSidSize);
  983. break;
  984. case SYSTEM_ALARM_ACE_TYPE:
  985. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  986. pAce = new BYTE[dwAceSize];
  987. if (!pAce) {
  988. hr = E_OUTOFMEMORY;
  989. BAIL_ON_FAILURE(hr);
  990. }
  991. pAceHeader = (PACE_HEADER)pAce;
  992. pAceHeader->AceType = (UCHAR)dwAceType;
  993. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  994. pAceHeader->AceSize = (USHORT)dwAceSize;
  995. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  996. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  997. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  998. memcpy(pSidAddress, pSid, dwSidSize);
  999. break;
  1000. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  1001. dwAceSize += sizeof(COMPOUND_ACCESS_ALLOWED_ACE);
  1002. pAce = new BYTE[dwAceSize];
  1003. if (!pAce) {
  1004. hr = E_OUTOFMEMORY;
  1005. BAIL_ON_FAILURE(hr);
  1006. }
  1007. pAceHeader = (PACE_HEADER)pAce;
  1008. pAceHeader->AceType = (UCHAR)dwAceType;
  1009. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  1010. pAceHeader->AceSize = (USHORT)dwAceSize;
  1011. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  1012. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  1013. pCompoundAceType = (PUSHORT)(pAccessMask + sizeof(ACCESS_MASK));
  1014. *pCompoundAceType = (USHORT)dwCompoundAceType;
  1015. //
  1016. // Fill in the reserved field here.
  1017. //
  1018. pSidAddress = (PSID)((LPBYTE)pCompoundAceType + sizeof(DWORD));
  1019. memcpy(pSidAddress, pSid, dwSidSize);
  1020. break;
  1021. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  1022. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  1023. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  1024. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  1025. hr = pAccessControlEntry->get_AceFlags((LONG *)&dwAceFlags);
  1026. BAIL_ON_FAILURE(hr);
  1027. hr = pAccessControlEntry->get_Flags((LONG *)&dwFlags);
  1028. BAIL_ON_FAILURE(hr);
  1029. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  1030. dwAceSize += sizeof(GUID);
  1031. }
  1032. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  1033. dwAceSize += sizeof(GUID);
  1034. }
  1035. hr = pAccessControlEntry->get_ObjectType(&bstrObjectTypeClsid);
  1036. BAIL_ON_FAILURE(hr);
  1037. hr = CLSIDFromString(bstrObjectTypeClsid, &ObjectTypeGUID);
  1038. BAIL_ON_FAILURE(hr);
  1039. hr = pAccessControlEntry->get_InheritedObjectType(&bstrInheritedObjectTypeClsid);
  1040. BAIL_ON_FAILURE(hr);
  1041. hr = CLSIDFromString(bstrInheritedObjectTypeClsid, &InheritedObjectTypeGUID);
  1042. BAIL_ON_FAILURE(hr);
  1043. dwAceSize += sizeof(ACCESS_ALLOWED_OBJECT_ACE);
  1044. pAce = new BYTE[dwAceSize];
  1045. if (!pAce) {
  1046. hr = E_OUTOFMEMORY;
  1047. BAIL_ON_FAILURE(hr);
  1048. }
  1049. pAceHeader = (PACE_HEADER)pAce;
  1050. pAceHeader->AceType = (UCHAR)dwAceType;
  1051. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  1052. pAceHeader->AceSize = (USHORT)dwAceSize;
  1053. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  1054. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  1055. //
  1056. // Fill in Flags
  1057. //
  1058. pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
  1059. pFlags = (PULONG)(pOffset);
  1060. *pFlags = dwFlags;
  1061. pOffset += sizeof(ULONG);
  1062. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  1063. memcpy(pOffset, &ObjectTypeGUID, sizeof(GUID));
  1064. pOffset += sizeof(GUID);
  1065. }
  1066. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  1067. memcpy(pOffset, &InheritedObjectTypeGUID, sizeof(GUID));
  1068. pOffset += sizeof(GUID);
  1069. }
  1070. pSidAddress = (PSID)((LPBYTE)pOffset);
  1071. memcpy(pSidAddress, pSid, dwSidSize);
  1072. break;
  1073. }
  1074. *ppAce = pAce;
  1075. error:
  1076. if (bstrTrustee) {
  1077. SysFreeString(bstrTrustee);
  1078. }
  1079. if (pSid) {
  1080. delete (pSid);
  1081. }
  1082. return(hr);
  1083. }
  1084. HRESULT AddACEEveryone(
  1085. IADsAccessControlList FAR * pAccessList
  1086. )
  1087. {
  1088. // Declarations
  1089. DWORD dwAceCount = 0;
  1090. HRESULT hr = S_OK;
  1091. IUnknown * pUnknown = NULL;
  1092. IEnumVARIANT * pEnumerator = NULL;
  1093. DWORD i = 0;
  1094. DWORD cReturned = 0;
  1095. VARIANT varAce;
  1096. BOOL bEveryone = FALSE;
  1097. IADsAccessControlEntry FAR * pAccessControlEntry = NULL;
  1098. IDispatch* pACEDispatch = NULL;
  1099. PSID pSid = NULL;
  1100. DWORD dwSidSize = 0;
  1101. BSTR bstrTrustee = NULL;
  1102. // Get the ACE count
  1103. hr = pAccessList->get_AceCount((long*)&dwAceCount);
  1104. BAIL_ON_FAILURE(hr);
  1105. // Get the ACE enumeration
  1106. hr = pAccessList->get__NewEnum( &pUnknown );
  1107. BAIL_ON_FAILURE(hr);
  1108. hr = pUnknown->QueryInterface(
  1109. IID_IEnumVARIANT,
  1110. (void FAR * FAR *)&pEnumerator);
  1111. BAIL_ON_FAILURE(hr);
  1112. // Browse the enumeration
  1113. for (i = 0; i < dwAceCount; i++)
  1114. {
  1115. VariantInit(&varAce);
  1116. hr = pEnumerator->Next(
  1117. 1,
  1118. &varAce,
  1119. &cReturned
  1120. );
  1121. CONTINUE_ON_FAILURE(hr);
  1122. hr = (V_DISPATCH(&varAce))->QueryInterface(
  1123. IID_IADsAccessControlEntry,
  1124. (void **)&pAccessControlEntry
  1125. );
  1126. CONTINUE_ON_FAILURE(hr);
  1127. //
  1128. // Get the user
  1129. //
  1130. hr = pAccessControlEntry->get_Trustee(&bstrTrustee);
  1131. if( FAILED(hr) )
  1132. {
  1133. // Clean-up
  1134. VariantClear(&varAce);
  1135. pAccessControlEntry->Release();
  1136. pAccessControlEntry = NULL;
  1137. continue;
  1138. }
  1139. //
  1140. // Get the SID
  1141. //
  1142. hr = ConvertTrusteeToSid(
  1143. bstrTrustee,
  1144. &pSid,
  1145. &dwSidSize
  1146. );
  1147. if( FAILED(hr) )
  1148. {
  1149. // Clean-up
  1150. if( bstrTrustee )
  1151. {
  1152. SysFreeString( bstrTrustee );
  1153. bstrTrustee = NULL;
  1154. }
  1155. VariantClear(&varAce);
  1156. pAccessControlEntry->Release();
  1157. pAccessControlEntry = NULL;
  1158. continue;
  1159. }
  1160. //
  1161. // Validate if is the Everyone SID
  1162. //
  1163. if( pSid )
  1164. {
  1165. PSID_IDENTIFIER_AUTHORITY pSIA = GetSidIdentifierAuthority( pSid );
  1166. if( pSIA )
  1167. {
  1168. SID_IDENTIFIER_AUTHORITY sidEveryone = SECURITY_WORLD_SID_AUTHORITY;
  1169. if( memcmp(pSIA, &sidEveryone, sizeof(SID_IDENTIFIER_AUTHORITY))== 0)
  1170. {
  1171. // It is an Everyone user
  1172. bEveryone = TRUE;
  1173. // Clean-up
  1174. VariantClear(&varAce);
  1175. pAccessControlEntry->Release();
  1176. pAccessControlEntry = NULL;
  1177. // Break the loop
  1178. break;
  1179. }
  1180. }
  1181. }
  1182. VariantClear(&varAce);
  1183. if (pAccessControlEntry)
  1184. {
  1185. pAccessControlEntry->Release();
  1186. pAccessControlEntry = NULL;
  1187. }
  1188. if( bstrTrustee )
  1189. {
  1190. SysFreeString( bstrTrustee );
  1191. bstrTrustee = NULL;
  1192. }
  1193. }
  1194. if( !bEveryone)
  1195. {
  1196. // We have to add an everyone entry
  1197. hr = CoCreateInstance(
  1198. CLSID_AccessControlEntry,
  1199. NULL,
  1200. CLSCTX_INPROC_SERVER,
  1201. IID_IADsAccessControlEntry,
  1202. (void**)&pAccessControlEntry);
  1203. BAIL_ON_FAILURE(hr);
  1204. // Access mask
  1205. hr = pAccessControlEntry->put_AccessMask( ADS_RIGHT_READ_CONTROL );
  1206. BAIL_ON_FAILURE(hr);
  1207. // Ace type
  1208. hr = pAccessControlEntry->put_AceType( 0 );
  1209. BAIL_ON_FAILURE(hr);
  1210. // Ace flags
  1211. hr = pAccessControlEntry->put_AceFlags( 0 );
  1212. BAIL_ON_FAILURE(hr);
  1213. // Get the SID for everyone
  1214. WCHAR Trustee[256];
  1215. PSID pSidEveryone = NULL;
  1216. SID_IDENTIFIER_AUTHORITY siaEveryone = SECURITY_WORLD_SID_AUTHORITY;
  1217. BOOL bAllocate = AllocateAndInitializeSid(
  1218. &siaEveryone,
  1219. 1,0,0,0,0,0,0,0,0,
  1220. &pSidEveryone);
  1221. if( !bAllocate )
  1222. {
  1223. BAIL_ON_FAILURE(E_OUTOFMEMORY);
  1224. }
  1225. // Get the trustee for everyone
  1226. hr = ConvertSidToString( pSidEveryone, Trustee );
  1227. FreeSid( pSidEveryone);
  1228. BAIL_ON_FAILURE(hr);
  1229. bstrTrustee = SysAllocString( Trustee );
  1230. if( bstrTrustee == NULL)
  1231. {
  1232. BAIL_ON_FAILURE(E_OUTOFMEMORY);
  1233. }
  1234. // Add trustee
  1235. hr = pAccessControlEntry->put_Trustee( bstrTrustee );
  1236. BAIL_ON_FAILURE(hr);
  1237. // Get the IDispatch
  1238. hr = pAccessControlEntry->QueryInterface(
  1239. IID_IDispatch,
  1240. (void**)&pACEDispatch);
  1241. BAIL_ON_FAILURE(hr);
  1242. // Add ACE to the ACL
  1243. hr = pAccessList->AddAce( pACEDispatch );
  1244. BAIL_ON_FAILURE(hr);
  1245. }
  1246. error:
  1247. if (pUnknown) {
  1248. pUnknown->Release();
  1249. }
  1250. if (pEnumerator) {
  1251. pEnumerator->Release();
  1252. }
  1253. if( pACEDispatch )
  1254. {
  1255. pACEDispatch->Release();
  1256. }
  1257. if(pAccessControlEntry)
  1258. {
  1259. pAccessControlEntry->Release();
  1260. }
  1261. if( bstrTrustee )
  1262. {
  1263. SysFreeString( bstrTrustee );
  1264. }
  1265. if (pSid)
  1266. {
  1267. delete (pSid);
  1268. }
  1269. return(hr);
  1270. }
  1271. HRESULT
  1272. ConvertAccessControlListToAcl(
  1273. IADsAccessControlList FAR * pAccessList,
  1274. PACL * ppAcl
  1275. )
  1276. {
  1277. IUnknown * pUnknown = NULL;
  1278. IEnumVARIANT * pEnumerator = NULL;
  1279. HRESULT hr = S_OK;
  1280. DWORD i = 0;
  1281. DWORD cReturned = 0;
  1282. VARIANT varAce;
  1283. DWORD dwAceCount = 0;
  1284. IADsAccessControlEntry FAR * pAccessControlEntry = NULL;
  1285. LPBYTE pTempAce = NULL;
  1286. DWORD dwCount = 0;
  1287. PACL pAcl = NULL;
  1288. DWORD dwAclSize = 0;
  1289. PACE_HEADER * ppAceHdr = NULL;
  1290. DWORD dwRet = 0;
  1291. DWORD dwAclRevision = 0;
  1292. DWORD dwStatus = 0;
  1293. DWORD dwError = 0;
  1294. hr = AddACEEveryone( pAccessList );
  1295. BAIL_ON_FAILURE(hr);
  1296. hr = pAccessList->get_AceCount((long *)&dwAceCount);
  1297. BAIL_ON_FAILURE(hr);
  1298. hr = pAccessList->get__NewEnum(
  1299. &pUnknown
  1300. );
  1301. BAIL_ON_FAILURE(hr);
  1302. hr = pUnknown->QueryInterface(
  1303. IID_IEnumVARIANT,
  1304. (void FAR * FAR *)&pEnumerator
  1305. );
  1306. BAIL_ON_FAILURE(hr);
  1307. ppAceHdr = new PACE_HEADER [dwAceCount];
  1308. if (!ppAceHdr) {
  1309. hr = E_OUTOFMEMORY;
  1310. BAIL_ON_FAILURE(hr);
  1311. }
  1312. for (i = 0; i < dwAceCount; i++) {
  1313. VariantInit(&varAce);
  1314. hr = pEnumerator->Next(
  1315. 1,
  1316. &varAce,
  1317. &cReturned
  1318. );
  1319. CONTINUE_ON_FAILURE(hr);
  1320. hr = (V_DISPATCH(&varAce))->QueryInterface(
  1321. IID_IADsAccessControlEntry,
  1322. (void **)&pAccessControlEntry
  1323. );
  1324. CONTINUE_ON_FAILURE(hr);
  1325. hr = ConvertAccessControlEntryToAce(
  1326. pAccessControlEntry,
  1327. &(pTempAce)
  1328. );
  1329. // ZoltanS: Rather than CONTINUE_ON_FAILURE, let's bail so that we
  1330. // know if the Ace we set is invalid.
  1331. BAIL_ON_FAILURE(hr);
  1332. *(ppAceHdr + dwCount) = (PACE_HEADER)pTempAce;
  1333. VariantClear(&varAce);
  1334. if (pAccessControlEntry) {
  1335. pAccessControlEntry->Release();
  1336. pAccessControlEntry = NULL;
  1337. }
  1338. dwCount++;
  1339. }
  1340. hr = ComputeTotalAclSize(ppAceHdr, dwCount, &dwAclSize);
  1341. BAIL_ON_FAILURE(hr);
  1342. pAcl = (PACL)new BYTE[dwAclSize];
  1343. if (!pAcl) {
  1344. hr = E_OUTOFMEMORY;
  1345. BAIL_ON_FAILURE(hr);
  1346. }
  1347. hr = pAccessList->get_AclRevision((long *)&dwAclRevision);
  1348. //
  1349. // we have to deallocate memory
  1350. //
  1351. if( FAILED(hr) && (NULL != pAcl) )
  1352. delete( pAcl );
  1353. BAIL_ON_FAILURE(hr);
  1354. dwRet = InitializeAcl(
  1355. pAcl,
  1356. dwAclSize,
  1357. dwAclRevision
  1358. );
  1359. if (!dwRet) {
  1360. hr = HRESULT_FROM_WIN32(GetLastError());
  1361. //
  1362. // we have to deallocate memory
  1363. //
  1364. if( FAILED(hr) && (NULL != pAcl) )
  1365. delete( pAcl );
  1366. BAIL_ON_FAILURE(hr);
  1367. }
  1368. for (i = 0; i < dwCount; i++) {
  1369. dwStatus = AddAce(
  1370. pAcl,
  1371. dwAclRevision,
  1372. i,
  1373. (LPBYTE)*(ppAceHdr + i),
  1374. (*(ppAceHdr + i))->AceSize
  1375. );
  1376. if (!dwStatus) {
  1377. dwError = GetLastError();
  1378. }
  1379. }
  1380. *ppAcl = pAcl;
  1381. error:
  1382. if (ppAceHdr) {
  1383. for (i = 0; i < dwCount; i++) {
  1384. if (*(ppAceHdr + i)) {
  1385. delete (*(ppAceHdr + i));
  1386. }
  1387. }
  1388. delete (ppAceHdr);
  1389. }
  1390. if (pUnknown) {
  1391. pUnknown->Release();
  1392. }
  1393. if (pEnumerator) {
  1394. pEnumerator->Release();
  1395. }
  1396. return(hr);
  1397. }
  1398. HRESULT
  1399. GetGroupSecurityIdentifier(
  1400. IADsSecurityDescriptor FAR * pSecDes,
  1401. PSID * ppSid,
  1402. PBOOL pfGroupDefaulted
  1403. )
  1404. {
  1405. BSTR bstrGroup = NULL;
  1406. DWORD dwSidSize = 0;
  1407. HRESULT hr = S_OK;
  1408. VARIANT_BOOL varBool = VARIANT_FALSE;
  1409. hr = pSecDes->get_Group(
  1410. &bstrGroup
  1411. );
  1412. BAIL_ON_FAILURE(hr);
  1413. hr = pSecDes->get_GroupDefaulted(
  1414. &varBool
  1415. );
  1416. BAIL_ON_FAILURE(hr);
  1417. if (varBool == VARIANT_FALSE) {
  1418. if (bstrGroup && *bstrGroup) {
  1419. hr = ConvertTrusteeToSid(
  1420. bstrGroup,
  1421. ppSid,
  1422. &dwSidSize
  1423. );
  1424. BAIL_ON_FAILURE(hr);
  1425. *pfGroupDefaulted = FALSE;
  1426. }else {
  1427. *ppSid = NULL;
  1428. *pfGroupDefaulted = FALSE;
  1429. }
  1430. }else {
  1431. *ppSid = NULL;
  1432. dwSidSize = 0;
  1433. *pfGroupDefaulted = TRUE;
  1434. }
  1435. error:
  1436. if (bstrGroup) {
  1437. SysFreeString(bstrGroup);
  1438. }
  1439. return(hr);
  1440. }
  1441. HRESULT
  1442. GetDacl(
  1443. IADsSecurityDescriptor FAR * pSecDes,
  1444. PACL * ppDacl,
  1445. PBOOL pfDaclDefaulted
  1446. )
  1447. {
  1448. IADsAccessControlList FAR * pDiscAcl = NULL;
  1449. IDispatch FAR * pDispatch = NULL;
  1450. HRESULT hr = S_OK;
  1451. VARIANT_BOOL varBool = VARIANT_FALSE;
  1452. hr = pSecDes->get_DaclDefaulted(
  1453. &varBool
  1454. );
  1455. BAIL_ON_FAILURE(hr);
  1456. if (varBool == VARIANT_FALSE) {
  1457. *pfDaclDefaulted = FALSE;
  1458. }else {
  1459. *pfDaclDefaulted = TRUE;
  1460. }
  1461. hr = pSecDes->get_DiscretionaryAcl(
  1462. &pDispatch
  1463. );
  1464. BAIL_ON_FAILURE(hr);
  1465. if (!pDispatch) {
  1466. *ppDacl = NULL;
  1467. goto error;
  1468. }
  1469. hr = pDispatch->QueryInterface(
  1470. IID_IADsAccessControlList,
  1471. (void **)&pDiscAcl
  1472. );
  1473. BAIL_ON_FAILURE(hr);
  1474. hr = ConvertAccessControlListToAcl(
  1475. pDiscAcl,
  1476. ppDacl
  1477. );
  1478. BAIL_ON_FAILURE(hr);
  1479. error:
  1480. if (pDispatch) {
  1481. pDispatch->Release();
  1482. }
  1483. if (pDiscAcl) {
  1484. pDiscAcl->Release();
  1485. }
  1486. return(hr);
  1487. }
  1488. HRESULT
  1489. GetSacl(
  1490. IADsSecurityDescriptor FAR * pSecDes,
  1491. PACL * ppSacl,
  1492. PBOOL pfSaclDefaulted
  1493. )
  1494. {
  1495. IADsAccessControlList FAR * pSystemAcl = NULL;
  1496. IDispatch FAR * pDispatch = NULL;
  1497. HRESULT hr = S_OK;
  1498. VARIANT_BOOL varBool = VARIANT_FALSE;
  1499. hr = pSecDes->get_SaclDefaulted(
  1500. &varBool
  1501. );
  1502. BAIL_ON_FAILURE(hr);
  1503. if (varBool == VARIANT_FALSE) {
  1504. *pfSaclDefaulted = FALSE;
  1505. }else {
  1506. *pfSaclDefaulted = TRUE;
  1507. }
  1508. hr = pSecDes->get_SystemAcl(
  1509. &pDispatch
  1510. );
  1511. BAIL_ON_FAILURE(hr);
  1512. if (!pDispatch) {
  1513. *ppSacl = NULL;
  1514. goto error;
  1515. }
  1516. hr = pDispatch->QueryInterface(
  1517. IID_IADsAccessControlList,
  1518. (void **)&pSystemAcl
  1519. );
  1520. BAIL_ON_FAILURE(hr);
  1521. hr = ConvertAccessControlListToAcl(
  1522. pSystemAcl,
  1523. ppSacl
  1524. );
  1525. BAIL_ON_FAILURE(hr);
  1526. error:
  1527. if (pDispatch) {
  1528. pDispatch->Release();
  1529. }
  1530. if (pSystemAcl) {
  1531. pSystemAcl->Release();
  1532. }
  1533. return(hr);
  1534. }
  1535. ///////////////////////////////////////////////////////////////////////////////
  1536. // //
  1537. // Public procedures //
  1538. // //
  1539. ///////////////////////////////////////////////////////////////////////////////
  1540. HRESULT
  1541. ConvertSDToIDispatch(
  1542. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1543. OUT IDispatch ** ppIDispatch
  1544. )
  1545. {
  1546. IADsSecurityDescriptor * pSecDes = NULL;
  1547. IDispatch * pDispatch = NULL;
  1548. LPWSTR pszGroup = NULL;
  1549. LPWSTR pszOwner = NULL;
  1550. BOOL fOwnerDefaulted = 0;
  1551. BOOL fGroupDefaulted = 0;
  1552. BOOL fDaclDefaulted = 0;
  1553. BOOL fSaclDefaulted = 0;
  1554. BOOL fSaclPresent = 0;
  1555. BOOL fDaclPresent = 0;
  1556. LPBYTE pOwnerSidAddress = NULL;
  1557. LPBYTE pGroupSidAddress = NULL;
  1558. LPBYTE pDACLAddress = NULL;
  1559. LPBYTE pSACLAddress = NULL;
  1560. DWORD dwRet = 0;
  1561. VARIANT varDACL;
  1562. VARIANT varSACL;
  1563. HRESULT hr = S_OK;
  1564. DWORD dwRevision = 0;
  1565. WORD wControl = 0;
  1566. memset(&varSACL, 0, sizeof(VARIANT));
  1567. memset(&varDACL, 0, sizeof(VARIANT));
  1568. if (!pSecurityDescriptor) {
  1569. return(E_FAIL);
  1570. }
  1571. dwRet = GetSecurityDescriptorControl(
  1572. pSecurityDescriptor,
  1573. &wControl,
  1574. &dwRevision
  1575. );
  1576. if (!dwRet){
  1577. hr = HRESULT_FROM_WIN32(GetLastError());
  1578. BAIL_ON_FAILURE(hr);
  1579. }
  1580. dwRet = GetSecurityDescriptorOwner(
  1581. pSecurityDescriptor,
  1582. (PSID *)&pOwnerSidAddress,
  1583. &fOwnerDefaulted
  1584. );
  1585. if (!dwRet){
  1586. hr = HRESULT_FROM_WIN32(GetLastError());
  1587. BAIL_ON_FAILURE(hr);
  1588. }
  1589. hr = ConvertSidToFriendlyName(
  1590. pOwnerSidAddress,
  1591. &pszOwner
  1592. );
  1593. BAIL_ON_FAILURE(hr);
  1594. dwRet = GetSecurityDescriptorGroup(
  1595. pSecurityDescriptor,
  1596. (PSID *)&pGroupSidAddress,
  1597. &fOwnerDefaulted
  1598. );
  1599. if (!dwRet){
  1600. hr = HRESULT_FROM_WIN32(GetLastError());
  1601. BAIL_ON_FAILURE(hr);
  1602. }
  1603. hr = ConvertSidToFriendlyName(
  1604. pGroupSidAddress,
  1605. &pszGroup
  1606. );
  1607. BAIL_ON_FAILURE(hr);
  1608. dwRet = GetSecurityDescriptorDacl(
  1609. pSecurityDescriptor,
  1610. &fDaclPresent,
  1611. (PACL*)&pDACLAddress,
  1612. &fDaclDefaulted
  1613. );
  1614. if (pDACLAddress) {
  1615. hr = ConvertACLToVariant(
  1616. (PACL)pDACLAddress,
  1617. &varDACL
  1618. );
  1619. BAIL_ON_FAILURE(hr);
  1620. }
  1621. dwRet = GetSecurityDescriptorSacl(
  1622. pSecurityDescriptor,
  1623. &fSaclPresent,
  1624. (PACL *)&pSACLAddress,
  1625. &fSaclDefaulted
  1626. );
  1627. if (!dwRet){
  1628. hr = HRESULT_FROM_WIN32(GetLastError());
  1629. BAIL_ON_FAILURE(hr);
  1630. }
  1631. if (pSACLAddress) {
  1632. hr = ConvertACLToVariant(
  1633. (PACL)pSACLAddress,
  1634. &varSACL
  1635. );
  1636. BAIL_ON_FAILURE(hr);
  1637. }
  1638. hr = CoCreateInstance(
  1639. CLSID_SecurityDescriptor,
  1640. NULL,
  1641. CLSCTX_INPROC_SERVER,
  1642. IID_IADsSecurityDescriptor,
  1643. (void **)&pSecDes
  1644. );
  1645. BAIL_ON_FAILURE(hr);
  1646. hr = pSecDes->put_Owner(pszOwner);
  1647. BAIL_ON_FAILURE(hr);
  1648. hr = pSecDes->put_Group(pszGroup);
  1649. BAIL_ON_FAILURE(hr);
  1650. hr = pSecDes->put_Revision(dwRevision);
  1651. BAIL_ON_FAILURE(hr);
  1652. hr = pSecDes->put_Control((DWORD)wControl);
  1653. BAIL_ON_FAILURE(hr);
  1654. hr = pSecDes->put_DiscretionaryAcl(V_DISPATCH(&varDACL));
  1655. BAIL_ON_FAILURE(hr);
  1656. hr = pSecDes->put_SystemAcl(V_DISPATCH(&varSACL));
  1657. BAIL_ON_FAILURE(hr);
  1658. hr = pSecDes->QueryInterface(IID_IDispatch, (void**)&pDispatch);
  1659. BAIL_ON_FAILURE(hr);
  1660. *ppIDispatch = pDispatch;
  1661. error:
  1662. VariantClear(&varSACL);
  1663. VariantClear(&varDACL);
  1664. if (pszOwner) {
  1665. delete (pszOwner);
  1666. }
  1667. if (pszGroup) {
  1668. delete (pszGroup);
  1669. }
  1670. if (pSecDes) {
  1671. pSecDes->Release();
  1672. }
  1673. return(hr);
  1674. }
  1675. HRESULT
  1676. ConvertSDToVariant(
  1677. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1678. OUT VARIANT * pVarSec
  1679. )
  1680. {
  1681. IDispatch *pIDispatch;
  1682. HRESULT hr = ConvertSDToIDispatch(pSecurityDescriptor, &pIDispatch);
  1683. if (FAILED(hr))
  1684. {
  1685. return hr;
  1686. }
  1687. VariantInit(pVarSec);
  1688. V_VT(pVarSec) = VT_DISPATCH;
  1689. V_DISPATCH(pVarSec) = pIDispatch;
  1690. return S_OK;
  1691. }
  1692. HRESULT
  1693. ConvertObjectToSD(
  1694. IN IADsSecurityDescriptor FAR * pSecDes,
  1695. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor,
  1696. OUT PDWORD pdwSDLength
  1697. )
  1698. {
  1699. HRESULT hr = S_OK;
  1700. SECURITY_DESCRIPTOR AbsoluteSD;
  1701. PSECURITY_DESCRIPTOR pRelative = NULL;
  1702. BOOL Defaulted = FALSE;
  1703. BOOL DaclPresent = FALSE;
  1704. BOOL SaclPresent = FALSE;
  1705. BOOL fDaclDefaulted = FALSE;
  1706. BOOL fSaclDefaulted = FALSE;
  1707. BOOL fOwnerDefaulted = FALSE;
  1708. BOOL fGroupDefaulted = FALSE;
  1709. PSID pOwnerSid = NULL;
  1710. PSID pGroupSid = NULL;
  1711. PACL pDacl = NULL;
  1712. PACL pSacl = NULL;
  1713. DWORD dwSDLength = 0;
  1714. DWORD dwRet = 0;
  1715. BOOL dwStatus = 0;
  1716. //
  1717. // Initialize *pSizeSD = 0;
  1718. //
  1719. dwRet = InitializeSecurityDescriptor (
  1720. &AbsoluteSD,
  1721. SECURITY_DESCRIPTOR_REVISION1
  1722. );
  1723. if (!dwRet) {
  1724. hr = E_FAIL;
  1725. BAIL_ON_FAILURE(hr);
  1726. }
  1727. hr = GetOwnerSecurityIdentifier(
  1728. pSecDes,
  1729. &pOwnerSid,
  1730. &fOwnerDefaulted
  1731. );
  1732. BAIL_ON_FAILURE(hr);
  1733. dwStatus = SetSecurityDescriptorOwner(
  1734. &AbsoluteSD,
  1735. pOwnerSid,
  1736. fOwnerDefaulted
  1737. );
  1738. if (!dwStatus) {
  1739. hr = HRESULT_FROM_WIN32(GetLastError());
  1740. BAIL_ON_FAILURE(hr);
  1741. }
  1742. hr = GetGroupSecurityIdentifier(
  1743. pSecDes,
  1744. &pGroupSid,
  1745. &fGroupDefaulted
  1746. );
  1747. BAIL_ON_FAILURE(hr);
  1748. dwStatus = SetSecurityDescriptorGroup(
  1749. &AbsoluteSD,
  1750. pGroupSid,
  1751. fGroupDefaulted
  1752. );
  1753. if (!dwStatus) {
  1754. hr = HRESULT_FROM_WIN32(GetLastError());
  1755. BAIL_ON_FAILURE(hr);
  1756. }
  1757. hr = GetDacl(
  1758. pSecDes,
  1759. &pDacl,
  1760. &fDaclDefaulted
  1761. );
  1762. BAIL_ON_FAILURE(hr);
  1763. if (pDacl || fDaclDefaulted) {
  1764. DaclPresent = TRUE;
  1765. }
  1766. dwStatus = SetSecurityDescriptorDacl(
  1767. &AbsoluteSD,
  1768. DaclPresent,
  1769. pDacl,
  1770. fDaclDefaulted
  1771. );
  1772. if (!dwStatus) {
  1773. hr = HRESULT_FROM_WIN32(GetLastError());
  1774. BAIL_ON_FAILURE(hr);
  1775. }
  1776. hr = GetSacl(
  1777. pSecDes,
  1778. &pSacl,
  1779. &fSaclDefaulted
  1780. );
  1781. BAIL_ON_FAILURE(hr);
  1782. if (pSacl || fSaclDefaulted) {
  1783. SaclPresent = TRUE;
  1784. }
  1785. dwStatus = SetSecurityDescriptorSacl(
  1786. &AbsoluteSD,
  1787. SaclPresent,
  1788. pSacl,
  1789. fSaclDefaulted
  1790. );
  1791. if (!dwStatus) {
  1792. hr = HRESULT_FROM_WIN32(GetLastError());
  1793. BAIL_ON_FAILURE(hr);
  1794. }
  1795. dwSDLength = GetSecurityDescriptorLength(
  1796. &AbsoluteSD
  1797. );
  1798. pRelative = new BYTE[dwSDLength];
  1799. if (!pRelative) {
  1800. hr = E_OUTOFMEMORY;
  1801. BAIL_ON_FAILURE(hr);
  1802. }
  1803. if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &dwSDLength)) {
  1804. delete (pRelative);
  1805. hr = HRESULT_FROM_WIN32(GetLastError());
  1806. BAIL_ON_FAILURE(hr);
  1807. }
  1808. *ppSecurityDescriptor = pRelative;
  1809. *pdwSDLength = dwSDLength;
  1810. cleanup:
  1811. if (pDacl) {
  1812. delete (pDacl);
  1813. }
  1814. if (pSacl) {
  1815. delete (pSacl);
  1816. }
  1817. if (pOwnerSid) {
  1818. delete (pOwnerSid);
  1819. }
  1820. if (pGroupSid) {
  1821. delete (pGroupSid);
  1822. }
  1823. return(hr);
  1824. error:
  1825. if (pRelative) {
  1826. delete (pRelative);
  1827. }
  1828. *ppSecurityDescriptor = NULL;
  1829. *pdwSDLength = 0;
  1830. goto cleanup;
  1831. }
  1832. HRESULT
  1833. ConvertObjectToSDDispatch(
  1834. IN IDispatch * pDisp,
  1835. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor,
  1836. OUT PDWORD pdwSDLength
  1837. )
  1838. {
  1839. HRESULT hr;
  1840. IADsSecurityDescriptor * pSecDes;
  1841. hr = pDisp->QueryInterface(
  1842. IID_IADsSecurityDescriptor,
  1843. (VOID **)&pSecDes
  1844. );
  1845. if (FAILED(hr))
  1846. {
  1847. return hr;
  1848. }
  1849. hr = ConvertObjectToSD(pSecDes, ppSecurityDescriptor, pdwSDLength);
  1850. //
  1851. // Release the reference to the pSecSes
  1852. //
  1853. pSecDes->Release();
  1854. return hr;
  1855. }
  1856. // Returns FALSE if these two security descriptors are identical.
  1857. // Returns TRUE if they differ, or if there is any error parsing either of them
  1858. BOOL CheckIfSecurityDescriptorsDiffer(PSECURITY_DESCRIPTOR pSD1,
  1859. DWORD dwSDSize1,
  1860. PSECURITY_DESCRIPTOR pSD2,
  1861. DWORD dwSDSize2)
  1862. {
  1863. //
  1864. // If one of them is null, then they differ. (It should be impossible for them
  1865. // to both be null, but if they are, they had better both have size 0, which
  1866. // would just make us return TRUE below, so that's ok.)
  1867. //
  1868. if ( ( pSD1 == NULL ) || ( pSD2 == NULL ) )
  1869. {
  1870. return TRUE;
  1871. }
  1872. // if they converted to different sized structures then they are different
  1873. if ( dwSDSize1 != dwSDSize2 )
  1874. {
  1875. return TRUE;
  1876. }
  1877. // we know both succeeded conversion and converted to the same sized structures
  1878. // if the structures contain the same bytes then they are identical
  1879. if ( 0 == memcmp(pSD1, pSD2, dwSDSize1) )
  1880. {
  1881. return FALSE;
  1882. }
  1883. // else they differ
  1884. return TRUE;
  1885. }
  1886. // eof