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.

302 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. registry.c
  5. Abstract:
  6. Registry interface routines for Windows NT Setup API Dll.
  7. Author:
  8. Ted Miller (tedm) 6-Feb-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. static
  14. BOOL
  15. _RegistryDelnodeWorker(
  16. IN HKEY ParentKeyHandle,
  17. IN PCTSTR KeyName,
  18. IN DWORD Flags,
  19. OUT PDWORD ErrorCode
  20. )
  21. /*++
  22. Routine Description:
  23. Delete all subkeys of a key whose name and parent's handle was passed as
  24. parameter.
  25. The algorithm used in this function guarantees that the maximum number of
  26. descendent keys will be deleted.
  27. Arguments:
  28. ParentKeyHandle - Handle to the parent of the key that is currently being
  29. examined.
  30. KeyName - Name of the key that is currently being examined. This name can
  31. be an empty string (but not a NULL pointer), and in this case
  32. ParentKeyHandle refers to the key that is being examined.
  33. ErrorCode - Pointer to a variable that will contain an Win32 error code if
  34. the function fails.
  35. Return Value:
  36. BOOL - Returns TRUE if the opearation succeeds.
  37. --*/
  38. {
  39. HKEY CurrentKeyTraverseAccess;
  40. DWORD iSubKey;
  41. TCHAR SubKeyName[MAX_PATH+1];
  42. DWORD SubKeyNameLength;
  43. FILETIME ftLastWriteTime;
  44. LONG Status;
  45. LONG StatusEnum;
  46. LONG SavedStatus;
  47. //
  48. // Do not accept NULL pointer for ErrorCode
  49. //
  50. if(ErrorCode == NULL) {
  51. return(FALSE);
  52. }
  53. //
  54. // Do not accept NULL pointer for KeyName.
  55. //
  56. if(KeyName == NULL) {
  57. *ErrorCode = ERROR_INVALID_PARAMETER;
  58. return(FALSE);
  59. }
  60. //
  61. // Open a handle to the key whose subkeys are to be deleted.
  62. // Since we need to delete its subkeys, the handle must have
  63. // KEY_ENUMERATE_SUB_KEYS access.
  64. //
  65. Status = RegOpenKeyEx(
  66. ParentKeyHandle,
  67. KeyName,
  68. 0,
  69. #ifdef _WIN64
  70. (( Flags & FLG_DELREG_32BITKEY ) ? KEY_WOW64_32KEY:0) |
  71. #else
  72. (( Flags & FLG_DELREG_64BITKEY ) ? KEY_WOW64_64KEY:0) |
  73. #endif
  74. KEY_ENUMERATE_SUB_KEYS | DELETE,
  75. &CurrentKeyTraverseAccess
  76. );
  77. if(Status != ERROR_SUCCESS) {
  78. //
  79. // If unable to enumerate the subkeys, return error.
  80. //
  81. *ErrorCode = Status;
  82. return(FALSE);
  83. }
  84. //
  85. // Traverse the key
  86. //
  87. iSubKey = 0;
  88. SavedStatus = ERROR_SUCCESS;
  89. do {
  90. //
  91. // Get the name of a subkey
  92. //
  93. SubKeyNameLength = sizeof(SubKeyName) / sizeof(TCHAR);
  94. StatusEnum = RegEnumKeyEx(
  95. CurrentKeyTraverseAccess,
  96. iSubKey,
  97. SubKeyName,
  98. &SubKeyNameLength,
  99. NULL,
  100. NULL,
  101. NULL,
  102. &ftLastWriteTime
  103. );
  104. if(StatusEnum == ERROR_SUCCESS) {
  105. //
  106. // Delete all children of the subkey.
  107. // Just assume that the children will be deleted, and don't check
  108. // for failure.
  109. //
  110. _RegistryDelnodeWorker(CurrentKeyTraverseAccess,SubKeyName,0,&Status);
  111. //
  112. // Now delete the subkey, and check for failure.
  113. //
  114. Status = RegDeleteKey(CurrentKeyTraverseAccess,SubKeyName);
  115. //
  116. // If unable to delete the subkey, then save the error code.
  117. // Note that the subkey index is incremented only if the subkey
  118. // was not deleted.
  119. //
  120. if(Status != ERROR_SUCCESS) {
  121. iSubKey++;
  122. SavedStatus = Status;
  123. }
  124. } else {
  125. //
  126. // If unable to get a subkey name due to ERROR_NO_MORE_ITEMS,
  127. // then the key doesn't have subkeys, or all subkeys were already
  128. // enumerated. Otherwise, an error has occurred, so just save
  129. // the error code.
  130. //
  131. if(StatusEnum != ERROR_NO_MORE_ITEMS) {
  132. SavedStatus = StatusEnum;
  133. }
  134. }
  135. //if((StatusEnum != ERROR_SUCCESS ) && (StatusEnum != ERROR_NO_MORE_ITEMS)) {
  136. // printf( "RegEnumKeyEx() failed, Key Name = %ls, Status = %d, iSubKey = %d \n",KeyName,StatusEnum,iSubKey);
  137. //}
  138. } while(StatusEnum == ERROR_SUCCESS);
  139. //
  140. // Close the handle to the key whose subkeys were deleted, and return
  141. // the result of the operation.
  142. //
  143. RegCloseKey(CurrentKeyTraverseAccess);
  144. if(SavedStatus != ERROR_SUCCESS) {
  145. *ErrorCode = SavedStatus;
  146. return(FALSE);
  147. }
  148. return(TRUE);
  149. }
  150. DWORD
  151. pSetupRegistryDelnodeEx(
  152. IN HKEY RootKey,
  153. IN PCTSTR SubKeyName,
  154. IN DWORD ExtraFlags
  155. )
  156. /*++
  157. Routine Description:
  158. This routine deletes a registry key and gets rid of everything under it recursively.
  159. Arguments:
  160. RootKey - Supplies handle to open registry key..ex. HKLM etc.
  161. SubKeyName - Name of the SubKey that we wish to recursively delete.
  162. ExtraFlags - Flags that are specified in the DelReg section of the INF.
  163. Return Value:
  164. If successful, the return value is NO_ERROR, otherwise, it is an error code.
  165. --*/
  166. {
  167. DWORD d,err,Status;
  168. HKEY hKey;
  169. PTSTR p;
  170. PTSTR TempKey = NULL;
  171. d = _RegistryDelnodeWorker(RootKey,SubKeyName,ExtraFlags,&err) ? NO_ERROR : err;
  172. if((d == ERROR_FILE_NOT_FOUND) || (d == ERROR_PATH_NOT_FOUND)) {
  173. d = NO_ERROR;
  174. }
  175. if(d == NO_ERROR) {
  176. //
  177. // Delete top-level key
  178. //
  179. #ifdef _WIN64
  180. if( ExtraFlags & FLG_DELREG_32BITKEY ) {
  181. #else
  182. if( ExtraFlags & FLG_DELREG_64BITKEY ) {
  183. #endif
  184. //
  185. // For handling the WOW64 case:
  186. // deleting RootKey\SubKeyName by itself won't work
  187. // split subkeyname into parent\final
  188. // open parent for 32-bit access, and delete final
  189. //
  190. if( TempKey = (PTSTR)pSetupCheckedMalloc( (lstrlen(SubKeyName)+2) * sizeof(TCHAR))){
  191. lstrcpy( TempKey, SubKeyName );
  192. p = _tcsrchr(TempKey, TEXT('\\'));
  193. if(p){
  194. *p++ = TEXT('\0');
  195. d = RegOpenKeyEx(
  196. RootKey,
  197. TempKey,
  198. 0,
  199. #ifdef _WIN64
  200. KEY_WOW64_32KEY |
  201. #else
  202. KEY_WOW64_64KEY |
  203. #endif
  204. DELETE,
  205. &hKey
  206. );
  207. d = RegDeleteKey(hKey, p);
  208. }else{
  209. d = NO_ERROR;
  210. }
  211. pSetupFree( TempKey );
  212. }else{
  213. d = ERROR_NOT_ENOUGH_MEMORY;
  214. }
  215. }else{
  216. //
  217. // native case
  218. //
  219. d = RegDeleteKey(RootKey, SubKeyName);
  220. }
  221. if((d == ERROR_FILE_NOT_FOUND) || (d == ERROR_PATH_NOT_FOUND)) {
  222. //
  223. // at a verbose level, log that this key wasn't found
  224. //
  225. d = NO_ERROR;
  226. }
  227. }
  228. return(d);
  229. }
  230. DWORD
  231. pSetupRegistryDelnode(
  232. IN HKEY RootKey,
  233. IN PCTSTR SubKeyName
  234. )
  235. {
  236. // Calls into Ex Function
  237. return pSetupRegistryDelnodeEx( RootKey, SubKeyName, 0);
  238. }