[NTOS:IO]
[reactos.git] / reactos / ntoskrnl / io / iomgr / driver.c
index fbe571b..3ea220e 100644 (file)
@@ -16,6 +16,8 @@
 
 /* GLOBALS ********************************************************************/
 
+ERESOURCE IopDriverLoadResource;
+
 LIST_ENTRY DriverReinitListHead;
 KSPIN_LOCK DriverReinitListLock;
 PLIST_ENTRY DriverReinitTailEntry;
@@ -113,6 +115,7 @@ IopGetDriverObject(
     DPRINT("IopGetDriverObject(%p '%wZ' %x)\n",
            DriverObject, ServiceName, FileSystem);
 
+    ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource));
     *DriverObject = NULL;
 
     /* Create ModuleName string */
@@ -124,7 +127,7 @@ IopGetDriverObject(
     DriverName.Length = 0;
     DriverName.MaximumLength = sizeof(NameBuffer);
 
-    if (FileSystem == TRUE)
+    if (FileSystem != FALSE)
         RtlAppendUnicodeToString(&DriverName, FILESYSTEM_ROOT_NAME);
     else
         RtlAppendUnicodeToString(&DriverName, DRIVER_ROOT_NAME);
@@ -194,7 +197,6 @@ IopSuffixUnicodeString(
  */
 VOID
 FASTCALL
-INIT_FUNCTION
 IopDisplayLoadingMessage(PUNICODE_STRING ServiceName)
 {
     CHAR TextBuffer[256];
@@ -239,39 +241,44 @@ IopNormalizeImagePath(
          PUNICODE_STRING ImagePath,
     _In_ PUNICODE_STRING ServiceName)
 {
+    UNICODE_STRING SystemRootString = RTL_CONSTANT_STRING(L"\\SystemRoot\\");
+    UNICODE_STRING DriversPathString = RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\drivers\\");
+    UNICODE_STRING DotSysString = RTL_CONSTANT_STRING(L".sys");
     UNICODE_STRING InputImagePath;
 
     DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
 
-    RtlCopyMemory(&InputImagePath,
-                  ImagePath,
-                  sizeof(UNICODE_STRING));
-
+    InputImagePath = *ImagePath;
     if (InputImagePath.Length == 0)
     {
         ImagePath->Length = 0;
-        ImagePath->MaximumLength =
-            (33 * sizeof(WCHAR)) + ServiceName->Length + sizeof(UNICODE_NULL);
-        ImagePath->Buffer = ExAllocatePool(NonPagedPool,
-                                           ImagePath->MaximumLength);
+        ImagePath->MaximumLength = DriversPathString.Length +
+                                   ServiceName->Length +
+                                   DotSysString.Length +
+                                   sizeof(UNICODE_NULL);
+        ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                                  ImagePath->MaximumLength,
+                                                  TAG_IO);
         if (ImagePath->Buffer == NULL)
             return STATUS_NO_MEMORY;
 
-        RtlAppendUnicodeToString(ImagePath, L"\\SystemRoot\\system32\\drivers\\");
+        RtlCopyUnicodeString(ImagePath, &DriversPathString);
         RtlAppendUnicodeStringToString(ImagePath, ServiceName);
-        RtlAppendUnicodeToString(ImagePath, L".sys");
+        RtlAppendUnicodeStringToString(ImagePath, &DotSysString);
     }
     else if (InputImagePath.Buffer[0] != L'\\')
     {
         ImagePath->Length = 0;
-        ImagePath->MaximumLength =
-            12 * sizeof(WCHAR) + InputImagePath.Length + sizeof(UNICODE_NULL);
-        ImagePath->Buffer = ExAllocatePool(NonPagedPool,
-                                           ImagePath->MaximumLength);
+        ImagePath->MaximumLength = SystemRootString.Length +
+                                   InputImagePath.Length +
+                                   sizeof(UNICODE_NULL);
+        ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                                  ImagePath->MaximumLength,
+                                                  TAG_IO);
         if (ImagePath->Buffer == NULL)
             return STATUS_NO_MEMORY;
 
-        RtlAppendUnicodeToString(ImagePath, L"\\SystemRoot\\");
+        RtlCopyUnicodeString(ImagePath, &SystemRootString);
         RtlAppendUnicodeStringToString(ImagePath, &InputImagePath);
 
         /* Free caller's string */
@@ -308,6 +315,7 @@ IopLoadServiceModule(
     HANDLE CCSKey, ServiceKey;
     PVOID BaseAddress;
 
+    ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource));
     ASSERT(ServiceName->Length);
     DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject);
 
@@ -319,8 +327,7 @@ IopLoadServiceModule(
         ServiceStart = 0;
 
         /* IopNormalizeImagePath will do all of the work for us if we give it an empty string */
-        ServiceImagePath.Length = ServiceImagePath.MaximumLength = 0;
-        ServiceImagePath.Buffer = NULL;
+        RtlInitEmptyUnicodeString(&ServiceImagePath, NULL, 0);
     }
     else
     {
@@ -486,7 +493,7 @@ IopInitializeDriverModule(
     /* Create ModuleName string */
     if (ServiceName && ServiceName->Length > 0)
     {
-        if (FileSystemDriver == TRUE)
+        if (FileSystemDriver != FALSE)
             wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME);
         else
             wcscpy(NameBuffer, DRIVER_ROOT_NAME);
@@ -563,6 +570,8 @@ IopAttachFilterDriversCallback(
         ServiceName.MaximumLength =
         ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR);
 
+        KeEnterCriticalRegion();
+        ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
         Status = IopGetDriverObject(&DriverObject,
                                     &ServiceName,
                                     FALSE);
@@ -571,7 +580,11 @@ IopAttachFilterDriversCallback(
             /* Load and initialize the filter driver */
             Status = IopLoadServiceModule(&ServiceName, &ModuleObject);
             if (!NT_SUCCESS(Status))
+            {
+                ExReleaseResourceLite(&IopDriverLoadResource);
+                KeLeaveCriticalRegion();
                 return Status;
+            }
 
             Status = IopInitializeDriverModule(DeviceNode,
                                                ModuleObject,
@@ -579,9 +592,16 @@ IopAttachFilterDriversCallback(
                                                FALSE,
                                                &DriverObject);
             if (!NT_SUCCESS(Status))
+            {
+                ExReleaseResourceLite(&IopDriverLoadResource);
+                KeLeaveCriticalRegion();
                 return Status;
+            }
         }
 
+        ExReleaseResourceLite(&IopDriverLoadResource);
+        KeLeaveCriticalRegion();
+
         Status = IopInitializeDevice(DeviceNode, DriverObject);
 
         /* Remove extra reference */
@@ -854,6 +874,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry)
     PLDR_DATA_TABLE_ENTRY LdrEntry;
     PLIST_ENTRY NextEntry;
     UNICODE_STRING ServiceName;
+    BOOLEAN Success;
 
     /*
      * Display 'Loading XXX...' message
@@ -877,7 +898,12 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry)
     /*
      * Strip the file extension from ServiceName
      */
-    RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath);
+    Success = RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath);
+    if (!Success)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
     FileExtension = wcsrchr(ServiceName.Buffer, '.');
     if (FileExtension != NULL)
     {
@@ -913,7 +939,7 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry)
 
         NextEntry = NextEntry->Flink;
     }
-    NT_ASSERT(NextEntry != &PsLoadedModuleList);
+    ASSERT(NextEntry != &PsLoadedModuleList);
 
     /*
      * Initialize the driver
@@ -926,7 +952,6 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry)
 
     if (!NT_SUCCESS(Status))
     {
-        IopFreeDeviceNode(DeviceNode);
         return Status;
     }
 
@@ -990,7 +1015,6 @@ IopInitializeBootDrivers(VOID)
     if (!NT_SUCCESS(Status))
     {
         /* Fail */
-        IopFreeDeviceNode(DeviceNode);
         return;
     }
 
@@ -999,7 +1023,6 @@ IopInitializeBootDrivers(VOID)
     if (!NT_SUCCESS(Status))
     {
         /* Fail */
-        IopFreeDeviceNode(DeviceNode);
         ObDereferenceObject(DriverObject);
         return;
     }
@@ -1009,7 +1032,6 @@ IopInitializeBootDrivers(VOID)
     if (!NT_SUCCESS(Status))
     {
         /* Fail */
-        IopFreeDeviceNode(DeviceNode);
         ObDereferenceObject(DriverObject);
         return;
     }
@@ -1357,7 +1379,7 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
         /* Set the unload invoked flag and call the unload routine */
         DriverObject->Flags |= DRVO_UNLOAD_INVOKED;
         Status = IopLoadUnloadDriver(NULL, &DriverObject);
-        NT_ASSERT(Status == STATUS_SUCCESS);
+        ASSERT(Status == STATUS_SUCCESS);
 
         /* Mark the driver object temporary, so it could be deleted later */
         ObMakeTemporaryObject(DriverObject);
@@ -1479,7 +1501,7 @@ try_again:
         /* Create a random name and set up the string*/
         NameLength = (USHORT)swprintf(NameBuffer,
                                       DRIVER_ROOT_NAME L"%08u",
-                                      KeTickCount);
+                                      KeTickCount.LowPart);
         LocalDriverName.Length = NameLength * sizeof(WCHAR);
         LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
         LocalDriverName.Buffer = NameBuffer;
@@ -1494,7 +1516,7 @@ try_again:
     ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);
     InitializeObjectAttributes(&ObjectAttributes,
                                &LocalDriverName,
-                               OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
+                               OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL);
 
@@ -1857,7 +1879,7 @@ IopLoadUnloadDriverWorker(
 {
     PLOAD_UNLOAD_PARAMS LoadParams = Parameter;
 
-    NT_ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess);
+    ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess);
     LoadParams->Status = IopLoadUnloadDriver(LoadParams->RegistryPath,
                                              &LoadParams->DriverObject);
     KeSetEvent(&LoadParams->Event, 0, FALSE);
@@ -1971,14 +1993,16 @@ IopLoadUnloadDriver(
     DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
     DPRINT("Type: %lx\n", Type);
 
+    KeEnterCriticalRegion();
+    ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
     /*
      * Get existing DriverObject pointer (in case the driver
      * has already been loaded and initialized).
      */
     Status = IopGetDriverObject(DriverObject,
                                 &ServiceName,
-                                (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
-                                 Type == 8 /* SERVICE_RECOGNIZER_DRIVER */));
+                                (Type == SERVICE_FILE_SYSTEM_DRIVER ||
+                                 Type == SERVICE_RECOGNIZER_DRIVER));
 
     if (!NT_SUCCESS(Status))
     {
@@ -1990,6 +2014,8 @@ IopLoadUnloadDriver(
         if (!NT_SUCCESS(Status))
         {
             DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
+            ExReleaseResourceLite(&IopDriverLoadResource);
+            KeLeaveCriticalRegion();
             return Status;
         }
 
@@ -2000,6 +2026,8 @@ IopLoadUnloadDriver(
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
+            ExReleaseResourceLite(&IopDriverLoadResource);
+            KeLeaveCriticalRegion();
             MmUnloadSystemImage(ModuleObject);
             return Status;
         }
@@ -2009,23 +2037,30 @@ IopLoadUnloadDriver(
         Status = IopInitializeDriverModule(DeviceNode,
                                            ModuleObject,
                                            &DeviceNode->ServiceName,
-                                           (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
-                                            Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
+                                           (Type == SERVICE_FILE_SYSTEM_DRIVER ||
+                                            Type == SERVICE_RECOGNIZER_DRIVER),
                                            DriverObject);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status);
+            ExReleaseResourceLite(&IopDriverLoadResource);
+            KeLeaveCriticalRegion();
             MmUnloadSystemImage(ModuleObject);
-            IopFreeDeviceNode(DeviceNode);
             return Status;
         }
 
+        ExReleaseResourceLite(&IopDriverLoadResource);
+        KeLeaveCriticalRegion();
+
         /* Initialize and start device */
         IopInitializeDevice(DeviceNode, *DriverObject);
         Status = IopStartDevice(DeviceNode);
     }
     else
     {
+        ExReleaseResourceLite(&IopDriverLoadResource);
+        KeLeaveCriticalRegion();
+
         DPRINT("DriverObject already exist in ObjectManager\n");
         Status = STATUS_IMAGE_ALREADY_LOADED;