mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
- 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:
parent
9b422ef6c6
commit
ee67c24dce
3 changed files with 511 additions and 509 deletions
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/io/driver.c
|
* FILE: ntoskrnl/io/iomgr/driver.c
|
||||||
* PURPOSE: Driver Object Management
|
* PURPOSE: Driver Object Management
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
* Filip Navara (navaraf@reactos.org)
|
* Filip Navara (navaraf@reactos.org)
|
||||||
|
@ -14,90 +14,38 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#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 ********************************************************************/
|
/* GLOBALS ********************************************************************/
|
||||||
|
|
||||||
static LIST_ENTRY DriverReinitListHead;
|
LIST_ENTRY DriverReinitListHead;
|
||||||
static KSPIN_LOCK DriverReinitListLock;
|
KSPIN_LOCK DriverReinitListLock;
|
||||||
static PLIST_ENTRY DriverReinitTailEntry;
|
PLIST_ENTRY DriverReinitTailEntry;
|
||||||
|
|
||||||
static PLIST_ENTRY DriverBootReinitTailEntry;
|
PLIST_ENTRY DriverBootReinitTailEntry;
|
||||||
static LIST_ENTRY DriverBootReinitListHead;
|
LIST_ENTRY DriverBootReinitListHead;
|
||||||
static KSPIN_LOCK DriverBootReinitListLock;
|
KSPIN_LOCK DriverBootReinitListLock;
|
||||||
|
|
||||||
static LIST_ENTRY GroupListHead = {NULL, NULL};
|
UNICODE_STRING IopHardwareDatabaseKey =
|
||||||
static LIST_ENTRY ServiceListHead = {NULL, NULL};
|
|
||||||
|
|
||||||
static UNICODE_STRING IopHardwareDatabaseKey =
|
|
||||||
RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
|
RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
|
||||||
|
|
||||||
POBJECT_TYPE IoDriverObjectType = NULL;
|
POBJECT_TYPE IoDriverObjectType = NULL;
|
||||||
|
|
||||||
|
extern BOOLEAN SetupMode;
|
||||||
|
extern BOOLEAN NoGuiBoot;
|
||||||
|
|
||||||
/* DECLARATIONS ***************************************************************/
|
/* DECLARATIONS ***************************************************************/
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
IopDeleteDriver(PVOID ObjectBody);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
LdrProcessModule(PVOID ModuleLoadBase,
|
LdrProcessModule(
|
||||||
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,
|
PVOID ModuleLoadBase,
|
||||||
PCHAR FileName,
|
PUNICODE_STRING ModuleName,
|
||||||
ULONG ModuleLength);
|
PLDR_DATA_TABLE_ENTRY *ModuleObject
|
||||||
|
);
|
||||||
static INIT_FUNCTION NTSTATUS
|
|
||||||
IopLoadDriver(PSERVICE Service);
|
|
||||||
|
|
||||||
#if defined (ALLOC_PRAGMA)
|
#if defined (ALLOC_PRAGMA)
|
||||||
#pragma alloc_text(INIT, IopInitDriverImplementation)
|
#pragma alloc_text(INIT, IopInitDriverImplementation)
|
||||||
#pragma alloc_text(INIT, IopDisplayLoadingMessage)
|
#pragma alloc_text(INIT, IopDisplayLoadingMessage)
|
||||||
#pragma alloc_text(INIT, IoCreateDriverList)
|
|
||||||
#pragma alloc_text(INIT, IoDestroyDriverList)
|
|
||||||
#pragma alloc_text(INIT, MiFreeBootDriverMemory)
|
#pragma alloc_text(INIT, MiFreeBootDriverMemory)
|
||||||
#pragma alloc_text(INIT, IopInitializeBuiltinDriver)
|
#pragma alloc_text(INIT, IopInitializeBuiltinDriver)
|
||||||
#pragma alloc_text(INIT, IopLoadDriver)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -841,338 +789,6 @@ IopAttachFilterDrivers(
|
||||||
return STATUS_SUCCESS;
|
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
|
static VOID INIT_FUNCTION
|
||||||
MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
|
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
|
* IopUnloadDriver
|
||||||
*
|
*
|
||||||
|
|
494
reactos/ntoskrnl/io/iomgr/drvrlist.c
Normal file
494
reactos/ntoskrnl/io/iomgr/drvrlist.c
Normal 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 */
|
|
@ -172,6 +172,7 @@
|
||||||
<file>deviface.c</file>
|
<file>deviface.c</file>
|
||||||
<file>disk.c</file>
|
<file>disk.c</file>
|
||||||
<file>driver.c</file>
|
<file>driver.c</file>
|
||||||
|
<file>drvrlist.c</file>
|
||||||
<file>error.c</file>
|
<file>error.c</file>
|
||||||
<file>event.c</file>
|
<file>event.c</file>
|
||||||
<file>file.c</file>
|
<file>file.c</file>
|
||||||
|
|
Loading…
Reference in a new issue