- Separate functions that deal with driver-related registry code, grouping, tagging, indexing, sorting into drvrlist.c... this code should eventually become part of Cm instead.

svn path=/trunk/; revision=22968
This commit is contained in:
Alex Ionescu 2006-07-09 02:34:32 +00:00
parent 9b422ef6c6
commit ee67c24dce
3 changed files with 511 additions and 509 deletions

View file

@ -1,7 +1,7 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/io/driver.c
* FILE: ntoskrnl/io/iomgr/driver.c
* PURPOSE: Driver Object Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Filip Navara (navaraf@reactos.org)
@ -14,90 +14,38 @@
#define NDEBUG
#include <internal/debug.h>
/* ke/main.c */
extern BOOLEAN SetupMode;
extern BOOLEAN NoGuiBoot;
typedef struct _SERVICE_GROUP
{
LIST_ENTRY GroupListEntry;
UNICODE_STRING GroupName;
BOOLEAN ServicesRunning;
ULONG TagCount;
PULONG TagArray;
} SERVICE_GROUP, *PSERVICE_GROUP;
typedef struct _SERVICE
{
LIST_ENTRY ServiceListEntry;
UNICODE_STRING ServiceName;
UNICODE_STRING RegistryPath;
UNICODE_STRING ServiceGroup;
UNICODE_STRING ImagePath;
ULONG Start;
ULONG Type;
ULONG ErrorControl;
ULONG Tag;
/* BOOLEAN ServiceRunning;*/ // needed ??
} SERVICE, *PSERVICE;
/* GLOBALS ********************************************************************/
static LIST_ENTRY DriverReinitListHead;
static KSPIN_LOCK DriverReinitListLock;
static PLIST_ENTRY DriverReinitTailEntry;
LIST_ENTRY DriverReinitListHead;
KSPIN_LOCK DriverReinitListLock;
PLIST_ENTRY DriverReinitTailEntry;
static PLIST_ENTRY DriverBootReinitTailEntry;
static LIST_ENTRY DriverBootReinitListHead;
static KSPIN_LOCK DriverBootReinitListLock;
PLIST_ENTRY DriverBootReinitTailEntry;
LIST_ENTRY DriverBootReinitListHead;
KSPIN_LOCK DriverBootReinitListLock;
static LIST_ENTRY GroupListHead = {NULL, NULL};
static LIST_ENTRY ServiceListHead = {NULL, NULL};
static UNICODE_STRING IopHardwareDatabaseKey =
UNICODE_STRING IopHardwareDatabaseKey =
RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
POBJECT_TYPE IoDriverObjectType = NULL;
extern BOOLEAN SetupMode;
extern BOOLEAN NoGuiBoot;
/* DECLARATIONS ***************************************************************/
VOID STDCALL
IopDeleteDriver(PVOID ObjectBody);
NTSTATUS
LdrProcessModule(PVOID ModuleLoadBase,
PUNICODE_STRING ModuleName,
PLDR_DATA_TABLE_ENTRY *ModuleObject);
static VOID
FASTCALL
INIT_FUNCTION
IopDisplayLoadingMessage(PVOID ServiceName,
BOOLEAN Unicode);
static VOID INIT_FUNCTION
MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length);
NTSTATUS FASTCALL INIT_FUNCTION
IopInitializeBuiltinDriver(
PDEVICE_NODE ModuleDeviceNode,
PVOID ModuleLoadBase,
PCHAR FileName,
ULONG ModuleLength);
static INIT_FUNCTION NTSTATUS
IopLoadDriver(PSERVICE Service);
LdrProcessModule(
PVOID ModuleLoadBase,
PUNICODE_STRING ModuleName,
PLDR_DATA_TABLE_ENTRY *ModuleObject
);
#if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, IopInitDriverImplementation)
#pragma alloc_text(INIT, IopDisplayLoadingMessage)
#pragma alloc_text(INIT, IoCreateDriverList)
#pragma alloc_text(INIT, IoDestroyDriverList)
#pragma alloc_text(INIT, MiFreeBootDriverMemory)
#pragma alloc_text(INIT, IopInitializeBuiltinDriver)
#pragma alloc_text(INIT, IopLoadDriver)
#endif
@ -841,338 +789,6 @@ IopAttachFilterDrivers(
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, 0x%p, %x, 0x%p, 0x%p)\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,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
{
PSERVICE_GROUP Group;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
if (ValueType == REG_SZ)
{
DPRINT("GroupName: '%S'\n", (PWCHAR)ValueData);
Group = ExAllocatePool(NonPagedPool,
sizeof(SERVICE_GROUP));
if (Group == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(Group, sizeof(SERVICE_GROUP));
if (!RtlCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData))
{
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);
}
return(STATUS_SUCCESS);
}
static NTSTATUS STDCALL
IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[7];
PSERVICE Service;
NTSTATUS Status;
DPRINT("ServiceName: '%wZ'\n", ServiceName);
/* Allocate service entry */
Service = (PSERVICE)ExAllocatePool(NonPagedPool, sizeof(SERVICE));
if (Service == NULL)
{
DPRINT1("ExAllocatePool() failed\n");
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(Service, sizeof(SERVICE));
/* Get service data */
RtlZeroMemory(&QueryTable,
sizeof(QueryTable));
QueryTable[0].Name = L"Start";
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].EntryContext = &Service->Start;
QueryTable[1].Name = L"Type";
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[1].EntryContext = &Service->Type;
QueryTable[2].Name = L"ErrorControl";
QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[2].EntryContext = &Service->ErrorControl;
QueryTable[3].Name = L"Group";
QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[3].EntryContext = &Service->ServiceGroup;
QueryTable[4].Name = L"ImagePath";
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,
NULL,
NULL);
if (!NT_SUCCESS(Status) || Service->Start > 1)
{
/*
* 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);
}
/* Copy service name */
Service->ServiceName.Length = ServiceName->Length;
Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR);
Service->ServiceName.Buffer = ExAllocatePool(NonPagedPool,
Service->ServiceName.MaximumLength);
RtlCopyMemory(Service->ServiceName.Buffer,
ServiceName->Buffer,
ServiceName->Length);
Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0;
/* Build registry path */
Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
Service->RegistryPath.Buffer = ExAllocatePool(NonPagedPool,
MAX_PATH * sizeof(WCHAR));
wcscpy(Service->RegistryPath.Buffer,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
wcscat(Service->RegistryPath.Buffer,
Service->ServiceName.Buffer);
Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR);
DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);
DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);
DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath);
DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
Service->Start, Service->Type, Service->Tag, Service->ErrorControl);
/* Append service entry */
InsertTailList(&ServiceListHead,
&Service->ServiceListEntry);
return(STATUS_SUCCESS);
}
NTSTATUS INIT_FUNCTION
IoCreateDriverList(VOID)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
PKEY_BASIC_INFORMATION KeyInfo = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ServicesKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
UNICODE_STRING SubKeyName;
HANDLE KeyHandle;
NTSTATUS Status;
ULONG Index;
ULONG KeyInfoLength = 0;
ULONG ReturnedLength;
DPRINT("IoCreateDriverList() called\n");
/* Initialize basic variables */
InitializeListHead(&GroupListHead);
InitializeListHead(&ServiceListHead);
/* Build group order list */
RtlZeroMemory(&QueryTable,
sizeof(QueryTable));
QueryTable[0].Name = L"List";
QueryTable[0].QueryRoutine = IopCreateGroupListEntry;
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
L"ServiceGroupOrder",
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS(Status))
return(Status);
/* Enumerate services and create the service list */
InitializeObjectAttributes(&ObjectAttributes,
&ServicesKeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(&KeyHandle,
KEY_ENUMERATE_SUB_KEYS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
return(Status);
}
KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);
KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength);
if (KeyInfo == NULL)
{
ZwClose(KeyHandle);
return(STATUS_INSUFFICIENT_RESOURCES);
}
Index = 0;
while (TRUE)
{
Status = ZwEnumerateKey(KeyHandle,
Index,
KeyBasicInformation,
KeyInfo,
KeyInfoLength,
&ReturnedLength);
if (NT_SUCCESS(Status))
{
if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR))
{
SubKeyName.Length = KeyInfo->NameLength;
SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR);
SubKeyName.Buffer = KeyInfo->Name;
SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;
DPRINT("KeyName: '%wZ'\n", &SubKeyName);
IopCreateServiceListEntry(&SubKeyName);
}
}
if (!NT_SUCCESS(Status))
break;
Index++;
}
ExFreePool(KeyInfo);
ZwClose(KeyHandle);
DPRINT("IoCreateDriverList() done\n");
return(STATUS_SUCCESS);
}
NTSTATUS INIT_FUNCTION
IoDestroyDriverList(VOID)
{
PSERVICE_GROUP CurrentGroup, tmp1;
PSERVICE CurrentService, tmp2;
DPRINT("IoDestroyDriverList() called\n");
/* Destroy group list */
LIST_FOR_EACH_SAFE(CurrentGroup, tmp1, &GroupListHead, SERVICE_GROUP, GroupListEntry)
{
ExFreePool(CurrentGroup->GroupName.Buffer);
RemoveEntryList(&CurrentGroup->GroupListEntry);
if (CurrentGroup->TagArray)
{
ExFreePool(CurrentGroup->TagArray);
}
ExFreePool(CurrentGroup);
}
/* Destroy service list */
LIST_FOR_EACH_SAFE(CurrentService, tmp2, &ServiceListHead, SERVICE, ServiceListEntry)
{
ExFreePool(CurrentService->ServiceName.Buffer);
ExFreePool(CurrentService->RegistryPath.Buffer);
ExFreePool(CurrentService->ServiceGroup.Buffer);
ExFreePool(CurrentService->ImagePath.Buffer);
RemoveEntryList(&CurrentService->ServiceListEntry);
ExFreePool(CurrentService);
}
DPRINT("IoDestroyDriverList() done\n");
return(STATUS_SUCCESS);
}
static VOID INIT_FUNCTION
MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
{
@ -1378,115 +994,6 @@ 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
*
* Load drivers marked as system start.
*
* Parameters
* None
*
* Return Value
* None
*/
VOID FASTCALL
IopInitializeSystemDrivers(VOID)
{
PSERVICE_GROUP CurrentGroup;
PSERVICE CurrentService;
NTSTATUS Status;
ULONG i;
DPRINT("IopInitializeSystemDrivers()\n");
LIST_FOR_EACH(CurrentGroup, &GroupListHead, SERVICE_GROUP, GroupListEntry)
{
DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
/* Load all drivers with a valid tag */
for (i = 0; i < CurrentGroup->TagCount; i++)
{
LIST_FOR_EACH(CurrentService, &ServiceListHead, 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);
}
}
}
/* Load all drivers without a tag or with an invalid tag */
LIST_FOR_EACH(CurrentService, &ServiceListHead, SERVICE, ServiceListEntry)
{
if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
&CurrentService->ServiceGroup, TRUE) == 0) &&
(CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/))
{
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);
}
}
}
}
DPRINT("IopInitializeSystemDrivers() done\n");
}
/*
* IopUnloadDriver
*

View file

@ -0,0 +1,494 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/io/iomgr/drvrlist.c
* PURPOSE: Driver List support for Grouping, Tagging, Sorting, etc.
* PROGRAMMERS: <UNKNOWN>
*/
/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
typedef struct _SERVICE_GROUP
{
LIST_ENTRY GroupListEntry;
UNICODE_STRING GroupName;
BOOLEAN ServicesRunning;
ULONG TagCount;
PULONG TagArray;
} SERVICE_GROUP, *PSERVICE_GROUP;
typedef struct _SERVICE
{
LIST_ENTRY ServiceListEntry;
UNICODE_STRING ServiceName;
UNICODE_STRING RegistryPath;
UNICODE_STRING ServiceGroup;
UNICODE_STRING ImagePath;
ULONG Start;
ULONG Type;
ULONG ErrorControl;
ULONG Tag;
/* BOOLEAN ServiceRunning;*/ // needed ??
} SERVICE, *PSERVICE;
/* GLOBALS ********************************************************************/
LIST_ENTRY GroupListHead = {NULL, NULL};
LIST_ENTRY ServiceListHead = {NULL, NULL};
extern BOOLEAN SetupMode;
extern BOOLEAN NoGuiBoot;
VOID
FASTCALL
INIT_FUNCTION
IopDisplayLoadingMessage(PVOID ServiceName,
BOOLEAN Unicode);
/* PRIVATE FUNCTIONS **********************************************************/
static NTSTATUS STDCALL
IopGetGroupOrderList(PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
{
PSERVICE_GROUP Group;
DPRINT("IopGetGroupOrderList(%S, %x, 0x%p, %x, 0x%p, 0x%p)\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,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext)
{
PSERVICE_GROUP Group;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
if (ValueType == REG_SZ)
{
DPRINT("GroupName: '%S'\n", (PWCHAR)ValueData);
Group = ExAllocatePool(NonPagedPool,
sizeof(SERVICE_GROUP));
if (Group == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(Group, sizeof(SERVICE_GROUP));
if (!RtlCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData))
{
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);
}
return(STATUS_SUCCESS);
}
static NTSTATUS STDCALL
IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[7];
PSERVICE Service;
NTSTATUS Status;
DPRINT("ServiceName: '%wZ'\n", ServiceName);
/* Allocate service entry */
Service = (PSERVICE)ExAllocatePool(NonPagedPool, sizeof(SERVICE));
if (Service == NULL)
{
DPRINT1("ExAllocatePool() failed\n");
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(Service, sizeof(SERVICE));
/* Get service data */
RtlZeroMemory(&QueryTable,
sizeof(QueryTable));
QueryTable[0].Name = L"Start";
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].EntryContext = &Service->Start;
QueryTable[1].Name = L"Type";
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[1].EntryContext = &Service->Type;
QueryTable[2].Name = L"ErrorControl";
QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[2].EntryContext = &Service->ErrorControl;
QueryTable[3].Name = L"Group";
QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[3].EntryContext = &Service->ServiceGroup;
QueryTable[4].Name = L"ImagePath";
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,
NULL,
NULL);
if (!NT_SUCCESS(Status) || Service->Start > 1)
{
/*
* 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);
}
/* Copy service name */
Service->ServiceName.Length = ServiceName->Length;
Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR);
Service->ServiceName.Buffer = ExAllocatePool(NonPagedPool,
Service->ServiceName.MaximumLength);
RtlCopyMemory(Service->ServiceName.Buffer,
ServiceName->Buffer,
ServiceName->Length);
Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0;
/* Build registry path */
Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
Service->RegistryPath.Buffer = ExAllocatePool(NonPagedPool,
MAX_PATH * sizeof(WCHAR));
wcscpy(Service->RegistryPath.Buffer,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
wcscat(Service->RegistryPath.Buffer,
Service->ServiceName.Buffer);
Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR);
DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);
DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);
DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath);
DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
Service->Start, Service->Type, Service->Tag, Service->ErrorControl);
/* Append service entry */
InsertTailList(&ServiceListHead,
&Service->ServiceListEntry);
return(STATUS_SUCCESS);
}
NTSTATUS INIT_FUNCTION
IoCreateDriverList(VOID)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
PKEY_BASIC_INFORMATION KeyInfo = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING ServicesKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
UNICODE_STRING SubKeyName;
HANDLE KeyHandle;
NTSTATUS Status;
ULONG Index;
ULONG KeyInfoLength = 0;
ULONG ReturnedLength;
DPRINT("IoCreateDriverList() called\n");
/* Initialize basic variables */
InitializeListHead(&GroupListHead);
InitializeListHead(&ServiceListHead);
/* Build group order list */
RtlZeroMemory(&QueryTable,
sizeof(QueryTable));
QueryTable[0].Name = L"List";
QueryTable[0].QueryRoutine = IopCreateGroupListEntry;
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
L"ServiceGroupOrder",
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS(Status))
return(Status);
/* Enumerate services and create the service list */
InitializeObjectAttributes(&ObjectAttributes,
&ServicesKeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(&KeyHandle,
KEY_ENUMERATE_SUB_KEYS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
return(Status);
}
KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);
KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength);
if (KeyInfo == NULL)
{
ZwClose(KeyHandle);
return(STATUS_INSUFFICIENT_RESOURCES);
}
Index = 0;
while (TRUE)
{
Status = ZwEnumerateKey(KeyHandle,
Index,
KeyBasicInformation,
KeyInfo,
KeyInfoLength,
&ReturnedLength);
if (NT_SUCCESS(Status))
{
if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR))
{
SubKeyName.Length = KeyInfo->NameLength;
SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR);
SubKeyName.Buffer = KeyInfo->Name;
SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;
DPRINT("KeyName: '%wZ'\n", &SubKeyName);
IopCreateServiceListEntry(&SubKeyName);
}
}
if (!NT_SUCCESS(Status))
break;
Index++;
}
ExFreePool(KeyInfo);
ZwClose(KeyHandle);
DPRINT("IoCreateDriverList() done\n");
return(STATUS_SUCCESS);
}
NTSTATUS INIT_FUNCTION
IoDestroyDriverList(VOID)
{
PSERVICE_GROUP CurrentGroup, tmp1;
PSERVICE CurrentService, tmp2;
DPRINT("IoDestroyDriverList() called\n");
/* Destroy group list */
LIST_FOR_EACH_SAFE(CurrentGroup, tmp1, &GroupListHead, SERVICE_GROUP, GroupListEntry)
{
ExFreePool(CurrentGroup->GroupName.Buffer);
RemoveEntryList(&CurrentGroup->GroupListEntry);
if (CurrentGroup->TagArray)
{
ExFreePool(CurrentGroup->TagArray);
}
ExFreePool(CurrentGroup);
}
/* Destroy service list */
LIST_FOR_EACH_SAFE(CurrentService, tmp2, &ServiceListHead, SERVICE, ServiceListEntry)
{
ExFreePool(CurrentService->ServiceName.Buffer);
ExFreePool(CurrentService->RegistryPath.Buffer);
ExFreePool(CurrentService->ServiceGroup.Buffer);
ExFreePool(CurrentService->ImagePath.Buffer);
RemoveEntryList(&CurrentService->ServiceListEntry);
ExFreePool(CurrentService);
}
DPRINT("IoDestroyDriverList() done\n");
return(STATUS_SUCCESS);
}
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
*
* Load drivers marked as system start.
*
* Parameters
* None
*
* Return Value
* None
*/
VOID FASTCALL
IopInitializeSystemDrivers(VOID)
{
PSERVICE_GROUP CurrentGroup;
PSERVICE CurrentService;
NTSTATUS Status;
ULONG i;
DPRINT("IopInitializeSystemDrivers()\n");
LIST_FOR_EACH(CurrentGroup, &GroupListHead, SERVICE_GROUP, GroupListEntry)
{
DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
/* Load all drivers with a valid tag */
for (i = 0; i < CurrentGroup->TagCount; i++)
{
LIST_FOR_EACH(CurrentService, &ServiceListHead, 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);
}
}
}
/* Load all drivers without a tag or with an invalid tag */
LIST_FOR_EACH(CurrentService, &ServiceListHead, SERVICE, ServiceListEntry)
{
if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
&CurrentService->ServiceGroup, TRUE) == 0) &&
(CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/))
{
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);
}
}
}
}
DPRINT("IopInitializeSystemDrivers() done\n");
}
/* EOF */

View file

@ -172,6 +172,7 @@
<file>deviface.c</file>
<file>disk.c</file>
<file>driver.c</file>
<file>drvrlist.c</file>
<file>error.c</file>
<file>event.c</file>
<file>file.c</file>