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.

309 lines
6.4 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // RegUtils.cpp
  7. //
  8. // Abstract:
  9. // Registry utilities
  10. //
  11. // Author:
  12. // Galen Barbee (galenb) November 16, 1998
  13. //
  14. // Revision History:
  15. // 16-Nov-1998 GalenB Stolen from nt\private\gina\samples\gptdemo
  16. //
  17. // Notes:
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "ClusRtlP.h"
  21. #include <tchar.h>
  22. //*************************************************************
  23. //
  24. // CheckSlash()
  25. //
  26. // Purpose: Checks for an ending slash and adds one if
  27. // it is missing.
  28. //
  29. // Parameters: lpDir - directory
  30. //
  31. // Return: Pointer to the end of the string
  32. //
  33. // Comments:
  34. //
  35. // History: Date Author Comment
  36. // 6/19/95 ericflo Created
  37. //
  38. //*************************************************************
  39. LPTSTR CheckSlash( LPTSTR lpDir )
  40. {
  41. DWORD dwStrLen;
  42. LPTSTR lpEnd;
  43. lpEnd = lpDir + lstrlen( lpDir );
  44. if ( *( lpEnd - 1 ) != TEXT( '\\' ) )
  45. {
  46. *lpEnd = TEXT( '\\' );
  47. lpEnd++;
  48. *lpEnd = TEXT( '\0' );
  49. }
  50. return lpEnd;
  51. }
  52. //*************************************************************
  53. //
  54. // RegDelnodeRecurse()
  55. //
  56. // Purpose: Deletes a registry key and all it's subkeys / values.
  57. // Called by RegDelnode
  58. //
  59. // Parameters: hKeyRoot - Root key
  60. // lpSubKey - SubKey to delete
  61. //
  62. // Return: TRUE if successful
  63. // FALSE if an error occurs
  64. //
  65. // Comments:
  66. //
  67. // History: Date Author Comment
  68. // 10/3/95 ericflo Created
  69. //
  70. //*************************************************************
  71. BOOL RegDelnodeRecurse( HKEY hKeyRoot, LPTSTR lpSubKey )
  72. {
  73. LPTSTR lpEnd;
  74. LONG lResult;
  75. DWORD dwSize;
  76. TCHAR szName[MAX_PATH];
  77. HKEY hKey;
  78. FILETIME ftWrite;
  79. //
  80. // First, see if we can delete the key without having
  81. // to recurse.
  82. //
  83. lResult = RegDeleteKey( hKeyRoot, lpSubKey );
  84. if (lResult == ERROR_SUCCESS)
  85. {
  86. return TRUE;
  87. }
  88. lResult = RegOpenKeyEx( hKeyRoot, lpSubKey, 0, KEY_READ, &hKey );
  89. if ( lResult != ERROR_SUCCESS )
  90. {
  91. return FALSE;
  92. }
  93. lpEnd = CheckSlash( lpSubKey );
  94. //
  95. // Enumerate the keys
  96. //
  97. dwSize = MAX_PATH;
  98. lResult = RegEnumKeyEx( hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite );
  99. if ( lResult == ERROR_SUCCESS )
  100. {
  101. do
  102. {
  103. lstrcpy( lpEnd, szName );
  104. if ( !RegDelnodeRecurse( hKeyRoot, lpSubKey ) )
  105. {
  106. break;
  107. }
  108. //
  109. // Enumerate again
  110. //
  111. dwSize = MAX_PATH;
  112. lResult = RegEnumKeyEx( hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite );
  113. } while ( lResult == ERROR_SUCCESS );
  114. }
  115. lpEnd--;
  116. *lpEnd = TEXT( '\0' );
  117. RegCloseKey( hKey );
  118. //
  119. // Try again to delete the key
  120. //
  121. lResult = RegDeleteKey( hKeyRoot, lpSubKey );
  122. if ( lResult == ERROR_SUCCESS )
  123. {
  124. return TRUE;
  125. }
  126. return FALSE;
  127. }
  128. //*************************************************************
  129. //
  130. // RegDelnode()
  131. //
  132. // Purpose: Deletes a registry key and all it's subkeys / values
  133. //
  134. // Parameters: hKeyRoot - Root key
  135. // lpSubKey - SubKey to delete
  136. //
  137. // Return: TRUE if successful
  138. // FALSE if an error occurs
  139. //
  140. // Comments:
  141. //
  142. // History: Date Author Comment
  143. // 10/3/95 ericflo Created
  144. //
  145. //*************************************************************
  146. BOOL RegDelnode( HKEY hKeyRoot, const LPTSTR lpSubKey )
  147. {
  148. TCHAR szDelKey[2 * MAX_PATH];
  149. lstrcpy ( szDelKey, lpSubKey );
  150. return RegDelnodeRecurse( hKeyRoot, szDelKey );
  151. }
  152. //*************************************************************
  153. //
  154. // RegCleanUpValue()
  155. //
  156. // Purpose: Removes the target value and if no more values / keys
  157. // are present, removes the key. This function then
  158. // works up the parent tree removing keys if they are
  159. // also empty. If any parent key has a value / subkey,
  160. // it won't be removed.
  161. //
  162. // Parameters: hKeyRoot - Root key
  163. // lpSubKey - SubKey
  164. // lpValueName - Value to remove
  165. //
  166. //
  167. // Return: TRUE if successful
  168. // FALSE if an error occurs
  169. //
  170. //*************************************************************
  171. BOOL RegCleanUpValue( HKEY hKeyRoot, LPTSTR lpSubKey, LPTSTR lpValueName )
  172. {
  173. LPTSTR lpEnd;
  174. DWORD dwKeys;
  175. DWORD dwValues;
  176. LONG lResult;
  177. HKEY hKey;
  178. TCHAR szDelKey[2 * MAX_PATH];
  179. //
  180. // Make a copy of the subkey so we can write to it.
  181. //
  182. lstrcpy( szDelKey, lpSubKey );
  183. //
  184. // First delete the value
  185. //
  186. lResult = RegOpenKeyEx( hKeyRoot, szDelKey, 0, KEY_WRITE, &hKey );
  187. if ( lResult == ERROR_SUCCESS )
  188. {
  189. lResult = RegDeleteValue( hKey, lpValueName );
  190. RegCloseKey( hKey );
  191. if ( lResult != ERROR_SUCCESS )
  192. {
  193. if ( lResult != ERROR_FILE_NOT_FOUND )
  194. {
  195. //DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to delete value <%s> with %d."), lpValueName, lResult));
  196. return FALSE;
  197. }
  198. }
  199. }
  200. //
  201. // Now loop through each of the parents. If the parent is empty
  202. // eg: no values and no other subkeys, then remove the parent and
  203. // keep working up.
  204. //
  205. lpEnd = szDelKey + lstrlen( szDelKey ) - 1;
  206. while ( lpEnd >= szDelKey )
  207. {
  208. //
  209. // Find the parent key
  210. //
  211. while ( ( lpEnd > szDelKey ) && ( *lpEnd != TEXT( '\\' ) ) )
  212. {
  213. lpEnd--;
  214. }
  215. //
  216. // Open the key
  217. //
  218. lResult = RegOpenKeyEx( hKeyRoot, szDelKey, 0, KEY_READ, &hKey );
  219. if ( lResult != ERROR_SUCCESS )
  220. {
  221. if ( lResult == ERROR_FILE_NOT_FOUND )
  222. {
  223. goto LoopAgain;
  224. }
  225. else
  226. {
  227. //DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to open key <%s> with %d."), szDelKey, lResult));
  228. return FALSE;
  229. }
  230. }
  231. //
  232. // See if there any any values / keys
  233. //
  234. lResult = RegQueryInfoKey( hKey, NULL, NULL, NULL, &dwKeys, NULL, NULL, &dwValues, NULL, NULL, NULL, NULL );
  235. RegCloseKey( hKey );
  236. if ( lResult != ERROR_SUCCESS )
  237. {
  238. //DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to query key <%s> with %d."), szDelKey, lResult));
  239. return FALSE;
  240. }
  241. //
  242. // Exit now if this key has values or keys
  243. //
  244. if ( ( dwKeys != 0 ) || ( dwValues != 0 ) )
  245. {
  246. return TRUE;
  247. }
  248. RegDeleteKey( hKeyRoot, szDelKey );
  249. LoopAgain:
  250. //
  251. // If we are at the beginning of the subkey, we can leave now.
  252. //
  253. if ( lpEnd == szDelKey )
  254. {
  255. return TRUE;
  256. }
  257. //
  258. // There is a parent key. Remove the slash and loop again.
  259. //
  260. if ( *lpEnd == TEXT( '\\' ) )
  261. {
  262. *lpEnd = TEXT( '\0' );
  263. }
  264. }
  265. return TRUE;
  266. }