Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2957 lines
81 KiB

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