windows-nt/Source/XPSP1/NT/base/screg/winreg/tools/crdel/crdel.c
2020-09-26 16:20:57 +08:00

340 lines
7.7 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
Crdel.c
Abstract:
Author:
David J. Gilman (davegi) 20-Dec-1991
Environment:
Windows, Crt - User Mode
--*/
#include <ctype.h>
#include <stdlib.h>
#include <windows.h>
#include "crtools.h"
//
// KEY_ELEMENT is used to maintain a list of KEYs.
//
typedef struct _KEY_ELEMENT
KEY_ELEMENT,
*PKEY_ELEMENT;
struct _KEY_ELEMENT {
PKEY Key;
PKEY_ELEMENT NextKeyElement;
};
//
// Error and informational messages.
//
PSTR UsageMessage =
"Usage: crdel [-?] [-q] key...\n";
PSTR HelpMessage =
"\n where:\n" \
" -? - display this message.\n" \
" -q - quiet mode\n" \
" key - name(s) of the key(s) to dump.\n" \
"\n A key is formed by specifying one of the predefined handles:\n" \
"\n - HKEY_LOCAL_MACHINE\n" \
" - HKEY_CLASSES_ROOT\n" \
" - HKEY_CURRENT_USER\n" \
" - HKEY_USERS\n" \
"\n followed by a sub-key name.\n" \
"\n An environment variable can be used as shorthand for the\n" \
" predefined handles. For example,\n" \
"\n crdel HKEY_USERS\\davegi\n" \
"\n is equivalent to\n" \
"\n set HKEY_USERS=hu\n" \
" crdel hu\\davegi\n";
PSTR InvalidKeyMessage =
"Invalid key - %s\n";
PSTR InvalidSwitchMessage =
"Invalid switch - %s\n";
PSTR DeletingTreeMessage =
"Deleteing tree %s\n";
VOID
DeleteTree(
IN HKEY KeyHandle
)
{
LONG Error;
DWORD Index;
HKEY ChildHandle;
TSTR KeyName[ MAX_PATH ];
DWORD KeyNameLength;
TSTR ClassName[ MAX_PATH ];
DWORD ClassNameLength;
DWORD TitleIndex;
DWORD NumberOfSubKeys;
DWORD MaxSubKeyLength;
DWORD MaxClassLength;
DWORD NumberOfValues;
DWORD MaxValueNameLength;
DWORD MaxValueDataLength;
DWORD SecurityDescriptorLength;
FILETIME LastWriteTime;
ClassNameLength = MAX_PATH;
Error = RegQueryInfoKey(
KeyHandle,
ClassName,
&ClassNameLength,
&TitleIndex,
&NumberOfSubKeys,
&MaxSubKeyLength,
&MaxClassLength,
&NumberOfValues,
&MaxValueNameLength,
&MaxValueDataLength,
&SecurityDescriptorLength,
&LastWriteTime
);
REG_API_SUCCESS( RegQueryInfoKey );
for( Index = 0; Index < NumberOfSubKeys; Index++ ) {
KeyNameLength = MAX_PATH;
Error = RegEnumKey(
KeyHandle,
0,
KeyName,
KeyNameLength
);
REG_API_SUCCESS( RegEnumKey );
Error = RegOpenKeyEx(
KeyHandle,
KeyName,
REG_OPTION_RESERVED,
KEY_ALL_ACCESS,
&ChildHandle
);
REG_API_SUCCESS( RegOpenKey );
DeleteTree( ChildHandle );
Error = RegCloseKey(
ChildHandle
);
REG_API_SUCCESS( RegCloseKey );
Error = RegDeleteKey(
KeyHandle,
KeyName
);
REG_API_SUCCESS( RegDeleteKey );
}
}
VOID
DeleteKey(
IN PKEY Key
)
{
LONG Error;
ASSERT( Key != NULL );
ASSERT( Key->KeyHandle != NULL );
DeleteTree( Key->KeyHandle );
Error = RegDeleteKey(
Key->Parent->KeyHandle,
Key->SubKeyName
);
REG_API_SUCCESS( RegDeleteKey );
}
VOID
main(
INT argc,
PCHAR argv[ ]
)
/*++
Routine Description:
Arguments:
Return Value:
None.
--*/
{
BOOL Quiet;
PKEY ParsedKey;
PKEY_ELEMENT ParsedKeyElement;
PKEY_ELEMENT ParsedKeysHead;
PKEY_ELEMENT ParsedKeysTail;
KEY_ELEMENT Dummy = { NULL, NULL };
//
// If CrDel is invoked without any command line options, display
// the usage message.
//
if( argc < 2 ) {
DisplayMessage( TRUE, UsageMessage );
}
//
// By default the user is prompted.
//
Quiet = FALSE;
//
// Use a Dummy KEY structure to simplify the list management.
// Initialize the head and tail pointers to point to the Dummy.
//
ParsedKeysHead = &Dummy;
ParsedKeysTail = &Dummy;
//
// Initialize options based on the command line.
//
while( *++argv ) {
//
// If the command line argument is a switch character...
//
if( isswitch(( *argv )[ 0 ] )) {
switch( tolower(( *argv )[ 1 ] )) {
//
// Display the detailed help message and quit.
//
case '?':
DisplayMessage( FALSE, UsageMessage );
DisplayMessage( TRUE, HelpMessage );
break;
//
// Do not prompt user for delete.
//
case 'q':
Quiet = TRUE;
break;
//
// Display invalid switch message and quit.
//
default:
DisplayMessage( FALSE, InvalidSwitchMessage, *argv );
DisplayMessage( TRUE, UsageMessage );
}
} else {
//
// The command line argument was not a switch so attempt to parse
// it into a predefined handle and a sub key.
//
ParsedKey = ParseKey( *argv );
if( ParsedKey ) {
//
// If the command line argument was succesfully parsed,
// allocate and initialize a KEY_ELEMENT, add it to the
// list and update the tail pointer.
//
ParsedKeyElement = ( PKEY_ELEMENT ) malloc(
sizeof( KEY_ELEMENT )
);
ASSERT( ParsedKeyElement );
ParsedKeyElement->Key = ParsedKey;
ParsedKeyElement->NextKeyElement = NULL;
ParsedKeysTail->NextKeyElement = ParsedKeyElement;
ParsedKeysTail = ParsedKeyElement;
} else {
//
// The command line argument was not succesfully parsed,
// so display an invalid key message and continue.
//
DisplayMessage( FALSE, InvalidKeyMessage, *argv );
}
}
}
//
// Command line parsing is complete. Delete the requested keys
// skipping the Dummy KEY_ELEMENT structure.
//
while( ParsedKeysHead = ParsedKeysHead->NextKeyElement ) {
if( ! Quiet ) {
DisplayMessage(
FALSE,
DeletingTreeMessage,
ParsedKeysHead->Key->SubKeyFullName
);
}
DeleteKey( ParsedKeysHead->Key );
//
// Once the KEY structure's Key is deleted both the KEY and
// KEY_ELEMENT can be freed.
//
FreeKey( ParsedKeysHead->Key );
free( ParsedKeysHead );
}
}