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.

1110 lines
28 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. * 03/07/2001 rodtoll WINBUG #228288 - PREFIX bug
  23. ***************************************************************************/
  24. #include "stdafx.h"
  25. #include "creg.h"
  26. #include "dndbg.h"
  27. //#include "OSInd.h"
  28. #include "dvosal.h"
  29. #include "guidutil.h"
  30. #define MODULE_ID CREGISTRY
  31. #undef DPF_MODNAME
  32. #define DPF_MODNAME "CRegistry::CRegistry"
  33. // CRegistry Constructor
  34. //
  35. // This is the default constructor for the registry class. It
  36. // is used to construct a registry object which has not yet
  37. // opened a handle to the registry. Open must be called before
  38. // this object can be used.
  39. //
  40. // Parameters:
  41. // N/A
  42. //
  43. // Returns:
  44. // N/A
  45. //
  46. CRegistry::CRegistry( ): m_isOpen(FALSE)
  47. {
  48. }
  49. #undef DPF_MODNAME
  50. #define DPF_MODNAME "CRegistry::CRegistry"
  51. // CRegistry Copy Constructor
  52. //
  53. // This is the copy constructor for the class which attempts to
  54. // open a new registry handle at the same point in the registry
  55. // as the registry parameter. You must check the IsOpen function
  56. // to see if the object was succesfully initialized.
  57. //
  58. // Parameters:
  59. // const CRegistry &registry - The registry object to set this
  60. // object to
  61. //
  62. // Returns:
  63. // N/A
  64. //
  65. /*
  66. CRegistry::CRegistry( const CRegistry &registry ): m_isOpen(FALSE)
  67. {
  68. Open( registry.GetBaseHandle(), FALSE );
  69. }
  70. */
  71. #undef DPF_MODNAME
  72. #define DPF_MODNAME "CRegistry::CRegistry"
  73. // CRegistry Constructor
  74. //
  75. // This constructor attempts to open a registry connection using
  76. // the given parameters. This is equivalent to calling the default
  77. // constructor and then Open with the equivalent parameters.
  78. //
  79. // After using this constructor you should call IsOpen to see if
  80. // the open succeeded.
  81. //
  82. // Parameters:
  83. // HKEY branch - Identifies the branch of the registry to open
  84. // a connect to. E.g. HKEY_LOCAL_MACHINE
  85. // This can also be an HKEY which points to another
  86. // open portion of the registry
  87. // const TCHAR *pathName - A string specifiying the registry path
  88. // to open within the key. NO leading
  89. // slash is required and path is relative
  90. // from the patch represented by the branch
  91. // parameter.
  92. // BOOL create - Set to TRUE to create the given path if it doesn't
  93. // exist, FALSE otherwise.
  94. //
  95. // Returns:
  96. // N/A
  97. //
  98. CRegistry::CRegistry( HKEY branch, LPWSTR pathName, BOOL create ): m_isOpen(FALSE) {
  99. Open( branch, pathName, create );
  100. }
  101. // CRegistry Destructor
  102. //
  103. // This is the destructor for the class, and will close the connection
  104. // to the registry if this object has one open.
  105. //
  106. // Parameters:
  107. // N/A
  108. //
  109. // Returns:
  110. // N/A
  111. //
  112. CRegistry::~CRegistry() {
  113. if( m_isOpen ) {
  114. Close();
  115. }
  116. }
  117. #undef DPF_MODNAME
  118. #define DPF_MODNAME "CRegistry::DeleteSubKey"
  119. // DeleteSubKey
  120. //
  121. // This function causes the key specified by the keyname parameter
  122. // to be deleted from the point in the registry this object is rooted
  123. // at, if the key exists. If the object does not have an open connection
  124. // to the registry, or the keyName is not specified
  125. //
  126. // Parmaters:
  127. // const TCHAR *keyName - key name to delete
  128. //
  129. // Returns:
  130. // BOOL - returns TRUE on success, FALSE on failure
  131. //
  132. BOOL CRegistry::DeleteSubKey( const LPCWSTR keyName ) {
  133. if( keyName == NULL || !IsOpen() ) return FALSE;
  134. LONG retValue;
  135. if( OSAL_IsUnicodePlatform() )
  136. {
  137. retValue = RegDeleteKeyW( m_regHandle, keyName );
  138. }
  139. else
  140. {
  141. LPSTR lpstrKeyName;
  142. if( FAILED( OSAL_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) )
  143. {
  144. return FALSE;
  145. }
  146. else
  147. {
  148. retValue = RegDeleteKeyA( m_regHandle, lpstrKeyName );
  149. delete [] lpstrKeyName;
  150. }
  151. }
  152. return (retValue == ERROR_SUCCESS);
  153. }
  154. #undef DPF_MODNAME
  155. #define DPF_MODNAME "CRegistry::Open"
  156. // Open
  157. //
  158. // This function opens a connection to the registry in the branch
  159. // specified by branch with the path specified by pathName. If
  160. // the path doesn't exist in the registry it will be created if
  161. // the create parameters is set to true, otherwise the call will
  162. // fail.
  163. //
  164. // If this object already has an open connection to the registry
  165. // the previous connection will be closed before this one is
  166. // attempted.
  167. //
  168. // Parameters:
  169. // HKEY branch - A handle to a registry location where the open
  170. // will be rooted. E.g. HKEY_LOCAL_MACHINE
  171. // const TCHAR *path - The path relative to the root specified by
  172. // branch where the registry connection will
  173. // be opened.
  174. // BOOL create - Settings this parameter conrols how this function
  175. // handles opens on paths which don't exists. If set
  176. // to TRUE the path will be created, if set to FALSE
  177. // the function will fail if the path doesn't exist.
  178. //
  179. // Returns:
  180. // BOOL - TRUE on success, FALSE on failure.
  181. //
  182. BOOL CRegistry::Open( HKEY branch, const LPCWSTR pathName, BOOL create ) {
  183. DWORD dwResult; // Temp used in call to RegXXXX
  184. LONG result; // used to store results
  185. DNASSERT( pathName != NULL );
  186. // Prefix found this. Ref Manbugs 29337
  187. // There are some code paths where the pathName can legitimately be NULL,
  188. // returning FALSE indicates a failure to open the registry key.
  189. if( pathName == NULL )
  190. {
  191. return FALSE;
  192. }
  193. // If there is an open connection, close it.
  194. if( m_isOpen ) {
  195. Close();
  196. }
  197. if( OSAL_IsUnicodePlatform() )
  198. {
  199. // Create or open the key based on create parameter
  200. if( create ) {
  201. result = RegCreateKeyExW( branch, pathName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  202. NULL, &m_regHandle, &dwResult );
  203. } else {
  204. result = RegOpenKeyExW( branch, pathName, 0, KEY_ALL_ACCESS, &m_regHandle );
  205. }
  206. }
  207. else
  208. {
  209. LPSTR lpszKeyName;
  210. if( OSAL_AllocAndConvertToANSI( &lpszKeyName, pathName ) == S_OK )
  211. {
  212. if( create ) {
  213. result = RegCreateKeyExA( branch, lpszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  214. NULL, &m_regHandle, &dwResult );
  215. } else {
  216. result = RegOpenKeyExA( branch, lpszKeyName, 0, KEY_ALL_ACCESS, &m_regHandle );
  217. }
  218. delete [] lpszKeyName;
  219. }
  220. else
  221. {
  222. return FALSE;
  223. }
  224. }
  225. // If succesful, initialize object, otherwise set it to
  226. // not open state.
  227. if( result == ERROR_SUCCESS ) {
  228. m_isOpen = TRUE;
  229. m_baseHandle = branch;
  230. return TRUE;
  231. } else {
  232. m_isOpen = FALSE;
  233. return FALSE;
  234. }
  235. }
  236. #undef DPF_MODNAME
  237. #define DPF_MODNAME "CRegistry::Open"
  238. // Open
  239. //
  240. // This function opens a connection to the registry in the branch
  241. // specified by branch with the path specified by pathName. If
  242. // the path doesn't exist in the registry it will be created if
  243. // the create parameters is set to true, otherwise the call will
  244. // fail.
  245. //
  246. // In this version of the function, the path is specified as
  247. // a guid instead of a string. The function will attempt to open
  248. // a key with a name in the form "{CB4961DB-D2FA-43f3-942A-991D9294DDBB}"
  249. // that corresponds to the guid as you would expect.
  250. //
  251. // If this object already has an open connection to the registry
  252. // the previous connection will be closed before this one is
  253. // attempted.
  254. //
  255. // Parameters:
  256. // HKEY branch - A handle to a registry location where the open
  257. // will be rooted. E.g. HKEY_LOCAL_MACHINE
  258. // const LPGUID lpguid - The path relative to the root specified by
  259. // branch where the registry connection will
  260. // be opened. See comment above.
  261. // BOOL create - Settings this parameter controls how this function
  262. // handles opens on paths which don't exist. If set
  263. // to TRUE the path will be created, if set to FALSE
  264. // the function will fail if the path doesn't exist.
  265. //
  266. // Returns:
  267. // BOOL - TRUE on success, FALSE on failure.
  268. //
  269. BOOL CRegistry::Open( HKEY branch, const GUID* lpguid, BOOL create )
  270. {
  271. WCHAR wszGuidString[GUID_STRING_LEN];
  272. HRESULT hr;
  273. DNASSERT( lpguid != NULL );
  274. // If there is an open connection, close it.
  275. if( m_isOpen ) {
  276. Close();
  277. }
  278. // convert the guid to a string
  279. hr = DVStringFromGUID(lpguid, wszGuidString, GUID_STRING_LEN);
  280. if (FAILED(hr))
  281. {
  282. DPF(DVF_ERRORLEVEL, "DVStringFromGUID failed");
  283. return FALSE;
  284. }
  285. return Open(branch, wszGuidString, create);
  286. }
  287. #undef DPF_MODNAME
  288. #define DPF_MODNAME "CRegistry::Close"
  289. // Close
  290. //
  291. // This function will close an open connection to the registry
  292. // if this object has one. Otherwise it does nothing.
  293. //
  294. // Parameters:
  295. // N/A
  296. //
  297. // Returns:
  298. // BOOL - Returns TRUE on success, FALSE on failure. If the object
  299. // is not open it will return TRUE.
  300. //
  301. BOOL CRegistry::Close() {
  302. LONG retValue;
  303. if( m_isOpen ) {
  304. retValue = RegCloseKey( m_regHandle );
  305. if( retValue == ERROR_SUCCESS )
  306. {
  307. m_isOpen = FALSE;
  308. return TRUE;
  309. }
  310. else
  311. {
  312. return FALSE;
  313. }
  314. } else {
  315. return TRUE;
  316. }
  317. }
  318. #undef DPF_MODNAME
  319. #define DPF_MODNAME "CRegistry::EnumKeys"
  320. // EnumKeys
  321. //
  322. // This function can be used to enumerate the keys at the point
  323. // in the registry rooted at the root this object was opened
  324. // with, at the path specified when opening the object.
  325. //
  326. // To properly enumerate the keys you should pass 0 as the index on
  327. // the first call, and increment the index parameter by one on each
  328. // call. You can stop enumerating when the function returns FALSE.
  329. //
  330. // Parameters:
  331. // BFC_STRING &name - The current key in the enumeration will be returned
  332. // in this string. Unless the enumeration fails or
  333. // ended at which case this parameter won't be touched.
  334. //
  335. // DWORD index - The current enum index. See above for details.
  336. //
  337. // Returns:
  338. // BOOL - FALSE when enumeration is done or on error, TRUE otherwise.
  339. //
  340. BOOL CRegistry::EnumKeys( LPWSTR lpwStrName, LPDWORD lpdwStringLen, DWORD index )
  341. {
  342. if( OSAL_IsUnicodePlatform() )
  343. {
  344. wchar_t buffer[MAX_REGISTRY_STRING_SIZE];
  345. DWORD bufferSize = MAX_REGISTRY_STRING_SIZE;
  346. FILETIME tmpTime;
  347. if( RegEnumKeyExW( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, &tmpTime ) != ERROR_SUCCESS )
  348. {
  349. return FALSE;
  350. }
  351. else
  352. {
  353. if( bufferSize+1 > *lpdwStringLen )
  354. {
  355. *lpdwStringLen = bufferSize+1;
  356. return FALSE;
  357. }
  358. lstrcpyW( lpwStrName, buffer );
  359. *lpdwStringLen = bufferSize+1;
  360. return TRUE;
  361. }
  362. }
  363. else
  364. {
  365. char buffer[MAX_REGISTRY_STRING_SIZE];
  366. DWORD bufferSize = MAX_REGISTRY_STRING_SIZE;
  367. FILETIME tmpTime;
  368. if( RegEnumKeyExA( m_regHandle, index, buffer, &bufferSize, NULL, NULL, NULL, &tmpTime ) != ERROR_SUCCESS )
  369. {
  370. return FALSE;
  371. }
  372. else
  373. {
  374. if( bufferSize+1 > *lpdwStringLen )
  375. {
  376. *lpdwStringLen = bufferSize+1;
  377. return FALSE;
  378. }
  379. if( OSAL_AnsiToWide( lpwStrName, buffer, *lpdwStringLen ) == 0 )
  380. {
  381. return FALSE;
  382. }
  383. else
  384. {
  385. *lpdwStringLen = bufferSize+1;
  386. return TRUE;
  387. }
  388. }
  389. }
  390. }
  391. // This comment documents ALL of the Read<Data Type> functions which
  392. // follow.
  393. //
  394. // CRegistry Read<Data Type> Functions
  395. //
  396. // The set of ReadXXXXX functions for the CRegistry class are
  397. // responsible for reading <data type> type data from the registry.
  398. // The object must have an open connection to the registry before
  399. // any of these functions may be used. A connection to the registry
  400. // can be made with the Open call or the constructors.
  401. //
  402. // Parameters:
  403. // const TCHAR *keyName - The keyname of the data you wish to read
  404. // <datatype> & - A reference to the specific data type where
  405. // the data will be placed on a succesful read.
  406. // This parameter will be unaffected if the read
  407. // fails.
  408. //
  409. // Returns:
  410. // BOOL - Returns TRUE on success, FALSE on failure.
  411. //
  412. // This comment documents ALL of the Write<Data Type> functions which
  413. // follow.
  414. //
  415. // CRegistry Write<Data Type> Functions
  416. //
  417. // The set of Write<Data Type> functions for the CRegistry class are
  418. // responsible for writing <data type> type data to the registry.
  419. // The object must have an open connection to the registry before
  420. // any of these functions may be used. A connection to the registry
  421. // can be made with the Open call or the constructors.
  422. //
  423. // Parameters:
  424. // const TCHAR *keyName - The keyname of the data you wish to write
  425. // <datatype> & - A reference to the specific data type which
  426. // contains the data to be written to the registry.
  427. //
  428. // Returns:
  429. // BOOL - Returns TRUE on success, FALSE on failure.
  430. //
  431. #undef DPF_MODNAME
  432. #define DPF_MODNAME "CRegistry::WriteString"
  433. // WriteString
  434. //
  435. // Writes Strings's to the registry, see block comment above
  436. // for details.
  437. //
  438. BOOL CRegistry::WriteString( LPCWSTR keyName, const LPCWSTR lpwstrValue )
  439. {
  440. LONG retValue;
  441. // Found by PREFIX: Millen Bug #129154, ManBugs:29338
  442. // lpwstrValue could conceivably be NULL and the
  443. if( keyName == NULL || !IsOpen() || lpwstrValue == NULL ) return FALSE;
  444. if( OSAL_IsUnicodePlatform() )
  445. {
  446. retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_SZ, (const unsigned char *) lpwstrValue, (lstrlenW( lpwstrValue )+1)*sizeof(wchar_t) );
  447. }
  448. else
  449. {
  450. LPSTR lpstrKeyName;
  451. LPSTR lpstrValue;
  452. if( FAILED( OSAL_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) )
  453. {
  454. return FALSE;
  455. }
  456. if( FAILED( OSAL_AllocAndConvertToANSI( &lpstrValue, lpwstrValue ) ) )
  457. {
  458. delete [] lpstrKeyName;
  459. return FALSE;
  460. }
  461. retValue = RegSetValueExA( m_regHandle, lpstrKeyName, 0, REG_SZ, (const unsigned char *) lpstrValue, lstrlenA( lpstrValue )+1 );
  462. delete [] lpstrKeyName;
  463. delete [] lpstrValue;
  464. }
  465. return (retValue == ERROR_SUCCESS);
  466. }
  467. #undef DPF_MODNAME
  468. #define DPF_MODNAME "CRegistry::ReadString"
  469. // ReadString
  470. //
  471. // Reads CString's from the registry, see block comment above
  472. // for details.
  473. //
  474. BOOL CRegistry::ReadString( const LPCWSTR keyName, LPWSTR lpwstrValue, LPDWORD lpdwLength )
  475. {
  476. if( keyName == NULL || !IsOpen() ) return FALSE;
  477. LONG retValue;
  478. DWORD tmpSize;;
  479. DWORD tmpType;
  480. if( OSAL_IsUnicodePlatform() )
  481. {
  482. wchar_t buffer[MAX_REGISTRY_STRING_SIZE];
  483. tmpSize = MAX_REGISTRY_STRING_SIZE*sizeof(wchar_t);
  484. retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, (unsigned char *) &buffer[0], &tmpSize );
  485. if( retValue != ERROR_SUCCESS )
  486. {
  487. return FALSE;
  488. }
  489. if( (tmpSize/2) > *lpdwLength )
  490. {
  491. *lpdwLength = (tmpSize/2);
  492. return FALSE;
  493. }
  494. lstrcpyW( lpwstrValue, buffer );
  495. *lpdwLength = (tmpSize/2);
  496. return TRUE;
  497. }
  498. else
  499. {
  500. LPSTR lpstrKeyName;
  501. char buffer[MAX_REGISTRY_STRING_SIZE];
  502. tmpSize = MAX_REGISTRY_STRING_SIZE;
  503. if( FAILED( OSAL_AllocAndConvertToANSI( &lpstrKeyName, keyName ) ) )
  504. return FALSE;
  505. retValue = RegQueryValueExA( m_regHandle, lpstrKeyName, 0, &tmpType, (unsigned char *) &buffer[0], &tmpSize );
  506. delete [] lpstrKeyName;
  507. if( retValue != ERROR_SUCCESS )
  508. {
  509. return FALSE;
  510. }
  511. if( tmpSize > *lpdwLength )
  512. {
  513. *lpdwLength = tmpSize;
  514. return FALSE;
  515. }
  516. if( OSAL_AnsiToWide( lpwstrValue, buffer, *lpdwLength ) == 0 )
  517. return FALSE;
  518. *lpdwLength = tmpSize;
  519. }
  520. if( retValue == ERROR_SUCCESS && tmpType == REG_SZ ) {
  521. return TRUE;
  522. } else {
  523. return FALSE;
  524. }
  525. }
  526. #undef DPF_MODNAME
  527. #define DPF_MODNAME "CRegistry::WriteGUID"
  528. // WriteGUID
  529. //
  530. // Writes GUID's to the registry, see block comment above
  531. // for details. The GUID is written in the format it is usually
  532. // displayed. (But without the '{''s).
  533. //
  534. BOOL CRegistry::WriteGUID( LPCWSTR keyName, const GUID &guid )
  535. {
  536. LONG retValue;
  537. WCHAR wszGuidString[GUID_STRING_LEN];
  538. HRESULT hr;
  539. hr = DVStringFromGUID(&guid, wszGuidString, GUID_STRING_LEN);
  540. if (FAILED(hr))
  541. {
  542. DPF(DVF_ERRORLEVEL, "DVStringFromGUID failed, code: %i", hr);
  543. return FALSE;
  544. }
  545. if( OSAL_IsUnicodePlatform() )
  546. {
  547. retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_SZ, (const unsigned char *) wszGuidString, (lstrlenW( wszGuidString )+1)*sizeof(wchar_t) );
  548. }
  549. else
  550. {
  551. LPSTR lpstrKeyName;
  552. LPSTR lpstrKeyValue;
  553. hr = OSAL_AllocAndConvertToANSI( &lpstrKeyName, keyName );
  554. if (FAILED(hr))
  555. {
  556. DPF(DVF_ERRORLEVEL, "DVStringFromGUID failed, code: %i", hr);
  557. return FALSE;
  558. }
  559. hr = OSAL_AllocAndConvertToANSI( &lpstrKeyValue, wszGuidString );
  560. if (FAILED(hr))
  561. {
  562. DPF(DVF_ERRORLEVEL, "DVStringFromGUID failed, code: %i", hr);
  563. delete [] lpstrKeyName;
  564. return FALSE;
  565. }
  566. retValue = RegSetValueExA( m_regHandle, lpstrKeyName, 0, REG_SZ, (const unsigned char *) lpstrKeyValue, lstrlenA( lpstrKeyValue )+1);
  567. delete [] lpstrKeyName;
  568. delete [] lpstrKeyValue;
  569. }
  570. if( retValue == ERROR_SUCCESS )
  571. return TRUE;
  572. else
  573. return FALSE;
  574. }
  575. #undef DPF_MODNAME
  576. #define DPF_MODNAME "CRegistry::ReadGUID"
  577. // ReadGUID
  578. //
  579. // Reads GUID's from the registry, see block comment above
  580. // for details. The GUID must be stored in the format written by
  581. // the WriteGUID function or it will not be read correctly.
  582. //
  583. BOOL CRegistry::ReadGUID( LPCWSTR keyName, GUID &guid )
  584. {
  585. wchar_t buffer[MAX_REGISTRY_STRING_SIZE];
  586. DWORD dwLength = MAX_REGISTRY_STRING_SIZE;
  587. HRESULT hr;
  588. if( !ReadString( keyName, buffer, &dwLength ) )
  589. {
  590. return FALSE;
  591. }
  592. else
  593. {
  594. hr = DVGUIDFromString(buffer, &guid);
  595. if (FAILED(hr))
  596. {
  597. DPF(DVF_ERRORLEVEL, "DVGUIDFromString failed, code: %i", hr);
  598. return FALSE;
  599. }
  600. return TRUE;
  601. }
  602. }
  603. #undef DPF_MODNAME
  604. #define DPF_MODNAME "CRegistry::WriteDWORD"
  605. // WriteDWORD
  606. //
  607. // Writes DWORDS to the registry, see block comment above
  608. // for details.
  609. //
  610. BOOL CRegistry::WriteDWORD( LPCWSTR keyName, DWORD value ) {
  611. LONG retValue;
  612. if( keyName == NULL || !IsOpen() ) return FALSE;
  613. if( OSAL_IsUnicodePlatform() )
  614. {
  615. retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_DWORD, (const unsigned char *) &value, sizeof( DWORD ) );
  616. }
  617. else
  618. {
  619. LPSTR lpszKeyName;
  620. if( FAILED( OSAL_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) )
  621. return FALSE;
  622. retValue = RegSetValueExA( m_regHandle, lpszKeyName, 0, REG_DWORD, (const unsigned char *) &value, sizeof( DWORD ) );
  623. delete [] lpszKeyName;
  624. }
  625. return (retValue == ERROR_SUCCESS);
  626. }
  627. #undef DPF_MODNAME
  628. #define DPF_MODNAME "Cregistry::ReadBOOL"
  629. BOOL CRegistry::ReadBOOL( LPCWSTR keyName, BOOL &result )
  630. {
  631. DWORD tmpResult;
  632. if( ReadDWORD( keyName, tmpResult ) )
  633. {
  634. result = (BOOL) tmpResult;
  635. return TRUE;
  636. }
  637. else
  638. {
  639. return FALSE;
  640. }
  641. }
  642. #undef DPF_MODNAME
  643. #define DPF_MODNAME "CRegistry::WriteBOOL"
  644. BOOL CRegistry::WriteBOOL( LPCWSTR keyName, BOOL value )
  645. {
  646. DWORD tmpValue = (DWORD) value;
  647. return WriteDWORD( keyName, tmpValue );
  648. }
  649. #undef DPF_MODNAME
  650. #define DPF_MODNAME "CRegistry::ReadDWORD"
  651. // ReadDWORD
  652. //
  653. // Reads DWORDS from the registry, see block comment above
  654. // for details.
  655. //
  656. BOOL CRegistry::ReadDWORD( LPCWSTR keyName, DWORD &result ) {
  657. if( keyName == NULL || !IsOpen() ) return FALSE;
  658. LONG retValue;
  659. DWORD tmpValue;
  660. DWORD tmpType;
  661. DWORD tmpSize;
  662. tmpSize = sizeof( DWORD );
  663. if( OSAL_IsUnicodePlatform() )
  664. {
  665. retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, (unsigned char *) &tmpValue, &tmpSize );
  666. }
  667. else
  668. {
  669. LPSTR lpszKeyName;
  670. if( FAILED( OSAL_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) )
  671. return FALSE;
  672. retValue = RegQueryValueExA( m_regHandle, lpszKeyName, 0, &tmpType, (unsigned char *) &tmpValue, &tmpSize );
  673. delete [] lpszKeyName;
  674. }
  675. if( retValue == ERROR_SUCCESS && tmpType == REG_DWORD ) {
  676. result = tmpValue;
  677. return TRUE;
  678. } else {
  679. return FALSE;
  680. }
  681. }
  682. #undef DPF_MODNAME
  683. #define DPF_MODNAME "CRegistry::Register"
  684. BOOL CRegistry::Register( LPCWSTR lpszProgID, const LPCWSTR lpszDesc, const LPCWSTR lpszProgName, GUID guidCLSID, LPCWSTR lpszVerIndProgID )
  685. {
  686. CRegistry core;
  687. DNASSERT( lpszDesc != NULL );
  688. DNASSERT( lpszProgID != NULL );
  689. // Build a string representation of the GUID from the GUID
  690. wchar_t lpszGUID[MAX_REGISTRY_STRING_SIZE];
  691. wchar_t lpszKeyName[_MAX_PATH];
  692. 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,
  693. guidCLSID.Data4[0], guidCLSID.Data4[1], guidCLSID.Data4[2], guidCLSID.Data4[3],
  694. guidCLSID.Data4[4], guidCLSID.Data4[5], guidCLSID.Data4[6], guidCLSID.Data4[7] );
  695. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID} section
  696. swprintf( lpszKeyName, L"CLSID\\%s", lpszGUID );
  697. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  698. {
  699. DPF( DVF_ERRORLEVEL, "Unable to open/create registry key %s", lpszKeyName );
  700. return FALSE;
  701. }
  702. core.WriteString( L"", lpszDesc );
  703. core.Close();
  704. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\InProcServer32 section
  705. swprintf( lpszKeyName, L"CLSID\\%s\\InProcServer32", lpszGUID );
  706. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  707. {
  708. DPF( DVF_ERRORLEVEL, "Unable to open/create registry key %s", lpszKeyName );
  709. return FALSE;
  710. }
  711. core.WriteString( L"", lpszProgName );
  712. core.WriteString( L"ThreadingModel", L"Both" );
  713. core.Close();
  714. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\VersionIndependentProgID section
  715. if( lpszVerIndProgID != NULL )
  716. {
  717. swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
  718. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  719. {
  720. DPF( DVF_ERRORLEVEL, "Unable to open/create verind registry key %s", lpszKeyName );
  721. return FALSE;
  722. }
  723. core.WriteString( L"", lpszVerIndProgID );
  724. core.Close();
  725. }
  726. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID}\ProgID section
  727. swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
  728. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  729. {
  730. DPF( DVF_ERRORLEVEL, "Unable to open/create verind registry key %s", lpszKeyName );
  731. return FALSE;
  732. }
  733. core.WriteString( L"", lpszProgID );
  734. core.Close();
  735. // Write The VersionIND ProgID
  736. if( lpszVerIndProgID != NULL )
  737. {
  738. if( !core.Open( HKEY_CLASSES_ROOT, lpszVerIndProgID ) )
  739. {
  740. DPF( DVF_ERRORLEVEL, "Unable to open/create reg key %s", lpszVerIndProgID );
  741. }
  742. else
  743. {
  744. core.WriteString( L"", lpszDesc );
  745. core.Close();
  746. }
  747. swprintf( lpszKeyName, L"%s\\CLSID", lpszVerIndProgID );
  748. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  749. {
  750. DPF( DVF_ERRORLEVEL, "Unable to open/create reg key %s", lpszKeyName );
  751. }
  752. else
  753. {
  754. core.WriteString( L"", lpszGUID );
  755. core.Close();
  756. }
  757. swprintf( lpszKeyName, L"%s\\CurVer", lpszVerIndProgID );
  758. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  759. {
  760. DPF( DVF_ERRORLEVEL, "Unable to open/create reg key %s", lpszKeyName );
  761. }
  762. else
  763. {
  764. core.WriteString( L"", lpszProgID );
  765. core.Close();
  766. }
  767. }
  768. if( !core.Open( HKEY_CLASSES_ROOT, lpszProgID ) )
  769. {
  770. DPF( DVF_ERRORLEVEL, "Unable to open/create reg key %s", lpszKeyName );
  771. }
  772. else
  773. {
  774. core.WriteString( L"", lpszDesc );
  775. core.Close();
  776. }
  777. swprintf( lpszKeyName, L"%s\\CLSID", lpszProgID );
  778. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  779. {
  780. DPF( DVF_ERRORLEVEL, "Unable to open/create reg key %s", lpszKeyName );
  781. }
  782. else
  783. {
  784. core.WriteString( L"", lpszGUID );
  785. core.Close();
  786. }
  787. return TRUE;
  788. }
  789. #undef DPF_MODNAME
  790. #define DPF_MODNAME "CRegistry::UnRegister"
  791. BOOL CRegistry::UnRegister( GUID guidCLSID )
  792. {
  793. CRegistry core, cregClasses, cregSub;
  794. // Build a string representation of the GUID from the GUID
  795. wchar_t lpszGUID[MAX_REGISTRY_STRING_SIZE];
  796. wchar_t lpszKeyName[_MAX_PATH];
  797. wchar_t szProgID[MAX_REGISTRY_STRING_SIZE];
  798. wchar_t szVerIndProgID[MAX_REGISTRY_STRING_SIZE];
  799. DWORD dwSize = MAX_REGISTRY_STRING_SIZE;
  800. 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,
  801. guidCLSID.Data4[0], guidCLSID.Data4[1], guidCLSID.Data4[2], guidCLSID.Data4[3],
  802. guidCLSID.Data4[4], guidCLSID.Data4[5], guidCLSID.Data4[6], guidCLSID.Data4[7] );
  803. if( !cregClasses.Open( HKEY_CLASSES_ROOT, L"" ) )
  804. {
  805. DPF( DVF_ERRORLEVEL, "Unable to open HKEY_CLASSES_ROOT" );
  806. return FALSE;
  807. }
  808. // Write the HKEY_CLASSES_ROOT\CLSID\{GUID} section
  809. swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
  810. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  811. {
  812. DPF( DVF_ERRORLEVEL, "Unable to open %s", lpszKeyName );
  813. return FALSE;
  814. }
  815. dwSize = MAX_REGISTRY_STRING_SIZE;
  816. if( core.ReadString( L"", szProgID, &dwSize ) )
  817. {
  818. swprintf( lpszKeyName, L"%s\\CLSID", szProgID );
  819. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  820. {
  821. DPF( DVF_ERRORLEVEL, "Unable to delete %s", lpszKeyName );
  822. return FALSE;
  823. }
  824. if( !cregClasses.DeleteSubKey( szProgID ) )
  825. {
  826. DPF( DVF_ERRORLEVEL, "Unable to delete HKEY_CLASSES_ROOT/ProgID" );
  827. return FALSE;
  828. }
  829. }
  830. core.Close();
  831. swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
  832. if( !core.Open( HKEY_CLASSES_ROOT, lpszKeyName ) )
  833. {
  834. DPF( DVF_ERRORLEVEL, "Unable to open %s", lpszKeyName );
  835. return FALSE;
  836. }
  837. dwSize = MAX_REGISTRY_STRING_SIZE;
  838. if( core.ReadString( L"", szVerIndProgID, &dwSize ) )
  839. {
  840. swprintf( lpszKeyName, L"%s\\CLSID", szVerIndProgID );
  841. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  842. {
  843. DPF( DVF_ERRORLEVEL, "Unable to delete %s", lpszKeyName );
  844. return FALSE;
  845. }
  846. swprintf( lpszKeyName, L"%s\\CurVer", szVerIndProgID );
  847. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  848. {
  849. DPF( DVF_ERRORLEVEL, "Unable to delete %s", lpszKeyName );
  850. return FALSE;
  851. }
  852. if( !cregClasses.DeleteSubKey( szVerIndProgID ) )
  853. {
  854. DPF( DVF_ERRORLEVEL, "Unable to delete HKEY_CLASSES_ROOT/%s", szVerIndProgID);
  855. return FALSE;
  856. }
  857. }
  858. core.Close();
  859. swprintf( lpszKeyName, L"CLSID\\%s\\InprocServer32", lpszGUID );
  860. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  861. {
  862. DPF( DVF_ERRORLEVEL, "Unable to delete %s", lpszKeyName );
  863. return FALSE;
  864. }
  865. swprintf( lpszKeyName, L"CLSID\\%s\\ProgID", lpszGUID );
  866. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  867. {
  868. DPF( DVF_ERRORLEVEL, "Unable to delete %s", lpszKeyName );
  869. return FALSE;
  870. }
  871. swprintf( lpszKeyName, L"CLSID\\%s\\VersionIndependentProgID", lpszGUID );
  872. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  873. {
  874. DPF( DVF_ERRORLEVEL, "Unable to delete %s", lpszKeyName );
  875. return FALSE;
  876. }
  877. swprintf( lpszKeyName, L"CLSID\\%s", lpszGUID );
  878. if( !cregClasses.DeleteSubKey( lpszKeyName ) )
  879. {
  880. DPF( DVF_ERRORLEVEL, "Unable to delete %s", lpszKeyName );
  881. return FALSE;
  882. }
  883. return TRUE;
  884. }
  885. #undef DPF_MODNAME
  886. #define DPF_MODNAME "CRegistry::ReadBlob"
  887. BOOL CRegistry::ReadBlob( LPCWSTR keyName, LPBYTE lpbBuffer, LPDWORD lpdwSize )
  888. {
  889. if( keyName == NULL || !IsOpen() ) return FALSE;
  890. LONG retValue;
  891. DWORD tmpType;
  892. if( OSAL_IsUnicodePlatform() )
  893. {
  894. retValue = RegQueryValueExW( m_regHandle, keyName, 0, &tmpType, lpbBuffer, lpdwSize );
  895. }
  896. else
  897. {
  898. LPSTR lpszKeyName;
  899. if( FAILED( OSAL_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) )
  900. return FALSE;
  901. retValue = RegQueryValueExA( m_regHandle, lpszKeyName, 0, &tmpType, lpbBuffer, lpdwSize );
  902. delete [] lpszKeyName;
  903. }
  904. if( retValue == ERROR_SUCCESS && tmpType == REG_BINARY ) {
  905. return TRUE;
  906. } else {
  907. return FALSE;
  908. }
  909. }
  910. #undef DPF_MODNAME
  911. #define DPF_MODNAME "CRegistry::WriteBlob"
  912. BOOL CRegistry::WriteBlob( LPCWSTR keyName, LPBYTE lpbBuffer, DWORD dwSize )
  913. {
  914. LONG retValue;
  915. if( keyName == NULL || !IsOpen() ) return FALSE;
  916. if( OSAL_IsUnicodePlatform() )
  917. {
  918. retValue = RegSetValueExW( m_regHandle, keyName, 0, REG_BINARY, lpbBuffer, dwSize );
  919. }
  920. else
  921. {
  922. LPSTR lpszKeyName;
  923. if( FAILED( OSAL_AllocAndConvertToANSI( &lpszKeyName, keyName ) ) )
  924. return FALSE;
  925. retValue = RegSetValueExA( m_regHandle, lpszKeyName, 0, REG_BINARY, lpbBuffer, dwSize );
  926. delete [] lpszKeyName;
  927. }
  928. return (retValue == ERROR_SUCCESS);
  929. }