From 093f4a09c5c0c6ea1c4f366e79d8393d252a209a Mon Sep 17 00:00:00 2001 From: Hartmut Birr Date: Mon, 20 Sep 2004 19:47:25 +0000 Subject: [PATCH] - Implemented the loading of drivers according to the order of the tag entries in the GroupOrderList key. svn path=/trunk/; revision=10949 --- reactos/ntoskrnl/io/driver.c | 183 +++++++++++++++++----- reactos/subsys/system/services/database.c | 97 +++++++++++- 2 files changed, 238 insertions(+), 42 deletions(-) diff --git a/reactos/ntoskrnl/io/driver.c b/reactos/ntoskrnl/io/driver.c index 7378a2c0cd9..1040345b88c 100644 --- a/reactos/ntoskrnl/io/driver.c +++ b/reactos/ntoskrnl/io/driver.c @@ -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 * PROJECT: ReactOS kernel @@ -29,6 +29,8 @@ typedef struct _SERVICE_GROUP LIST_ENTRY GroupListEntry; UNICODE_STRING GroupName; BOOLEAN ServicesRunning; + ULONG TagCount; + PULONG TagArray; } SERVICE_GROUP, *PSERVICE_GROUP; typedef struct _SERVICE @@ -705,6 +707,48 @@ 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, %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, @@ -714,6 +758,9 @@ IopCreateGroupListEntry(PWSTR ValueName, PVOID EntryContext) { PSERVICE_GROUP Group; + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; + if (ValueType == REG_SZ) { @@ -735,6 +782,16 @@ IopCreateGroupListEntry(PWSTR ValueName, 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); @@ -747,7 +804,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; @@ -786,6 +843,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, @@ -823,8 +884,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, @@ -952,6 +1013,10 @@ IoDestroyDriverList(VOID) RtlFreeUnicodeString(&CurrentGroup->GroupName); RemoveEntryList(GroupEntry); + if (CurrentGroup->TagArray) + { + ExFreePool(CurrentGroup->TagArray); + } ExFreePool(CurrentGroup); GroupEntry = GroupListHead.Flink; @@ -978,7 +1043,7 @@ IoDestroyDriverList(VOID) return(STATUS_SUCCESS); } -VOID STATIC +VOID STATIC INIT_FUNCTION MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length) { ULONG i; @@ -995,7 +1060,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, @@ -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 * @@ -1199,6 +1303,7 @@ IopInitializeSystemDrivers(VOID) PSERVICE_GROUP CurrentGroup; PSERVICE CurrentService; NTSTATUS Status; + ULONG i; DPRINT("IopInitializeSystemDrivers()\n"); @@ -1209,45 +1314,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; } diff --git a/reactos/subsys/system/services/database.c b/reactos/subsys/system/services/database.c index 31127b8b8be..404ba3dc11b 100644 --- a/reactos/subsys/system/services/database.c +++ b/reactos/subsys/system/services/database.c @@ -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 * @@ -46,6 +46,8 @@ typedef struct _SERVICE_GROUP UNICODE_STRING GroupName; BOOLEAN ServicesRunning; + ULONG TagCount; + PULONG TagArray; } SERVICE_GROUP, *PSERVICE_GROUP; @@ -79,6 +81,52 @@ LIST_ENTRY ServiceListHead; /* 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 CreateGroupListRoutine(PWSTR ValueName, ULONG ValueType, @@ -88,6 +136,8 @@ CreateGroupListRoutine(PWSTR ValueName, PVOID EntryContext) { PSERVICE_GROUP Group; + RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + NTSTATUS Status; if (ValueType == REG_SZ) { @@ -106,6 +156,17 @@ CreateGroupListRoutine(PWSTR ValueName, { 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, @@ -184,6 +245,10 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName) QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; 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, ServiceName->Buffer, QueryTable, @@ -201,8 +266,8 @@ CreateServiceListEntry(PUNICODE_STRING ServiceName) DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName); DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath); DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup); - 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, @@ -636,6 +701,7 @@ ScmAutoStartServices(VOID) PLIST_ENTRY ServiceEntry; PSERVICE_GROUP CurrentGroup; PSERVICE CurrentService; + ULONG i; /* Clear 'ServiceVisited' flag */ ServiceEntry = ServiceListHead.Flink; @@ -654,6 +720,29 @@ ScmAutoStartServices(VOID) 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; while (ServiceEntry != &ServiceListHead) { @@ -680,7 +769,7 @@ ScmAutoStartServices(VOID) { CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry); - if ((CurrentService->ServiceGroup.Length == 0) && + if ((CurrentService->ServiceGroup.Length != 0) && (CurrentService->Start == SERVICE_AUTO_START) && (CurrentService->ServiceVisited == FALSE)) {