[NTOS]: Implement Configuration Manager routines for building a driver list, sorting...
authorSir Richard <sir_richard@svn.reactos.org>
Sat, 3 Apr 2010 07:44:38 +0000 (07:44 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Sat, 3 Apr 2010 07:44:38 +0000 (07:44 +0000)
[NTOS]: Use the new Cm interface in IopInitializeSystemDrivers to parse the ordered list of system drivers to load. Make it use ZwLoadDriver directly instead of having a hacked IopLoadDriver function.
[NTOS]: Drivers should not show up loading n times a reboot now (some drivers seemed to do this in the past when they failed to load).
[NTOS]: The system driver code could be further improved by checknig if the driver has already been loaded, or attempted and failed to load, but it is already much better now than in the past.
[PERF]: Boot-time improvement since the new system driver loading code uses low-level Cm interfaces (portability side-effect: can be shared with FreeLDR) instead of the complex parse-based object-manager-based system-calls.

svn path=/trunk/; revision=46693

reactos/ntoskrnl/config/cmboot.c
reactos/ntoskrnl/config/cmsysini.c
reactos/ntoskrnl/include/internal/cm.h
reactos/ntoskrnl/io/iomgr/driver.c
reactos/ntoskrnl/io/iomgr/drvrlist.c [deleted file]
reactos/ntoskrnl/io/iomgr/iomgr.c
reactos/ntoskrnl/ntoskrnl-generic.rbuild

index f1dcc34..50c6815 100644 (file)
@@ -1,20 +1,19 @@
 /*
  * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
  * FILE:            ntoskrnl/config/cmboot.c
  * PURPOSE:         Configuration Manager - Boot Initialization
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ *                  Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include "ntoskrnl.h"
 #define NDEBUG
 #include "debug.h"
-
-/* GLOBALS *******************************************************************/
-
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
 
 HCELL_INDEX
 NTAPI
@@ -124,3 +123,559 @@ CmpFindControlSet(IN PHHIVE SystemHive,
     /* Return the CCS Cell */
     return ControlSetCell;
 }
+
+ULONG
+NTAPI
+CmpFindTagIndex(IN PHHIVE Hive,
+                IN HCELL_INDEX TagCell,
+                IN HCELL_INDEX GroupOrderCell,
+                IN PUNICODE_STRING GroupName)
+{
+    PCM_KEY_VALUE TagValue, Value;
+    HCELL_INDEX OrderCell;
+    PULONG TagOrder, DriverTag;
+    ULONG CurrentTag, Length;
+    PCM_KEY_NODE Node;
+    BOOLEAN BufferAllocated;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+    
+    /* Get the tag */
+    Value = HvGetCell(Hive, TagCell);
+    ASSERT(Value);
+    DriverTag = (PULONG)CmpValueToData(Hive, Value, &Length);
+    ASSERT(DriverTag);
+
+    /* Get the order array */
+    Node = HvGetCell(Hive, GroupOrderCell);
+    ASSERT(Node);
+    OrderCell = CmpFindValueByName(Hive, Node, GroupName);
+    if (OrderCell == HCELL_NIL) return -2;
+    
+    /* And read it */
+    TagValue = HvGetCell(Hive, OrderCell);
+    CmpGetValueData(Hive, TagValue, &Length, (PVOID*)&TagOrder, &BufferAllocated, &OrderCell);
+    ASSERT(TagOrder);
+    
+    /* Parse each tag */
+    for (CurrentTag = 1; CurrentTag <= TagOrder[0]; CurrentTag++)
+    {
+        /* Find a match */
+        if (TagOrder[CurrentTag] == *DriverTag)
+        {
+            /* Found it -- return the tag */
+            if (BufferAllocated) ExFreePool(TagOrder);
+            return CurrentTag;
+        }
+    }
+    
+    /* No matches, so assume next to last ordering */
+    if (BufferAllocated) ExFreePool(TagOrder);
+    return -2;
+}
+
+BOOLEAN
+NTAPI
+CmpAddDriverToList(IN PHHIVE Hive,
+                   IN HCELL_INDEX DriverCell,
+                   IN HCELL_INDEX GroupOrderCell,
+                   IN PUNICODE_STRING RegistryPath,
+                   IN PLIST_ENTRY BootDriverListHead)
+{
+    PBOOT_DRIVER_NODE DriverNode;
+    PBOOT_DRIVER_LIST_ENTRY DriverEntry;
+    PCM_KEY_NODE Node;
+    ULONG NameLength, Length;
+    HCELL_INDEX ValueCell, TagCell;    
+    PCM_KEY_VALUE Value;
+    PUNICODE_STRING FileName, RegistryString;
+    UNICODE_STRING UnicodeString;
+    PULONG ErrorControl;
+    PWCHAR Buffer;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+    
+    /* Allocate a driver node and initialize it */
+    DriverNode = CmpAllocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM);
+    if (!DriverNode) return FALSE;
+    DriverEntry = &DriverNode->ListEntry;
+    DriverEntry->RegistryPath.Buffer = NULL;
+    DriverEntry->FilePath.Buffer = NULL;
+    
+    /* Get the driver cell */
+    Node = HvGetCell(Hive, DriverCell);
+    ASSERT(Node);
+    
+    /* Get the name from the cell */
+    DriverNode->Name.Length = Node->Flags & KEY_COMP_NAME ? 
+                              CmpCompressedNameSize(Node->Name, Node->NameLength) :
+                              Node->NameLength;
+    DriverNode->Name.MaximumLength = DriverNode->Name.Length;
+    NameLength = DriverNode->Name.Length;
+    
+    /* Now allocate the buffer for it and copy the name */
+    DriverNode->Name.Buffer = CmpAllocate(NameLength, FALSE, TAG_CM);
+    if (!DriverNode->Name.Buffer) return FALSE;
+    if (Node->Flags & KEY_COMP_NAME)
+    {
+        /* Compressed name */
+        CmpCopyCompressedName(DriverNode->Name.Buffer,
+                              DriverNode->Name.Length,
+                              Node->Name,
+                              Node->NameLength);
+    }
+    else
+    {
+        /* Normal name */
+        RtlCopyMemory(DriverNode->Name.Buffer, Node->Name, Node->NameLength);
+    }
+    
+    /* Now find the image path */
+    RtlInitUnicodeString(&UnicodeString, L"ImagePath");
+    ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
+    if (ValueCell == HCELL_NIL)
+    {
+        /* Couldn't find it, so assume the drivers path */
+        Length = sizeof(L"System32\\Drivers\\") + NameLength + sizeof(L".sys");
+        
+        /* Allocate the path name */
+        FileName = &DriverEntry->FilePath;
+        FileName->Length = 0;
+        FileName->MaximumLength = Length;
+        FileName->Buffer = CmpAllocate(Length, FALSE,TAG_CM);
+        if (!FileName->Buffer) return FALSE;
+
+        /* Write the path name */
+        RtlAppendUnicodeToString(FileName, L"System32\\Drivers\\");
+        RtlAppendUnicodeStringToString(FileName, &DriverNode->Name);
+        RtlAppendUnicodeToString(FileName, L".sys");        
+    }
+    else
+    {
+        /* Path name exists, so grab it */
+        Value = HvGetCell(Hive, ValueCell);
+        ASSERT(Value);
+
+        /* Allocate and setup the path name */
+        FileName = &DriverEntry->FilePath;
+        Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length);
+        FileName->MaximumLength = FileName->Length = Length;
+        FileName->Buffer = CmpAllocate(Length, FALSE, TAG_CM);
+        
+        /* Transfer the data */  
+        if (!(FileName->Buffer) || !(Buffer)) return FALSE;        
+        RtlCopyMemory(FileName->Buffer, Buffer, Length);
+    }
+    
+    /* Now build the registry path */
+    RegistryString = &DriverEntry->RegistryPath;
+    RegistryString->Length = 0;
+    RegistryString->MaximumLength = RegistryPath->Length + NameLength;
+    RegistryString->Buffer = CmpAllocate(RegistryString->MaximumLength, FALSE, TAG_CM);
+    if (!RegistryString->Buffer) return FALSE;
+    
+    /* Add the driver name to it */
+    RtlAppendUnicodeStringToString(RegistryString, RegistryPath);
+    RtlAppendUnicodeStringToString(RegistryString, &DriverNode->Name);
+    
+    /* The entry is done, add it */
+    InsertHeadList(BootDriverListHead, &DriverEntry->Link);
+    
+    /* Now find error control settings */    
+    RtlInitUnicodeString(&UnicodeString, L"ErrorControl");
+    ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
+    if (ValueCell == HCELL_NIL)
+    {
+        /* Couldn't find it, so assume default */
+        DriverNode->ErrorControl = NormalError;
+    }
+    else
+    {
+        /* Otherwise, read whatever the data says */
+        Value = HvGetCell(Hive, ValueCell);
+        ASSERT(Value);
+        ErrorControl = (PULONG)CmpValueToData(Hive, Value, &Length);
+        ASSERT(ErrorControl);
+        DriverNode->ErrorControl = *ErrorControl;
+    }
+    
+    /* Next, get the group cell */
+    RtlInitUnicodeString(&UnicodeString, L"group");
+    ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
+    if (ValueCell == HCELL_NIL)
+    {
+        /* Couldn't find, so set an empty string */
+        RtlInitEmptyUnicodeString(&DriverNode->Group, NULL, 0);
+    }
+    else
+    {
+        /* Found it, read the group value */
+        Value = HvGetCell(Hive, ValueCell);
+        ASSERT(Value);
+        
+        /* Copy it into the node */
+        DriverNode->Group.Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length);
+        if (!DriverNode->Group.Buffer) return FALSE;
+        DriverNode->Group.Length = Length - sizeof(UNICODE_NULL);
+        DriverNode->Group.MaximumLength = DriverNode->Group.Length;
+    }
+    
+    /* Finally, find the tag */
+    RtlInitUnicodeString(&UnicodeString, L"Tag");
+    TagCell = CmpFindValueByName(Hive, Node, &UnicodeString);
+    if (TagCell == HCELL_NIL)
+    {
+        /* No tag, so load last */
+        DriverNode->Tag = -1;
+    }
+    else
+    {
+        /* Otherwise, decode it based on tag order */
+        DriverNode->Tag = CmpFindTagIndex(Hive,
+                                          TagCell,
+                                          GroupOrderCell,
+                                          &DriverNode->Group);
+    }
+    
+    /* All done! */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpIsLoadType(IN PHHIVE Hive,
+              IN HCELL_INDEX Cell,
+              IN SERVICE_LOAD_TYPE LoadType)
+{
+    PCM_KEY_NODE Node;
+    HCELL_INDEX ValueCell;
+    UNICODE_STRING ValueString = RTL_CONSTANT_STRING(L"Start");
+    PCM_KEY_VALUE Value;
+    ULONG Length;
+    PLONG Data;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+
+    /* Open the start cell */
+    Node = HvGetCell(Hive, Cell);
+    ASSERT(Node);
+    ValueCell = CmpFindValueByName(Hive, Node, &ValueString);
+    if (ValueCell == HCELL_NIL) return FALSE;
+    
+    /* Read the start value */
+    Value = HvGetCell(Hive, ValueCell);
+    ASSERT(Value);
+    Data = (PLONG)CmpValueToData(Hive, Value, &Length);
+    ASSERT(Data);
+    
+    /* Return if the type matches */
+    return (*Data == LoadType);
+}
+
+BOOLEAN
+NTAPI
+CmpFindDrivers(IN PHHIVE Hive,
+               IN HCELL_INDEX ControlSet,
+               IN SERVICE_LOAD_TYPE LoadType,
+               IN PWCHAR BootFileSystem OPTIONAL,
+               IN PLIST_ENTRY DriverListHead)
+{
+    HCELL_INDEX ServicesCell, ControlCell, GroupOrderCell, DriverCell;
+    UNICODE_STRING Name;
+    ULONG i;
+    WCHAR Buffer[128];
+    UNICODE_STRING UnicodeString, KeyPath;
+    PBOOT_DRIVER_NODE FsNode;
+    PCM_KEY_NODE ControlNode, ServicesNode, Node;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+    
+    /* Open the control set key */
+    ControlNode = HvGetCell(Hive, ControlSet);
+    ASSERT(ControlNode);
+    
+    /* Get services cell */
+    RtlInitUnicodeString(&Name, L"Services");
+    ServicesCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
+    if (ServicesCell == HCELL_NIL) return FALSE;
+
+    /* Open services key */
+    ServicesNode = HvGetCell(Hive, ServicesCell);
+    ASSERT(ServicesNode);
+    
+    /* Get control cell */
+    RtlInitUnicodeString(&Name, L"Control");
+    ControlCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
+    if (ControlCell == HCELL_NIL) return FALSE;
+    
+    /* Get the group order cell and read it */
+    RtlInitUnicodeString(&Name, L"GroupOrderList");
+    Node = HvGetCell(Hive, ControlCell);
+    ASSERT(Node);
+    GroupOrderCell = CmpFindSubKeyByName(Hive, Node, &Name);
+    if (GroupOrderCell == HCELL_NIL) return FALSE;
+
+    /* Build the root registry path */
+    RtlInitEmptyUnicodeString(&KeyPath, Buffer, sizeof(Buffer));
+    RtlAppendUnicodeToString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+    
+    /* Find the first subkey (ie: the first driver or service) */
+    i = 0;
+    DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, i);
+    while (DriverCell != HCELL_NIL)
+    {
+        /* Make sure it's a driver of this start type */
+        if (CmpIsLoadType(Hive, DriverCell, LoadType))
+        {
+            /* Add it to the list */
+            CmpAddDriverToList(Hive,
+                               DriverCell,
+                               GroupOrderCell,
+                               &KeyPath,
+                               DriverListHead);
+            
+        }
+        
+        /* Try the next subkey */
+        DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, ++i);
+    }
+    
+    /* Check if we have a boot file system */
+    if (BootFileSystem)
+    {
+        /* Find it */
+        RtlInitUnicodeString(&UnicodeString, BootFileSystem);
+        DriverCell = CmpFindSubKeyByName(Hive, ServicesNode, &UnicodeString);
+        if (DriverCell != HCELL_NIL)
+        {
+            /* Always add it to the list */
+            CmpAddDriverToList(Hive,
+                               DriverCell,
+                               GroupOrderCell,
+                               &KeyPath,
+                               DriverListHead);
+            
+            /* Mark it as critical so it always loads */
+            FsNode = CONTAINING_RECORD(DriverListHead->Flink,
+                                       BOOT_DRIVER_NODE,
+                                       ListEntry.Link);
+            FsNode->ErrorControl = SERVICE_ERROR_CRITICAL;
+        }
+    }
+    
+    /* We're done! */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpDoSort(IN PLIST_ENTRY DriverListHead,
+          IN PUNICODE_STRING OrderList)
+{
+    PWCHAR Current, End = NULL;
+    PLIST_ENTRY NextEntry;
+    UNICODE_STRING GroupName;
+    PBOOT_DRIVER_NODE CurrentNode;
+    
+    /* We're going from end to start, so get to the last group and keep going */
+    Current = &OrderList->Buffer[OrderList->Length / sizeof(WCHAR)];
+    while (Current > OrderList->Buffer)
+    {
+        /* Scan the current string */
+        do
+        {
+            if (*Current == UNICODE_NULL) End = Current;
+        } while ((*(--Current - 1) != UNICODE_NULL) && (Current != OrderList->Buffer));
+
+        /* This is our cleaned up string for this specific group */
+        ASSERT(End != NULL);
+        GroupName.Length = (End - Current) * sizeof(WCHAR);
+        GroupName.MaximumLength = GroupName.Length;
+        GroupName.Buffer = Current;
+
+        /* Now loop the driver list */
+        NextEntry = DriverListHead->Flink;
+        while (NextEntry != DriverListHead)
+        {
+            /* Get this node */
+            CurrentNode = CONTAINING_RECORD(NextEntry,
+                                            BOOT_DRIVER_NODE,
+                                            ListEntry.Link);
+                                            
+            /* Get the next entry now since we'll do a relink */
+            NextEntry = CurrentNode->ListEntry.Link.Flink;
+            
+            /* Is there a group name and does it match the current group? */
+            if ((CurrentNode->Group.Buffer) &&
+                (RtlEqualUnicodeString(&GroupName, &CurrentNode->Group, TRUE)))
+            {
+                /* Remove from this location and re-link in the new one */
+                RemoveEntryList(&CurrentNode->ListEntry.Link);
+                InsertHeadList(DriverListHead, &CurrentNode->ListEntry.Link);
+            }
+        }        
+        
+        /* Move on */
+        Current--;
+    }
+    
+    /* All done */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpSortDriverList(IN PHHIVE Hive,
+                  IN HCELL_INDEX ControlSet,
+                  IN PLIST_ENTRY DriverListHead)
+{
+    HCELL_INDEX Controls, GroupOrder, ListCell;
+    UNICODE_STRING Name, DependList;
+    PCM_KEY_VALUE ListNode;
+    ULONG Length;
+    PCM_KEY_NODE Node;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+
+    /* Open the control key */
+    Node = HvGetCell(Hive, ControlSet);
+    ASSERT(Node);
+    RtlInitUnicodeString(&Name, L"Control");
+    Controls = CmpFindSubKeyByName(Hive, Node, &Name);
+    if (Controls == HCELL_NIL) return FALSE;
+
+    /* Open the service group order */
+    Node = HvGetCell(Hive, Controls);
+    ASSERT(Node);
+    RtlInitUnicodeString(&Name, L"ServiceGroupOrder");
+    GroupOrder = CmpFindSubKeyByName(Hive, Node, &Name);
+    if (GroupOrder == HCELL_NIL) return FALSE;
+
+    /* Open the list key */
+    Node = HvGetCell(Hive, GroupOrder);
+    ASSERT(Node);
+    RtlInitUnicodeString(&Name, L"list");
+    ListCell = CmpFindValueByName(Hive, Node, &Name);
+    if (ListCell == HCELL_NIL) return FALSE;
+    
+    /* Now read the actual list */
+    ListNode = HvGetCell(Hive, ListCell);
+    ASSERT(ListNode);
+    if (ListNode->Type != REG_MULTI_SZ) return FALSE;
+    
+    /* Copy it into a buffer */
+    DependList.Buffer = (PWCHAR)CmpValueToData(Hive, ListNode, &Length);
+    if (!DependList.Buffer) return FALSE;
+    DependList.Length = DependList.MaximumLength = Length - sizeof(UNICODE_NULL);
+    
+    /* And start the recurive sort algorithm */
+    return CmpDoSort(DriverListHead, &DependList);
+}
+
+BOOLEAN
+NTAPI
+CmpOrderGroup(IN PBOOT_DRIVER_NODE StartNode,
+              IN PBOOT_DRIVER_NODE EndNode)
+{
+    PBOOT_DRIVER_NODE CurrentNode, PreviousNode;
+    PLIST_ENTRY ListEntry;
+    
+    /* Base case, nothing to do */
+    if (StartNode == EndNode) return TRUE;
+    
+    /* Loop the nodes */
+    CurrentNode = StartNode;
+    do
+    {
+        /* Save this as the previous node */
+        PreviousNode = CurrentNode;
+        
+        /* And move to the next one */
+        ListEntry = CurrentNode->ListEntry.Link.Flink;
+        CurrentNode = CONTAINING_RECORD(ListEntry,
+                                        BOOT_DRIVER_NODE,
+                                        ListEntry.Link);
+        
+        /* Check if the previous driver had a bigger tag */
+        if (PreviousNode->Tag > CurrentNode->Tag)
+        {
+            /* Check if we need to update the tail */
+            if (CurrentNode == EndNode)
+            {
+                /* Update the tail */
+                ListEntry = CurrentNode->ListEntry.Link.Blink;
+                EndNode = CONTAINING_RECORD(ListEntry,
+                                            BOOT_DRIVER_NODE,
+                                            ListEntry.Link);
+            }
+            
+            /* Remove this driver since we need to move it */
+            RemoveEntryList(&CurrentNode->ListEntry.Link);
+            
+            /* Keep looping until we find a driver with a lower tag than ours */
+            while ((PreviousNode->Tag > CurrentNode->Tag) && (PreviousNode != StartNode))
+            {
+                /* We'll be re-inserted at this spot */
+                ListEntry = PreviousNode->ListEntry.Link.Blink;
+                PreviousNode = CONTAINING_RECORD(ListEntry,
+                                                 BOOT_DRIVER_NODE,
+                                                 ListEntry.Link);
+            }
+            
+            /* Do the insert in the new location */
+            InsertTailList(&PreviousNode->ListEntry.Link, &CurrentNode->ListEntry.Link);
+            
+            /* Update the head, if needed */
+            if (PreviousNode == StartNode) StartNode = CurrentNode;
+        }
+    } while (CurrentNode != EndNode);
+    
+    /* All done */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpResolveDriverDependencies(IN PLIST_ENTRY DriverListHead)
+{
+    PLIST_ENTRY NextEntry;
+    PBOOT_DRIVER_NODE StartNode, EndNode, CurrentNode;
+    
+    /* Loop the list */
+    NextEntry = DriverListHead->Flink;
+    while (NextEntry != DriverListHead)
+    {
+        /* Find the first entry */
+        StartNode = CONTAINING_RECORD(NextEntry,
+                                      BOOT_DRIVER_NODE,
+                                      ListEntry.Link);
+        do
+        {
+            /* Find the last entry */
+            EndNode = CONTAINING_RECORD(NextEntry,
+                                        BOOT_DRIVER_NODE,
+                                        ListEntry.Link);
+            
+            /* Get the next entry */
+            NextEntry = NextEntry->Flink;
+            CurrentNode = CONTAINING_RECORD(NextEntry,
+                                            BOOT_DRIVER_NODE,
+                                            ListEntry.Link);
+            
+            /* If the next entry is back to the top, break out */
+            if (NextEntry == DriverListHead) break;
+            
+            /* Otherwise, check if this entry is equal */
+            if (!RtlEqualUnicodeString(&StartNode->Group,
+                                       &CurrentNode->Group,
+                                       TRUE))
+            {
+                /* It is, so we've detected a cycle, break out */
+                break;
+            }
+        } while (NextEntry != DriverListHead);
+        
+        /* Now we have the correct start and end pointers, so do the sort */
+        CmpOrderGroup(StartNode, EndNode);
+    }
+    
+    /* We're done */
+    return TRUE;
+}
+
+/* EOF */
index 0326e88..3587efe 100644 (file)
@@ -1,12 +1,13 @@
 /*
  * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
  * FILE:            ntoskrnl/config/cmsysini.c
  * PURPOSE:         Configuration Manager - System Initialization Code
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ *                  Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include "ntoskrnl.h"
 #define NDEBUG
@@ -33,7 +34,7 @@ ULONG CmpTraceLevel = 0;
 extern LONG CmpFlushStarveWriters;
 extern BOOLEAN CmFirstTime;
 
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
 
 VOID
 NTAPI
@@ -1574,6 +1575,162 @@ CmInitSystem1(VOID)
     return TRUE;
 }
 
+VOID
+NTAPI
+CmpFreeDriverList(IN PHHIVE Hive,
+                  IN PLIST_ENTRY DriverList)
+{
+    PLIST_ENTRY NextEntry, OldEntry;
+    PBOOT_DRIVER_NODE DriverNode;
+    PAGED_CODE();
+    
+    /* Parse the current list */
+    NextEntry = DriverList->Flink;
+    while (NextEntry != DriverList)
+    {
+        /* Get the driver node */
+        DriverNode = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_NODE, ListEntry.Link);
+        
+        /* Get the next entry now, since we're going to free it later */
+        OldEntry = NextEntry;
+        NextEntry = NextEntry->Flink;
+        
+        /* Was there a name? */
+        if (DriverNode->Name.Buffer)
+        {
+            /* Free it */
+            CmpFree(DriverNode->Name.Buffer, DriverNode->Name.Length);
+        }
+        
+        /* Was there a registry path? */
+        if (DriverNode->ListEntry.RegistryPath.Buffer)
+        {
+            /* Free it */
+            CmpFree(DriverNode->ListEntry.RegistryPath.Buffer, 
+                    DriverNode->ListEntry.RegistryPath.MaximumLength);
+        }
+        
+        /* Was there a file path? */
+        if (DriverNode->ListEntry.FilePath.Buffer)
+        {
+            /* Free it */
+            CmpFree(DriverNode->ListEntry.FilePath.Buffer,
+                    DriverNode->ListEntry.FilePath.MaximumLength);
+        }
+        
+        /* Now free the node, and move on */
+        CmpFree(OldEntry, sizeof(BOOT_DRIVER_NODE));
+    }
+}
+
+PUNICODE_STRING*
+NTAPI
+CmGetSystemDriverList(VOID)
+{
+    LIST_ENTRY DriverList;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    PCM_KEY_BODY KeyBody;
+    PHHIVE Hive;
+    HCELL_INDEX RootCell, ControlCell;
+    HANDLE KeyHandle;
+    UNICODE_STRING KeyName;
+    PLIST_ENTRY NextEntry;
+    ULONG i;
+    PUNICODE_STRING* ServicePath = NULL;
+    BOOLEAN Success, AutoSelect;
+    PBOOT_DRIVER_LIST_ENTRY DriverEntry;
+    PAGED_CODE();
+
+    /* Initialize the driver list */
+    InitializeListHead(&DriverList);
+    
+    /* Open the system hive key */
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+    if (!NT_SUCCESS(Status)) return NULL;
+    
+    /* Reference the key object to get the root hive/cell to access directly */
+    Status = ObReferenceObjectByHandle(KeyHandle,
+                                       KEY_QUERY_VALUE,
+                                       CmpKeyObjectType,
+                                       KernelMode,
+                                       (PVOID*)&KeyBody,
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        NtClose(KeyHandle);
+        return NULL;
+    }
+    
+    /* Do all this under the registry lock */
+    CmpLockRegistryExclusive();
+    
+    /* Get the hive and key cell */
+    Hive = KeyBody->KeyControlBlock->KeyHive;
+    RootCell = KeyBody->KeyControlBlock->KeyCell;
+    
+    /* Open the current control set key */
+    RtlInitUnicodeString(&KeyName, L"Current");
+    ControlCell = CmpFindControlSet(Hive, RootCell, &KeyName, &AutoSelect);
+    if (ControlCell == HCELL_NIL) goto EndPath;
+    
+    /* Find all system drivers */
+    Success = CmpFindDrivers(Hive, ControlCell, SystemLoad, NULL, &DriverList);
+    if (!Success) goto EndPath;
+    
+    /* Sort by group/tag */
+    if (!CmpSortDriverList(Hive, ControlCell, &DriverList)) goto EndPath;
+    
+    /* Remove circular dependencies (cycles) and sort */
+    if (!CmpResolveDriverDependencies(&DriverList)) goto EndPath;
+    
+    /* Loop the list to count drivers */
+    for (i = 0, NextEntry = DriverList.Flink;
+         NextEntry != &DriverList;
+         i++, NextEntry = NextEntry->Flink);
+    
+    /* Allocate the array */
+    ServicePath = ExAllocatePool(NonPagedPool, (i + 1) * sizeof(PUNICODE_STRING));
+    if (!ServicePath) KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 2, 1, 0, 0);
+    
+    /* Loop the driver list */
+    for (i = 0, NextEntry = DriverList.Flink;
+         NextEntry != &DriverList;
+         i++, NextEntry = NextEntry->Flink)
+    {
+        /* Get the entry */
+        DriverEntry = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_LIST_ENTRY, Link);
+
+        /* Allocate the path for the caller and duplicate the registry path */
+        ServicePath[i] = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING));
+        RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                                  &DriverEntry->RegistryPath,
+                                  ServicePath[i]);
+    }
+    
+    /* Terminate the list */
+    ServicePath[i] = NULL;
+    
+EndPath:
+    /* Free the driver list if we had one */
+    if (!IsListEmpty(&DriverList)) CmpFreeDriverList(Hive, &DriverList);
+    
+    /* Unlock the registry */
+    CmpUnlockRegistry();
+    
+    /* Close the key handle and dereference the object, then return the path */
+    ObDereferenceObject(KeyBody);
+    NtClose(KeyHandle);
+    return ServicePath;
+}
+
 VOID
 NTAPI
 CmpLockRegistryExclusive(VOID)
@@ -1771,3 +1928,5 @@ CmShutdownSystem(VOID)
     if (!CmFirstTime) CmpShutdownWorkers();
     CmpDoFlushAll(TRUE);
 }
+
+/* EOF */
index 4880dc0..62f4010 100644 (file)
@@ -1522,6 +1522,40 @@ CmSetLazyFlushState(
     IN BOOLEAN Enable
 );
 
+//
+// Driver List Routines
+//
+PUNICODE_STRING*
+NTAPI
+CmGetSystemDriverList(
+    VOID
+);
+
+BOOLEAN
+NTAPI
+CmpFindDrivers(
+    IN PHHIVE Hive,
+    IN HCELL_INDEX ControlSet,
+    IN SERVICE_LOAD_TYPE LoadType,
+    IN PWSTR BootFileSystem OPTIONAL,
+    IN PLIST_ENTRY DriverListHead
+);
+
+
+BOOLEAN
+NTAPI
+CmpSortDriverList(
+    IN PHHIVE Hive,
+    IN HCELL_INDEX ControlSet,
+    IN PLIST_ENTRY DriverListHead
+);
+
+BOOLEAN
+NTAPI
+CmpResolveDriverDependencies(
+    IN PLIST_ENTRY DriverListHead
+);
+
 //
 // Global variables accessible from all of Cm
 //
index f00a87d..18202bf 100644 (file)
@@ -200,6 +200,7 @@ IopDisplayLoadingMessage(PUNICODE_STRING ServiceName)
     UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS");
 
     if (ExpInTextModeSetup) return;
+    if (!KeLoaderBlock) return;
     RtlUpcaseUnicodeString(ServiceName, ServiceName, FALSE);
     snprintf(TextBuffer, sizeof(TextBuffer),
             "%s%sSystem32\\Drivers\\%wZ%s\n",
@@ -1070,6 +1071,38 @@ IopInitializeBootDrivers(VOID)
     InitializeListHead(&KeLoaderBlock->LoadOrderListHead);
 }
 
+VOID
+FASTCALL
+IopInitializeSystemDrivers(VOID)
+{
+    PUNICODE_STRING *DriverList, *SavedList;
+    
+    /* No system drivers on the boot cd */
+    if (KeLoaderBlock->SetupLdrBlock) return;
+    
+    /* Get the driver list */
+    SavedList = DriverList = CmGetSystemDriverList();
+    ASSERT(DriverList);
+    
+    /* Loop it */
+    while (*DriverList)
+    {
+        /* Load the driver */
+        ZwLoadDriver(*DriverList);
+        
+        /* Free the entry */
+        RtlFreeUnicodeString(*DriverList);
+        ExFreePool(*DriverList);
+        
+        /* Next entry */
+        InbvIndicateProgress();
+        DriverList++;
+    }
+
+    /* Free the list */
+    ExFreePool(SavedList);
+}
+
 /*
  * IopUnloadDriver
  *
@@ -1791,6 +1824,8 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
       cur--;
    }
 
+   IopDisplayLoadingMessage(&ServiceName);
+
    /*
     * Get service type.
     */
diff --git a/reactos/ntoskrnl/io/iomgr/drvrlist.c b/reactos/ntoskrnl/io/iomgr/drvrlist.c
deleted file mode 100644 (file)
index e15aab2..0000000
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * 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 <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;
-
-#define TAG_RTLREGISTRY 'vrqR'
-
-/* GLOBALS ********************************************************************/
-
-LIST_ENTRY GroupListHead = {NULL, NULL};
-LIST_ENTRY ServiceListHead  = {NULL, NULL};
-extern BOOLEAN NoGuiBoot;
-
-VOID
-FASTCALL
-INIT_FUNCTION
-IopDisplayLoadingMessage(PUNICODE_STRING ServiceName);
-
-/* PRIVATE FUNCTIONS **********************************************************/
-
-static NTSTATUS NTAPI
-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(ULONG) &&
-      ValueLength >= (*(PULONG)ValueData + 1) * sizeof(ULONG))
-    {
-      Group = (PSERVICE_GROUP)Context;
-      Group->TagCount = ((PULONG)ValueData)[0];
-      if (Group->TagCount > 0)
-        {
-         if (ValueLength >= (Group->TagCount + 1) * sizeof(ULONG))
-            {
-              Group->TagArray = ExAllocatePool(NonPagedPool, Group->TagCount * sizeof(ULONG));
-             if (Group->TagArray == NULL)
-               {
-                 Group->TagCount = 0;
-                 return STATUS_INSUFFICIENT_RESOURCES;
-               }
-             memcpy(Group->TagArray, (PULONG)ValueData + 1, Group->TagCount * sizeof(ULONG));
-           }
-         else
-           {
-             Group->TagCount = 0;
-             return STATUS_UNSUCCESSFUL;
-           }
-       }
-    }
-  return STATUS_SUCCESS;
-}
-
-static NTSTATUS NTAPI
-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 NTAPI
-IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
-{
-  RTL_QUERY_REGISTRY_TABLE QueryTable[7];
-  PSERVICE Service;
-  NTSTATUS Status;
-  ULONG DefaultTag = MAXULONG;
-
-  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;
-  QueryTable[5].DefaultData = &DefaultTag;
-  QueryTable[5].DefaultType = REG_DWORD;
-  QueryTable[5].DefaultLength = sizeof(DefaultTag);
-
-  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)
-        {
-          ExFreePoolWithTag(Service->ServiceGroup.Buffer, TAG_RTLREGISTRY);
-        }
-      if (Service->ImagePath.Buffer)
-        {
-          ExFreePoolWithTag(Service->ImagePath.Buffer, TAG_RTLREGISTRY);
-        }
-      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 = (USHORT)KeyInfo->NameLength;
-             SubKeyName.MaximumLength = (USHORT)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;
-    PSERVICE CurrentService;
-    PLIST_ENTRY NextEntry, TempEntry;
-
-    DPRINT("IoDestroyDriverList() called\n");
-
-    /* Destroy the Group List */
-    for (NextEntry = GroupListHead.Flink, TempEntry = NextEntry->Flink;
-         NextEntry != &GroupListHead;
-         NextEntry = TempEntry, TempEntry = NextEntry->Flink)
-    {
-        /* Get the entry */
-        CurrentGroup = CONTAINING_RECORD(NextEntry,
-                                         SERVICE_GROUP,
-                                         GroupListEntry);
-
-        /* Remove it from the list */
-        RemoveEntryList(&CurrentGroup->GroupListEntry);
-
-        /* Free buffers */
-        ExFreePool(CurrentGroup->GroupName.Buffer);
-        if (CurrentGroup->TagArray)
-            ExFreePool(CurrentGroup->TagArray);
-        ExFreePool(CurrentGroup);
-    }
-
-    /* Destroy the Service List */
-    for (NextEntry = ServiceListHead.Flink, TempEntry = NextEntry->Flink;
-         NextEntry != &ServiceListHead;
-         NextEntry = TempEntry, TempEntry = NextEntry->Flink)
-    {
-        /* Get the entry */
-        CurrentService = CONTAINING_RECORD(NextEntry,
-                                           SERVICE,
-                                           ServiceListEntry);
-
-        /* Remove it from the list */
-        RemoveEntryList(&CurrentService->ServiceListEntry);
-
-        /* Free buffers */
-        ExFreePool(CurrentService->ServiceName.Buffer);
-        ExFreePool(CurrentService->RegistryPath.Buffer);
-        if (CurrentService->ServiceGroup.Buffer)
-            ExFreePool(CurrentService->ServiceGroup.Buffer);
-        if (CurrentService->ImagePath.Buffer)
-            ExFreePool(CurrentService->ImagePath.Buffer);
-        ExFreePool(CurrentService);
-    }
-
-    DPRINT("IoDestroyDriverList() done\n");
-
-    /* Return success */
-    return STATUS_SUCCESS;
-}
-
-static INIT_FUNCTION NTSTATUS
-IopLoadDriver(PSERVICE Service)
-{
-   NTSTATUS Status = STATUS_UNSUCCESSFUL;
-   PUNICODE_STRING ImagePath = &Service->ImagePath;
-   PWCHAR ImageName;
-   UNICODE_STRING ImageNameU;
-
-   ImageName = wcsrchr(ImagePath->Buffer, L'\\');
-   if (!ImageName)
-       ImageName = ImagePath->Buffer;
-   else
-       ImageName++;
-
-   RtlInitUnicodeString(&ImageNameU, ImageName);
-
-   IopDisplayLoadingMessage(&ImageNameU);
-
-   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;
-   PLIST_ENTRY NextGroupEntry, NextServiceEntry;
-
-   DPRINT("IopInitializeSystemDrivers()\n");
-
-    /* Start looping */
-    for (NextGroupEntry = GroupListHead.Flink;
-         NextGroupEntry != &GroupListHead;
-         NextGroupEntry = NextGroupEntry->Flink)
-    {
-        /* Get the entry */
-        CurrentGroup = CONTAINING_RECORD(NextGroupEntry,
-                                         SERVICE_GROUP,
-                                         GroupListEntry);
-
-        DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
-
-        /* Load all drivers with a valid tag */
-        for (i = 0; i < CurrentGroup->TagCount; i++)
-        {
-            /* Start looping */
-            for (NextServiceEntry = ServiceListHead.Flink;
-                 NextServiceEntry != &ServiceListHead;
-                 NextServiceEntry = NextServiceEntry->Flink)
-            {
-                /* Get the entry */
-                CurrentService = CONTAINING_RECORD(NextServiceEntry,
-                                                   SERVICE,
-                                                   ServiceListEntry);
-
-                if ((!RtlCompareUnicodeString(&CurrentGroup->GroupName,
-                                             &CurrentService->ServiceGroup,
-                                             TRUE)) &&
-                       (CurrentService->Start == SERVICE_SYSTEM_START) &&
-                           (CurrentService->Tag == CurrentGroup->TagArray[i]))
-
-                {
-                    DPRINT("  Path: %wZ\n", &CurrentService->RegistryPath);
-                    Status = IopLoadDriver(CurrentService);
-                    InbvIndicateProgress();
-                }
-            }
-        }
-
-        /* Load all drivers without a tag or with an invalid tag */
-        for (NextServiceEntry = ServiceListHead.Flink;
-             NextServiceEntry != &ServiceListHead;
-             NextServiceEntry = NextServiceEntry->Flink)
-        {
-            /* Get the entry */
-            CurrentService = CONTAINING_RECORD(NextServiceEntry,
-                                               SERVICE,
-                                               ServiceListEntry);
-
-            if ((!RtlCompareUnicodeString(&CurrentGroup->GroupName,
-                                         &CurrentService->ServiceGroup,
-                                         TRUE)) &&
-                   (CurrentService->Start == 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);
-                    InbvIndicateProgress();
-                }
-                
-            }
-        }
-    }
-
-    DPRINT("IopInitializeSystemDrivers() done\n");
-}
index c799966..e52f2fe 100644 (file)
@@ -493,9 +493,6 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     /* Setup the group cache */
     if (!NT_SUCCESS(PiInitCacheGroupInformation())) return FALSE;
 
-    /* Create the group driver list */
-    IoCreateDriverList();
-
     /* Load boot start drivers */
     IopInitializeBootDrivers();
 
@@ -533,9 +530,6 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     IopInitializeSystemDrivers();
     PnpSystemInit = TRUE;
 
-    /* Destroy the group driver list */
-    IoDestroyDriverList();
-
     /* Reinitialize drivers that requested it */
     IopReinitializeDrivers();
 
index b6ed182..a349f88 100644 (file)
                        <file>device.c</file>
                        <file>deviface.c</file>
                        <file>driver.c</file>
-                       <file>drvrlist.c</file>
                        <file>error.c</file>
                        <file>file.c</file>
                        <file>iocomp.c</file>