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.

312 lines
8.0 KiB

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