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.

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