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.

1617 lines
49 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. regsec.cpp
  5. Abstract:
  6. ISecurityInformation implementation for Registry Key
  7. Author:
  8. Hitesh Raigandhi (raigah) May-1999
  9. Revision History:
  10. --*/
  11. //Include Files:
  12. #include "wchar.h"
  13. #include "regsec.h"
  14. #include "regresid.h"
  15. #include "assert.h"
  16. // ISecurityInformation interface implementation
  17. EXTERN_C const GUID IID_ISecurityInformation ;
  18. // = { 0x965fc360, 0x16ff, 0x11d0, 0x91, 0xcb, 0x0, 0xaa, 0x0, 0xbb, 0xb7, 0x23 };
  19. //The Following array defines the permission names for Registry Key Objects
  20. SI_ACCESS siKeyAccesses[] =
  21. {
  22. { NULL,
  23. KEY_ALL_ACCESS,
  24. MAKEINTRESOURCE(IDS_SEC_EDITOR_FULL_ACCESS),
  25. SI_ACCESS_GENERAL | CONTAINER_INHERIT_ACE | SI_ACCESS_SPECIFIC },
  26. { NULL,
  27. KEY_QUERY_VALUE,
  28. MAKEINTRESOURCE(IDS_SEC_EDITOR_QUERY_VALUE),
  29. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  30. { NULL,
  31. KEY_SET_VALUE,
  32. MAKEINTRESOURCE(IDS_SEC_EDITOR_SET_VALUE),
  33. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  34. { NULL,
  35. KEY_CREATE_SUB_KEY,
  36. MAKEINTRESOURCE(IDS_SEC_EDITOR_CREATE_SUBKEY),
  37. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  38. { NULL,
  39. KEY_ENUMERATE_SUB_KEYS,
  40. MAKEINTRESOURCE(IDS_SEC_EDITOR_ENUM_SUBKEYS),
  41. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  42. { NULL,
  43. KEY_NOTIFY,
  44. MAKEINTRESOURCE(IDS_SEC_EDITOR_NOTIFY),
  45. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  46. { NULL,
  47. KEY_CREATE_LINK,
  48. MAKEINTRESOURCE(IDS_SEC_EDITOR_CREATE_LINK),
  49. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  50. { NULL,
  51. 0x00010000, /* DELETE, */
  52. MAKEINTRESOURCE(IDS_SEC_EDITOR_DELETE),
  53. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  54. { NULL,
  55. WRITE_DAC,
  56. MAKEINTRESOURCE(IDS_SEC_EDITOR_WRITE_DAC),
  57. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  58. { NULL,
  59. WRITE_OWNER,
  60. MAKEINTRESOURCE(IDS_SEC_EDITOR_WRITE_OWNER),
  61. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  62. { NULL,
  63. READ_CONTROL,
  64. MAKEINTRESOURCE(IDS_SEC_EDITOR_READ_CONTROL),
  65. SI_ACCESS_SPECIFIC | CONTAINER_INHERIT_ACE },
  66. { NULL,
  67. KEY_READ,
  68. MAKEINTRESOURCE(IDS_SEC_EDITOR_READ),
  69. SI_ACCESS_GENERAL | CONTAINER_INHERIT_ACE },
  70. };
  71. // The following array defines the inheritance types for Registry.
  72. //
  73. //
  74. // For Keys, objects and containers are the same, so no need for OBJECT_INHERIT_ACE
  75. //
  76. SI_INHERIT_TYPE siKeyInheritTypes[] =
  77. {
  78. NULL, 0, MAKEINTRESOURCE(IDS_KEY_FOLDER),
  79. NULL, CONTAINER_INHERIT_ACE, MAKEINTRESOURCE(IDS_KEY_FOLDER_SUBFOLDER),
  80. NULL, INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, MAKEINTRESOURCE(IDS_KEY_SUBFOLDER_ONLY)
  81. };
  82. #define iKeyDefAccess 10 // index of value in array siKeyAccesses
  83. #ifndef ARRAYSIZE
  84. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  85. #endif
  86. PWSTR _PredefinedKeyName[] = { L"CLASSES_ROOT",
  87. L"CURRENT_USER",
  88. L"MACHINE",
  89. L"USERS",
  90. L"CONFIG" };
  91. //CKeySecurityInformation Functions
  92. HRESULT
  93. CKeySecurityInformation::Initialize( LPCWSTR strKeyName,
  94. LPCWSTR strParentName,
  95. LPCWSTR strMachineName,
  96. LPCWSTR strPageTitle,
  97. BOOL bRemote,
  98. PREDEFINE_KEY PredefinedKey,
  99. BOOL bReadOnly,
  100. HWND hWnd)
  101. {
  102. if( strParentName )
  103. if( !strKeyName )
  104. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  105. if( NULL == strMachineName )
  106. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  107. if( NULL == hWnd )
  108. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  109. if( NULL == strPageTitle )
  110. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  111. AuthzInitializeResourceManager(NULL,
  112. NULL,
  113. NULL,
  114. NULL,
  115. 0,
  116. &m_ResourceManager );
  117. HRESULT hr = S_OK;
  118. m_strKeyName = strKeyName;
  119. m_strParentName = strParentName;
  120. m_strMachineName = strMachineName;
  121. m_strPageTitle = strPageTitle;
  122. m_bRemote = bRemote;
  123. m_PredefinedKey = PredefinedKey;
  124. m_bReadOnly = bReadOnly;
  125. m_hWnd = hWnd;
  126. m_dwFlags = SI_EDIT_ALL | SI_ADVANCED | SI_CONTAINER
  127. | SI_RESET_DACL_TREE | SI_RESET_SACL_TREE
  128. | SI_OWNER_RECURSE | SI_PAGE_TITLE | SI_EDIT_EFFECTIVE;
  129. if( m_bReadOnly )
  130. m_dwFlags |= SI_READONLY | SI_OWNER_READONLY ;
  131. //Set Handle to Predfined key
  132. if( S_OK != ( hr = SetHandleToPredefinedKey() ) )
  133. return hr;
  134. //Set CompleteName
  135. if( S_OK != ( hr = SetCompleteName() ) )
  136. return hr;
  137. return S_OK;
  138. }
  139. CKeySecurityInformation::~CKeySecurityInformation()
  140. {
  141. if( m_strCompleteName )
  142. LocalFree( m_strCompleteName );
  143. //Close Handle to Remote Registry if it was successfully opened.
  144. if( m_bRemote && m_hkeyPredefinedKey )
  145. RegCloseKey(m_hkeyPredefinedKey);
  146. AuthzFreeResourceManager(m_ResourceManager);
  147. }
  148. //Sets the complete name in Format:
  149. // "\\machine_name\Predefined_keyName\regkey_path
  150. HRESULT
  151. CKeySecurityInformation::SetCompleteName()
  152. {
  153. UINT len = 0;
  154. PWSTR pstrCompleteName;
  155. if( m_bRemote )
  156. {
  157. len += wcslen( m_strMachineName );
  158. len++;
  159. }
  160. len += wcslen(_PredefinedKeyName[ m_PredefinedKey]);
  161. len++;
  162. if( m_strParentName )
  163. {
  164. len += wcslen(m_strParentName);
  165. len++;
  166. }
  167. if( m_strKeyName )
  168. {
  169. len += wcslen(m_strKeyName);
  170. len++;
  171. }
  172. len++; //Terminating null
  173. pstrCompleteName = (PWSTR)LocalAlloc(LPTR, len * sizeof(WCHAR));
  174. if( pstrCompleteName == NULL )
  175. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  176. if( m_bRemote )
  177. {
  178. wcscpy(pstrCompleteName,m_strMachineName);
  179. wcscat(pstrCompleteName, L"\\");
  180. }
  181. wcscat(pstrCompleteName,_PredefinedKeyName[ m_PredefinedKey]);
  182. wcscat(pstrCompleteName,L"\\");
  183. if(m_strParentName)
  184. {
  185. wcscat(pstrCompleteName,m_strParentName);
  186. wcscat(pstrCompleteName,L"\\");
  187. }
  188. if(m_strKeyName)
  189. {
  190. wcscat(pstrCompleteName, m_strKeyName );
  191. wcscat(pstrCompleteName,L"\\");
  192. }
  193. m_strCompleteName = pstrCompleteName;
  194. return S_OK;
  195. }
  196. //Doesn't have Predefined key name attached
  197. //Caller must LocalFree
  198. LPCWSTR
  199. CKeySecurityInformation::GetCompleteName1()
  200. {
  201. UINT len = 0;
  202. PWSTR pstrCompleteName;
  203. if( m_strParentName )
  204. {
  205. len += wcslen(m_strParentName);
  206. len++;
  207. }
  208. if( m_strKeyName )
  209. {
  210. len += wcslen(m_strKeyName);
  211. len++;
  212. }
  213. len++; //Terminating null
  214. pstrCompleteName = (PWSTR)LocalAlloc(LPTR, len * sizeof(WCHAR));
  215. if( pstrCompleteName == NULL )
  216. return NULL;
  217. if(m_strParentName)
  218. {
  219. wcscpy(pstrCompleteName,m_strParentName);
  220. wcscat(pstrCompleteName,L"\\");
  221. }
  222. if(m_strKeyName)
  223. {
  224. wcscat(pstrCompleteName, m_strKeyName );
  225. wcscat(pstrCompleteName,L"\\");
  226. }
  227. return pstrCompleteName;
  228. }
  229. HRESULT
  230. CKeySecurityInformation::SetHandleToPredefinedKey()
  231. {
  232. DWORD dwErr;
  233. HRESULT hr = S_OK;
  234. if( !m_bRemote ) {
  235. switch ( m_PredefinedKey ){
  236. case PREDEFINE_KEY_CLASSES_ROOT:
  237. m_hkeyPredefinedKey= HKEY_CLASSES_ROOT;
  238. break;
  239. case PREDEFINE_KEY_CURRENT_USER:
  240. m_hkeyPredefinedKey = HKEY_CURRENT_USER;
  241. break;
  242. case PREDEFINE_KEY_LOCAL_MACHINE :
  243. m_hkeyPredefinedKey = HKEY_LOCAL_MACHINE;
  244. break;
  245. case PREDEFINE_KEY_USERS:
  246. m_hkeyPredefinedKey = HKEY_USERS;
  247. break;
  248. case PREDEFINE_KEY_CURRENT_CONFIG :
  249. m_hkeyPredefinedKey = HKEY_CURRENT_CONFIG;
  250. break;
  251. default:
  252. //assert(false);
  253. break;
  254. }
  255. }
  256. else { //IsRemoteRegistry
  257. switch ( m_PredefinedKey ){
  258. case PREDEFINE_KEY_CLASSES_ROOT:
  259. case PREDEFINE_KEY_CURRENT_USER:
  260. case PREDEFINE_KEY_CURRENT_CONFIG:
  261. m_hkeyPredefinedKey = 0;
  262. break;
  263. case PREDEFINE_KEY_LOCAL_MACHINE :
  264. m_hkeyPredefinedKey = HKEY_LOCAL_MACHINE;
  265. break;
  266. case PREDEFINE_KEY_USERS:
  267. m_hkeyPredefinedKey = HKEY_USERS;
  268. break;
  269. default:
  270. //assert(false);
  271. break;
  272. }
  273. if( m_hkeyPredefinedKey ){
  274. dwErr = RegConnectRegistry( m_strMachineName,
  275. m_hkeyPredefinedKey,
  276. &m_hkeyPredefinedKey );
  277. if( dwErr ) {
  278. m_hkeyPredefinedKey = 0;
  279. hr = HRESULT_FROM_WIN32( dwErr );
  280. }
  281. }
  282. } //IsRemoteRegistry
  283. return hr;
  284. }
  285. /*
  286. JeffreyS 1/24/97:
  287. If you don't set the SI_RESET flag in
  288. ISecurityInformation::GetObjectInformation, then fDefault should never be TRUE
  289. so you can ignore it. Returning E_NOTIMPL in this case is OK too.
  290. If you want the user to be able to reset the ACL to some default state
  291. (defined by you) then turn on SI_RESET and return your default ACL
  292. when fDefault is TRUE. This happens if/when the user pushes a button
  293. that is only visible when SI_RESET is on.
  294. */
  295. STDMETHODIMP
  296. CKeySecurityInformation::GetObjectInformation (
  297. PSI_OBJECT_INFO pObjectInfo )
  298. {
  299. assert( NULL != pObjectInfo );
  300. pObjectInfo->dwFlags = m_dwFlags;
  301. pObjectInfo->hInstance = GetModuleHandle(NULL);
  302. // pObjectInfo->pszServerName = (LPWSTR)m_strMachineName;
  303. pObjectInfo->pszServerName = (LPWSTR)m_strMachineName;
  304. pObjectInfo->pszObjectName = (LPWSTR)m_strPageTitle;
  305. return S_OK;
  306. }
  307. STDMETHODIMP
  308. CKeySecurityInformation::GetAccessRights(
  309. const GUID *pguidObjectType,
  310. DWORD dwFlags,
  311. PSI_ACCESS *ppAccess,
  312. ULONG *pcAccesses,
  313. ULONG *piDefaultAccess
  314. )
  315. {
  316. assert( NULL != ppAccess );
  317. assert( NULL != pcAccesses );
  318. assert( NULL != piDefaultAccess );
  319. *ppAccess = siKeyAccesses;
  320. *pcAccesses = ARRAYSIZE(siKeyAccesses);
  321. *piDefaultAccess = iKeyDefAccess;
  322. return S_OK;
  323. }
  324. GENERIC_MAPPING KeyMap =
  325. {
  326. KEY_READ,
  327. KEY_WRITE,
  328. KEY_READ,
  329. KEY_ALL_ACCESS
  330. };
  331. STDMETHODIMP
  332. CKeySecurityInformation::MapGeneric(
  333. const GUID *pguidObjectType,
  334. UCHAR *pAceFlags,
  335. ACCESS_MASK *pMask
  336. )
  337. {
  338. //jeffreys
  339. // After returning from the object picker dialog, aclui passes
  340. //CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE to MapGeneric for validation when
  341. // initializing Permission entry for <objectname> dialog.
  342. //hiteshr: since registry keys don't have OBJECT_INHERIT_ACE, remove this FLAG,
  343. //this will cause "this keys and subkeys" to appear as default in combobox.
  344. *pAceFlags &= ~OBJECT_INHERIT_ACE;
  345. MapGenericMask(pMask, &KeyMap);
  346. return S_OK;
  347. }
  348. STDMETHODIMP
  349. CKeySecurityInformation::GetInheritTypes (
  350. PSI_INHERIT_TYPE *ppInheritTypes,
  351. ULONG *pcInheritTypes
  352. )
  353. {
  354. assert( NULL != ppInheritTypes );
  355. assert( NULL != pcInheritTypes );
  356. *ppInheritTypes = siKeyInheritTypes;
  357. *pcInheritTypes = ARRAYSIZE(siKeyInheritTypes);
  358. return S_OK;
  359. }
  360. STDMETHODIMP
  361. CKeySecurityInformation::PropertySheetPageCallback(
  362. HWND hwnd,
  363. UINT uMsg,
  364. SI_PAGE_TYPE uPage
  365. )
  366. {
  367. switch (uMsg)
  368. {
  369. case PSPCB_SI_INITDIALOG:
  370. m_hWndProperty = hwnd;
  371. break;
  372. case PSPCB_RELEASE:
  373. m_hWndProperty = NULL;
  374. break;
  375. }
  376. return S_OK;
  377. }
  378. STDMETHODIMP
  379. CKeySecurityInformation::GetSecurity( IN SECURITY_INFORMATION RequestedInformation,
  380. OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor,
  381. IN BOOL fDefault )
  382. {
  383. if( fDefault )
  384. return E_NOTIMPL;
  385. assert( NULL != ppSecurityDescriptor );
  386. HRESULT hr;
  387. LPCTSTR pstrKeyName = GetCompleteName();
  388. DWORD dwErr = 0;
  389. dwErr = GetNamedSecurityInfo( (LPTSTR)pstrKeyName,
  390. SE_REGISTRY_KEY,
  391. RequestedInformation,
  392. NULL,
  393. NULL,
  394. NULL,
  395. NULL,
  396. ppSecurityDescriptor);
  397. return ( ( dwErr != ERROR_SUCCESS ) ? HRESULT_FROM_WIN32(dwErr) : S_OK);
  398. }
  399. STDMETHODIMP
  400. CKeySecurityInformation::SetSecurity(IN SECURITY_INFORMATION si,
  401. IN PSECURITY_DESCRIPTOR pSD )
  402. {
  403. if( NULL == pSD )
  404. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  405. HRESULT hr = S_OK;
  406. SECURITY_INFORMATION siLocal = 0;
  407. SECURITY_DESCRIPTOR sdLocal = {0};
  408. ACL daclEmpty = {0};
  409. HKEY hkeyOld = NULL;
  410. HKEY hKeyNew = NULL;
  411. BOOL bWriteInfo = false;
  412. DWORD Error = 0;
  413. //
  414. // Create a security descriptor with no SACL and an
  415. // empty DACL for recursively resetting security
  416. //
  417. InitializeSecurityDescriptor(&sdLocal, SECURITY_DESCRIPTOR_REVISION);
  418. InitializeAcl(&daclEmpty, sizeof(ACL), ACL_REVISION);
  419. SetSecurityDescriptorDacl(&sdLocal, TRUE, &daclEmpty, FALSE);
  420. SetSecurityDescriptorSacl(&sdLocal, TRUE, &daclEmpty, FALSE);
  421. //
  422. // If we need to recursively set the Owner, get the Owner &
  423. // Group from pSD.
  424. //
  425. if (si & SI_OWNER_RECURSE)
  426. {
  427. PSID psid;
  428. BOOL bDefaulted;
  429. assert(si & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION));
  430. siLocal |= si & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION);
  431. if (GetSecurityDescriptorOwner(pSD, &psid, &bDefaulted))
  432. SetSecurityDescriptorOwner(&sdLocal, psid, bDefaulted);
  433. if (GetSecurityDescriptorGroup(pSD, &psid, &bDefaulted))
  434. SetSecurityDescriptorGroup(&sdLocal, psid, bDefaulted);
  435. }
  436. if (si & SI_RESET_DACL_TREE)
  437. {
  438. assert(si & DACL_SECURITY_INFORMATION);
  439. siLocal |= si & DACL_SECURITY_INFORMATION;
  440. }
  441. if (si & SI_RESET_SACL_TREE)
  442. {
  443. assert(si & SACL_SECURITY_INFORMATION);
  444. siLocal |= si & SACL_SECURITY_INFORMATION;
  445. }
  446. if( siLocal )
  447. {
  448. //Open the key with current Maximum Allowed Permisson
  449. //When applying permissons recursively , we first use current permisson,
  450. //if current permisson doesn't have enough rights, we reopen handle to key with
  451. //new permissons. If none (old or new )has enough permissons to enumerate child and
  452. // Query info we fail.
  453. REGSAM samDesired = MAXIMUM_ALLOWED;
  454. if( si & SACL_SECURITY_INFORMATION )
  455. samDesired |= ACCESS_SYSTEM_SECURITY;
  456. if( si & DACL_SECURITY_INFORMATION )
  457. samDesired |= WRITE_DAC;
  458. if( si & OWNER_SECURITY_INFORMATION )
  459. samDesired |= WRITE_OWNER;
  460. //Open the selected key
  461. if( S_OK != ( hr = OpenKey( samDesired, &hkeyOld ) ) ){
  462. return hr;
  463. }
  464. //Check if key has Enumeration Permisson
  465. DWORD NumberOfSubKeys = 0;
  466. DWORD MaxSubKeyLength = 0;
  467. // Find out the total number of subkeys
  468. Error = RegQueryInfoKey(
  469. hkeyOld,
  470. NULL,
  471. NULL,
  472. NULL,
  473. &NumberOfSubKeys,
  474. &MaxSubKeyLength,
  475. NULL,
  476. NULL,
  477. NULL,
  478. NULL,
  479. NULL,
  480. NULL
  481. );
  482. if( Error != ERROR_SUCCESS ){
  483. if( Error == ERROR_ACCESS_DENIED ) {
  484. hr = WriteObjectSecurity( hkeyOld, si, pSD );
  485. if( hr != S_OK )
  486. {
  487. if( m_hkeyPredefinedKey != hkeyOld )
  488. RegCloseKey( hkeyOld );
  489. return hr;
  490. }
  491. bWriteInfo = true;
  492. //
  493. // Handle doesn't allow KEY_QUERY_VALUE or READ_CONTROL access.
  494. // Open a new handle with these accesses.
  495. //
  496. samDesired = MAXIMUM_ALLOWED;
  497. if( si & SACL_SECURITY_INFORMATION ) {
  498. samDesired |= ACCESS_SYSTEM_SECURITY;
  499. } else if( si & DACL_SECURITY_INFORMATION ) {
  500. samDesired |= WRITE_DAC;
  501. } else if( si & OWNER_SECURITY_INFORMATION ) {
  502. samDesired |= WRITE_OWNER;
  503. }
  504. Error = RegOpenKeyEx( hkeyOld,
  505. NULL,
  506. REG_OPTION_RESERVED,
  507. samDesired,
  508. &hKeyNew
  509. );
  510. if( Error != ERROR_SUCCESS )
  511. {
  512. if( m_hkeyPredefinedKey != hkeyOld )
  513. RegCloseKey( hkeyOld );
  514. return HRESULT_FROM_WIN32(Error);
  515. }
  516. else
  517. {
  518. if( m_hkeyPredefinedKey != hkeyOld )
  519. RegCloseKey( hkeyOld );
  520. }
  521. Error = RegQueryInfoKey(
  522. hKeyNew,
  523. NULL,
  524. NULL,
  525. NULL,
  526. &NumberOfSubKeys,
  527. &MaxSubKeyLength,
  528. NULL,
  529. NULL,
  530. NULL,
  531. NULL,
  532. NULL,
  533. NULL );
  534. if( Error != ERROR_SUCCESS ) {
  535. RegCloseKey( hKeyNew );
  536. return HRESULT_FROM_WIN32( Error );
  537. }
  538. }
  539. else
  540. {
  541. if( m_hkeyPredefinedKey != hkeyOld )
  542. RegCloseKey( hkeyOld );
  543. return HRESULT_FROM_WIN32( Error );
  544. }
  545. }
  546. else
  547. hKeyNew = hkeyOld;
  548. if( NumberOfSubKeys )
  549. {
  550. assert( MaxSubKeyLength <= MAX_PATH );
  551. DWORD SubKeyNameLength = 0;
  552. WCHAR SubKeyName[MAX_PATH + 1];
  553. //
  554. // The key has subkeys.
  555. // Find out if we are able to enumerate the key using the handle
  556. // passed as argument.
  557. //
  558. SubKeyNameLength = MAX_PATH;
  559. Error = RegEnumKey( hKeyNew,
  560. 0,
  561. SubKeyName,
  562. SubKeyNameLength );
  563. if( Error != ERROR_SUCCESS ){
  564. if( Error == ERROR_ACCESS_DENIED && bWriteInfo == false ){
  565. hr = WriteObjectSecurity( hkeyOld, si, pSD );
  566. if( hr != S_OK )
  567. {
  568. if( m_hkeyPredefinedKey != hkeyOld )
  569. RegCloseKey( hkeyOld );
  570. return hr;
  571. }
  572. bWriteInfo = true;
  573. //
  574. // Handle doesn't allow KEY_QUERY_VALUE or READ_CONTROL access.
  575. // Open a new handle with these accesses.
  576. //
  577. samDesired = MAXIMUM_ALLOWED;
  578. if( si & SACL_SECURITY_INFORMATION ) {
  579. samDesired |= ACCESS_SYSTEM_SECURITY;
  580. } else if( si & DACL_SECURITY_INFORMATION ) {
  581. samDesired |= WRITE_DAC;
  582. } else if( si & OWNER_SECURITY_INFORMATION ) {
  583. samDesired |= WRITE_OWNER;
  584. }
  585. Error = RegOpenKeyEx( hkeyOld,
  586. NULL,
  587. REG_OPTION_RESERVED,
  588. samDesired,
  589. &hKeyNew
  590. );
  591. if( Error != ERROR_SUCCESS )
  592. {
  593. if( m_hkeyPredefinedKey != hkeyOld )
  594. RegCloseKey( hkeyOld );
  595. return HRESULT_FROM_WIN32(Error);
  596. }
  597. else
  598. {
  599. if( m_hkeyPredefinedKey != hkeyOld )
  600. RegCloseKey( hkeyOld );
  601. }
  602. SubKeyNameLength = MAX_PATH;
  603. Error = RegEnumKey( hKeyNew,
  604. 0,
  605. SubKeyName,
  606. SubKeyNameLength );
  607. if( Error != ERROR_SUCCESS ){
  608. RegCloseKey( hKeyNew );
  609. return HRESULT_FROM_WIN32(Error);
  610. }
  611. }
  612. else
  613. {
  614. if( m_hkeyPredefinedKey != hKeyNew )
  615. RegCloseKey( hKeyNew );
  616. return HRESULT_FROM_WIN32(Error);
  617. }
  618. }
  619. }
  620. }
  621. //
  622. // Recursively apply new Owner and/or reset the ACLs
  623. //
  624. if (siLocal)
  625. {
  626. BOOL bNotAllApplied = FALSE;
  627. hr = SetSubKeysSecurity( hKeyNew, siLocal, &sdLocal, &bNotAllApplied, true );
  628. RegFlushKey( hKeyNew );
  629. if( m_hkeyPredefinedKey != hKeyNew )
  630. RegCloseKey( hKeyNew );
  631. if( bNotAllApplied )
  632. {
  633. if( siLocal & OWNER_SECURITY_INFORMATION )
  634. {
  635. DisplayMessage( GetInFocusHWnd(),
  636. GetModuleHandle(NULL),
  637. IDS_SET_OWNER_RECURSIVE_EX_FAIL,
  638. IDS_SECURITY );
  639. }
  640. else if( ( siLocal & DACL_SECURITY_INFORMATION ) || ( siLocal & SACL_SECURITY_INFORMATION ) )
  641. {
  642. DisplayMessage( GetInFocusHWnd(),
  643. GetModuleHandle(NULL),
  644. IDS_SET_SECURITY_RECURSIVE_EX_FAIL,
  645. IDS_SECURITY);
  646. }
  647. }
  648. if( hr != S_OK )
  649. return hr;
  650. }
  651. si &= ~(SI_OWNER_RECURSE | SI_RESET_DACL_TREE | SI_RESET_SACL_TREE);
  652. //This sets the security for the top keys
  653. if (si != 0)
  654. {
  655. hr = WriteObjectSecurity( GetCompleteName(),
  656. si,
  657. pSD );
  658. if( hr != S_OK )
  659. {
  660. if( siLocal )
  661. RegCloseKey( hkeyOld );
  662. return hr;
  663. }
  664. }
  665. return hr;
  666. }
  667. STDMETHODIMP
  668. CKeySecurityInformation::WriteObjectSecurity(LPCTSTR pszObject,
  669. IN SECURITY_INFORMATION si,
  670. IN PSECURITY_DESCRIPTOR pSD )
  671. {
  672. DWORD dwErr;
  673. SECURITY_DESCRIPTOR_CONTROL wSDControl = 0;
  674. DWORD dwRevision;
  675. PSID psidOwner = NULL;
  676. PSID psidGroup = NULL;
  677. PACL pDacl = NULL;
  678. PACL pSacl = NULL;
  679. BOOL bDefaulted;
  680. BOOL bPresent;
  681. //
  682. // Get pointers to various security descriptor parts for
  683. // calling SetNamedSecurityInfo
  684. //
  685. if( !GetSecurityDescriptorControl(pSD, &wSDControl, &dwRevision) )
  686. {
  687. dwErr = GetLastError();
  688. return HRESULT_FROM_WIN32(dwErr);
  689. }
  690. if( !GetSecurityDescriptorOwner(pSD, &psidOwner, &bDefaulted) )
  691. {
  692. dwErr = GetLastError();
  693. return HRESULT_FROM_WIN32(dwErr);
  694. }
  695. if( !GetSecurityDescriptorGroup(pSD, &psidGroup, &bDefaulted) )
  696. {
  697. dwErr = GetLastError();
  698. return HRESULT_FROM_WIN32(dwErr);
  699. }
  700. if( !GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaulted) )
  701. {
  702. dwErr = GetLastError();
  703. return HRESULT_FROM_WIN32(dwErr);
  704. }
  705. if( !GetSecurityDescriptorSacl(pSD, &bPresent, &pSacl, &bDefaulted) )
  706. {
  707. dwErr = GetLastError();
  708. return HRESULT_FROM_WIN32(dwErr);
  709. }
  710. if ((si & DACL_SECURITY_INFORMATION) && (wSDControl & SE_DACL_PROTECTED))
  711. si |= PROTECTED_DACL_SECURITY_INFORMATION;
  712. else
  713. si |= UNPROTECTED_DACL_SECURITY_INFORMATION;
  714. if ((si & SACL_SECURITY_INFORMATION) && (wSDControl & SE_SACL_PROTECTED))
  715. si |= PROTECTED_SACL_SECURITY_INFORMATION;
  716. else
  717. si |= UNPROTECTED_SACL_SECURITY_INFORMATION;
  718. //if the selected key is predefined key, it has no parent and hence
  719. //cannot inherit any permisson from parent.
  720. //if PROTECTED_DACL_SECURITY_INFORMATION flag is not set in this case
  721. // SetSecurityInfo succeeds, but permissions are not set.[bug in SetSecurityInfo].
  722. if ( (si & DACL_SECURITY_INFORMATION) && !m_strKeyName )
  723. si |= PROTECTED_DACL_SECURITY_INFORMATION;
  724. else
  725. si |= UNPROTECTED_DACL_SECURITY_INFORMATION;
  726. if ( (si & SACL_SECURITY_INFORMATION) && !m_strKeyName )
  727. si |= PROTECTED_SACL_SECURITY_INFORMATION;
  728. else
  729. si |= UNPROTECTED_SACL_SECURITY_INFORMATION;
  730. //We are on the root object
  731. if( m_strKeyName == NULL )
  732. {
  733. dwErr = SetSecurityInfo( m_hkeyPredefinedKey,
  734. SE_REGISTRY_KEY,
  735. si,
  736. psidOwner,
  737. psidGroup,
  738. pDacl,
  739. pSacl);
  740. }else
  741. {
  742. dwErr = SetNamedSecurityInfo((LPWSTR)pszObject,
  743. SE_REGISTRY_KEY,
  744. si,
  745. psidOwner,
  746. psidGroup,
  747. pDacl,
  748. pSacl);
  749. }
  750. return (dwErr ? HRESULT_FROM_WIN32(dwErr) : S_OK);
  751. }
  752. STDMETHODIMP
  753. CKeySecurityInformation::WriteObjectSecurity(HKEY hkey,
  754. IN SECURITY_INFORMATION si,
  755. IN PSECURITY_DESCRIPTOR pSD )
  756. {
  757. DWORD dwErr;
  758. SECURITY_DESCRIPTOR_CONTROL wSDControl = 0;
  759. DWORD dwRevision;
  760. PSID psidOwner = NULL;
  761. PSID psidGroup = NULL;
  762. PACL pDacl = NULL;
  763. PACL pSacl = NULL;
  764. BOOL bDefaulted;
  765. BOOL bPresent;
  766. //
  767. // Get pointers to various security descriptor parts for
  768. // calling SetNamedSecurityInfo
  769. //
  770. ;
  771. if( !GetSecurityDescriptorControl(pSD, &wSDControl, &dwRevision) )
  772. {
  773. dwErr = GetLastError();
  774. return HRESULT_FROM_WIN32(dwErr);
  775. }
  776. if( !GetSecurityDescriptorOwner(pSD, &psidOwner, &bDefaulted) )
  777. {
  778. dwErr = GetLastError();
  779. return HRESULT_FROM_WIN32(dwErr);
  780. }
  781. if( !GetSecurityDescriptorGroup(pSD, &psidGroup, &bDefaulted) )
  782. {
  783. dwErr = GetLastError();
  784. return HRESULT_FROM_WIN32(dwErr);
  785. }
  786. if( !GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaulted) )
  787. {
  788. dwErr = GetLastError();
  789. return HRESULT_FROM_WIN32(dwErr);
  790. }
  791. if( !GetSecurityDescriptorSacl(pSD, &bPresent, &pSacl, &bDefaulted) )
  792. {
  793. dwErr = GetLastError();
  794. return HRESULT_FROM_WIN32(dwErr);
  795. }
  796. if ((si & DACL_SECURITY_INFORMATION) && (wSDControl & SE_DACL_PROTECTED))
  797. si |= PROTECTED_DACL_SECURITY_INFORMATION;
  798. else
  799. si |= UNPROTECTED_DACL_SECURITY_INFORMATION;
  800. if ((si & SACL_SECURITY_INFORMATION) && (wSDControl & SE_SACL_PROTECTED))
  801. si |= PROTECTED_SACL_SECURITY_INFORMATION;
  802. else
  803. si |= UNPROTECTED_SACL_SECURITY_INFORMATION;
  804. dwErr = SetSecurityInfo( hkey,
  805. SE_REGISTRY_KEY,
  806. si,
  807. psidOwner,
  808. psidGroup,
  809. pDacl,
  810. pSacl);
  811. return (dwErr ? HRESULT_FROM_WIN32(dwErr) : S_OK);
  812. }
  813. HRESULT
  814. CKeySecurityInformation::SetSubKeysSecurity( HKEY hkey,
  815. SECURITY_INFORMATION si,
  816. PSECURITY_DESCRIPTOR pSD,
  817. LPBOOL pbNotAllApplied,
  818. bool bFirstCall )
  819. {
  820. ULONG Error;
  821. REGSAM samDesired;
  822. HRESULT hr;
  823. HRESULT hrRet;
  824. HKEY hKeyNew;
  825. //For First Call we call SetSecurityInfoEx in last
  826. if( !bFirstCall ){
  827. SECURITY_DESCRIPTOR_CONTROL wSDControl = 0;
  828. DWORD dwRevision;
  829. PSID psidOwner = NULL;
  830. PSID psidGroup = NULL;
  831. PACL pDacl = NULL;
  832. PACL pSacl = NULL;
  833. BOOL bDefaulted;
  834. BOOL bPresent;
  835. DWORD dwErr;
  836. //
  837. // Get pointers to various security descriptor parts for
  838. // calling SetNamedSecurityInfo
  839. //
  840. if( !GetSecurityDescriptorControl(pSD, &wSDControl, &dwRevision) )
  841. {
  842. *pbNotAllApplied = TRUE;
  843. goto SET_FOR_CHILD;
  844. }
  845. if( !GetSecurityDescriptorOwner(pSD, &psidOwner, &bDefaulted) )
  846. {
  847. *pbNotAllApplied = TRUE;
  848. goto SET_FOR_CHILD;
  849. }
  850. if( !GetSecurityDescriptorGroup(pSD, &psidGroup, &bDefaulted) )
  851. {
  852. *pbNotAllApplied = TRUE;
  853. goto SET_FOR_CHILD;
  854. }
  855. if( !GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefaulted) )
  856. {
  857. *pbNotAllApplied = TRUE;
  858. goto SET_FOR_CHILD;
  859. }
  860. if( !GetSecurityDescriptorSacl(pSD, &bPresent, &pSacl, &bDefaulted) )
  861. {
  862. *pbNotAllApplied = TRUE;
  863. goto SET_FOR_CHILD;
  864. }
  865. if ((si & DACL_SECURITY_INFORMATION) && (wSDControl & SE_DACL_PROTECTED))
  866. si |= PROTECTED_DACL_SECURITY_INFORMATION;
  867. else
  868. si |= UNPROTECTED_DACL_SECURITY_INFORMATION;
  869. if ((si & SACL_SECURITY_INFORMATION) && (wSDControl & SE_SACL_PROTECTED))
  870. si |= PROTECTED_SACL_SECURITY_INFORMATION;
  871. else
  872. si |= UNPROTECTED_SACL_SECURITY_INFORMATION;
  873. dwErr = SetSecurityInfo( hkey,
  874. SE_REGISTRY_KEY,
  875. si,
  876. psidOwner,
  877. psidGroup,
  878. pDacl,
  879. pSacl);
  880. if( dwErr != ERROR_SUCCESS )
  881. {
  882. *pbNotAllApplied = TRUE;
  883. goto SET_FOR_CHILD;
  884. //return HRESULT_FROM_WIN32(dwErr);
  885. }
  886. //RegFlushKey( hkey );
  887. }
  888. SET_FOR_CHILD:
  889. DWORD NumberOfSubKeys = 0;
  890. DWORD MaxSubKeyLength = 0;
  891. // Find out the total number of subkeys
  892. Error = RegQueryInfoKey(
  893. hkey,
  894. NULL,
  895. NULL,
  896. NULL,
  897. &NumberOfSubKeys,
  898. &MaxSubKeyLength,
  899. NULL,
  900. NULL,
  901. NULL,
  902. NULL,
  903. NULL,
  904. NULL
  905. );
  906. if( Error != ERROR_SUCCESS ){
  907. if( Error == ERROR_ACCESS_DENIED ) {
  908. //
  909. // Handle doesn't allow KEY_QUERY_VALUE or READ_CONTROL access.
  910. // Open a new handle with these accesses.
  911. //
  912. samDesired = KEY_QUERY_VALUE | READ_CONTROL; // MAXIMUM_ALLOWED | READ_CONTROL;
  913. if( si & SACL_SECURITY_INFORMATION ) {
  914. samDesired |= ACCESS_SYSTEM_SECURITY;
  915. } else if( si & DACL_SECURITY_INFORMATION ) {
  916. samDesired |= WRITE_DAC;
  917. } else if( si & OWNER_SECURITY_INFORMATION ) {
  918. samDesired |= WRITE_OWNER;
  919. }
  920. Error = RegOpenKeyEx( hkey,
  921. NULL,
  922. REG_OPTION_RESERVED,
  923. samDesired,
  924. &hKeyNew
  925. );
  926. if( Error != ERROR_SUCCESS ) {
  927. *pbNotAllApplied = TRUE;
  928. return S_OK;
  929. }
  930. Error = RegQueryInfoKey(
  931. hKeyNew,
  932. NULL,
  933. NULL,
  934. NULL,
  935. &NumberOfSubKeys,
  936. &MaxSubKeyLength,
  937. NULL,
  938. NULL,
  939. NULL,
  940. NULL,
  941. NULL,
  942. NULL );
  943. if( Error != ERROR_SUCCESS ) {
  944. RegCloseKey( hKeyNew );
  945. *pbNotAllApplied = TRUE;
  946. return S_OK;
  947. }
  948. else
  949. RegCloseKey( hKeyNew );
  950. }
  951. else{
  952. *pbNotAllApplied = TRUE;
  953. return S_OK;
  954. }
  955. }
  956. if( NumberOfSubKeys == 0 ) {
  957. return S_OK;
  958. }
  959. assert( MaxSubKeyLength <= MAX_PATH );
  960. DWORD SubKeyNameLength = 0;
  961. WCHAR SubKeyName[MAX_PATH + 1];
  962. //
  963. // The key has subkeys.
  964. // Find out if we are able to enumerate the key using the handle
  965. // passed as argument.
  966. //
  967. SubKeyNameLength = MAX_PATH;
  968. Error = RegEnumKey( hkey,
  969. 0,
  970. SubKeyName,
  971. SubKeyNameLength );
  972. if( Error != ERROR_SUCCESS ){
  973. if( Error == ERROR_ACCESS_DENIED ) {
  974. //
  975. // Handle doesn't allow 'enumerate' access.
  976. // Open a new handle with KEY_ENUMERATE_SUB_KEYS access.
  977. //
  978. Error = RegOpenKeyEx( hkey,
  979. NULL,
  980. REG_OPTION_RESERVED,
  981. KEY_ENUMERATE_SUB_KEYS, // samDesired,
  982. &hKeyNew
  983. );
  984. if( Error != ERROR_SUCCESS ){
  985. *pbNotAllApplied = TRUE;
  986. return S_OK;
  987. }
  988. }
  989. else{
  990. *pbNotAllApplied = TRUE;
  991. return S_OK;
  992. }
  993. }
  994. else {
  995. hKeyNew = hkey;
  996. }
  997. for( DWORD Index = 0; Index < NumberOfSubKeys; Index++ )
  998. {
  999. // If the key has subkeys, then for each subkey, do:
  1000. // - Determine the subkey name
  1001. SubKeyNameLength = MAX_PATH;
  1002. Error = RegEnumKey( hKeyNew,
  1003. Index,
  1004. SubKeyName,
  1005. SubKeyNameLength );
  1006. if( Error != ERROR_SUCCESS ) {
  1007. *pbNotAllApplied = TRUE;
  1008. continue;
  1009. //return HRESULT_FROM_WIN32( Error );
  1010. }
  1011. // - Open a handle to the subkey
  1012. samDesired = MAXIMUM_ALLOWED;
  1013. if( si & SACL_SECURITY_INFORMATION )
  1014. samDesired |= ACCESS_SYSTEM_SECURITY;
  1015. if( si & DACL_SECURITY_INFORMATION )
  1016. samDesired |= WRITE_DAC;
  1017. if( si & OWNER_SECURITY_INFORMATION )
  1018. samDesired |= WRITE_OWNER;
  1019. HKEY hkeyChild;
  1020. Error = RegOpenKeyEx( hKeyNew,
  1021. SubKeyName,
  1022. REG_OPTION_RESERVED,
  1023. samDesired,
  1024. &hkeyChild
  1025. );
  1026. if( ERROR_SUCCESS != Error ){
  1027. *pbNotAllApplied = TRUE;
  1028. continue;
  1029. // return HRESULT_FROM_WIN32( Error );
  1030. }
  1031. // - Set the security of the child's subkeys
  1032. if( S_OK != ( hr = SetSubKeysSecurity( hkeyChild,
  1033. si,
  1034. pSD,
  1035. pbNotAllApplied,
  1036. false ) ) ){
  1037. //This case will occur only if some fatal error occur which
  1038. //prevents propogation on rest of the tree.
  1039. if( hKeyNew != hkey )
  1040. RegCloseKey( hKeyNew );
  1041. RegCloseKey( hkeyChild );
  1042. return hr;
  1043. }
  1044. else{
  1045. RegCloseKey( hkeyChild );
  1046. }
  1047. } //For loop
  1048. if( hKeyNew != hkey )
  1049. RegCloseKey( hKeyNew );
  1050. return S_OK;;
  1051. }
  1052. HRESULT
  1053. CKeySecurityInformation::OpenKey(IN DWORD Permission,
  1054. OUT PHKEY pKey )
  1055. {
  1056. LPCWSTR CompleteNameString = NULL;;
  1057. ULONG Error;
  1058. if( m_strKeyName == NULL){
  1059. //This is a predefined key
  1060. *pKey = m_hkeyPredefinedKey;
  1061. }
  1062. else{
  1063. CompleteNameString = GetCompleteName1();
  1064. assert( CompleteNameString != NULL );
  1065. // Open handle to the key
  1066. Error = RegOpenKeyEx(m_hkeyPredefinedKey,
  1067. CompleteNameString,
  1068. 0,
  1069. Permission,
  1070. pKey );
  1071. if( Error != ERROR_SUCCESS ) {
  1072. return HRESULT_FROM_WIN32( Error );
  1073. }
  1074. }
  1075. if( CompleteNameString )
  1076. LocalFree( (HLOCAL) CompleteNameString);
  1077. return S_OK;
  1078. }
  1079. OBJECT_TYPE_LIST g_DefaultOTL[] = {
  1080. {0, 0, (LPGUID)&GUID_NULL},
  1081. };
  1082. BOOL SkipLocalGroup(LPCWSTR pszServerName, PSID psid)
  1083. {
  1084. SID_NAME_USE use;
  1085. WCHAR szAccountName[MAX_PATH];
  1086. WCHAR szDomainName[MAX_PATH];
  1087. DWORD dwAccountLen = MAX_PATH;
  1088. DWORD dwDomainLen = MAX_PATH;
  1089. if(LookupAccountSid(pszServerName,
  1090. psid,
  1091. szAccountName,
  1092. &dwAccountLen,
  1093. szDomainName,
  1094. &dwDomainLen,
  1095. &use))
  1096. {
  1097. if(use == SidTypeWellKnownGroup)
  1098. return TRUE;
  1099. }
  1100. //Built In sids have first subauthority of 32 ( s-1-5-32 )
  1101. //
  1102. if((*(GetSidSubAuthorityCount(psid)) >= 1 ) && (*(GetSidSubAuthority(psid,0)) == 32))
  1103. return TRUE;
  1104. return FALSE;
  1105. }
  1106. STDMETHODIMP
  1107. CKeySecurityInformation::GetEffectivePermission(const GUID* pguidObjectType,
  1108. PSID pUserSid,
  1109. LPCWSTR pszServerName,
  1110. PSECURITY_DESCRIPTOR pSD,
  1111. POBJECT_TYPE_LIST *ppObjectTypeList,
  1112. ULONG *pcObjectTypeListLength,
  1113. PACCESS_MASK *ppGrantedAccessList,
  1114. ULONG *pcGrantedAccessListLength)
  1115. {
  1116. AUTHZ_RESOURCE_MANAGER_HANDLE RM = NULL; //Used for access check
  1117. AUTHZ_CLIENT_CONTEXT_HANDLE CC = NULL;
  1118. LUID luid = {0xdead,0xbeef};
  1119. AUTHZ_ACCESS_REQUEST AReq;
  1120. AUTHZ_ACCESS_REPLY AReply;
  1121. HRESULT hr = S_OK;
  1122. DWORD dwFlags;
  1123. AReq.ObjectTypeList = g_DefaultOTL;
  1124. AReq.ObjectTypeListLength = ARRAYSIZE(g_DefaultOTL);
  1125. AReply.GrantedAccessMask = NULL;
  1126. AReply.Error = NULL;
  1127. //Get RM
  1128. if( (RM = GetAUTHZ_RM()) == NULL )
  1129. return S_FALSE;
  1130. //Initialize the client context
  1131. BOOL bSkipLocalGroup = SkipLocalGroup(pszServerName, pUserSid);
  1132. if( !AuthzInitializeContextFromSid(bSkipLocalGroup? AUTHZ_SKIP_TOKEN_GROUPS :0,
  1133. pUserSid,
  1134. RM,
  1135. NULL,
  1136. luid,
  1137. NULL,
  1138. &CC) )
  1139. {
  1140. return HRESULT_FROM_WIN32(GetLastError());
  1141. }
  1142. //Do the Access Check
  1143. AReq.DesiredAccess = MAXIMUM_ALLOWED;
  1144. AReq.PrincipalSelfSid = NULL;
  1145. AReq.OptionalArguments = NULL;
  1146. AReply.ResultListLength = AReq.ObjectTypeListLength;
  1147. AReply.SaclEvaluationResults = NULL;
  1148. if( (AReply.GrantedAccessMask = (PACCESS_MASK)LocalAlloc(LPTR, sizeof(ACCESS_MASK)*AReply.ResultListLength) ) == NULL )
  1149. return E_OUTOFMEMORY;
  1150. if( (AReply.Error = (PDWORD)LocalAlloc(LPTR, sizeof(DWORD)*AReply.ResultListLength)) == NULL )
  1151. {
  1152. LocalFree(AReply.GrantedAccessMask);
  1153. return E_OUTOFMEMORY;
  1154. }
  1155. if( !AuthzAccessCheck(0,
  1156. CC,
  1157. &AReq,
  1158. NULL,
  1159. pSD,
  1160. NULL,
  1161. 0,
  1162. &AReply,
  1163. NULL) )
  1164. {
  1165. LocalFree(AReply.GrantedAccessMask);
  1166. LocalFree(AReply.Error);
  1167. return HRESULT_FROM_WIN32(GetLastError());
  1168. }
  1169. if(CC)
  1170. AuthzFreeContext(CC);
  1171. *ppObjectTypeList = AReq.ObjectTypeList;
  1172. *pcObjectTypeListLength = AReq.ObjectTypeListLength;
  1173. *ppGrantedAccessList = AReply.GrantedAccessMask;
  1174. *pcGrantedAccessListLength = AReq.ObjectTypeListLength;
  1175. return S_OK;
  1176. }
  1177. STDMETHODIMP
  1178. CKeySecurityInformation::GetInheritSource(SECURITY_INFORMATION si,
  1179. PACL pACL,
  1180. PINHERITED_FROM *ppInheritArray)
  1181. {
  1182. HRESULT hr = S_OK;
  1183. if (NULL == m_strKeyName || !pACL || !ppInheritArray)
  1184. return E_UNEXPECTED;
  1185. DWORD dwErr = ERROR_SUCCESS;
  1186. PINHERITED_FROM pTempInherit = NULL;
  1187. PINHERITED_FROM pTempInherit2 = NULL;
  1188. LPWSTR pStrTemp = NULL;
  1189. LPCWSTR pszName = GetCompleteName();
  1190. pTempInherit = (PINHERITED_FROM)LocalAlloc( LPTR, sizeof(INHERITED_FROM)*pACL->AceCount);
  1191. if(pTempInherit == NULL)
  1192. {
  1193. hr = E_OUTOFMEMORY;
  1194. goto exit_gracefully;
  1195. }
  1196. dwErr = GetInheritanceSource((LPWSTR)pszName,
  1197. SE_REGISTRY_KEY,
  1198. si,
  1199. TRUE,
  1200. NULL,
  1201. 0,
  1202. pACL,
  1203. NULL,
  1204. &KeyMap,
  1205. pTempInherit);
  1206. hr = HRESULT_FROM_WIN32(dwErr);
  1207. if( FAILED(hr) )
  1208. goto exit_gracefully;
  1209. DWORD nSize;
  1210. UINT i;
  1211. nSize = sizeof(INHERITED_FROM)*pACL->AceCount;
  1212. for(i = 0; i < pACL->AceCount; ++i)
  1213. {
  1214. if(pTempInherit[i].AncestorName)
  1215. nSize += ((wcslen(pTempInherit[i].AncestorName)+1)*sizeof(WCHAR));
  1216. }
  1217. pTempInherit2 = (PINHERITED_FROM)LocalAlloc( LPTR, nSize );
  1218. if(pTempInherit2 == NULL)
  1219. {
  1220. hr = E_OUTOFMEMORY;
  1221. goto exit_gracefully;
  1222. }
  1223. pStrTemp = (LPWSTR)(pTempInherit2 + pACL->AceCount);
  1224. for(i = 0; i < pACL->AceCount; ++i)
  1225. {
  1226. pTempInherit2[i].GenerationGap = pTempInherit[i].GenerationGap;
  1227. if(pTempInherit[i].AncestorName)
  1228. {
  1229. pTempInherit2[i].AncestorName = pStrTemp;
  1230. wcscpy(pStrTemp,pTempInherit[i].AncestorName);
  1231. pStrTemp += (wcslen(pTempInherit[i].AncestorName)+1);
  1232. }
  1233. }
  1234. exit_gracefully:
  1235. if(SUCCEEDED(hr))
  1236. {
  1237. //FreeInheritedFromArray(pTempInherit, pACL->AceCount,NULL);
  1238. *ppInheritArray = pTempInherit2;
  1239. }
  1240. if(pTempInherit)
  1241. LocalFree(pTempInherit);
  1242. return hr;
  1243. }
  1244. ///////////////////////////////////////////////////////////
  1245. //
  1246. // IUnknown methods
  1247. //
  1248. ///////////////////////////////////////////////////////////
  1249. STDMETHODIMP_(ULONG)
  1250. CSecurityInformation::AddRef()
  1251. {
  1252. return ++m_cRef;
  1253. }
  1254. STDMETHODIMP_(ULONG)
  1255. CSecurityInformation::Release()
  1256. {
  1257. if (--m_cRef == 0)
  1258. {
  1259. delete this;
  1260. return 0;
  1261. }
  1262. return m_cRef;
  1263. }
  1264. STDMETHODIMP
  1265. CSecurityInformation::QueryInterface(REFIID riid, LPVOID FAR* ppv)
  1266. {
  1267. // if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ISecurityInformation))
  1268. if ( IsEqualIID(riid, IID_ISecurityInformation) )
  1269. {
  1270. *ppv = (LPSECURITYINFO)this;
  1271. m_cRef++;
  1272. return S_OK;
  1273. }
  1274. else if(IsEqualIID(riid, IID_IEffectivePermission) )
  1275. {
  1276. *ppv = (LPEFFECTIVEPERMISSION)this;
  1277. m_cRef++;
  1278. return S_OK;
  1279. }
  1280. else if(IsEqualIID(riid, IID_ISecurityObjectTypeInfo) )
  1281. {
  1282. *ppv = (LPSecurityObjectTypeInfo)this;
  1283. m_cRef++;
  1284. return S_OK;
  1285. }
  1286. else
  1287. {
  1288. *ppv = NULL;
  1289. return E_NOINTERFACE;
  1290. }
  1291. }
  1292. HRESULT CreateSecurityInformation( IN LPCWSTR strKeyName,
  1293. IN LPCWSTR strParentName,
  1294. IN LPCWSTR strMachineName,
  1295. IN LPCWSTR strPageTitle,
  1296. IN BOOL bRemote,
  1297. IN PREDEFINE_KEY PredefinedKey,
  1298. IN BOOL bReadOnly,
  1299. IN HWND hWnd,
  1300. OUT LPSECURITYINFO *ppSi)
  1301. {
  1302. HRESULT hr;
  1303. if( !ppSi )
  1304. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1305. CKeySecurityInformation *ckey = new CKeySecurityInformation;
  1306. if( NULL == ckey )
  1307. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  1308. if( S_OK != ( hr = ckey->Initialize( strKeyName,
  1309. strParentName,
  1310. strMachineName,
  1311. strPageTitle,
  1312. bRemote,
  1313. PredefinedKey,
  1314. bReadOnly,
  1315. hWnd ) ) )
  1316. {
  1317. delete ckey;
  1318. return hr;
  1319. }
  1320. else
  1321. {
  1322. *ppSi = ckey;
  1323. return S_OK;
  1324. }
  1325. }
  1326. //Some helper functions
  1327. BOOL DisplayMessage( HWND hWnd,
  1328. HINSTANCE hInstance,
  1329. DWORD dwMessageId,
  1330. DWORD dwCaptionId )
  1331. {
  1332. WCHAR pszMessage[1025];
  1333. WCHAR pszTitle[1025];
  1334. LPWSTR lpTitle = NULL;
  1335. if( !LoadString(hInstance, dwMessageId, pszMessage, 1024 ) )
  1336. return FALSE;
  1337. if( dwCaptionId )
  1338. {
  1339. if( LoadString(hInstance, dwCaptionId, pszTitle, 1024 ) )
  1340. lpTitle = pszTitle;
  1341. }
  1342. // Display the string.
  1343. MessageBox( hWnd, (LPCTSTR)pszMessage, (LPCTSTR)lpTitle, MB_OK | MB_ICONINFORMATION |MB_APPLMODAL );
  1344. return TRUE;
  1345. }