[ros-diffs] [hpoussin] 27435: Simplify IoSynchronousInvalidateDeviceRelations/IoInvalidateDeviceRelations IoInvalidateDeviceRelations now creates a workitem, which will call IoSynchronousInvalidateDeviceRelations()

hpoussin at svn.reactos.org hpoussin at svn.reactos.org
Fri Jul 6 23:12:44 CEST 2007


Author: hpoussin
Date: Sat Jul  7 01:12:44 2007
New Revision: 27435

URL: http://svn.reactos.org/svn/reactos?rev=27435&view=rev
Log:
Simplify IoSynchronousInvalidateDeviceRelations/IoInvalidateDeviceRelations
IoInvalidateDeviceRelations now creates a workitem, which will call IoSynchronousInvalidateDeviceRelations()

Modified:
    trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c

Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c?rev=27435&r1=27434&r2=27435&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c Sat Jul  7 01:12:44 2007
@@ -37,16 +37,10 @@
 
 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
 {
+    PDEVICE_OBJECT DeviceObject;
     DEVICE_RELATION_TYPE Type;
     PIO_WORKITEM WorkItem;
-    PKEVENT Event;
-    NTSTATUS Status;
 } INVALIDATE_DEVICE_RELATION_DATA, *PINVALIDATE_DEVICE_RELATION_DATA;
-
-static VOID NTAPI
-IopInvalidateDeviceRelations(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PVOID InvalidateContext);
 
 VOID
 NTAPI
@@ -253,6 +247,22 @@
                             &Stack);
 }
 
+static VOID NTAPI
+IopAsynchronousInvalidateDeviceRelations(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PVOID InvalidateContext)
+{
+    PINVALIDATE_DEVICE_RELATION_DATA Data = InvalidateContext;
+
+    IoSynchronousInvalidateDeviceRelations(
+        Data->DeviceObject,
+        Data->Type);
+
+    ObDereferenceObject(Data->WorkItem);
+    IoFreeWorkItem(Data->WorkItem);
+    ExFreePool(Data);
+}
+
 /*
  * @implemented
  */
@@ -275,53 +285,16 @@
         return;
     }
 
+    ObReferenceObject(DeviceObject);
+    Data->DeviceObject = DeviceObject;
     Data->Type = Type;
     Data->WorkItem = WorkItem;
-    Data->Event = NULL;
 
     IoQueueWorkItem(
         WorkItem,
-        IopInvalidateDeviceRelations,
+        IopAsynchronousInvalidateDeviceRelations,
         DelayedWorkQueue,
         Data);
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-IoSynchronousInvalidateDeviceRelations(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN DEVICE_RELATION_TYPE Type)
-{
-    PIO_WORKITEM WorkItem;
-    PINVALIDATE_DEVICE_RELATION_DATA Data;
-    KEVENT Event;
-
-    Data = ExAllocatePool(PagedPool, sizeof(INVALIDATE_DEVICE_RELATION_DATA));
-    if (!Data)
-        return;
-    WorkItem = IoAllocateWorkItem(DeviceObject);
-    if (!WorkItem)
-    {
-        ExFreePool(Data);
-        return;
-    }
-
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-    Data->Type = Type;
-    Data->WorkItem = WorkItem;
-    Data->Event = &Event;
-
-    IoQueueWorkItem(
-        WorkItem,
-        IopInvalidateDeviceRelations,
-        DelayedWorkQueue,
-        Data);
-
-    KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-    ExFreePool(Data);
 }
 
 /*
@@ -2186,359 +2159,15 @@
 }
 
 /*
- * IopActionConfigureChildServices
- *
- * Retrieve configuration for all (direct) child nodes of a parent node.
- *
- * Parameters
- *    DeviceNode
- *       Pointer to device node.
- *    Context
- *       Pointer to parent node to retrieve child node configuration for.
- *
- * Remarks
- *    We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
- *    when we reach a device node which is not a direct child of the device
- *    node for which we configure child services for. Any errors that occur is
- *    logged instead so that all child services have a chance of beeing
- *    configured.
+ * @implemented
  */
-
-NTSTATUS
-IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
-                                PVOID Context)
-{
-   RTL_QUERY_REGISTRY_TABLE QueryTable[3];
-   PDEVICE_NODE ParentDeviceNode;
-   PUNICODE_STRING Service;
-   UNICODE_STRING ClassGUID;
-   NTSTATUS Status;
-
-   DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context);
-
-   ParentDeviceNode = (PDEVICE_NODE)Context;
-
-   /*
-    * We are called for the parent too, but we don't need to do special
-    * handling for this node
-    */
-   if (DeviceNode == ParentDeviceNode)
-   {
-      DPRINT("Success\n");
-      return STATUS_SUCCESS;
-   }
-
-   /*
-    * Make sure this device node is a direct child of the parent device node
-    * that is given as an argument
-    */
-   if (DeviceNode->Parent != ParentDeviceNode)
-   {
-      /* Stop the traversal immediately and indicate successful operation */
-      DPRINT("Stop\n");
-      return STATUS_UNSUCCESSFUL;
-   }
-
-   if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED))
-   {
-      WCHAR RegKeyBuffer[MAX_PATH];
-      UNICODE_STRING RegKey;
-
-      RegKey.Length = 0;
-      RegKey.MaximumLength = sizeof(RegKeyBuffer);
-      RegKey.Buffer = RegKeyBuffer;
-
-      /*
-       * Retrieve configuration from Enum key
-       */
-
-      Service = &DeviceNode->ServiceName;
-
-      RtlZeroMemory(QueryTable, sizeof(QueryTable));
-      RtlInitUnicodeString(Service, NULL);
-      RtlInitUnicodeString(&ClassGUID, NULL);
-
-      QueryTable[0].Name = L"Service";
-      QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
-      QueryTable[0].EntryContext = Service;
-
-      QueryTable[1].Name = L"ClassGUID";
-      QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
-      QueryTable[1].EntryContext = &ClassGUID;
-      QueryTable[1].DefaultType = REG_SZ;
-      QueryTable[1].DefaultData = L"";
-      QueryTable[1].DefaultLength = 0;
-
-      RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
-      RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath);
-
-      Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
-         RegKey.Buffer, QueryTable, NULL, NULL);
-
-      if (!NT_SUCCESS(Status))
-      {
-         /* FIXME: Log the error */
-         DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
-            &DeviceNode->InstancePath, Status);
-         IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
-         return STATUS_SUCCESS;
-      }
-
-      if (Service->Buffer == NULL)
-      {
-         IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
-
-         if (ClassGUID.Length != 0)
-         {
-            /* Device has a ClassGUID value, but no Service value.
-             * Suppose it is using the NULL driver, so state the
-             * device is started */
-            DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath);
-            IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
-            DeviceNode->Flags |= DN_STARTED;
-         }
-         return STATUS_SUCCESS;
-      }
-
-      DPRINT("Got Service %S\n", Service->Buffer);
-   }
-
-   return STATUS_SUCCESS;
-}
-
-/*
- * IopActionInitChildServices
- *
- * Initialize the service for all (direct) child nodes of a parent node
- *
- * Parameters
- *    DeviceNode
- *       Pointer to device node.
- *    Context
- *       Pointer to parent node to initialize child node services for.
- *    BootDrivers
- *       Load only driver marked as boot start.
- *
- * Remarks
- *    If the driver image for a service is not loaded and initialized
- *    it is done here too. We only return a status code indicating an
- *    error (STATUS_UNSUCCESSFUL) when we reach a device node which is
- *    not a direct child of the device node for which we initialize
- *    child services for. Any errors that occur is logged instead so
- *    that all child services have a chance of being initialized.
- */
-
-NTSTATUS
-IopActionInitChildServices(PDEVICE_NODE DeviceNode,
-                           PVOID Context,
-                           BOOLEAN BootDrivers)
-{
-   PDEVICE_NODE ParentDeviceNode;
-   NTSTATUS Status;
-
-   DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode, Context,
-      BootDrivers);
-
-   ParentDeviceNode = (PDEVICE_NODE)Context;
-
-   /*
-    * We are called for the parent too, but we don't need to do special
-    * handling for this node
-    */
-   if (DeviceNode == ParentDeviceNode)
-   {
-      DPRINT("Success\n");
-      return STATUS_SUCCESS;
-   }
-
-   /*
-    * Make sure this device node is a direct child of the parent device node
-    * that is given as an argument
-    */
-#if 0
-   if (DeviceNode->Parent != ParentDeviceNode)
-   {
-      /*
-       * Stop the traversal immediately and indicate unsuccessful operation
-       */
-      DPRINT("Stop\n");
-      return STATUS_UNSUCCESSFUL;
-   }
-#endif
-
-   if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
-       !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
-       !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED))
-   {
-      PLDR_DATA_TABLE_ENTRY ModuleObject;
-      PDRIVER_OBJECT DriverObject;
-
-      /* Get existing DriverObject pointer (in case the driver has
-         already been loaded and initialized) */
-      Status = IopGetDriverObject(
-          &DriverObject,
-          &DeviceNode->ServiceName,
-          FALSE);
-
-      if (!NT_SUCCESS(Status))
-      {
-         /* Driver is not initialized, try to load it */
-         Status = IopLoadServiceModule(&DeviceNode->ServiceName, &ModuleObject);
-
-         if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED)
-         {
-            /* STATUS_IMAGE_ALREADY_LOADED means this driver
-               was loaded by the bootloader */
-            if (Status != STATUS_IMAGE_ALREADY_LOADED)
-            {
-               /* Initialize the driver */
-               Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
-                  &DeviceNode->ServiceName, FALSE, &DriverObject);
-            }
-            else
-            {
-               Status = STATUS_SUCCESS;
-            }
-         }
-         else
-         {
-            DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
-                    &DeviceNode->ServiceName, Status);
-         }
-      }
-
-      /* Driver is loaded and initialized at this point */
-      if (NT_SUCCESS(Status))
-      {
-         /* We have a driver for this DeviceNode */
-         DeviceNode->Flags |= DN_DRIVER_LOADED;
-         /* 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);
-            IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
-
-            Status = IopStartDevice(DeviceNode);
-         }
-         else
-         {
-            DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
-                    &DeviceNode->InstancePath, Status);
-         }
-      }
-      else
-      {
-         /*
-          * Don't disable when trying to load only boot drivers
-          */
-         if (!BootDrivers)
-         {
-            IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
-            IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
-            /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
-            CPRINT("Initialization of service %S failed (Status %x)\n",
-              DeviceNode->ServiceName.Buffer, Status);
-         }
-      }
-   }
-   else
-   {
-      DPRINT("Device %wZ is disabled or already initialized\n",
-         &DeviceNode->InstancePath);
-   }
-
-   return STATUS_SUCCESS;
-}
-
-/*
- * IopActionInitAllServices
- *
- * Initialize the service for all (direct) child nodes of a parent node. This
- * function just calls IopActionInitChildServices with BootDrivers = FALSE.
- */
-
-NTSTATUS
-IopActionInitAllServices(PDEVICE_NODE DeviceNode,
-                         PVOID Context)
-{
-   return IopActionInitChildServices(DeviceNode, Context, FALSE);
-}
-
-/*
- * IopActionInitBootServices
- *
- * Initialize the boot start services for all (direct) child nodes of a
- * parent node. This function just calls IopActionInitChildServices with
- * BootDrivers = TRUE.
- */
-NTSTATUS
-IopActionInitBootServices(PDEVICE_NODE DeviceNode,
-                          PVOID Context)
-{
-   return IopActionInitChildServices(DeviceNode, Context, TRUE);
-}
-
-/*
- * IopInitializePnpServices
- *
- * Initialize services for discovered children
- *
- * Parameters
- *    DeviceNode
- *       Top device node to start initializing services.
- *
- *    BootDrivers
- *       When set to TRUE, only drivers marked as boot start will
- *       be loaded. Otherwise, all drivers will be loaded.
- *
- * Return Value
- *    Status
- */
-NTSTATUS
-IopInitializePnpServices(IN PDEVICE_NODE DeviceNode,
-                         IN BOOLEAN BootDrivers)
-{
-   DEVICETREE_TRAVERSE_CONTEXT Context;
-
-   DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode, BootDrivers);
-
-   if (BootDrivers)
-   {
-      IopInitDeviceTreeTraverseContext(
-         &Context,
-         DeviceNode,
-         IopActionInitBootServices,
-         DeviceNode);
-   }
-   else
-   {
-      IopInitDeviceTreeTraverseContext(
-         &Context,
-         DeviceNode,
-         IopActionInitAllServices,
-         DeviceNode);
-   }
-
-   return IopTraverseDeviceTree(&Context);
-}
-
-/* Invalidate device list enumerated by a device node.
- * The call can be make synchronous by defining the Event field
- * of the INVALIDATE_DEVICE_RELATION_DATA structure
- */
-static VOID NTAPI
-IopInvalidateDeviceRelations(
+VOID
+NTAPI
+IoSynchronousInvalidateDeviceRelations(
     IN PDEVICE_OBJECT DeviceObject,
-    IN PVOID InvalidateContext) /* PINVALIDATE_DEVICE_RELATION_DATA */
-{
-    PINVALIDATE_DEVICE_RELATION_DATA Data = InvalidateContext;
+    IN DEVICE_RELATION_TYPE Type)
+{
     PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
-    PKEVENT Event = Data->Event;
     DEVICETREE_TRAVERSE_CONTEXT Context;
     PDEVICE_RELATIONS DeviceRelations;
     IO_STATUS_BLOCK IoStatusBlock;
@@ -2555,7 +2184,7 @@
 
     DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
 
-    Stack.Parameters.QueryDeviceRelations.Type = Data->Type;
+    Stack.Parameters.QueryDeviceRelations.Type = Type;
 
     Status = IopInitiatePnpIrp(
         DeviceObject,
@@ -2565,7 +2194,7 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
-        goto cleanup;
+        return;
     }
 
     DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
@@ -2577,8 +2206,7 @@
         {
             ExFreePool(DeviceRelations);
         }
-        Status = STATUS_SUCCESS;
-        goto cleanup;
+        return;
     }
 
     DPRINT("Got %d PDOs\n", DeviceRelations->Count);
@@ -2605,8 +2233,7 @@
             for (i = 0; i < DeviceRelations->Count; i++)
                 ObDereferenceObject(DeviceRelations->Objects[i]);
             ExFreePool(DeviceRelations);
-            Status = STATUS_NO_MEMORY;
-            goto cleanup;
+            return;
         }
     }
     ExFreePool(DeviceRelations);
@@ -2624,7 +2251,7 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status);
-        goto cleanup;
+        return;
     }
 
     /*
@@ -2640,7 +2267,7 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status);
-        goto cleanup;
+        return;
     }
 
     /*
@@ -2677,21 +2304,352 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status);
-        goto cleanup;
+        return;
     }
 
     DPRINT("IopInvalidateDeviceRelations() finished\n");
-    Status = STATUS_SUCCESS;
-
-cleanup:
-    IoFreeWorkItem(Data->WorkItem);
-    if (Event)
-    {
-        Data->Status = Status;
-        KeSetEvent(Event, 0, FALSE);
-    }
-    else
-        ExFreePool(Data);
+}
+
+/*
+ * IopActionConfigureChildServices
+ *
+ * Retrieve configuration for all (direct) child nodes of a parent node.
+ *
+ * Parameters
+ *    DeviceNode
+ *       Pointer to device node.
+ *    Context
+ *       Pointer to parent node to retrieve child node configuration for.
+ *
+ * Remarks
+ *    We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
+ *    when we reach a device node which is not a direct child of the device
+ *    node for which we configure child services for. Any errors that occur is
+ *    logged instead so that all child services have a chance of beeing
+ *    configured.
+ */
+
+NTSTATUS
+IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
+                                PVOID Context)
+{
+   RTL_QUERY_REGISTRY_TABLE QueryTable[3];
+   PDEVICE_NODE ParentDeviceNode;
+   PUNICODE_STRING Service;
+   UNICODE_STRING ClassGUID;
+   NTSTATUS Status;
+
+   DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context);
+
+   ParentDeviceNode = (PDEVICE_NODE)Context;
+
+   /*
+    * We are called for the parent too, but we don't need to do special
+    * handling for this node
+    */
+   if (DeviceNode == ParentDeviceNode)
+   {
+      DPRINT("Success\n");
+      return STATUS_SUCCESS;
+   }
+
+   /*
+    * Make sure this device node is a direct child of the parent device node
+    * that is given as an argument
+    */
+   if (DeviceNode->Parent != ParentDeviceNode)
+   {
+      /* Stop the traversal immediately and indicate successful operation */
+      DPRINT("Stop\n");
+      return STATUS_UNSUCCESSFUL;
+   }
+
+   if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED))
+   {
+      WCHAR RegKeyBuffer[MAX_PATH];
+      UNICODE_STRING RegKey;
+
+      RegKey.Length = 0;
+      RegKey.MaximumLength = sizeof(RegKeyBuffer);
+      RegKey.Buffer = RegKeyBuffer;
+
+      /*
+       * Retrieve configuration from Enum key
+       */
+
+      Service = &DeviceNode->ServiceName;
+
+      RtlZeroMemory(QueryTable, sizeof(QueryTable));
+      RtlInitUnicodeString(Service, NULL);
+      RtlInitUnicodeString(&ClassGUID, NULL);
+
+      QueryTable[0].Name = L"Service";
+      QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+      QueryTable[0].EntryContext = Service;
+
+      QueryTable[1].Name = L"ClassGUID";
+      QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
+      QueryTable[1].EntryContext = &ClassGUID;
+      QueryTable[1].DefaultType = REG_SZ;
+      QueryTable[1].DefaultData = L"";
+      QueryTable[1].DefaultLength = 0;
+
+      RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
+      RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath);
+
+      Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+         RegKey.Buffer, QueryTable, NULL, NULL);
+
+      if (!NT_SUCCESS(Status))
+      {
+         /* FIXME: Log the error */
+         DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
+            &DeviceNode->InstancePath, Status);
+         IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+         return STATUS_SUCCESS;
+      }
+
+      if (Service->Buffer == NULL)
+      {
+         IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+
+         if (ClassGUID.Length != 0)
+         {
+            /* Device has a ClassGUID value, but no Service value.
+             * Suppose it is using the NULL driver, so state the
+             * device is started */
+            DPRINT1("%wZ is using NULL driver\n", &DeviceNode->InstancePath);
+            IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
+            DeviceNode->Flags |= DN_STARTED;
+         }
+         return STATUS_SUCCESS;
+      }
+
+      DPRINT("Got Service %S\n", Service->Buffer);
+   }
+
+   return STATUS_SUCCESS;
+}
+
+/*
+ * IopActionInitChildServices
+ *
+ * Initialize the service for all (direct) child nodes of a parent node
+ *
+ * Parameters
+ *    DeviceNode
+ *       Pointer to device node.
+ *    Context
+ *       Pointer to parent node to initialize child node services for.
+ *    BootDrivers
+ *       Load only driver marked as boot start.
+ *
+ * Remarks
+ *    If the driver image for a service is not loaded and initialized
+ *    it is done here too. We only return a status code indicating an
+ *    error (STATUS_UNSUCCESSFUL) when we reach a device node which is
+ *    not a direct child of the device node for which we initialize
+ *    child services for. Any errors that occur is logged instead so
+ *    that all child services have a chance of being initialized.
+ */
+
+NTSTATUS
+IopActionInitChildServices(PDEVICE_NODE DeviceNode,
+                           PVOID Context,
+                           BOOLEAN BootDrivers)
+{
+   PDEVICE_NODE ParentDeviceNode;
+   NTSTATUS Status;
+
+   DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode, Context,
+      BootDrivers);
+
+   ParentDeviceNode = (PDEVICE_NODE)Context;
+
+   /*
+    * We are called for the parent too, but we don't need to do special
+    * handling for this node
+    */
+   if (DeviceNode == ParentDeviceNode)
+   {
+      DPRINT("Success\n");
+      return STATUS_SUCCESS;
+   }
+
+   /*
+    * Make sure this device node is a direct child of the parent device node
+    * that is given as an argument
+    */
+#if 0
+   if (DeviceNode->Parent != ParentDeviceNode)
+   {
+      /*
+       * Stop the traversal immediately and indicate unsuccessful operation
+       */
+      DPRINT("Stop\n");
+      return STATUS_UNSUCCESSFUL;
+   }
+#endif
+
+   if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
+       !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
+       !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED))
+   {
+      PLDR_DATA_TABLE_ENTRY ModuleObject;
+      PDRIVER_OBJECT DriverObject;
+
+      /* Get existing DriverObject pointer (in case the driver has
+         already been loaded and initialized) */
+      Status = IopGetDriverObject(
+          &DriverObject,
+          &DeviceNode->ServiceName,
+          FALSE);
+
+      if (!NT_SUCCESS(Status))
+      {
+         /* Driver is not initialized, try to load it */
+         Status = IopLoadServiceModule(&DeviceNode->ServiceName, &ModuleObject);
+
+         if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED)
+         {
+            /* STATUS_IMAGE_ALREADY_LOADED means this driver
+               was loaded by the bootloader */
+            if (Status != STATUS_IMAGE_ALREADY_LOADED)
+            {
+               /* Initialize the driver */
+               Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
+                  &DeviceNode->ServiceName, FALSE, &DriverObject);
+            }
+            else
+            {
+               Status = STATUS_SUCCESS;
+            }
+         }
+         else
+         {
+            DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
+                    &DeviceNode->ServiceName, Status);
+         }
+      }
+
+      /* Driver is loaded and initialized at this point */
+      if (NT_SUCCESS(Status))
+      {
+         /* We have a driver for this DeviceNode */
+         DeviceNode->Flags |= DN_DRIVER_LOADED;
+         /* 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);
+            IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
+
+            Status = IopStartDevice(DeviceNode);
+         }
+         else
+         {
+            DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
+                    &DeviceNode->InstancePath, Status);
+         }
+      }
+      else
+      {
+         /*
+          * Don't disable when trying to load only boot drivers
+          */
+         if (!BootDrivers)
+         {
+            IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+            IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
+            /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
+            CPRINT("Initialization of service %S failed (Status %x)\n",
+              DeviceNode->ServiceName.Buffer, Status);
+         }
+      }
+   }
+   else
+   {
+      DPRINT("Device %wZ is disabled or already initialized\n",
+         &DeviceNode->InstancePath);
+   }
+
+   return STATUS_SUCCESS;
+}
+
+/*
+ * IopActionInitAllServices
+ *
+ * Initialize the service for all (direct) child nodes of a parent node. This
+ * function just calls IopActionInitChildServices with BootDrivers = FALSE.
+ */
+
+NTSTATUS
+IopActionInitAllServices(PDEVICE_NODE DeviceNode,
+                         PVOID Context)
+{
+   return IopActionInitChildServices(DeviceNode, Context, FALSE);
+}
+
+/*
+ * IopActionInitBootServices
+ *
+ * Initialize the boot start services for all (direct) child nodes of a
+ * parent node. This function just calls IopActionInitChildServices with
+ * BootDrivers = TRUE.
+ */
+NTSTATUS
+IopActionInitBootServices(PDEVICE_NODE DeviceNode,
+                          PVOID Context)
+{
+   return IopActionInitChildServices(DeviceNode, Context, TRUE);
+}
+
+/*
+ * IopInitializePnpServices
+ *
+ * Initialize services for discovered children
+ *
+ * Parameters
+ *    DeviceNode
+ *       Top device node to start initializing services.
+ *
+ *    BootDrivers
+ *       When set to TRUE, only drivers marked as boot start will
+ *       be loaded. Otherwise, all drivers will be loaded.
+ *
+ * Return Value
+ *    Status
+ */
+NTSTATUS
+IopInitializePnpServices(IN PDEVICE_NODE DeviceNode,
+                         IN BOOLEAN BootDrivers)
+{
+   DEVICETREE_TRAVERSE_CONTEXT Context;
+
+   DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode, BootDrivers);
+
+   if (BootDrivers)
+   {
+      IopInitDeviceTreeTraverseContext(
+         &Context,
+         DeviceNode,
+         IopActionInitBootServices,
+         DeviceNode);
+   }
+   else
+   {
+      IopInitDeviceTreeTraverseContext(
+         &Context,
+         DeviceNode,
+         IopActionInitAllServices,
+         DeviceNode);
+   }
+
+   return IopTraverseDeviceTree(&Context);
 }
 
 static NTSTATUS INIT_FUNCTION




More information about the Ros-diffs mailing list