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.

800 lines
23 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. aclmgmt.cpp
  5. Abstract:
  6. Routines to manage access control lists
  7. Geoffrey Guo (geoffguo) 26-Apr-2002 Created
  8. Revision History:
  9. <alias> <date> <comments>
  10. --*/
  11. #include "clmt.h"
  12. #define STRSAFE_LIB
  13. #include <strsafe.h>
  14. DWORD ChangeOwner (
  15. LPTSTR lpObjectName,
  16. SE_OBJECT_TYPE ObjectType)
  17. {
  18. DWORD dwRet = ERROR_SUCCESS;
  19. PSID psidAdministrators;
  20. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  21. SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION;
  22. if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
  23. SECURITY_BUILTIN_DOMAIN_RID,
  24. DOMAIN_ALIAS_RID_ADMINS,
  25. 0, 0, 0, 0, 0, 0,
  26. &psidAdministrators))
  27. {
  28. dwRet = GetLastError();
  29. goto Exit;
  30. }
  31. EnablePrivilege(SE_TAKE_OWNERSHIP_NAME,TRUE);
  32. si |= SI_OWNER_RECURSE;
  33. dwRet = SetNamedSecurityInfo(lpObjectName,
  34. ObjectType,
  35. si,
  36. psidAdministrators,
  37. NULL,
  38. NULL,
  39. NULL);
  40. EnablePrivilege(SE_TAKE_OWNERSHIP_NAME,FALSE);
  41. FreeSid(psidAdministrators);
  42. Exit:
  43. return dwRet;
  44. }
  45. //-----------------------------------------------------------------------//
  46. //
  47. // CopyACL: Copy ACL
  48. //
  49. // OldACL: Pointer to source Access Control List
  50. // NewACL: Pointer to destination Access Control List
  51. //-----------------------------------------------------------------------//
  52. DWORD
  53. CopyACL (
  54. PACL OldACL,
  55. PACL NewACL)
  56. {
  57. ACL_SIZE_INFORMATION aclSizeInfo;
  58. LPVOID ace;
  59. ACE_HEADER *aceHeader;
  60. ULONG i;
  61. GetAclInformation (OldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (aclSizeInfo), AclSizeInformation);
  62. //
  63. // Copy all of the ACEs to the new ACL
  64. //
  65. for (i = 0; i < aclSizeInfo.AceCount; i++)
  66. {
  67. //
  68. // Get the ACE and header info
  69. //
  70. if (!GetAce (OldACL, i, &ace))
  71. return GetLastError();
  72. aceHeader = (ACE_HEADER *) ace;
  73. //
  74. // Add the ACE to the new list
  75. //
  76. if (!AddAce (NewACL, ACL_REVISION, 0xffffffff, ace, aceHeader->AceSize))
  77. return GetLastError();
  78. }
  79. return ERROR_SUCCESS;
  80. }
  81. //-----------------------------------------------------------------------//
  82. //
  83. // AddAccessAllowedACEToACL: Add Administrator Allowed ACE to ACL
  84. //
  85. // Acl: Pointer to Access Control List
  86. // PermissionMask: Permission will be set for new ACE
  87. //-----------------------------------------------------------------------//
  88. DWORD
  89. AddAccessAllowedACEToACL (
  90. PACL *Acl,
  91. DWORD PermissionMask)
  92. {
  93. ACL_SIZE_INFORMATION aclSizeInfo;
  94. int aclSize;
  95. DWORD dwRet = ERROR_SUCCESS;
  96. USHORT AceSize;
  97. PSID psidAdministrators;
  98. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  99. PACL oldACL, newACL;
  100. ACCESS_ALLOWED_ACE *pAllowedAce;
  101. oldACL = *Acl;
  102. if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
  103. SECURITY_BUILTIN_DOMAIN_RID,
  104. DOMAIN_ALIAS_RID_ADMINS,
  105. 0, 0, 0, 0, 0, 0,
  106. &psidAdministrators))
  107. {
  108. dwRet = GetLastError();
  109. goto Exit;
  110. }
  111. GetAclInformation (oldACL, (LPVOID) &aclSizeInfo, (DWORD) sizeof (ACL_SIZE_INFORMATION), AclSizeInformation);
  112. aclSize = aclSizeInfo.AclBytesInUse +
  113. sizeof (ACL) + sizeof (ACCESS_ALLOWED_ACE) +
  114. GetLengthSid (psidAdministrators) - sizeof (DWORD);
  115. newACL = (PACL) calloc(aclSize, 1);
  116. if (!newACL)
  117. {
  118. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  119. goto Exit1;
  120. }
  121. if (!InitializeAcl (newACL, aclSize, ACL_REVISION))
  122. {
  123. dwRet = GetLastError();
  124. free (newACL);
  125. goto Exit1;
  126. }
  127. dwRet = CopyACL (oldACL, newACL);
  128. if (dwRet != ERROR_SUCCESS)
  129. {
  130. free (newACL);
  131. goto Exit1;
  132. }
  133. AceSize = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + (USHORT)GetLengthSid(psidAdministrators);
  134. pAllowedAce = (ACCESS_ALLOWED_ACE *)calloc(AceSize, 1);
  135. if (!(pAllowedAce))
  136. {
  137. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  138. goto Exit1;
  139. }
  140. pAllowedAce->Header.AceFlags = 0;
  141. pAllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  142. pAllowedAce->Header.AceSize = AceSize;
  143. pAllowedAce->Mask = PermissionMask;
  144. CopySid(GetLengthSid(psidAdministrators), &(pAllowedAce->SidStart), psidAdministrators);
  145. if (!AddAce (newACL, ACL_REVISION, 0, pAllowedAce, AceSize))
  146. {
  147. dwRet = GetLastError();
  148. free (newACL);
  149. goto Exit1;
  150. }
  151. *Acl = newACL;
  152. Exit1:
  153. FreeSid(psidAdministrators);
  154. Exit:
  155. return dwRet;
  156. }
  157. //-----------------------------------------------------------------------//
  158. //
  159. // RestoreACE: Restore denied ACE
  160. //
  161. // pACE: Pointer to source Access Control Entry
  162. // lpOnjectName: Pointer to the object name
  163. //-----------------------------------------------------------------------//
  164. DWORD
  165. RestoreACE (
  166. PACL *ppAcl,
  167. LPTSTR lpObjectName)
  168. {
  169. DWORD dwRet = ERROR_INVALID_PARAMETER;
  170. DWORD dwLen;
  171. PACL newACL;
  172. LPDENIED_ACE_LIST pList;
  173. if (!*ppAcl)
  174. goto Exit;
  175. pList = g_DeniedACEList;
  176. if (pList)
  177. {
  178. do
  179. {
  180. if (lstrcmp(lpObjectName, pList->lpObjectName) == 0)
  181. {
  182. newACL = (PACL) calloc(pList->dwAclSize, 1);
  183. if (!newACL)
  184. {
  185. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  186. goto Exit;
  187. }
  188. if (!InitializeAcl (newACL, pList->dwAclSize, ACL_REVISION))
  189. {
  190. free(newACL);
  191. dwRet = GetLastError();
  192. goto Exit;
  193. }
  194. dwRet = CopyACL (*ppAcl, newACL);
  195. if (dwRet != ERROR_SUCCESS)
  196. {
  197. free(newACL);
  198. dwRet = GetLastError();
  199. goto Exit;
  200. }
  201. if (!AddAce (newACL,
  202. ACL_REVISION,
  203. 0,
  204. pList->pace,
  205. ((PACE_HEADER)(pList->pace))->AceSize))
  206. {
  207. dwRet = GetLastError();
  208. goto Exit;
  209. }
  210. else
  211. DPF(REGmsg, L"Restore denied ACE to ACL: ObjectName=%s", lpObjectName);
  212. if (pList->previous)
  213. pList->previous->next = pList->next;
  214. else
  215. g_DeniedACEList = pList->next;
  216. if (pList->next)
  217. pList->next->previous = pList->previous;
  218. *ppAcl = newACL;
  219. free (pList->lpObjectName);
  220. free (pList->pace);
  221. free (pList);
  222. break;
  223. }
  224. pList = pList->next;
  225. } while (pList->next);
  226. }
  227. dwRet = ERROR_SUCCESS;
  228. Exit:
  229. return dwRet;
  230. }
  231. //-----------------------------------------------------------------------//
  232. //
  233. // RemoveACEFromACL: Remove Administrator ACE from ACL
  234. //
  235. // Acl: Pointer to Access Control List
  236. //-----------------------------------------------------------------------//
  237. DWORD
  238. RemoveACEFromACL (
  239. PACL Acl)
  240. {
  241. ACL_SIZE_INFORMATION aclSizeInfo;
  242. ULONG i;
  243. LPVOID ace;
  244. ACCESS_ALLOWED_ACE *accessAllowedAce;
  245. ACCESS_DENIED_ACE *accessDeniedAce;
  246. SYSTEM_AUDIT_ACE *systemAuditAce;
  247. PSID psidAdministrators;
  248. DWORD returnValue;
  249. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  250. ACE_HEADER *aceHeader;
  251. if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
  252. SECURITY_BUILTIN_DOMAIN_RID,
  253. DOMAIN_ALIAS_RID_ADMINS,
  254. 0, 0, 0, 0, 0, 0,
  255. &psidAdministrators))
  256. return GetLastError();
  257. GetAclInformation (Acl, (LPVOID) &aclSizeInfo, (DWORD) sizeof (ACL_SIZE_INFORMATION), AclSizeInformation);
  258. for (i = 0; i < aclSizeInfo.AceCount; i++)
  259. {
  260. if (!GetAce (Acl, i, &ace))
  261. {
  262. FreeSid(psidAdministrators);
  263. return GetLastError();
  264. }
  265. aceHeader = (ACE_HEADER *) ace;
  266. if (aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE)
  267. {
  268. accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  269. if (EqualSid (psidAdministrators, (PSID) &accessAllowedAce->SidStart))
  270. {
  271. DeleteAce (Acl, i);
  272. FreeSid(psidAdministrators);
  273. return ERROR_SUCCESS;
  274. }
  275. }
  276. }
  277. FreeSid(psidAdministrators);
  278. return ERROR_NO_MORE_ITEMS;
  279. }
  280. //-----------------------------------------------------------------------//
  281. //
  282. // AddACE2List: Add ACE to the list
  283. //
  284. // pACE: Pointer to source Access Control Entry
  285. // lpOnjectName: Pointer to the object name
  286. //-----------------------------------------------------------------------//
  287. DWORD
  288. AddACE2List (
  289. ACCESS_DENIED_ACE *pACE,
  290. LPTSTR lpObjectName,
  291. DWORD dwAclSize)
  292. {
  293. HRESULT hr;
  294. DWORD dwRet = ERROR_SUCCESS;
  295. DWORD dwLen;
  296. LPDENIED_ACE_LIST pList1;
  297. LPDENIED_ACE_LIST pList2;
  298. if (!pACE)
  299. {
  300. dwRet = ERROR_INVALID_PARAMETER;
  301. goto Exit;
  302. }
  303. pList1 = (LPDENIED_ACE_LIST)calloc (sizeof(DENIED_ACE_LIST), 1);
  304. if (!pList1)
  305. {
  306. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  307. goto Exit;
  308. }
  309. pList1->next = NULL;
  310. pList1->dwAclSize = dwAclSize;
  311. pList1->pace = (ACCESS_DENIED_ACE *)calloc(((PACE_HEADER)pACE)->AceSize, 1);
  312. if (!(pList1->pace))
  313. {
  314. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  315. free (pList1);
  316. goto Exit;
  317. }
  318. memcpy (pList1->pace, pACE, ((PACE_HEADER)pACE)->AceSize);
  319. dwLen = lstrlen(lpObjectName)+1;
  320. pList1->lpObjectName = (LPTSTR)calloc (dwLen, sizeof(TCHAR));
  321. if (!(pList1->lpObjectName))
  322. {
  323. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  324. free (pList1);
  325. free (pList1->pace);
  326. goto Exit;
  327. }
  328. hr = StringCchCopy (pList1->lpObjectName, dwLen, lpObjectName);
  329. if (hr != S_OK)
  330. {
  331. dwRet = HRESULT_CODE(hr);
  332. free (pList1);
  333. free (pList1->pace);
  334. goto Exit;
  335. }
  336. pList2 = g_DeniedACEList;
  337. if (pList2)
  338. {
  339. while (pList2->next)
  340. pList2 = pList2->next;
  341. pList2->next = pList1;
  342. pList1->previous = pList2;
  343. }
  344. else
  345. {
  346. g_DeniedACEList = pList1;
  347. pList1->previous = NULL;
  348. }
  349. Exit:
  350. return dwRet;
  351. }
  352. //-----------------------------------------------------------------------//
  353. //
  354. // RemoveDeniedACEFromACL: Remove Denied ACE from ACL
  355. //
  356. // Acl: Pointer to Access Control List
  357. // lpOnjectName: Pointer to the object name
  358. //-----------------------------------------------------------------------//
  359. DWORD
  360. RemoveDeniedACEFromACL (
  361. PACL Acl,
  362. LPTSTR lpObjectName)
  363. {
  364. ACL_SIZE_INFORMATION aclSizeInfo;
  365. ULONG i;
  366. ACCESS_DENIED_ACE *accessDeniedAce;
  367. LPVOID ace;
  368. DWORD dwRet = ERROR_SUCCESS;
  369. ACE_HEADER *aceHeader;
  370. GetAclInformation (Acl, (LPVOID) &aclSizeInfo, (DWORD) sizeof (ACL_SIZE_INFORMATION), AclSizeInformation);
  371. for (i = 0; i < aclSizeInfo.AceCount; i++)
  372. {
  373. if (!GetAce (Acl, i, &ace))
  374. {
  375. dwRet = GetLastError();
  376. if (dwRet == ERROR_NO_MORE_ITEMS)
  377. dwRet = ERROR_SUCCESS;
  378. }
  379. aceHeader = (ACE_HEADER *) ace;
  380. if (aceHeader->AceType == ACCESS_DENIED_ACE_TYPE)
  381. {
  382. accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  383. AddACE2List (accessDeniedAce, lpObjectName, aclSizeInfo.AclBytesInUse);
  384. if (!DeleteAce (Acl, i))
  385. dwRet = GetLastError();
  386. else
  387. DPF(REGmsg, L"Remove denied ACE from ACL: ObjectName=%s", lpObjectName);
  388. break;
  389. }
  390. }
  391. return dwRet;
  392. }
  393. //-----------------------------------------------------------------------//
  394. //
  395. // AdjustObjectSecurity: Add full control ACE for local administrator.
  396. //
  397. // lpObjectName: Object Name
  398. // ObjectType: Object Type
  399. // ppOldSidOwner: Current object owner
  400. // bSetOrRestore: True --- Add ACE, FALSE --- Remove ACE
  401. //-----------------------------------------------------------------------//
  402. DWORD AdjustObjectSecurity (
  403. LPTSTR lpObjectName,
  404. SE_OBJECT_TYPE ObjectType,
  405. BOOL bSetOrRestore)
  406. {
  407. DWORD dwErr;
  408. HRESULT hr;
  409. PSID psid = NULL;
  410. PSECURITY_DESCRIPTOR pSD;
  411. PACL pDacl = NULL;
  412. PACL psidDacl = NULL;
  413. SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
  414. dwErr = GetNamedSecurityInfo(lpObjectName,
  415. ObjectType,
  416. secInfo,
  417. NULL,
  418. NULL,
  419. &psidDacl,
  420. NULL,
  421. &pSD);
  422. if (dwErr == ERROR_ACCESS_DENIED)
  423. {
  424. TCHAR szString[MAX_PATH*2];
  425. TCHAR szCaption[MAX_PATH];
  426. LoadString((HINSTANCE)g_hInstDll, IDS_OWNERSHIP, szCaption, MAX_PATH-1);
  427. hr = StringCchPrintf(szString, MAX_PATH*2-1, szCaption, lpObjectName);
  428. LoadString((HINSTANCE)g_hInstDll, IDS_MAIN_TITLE, szCaption, MAX_PATH-1);
  429. if (SUCCEEDED(hr) && MessageBox(GetConsoleWindow(), szString, szCaption, MB_YESNO) == IDYES)
  430. {
  431. if (ChangeOwner(lpObjectName, ObjectType) == ERROR_SUCCESS)
  432. {
  433. DPF(REGmsg, L"Administrator takes over the ownership: ObjectName=%s", lpObjectName);
  434. dwErr = GetNamedSecurityInfo(lpObjectName,
  435. ObjectType,
  436. secInfo,
  437. NULL,
  438. NULL,
  439. &psidDacl,
  440. NULL,
  441. &pSD);
  442. }
  443. }
  444. }
  445. if (dwErr == ERROR_SUCCESS)
  446. {
  447. pDacl = psidDacl;
  448. if (bSetOrRestore)
  449. {
  450. dwErr = AddAccessAllowedACEToACL (&pDacl, GENERIC_ALL | SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL);
  451. if (dwErr == ERROR_SUCCESS)
  452. DPF(REGmsg, L"Add Administrator with full control to ACL: ObjectName=%s", lpObjectName);
  453. else
  454. DPF(REGerr, L"Fails to add Administrator with full control to ACL: ObjectName=%s", lpObjectName);
  455. }
  456. else
  457. {
  458. dwErr = RemoveACEFromACL(pDacl);
  459. if (dwErr == ERROR_SUCCESS)
  460. DPF(REGmsg, L"Remove Administrator with full control from ACL: ObjectName=%s", lpObjectName);
  461. else
  462. DPF(REGerr, L"Fails to remove Administrator with full control from ACL: ObjectName=%s", lpObjectName);
  463. }
  464. if (dwErr == ERROR_SUCCESS)
  465. {
  466. dwErr = SetNamedSecurityInfo(lpObjectName,
  467. ObjectType,
  468. secInfo,
  469. NULL,
  470. NULL,
  471. pDacl,
  472. NULL);
  473. }
  474. if (psidDacl != pDacl && pDacl)
  475. free(pDacl);
  476. LocalFree(pSD);
  477. }
  478. return dwErr;
  479. }
  480. #define ACCESS_STATUS_ALLOWED 0
  481. #define ACCESS_STATUS_DENIED 1
  482. #define ACCESS_STATUS_NOTPRESENT 2
  483. HRESULT GetObjectAccessStatus(
  484. LPTSTR lpObjectName,
  485. SE_OBJECT_TYPE ObjectType,
  486. PSID pOwnerSid,
  487. PDWORD pdwStatus)
  488. {
  489. DWORD dwErr;
  490. HRESULT hr;
  491. PSECURITY_DESCRIPTOR pSD = NULL;
  492. PACL psidDacl = NULL;
  493. SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
  494. ACL_SIZE_INFORMATION aclSizeInfo;
  495. LPVOID ace;
  496. ACE_HEADER *aceHeader;
  497. ULONG i;
  498. ACCESS_MASK dwAllowMask,dwDeniedMask;
  499. if (!lpObjectName || !pOwnerSid || !pdwStatus)
  500. {
  501. hr = E_INVALIDARG;
  502. goto cleanup;
  503. }
  504. dwErr = GetNamedSecurityInfo(lpObjectName,
  505. ObjectType,
  506. secInfo,
  507. NULL,
  508. NULL,
  509. &psidDacl,
  510. NULL,
  511. &pSD);
  512. if (dwErr != ERROR_SUCCESS)
  513. {
  514. hr = HRESULT_FROM_WIN32(dwErr);
  515. goto cleanup;
  516. }
  517. if (!psidDacl)
  518. {
  519. // in FS, this must be FAT/FAT32
  520. hr = S_OK;
  521. *pdwStatus = ACCESS_STATUS_ALLOWED;
  522. goto cleanup;
  523. }
  524. if (!GetAclInformation (psidDacl,
  525. (LPVOID) &aclSizeInfo,
  526. (DWORD) sizeof (ACL_SIZE_INFORMATION),
  527. AclSizeInformation))
  528. {
  529. hr = HRESULT_FROM_WIN32(GetLastError());
  530. goto cleanup;
  531. }
  532. *pdwStatus = ACCESS_STATUS_NOTPRESENT;
  533. dwAllowMask = dwDeniedMask = 0;
  534. for (i = 0; i < aclSizeInfo.AceCount; i++)
  535. {
  536. ACCESS_ALLOWED_ACE *accessAllowedAce;
  537. ACCESS_DENIED_ACE *accessDeniedAce;
  538. PSID pAclSid;
  539. if (!GetAce (psidDacl, i, &ace))
  540. {
  541. hr = HRESULT_FROM_WIN32(GetLastError());
  542. goto cleanup;
  543. }
  544. aceHeader = (ACE_HEADER *) ace;
  545. switch (aceHeader->AceType)
  546. {
  547. case ACCESS_ALLOWED_ACE_TYPE:
  548. accessAllowedAce = (ACCESS_ALLOWED_ACE *) ace;
  549. pAclSid = (PSID) &accessAllowedAce->SidStart;
  550. if (EqualSid (pOwnerSid, pAclSid))
  551. {
  552. dwAllowMask |= accessAllowedAce->Mask;
  553. }
  554. break;
  555. case ACCESS_DENIED_ACE_TYPE:
  556. accessDeniedAce = (ACCESS_DENIED_ACE *) ace;
  557. pAclSid = (PSID) &accessDeniedAce->SidStart;
  558. if (EqualSid (pOwnerSid, pAclSid))
  559. {
  560. dwDeniedMask |= accessDeniedAce->Mask;
  561. }
  562. break;
  563. default:
  564. continue;
  565. }
  566. }
  567. GENERIC_MAPPING gm;
  568. gm.GenericRead = FILE_GENERIC_READ ;
  569. gm.GenericWrite = FILE_GENERIC_WRITE ;
  570. gm.GenericExecute = FILE_GENERIC_EXECUTE ;
  571. gm.GenericAll = FILE_ALL_ACCESS ;
  572. DWORD dwExpected = GENERIC_ALL|GENERIC_WRITE|GENERIC_READ;
  573. MapGenericMask(&dwExpected,&gm);
  574. if (AreAnyAccessesGranted(dwDeniedMask,dwExpected))
  575. {
  576. *pdwStatus = ACCESS_STATUS_DENIED;
  577. hr = S_OK;
  578. goto cleanup;
  579. }
  580. dwExpected = GENERIC_ALL;
  581. MapGenericMask(&dwExpected,&gm);
  582. if (AreAllAccessesGranted(dwAllowMask,dwExpected))
  583. {
  584. *pdwStatus = ACCESS_STATUS_ALLOWED;
  585. hr = S_OK;
  586. goto cleanup;
  587. }
  588. dwExpected = GENERIC_WRITE|GENERIC_READ;
  589. MapGenericMask(&dwExpected,&gm);
  590. if (AreAllAccessesGranted(dwAllowMask,dwExpected))
  591. {
  592. *pdwStatus = ACCESS_STATUS_ALLOWED;
  593. hr = S_OK;
  594. goto cleanup;
  595. }
  596. *pdwStatus = ACCESS_STATUS_NOTPRESENT;
  597. hr = S_OK;
  598. cleanup:
  599. if (pSD)
  600. {
  601. LocalFree(pSD);
  602. }
  603. return hr;
  604. }
  605. HRESULT IsObjectAccessiablebyLocalSys(
  606. LPTSTR lpObjectName,
  607. SE_OBJECT_TYPE ObjectType,
  608. PBOOL pbCanAccess)
  609. {
  610. HRESULT hr = S_OK;
  611. PSID pUserSid = NULL;
  612. DWORD dwLocal,dwEveryone,dwAdmins;
  613. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  614. *pbCanAccess = FALSE;
  615. //Local System
  616. if (!ConvertStringSidToSid(TEXT("S-1-5-18"),&pUserSid))
  617. {
  618. hr = HRESULT_FROM_WIN32(GetLastError());
  619. pUserSid = NULL;
  620. goto cleanup;
  621. }
  622. hr = GetObjectAccessStatus(lpObjectName,ObjectType,pUserSid,&dwLocal);
  623. if (hr != S_OK)
  624. {
  625. goto cleanup;
  626. }
  627. if (dwLocal == ACCESS_STATUS_DENIED)
  628. {
  629. *pbCanAccess = FALSE;
  630. goto cleanup;
  631. }
  632. LocalFree(pUserSid);
  633. pUserSid = NULL;
  634. //Everyone
  635. if (!ConvertStringSidToSid(TEXT("S-1-1-0"),&pUserSid))
  636. {
  637. hr = HRESULT_FROM_WIN32(GetLastError());
  638. pUserSid = NULL;
  639. goto cleanup;
  640. }
  641. hr = GetObjectAccessStatus(lpObjectName,ObjectType,pUserSid,&dwEveryone);
  642. if (hr != S_OK)
  643. {
  644. goto cleanup;
  645. }
  646. if (dwEveryone == ACCESS_STATUS_DENIED)
  647. {
  648. *pbCanAccess = FALSE;
  649. goto cleanup;
  650. }
  651. LocalFree(pUserSid);
  652. pUserSid = NULL;
  653. //Local Admins
  654. if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
  655. SECURITY_BUILTIN_DOMAIN_RID,
  656. DOMAIN_ALIAS_RID_ADMINS,
  657. 0, 0, 0, 0, 0, 0,
  658. &pUserSid))
  659. {
  660. hr = HRESULT_FROM_WIN32(GetLastError());
  661. pUserSid = NULL;
  662. goto cleanup;
  663. }
  664. hr = GetObjectAccessStatus(lpObjectName,ObjectType,pUserSid,&dwAdmins);
  665. if (hr != S_OK)
  666. {
  667. goto cleanup;
  668. }
  669. if (dwAdmins == ACCESS_STATUS_DENIED)
  670. {
  671. *pbCanAccess = FALSE;
  672. goto cleanup;
  673. }
  674. LocalFree(pUserSid);
  675. pUserSid = NULL;
  676. if (dwEveryone == ACCESS_STATUS_ALLOWED)
  677. {
  678. *pbCanAccess = TRUE;
  679. }
  680. else if ( (dwAdmins ==ACCESS_STATUS_ALLOWED) && (dwLocal ==ACCESS_STATUS_ALLOWED) )
  681. {
  682. *pbCanAccess = TRUE;
  683. }
  684. else
  685. {
  686. *pbCanAccess = FALSE;
  687. }
  688. hr = S_OK;
  689. cleanup:
  690. if (pUserSid)
  691. {
  692. LocalFree(pUserSid);
  693. }
  694. return hr;
  695. }