- Implemented the loading of drivers according to the order

of the tag entries in the GroupOrderList key.

svn path=/trunk/; revision=10949
This commit is contained in:
Hartmut Birr 2004-09-20 19:47:25 +00:00
parent c9ece8cfa5
commit 093f4a09c5
2 changed files with 238 additions and 42 deletions

View file

@ -1,4 +1,4 @@
/* $Id: driver.c,v 1.51 2004/09/07 11:48:16 ekohl Exp $ /* $Id: driver.c,v 1.52 2004/09/20 19:47:25 hbirr Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -29,6 +29,8 @@ typedef struct _SERVICE_GROUP
LIST_ENTRY GroupListEntry; LIST_ENTRY GroupListEntry;
UNICODE_STRING GroupName; UNICODE_STRING GroupName;
BOOLEAN ServicesRunning; BOOLEAN ServicesRunning;
ULONG TagCount;
PULONG TagArray;
} SERVICE_GROUP, *PSERVICE_GROUP; } SERVICE_GROUP, *PSERVICE_GROUP;
typedef struct _SERVICE typedef struct _SERVICE
@ -705,6 +707,48 @@ 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, %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 static NTSTATUS STDCALL
IopCreateGroupListEntry(PWSTR ValueName, IopCreateGroupListEntry(PWSTR ValueName,
ULONG ValueType, ULONG ValueType,
@ -714,6 +758,9 @@ IopCreateGroupListEntry(PWSTR ValueName,
PVOID EntryContext) PVOID EntryContext)
{ {
PSERVICE_GROUP Group; PSERVICE_GROUP Group;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
if (ValueType == REG_SZ) if (ValueType == REG_SZ)
{ {
@ -735,6 +782,16 @@ IopCreateGroupListEntry(PWSTR ValueName,
return(STATUS_INSUFFICIENT_RESOURCES); 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, InsertTailList(&GroupListHead,
&Group->GroupListEntry); &Group->GroupListEntry);
@ -747,7 +804,7 @@ IopCreateGroupListEntry(PWSTR ValueName,
static NTSTATUS STDCALL static NTSTATUS STDCALL
IopCreateServiceListEntry(PUNICODE_STRING ServiceName) IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
{ {
RTL_QUERY_REGISTRY_TABLE QueryTable[6]; RTL_QUERY_REGISTRY_TABLE QueryTable[7];
PSERVICE Service; PSERVICE Service;
NTSTATUS Status; NTSTATUS Status;
@ -786,6 +843,10 @@ IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[4].EntryContext = &Service->ImagePath; 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, Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ServiceName->Buffer, ServiceName->Buffer,
QueryTable, QueryTable,
@ -823,8 +884,8 @@ IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath); DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);
DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup); DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);
DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath); DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath);
DPRINT("Start %lx Type %lx ErrorControl %lx\n", DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
Service->Start, Service->Type, Service->ErrorControl); Service->Start, Service->Type, Service->Tag, Service->ErrorControl);
/* Append service entry */ /* Append service entry */
InsertTailList(&ServiceListHead, InsertTailList(&ServiceListHead,
@ -952,6 +1013,10 @@ IoDestroyDriverList(VOID)
RtlFreeUnicodeString(&CurrentGroup->GroupName); RtlFreeUnicodeString(&CurrentGroup->GroupName);
RemoveEntryList(GroupEntry); RemoveEntryList(GroupEntry);
if (CurrentGroup->TagArray)
{
ExFreePool(CurrentGroup->TagArray);
}
ExFreePool(CurrentGroup); ExFreePool(CurrentGroup);
GroupEntry = GroupListHead.Flink; GroupEntry = GroupListHead.Flink;
@ -978,7 +1043,7 @@ IoDestroyDriverList(VOID)
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
VOID STATIC VOID STATIC INIT_FUNCTION
MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length) MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
{ {
ULONG i; ULONG i;
@ -995,7 +1060,7 @@ MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
* Initialize a driver that is already loaded in memory. * Initialize a driver that is already loaded in memory.
*/ */
NTSTATUS FASTCALL NTSTATUS FASTCALL INIT_FUNCTION
IopInitializeBuiltinDriver( IopInitializeBuiltinDriver(
PDEVICE_NODE ModuleDeviceNode, PDEVICE_NODE ModuleDeviceNode,
PVOID ModuleLoadBase, PVOID ModuleLoadBase,
@ -1179,6 +1244,45 @@ IopInitializeBootDrivers(VOID)
} }
} }
static INIT_FUNCTION NTSTATUS
IopLoadDriver(PSERVICE Service)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
IopDisplayLoadingMessage(Service->ServiceName.Buffer);
Status = NtLoadDriver(&Service->RegistryPath);
if (!NT_SUCCESS(Status))
{
DPRINT("NtLoadDriver() 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 * IopInitializeSystemDrivers
* *
@ -1199,6 +1303,7 @@ IopInitializeSystemDrivers(VOID)
PSERVICE_GROUP CurrentGroup; PSERVICE_GROUP CurrentGroup;
PSERVICE CurrentService; PSERVICE CurrentService;
NTSTATUS Status; NTSTATUS Status;
ULONG i;
DPRINT("IopInitializeSystemDrivers()\n"); DPRINT("IopInitializeSystemDrivers()\n");
@ -1209,6 +1314,9 @@ IopInitializeSystemDrivers(VOID)
DPRINT("Group: %wZ\n", &CurrentGroup->GroupName); DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
/* Load all drivers with a valid tag */
for (i = 0; i < CurrentGroup->TagCount; i++)
{
ServiceEntry = ServiceListHead.Flink; ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead) while (ServiceEntry != &ServiceListHead)
{ {
@ -1216,37 +1324,36 @@ IopInitializeSystemDrivers(VOID)
if ((RtlCompareUnicodeString(&CurrentGroup->GroupName, if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
&CurrentService->ServiceGroup, TRUE) == 0) && &CurrentService->ServiceGroup, TRUE) == 0) &&
(CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/)) (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/) &&
(CurrentService->Tag == CurrentGroup->TagArray[i]))
{ {
DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath); DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath);
IopDisplayLoadingMessage(CurrentService->ServiceName.Buffer); Status = IopLoadDriver(CurrentService);
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 ServiceEntry = ServiceEntry->Flink;
if (CurrentService->ErrorControl == 3)
{
if (IsLastKnownGood == FALSE)
{
/* Boot last known good configuration */
} else
{
/* BSOD! */
} }
} }
#endif
/* 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->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);
} }
} }
ServiceEntry = ServiceEntry->Flink; ServiceEntry = ServiceEntry->Flink;

View file

@ -1,4 +1,4 @@
/* $Id: database.c,v 1.17 2004/07/03 17:40:24 navaraf Exp $ /* $Id: database.c,v 1.18 2004/09/20 19:47:25 hbirr Exp $
* *
* service control manager * service control manager
* *
@ -46,6 +46,8 @@ typedef struct _SERVICE_GROUP
UNICODE_STRING GroupName; UNICODE_STRING GroupName;
BOOLEAN ServicesRunning; BOOLEAN ServicesRunning;
ULONG TagCount;
PULONG TagArray;
} SERVICE_GROUP, *PSERVICE_GROUP; } SERVICE_GROUP, *PSERVICE_GROUP;
@ -79,6 +81,52 @@ LIST_ENTRY ServiceListHead;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
static NTSTATUS STDCALL
CreateGroupOrderListRoutine(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 = (PULONG)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
Group->TagCount * sizeof(DWORD));
if (Group->TagArray == NULL)
{
Group->TagCount = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(Group->TagArray,
(PULONG)ValueData + 1,
Group->TagCount * sizeof(DWORD));
}
else
{
Group->TagCount = 0;
return STATUS_UNSUCCESSFUL;
}
}
}
return STATUS_SUCCESS;
}
static NTSTATUS STDCALL static NTSTATUS STDCALL
CreateGroupListRoutine(PWSTR ValueName, CreateGroupListRoutine(PWSTR ValueName,
ULONG ValueType, ULONG ValueType,
@ -88,6 +136,8 @@ CreateGroupListRoutine(PWSTR ValueName,
PVOID EntryContext) PVOID EntryContext)
{ {
PSERVICE_GROUP Group; PSERVICE_GROUP Group;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
if (ValueType == REG_SZ) if (ValueType == REG_SZ)
{ {
@ -107,6 +157,17 @@ CreateGroupListRoutine(PWSTR ValueName,
return(STATUS_INSUFFICIENT_RESOURCES); return(STATUS_INSUFFICIENT_RESOURCES);
} }
RtlZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].Name = (PWSTR)ValueData;
QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine;
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
L"GroupOrderList",
QueryTable,
(PVOID)Group,
NULL);
DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData);
InsertTailList(&GroupListHead, InsertTailList(&GroupListHead,
&Group->GroupListEntry); &Group->GroupListEntry);
@ -184,6 +245,10 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[3].EntryContext = &Service->ServiceGroup; QueryTable[3].EntryContext = &Service->ServiceGroup;
QueryTable[4].Name = L"Tag";
QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
QueryTable[4].EntryContext = &Service->Tag;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ServiceName->Buffer, ServiceName->Buffer,
QueryTable, QueryTable,
@ -201,8 +266,8 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName)
DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName); DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath); DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);
DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup); DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);
DPRINT("Start %lx Type %lx ErrorControl %lx\n", DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n",
Service->Start, Service->Type, Service->ErrorControl); Service->Start, Service->Type, Service->Tag, Service->ErrorControl);
/* Append service entry */ /* Append service entry */
InsertTailList(&ServiceListHead, InsertTailList(&ServiceListHead,
@ -636,6 +701,7 @@ ScmAutoStartServices(VOID)
PLIST_ENTRY ServiceEntry; PLIST_ENTRY ServiceEntry;
PSERVICE_GROUP CurrentGroup; PSERVICE_GROUP CurrentGroup;
PSERVICE CurrentService; PSERVICE CurrentService;
ULONG i;
/* Clear 'ServiceVisited' flag */ /* Clear 'ServiceVisited' flag */
ServiceEntry = ServiceListHead.Flink; ServiceEntry = ServiceListHead.Flink;
@ -654,6 +720,29 @@ ScmAutoStartServices(VOID)
DPRINT("Group '%wZ'\n", &CurrentGroup->GroupName); DPRINT("Group '%wZ'\n", &CurrentGroup->GroupName);
/* Start all services witch have a valid tag */
for (i = 0; i < CurrentGroup->TagCount; i++)
{
ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead)
{
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
if ((RtlEqualUnicodeString(&CurrentGroup->GroupName, &CurrentService->ServiceGroup, TRUE)) &&
(CurrentService->Start == SERVICE_AUTO_START) &&
(CurrentService->ServiceVisited == FALSE) &&
(CurrentService->Tag == CurrentGroup->TagArray[i]))
{
CurrentService->ServiceVisited = TRUE;
ScmStartService(CurrentService,
CurrentGroup);
}
ServiceEntry = ServiceEntry->Flink;
}
}
/* Start all services which have an invalid tag or which do not have a tag */
ServiceEntry = ServiceListHead.Flink; ServiceEntry = ServiceListHead.Flink;
while (ServiceEntry != &ServiceListHead) while (ServiceEntry != &ServiceListHead)
{ {
@ -680,7 +769,7 @@ ScmAutoStartServices(VOID)
{ {
CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
if ((CurrentService->ServiceGroup.Length == 0) && if ((CurrentService->ServiceGroup.Length != 0) &&
(CurrentService->Start == SERVICE_AUTO_START) && (CurrentService->Start == SERVICE_AUTO_START) &&
(CurrentService->ServiceVisited == FALSE)) (CurrentService->ServiceVisited == FALSE))
{ {