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.

580 lines
16 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CRegistryKey.cpp
  7. //
  8. // Description:
  9. // Contains the definition of the CRegistryKey class.
  10. //
  11. // Maintained By:
  12. // Vij Vasu (Vvasu) 08-MAR-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. //////////////////////////////////////////////////////////////////////////////
  16. // Include Files
  17. //////////////////////////////////////////////////////////////////////////////
  18. // The precompiled header.
  19. #include "pch.h"
  20. //////////////////////////////////////////////////////////////////////////////
  21. //++
  22. //
  23. // CRegistryKey::CRegistryKey()
  24. //
  25. // Description:
  26. // Default constructor of the CRegistryKey class
  27. //
  28. // Arguments:
  29. // None.
  30. //
  31. // Return Value:
  32. // None.
  33. //
  34. // Exceptions Thrown:
  35. // None.
  36. //
  37. //--
  38. //////////////////////////////////////////////////////////////////////////////
  39. CRegistryKey::CRegistryKey( void ) throw()
  40. {
  41. BCATraceScope( "" );
  42. } //*** CRegistryKey::CRegistryKey()
  43. //////////////////////////////////////////////////////////////////////////////
  44. //++
  45. //
  46. // CRegistryKey::CRegistryKey()
  47. //
  48. // Description:
  49. // Constructor of the CRegistryKey class. Opens the specified key.
  50. //
  51. // Arguments:
  52. // hKeyParentIn
  53. // Handle to the parent key.
  54. //
  55. // pszSubKeyNameIn
  56. // Name of the subkey.
  57. //
  58. // samDesiredIn
  59. // Access rights desired. Defaults to KEY_ALL_ACCESS
  60. //
  61. // Return Value:
  62. // None.
  63. //
  64. // Exceptions Thrown:
  65. // Any thrown by functions called.
  66. //
  67. //--
  68. //////////////////////////////////////////////////////////////////////////////
  69. CRegistryKey::CRegistryKey(
  70. HKEY hKeyParentIn
  71. , const WCHAR * pszSubKeyNameIn
  72. , REGSAM samDesiredIn
  73. )
  74. {
  75. BCATraceScope( "" );
  76. OpenKey( hKeyParentIn, pszSubKeyNameIn, samDesiredIn );
  77. } //*** CRegistryKey::CRegistryKey()
  78. //////////////////////////////////////////////////////////////////////////////
  79. //++
  80. //
  81. // CRegistryKey::~CRegistryKey()
  82. //
  83. // Description:
  84. // Default destructor of the CRegistryKey class
  85. //
  86. // Arguments:
  87. // None.
  88. //
  89. // Return Value:
  90. // None.
  91. //
  92. // Exceptions Thrown:
  93. // None.
  94. //
  95. //--
  96. //////////////////////////////////////////////////////////////////////////////
  97. CRegistryKey::~CRegistryKey( void ) throw()
  98. {
  99. BCATraceScope( "" );
  100. } //*** CRegistryKey::~CRegistryKey()
  101. //////////////////////////////////////////////////////////////////////////////
  102. //++
  103. //
  104. // void
  105. // CRegistryKey::OpenKey()
  106. //
  107. // Description:
  108. // Opens the specified key.
  109. //
  110. // Arguments:
  111. // hKeyParentIn
  112. // Handle to the parent key.
  113. //
  114. // pszSubKeyNameIn
  115. // Name of the subkey.
  116. //
  117. // samDesiredIn
  118. // Access rights desired. Defaults to KEY_ALL_ACCESS
  119. //
  120. // Return Value:
  121. // None.
  122. //
  123. // Exceptions Thrown:
  124. // CRuntimeError
  125. // If any of the APIs fail.
  126. //
  127. //--
  128. //////////////////////////////////////////////////////////////////////////////
  129. void
  130. CRegistryKey::OpenKey(
  131. HKEY hKeyParentIn
  132. , const WCHAR * pszSubKeyNameIn
  133. , REGSAM samDesiredIn
  134. )
  135. {
  136. BCATraceScope3( "hKeyParentIn = %p, pszSubKeyNameIn = '%ws', samDesiredIn = %#x", hKeyParentIn, pszSubKeyNameIn == NULL ? L"<null>" : pszSubKeyNameIn, samDesiredIn );
  137. HKEY hTempKey = NULL;
  138. LONG lRetVal;
  139. lRetVal = TW32( RegOpenKeyEx(
  140. hKeyParentIn
  141. , pszSubKeyNameIn
  142. , 0
  143. , samDesiredIn
  144. , &hTempKey
  145. ) );
  146. // Was the key opened properly?
  147. if ( lRetVal != ERROR_SUCCESS )
  148. {
  149. BCATraceMsg2( "RegOpenKeyEx( '%ws' ) retured error %#08x. Throwing an exception.", pszSubKeyNameIn, lRetVal );
  150. LogMsg( "CRegistryKey::OpenKey - RegOpenKeyEx( '%ws' ) retured error %#08x. Throwing an exception.", pszSubKeyNameIn, lRetVal );
  151. THROW_RUNTIME_ERROR(
  152. HRESULT_FROM_WIN32( lRetVal )
  153. , IDS_ERROR_REGISTRY_OPEN
  154. );
  155. } // if: RegOpenKeyEx failed.
  156. BCATraceMsg1( "Handle to key = %p", hTempKey );
  157. // Store the opened key in the member variable.
  158. m_shkKey.Assign( hTempKey );
  159. } //*** CRegistryKey::OpenKey()
  160. //////////////////////////////////////////////////////////////////////////////
  161. //++
  162. //
  163. // void
  164. // CRegistryKey::CreateKey()
  165. //
  166. // Description:
  167. // Creates the specified key. If the key already exists, this functions
  168. // opens the key.
  169. //
  170. // Arguments:
  171. // hKeyParentIn
  172. // Handle to the parent key.
  173. //
  174. // pszSubKeyNameIn
  175. // Name of the subkey.
  176. //
  177. // samDesiredIn
  178. // Access rights desired. Defaults to KEY_ALL_ACCESS
  179. //
  180. // Return Value:
  181. // None.
  182. //
  183. // Exceptions Thrown:
  184. // CRuntimeError
  185. // If any of the APIs fail.
  186. //
  187. //--
  188. //////////////////////////////////////////////////////////////////////////////
  189. void
  190. CRegistryKey::CreateKey(
  191. HKEY hKeyParentIn
  192. , const WCHAR * pszSubKeyNameIn
  193. , REGSAM samDesiredIn
  194. )
  195. {
  196. BCATraceScope3( "hKeyParentIn = %p, pszSubKeyNameIn = '%ws', samDesiredIn = %#x", hKeyParentIn, pszSubKeyNameIn == NULL ? L"<null>" : pszSubKeyNameIn, samDesiredIn );
  197. if ( pszSubKeyNameIn == NULL )
  198. {
  199. BCATraceMsg( "Key = NULL. This is an error! Throwing exception." );
  200. THROW_ASSERT( E_INVALIDARG, "The name of the subkey cannot be NULL." );
  201. }
  202. HKEY hTempKey = NULL;
  203. LONG lRetVal;
  204. lRetVal = TW32( RegCreateKeyEx(
  205. hKeyParentIn
  206. , pszSubKeyNameIn
  207. , 0
  208. , NULL
  209. , REG_OPTION_NON_VOLATILE
  210. , samDesiredIn
  211. , NULL
  212. , &hTempKey
  213. , NULL
  214. ) );
  215. // Was the key opened properly?
  216. if ( lRetVal != ERROR_SUCCESS )
  217. {
  218. BCATraceMsg2( "RegCreateKeyEx( '%ws' ) retured error %#08x. Throwing an exception.", pszSubKeyNameIn, lRetVal );
  219. LogMsg( "CRegistryKey::CreateKey - RegCreateKeyEx( '%ws' ) retured error %#08x.", pszSubKeyNameIn, lRetVal );
  220. THROW_RUNTIME_ERROR(
  221. HRESULT_FROM_WIN32( lRetVal )
  222. , IDS_ERROR_REGISTRY_CREATE
  223. );
  224. } // if: RegCreateKeyEx failed.
  225. BCATraceMsg1( "Handle to key = %p", hTempKey );
  226. // Store the opened key in the member variable.
  227. m_shkKey.Assign( hTempKey );
  228. } //*** CRegistryKey::CreateKey()
  229. //////////////////////////////////////////////////////////////////////////////
  230. //++
  231. //
  232. // void
  233. // CRegistryKey::QueryValue()
  234. //
  235. // Description:
  236. // Reads a value under this key. The memory for this value is allocated
  237. // by this function. The caller is responsible for freeing this memory.
  238. //
  239. // Arguments:
  240. // pszValueNameIn
  241. // Name of the value to read.
  242. //
  243. // ppbDataOut
  244. // Pointer to the pointer to the data. Cannot be NULL.
  245. //
  246. // pdwDataSizeInBytesOut
  247. // Number of bytes allocated in the data buffer. Cannot be NULL.
  248. //
  249. // pdwTypeOut
  250. // Pointer to the type of the value.
  251. //
  252. // Return Value:
  253. // None.
  254. //
  255. // Exceptions Thrown:
  256. // CRuntimeError
  257. // If any of the APIs fail.
  258. //
  259. // CAssert
  260. // If the parameters are incorrect.
  261. //
  262. //--
  263. //////////////////////////////////////////////////////////////////////////////
  264. void
  265. CRegistryKey::QueryValue(
  266. const WCHAR * pszValueNameIn
  267. , LPBYTE * ppbDataOut
  268. , LPDWORD pdwDataSizeBytesOut
  269. , LPDWORD pdwTypeOut
  270. ) const
  271. {
  272. BCATraceScope1( "pszValueNameIn = '%ws'", pszValueNameIn == NULL ? L"<null>" : pszValueNameIn );
  273. LONG lRetVal = ERROR_SUCCESS;
  274. DWORD cbBufferSize = 0;
  275. DWORD dwType = REG_SZ;
  276. // Check parameters
  277. if ( ( pdwDataSizeBytesOut == NULL )
  278. || ( ppbDataOut == NULL )
  279. )
  280. {
  281. BCATraceMsg( "One of the required input pointers is NULL. Throwing exception." );
  282. THROW_ASSERT(
  283. E_INVALIDARG
  284. , "CRegistryKey::QueryValue() => Required input pointer in NULL"
  285. );
  286. } // if: parameters are invalid.
  287. // Initialize outputs.
  288. *ppbDataOut = NULL;
  289. *pdwDataSizeBytesOut = 0;
  290. // Get the required size of the buffer.
  291. lRetVal = TW32( RegQueryValueEx(
  292. m_shkKey.HHandle() // handle to key to query
  293. , pszValueNameIn // address of name of value to query
  294. , 0 // reserved
  295. , NULL // address of buffer for value type
  296. , NULL // address of data buffer
  297. , &cbBufferSize // address of data buffer size
  298. ) );
  299. if ( lRetVal != ERROR_SUCCESS )
  300. {
  301. BCATraceMsg2( "RegQueryValueEx( '%ws' ) retured error %#08x. Throwing an exception.", pszValueNameIn, lRetVal );
  302. LogMsg( "CRegistryKey::QueryValue - RegQueryValueEx( '%ws' ) retured error %#08x.", pszValueNameIn, lRetVal );
  303. THROW_RUNTIME_ERROR(
  304. HRESULT_FROM_WIN32( lRetVal )
  305. , IDS_ERROR_REGISTRY_QUERY
  306. );
  307. }
  308. SmartByteArray sbaBuffer( new BYTE[ cbBufferSize ] );
  309. if ( sbaBuffer.FIsEmpty() )
  310. {
  311. BCATraceMsg1( "Could not allocate %d bytes of memory. Throwing an exception.", cbBufferSize );
  312. LogMsg( "CRegistryKey::QueryValue - Could not allocate %d bytes of memory.", lRetVal );
  313. THROW_RUNTIME_ERROR(
  314. THR( E_OUTOFMEMORY )
  315. , IDS_ERROR_REGISTRY_QUERY
  316. );
  317. }
  318. // Read the value.
  319. lRetVal = TW32( RegQueryValueEx(
  320. m_shkKey.HHandle() // handle to key to query
  321. , pszValueNameIn // address of name of value to query
  322. , 0 // reserved
  323. , &dwType // address of buffer for value type
  324. , sbaBuffer.PMem() // address of data buffer
  325. , &cbBufferSize // address of data buffer size
  326. ) );
  327. // Was the key read properly?
  328. if ( lRetVal != ERROR_SUCCESS )
  329. {
  330. BCATraceMsg2( "RegQueryValueEx( '%ws' ) retured error %#08x. Throwing an exception.", pszValueNameIn, lRetVal );
  331. LogMsg( "CRegistryKey::QueryValue - RegQueryValueEx( '%ws' ) retured error %#08x.", pszValueNameIn, lRetVal );
  332. THROW_RUNTIME_ERROR(
  333. HRESULT_FROM_WIN32( lRetVal )
  334. , IDS_ERROR_REGISTRY_QUERY
  335. );
  336. } // if: RegQueryValueEx failed.
  337. *ppbDataOut = sbaBuffer.PRelease();
  338. *pdwDataSizeBytesOut = cbBufferSize;
  339. if ( pdwTypeOut != NULL )
  340. {
  341. *pdwTypeOut = dwType;
  342. }
  343. } //*** CRegistryKey::QueryValue()
  344. //////////////////////////////////////////////////////////////////////////////
  345. //++
  346. //
  347. // void
  348. // CRegistryKey::SetValue()
  349. //
  350. // Description:
  351. // Writes a value under this key.
  352. //
  353. // Arguments:
  354. // pszValueNameIn
  355. // Name of the value to be set.
  356. //
  357. // cpbDataIn
  358. // Pointer to the pointer to the data buffer.
  359. //
  360. // dwDataSizeInBytesIn
  361. // Number of bytes in the data buffer.
  362. //
  363. // pdwTypeIn
  364. // Type of the value.
  365. //
  366. // Return Value:
  367. // None.
  368. //
  369. // Exceptions Thrown:
  370. // CRuntimeError
  371. // If any of the APIs fail.
  372. //
  373. //--
  374. //////////////////////////////////////////////////////////////////////////////
  375. void
  376. CRegistryKey::SetValue(
  377. const WCHAR * pszValueNameIn
  378. , DWORD dwTypeIn
  379. , const BYTE * cpbDataIn
  380. , DWORD dwDataSizeBytesIn
  381. ) const
  382. {
  383. BCATraceScope5(
  384. "HKEY = %p, pszValueNameIn = '%s', dwTypeIn = %d, cpbDataIn = %p, dwDataSizeBytesIn = %d."
  385. , m_shkKey.HHandle()
  386. , pszValueNameIn
  387. , dwTypeIn
  388. , cpbDataIn
  389. , dwDataSizeBytesIn
  390. );
  391. DWORD dwRetVal = TW32( RegSetValueEx(
  392. m_shkKey.HHandle()
  393. , pszValueNameIn
  394. , 0
  395. , dwTypeIn
  396. , cpbDataIn
  397. , dwDataSizeBytesIn
  398. ) );
  399. if ( dwRetVal != ERROR_SUCCESS )
  400. {
  401. BCATraceMsg2( "RegSetValueEx( '%s' ) retured error %#x. Throwing an exception.", pszValueNameIn, dwRetVal );
  402. LogMsg( "CRegistryKey::SetValue - RegSetValueEx( '%s' ) retured error %#x.", pszValueNameIn, dwRetVal );
  403. THROW_RUNTIME_ERROR(
  404. HRESULT_FROM_WIN32( dwRetVal )
  405. , IDS_ERROR_REGISTRY_SET
  406. );
  407. } // if: RegSetValueEx failed.
  408. } //*** CRegistryKey::SetValue()
  409. //////////////////////////////////////////////////////////////////////////////
  410. //++
  411. //
  412. // void
  413. // CRegistryKey::RenameKey()
  414. //
  415. // Description:
  416. // Rename this key.
  417. //
  418. // Arguments:
  419. // pszNewNameIn
  420. // The new name for this key.
  421. //
  422. // Return Value:
  423. // None.
  424. //
  425. // Exceptions Thrown:
  426. // CRuntimeError
  427. // If any of the APIs fail.
  428. //
  429. // IMPORTANT NOTE:
  430. // This function calls the NtRenameKey API with the handle returned by
  431. // RegOpenKeyEx. This will work as long as we are not dealing with a
  432. // remote registry key.
  433. //
  434. //--
  435. //////////////////////////////////////////////////////////////////////////////
  436. void
  437. CRegistryKey::RenameKey(
  438. const WCHAR * pszNewNameIn
  439. )
  440. {
  441. BCATraceScope2(
  442. "HKEY = %p, pszNewNameIn = '%s'."
  443. , m_shkKey.HHandle()
  444. , pszNewNameIn
  445. );
  446. UNICODE_STRING ustrNewName;
  447. DWORD dwRetVal = ERROR_SUCCESS;
  448. RtlInitUnicodeString( &ustrNewName, pszNewNameIn );
  449. // Begin_Replace00
  450. //
  451. // BUGBUG: Vij Vasu (Vvasu) 10-APR-2000
  452. // Dynamically linking to NtDll.dll to allow testing on Win2K
  453. // Replace the section below ( Begin_Replace00 to End-Replace00 ) with
  454. // the single marked statment ( Begin_Replacement00 to End_Replacement00 ).
  455. //
  456. {
  457. typedef CSmartResource<
  458. CHandleTrait<
  459. HMODULE
  460. , BOOL
  461. , FreeLibrary
  462. , reinterpret_cast< HMODULE >( NULL )
  463. >
  464. > SmartModuleHandle;
  465. SmartModuleHandle smhNtDll( LoadLibrary( L"NtDll.dll" ) );
  466. if ( smhNtDll.FIsInvalid() )
  467. {
  468. dwRetVal = GetLastError();
  469. BCATraceMsg1( "LoadLibrary() retured error %#08x. Throwing an exception.", dwRetVal );
  470. THROW_RUNTIME_ERROR(
  471. dwRetVal // NTSTATUS codes are compatible with HRESULTS
  472. , IDS_ERROR_REGISTRY_RENAME
  473. );
  474. } // if: LoadLibrary failed.
  475. FARPROC pNtRenameKey = GetProcAddress( smhNtDll.HHandle(), "NtRenameKey" );
  476. if ( pNtRenameKey == NULL )
  477. {
  478. dwRetVal = GetLastError();
  479. BCATraceMsg1( "GetProcAddress() retured error %#08x. Throwing an exception.", dwRetVal );
  480. THROW_RUNTIME_ERROR(
  481. dwRetVal // NTSTATUS codes are compatible with HRESULTS
  482. , IDS_ERROR_REGISTRY_RENAME
  483. );
  484. } // if: GetProcAddress() failed
  485. dwRetVal = ( reinterpret_cast< NTSTATUS (*)( HANDLE, PUNICODE_STRING ) >( pNtRenameKey ) )(
  486. m_shkKey.HHandle()
  487. , &ustrNewName
  488. );
  489. }
  490. // End_Replace00
  491. /* Begin_Replacement00 - delete this line
  492. dwRetVal = NtRenameKey(
  493. m_shkKey.HHandle()
  494. , &ustrNewName
  495. );
  496. End_Replacement00 - delete this line */
  497. if ( NT_ERROR( dwRetVal ) )
  498. {
  499. BCATraceMsg2( "NtRenameKey( '%ws' ) retured error %#08x. Throwing an exception.", pszNewNameIn, dwRetVal );
  500. LogMsg( "CRegistryKey::RenameKey - NtRenameKey( '%ws' ) retured error %#08x.", pszNewNameIn, dwRetVal );
  501. THROW_RUNTIME_ERROR(
  502. dwRetVal // NTSTATUS codes are compatible with HRESULTS
  503. , IDS_ERROR_REGISTRY_RENAME
  504. );
  505. } // if: RegRenameKeyEx failed.
  506. } //*** CRegistryKey::RenameKey()