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.…
==============================================================================
--- 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