- Added support for NTLDR style freeloader GUI. To enable, edit freeldr.ini and add:
[reactos.git] / reactos / ntoskrnl / io / driver.c
index a95a142..862d982 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/io/driver.c
 #include <internal/debug.h>
 
 /* ke/main.c */
-extern LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
+extern LOADER_PARAMETER_BLOCK KeLoaderBlock;
 extern ULONG KeTickCount;
 extern BOOLEAN SetupMode;
-
-NTSTATUS
-LdrProcessModule(PVOID ModuleLoadBase,
-                PUNICODE_STRING ModuleName,
-                PMODULE_OBJECT *ModuleObject);
+extern BOOLEAN NoGuiBoot;
 
 typedef struct _SERVICE_GROUP
 {
@@ -72,15 +67,50 @@ static LIST_ENTRY GroupListHead = {NULL, NULL};
 static LIST_ENTRY ServiceListHead  = {NULL, NULL};
 
 static UNICODE_STRING IopHardwareDatabaseKey =
-   ROS_STRING_INITIALIZER(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
+   RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
 
-POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
+POBJECT_TYPE IoDriverObjectType = NULL;
 
 /* DECLARATIONS ***************************************************************/
 
 VOID STDCALL
 IopDeleteDriver(PVOID ObjectBody);
 
+NTSTATUS
+LdrProcessModule(PVOID ModuleLoadBase,
+                PUNICODE_STRING ModuleName,
+                PLDR_DATA_TABLE_ENTRY *ModuleObject);
+
+VOID 
+FASTCALL
+INIT_FUNCTION
+IopDisplayLoadingMessage(PVOID ServiceName, 
+                         BOOLEAN Unicode);
+
+static VOID INIT_FUNCTION
+MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length);
+
+NTSTATUS FASTCALL INIT_FUNCTION
+IopInitializeBuiltinDriver(
+   PDEVICE_NODE ModuleDeviceNode,
+   PVOID ModuleLoadBase,
+   PCHAR FileName,
+   ULONG ModuleLength);
+
+static INIT_FUNCTION NTSTATUS
+IopLoadDriver(PSERVICE Service);
+
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, IopInitDriverImplementation)
+#pragma alloc_text(INIT, IopDisplayLoadingMessage)
+#pragma alloc_text(INIT, IoCreateDriverList)
+#pragma alloc_text(INIT, IoDestroyDriverList)
+#pragma alloc_text(INIT, MiFreeBootDriverMemory)
+#pragma alloc_text(INIT, IopInitializeBuiltinDriver)
+#pragma alloc_text(INIT, IopLoadDriver)
+#endif
+
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 VOID 
@@ -90,7 +120,7 @@ IopInitDriverImplementation(VOID)
    OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
    UNICODE_STRING Name;
 
-   DPRINT1("Creating Registry Object Type\n");
+   DPRINT("Creating Registry Object Type\n");
   
    /* Initialize the Driver object type  */
    RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
@@ -130,7 +160,7 @@ IopDeleteDriver(PVOID ObjectBody)
    KIRQL OldIrql;
    PPRIVATE_DRIVER_EXTENSIONS DriverExtension, NextDriverExtension;
 
-   DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody);
+   DPRINT("IopDeleteDriver(ObjectBody 0x%p)\n", ObjectBody);
 
    ExFreePool(Object->DriverExtension);
    ExFreePool(Object->DriverName.Buffer);
@@ -170,13 +200,16 @@ IopGetDriverObject(
       /* We don't know which DriverObject we have to open */
       return STATUS_INVALID_PARAMETER_2;
 
+   DriverName.Buffer = NameBuffer;
+   DriverName.Length = 0;
+   DriverName.MaximumLength = sizeof(NameBuffer);
+
    if (FileSystem == TRUE)
-      wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
+      RtlAppendUnicodeToString(&DriverName, FILESYSTEM_ROOT_NAME);
    else
-      wcscpy(NameBuffer, DRIVER_ROOT_NAME);
-   wcscat(NameBuffer, ServiceName->Buffer);
+      RtlAppendUnicodeToString(&DriverName, DRIVER_ROOT_NAME);
+   RtlAppendUnicodeStringToString(&DriverName, ServiceName);
 
-   RtlInitUnicodeString(&DriverName, NameBuffer);
    DPRINT("Driver name: '%wZ'\n", &DriverName);
 
    /* Initialize ObjectAttributes for driver object */
@@ -240,7 +273,7 @@ IopCreateDriverObject(
       RtlInitUnicodeString(&DriverName, NameBuffer);
       DPRINT("Driver name: '%wZ'\n", &DriverName);
 
-      Buffer = (PWSTR)ExAllocatePool(NonPagedPool, DriverName.Length);
+      Buffer = (PWSTR)ExAllocatePool(PagedPool, DriverName.Length + sizeof(WCHAR));
       /* If we don't success, it is not a problem. Our driver
        * object will not have associated driver name... */
    }
@@ -313,8 +346,10 @@ IopCreateDriverObject(
       if (!Object->DriverName.Buffer)
       {
          Object->DriverName.Buffer = Buffer;
-         Object->DriverName.Length = Object->DriverName.MaximumLength = DriverName.Length;
+         Object->DriverName.Length = DriverName.Length;
+         Object->DriverName.MaximumLength = DriverName.Length + sizeof(WCHAR);
          RtlCopyMemory(Object->DriverName.Buffer, DriverName.Buffer, DriverName.Length);
+         Object->DriverName.Buffer[Object->DriverName.Length / sizeof(WCHAR)] = L'\0';
       }
       else
          ExFreePool(Buffer);
@@ -337,8 +372,8 @@ INIT_FUNCTION
 IopDisplayLoadingMessage(PVOID ServiceName, 
                          BOOLEAN Unicode)
 {
-    if (SetupMode) return;
     CHAR TextBuffer[256];
+    if (SetupMode || !NoGuiBoot) return;
     if (Unicode) 
     {
         sprintf(TextBuffer, "Loading %S...\n", (PWCHAR)ServiceName);
@@ -427,14 +462,14 @@ IopNormalizeImagePath(
 NTSTATUS FASTCALL
 IopLoadServiceModule(
    IN PUNICODE_STRING ServiceName,
-   OUT PMODULE_OBJECT *ModuleObject)
+   OUT PLDR_DATA_TABLE_ENTRY *ModuleObject)
 {
    RTL_QUERY_REGISTRY_TABLE QueryTable[3];
    ULONG ServiceStart;
    UNICODE_STRING ServiceImagePath;
    NTSTATUS Status;
 
-   DPRINT("IopLoadServiceModule(%wZ, %x)\n", ServiceName, ModuleObject);
+   DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject);
 
    /*
     * Get information about the service.
@@ -461,7 +496,7 @@ IopLoadServiceModule(
       return Status;
    }
    
-   IopDisplayLoadingMessage(ServiceName->Buffer, TRUE);
+   //IopDisplayLoadingMessage(ServiceName->Buffer, TRUE);
 
    /*
     * Normalize the image path for all later processing.
@@ -525,6 +560,9 @@ IopLoadServiceModule(
                break;
             }
          }
+         if (!NT_SUCCESS(Status))
+            /* Try to load it. It may just have been installed by PnP manager */
+            Status = LdrLoadModule(&ServiceImagePath, ModuleObject);
       }
 
       /*
@@ -586,7 +624,7 @@ IopLoadServiceModule(
 NTSTATUS FASTCALL
 IopInitializeDriverModule(
    IN PDEVICE_NODE DeviceNode,
-   IN PMODULE_OBJECT ModuleObject,
+   IN PLDR_DATA_TABLE_ENTRY ModuleObject,
    IN PUNICODE_STRING ServiceName,
    IN BOOLEAN FileSystemDriver,
    OUT PDRIVER_OBJECT *DriverObject)
@@ -620,8 +658,8 @@ IopInitializeDriverModule(
       ServiceName,
       0,
       FileSystemDriver,
-      ModuleObject->Base,
-      ModuleObject->Length);
+      ModuleObject->DllBase,
+      ModuleObject->SizeOfImage);
 
    if (!NT_SUCCESS(Status))
    {
@@ -668,7 +706,7 @@ IopAttachFilterDriversCallback(
    PDEVICE_NODE DeviceNode = Context;
    UNICODE_STRING ServiceName;
    PWCHAR Filters;
-   PMODULE_OBJECT ModuleObject;
+   PLDR_DATA_TABLE_ENTRY ModuleObject;
    PDRIVER_OBJECT DriverObject;
    NTSTATUS Status;
 
@@ -824,7 +862,7 @@ IopGetGroupOrderList(PWSTR ValueName,
 {
   PSERVICE_GROUP Group;
 
-  DPRINT("IopGetGroupOrderList(%S, %x, %x, %x, %x, %x)\n",
+  DPRINT("IopGetGroupOrderList(%S, %x, 0x%p, %x, 0x%p, 0x%p)\n",
          ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
 
   if (ValueType == REG_BINARY &&
@@ -882,7 +920,7 @@ IopCreateGroupListEntry(PWSTR ValueName,
 
       RtlZeroMemory(Group, sizeof(SERVICE_GROUP));
 
-      if (!RtlpCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData, NonPagedPool))
+      if (!RtlCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData))
        {
          ExFreePool(Group);
          return(STATUS_INSUFFICIENT_RESOURCES);
@@ -1019,7 +1057,7 @@ IoCreateDriverList(VOID)
   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
   PKEY_BASIC_INFORMATION KeyInfo = NULL;
   OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING ServicesKeyName;
+  UNICODE_STRING ServicesKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
   UNICODE_STRING SubKeyName;
   HANDLE KeyHandle;
   NTSTATUS Status;
@@ -1050,9 +1088,6 @@ IoCreateDriverList(VOID)
     return(Status);
 
   /* Enumerate services and create the service list */
-  RtlRosInitUnicodeStringFromLiteral(&ServicesKeyName,
-                      L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
-
   InitializeObjectAttributes(&ObjectAttributes,
                             &ServicesKeyName,
                             OBJ_CASE_INSENSITIVE,
@@ -1116,44 +1151,32 @@ IoCreateDriverList(VOID)
 NTSTATUS INIT_FUNCTION
 IoDestroyDriverList(VOID)
 {
-  PLIST_ENTRY GroupEntry;
-  PLIST_ENTRY ServiceEntry;
-  PSERVICE_GROUP CurrentGroup;
-  PSERVICE CurrentService;
+  PSERVICE_GROUP CurrentGroup, tmp1;
+  PSERVICE CurrentService, tmp2;
 
   DPRINT("IoDestroyDriverList() called\n");
 
   /* Destroy group list */
-  GroupEntry = GroupListHead.Flink;
-  while (GroupEntry != &GroupListHead)
+  LIST_FOR_EACH_SAFE(CurrentGroup, tmp1, &GroupListHead, SERVICE_GROUP, GroupListEntry)
     {
-      CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
-
       ExFreePool(CurrentGroup->GroupName.Buffer);
-      RemoveEntryList(GroupEntry);
+      RemoveEntryList(&CurrentGroup->GroupListEntry);
       if (CurrentGroup->TagArray)
         {
          ExFreePool(CurrentGroup->TagArray);
        }
       ExFreePool(CurrentGroup);
-
-      GroupEntry = GroupListHead.Flink;
     }
 
   /* Destroy service list */
-  ServiceEntry = ServiceListHead.Flink;
-  while (ServiceEntry != &ServiceListHead)
+  LIST_FOR_EACH_SAFE(CurrentService, tmp2, &ServiceListHead, SERVICE, ServiceListEntry)
     {
-      CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
-
       ExFreePool(CurrentService->ServiceName.Buffer);
       ExFreePool(CurrentService->RegistryPath.Buffer);
       ExFreePool(CurrentService->ServiceGroup.Buffer);
       ExFreePool(CurrentService->ImagePath.Buffer);
-      RemoveEntryList(ServiceEntry);
+      RemoveEntryList(&CurrentService->ServiceListEntry);
       ExFreePool(CurrentService);
-
-      ServiceEntry = ServiceListHead.Flink;
     }
 
   DPRINT("IoDestroyDriverList() done\n");
@@ -1161,7 +1184,7 @@ IoDestroyDriverList(VOID)
   return(STATUS_SUCCESS);
 }
 
-VOID STATIC INIT_FUNCTION
+static VOID INIT_FUNCTION
 MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
 {
    ULONG i;
@@ -1185,7 +1208,7 @@ IopInitializeBuiltinDriver(
    PCHAR FileName,
    ULONG ModuleLength)
 {
-   PMODULE_OBJECT ModuleObject;
+   PLDR_DATA_TABLE_ENTRY ModuleObject;
    PDEVICE_NODE DeviceNode;
    PDRIVER_OBJECT DriverObject;
    NTSTATUS Status;
@@ -1210,7 +1233,7 @@ IopInitializeBuiltinDriver(
       Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
       if (!NT_SUCCESS(Status))
       {
-         CPRINT("Driver load failed, status (%x)\n", Status);
+         CPRINT("Driver '%s' load failed, status (%x)\n", FileName, Status);
          return(Status);
       }
    } else
@@ -1240,7 +1263,7 @@ IopInitializeBuiltinDriver(
    {
       if (ModuleDeviceNode == NULL)
          IopFreeDeviceNode(DeviceNode);
-      CPRINT("Driver load failed, status (%x)\n", Status);
+      CPRINT("Driver '%s' load failed, status (%x)\n", FileName, Status);
       return Status;
    }
 
@@ -1269,7 +1292,7 @@ IopInitializeBuiltinDriver(
    {
       if (ModuleDeviceNode == NULL)
          IopFreeDeviceNode(DeviceNode);
-      CPRINT("Driver load failed, status (%x)\n", Status);
+      CPRINT("Driver '%s' load failed, status (%x)\n", FileName, Status);
       return Status;
    }
 
@@ -1362,7 +1385,7 @@ IopInitializeBootDrivers(VOID)
    if (BootDriverCount == 0)
    {
       DbgPrint("No boot drivers available.\n");
-      KEBUGCHECK(0);
+      KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
    }
 }
 
@@ -1421,8 +1444,6 @@ IopLoadDriver(PSERVICE Service)
 VOID FASTCALL
 IopInitializeSystemDrivers(VOID)
 {
-   PLIST_ENTRY GroupEntry;
-   PLIST_ENTRY ServiceEntry;
    PSERVICE_GROUP CurrentGroup;
    PSERVICE CurrentService;
    NTSTATUS Status;
@@ -1430,21 +1451,15 @@ IopInitializeSystemDrivers(VOID)
 
    DPRINT("IopInitializeSystemDrivers()\n");
 
-   GroupEntry = GroupListHead.Flink;
-   while (GroupEntry != &GroupListHead)
+   LIST_FOR_EACH(CurrentGroup, &GroupListHead, SERVICE_GROUP, GroupListEntry)
    {
-      CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
-
       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)
+         LIST_FOR_EACH(CurrentService, &ServiceListHead, SERVICE, ServiceListEntry)
          {
-            CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
-
             if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
                                          &CurrentService->ServiceGroup, TRUE) == 0) &&
                (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/) &&
@@ -1453,15 +1468,12 @@ IopInitializeSystemDrivers(VOID)
               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)
+      LIST_FOR_EACH(CurrentService, &ServiceListHead, SERVICE, ServiceListEntry)
       {
-         CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
          if ((RtlCompareUnicodeString(&CurrentGroup->GroupName,
                                       &CurrentService->ServiceGroup, TRUE) == 0) &&
             (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/))
@@ -1479,10 +1491,8 @@ IopInitializeSystemDrivers(VOID)
                Status = IopLoadDriver(CurrentService);
            }
         }
-         ServiceEntry = ServiceEntry->Flink;
       }
 
-      GroupEntry = GroupEntry->Flink;
    }
 
    DPRINT("IopInitializeSystemDrivers() done\n");
@@ -1517,12 +1527,14 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
    UNICODE_STRING ServiceName;
    UNICODE_STRING ObjectName;
    PDRIVER_OBJECT DriverObject;
-   PMODULE_OBJECT ModuleObject;
+   PLDR_DATA_TABLE_ENTRY ModuleObject;
    NTSTATUS Status;
    LPWSTR Start;
 
    DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName, UnloadPnpDrivers);
 
+   PAGED_CODE();
+
    /*
     * Get the service name from the registry key name
     */
@@ -1541,7 +1553,7 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
 
    ObjectName.Length = (wcslen(Start) + 8) * sizeof(WCHAR);
    ObjectName.MaximumLength = ObjectName.Length + sizeof(WCHAR);
-   ObjectName.Buffer = ExAllocatePool(NonPagedPool, ObjectName.MaximumLength);
+   ObjectName.Buffer = ExAllocatePool(PagedPool, ObjectName.MaximumLength);
    wcscpy(ObjectName.Buffer, L"\\Driver\\");
    memcpy(ObjectName.Buffer + 8, Start, (ObjectName.Length - 8) * sizeof(WCHAR));
    ObjectName.Buffer[ObjectName.Length/sizeof(WCHAR)] = 0;
@@ -1659,16 +1671,16 @@ IopReinitializeDrivers(VOID)
   KeAcquireSpinLock(&DriverReinitListLock,
                    &Irql);
 
-  if (DriverReinitTailEntry == NULL)
-  {
-    KeReleaseSpinLock(&DriverReinitListLock,
-                     Irql);
-    return;
-  }
+  Entry = DriverReinitTailEntry;
 
   KeReleaseSpinLock(&DriverReinitListLock,
                    Irql);
 
+  if (Entry == NULL)
+  {
+    return;
+  }
+
   for (;;)
   {
     Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
@@ -1848,12 +1860,12 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
    RTL_QUERY_REGISTRY_TABLE QueryTable[3];
    UNICODE_STRING ImagePath;
    UNICODE_STRING ServiceName;
-   UNICODE_STRING CapturedDriverServiceName;
+   UNICODE_STRING CapturedDriverServiceName = {0};
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;
    ULONG Type;
    PDEVICE_NODE DeviceNode;
-   PMODULE_OBJECT ModuleObject;
+   PLDR_DATA_TABLE_ENTRY ModuleObject;
    PDRIVER_OBJECT DriverObject;
    WCHAR *cur;
 
@@ -1874,11 +1886,9 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
    }
 #endif
 
-   Status = RtlCaptureUnicodeString(&CapturedDriverServiceName,
-                                    PreviousMode,
-                                    PagedPool,
-                                    FALSE,
-                                    DriverServiceName);
+   Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName,
+                                         PreviousMode,
+                                         DriverServiceName);
    if (!NT_SUCCESS(Status))
    {
       return Status;
@@ -1991,7 +2001,7 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
     * Set a service name for the device node
     */
 
-   RtlpCreateUnicodeString(&DeviceNode->ServiceName, ServiceName.Buffer, NonPagedPool);
+   RtlCreateUnicodeString(&DeviceNode->ServiceName, ServiceName.Buffer);
 
    /*
     * Initialize the driver module
@@ -2017,9 +2027,8 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
    Status = IopStartDevice(DeviceNode);
 
 ReleaseCapturedString:
-   RtlReleaseCapturedUnicodeString(&CapturedDriverServiceName,
-                                   PreviousMode,
-                                   FALSE);
+   ReleaseCapturedUnicodeString(&CapturedDriverServiceName,
+                                PreviousMode);
 
    return Status;
 }