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.

592 lines
13 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name :
  4. reg.cxx
  5. Abstract:
  6. Class that modifies the registry
  7. Author:
  8. Christopher Achille (cachille)
  9. Project:
  10. Internet Services Setup
  11. Revision History:
  12. June 2001: Created
  13. --*/
  14. #include "stdafx.h"
  15. #include "reg.hxx"
  16. #include "tstr.hxx"
  17. // constructor
  18. //
  19. CRegistry::CRegistry():
  20. m_hKey(NULL)
  21. {
  22. }
  23. // destructor
  24. //
  25. CRegistry::~CRegistry()
  26. {
  27. CloseRegistry();
  28. }
  29. // function: QueryKey
  30. //
  31. // Query our current registry key
  32. //
  33. HKEY
  34. CRegistry::QueryKey()
  35. {
  36. return m_hKey;
  37. }
  38. // function: OpenRegistry
  39. //
  40. // Open a registry handle
  41. //
  42. // Parameters:
  43. // szNodetoOpen - A string containing the node to open
  44. // szSubKey - The subkey that you need to open
  45. // dwAccess - Access that is needed
  46. // pKey - A pointer to a key that is returned
  47. //
  48. // Return
  49. // TRUE - Success
  50. // FALSE - Failure
  51. //
  52. BOOL
  53. CRegistry::OpenRegistry(LPTSTR szNodetoOpen, LPTSTR szSubKey, DWORD dwAccess)
  54. {
  55. HKEY hHandleValue = HKEY_LOCAL_MACHINE;
  56. if ( _tcsicmp( szNodetoOpen, _T("HKCR") ) == 0 )
  57. {
  58. hHandleValue = HKEY_CLASSES_ROOT;
  59. }
  60. else if ( _tcsicmp( szNodetoOpen, _T("HKCC") ) == 0 )
  61. {
  62. hHandleValue = HKEY_CURRENT_CONFIG;
  63. }
  64. else if ( _tcsicmp( szNodetoOpen, _T("HKCU") ) == 0 )
  65. {
  66. hHandleValue = HKEY_CURRENT_USER;
  67. }
  68. else if ( _tcsicmp( szNodetoOpen, _T("HKLM") ) == 0 )
  69. {
  70. hHandleValue = HKEY_LOCAL_MACHINE;
  71. }
  72. else if ( _tcsicmp( szNodetoOpen, _T("HKU") ) == 0 )
  73. {
  74. hHandleValue = HKEY_USERS;
  75. }
  76. return OpenRegistry( hHandleValue, szSubKey, dwAccess );
  77. }
  78. // function: OpenRegistry
  79. //
  80. // Open a registry handle
  81. //
  82. // Parameters:
  83. // hKey - Key to open from
  84. // szSubKey - The subkey that you need to open
  85. // dwAccess - Access that is needed
  86. // bCreateIfNotPresent - Should we create key if not existent?
  87. //
  88. // Return
  89. // TRUE - Success
  90. // FALSE - Failure
  91. //
  92. BOOL
  93. CRegistry::OpenRegistry(HKEY hKey, LPCTSTR szSubKey, DWORD dwAccess, BOOL bCreateIfNotPresent /*= FALSE*/ )
  94. {
  95. DWORD dwRet;
  96. // Close just incase it was open before
  97. CloseRegistry();
  98. dwRet = RegOpenKeyEx(hKey, szSubKey, 0, dwAccess, &m_hKey);
  99. if ( ( dwRet == ERROR_PATH_NOT_FOUND ) &&
  100. ( bCreateIfNotPresent ) )
  101. {
  102. // Try to create is
  103. dwRet = RegCreateKeyEx( hKey,
  104. szSubKey,
  105. 0, // Reserved
  106. NULL,
  107. REG_OPTION_NON_VOLATILE,
  108. dwAccess,
  109. NULL, // SD
  110. &m_hKey,
  111. NULL );
  112. }
  113. return ( dwRet == ERROR_SUCCESS );
  114. }
  115. // function: CloseRegistry
  116. //
  117. void
  118. CRegistry::CloseRegistry()
  119. {
  120. if ( m_hKey )
  121. {
  122. RegCloseKey( m_hKey );
  123. m_hKey = NULL;
  124. }
  125. }
  126. // function: ReadValue
  127. //
  128. // Parameters:
  129. // Value - The container for the Value
  130. //
  131. // Return:
  132. // TRUE - Successfully read
  133. // FALSE - Could not be read
  134. BOOL
  135. CRegistry::ReadValue(LPCTSTR szName, CRegValue &Value)
  136. {
  137. DWORD dwSize = 0;
  138. DWORD dwType;
  139. if ( RegQueryValueEx(m_hKey, szName, NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS)
  140. {
  141. // We could not request the size
  142. return FALSE;
  143. }
  144. if ( !Value.m_buffData.Resize( dwSize ) )
  145. {
  146. // Could not expland value size
  147. return FALSE;
  148. }
  149. Value.m_dwSize = dwSize;
  150. if ( RegQueryValueEx(m_hKey, szName, NULL, &Value.m_dwType, (LPBYTE) Value.m_buffData.QueryPtr() , &dwSize) != ERROR_SUCCESS)
  151. {
  152. // Could not retrieve value
  153. return FALSE;
  154. }
  155. return TRUE;
  156. }
  157. // funtion : ReadValueString
  158. //
  159. // Read a string in from the registry. If it is not string, then fail
  160. //
  161. // Parameters:
  162. // szName - The name of the registry key
  163. // strValue - The value of the registry value
  164. //
  165. // Return:
  166. // TRUE - Successfully read
  167. // FALSE - Could not be read, or it is not a string value
  168. BOOL
  169. CRegistry::ReadValueString(LPCTSTR szName, TSTR *strValue)
  170. {
  171. DWORD dwSize = 0;
  172. DWORD dwType;
  173. if ( RegQueryValueEx(m_hKey, szName, NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS)
  174. {
  175. // We could not request the size
  176. return FALSE;
  177. }
  178. if ( dwType != REG_SZ )
  179. {
  180. // It is not a string
  181. return FALSE;
  182. }
  183. if ( !strValue->Resize( dwSize ) )
  184. {
  185. // Could not expland the string
  186. return FALSE;
  187. }
  188. if ( RegQueryValueEx(m_hKey, szName, NULL, &dwType, (LPBYTE) strValue->QueryStr() , &dwSize) != ERROR_SUCCESS)
  189. {
  190. // Could not retrieve value
  191. return FALSE;
  192. }
  193. return TRUE;
  194. }
  195. // function: SetValue
  196. //
  197. // Parameters:
  198. // szName - Name of Value
  199. // Value - The container for the Value
  200. //
  201. // Return:
  202. // TRUE - Successfully written
  203. // FALSE - Could not be written
  204. BOOL
  205. CRegistry::SetValue(LPCTSTR szName, CRegValue &Value)
  206. {
  207. DWORD dwSize = 0;
  208. if ( RegSetValueEx(m_hKey, szName, NULL, Value.m_dwType, (LPBYTE) Value.m_buffData.QueryPtr(), Value.m_dwSize ) != ERROR_SUCCESS)
  209. {
  210. // Failed to write value
  211. return FALSE;
  212. }
  213. return TRUE;
  214. }
  215. // function: DeleteValue
  216. //
  217. // Parameters:
  218. // szName - Name of item to remove
  219. //
  220. BOOL
  221. CRegistry::DeleteValue(LPCTSTR szName)
  222. {
  223. return ( RegDeleteValue( m_hKey, szName ) == ERROR_SUCCESS );
  224. }
  225. // function: DeleteAllValues
  226. //
  227. // Delete all of the values inside a key
  228. //
  229. // Parameters:
  230. //
  231. BOOL
  232. CRegistry::DeleteAllValues()
  233. {
  234. TSTR strValueName;
  235. DWORD dwRet = ERROR_SUCCESS;
  236. DWORD dwValueNameSize;
  237. if ( !strValueName.Resize( MAX_PATH ) )
  238. {
  239. return FALSE;
  240. }
  241. while ( dwRet == ERROR_SUCCESS )
  242. {
  243. dwValueNameSize = strValueName.QuerySize();
  244. dwRet = RegEnumValue( m_hKey,
  245. 0, // Always delete first item
  246. strValueName.QueryStr(), // Buffer
  247. &dwValueNameSize, // Buffer Size
  248. NULL, // Reserverd
  249. NULL, // Type
  250. NULL, // Data
  251. 0); // Size of Data Buffer
  252. if ( dwRet == ERROR_SUCCESS )
  253. {
  254. dwRet = RegDeleteValue( m_hKey, strValueName.QueryStr() );
  255. }
  256. }
  257. return ( ( dwRet == ERROR_SUCCESS ) ||
  258. ( dwRet == ERROR_NO_MORE_ITEMS )
  259. );
  260. }
  261. // function: DeleteKey
  262. //
  263. // Delete a key, and possible recursively delete the keys within it
  264. //
  265. // Parameters:
  266. // szKeyName - The name of the key to delete
  267. // bDeleteSubKeys - Should we delete all subkeys?
  268. // dwDepth - The depth that we are in, in our recursive calls
  269. //
  270. BOOL
  271. CRegistry::DeleteKey(LPTSTR szKeyName, BOOL bDeleteSubKeys, DWORD dwDepth )
  272. {
  273. CRegistry CurrentKey;
  274. TSTR strSubKeyName;
  275. DWORD dwSubKeySize;
  276. DWORD dwErr = ERROR_SUCCESS;
  277. FILETIME ft;
  278. if ( dwDepth >= REGKEY_RECURSION_MAXDEPTH )
  279. {
  280. // For security reasons, and stack space, lets put a limit on the depth
  281. return FALSE;
  282. }
  283. if ( !strSubKeyName.Resize( MAX_PATH ) )
  284. {
  285. return FALSE;
  286. }
  287. if ( bDeleteSubKeys )
  288. {
  289. if ( !CurrentKey.OpenRegistry( m_hKey, szKeyName, KEY_ALL_ACCESS ) )
  290. {
  291. return FALSE;
  292. }
  293. while ( dwErr == ERROR_SUCCESS )
  294. {
  295. dwSubKeySize = strSubKeyName.QuerySize();
  296. // Always look at the first key, since after you delete the first key,
  297. // the second will automatically become the first, and so on
  298. // WARNING: Watch the return paths for DeleteKey, because if it returns
  299. // a true without deleting the key, we will loop forever...
  300. dwErr = RegEnumKeyEx( CurrentKey.QueryKey(),
  301. 0,
  302. strSubKeyName.QueryStr(),
  303. &dwSubKeySize,
  304. NULL,
  305. NULL,
  306. 0,
  307. &ft );
  308. // Not call this function, to recursively delete the key
  309. // that we have found
  310. if ( dwErr == ERROR_SUCCESS )
  311. {
  312. if ( !CurrentKey.DeleteKey( strSubKeyName.QueryStr(), TRUE, dwDepth + 1 ) )
  313. {
  314. dwErr = ERROR_ACCESS_DENIED;
  315. }
  316. }
  317. }
  318. // This should be treated as success, we hit the end of the list
  319. if ( dwErr == ERROR_NO_MORE_ITEMS )
  320. {
  321. dwErr = ERROR_SUCCESS;
  322. }
  323. // If we had not problem so far and we are deleting recurisively,
  324. // delete all the values in this key
  325. if ( dwErr == ERROR_SUCCESS )
  326. {
  327. if (!CurrentKey.DeleteAllValues() )
  328. {
  329. dwErr = ERROR_ACCESS_DENIED;
  330. }
  331. }
  332. CurrentKey.CloseRegistry();
  333. }
  334. // If we had not problem so far, delete the key itself
  335. if ( dwErr == ERROR_SUCCESS )
  336. {
  337. dwErr = RegDeleteKey( m_hKey, strSubKeyName.QueryStr() );
  338. }
  339. return ( dwErr == ERROR_SUCCESS );
  340. }
  341. // function: Verify Parameters
  342. //
  343. // Verify that the parameters are correct
  344. //
  345. BOOL
  346. CRegistry_MoveValue::VerifyParameters(CItemList &ciParams)
  347. {
  348. if ( ciParams.GetNumberOfItems() == 6 )
  349. {
  350. return TRUE;
  351. }
  352. return FALSE;
  353. }
  354. // function: DoInternalWork
  355. //
  356. // Move a registry value
  357. //
  358. // Parameters:
  359. // ciList - Parameters for function
  360. // 0 - Source location (HKLM/HKCU/...)
  361. // 1 - Source Path (/Software/Microsoft/...)
  362. // 2 - Source Name
  363. // 3 - Target location
  364. // 4 - Target Path
  365. // 5 - Target Name
  366. //
  367. BOOL
  368. CRegistry_MoveValue::DoInternalWork(CItemList &ciList)
  369. {
  370. CRegistry RegSource;
  371. CRegistry RegTarget;
  372. CRegValue Value;
  373. BOOL bRet = TRUE;
  374. BOOL bSameLocation = TRUE;
  375. if ( !RegSource.OpenRegistry(ciList.GetItem(0), ciList.GetItem(1), KEY_READ | KEY_WRITE) )
  376. {
  377. // We could not open this node in the registry
  378. return FALSE;
  379. }
  380. if ( ( _tcsicmp( ciList.GetItem(0), ciList.GetItem(3) ) != 0 ) ||
  381. ( _tcsicmp( ciList.GetItem(1), ciList.GetItem(4) ) != 0 )
  382. )
  383. {
  384. // Since the read and write are not both located at the same node, open the
  385. // write node also.
  386. if ( !RegTarget.OpenRegistry(ciList.GetItem(3), ciList.GetItem(4), KEY_READ |KEY_WRITE ) )
  387. {
  388. // We could not open the node needed for write in the registry
  389. return FALSE;
  390. }
  391. bSameLocation = FALSE;
  392. }
  393. // See if the target already has a value, if it does, then we do not need to move the old value
  394. if ( bSameLocation )
  395. bRet = !RegSource.ReadValue( ciList.GetItem(5), Value );
  396. else
  397. bRet = !RegTarget.ReadValue( ciList.GetItem(5), Value );
  398. if ( bRet )
  399. {
  400. // Try to read old value
  401. bRet = RegSource.ReadValue( ciList.GetItem(2), Value );
  402. }
  403. if ( bRet )
  404. {
  405. // Try to Set the new value
  406. if ( bSameLocation )
  407. bRet = RegSource.SetValue( ciList.GetItem(5), Value );
  408. else
  409. bRet = RegTarget.SetValue( ciList.GetItem(5), Value );
  410. }
  411. if ( bRet )
  412. {
  413. // Remove old value, since we have successfully copied it
  414. bRet = RegSource.DeleteValue( ciList.GetItem(2) );
  415. }
  416. return bRet;
  417. }
  418. // function: GetMethodName
  419. //
  420. LPTSTR
  421. CRegistry_MoveValue::GetMethodName()
  422. {
  423. return _T("Registry_MoveValue");
  424. }
  425. // function: Verify Parameters
  426. //
  427. // Verify that the parameters are correct
  428. //
  429. BOOL
  430. CRegistry_DeleteKey::VerifyParameters(CItemList &ciParams)
  431. {
  432. // 3 parameters are for Root,Path,Name of Key
  433. // 4th parameter can be the if you want it recursively deleted
  434. if ( ( ciParams.GetNumberOfItems() == 3 ) ||
  435. ( ( ciParams.GetNumberOfItems() == 4 ) &&
  436. ( ciParams.IsNumber(3) )
  437. )
  438. )
  439. {
  440. return TRUE;
  441. }
  442. return FALSE;
  443. }
  444. // function: DoInternalWork
  445. //
  446. // Delete a registry key
  447. //
  448. // Parameters:
  449. // ciList - Parameters for function
  450. // 0 - Source location (HKLM/HKCU/...)
  451. // 1 - Source Path (/Software/Microsoft/...)
  452. // 2 - Source Name
  453. // 3 - Recursively delete keys? (optional)
  454. //
  455. BOOL
  456. CRegistry_DeleteKey::DoInternalWork(CItemList &ciList)
  457. {
  458. CRegistry Reg;
  459. BOOL bRet = TRUE;
  460. if ( !Reg.OpenRegistry(ciList.GetItem(0), ciList.GetItem(1), KEY_ALL_ACCESS ) )
  461. {
  462. // We could not open this node in the registry
  463. return FALSE;
  464. }
  465. bRet = Reg.DeleteKey( ciList.GetItem(2), // Name of specific key to delete
  466. ciList.GetNumberOfItems() == 4 ? ciList.GetNumber(3) != 0 : TRUE); // Delete recursively
  467. Reg.CloseRegistry( );
  468. return bRet;
  469. }
  470. // function: GetMethodName
  471. //
  472. LPTSTR
  473. CRegistry_DeleteKey::GetMethodName()
  474. {
  475. return _T("Registry_DeleteKey");
  476. }
  477. // SetDword
  478. //
  479. // Set the value to a DWORD
  480. //
  481. BOOL
  482. CRegValue::SetDword( DWORD dwNewValue )
  483. {
  484. if ( !m_buffData.Resize( sizeof( DWORD ) ) )
  485. {
  486. return FALSE;
  487. }
  488. m_dwSize = sizeof( DWORD );
  489. m_dwType = REG_DWORD;
  490. *( (LPDWORD) m_buffData.QueryPtr() ) = dwNewValue;
  491. return TRUE;
  492. }
  493. // GetDword
  494. //
  495. // Retrieve the DWORD Value from the class
  496. //
  497. BOOL
  498. CRegValue::GetDword( LPDWORD pdwValue )
  499. {
  500. if ( m_dwType != REG_DWORD )
  501. {
  502. // This is not a DWORD
  503. return FALSE;
  504. }
  505. *pdwValue = *( (LPDWORD) m_buffData.QueryPtr() );
  506. return TRUE;
  507. }