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.

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