X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fntoskrnl%2Fio%2Fdriver.c;h=a95a142ae1533d7f9d45afda33e073ea6a17daae;hp=0b88897b97bd91aa5a5ae0e89b5cc00b7fc4bfc3;hb=3354ce28a8597585980ee88084f5c06ae59df604;hpb=c73475996489f0c938a266454b6b24247976869d diff --git a/reactos/ntoskrnl/io/driver.c b/reactos/ntoskrnl/io/driver.c index 0b88897b97b..a95a142ae15 100644 --- a/reactos/ntoskrnl/io/driver.c +++ b/reactos/ntoskrnl/io/driver.c @@ -1,37 +1,24 @@ -/* $Id: driver.c,v 1.40 2004/03/28 09:48:13 navaraf Exp $ +/* $Id$ * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/io/driver.c - * PURPOSE: Loading and unloading of drivers - * PROGRAMMER: David Welch (welch@cwcom.net) - * Filip Navara (xnavara@volny.cz) - * UPDATE HISTORY: - * 15/05/98: Created + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/io/driver.c + * PURPOSE: Loading and unloading of drivers + * + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Filip Navara (xnavara@volny.cz) */ /* INCLUDES *******************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - +#include #define NDEBUG #include /* ke/main.c */ extern LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock; +extern ULONG KeTickCount; +extern BOOLEAN SetupMode; NTSTATUS LdrProcessModule(PVOID ModuleLoadBase, @@ -43,6 +30,8 @@ typedef struct _SERVICE_GROUP LIST_ENTRY GroupListEntry; UNICODE_STRING GroupName; BOOLEAN ServicesRunning; + ULONG TagCount; + PULONG TagArray; } SERVICE_GROUP, *PSERVICE_GROUP; typedef struct _SERVICE @@ -72,62 +61,55 @@ typedef struct _DRIVER_REINIT_ITEM /* GLOBALS ********************************************************************/ static LIST_ENTRY DriverReinitListHead; -static PLIST_ENTRY DriverReinitTailEntry; static KSPIN_LOCK DriverReinitListLock; +static PLIST_ENTRY DriverReinitTailEntry; + +static PLIST_ENTRY DriverBootReinitTailEntry; +static LIST_ENTRY DriverBootReinitListHead; +static KSPIN_LOCK DriverBootReinitListLock; static LIST_ENTRY GroupListHead = {NULL, NULL}; static LIST_ENTRY ServiceListHead = {NULL, NULL}; -POBJECT_TYPE EXPORTED IoDriverObjectType = NULL; +static UNICODE_STRING IopHardwareDatabaseKey = + ROS_STRING_INITIALIZER(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM"); -#define TAG_DRIVER TAG('D', 'R', 'V', 'R') -#define TAG_DRIVER_EXTENSION TAG('D', 'R', 'V', 'E') - -#define DRIVER_REGISTRY_KEY_BASENAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" +POBJECT_TYPE EXPORTED IoDriverObjectType = NULL; /* DECLARATIONS ***************************************************************/ -NTSTATUS STDCALL -IopCreateDriver( - PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes); - VOID STDCALL IopDeleteDriver(PVOID ObjectBody); /* PRIVATE FUNCTIONS **********************************************************/ -VOID INIT_FUNCTION +VOID +INIT_FUNCTION IopInitDriverImplementation(VOID) { - /* Register the process object type */ - IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE)); - IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'R'); - IoDriverObjectType->TotalObjects = 0; - IoDriverObjectType->TotalHandles = 0; - IoDriverObjectType->MaxObjects = ULONG_MAX; - IoDriverObjectType->MaxHandles = ULONG_MAX; - IoDriverObjectType->PagedPoolCharge = 0; - IoDriverObjectType->NonpagedPoolCharge = sizeof(DRIVER_OBJECT); - IoDriverObjectType->Dump = NULL; - IoDriverObjectType->Open = NULL; - IoDriverObjectType->Close = NULL; - IoDriverObjectType->Delete = IopDeleteDriver; - IoDriverObjectType->Parse = NULL; - IoDriverObjectType->Security = NULL; - IoDriverObjectType->QueryName = NULL; - IoDriverObjectType->OkayToClose = NULL; - IoDriverObjectType->Create = IopCreateDriver; - IoDriverObjectType->DuplicationNotify = NULL; - RtlRosInitUnicodeStringFromLiteral(&IoDriverObjectType->TypeName, L"Driver"); - - ObpCreateTypeObject(IoDriverObjectType); + OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; + UNICODE_STRING Name; + + DPRINT1("Creating Registry Object Type\n"); + + /* Initialize the Driver object type */ + RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); + RtlInitUnicodeString(&Name, L"Driver"); + ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); + ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DRIVER_OBJECT); + ObjectTypeInitializer.PoolType = NonPagedPool; + ObjectTypeInitializer.UseDefaultObject = TRUE; + ObjectTypeInitializer.DeleteProcedure = IopDeleteDriver; + + ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &IoDriverObjectType); InitializeListHead(&DriverReinitListHead); KeInitializeSpinLock(&DriverReinitListLock); DriverReinitTailEntry = NULL; + + InitializeListHead(&DriverBootReinitListHead); + KeInitializeSpinLock(&DriverBootReinitListLock); + DriverBootReinitTailEntry = NULL; } NTSTATUS STDCALL @@ -135,48 +117,10 @@ IopInvalidDeviceRequest( PDEVICE_OBJECT DeviceObject, PIRP Irp) { - Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS STDCALL -IopCreateDriver( - PVOID ObjectBody, - PVOID Parent, - PWSTR RemainingPath, - POBJECT_ATTRIBUTES ObjectAttributes) -{ - PDRIVER_OBJECT Object = ObjectBody; - ULONG i; - - DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n", - ObjectBody, Parent, RemainingPath); - - if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL) - return STATUS_UNSUCCESSFUL; - - /* Create driver extension */ - Object->DriverExtension = (PDRIVER_EXTENSION) - ExAllocatePoolWithTag( - NonPagedPool, - sizeof(DRIVER_EXTENSION), - TAG_DRIVER_EXTENSION); - - if (Object->DriverExtension == NULL) - { - return STATUS_NO_MEMORY; - } - - RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION)); - - Object->Type = InternalDriverType; - - for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) - Object->MajorFunction[i] = IopInvalidDeviceRequest; - - return STATUS_SUCCESS; + return STATUS_INVALID_DEVICE_REQUEST; } VOID STDCALL @@ -189,6 +133,7 @@ IopDeleteDriver(PVOID ObjectBody) DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody); ExFreePool(Object->DriverExtension); + ExFreePool(Object->DriverName.Buffer); OldIrql = KeRaiseIrqlToDpcLevel(); @@ -197,16 +142,75 @@ IopDeleteDriver(PVOID ObjectBody) DriverExtension = NextDriverExtension) { NextDriverExtension = DriverExtension->Link; - ExFreePool(DriverExtension); + ExFreePoolWithTag(DriverExtension, TAG_DRIVER_EXTENSION); } KfLowerIrql(OldIrql); } +NTSTATUS FASTCALL +IopGetDriverObject( + PDRIVER_OBJECT *DriverObject, + PUNICODE_STRING ServiceName, + BOOLEAN FileSystem) +{ + PDRIVER_OBJECT Object; + WCHAR NameBuffer[MAX_PATH]; + UNICODE_STRING DriverName; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + + DPRINT("IopOpenDriverObject(%p '%wZ' %x)\n", + DriverObject, ServiceName, FileSystem); + + *DriverObject = NULL; + + /* Create ModuleName string */ + if (ServiceName == NULL || ServiceName->Buffer == NULL) + /* We don't know which DriverObject we have to open */ + return STATUS_INVALID_PARAMETER_2; + + if (FileSystem == TRUE) + wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME); + else + wcscpy(NameBuffer, DRIVER_ROOT_NAME); + wcscat(NameBuffer, ServiceName->Buffer); + + RtlInitUnicodeString(&DriverName, NameBuffer); + DPRINT("Driver name: '%wZ'\n", &DriverName); + + /* Initialize ObjectAttributes for driver object */ + InitializeObjectAttributes( + &ObjectAttributes, + &DriverName, + OBJ_OPENIF | OBJ_KERNEL_HANDLE, + NULL, + NULL); + + /* Open driver object */ + Status = ObReferenceObjectByName( + &DriverName, + 0, /* Attributes */ + NULL, /* PassedAccessState */ + 0, /* DesiredAccess */ + IoDriverObjectType, + KernelMode, + NULL, /* ParseContext */ + (PVOID*)&Object); + + if (!NT_SUCCESS(Status)) + return Status; + + *DriverObject = Object; + + return STATUS_SUCCESS; +} + NTSTATUS FASTCALL IopCreateDriverObject( PDRIVER_OBJECT *DriverObject, PUNICODE_STRING ServiceName, + ULONG CreateAttributes, BOOLEAN FileSystem, PVOID DriverImageStart, ULONG DriverImageSize) @@ -216,6 +220,8 @@ IopCreateDriverObject( UNICODE_STRING DriverName; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; + ULONG i; + PWSTR Buffer = NULL; DPRINT("IopCreateDriverObject(%p '%wZ' %x %p %x)\n", DriverObject, ServiceName, FileSystem, DriverImageStart, DriverImageSize); @@ -233,6 +239,10 @@ IopCreateDriverObject( RtlInitUnicodeString(&DriverName, NameBuffer); DPRINT("Driver name: '%wZ'\n", &DriverName); + + Buffer = (PWSTR)ExAllocatePool(NonPagedPool, DriverName.Length); + /* If we don't success, it is not a problem. Our driver + * object will not have associated driver name... */ } else { @@ -243,7 +253,7 @@ IopCreateDriverObject( InitializeObjectAttributes( &ObjectAttributes, &DriverName, - OBJ_PERMANENT, + CreateAttributes | OBJ_PERMANENT, NULL, NULL); @@ -264,8 +274,51 @@ IopCreateDriverObject( return Status; } + Status = ObInsertObject(Object, + NULL, + FILE_ALL_ACCESS, + 0, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Create driver extension */ + Object->DriverExtension = (PDRIVER_EXTENSION) + ExAllocatePoolWithTag( + NonPagedPool, + sizeof(DRIVER_EXTENSION), + TAG_DRIVER_EXTENSION); + + if (Object->DriverExtension == NULL) + { + return STATUS_NO_MEMORY; + } + + RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION)); + + Object->Type = IO_TYPE_DRIVER; + + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + Object->MajorFunction[i] = IopInvalidDeviceRequest; + + Object->HardwareDatabase = &IopHardwareDatabaseKey; + Object->DriverStart = DriverImageStart; Object->DriverSize = DriverImageSize; + if (Buffer) + { + if (!Object->DriverName.Buffer) + { + Object->DriverName.Buffer = Buffer; + Object->DriverName.Length = Object->DriverName.MaximumLength = DriverName.Length; + RtlCopyMemory(Object->DriverName.Buffer, DriverName.Buffer, DriverName.Length); + } + else + ExFreePool(Buffer); + } *DriverObject = Object; @@ -278,12 +331,23 @@ IopCreateDriverObject( * Display 'Loading XXX...' message. */ -VOID FASTCALL -IopDisplayLoadingMessage(PWCHAR ServiceName) +VOID +FASTCALL +INIT_FUNCTION +IopDisplayLoadingMessage(PVOID ServiceName, + BOOLEAN Unicode) { - CHAR TextBuffer[256]; - sprintf(TextBuffer, "Loading %S...\n", ServiceName); - HalDisplayString(TextBuffer); + if (SetupMode) return; + CHAR TextBuffer[256]; + if (Unicode) + { + sprintf(TextBuffer, "Loading %S...\n", (PWCHAR)ServiceName); + } + else + { + sprintf(TextBuffer, "Loading %s...\n", (PCHAR)ServiceName); + } + HalDisplayString(TextBuffer); } /* @@ -341,7 +405,7 @@ IopNormalizeImagePath( wcscpy(ImagePath->Buffer, L"\\SystemRoot\\"); wcscat(ImagePath->Buffer, InputImagePath.Buffer); - RtlFreeUnicodeString(&InputImagePath); + ExFreePool(InputImagePath.Buffer); } return STATUS_SUCCESS; @@ -370,6 +434,8 @@ IopLoadServiceModule( UNICODE_STRING ServiceImagePath; NTSTATUS Status; + DPRINT("IopLoadServiceModule(%wZ, %x)\n", ServiceName, ModuleObject); + /* * Get information about the service. */ @@ -394,8 +460,8 @@ IopLoadServiceModule( DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status); return Status; } - - IopDisplayLoadingMessage(ServiceName->Buffer); + + IopDisplayLoadingMessage(ServiceName->Buffer, TRUE); /* * Normalize the image path for all later processing. @@ -417,6 +483,8 @@ IopLoadServiceModule( if (*ModuleObject == NULL) { + Status = STATUS_UNSUCCESSFUL; + /* * Special case for boot modules that were loaded by boot loader. */ @@ -429,8 +497,6 @@ IopLoadServiceModule( PLOADER_MODULE KeLoaderModules = (PLOADER_MODULE)KeLoaderBlock.ModsAddr; - Status = STATUS_UNSUCCESSFUL; - /* * FIXME: * Improve this searching algorithm by using the image name @@ -442,8 +508,10 @@ IopLoadServiceModule( for (i = 1; i < KeLoaderBlock.ModsCount; i++) { ModuleName = (PCHAR)KeLoaderModules[i].String; - if (!strcmp(ModuleName, SearchName)) + if (!_stricmp(ModuleName, SearchName)) { + DPRINT("Initializing boot module\n"); + /* Tell, that the module is already loaded */ KeLoaderModules[i].Reserved = 1; @@ -452,6 +520,8 @@ IopLoadServiceModule( &ServiceImagePath, ModuleObject); + KDB_SYMBOLFILE_HOOK(SearchName); + break; } } @@ -470,10 +540,10 @@ IopLoadServiceModule( else { DPRINT("Module already loaded\n"); - Status = STATUS_SUCCESS; + Status = STATUS_IMAGE_ALREADY_LOADED; } - RtlFreeUnicodeString(&ServiceImagePath); + ExFreePool(ServiceImagePath.Buffer); /* * Now check if the module was loaded successfully. @@ -502,6 +572,9 @@ IopLoadServiceModule( * Module object representing the driver. It can be retrieve by * IopLoadServiceModule. * + * ServiceName + * Name of the service (as in registry). + * * FileSystemDriver * Set to TRUE for file system drivers. * @@ -514,16 +587,38 @@ NTSTATUS FASTCALL IopInitializeDriverModule( IN PDEVICE_NODE DeviceNode, IN PMODULE_OBJECT ModuleObject, + IN PUNICODE_STRING ServiceName, IN BOOLEAN FileSystemDriver, OUT PDRIVER_OBJECT *DriverObject) { + const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"; UNICODE_STRING RegistryKey; - PDRIVER_INITIALIZE DriverEntry = ModuleObject->EntryPoint; + PDRIVER_INITIALIZE DriverEntry; NTSTATUS Status; + DriverEntry = ModuleObject->EntryPoint; + + if (ServiceName != NULL && ServiceName->Length != 0) + { + RegistryKey.Length = 0; + RegistryKey.MaximumLength = sizeof(ServicesKeyName) + ServiceName->Length; + RegistryKey.Buffer = ExAllocatePool(PagedPool, RegistryKey.MaximumLength); + if (RegistryKey.Buffer == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + RtlAppendUnicodeToString(&RegistryKey, ServicesKeyName); + RtlAppendUnicodeStringToString(&RegistryKey, ServiceName); + } + else + { + RtlInitUnicodeString(&RegistryKey, NULL); + } + Status = IopCreateDriverObject( DriverObject, - &DeviceNode->ServiceName, + ServiceName, + 0, FileSystemDriver, ModuleObject->Base, ModuleObject->Length); @@ -534,31 +629,19 @@ IopInitializeDriverModule( return Status; } - if (DeviceNode->ServiceName.Buffer) - { - RegistryKey.Length = DeviceNode->ServiceName.Length + - sizeof(DRIVER_REGISTRY_KEY_BASENAME); - RegistryKey.MaximumLength = RegistryKey.Length + sizeof(UNICODE_NULL); - RegistryKey.Buffer = ExAllocatePool(PagedPool, RegistryKey.MaximumLength); - wcscpy(RegistryKey.Buffer, DRIVER_REGISTRY_KEY_BASENAME); - wcscat(RegistryKey.Buffer, DeviceNode->ServiceName.Buffer); - } - else - { - RtlInitUnicodeString(&RegistryKey, NULL); - } - DPRINT("RegistryKey: %wZ\n", &RegistryKey); DPRINT("Calling driver entrypoint at %08lx\n", DriverEntry); IopMarkLastReinitializeDriver(); Status = DriverEntry(*DriverObject, &RegistryKey); + + RtlFreeUnicodeString(&RegistryKey); + if (!NT_SUCCESS(Status)) { - ExFreePool((*DriverObject)->DriverExtension); - ObMakeTemporaryObject(DriverObject); - ObDereferenceObject(DriverObject); + ObMakeTemporaryObject(*DriverObject); + ObDereferenceObject(*DriverObject); return Status; } @@ -588,7 +671,7 @@ IopAttachFilterDriversCallback( PMODULE_OBJECT ModuleObject; PDRIVER_OBJECT DriverObject; NTSTATUS Status; - + for (Filters = ValueData; ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength && *Filters != 0; @@ -596,17 +679,31 @@ IopAttachFilterDriversCallback( { DPRINT("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath); ServiceName.Buffer = Filters; - ServiceName.MaximumLength = + ServiceName.MaximumLength = ServiceName.Length = wcslen(Filters) * sizeof(WCHAR); /* Load and initialize the filter driver */ Status = IopLoadServiceModule(&ServiceName, &ModuleObject); - if (!NT_SUCCESS(Status)) - continue; + if (Status != STATUS_IMAGE_ALREADY_LOADED) + { + if (!NT_SUCCESS(Status)) + continue; - Status = IopInitializeDriverModule(DeviceNode, ModuleObject, FALSE, &DriverObject); - if (!NT_SUCCESS(Status)) - continue; + Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName, + FALSE, &DriverObject); + if (!NT_SUCCESS(Status)) + continue; + } + else + { + /* get existing DriverObject pointer */ + Status = IopGetDriverObject( + &DriverObject, + &ServiceName, + FALSE); + if (!NT_SUCCESS(Status)) + continue; + } Status = IopInitializeDevice(DeviceNode, DriverObject); if (!NT_SUCCESS(Status)) @@ -641,7 +738,7 @@ IopAttachFilterDrivers( /* * First load the device filters */ - + QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback; if (Lower) QueryTable[0].Name = L"LowerFilters"; @@ -653,10 +750,10 @@ IopAttachFilterDrivers( QueryTable[1].Name = NULL; KeyBuffer = ExAllocatePool( - PagedPool, + PagedPool, (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length); wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); - wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer); + wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer); RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, @@ -713,10 +810,52 @@ IopAttachFilterDrivers( ExFreePool(KeyBuffer); } - + return STATUS_SUCCESS; } +static NTSTATUS STDCALL +IopGetGroupOrderList(PWSTR ValueName, + ULONG ValueType, + PVOID ValueData, + ULONG ValueLength, + PVOID Context, + PVOID EntryContext) +{ + PSERVICE_GROUP Group; + + DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n", + ValueName, ValueType, ValueData, ValueLength, Context, EntryContext); + + if (ValueType == REG_BINARY && + ValueData != NULL && + ValueLength >= sizeof(DWORD) && + ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD)) + { + Group = (PSERVICE_GROUP)Context; + Group->TagCount = ((PULONG)ValueData)[0]; + if (Group->TagCount > 0) + { + if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD)) + { + Group->TagArray = ExAllocatePool(NonPagedPool, Group->TagCount * sizeof(DWORD)); + if (Group->TagArray == NULL) + { + Group->TagCount = 0; + return STATUS_INSUFFICIENT_RESOURCES; + } + memcpy(Group->TagArray, (PULONG)ValueData + 1, Group->TagCount * sizeof(DWORD)); + } + else + { + Group->TagCount = 0; + return STATUS_UNSUCCESSFUL; + } + } + } + return STATUS_SUCCESS; +} + static NTSTATUS STDCALL IopCreateGroupListEntry(PWSTR ValueName, ULONG ValueType, @@ -726,6 +865,9 @@ IopCreateGroupListEntry(PWSTR ValueName, PVOID EntryContext) { PSERVICE_GROUP Group; + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + if (ValueType == REG_SZ) { @@ -740,13 +882,22 @@ IopCreateGroupListEntry(PWSTR ValueName, RtlZeroMemory(Group, sizeof(SERVICE_GROUP)); - if (!RtlCreateUnicodeString(&Group->GroupName, - (PWSTR)ValueData)) + if (!RtlpCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData, NonPagedPool)) { ExFreePool(Group); return(STATUS_INSUFFICIENT_RESOURCES); } + RtlZeroMemory(&QueryTable, sizeof(QueryTable)); + QueryTable[0].Name = (PWSTR)ValueData; + QueryTable[0].QueryRoutine = IopGetGroupOrderList; + + Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + L"GroupOrderList", + QueryTable, + (PVOID)Group, + NULL); + DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData); InsertTailList(&GroupListHead, &Group->GroupListEntry); @@ -759,7 +910,7 @@ IopCreateGroupListEntry(PWSTR ValueName, static NTSTATUS STDCALL IopCreateServiceListEntry(PUNICODE_STRING ServiceName) { - RTL_QUERY_REGISTRY_TABLE QueryTable[6]; + RTL_QUERY_REGISTRY_TABLE QueryTable[7]; PSERVICE Service; NTSTATUS Status; @@ -798,6 +949,10 @@ IopCreateServiceListEntry(PUNICODE_STRING ServiceName) QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[4].EntryContext = &Service->ImagePath; + QueryTable[5].Name = L"Tag"; + QueryTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT; + QueryTable[5].EntryContext = &Service->Tag; + Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, ServiceName->Buffer, QueryTable, @@ -805,8 +960,20 @@ IopCreateServiceListEntry(PUNICODE_STRING ServiceName) NULL); if (!NT_SUCCESS(Status) || Service->Start > 1) { - RtlFreeUnicodeString(&Service->ServiceGroup); - RtlFreeUnicodeString(&Service->ImagePath); + /* + * If something goes wrong during RtlQueryRegistryValues + * it'll just drop everything on the floor and return, + * so you have to check if the buffers were filled. + * Luckily we zerofilled the Service. + */ + if (Service->ServiceGroup.Buffer) + { + ExFreePool(Service->ServiceGroup.Buffer); + } + if (Service->ImagePath.Buffer) + { + ExFreePool(Service->ImagePath.Buffer); + } ExFreePool(Service); return(Status); } @@ -835,8 +1002,8 @@ IopCreateServiceListEntry(PUNICODE_STRING ServiceName) DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath); DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup); DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath); - DPRINT("Start %lx Type %lx ErrorControl %lx\n", - Service->Start, Service->Type, Service->ErrorControl); + DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n", + Service->Start, Service->Type, Service->Tag, Service->ErrorControl); /* Append service entry */ InsertTailList(&ServiceListHead, @@ -892,8 +1059,8 @@ IoCreateDriverList(VOID) NULL, NULL); - Status = NtOpenKey(&KeyHandle, - 0x10001, + Status = ZwOpenKey(&KeyHandle, + KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { @@ -904,14 +1071,14 @@ IoCreateDriverList(VOID) KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength); if (KeyInfo == NULL) { - NtClose(KeyHandle); + ZwClose(KeyHandle); return(STATUS_INSUFFICIENT_RESOURCES); } Index = 0; while (TRUE) { - Status = NtEnumerateKey(KeyHandle, + Status = ZwEnumerateKey(KeyHandle, Index, KeyBasicInformation, KeyInfo, @@ -939,7 +1106,7 @@ IoCreateDriverList(VOID) } ExFreePool(KeyInfo); - NtClose(KeyHandle); + ZwClose(KeyHandle); DPRINT("IoCreateDriverList() done\n"); @@ -962,8 +1129,12 @@ IoDestroyDriverList(VOID) { CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry); - RtlFreeUnicodeString(&CurrentGroup->GroupName); + ExFreePool(CurrentGroup->GroupName.Buffer); RemoveEntryList(GroupEntry); + if (CurrentGroup->TagArray) + { + ExFreePool(CurrentGroup->TagArray); + } ExFreePool(CurrentGroup); GroupEntry = GroupListHead.Flink; @@ -975,10 +1146,10 @@ IoDestroyDriverList(VOID) { CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); - RtlFreeUnicodeString(&CurrentService->ServiceName); - RtlFreeUnicodeString(&CurrentService->RegistryPath); - RtlFreeUnicodeString(&CurrentService->ServiceGroup); - RtlFreeUnicodeString(&CurrentService->ImagePath); + ExFreePool(CurrentService->ServiceName.Buffer); + ExFreePool(CurrentService->RegistryPath.Buffer); + ExFreePool(CurrentService->ServiceGroup.Buffer); + ExFreePool(CurrentService->ImagePath.Buffer); RemoveEntryList(ServiceEntry); ExFreePool(CurrentService); @@ -990,7 +1161,7 @@ IoDestroyDriverList(VOID) return(STATUS_SUCCESS); } -VOID STATIC +VOID STATIC INIT_FUNCTION MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length) { ULONG i; @@ -1007,7 +1178,7 @@ MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length) * Initialize a driver that is already loaded in memory. */ -NTSTATUS FASTCALL +NTSTATUS FASTCALL INIT_FUNCTION IopInitializeBuiltinDriver( PDEVICE_NODE ModuleDeviceNode, PVOID ModuleLoadBase, @@ -1018,7 +1189,6 @@ IopInitializeBuiltinDriver( PDEVICE_NODE DeviceNode; PDRIVER_OBJECT DriverObject; NTSTATUS Status; - CHAR TextBuffer[256]; PCHAR FileNameWithoutPath; LPWSTR FileExtension; @@ -1026,11 +1196,9 @@ IopInitializeBuiltinDriver( FileName, ModuleLoadBase, ModuleLength); /* - * Display 'Initializing XXX...' message + * Display 'Loading XXX...' message */ - - sprintf(TextBuffer, "Initializing %s...\n", FileName); - HalDisplayString(TextBuffer); + IopDisplayLoadingMessage(FileName, FALSE); /* * Determine the right device object @@ -1068,14 +1236,17 @@ IopInitializeBuiltinDriver( FileNameWithoutPath); Status = LdrProcessModule(ModuleLoadBase, &DeviceNode->ServiceName, &ModuleObject); - if (ModuleObject == NULL) + if (!NT_SUCCESS(Status)) { if (ModuleDeviceNode == NULL) IopFreeDeviceNode(DeviceNode); CPRINT("Driver load failed, status (%x)\n", Status); - return STATUS_UNSUCCESSFUL; + return Status; } + /* Load symbols */ + KDB_SYMBOLFILE_HOOK(FileName); + /* * Strip the file extension from ServiceName */ @@ -1083,7 +1254,7 @@ IopInitializeBuiltinDriver( FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.'); if (FileExtension != NULL) { - DeviceNode->ServiceName.Length -= wcslen(DeviceNode->ServiceName.Buffer); + DeviceNode->ServiceName.Length -= wcslen(FileExtension) * sizeof(WCHAR); FileExtension[0] = 0; } @@ -1091,9 +1262,9 @@ IopInitializeBuiltinDriver( * Initialize the driver */ - Status = IopInitializeDriverModule(DeviceNode, ModuleObject, FALSE, - &DriverObject); - + Status = IopInitializeDriverModule(DeviceNode, ModuleObject, + &DeviceNode->ServiceName, FALSE, &DriverObject); + if (!NT_SUCCESS(Status)) { if (ModuleDeviceNode == NULL) @@ -1103,6 +1274,10 @@ IopInitializeBuiltinDriver( } Status = IopInitializeDevice(DeviceNode, DriverObject); + if (NT_SUCCESS(Status)) + { + Status = IopStartDevice(DeviceNode); + } return Status; } @@ -1114,7 +1289,7 @@ IopInitializeBuiltinDriver( * * Parameters * None - * + * * Return Value * None */ @@ -1130,11 +1305,13 @@ IopInitializeBootDrivers(VOID) PCHAR Extension; PLOADER_MODULE KeLoaderModules = (PLOADER_MODULE)KeLoaderBlock.ModsAddr; ULONG i; + UNICODE_STRING DriverName; + NTSTATUS Status; DPRINT("IopInitializeBootDrivers()\n"); BootDriverCount = 0; - for (i = 2; i < KeLoaderBlock.ModsCount; i++) + for (i = 0; i < KeLoaderBlock.ModsCount; i++) { ModuleStart = KeLoaderModules[i].ModStart; ModuleSize = KeLoaderModules[i].ModEnd - ModuleStart; @@ -1144,46 +1321,44 @@ IopInitializeBootDrivers(VOID) if (Extension == NULL) Extension = ""; - /* - * Pass symbol files to kernel debugger - */ - - if (!_stricmp(Extension, ".sym")) + if (!_stricmp(Extension, ".sym") || !_stricmp(Extension, ".dll")) { - KDB_SYMBOLFILE_HOOK((PVOID)ModuleStart, ModuleName, ModuleSize); - } else + /* Process symbols for *.exe and *.dll */ + KDB_SYMBOLFILE_HOOK(ModuleName); - /* - * Load builtin driver - */ - - if (!_stricmp(Extension, ".sys")) + /* Log *.exe and *.dll files */ + RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName); + IopBootLog(&DriverName, TRUE); + RtlFreeUnicodeString(&DriverName); + } + else if (!_stricmp(Extension, ".sys")) { + /* Initialize and log boot start driver */ if (!ModuleLoaded) { - IopInitializeBuiltinDriver(NULL, (PVOID)ModuleStart, ModuleName, - ModuleSize); + Status = IopInitializeBuiltinDriver(NULL, + (PVOID)ModuleStart, + ModuleName, + ModuleSize); + RtlCreateUnicodeStringFromAsciiz(&DriverName, ModuleName); + IopBootLog(&DriverName, NT_SUCCESS(Status) ? TRUE : FALSE); + RtlFreeUnicodeString(&DriverName); } - ++BootDriverCount; + BootDriverCount++; } + } - /* - * Free memory for all boot files, except ntoskrnl.exe and hal.dll - */ - -#ifdef KDBG - /* - * Do not free the memory from symbol files, if the kernel debugger - * is active - */ - if (_stricmp(Extension, ".sym")) -#endif - { - MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart, - KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart); - } + /* + * Free memory for all boot files, except ntoskrnl.exe. + */ + for (i = 1; i < KeLoaderBlock.ModsCount; i++) + { + MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart, + KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart); } + KeLoaderBlock.ModsCount = 0; + if (BootDriverCount == 0) { DbgPrint("No boot drivers available.\n"); @@ -1191,6 +1366,46 @@ IopInitializeBootDrivers(VOID) } } +static INIT_FUNCTION NTSTATUS +IopLoadDriver(PSERVICE Service) +{ + NTSTATUS Status = STATUS_UNSUCCESSFUL; + + IopDisplayLoadingMessage(Service->ServiceName.Buffer, TRUE); + Status = ZwLoadDriver(&Service->RegistryPath); + IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopLoadDriver() failed (Status %lx)\n", Status); +#if 0 + if (Service->ErrorControl == 1) + { + /* Log error */ + } + else if (Service->ErrorControl == 2) + { + if (IsLastKnownGood == FALSE) + { + /* Boot last known good configuration */ + } + } + else if (Service->ErrorControl == 3) + { + if (IsLastKnownGood == FALSE) + { + /* Boot last known good configuration */ + } + else + { + /* BSOD! */ + } + } +#endif + } + return Status; +} + + /* * IopInitializeSystemDrivers * @@ -1198,7 +1413,7 @@ IopInitializeBootDrivers(VOID) * * Parameters * None - * + * * Return Value * None */ @@ -1211,6 +1426,7 @@ IopInitializeSystemDrivers(VOID) PSERVICE_GROUP CurrentGroup; PSERVICE CurrentService; NTSTATUS Status; + ULONG i; DPRINT("IopInitializeSystemDrivers()\n"); @@ -1221,45 +1437,47 @@ IopInitializeSystemDrivers(VOID) DPRINT("Group: %wZ\n", &CurrentGroup->GroupName); + /* Load all drivers with a valid tag */ + for (i = 0; i < CurrentGroup->TagCount; i++) + { + ServiceEntry = ServiceListHead.Flink; + while (ServiceEntry != &ServiceListHead) + { + CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); + + if ((RtlCompareUnicodeString(&CurrentGroup->GroupName, + &CurrentService->ServiceGroup, TRUE) == 0) && + (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/) && + (CurrentService->Tag == CurrentGroup->TagArray[i])) + { + DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath); + Status = IopLoadDriver(CurrentService); + } + ServiceEntry = ServiceEntry->Flink; + } + } + + /* Load all drivers without a tag or with an invalid tag */ ServiceEntry = ServiceListHead.Flink; while (ServiceEntry != &ServiceListHead) { CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); - if ((RtlCompareUnicodeString(&CurrentGroup->GroupName, - &CurrentService->ServiceGroup, TRUE) == 0) && + &CurrentService->ServiceGroup, TRUE) == 0) && (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/)) { - DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath); - IopDisplayLoadingMessage(CurrentService->ServiceName.Buffer); - Status = NtLoadDriver(&CurrentService->RegistryPath); - if (!NT_SUCCESS(Status)) - { - DPRINT("NtLoadDriver() failed (Status %lx)\n", Status); -#if 0 - if (CurrentService->ErrorControl == 1) - { - /* Log error */ - } else - if (CurrentService->ErrorControl == 2) - { - if (IsLastKnownGood == FALSE) - { - /* Boot last known good configuration */ - } - } else - if (CurrentService->ErrorControl == 3) - { - if (IsLastKnownGood == FALSE) - { - /* Boot last known good configuration */ - } else - { - /* BSOD! */ - } - } -#endif - } + for (i = 0; i < CurrentGroup->TagCount; i++) + { + if (CurrentGroup->TagArray[i] == CurrentService->Tag) + { + break; + } + } + if (i >= CurrentGroup->TagCount) + { + DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath); + Status = IopLoadDriver(CurrentService); + } } ServiceEntry = ServiceEntry->Flink; } @@ -1283,7 +1501,7 @@ IopInitializeSystemDrivers(VOID) * Whether to unload Plug & Plug or only legacy drivers. If this * parameter is set to FALSE, the routine will unload only legacy * drivers. - * + * * Return Value * Status * @@ -1394,7 +1612,7 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) * Free the service path */ - RtlFreeUnicodeString(&ImagePath); + ExFreePool(ImagePath.Buffer); /* * Unload the module and release the references to the device object @@ -1476,6 +1694,138 @@ IopReinitializeDrivers(VOID) /* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * @implemented + */ +NTSTATUS +STDCALL +IoCreateDriver ( + IN PUNICODE_STRING DriverName, OPTIONAL + IN PDRIVER_INITIALIZE InitializationFunction + ) +{ + WCHAR NameBuffer[100]; + USHORT NameLength; + UNICODE_STRING LocalDriverName; /* To reduce code if no name given */ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG ObjectSize; + PDRIVER_OBJECT DriverObject; + UNICODE_STRING ServiceKeyName; + HANDLE hDriver; + ULONG i; + + /* First, create a unique name for the driver if we don't have one */ + if (!DriverName) { + + /* Create a random name and set up the string*/ + NameLength = swprintf(NameBuffer, L"\\Driver\\%08u", KeTickCount); + LocalDriverName.Length = NameLength * sizeof(WCHAR); + LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL); + LocalDriverName.Buffer = NameBuffer; + + } else { + + /* So we can avoid another code path, use a local var */ + LocalDriverName = *DriverName; + } + + /* Initialize the Attributes */ + ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(DRIVER_EXTENSION); + InitializeObjectAttributes(&ObjectAttributes, + &LocalDriverName, + OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Create the Object */ + Status = ObCreateObject(KernelMode, + IoDriverObjectType, + &ObjectAttributes, + KernelMode, + NULL, + ObjectSize, + 0, + 0, + (PVOID*)&DriverObject); + + /* Return on failure */ + if (!NT_SUCCESS(Status)) return Status; + + /* Set up the Object */ + RtlZeroMemory(DriverObject, ObjectSize); + DriverObject->Type = IO_TYPE_DRIVER; + DriverObject->Size = sizeof(DRIVER_OBJECT); + DriverObject->Flags = DRVO_BUILTIN_DRIVER; + DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1); + DriverObject->DriverExtension->DriverObject = DriverObject; + DriverObject->DriverInit = InitializationFunction; + + /* Invalidate all Major Functions */ + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + { + DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; + } + + /* Set up the Service Key Name */ + ServiceKeyName.Buffer = ExAllocatePool(PagedPool, LocalDriverName.Length + sizeof(WCHAR)); + ServiceKeyName.Length = LocalDriverName.Length; + ServiceKeyName.MaximumLength = LocalDriverName.MaximumLength; + RtlMoveMemory(ServiceKeyName.Buffer, LocalDriverName.Buffer, LocalDriverName.Length); + ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = L'\0'; + DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName; + + /* Also store it in the Driver Object. This is a bit of a hack. */ + RtlMoveMemory(&DriverObject->DriverName, &ServiceKeyName, sizeof(UNICODE_STRING)); + + /* Add the Object and get its handle */ + Status = ObInsertObject(DriverObject, + NULL, + FILE_READ_DATA, + 0, + NULL, + &hDriver); + + /* Return on Failure */ + if (!NT_SUCCESS(Status)) return Status; + + /* Now reference it */ + Status = ObReferenceObjectByHandle(hDriver, + 0, + IoDriverObjectType, + KernelMode, + (PVOID*)&DriverObject, + NULL); + ZwClose(hDriver); + + /* Finally, call its init function */ + Status = (*InitializationFunction)(DriverObject, NULL); + + if (!NT_SUCCESS(Status)) { + /* If it didn't work, then kill the object */ + ObMakeTemporaryObject(DriverObject); + ObDereferenceObject(DriverObject); + } + + /* Return the Status */ + return Status; +} + +/* + * @implemented + */ +VOID +STDCALL +IoDeleteDriver ( + IN PDRIVER_OBJECT DriverObject + ) +{ + /* Simply derefence the Object */ + ObDereferenceObject(DriverObject); +} + + /* * NtLoadDriver * @@ -1484,7 +1834,7 @@ IopReinitializeDrivers(VOID) * Parameters * DriverServiceName * Name of the service to load (registry key). - * + * * Return Value * Status * @@ -1498,35 +1848,65 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) RTL_QUERY_REGISTRY_TABLE QueryTable[3]; UNICODE_STRING ImagePath; UNICODE_STRING ServiceName; + UNICODE_STRING CapturedDriverServiceName; + KPROCESSOR_MODE PreviousMode; NTSTATUS Status; ULONG Type; PDEVICE_NODE DeviceNode; PMODULE_OBJECT ModuleObject; PDRIVER_OBJECT DriverObject; - LPWSTR Start; + WCHAR *cur; - DPRINT("NtLoadDriver('%wZ')\n", DriverServiceName); + PAGED_CODE(); + + PreviousMode = KeGetPreviousMode(); /* * Check security privileges */ - if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, KeGetPreviousMode())) +/* FIXME: Uncomment when privileges will be correctly implemented. */ +#if 0 + if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) + { + DPRINT("Privilege not held\n"); return STATUS_PRIVILEGE_NOT_HELD; + } +#endif + + Status = RtlCaptureUnicodeString(&CapturedDriverServiceName, + PreviousMode, + PagedPool, + FALSE, + DriverServiceName); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName); RtlInitUnicodeString(&ImagePath, NULL); /* * Get the service name from the registry key name. */ + ASSERT(CapturedDriverServiceName.Length >= sizeof(WCHAR)); - Start = wcsrchr(DriverServiceName->Buffer, L'\\'); - if (Start == NULL) - Start = DriverServiceName->Buffer; - else - Start++; - - RtlInitUnicodeString(&ServiceName, Start); + ServiceName = CapturedDriverServiceName; + cur = CapturedDriverServiceName.Buffer + (CapturedDriverServiceName.Length / sizeof(WCHAR)) - 1; + while (CapturedDriverServiceName.Buffer != cur) + { + if(*cur == L'\\') + { + ServiceName.Buffer = cur + 1; + ServiceName.Length = CapturedDriverServiceName.Length - + (USHORT)((ULONG_PTR)ServiceName.Buffer - + (ULONG_PTR)CapturedDriverServiceName.Buffer); + break; + } + cur--; + } /* * Get service type. @@ -1545,13 +1925,13 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) QueryTable[1].EntryContext = &ImagePath; Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, - DriverServiceName->Buffer, QueryTable, NULL, NULL); + CapturedDriverServiceName.Buffer, QueryTable, NULL, NULL); if (!NT_SUCCESS(Status)) { DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status); - RtlFreeUnicodeString(&ImagePath); - return Status; + ExFreePool(ImagePath.Buffer); + goto ReleaseCapturedString; } /* @@ -1563,10 +1943,10 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) if (!NT_SUCCESS(Status)) { DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status); - return Status; + goto ReleaseCapturedString; } - DPRINT("FullImagePath: '%S'\n", ImagePath.Buffer); + DPRINT("FullImagePath: '%wZ'\n", &ImagePath); DPRINT("Type: %lx\n", Type); /* @@ -1576,7 +1956,9 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) ModuleObject = LdrGetModuleObject(&ImagePath); if (ModuleObject != NULL) { - return STATUS_IMAGE_ALREADY_LOADED; + DPRINT("Image already loaded\n"); + Status = STATUS_IMAGE_ALREADY_LOADED; + goto ReleaseCapturedString; } /* @@ -1589,7 +1971,7 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) if (!NT_SUCCESS(Status)) { DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status); - return Status; + goto ReleaseCapturedString; } /* @@ -1602,19 +1984,14 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) { DPRINT("LdrLoadModule() failed (Status %lx)\n", Status); IopFreeDeviceNode(DeviceNode); - return Status; + goto ReleaseCapturedString; } /* * Set a service name for the device node */ - Start = wcsrchr(DriverServiceName->Buffer, L'\\'); - if (Start == NULL) - Start = DriverServiceName->Buffer; - else - Start++; - RtlCreateUnicodeString(&DeviceNode->ServiceName, Start); + RtlpCreateUnicodeString(&DeviceNode->ServiceName, ServiceName.Buffer, NonPagedPool); /* * Initialize the driver module @@ -1623,6 +2000,7 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) Status = IopInitializeDriverModule( DeviceNode, ModuleObject, + &DeviceNode->ServiceName, (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ || Type == 8 /* SERVICE_RECOGNIZER_DRIVER */), &DriverObject); @@ -1632,10 +2010,16 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status); LdrUnloadModule(ModuleObject); IopFreeDeviceNode(DeviceNode); - return Status; + goto ReleaseCapturedString; } IopInitializeDevice(DeviceNode, DriverObject); + Status = IopStartDevice(DeviceNode); + +ReleaseCapturedString: + RtlReleaseCapturedUnicodeString(&CapturedDriverServiceName, + PreviousMode, + FALSE); return Status; } @@ -1648,7 +2032,7 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName) * Parameters * DriverServiceName * Name of the service to unload (registry key). - * + * * Return Value * Status * @@ -1685,12 +2069,43 @@ IoRegisterDriverReinitialization( ReinitItem->ReinitRoutine = ReinitRoutine; ReinitItem->Context = Context; + DriverObject->Flags |= DRVO_REINIT_REGISTERED; + ExInterlockedInsertTailList( &DriverReinitListHead, &ReinitItem->ItemEntry, &DriverReinitListLock); } +/* + * @implemented + */ +VOID +STDCALL +IoRegisterBootDriverReinitialization( + IN PDRIVER_OBJECT DriverObject, + IN PDRIVER_REINITIALIZE DriverReinitializationRoutine, + IN PVOID Context + ) +{ + PDRIVER_REINIT_ITEM ReinitItem; + + ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM)); + if (ReinitItem == NULL) + return; + + ReinitItem->DriverObject = DriverObject; + ReinitItem->ReinitRoutine = DriverReinitializationRoutine; + ReinitItem->Context = Context; + + DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED; + + ExInterlockedInsertTailList( + &DriverBootReinitListHead, + &ReinitItem->ItemEntry, + &DriverReinitListLock); +} + /* * IoAllocateDriverObjectExtension * @@ -1717,9 +2132,9 @@ IoAllocateDriverObjectExtension( if (NewDriverExtension == NULL) { - return STATUS_INSUFFICIENT_RESOURCES; + return STATUS_INSUFFICIENT_RESOURCES; } - + OldIrql = KeRaiseIrqlToDpcLevel(); NewDriverExtension->Link = DriverObject->DriverSection; @@ -1743,7 +2158,7 @@ IoAllocateDriverObjectExtension( *DriverObjectExtension = &NewDriverExtension->Extension; - return STATUS_SUCCESS; + return STATUS_SUCCESS; } /*