|
|
/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
registry.c
Abstract:
Registry interface routines for Windows NT Setup API Dll.
Author:
Ted Miller (tedm) 6-Feb-1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
static BOOL _RegistryDelnodeWorker( IN HKEY ParentKeyHandle, IN PCTSTR KeyName, IN DWORD Flags, OUT PDWORD ErrorCode )
/*++
Routine Description:
Delete all subkeys of a key whose name and parent's handle was passed as parameter. The algorithm used in this function guarantees that the maximum number of descendent keys will be deleted.
Arguments:
ParentKeyHandle - Handle to the parent of the key that is currently being examined.
KeyName - Name of the key that is currently being examined. This name can be an empty string (but not a NULL pointer), and in this case ParentKeyHandle refers to the key that is being examined.
ErrorCode - Pointer to a variable that will contain an Win32 error code if the function fails.
Return Value:
BOOL - Returns TRUE if the opearation succeeds.
--*/
{ HKEY CurrentKeyTraverseAccess; DWORD iSubKey; TCHAR SubKeyName[MAX_PATH+1]; DWORD SubKeyNameLength; FILETIME ftLastWriteTime; LONG Status; LONG StatusEnum; LONG SavedStatus;
//
// Do not accept NULL pointer for ErrorCode
//
if(ErrorCode == NULL) { return(FALSE); } //
// Do not accept NULL pointer for KeyName.
//
if(KeyName == NULL) { *ErrorCode = ERROR_INVALID_PARAMETER; return(FALSE); }
//
// Open a handle to the key whose subkeys are to be deleted.
// Since we need to delete its subkeys, the handle must have
// KEY_ENUMERATE_SUB_KEYS access.
//
Status = RegOpenKeyEx( ParentKeyHandle, KeyName, 0, #ifdef _WIN64
(( Flags & FLG_DELREG_32BITKEY ) ? KEY_WOW64_32KEY:0) | #else
(( Flags & FLG_DELREG_64BITKEY ) ? KEY_WOW64_64KEY:0) | #endif
KEY_ENUMERATE_SUB_KEYS | DELETE, &CurrentKeyTraverseAccess );
if(Status != ERROR_SUCCESS) { //
// If unable to enumerate the subkeys, return error.
//
*ErrorCode = Status; return(FALSE); }
//
// Traverse the key
//
iSubKey = 0; SavedStatus = ERROR_SUCCESS; do { //
// Get the name of a subkey
//
SubKeyNameLength = sizeof(SubKeyName) / sizeof(TCHAR); StatusEnum = RegEnumKeyEx( CurrentKeyTraverseAccess, iSubKey, SubKeyName, &SubKeyNameLength, NULL, NULL, NULL, &ftLastWriteTime );
if(StatusEnum == ERROR_SUCCESS) { //
// Delete all children of the subkey.
// Just assume that the children will be deleted, and don't check
// for failure.
//
_RegistryDelnodeWorker(CurrentKeyTraverseAccess,SubKeyName,0,&Status); //
// Now delete the subkey, and check for failure.
//
Status = RegDeleteKey(CurrentKeyTraverseAccess,SubKeyName); //
// If unable to delete the subkey, then save the error code.
// Note that the subkey index is incremented only if the subkey
// was not deleted.
//
if(Status != ERROR_SUCCESS) { iSubKey++; SavedStatus = Status; } } else { //
// If unable to get a subkey name due to ERROR_NO_MORE_ITEMS,
// then the key doesn't have subkeys, or all subkeys were already
// enumerated. Otherwise, an error has occurred, so just save
// the error code.
//
if(StatusEnum != ERROR_NO_MORE_ITEMS) { SavedStatus = StatusEnum; } } //if((StatusEnum != ERROR_SUCCESS ) && (StatusEnum != ERROR_NO_MORE_ITEMS)) {
// printf( "RegEnumKeyEx() failed, Key Name = %ls, Status = %d, iSubKey = %d \n",KeyName,StatusEnum,iSubKey);
//}
} while(StatusEnum == ERROR_SUCCESS);
//
// Close the handle to the key whose subkeys were deleted, and return
// the result of the operation.
//
RegCloseKey(CurrentKeyTraverseAccess);
if(SavedStatus != ERROR_SUCCESS) { *ErrorCode = SavedStatus; return(FALSE); } return(TRUE); }
DWORD pSetupRegistryDelnodeEx( IN HKEY RootKey, IN PCTSTR SubKeyName, IN DWORD ExtraFlags ) /*++
Routine Description:
This routine deletes a registry key and gets rid of everything under it recursively.
Arguments:
RootKey - Supplies handle to open registry key..ex. HKLM etc.
SubKeyName - Name of the SubKey that we wish to recursively delete.
ExtraFlags - Flags that are specified in the DelReg section of the INF.
Return Value:
If successful, the return value is NO_ERROR, otherwise, it is an error code.
--*/ { DWORD d,err,Status; HKEY hKey; PTSTR p; PTSTR TempKey = NULL;
d = _RegistryDelnodeWorker(RootKey,SubKeyName,ExtraFlags,&err) ? NO_ERROR : err;
if((d == ERROR_FILE_NOT_FOUND) || (d == ERROR_PATH_NOT_FOUND)) { d = NO_ERROR; }
if(d == NO_ERROR) { //
// Delete top-level key
//
#ifdef _WIN64
if( ExtraFlags & FLG_DELREG_32BITKEY ) { #else
if( ExtraFlags & FLG_DELREG_64BITKEY ) { #endif
//
// For handling the WOW64 case:
// deleting RootKey\SubKeyName by itself won't work
// split subkeyname into parent\final
// open parent for 32-bit access, and delete final
//
if( TempKey = (PTSTR)pSetupCheckedMalloc( (lstrlen(SubKeyName)+2) * sizeof(TCHAR))){
lstrcpy( TempKey, SubKeyName ); p = _tcsrchr(TempKey, TEXT('\\')); if(p){ *p++ = TEXT('\0');
d = RegOpenKeyEx( RootKey, TempKey, 0, #ifdef _WIN64
KEY_WOW64_32KEY | #else
KEY_WOW64_64KEY | #endif
DELETE, &hKey );
d = RegDeleteKey(hKey, p);
}else{
d = NO_ERROR;
} pSetupFree( TempKey );
}else{ d = ERROR_NOT_ENOUGH_MEMORY; } }else{ //
// native case
//
d = RegDeleteKey(RootKey, SubKeyName); }
if((d == ERROR_FILE_NOT_FOUND) || (d == ERROR_PATH_NOT_FOUND)) { //
// at a verbose level, log that this key wasn't found
//
d = NO_ERROR; } }
return(d); }
DWORD pSetupRegistryDelnode( IN HKEY RootKey, IN PCTSTR SubKeyName ) { // Calls into Ex Function
return pSetupRegistryDelnodeEx( RootKey, SubKeyName, 0);
}
|