IopInvalidDeviceRequest must return STATUS_INVALID_DEVICE_REQUEST.
[reactos.git] / reactos / ntoskrnl / io / driver.c
index 3259c70..7378a2c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: driver.c,v 1.39 2004/03/27 19:41:32 navaraf Exp $
+/* $Id: driver.c,v 1.51 2004/09/07 11:48:16 ekohl Exp $
  *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
 
 /* INCLUDES *******************************************************************/
 
-#include <limits.h>
-#include <ddk/ntddk.h>
-#include <internal/io.h>
-#include <internal/po.h>
-#include <internal/ldr.h>
-#include <internal/id.h>
-#include <internal/pool.h>
-#include <internal/se.h>
-#include <internal/mm.h>
-#include <internal/ke.h>
-#include <internal/kd.h>
-#include <rosrtl/string.h>
-
-#include <roscfg.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
@@ -83,26 +69,19 @@ POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
 #define TAG_DRIVER             TAG('D', 'R', 'V', 'R')
 #define TAG_DRIVER_EXTENSION   TAG('D', 'R', 'V', 'E')
 
-#define DRIVER_REGISTRY_KEY_BASENAME  L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
-
-/* PRIVATE FUNCTIONS **********************************************************/
+/* DECLARATIONS ***************************************************************/
 
 NTSTATUS STDCALL
 IopCreateDriver(
    PVOID ObjectBody,
    PVOID Parent,
    PWSTR RemainingPath,
-   POBJECT_ATTRIBUTES ObjectAttributes)
-{
-   DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
-      ObjectBody, Parent, RemainingPath);
-
-   if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
-      return STATUS_UNSUCCESSFUL;
+   POBJECT_ATTRIBUTES ObjectAttributes);
 
-   return STATUS_SUCCESS;
-}
+VOID STDCALL
+IopDeleteDriver(PVOID ObjectBody);
 
+/* PRIVATE FUNCTIONS **********************************************************/
 
 VOID INIT_FUNCTION
 IopInitDriverImplementation(VOID)
@@ -119,7 +98,7 @@ IopInitDriverImplementation(VOID)
    IoDriverObjectType->Dump = NULL;
    IoDriverObjectType->Open = NULL;
    IoDriverObjectType->Close = NULL;
-   IoDriverObjectType->Delete = NULL;
+   IoDriverObjectType->Delete = IopDeleteDriver;
    IoDriverObjectType->Parse = NULL;
    IoDriverObjectType->Security = NULL;
    IoDriverObjectType->QueryName = NULL;
@@ -136,14 +115,76 @@ IopInitDriverImplementation(VOID)
 }
 
 NTSTATUS STDCALL
-IopDefaultDispatchFunction(
+IopInvalidDeviceRequest(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp)
 {
-   Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+   Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-   return STATUS_NOT_IMPLEMENTED;
+   return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+NTSTATUS STDCALL
+IopCreateDriver(
+   PVOID ObjectBody,
+   PVOID Parent,
+   PWSTR RemainingPath,
+   POBJECT_ATTRIBUTES ObjectAttributes)
+{
+   PDRIVER_OBJECT Object = ObjectBody;
+   ULONG i;
+
+   DPRINT("IopCreateDriver(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+      ObjectBody, Parent, RemainingPath);
+
+   if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
+      return STATUS_UNSUCCESSFUL;
+
+   /* Create driver extension */
+   Object->DriverExtension = (PDRIVER_EXTENSION)
+      ExAllocatePoolWithTag(
+         NonPagedPool,
+         sizeof(DRIVER_EXTENSION),
+         TAG_DRIVER_EXTENSION);
+
+   if (Object->DriverExtension == NULL)
+   {
+      return STATUS_NO_MEMORY;
+   }
+
+   RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
+
+   Object->Type = InternalDriverType;
+
+   for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+      Object->MajorFunction[i] = IopInvalidDeviceRequest;
+
+   return STATUS_SUCCESS;
+}
+
+VOID STDCALL
+IopDeleteDriver(PVOID ObjectBody)
+{
+   PDRIVER_OBJECT Object = ObjectBody;
+   KIRQL OldIrql;
+   PPRIVATE_DRIVER_EXTENSIONS DriverExtension, NextDriverExtension;
+
+   DPRINT("IopDeleteDriver(ObjectBody %x)\n", ObjectBody);
+
+   ExFreePool(Object->DriverExtension);
+
+   OldIrql = KeRaiseIrqlToDpcLevel();
+
+   for (DriverExtension = Object->DriverSection;
+        DriverExtension != NULL;
+        DriverExtension = NextDriverExtension)
+   {
+      NextDriverExtension = DriverExtension->Link;
+      ExFreePool(DriverExtension);
+   }
+
+   KfLowerIrql(OldIrql);
 }
 
 NTSTATUS FASTCALL
@@ -155,7 +196,6 @@ IopCreateDriverObject(
    ULONG DriverImageSize)
 {
    PDRIVER_OBJECT Object;
-   ULONG i;
    WCHAR NameBuffer[MAX_PATH];
    UNICODE_STRING DriverName;
    OBJECT_ATTRIBUTES ObjectAttributes;
@@ -208,28 +248,9 @@ IopCreateDriverObject(
       return Status;
    }
 
-   /* Create driver extension */
-   Object->DriverExtension = (PDRIVER_EXTENSION)
-      ExAllocatePoolWithTag(
-         NonPagedPool,
-         sizeof(DRIVER_EXTENSION),
-         TAG_DRIVER_EXTENSION);
-
-   if (Object->DriverExtension == NULL)
-   {
-      ExFreePool(Object);
-      return STATUS_NO_MEMORY;
-   }
-
-   RtlZeroMemory(Object->DriverExtension, sizeof(DRIVER_EXTENSION));
-
-   Object->Type = InternalDriverType;
    Object->DriverStart = DriverImageStart;
    Object->DriverSize = DriverImageSize;
 
-   for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
-      Object->MajorFunction[i] = IopDefaultDispatchFunction;
-
    *DriverObject = Object;
 
    return STATUS_SUCCESS;
@@ -333,6 +354,8 @@ IopLoadServiceModule(
    UNICODE_STRING ServiceImagePath;
    NTSTATUS Status;
 
+   DPRINT("IopLoadServiceModule(%wZ, %x)\n", ServiceName, ModuleObject);
+
    /*
     * Get information about the service.
     */
@@ -380,6 +403,8 @@ IopLoadServiceModule(
 
    if (*ModuleObject == NULL)
    {
+      Status = STATUS_UNSUCCESSFUL;
+
       /*
        * Special case for boot modules that were loaded by boot loader.
        */
@@ -392,8 +417,6 @@ IopLoadServiceModule(
          PLOADER_MODULE KeLoaderModules =
             (PLOADER_MODULE)KeLoaderBlock.ModsAddr;
 
-         Status = STATUS_UNSUCCESSFUL;
-
          /*
           * FIXME:
           * Improve this searching algorithm by using the image name
@@ -405,8 +428,10 @@ IopLoadServiceModule(
          for (i = 1; i < KeLoaderBlock.ModsCount; i++)
          {
             ModuleName = (PCHAR)KeLoaderModules[i].String;
-            if (!strcmp(ModuleName, SearchName))
+            if (!_stricmp(ModuleName, SearchName))
             {
+               DPRINT("Initializing boot module\n");
+
                /* Tell, that the module is already loaded */
                KeLoaderModules[i].Reserved = 1;
 
@@ -483,6 +508,7 @@ IopInitializeDriverModule(
    UNICODE_STRING RegistryKey;
    PDRIVER_INITIALIZE DriverEntry = ModuleObject->EntryPoint;
    NTSTATUS Status;
+   WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
 
    Status = IopCreateDriverObject(
       DriverObject,
@@ -500,10 +526,10 @@ IopInitializeDriverModule(
    if (DeviceNode->ServiceName.Buffer)
    {
       RegistryKey.Length = DeviceNode->ServiceName.Length +
-         sizeof(DRIVER_REGISTRY_KEY_BASENAME);
+         sizeof(ServicesKeyName);
       RegistryKey.MaximumLength = RegistryKey.Length + sizeof(UNICODE_NULL);
       RegistryKey.Buffer = ExAllocatePool(PagedPool, RegistryKey.MaximumLength);
-      wcscpy(RegistryKey.Buffer, DRIVER_REGISTRY_KEY_BASENAME);
+      wcscpy(RegistryKey.Buffer, ServicesKeyName);
       wcscat(RegistryKey.Buffer, DeviceNode->ServiceName.Buffer);
    }
    else
@@ -519,9 +545,8 @@ IopInitializeDriverModule(
    Status = DriverEntry(*DriverObject, &RegistryKey);
    if (!NT_SUCCESS(Status))
    {
-      ExFreePool((*DriverObject)->DriverExtension);
-      ObMakeTemporaryObject(DriverObject);
-      ObDereferenceObject(DriverObject);
+      ObMakeTemporaryObject(*DriverObject);
+      ObDereferenceObject(*DriverObject);
       return Status;
    }
 
@@ -551,7 +576,6 @@ IopAttachFilterDriversCallback(
    PMODULE_OBJECT ModuleObject;
    PDRIVER_OBJECT DriverObject;
    NTSTATUS Status;
-
    
    for (Filters = ValueData;
         ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength &&
@@ -681,13 +705,6 @@ IopAttachFilterDrivers(
    return STATUS_SUCCESS;
 }
 
-
-
-
-
-
-
-
 static NTSTATUS STDCALL
 IopCreateGroupListEntry(PWSTR ValueName,
                        ULONG ValueType,
@@ -964,12 +981,12 @@ IoDestroyDriverList(VOID)
 VOID STATIC
 MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
 {
-  ULONG i;
+   ULONG i;
 
-  for (i = 0; i < PAGE_ROUND_UP(Length)/PAGE_SIZE; i++)
-  {
-     MmDeleteVirtualMapping(NULL, (char*)StartAddress + i * PAGE_SIZE, TRUE, NULL, NULL);
-  }
+   for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
+   {
+      MmDeleteVirtualMapping(NULL, (char*)StartAddress + i * PAGE_SIZE, TRUE, NULL, NULL);
+   }
 }
 
 /*
@@ -999,12 +1016,14 @@ IopInitializeBuiltinDriver(
    /*
     * Display 'Initializing XXX...' message
     */
+
    sprintf(TextBuffer, "Initializing %s...\n", FileName);
    HalDisplayString(TextBuffer);
 
    /*
     * Determine the right device object
     */
+
    if (ModuleDeviceNode == NULL)
    {
       /* Use IopRootDeviceNode for now */
@@ -1022,6 +1041,7 @@ IopInitializeBuiltinDriver(
    /*
     * Generate filename without path (not needed by freeldr)
     */
+
    FileNameWithoutPath = strrchr(FileName, '\\');
    if (FileNameWithoutPath == NULL)
    {
@@ -1031,6 +1051,7 @@ IopInitializeBuiltinDriver(
    /*
     * Load the module
     */
+
    RtlCreateUnicodeStringFromAsciiz(&DeviceNode->ServiceName,
       FileNameWithoutPath);
    Status = LdrProcessModule(ModuleLoadBase, &DeviceNode->ServiceName,
@@ -1046,16 +1067,18 @@ IopInitializeBuiltinDriver(
    /*
     * Strip the file extension from ServiceName
     */
+
    FileExtension = wcsrchr(DeviceNode->ServiceName.Buffer, '.');
    if (FileExtension != NULL)
    {
-      DeviceNode->ServiceName.Length -= wcslen(DeviceNode->ServiceName.Buffer);
+      DeviceNode->ServiceName.Length -= wcslen(FileExtension) * sizeof(WCHAR);
       FileExtension[0] = 0;
    }
 
    /*
     * Initialize the driver
     */
+
    Status = IopInitializeDriverModule(DeviceNode, ModuleObject, FALSE,
       &DriverObject);
    
@@ -1112,6 +1135,7 @@ IopInitializeBootDrivers(VOID)
       /*
        * Pass symbol files to kernel debugger
        */
+
       if (!_stricmp(Extension, ".sym"))
       {
          KDB_SYMBOLFILE_HOOK((PVOID)ModuleStart, ModuleName, ModuleSize);
@@ -1120,6 +1144,7 @@ IopInitializeBootDrivers(VOID)
       /*
        * Load builtin driver
        */
+
       if (!_stricmp(Extension, ".sys"))
       {
          if (!ModuleLoaded)
@@ -1133,6 +1158,7 @@ IopInitializeBootDrivers(VOID)
       /*
        * Free memory for all boot files, except ntoskrnl.exe and hal.dll
        */
+
 #ifdef KDBG
       /*
        * Do not free the memory from symbol files, if the kernel debugger
@@ -1371,7 +1397,100 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
    return STATUS_SUCCESS;
 }
 
-/* FUNCTIONS ******************************************************************/
+VOID FASTCALL
+IopMarkLastReinitializeDriver(VOID)
+{
+  KIRQL Irql;
+
+  KeAcquireSpinLock(&DriverReinitListLock,
+                   &Irql);
+
+  if (IsListEmpty(&DriverReinitListHead))
+  {
+    DriverReinitTailEntry = NULL;
+  }
+  else
+  {
+    DriverReinitTailEntry = DriverReinitListHead.Blink;
+  }
+
+  KeReleaseSpinLock(&DriverReinitListLock,
+                   Irql);
+}
+
+
+VOID FASTCALL
+IopReinitializeDrivers(VOID)
+{
+  PDRIVER_REINIT_ITEM ReinitItem;
+  PLIST_ENTRY Entry;
+  KIRQL Irql;
+
+  KeAcquireSpinLock(&DriverReinitListLock,
+                   &Irql);
+
+  if (DriverReinitTailEntry == NULL)
+  {
+    KeReleaseSpinLock(&DriverReinitListLock,
+                     Irql);
+    return;
+  }
+
+  KeReleaseSpinLock(&DriverReinitListLock,
+                   Irql);
+
+  for (;;)
+  {
+    Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
+                                       &DriverReinitListLock);
+    if (Entry == NULL)
+      return;
+
+    ReinitItem = (PDRIVER_REINIT_ITEM)CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
+
+    /* Increment reinitialization counter */
+    ReinitItem->DriverObject->DriverExtension->Count++;
+
+    ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
+                             ReinitItem->Context,
+                             ReinitItem->DriverObject->DriverExtension->Count);
+
+    ExFreePool(Entry);
+
+    if (Entry == DriverReinitTailEntry)
+      return;
+  }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+IoCreateDriver (
+       IN PUNICODE_STRING DriverName,   OPTIONAL
+       IN PDRIVER_INITIALIZE InitializationFunction
+       )
+{
+       UNIMPLEMENTED;
+       return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * @unimplemented
+ */
+VOID
+STDCALL
+IoDeleteDriver (
+       IN PDRIVER_OBJECT DriverObject
+       )
+{
+       UNIMPLEMENTED;
+}
+
 
 /*
  * NtLoadDriver
@@ -1384,6 +1503,9 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
  *             
  * Return Value
  *    Status
+ *
+ * Status
+ *    implemented
  */
 
 NTSTATUS STDCALL
@@ -1405,9 +1527,13 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
     * Check security privileges
     */
 
+/* FIXME: Uncomment when privileges will be correctly implemented. */
 #if 0
    if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, KeGetPreviousMode()))
+   {
+      DPRINT("Privilege not held\n");
       return STATUS_PRIVILEGE_NOT_HELD;
+   }
 #endif
 
    RtlInitUnicodeString(&ImagePath, NULL);
@@ -1468,9 +1594,11 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
    /*
     * See, if the driver module isn't already loaded
     */
+
    ModuleObject = LdrGetModuleObject(&ImagePath);
    if (ModuleObject != NULL)
    {
+      DPRINT("Image already loaded\n");
       return STATUS_IMAGE_ALREADY_LOADED;
    }
 
@@ -1518,13 +1646,13 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
    Status = IopInitializeDriverModule(
       DeviceNode,
       ModuleObject,
-      (Type == 2 /*SERVICE_FILE_SYSTEM_DRIVER*/ ||
-       Type == 8 /*SERVICE_RECOGNIZER_DRIVER*/),
+      (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ ||
+       Type == 8 /* SERVICE_RECOGNIZER_DRIVER */),
       &DriverObject);
 
    if (!NT_SUCCESS(Status))
    {
-      DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status);
+      DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status);
       LdrUnloadModule(ModuleObject);
       IopFreeDeviceNode(DeviceNode);
       return Status;
@@ -1546,6 +1674,9 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
  *             
  * Return Value
  *    Status
+ *
+ * Status
+ *    implemented
  */
 
 NTSTATUS STDCALL
@@ -1554,102 +1685,41 @@ NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
    return IopUnloadDriver(DriverServiceName, FALSE);
 }
 
-
 /*
- * @implemented
+ * IoRegisterDriverReinitialization
+ *
+ * Status
+ *    @implemented
  */
-VOID STDCALL
-IoRegisterDriverReinitialization(PDRIVER_OBJECT DriverObject,
-                                PDRIVER_REINITIALIZE ReinitRoutine,
-                                PVOID Context)
-{
-  PDRIVER_REINIT_ITEM ReinitItem;
-
-  ReinitItem = ExAllocatePool(NonPagedPool,
-                             sizeof(DRIVER_REINIT_ITEM));
-  if (ReinitItem == NULL)
-    return;
-
-  ReinitItem->DriverObject = DriverObject;
-  ReinitItem->ReinitRoutine = ReinitRoutine;
-  ReinitItem->Context = Context;
 
-  ExInterlockedInsertTailList(&DriverReinitListHead,
-                             &ReinitItem->ItemEntry,
-                             &DriverReinitListLock);
-}
-
-
-VOID FASTCALL
-IopMarkLastReinitializeDriver(VOID)
-{
-  KIRQL Irql;
-
-  KeAcquireSpinLock(&DriverReinitListLock,
-                   &Irql);
-
-  if (IsListEmpty(&DriverReinitListHead))
-  {
-    DriverReinitTailEntry = NULL;
-  }
-  else
-  {
-    DriverReinitTailEntry = DriverReinitListHead.Blink;
-  }
-
-  KeReleaseSpinLock(&DriverReinitListLock,
-                   Irql);
-}
-
-
-VOID FASTCALL
-IopReinitializeDrivers(VOID)
+VOID STDCALL
+IoRegisterDriverReinitialization(
+   PDRIVER_OBJECT DriverObject,
+   PDRIVER_REINITIALIZE ReinitRoutine,
+   PVOID Context)
 {
-  PDRIVER_REINIT_ITEM ReinitItem;
-  PLIST_ENTRY Entry;
-  KIRQL Irql;
-
-  KeAcquireSpinLock(&DriverReinitListLock,
-                   &Irql);
-
-  if (DriverReinitTailEntry == NULL)
-  {
-    KeReleaseSpinLock(&DriverReinitListLock,
-                     Irql);
-    return;
-  }
+   PDRIVER_REINIT_ITEM ReinitItem;
 
-  KeReleaseSpinLock(&DriverReinitListLock,
-                   Irql);
-
-  for (;;)
-  {
-    Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
-                                       &DriverReinitListLock);
-    if (Entry == NULL)
+   ReinitItem = ExAllocatePool(NonPagedPool, sizeof(DRIVER_REINIT_ITEM));
+   if (ReinitItem == NULL)
       return;
 
-    ReinitItem = (PDRIVER_REINIT_ITEM)CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
-
-    /* Increment reinitialization counter */
-    ReinitItem->DriverObject->DriverExtension->Count++;
+   ReinitItem->DriverObject = DriverObject;
+   ReinitItem->ReinitRoutine = ReinitRoutine;
+   ReinitItem->Context = Context;
 
-    ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
-                             ReinitItem->Context,
-                             ReinitItem->DriverObject->DriverExtension->Count);
-
-    ExFreePool(Entry);
-
-    if (Entry == DriverReinitTailEntry)
-      return;
-  }
+   ExInterlockedInsertTailList(
+      &DriverReinitListHead,
+      &ReinitItem->ItemEntry,
+      &DriverReinitListLock);
 }
 
-typedef struct _PRIVATE_DRIVER_EXTENSIONS {
-   struct _PRIVATE_DRIVER_EXTENSIONS *Link;
-   PVOID ClientIdentificationAddress;
-   CHAR Extension[1];
-} PRIVATE_DRIVER_EXTENSIONS, *PPRIVATE_DRIVER_EXTENSIONS;
+/*
+ * IoAllocateDriverObjectExtension
+ *
+ * Status
+ *    @implemented
+ */
 
 NTSTATUS STDCALL
 IoAllocateDriverObjectExtension(
@@ -1699,6 +1769,13 @@ IoAllocateDriverObjectExtension(
    return STATUS_SUCCESS;      
 }
 
+/*
+ * IoGetDriverObjectExtension
+ *
+ * Status
+ *    @implemented
+ */
+
 PVOID STDCALL
 IoGetDriverObjectExtension(
    PDRIVER_OBJECT DriverObject,