windows-nt/Source/XPSP1/NT/base/pnp/setupapi/sputils/registry.c
2020-09-26 16:20:57 +08:00

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);
}