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.

1949 lines
44 KiB

  1. /*++
  2. Copyright (c) 1995 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. #define SECURITY_WIN32
  21. //#include <security.h>
  22. #include "winlocal.h"
  23. #include <objbase.h>
  24. #include <initguid.h>
  25. #include <iads.h>
  26. #include <stdlib.h>
  27. #include <limits.h>
  28. #include <io.h>
  29. #include <wchar.h>
  30. #include <tchar.h>
  31. //#include "ntseapi.h"
  32. #include "rndsec.h"
  33. ///////////////////////////////////////////////////////////////////////////////
  34. //Not defined, so I pulled it from ntseapi.h
  35. ///////////////////////////////////////////////////////////////////////////////
  36. typedef struct _COMPOUND_ACCESS_ALLOWED_ACE {
  37. ACE_HEADER Header;
  38. ACCESS_MASK Mask;
  39. USHORT CompoundAceType;
  40. USHORT Reserved;
  41. ULONG SidStart;
  42. } COMPOUND_ACCESS_ALLOWED_ACE;
  43. typedef COMPOUND_ACCESS_ALLOWED_ACE *PCOMPOUND_ACCESS_ALLOWED_ACE;
  44. ///////////////////////////////////////////////////////////////////////////////
  45. // //
  46. // Private macros //
  47. // //
  48. ///////////////////////////////////////////////////////////////////////////////
  49. #define BAIL_ON_FAILURE(hr) \
  50. if (FAILED(hr)) { goto error; }
  51. #define CONTINUE_ON_FAILURE(hr) \
  52. if (FAILED(hr)) { continue; }
  53. ///////////////////////////////////////////////////////////////////////////////
  54. // //
  55. // Private procedures //
  56. // //
  57. ///////////////////////////////////////////////////////////////////////////////
  58. LPWSTR
  59. AllocADsStr(
  60. LPWSTR pStr
  61. )
  62. {
  63. LPWSTR pMem;
  64. if (!pStr)
  65. return NULL;
  66. if (pMem = new WCHAR[wcslen(pStr) + 1])
  67. wcscpy(pMem, pStr);
  68. return pMem;
  69. }
  70. HRESULT
  71. ConvertSidToString(
  72. PSID pSid,
  73. LPWSTR String
  74. )
  75. /*++
  76. Routine Description:
  77. This function generates a printable unicode string representation
  78. of a SID.
  79. The resulting string will take one of two forms. If the
  80. IdentifierAuthority value is not greater than 2^32, then
  81. the SID will be in the form:
  82. S-1-281736-12-72-9-110
  83. ^ ^^ ^^ ^ ^^^
  84. | | | | |
  85. +-----+--+-+--+---- Decimal
  86. Otherwise it will take the form:
  87. S-1-0x173495281736-12-72-9-110
  88. ^^^^^^^^^^^^^^ ^^ ^^ ^ ^^^
  89. Hexidecimal | | | |
  90. +--+-+--+---- Decimal
  91. Arguments:
  92. pSid - opaque pointer that supplies the SID that is to be
  93. converted to Unicode.
  94. Return Value:
  95. If the Sid is successfully converted to a Unicode string, a
  96. pointer to the Unicode string is returned, else NULL is
  97. returned.
  98. --*/
  99. {
  100. WCHAR Buffer[256];
  101. UCHAR i;
  102. ULONG Tmp;
  103. HRESULT hr = S_OK;
  104. SID_IDENTIFIER_AUTHORITY *pSidIdentifierAuthority;
  105. PUCHAR pSidSubAuthorityCount;
  106. if (!IsValidSid( pSid )) {
  107. *String= L'\0';
  108. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  109. return(hr);
  110. }
  111. wsprintfW(Buffer, L"S-%u-", (USHORT)(((PISID)pSid)->Revision ));
  112. wcscpy(String, Buffer);
  113. pSidIdentifierAuthority = GetSidIdentifierAuthority(pSid);
  114. if ( (pSidIdentifierAuthority->Value[0] != 0) ||
  115. (pSidIdentifierAuthority->Value[1] != 0) ){
  116. wsprintfW(Buffer, L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
  117. (USHORT)pSidIdentifierAuthority->Value[0],
  118. (USHORT)pSidIdentifierAuthority->Value[1],
  119. (USHORT)pSidIdentifierAuthority->Value[2],
  120. (USHORT)pSidIdentifierAuthority->Value[3],
  121. (USHORT)pSidIdentifierAuthority->Value[4],
  122. (USHORT)pSidIdentifierAuthority->Value[5] );
  123. wcscat(String, Buffer);
  124. } else {
  125. Tmp = (ULONG)pSidIdentifierAuthority->Value[5] +
  126. (ULONG)(pSidIdentifierAuthority->Value[4] << 8) +
  127. (ULONG)(pSidIdentifierAuthority->Value[3] << 16) +
  128. (ULONG)(pSidIdentifierAuthority->Value[2] << 24);
  129. wsprintfW(Buffer, L"%lu", Tmp);
  130. wcscat(String, Buffer);
  131. }
  132. pSidSubAuthorityCount = GetSidSubAuthorityCount(pSid);
  133. for (i=0;i< *(pSidSubAuthorityCount);i++ ) {
  134. wsprintfW(Buffer, L"-%lu", *(GetSidSubAuthority(pSid, i)));
  135. wcscat(String, Buffer);
  136. }
  137. return(S_OK);
  138. }
  139. HRESULT
  140. ConvertSidToFriendlyName(
  141. PSID pSid,
  142. LPWSTR * ppszAccountName
  143. )
  144. {
  145. HRESULT hr = S_OK;
  146. SID_NAME_USE eUse;
  147. WCHAR szAccountName[MAX_PATH];
  148. szAccountName[0] = L'\0';
  149. WCHAR szDomainName[MAX_PATH];
  150. szDomainName[0] = L'\0';
  151. DWORD dwLen = 0;
  152. DWORD dwRet = 0;
  153. LPWSTR pszAccountName = NULL;
  154. DWORD dwAcctLen = 0;
  155. DWORD dwDomainLen = 0;
  156. dwAcctLen = sizeof(szAccountName);
  157. dwDomainLen = sizeof(szDomainName);
  158. dwRet = LookupAccountSidW(
  159. NULL,
  160. pSid,
  161. szAccountName,
  162. &dwAcctLen,
  163. szDomainName,
  164. &dwDomainLen,
  165. (PSID_NAME_USE)&eUse
  166. );
  167. if (!dwRet) {
  168. hr = ConvertSidToString(
  169. pSid,
  170. szAccountName
  171. );
  172. BAIL_ON_FAILURE(hr);
  173. pszAccountName = AllocADsStr(szAccountName);
  174. if (!pszAccountName) {
  175. hr = E_OUTOFMEMORY;
  176. BAIL_ON_FAILURE(hr);
  177. }
  178. *ppszAccountName = pszAccountName;
  179. }else {
  180. dwLen = wcslen(szAccountName) + wcslen(szDomainName) + 1 + 1;
  181. pszAccountName = new WCHAR [dwLen];
  182. if (!pszAccountName) {
  183. hr = E_OUTOFMEMORY;
  184. BAIL_ON_FAILURE(hr);
  185. }
  186. if (szDomainName[0] && szAccountName[0]) {
  187. wsprintfW(pszAccountName,L"%s\\%s",szDomainName, szAccountName);
  188. }else if (szAccountName[0]) {
  189. wsprintfW(pszAccountName,L"%s", szAccountName);
  190. }
  191. *ppszAccountName = pszAccountName;
  192. }
  193. error:
  194. return(hr);
  195. }
  196. HRESULT
  197. ConvertAceToVariant(
  198. PBYTE pAce,
  199. LPVARIANT pvarAce
  200. )
  201. {
  202. IADsAccessControlEntry * pAccessControlEntry = NULL;
  203. IDispatch * pDispatch = NULL;
  204. DWORD dwAceType = 0;
  205. DWORD dwAceFlags = 0;
  206. DWORD dwAccessMask = 0;
  207. LPWSTR pszAccountName = NULL;
  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. BAIL_ON_FAILURE(hr);
  263. break;
  264. }
  265. hr = ConvertSidToFriendlyName(
  266. pSidAddress,
  267. &pszAccountName
  268. );
  269. if (FAILED(hr)){
  270. pszAccountName = AllocADsStr(L"Unknown Trustee");
  271. }
  272. //
  273. // Now set all the information in the Access Control Entry
  274. //
  275. hr = pAccessControlEntry->put_AccessMask(dwAccessMask);
  276. hr = pAccessControlEntry->put_AceFlags(dwAceFlags);
  277. hr = pAccessControlEntry->put_AceType(dwAceType);
  278. //
  279. // Extended ACE information
  280. //
  281. hr = pAccessControlEntry->put_Flags(dwFlags);
  282. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  283. //
  284. // Add in the Object Type GUID
  285. //
  286. hr = pAccessControlEntry->put_ObjectType(szObjectGUID);
  287. }
  288. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  289. //
  290. // Add in the Inherited Object Type GUID
  291. //
  292. hr = pAccessControlEntry->put_InheritedObjectType(szInheritedObjectGUID);
  293. }
  294. hr = pAccessControlEntry->put_Trustee(pszAccountName);
  295. hr = pAccessControlEntry->QueryInterface(
  296. IID_IDispatch,
  297. (void **)&pDispatch
  298. );
  299. BAIL_ON_FAILURE(hr);
  300. V_DISPATCH(pvarAce) = pDispatch;
  301. V_VT(pvarAce) = VT_DISPATCH;
  302. cleanup:
  303. if (pszAccountName) {
  304. delete (pszAccountName);
  305. }
  306. if (pAccessControlEntry) {
  307. pAccessControlEntry->Release();
  308. }
  309. return(hr);
  310. error:
  311. if (pDispatch) {
  312. pDispatch->Release();
  313. }
  314. goto cleanup;
  315. }
  316. HRESULT
  317. ConvertACLToVariant(
  318. PACL pACL,
  319. LPVARIANT pvarACL
  320. )
  321. {
  322. IADsAccessControlList * pAccessControlList = NULL;
  323. IDispatch * pDispatch = NULL;
  324. VARIANT varAce;
  325. DWORD dwAclSize = 0;
  326. DWORD dwAclRevision = 0;
  327. DWORD dwAceCount = 0;
  328. ACL_SIZE_INFORMATION AclSize;
  329. ACL_REVISION_INFORMATION AclRevision;
  330. DWORD dwStatus = 0;
  331. DWORD i = 0;
  332. DWORD dwNewAceCount = 0;
  333. HRESULT hr = S_OK;
  334. LPBYTE pAceAddress = NULL;
  335. memset(&AclSize, 0, sizeof(ACL_SIZE_INFORMATION));
  336. memset(&AclRevision, 0, sizeof(ACL_REVISION_INFORMATION));
  337. dwStatus = GetAclInformation(
  338. pACL,
  339. &AclSize,
  340. sizeof(ACL_SIZE_INFORMATION),
  341. AclSizeInformation
  342. );
  343. dwStatus = GetAclInformation(
  344. pACL,
  345. &AclRevision,
  346. sizeof(ACL_REVISION_INFORMATION),
  347. AclRevisionInformation
  348. );
  349. dwAceCount = AclSize.AceCount;
  350. dwAclRevision = AclRevision.AclRevision;
  351. VariantInit(pvarACL);
  352. hr = CoCreateInstance(
  353. CLSID_AccessControlList,
  354. NULL,
  355. CLSCTX_INPROC_SERVER,
  356. IID_IADsAccessControlList,
  357. (void **)&pAccessControlList
  358. );
  359. BAIL_ON_FAILURE(hr);
  360. for (i = 0; i < dwAceCount; i++) {
  361. dwStatus = GetAce(pACL, i, (void **)&pAceAddress);
  362. hr = ConvertAceToVariant(
  363. pAceAddress,
  364. (LPVARIANT)&varAce
  365. );
  366. hr = pAccessControlList->AddAce(V_DISPATCH(&varAce));
  367. if (SUCCEEDED(hr)) {
  368. dwNewAceCount++;
  369. }
  370. VariantClear(&varAce);
  371. }
  372. pAccessControlList->put_AclRevision(dwAclRevision);
  373. pAccessControlList->put_AceCount(dwNewAceCount);
  374. hr = pAccessControlList->QueryInterface(
  375. IID_IDispatch,
  376. (void **)&pDispatch
  377. );
  378. V_VT(pvarACL) = VT_DISPATCH;
  379. V_DISPATCH(pvarACL) = pDispatch;
  380. error:
  381. if (pAccessControlList) {
  382. pAccessControlList->Release();
  383. }
  384. return(hr);
  385. }
  386. HRESULT
  387. SecCreateSidFromArray (
  388. OUT PSID *PPSid,
  389. IN PSID_IDENTIFIER_AUTHORITY PSidAuthority,
  390. IN UCHAR SubAuthorityCount,
  391. IN ULONG SubAuthorities[],
  392. OUT PDWORD pdwSidSize
  393. )
  394. /*++
  395. Routine Description:
  396. Creates a SID with desired authority and sub authorities.
  397. NOTE: This routine allocates memory for the SID. When finished
  398. the caller should free memory using SEC_FREE (PSid).
  399. Arguments:
  400. PPSid -- addr of ptr to SID to be created
  401. Note: if SID creation fails ptr set to NULL
  402. PSidAuthority -- desired value for SID authority
  403. SubAuthorityCount -- number of sub authorities desired
  404. SubAuthorities -- sub-authority values, MUST SPECIFY contain
  405. at least SubAuthorityCount number of values
  406. Return Value:
  407. STATUS_SUCCESS if SID created.
  408. STATUS_UNSUCCESSFUL otherwise.
  409. --*/
  410. {
  411. USHORT iSub; /* sub-authority index */
  412. DWORD dwSidSize = 0;
  413. HRESULT hr = S_OK;
  414. /* allocate memory for SID */
  415. dwSidSize = GetSidLengthRequired(SubAuthorityCount);
  416. *PPSid = (PSID) new BYTE[dwSidSize];
  417. if (! *PPSid){
  418. hr = E_OUTOFMEMORY;
  419. BAIL_ON_FAILURE(hr);
  420. }
  421. *pdwSidSize = dwSidSize;
  422. /* initialize SID with top level SID identifier authority */
  423. InitializeSid( *PPSid, PSidAuthority, SubAuthorityCount);
  424. /* fill in sub authorities */
  425. for (iSub=0; iSub < SubAuthorityCount; iSub++)
  426. * GetSidSubAuthority( *PPSid, iSub) = SubAuthorities[iSub];
  427. /* sanity check */
  428. if ( ! IsValidSid( *PPSid) ) {
  429. delete (*PPSid);
  430. *PPSid = NULL;
  431. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  432. BAIL_ON_FAILURE(hr);
  433. }
  434. error:
  435. return(hr);
  436. }
  437. HRESULT
  438. ConvertStringToSid(
  439. IN PWSTR string,
  440. OUT PSID *sid,
  441. OUT PDWORD pdwSidSize,
  442. OUT PWSTR *end
  443. )
  444. {
  445. HRESULT hr = S_OK;
  446. UCHAR revision;
  447. UCHAR sub_authority_count;
  448. SID_IDENTIFIER_AUTHORITY authority;
  449. ULONG sub_authority[SID_MAX_SUB_AUTHORITIES];
  450. PWSTR end_list;
  451. PWSTR current;
  452. PWSTR next;
  453. ULONG x;
  454. *sid = NULL;
  455. if (((*string != L'S') && (*string != L's')) || (*(string + 1) != L'-'))
  456. {
  457. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  458. BAIL_ON_FAILURE(hr);
  459. }
  460. current = string + 2;
  461. revision = (UCHAR)wcstol(current, &end_list, 10);
  462. current = end_list + 1;
  463. //
  464. // Count the number of characters in the indentifer authority...
  465. //
  466. next = wcschr(current, L'-');
  467. if((next != NULL) &&
  468. (next - current == 6))
  469. {
  470. for(x = 0; x < 6; x++)
  471. {
  472. authority.Value[x] = (UCHAR)next[x];
  473. }
  474. current +=6;
  475. }
  476. else
  477. {
  478. ULONG Auto = wcstoul(current, &end_list, 10);
  479. authority.Value[0] = authority.Value[1] = 0;
  480. authority.Value[5] = (UCHAR)Auto & 0xF;
  481. authority.Value[4] = (UCHAR)((Auto >> 8) & 0xFF);
  482. authority.Value[3] = (UCHAR)((Auto >> 16) & 0xFF);
  483. authority.Value[2] = (UCHAR)((Auto >> 24) & 0xFF);
  484. current = end_list;
  485. }
  486. //
  487. // Now, count the number of sub auths
  488. //
  489. sub_authority_count = 0;
  490. next = current;
  491. //
  492. // We'll have to count our sub authoritys one character at a time,
  493. // since there are several deliminators that we can have...
  494. //
  495. while(next)
  496. {
  497. next++;
  498. if(*next == L'-')
  499. {
  500. //
  501. // We've found one!
  502. //
  503. sub_authority_count++;
  504. }
  505. else if(*next == L';' || *next == L'\0')
  506. {
  507. *end = next;
  508. sub_authority_count++;
  509. break;
  510. }
  511. }
  512. if(sub_authority_count != 0)
  513. {
  514. current++;
  515. for(x = 0; x < sub_authority_count; x++)
  516. {
  517. sub_authority[x] = wcstoul(current, &end_list, 10);
  518. current = end_list + 1;
  519. }
  520. }
  521. //
  522. // Now, create the SID
  523. //
  524. hr = SecCreateSidFromArray(
  525. sid,
  526. &authority,
  527. sub_authority_count,
  528. sub_authority,
  529. pdwSidSize
  530. );
  531. if (SUCCEEDED(hr))
  532. {
  533. /* Set the revision to what was specified in the string, in case, our
  534. system creates one with newer revision */
  535. ((SID *)(*sid))->Revision = revision;
  536. }
  537. error:
  538. return(hr);
  539. }
  540. HRESULT
  541. ConvertTrusteeToSid(
  542. BSTR bstrTrustee,
  543. PSID * ppSid,
  544. PDWORD pdwSidSize
  545. )
  546. {
  547. HRESULT hr = S_OK;
  548. BYTE Sid[MAX_PATH];
  549. DWORD dwSidSize = sizeof(Sid);
  550. DWORD dwRet = 0;
  551. WCHAR szDomainName[MAX_PATH];
  552. DWORD dwDomainSize = sizeof(szDomainName)/sizeof(WCHAR);
  553. SID_NAME_USE eUse;
  554. PSID pSid = NULL;
  555. LPWSTR pszEnd = NULL;
  556. BOOL fNTDSType = FALSE;
  557. dwSidSize = sizeof(Sid);
  558. dwRet = LookupAccountNameW(
  559. NULL,
  560. bstrTrustee,
  561. Sid,
  562. &dwSidSize,
  563. szDomainName,
  564. &dwDomainSize,
  565. (PSID_NAME_USE)&eUse
  566. );
  567. if (!dwRet) {
  568. hr = HRESULT_FROM_WIN32(GetLastError());
  569. }
  570. //
  571. // If neither the NTDS nor the U2 conversion
  572. // worked, then try a textual translation
  573. //
  574. if (FAILED(hr)) {
  575. hr = ConvertStringToSid(
  576. bstrTrustee,
  577. &pSid,
  578. &dwSidSize,
  579. &pszEnd
  580. );
  581. BAIL_ON_FAILURE(hr);
  582. memcpy(Sid,pSid, dwSidSize);
  583. if (pSid) {
  584. delete pSid;
  585. }
  586. }
  587. pSid = (PSID) new BYTE[dwSidSize];
  588. if (!pSid) {
  589. hr = E_OUTOFMEMORY;
  590. BAIL_ON_FAILURE(hr);
  591. }
  592. memcpy(pSid, Sid, dwSidSize);
  593. *pdwSidSize = dwSidSize;
  594. *ppSid = pSid;
  595. error:
  596. return(hr);
  597. }
  598. HRESULT
  599. GetOwnerSecurityIdentifier(
  600. IADsSecurityDescriptor FAR * pSecDes,
  601. PSID * ppSid,
  602. PBOOL pfOwnerDefaulted
  603. )
  604. {
  605. BSTR bstrOwner = NULL;
  606. DWORD dwSidSize = 0;
  607. HRESULT hr = S_OK;
  608. VARIANT_BOOL varBool = VARIANT_FALSE;
  609. hr = pSecDes->get_Owner(
  610. &bstrOwner
  611. );
  612. BAIL_ON_FAILURE(hr);
  613. hr = pSecDes->get_OwnerDefaulted(
  614. &varBool
  615. );
  616. BAIL_ON_FAILURE(hr);
  617. if (varBool == VARIANT_FALSE) {
  618. if (bstrOwner && *bstrOwner) {
  619. hr = ConvertTrusteeToSid(
  620. bstrOwner,
  621. ppSid,
  622. &dwSidSize
  623. );
  624. BAIL_ON_FAILURE(hr);
  625. *pfOwnerDefaulted = FALSE;
  626. }else {
  627. *ppSid = NULL;
  628. *pfOwnerDefaulted = FALSE;
  629. }
  630. }else {
  631. *ppSid = NULL;
  632. dwSidSize = 0;
  633. *pfOwnerDefaulted = TRUE;
  634. }
  635. error:
  636. if (bstrOwner) {
  637. SysFreeString(bstrOwner);
  638. }
  639. return(hr);
  640. }
  641. HRESULT
  642. ComputeTotalAclSize(
  643. PACE_HEADER * ppAceHdr,
  644. DWORD dwAceCount,
  645. PDWORD pdwAclSize
  646. )
  647. {
  648. DWORD i = 0;
  649. PACE_HEADER pAceHdr = NULL;
  650. DWORD dwAceSize = 0;
  651. DWORD dwAclSize = 0;
  652. for (i = 0; i < dwAceCount; i++) {
  653. pAceHdr = *(ppAceHdr + i);
  654. dwAceSize = pAceHdr->AceSize;
  655. dwAclSize += dwAceSize;
  656. }
  657. dwAclSize += sizeof(ACL);
  658. *pdwAclSize = dwAclSize;
  659. return(S_OK);
  660. }
  661. HRESULT
  662. ConvertAccessControlEntryToAce(
  663. IADsAccessControlEntry * pAccessControlEntry,
  664. LPBYTE * ppAce
  665. )
  666. {
  667. DWORD dwAceType = 0;
  668. HRESULT hr = S_OK;
  669. BSTR bstrTrustee = NULL;
  670. PSID pSid = NULL;
  671. DWORD dwSidSize = 0;
  672. DWORD dwAceFlags = 0;
  673. DWORD dwAccessMask = 0;
  674. DWORD dwAceSize = 0;
  675. LPBYTE pAce = NULL;
  676. PACCESS_MASK pAccessMask = NULL;
  677. PSID pSidAddress = NULL;
  678. PUSHORT pCompoundAceType = NULL;
  679. DWORD dwCompoundAceType = 0;
  680. PACE_HEADER pAceHeader = NULL;
  681. LPBYTE pOffset = NULL;
  682. BSTR bstrObjectTypeClsid = NULL;
  683. BSTR bstrInheritedObjectTypeClsid = NULL;
  684. GUID ObjectTypeGUID;
  685. GUID InheritedObjectTypeGUID;
  686. PULONG pFlags;
  687. DWORD dwFlags = 0;
  688. hr = pAccessControlEntry->get_AceType((LONG *)&dwAceType);
  689. BAIL_ON_FAILURE(hr);
  690. hr = pAccessControlEntry->get_Trustee(&bstrTrustee);
  691. BAIL_ON_FAILURE(hr);
  692. hr = ConvertTrusteeToSid(
  693. bstrTrustee,
  694. &pSid,
  695. &dwSidSize
  696. );
  697. BAIL_ON_FAILURE(hr);
  698. hr = pAccessControlEntry->get_AceFlags((long *)&dwAceFlags);
  699. BAIL_ON_FAILURE(hr);
  700. hr = pAccessControlEntry->get_AccessMask((long *)&dwAccessMask);
  701. BAIL_ON_FAILURE(hr);
  702. //
  703. // we will compensateby adding the entire ACE size
  704. //
  705. dwAceSize = dwSidSize - sizeof(ULONG);
  706. switch (dwAceType) {
  707. case ACCESS_ALLOWED_ACE_TYPE:
  708. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  709. pAce = new BYTE[dwAceSize];
  710. if (!pAce) {
  711. hr = E_OUTOFMEMORY;
  712. BAIL_ON_FAILURE(hr);
  713. }
  714. pAceHeader = (PACE_HEADER)pAce;
  715. pAceHeader->AceType = (UCHAR)dwAceType;
  716. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  717. pAceHeader->AceSize = (USHORT)dwAceSize;
  718. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  719. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  720. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  721. memcpy(pSidAddress, pSid, dwSidSize);
  722. break;
  723. case ACCESS_DENIED_ACE_TYPE:
  724. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  725. pAce = new BYTE[dwAceSize];
  726. if (!pAce) {
  727. hr = E_OUTOFMEMORY;
  728. BAIL_ON_FAILURE(hr);
  729. }
  730. pAceHeader = (PACE_HEADER)pAce;
  731. pAceHeader->AceType = (UCHAR)dwAceType;
  732. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  733. pAceHeader->AceSize = (USHORT)dwAceSize;
  734. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  735. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  736. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  737. memcpy(pSidAddress, pSid, dwSidSize);
  738. break;
  739. case SYSTEM_AUDIT_ACE_TYPE:
  740. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  741. pAce = new BYTE[dwAceSize];
  742. if (!pAce) {
  743. hr = E_OUTOFMEMORY;
  744. BAIL_ON_FAILURE(hr);
  745. }
  746. pAceHeader = (PACE_HEADER)pAce;
  747. pAceHeader->AceType = (UCHAR)dwAceType;
  748. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  749. pAceHeader->AceSize = (USHORT)dwAceSize;
  750. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  751. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  752. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  753. memcpy(pSidAddress, pSid, dwSidSize);
  754. break;
  755. case SYSTEM_ALARM_ACE_TYPE:
  756. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  757. pAce = new BYTE[dwAceSize];
  758. if (!pAce) {
  759. hr = E_OUTOFMEMORY;
  760. BAIL_ON_FAILURE(hr);
  761. }
  762. pAceHeader = (PACE_HEADER)pAce;
  763. pAceHeader->AceType = (UCHAR)dwAceType;
  764. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  765. pAceHeader->AceSize = (USHORT)dwAceSize;
  766. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  767. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  768. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  769. memcpy(pSidAddress, pSid, dwSidSize);
  770. break;
  771. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  772. dwAceSize += sizeof(COMPOUND_ACCESS_ALLOWED_ACE);
  773. pAce = new BYTE[dwAceSize];
  774. if (!pAce) {
  775. hr = E_OUTOFMEMORY;
  776. BAIL_ON_FAILURE(hr);
  777. }
  778. pAceHeader = (PACE_HEADER)pAce;
  779. pAceHeader->AceType = (UCHAR)dwAceType;
  780. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  781. pAceHeader->AceSize = (USHORT)dwAceSize;
  782. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  783. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  784. pCompoundAceType = (PUSHORT)(pAccessMask + sizeof(ACCESS_MASK));
  785. *pCompoundAceType = (USHORT)dwCompoundAceType;
  786. //
  787. // Fill in the reserved field here.
  788. //
  789. pSidAddress = (PSID)((LPBYTE)pCompoundAceType + sizeof(DWORD));
  790. memcpy(pSidAddress, pSid, dwSidSize);
  791. break;
  792. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  793. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  794. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  795. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  796. hr = pAccessControlEntry->get_AceFlags((LONG *)&dwAceFlags);
  797. BAIL_ON_FAILURE(hr);
  798. hr = pAccessControlEntry->get_Flags((LONG *)&dwFlags);
  799. BAIL_ON_FAILURE(hr);
  800. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  801. dwAceSize += sizeof(GUID);
  802. }
  803. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  804. dwAceSize += sizeof(GUID);
  805. }
  806. hr = pAccessControlEntry->get_ObjectType(&bstrObjectTypeClsid);
  807. BAIL_ON_FAILURE(hr);
  808. hr = CLSIDFromString(bstrObjectTypeClsid, &ObjectTypeGUID);
  809. BAIL_ON_FAILURE(hr);
  810. hr = pAccessControlEntry->get_InheritedObjectType(&bstrInheritedObjectTypeClsid);
  811. BAIL_ON_FAILURE(hr);
  812. hr = CLSIDFromString(bstrInheritedObjectTypeClsid, &InheritedObjectTypeGUID);
  813. BAIL_ON_FAILURE(hr);
  814. dwAceSize += sizeof(ACCESS_ALLOWED_OBJECT_ACE);
  815. pAce = new BYTE[dwAceSize];
  816. if (!pAce) {
  817. hr = E_OUTOFMEMORY;
  818. BAIL_ON_FAILURE(hr);
  819. }
  820. pAceHeader = (PACE_HEADER)pAce;
  821. pAceHeader->AceType = (UCHAR)dwAceType;
  822. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  823. pAceHeader->AceSize = (USHORT)dwAceSize;
  824. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  825. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  826. //
  827. // Fill in Flags
  828. //
  829. pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
  830. pFlags = (PULONG)(pOffset);
  831. *pFlags = dwFlags;
  832. pOffset += sizeof(ULONG);
  833. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  834. memcpy(pOffset, &ObjectTypeGUID, sizeof(GUID));
  835. pOffset += sizeof(GUID);
  836. }
  837. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  838. memcpy(pOffset, &InheritedObjectTypeGUID, sizeof(GUID));
  839. pOffset += sizeof(GUID);
  840. }
  841. pSidAddress = (PSID)((LPBYTE)pOffset);
  842. memcpy(pSidAddress, pSid, dwSidSize);
  843. break;
  844. }
  845. *ppAce = pAce;
  846. error:
  847. if (bstrTrustee) {
  848. SysFreeString(bstrTrustee);
  849. }
  850. if (pSid) {
  851. delete (pSid);
  852. }
  853. return(hr);
  854. }
  855. HRESULT
  856. ConvertAccessControlListToAcl(
  857. IADsAccessControlList FAR * pAccessList,
  858. PACL * ppAcl
  859. )
  860. {
  861. IUnknown * pUnknown = NULL;
  862. IEnumVARIANT * pEnumerator = NULL;
  863. HRESULT hr = S_OK;
  864. DWORD i = 0;
  865. DWORD cReturned = 0;
  866. VARIANT varAce;
  867. DWORD dwAceCount = 0;
  868. IADsAccessControlEntry FAR * pAccessControlEntry = NULL;
  869. LPBYTE pTempAce = NULL;
  870. DWORD dwCount = 0;
  871. PACL pAcl = NULL;
  872. DWORD dwAclSize = 0;
  873. PACE_HEADER * ppAceHdr = NULL;
  874. DWORD dwRet = 0;
  875. DWORD dwAclRevision = 0;
  876. DWORD dwStatus = 0;
  877. DWORD dwError = 0;
  878. hr = pAccessList->get_AceCount((long *)&dwAceCount);
  879. BAIL_ON_FAILURE(hr);
  880. hr = pAccessList->get__NewEnum(
  881. &pUnknown
  882. );
  883. BAIL_ON_FAILURE(hr);
  884. hr = pUnknown->QueryInterface(
  885. IID_IEnumVARIANT,
  886. (void FAR * FAR *)&pEnumerator
  887. );
  888. BAIL_ON_FAILURE(hr);
  889. ppAceHdr = new PACE_HEADER [dwAceCount];
  890. if (!ppAceHdr) {
  891. hr = E_OUTOFMEMORY;
  892. BAIL_ON_FAILURE(hr);
  893. }
  894. for (i = 0; i < dwAceCount; i++) {
  895. VariantInit(&varAce);
  896. hr = pEnumerator->Next(
  897. 1,
  898. &varAce,
  899. &cReturned
  900. );
  901. CONTINUE_ON_FAILURE(hr);
  902. hr = (V_DISPATCH(&varAce))->QueryInterface(
  903. IID_IADsAccessControlEntry,
  904. (void **)&pAccessControlEntry
  905. );
  906. CONTINUE_ON_FAILURE(hr);
  907. hr = ConvertAccessControlEntryToAce(
  908. pAccessControlEntry,
  909. &(pTempAce)
  910. );
  911. // ZoltanS: Rather than CONTINUE_ON_FAILURE, let's bail so that we
  912. // know if the Ace we set is invalid.
  913. BAIL_ON_FAILURE(hr);
  914. *(ppAceHdr + dwCount) = (PACE_HEADER)pTempAce;
  915. VariantClear(&varAce);
  916. if (pAccessControlEntry) {
  917. pAccessControlEntry->Release();
  918. pAccessControlEntry = NULL;
  919. }
  920. dwCount++;
  921. }
  922. hr = ComputeTotalAclSize(ppAceHdr, dwCount, &dwAclSize);
  923. BAIL_ON_FAILURE(hr);
  924. pAcl = (PACL)new BYTE[dwAclSize];
  925. if (!pAcl) {
  926. hr = E_OUTOFMEMORY;
  927. BAIL_ON_FAILURE(hr);
  928. }
  929. hr = pAccessList->get_AclRevision((long *)&dwAclRevision);
  930. BAIL_ON_FAILURE(hr);
  931. dwRet = InitializeAcl(
  932. pAcl,
  933. dwAclSize,
  934. dwAclRevision
  935. );
  936. if (!dwRet) {
  937. hr = HRESULT_FROM_WIN32(GetLastError());
  938. BAIL_ON_FAILURE(hr);
  939. }
  940. for (i = 0; i < dwCount; i++) {
  941. dwStatus = AddAce(
  942. pAcl,
  943. dwAclRevision,
  944. i,
  945. (LPBYTE)*(ppAceHdr + i),
  946. (*(ppAceHdr + i))->AceSize
  947. );
  948. if (!dwStatus) {
  949. dwError = GetLastError();
  950. }
  951. }
  952. *ppAcl = pAcl;
  953. error:
  954. if (ppAceHdr) {
  955. for (i = 0; i < dwCount; i++) {
  956. if (*(ppAceHdr + i)) {
  957. delete (*(ppAceHdr + i));
  958. }
  959. }
  960. delete (ppAceHdr);
  961. }
  962. if (pUnknown) {
  963. pUnknown->Release();
  964. }
  965. if (pEnumerator) {
  966. pEnumerator->Release();
  967. }
  968. return(hr);
  969. }
  970. HRESULT
  971. GetGroupSecurityIdentifier(
  972. IADsSecurityDescriptor FAR * pSecDes,
  973. PSID * ppSid,
  974. PBOOL pfGroupDefaulted
  975. )
  976. {
  977. BSTR bstrGroup = NULL;
  978. DWORD dwSidSize = 0;
  979. HRESULT hr = S_OK;
  980. VARIANT_BOOL varBool = VARIANT_FALSE;
  981. hr = pSecDes->get_Group(
  982. &bstrGroup
  983. );
  984. BAIL_ON_FAILURE(hr);
  985. hr = pSecDes->get_GroupDefaulted(
  986. &varBool
  987. );
  988. BAIL_ON_FAILURE(hr);
  989. if (varBool == VARIANT_FALSE) {
  990. if (bstrGroup && *bstrGroup) {
  991. hr = ConvertTrusteeToSid(
  992. bstrGroup,
  993. ppSid,
  994. &dwSidSize
  995. );
  996. BAIL_ON_FAILURE(hr);
  997. *pfGroupDefaulted = FALSE;
  998. }else {
  999. *ppSid = NULL;
  1000. *pfGroupDefaulted = FALSE;
  1001. }
  1002. }else {
  1003. *ppSid = NULL;
  1004. dwSidSize = 0;
  1005. *pfGroupDefaulted = TRUE;
  1006. }
  1007. error:
  1008. if (bstrGroup) {
  1009. SysFreeString(bstrGroup);
  1010. }
  1011. return(hr);
  1012. }
  1013. HRESULT
  1014. GetDacl(
  1015. IADsSecurityDescriptor FAR * pSecDes,
  1016. PACL * ppDacl,
  1017. PBOOL pfDaclDefaulted
  1018. )
  1019. {
  1020. IADsAccessControlList FAR * pDiscAcl = NULL;
  1021. IDispatch FAR * pDispatch = NULL;
  1022. HRESULT hr = S_OK;
  1023. VARIANT_BOOL varBool = VARIANT_FALSE;
  1024. hr = pSecDes->get_DaclDefaulted(
  1025. &varBool
  1026. );
  1027. BAIL_ON_FAILURE(hr);
  1028. if (varBool == VARIANT_FALSE) {
  1029. *pfDaclDefaulted = FALSE;
  1030. }else {
  1031. *pfDaclDefaulted = TRUE;
  1032. }
  1033. hr = pSecDes->get_DiscretionaryAcl(
  1034. &pDispatch
  1035. );
  1036. BAIL_ON_FAILURE(hr);
  1037. if (!pDispatch) {
  1038. *ppDacl = NULL;
  1039. goto error;
  1040. }
  1041. hr = pDispatch->QueryInterface(
  1042. IID_IADsAccessControlList,
  1043. (void **)&pDiscAcl
  1044. );
  1045. BAIL_ON_FAILURE(hr);
  1046. hr = ConvertAccessControlListToAcl(
  1047. pDiscAcl,
  1048. ppDacl
  1049. );
  1050. BAIL_ON_FAILURE(hr);
  1051. error:
  1052. if (pDispatch) {
  1053. pDispatch->Release();
  1054. }
  1055. if (pDiscAcl) {
  1056. pDiscAcl->Release();
  1057. }
  1058. return(hr);
  1059. }
  1060. HRESULT
  1061. GetSacl(
  1062. IADsSecurityDescriptor FAR * pSecDes,
  1063. PACL * ppSacl,
  1064. PBOOL pfSaclDefaulted
  1065. )
  1066. {
  1067. IADsAccessControlList FAR * pSystemAcl = NULL;
  1068. IDispatch FAR * pDispatch = NULL;
  1069. HRESULT hr = S_OK;
  1070. VARIANT_BOOL varBool = VARIANT_FALSE;
  1071. hr = pSecDes->get_SaclDefaulted(
  1072. &varBool
  1073. );
  1074. BAIL_ON_FAILURE(hr);
  1075. if (varBool == VARIANT_FALSE) {
  1076. *pfSaclDefaulted = FALSE;
  1077. }else {
  1078. *pfSaclDefaulted = TRUE;
  1079. }
  1080. hr = pSecDes->get_SystemAcl(
  1081. &pDispatch
  1082. );
  1083. BAIL_ON_FAILURE(hr);
  1084. if (!pDispatch) {
  1085. *ppSacl = NULL;
  1086. goto error;
  1087. }
  1088. hr = pDispatch->QueryInterface(
  1089. IID_IADsAccessControlList,
  1090. (void **)&pSystemAcl
  1091. );
  1092. BAIL_ON_FAILURE(hr);
  1093. hr = ConvertAccessControlListToAcl(
  1094. pSystemAcl,
  1095. ppSacl
  1096. );
  1097. BAIL_ON_FAILURE(hr);
  1098. error:
  1099. if (pDispatch) {
  1100. pDispatch->Release();
  1101. }
  1102. if (pSystemAcl) {
  1103. pSystemAcl->Release();
  1104. }
  1105. return(hr);
  1106. }
  1107. ///////////////////////////////////////////////////////////////////////////////
  1108. // //
  1109. // Public procedures //
  1110. // //
  1111. ///////////////////////////////////////////////////////////////////////////////
  1112. HRESULT
  1113. ConvertSDToIDispatch(
  1114. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1115. OUT IDispatch ** ppIDispatch
  1116. )
  1117. {
  1118. IADsSecurityDescriptor * pSecDes = NULL;
  1119. IDispatch * pDispatch = NULL;
  1120. LPWSTR pszGroup = NULL;
  1121. LPWSTR pszOwner = NULL;
  1122. BOOL fOwnerDefaulted = 0;
  1123. BOOL fGroupDefaulted = 0;
  1124. BOOL fDaclDefaulted = 0;
  1125. BOOL fSaclDefaulted = 0;
  1126. BOOL fSaclPresent = 0;
  1127. BOOL fDaclPresent = 0;
  1128. LPBYTE pOwnerSidAddress = NULL;
  1129. LPBYTE pGroupSidAddress = NULL;
  1130. LPBYTE pDACLAddress = NULL;
  1131. LPBYTE pSACLAddress = NULL;
  1132. DWORD dwRet = 0;
  1133. VARIANT varDACL;
  1134. VARIANT varSACL;
  1135. HRESULT hr = S_OK;
  1136. DWORD dwRevision = 0;
  1137. WORD wControl = 0;
  1138. memset(&varSACL, 0, sizeof(VARIANT));
  1139. memset(&varDACL, 0, sizeof(VARIANT));
  1140. if (!pSecurityDescriptor) {
  1141. return(E_FAIL);
  1142. }
  1143. dwRet = GetSecurityDescriptorControl(
  1144. pSecurityDescriptor,
  1145. &wControl,
  1146. &dwRevision
  1147. );
  1148. if (!dwRet){
  1149. hr = HRESULT_FROM_WIN32(GetLastError());
  1150. BAIL_ON_FAILURE(hr);
  1151. }
  1152. dwRet = GetSecurityDescriptorOwner(
  1153. pSecurityDescriptor,
  1154. (PSID *)&pOwnerSidAddress,
  1155. &fOwnerDefaulted
  1156. );
  1157. if (!dwRet){
  1158. hr = HRESULT_FROM_WIN32(GetLastError());
  1159. BAIL_ON_FAILURE(hr);
  1160. }
  1161. hr = ConvertSidToFriendlyName(
  1162. pOwnerSidAddress,
  1163. &pszOwner
  1164. );
  1165. BAIL_ON_FAILURE(hr);
  1166. dwRet = GetSecurityDescriptorGroup(
  1167. pSecurityDescriptor,
  1168. (PSID *)&pGroupSidAddress,
  1169. &fOwnerDefaulted
  1170. );
  1171. if (!dwRet){
  1172. hr = HRESULT_FROM_WIN32(GetLastError());
  1173. BAIL_ON_FAILURE(hr);
  1174. }
  1175. hr = ConvertSidToFriendlyName(
  1176. pGroupSidAddress,
  1177. &pszGroup
  1178. );
  1179. BAIL_ON_FAILURE(hr);
  1180. dwRet = GetSecurityDescriptorDacl(
  1181. pSecurityDescriptor,
  1182. &fDaclPresent,
  1183. (PACL*)&pDACLAddress,
  1184. &fDaclDefaulted
  1185. );
  1186. if (pDACLAddress) {
  1187. hr = ConvertACLToVariant(
  1188. (PACL)pDACLAddress,
  1189. &varDACL
  1190. );
  1191. BAIL_ON_FAILURE(hr);
  1192. }
  1193. dwRet = GetSecurityDescriptorSacl(
  1194. pSecurityDescriptor,
  1195. &fSaclPresent,
  1196. (PACL *)&pSACLAddress,
  1197. &fSaclDefaulted
  1198. );
  1199. if (!dwRet){
  1200. hr = HRESULT_FROM_WIN32(GetLastError());
  1201. BAIL_ON_FAILURE(hr);
  1202. }
  1203. if (pSACLAddress) {
  1204. hr = ConvertACLToVariant(
  1205. (PACL)pSACLAddress,
  1206. &varSACL
  1207. );
  1208. BAIL_ON_FAILURE(hr);
  1209. }
  1210. hr = CoCreateInstance(
  1211. CLSID_SecurityDescriptor,
  1212. NULL,
  1213. CLSCTX_INPROC_SERVER,
  1214. IID_IADsSecurityDescriptor,
  1215. (void **)&pSecDes
  1216. );
  1217. BAIL_ON_FAILURE(hr);
  1218. if ( pszOwner )
  1219. hr = pSecDes->put_Owner(pszOwner);
  1220. BAIL_ON_FAILURE(hr);
  1221. if ( pszGroup )
  1222. hr = pSecDes->put_Group(pszGroup);
  1223. BAIL_ON_FAILURE(hr);
  1224. hr = pSecDes->put_Revision(dwRevision);
  1225. BAIL_ON_FAILURE(hr);
  1226. hr = pSecDes->put_Control((DWORD)wControl);
  1227. BAIL_ON_FAILURE(hr);
  1228. hr = pSecDes->put_DiscretionaryAcl(V_DISPATCH(&varDACL));
  1229. BAIL_ON_FAILURE(hr);
  1230. hr = pSecDes->put_SystemAcl(V_DISPATCH(&varSACL));
  1231. BAIL_ON_FAILURE(hr);
  1232. hr = pSecDes->QueryInterface(IID_IDispatch, (void**)&pDispatch);
  1233. BAIL_ON_FAILURE(hr);
  1234. *ppIDispatch = pDispatch;
  1235. error:
  1236. VariantClear(&varSACL);
  1237. VariantClear(&varDACL);
  1238. if (pszOwner) {
  1239. delete (pszOwner);
  1240. }
  1241. if (pszGroup) {
  1242. delete (pszGroup);
  1243. }
  1244. if (pSecDes) {
  1245. pSecDes->Release();
  1246. }
  1247. return(hr);
  1248. }
  1249. HRESULT
  1250. ConvertSDToVariant(
  1251. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1252. OUT VARIANT * pVarSec
  1253. )
  1254. {
  1255. IDispatch *pIDispatch;
  1256. HRESULT hr = ConvertSDToIDispatch(pSecurityDescriptor, &pIDispatch);
  1257. if (FAILED(hr))
  1258. {
  1259. return hr;
  1260. }
  1261. VariantInit(pVarSec);
  1262. V_VT(pVarSec) = VT_DISPATCH;
  1263. V_DISPATCH(pVarSec) = pIDispatch;
  1264. return S_OK;
  1265. }
  1266. HRESULT
  1267. ConvertObjectToSD(
  1268. IN IADsSecurityDescriptor FAR * pSecDes,
  1269. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor,
  1270. OUT PDWORD pdwSDLength
  1271. )
  1272. {
  1273. HRESULT hr = S_OK;
  1274. SECURITY_DESCRIPTOR AbsoluteSD;
  1275. PSECURITY_DESCRIPTOR pRelative = NULL;
  1276. BOOL Defaulted = FALSE;
  1277. BOOL DaclPresent = FALSE;
  1278. BOOL SaclPresent = FALSE;
  1279. BOOL fDaclDefaulted = FALSE;
  1280. BOOL fSaclDefaulted = FALSE;
  1281. BOOL fOwnerDefaulted = FALSE;
  1282. BOOL fGroupDefaulted = FALSE;
  1283. PSID pOwnerSid = NULL;
  1284. PSID pGroupSid = NULL;
  1285. PACL pDacl = NULL;
  1286. PACL pSacl = NULL;
  1287. DWORD dwSDLength = 0;
  1288. DWORD dwRet = 0;
  1289. BOOL dwStatus = 0;
  1290. //
  1291. // Initialize *pSizeSD = 0;
  1292. //
  1293. dwRet = InitializeSecurityDescriptor (
  1294. &AbsoluteSD,
  1295. SECURITY_DESCRIPTOR_REVISION1
  1296. );
  1297. if (!dwRet) {
  1298. hr = E_FAIL;
  1299. BAIL_ON_FAILURE(hr);
  1300. }
  1301. hr = GetOwnerSecurityIdentifier(
  1302. pSecDes,
  1303. &pOwnerSid,
  1304. &fOwnerDefaulted
  1305. );
  1306. BAIL_ON_FAILURE(hr);
  1307. dwStatus = SetSecurityDescriptorOwner(
  1308. &AbsoluteSD,
  1309. pOwnerSid,
  1310. fOwnerDefaulted
  1311. );
  1312. if (!dwStatus) {
  1313. hr = HRESULT_FROM_WIN32(GetLastError());
  1314. BAIL_ON_FAILURE(hr);
  1315. }
  1316. hr = GetGroupSecurityIdentifier(
  1317. pSecDes,
  1318. &pGroupSid,
  1319. &fGroupDefaulted
  1320. );
  1321. BAIL_ON_FAILURE(hr);
  1322. dwStatus = SetSecurityDescriptorGroup(
  1323. &AbsoluteSD,
  1324. pGroupSid,
  1325. fGroupDefaulted
  1326. );
  1327. if (!dwStatus) {
  1328. hr = HRESULT_FROM_WIN32(GetLastError());
  1329. BAIL_ON_FAILURE(hr);
  1330. }
  1331. hr = GetDacl(
  1332. pSecDes,
  1333. &pDacl,
  1334. &fDaclDefaulted
  1335. );
  1336. BAIL_ON_FAILURE(hr);
  1337. if (pDacl || fDaclDefaulted) {
  1338. DaclPresent = TRUE;
  1339. }
  1340. dwStatus = SetSecurityDescriptorDacl(
  1341. &AbsoluteSD,
  1342. DaclPresent,
  1343. pDacl,
  1344. fDaclDefaulted
  1345. );
  1346. if (!dwStatus) {
  1347. hr = HRESULT_FROM_WIN32(GetLastError());
  1348. BAIL_ON_FAILURE(hr);
  1349. }
  1350. hr = GetSacl(
  1351. pSecDes,
  1352. &pSacl,
  1353. &fSaclDefaulted
  1354. );
  1355. BAIL_ON_FAILURE(hr);
  1356. if (pSacl || fSaclDefaulted) {
  1357. SaclPresent = TRUE;
  1358. }
  1359. dwStatus = SetSecurityDescriptorSacl(
  1360. &AbsoluteSD,
  1361. SaclPresent,
  1362. pSacl,
  1363. fSaclDefaulted
  1364. );
  1365. if (!dwStatus) {
  1366. hr = HRESULT_FROM_WIN32(GetLastError());
  1367. BAIL_ON_FAILURE(hr);
  1368. }
  1369. dwSDLength = GetSecurityDescriptorLength(
  1370. &AbsoluteSD
  1371. );
  1372. pRelative = LocalAlloc(LPTR, dwSDLength);
  1373. if (!pRelative) {
  1374. hr = E_OUTOFMEMORY;
  1375. BAIL_ON_FAILURE(hr);
  1376. }
  1377. if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &dwSDLength)) {
  1378. delete (pRelative);
  1379. hr = HRESULT_FROM_WIN32(GetLastError());
  1380. BAIL_ON_FAILURE(hr);
  1381. }
  1382. *ppSecurityDescriptor = pRelative;
  1383. *pdwSDLength = dwSDLength;
  1384. cleanup:
  1385. if (pDacl) {
  1386. delete (pDacl);
  1387. }
  1388. if (pSacl) {
  1389. delete (pSacl);
  1390. }
  1391. if (pOwnerSid) {
  1392. delete (pOwnerSid);
  1393. }
  1394. if (pGroupSid) {
  1395. delete (pGroupSid);
  1396. }
  1397. return(hr);
  1398. error:
  1399. if (pRelative) {
  1400. LocalFree( pRelative );
  1401. }
  1402. *ppSecurityDescriptor = NULL;
  1403. *pdwSDLength = 0;
  1404. goto cleanup;
  1405. }
  1406. HRESULT
  1407. ConvertObjectToSDDispatch(
  1408. IN IDispatch * pDisp,
  1409. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor,
  1410. OUT PDWORD pdwSDLength
  1411. )
  1412. {
  1413. HRESULT hr;
  1414. IADsSecurityDescriptor * pSecDes;
  1415. hr = pDisp->QueryInterface(
  1416. IID_IADsSecurityDescriptor,
  1417. (VOID **)&pSecDes
  1418. );
  1419. if (FAILED(hr))
  1420. {
  1421. return hr;
  1422. }
  1423. hr = ConvertObjectToSD(pSecDes, ppSecurityDescriptor, pdwSDLength);
  1424. return hr;
  1425. }