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.

1588 lines
42 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: creg.cpp
  6. * Content:
  7. * This module contains the implementation of the CRegistry class.
  8. * For a class description, see creg.h
  9. *
  10. * History:
  11. * Date By Reason
  12. * ==== == ======
  13. * 07/16/99 rodtoll Created
  14. * 08/18/99 rodtoll Added Register/UnRegister that can be used to
  15. * allow COM objects to register themselves.
  16. * 08/25/99 rodtoll Updated to provide read/write of binary (blob) data
  17. * 10/05/99 rodtoll Added DPF_MODNAMEs
  18. * 10/07/99 rodtoll Updated to work in Unicode
  19. * 10/08/99 rodtoll Fixes to DeleteKey / Reg/UnReg for Win9X
  20. * 10/15/99 rodtoll Plugged some memory leaks
  21. * 10/27/99 pnewson added Open() call that takes a GUID
  22. * 01/18/00 mjn Added GetMaxKeyLen function
  23. * 01/24/00 mjn Added GetValueSize function
  24. * 01/24/00 rodtoll Fixed error handling for ReadString (Unicode version)
  25. * 04/21/2000 rodtoll Bug #32889 - Does not run on Win2k on non-admin account
  26. * rodtoll Bug #32952 - Does not run on Win95 GOLD w/o IE4 -- modified
  27. * to allow reads of REG_BINARY when expecting REG_DWORD
  28. * 05/02/00 mjn Changed CRegistry::Open() to use KEY_READ when Create set to FALSE
  29. * 06/08/00 rmt Updated to use common string utils
  30. * 07/06/00 rmt Modified to allow seperate read/write parameter
  31. * 07/09/2000 rodtoll Added signature bytes
  32. * 07/21/00 rmt Fixed a memory leak
  33. * 08/08/2000 rmt Bug #41736 - AV in call to lstrcpy by COM_GetDllName
  34. * 08/28/2000 masonb Voice Merge: Modified platform checks to use osind.cpp layer
  35. * 08/30/2000 rodtoll Bug #171822 - PREFIX Bug
  36. * 04/13/2001 VanceO Moved granting registry permissions into common, and
  37. * added DeleteValue and EnumValues.
  38. * 06/19/2001 RichGr DX8.0 added special security rights for "everyone" - remove them if
  39. * they exist with new RemoveAllAccessSecurityPermissions() method.
  40. ***************************************************************************/
  41. #include "dncmni.h"
  42. #ifndef DPNBUILD_NOREGISTRY
  43. #ifdef WINNT
  44. // Security function prototypes
  45. typedef BOOL (*PALLOCATEANDINITIALIZESID)(
  46. PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, // authority
  47. BYTE nSubAuthorityCount, // count of subauthorities
  48. DWORD dwSubAuthority0, // subauthority 0
  49. DWORD dwSubAuthority1, // subauthority 1
  50. DWORD dwSubAuthority2, // subauthority 2
  51. DWORD dwSubAuthority3, // subauthority 3
  52. DWORD dwSubAuthority4, // subauthority 4
  53. DWORD dwSubAuthority5, // subauthority 5
  54. DWORD dwSubAuthority6, // subauthority 6
  55. DWORD dwSubAuthority7, // subauthority 7
  56. PSID *pSid // SID
  57. );
  58. typedef VOID (*PBUILDTRUSTEEWITHSID)(
  59. PTRUSTEE pTrustee, // structure
  60. PSID pSid // trustee name
  61. );
  62. typedef DWORD (*PSETENTRIESINACL)(
  63. ULONG cCountOfExplicitEntries, // number of entries
  64. PEXPLICIT_ACCESS pListOfExplicitEntries, // buffer
  65. PACL OldAcl, // original ACL
  66. PACL *NewAcl // new ACL
  67. );
  68. typedef DWORD (*PSETSECURITYINFO)(
  69. HANDLE handle, // handle to object
  70. SE_OBJECT_TYPE ObjectType, // object type
  71. SECURITY_INFORMATION SecurityInfo, // buffer
  72. PSID psidOwner, // new owner SID
  73. PSID psidGroup, // new primary group SID
  74. PACL pDacl, // new DACL
  75. PACL pSacl // new SACL
  76. );
  77. typedef PVOID (*PFREESID)(
  78. PSID pSid // SID to free
  79. );
  80. #endif // WINNT
  81. #undef DPF_MODNAME
  82. #define DPF_MODNAME "CRegistry::CRegistry"
  83. // CRegistry Constructor
  84. //
  85. // This is the default constructor for the registry class. It
  86. // is used to construct a registry object which has not yet
  87. // opened a handle to the registry. Open must be called before
  88. // this object can be used.
  89. //
  90. // Parameters:
  91. // N/A
  92. //
  93. // Returns:
  94. // N/A
  95. //
  96. CRegistry::CRegistry( ): m_isOpen(FALSE), m_dwSignature(VSIG_CREGISTRY)
  97. {
  98. }
  99. // CRegistry Destructor
  100. //
  101. // This is the destructor for the class, and will close the connection
  102. // to the registry if this object has one open.
  103. //
  104. // Parameters:
  105. // N/A
  106. //
  107. // Returns:
  108. // N/A
  109. //
  110. CRegistry::~CRegistry()
  111. {
  112. if( m_isOpen )
  113. {
  114. Close();
  115. }
  116. m_dwSignature = VSIG_CREGISTRY_FREE;
  117. }
  118. // DeleteSubKey
  119. //
  120. // This function causes the key specified by the string equivalent of
  121. // the pGuidName parameter to be deleted from the point in the registry
  122. // this object is rooted at, if the key exists. If the object does not
  123. // have an open connection to the registry, or the keyName is not specified
  124. //
  125. // Parmaters:
  126. // const GUID *pGuidName - GUID whose equivalent string needs to be deleted
  127. //
  128. // Returns:
  129. // BOOL - returns TRUE on success, FALSE on failure
  130. //
  131. BOOL CRegistry::DeleteSubKey( const GUID *pGuidName )
  132. {
  133. WCHAR wszGuidString[GUID_STRING_LEN];
  134. DNASSERT( pGuidName != NULL );
  135. // convert the guid to a string
  136. if(!StringFromGUID2(*pGuidName, wszGuidString, GUID_STRING_LEN))
  137. {
  138. DPFX(DPFPREP, 0, "StringFromGUID2 failed");
  139. return FALSE;
  140. }
  141. return DeleteSubKey(wszGuidString);
  142. }
  143. #undef DPF_MODNAME
  144. #define DPF_MODNAME "CRegistry::DeleteSubKey"
  145. // DeleteSubKey
  146. //
  147. // This function causes the key specified by the keyName parameter
  148. // to be deleted from the point in the registry this object is rooted
  149. // at, if the key exists. If the object does not have an open connection
  150. // to the registry, or the keyName is not specified, FALSE is returned
  151. //
  152. // Parmaters:
  153. // const TCHAR *keyName - key name to delete
  154. //
  155. // Returns:
  156. // BOOL - returns TRUE on success, FALSE on failure
  157. //
  158. BOOL CRegistry::DeleteSubKey( const LPCWSTR keyName )
  159. {
  160. if( keyName == NULL || !IsOpen() )
  161. {
  162. return FALSE;
  163. }
  164. LONG retValue;
  165. #ifdef UNICODE
  166. retValue = RegDeleteKeyW( m_regHandle, keyName );
  167. #else
  168. LPSTR lpstrKeyName;
  169. if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) )
  170. {
  171. return FALSE;
  172. }
  173. else
  174. {
  175. retValue = RegDeleteKeyA( m_regHandle, lpstrKeyName );
  176. DNFree(lpstrKeyName);
  177. }
  178. #endif // UNICODE
  179. return (retValue == ERROR_SUCCESS);
  180. }
  181. #undef DPF_MODNAME
  182. #define DPF_MODNAME "CRegistry::DeleteValue"
  183. // DeleteValue
  184. //
  185. // This function causes the value specified by the valueName parameter
  186. // to be deleted from the point in the registry this object is rooted
  187. // at, if the value exists. If the object does not have an open connection
  188. // to the registry, or the valueName is not specified, FALSE is returned
  189. //
  190. // Parmaters:
  191. // const TCHAR *keyName - key name to delete
  192. //
  193. // Returns:
  194. // BOOL - returns TRUE on success, FALSE on failure
  195. //
  196. BOOL CRegistry::DeleteValue( const LPCWSTR valueName )
  197. {
  198. if( valueName == NULL || !IsOpen() ) return FALSE;
  199. LONG retValue;
  200. #ifdef UNICODE
  201. retValue = RegDeleteValueW( m_regHandle, valueName );
  202. #else
  203. LPSTR lpstrValueName;
  204. if( FAILED( STR_AllocAndConvertToANSI( &lpstrValueName, valueName ) ) )
  205. {
  206. return FALSE;
  207. }
  208. else
  209. {
  210. retValue = RegDeleteValueA( m_regHandle, lpstrValueName );
  211. DNFree(lpstrValueName);
  212. }
  213. #endif // UNICODE
  214. return (retValue == ERROR_SUCCESS);
  215. }
  216. #undef DPF_MODNAME
  217. #define DPF_MODNAME "CRegistry::Open"
  218. // Open
  219. //
  220. // This function opens a connection to the registry in the branch
  221. // specified by branch with the path specified by pathName. If
  222. // the path doesn't exist in the registry it will be created if
  223. // the create parameters is set to true, otherwise the call will
  224. // fail.
  225. //
  226. // If this object already has an open connection to the registry
  227. // the previous connection will be closed before this one is
  228. // attempted.
  229. //
  230. // Parameters:
  231. // HKEY branch - A handle to a registry location where the open
  232. // will be rooted. E.g. HKEY_LOCAL_MACHINE
  233. // const TCHAR *path - The path relative to the root specified by
  234. // branch where the registry connection will
  235. // be opened.
  236. // BOOL create - Settings this parameter conrols how this function
  237. // handles opens on paths which don't exists. If set
  238. // to TRUE the path will be created, if set to FALSE
  239. // the function will fail if the path doesn't exist.
  240. //
  241. // Returns:
  242. // BOOL - TRUE on success, FALSE on failure.
  243. //
  244. BOOL CRegistry::Open( HKEY branch, const LPCWSTR pathName, BOOL fReadOnly, BOOL create, BOOL fCustomSAM, REGSAM samCustom )
  245. {
  246. DWORD dwResult; // Temp used in call to RegXXXX
  247. LONG result; // used to store results
  248. if( pathName == NULL )
  249. return FALSE;
  250. // If there is an open connection, close it.
  251. if( m_isOpen )
  252. {
  253. Close();
  254. }
  255. m_fReadOnly = fReadOnly;
  256. #ifdef UNICODE
  257. // Create or open the key based on create parameter
  258. if( create )
  259. {
  260. result = RegCreateKeyExW( branch, pathName, 0, NULL, REG_OPTION_NON_VOLATILE, (fCustomSAM) ? samCustom : KEY_ALL_ACCESS,
  261. NULL, &m_regHandle, &dwResult );
  262. }
  263. else
  264. {
  265. result = RegOpenKeyExW( branch, pathName, 0, (fReadOnly) ? KEY_READ : ((fCustomSAM) ? samCustom : KEY_ALL_ACCESS), &m_regHandle );
  266. }
  267. #else
  268. LPSTR lpszKeyName;
  269. if( STR_AllocAndConvertToANSI( &lpszKeyName, pathName ) == S_OK && pathName )
  270. {
  271. if( create )
  272. {
  273. result = RegCreateKeyExA( branch, lpszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  274. NULL, &m_regHandle, &dwResult );
  275. }
  276. else
  277. {
  278. result = RegOpenKeyExA( branch, lpszKeyName, 0, (fReadOnly) ? KEY_READ : KEY_ALL_ACCESS, &m_regHandle );
  279. }
  280. DNFree(lpszKeyName);
  281. }
  282. else
  283. {
  284. return FALSE;
  285. }
  286. #endif // UNICODE
  287. // If succesful, initialize object, otherwise set it to
  288. // not open state.
  289. if( result == ERROR_SUCCESS )
  290. {
  291. m_isOpen = TRUE;
  292. m_baseHandle = branch;
  293. return TRUE;
  294. }
  295. else
  296. {
  297. m_isOpen = FALSE;
  298. return FALSE;
  299. }
  300. }
  301. #undef DPF_MODNAME
  302. #define DPF_MODNAME "CRegistry::Open"
  303. // Open
  304. //
  305. // This function opens a connection to the registry in the branch
  306. // specified by branch with the path specified by pathName. If
  307. // the path doesn't exist in the registry it will be created if
  308. // the create parameters is set to true, otherwise the call will
  309. // fail.
  310. //
  311. // In this version of the function, the path is specified as
  312. // a guid instead of a string. The function will attempt to open
  313. // a key with a name in the form "{CB4961DB-D2FA-43f3-942A-991D9294DDBB}"
  314. // that corresponds to the guid as you would expect.
  315. //
  316. // If this object already has an open connection to the registry
  317. // the previous connection will be closed before this one is
  318. // attempted.
  319. //
  320. // Parameters:
  321. // HKEY branch - A handle to a registry location where the open
  322. // will be rooted. E.g. HKEY_LOCAL_MACHINE
  323. // const LPGUID lpguid - The path relative to the root specified by
  324. // branch where the registry connection will
  325. // be opened. See comment above.
  326. // BOOL create - Settings this parameter conrols how this function
  327. // handles opens on paths which don't exists. If set
  328. // to TRUE the path will be created, if set to FALSE
  329. // the function will fail if the path doesn't exist.
  330. //
  331. // Returns:
  332. // BOOL - TRUE on success, FALSE on failure.
  333. //
  334. BOOL CRegistry::Open( HKEY branch, const GUID* lpguid, BOOL fReadOnly, BOOL create, BOOL fCustomSAM, REGSAM samCustom )
  335. {
  336. WCHAR wszGuidString[GUID_STRING_LEN];
  337. DNASSERT( lpguid != NULL );
  338. // convert the guid to a string
  339. if (!StringFromGUID2(*lpguid, wszGuidString, GUID_STRING_LEN))
  340. {
  341. DPFX(DPFPREP, 0, "StringFromGUID2 failed");
  342. return FALSE;
  343. }
  344. return Open(branch, wszGuidString, fReadOnly, create, fCustomSAM, samCustom);
  345. }
  346. #undef DPF_MODNAME
  347. #define DPF_MODNAME "CRegistry::Close"
  348. // Close
  349. //
  350. // This function will close an open connection to the registry
  351. // if this object has one. Otherwise it does nothing.
  352. //
  353. // Parameters:
  354. // N/A
  355. //
  356. // Returns:
  357. // BOOL - Returns TRUE on success, FALSE on failure. If the object
  358. // is not open it will return TRUE.
  359. //
  360. BOOL CRegistry::Close()
  361. {
  362. LONG retValue;
  363. if( m_isOpen )
  364. {
  365. retValue = RegCloseKey( m_regHandle );
  366. if( retValue == ERROR_SUCCESS )
  367. {
  368. m_isOpen = FALSE;
  369. return TRUE;
  370. }
  371. else
  372. {
  373. return FALSE;
  374. }
  375. }
  376. else
  377. {
  378. return TRUE;
  379. }
  380. }
  381. #undef DPF_MODNAME
  382. #define DPF_MODNAME "CRegistry::EnumKeys"
  383. // EnumKeys
  384. //
  385. // This function can be used to enumerate the keys at the point
  386. // in the registry rooted at the root this object was opened
  387. // with, at the path specified when opening the object.
  388. //
  389. // To properly enumerate the keys you should pass 0 as the index on
  390. // the first call, and increment the index parameter by one on each
  391. // call. You can stop enumerating when the function returns FALSE.
  392. //
  393. // Parameters:
  394. // LPWSTR lpwStrName - The current key in the enumeration will be returned
  395. // in this string. Unless the enumeration fails or
  396. // ended at which case this parameter won't be touched.
  397. //
  398. // LPDWORD lpdwStringLen - pointer to length of string buffer, or place to
  399. // to store size required.
  400. //
  401. // DWORD index - The current enum index. See above for details.
  402. //
  403. // Returns:
  404. // BOOL - FALSE when enumeration is done or on error, TRUE otherwise.
  405. //
  406. BOOL CRegistry::EnumKeys( LPWSTR lpwStrName, LPDWORD lpdwStringLen, DWORD index )
  407. {
  408. #ifdef UNICODE
  409. wchar_t buffer[MAX_REGISTRY_STRING_SIZE];
  410. DWORD bufferSize = MAX_REGISTRY_STRING_SIZE;
  411. FILETIME tmpTime;
  412. if( RegEnumKeyExW( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, &tmpTime ) != ERROR_SUCCESS )
  413. {
  414. return FALSE;
  415. }
  416. else
  417. {
  418. if( bufferSize+1 > *lpdwStringLen )
  419. {
  420. *lpdwStringLen = bufferSize+1;
  421. return FALSE;
  422. }
  423. lstrcpyW( lpwStrName, buffer );
  424. *lpdwStringLen = bufferSize+1;
  425. return TRUE;
  426. }
  427. #else
  428. char buffer[MAX_REGISTRY_STRING_SIZE];
  429. DWORD bufferSize = MAX_REGISTRY_STRING_SIZE;
  430. FILETIME tmpTime;
  431. if( RegEnumKeyExA( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, &tmpTime ) != ERROR_SUCCESS )
  432. {
  433. return FALSE;
  434. }
  435. else
  436. {
  437. if( bufferSize+1 > *lpdwStringLen )
  438. {
  439. *lpdwStringLen = bufferSize+1;
  440. return FALSE;
  441. }
  442. if( FAILED( STR_jkAnsiToWide( lpwStrName, buffer, *lpdwStringLen ) ) )
  443. {
  444. return FALSE;
  445. }
  446. else
  447. {
  448. *lpdwStringLen = bufferSize+1;
  449. return TRUE;
  450. }
  451. }
  452. #endif // UNICODE
  453. }
  454. #undef DPF_MODNAME
  455. #define DPF_MODNAME "CRegistry::EnumValues"
  456. // EnumValues
  457. //
  458. // This function can be used to enumerate the values at the point
  459. // in the registry rooted at the root this object was opened
  460. // with, at the path specified when opening the object.
  461. //
  462. // To properly enumerate the values you should pass 0 as the index on
  463. // the first call, and increment the index parameter by one on each
  464. // call. You can stop enumerating when the function returns FALSE.
  465. //
  466. // Parameters:
  467. // LPWSTR lpwStrName - The current value in the enumeration will be returned
  468. // in this string. Unless the enumeration fails or
  469. // ended at which case this parameter won't be touched.
  470. //
  471. // LPDWORD lpdwStringLen - pointer to length of string buffer, or place to
  472. // to store size required.
  473. //
  474. // DWORD index - The current enum index. See above for details.
  475. //
  476. // Returns:
  477. // BOOL - FALSE when enumeration is done or on error, TRUE otherwise.
  478. //
  479. BOOL CRegistry::EnumValues( LPWSTR lpwStrName, LPDWORD lpdwStringLen, DWORD index )
  480. {
  481. #ifdef UNICODE
  482. wchar_t buffer[MAX_REGISTRY_STRING_SIZE];
  483. DWORD bufferSize = MAX_REGISTRY_STRING_SIZE;
  484. if( RegEnumValueW( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, NULL ) != ERROR_SUCCESS )
  485. {
  486. return FALSE;
  487. }
  488. else
  489. {
  490. if( bufferSize+1 > *lpdwStringLen )
  491. {
  492. *lpdwStringLen = bufferSize+1;
  493. return FALSE;
  494. }
  495. lstrcpyW( lpwStrName, buffer );
  496. *lpdwStringLen = bufferSize+1;
  497. return TRUE;
  498. }
  499. #else
  500. char buffer[MAX_REGISTRY_STRING_SIZE];
  501. DWORD bufferSize = MAX_REGISTRY_STRING_SIZE;
  502. if( RegEnumValueA( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, NULL ) != ERROR_SUCCESS )
  503. {
  504. return FALSE;
  505. }
  506. else
  507. {
  508. if( bufferSize+1 > *lpdwStringLen )
  509. {
  510. *lpdwStringLen = bufferSize+1;
  511. return FALSE;
  512. }
  513. if( FAILED( STR_jkAnsiToWide( lpwStrName, buffer, *lpdwStringLen ) ) )
  514. {
  515. return FALSE;
  516. }
  517. else
  518. {
  519. *lpdwStringLen = bufferSize+1;
  520. return TRUE;
  521. }
  522. }
  523. #endif // UNICODE
  524. }
  525. // This comment documents ALL of the Read<Data Type> functions which
  526. // follow.
  527. //
  528. // CRegistry Read<Data Type> Functions
  529. //
  530. // The set of ReadXXXXX functions for the CRegistry class are
  531. // responsible for reading <data type> type data from the registry.
  532. // The object must have an open connection to the registry before
  533. // any of these functions may be used. A connection to the registry
  534. // can be made with the Open call or the constructors.
  535. //
  536. // Parameters:
  537. // const TCHAR *keyName - The keyname of the data you wish to read
  538. // <datatype> & - A reference to the specific data type where
  539. // the data will be placed on a succesful read.
  540. // This parameter will be unaffected if the read
  541. // fails.
  542. //
  543. // Returns:
  544. // BOOL - Returns TRUE on success, FALSE on failure.
  545. //
  546. // This comment documents ALL of the Write<Data Type> functions which
  547. // follow.
  548. //
  549. // CRegistry Write<Data Type> Functions
  550. //
  551. // The set of Write<Data Type> functions for the CRegistry class are
  552. // responsible for writing <data type> type data to the registry.
  553. // The object must have an open connection to the registry before
  554. // any of these functions may be used. A connection to the registry
  555. // can be made with the Open call or the constructors.
  556. //
  557. // Parameters:
  558. // const TCHAR *keyName - The keyname of the data you wish to write
  559. // <datatype> & - A reference to the specific data type which
  560. // contains the data to be written to the registry.
  561. //
  562. // Returns:
  563. // BOOL - Returns TRUE on success, FALSE on failure.
  564. //
  565. #undef DPF_MODNAME
  566. #define DPF_MODNAME "CRegistry::WriteString"
  567. // WriteString
  568. //
  569. // Writes Strings's to the registry, see block comment above
  570. // for details.
  571. //
  572. BOOL CRegistry::WriteString( LPCWSTR keyName, const LPCWSTR lpwstrValue )
  573. {
  574. LONG retValue;
  575. if( keyName == NULL || !IsOpen() )
  576. {
  577. return FALSE;
  578. }
  579. if( m_fReadOnly )
  580. {
  581. DPFX(DPFPREP, 0, "Attempt to Write to read-only CRegistry key");
  582. return FALSE;
  583. }
  584. #ifdef UNICODE
  585. retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_SZ, (const unsigned char *) lpwstrValue, (lstrlenW( lpwstrValue )+1)*sizeof(wchar_t) );
  586. #else
  587. LPSTR lpstrKeyName;
  588. LPSTR lpstrValue;
  589. if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) )
  590. {
  591. return FALSE;
  592. }
  593. if( FAILED( STR_AllocAndConvertToANSI( &lpstrValue, lpwstrValue ) ) )
  594. {
  595. DNFree(lpstrKeyName);
  596. return FALSE;
  597. }
  598. retValue = RegSetValueExA( m_regHandle, lpstrKeyName, 0, REG_SZ, (const unsigned char *) lpstrValue, lstrlenA( lpstrValue )+1 );
  599. DNFree(lpstrKeyName);
  600. DNFree(lpstrValue);
  601. #endif // UNICODE
  602. return (retValue == ERROR_SUCCESS);
  603. }
  604. #undef DPF_MODNAME
  605. #define DPF_MODNAME "CRegistry::ReadString"
  606. // ReadString
  607. //
  608. // Reads CString's from the registry, see block comment above
  609. // for details.
  610. //
  611. BOOL CRegistry::ReadString( const LPCWSTR keyName, LPWSTR lpwstrValue, LPDWORD lpdwLength )
  612. {
  613. if( keyName == NULL || !IsOpen() )
  614. {
  615. return FALSE;
  616. }
  617. LONG retValue;
  618. DWORD tmpSize;
  619. DWORD tmpType;
  620. #ifdef UNICODE
  621. wchar_t buffer[MAX_REGISTRY_STRING_SIZE];
  622. tmpSize = MAX_REGISTRY_STRING_SIZE*sizeof(wchar_t);
  623. retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, (unsigned char *) &buffer[0], &tmpSize );
  624. if (retValue != ERROR_SUCCESS)
  625. {
  626. return FALSE;
  627. }
  628. if( (tmpSize/2) > *lpdwLength || !lpwstrValue )
  629. {
  630. *lpdwLength = (tmpSize/2);
  631. return FALSE;
  632. }
  633. lstrcpyW( lpwstrValue, buffer );
  634. *lpdwLength = (tmpSize/2);
  635. return TRUE;
  636. #else
  637. LPSTR lpstrKeyName;
  638. char buffer[MAX_REGISTRY_STRING_SIZE];
  639. tmpSize = MAX_REGISTRY_STRING_SIZE;
  640. if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) )
  641. {
  642. return FALSE;
  643. }
  644. retValue = RegQueryValueExA( m_regHandle, lpstrKeyName, 0, &tmpType, (unsigned char *) &buffer[0], &tmpSize );
  645. if (retValue != ERROR_SUCCESS)
  646. {
  647. DNFree(lpstrKeyName);
  648. return FALSE;
  649. }
  650. DNFree(lpstrKeyName);
  651. if( tmpSize > *lpdwLength || !lpwstrValue )
  652. {
  653. *lpdwLength = tmpSize;
  654. return FALSE;
  655. }
  656. if( FAILED( STR_jkAnsiToWide( lpwstrValue, buffer, *lpdwLength ) ) )
  657. {
  658. return FALSE;
  659. }
  660. *lpdwLength = tmpSize;
  661. if( retValue == ERROR_SUCCESS && tmpType == REG_SZ )
  662. {
  663. return TRUE;
  664. }
  665. else
  666. {
  667. return FALSE;
  668. }
  669. #endif // UNICODE
  670. }
  671. #undef DPF_MODNAME
  672. #define DPF_MODNAME "CRegistry::WriteGUID"
  673. // WriteGUID
  674. //
  675. // Writes GUID's to the registry, see block comment above
  676. // for details. The GUID is written in the format it is usually
  677. // displayed. (But without the '{''s).
  678. //
  679. BOOL CRegistry::WriteGUID( LPCWSTR keyName, const GUID &guid )
  680. {
  681. LONG retValue;
  682. WCHAR wszGuidString[GUID_STRING_LEN];
  683. if( m_fReadOnly )
  684. {
  685. DPFX(DPFPREP, 0, "Attempt to Write to read-only CRegistry key");
  686. return FALSE;
  687. }
  688. if (!StringFromGUID2(guid, wszGuidString, GUID_STRING_LEN))
  689. {
  690. DPFX(DPFPREP, 0, "StringFromGUID2 failed");
  691. return FALSE;
  692. }
  693. #ifdef UNICODE
  694. retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_SZ, (const unsigned char *) wszGuidString, (lstrlenW( wszGuidString )+1)*sizeof(wchar_t) );
  695. #else
  696. HRESULT hr;
  697. LPSTR lpstrKeyName;
  698. LPSTR lpstrKeyValue;
  699. hr = STR_AllocAndConvertToANSI( &lpstrKeyName, keyName );
  700. if (FAILED(hr))
  701. {
  702. DPFX(DPFPREP, 0, "STR_AllocAndConvertToANSI failed, code: 0x%08x", hr);
  703. return FALSE;
  704. }
  705. hr = STR_AllocAndConvertToANSI( &lpstrKeyValue, wszGuidString );
  706. if (FAILED(hr))
  707. {
  708. DPFX(DPFPREP, 0, "STR_AllocAndConvertToANSI failed, code: 0x%08x", hr);
  709. DNFree(lpstrKeyName);
  710. return FALSE;
  711. }
  712. retValue = RegSetValueExA( m_regHandle, lpstrKeyName, 0, REG_SZ, (const unsigned char *) lpstrKeyValue, lstrlenA( lpstrKeyValue )+1);
  713. DNFree(lpstrKeyName);
  714. DNFree(lpstrKeyValue);
  715. #endif // UNICODE
  716. if( retValue == ERROR_SUCCESS )
  717. {
  718. return TRUE;
  719. }
  720. else
  721. {
  722. return FALSE;
  723. }
  724. }
  725. #undef DPF_MODNAME
  726. #define DPF_MODNAME "CRegistry::ReadGUID"
  727. // ReadGUID
  728. //
  729. // Reads GUID's from the registry, see block comment above
  730. // for details. The GUID must be stored in the format written by
  731. // the WriteGUID function or it will not be read correctly.
  732. //
  733. BOOL CRegistry::ReadGUID( LPCWSTR keyName, GUID* pguid )
  734. {
  735. wchar_t buffer[MAX_REGISTRY_STRING_SIZE];
  736. DWORD dwLength = MAX_REGISTRY_STRING_SIZE;
  737. HRESULT hr;
  738. if( !ReadString( keyName, buffer, &dwLength ) )
  739. {
  740. return FALSE;
  741. }
  742. else
  743. {
  744. hr = CLSIDFromString(buffer, pguid);
  745. if (FAILED(hr))
  746. {
  747. DPFX(DPFPREP, 0, "CLSIDFromString failed, code: 0x%08x", hr);
  748. return FALSE;
  749. }
  750. return TRUE;
  751. }
  752. }
  753. #undef DPF_MODNAME
  754. #define DPF_MODNAME "CRegistry::WriteDWORD"
  755. // WriteDWORD
  756. //
  757. // Writes DWORDS to the registry, see block comment above
  758. // for details.
  759. //
  760. BOOL CRegistry::WriteDWORD( LPCWSTR keyName, DWORD value )
  761. {
  762. LONG retValue;
  763. if( keyName == NULL || !IsOpen() )
  764. {
  765. return FALSE;
  766. }
  767. if( m_fReadOnly )
  768. {
  769. DPFX(DPFPREP, 0, "Attempt to Write to read-only CRegistry key");
  770. return FALSE;
  771. }
  772. #ifdef UNICODE
  773. retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_DWORD, (const unsigned char *) &value, sizeof( DWORD ) );
  774. #else
  775. LPSTR lpszKeyName;
  776. if( FAILED( STR_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) )
  777. {
  778. return FALSE;
  779. }
  780. retValue = RegSetValueExA( m_regHandle, lpszKeyName, 0, REG_DWORD, (const unsigned char *) &value, sizeof( DWORD ) );
  781. DNFree(lpszKeyName);
  782. #endif // UNICODE
  783. return (retValue == ERROR_SUCCESS);
  784. }
  785. #undef DPF_MODNAME
  786. #define DPF_MODNAME "CRegistry::ReadDWORD"
  787. // ReadDWORD
  788. //
  789. // Reads DWORDS from the registry, see block comment above
  790. // for details.
  791. //
  792. BOOL CRegistry::ReadDWORD( LPCWSTR keyName, DWORD* presult )
  793. {
  794. if( keyName == NULL || !IsOpen() )
  795. {
  796. return FALSE;
  797. }
  798. LONG retValue;
  799. DWORD tmpValue;
  800. DWORD tmpType;
  801. DWORD tmpSize;
  802. tmpSize = sizeof( DWORD );
  803. #ifdef UNICODE
  804. retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, (unsigned char *) &tmpValue, &tmpSize );
  805. #else
  806. LPSTR lpszKeyName;
  807. if( FAILED( STR_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) )
  808. {
  809. return FALSE;
  810. }
  811. retValue = RegQueryValueExA( m_regHandle, lpszKeyName, 0, &tmpType, (unsigned char *) &tmpValue, &tmpSize );
  812. DNFree(lpszKeyName);
  813. #endif // UNICODE
  814. if( retValue == ERROR_SUCCESS && (tmpType == REG_DWORD || tmpType == REG_BINARY) && tmpSize == sizeof(DWORD) )
  815. {
  816. *presult = tmpValue;
  817. return TRUE;
  818. }
  819. else
  820. {
  821. return FALSE;
  822. }
  823. }
  824. #ifndef DPNBUILD_NOCOMREGISTER
  825. #undef DPF_MODNAME
  826. #define DPF_MODNAME "CRegistry::Register"
  827. BOOL CRegistry::Register( LPCWSTR lpszProgID, const LPCWSTR lpszDesc, const LPCWSTR lpszProgName, const GUID* pguidCLSID, LPCWSTR lpszVerIndProgID )
  828. {
  829. CRegistry core;
  830. DNASSERT( lpszDesc != NULL );
  831. DNASSERT( lpszProgID != NULL );
  832. // Build a string representation of the GUID from the GUID
  833. wchar_t lpszGUID[GUID_STRING_LEN];
  834. wchar_t lpszKeyName[_MAX_PATH];
  835. // convert the guid to a string
  836. if (!StringFromGUID2(*pguidCLSID, lpszGUID, GUID_STRING_LEN))
  837. {
  838. DPFX(DPFPREP, 0, "StringFromGUID2 failed");
  839. return FALSE;
  840. }
  841. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID} section
  842. swprintf( lpszKeyName, L"CLSID\\%s", lpszGUID );
  843. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) )
  844. {
  845. DPFX(DPFPREP, 0, "Unable to open/create registry key \"%ls\"", lpszKeyName );
  846. return FALSE;
  847. }
  848. core.WriteString( L"", lpszDesc );
  849. core.Close();
  850. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\InProcServer32 section
  851. swprintf( lpszKeyName, L"CLSID\\%s\\InProcServer32", lpszGUID );
  852. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) )
  853. {
  854. DPFX(DPFPREP, 0, "Unable to open/create registry key \"%ls\"", lpszKeyName );
  855. return FALSE;
  856. }
  857. core.WriteString( L"", lpszProgName );
  858. core.WriteString( L"ThreadingModel", L"Both" );
  859. core.Close();
  860. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\VersionIndependentProgID section
  861. if( lpszVerIndProgID != NULL )
  862. {
  863. swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
  864. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) )
  865. {
  866. DPFX(DPFPREP, 0, "Unable to open/create verind registry key \"%ls\"", lpszKeyName );
  867. return FALSE;
  868. }
  869. core.WriteString( L"", lpszVerIndProgID );
  870. core.Close();
  871. }
  872. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\ProgID section
  873. swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
  874. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) )
  875. {
  876. DPFX(DPFPREP, 0, "Unable to open/create verind registry key \"%ls\"", lpszKeyName );
  877. return FALSE;
  878. }
  879. core.WriteString( L"", lpszProgID );
  880. core.Close();
  881. // Write The VersionIND ProgID
  882. if( lpszVerIndProgID != NULL )
  883. {
  884. if( !core.Open( HKEY_CLASSES_ROOT, lpszVerIndProgID, FALSE, TRUE ) )
  885. {
  886. DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszVerIndProgID );
  887. }
  888. else
  889. {
  890. core.WriteString( L"", lpszDesc );
  891. core.Close();
  892. }
  893. swprintf( lpszKeyName, L"%s\\CLSID", lpszVerIndProgID );
  894. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) )
  895. {
  896. DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszKeyName );
  897. }
  898. else
  899. {
  900. core.WriteString( L"", lpszGUID );
  901. core.Close();
  902. }
  903. swprintf( lpszKeyName, L"%s\\CurVer", lpszVerIndProgID );
  904. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) )
  905. {
  906. DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszKeyName );
  907. }
  908. else
  909. {
  910. core.WriteString( L"", lpszProgID );
  911. core.Close();
  912. }
  913. }
  914. if( !core.Open( HKEY_CLASSES_ROOT, lpszProgID, FALSE, TRUE ) )
  915. {
  916. DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszKeyName );
  917. }
  918. else
  919. {
  920. core.WriteString( L"", lpszDesc );
  921. core.Close();
  922. }
  923. swprintf( lpszKeyName, L"%s\\CLSID", lpszProgID );
  924. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, TRUE ) )
  925. {
  926. DPFX(DPFPREP, 0, "Unable to open/create reg key \"%ls\"", lpszKeyName );
  927. }
  928. else
  929. {
  930. core.WriteString( L"", lpszGUID );
  931. core.Close();
  932. }
  933. return TRUE;
  934. }
  935. #undef DPF_MODNAME
  936. #define DPF_MODNAME "CRegistry::UnRegister"
  937. BOOL CRegistry::UnRegister( const GUID* pguidCLSID )
  938. {
  939. CRegistry core, cregClasses, cregSub;
  940. // Build a string representation of the GUID from the GUID
  941. wchar_t lpszGUID[GUID_STRING_LEN];
  942. wchar_t lpszKeyName[_MAX_PATH];
  943. wchar_t szProgID[MAX_REGISTRY_STRING_SIZE];
  944. wchar_t szVerIndProgID[MAX_REGISTRY_STRING_SIZE];
  945. DWORD dwSize = MAX_REGISTRY_STRING_SIZE;
  946. // convert the guid to a string
  947. if (!StringFromGUID2(*pguidCLSID, lpszGUID, GUID_STRING_LEN))
  948. {
  949. DPFX(DPFPREP, 0, "StringFromGUID2 failed");
  950. return FALSE;
  951. }
  952. if( !cregClasses.Open( HKEY_CLASSES_ROOT, L"", FALSE, FALSE ) )
  953. {
  954. DPFX(DPFPREP, 0, "Unable to open HKEY_CLASSES_ROOT" );
  955. return FALSE;
  956. }
  957. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID} section
  958. swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
  959. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, FALSE ) )
  960. {
  961. DPFX(DPFPREP, 0, "Unable to open \"%ls\"", lpszKeyName );
  962. return FALSE;
  963. }
  964. dwSize = MAX_REGISTRY_STRING_SIZE;
  965. if( core.ReadString( L"", szProgID, &dwSize ) )
  966. {
  967. swprintf( lpszKeyName, L"%s\\CLSID", szProgID );
  968. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  969. {
  970. DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName );
  971. return FALSE;
  972. }
  973. if( !cregClasses.DeleteSubKey( szProgID ) )
  974. {
  975. DPFX(DPFPREP, 0, "Unable to delete HKEY_CLASSES_ROOT/ProgID" );
  976. return FALSE;
  977. }
  978. }
  979. core.Close();
  980. swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
  981. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName, FALSE, FALSE ) )
  982. {
  983. DPFX(DPFPREP, 0, "Unable to open \"%ls\"", lpszKeyName );
  984. return FALSE;
  985. }
  986. dwSize = MAX_REGISTRY_STRING_SIZE;
  987. if( core.ReadString( L"", szVerIndProgID, &dwSize ) )
  988. {
  989. swprintf( lpszKeyName, L"%s\\CLSID", szVerIndProgID );
  990. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  991. {
  992. DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName );
  993. return FALSE;
  994. }
  995. swprintf( lpszKeyName, L"%s\\CurVer", szVerIndProgID );
  996. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  997. {
  998. DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName );
  999. return FALSE;
  1000. }
  1001. if( !cregClasses.DeleteSubKey( szVerIndProgID ) )
  1002. {
  1003. DPFX(DPFPREP, 0, "Unable to delete \"HKEY_CLASSES_ROOT/%ls\"", szVerIndProgID);
  1004. return FALSE;
  1005. }
  1006. }
  1007. core.Close();
  1008. swprintf( lpszKeyName, L"CLSID\\%s\\InprocServer32", lpszGUID );
  1009. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  1010. {
  1011. DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName );
  1012. return FALSE;
  1013. }
  1014. swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
  1015. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  1016. {
  1017. DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName );
  1018. return FALSE;
  1019. }
  1020. swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
  1021. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  1022. {
  1023. DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName );
  1024. return FALSE;
  1025. }
  1026. swprintf( lpszKeyName, L"CLSID\\%s", lpszGUID );
  1027. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  1028. {
  1029. DPFX(DPFPREP, 0, "Unable to delete \"%ls\"", lpszKeyName );
  1030. return FALSE;
  1031. }
  1032. return TRUE;
  1033. }
  1034. #endif // !DPNBUILD_NOCOMREGISTER
  1035. #undef DPF_MODNAME
  1036. #define DPF_MODNAME "CRegistry::ReadBlob"
  1037. BOOL CRegistry::ReadBlob( LPCWSTR keyName, LPBYTE lpbBuffer, LPDWORD lpdwSize )
  1038. {
  1039. if( keyName == NULL || !IsOpen() ) return FALSE;
  1040. LONG retValue;
  1041. DWORD tmpType;
  1042. #ifdef UNICODE
  1043. retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, lpbBuffer, lpdwSize );
  1044. #else
  1045. LPSTR lpszKeyName;
  1046. if( FAILED( STR_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) )
  1047. {
  1048. return FALSE;
  1049. }
  1050. retValue = RegQueryValueExA( m_regHandle, lpszKeyName, 0, &tmpType, lpbBuffer, lpdwSize );
  1051. DNFree(lpszKeyName);
  1052. #endif // UNICODE
  1053. if( retValue == ERROR_SUCCESS && tmpType == REG_BINARY )
  1054. {
  1055. return TRUE;
  1056. }
  1057. else
  1058. {
  1059. return FALSE;
  1060. }
  1061. }
  1062. #undef DPF_MODNAME
  1063. #define DPF_MODNAME "CRegistry::WriteBlob"
  1064. BOOL CRegistry::WriteBlob( LPCWSTR keyName, const BYTE* const lpbBuffer, DWORD dwSize )
  1065. {
  1066. LONG retValue;
  1067. if( keyName == NULL || !IsOpen() )
  1068. {
  1069. return FALSE;
  1070. }
  1071. if( m_fReadOnly )
  1072. {
  1073. DPFX(DPFPREP, 0, "Attempt to Write to read-only CRegistry key");
  1074. return FALSE;
  1075. }
  1076. #ifdef UNICODE
  1077. retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_BINARY, lpbBuffer, dwSize );
  1078. #else
  1079. LPSTR lpszKeyName;
  1080. if( FAILED( STR_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) )
  1081. return FALSE;
  1082. retValue = RegSetValueExA( m_regHandle, lpszKeyName, 0, REG_BINARY, lpbBuffer, dwSize );
  1083. DNFree(lpszKeyName);
  1084. #endif // UNICODE
  1085. return (retValue == ERROR_SUCCESS);
  1086. }
  1087. #undef DPF_MODNAME
  1088. #define DPF_MODNAME "CRegistry::GetMaxKeyLen"
  1089. BOOL CRegistry::GetMaxKeyLen( DWORD* pdwMaxKeyLen )
  1090. {
  1091. LONG retVal;
  1092. #ifdef UNICODE
  1093. retVal = RegQueryInfoKeyW( m_regHandle,NULL,NULL,NULL,NULL,pdwMaxKeyLen,
  1094. NULL,NULL,NULL,NULL,NULL,NULL);
  1095. #else
  1096. retVal = RegQueryInfoKeyA( m_regHandle,NULL,NULL,NULL,NULL,pdwMaxKeyLen,
  1097. NULL,NULL,NULL,NULL,NULL,NULL);
  1098. #endif // UNICODE
  1099. return (retVal == ERROR_SUCCESS);
  1100. }
  1101. #undef DPF_MODNAME
  1102. #define DPF_MODNAME "CRegistry::GetValueLength"
  1103. // GetValueLength
  1104. //
  1105. // Determines the length of a particular key value
  1106. //
  1107. BOOL CRegistry::GetValueLength( const LPCWSTR keyName, DWORD *const pdwValueLength )
  1108. {
  1109. LONG retValue;
  1110. DWORD tmpLength;
  1111. if ( keyName == NULL || pdwValueLength == NULL || !IsOpen() )
  1112. {
  1113. return FALSE;
  1114. }
  1115. #ifdef UNICODE
  1116. DWORD dwType;
  1117. retValue = RegQueryValueExW( m_regHandle, keyName, 0, &dwType, NULL, &tmpLength );
  1118. if (retValue != ERROR_SUCCESS)
  1119. {
  1120. return FALSE;
  1121. }
  1122. //
  1123. // if this is a string, we need to compensate for WCHAR characters being
  1124. // returned
  1125. //
  1126. if ( dwType == REG_SZ )
  1127. {
  1128. tmpLength /= sizeof( WCHAR );
  1129. }
  1130. #else
  1131. LPSTR lpstrKeyName;
  1132. if( FAILED( STR_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) )
  1133. {
  1134. return FALSE;
  1135. }
  1136. retValue = RegQueryValueExA( m_regHandle, lpstrKeyName, 0, NULL, NULL, &tmpLength );
  1137. DNFree(lpstrKeyName);
  1138. if (retValue != ERROR_SUCCESS)
  1139. {
  1140. return FALSE;
  1141. }
  1142. #endif // UNICODE
  1143. *pdwValueLength = tmpLength;
  1144. return TRUE;
  1145. }
  1146. #ifdef WINNT
  1147. #undef DPF_MODNAME
  1148. #define DPF_MODNAME "CRegistry::GrantAllAccessSecurityPermissions"
  1149. // GrantAllAccessSecurityPermissions
  1150. //
  1151. // Gives the given key all access for everyone rights
  1152. //
  1153. // Taken from hresMumbleKeyEx in diregutl.c in the dinput tree.
  1154. //
  1155. BOOL CRegistry::GrantAllAccessSecurityPermissions()
  1156. {
  1157. BOOL fResult = FALSE;
  1158. HRESULT hr;
  1159. EXPLICIT_ACCESS ExplicitAccess;
  1160. PACL pACL = NULL;
  1161. PSID pSid = NULL;
  1162. HMODULE hModuleADVAPI32 = NULL;
  1163. SID_IDENTIFIER_AUTHORITY authority = SECURITY_WORLD_SID_AUTHORITY;
  1164. PALLOCATEANDINITIALIZESID pAllocateAndInitializeSid = NULL;
  1165. PBUILDTRUSTEEWITHSID pBuildTrusteeWithSid = NULL;
  1166. PSETENTRIESINACL pSetEntriesInAcl = NULL;
  1167. PSETSECURITYINFO pSetSecurityInfo = NULL;
  1168. PFREESID pFreeSid = NULL;
  1169. hModuleADVAPI32 = LoadLibrary( _T("advapi32.dll") );
  1170. if( !hModuleADVAPI32 )
  1171. {
  1172. DPFX(DPFPREP, 0, "Failed loading advapi32.dll" );
  1173. goto EXIT;
  1174. }
  1175. pFreeSid = reinterpret_cast<PFREESID>( GetProcAddress( hModuleADVAPI32, "FreeSid" ) );
  1176. pSetSecurityInfo = reinterpret_cast<PSETSECURITYINFO>( GetProcAddress( hModuleADVAPI32, "SetSecurityInfo" ) );
  1177. pSetEntriesInAcl = reinterpret_cast<PSETENTRIESINACL>( GetProcAddress( hModuleADVAPI32, "SetEntriesInAclA" ) );
  1178. pBuildTrusteeWithSid = reinterpret_cast<PBUILDTRUSTEEWITHSID>( GetProcAddress( hModuleADVAPI32, "BuildTrusteeWithSidA" ) );
  1179. pAllocateAndInitializeSid = reinterpret_cast<PALLOCATEANDINITIALIZESID>( GetProcAddress( hModuleADVAPI32, "AllocateAndInitializeSid" ) );
  1180. if( !pFreeSid || !pSetSecurityInfo || !pSetEntriesInAcl || !pBuildTrusteeWithSid || !pAllocateAndInitializeSid )
  1181. {
  1182. DPFX(DPFPREP, 0, "Failed loading entry points" );
  1183. goto EXIT;
  1184. }
  1185. // Describe the access we want to create the key with
  1186. ZeroMemory (&ExplicitAccess, sizeof(ExplicitAccess) );
  1187. ExplicitAccess.grfAccessPermissions = ((KEY_ALL_ACCESS & ~WRITE_DAC) & ~WRITE_OWNER);
  1188. /*KEY_QUERY_VALUE | KEY_SET_VALUE
  1189. | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS
  1190. | KEY_NOTIFY | KEY_CREATE_LINK
  1191. | DELETE | READ_CONTROL; */
  1192. ExplicitAccess.grfAccessMode = SET_ACCESS; // discard any existing AC info
  1193. ExplicitAccess.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  1194. if (pAllocateAndInitializeSid(
  1195. &authority,
  1196. 1,
  1197. SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0,
  1198. &pSid
  1199. ))
  1200. {
  1201. pBuildTrusteeWithSid(&(ExplicitAccess.Trustee), pSid );
  1202. hr = pSetEntriesInAcl( 1, &ExplicitAccess, NULL, &pACL );
  1203. if( hr == ERROR_SUCCESS )
  1204. {
  1205. hr = pSetSecurityInfo( m_regHandle, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL );
  1206. if( FAILED( hr ) )
  1207. {
  1208. DPFX(DPFPREP, 0, "Unable to set security for key. Error! hr=0x%x", hr );
  1209. }
  1210. else
  1211. {
  1212. fResult = TRUE;
  1213. }
  1214. }
  1215. else
  1216. {
  1217. DPFX(DPFPREP, 0, "SetEntriesInACL failed, hr=0x%x", hr );
  1218. }
  1219. }
  1220. else
  1221. {
  1222. hr = GetLastError();
  1223. DPFX(DPFPREP, 0, "AllocateAndInitializeSid failed lastError=0x%x", hr );
  1224. }
  1225. EXIT:
  1226. if( pACL )
  1227. {
  1228. LocalFree( pACL );
  1229. }
  1230. //Cleanup pSid
  1231. if (pSid != NULL)
  1232. {
  1233. (pFreeSid)(pSid);
  1234. }
  1235. if( hModuleADVAPI32 )
  1236. {
  1237. FreeLibrary( hModuleADVAPI32 );
  1238. }
  1239. return fResult;
  1240. }
  1241. #endif // WINNT
  1242. #ifdef WINNT
  1243. #undef DPF_MODNAME
  1244. #define DPF_MODNAME "CRegistry::RemoveAllAccessSecurityPermissions"
  1245. // RemoveAllAccessSecurityPermissions
  1246. //
  1247. // Removes "all access for everyone" rights from the specified key.
  1248. // This is identical to GrantAllAccessSecurityPermissions(), except that
  1249. // now we REVOKE_ACCESS instead of SET_ACCESS, and we don't have to fill
  1250. // out the rest of the EXPLICIT_ACCESS struct.
  1251. //
  1252. //
  1253. BOOL CRegistry::RemoveAllAccessSecurityPermissions()
  1254. {
  1255. BOOL fResult = FALSE;
  1256. HRESULT hr;
  1257. EXPLICIT_ACCESS ExplicitAccess;
  1258. PACL pACL = NULL;
  1259. PSID pSid = NULL;
  1260. HMODULE hModuleADVAPI32 = NULL;
  1261. SID_IDENTIFIER_AUTHORITY authority = SECURITY_WORLD_SID_AUTHORITY;
  1262. PALLOCATEANDINITIALIZESID pAllocateAndInitializeSid = NULL;
  1263. PBUILDTRUSTEEWITHSID pBuildTrusteeWithSid = NULL;
  1264. PSETENTRIESINACL pSetEntriesInAcl = NULL;
  1265. PSETSECURITYINFO pSetSecurityInfo = NULL;
  1266. PFREESID pFreeSid = NULL;
  1267. hModuleADVAPI32 = LoadLibrary( _T("advapi32.dll") );
  1268. if( !hModuleADVAPI32 )
  1269. {
  1270. DPFX(DPFPREP, 0, "Failed loading advapi32.dll" );
  1271. goto EXIT;
  1272. }
  1273. pFreeSid = reinterpret_cast<PFREESID>( GetProcAddress( hModuleADVAPI32, "FreeSid" ) );
  1274. pSetSecurityInfo = reinterpret_cast<PSETSECURITYINFO>( GetProcAddress( hModuleADVAPI32, "SetSecurityInfo" ) );
  1275. pSetEntriesInAcl = reinterpret_cast<PSETENTRIESINACL>( GetProcAddress( hModuleADVAPI32, "SetEntriesInAclA" ) );
  1276. pBuildTrusteeWithSid = reinterpret_cast<PBUILDTRUSTEEWITHSID>( GetProcAddress( hModuleADVAPI32, "BuildTrusteeWithSidA" ) );
  1277. pAllocateAndInitializeSid = reinterpret_cast<PALLOCATEANDINITIALIZESID>( GetProcAddress( hModuleADVAPI32, "AllocateAndInitializeSid" ) );
  1278. if( !pFreeSid || !pSetSecurityInfo || !pSetEntriesInAcl || !pBuildTrusteeWithSid || !pAllocateAndInitializeSid )
  1279. {
  1280. DPFX(DPFPREP, 0, "Failed loading entry points" );
  1281. goto EXIT;
  1282. }
  1283. ZeroMemory (&ExplicitAccess, sizeof(ExplicitAccess) );
  1284. ExplicitAccess.grfAccessMode = REVOKE_ACCESS; //Remove any existing ACEs for the specified trustee
  1285. if (pAllocateAndInitializeSid(
  1286. &authority,
  1287. 1,
  1288. SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, // trustee is "Everyone"
  1289. &pSid
  1290. ))
  1291. {
  1292. pBuildTrusteeWithSid(&(ExplicitAccess.Trustee), pSid );
  1293. hr = pSetEntriesInAcl( 1, &ExplicitAccess, NULL, &pACL );
  1294. if( hr == ERROR_SUCCESS )
  1295. {
  1296. hr = pSetSecurityInfo( m_regHandle, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL );
  1297. if( FAILED( hr ) )
  1298. {
  1299. DPFX(DPFPREP, 0, "Unable to set security for key. Error! hr=0x%x", hr );
  1300. }
  1301. else
  1302. {
  1303. fResult = TRUE;
  1304. }
  1305. }
  1306. else
  1307. {
  1308. DPFX(DPFPREP, 0, "SetEntriesInACL failed, hr=0x%x", hr );
  1309. }
  1310. }
  1311. else
  1312. {
  1313. hr = GetLastError();
  1314. DPFX(DPFPREP, 0, "AllocateAndInitializeSid failed lastError=0x%x", hr );
  1315. }
  1316. EXIT:
  1317. if( pACL )
  1318. {
  1319. LocalFree( pACL );
  1320. }
  1321. //Cleanup pSid
  1322. if (pSid != NULL)
  1323. {
  1324. (pFreeSid)(pSid);
  1325. }
  1326. if( hModuleADVAPI32 )
  1327. {
  1328. FreeLibrary( hModuleADVAPI32 );
  1329. }
  1330. return fResult;
  1331. }
  1332. #endif // WINNT
  1333. #endif // ! DPNBUILD_NOREGISTRY