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.

339 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. Crdel.c
  5. Abstract:
  6. Author:
  7. David J. Gilman (davegi) 20-Dec-1991
  8. Environment:
  9. Windows, Crt - User Mode
  10. --*/
  11. #include <ctype.h>
  12. #include <stdlib.h>
  13. #include <windows.h>
  14. #include "crtools.h"
  15. //
  16. // KEY_ELEMENT is used to maintain a list of KEYs.
  17. //
  18. typedef struct _KEY_ELEMENT
  19. KEY_ELEMENT,
  20. *PKEY_ELEMENT;
  21. struct _KEY_ELEMENT {
  22. PKEY Key;
  23. PKEY_ELEMENT NextKeyElement;
  24. };
  25. //
  26. // Error and informational messages.
  27. //
  28. PSTR UsageMessage =
  29. "Usage: crdel [-?] [-q] key...\n";
  30. PSTR HelpMessage =
  31. "\n where:\n" \
  32. " -? - display this message.\n" \
  33. " -q - quiet mode\n" \
  34. " key - name(s) of the key(s) to dump.\n" \
  35. "\n A key is formed by specifying one of the predefined handles:\n" \
  36. "\n - HKEY_LOCAL_MACHINE\n" \
  37. " - HKEY_CLASSES_ROOT\n" \
  38. " - HKEY_CURRENT_USER\n" \
  39. " - HKEY_USERS\n" \
  40. "\n followed by a sub-key name.\n" \
  41. "\n An environment variable can be used as shorthand for the\n" \
  42. " predefined handles. For example,\n" \
  43. "\n crdel HKEY_USERS\\davegi\n" \
  44. "\n is equivalent to\n" \
  45. "\n set HKEY_USERS=hu\n" \
  46. " crdel hu\\davegi\n";
  47. PSTR InvalidKeyMessage =
  48. "Invalid key - %s\n";
  49. PSTR InvalidSwitchMessage =
  50. "Invalid switch - %s\n";
  51. PSTR DeletingTreeMessage =
  52. "Deleteing tree %s\n";
  53. VOID
  54. DeleteTree(
  55. IN HKEY KeyHandle
  56. )
  57. {
  58. LONG Error;
  59. DWORD Index;
  60. HKEY ChildHandle;
  61. TSTR KeyName[ MAX_PATH ];
  62. DWORD KeyNameLength;
  63. TSTR ClassName[ MAX_PATH ];
  64. DWORD ClassNameLength;
  65. DWORD TitleIndex;
  66. DWORD NumberOfSubKeys;
  67. DWORD MaxSubKeyLength;
  68. DWORD MaxClassLength;
  69. DWORD NumberOfValues;
  70. DWORD MaxValueNameLength;
  71. DWORD MaxValueDataLength;
  72. DWORD SecurityDescriptorLength;
  73. FILETIME LastWriteTime;
  74. ClassNameLength = MAX_PATH;
  75. Error = RegQueryInfoKey(
  76. KeyHandle,
  77. ClassName,
  78. &ClassNameLength,
  79. &TitleIndex,
  80. &NumberOfSubKeys,
  81. &MaxSubKeyLength,
  82. &MaxClassLength,
  83. &NumberOfValues,
  84. &MaxValueNameLength,
  85. &MaxValueDataLength,
  86. &SecurityDescriptorLength,
  87. &LastWriteTime
  88. );
  89. REG_API_SUCCESS( RegQueryInfoKey );
  90. for( Index = 0; Index < NumberOfSubKeys; Index++ ) {
  91. KeyNameLength = MAX_PATH;
  92. Error = RegEnumKey(
  93. KeyHandle,
  94. 0,
  95. KeyName,
  96. KeyNameLength
  97. );
  98. REG_API_SUCCESS( RegEnumKey );
  99. Error = RegOpenKeyEx(
  100. KeyHandle,
  101. KeyName,
  102. REG_OPTION_RESERVED,
  103. KEY_ALL_ACCESS,
  104. &ChildHandle
  105. );
  106. REG_API_SUCCESS( RegOpenKey );
  107. DeleteTree( ChildHandle );
  108. Error = RegCloseKey(
  109. ChildHandle
  110. );
  111. REG_API_SUCCESS( RegCloseKey );
  112. Error = RegDeleteKey(
  113. KeyHandle,
  114. KeyName
  115. );
  116. REG_API_SUCCESS( RegDeleteKey );
  117. }
  118. }
  119. VOID
  120. DeleteKey(
  121. IN PKEY Key
  122. )
  123. {
  124. LONG Error;
  125. ASSERT( Key != NULL );
  126. ASSERT( Key->KeyHandle != NULL );
  127. DeleteTree( Key->KeyHandle );
  128. Error = RegDeleteKey(
  129. Key->Parent->KeyHandle,
  130. Key->SubKeyName
  131. );
  132. REG_API_SUCCESS( RegDeleteKey );
  133. }
  134. VOID
  135. main(
  136. INT argc,
  137. PCHAR argv[ ]
  138. )
  139. /*++
  140. Routine Description:
  141. Arguments:
  142. Return Value:
  143. None.
  144. --*/
  145. {
  146. BOOL Quiet;
  147. PKEY ParsedKey;
  148. PKEY_ELEMENT ParsedKeyElement;
  149. PKEY_ELEMENT ParsedKeysHead;
  150. PKEY_ELEMENT ParsedKeysTail;
  151. KEY_ELEMENT Dummy = { NULL, NULL };
  152. //
  153. // If CrDel is invoked without any command line options, display
  154. // the usage message.
  155. //
  156. if( argc < 2 ) {
  157. DisplayMessage( TRUE, UsageMessage );
  158. }
  159. //
  160. // By default the user is prompted.
  161. //
  162. Quiet = FALSE;
  163. //
  164. // Use a Dummy KEY structure to simplify the list management.
  165. // Initialize the head and tail pointers to point to the Dummy.
  166. //
  167. ParsedKeysHead = &Dummy;
  168. ParsedKeysTail = &Dummy;
  169. //
  170. // Initialize options based on the command line.
  171. //
  172. while( *++argv ) {
  173. //
  174. // If the command line argument is a switch character...
  175. //
  176. if( isswitch(( *argv )[ 0 ] )) {
  177. switch( tolower(( *argv )[ 1 ] )) {
  178. //
  179. // Display the detailed help message and quit.
  180. //
  181. case '?':
  182. DisplayMessage( FALSE, UsageMessage );
  183. DisplayMessage( TRUE, HelpMessage );
  184. break;
  185. //
  186. // Do not prompt user for delete.
  187. //
  188. case 'q':
  189. Quiet = TRUE;
  190. break;
  191. //
  192. // Display invalid switch message and quit.
  193. //
  194. default:
  195. DisplayMessage( FALSE, InvalidSwitchMessage, *argv );
  196. DisplayMessage( TRUE, UsageMessage );
  197. }
  198. } else {
  199. //
  200. // The command line argument was not a switch so attempt to parse
  201. // it into a predefined handle and a sub key.
  202. //
  203. ParsedKey = ParseKey( *argv );
  204. if( ParsedKey ) {
  205. //
  206. // If the command line argument was succesfully parsed,
  207. // allocate and initialize a KEY_ELEMENT, add it to the
  208. // list and update the tail pointer.
  209. //
  210. ParsedKeyElement = ( PKEY_ELEMENT ) malloc(
  211. sizeof( KEY_ELEMENT )
  212. );
  213. ASSERT( ParsedKeyElement );
  214. ParsedKeyElement->Key = ParsedKey;
  215. ParsedKeyElement->NextKeyElement = NULL;
  216. ParsedKeysTail->NextKeyElement = ParsedKeyElement;
  217. ParsedKeysTail = ParsedKeyElement;
  218. } else {
  219. //
  220. // The command line argument was not succesfully parsed,
  221. // so display an invalid key message and continue.
  222. //
  223. DisplayMessage( FALSE, InvalidKeyMessage, *argv );
  224. }
  225. }
  226. }
  227. //
  228. // Command line parsing is complete. Delete the requested keys
  229. // skipping the Dummy KEY_ELEMENT structure.
  230. //
  231. while( ParsedKeysHead = ParsedKeysHead->NextKeyElement ) {
  232. if( ! Quiet ) {
  233. DisplayMessage(
  234. FALSE,
  235. DeletingTreeMessage,
  236. ParsedKeysHead->Key->SubKeyFullName
  237. );
  238. }
  239. DeleteKey( ParsedKeysHead->Key );
  240. //
  241. // Once the KEY structure's Key is deleted both the KEY and
  242. // KEY_ELEMENT can be freed.
  243. //
  244. FreeKey( ParsedKeysHead->Key );
  245. free( ParsedKeysHead );
  246. }
  247. }