|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
services.c
Abstract:
This module implements all access to the services db.
Author:
Wesley Witt (wesw) 21-Oct-1998
Revision History:
--*/
#include "cmdcons.h"
#pragma hdrstop
#include "ntregapi.h"
// forward-decl
BOOLEAN RcFindService( IN LPCWSTR ServiceName, OUT HANDLE* KeyHandle ); BOOLEAN RcFindServiceByDisplayName( IN HANDLE ServicesKey, IN LPCWSTR ServiceName, OUT HANDLE* KeyHandle ); BOOLEAN RcGetStartType( IN HANDLE hKey, OUT DWORD *start_type ); BOOLEAN RcSetStartType( IN HANDLE hKey, OUT DWORD start_type ); BOOLEAN RcPrintStartType( IN ULONG msg_id, IN DWORD start_type );
RcOpenHive( PWSTR szHiveName, PWSTR szHiveKey );
BOOLEAN RcCloseHive( PWSTR szHiveKey ); BOOLEAN RcOpenSystemHive(); BOOLEAN RcCloseSystemHive(); BOOLEAN RcDetermineCorrectControlKey( OUT DWORD * pCorrectKey );
ULONG RcCmdEnableService( IN PTOKENIZED_LINE TokenizedLine )
/*++
Routine Description:
Top-level routine supporting the enable command in the setup diagnostic command interpreter.
Arguments:
TokenizedLine - supplies structure built by the line parser describing each string on the line as typed by the user.
Return Value:
None.
--*/
{ DWORD correctKey = 0; DWORD new_start_type = 4; DWORD start_type = 0; HANDLE hkey = 0;
ASSERT(TokenizedLine->TokenCount >= 1);
// there should be three tokens,
// enable_service
// the name of the service/driver to be enabled
// the start_type of the service
if (RcCmdParseHelp( TokenizedLine, MSG_SERVICE_ENABLE_HELP )) { return 1; }
if(TokenizedLine->TokenCount == 2) { // just display the current setting
RcOpenSystemHive();
if( RcFindService( TokenizedLine->Tokens->Next->String, &hkey ) ) { RcMessageOut( MSG_SERVICE_FOUND, TokenizedLine->Tokens->Next->String ); if( RcGetStartType(hkey, &start_type ) ) { RcPrintStartType( MSG_SERVICE_CURRENT_STATE, start_type ); RcMessageOut( MSG_START_TYPE_NOT_SPECIFIED ); } } else { RcMessageOut( MSG_SERVICE_NOT_FOUND, TokenizedLine->Tokens->Next->String ); } NtClose( hkey );
RcCloseSystemHive();
} else if(TokenizedLine->TokenCount == 3) { // change the setting
RcOpenSystemHive();
if( RcFindService( TokenizedLine->Tokens->Next->String, &hkey ) ) { RcMessageOut( MSG_SERVICE_FOUND, TokenizedLine->Tokens->Next->String ); // we found it - open and retrieve the start type
if( RcGetStartType(hkey, &start_type ) ) {
if( !_wcsicmp( TokenizedLine->Tokens->Next->Next->String, L"SERVICE_BOOT_START" ) ) { new_start_type = 0; } else if( !_wcsicmp( TokenizedLine->Tokens->Next->Next->String, L"SERVICE_SYSTEM_START" ) ) { new_start_type = 1; } else if( !_wcsicmp( TokenizedLine->Tokens->Next->Next->String, L"SERVICE_AUTO_START" ) ) { new_start_type = 2; } else if( !_wcsicmp( TokenizedLine->Tokens->Next->Next->String, L"SERVICE_DEMAND_START" ) ) { new_start_type = 3; } else { new_start_type = -1; }
if( new_start_type == start_type ) { // the service is already in the state
RcPrintStartType( MSG_SERVICE_SAME_STATE, start_type ); } else if( new_start_type != -1 ) { // print the old start type
RcPrintStartType( MSG_SERVICE_CURRENT_STATE, start_type );
// setup the service
if( RcSetStartType( hkey, new_start_type ) ) { RcPrintStartType( MSG_SERVICE_CHANGE_STATE, new_start_type ); } } else { RcMessageOut( MSG_SERVICE_ENABLE_SYNTAX_ERROR ); } }
// close the key
NtClose( hkey );
} else { // we couldn't find the service - report an error
RcMessageOut( MSG_SERVICE_NOT_FOUND, TokenizedLine->Tokens->Next->String ); }
RcCloseSystemHive();
} else { // oops, we didn't get two or three parameters, print a help string.
pRcEnableMoreMode(); RcMessageOut( MSG_SERVICE_ENABLE_HELP ); pRcDisableMoreMode(); }
return 1; }
ULONG RcCmdDisableService( IN PTOKENIZED_LINE TokenizedLine )
/*++
Routine Description:
Top-level routine supporting the disable command in the setup diagnostic command interpreter.
Arguments:
TokenizedLine - supplies structure built by the line parser describing each string on the line as typed by the user.
Return Value:
None.
--*/
{ HANDLE hkey; DWORD start_type; WCHAR start_type_string[10]; PLINE_TOKEN Token; BOOL syntaxError = FALSE; BOOL doHelp = FALSE; LPCWSTR Arg;
if (RcCmdParseHelp( TokenizedLine, MSG_SERVICE_DISABLE_HELP )) { return 1; }
RtlZeroMemory( (VOID *)&start_type_string, sizeof( WCHAR ) * 10 );
// the command will print the old start_type of the
// service before it asks for verification to disable it.
if(TokenizedLine->TokenCount == 2) {
// find the service key
RcOpenSystemHive(); if( RcFindService( TokenizedLine->Tokens->Next->String, &hkey ) ) { RcMessageOut( MSG_SERVICE_FOUND, TokenizedLine->Tokens->Next->String ); // we found it - open and retrieve the start type
if( RcGetStartType(hkey, &start_type ) ) { if( start_type != SERVICE_DISABLED ) { // print the old start type
RcPrintStartType( MSG_SERVICE_CURRENT_STATE, start_type ); // disable the service
if( RcSetStartType( hkey, SERVICE_DISABLED ) ) { RcPrintStartType( MSG_SERVICE_CHANGE_STATE, SERVICE_DISABLED ); } } else { RcMessageOut( MSG_SERVICE_ALREADY_DISABLED, TokenizedLine->Tokens->Next->String ); } } // close the key
NtClose( hkey );
} else { // we couldn't find the service - report an error
RcMessageOut( MSG_SERVICE_NOT_FOUND, TokenizedLine->Tokens->Next->String ); } RcCloseSystemHive();
} else { // oops, we didn't get two parameters, print a help string.
pRcEnableMoreMode(); RcMessageOut( MSG_SERVICE_DISABLE_HELP ); pRcDisableMoreMode(); }
return 1; }
BOOLEAN RcFindService( IN LPCWSTR ServiceName, OUT PHANDLE KeyHandle )
/*++
Routine Description: Attempts to find and open the registry key for a particular service by its key name in
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.
If it fails, it will call RcFindServiceByDisplayName() to locate the service by the DisplayName string value.
Arguments:
ServiceName - the name of the service as a wstring.
KeyHandle - pointer to a HANDLE where the function should return the open registry handle.
this handle needs to be closed when the key is no longer needed.
Return Value:
TRUE indicates sucess. FALSE indicates that it couldn't find the service or failure.
--*/
{ NTSTATUS Status; WCHAR RegPath[ MAX_PATH ]; OBJECT_ATTRIBUTES Obja; DWORD correctKey;
UNICODE_STRING ServiceString; HANDLE ServiceKeyHandle;
// zero out the buffer
RtlZeroMemory( (VOID * )&RegPath, sizeof( WCHAR ) * MAX_PATH );
// find the correct controlset key
if( !RcDetermineCorrectControlKey( &correctKey ) ) { return FALSE; }
// prepend HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services to
// the supplied parameter
swprintf( RegPath, L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Services\\", correctKey ); wcscat( RegPath, ServiceName );
// build the unicode string
RtlInitUnicodeString( &ServiceString, RegPath ); InitializeObjectAttributes( &Obja,&ServiceString, OBJ_CASE_INSENSITIVE, NULL, NULL);
// attempt to open the key.
Status = ZwOpenKey( &ServiceKeyHandle, KEY_ALL_ACCESS, &Obja );
if( NT_SUCCESS( Status) ) { // if we suceeded, set and return
// the handle.
*KeyHandle = ServiceKeyHandle; } else {
// build the unicode string
swprintf( RegPath, L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Services", correctKey ); RtlInitUnicodeString( &ServiceString, RegPath ); InitializeObjectAttributes( &Obja,&ServiceString, OBJ_CASE_INSENSITIVE, NULL, NULL);
// open a handle to \\registry\\machine\\xSYSTEM\\ControlSet%03d\\Services
if( NT_SUCCESS( ZwOpenKey( &ServiceKeyHandle, KEY_ALL_ACCESS, &Obja ) ) ) { if( !RcFindServiceByDisplayName( ServiceKeyHandle, ServiceName, KeyHandle ) ) { // if we failed, NULL out KeyHandle, and return FALSE.
DEBUG_PRINTF(( "CMDCONS: failed to find key!\n" )); *KeyHandle = INVALID_HANDLE_VALUE; if( !NT_SUCCESS( NtClose( ServiceKeyHandle ) ) ) { DEBUG_PRINTF(( "CMDCONS: failed to close service key handle\n" )); } return FALSE; }
// we found the key!
// close the service key handle
if( !NT_SUCCESS( NtClose( ServiceKeyHandle ) ) ) { DEBUG_PRINTF(( "CMDCONS: failed to close service key handle\n" )); } } else { DEBUG_PRINTF(( "CMDCONS: failed to open service key handle\n" )); RcMessageOut( MSG_SYSTEM_MISSING_CURRENT_CONTROLS ); } }
// return true
return TRUE; }
// buffersizes
#define sizeof_buffer1 sizeof( KEY_FULL_INFORMATION ) + (MAX_PATH+1) * sizeof( WCHAR )
#define sizeof_buffer2 sizeof( KEY_BASIC_INFORMATION ) + (MAX_PATH+1) * sizeof( WCHAR )
#define sizeof_buffer3 sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + (MAX_PATH+1) * sizeof( WCHAR )
BOOLEAN RcFindServiceByDisplayName( IN HANDLE ServicesKey, IN LPCWSTR ServiceName, OUT PHANDLE KeyHandle )
/*++
Routine Description: Attempts to find and open the registry key for a particular service by the DisplayName string value.
Arguments:
SevicesKey - an open handle to the correct Services Key to search under
ServiceName - the name of the service as a wstring.
KeyHandle - pointer to a HANDLE where the function should return the open registry handle.
this handle needs to be closed when the key is no longer needed.
Return Value:
TRUE indicates sucess. FALSE indicates that it couldn't find the service or failure.
--*/ {
WCHAR ValueName[] = L"DisplayName";
BYTE buffer1[ sizeof_buffer1 ]; BYTE buffer2[ sizeof_buffer2 ]; BYTE buffer3[ sizeof_buffer3 ];
KEY_FULL_INFORMATION * pKeyFullInfo; KEY_BASIC_INFORMATION * pKeyBasicInfo; KEY_VALUE_PARTIAL_INFORMATION * pKeyValuePartialInfo; ULONG actualBytes; ULONG loopCount; ULONG keyCount; OBJECT_ATTRIBUTES Obja; HANDLE newHandle; UNICODE_STRING unicodeString; BOOL keyFound = FALSE;
// zero out the buffer
RtlZeroMemory( (VOID * ) &(buffer1[0]), sizeof_buffer1 );
pKeyFullInfo= (KEY_FULL_INFORMATION*) &( buffer1[0] ); pKeyBasicInfo = (KEY_BASIC_INFORMATION* ) &( buffer2[0] ); pKeyValuePartialInfo = (KEY_VALUE_PARTIAL_INFORMATION* ) &(buffer3[0]);
// do a ZwQueryKey() to find out the number of subkeys.
if( !NT_SUCCESS( ZwQueryKey( ServicesKey, KeyFullInformation, pKeyFullInfo, sizeof_buffer1, &actualBytes ) ) ) { *KeyHandle = INVALID_HANDLE_VALUE; DEBUG_PRINTF(( "FindServiceByDisplayName: failed to get number of keys!\n" )); return FALSE; }
keyCount = pKeyFullInfo->SubKeys;
// loop
for( loopCount = 0; loopCount < keyCount; loopCount++ ) { // zero out the buffer
RtlZeroMemory( (VOID * ) &(buffer2[0]), sizeof_buffer2 );
// zero out the buffer
RtlZeroMemory( (VOID * ) &(buffer3[0]), sizeof_buffer3 );
// do an ZwEnumerateKey() to find the name of the subkey
ZwEnumerateKey( ServicesKey, loopCount, KeyBasicInformation, pKeyBasicInfo, sizeof_buffer2, &actualBytes );
// setup the ZwOpenKey() with the name we just got back
RtlInitUnicodeString( &unicodeString, pKeyBasicInfo->Name ); InitializeObjectAttributes( &Obja, &unicodeString, OBJ_CASE_INSENSITIVE, ServicesKey, NULL);
// do a ZwOpenKey() to open the key
if( !NT_SUCCESS( ZwOpenKey( &newHandle, KEY_ALL_ACCESS, &Obja ) ) ) { DEBUG_PRINTF(( "FindServiceByDisplayName: failed to open the subkey?!\n" )); }
// do a ZwQueryKeyValue() to find the key value DisplayName if it exists
RtlInitUnicodeString( &unicodeString, ValueName );
if( !NT_SUCCESS( ZwQueryValueKey( newHandle, &unicodeString, KeyValuePartialInformation, pKeyValuePartialInfo, sizeof_buffer3, &actualBytes ) ) ) { DEBUG_PRINTF(( "FindServiceByDisplayName: display name get failed\n" )); } else { // if the ZwQueryKeyValue() succeeded
if( pKeyValuePartialInfo->Type != REG_SZ ) { DEBUG_PRINTF(( "FindServiceByDisplayName: paranoia!! mismatched key type?!\n" )); } else { // paranoia check SUCCEEDED
// if the value matches, break out of the loop
if( _wcsicmp( (WCHAR*)&(pKeyValuePartialInfo->Data[0]), ServiceName ) == 0 ) { keyFound = TRUE; break; } } }
// close the key
if( !NT_SUCCESS( ZwClose( newHandle ) ) ) { DEBUG_PRINTF(( "FindServiceByDisplayName: Failure closing the handle!!" )); } }
// return the handle to the opened key.
if( keyFound == TRUE ) { *KeyHandle = newHandle; return TRUE; }
*KeyHandle = INVALID_HANDLE_VALUE; return FALSE; }
BOOLEAN RcGetStartType( IN HANDLE hKey, OUT PULONG start_type )
/*++
Routine Description: Given an open service key, gets the start_type of the service.
Arguments:
hKey - a handle to the open service key
start_type - integer indicating the start type of the service
SERVICE_BOOT_START - 0x0 SERVICE_SYSTEM_START - 0x1 SERVICE_AUTO_START - 0x2 SERVUCE_DEMAMD_START - 0x3 SERVICE_DISABLED - 0x4
Return Value:
TRUE indicates sucess. FALSE indicates failure.
--*/
{ BYTE buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100 ]; // just grab a bunch of bytes
ULONG resultSize; KEY_VALUE_PARTIAL_INFORMATION * keyPartialInfo; UNICODE_STRING StartKey; WCHAR KEY_NAME[] = L"Start";
RtlZeroMemory( (VOID * )&(buffer[0]), sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100 );
keyPartialInfo = (KEY_VALUE_PARTIAL_INFORMATION*)&(buffer[0]);
ASSERT( keyPartialInfo );
RtlInitUnicodeString( &StartKey, KEY_NAME );
if( !NT_SUCCESS( ZwQueryValueKey( hKey, &StartKey, KeyValuePartialInformation, keyPartialInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &resultSize ) ) ) { DEBUG_PRINTF(( "CMDCONS: start type get failed\n" )); RcMessageOut( MSG_SERVICE_MISSING_START_KEY ); *start_type = -1; return FALSE; }
// paranoia check
if( keyPartialInfo->Type != REG_DWORD ) { RcMessageOut( MSG_SERVICE_MISSING_START_KEY ); DEBUG_PRINTF(( "CMDCONS: mismatched key type?!\n" )); *start_type = -1; return FALSE; }
*start_type = *( (DWORD*) &(keyPartialInfo->Data[0]) ); return TRUE; }
BOOLEAN RcSetStartType( IN HANDLE hKey, IN DWORD start_type )
/*++
Routine Description: Given an open service key, sets the start_type of the service.
Arguments:
hKey - a handle to the open service key
start_type - integer indicating the start type of the service
SERVICE_BOOT_START - 0x0 SERVICE_SYSTEM_START - 0x1 SERVICE_AUTO_START - 0x2 SERVUCE_DEMAMD_START - 0x3 SERVICE_DISABLED - 0x4
Return Value:
TRUE indicates sucess. FALSE indicates failure.
--*/
{ UNICODE_STRING StartKey;
RtlInitUnicodeString( &StartKey, L"Start" );
if( NT_SUCCESS( ZwSetValueKey( hKey, &StartKey, 0, REG_DWORD, &start_type, sizeof( DWORD ) ) ) ) { return TRUE; }
RcMessageOut( MSG_SERVICE_MISSING_START_KEY ); DEBUG_PRINTF(( "CMDCONS: start type get failed\n" )); return FALSE; }
BOOLEAN RcPrintStartType( ULONG msg_id, DWORD start_type )
/*++
Routine Description:
Prints the start_type.
Arguments:
start_type - integer indicating the start type of the service
SERVICE_BOOT_START - 0x0 SERVICE_SYSTEM_START - 0x1 SERVICE_AUTO_START - 0x2 SERVUCE_DEMAMD_START - 0x3 SERVICE_DISABLED - 0x4
Return Value:
TRUE - indicates sucess FALSE - indicates failure
--*/
{ switch( start_type ) { case 0: RcMessageOut( msg_id, L"SERVICE_BOOT_START" ); break; case 1: RcMessageOut( msg_id, L"SERVICE_SYSTEM_START" ); break; case 2: RcMessageOut( msg_id, L"SERVICE_AUTO_START" ); break; case 3: RcMessageOut( msg_id, L"SERVICE_DEMAND_START" ); break; case 4: RcMessageOut( msg_id, L"SERVICE_DISABLED" ); break; default: break; } return TRUE; }
BOOLEAN RcOpenSystemHive( VOID )
/*++
Routine Description:
Opens the SYSTEM hive of the selected NT install.
Arguments:
None.
Return Value:
TRUE - indicates sucess FALSE - indicates failure
--*/
{ PWSTR Hive = NULL; PWSTR HiveKey = NULL; PUCHAR buffer = NULL; PWSTR PartitionPath = NULL; NTSTATUS Status;
if (SelectedInstall == NULL) { return FALSE; }
//
// Allocate buffers.
//
Hive = SpMemAlloc(MAX_PATH * sizeof(WCHAR)); HiveKey = SpMemAlloc(MAX_PATH * sizeof(WCHAR)); buffer = SpMemAlloc(BUFFERSIZE);
//
// Load the SYSTEM hive
//
wcscpy(Hive,SelectedInstall->NtNameSelectedInstall); SpConcatenatePaths(Hive,SelectedInstall->Path); SpConcatenatePaths(Hive,L"system32\\config"); SpConcatenatePaths(Hive,L"system");
//
// Form the path of the key into which we will
// load the hive. We'll use the convention that
// a hive will be loaded into \registry\machine\x<hivename>.
//
wcscpy(HiveKey,L"\\registry\\machine\\xSYSTEM");
//
// Attempt to load the key.
//
Status = SpLoadUnloadKey(NULL,NULL,HiveKey,Hive); if(!NT_SUCCESS(Status)) { DEBUG_PRINTF(("CMDCONS: Unable to load hive %ws to key %ws (%lx)\n",Hive,HiveKey,Status));
SpMemFree( Hive ); SpMemFree( HiveKey ); SpMemFree( buffer );
return FALSE; }
SpMemFree( Hive ); SpMemFree( HiveKey ); SpMemFree( buffer );
return TRUE; }
BOOLEAN RcCloseSystemHive( VOID )
/*++
Routine Description:
Closes the SYSTEM hive of the selected NT install.
Arguments:
none.
Return Value:
TRUE - indicates sucess FALSE - indicates failure
--*/
{ PWSTR HiveKey = NULL; NTSTATUS TmpStatus;
//
// Allocate buffers.
//
HiveKey = SpMemAlloc(MAX_PATH * sizeof(WCHAR)); wcscpy(HiveKey,L"\\registry\\machine\\xSYSTEM");
//
// Unload the SYSTEM hive
//
TmpStatus = SpLoadUnloadKey(NULL,NULL,HiveKey,NULL); if(!NT_SUCCESS(TmpStatus)) { KdPrint(("CMDCONS: warning: unable to unload key %ws (%lx)\n",HiveKey,TmpStatus)); SpMemFree( HiveKey ); return FALSE; }
SpMemFree( HiveKey );
return TRUE; }
BOOLEAN RcDetermineCorrectControlKey( OUT PULONG pCorrectKey )
/*++
Routine Description:
Parses the select node and finds the correct ControlSetXXX to use.
Arguments:
pCorrectKey - pointer to a DWORD which will contain the number.
Return Value:
TRUE - indicates sucess FALSE - indicates failure
--*/
{ NTSTATUS Status; WCHAR RegPath[ MAX_PATH ]; OBJECT_ATTRIBUTES Obja;
UNICODE_STRING SelectString; HANDLE SelectKeyHandle;
BYTE buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100 ]; // just grab a bunch of bytes
ULONG resultSize = 0; KEY_VALUE_PARTIAL_INFORMATION * keyPartialInfo; UNICODE_STRING SelectValue; WCHAR VALUE_NAME[] = L"Current";
RtlZeroMemory( (VOID * )&(buffer[0]), sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100 );
keyPartialInfo = (KEY_VALUE_PARTIAL_INFORMATION*)&(buffer[0]);
ASSERT( keyPartialInfo );
*pCorrectKey = -1;
// prepend HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services to
// the supplied parameter
wcscpy( RegPath, L"\\registry\\machine\\xSYSTEM\\Select" );
// build the unicode string
RtlInitUnicodeString( &SelectString, RegPath ); InitializeObjectAttributes( &Obja,&SelectString, OBJ_CASE_INSENSITIVE, NULL, NULL);
// we need to determine the correct ControlSet to open
Status = ZwOpenKey( &SelectKeyHandle, KEY_ALL_ACCESS, &Obja );
if( NT_SUCCESS( Status ) ) { RtlInitUnicodeString( &SelectValue, VALUE_NAME );
Status = ZwQueryValueKey( SelectKeyHandle, &SelectValue, KeyValuePartialInformation, keyPartialInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &resultSize );
if( !NT_SUCCESS(Status) || Status == STATUS_OBJECT_NAME_NOT_FOUND ) { // couldn't find correct control value!
DEBUG_PRINTF(( "CMDCONS: failed to find correct control value!\n" )); } else { // we found a control value
// check if it's ok
if( keyPartialInfo->Type != REG_DWORD ) { // paranoia check failed
DEBUG_PRINTF(( "CMDCONS: paranoia check failed?!\n" )); DEBUG_PRINTF(( "CMDCONS: mismatched key type?!\n" )); DEBUG_PRINTF(( "CMDCONS: key type of %d?!\n", keyPartialInfo->Type )); DEBUG_PRINTF(( "CMDCONS: resultsize of %d?!\n", resultSize )); } else { // parnoia check sucess
*pCorrectKey = *( (DWORD*) &(keyPartialInfo->Data[0]) ); Status = NtClose( SelectKeyHandle ); if( !NT_SUCCESS ( Status ) ) { DEBUG_PRINTF(( "CMDCONS: failure closing handle?!\n" )); } return TRUE; } } }
// failed to find the Select node.
RcMessageOut( MSG_SYSTEM_MISSING_CURRENT_CONTROLS ); DEBUG_PRINTF(( "CMDCONS: failed to find select node!\n", *pCorrectKey ));
Status = NtClose( SelectKeyHandle ); if( !NT_SUCCESS ( Status ) ) { DEBUG_PRINTF(( "CMDCONS: failure closing handle?!\n" )); }
return FALSE; }
ULONG RcCmdListSvc( IN PTOKENIZED_LINE TokenizedLine ) { #define DISPLAY_BUFFER_SIZE 512
NTSTATUS Status; UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES Obja; HANDLE ServiceKeyHandle = NULL; ULONG ControlSetNumber; ULONG cb; ULONG KeyCount; ULONG i; HANDLE ValueHandle; ULONG StartType; PWSTR DisplayBuffer = NULL; PKEY_BASIC_INFORMATION bi; PKEY_VALUE_PARTIAL_INFORMATION pi; WCHAR ServiceName[64]; PWSTR DisplayName; static ULONG StartTypeIds[] = { MSG_SVCTYPE_BOOT, MSG_SVCTYPE_SYSTEM, MSG_SVCTYPE_AUTO, MSG_SVCTYPE_MANUAL, MSG_SVCTYPE_DISABLED }; static WCHAR *StartTypeStr[sizeof(StartTypeIds)/sizeof(ULONG)] = { 0 }; static WCHAR *DefaultSvcTypes[sizeof(StartTypeIds)/sizeof(ULONG)] = { L"Boot", L"System", L"Auto", L"Manual", L"Disabled" };
if (!StartTypeStr[0]) { //
// load all the service type strings
//
ULONG Index; for (Index = 0; Index < sizeof(StartTypeIds)/sizeof(ULONG); Index++) { StartTypeStr[Index] = SpRetreiveMessageText(ImageBase, StartTypeIds[Index], NULL, 0);
if (!StartTypeStr[Index]) StartTypeStr[Index] = DefaultSvcTypes[Index]; } }
if (RcCmdParseHelp( TokenizedLine, MSG_LISTSVC_HELP )) { return 1; }
if (!RcOpenSystemHive()) { return 1; }
pRcEnableMoreMode();
if (!RcDetermineCorrectControlKey( &ControlSetNumber ) ) { goto exit; }
DisplayBuffer = (PWSTR) SpMemAlloc( DISPLAY_BUFFER_SIZE ); if (DisplayBuffer == NULL) { goto exit; }
swprintf( _CmdConsBlock->TemporaryBuffer, L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Services\\", ControlSetNumber ); RtlInitUnicodeString( &UnicodeString, _CmdConsBlock->TemporaryBuffer ); InitializeObjectAttributes( &Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = ZwOpenKey( &ServiceKeyHandle, KEY_ALL_ACCESS, &Obja ); if (!NT_SUCCESS(Status)) { goto exit; }
Status = ZwQueryKey( ServiceKeyHandle, KeyFullInformation, _CmdConsBlock->TemporaryBuffer, _CmdConsBlock->TemporaryBufferSize, &cb ); if (!NT_SUCCESS(Status)) { goto exit; }
KeyCount = ((KEY_FULL_INFORMATION*)_CmdConsBlock->TemporaryBuffer)->SubKeys; bi = (PKEY_BASIC_INFORMATION)_CmdConsBlock->TemporaryBuffer; pi = (PKEY_VALUE_PARTIAL_INFORMATION)_CmdConsBlock->TemporaryBuffer;
for (i=0; i<KeyCount; i++) {
RtlZeroMemory( DisplayBuffer, DISPLAY_BUFFER_SIZE ); RtlZeroMemory( _CmdConsBlock->TemporaryBuffer, _CmdConsBlock->TemporaryBufferSize );
Status = ZwEnumerateKey( ServiceKeyHandle, i, KeyBasicInformation, _CmdConsBlock->TemporaryBuffer, _CmdConsBlock->TemporaryBufferSize, &cb ); if (!NT_SUCCESS(Status)) { goto exit; }
wcsncpy( ServiceName, bi->Name, (sizeof(ServiceName)/sizeof(WCHAR))-1 );
RtlInitUnicodeString( &UnicodeString, bi->Name ); InitializeObjectAttributes( &Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, ServiceKeyHandle, NULL );
Status = ZwOpenKey( &ValueHandle, KEY_ALL_ACCESS, &Obja ); if (!NT_SUCCESS(Status)) { goto exit; }
RtlInitUnicodeString( &UnicodeString, L"Start" );
Status = ZwQueryValueKey( ValueHandle, &UnicodeString, KeyValuePartialInformation, _CmdConsBlock->TemporaryBuffer, _CmdConsBlock->TemporaryBufferSize, &cb ); if (!NT_SUCCESS(Status)) { ZwClose( ValueHandle ); continue; }
if (pi->Type != REG_DWORD) { StartType = 5; } else { StartType = *(PULONG)&(pi->Data[0]); }
RtlInitUnicodeString( &UnicodeString, L"DisplayName" );
Status = ZwQueryValueKey( ValueHandle, &UnicodeString, KeyValuePartialInformation, _CmdConsBlock->TemporaryBuffer, _CmdConsBlock->TemporaryBufferSize, &cb ); if (NT_SUCCESS(Status)) { DisplayName = (PWSTR)&(pi->Data[0]); } else { DisplayName = NULL; }
ZwClose( ValueHandle );
if (StartType != 5) { swprintf( DisplayBuffer, L"%-15s %-8s %s\r\n", ServiceName, StartTypeStr[StartType], DisplayName == NULL ? L"" : DisplayName ); if (!RcTextOut( DisplayBuffer )){ goto exit; } } }
exit: if (ServiceKeyHandle) { ZwClose( ServiceKeyHandle ); } RcCloseSystemHive();
if (DisplayBuffer) { SpMemFree(DisplayBuffer); }
pRcDisableMoreMode();
return 1; }
#define VERIFIER_DRV_LEVEL L"VerifyDriverLevel"
#define VERIFIER_DRIVERS L"VerifyDrivers"
#define VERIFIER_IO_LEVEL L"IoVerifierLevel"
#define VERIFIER_QUERY_INFO L"Flags = %ld; IO Level = %ld\r\nDrivers = %ws\r\n"
#define MEMMGR_PATH L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Control\\Session Manager\\Memory Management"
#define IOSYS_PATH L"\\registry\\machine\\xSYSTEM\\ControlSet%03d\\Control\\Session Manager\\I/O System"
#define SYS_HIVE_NAME L"system"
#define SYS_HIVE_KEY L"\\registry\\machine\\xSYSTEM"
ULONG RcCmdVerifier( IN PTOKENIZED_LINE TokenizedLine ) { BOOLEAN ShowHelp = FALSE; WCHAR *Args[128] = {0}; ULONG Index; PLINE_TOKEN CurrToken = 0; WCHAR Drivers[256] = {0}; DWORD Flags = -1; DWORD IoLevel = -1; BOOLEAN DisplaySettings = FALSE; UNICODE_STRING UnicodeString; ULONG NumArgs = 0; BOOLEAN UseDefFlags = TRUE; BOOLEAN UseDefIoLevel = TRUE; BOOLEAN ResetSettings = FALSE; if (RcCmdParseHelp(TokenizedLine, MSG_VERIFIER_HELP)) { return 1; }
//
// parse the arguments
//
Index = 0; CurrToken = TokenizedLine->Tokens; do { Args[Index] = CurrToken->String; CurrToken = CurrToken->Next; Index++; } while ((Index < TokenizedLine->TokenCount) && (Index < sizeof(Args)/sizeof(PWCHAR)) && CurrToken);
NumArgs = min(TokenizedLine->TokenCount, Index);
if (TokenizedLine->TokenCount == 2) { //
// should be one of /all, /reset, /query
//
if (!_wcsicmp(Args[1], L"/all")) { wcscpy(Drivers, L"*"); Flags = 0; IoLevel = 1; } else if (!_wcsicmp(Args[1], L"/reset")) { Drivers[0] = 0; Flags = 0; IoLevel = 1; ResetSettings = TRUE; } else if (!_wcsicmp(Args[1], L"/query")) { DisplaySettings = TRUE; } else { ShowHelp = TRUE; } } else { ULONG NextArg = 1; if (!_wcsicmp(Args[NextArg], L"/flags")) { RtlInitUnicodeString(&UnicodeString, Args[NextArg + 1]); RtlUnicodeStringToInteger(&UnicodeString, 10, &Flags); NextArg += 2; UseDefFlags = FALSE; }
if (!_wcsicmp(Args[NextArg], L"/iolevel")) { RtlInitUnicodeString(&UnicodeString, Args[NextArg + 1]); RtlUnicodeStringToInteger(&UnicodeString, 10, &IoLevel); NextArg += 2; UseDefIoLevel = FALSE; }
if (!_wcsicmp(Args[NextArg], L"/driver")) { ULONG Len = 0; Drivers[0] = 0;
for (Index = NextArg + 1; Index < NumArgs; Index++) { wcscat(Drivers, Args[Index]); wcscat(Drivers, L" "); }
if (!Drivers[0]) ShowHelp = TRUE; // need a driver name
} else if (!_wcsicmp(Args[NextArg], L"/all")) { wcscpy(Drivers, L"*"); } else { ShowHelp = TRUE; } }
//
// Verify the arguments
//
if (!ShowHelp) { ShowHelp = !DisplaySettings && !ResetSettings && (Flags == -1) && (IoLevel == -1) && (!Drivers[0]); }
if (ShowHelp) { pRcEnableMoreMode(); RcMessageOut(MSG_VERIFIER_HELP); pRcDisableMoreMode(); } else { ULONG ControlSetNumber = 0; HANDLE MemMgrKeyHandle = NULL; HANDLE IOMgrKeyHandle = NULL; OBJECT_ATTRIBUTES ObjAttrs; BOOLEAN KeysOpened = FALSE; PVOID TemporaryBuffer = _CmdConsBlock->TemporaryBuffer; ULONG TemporaryBufferSize = _CmdConsBlock->TemporaryBufferSize; NTSTATUS Status; BOOLEAN SysHiveOpened;
//
// open the system hive & determine correct control set to use
//
SysHiveOpened = (BOOLEAN)RcOpenHive(SYS_HIVE_NAME, SYS_HIVE_KEY);
//
// get the control set which we are going to manipulate
//
if (SysHiveOpened && RcDetermineCorrectControlKey(&ControlSetNumber)) { //
// open "Memory Management" subkey under "SM"
//
swprintf((PWSTR)TemporaryBuffer, MEMMGR_PATH, ControlSetNumber);
RtlInitUnicodeString(&UnicodeString, (PWSTR)TemporaryBuffer); InitializeObjectAttributes(&ObjAttrs, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwOpenKey(&MemMgrKeyHandle, KEY_ALL_ACCESS, &ObjAttrs);
if (NT_SUCCESS(Status)) { //
// open "I/O System" subkey under "SM"
//
swprintf((PWSTR)TemporaryBuffer, IOSYS_PATH, ControlSetNumber); RtlInitUnicodeString(&UnicodeString, (PWSTR)TemporaryBuffer); InitializeObjectAttributes(&ObjAttrs, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwOpenKey(&IOMgrKeyHandle, KEY_ALL_ACCESS, &ObjAttrs);
if (!NT_SUCCESS(Status)) { ULONG Disposition = 0; //
// Create "I/O System" subkey under "SM", if it does not exist
//
Status = ZwCreateKey(&IOMgrKeyHandle, KEY_ALL_ACCESS, &ObjAttrs, 0, NULL, REG_OPTION_NON_VOLATILE, NULL); }
if (NT_SUCCESS(Status)) KeysOpened = TRUE; } }
if (KeysOpened) { ULONG ByteCount = 0; ULONG KeyCount = 0; PKEY_VALUE_FULL_INFORMATION ValueFullInfo; WCHAR ValueName[256]; ULONG Len; if (DisplaySettings) { //
// Query the Flags and Drivers
//
Flags = 0; Drivers[0] = 0; for(Index=0; ;Index++){ Status = ZwEnumerateValueKey( MemMgrKeyHandle, Index, KeyValueFullInformation, TemporaryBuffer, TemporaryBufferSize, &ByteCount ); if (!NT_SUCCESS(Status)) { if (Status == STATUS_NO_MORE_ENTRIES) Status = STATUS_SUCCESS;
break; }
ValueFullInfo = (PKEY_VALUE_FULL_INFORMATION)TemporaryBuffer; Len = ValueFullInfo->NameLength / sizeof(WCHAR); wcsncpy(ValueName, ValueFullInfo->Name, Len); ValueName[Len] = 0; if ((!_wcsicmp(ValueName, VERIFIER_DRV_LEVEL)) && (ValueFullInfo->Type == REG_DWORD)) { Flags = *(PDWORD)(((PUCHAR)ValueFullInfo) + ValueFullInfo->DataOffset); } else if ((!_wcsicmp(ValueName, VERIFIER_DRIVERS)) && (ValueFullInfo->Type == REG_SZ)) { Len = ValueFullInfo->DataLength / sizeof(WCHAR); wcsncpy(Drivers, (PWSTR)(((PUCHAR)ValueFullInfo) + ValueFullInfo->DataOffset), Len); Drivers[Len] = 0; } }
//
// Query the IO level
//
for(Index=0; ;Index++){ Status = ZwEnumerateValueKey( IOMgrKeyHandle, Index, KeyValueFullInformation, TemporaryBuffer, TemporaryBufferSize, &ByteCount ); if (!NT_SUCCESS(Status)) { if (Status == STATUS_NO_MORE_ENTRIES) Status = STATUS_SUCCESS;
break; }
ValueFullInfo = (PKEY_VALUE_FULL_INFORMATION)TemporaryBuffer; Len = ValueFullInfo->NameLength / sizeof(WCHAR); wcsncpy(ValueName, ValueFullInfo->Name, Len); ValueName[Len] = 0; if ((!_wcsicmp(ValueName, VERIFIER_IO_LEVEL)) && (ValueFullInfo->Type == REG_DWORD)) { IoLevel = *(PDWORD)(((PUCHAR)ValueFullInfo) + ValueFullInfo->DataOffset); } }
if (IoLevel == 3) IoLevel = 2; else IoLevel = 1; //
// format the output and display it
//
swprintf((PWSTR)TemporaryBuffer, VERIFIER_QUERY_INFO, Flags, IoLevel, Drivers);
RcTextOut((PWSTR)TemporaryBuffer); } else { //
// If IO verify bit is not set, then clear IoLevel
//
if (!(Flags & 0x10)) IoLevel = 0;
if (IoLevel == 2) IoLevel = 3; // actual value stored in the registry
if (IoLevel != 3) UseDefIoLevel = TRUE;
//
// set IO level
//
RtlInitUnicodeString(&UnicodeString, VERIFIER_IO_LEVEL); if (UseDefIoLevel) { Status = ZwDeleteValueKey(IOMgrKeyHandle, &UnicodeString); } else { Status = ZwSetValueKey(IOMgrKeyHandle, &UnicodeString, 0, REG_DWORD, &IoLevel, sizeof(DWORD)); }
//
// set the DRV verification level
//
RtlInitUnicodeString(&UnicodeString, VERIFIER_DRV_LEVEL);
if (UseDefFlags) { Status = ZwDeleteValueKey(MemMgrKeyHandle, &UnicodeString); } else { Status = ZwSetValueKey(MemMgrKeyHandle, &UnicodeString, 0, REG_DWORD, &Flags, sizeof(DWORD)); }
//
// set the drivers to be verified
//
RtlInitUnicodeString(&UnicodeString, VERIFIER_DRIVERS);
if (Drivers[0]) { Status = ZwSetValueKey(MemMgrKeyHandle, &UnicodeString, 0, REG_SZ, Drivers, (wcslen(Drivers) + 1) * sizeof(WCHAR)); } else { Status = ZwDeleteValueKey(MemMgrKeyHandle, &UnicodeString); } } }
if (MemMgrKeyHandle) ZwClose(MemMgrKeyHandle);
if (IOMgrKeyHandle) ZwClose(IOMgrKeyHandle);
if (SysHiveOpened) RcCloseHive(SYS_HIVE_KEY); } return 1; }
|