Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

693 lines
21 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: si.cpp
  8. //
  9. // This file contains the implementation of the CSecurityInformation
  10. // base class.
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "rshx32.h"
  14. #include <shlapip.h>
  15. #if(_WIN32_WINNT < 0x0500)
  16. //
  17. // NT4 SP4 doesn't support SetSecurityDescriptorControl, so
  18. // emulate it here
  19. //
  20. BOOL
  21. WINAPI
  22. SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR psd,
  23. SECURITY_DESCRIPTOR_CONTROL wControlMask,
  24. SECURITY_DESCRIPTOR_CONTROL wControlBits)
  25. {
  26. DWORD dwErr = NOERROR;
  27. PISECURITY_DESCRIPTOR pSD = (PISECURITY_DESCRIPTOR)psd;
  28. if (pSD)
  29. pSD->Control = (pSD->Control & ~wControlMask) | wControlBits;
  30. else
  31. dwErr = ERROR_INVALID_PARAMETER;
  32. return dwErr;
  33. }
  34. #endif
  35. #include <dsrole.h>
  36. BOOL IsStandalone(LPCTSTR pszMachine, PBOOL pbIsDC)
  37. {
  38. BOOL bStandalone = TRUE;
  39. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDsRole = NULL;
  40. //
  41. // Find out if target machine is a standalone machine or joined to
  42. // an NT domain.
  43. //
  44. __try
  45. {
  46. if (pbIsDC)
  47. *pbIsDC = FALSE;
  48. DsRoleGetPrimaryDomainInformation(pszMachine,
  49. DsRolePrimaryDomainInfoBasic,
  50. (PBYTE*)&pDsRole);
  51. }
  52. __finally
  53. {
  54. }
  55. if (NULL != pDsRole)
  56. {
  57. if (pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation ||
  58. pDsRole->MachineRole == DsRole_RoleStandaloneServer)
  59. {
  60. bStandalone = TRUE;
  61. }
  62. else
  63. bStandalone = FALSE;
  64. if (pbIsDC)
  65. {
  66. if (pDsRole->MachineRole == DsRole_RolePrimaryDomainController ||
  67. pDsRole->MachineRole == DsRole_RoleBackupDomainController)
  68. {
  69. *pbIsDC = TRUE;
  70. }
  71. }
  72. DsRoleFreeMemory(pDsRole);
  73. }
  74. return bStandalone;
  75. }
  76. void
  77. ProtectACLs(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR pSD)
  78. {
  79. SECURITY_DESCRIPTOR_CONTROL wSDControl;
  80. DWORD dwRevision;
  81. PACL pAcl;
  82. BOOL bDefaulted;
  83. BOOL bPresent;
  84. PACE_HEADER pAce;
  85. UINT cAces;
  86. TraceEnter(TRACE_SI, "ProtectACLs");
  87. if (0 == si || NULL == pSD)
  88. TraceLeaveVoid(); // Nothing to do
  89. // Get the ACL protection control bits
  90. GetSecurityDescriptorControl(pSD, &wSDControl, &dwRevision);
  91. wSDControl &= SE_DACL_PROTECTED | SE_SACL_PROTECTED;
  92. if ((si & DACL_SECURITY_INFORMATION) && !(wSDControl & SE_DACL_PROTECTED))
  93. {
  94. wSDControl |= SE_DACL_PROTECTED;
  95. pAcl = NULL;
  96. GetSecurityDescriptorDacl(pSD, &bPresent, &pAcl, &bDefaulted);
  97. // Theoretically, modifying the DACL in this way can cause it to be
  98. // no longer canonical. However, the only way this can happen is if
  99. // there is an inherited Deny ACE and a non-inherited Allow ACE.
  100. // Since this function is only called for root objects, this means
  101. // a) the server DACL must have a Deny ACE and b) the DACL on this
  102. // object must have been modified later. But if the DACL was
  103. // modified through the UI, then we would have eliminated all of the
  104. // Inherited ACEs already. Therefore, it must have been modified
  105. // through some other means. Considering that the DACL originally
  106. // inherited from the server never has a Deny ACE, this situation
  107. // should be extrememly rare. If it ever does happen, the ACL
  108. // Editor will just tell the user that the DACL is non-canonical.
  109. //
  110. // Therefore, let's ignore the possibility here.
  111. if (NULL != pAcl)
  112. {
  113. for (cAces = pAcl->AceCount, pAce = (PACE_HEADER)FirstAce(pAcl);
  114. cAces > 0;
  115. --cAces, pAce = (PACE_HEADER)NextAce(pAce))
  116. {
  117. pAce->AceFlags &= ~INHERITED_ACE;
  118. }
  119. }
  120. }
  121. if ((si & SACL_SECURITY_INFORMATION) && !(wSDControl & SE_SACL_PROTECTED))
  122. {
  123. wSDControl |= SE_SACL_PROTECTED;
  124. pAcl = NULL;
  125. GetSecurityDescriptorSacl(pSD, &bPresent, &pAcl, &bDefaulted);
  126. if (NULL != pAcl)
  127. {
  128. for (cAces = pAcl->AceCount, pAce = (PACE_HEADER)FirstAce(pAcl);
  129. cAces > 0;
  130. --cAces, pAce = (PACE_HEADER)NextAce(pAce))
  131. {
  132. pAce->AceFlags &= ~INHERITED_ACE;
  133. }
  134. }
  135. }
  136. SetSecurityDescriptorControl(pSD, SE_DACL_PROTECTED | SE_SACL_PROTECTED, wSDControl);
  137. TraceLeaveVoid();
  138. }
  139. CSecurityInformation::CSecurityInformation(SE_OBJECT_TYPE seType)
  140. : m_cRef(1), m_seType(seType), m_hwndOwner(NULL),m_ResourceManager(NULL),m_bIsStandAlone(FALSE)
  141. {
  142. InterlockedIncrement(&g_cRefThisDll);
  143. AuthzInitializeResourceManager(0,
  144. NULL,
  145. NULL,
  146. NULL,
  147. L"Dummy",
  148. &m_ResourceManager );
  149. }
  150. CSecurityInformation::~CSecurityInformation()
  151. {
  152. LocalFreeDPA(m_hItemList);
  153. LocalFreeString(&m_pszObjectName);
  154. LocalFreeString(&m_pszServerName);
  155. AuthzFreeResourceManager(m_ResourceManager);
  156. InterlockedDecrement(&g_cRefThisDll);
  157. }
  158. STDMETHODIMP
  159. CSecurityInformation::Initialize(HDPA hItemList,
  160. DWORD dwFlags,
  161. LPTSTR pszServer,
  162. LPTSTR pszObject)
  163. {
  164. TraceEnter(TRACE_SI, "CSecurityInformation::Initialize");
  165. TraceAssert(hItemList != NULL);
  166. TraceAssert(DPA_GetPtrCount(hItemList) > 0);
  167. TraceAssert(pszObject != NULL);
  168. TraceAssert(m_pszObjectName == NULL); // only initialize once
  169. m_hItemList = hItemList;
  170. m_dwSIFlags = dwFlags;
  171. m_pszServerName = pszServer;
  172. m_pszObjectName = pszObject;
  173. m_bIsStandAlone = IsStandalone(pszServer, NULL);
  174. TraceLeaveResult(S_OK);
  175. }
  176. ///////////////////////////////////////////////////////////
  177. //
  178. // IUnknown methods
  179. //
  180. ///////////////////////////////////////////////////////////
  181. STDMETHODIMP_(ULONG)
  182. CSecurityInformation::AddRef()
  183. {
  184. return ++m_cRef;
  185. }
  186. STDMETHODIMP_(ULONG)
  187. CSecurityInformation::Release()
  188. {
  189. if (--m_cRef == 0)
  190. {
  191. delete this;
  192. return 0;
  193. }
  194. return m_cRef;
  195. }
  196. STDMETHODIMP
  197. CSecurityInformation::QueryInterface(REFIID riid, LPVOID FAR* ppv)
  198. {
  199. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation))
  200. {
  201. *ppv = (LPSECURITYINFO)this;
  202. m_cRef++;
  203. return S_OK;
  204. }
  205. else if (IsEqualIID(riid, IID_IEffectivePermission))
  206. {
  207. *ppv = (LPEFFECTIVEPERMISSION)this;
  208. m_cRef++;
  209. return S_OK;
  210. }
  211. else if((m_seType != SE_PRINTER) && IsEqualIID(riid, IID_ISecurityObjectTypeInfo))
  212. {
  213. *ppv = (LPSecurityObjectTypeInfo)this;
  214. m_cRef++;
  215. return S_OK;
  216. }
  217. else
  218. {
  219. *ppv = NULL;
  220. return E_NOINTERFACE;
  221. }
  222. }
  223. ///////////////////////////////////////////////////////////
  224. //
  225. // ISecurityInformation methods
  226. //
  227. ///////////////////////////////////////////////////////////
  228. STDMETHODIMP
  229. CSecurityInformation::GetObjectInformation(PSI_OBJECT_INFO pObjectInfo)
  230. {
  231. TraceEnter(TRACE_SI, "CSecurityInformation::GetObjectInformation");
  232. TraceAssert(pObjectInfo != NULL &&
  233. !IsBadWritePtr(pObjectInfo, sizeof(*pObjectInfo)));
  234. pObjectInfo->dwFlags = m_dwSIFlags;
  235. pObjectInfo->hInstance = g_hInstance;
  236. pObjectInfo->pszServerName = m_pszServerName;
  237. pObjectInfo->pszObjectName = m_pszObjectName;
  238. TraceLeaveResult(S_OK);
  239. }
  240. STDMETHODIMP
  241. CSecurityInformation::GetSecurity(SECURITY_INFORMATION si,
  242. PSECURITY_DESCRIPTOR *ppSD,
  243. BOOL fDefault)
  244. {
  245. HRESULT hr = S_OK;
  246. LPTSTR pszItem;
  247. TraceEnter(TRACE_SI, "CSecurityInformation::GetSecurity");
  248. TraceAssert(si != 0);
  249. TraceAssert(ppSD != NULL);
  250. *ppSD = NULL;
  251. //Default security descriptor not supported
  252. if (fDefault)
  253. ExitGracefully(hr, E_NOTIMPL, "Default security descriptor not supported");
  254. // Get the name of the first item
  255. pszItem = (LPTSTR)DPA_GetPtr(m_hItemList, 0);
  256. if (NULL == pszItem)
  257. ExitGracefully(hr, E_UNEXPECTED, "CSecurityInformation not initialized");
  258. hr = ReadObjectSecurity(pszItem, si, ppSD);
  259. // If this is a Root object, then we pretend that the ACLs are
  260. // always protected and no ACEs are inherited.
  261. if (SUCCEEDED(hr) && (m_dwSIFlags & SI_NO_ACL_PROTECT))
  262. ProtectACLs(si & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION), *ppSD);
  263. exit_gracefully:
  264. TraceLeaveResult(hr);
  265. }
  266. STDMETHODIMP
  267. CSecurityInformation::SetSecurity(SECURITY_INFORMATION si,
  268. PSECURITY_DESCRIPTOR pSD)
  269. {
  270. HRESULT hr = S_OK;
  271. HCURSOR hcurPrevious = (HCURSOR)INVALID_HANDLE_VALUE;
  272. UINT cItems;
  273. int i;
  274. TraceEnter(TRACE_SI, "CSecurityInformation::SetSecurity");
  275. TraceAssert(si != 0);
  276. TraceAssert(pSD != NULL);
  277. if (NULL == m_hItemList)
  278. ExitGracefully(hr, E_UNEXPECTED, "CSecurityInformation not initialized");
  279. hcurPrevious = SetCursor(LoadCursor(NULL, IDC_WAIT));
  280. //
  281. // Apply the new permissions to every item in the list
  282. //
  283. for (i = 0; i < DPA_GetPtrCount(m_hItemList); i++)
  284. {
  285. LPTSTR pszItem = (LPTSTR)DPA_FastGetPtr(m_hItemList, i);
  286. hr = WriteObjectSecurity(pszItem, si, pSD);
  287. FailGracefully(hr, "Unable to write new security descriptor");
  288. if (IsFile()) // If this is a file, delete it's thumbnail from the database, it will get put back if appropriate
  289. {
  290. DeleteFileThumbnail(pszItem);
  291. }
  292. }
  293. exit_gracefully:
  294. // Restore previous cursor
  295. if (hcurPrevious != INVALID_HANDLE_VALUE)
  296. SetCursor(hcurPrevious);
  297. TraceLeaveResult(hr);
  298. }
  299. STDMETHODIMP
  300. CSecurityInformation::PropertySheetPageCallback(HWND hwnd,
  301. UINT uMsg,
  302. SI_PAGE_TYPE uPage)
  303. {
  304. if (SI_PAGE_PERM == uPage)
  305. {
  306. switch (uMsg)
  307. {
  308. case PSPCB_SI_INITDIALOG:
  309. do
  310. {
  311. m_hwndOwner = hwnd;
  312. } while (hwnd = GetParent(hwnd));
  313. break;
  314. case PSPCB_RELEASE:
  315. m_hwndOwner = NULL;
  316. break;
  317. }
  318. }
  319. return S_OK;
  320. }
  321. STDMETHODIMP
  322. CSecurityInformation::ReadObjectSecurity(LPCTSTR pszObject,
  323. SECURITY_INFORMATION si,
  324. PSECURITY_DESCRIPTOR *ppSD)
  325. {
  326. DWORD dwErr;
  327. TraceEnter(TRACE_SI, "CSecurityInformation::ReadObjectSecurity");
  328. TraceAssert(pszObject != NULL);
  329. TraceAssert(si != 0);
  330. TraceAssert(ppSD != NULL);
  331. //
  332. // This is kinda screwy. The new APIs are being removed from NT5, but have
  333. // already been added to NT4 SP4. The old APIs have new functionality on NT5,
  334. // but not on NT4 SPx. Since we need the new functionality (auto-inheritance),
  335. // we have to call the new (defunct) API on NT4 and the old API on NT5.
  336. //
  337. #if(_WIN32_WINNT >= 0x0500)
  338. dwErr = GetNamedSecurityInfo((LPTSTR)pszObject,
  339. m_seType,
  340. si,
  341. NULL,
  342. NULL,
  343. NULL,
  344. NULL,
  345. ppSD);
  346. #else // _WIN32_WINNT < 0x0500
  347. PACTRL_ACCESS pAccessList = NULL;
  348. PACTRL_AUDIT pAuditList = NULL;
  349. LPTSTR pOwner = NULL;
  350. LPTSTR pGroup = NULL;
  351. dwErr = GetNamedSecurityInfoEx(pszObject,
  352. m_seType,
  353. si,
  354. NULL,
  355. NULL,
  356. (si & DACL_SECURITY_INFORMATION) ? &pAccessList : NULL,
  357. (si & SACL_SECURITY_INFORMATION) ? &pAuditList : NULL,
  358. (si & OWNER_SECURITY_INFORMATION) ? &pOwner : NULL,
  359. (si & GROUP_SECURITY_INFORMATION) ? &pGroup : NULL);
  360. if (!dwErr)
  361. {
  362. dwErr = ConvertAccessToSecurityDescriptor(pAccessList,
  363. pAuditList,
  364. pOwner,
  365. pGroup,
  366. ppSD);
  367. if (pAccessList)
  368. LocalFree(pAccessList);
  369. if (pAuditList)
  370. LocalFree(pAuditList);
  371. if (pOwner)
  372. LocalFree(pOwner);
  373. if (pGroup)
  374. LocalFree(pGroup);
  375. }
  376. #endif // _WIN32_WINNT < 0x0500
  377. TraceLeaveResult(HRESULT_FROM_WIN32(dwErr));
  378. }
  379. STDMETHODIMP
  380. CSecurityInformation::WriteObjectSecurity(LPCTSTR pszObject,
  381. SECURITY_INFORMATION si,
  382. PSECURITY_DESCRIPTOR pSD)
  383. {
  384. DWORD dwErr;
  385. TraceEnter(TRACE_SI, "CSecurityInformation::WriteObjectSecurity");
  386. TraceAssert(pszObject != NULL);
  387. TraceAssert(si != 0);
  388. TraceAssert(pSD != NULL);
  389. //
  390. // This is kinda screwy. The new APIs are being removed from NT5, but have
  391. // already been added to NT4 SP4. The old APIs have new functionality on NT5,
  392. // but not on NT4 SPx. Since we need the new functionality (auto-inheritance),
  393. // we have to call the new (defunct) API on NT4 and the old API on NT5.
  394. //
  395. #if(_WIN32_WINNT >= 0x0500)
  396. SECURITY_DESCRIPTOR_CONTROL wSDControl = 0;
  397. DWORD dwRevision;
  398. PSID psidOwner = NULL;
  399. PSID psidGroup = NULL;
  400. PACL pDacl = NULL;
  401. PACL pSacl = NULL;
  402. BOOL bDefaulted;
  403. BOOL bPresent;
  404. //
  405. // Get pointers to various security descriptor parts for
  406. // calling SetNamedSecurityInfo
  407. //
  408. GetSecurityDescriptorControl(pSD, &wSDControl, &dwRevision);
  409. GetSecurityDescriptorOwner(pSD, &psidOwner, &bDefaulted);
  410. GetSecurityDescriptorGroup(pSD, &psidGroup, &bDefaulted);
  411. GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaulted);
  412. GetSecurityDescriptorSacl(pSD, &bPresent, &pSacl, &bDefaulted);
  413. if (si & DACL_SECURITY_INFORMATION)
  414. {
  415. if (wSDControl & SE_DACL_PROTECTED)
  416. si |= PROTECTED_DACL_SECURITY_INFORMATION;
  417. else
  418. si |= UNPROTECTED_DACL_SECURITY_INFORMATION;
  419. }
  420. if (si & SACL_SECURITY_INFORMATION)
  421. {
  422. if (wSDControl & SE_SACL_PROTECTED)
  423. si |= PROTECTED_SACL_SECURITY_INFORMATION;
  424. else
  425. si |= UNPROTECTED_SACL_SECURITY_INFORMATION;
  426. }
  427. dwErr = SetNamedSecurityInfo((LPTSTR)pszObject,
  428. m_seType,
  429. si,
  430. psidOwner,
  431. psidGroup,
  432. pDacl,
  433. pSacl);
  434. #else // _WIN32_WINNT < 0x0500
  435. PACTRL_ACCESS pAccessList = NULL;
  436. PACTRL_AUDIT pAuditList = NULL;
  437. LPTSTR pOwner = NULL;
  438. LPTSTR pGroup = NULL;
  439. dwErr = ConvertSecurityDescriptorToAccessNamed(pszObject,
  440. m_seType,
  441. pSD,
  442. (si & DACL_SECURITY_INFORMATION) ? &pAccessList : NULL,
  443. (si & SACL_SECURITY_INFORMATION) ? &pAuditList : NULL,
  444. (si & OWNER_SECURITY_INFORMATION) ? &pOwner : NULL,
  445. (si & GROUP_SECURITY_INFORMATION) ? &pGroup : NULL);
  446. if (!dwErr)
  447. {
  448. dwErr = SetNamedSecurityInfoEx(pszObject,
  449. m_seType,
  450. si,
  451. NULL,
  452. pAccessList,
  453. pAuditList,
  454. pOwner,
  455. pGroup,
  456. NULL);
  457. if (pAccessList)
  458. LocalFree(pAccessList);
  459. if (pAuditList)
  460. LocalFree(pAuditList);
  461. if (pOwner)
  462. LocalFree(pOwner);
  463. if (pGroup)
  464. LocalFree(pGroup);
  465. }
  466. #endif // _WIN32_WINNT < 0x0500
  467. TraceLeaveResult(HRESULT_FROM_WIN32(dwErr));
  468. }
  469. OBJECT_TYPE_LIST g_DefaultOTL[] = {
  470. {0, 0, (LPGUID)&GUID_NULL},
  471. };
  472. BOOL SkipLocalGroup(LPCWSTR pszServerName, PSID psid)
  473. {
  474. SID_NAME_USE use;
  475. WCHAR szAccountName[MAX_PATH];
  476. WCHAR szDomainName[MAX_PATH];
  477. DWORD dwAccountLen = MAX_PATH;
  478. DWORD dwDomainLen = MAX_PATH;
  479. if(LookupAccountSid(pszServerName,
  480. psid,
  481. szAccountName,
  482. &dwAccountLen,
  483. szDomainName,
  484. &dwDomainLen,
  485. &use))
  486. {
  487. if(use == SidTypeWellKnownGroup)
  488. return TRUE;
  489. }
  490. //Built In sids have first subauthority of 32 ( s-1-5-32 )
  491. //
  492. if((*(GetSidSubAuthorityCount(psid)) >= 1 ) && (*(GetSidSubAuthority(psid,0)) == 32))
  493. return TRUE;
  494. return FALSE;
  495. }
  496. STDMETHODIMP
  497. CSecurityInformation::GetEffectivePermission(const GUID* pguidObjectType,
  498. PSID pUserSid,
  499. LPCWSTR pszServerName,
  500. PSECURITY_DESCRIPTOR pSD,
  501. POBJECT_TYPE_LIST *ppObjectTypeList,
  502. ULONG *pcObjectTypeListLength,
  503. PACCESS_MASK *ppGrantedAccessList,
  504. ULONG *pcGrantedAccessListLength)
  505. {
  506. AUTHZ_RESOURCE_MANAGER_HANDLE RM = NULL; //Used for access check
  507. AUTHZ_CLIENT_CONTEXT_HANDLE CC = NULL;
  508. LUID luid = {0xdead,0xbeef};
  509. AUTHZ_ACCESS_REQUEST AReq;
  510. AUTHZ_ACCESS_REPLY AReply;
  511. HRESULT hr = S_OK;
  512. DWORD dwFlags;
  513. TraceEnter(TRACE_SI, "CDSSecurityInfo::GetEffectivePermission");
  514. TraceAssert(pUserSid && IsValidSecurityDescriptor(pSD));
  515. TraceAssert(ppObjectTypeList != NULL);
  516. TraceAssert(pcObjectTypeListLength != NULL);
  517. TraceAssert(ppGrantedAccessList != NULL);
  518. TraceAssert(pcGrantedAccessListLength != NULL);
  519. AReq.ObjectTypeList = g_DefaultOTL;
  520. AReq.ObjectTypeListLength = ARRAYSIZE(g_DefaultOTL);
  521. AReply.GrantedAccessMask = NULL;
  522. AReply.Error = NULL;
  523. //Get RM
  524. if( (RM = GetAUTHZ_RM()) == NULL )
  525. ExitGracefully(hr, E_UNEXPECTED, "LocalAlloc failed");
  526. //Initialize the client context
  527. BOOL bSkipLocalGroup = SkipLocalGroup(pszServerName, pUserSid);
  528. if( !AuthzInitializeContextFromSid((m_bIsStandAlone||bSkipLocalGroup)? AUTHZ_SKIP_TOKEN_GROUPS :0,
  529. pUserSid,
  530. RM,
  531. NULL,
  532. luid,
  533. NULL,
  534. &CC) )
  535. {
  536. DWORD dwErr = GetLastError();
  537. ExitGracefully(hr,
  538. HRESULT_FROM_WIN32(dwErr),
  539. "AuthzInitializeContextFromSid Failed");
  540. }
  541. //Do the Access Check
  542. AReq.DesiredAccess = MAXIMUM_ALLOWED;
  543. AReq.PrincipalSelfSid = NULL;
  544. AReq.OptionalArguments = NULL;
  545. AReply.ResultListLength = AReq.ObjectTypeListLength;
  546. AReply.SaclEvaluationResults = NULL;
  547. if( (AReply.GrantedAccessMask = (PACCESS_MASK)LocalAlloc(LPTR, sizeof(ACCESS_MASK)*AReply.ResultListLength) ) == NULL )
  548. ExitGracefully(hr, E_OUTOFMEMORY, "Unable to LocalAlloc");
  549. if( (AReply.Error = (PDWORD)LocalAlloc(LPTR, sizeof(DWORD)*AReply.ResultListLength)) == NULL )
  550. ExitGracefully(hr, E_OUTOFMEMORY, "Unable to LocalAlloc");
  551. if( !AuthzAccessCheck(0,
  552. CC,
  553. &AReq,
  554. NULL,
  555. pSD,
  556. NULL,
  557. 0,
  558. &AReply,
  559. NULL) )
  560. {
  561. DWORD dwErr = GetLastError();
  562. ExitGracefully(hr,
  563. HRESULT_FROM_WIN32(dwErr),
  564. "AuthzAccessCheck Failed");
  565. }
  566. exit_gracefully:
  567. if(CC)
  568. AuthzFreeContext(CC);
  569. if(!SUCCEEDED(hr))
  570. {
  571. if(AReply.GrantedAccessMask)
  572. LocalFree(AReply.GrantedAccessMask);
  573. if(AReply.Error)
  574. LocalFree(AReply.Error);
  575. AReply.Error = NULL;
  576. AReply.GrantedAccessMask = NULL;
  577. }
  578. else
  579. {
  580. *ppObjectTypeList = AReq.ObjectTypeList;
  581. *pcObjectTypeListLength = AReq.ObjectTypeListLength;
  582. *ppGrantedAccessList = AReply.GrantedAccessMask;
  583. *pcGrantedAccessListLength = AReq.ObjectTypeListLength;
  584. }
  585. TraceLeaveResult(hr);
  586. }