303 lines
7.3 KiB
C
303 lines
7.3 KiB
C
|
/*++
|
||
|
|
||
|
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);
|
||
|
|
||
|
}
|
||
|
|
||
|
|