[NTOS]: Some PnP ABI refactoring for future patches/work.
authorSir Richard <sir_richard@svn.reactos.org>
Sun, 11 Apr 2010 16:10:49 +0000 (16:10 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Sun, 11 Apr 2010 16:10:49 +0000 (16:10 +0000)
[NTOS]: Switch to PnP Add Device routine, currently mostly a copy of the original ReactOS code. However, PnP now tries to open all the required registry keys before attempting to start the device. Failures are reported and load cancelled. More work TBD.

svn path=/trunk/; revision=46841

reactos/ntoskrnl/include/internal/io.h
reactos/ntoskrnl/io/iomgr/device.c
reactos/ntoskrnl/io/iomgr/driver.c
reactos/ntoskrnl/io/pnpmgr/pnpinit.c
reactos/ntoskrnl/io/pnpmgr/pnpmgr.c

index dc80ff2..4f2b236 100644 (file)
@@ -509,6 +509,14 @@ typedef struct _DEVICETREE_TRAVERSE_CONTEXT
 //
 // PNP Routines
 //
+NTSTATUS
+NTAPI
+PipCallDriverAddDevice(
+    IN PDEVICE_NODE DeviceNode,
+    IN BOOLEAN LoadDriver,     
+    IN PDRIVER_OBJECT DriverObject
+);
+
 VOID
 PnpInit(
     VOID
@@ -563,6 +571,15 @@ IopFreeDeviceNode(
 );
 
 NTSTATUS
+NTAPI
+IopSynchronousCall(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIO_STACK_LOCATION IoStackLocation,
+    OUT PVOID *Information
+);
+
+NTSTATUS
+NTAPI
 IopInitiatePnpIrp(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIO_STATUS_BLOCK IoStatusBlock,
@@ -694,6 +711,12 @@ IoInitSystem(
 //
 // Device/Volume Routines
 //
+VOID
+NTAPI
+IopReadyDeviceObjects(
+    IN PDRIVER_OBJECT Driver
+);
+
 NTSTATUS
 FASTCALL
 IopInitializeDevice(
index 7434970..b9176ce 100644 (file)
@@ -25,6 +25,24 @@ extern LIST_ENTRY IopTapeFsListHead;
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
+VOID
+NTAPI
+IopReadyDeviceObjects(IN PDRIVER_OBJECT Driver)
+{
+    PAGED_CODE();
+    PDEVICE_OBJECT DeviceObject;
+
+    /* Set the driver as initialized */
+    Driver->Flags |= DRVO_INITIALIZED;
+    DeviceObject = Driver->DeviceObject;
+    while (DeviceObject)
+    {
+        /* Set every device as initialized too */
+        DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+        DeviceObject = DeviceObject->NextDevice;
+    }
+}
+
 VOID
 NTAPI
 IopDeleteDevice(IN PVOID ObjectBody)
index 18202bf..1ab5445 100644 (file)
@@ -438,7 +438,6 @@ IopInitializeDriverModule(
    UNICODE_STRING RegistryKey;
    PDRIVER_INITIALIZE DriverEntry;
    PDRIVER_OBJECT Driver;
-   PDEVICE_OBJECT DeviceObject;
    NTSTATUS Status;
 
    DriverEntry = ModuleObject->EntryPoint;
@@ -495,14 +494,7 @@ IopInitializeDriverModule(
    }
 
    /* Set the driver as initialized */
-   Driver->Flags |= DRVO_INITIALIZED;
-   DeviceObject = Driver->DeviceObject;
-   while (DeviceObject)
-   {
-       /* Set every device as initialized too */
-       DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
-       DeviceObject = DeviceObject->NextDevice;
-   }
+   IopReadyDeviceObjects(Driver);
 
    if (PnpSystemInit) IopReinitializeDrivers();
 
index 8c56072..24c8ba6 100644 (file)
@@ -219,4 +219,116 @@ Quickie:
     return i;
 }
 
+NTSTATUS
+NTAPI
+PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode,
+                       IN BOOLEAN LoadDriver,     
+                       IN PDRIVER_OBJECT DriverObject)
+{ 
+    NTSTATUS Status;
+    HANDLE EnumRootKey, SubKey, ControlKey, ClassKey, PropertiesKey;
+    UNICODE_STRING ClassGuid, Properties;
+    UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT);
+    UNICODE_STRING ControlClass =
+    RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
+    PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL;
+    PWCHAR Buffer;
+    
+    /* Open enumeration root key */
+    Status = IopOpenRegistryKeyEx(&EnumRootKey,
+                                  NULL,
+                                  &EnumRoot,
+                                  KEY_READ);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+        return Status;
+    }
+    
+    /* Open instance subkey */
+    Status = IopOpenRegistryKeyEx(&SubKey,
+                                  EnumRootKey,
+                                  &DeviceNode->InstancePath,
+                                  KEY_READ);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+        ZwClose(EnumRootKey);
+        return Status;
+    }
+    
+    /* Get class GUID */
+    Status = IopGetRegistryValue(SubKey,
+                                 REGSTR_VAL_CLASSGUID,
+                                 &KeyValueInformation);
+    if (NT_SUCCESS(Status))
+    {
+        /* Convert to unicode string */
+        Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset);
+        PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &ClassGuid.Length);
+        ClassGuid.MaximumLength = KeyValueInformation->DataLength;
+        ClassGuid.Buffer = Buffer;
+        
+        /* Open the key */
+        Status = IopOpenRegistryKeyEx(&ControlKey,
+                                      NULL,
+                                      &ControlClass,
+                                      KEY_READ);
+        if (!NT_SUCCESS(Status))
+        {
+            /* No class key */
+            DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+            ClassKey = NULL;
+        }
+        else
+        {
+            /* Open the class key */
+            Status = IopOpenRegistryKeyEx(&ClassKey,
+                                          ControlKey,
+                                          &ClassGuid,
+                                          KEY_READ);
+            ZwClose(ControlKey);
+            if (!NT_SUCCESS(Status))
+            {
+                /* No class key */
+                DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+                ClassKey = NULL;
+            }
+        }
+        
+        /* Check if we made it till here */
+        if (ClassKey)
+        {
+            /* Get the device properties */
+            RtlInitUnicodeString(&Properties, REGSTR_KEY_DEVICE_PROPERTIES);
+            Status = IopOpenRegistryKeyEx(&PropertiesKey,
+                                          ClassKey,
+                                          &Properties,
+                                          KEY_READ);
+            if (!NT_SUCCESS(Status))
+            {
+                /* No properties */
+                DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status);
+                PropertiesKey = NULL;
+            }
+        }
+        
+        /* Free the registry data */
+        ExFreePool(KeyValueInformation);
+    }
+    
+    /* Do ReactOS-style setup */
+    IopAttachFilterDrivers(DeviceNode, TRUE);
+    Status = IopInitializeDevice(DeviceNode, DriverObject);
+    if (NT_SUCCESS(Status))
+    {
+        IopAttachFilterDrivers(DeviceNode, FALSE);
+        IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
+        Status = IopStartDevice(DeviceNode);
+    }
+    
+    /* Return status */
+    return Status;
+}
+
 /* EOF */
index e5aee20..8862fd8 100644 (file)
@@ -618,69 +618,90 @@ IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
 }
 
 NTSTATUS
-IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject,
-                  PIO_STATUS_BLOCK IoStatusBlock,
-                  ULONG MinorFunction,
-                  PIO_STACK_LOCATION Stack OPTIONAL)
+NTAPI
+IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject,
+                   IN PIO_STACK_LOCATION IoStackLocation,
+                   OUT PVOID *Information)
 {
-   PDEVICE_OBJECT TopDeviceObject;
-   PIO_STACK_LOCATION IrpSp;
-   NTSTATUS Status;
-   KEVENT Event;
-   PIRP Irp;
-
-   /* Always call the top of the device stack */
-   TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
-
-   KeInitializeEvent(
-      &Event,
-      NotificationEvent,
-      FALSE);
-
-   Irp = IoBuildSynchronousFsdRequest(
-      IRP_MJ_PNP,
-      TopDeviceObject,
-      NULL,
-      0,
-      NULL,
-      &Event,
-      IoStatusBlock);
-
-   /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
-   Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-   Irp->IoStatus.Information = 0;
-
-   if (MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS)
-   {
-      Irp->IoStatus.Information = (ULONG_PTR)Stack->Parameters.FilterResourceRequirements.IoResourceRequirementList;
-   }
-
-   IrpSp = IoGetNextIrpStackLocation(Irp);
-   IrpSp->MinorFunction = (UCHAR)MinorFunction;
-
-   if (Stack)
-   {
-      RtlCopyMemory(&IrpSp->Parameters,
-                    &Stack->Parameters,
-                    sizeof(Stack->Parameters));
-   }
-
-   Status = IoCallDriver(TopDeviceObject, Irp);
-   if (Status == STATUS_PENDING)
-   {
-      KeWaitForSingleObject(&Event,
-                            Executive,
-                            KernelMode,
-                            FALSE,
-                            NULL);
-      Status = IoStatusBlock->Status;
-   }
-
-   ObDereferenceObject(TopDeviceObject);
-
-   return Status;
+    PIRP Irp;
+    PIO_STACK_LOCATION IrpStack;
+    IO_STATUS_BLOCK IoStatusBlock;
+    KEVENT Event;
+    NTSTATUS Status;
+    PDEVICE_OBJECT TopDeviceObject;
+    PAGED_CODE();
+    
+    /* Call the top of the device stack */
+    TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
+    
+    /* Allocate an IRP */
+    Irp = IoAllocateIrp(TopDeviceObject->StackSize, FALSE);
+    if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
+    
+    /* Initialize to failure */
+    Irp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED;
+    Irp->IoStatus.Information = IoStatusBlock.Information = 0;
+    
+    /* Initialize the event */
+    KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+    
+    /* Set them up */
+    Irp->UserIosb = &IoStatusBlock;
+    Irp->UserEvent = &Event;
+    
+    /* Queue the IRP */
+    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+    IoQueueThreadIrp(Irp);
+    
+    /* Copy-in the stack */
+    IrpStack = IoGetNextIrpStackLocation(Irp);
+    *IrpStack = *IoStackLocation;
+    
+    /* Call the driver */
+    Status = IoCallDriver(TopDeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        /* Wait for it */
+        KeWaitForSingleObject(&Event,
+                              Executive,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+        Status = IoStatusBlock.Status;
+    }
+    
+    /* Return the information */
+    *Information = (PVOID)IoStatusBlock.Information;
+    return Status;
 }
 
+NTSTATUS
+NTAPI
+IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject,
+                  IN OUT PIO_STATUS_BLOCK IoStatusBlock,
+                  IN ULONG MinorFunction,
+                  IN PIO_STACK_LOCATION Stack OPTIONAL)
+{
+    IO_STACK_LOCATION IoStackLocation;
+    
+    /* Fill out the stack information */
+    RtlZeroMemory(&IoStackLocation, sizeof(IO_STACK_LOCATION));
+    IoStackLocation.MajorFunction = IRP_MJ_PNP;
+    IoStackLocation.MinorFunction = MinorFunction;
+    if (Stack)
+    {
+        /* Copy the rest */
+        RtlCopyMemory(&IoStackLocation.Parameters,
+                      &Stack->Parameters,
+                      sizeof(Stack->Parameters));
+    }
+    
+    /* Do the PnP call */
+    IoStatusBlock->Status = IopSynchronousCall(DeviceObject,
+                                               &IoStackLocation,
+                                               (PVOID)&IoStatusBlock->Information);
+    return IoStatusBlock->Status;
+}
 
 NTSTATUS
 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context)
@@ -2909,29 +2930,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
       /* Driver is loaded and initialized at this point */
       if (NT_SUCCESS(Status))
       {
-         /* Attach lower level filter drivers. */
-         IopAttachFilterDrivers(DeviceNode, TRUE);
-
-         /* Initialize the function driver for the device node */
-         Status = IopInitializeDevice(DeviceNode, DriverObject);
-
-         if (NT_SUCCESS(Status))
-         {
-            /* Attach upper level filter drivers. */
-            IopAttachFilterDrivers(DeviceNode, FALSE);
-
-            Status = IopStartDevice(DeviceNode);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
-                        &DeviceNode->InstancePath, Status);
-            }
-         }
-         else
-         {
-            DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
-                    &DeviceNode->InstancePath, Status);
-         }
+          /* Initialize the device, including all filters */
+          Status = PipCallDriverAddDevice(DeviceNode, FALSE, DriverObject);
       }
       else
       {