|
|
#include "spprecmp.h"
#pragma hdrstop
NTSTATUS SpDeleteServiceEntry( IN PWCHAR ServiceKey ) { NTSTATUS Status; HANDLE KeyHandle; UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES Obja;
RtlInitUnicodeString(&UnicodeString,ServiceKey); InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL); Status = ZwOpenKey(&KeyHandle,KEY_WRITE|DELETE,&Obja);
if(NT_SUCCESS(Status)) { Status = ZwDeleteKey(KeyHandle); if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: ZwDeleteKey of %ws returned %lx\n",ServiceKey,Status)); } } else { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: ZwOpenKey of %ws returned %lx\n",ServiceKey,Status)); }
return(Status); }
NTSTATUS SpCreateServiceEntry( IN PWCHAR ImagePath, IN OUT PWCHAR *ServiceKey )
/*++
Routine Description:
Create an services entry in the registry suitable for loading a given device driver file.
Arguments:
ImagePath - supplies the fully-qualified pathname of the device driver.
ServiceKey - If *ServiceKey is not NULL, then it specifies the registry path to the service node for this driver. If it is NULL, then it receives a pointer to a buffer containing the name of the service node created by this routine. The caller must free this buffer via SpMemFree when finished.
Return Value:
Status code indicating outcome.
--*/
{ WCHAR KeyName[128]; WCHAR FilePart[32]; OBJECT_ATTRIBUTES Obja; UNICODE_STRING UnicodeString; HANDLE KeyHandle; ULONG u; NTSTATUS Status; PWSTR p; BYTE DataBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)]; ULONG ResultLength; if (*ServiceKey) { wcscpy(KeyName, *ServiceKey); } else { //
// Isolate the name of the device driver file from its path.
//
if(p = wcsrchr(ImagePath,L'\\')) { p++; } else { p = ImagePath; } wcsncpy(FilePart,p,(sizeof(FilePart)/sizeof(FilePart[0]))-1); FilePart[(sizeof(FilePart)/sizeof(FilePart[0]))-1] = 0; if(p=wcsrchr(FilePart,L'.')) { *p = 0; }
//
// Form a unique key name in
// HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services.
//
swprintf( KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%ws", FilePart ); }
//
// Attempt to create the key for the service.
//
RtlInitUnicodeString(&UnicodeString,KeyName); InitializeObjectAttributes(&Obja,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
Status = ZwCreateKey( &KeyHandle, KEY_READ | KEY_WRITE, &Obja, 0, NULL, REG_OPTION_NON_VOLATILE, NULL );
if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: SpCreateServiceEntry: ZwCreateKey %ws returns %lx\n",KeyName,Status)); return(Status); }
//
// Set the ImagePath value in the service key.
//
RtlInitUnicodeString(&UnicodeString,L"ImagePath"); Status = ZwSetValueKey( KeyHandle, &UnicodeString, 0, REG_SZ, ImagePath, (wcslen(ImagePath) + 1) * sizeof(WCHAR) );
if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set ImagePath value in key %ws (%lx)\n",KeyName,Status)); goto cs1; }
//
// Set the Type value in the service key. If the type is preset in the registry to SERVICE_FILE_SYSTEM_DRIVER
// leave it alone. Otherwise set it to SERVICE_KERNEL_DRIVER.
//
RtlInitUnicodeString(&UnicodeString, REGSTR_VALUE_TYPE); ResultLength = 0; Status = ZwQueryValueKey(KeyHandle, &UnicodeString, KeyValuePartialInformation, (PKEY_VALUE_PARTIAL_INFORMATION)DataBuffer, sizeof(DataBuffer), &ResultLength);
if( NT_SUCCESS(Status) && ResultLength && ( (INT) ( (PKEY_VALUE_PARTIAL_INFORMATION) DataBuffer)->Type == REG_DWORD ) && ( (INT) *(( (PKEY_VALUE_PARTIAL_INFORMATION) DataBuffer)->Data) == SERVICE_FILE_SYSTEM_DRIVER ) ) { u = SERVICE_FILE_SYSTEM_DRIVER; } else { //
// If the type is not preset in the registry to SERVICE_FILE_SYSTEM_DRIVER set it to SERVICE_KERNEL_DRIVER by default.
//
u = SERVICE_KERNEL_DRIVER; } Status = ZwSetValueKey( KeyHandle, &UnicodeString, 0, REG_DWORD, &u, sizeof(ULONG) );
if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set Type value in key %ws (%lx)\n",KeyName,Status)); goto cs1; }
//
// Set the Start value in the service key.
//
u = SERVICE_DEMAND_START; RtlInitUnicodeString(&UnicodeString,L"Start"); Status = ZwSetValueKey( KeyHandle, &UnicodeString, 0, REG_DWORD, &u, sizeof(ULONG) );
if(!NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to set Start value in key %ws (%lx)\n",KeyName,Status)); goto cs1; }
cs1:
//
// If we were not entirely successful creating the service,
// we'll want to clean it out here. Otherwise duplicate the KeyName
// string to return to the caller, if it was not passed in.
//
if(NT_SUCCESS(Status)) {
if (*ServiceKey == NULL) { if((*ServiceKey = SpDupStringW(KeyName)) == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; } } }
if(!NT_SUCCESS(Status)) {
NTSTATUS s;
//
// Remove the key we just created.
//
s = ZwDeleteKey(KeyHandle); if(!NT_SUCCESS(s)) { KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: warning: ZwDeleteKey of %ws returned %lx\n",KeyName,s)); } }
NtClose(KeyHandle);
return(Status); }
NTSTATUS SpLoadDeviceDriver( IN PWSTR Description, IN PWSTR PathPart1, IN PWSTR PathPart2, OPTIONAL IN PWSTR PathPart3 OPTIONAL )
/*++
Routine Description:
Load a device driver by creating a services entry for the driver and then calling the I/O subsystem.
Arguments:
Description - supplies a human-readable description of the driver or hardware that the driver targets.
PathPart1 - supplies first part of full pathname to driver file.
PathPart2 - if specified, supplies the second part of the full pathname; PathPart2 will be concatenated to PathPart1. If not specified, then PathPart1 is the full path.
PathPart3 - if specified, supplies a third part of the full pathname; PathPart3 will be concatenated to PathPart1 and PathPart2.
Return Value:
Status code indicating outcome.
--*/
{ PWCHAR FullName; NTSTATUS Status; PWCHAR ServiceKey; UNICODE_STRING ServiceKeyU; PWSTR pwstr;
SpDisplayStatusText( SP_STAT_LOADING_DRIVER, DEFAULT_STATUS_ATTRIBUTE, Description );
pwstr = TemporaryBuffer;
//
// Form the full name of the device driver file.
//
wcscpy(pwstr,PathPart1); if(PathPart2) { SpConcatenatePaths(pwstr,PathPart2); } if(PathPart3) { SpConcatenatePaths(pwstr,PathPart3); }
FullName = SpDupStringW(pwstr);
//
// Create a service entry for the driver.
//
ServiceKey = NULL; Status = SpCreateServiceEntry(FullName,&ServiceKey); if(NT_SUCCESS(Status)) {
RtlInitUnicodeString(&ServiceKeyU,ServiceKey);
//
// Attempt to load the driver.
//
Status = ZwLoadDriver(&ServiceKeyU); if(!NT_SUCCESS(Status)) {
KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: ZwLoadDriver %ws returned %lx\n",FullName,Status));
//
// Remove the service entry we created in the registry.
//
SpDeleteServiceEntry(ServiceKey); }
SpMemFree(ServiceKey); }
SpMemFree(FullName);
return(Status); }
|