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.

2950 lines
77 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  4. //
  5. // cregcls.cpp
  6. //
  7. // Purpose: registry wrapper class
  8. //
  9. //***************************************************************************
  10. #include "precomp.h"
  11. #pragma warning( disable : 4290 )
  12. #include <CHString.h>
  13. #include <stdio.h>
  14. #include "CRegCls.h"
  15. #include <malloc.h>
  16. #include <cnvmacros.h>
  17. DWORD CRegistry::s_dwPlatform = CRegistry::GetPlatformID () ;
  18. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  19. Function:
  20. Description:
  21. Arguments:
  22. Returns:
  23. Inputs:
  24. Outputs:
  25. Caveats:
  26. Raid:
  27. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  28. CRegistry::CRegistry()
  29. : m_fFromCurrentUser(false)
  30. {
  31. // Set the key to null so that if the caller does not open the key
  32. // but still tries to use it we can return an error
  33. hKey = (HKEY)NULL;
  34. hSubKey = (HKEY)NULL;
  35. hRootKey = (HKEY)NULL;
  36. // To prevent garbage values being returned if they try to get
  37. // some information before they open the class
  38. SetDefaultValues();
  39. }
  40. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  41. Function:
  42. Description:
  43. Arguments:
  44. Returns:
  45. Inputs:
  46. Outputs:
  47. Caveats:
  48. Raid:
  49. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  50. CRegistry::~CRegistry()
  51. {
  52. Close();
  53. }
  54. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  55. Function:
  56. Description:
  57. Arguments:
  58. Returns:
  59. Inputs:
  60. Outputs:
  61. Caveats:
  62. Raid:
  63. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  64. void CRegistry::SetDefaultValues()
  65. {
  66. // Information inited here rather than constructor so that this instance
  67. // can be reused
  68. ClassName[0] = '\0';
  69. dwcClassLen = MAX_PATH; // Length of class string.
  70. dwcSubKeys = NULL_DWORD; // Number of sub keys.
  71. dwcMaxSubKey = NULL_DWORD; // Longest sub key size.
  72. dwcMaxClass = NULL_DWORD; // Longest class string.
  73. dwcValues = NULL_DWORD; // Number of values for this key.
  74. dwcMaxValueName = NULL_DWORD; // Longest Value name.
  75. dwcMaxValueData = NULL_DWORD; // Longest Value data.
  76. RewindSubKeys(); // Rewind the index to zero
  77. RootKeyPath.Empty();
  78. }
  79. ////////////////////////////////////////////////////////////////
  80. // Function: EnumerateAndGetValues
  81. // Description: This function enumerates the values under the
  82. // specified key and gets the value, keeps on
  83. // going and going... until there aren't any more
  84. // values to get. The first call must set the
  85. // value index to 0, this indicates for the function
  86. // to start over;
  87. //
  88. //
  89. // NOTE!!!! The USER has the responsibility of deleting the
  90. // allocated memory for pValueName and pValueData
  91. //
  92. //
  93. // Arguments:
  94. // Returns: Standard return value from registry open function
  95. // Inputs:
  96. // Outputs:
  97. // Caveats:
  98. // Raid:
  99. ////////////////////////////////////////////////////////////////
  100. LONG CRegistry::EnumerateAndGetValues (
  101. DWORD &dwIndexOfValue,
  102. WCHAR *&pValueName,
  103. BYTE *&pValueData
  104. )
  105. {
  106. DWORD dwIndex = dwIndexOfValue, dwType;
  107. DWORD dwValueNameSize = dwcMaxValueName + 2; // add extra for null
  108. DWORD dwValueDataSize = dwcMaxValueData + 2; // add extra for null
  109. // If this is the first time we have come thru, then we
  110. // need to get the max size of things.
  111. pValueName = new WCHAR[dwValueNameSize + 2];
  112. if ( ! pValueName )
  113. {
  114. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  115. }
  116. // We have to use WCHAR's since for 9x, we'll be converting the
  117. // data from chars to WCHARs.
  118. pValueData = (LPBYTE) new WCHAR[dwValueDataSize + 2];
  119. if ( ! pValueData )
  120. {
  121. delete [] pValueName ;
  122. pValueName = NULL;
  123. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  124. }
  125. LONG lRc = ERROR_SUCCESS ;
  126. try
  127. {
  128. lRc = myRegEnumValue (
  129. hKey, // handle of key to query
  130. dwIndex, // index of value to query
  131. pValueName, // address of buffer for value string
  132. &dwValueNameSize, // address for size of value buffer
  133. 0, // reserved
  134. &dwType, // address of buffer for type code
  135. pValueData, // address of buffer for value data
  136. &dwValueDataSize
  137. ) ;
  138. dwIndexOfValue = dwIndex;
  139. if ( lRc != ERROR_SUCCESS )
  140. {
  141. delete[] pValueName;
  142. pValueName = NULL ;
  143. delete[] pValueData;
  144. pValueData = NULL ;
  145. }
  146. }
  147. catch ( ... )
  148. {
  149. delete[] pValueName;
  150. pValueName = NULL ;
  151. delete[] pValueData;
  152. pValueData = NULL ;
  153. throw ; // throw the exception up
  154. }
  155. return lRc ;
  156. }
  157. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  158. Function: LONG CRegistry::OpenCurrentUser(LPCWSTR lpszSubKey, REGSAM samDesired)
  159. Description:
  160. Arguments:
  161. Returns: Standard return value from registry open function
  162. Inputs:
  163. Outputs:
  164. Caveats:
  165. Raid:
  166. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  167. DWORD CRegistry::OpenCurrentUser (
  168. LPCWSTR lpszSubKey, // address of name of subkey to open
  169. REGSAM samDesired) // Access mask
  170. {
  171. LONG RetValue = ERROR_SUCCESS;
  172. // If we have a key value, we are open, so lets cleanup the previous
  173. // use of this instance
  174. PrepareToReOpen();
  175. RetValue = ::RegOpenCurrentUser(
  176. samDesired,
  177. &hRootKey);
  178. m_fFromCurrentUser = true;
  179. if(RetValue == ERROR_SUCCESS)
  180. {
  181. // Just return the value and the hKey value never gets changed from NULL
  182. //======================================================================
  183. RetValue = myRegOpenKeyEx (
  184. hRootKey,
  185. lpszSubKey, // address of name of subkey to open
  186. (DWORD) 0, // reserved
  187. samDesired, // security access mask
  188. (PHKEY)&hKey // address of handle of open key
  189. );
  190. // If we are not successful, then return the registry error
  191. //=========================================================
  192. if(RetValue == ERROR_SUCCESS)
  193. {
  194. dwcClassLen = sizeof(ClassName);
  195. // Get the key information now, so it's available
  196. // this is not critical, so we won't fail the open if this fails
  197. //===============================================
  198. myRegQueryInfoKey (
  199. hKey, // Key handle.
  200. ClassName, // Buffer for class name.
  201. &dwcClassLen, // Length of class string.
  202. NULL, // Reserved.
  203. &dwcSubKeys, // Number of sub keys.
  204. &dwcMaxSubKey, // Longest sub key size.
  205. &dwcMaxClass, // Longest class string.
  206. &dwcValues, // Number of values for this key.
  207. &dwcMaxValueName, // Longest Value name.
  208. &dwcMaxValueData, // Longest Value data.
  209. &dwcSecDesc, // Security descriptor.
  210. &ftLastWriteTime // Last write time.
  211. );
  212. RootKeyPath = lpszSubKey; // Assign
  213. }
  214. }
  215. return RetValue;
  216. }
  217. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  218. Function: LONG CRegistry::Open(HKEY hKey, LPCWSTR lpszSubKey, REGSAM samDesired)
  219. Description:
  220. Arguments:
  221. Returns: Standard return value from registry open function
  222. Inputs:
  223. Outputs:
  224. Caveats:
  225. Raid:
  226. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  227. LONG CRegistry::Open(
  228. HKEY hInRootKey,
  229. LPCWSTR lpszSubKey,
  230. REGSAM samDesired
  231. )
  232. {
  233. LONG RetValue;
  234. // If we have a key value, we are open, so lets cleanup the previous
  235. // use of this instance
  236. if(hKey != NULL)
  237. {
  238. PrepareToReOpen();
  239. }
  240. hRootKey = hInRootKey;
  241. // Just return the value and the hKey value never gets changed from NULL
  242. //======================================================================
  243. RetValue = myRegOpenKeyEx (
  244. hRootKey,
  245. lpszSubKey, // address of name of subkey to open
  246. (DWORD) 0, // reserved
  247. samDesired, // security access mask
  248. (PHKEY)&hKey // address of handle of open key
  249. );
  250. // If we are not successful, then return the registry error
  251. //=========================================================
  252. if(RetValue != ERROR_SUCCESS)
  253. {
  254. return RetValue;
  255. }
  256. dwcClassLen = sizeof(ClassName);
  257. // Get the key information now, so it's available
  258. // this is not critical, so we won't fail the open if this fails
  259. //===============================================
  260. myRegQueryInfoKey (
  261. hKey, // Key handle.
  262. ClassName, // Buffer for class name.
  263. &dwcClassLen, // Length of class string.
  264. NULL, // Reserved.
  265. &dwcSubKeys, // Number of sub keys.
  266. &dwcMaxSubKey, // Longest sub key size.
  267. &dwcMaxClass, // Longest class string.
  268. &dwcValues, // Number of values for this key.
  269. &dwcMaxValueName, // Longest Value name.
  270. &dwcMaxValueData, // Longest Value data.
  271. &dwcSecDesc, // Security descriptor.
  272. &ftLastWriteTime // Last write time.
  273. );
  274. RootKeyPath = lpszSubKey; // Assign
  275. return ERROR_SUCCESS;
  276. }
  277. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  278. Function: LONG CRegistry::CreateOpen(HKEY hInRootKey,
  279. LPCWSTR lpszSubKey,
  280. LPSTR lpClass = NULL,
  281. DWORD dwOptions = REG_OPTION_NON_VOLATILE,
  282. REGSAM samDesired = KEY_ALL_ACCESS,
  283. LPSECURITY_ATTRIBUTES lpSecurityAttrib = NULL
  284. LPDWORD pdwDisposition = NULL );
  285. Description:
  286. Arguments: lpClass, dwOptions, samDesired and lpSecurityAttrib have signature defaults
  287. Returns: Standard return value from registry RegCreateKeyEx function
  288. Inputs:
  289. Outputs:
  290. Caveats:
  291. Raid:
  292. History: a-peterc 28-Jul-1998 Created
  293. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  294. LONG CRegistry::CreateOpen (
  295. HKEY hInRootKey,
  296. LPCWSTR lpszSubKey,
  297. LPWSTR lpClass,
  298. DWORD dwOptions,
  299. REGSAM samDesired,
  300. LPSECURITY_ATTRIBUTES lpSecurityAttrib,
  301. LPDWORD pdwDisposition
  302. )
  303. {
  304. LONG RetValue;
  305. DWORD dwDisposition;
  306. // If we have a key value, we are open, so lets cleanup the previous
  307. // use of this instance
  308. if(hKey != NULL)
  309. {
  310. PrepareToReOpen();
  311. }
  312. hRootKey = hInRootKey;
  313. // Just return the value and the hKey value never gets changed from NULL
  314. //======================================================================
  315. RetValue = myRegCreateKeyEx (
  316. hRootKey,
  317. lpszSubKey, // address of name of subkey to open
  318. (DWORD) 0, // reserved
  319. lpClass, // address of the object class string
  320. dwOptions, // special options flag
  321. samDesired, // security access mask
  322. lpSecurityAttrib, // address of the key security structure
  323. (PHKEY)&hKey, // address of handle of open key
  324. &dwDisposition // address of the disposition value buffer
  325. );
  326. // If we are not successful, then return the registry error
  327. //=========================================================
  328. if(RetValue != ERROR_SUCCESS)
  329. {
  330. return RetValue;
  331. }
  332. if( pdwDisposition )
  333. {
  334. *pdwDisposition = dwDisposition;
  335. }
  336. // Get the key information now, so it's available
  337. // this is not critical, so we won't fail the open if this fails
  338. //===============================================
  339. myRegQueryInfoKey (
  340. hKey, // Key handle.
  341. ClassName, // Buffer for class name.
  342. &dwcClassLen, // Length of class string.
  343. NULL, // Reserved.
  344. &dwcSubKeys, // Number of sub keys.
  345. &dwcMaxSubKey, // Longest sub key size.
  346. &dwcMaxClass, // Longest class string.
  347. &dwcValues, // Number of values for this key.
  348. &dwcMaxValueName, // Longest Value name.
  349. &dwcMaxValueData, // Longest Value data.
  350. &dwcSecDesc, // Security descriptor.
  351. &ftLastWriteTime // Last write time.
  352. );
  353. RootKeyPath = lpszSubKey; // Assign
  354. return ERROR_SUCCESS;
  355. }
  356. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  357. Function: DWORD CRegistry::DeleteKey( CHString* pchsSubKeyPath = NULL )
  358. Description: deletes the specified subkey or the Rootkey specified in the open
  359. Arguments: pchsSubKeyPath has signature default of NULL,
  360. specifying the RootKeyPath by default
  361. Returns: Standard return value from registry RegDeleteKey function
  362. Inputs:
  363. Outputs:
  364. Caveats: A deleted key is not removed until the last handle to it has been closed.
  365. Subkeys and values cannot be created under a deleted key.
  366. Raid:
  367. History: a-peterc 28-Jul-1998 Created
  368. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  369. LONG CRegistry::DeleteKey( CHString* pchsSubKeyPath )
  370. {
  371. CHString* pSubKey = pchsSubKeyPath ? pchsSubKeyPath : &RootKeyPath;
  372. return myRegDeleteKey( hKey, pSubKey->GetBuffer(0) );
  373. }
  374. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  375. Function: DWORD CRegistry::DeleteValue( LPCWSTR pValueName )
  376. Description: deletes the specified value in the createopen
  377. Arguments: pValueName to be deleted
  378. Returns: Standard return value from registry RegDeleteValue function
  379. Inputs:
  380. Outputs:
  381. Caveats:
  382. Raid:
  383. History: a-peterc 30-Sep-1998 Created
  384. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  385. LONG CRegistry::DeleteValue( LPCWSTR pValueName )
  386. {
  387. return myRegDeleteValue( hKey, pValueName );
  388. }
  389. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  390. Function: LONG CRegistry::OpenAndEnumerateSubKeys(HKEY hKey, LPCWSTR lpszSubKey, REGSAM samDesired)
  391. Description:
  392. Arguments:
  393. Returns: Standard return value from registry open function
  394. Inputs:
  395. Outputs:
  396. Caveats:
  397. Raid:
  398. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  399. LONG CRegistry::OpenAndEnumerateSubKeys (
  400. HKEY hInRootKey,
  401. LPCWSTR lpszSubKey,
  402. REGSAM samDesired
  403. )
  404. {
  405. return (Open( hInRootKey, lpszSubKey, samDesired | KEY_ENUMERATE_SUB_KEYS));
  406. }
  407. /////////////////////////////////////////////////////////////////////
  408. //
  409. // This function opens and enumerates a key, then gets the requested
  410. // value
  411. //
  412. /////////////////////////////////////////////////////////////////////
  413. LONG CRegistry::OpenLocalMachineKeyAndReadValue(
  414. LPCWSTR lpszSubKey,
  415. LPCWSTR pValueName,
  416. CHString &DestValue
  417. )
  418. {
  419. LONG lRc;
  420. //===============================================
  421. // Open the key. Note, if it is already in use
  422. // the current key will be closed and everything
  423. // reinitilized by the Open call
  424. //===============================================
  425. lRc = Open( HKEY_LOCAL_MACHINE,lpszSubKey,KEY_READ );
  426. if( lRc != ERROR_SUCCESS )
  427. {
  428. return lRc;
  429. }
  430. //===============================================
  431. // Get the value
  432. //===============================================
  433. return( GetCurrentKeyValue( pValueName, DestValue ));
  434. }
  435. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  436. Function:
  437. Description:
  438. Arguments:
  439. Returns:
  440. Inputs:
  441. Outputs:
  442. Caveats:
  443. Raid:
  444. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  445. DWORD CRegistry::GetCurrentRawKeyValue (
  446. HKEY UseKey,
  447. LPCWSTR pValueName,
  448. void *pDestValue,
  449. LPDWORD pValueType,
  450. LPDWORD pSizeOfDestValue
  451. )
  452. {
  453. DWORD RetValue;
  454. // If subkey is open then get value
  455. // ================================
  456. RetValue = myRegQueryValueEx(
  457. UseKey, // handle of key to query
  458. pValueName, // address of name of value to query
  459. NULL, // reserved
  460. pValueType, // address of buffer for value type
  461. (LPBYTE) pDestValue, // address of data buffer
  462. (LPDWORD)pSizeOfDestValue // address of data buffer size
  463. );
  464. return RetValue;
  465. }
  466. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  467. Function:
  468. Description:
  469. Arguments:
  470. Returns:
  471. Inputs:
  472. Outputs:
  473. Caveats:
  474. Raid:
  475. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  476. DWORD CRegistry::GetCurrentKeyValue (
  477. HKEY UseKey,
  478. LPCWSTR pValueName,
  479. CHString &DestValue
  480. )
  481. {
  482. DWORD SizeOfValue = 0L;
  483. DWORD TypeOfValue;
  484. LPBYTE pValue = NULL ; // Pointer to buffer for value
  485. DestValue = L"";
  486. LONG t_Status = myRegQueryValueEx(
  487. UseKey, // handle of key to query
  488. pValueName, // address of name of value to query
  489. NULL, // reserved
  490. (LPDWORD)&TypeOfValue, // address of buffer for value type
  491. (LPBYTE) NULL, // address of data buffer NULL to force size being returned
  492. (LPDWORD)&SizeOfValue // Get the size of the buffer we need
  493. ) ;
  494. if( t_Status != ERROR_SUCCESS )
  495. {
  496. return (DWORD) REGDB_E_INVALIDVALUE;
  497. }
  498. /////////////////////////////////////////////////////////////
  499. if( SizeOfValue <= 0 )
  500. {
  501. return (DWORD) REGDB_E_INVALIDVALUE;
  502. }
  503. // Allow extra room for strings -- query doesn't include room for NULLs
  504. // a-jmoon 8/19/97
  505. //=====================================================================
  506. if(TypeOfValue == REG_SZ ||
  507. TypeOfValue == REG_EXPAND_SZ ||
  508. TypeOfValue == REG_MULTI_SZ)
  509. {
  510. SizeOfValue += 2 ;
  511. }
  512. pValue = new BYTE[SizeOfValue];
  513. if( ! pValue )
  514. {
  515. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  516. }
  517. try
  518. {
  519. ///////////////////////////////////////////////////////////////////
  520. // Get the value in its RAW format
  521. ///////////////////////////////////////////////////////////////////
  522. if( GetCurrentRawKeyValue(UseKey, pValueName, pValue, (LPDWORD)&TypeOfValue, (LPDWORD)&SizeOfValue) != ERROR_SUCCESS )
  523. {
  524. delete []pValue;
  525. pValue = NULL;
  526. return (DWORD) REGDB_E_INVALIDVALUE;
  527. }
  528. // If the type is a null termiated string
  529. // then assign it to the CHString
  530. // ======================================
  531. switch(TypeOfValue)
  532. {
  533. case REG_SZ:
  534. case REG_EXPAND_SZ:
  535. {
  536. DestValue = (LPCWSTR)pValue; // Move string in
  537. }
  538. break;
  539. case REG_MULTI_SZ:
  540. {
  541. WCHAR *ptemp = (WCHAR *) pValue;
  542. int stringlength;
  543. stringlength = wcslen((LPCWSTR)ptemp);
  544. while(stringlength)
  545. {
  546. DestValue += (LPCWSTR)ptemp; // Move string in
  547. DestValue += L"\n"; // Linefeed as separator
  548. ptemp += stringlength+1;
  549. stringlength = wcslen((LPCWSTR)ptemp);
  550. }
  551. }
  552. break;
  553. case REG_DWORD:
  554. {
  555. LPWSTR pTemp = new WCHAR[MAX_SUBKEY_BUFFERSIZE];
  556. if(pTemp)
  557. {
  558. try
  559. {
  560. swprintf(pTemp, L"%ld", *((DWORD*)pValue));
  561. DestValue = pTemp;
  562. delete []pTemp;
  563. pTemp = NULL;
  564. }
  565. catch ( ... )
  566. {
  567. delete [] pTemp ;
  568. pTemp = NULL;
  569. throw ;
  570. }
  571. }
  572. else
  573. {
  574. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  575. }
  576. }
  577. break;
  578. case REG_BINARY:
  579. {
  580. DestValue.Empty();
  581. // copy into DestValue, Creating a byte buffer wide enough.
  582. // Note: SizeOfValue is in bytes, while GetBuffer() returns wide char allocation.
  583. DWORD t_dwResidual = ( SizeOfValue % 2 ) ;
  584. DWORD t_dwWideSize = ( SizeOfValue / 2 ) + t_dwResidual ;
  585. memcpy( DestValue.GetBuffer( t_dwWideSize ), pValue, SizeOfValue );
  586. // cap the byte blob
  587. if( t_dwResidual )
  588. {
  589. *( (LPBYTE)((LPCWSTR) DestValue) + SizeOfValue ) = NULL;
  590. }
  591. DestValue.GetBufferSetLength( t_dwWideSize ) ;
  592. }
  593. break;
  594. default:
  595. {
  596. delete []pValue;
  597. pValue = NULL;
  598. return (DWORD) REGDB_E_INVALIDVALUE;
  599. }
  600. }
  601. }
  602. catch ( ... )
  603. {
  604. delete []pValue;
  605. pValue = NULL;
  606. throw;
  607. }
  608. /////////////////////////////////////////////////////////////
  609. delete []pValue;
  610. return (DWORD)ERROR_SUCCESS;
  611. }
  612. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  613. Function:
  614. Description:
  615. Arguments:
  616. Returns:
  617. Inputs:
  618. Outputs:
  619. Caveats:
  620. Raid:
  621. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  622. DWORD CRegistry::GetCurrentKeyValue(LPCWSTR pValueName, CHString &DestValue)
  623. {
  624. return( GetCurrentKeyValue(hKey, pValueName, DestValue));
  625. }
  626. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  627. Function:
  628. Description:
  629. Arguments:
  630. Returns:
  631. Inputs:
  632. Outputs:
  633. Caveats:
  634. Raid:
  635. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  636. DWORD CRegistry::GetCurrentKeyValue(HKEY UseKey, LPCWSTR pValueName, CHStringArray &DestValue)
  637. {
  638. DWORD SizeOfValue = 0L;
  639. DWORD TypeOfValue;
  640. LPBYTE pValue; // Pointer to buffer for value
  641. DestValue.RemoveAll();
  642. // Get the size of the buffer we need
  643. LONG t_Status = myRegQueryValueEx(
  644. UseKey, // handle of key to query
  645. pValueName, // address of name of value to query
  646. NULL, // reserved
  647. (LPDWORD)&TypeOfValue, // address of buffer for value type
  648. (LPBYTE) NULL, // address of data buffer NULL to force size being returned
  649. (LPDWORD)&SizeOfValue
  650. ) ;
  651. if( t_Status != ERROR_SUCCESS )
  652. {
  653. return (DWORD) REGDB_E_INVALIDVALUE;
  654. }
  655. /////////////////////////////////////////////////////////////
  656. if (( SizeOfValue <= 0 ) || (TypeOfValue != REG_MULTI_SZ))
  657. {
  658. return (DWORD) REGDB_E_INVALIDVALUE;
  659. }
  660. SizeOfValue += 2 ;
  661. pValue = new BYTE[SizeOfValue];
  662. if( !pValue )
  663. {
  664. return (DWORD) REGDB_E_INVALIDVALUE;
  665. }
  666. ///////////////////////////////////////////////////////////////////
  667. // Get the value in its RAW format
  668. ///////////////////////////////////////////////////////////////////
  669. try {
  670. if( GetCurrentRawKeyValue(UseKey, pValueName, pValue, (LPDWORD)&TypeOfValue, (LPDWORD)&SizeOfValue) != ERROR_SUCCESS )
  671. {
  672. delete []pValue;
  673. pValue = NULL;
  674. return (DWORD) REGDB_E_INVALIDVALUE;
  675. }
  676. // If the type is a null termiated string
  677. // then assign it to the CHString
  678. // ======================================
  679. switch(TypeOfValue)
  680. {
  681. case REG_MULTI_SZ:
  682. {
  683. LPCWSTR ptemp = (LPCWSTR)pValue;
  684. int stringlength;
  685. stringlength = wcslen(ptemp);
  686. while(stringlength)
  687. {
  688. DestValue.Add(ptemp); // Move string in
  689. ptemp += stringlength+1;
  690. stringlength = wcslen(ptemp);
  691. }
  692. }
  693. break;
  694. default:
  695. {
  696. delete [] pValue;
  697. pValue = NULL;
  698. return (DWORD) REGDB_E_INVALIDVALUE;
  699. }
  700. }
  701. }
  702. catch ( ... )
  703. {
  704. delete [] pValue ;
  705. pValue = NULL;
  706. throw ;
  707. }
  708. delete [] pValue;
  709. pValue = NULL;
  710. return (DWORD)ERROR_SUCCESS;
  711. }
  712. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  713. Function:
  714. Description:
  715. Arguments:
  716. Returns:
  717. Inputs:
  718. Outputs:
  719. Caveats:
  720. Raid:
  721. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  722. DWORD CRegistry::GetCurrentKeyValue (
  723. LPCWSTR pValueName,
  724. CHStringArray &DestValue
  725. )
  726. {
  727. return GetCurrentKeyValue (
  728. hKey,
  729. pValueName,
  730. DestValue
  731. );
  732. }
  733. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  734. Function:
  735. Description:
  736. Arguments:
  737. Returns:
  738. Inputs:
  739. Outputs:
  740. Caveats:
  741. Raid:
  742. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  743. DWORD CRegistry::GetCurrentKeyValue (
  744. HKEY UseKey,
  745. LPCWSTR pValueName,
  746. DWORD &DestValue
  747. )
  748. {
  749. DWORD SizeOfValue = MAX_SUBKEY_BUFFERSIZE;
  750. long RetValue;
  751. DWORD TypeOfValue;
  752. LPBYTE pValue; // Pointer to buffer for value
  753. pValue = new BYTE[MAX_SUBKEY_BUFFERSIZE];
  754. if(pValue)
  755. {
  756. try
  757. {
  758. // Get the value in its RAW format
  759. // ===============================
  760. RetValue = GetCurrentRawKeyValue (
  761. UseKey,
  762. pValueName,
  763. pValue,
  764. (LPDWORD)&TypeOfValue,
  765. (LPDWORD)&SizeOfValue
  766. );
  767. if( ERROR_SUCCESS == RetValue )
  768. {
  769. // If the type is a null termiated string
  770. // then assign it to the CHString
  771. // ======================================
  772. switch(TypeOfValue)
  773. {
  774. case REG_SZ:
  775. {
  776. DestValue = atol((LPSTR)pValue);
  777. }
  778. break;
  779. case REG_DWORD:
  780. {
  781. DestValue = *((DWORD*)(pValue));
  782. }
  783. break;
  784. default:
  785. {
  786. DestValue = (DWORD)0L;
  787. RetValue = REGDB_E_INVALIDVALUE; // Invalid value
  788. }
  789. break;
  790. }
  791. }
  792. delete[] pValue;
  793. pValue = NULL;
  794. }
  795. catch ( ... )
  796. {
  797. delete [] pValue ;
  798. pValue = NULL;
  799. throw ;
  800. }
  801. }
  802. else
  803. {
  804. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  805. }
  806. return RetValue;
  807. }
  808. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  809. Function:
  810. Description:
  811. Arguments:
  812. Returns:
  813. Inputs:
  814. Outputs:
  815. Caveats:
  816. Raid:
  817. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  818. DWORD CRegistry::GetCurrentKeyValue (
  819. LPCWSTR pValueName,
  820. DWORD &DestValue
  821. )
  822. {
  823. return( GetCurrentKeyValue(hKey, pValueName, DestValue));
  824. }
  825. //////////////////////////////////////////////////////////////////////
  826. // Added support for Binary Type
  827. //////////////////////////////////////////////////////////////////////
  828. DWORD CRegistry::GetCurrentBinaryKeyValue (
  829. LPCWSTR pValueName,
  830. CHString &chsDest
  831. )
  832. {
  833. DWORD dwType = REG_BINARY;
  834. DWORD dwRc;
  835. WCHAR szDest[_MAX_PATH+2], ByteBuf[_MAX_PATH];
  836. BYTE bRevision[_MAX_PATH+2];
  837. DWORD dwSize = _MAX_PATH;
  838. dwRc = GetCurrentRawKeyValue (
  839. hKey,
  840. pValueName,
  841. bRevision,
  842. &dwType,
  843. &dwSize
  844. );
  845. if( dwRc != ERROR_SUCCESS )
  846. {
  847. return dwRc;
  848. }
  849. wcscpy( szDest, QUOTE );
  850. for( DWORD i=0; i<dwSize; i++ )
  851. {
  852. swprintf( ByteBuf, L"%02x", bRevision[i]);
  853. wcscat( szDest, ByteBuf );
  854. }
  855. wcscat(szDest, QUOTE);
  856. chsDest = szDest;
  857. return dwRc;
  858. }
  859. DWORD CRegistry::GetCurrentBinaryKeyValue (
  860. LPCWSTR pValueName,
  861. LPBYTE pbDest,
  862. LPDWORD pSizeOfDestValue
  863. )
  864. {
  865. DWORD dwType = 0 ;
  866. return GetCurrentRawKeyValue (
  867. hKey,
  868. pValueName,
  869. pbDest,
  870. &dwType,
  871. &(*pSizeOfDestValue)
  872. ) ;
  873. }
  874. DWORD CRegistry::GetCurrentBinaryKeyValue (
  875. HKEY UseKey ,
  876. LPCWSTR pValueName ,
  877. LPBYTE pbDest ,
  878. LPDWORD pSizeOfDestValue )
  879. {
  880. DWORD dwType = 0 ;
  881. return GetCurrentRawKeyValue (
  882. UseKey,
  883. pValueName,
  884. pbDest,
  885. &dwType,
  886. &(*pSizeOfDestValue)
  887. ) ;
  888. }
  889. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  890. Function:
  891. Description:
  892. Arguments:
  893. Returns:
  894. Inputs:
  895. Outputs:
  896. Caveats:
  897. Raid:
  898. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  899. DWORD CRegistry::GetCurrentSubKeyName (
  900. CHString &DestSubKeyName
  901. )
  902. {
  903. WCHAR KeyName[MAX_SUBKEY_BUFFERSIZE];
  904. DWORD RetValue;
  905. // and don't bother having RegEnumKey error out
  906. if(CurrentSubKeyIndex >= dwcSubKeys)
  907. {
  908. // If we have exceeded the number of subkeys available tell the caller
  909. return( ERROR_NO_MORE_ITEMS );
  910. }
  911. RetValue = myRegEnumKey (
  912. hKey,
  913. CurrentSubKeyIndex,
  914. KeyName,
  915. MAX_SUBKEY_BUFFERSIZE
  916. );
  917. // If we are successfull reading the name
  918. //=======================================
  919. if(ERROR_SUCCESS == RetValue)
  920. {
  921. DestSubKeyName = KeyName;
  922. }
  923. else
  924. {
  925. // Otherwise clear the string so we don't leave garbage
  926. //=====================================================
  927. DestSubKeyName.Empty();
  928. }
  929. return RetValue; // In either event, return the value RegEnumKey returned
  930. }
  931. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  932. Function:
  933. Description:
  934. Arguments:
  935. Returns:
  936. Inputs:
  937. Outputs:
  938. Caveats:
  939. Raid:
  940. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  941. DWORD CRegistry::GetCurrentSubKeyPath (
  942. CHString &DestSubKeyPath
  943. )
  944. {
  945. CHString TempName;
  946. DWORD dwRet;
  947. dwRet = GetCurrentSubKeyName(TempName);
  948. if (dwRet == ERROR_SUCCESS)
  949. {
  950. DestSubKeyPath = RootKeyPath+"\\";
  951. DestSubKeyPath += TempName;
  952. }
  953. else
  954. {
  955. DestSubKeyPath.Empty();
  956. }
  957. return dwRet;
  958. }
  959. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  960. Function:
  961. Description:
  962. Arguments:
  963. Returns:
  964. Inputs:
  965. Outputs:
  966. Caveats:
  967. Raid:
  968. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  969. void CRegistry::Close(void)
  970. {
  971. if(hSubKey != NULL)
  972. {
  973. RegCloseKey(hSubKey) ;
  974. hSubKey = NULL ;
  975. }
  976. if(hKey != NULL)
  977. {
  978. RegCloseKey(hKey);
  979. hKey = NULL;
  980. }
  981. if(hRootKey != NULL && m_fFromCurrentUser)
  982. {
  983. RegCloseKey(hRootKey);
  984. hRootKey = NULL;
  985. }
  986. SetDefaultValues(); // Reset all the member vars for next
  987. }
  988. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  989. Function:
  990. Description:
  991. Arguments:
  992. Returns:
  993. Inputs:
  994. Outputs:
  995. Caveats:
  996. Raid:
  997. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  998. DWORD CRegistry::OpenSubKey(void)
  999. {
  1000. CHString SubKeyPath;
  1001. LONG RetValue;
  1002. // If they try and open the same subkey again then
  1003. // leave things alone, otherwise open the subkey
  1004. if(hSubKey)
  1005. {
  1006. return ERROR_SUCCESS;
  1007. }
  1008. // Get the current subkey path
  1009. //============================
  1010. GetCurrentSubKeyPath(SubKeyPath);
  1011. // Just return the value and the hKey value never gets changed from NULL
  1012. //======================================================================
  1013. RetValue = myRegOpenKeyEx (
  1014. hRootKey,
  1015. (LPCWSTR)SubKeyPath, // address of name of subkey to open
  1016. (DWORD) 0, // reserved
  1017. KEY_READ, // security access mask
  1018. (PHKEY)&hSubKey // address of handle of open key
  1019. );
  1020. return RetValue;
  1021. }
  1022. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1023. Function:
  1024. Description:
  1025. Arguments:
  1026. Returns:
  1027. Inputs:
  1028. Outputs:
  1029. Caveats:
  1030. Raid:
  1031. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1032. void CRegistry::RewindSubKeys(void)
  1033. {
  1034. CurrentSubKeyIndex = 0;
  1035. }
  1036. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1037. Function:
  1038. Description:
  1039. Arguments:
  1040. Returns:
  1041. Inputs:
  1042. Outputs:
  1043. Caveats:
  1044. Raid:
  1045. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1046. void CRegistry::CloseSubKey(void)
  1047. {
  1048. if(hSubKey != NULL)
  1049. {
  1050. RegCloseKey(hSubKey);
  1051. }
  1052. hSubKey = NULL; // Only Close once
  1053. }
  1054. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1055. Function:
  1056. Description:
  1057. Arguments:
  1058. Returns:
  1059. Inputs:
  1060. Outputs:
  1061. Caveats:
  1062. Raid:
  1063. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1064. DWORD CRegistry::GetCurrentRawSubKeyValue (
  1065. LPCWSTR pValueName,
  1066. void *pDestValue,
  1067. LPDWORD pValueType,
  1068. LPDWORD pSizeOfDestValue
  1069. )
  1070. {
  1071. // Try and open subkey
  1072. // and set hSubKey variable
  1073. // ========================
  1074. DWORD RetValue = OpenSubKey();
  1075. // If subkey is open then get value
  1076. // ================================
  1077. if(ERROR_SUCCESS == RetValue)
  1078. {
  1079. RetValue = GetCurrentRawKeyValue (
  1080. hSubKey,
  1081. pValueName,
  1082. pDestValue,
  1083. pValueType,
  1084. pSizeOfDestValue
  1085. );
  1086. }
  1087. return RetValue;
  1088. }
  1089. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1090. Function:
  1091. Description:
  1092. Arguments:
  1093. Returns:
  1094. Inputs:
  1095. Outputs:
  1096. Caveats:
  1097. Raid:
  1098. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1099. DWORD CRegistry::GetCurrentSubKeyValue (
  1100. LPCWSTR pValueName,
  1101. void *pDestValue,
  1102. LPDWORD pSizeOfDestValue
  1103. )
  1104. {
  1105. DWORD RetValue;
  1106. // Try and open subkey
  1107. // and set hSubKey variable
  1108. // ========================
  1109. RetValue = OpenSubKey();
  1110. // If subkey is open then get value
  1111. // ================================
  1112. if(ERROR_SUCCESS == RetValue)
  1113. {
  1114. RetValue = GetCurrentRawSubKeyValue (
  1115. pValueName,
  1116. pDestValue,
  1117. NULL,
  1118. pSizeOfDestValue
  1119. );
  1120. }
  1121. return RetValue;
  1122. }
  1123. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1124. Function:
  1125. Description:
  1126. Arguments:
  1127. Returns:
  1128. Inputs:
  1129. Outputs:
  1130. Caveats:
  1131. Raid:
  1132. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1133. DWORD CRegistry::GetCurrentSubKeyValue (
  1134. LPCWSTR pValueName,
  1135. CHString &DestValue
  1136. )
  1137. {
  1138. DWORD RetValue;
  1139. // Try and open subkey
  1140. // and set hSubKey variable
  1141. // ========================
  1142. RetValue = OpenSubKey();
  1143. // If subkey is open then get value
  1144. // ================================
  1145. if(ERROR_SUCCESS == RetValue)
  1146. {
  1147. RetValue = GetCurrentKeyValue (
  1148. hSubKey,
  1149. pValueName,
  1150. DestValue
  1151. );
  1152. }
  1153. return RetValue;
  1154. }
  1155. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1156. Function:
  1157. Description:
  1158. Arguments:
  1159. Returns:
  1160. Inputs:
  1161. Outputs:
  1162. Caveats:
  1163. Raid:
  1164. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1165. DWORD CRegistry::GetCurrentSubKeyValue (
  1166. LPCWSTR pValueName,
  1167. DWORD &DestValue
  1168. )
  1169. {
  1170. DWORD RetValue;
  1171. // Try and open subkey
  1172. // and set hSubKey variable
  1173. // ========================
  1174. RetValue = OpenSubKey();
  1175. // If subkey is open then get value
  1176. // ================================
  1177. if(ERROR_SUCCESS == RetValue)
  1178. {
  1179. RetValue = GetCurrentKeyValue (
  1180. hSubKey,
  1181. pValueName,
  1182. DestValue
  1183. );
  1184. }
  1185. return RetValue;
  1186. }
  1187. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1188. Function:
  1189. Description:
  1190. Arguments:
  1191. Returns:
  1192. Inputs:
  1193. Outputs:
  1194. Caveats:
  1195. Raid:
  1196. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1197. DWORD CRegistry::NextSubKey(void)
  1198. {
  1199. if (CurrentSubKeyIndex >= dwcSubKeys)
  1200. {
  1201. return( ERROR_NO_MORE_ITEMS );
  1202. }
  1203. // Close the currently opened subkey
  1204. CloseSubKey();
  1205. if(++CurrentSubKeyIndex >= dwcSubKeys)
  1206. {
  1207. // CurrentSubKeyIndex is 0 based, dwcSubKeys is one based
  1208. return( ERROR_NO_MORE_ITEMS );
  1209. }
  1210. else
  1211. {
  1212. return (ERROR_SUCCESS);
  1213. }
  1214. }
  1215. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1216. Function:
  1217. Description:
  1218. Arguments:
  1219. Returns:
  1220. Inputs:
  1221. Outputs:
  1222. Caveats:
  1223. Raid:
  1224. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1225. void CRegistry::PrepareToReOpen(void)
  1226. {
  1227. Close();
  1228. SetDefaultValues();
  1229. }
  1230. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1231. Function: SetCurrentKeyValueString(LPCSTR pValueName, CHString &DestValue)
  1232. Description: sets registry string using REG_SZ
  1233. Arguments:
  1234. Returns:
  1235. Inputs:
  1236. Outputs:
  1237. Caveats:
  1238. Raid:
  1239. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1240. DWORD CRegistry::SetCurrentKeyValue (
  1241. LPCWSTR pValueName,
  1242. CHString &DestValue
  1243. )
  1244. {
  1245. DWORD dwResult;
  1246. if(DestValue.Find(_T('%')) != -1)
  1247. {
  1248. dwResult = SetCurrentKeyValueExpand (
  1249. hKey,
  1250. pValueName,
  1251. DestValue
  1252. );
  1253. }
  1254. else
  1255. {
  1256. dwResult = SetCurrentKeyValue (
  1257. hKey,
  1258. pValueName,
  1259. DestValue
  1260. );
  1261. }
  1262. return dwResult ;
  1263. }
  1264. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1265. Function:
  1266. Description:
  1267. Arguments:
  1268. Returns:
  1269. Inputs:
  1270. Outputs:
  1271. Caveats:
  1272. Raid:
  1273. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1274. DWORD CRegistry::SetCurrentKeyValue (
  1275. LPCWSTR pValueName,
  1276. DWORD &DestValue
  1277. )
  1278. {
  1279. DWORD dwResult = SetCurrentKeyValue (
  1280. hKey,
  1281. pValueName,
  1282. DestValue
  1283. );
  1284. return dwResult ;
  1285. }
  1286. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1287. Function: SetCurrentKeyValue(LPCSTR pValueName, CHStringArray &DestValue)
  1288. Description: sets registry string using REG_MULIT_SZ
  1289. Arguments:
  1290. Returns:
  1291. Inputs:
  1292. Outputs:
  1293. Caveats:
  1294. Raid:
  1295. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1296. DWORD CRegistry::SetCurrentKeyValue (
  1297. LPCWSTR pValueName,
  1298. CHStringArray &DestValue
  1299. )
  1300. {
  1301. DWORD dwResult = SetCurrentKeyValue (
  1302. hKey,
  1303. pValueName,
  1304. DestValue
  1305. );
  1306. return dwResult ;
  1307. }
  1308. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1309. Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, CHString &DestValue)
  1310. Description: sets registry string using REG_MULIT_SZ
  1311. Arguments:
  1312. Returns:
  1313. Inputs:
  1314. Outputs:
  1315. Caveats:
  1316. Raid:
  1317. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1318. DWORD CRegistry::SetCurrentKeyValue (
  1319. HKEY hUseKey,
  1320. LPCWSTR pValueName,
  1321. CHString &DestValue
  1322. )
  1323. {
  1324. DWORD dwResult = myRegSetValueEx (
  1325. hUseKey, // key handle
  1326. pValueName, // name of value
  1327. 0, // reserved -- must be zero
  1328. REG_SZ, // data type
  1329. (const BYTE*)(LPCWSTR)DestValue,
  1330. ( DestValue.GetLength() + 1 ) * sizeof ( WCHAR )
  1331. );
  1332. return dwResult ;
  1333. }
  1334. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1335. Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, DWORD &DestValue)
  1336. Description: sets registry string using REG_MULIT_SZ
  1337. Arguments:
  1338. Returns:
  1339. Inputs:
  1340. Outputs:
  1341. Caveats:
  1342. Raid:
  1343. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1344. DWORD CRegistry::SetCurrentKeyValue (
  1345. HKEY hUseKey,
  1346. LPCWSTR pValueName,
  1347. DWORD &DestValue
  1348. )
  1349. {
  1350. DWORD dwResult = myRegSetValueEx (
  1351. hUseKey, // key handle
  1352. pValueName, // name of value
  1353. 0, // reserved -- must be zero
  1354. REG_DWORD, // data type
  1355. (const BYTE*)&DestValue,
  1356. sizeof(DWORD)
  1357. );
  1358. return dwResult ;
  1359. }
  1360. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1361. Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, CHStringArray &DestValue)
  1362. Description: sets registry string using REG_MULIT_SZ
  1363. Arguments:
  1364. Returns:
  1365. Inputs:
  1366. Outputs:
  1367. Caveats:
  1368. Raid:
  1369. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1370. DWORD CRegistry::SetCurrentKeyValue (
  1371. HKEY hUseKey,
  1372. LPCWSTR pValueName,
  1373. CHStringArray &DestValue
  1374. )
  1375. {
  1376. DWORD dwResult = ERROR_SUCCESS;
  1377. DWORD dwArrayChars = 0;
  1378. for ( LONG Index = 0; Index < DestValue.GetSize(); Index++ )
  1379. {
  1380. CHString chsTemp = DestValue.GetAt(Index);
  1381. dwArrayChars += ( chsTemp.GetLength() + 1 ) * sizeof(WCHAR);
  1382. }
  1383. // Add room for the trailing wide character null
  1384. dwArrayChars += 2;
  1385. WCHAR* pValue = new WCHAR[dwArrayChars];
  1386. if( !pValue )
  1387. {
  1388. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1389. }
  1390. try
  1391. {
  1392. memset( pValue, 0, dwArrayChars*sizeof(WCHAR) );
  1393. DWORD dwCharCount = 0;
  1394. for ( Index = 0; Index < DestValue.GetSize(); Index++ )
  1395. {
  1396. CHString chsTemp = DestValue.GetAt(Index);
  1397. wcscpy(&pValue[dwCharCount], chsTemp.GetBuffer(0));
  1398. dwCharCount += ( chsTemp.GetLength() + 1 ) ;
  1399. }
  1400. dwResult = myRegSetValueEx (
  1401. hUseKey, // key handle
  1402. pValueName, // name of value
  1403. 0, // reserved -- must be zero
  1404. REG_MULTI_SZ, // data type
  1405. (const BYTE *)pValue,
  1406. dwArrayChars
  1407. );
  1408. delete [] pValue;
  1409. pValue = NULL;
  1410. }
  1411. catch ( ... )
  1412. {
  1413. delete [] pValue;
  1414. pValue = NULL;
  1415. throw ;
  1416. }
  1417. return dwResult ;
  1418. }
  1419. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1420. Function: SetCurrentKeyValueExpand(HKEY UseKey, LPCSTR pValueName, CHString &DestValue)
  1421. Description: sets registry string using REG_EXPAND_SZ, required when the string contains variables (e.g., %SystemRoot%)
  1422. Arguments:
  1423. Returns:
  1424. Inputs:
  1425. Outputs:
  1426. Caveats:
  1427. Raid:
  1428. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1429. DWORD CRegistry::SetCurrentKeyValueExpand (
  1430. HKEY hUseKey,
  1431. LPCWSTR pValueName,
  1432. CHString &DestValue
  1433. )
  1434. {
  1435. DWORD dwResult = myRegSetValueEx (
  1436. hUseKey, // key handle
  1437. pValueName, // name of value
  1438. 0, // reserved -- must be zero
  1439. REG_EXPAND_SZ, // data type
  1440. (const BYTE*)(LPCWSTR)DestValue,
  1441. ( DestValue.GetLength() + 1 ) * sizeof ( WCHAR )
  1442. );
  1443. return dwResult ;
  1444. }
  1445. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1446. Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, CHStringArray &DestValue)
  1447. Description: sets registry string using REG_MULIT_SZ
  1448. Arguments:
  1449. Returns:
  1450. Inputs:
  1451. Outputs:
  1452. Caveats:
  1453. Raid:
  1454. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1455. DWORD CRegistry::DeleteCurrentKeyValue (
  1456. LPCWSTR pValueName
  1457. )
  1458. {
  1459. return myRegDeleteValue (
  1460. hKey,
  1461. pValueName
  1462. );
  1463. }
  1464. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1465. Function: SetCurrentKeyValue(HKEY UseKey, LPCSTR pValueName, CHStringArray &DestValue)
  1466. Description: sets registry string using REG_MULIT_SZ
  1467. Arguments:
  1468. Returns:
  1469. Inputs:
  1470. Outputs:
  1471. Caveats:
  1472. Raid:
  1473. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1474. DWORD CRegistry::DeleteCurrentKeyValue (
  1475. HKEY UseKey,
  1476. LPCWSTR pValueName
  1477. )
  1478. {
  1479. return myRegDeleteValue (
  1480. UseKey,
  1481. pValueName
  1482. );
  1483. }
  1484. //*****************************************************************
  1485. ///////////////////////////////////////////////////////////////////
  1486. //
  1487. // Class: CRegistrySearch
  1488. //
  1489. // This class searches through the registry for matching Values,
  1490. // Keys and Partial Keys
  1491. //
  1492. ///////////////////////////////////////////////////////////////////
  1493. //*****************************************************************
  1494. CRegistrySearch::CRegistrySearch()
  1495. {
  1496. }
  1497. ///////////////////////////////////////////////////////////////////
  1498. CRegistrySearch::~CRegistrySearch()
  1499. {
  1500. }
  1501. ///////////////////////////////////////////////////////////////////
  1502. //
  1503. // void CRegistrySearch::CheckAndAddToList( CRegistry * pReg,
  1504. // CHString chsSubKey,
  1505. // CHString chsFullKey,
  1506. // CHPtrArray & chpaList,
  1507. // CHString chsSearchString,
  1508. // int nSearchType)
  1509. //
  1510. // Desc: This function performs the requested search on the
  1511. // current key and if it matches, then adds it to the
  1512. // CHPtrArray
  1513. //
  1514. // Parameters:
  1515. // pReg - The current registry class
  1516. // chsSubKey - The current Key
  1517. // chsFullKey - The complete key
  1518. // chpaList - The target CHPtrArray
  1519. // chsSearchString - The string to search for
  1520. // nSearchType - The type of search, the following are
  1521. // supported:
  1522. // KEY_FULL_MATCH_SEARCH
  1523. // Only keys that match the chsSearchString
  1524. // KEY_PARTIAL_MATCH_SEARCH
  1525. // Keys that have chsSearchString anywhere in them
  1526. // VALUE_SEARCH
  1527. // Values that match chsSearchString
  1528. //
  1529. // History
  1530. // Initial coding jennymc 10/10/96
  1531. //
  1532. ///////////////////////////////////////////////////////////////////
  1533. void CRegistrySearch::CheckAndAddToList (
  1534. CRegistry * pReg,
  1535. CHString chsSubKey,
  1536. CHString chsFullKey,
  1537. CHPtrArray & chpaList,
  1538. CHString chsSearchString,
  1539. CHString chsValue,
  1540. int nSearchType
  1541. )
  1542. {
  1543. BOOL bFound = FALSE;
  1544. //====================================================
  1545. // We need to check out the current key to see if it
  1546. // matches any of our criteria.
  1547. //====================================================
  1548. if( nSearchType == VALUE_SEARCH )
  1549. {
  1550. //====================================================
  1551. // If it is a Value search, then let us try to open
  1552. // the value.
  1553. //====================================================
  1554. CHString chsTmp ;
  1555. if( pReg->GetCurrentSubKeyValue(chsValue, chsTmp) == ERROR_SUCCESS)
  1556. {
  1557. if( chsSearchString.CompareNoCase(chsTmp) == 0 )
  1558. {
  1559. bFound = TRUE;
  1560. }
  1561. }
  1562. }
  1563. else if( nSearchType == KEY_FULL_MATCH_SEARCH )
  1564. {
  1565. if( chsSearchString == chsSubKey )
  1566. {
  1567. bFound = TRUE;
  1568. }
  1569. }
  1570. else
  1571. {
  1572. if( chsSubKey.Find(chsSearchString) )
  1573. {
  1574. bFound = TRUE;
  1575. }
  1576. }
  1577. //====================================================
  1578. // If it was found, then record the key location
  1579. //====================================================
  1580. if( bFound )
  1581. {
  1582. CHString *pchsPtr = new CHString;
  1583. if ( pchsPtr )
  1584. {
  1585. try
  1586. {
  1587. *pchsPtr = chsFullKey;
  1588. chpaList.Add( pchsPtr );
  1589. }
  1590. catch ( ... )
  1591. {
  1592. delete pchsPtr ;
  1593. pchsPtr = NULL;
  1594. throw ;
  1595. }
  1596. }
  1597. else
  1598. {
  1599. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1600. }
  1601. }
  1602. }
  1603. ///////////////////////////////////////////////////////////////////
  1604. // Public function: Documented in cregcls.h
  1605. //
  1606. // History
  1607. // Initial coding jennymc 10/10/96
  1608. //
  1609. ///////////////////////////////////////////////////////////////////
  1610. BOOL CRegistrySearch::SearchAndBuildList (
  1611. CHString chsRootKey,
  1612. CHPtrArray & cpaList,
  1613. CHString chsSearchString,
  1614. CHString chsValue,
  1615. int nSearchType,
  1616. HKEY hkDefault
  1617. )
  1618. {
  1619. BOOL bRc;
  1620. //=======================================================
  1621. // Allocate a registry class to open and enumerate the
  1622. // requested key.
  1623. //=======================================================
  1624. CRegistry *pReg = new CRegistry;
  1625. if( !pReg )
  1626. {
  1627. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1628. }
  1629. try
  1630. {
  1631. //=======================================================
  1632. // If the key cannot be opened, then cleanup and back
  1633. // out.
  1634. //=======================================================
  1635. if( pReg->OpenAndEnumerateSubKeys(hkDefault,chsRootKey, KEY_READ ) != ERROR_SUCCESS )
  1636. {
  1637. delete pReg ;
  1638. pReg = NULL;
  1639. return FALSE;
  1640. }
  1641. try
  1642. {
  1643. CHString chsSubKey ;
  1644. //=======================================================
  1645. // As long as there are subkeys under this key,
  1646. // let us open and enumerate each one, each time
  1647. // checking if it has the value or part of the
  1648. // string we want.
  1649. //
  1650. // The GetCurrentSubKeyName function only returns the
  1651. // current key, we have to add it to the end of the
  1652. // Parent key in order to get the full key name.
  1653. //=======================================================
  1654. while ( pReg->GetCurrentSubKeyName(chsSubKey) == ERROR_SUCCESS )
  1655. {
  1656. CHString chsFullKey ;
  1657. CHString chsSlash = L"\\";
  1658. chsFullKey = chsRootKey + chsSlash + chsSubKey;
  1659. CheckAndAddToList (
  1660. pReg,
  1661. chsSubKey,
  1662. chsFullKey,
  1663. cpaList,
  1664. chsSearchString,
  1665. chsValue,
  1666. nSearchType
  1667. );
  1668. pReg->NextSubKey();
  1669. bRc = SearchAndBuildList (
  1670. chsFullKey,
  1671. cpaList,
  1672. chsSearchString,
  1673. chsValue,
  1674. nSearchType
  1675. );
  1676. }
  1677. //=======================================================
  1678. // Close the current key and delete the registry pointer
  1679. //=======================================================
  1680. pReg->Close();
  1681. }
  1682. catch ( ... )
  1683. {
  1684. pReg->Close();
  1685. throw ;
  1686. }
  1687. delete pReg;
  1688. pReg = NULL;
  1689. }
  1690. catch ( ... )
  1691. {
  1692. delete pReg ;
  1693. pReg = NULL;
  1694. throw ;
  1695. }
  1696. return TRUE;
  1697. }
  1698. ///////////////////////////////////////////////////////////////////
  1699. BOOL CRegistrySearch::FreeSearchList (
  1700. int nType,
  1701. CHPtrArray & cpaList
  1702. )
  1703. {
  1704. BOOL bRc;
  1705. int i;
  1706. int nNum = cpaList.GetSize();
  1707. switch( nType )
  1708. {
  1709. case CSTRING_PTR:
  1710. {
  1711. CHString *pPtr;
  1712. for ( i=0; i < nNum; i++ )
  1713. {
  1714. pPtr = ( CHString * ) cpaList.GetAt(i);
  1715. delete pPtr;
  1716. pPtr = NULL;
  1717. }
  1718. bRc = TRUE;
  1719. }
  1720. break;
  1721. default:
  1722. {
  1723. bRc = FALSE;
  1724. }
  1725. break;
  1726. }
  1727. if( bRc )
  1728. {
  1729. cpaList.RemoveAll();
  1730. }
  1731. return bRc;
  1732. }
  1733. //////////////////////////////////////////////////////////////////////////////
  1734. //
  1735. // FUNCTION : MOPropertySet_DevMem::LocateNTOwnerDevice
  1736. //
  1737. // DESCRIPTION : Helper function for locating a key of the specified
  1738. // name, or a key containg the specified value name.
  1739. //
  1740. // INPUTS : HKEY hKeyParent - Parent Key
  1741. // LPCWSTR pszKeyName - Name of Key to open
  1742. // LPCWSTR pszSubKeyName - Name of SubKey to Find
  1743. // LPCWSTR* ppszValueNames - Array of Value Names
  1744. // DWORD dwNumValueNames - Number of names in array
  1745. //
  1746. // OUTPUTS : CHString& strFoundKeyName - Storage for name of key if found.
  1747. // CHString& strFoundKeyPath - Storage for pathed key name
  1748. //
  1749. // RETURNS : nothing
  1750. //
  1751. // COMMENTS : Recursively Enumerates the registry from a specified
  1752. // starting point until it locates a subkey matching either
  1753. // a supplied subkey name or a value name matching one of
  1754. // the supplied names.
  1755. //
  1756. //////////////////////////////////////////////////////////////////////////////
  1757. BOOL CRegistrySearch::LocateKeyByNameOrValueName(
  1758. HKEY hKeyParent,
  1759. LPCWSTR pszKeyName,
  1760. LPCWSTR pszSubKeyName,
  1761. LPCWSTR* ppszValueNames,
  1762. DWORD dwNumValueNames,
  1763. CHString& strFoundKeyName,
  1764. CHString& strFoundKeyPath
  1765. )
  1766. {
  1767. CRegistry reg;
  1768. BOOL fFound = FALSE;
  1769. // Get out of here if we got garbage parameters
  1770. if ( NULL == pszSubKeyName && NULL == ppszValueNames )
  1771. {
  1772. return FALSE;
  1773. }
  1774. // Open the key for enumeration and go through the sub keys.
  1775. LONG t_Status = reg.OpenAndEnumerateSubKeys (
  1776. hKeyParent,
  1777. pszKeyName,
  1778. KEY_READ
  1779. ) ;
  1780. if ( ERROR_SUCCESS == t_Status )
  1781. {
  1782. try
  1783. {
  1784. CHString strSubKeyName;
  1785. DWORD dwValueBuffSize = 0;
  1786. // As long as we can get sub keys, we can try to find values.
  1787. while ( !fFound && ERROR_SUCCESS == reg.GetCurrentSubKeyName( strSubKeyName ) )
  1788. {
  1789. // First check if the specified sub key name matches the sub key name.
  1790. // If not, then check for the value names.
  1791. if ( NULL != pszSubKeyName && strSubKeyName == pszSubKeyName )
  1792. {
  1793. fFound = TRUE;
  1794. }
  1795. else if ( NULL != ppszValueNames )
  1796. {
  1797. // Enumerate the value names in the array until one is found.
  1798. for ( DWORD dwEnum = 0; !fFound && dwEnum < dwNumValueNames; dwEnum++ )
  1799. {
  1800. t_Status = reg.GetCurrentSubKeyValue(
  1801. ppszValueNames[dwEnum],
  1802. NULL,
  1803. &dwValueBuffSize
  1804. ) ;
  1805. if ( ERROR_SUCCESS == t_Status )
  1806. {
  1807. fFound = TRUE;
  1808. }
  1809. } // FOR dwEnum
  1810. } // IF NULL != ppszValueNames
  1811. // Check if one of the methods located the key. If so, store all
  1812. // the current values.
  1813. if ( !fFound )
  1814. {
  1815. //
  1816. // No success, so recurse (WOOHOO!)
  1817. //
  1818. fFound = LocateKeyByNameOrValueName (
  1819. reg.GethKey(),
  1820. strSubKeyName,
  1821. pszSubKeyName,
  1822. ppszValueNames,
  1823. dwNumValueNames,
  1824. strFoundKeyName,
  1825. strFoundKeyPath
  1826. );
  1827. }
  1828. else
  1829. {
  1830. // Store the actual key name in both the single
  1831. // name and path. We will build the full path
  1832. // as we slide back up the recursive chain.
  1833. strFoundKeyName = strSubKeyName;
  1834. strFoundKeyPath = strSubKeyName;
  1835. }
  1836. // Lastly, since fFound may now have been set by recursion, we will
  1837. // want to attach the current key path to the key name we've opened
  1838. // so when we return out of here, we get the full path to the
  1839. // located key name stored correctly.
  1840. if ( fFound )
  1841. {
  1842. CHString strSavePath( strFoundKeyPath );
  1843. strFoundKeyPath.Format(L"%s\\%s", (LPCWSTR) pszKeyName, (LPCWSTR) strSavePath );
  1844. }
  1845. else
  1846. {
  1847. // Not found yet, so go to the next key.
  1848. reg.NextSubKey();
  1849. }
  1850. } // While !Found
  1851. reg.Close();
  1852. }
  1853. catch ( ... )
  1854. {
  1855. reg.Close () ;
  1856. throw ;
  1857. }
  1858. } // If OpenAndEnumerateSubKeys
  1859. return fFound;
  1860. }
  1861. //========================================================================================
  1862. // These routines are for the multiplatform support
  1863. DWORD CRegistry::GetPlatformID(void)
  1864. {
  1865. OSVERSIONINFOA OsVersionInfoA;
  1866. OsVersionInfoA.dwOSVersionInfoSize = sizeof (OSVERSIONINFOA) ;
  1867. GetVersionExA(&OsVersionInfoA);
  1868. return OsVersionInfoA.dwPlatformId;
  1869. }
  1870. LONG CRegistry::myRegCreateKeyEx (
  1871. HKEY hKey,
  1872. LPCWSTR lpwcsSubKey,
  1873. DWORD Reserved,
  1874. LPWSTR lpwcsClass,
  1875. DWORD dwOptions,
  1876. REGSAM samDesired,
  1877. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  1878. PHKEY phkResult,
  1879. LPDWORD lpdwDisposition
  1880. )
  1881. {
  1882. if (CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT)
  1883. {
  1884. return RegCreateKeyExW (
  1885. hKey,
  1886. lpwcsSubKey,
  1887. Reserved,
  1888. lpwcsClass,
  1889. dwOptions,
  1890. samDesired,
  1891. lpSecurityAttributes,
  1892. phkResult,
  1893. lpdwDisposition
  1894. );
  1895. }
  1896. else
  1897. {
  1898. char *szSubKey = NULL ;
  1899. bool t_ConversionFailure = false ;
  1900. WCSTOANSISTRING ( lpwcsSubKey , szSubKey , t_ConversionFailure ) ;
  1901. if (t_ConversionFailure)
  1902. {
  1903. return ERROR_NO_UNICODE_TRANSLATION;
  1904. }
  1905. char *lpClass = NULL ;
  1906. t_ConversionFailure = false ;
  1907. WCSTOANSISTRING ( lpwcsClass , lpClass , t_ConversionFailure );
  1908. if (t_ConversionFailure)
  1909. {
  1910. return ERROR_NO_UNICODE_TRANSLATION;
  1911. }
  1912. return RegCreateKeyExA (
  1913. hKey,
  1914. szSubKey,
  1915. Reserved,
  1916. lpClass,
  1917. dwOptions,
  1918. samDesired,
  1919. lpSecurityAttributes,
  1920. phkResult,
  1921. lpdwDisposition
  1922. );
  1923. }
  1924. return ERROR_NO_UNICODE_TRANSLATION;
  1925. }
  1926. LONG CRegistry::myRegSetValueEx (
  1927. HKEY hKey,
  1928. LPCWSTR lpwcsSubKey,
  1929. DWORD Reserved,
  1930. DWORD dwType,
  1931. CONST BYTE *lpData,
  1932. DWORD cbData
  1933. )
  1934. {
  1935. LONG lRet;
  1936. if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
  1937. {
  1938. lRet = RegSetValueExW (
  1939. hKey,
  1940. lpwcsSubKey,
  1941. Reserved,
  1942. dwType,
  1943. lpData,
  1944. cbData
  1945. );
  1946. }
  1947. else
  1948. {
  1949. // First convert the key name
  1950. bool t_ConversionFailure = false ;
  1951. char *pName = NULL ;
  1952. if ( lpwcsSubKey != NULL )
  1953. {
  1954. WCSTOANSISTRING ( lpwcsSubKey , pName , t_ConversionFailure ) ;
  1955. if ( ! t_ConversionFailure )
  1956. {
  1957. if ( ! pName )
  1958. {
  1959. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1960. }
  1961. }
  1962. else
  1963. {
  1964. return ERROR_NO_UNICODE_TRANSLATION ;
  1965. }
  1966. }
  1967. // Now, we may need to convert the data
  1968. BYTE *pMyData = NULL ;
  1969. try
  1970. {
  1971. DWORD dwMySize = 0 ;
  1972. bool bDoit = false ;
  1973. switch ( dwType )
  1974. {
  1975. case REG_EXPAND_SZ:
  1976. case REG_SZ:
  1977. {
  1978. // If it's a simple string, convert it
  1979. t_ConversionFailure = false ;
  1980. WCHAR *pStrUnicode = ( WCHAR * ) lpData ;
  1981. char *pStrAnsi = NULL ;
  1982. WCSTOANSISTRING ( pStrUnicode , pStrAnsi , t_ConversionFailure ) ;
  1983. if ( ! t_ConversionFailure )
  1984. {
  1985. if ( pStrAnsi != NULL )
  1986. {
  1987. pMyData = ( BYTE * ) pStrAnsi ;
  1988. dwMySize = strlen ( pStrAnsi ) ;
  1989. bDoit = true ;
  1990. }
  1991. else
  1992. {
  1993. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  1994. }
  1995. }
  1996. else
  1997. {
  1998. return ERROR_NO_UNICODE_TRANSLATION ;
  1999. }
  2000. }
  2001. break ;
  2002. case REG_MULTI_SZ:
  2003. {
  2004. // If it's a multi-sz, it take a little more
  2005. int nLen = ::WideCharToMultiByte (
  2006. CP_ACP ,
  2007. 0 ,
  2008. ( const WCHAR *) lpData ,
  2009. cbData ,
  2010. NULL ,
  2011. 0 ,
  2012. NULL ,
  2013. NULL
  2014. );
  2015. if ( nLen > 0 )
  2016. {
  2017. pMyData = new BYTE [ nLen ] ;
  2018. if ( pMyData != NULL )
  2019. {
  2020. dwMySize = WideCharToMultiByte (
  2021. CP_ACP ,
  2022. 0,
  2023. ( const WCHAR * ) lpData ,
  2024. cbData ,
  2025. ( char * )pMyData ,
  2026. nLen ,
  2027. NULL ,
  2028. NULL
  2029. ) ;
  2030. bDoit = true;
  2031. }
  2032. else
  2033. {
  2034. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2035. }
  2036. }
  2037. else
  2038. {
  2039. lRet = ERROR_NO_UNICODE_TRANSLATION ;
  2040. }
  2041. }
  2042. break ;
  2043. default:
  2044. {
  2045. // All other types, just write it
  2046. pMyData = ( BYTE * ) lpData ;
  2047. dwMySize = cbData ;
  2048. bDoit = true;
  2049. }
  2050. break ;
  2051. }
  2052. if ( bDoit )
  2053. {
  2054. lRet = RegSetValueExA (
  2055. hKey,
  2056. pName,
  2057. Reserved,
  2058. dwType,
  2059. pMyData,
  2060. dwMySize
  2061. );
  2062. }
  2063. if ( ( dwType == REG_MULTI_SZ ) && ( pMyData != NULL ) )
  2064. {
  2065. delete [] pMyData ;
  2066. pMyData = NULL;
  2067. }
  2068. }
  2069. catch ( ... )
  2070. {
  2071. if ( ( dwType == REG_MULTI_SZ ) && ( pMyData != NULL ) )
  2072. {
  2073. delete [] pMyData ;
  2074. pMyData = NULL;
  2075. }
  2076. throw ;
  2077. }
  2078. }
  2079. return lRet;
  2080. }
  2081. LONG CRegistry::myRegQueryValueEx (
  2082. HKEY hKey,
  2083. LPCWSTR lpwcsSubKey,
  2084. LPDWORD Reserved,
  2085. LPDWORD dwType,
  2086. LPBYTE lpData,
  2087. LPDWORD cbData
  2088. )
  2089. {
  2090. LONG lRet;
  2091. if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
  2092. {
  2093. lRet = RegQueryValueExW (
  2094. hKey,
  2095. lpwcsSubKey,
  2096. Reserved,
  2097. dwType,
  2098. lpData,
  2099. cbData
  2100. );
  2101. }
  2102. else
  2103. {
  2104. bool t_ConversionFailure = false ;
  2105. char *pName = NULL ;
  2106. if ( lpwcsSubKey != NULL )
  2107. {
  2108. WCSTOANSISTRING ( lpwcsSubKey , pName , t_ConversionFailure ) ;
  2109. if ( ! t_ConversionFailure )
  2110. {
  2111. if ( ! pName )
  2112. {
  2113. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2114. }
  2115. }
  2116. else
  2117. {
  2118. return ERROR_NO_UNICODE_TRANSLATION ;
  2119. }
  2120. }
  2121. BYTE *pMyData = NULL ;
  2122. try
  2123. {
  2124. if ( lpData != NULL )
  2125. {
  2126. pMyData = new BYTE [ *cbData ] ;
  2127. if ( ! pMyData )
  2128. {
  2129. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2130. }
  2131. }
  2132. if ( ( pMyData != NULL ) || (lpData == NULL))
  2133. {
  2134. DWORD dwMySize = *cbData;
  2135. lRet = RegQueryValueExA (
  2136. hKey,
  2137. pName,
  2138. Reserved,
  2139. dwType,
  2140. pMyData,
  2141. & dwMySize
  2142. ) ;
  2143. // If it worked, we may need to convert the strings
  2144. if ( lRet == ERROR_SUCCESS )
  2145. {
  2146. switch ( *dwType )
  2147. {
  2148. case REG_EXPAND_SZ:
  2149. case REG_SZ:
  2150. {
  2151. // If lpData is null, there isn't any way to say for sure how long the target string needs
  2152. // to be. However, it can't be more than twice as long (it can be less).
  2153. if (lpData == NULL)
  2154. {
  2155. *cbData = dwMySize * 2;
  2156. }
  2157. else
  2158. {
  2159. int nLen = ::MultiByteToWideChar (
  2160. CP_ACP,
  2161. 0,
  2162. (const char *)pMyData,
  2163. -1,
  2164. (WCHAR *)lpData,
  2165. *cbData
  2166. );
  2167. // Convert to bytes
  2168. *cbData = nLen * 2;
  2169. }
  2170. }
  2171. break ;
  2172. case REG_MULTI_SZ:
  2173. {
  2174. // If lpData is null, there isn't any way to say for sure how long the target string needs
  2175. // to be. However, it can't be more than twice as long (it can be less).
  2176. if (lpData == NULL)
  2177. {
  2178. *cbData = dwMySize * 2;
  2179. }
  2180. else
  2181. {
  2182. DWORD dwConverted = MultiByteToWideChar (
  2183. CP_ACP,
  2184. 0,
  2185. (const char *)pMyData,
  2186. dwMySize,
  2187. (WCHAR *)lpData,
  2188. *cbData
  2189. );
  2190. }
  2191. }
  2192. break ;
  2193. default:
  2194. {
  2195. // All other types are handled in RegQueryValue
  2196. *cbData = dwMySize ;
  2197. if( NULL != lpData )
  2198. {
  2199. memcpy ( lpData , pMyData , *cbData ) ;
  2200. }
  2201. }
  2202. break ;
  2203. }
  2204. }
  2205. delete [] pMyData;
  2206. pMyData = NULL;
  2207. }
  2208. }
  2209. catch ( ... )
  2210. {
  2211. delete [] pMyData ;
  2212. pMyData = NULL;
  2213. throw ;
  2214. }
  2215. }
  2216. return lRet;
  2217. }
  2218. LONG CRegistry::myRegEnumKey (
  2219. HKEY hKey,
  2220. DWORD dwIndex,
  2221. LPWSTR lpwcsName,
  2222. DWORD cbData
  2223. )
  2224. {
  2225. if (CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT)
  2226. {
  2227. return RegEnumKeyW (
  2228. hKey,
  2229. dwIndex,
  2230. lpwcsName,
  2231. cbData
  2232. );
  2233. }
  2234. else
  2235. {
  2236. char szName[_MAX_PATH];
  2237. LONG lRet = RegEnumKeyA (
  2238. hKey,
  2239. dwIndex,
  2240. szName,
  2241. cbData
  2242. );
  2243. if (lRet == ERROR_SUCCESS)
  2244. {
  2245. bool t_ConversionFailure = false ;
  2246. WCHAR *pName = NULL ;
  2247. ANSISTRINGTOWCS ( szName , pName , t_ConversionFailure ) ;
  2248. if ( ! t_ConversionFailure )
  2249. {
  2250. if ( pName )
  2251. {
  2252. wcscpy(lpwcsName, pName);
  2253. }
  2254. else
  2255. {
  2256. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2257. }
  2258. }
  2259. else
  2260. {
  2261. return ERROR_NO_UNICODE_TRANSLATION ;
  2262. }
  2263. }
  2264. return lRet;
  2265. }
  2266. }
  2267. LONG CRegistry::myRegDeleteValue (
  2268. HKEY hKey,
  2269. LPCWSTR lpwcsName
  2270. )
  2271. {
  2272. if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
  2273. {
  2274. return RegDeleteValueW (
  2275. hKey,
  2276. lpwcsName
  2277. );
  2278. }
  2279. else
  2280. {
  2281. bool t_ConversionFailure = false ;
  2282. char *pName = NULL ;
  2283. WCSTOANSISTRING ( lpwcsName, pName , t_ConversionFailure ) ;
  2284. if ( ! t_ConversionFailure )
  2285. {
  2286. if ( pName )
  2287. {
  2288. return RegDeleteValueA (
  2289. hKey,
  2290. pName
  2291. );
  2292. }
  2293. else
  2294. {
  2295. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2296. }
  2297. }
  2298. else
  2299. {
  2300. return ERROR_NO_UNICODE_TRANSLATION ;
  2301. }
  2302. }
  2303. return ERROR_NO_UNICODE_TRANSLATION;
  2304. }
  2305. LONG CRegistry::myRegDeleteKey (
  2306. HKEY hKey,
  2307. LPCWSTR lpwcsName
  2308. )
  2309. {
  2310. if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
  2311. {
  2312. return RegDeleteKeyW (
  2313. hKey,
  2314. lpwcsName
  2315. );
  2316. }
  2317. else
  2318. {
  2319. bool t_ConversionFailure = false ;
  2320. char *pName = NULL ;
  2321. WCSTOANSISTRING ( lpwcsName, pName , t_ConversionFailure ) ;
  2322. if ( ! t_ConversionFailure )
  2323. {
  2324. if ( pName )
  2325. {
  2326. return RegDeleteKeyA (
  2327. hKey,
  2328. pName
  2329. );
  2330. }
  2331. else
  2332. {
  2333. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2334. }
  2335. }
  2336. else
  2337. {
  2338. return ERROR_NO_UNICODE_TRANSLATION ;
  2339. }
  2340. }
  2341. return ERROR_NO_UNICODE_TRANSLATION;
  2342. }
  2343. LONG CRegistry::myRegOpenKeyEx (
  2344. HKEY hKey,
  2345. LPCWSTR lpwcsSubKey,
  2346. DWORD ulOptions,
  2347. REGSAM samDesired,
  2348. PHKEY phkResult
  2349. )
  2350. {
  2351. if (CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT)
  2352. {
  2353. return RegOpenKeyExW (
  2354. hKey,
  2355. lpwcsSubKey,
  2356. ulOptions,
  2357. samDesired,
  2358. phkResult
  2359. );
  2360. }
  2361. char *pName = NULL ;
  2362. bool t_ConversionFailure = false ;
  2363. WCSTOANSISTRING ( lpwcsSubKey, pName , t_ConversionFailure );
  2364. if ( ! t_ConversionFailure )
  2365. {
  2366. if ( pName )
  2367. {
  2368. return RegOpenKeyExA (
  2369. hKey,
  2370. pName,
  2371. ulOptions,
  2372. samDesired,
  2373. phkResult
  2374. );
  2375. }
  2376. else
  2377. {
  2378. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2379. }
  2380. }
  2381. return ERROR_NO_UNICODE_TRANSLATION;
  2382. }
  2383. LONG CRegistry::myRegQueryInfoKey (
  2384. HKEY hKey,
  2385. LPWSTR lpwstrClass,
  2386. LPDWORD lpcbClass,
  2387. LPDWORD lpReserved,
  2388. LPDWORD lpcSubKeys,
  2389. LPDWORD lpcbMaxSubKeyLen,
  2390. LPDWORD lpcbMaxClassLen,
  2391. LPDWORD lpcValues,
  2392. LPDWORD lpcbMaxValueNameLen,
  2393. LPDWORD lpcbMaxValueLen,
  2394. LPDWORD lpcbSecurityDescriptor,
  2395. PFILETIME lpftLastWriteTime
  2396. )
  2397. {
  2398. if ( CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT )
  2399. {
  2400. return RegQueryInfoKeyW (
  2401. hKey,
  2402. lpwstrClass,
  2403. lpcbClass,
  2404. lpReserved,
  2405. lpcSubKeys,
  2406. lpcbMaxSubKeyLen,
  2407. lpcbMaxClassLen,
  2408. lpcValues,
  2409. lpcbMaxValueNameLen,
  2410. lpcbMaxValueLen,
  2411. lpcbSecurityDescriptor,
  2412. lpftLastWriteTime
  2413. );
  2414. }
  2415. else
  2416. {
  2417. bool t_ConversionFailure = false ;
  2418. char *pName = NULL ;
  2419. WCSTOANSISTRING ( lpwstrClass, pName, t_ConversionFailure );
  2420. if ( ! t_ConversionFailure )
  2421. {
  2422. if ( pName )
  2423. {
  2424. return RegQueryInfoKeyA (
  2425. hKey,
  2426. pName,
  2427. lpcbClass,
  2428. lpReserved,
  2429. lpcSubKeys,
  2430. lpcbMaxSubKeyLen,
  2431. lpcbMaxClassLen,
  2432. lpcValues,
  2433. lpcbMaxValueNameLen,
  2434. lpcbMaxValueLen,
  2435. lpcbSecurityDescriptor,
  2436. lpftLastWriteTime
  2437. ) ;
  2438. }
  2439. else
  2440. {
  2441. throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
  2442. }
  2443. }
  2444. else
  2445. {
  2446. return ERROR_NO_UNICODE_TRANSLATION;
  2447. }
  2448. }
  2449. return ERROR_NO_UNICODE_TRANSLATION;
  2450. }
  2451. LONG CRegistry::myRegEnumValue (
  2452. HKEY hKey,
  2453. DWORD dwIndex,
  2454. LPWSTR lpValueName,
  2455. LPDWORD lpcbValueName,
  2456. LPDWORD lpReserved,
  2457. LPDWORD lpType,
  2458. LPBYTE lpData,
  2459. LPDWORD lpcbData
  2460. )
  2461. {
  2462. if (CRegistry::s_dwPlatform == VER_PLATFORM_WIN32_NT)
  2463. {
  2464. return RegEnumValueW (
  2465. hKey,
  2466. dwIndex,
  2467. lpValueName,
  2468. lpcbValueName,
  2469. lpReserved,
  2470. lpType,
  2471. lpData,
  2472. lpcbData
  2473. );
  2474. }
  2475. else
  2476. {
  2477. char szData[MAX_PATH * 2];
  2478. LONG lRet = RegEnumValueA (
  2479. hKey,
  2480. dwIndex,
  2481. szData,
  2482. lpcbValueName,
  2483. lpReserved,
  2484. lpType,
  2485. lpData,
  2486. lpcbData
  2487. );
  2488. if (lRet == ERROR_SUCCESS)
  2489. {
  2490. // Get the name.
  2491. mbstowcs(lpValueName, szData, lstrlenA(szData) + 1);
  2492. // Get the value if the data is a string.
  2493. if (*lpType == REG_SZ || *lpType == REG_MULTI_SZ)
  2494. {
  2495. lstrcpyA(szData, (LPSTR) lpData);
  2496. mbstowcs((LPWSTR) lpData, szData, lstrlenA(szData) + 1);
  2497. *lpcbData = (lstrlenW((LPWSTR) lpData) + 1) * sizeof(WCHAR);
  2498. }
  2499. }
  2500. return lRet;
  2501. }
  2502. }