mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[NTOS:PNP] Implement NT5.2-like DEVICE_NODE state management
- Use DeviceNode->State field and its values, instead of DeviceNode->Flags for tracking current node state - Change DNF_* flags to the ones compatible with Windows XP+ - Simplify state changes for device nodes and encapsulate all the logic inside the PiDevNodeStateMachine routine. This makes the ground for future improvements in the device removal sequence and resource management - Now values inside DeviceNode->State and ->Flags are compatible with the windbg !devnode macro and can be tracked using it - BUGFIX: fixed cases where IRP_MN_START_DEVICE or IRP_MN_QUERY_DEVICE_RELATIONS may be sent to a device after a IRP_MN_REMOVE_DEVICE CORE-7826
This commit is contained in:
parent
b704292808
commit
798fc13b48
12 changed files with 723 additions and 967 deletions
|
@ -567,11 +567,6 @@ IopDetectResourceConflict(
|
|||
//
|
||||
// PNP Routines
|
||||
//
|
||||
NTSTATUS
|
||||
PiCallDriverAddDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_In_ BOOLEAN LoadDrivers);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopInitializePlugPlayServices(
|
||||
|
@ -609,6 +604,11 @@ PiInsertDevNode(
|
|||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_In_ PDEVICE_NODE ParentNode);
|
||||
|
||||
PNP_DEVNODE_STATE
|
||||
PiSetDevNodeState(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_In_ PNP_DEVNODE_STATE NewState);
|
||||
|
||||
VOID
|
||||
PiSetDevNodeProblem(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
|
@ -629,7 +629,6 @@ IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode,
|
|||
PDEVICE_CAPABILITIES DeviceCaps);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopSynchronousCall(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IoStackLocation,
|
||||
|
@ -651,18 +650,6 @@ IopGetDeviceNode(
|
|||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
IopActionConfigureChildServices(
|
||||
IN PDEVICE_NODE DeviceNode,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
IopActionInitChildServices(
|
||||
IN PDEVICE_NODE DeviceNode,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
IoCreateDriverList(
|
||||
VOID
|
||||
|
@ -682,10 +669,6 @@ IopQueueTargetDeviceEvent(
|
|||
PUNICODE_STRING DeviceIds
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
IopInitializePnpServices(
|
||||
IN PDEVICE_NODE DeviceNode);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopOpenRegistryKeyEx(
|
||||
|
@ -817,21 +800,6 @@ IopReadyDeviceObjects(
|
|||
IN PDRIVER_OBJECT Driver
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
IopStartDevice(
|
||||
IN PDEVICE_NODE DeviceNode
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
IopStopDevice(
|
||||
IN PDEVICE_NODE DeviceNode
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
IopRemoveDevice(
|
||||
IN PDEVICE_NODE DeviceNode
|
||||
);
|
||||
|
||||
PVPB
|
||||
NTAPI
|
||||
IopCheckVpbMounted(
|
||||
|
@ -1387,6 +1355,35 @@ PiNotifyTargetDeviceChange(
|
|||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_opt_ PTARGET_DEVICE_CUSTOM_NOTIFICATION CustomNotification);
|
||||
|
||||
//
|
||||
// PnP IRPs
|
||||
//
|
||||
NTSTATUS
|
||||
PiIrpStartDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode);
|
||||
|
||||
NTSTATUS
|
||||
PiIrpStopDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode);
|
||||
|
||||
NTSTATUS
|
||||
PiIrpQueryStopDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode);
|
||||
|
||||
NTSTATUS
|
||||
PiIrpCancelStopDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode);
|
||||
|
||||
NTSTATUS
|
||||
PiIrpQueryDeviceRelations(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_In_ DEVICE_RELATION_TYPE Type);
|
||||
|
||||
NTSTATUS
|
||||
PiIrpQueryPnPDeviceState(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_Out_ PPNP_DEVICE_STATE DeviceState);
|
||||
|
||||
//
|
||||
// Global I/O Data
|
||||
//
|
||||
|
|
|
@ -596,9 +596,6 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
KdInitSystem(3, LoaderBlock);
|
||||
#endif
|
||||
|
||||
/* Load services for devices found by PnP manager */
|
||||
IopInitializePnpServices(IopRootDeviceNode);
|
||||
|
||||
/* Load system start drivers */
|
||||
IopInitializeSystemDrivers();
|
||||
PnpSystemInit = TRUE;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -70,6 +70,8 @@ PipAllocateDeviceNode(
|
|||
PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
}
|
||||
|
||||
DPRINT("Allocated devnode 0x%p\n", DeviceNode);
|
||||
|
||||
/* Return the node */
|
||||
return DeviceNode;
|
||||
}
|
||||
|
@ -98,6 +100,32 @@ PiInsertDevNode(
|
|||
}
|
||||
KeReleaseSpinLock(&IopDeviceTreeLock, oldIrql);
|
||||
DeviceNode->Level = ParentNode->Level + 1;
|
||||
|
||||
DPRINT("Inserted devnode 0x%p to parent 0x%p\n", DeviceNode, ParentNode);
|
||||
}
|
||||
|
||||
PNP_DEVNODE_STATE
|
||||
PiSetDevNodeState(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_In_ PNP_DEVNODE_STATE NewState)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
|
||||
KeAcquireSpinLock(&IopDeviceTreeLock, &oldIrql);
|
||||
|
||||
PNP_DEVNODE_STATE prevState = DeviceNode->State;
|
||||
if (prevState != NewState)
|
||||
{
|
||||
DeviceNode->State = NewState;
|
||||
DeviceNode->PreviousState = prevState;
|
||||
DeviceNode->StateHistory[DeviceNode->StateHistoryEntry++] = prevState;
|
||||
DeviceNode->StateHistoryEntry %= DEVNODE_HISTORY_SIZE;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&IopDeviceTreeLock, oldIrql);
|
||||
|
||||
DPRINT("%wZ Changed state 0x%x => 0x%x\n", &DeviceNode->InstancePath, prevState, NewState);
|
||||
return prevState;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -302,9 +330,11 @@ IopFreeDeviceNode(
|
|||
KIRQL OldIrql;
|
||||
PDEVICE_NODE PrevSibling = NULL;
|
||||
|
||||
/* All children must be deleted before a parent is deleted */
|
||||
ASSERT(!DeviceNode->Child);
|
||||
ASSERT(DeviceNode->PhysicalDeviceObject);
|
||||
/* All children must be deleted before a parent is deleted */
|
||||
ASSERT(DeviceNode->Child == NULL);
|
||||
/* This is the only state where we are allowed to remove the node */
|
||||
ASSERT(DeviceNode->State == DeviceNodeRemoved);
|
||||
/* No notifications should be registered for this device */
|
||||
ASSERT(IsListEmpty(&DeviceNode->TargetDeviceNotify));
|
||||
|
||||
|
|
|
@ -689,37 +689,54 @@ IopGetRelatedDevice(PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA RelatedDeviceData)
|
|||
return Status;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
PiIsDevNodeStarted(
|
||||
_In_ PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
return (DeviceNode->State == DeviceNodeStartPending ||
|
||||
DeviceNode->State == DeviceNodeStartCompletion ||
|
||||
DeviceNode->State == DeviceNodeStartPostWork ||
|
||||
DeviceNode->State == DeviceNodeStarted ||
|
||||
DeviceNode->State == DeviceNodeQueryStopped ||
|
||||
DeviceNode->State == DeviceNodeEnumeratePending ||
|
||||
DeviceNode->State == DeviceNodeEnumerateCompletion ||
|
||||
DeviceNode->State == DeviceNodeStopped ||
|
||||
DeviceNode->State == DeviceNodeRestartCompletion);
|
||||
}
|
||||
|
||||
static ULONG
|
||||
IopGetDeviceNodeStatus(PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
ULONG Output = 0;
|
||||
ULONG Output = DN_NT_ENUMERATOR | DN_NT_DRIVER;
|
||||
|
||||
if (DeviceNode->Parent == IopRootDeviceNode)
|
||||
Output |= DN_ROOT_ENUMERATED;
|
||||
|
||||
if (DeviceNode->Flags & DNF_ADDED)
|
||||
// FIXME: review for deleted and removed states
|
||||
if (DeviceNode->State >= DeviceNodeDriversAdded)
|
||||
Output |= DN_DRIVER_LOADED;
|
||||
|
||||
/* FIXME: DN_ENUM_LOADED */
|
||||
|
||||
if (DeviceNode->Flags & DNF_STARTED)
|
||||
if (PiIsDevNodeStarted(DeviceNode))
|
||||
Output |= DN_STARTED;
|
||||
|
||||
/* FIXME: Manual */
|
||||
if (DeviceNode->UserFlags & DNUF_WILL_BE_REMOVED)
|
||||
Output |= DN_WILL_BE_REMOVED;
|
||||
|
||||
if (!(DeviceNode->Flags & DNF_PROCESSED))
|
||||
Output |= DN_NEED_TO_ENUM;
|
||||
|
||||
/* DN_NOT_FIRST_TIME is 9x only */
|
||||
|
||||
/* FIXME: DN_HARDWARE_ENUM */
|
||||
|
||||
/* DN_LIAR and DN_HAS_MARK are 9x only */
|
||||
|
||||
if (DeviceNode->Problem != 0)
|
||||
if (DeviceNode->Flags & DNF_HAS_PROBLEM)
|
||||
Output |= DN_HAS_PROBLEM;
|
||||
|
||||
/* FIXME: DN_FILTERED */
|
||||
if (DeviceNode->Flags & DNF_HAS_PRIVATE_PROBLEM)
|
||||
Output |= DN_PRIVATE_PROBLEM;
|
||||
|
||||
if (DeviceNode->Flags & DNF_DRIVER_BLOCKED)
|
||||
Output |= DN_DRIVER_BLOCKED;
|
||||
|
||||
if (DeviceNode->Flags & DNF_CHILD_WITH_INVALID_ID)
|
||||
Output |= DN_CHILD_WITH_INVALID_ID;
|
||||
|
||||
if (DeviceNode->Flags & DNF_HAS_PRIVATE_PROBLEM)
|
||||
Output |= DN_PRIVATE_PROBLEM;
|
||||
|
||||
if (DeviceNode->Flags & DNF_LEGACY_DRIVER)
|
||||
Output |= DN_LEGACY_DRIVER;
|
||||
|
@ -730,10 +747,6 @@ IopGetDeviceNodeStatus(PDEVICE_NODE DeviceNode)
|
|||
if (!(DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE))
|
||||
Output |= DN_DISABLEABLE;
|
||||
|
||||
/* FIXME: Implement the rest */
|
||||
|
||||
Output |= DN_NT_ENUMERATOR | DN_NT_DRIVER;
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
|
|
|
@ -431,9 +431,8 @@ IopInitializePlugPlayServices(VOID)
|
|||
IopRootDeviceNode = PipAllocateDeviceNode(Pdo);
|
||||
|
||||
/* Set flags */
|
||||
IopRootDeviceNode->Flags |= DNF_STARTED + DNF_PROCESSED + DNF_ENUMERATED +
|
||||
DNF_MADEUP + DNF_NO_RESOURCE_REQUIRED +
|
||||
DNF_ADDED;
|
||||
IopRootDeviceNode->Flags |= DNF_MADEUP | DNF_ENUMERATED |
|
||||
DNF_IDS_QUERIED | DNF_NO_RESOURCE_REQUIRED;
|
||||
|
||||
/* Create instance path */
|
||||
RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath,
|
||||
|
@ -443,19 +442,20 @@ IopInitializePlugPlayServices(VOID)
|
|||
IopRootDriverObject->DriverExtension->AddDevice(IopRootDriverObject,
|
||||
IopRootDeviceNode->PhysicalDeviceObject);
|
||||
|
||||
PiSetDevNodeState(IopRootDeviceNode, DeviceNodeStarted);
|
||||
|
||||
/* Initialize PnP-Event notification support */
|
||||
Status = IopInitPlugPlayEvents();
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Report the device to the user-mode pnp manager */
|
||||
IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
|
||||
&IopRootDeviceNode->InstancePath);
|
||||
|
||||
/* Initialize the Bus Type GUID List */
|
||||
PnpBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST));
|
||||
RtlZeroMemory(PnpBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST));
|
||||
ExInitializeFastMutex(&PnpBusTypeGuidList->Lock);
|
||||
|
||||
/* Initialize PnP root relations (this is a syncronous operation) */
|
||||
PiQueueDeviceAction(IopRootDeviceNode->PhysicalDeviceObject, PiActionEnumRootDevices, NULL, NULL);
|
||||
|
||||
/* Launch the firmware mapper */
|
||||
Status = IopUpdateRootKey();
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
|
225
ntoskrnl/io/pnpmgr/pnpirp.c
Normal file
225
ntoskrnl/io/pnpmgr/pnpirp.c
Normal file
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Shortcuts for sending different IRP_MJ_PNP requests
|
||||
* COPYRIGHT: Copyright 2010 Sir Richard <sir_richard@svn.reactos.org>
|
||||
* Copyright 2020 Victor Perevertkin <victor.perevertkin@reactos.org>
|
||||
*/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
NTSTATUS
|
||||
IopSynchronousCall(
|
||||
_In_ PDEVICE_OBJECT DeviceObject,
|
||||
_In_ PIO_STACK_LOCATION IoStackLocation,
|
||||
_Out_ PVOID *Information)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ObDereferenceObject(TopDeviceObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Initialize to failure */
|
||||
Irp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED;
|
||||
Irp->IoStatus.Information = IoStatusBlock.Information = 0;
|
||||
|
||||
/* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
|
||||
if ((IoStackLocation->MajorFunction == IRP_MJ_PNP) &&
|
||||
(IoStackLocation->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS))
|
||||
{
|
||||
/* Copy the resource requirements list into the IOSB */
|
||||
Irp->IoStatus.Information =
|
||||
IoStatusBlock.Information = (ULONG_PTR)IoStackLocation->Parameters.FilterResourceRequirements.IoResourceRequirementList;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* Otherwise we may get stuck here or have IoStatusBlock not populated */
|
||||
ASSERT(!KeAreAllApcsDisabled());
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* Wait for it */
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
/* Remove the reference */
|
||||
ObDereferenceObject(TopDeviceObject);
|
||||
|
||||
/* Return the information */
|
||||
*Information = (PVOID)IoStatusBlock.Information;
|
||||
return Status;
|
||||
}
|
||||
|
||||
// IRP_MN_START_DEVICE (0x00)
|
||||
NTSTATUS
|
||||
PiIrpStartDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
ASSERT(DeviceNode->State == DeviceNodeResourcesAssigned);
|
||||
|
||||
PVOID info;
|
||||
IO_STACK_LOCATION stack = {
|
||||
.MajorFunction = IRP_MJ_PNP,
|
||||
.MinorFunction = IRP_MN_START_DEVICE,
|
||||
.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList,
|
||||
.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->ResourceListTranslated
|
||||
};
|
||||
|
||||
// Vista+ does an asynchronous call
|
||||
NTSTATUS status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, &info);
|
||||
DeviceNode->CompletionStatus = status;
|
||||
return status;
|
||||
}
|
||||
|
||||
// IRP_MN_STOP_DEVICE (0x04)
|
||||
NTSTATUS
|
||||
PiIrpStopDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
ASSERT(DeviceNode->State == DeviceNodeQueryStopped);
|
||||
|
||||
PVOID info;
|
||||
IO_STACK_LOCATION stack = {
|
||||
.MajorFunction = IRP_MJ_PNP,
|
||||
.MinorFunction = IRP_MN_STOP_DEVICE
|
||||
};
|
||||
|
||||
// Drivers should never fail a IRP_MN_STOP_DEVICE request
|
||||
NTSTATUS status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, &info);
|
||||
ASSERT(NT_SUCCESS(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
// IRP_MN_QUERY_STOP_DEVICE (0x05)
|
||||
NTSTATUS
|
||||
PiIrpQueryStopDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
ASSERT(DeviceNode->State == DeviceNodeStarted);
|
||||
|
||||
PVOID info;
|
||||
IO_STACK_LOCATION stack = {
|
||||
.MajorFunction = IRP_MJ_PNP,
|
||||
.MinorFunction = IRP_MN_QUERY_STOP_DEVICE
|
||||
};
|
||||
|
||||
NTSTATUS status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, &info);
|
||||
DeviceNode->CompletionStatus = status;
|
||||
return status;
|
||||
}
|
||||
|
||||
// IRP_MN_CANCEL_STOP_DEVICE (0x06)
|
||||
NTSTATUS
|
||||
PiIrpCancelStopDevice(
|
||||
_In_ PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
ASSERT(DeviceNode->State == DeviceNodeQueryStopped);
|
||||
|
||||
PVOID info;
|
||||
IO_STACK_LOCATION stack = {
|
||||
.MajorFunction = IRP_MJ_PNP,
|
||||
.MinorFunction = IRP_MN_CANCEL_STOP_DEVICE
|
||||
};
|
||||
|
||||
// in fact we don't care which status is returned here
|
||||
NTSTATUS status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, &info);
|
||||
ASSERT(NT_SUCCESS(status));
|
||||
return status;
|
||||
}
|
||||
|
||||
// IRP_MN_QUERY_DEVICE_RELATIONS (0x07)
|
||||
NTSTATUS
|
||||
PiIrpQueryDeviceRelations(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_In_ DEVICE_RELATION_TYPE Type)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
ASSERT(DeviceNode->State == DeviceNodeStarted);
|
||||
|
||||
IO_STACK_LOCATION stack = {
|
||||
.MajorFunction = IRP_MJ_PNP,
|
||||
.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS,
|
||||
.Parameters.QueryDeviceRelations.Type = Type
|
||||
};
|
||||
|
||||
// Vista+ does an asynchronous call
|
||||
NTSTATUS status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject,
|
||||
&stack,
|
||||
(PVOID)&DeviceNode->OverUsed1.PendingDeviceRelations);
|
||||
DeviceNode->CompletionStatus = status;
|
||||
return status;
|
||||
}
|
||||
|
||||
// IRP_MN_QUERY_PNP_DEVICE_STATE (0x14)
|
||||
NTSTATUS
|
||||
PiIrpQueryPnPDeviceState(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_Out_ PPNP_DEVICE_STATE DeviceState)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
ASSERT(DeviceNode->State == DeviceNodeStartPostWork ||
|
||||
DeviceNode->State == DeviceNodeStarted);
|
||||
|
||||
ULONG_PTR longState;
|
||||
IO_STACK_LOCATION stack = {
|
||||
.MajorFunction = IRP_MJ_PNP,
|
||||
.MinorFunction = IRP_MN_QUERY_PNP_DEVICE_STATE
|
||||
};
|
||||
|
||||
NTSTATUS status;
|
||||
status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, (PVOID)&longState);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*DeviceState = longState;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
|
@ -475,82 +475,6 @@ Quickie:
|
|||
return FoundIndex;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IoStackLocation,
|
||||
OUT PVOID *Information)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ObDereferenceObject(TopDeviceObject);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Initialize to failure */
|
||||
Irp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED;
|
||||
Irp->IoStatus.Information = IoStatusBlock.Information = 0;
|
||||
|
||||
/* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
|
||||
if ((IoStackLocation->MajorFunction == IRP_MJ_PNP) &&
|
||||
(IoStackLocation->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS))
|
||||
{
|
||||
/* Copy the resource requirements list into the IOSB */
|
||||
Irp->IoStatus.Information =
|
||||
IoStatusBlock.Information = (ULONG_PTR)IoStackLocation->Parameters.FilterResourceRequirements.IoResourceRequirementList;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* Otherwise we may get stuck here or have IoStatusBlock not populated */
|
||||
ASSERT(!KeAreAllApcsDisabled());
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* Wait for it */
|
||||
KeWaitForSingleObject(&Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
/* Remove the reference */
|
||||
ObDereferenceObject(TopDeviceObject);
|
||||
|
||||
/* Return the information */
|
||||
*Information = (PVOID)IoStatusBlock.Information;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject,
|
||||
|
|
|
@ -28,10 +28,6 @@ NTSTATUS
|
|||
IopSetDeviceInstanceData(HANDLE InstanceKey,
|
||||
PDEVICE_NODE DeviceNode);
|
||||
|
||||
NTSTATUS
|
||||
IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
|
||||
PVOID Context);
|
||||
|
||||
NTSTATUS
|
||||
PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OUT PKEVENT SyncEvent OPTIONAL,
|
||||
|
@ -149,20 +145,20 @@ PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
|
||||
IN INTERFACE_TYPE LegacyBusType,
|
||||
IN ULONG BusNumber,
|
||||
IN ULONG SlotNumber,
|
||||
IN PCM_RESOURCE_LIST ResourceList,
|
||||
IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL,
|
||||
IN BOOLEAN ResourceAssigned,
|
||||
IN OUT PDEVICE_OBJECT *DeviceObject OPTIONAL)
|
||||
IoReportDetectedDevice(
|
||||
_In_ PDRIVER_OBJECT DriverObject,
|
||||
_In_ INTERFACE_TYPE LegacyBusType,
|
||||
_In_ ULONG BusNumber,
|
||||
_In_ ULONG SlotNumber,
|
||||
_In_opt_ PCM_RESOURCE_LIST ResourceList,
|
||||
_In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements,
|
||||
_In_ BOOLEAN ResourceAssigned,
|
||||
_Inout_ PDEVICE_OBJECT *DeviceObject)
|
||||
{
|
||||
PDEVICE_NODE DeviceNode;
|
||||
PDEVICE_OBJECT Pdo;
|
||||
NTSTATUS Status;
|
||||
HANDLE InstanceKey;
|
||||
ULONG RequiredLength;
|
||||
UNICODE_STRING ValueName, ServiceLongName, ServiceName;
|
||||
WCHAR HardwareId[256];
|
||||
PWCHAR IfString;
|
||||
|
@ -223,6 +219,7 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
|
|||
}
|
||||
|
||||
/* We use the caller's PDO if they supplied one */
|
||||
UNICODE_STRING instancePath;
|
||||
if (DeviceObject && *DeviceObject)
|
||||
{
|
||||
Pdo = *DeviceObject;
|
||||
|
@ -230,10 +227,7 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
|
|||
else
|
||||
{
|
||||
/* Create the PDO */
|
||||
Status = PnpRootCreateDevice(&ServiceName,
|
||||
NULL,
|
||||
&Pdo,
|
||||
NULL);
|
||||
Status = PnpRootCreateDevice(&ServiceName, NULL, &Pdo, &instancePath);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status);
|
||||
|
@ -249,28 +243,7 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
PiInsertDevNode(DeviceNode, IopRootDeviceNode);
|
||||
|
||||
/* We're enumerated already */
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_ENUMERATED);
|
||||
|
||||
/* We don't call AddDevice for devices reported this way */
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
|
||||
|
||||
/* We don't send IRP_MN_START_DEVICE */
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
|
||||
|
||||
/* We need to get device IDs */
|
||||
#if 0
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_NEED_QUERY_IDS);
|
||||
#endif
|
||||
|
||||
/* This is a legacy driver for this device */
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_LEGACY_DRIVER);
|
||||
|
||||
/* Perform a manual configuration of our device */
|
||||
IopActionInterrogateDeviceStack(DeviceNode, DeviceNode->Parent);
|
||||
IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
|
||||
Status = RtlDuplicateUnicodeString(0, &instancePath, &DeviceNode->InstancePath);
|
||||
|
||||
/* Open a handle to the instance path key */
|
||||
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
|
||||
|
@ -321,30 +294,6 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* Add a hardware ID if the driver didn't report one */
|
||||
RtlInitUnicodeString(&ValueName, L"HardwareID");
|
||||
if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||
{
|
||||
/* Just use our most specific compatible ID */
|
||||
IdLength = 0;
|
||||
IdLength += swprintf(&HardwareId[IdLength],
|
||||
L"DETECTED%ls\\%wZ",
|
||||
IfString,
|
||||
&ServiceName);
|
||||
IdLength++;
|
||||
|
||||
HardwareId[IdLength++] = UNICODE_NULL;
|
||||
|
||||
/* Write the value to the registry */
|
||||
Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Failed to write the hardware ID: 0x%x\n", Status);
|
||||
ZwClose(InstanceKey);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign the resources to the device node */
|
||||
DeviceNode->BootResources = ResourceList;
|
||||
DeviceNode->ResourceRequirements = ResourceRequirements;
|
||||
|
@ -380,13 +329,11 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
|
|||
if (DeviceObject && *DeviceObject)
|
||||
PnpRootRegisterDevice(*DeviceObject);
|
||||
|
||||
/* Report the device's enumeration to umpnpmgr */
|
||||
IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED,
|
||||
&DeviceNode->InstancePath);
|
||||
PiInsertDevNode(DeviceNode, IopRootDeviceNode);
|
||||
DeviceNode->Flags |= DNF_MADEUP | DNF_ENUMERATED;
|
||||
|
||||
/* Report the device's arrival to umpnpmgr */
|
||||
IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
|
||||
&DeviceNode->InstancePath);
|
||||
// we still need to query IDs, send events and reenumerate this node
|
||||
PiSetDevNodeState(DeviceNode, DeviceNodeStartPostWork);
|
||||
|
||||
DPRINT("Reported device: %S (%wZ)\n", HardwareId, &DeviceNode->InstancePath);
|
||||
|
||||
|
|
|
@ -698,7 +698,7 @@ ByeBye:
|
|||
|
||||
// Hacked, because after fixing resource list parsing
|
||||
// we actually detect resource conflicts
|
||||
return Silent ? Result : FALSE; // Result;
|
||||
return Silent ? Result : FALSE; // Result;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -1109,20 +1109,17 @@ IopAssignDeviceResources(
|
|||
NTSTATUS Status;
|
||||
ULONG ListSize;
|
||||
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
|
||||
|
||||
Status = IopFilterResourceRequirements(DeviceNode);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto ByeBye;
|
||||
|
||||
if (!DeviceNode->BootResources && !DeviceNode->ResourceRequirements)
|
||||
{
|
||||
DeviceNode->Flags |= DNF_NO_RESOURCE_REQUIRED;
|
||||
DeviceNode->Flags &= ~DNF_ASSIGNING_RESOURCES;
|
||||
|
||||
/* No resource needed for this device */
|
||||
DeviceNode->ResourceList = NULL;
|
||||
DeviceNode->ResourceListTranslated = NULL;
|
||||
PiSetDevNodeState(DeviceNode, DeviceNodeResourcesAssigned);
|
||||
DeviceNode->Flags |= DNF_NO_RESOURCE_REQUIRED;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1191,9 +1188,7 @@ Finish:
|
|||
if (!NT_SUCCESS(Status))
|
||||
goto ByeBye;
|
||||
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED);
|
||||
|
||||
IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
|
||||
PiSetDevNodeState(DeviceNode, DeviceNodeResourcesAssigned);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
|
@ -1206,8 +1201,6 @@ ByeBye:
|
|||
|
||||
DeviceNode->ResourceListTranslated = NULL;
|
||||
|
||||
IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -157,6 +157,7 @@ list(APPEND SOURCE
|
|||
${REACTOS_SOURCE_DIR}/ntoskrnl/io/pnpmgr/plugplay.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/io/pnpmgr/pnpdma.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/io/pnpmgr/pnpinit.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/io/pnpmgr/pnpirp.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/io/pnpmgr/pnpmgr.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/io/pnpmgr/pnpnotify.c
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/io/pnpmgr/pnpreport.c
|
||||
|
|
|
@ -164,44 +164,53 @@ extern POBJECT_TYPE NTSYSAPI IoDriverObjectType;
|
|||
//
|
||||
// Device Node Flags
|
||||
//
|
||||
#define DNF_PROCESSED 0x00000001
|
||||
#define DNF_STARTED 0x00000002
|
||||
#define DNF_START_FAILED 0x00000004
|
||||
#define DNF_ENUMERATED 0x00000008
|
||||
#define DNF_DELETED 0x00000010
|
||||
#define DNF_MADEUP 0x00000020
|
||||
#define DNF_START_REQUEST_PENDING 0x00000040
|
||||
#define DNF_NO_RESOURCE_REQUIRED 0x00000080
|
||||
#define DNF_INSUFFICIENT_RESOURCES 0x00000100
|
||||
#define DNF_RESOURCE_ASSIGNED 0x00000200
|
||||
#define DNF_RESOURCE_REPORTED 0x00000400
|
||||
#define DNF_HAL_NODE 0x00000800 // ???
|
||||
#define DNF_ADDED 0x00001000
|
||||
#define DNF_ADD_FAILED 0x00002000
|
||||
#define DNF_LEGACY_DRIVER 0x00004000
|
||||
#define DNF_STOPPED 0x00008000
|
||||
#define DNF_WILL_BE_REMOVED 0x00010000
|
||||
|
||||
// this set of flags is relevant for w2k3 and newer
|
||||
// w2k has a completely different set of flags
|
||||
#define DNF_MADEUP 0x00000001
|
||||
#define DNF_DUPLICATE 0x00000002
|
||||
#define DNF_HAL_NODE 0x00000004
|
||||
#define DNF_REENUMERATE 0x00000008
|
||||
#define DNF_ENUMERATED 0x00000010
|
||||
#define DNF_IDS_QUERIED 0x00000020
|
||||
#define DNF_HAS_BOOT_CONFIG 0x00000040
|
||||
#define DNF_BOOT_CONFIG_RESERVED 0x00000080
|
||||
#define DNF_NO_RESOURCE_REQUIRED 0x00000100
|
||||
#define DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED 0x00000200
|
||||
#define DNF_RESOURCE_REQUIREMENTS_CHANGED 0x00000400
|
||||
#define DNF_NON_STOPPED_REBALANCE 0x00000800
|
||||
#define DNF_LEGACY_DRIVER 0x00001000
|
||||
#define DNF_HAS_PROBLEM 0x00002000
|
||||
#define DNF_HAS_PRIVATE_PROBLEM 0x00004000
|
||||
#define DNF_HARDWARE_VERIFICATION 0x00008000
|
||||
#define DNF_DEVICE_GONE 0x00010000
|
||||
#define DNF_LEGACY_RESOURCE_DEVICENODE 0x00020000
|
||||
#define DNF_NOT_CONFIGURED 0x00040000
|
||||
#define DNF_REINSTALL 0x00080000
|
||||
#define DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED 0x00100000 // ???
|
||||
#define DNF_DISABLED 0x00200000
|
||||
#define DNF_RESTART_OK 0x00400000
|
||||
#define DNF_NEED_RESTART 0x00800000
|
||||
#define DNF_VISITED 0x01000000
|
||||
#define DNF_ASSIGNING_RESOURCES 0x02000000
|
||||
#define DNF_BEEING_ENUMERATED 0x04000000
|
||||
#define DNF_NEED_ENUMERATION_ONLY 0x08000000
|
||||
#define DNF_LOCKED 0x10000000
|
||||
#define DNF_HAS_BOOT_CONFIG 0x20000000
|
||||
#define DNF_BOOT_CONFIG_RESERVED 0x40000000
|
||||
#define DNF_HAS_PROBLEM 0x80000000 // ???
|
||||
#define DNF_NEEDS_REBALANCE 0x00040000
|
||||
#define DNF_LOCKED_FOR_EJECT 0x00080000
|
||||
#define DNF_DRIVER_BLOCKED 0x00100000
|
||||
#define DNF_CHILD_WITH_INVALID_ID 0x00200000
|
||||
|
||||
// these flags were added in Vista or later
|
||||
#define DNF_ASYNC_START_NOT_SUPPORTED 0x00400000
|
||||
#define DNF_ASYNC_ENUMERATION_NOT_SUPPORTED 0x00800000
|
||||
#define DNF_LOCKED_FOR_REBALANCE 0x01000000
|
||||
#define DNF_UNINSTALLED 0x02000000
|
||||
#define DNF_NO_LOWER_DEVICE_FILTERS 0x04000000
|
||||
#define DNF_NO_LOWER_CLASS_FILTERS 0x08000000
|
||||
#define DNF_NO_SERVICE 0x10000000
|
||||
#define DNF_NO_UPPER_DEVICE_FILTERS 0x20000000
|
||||
#define DNF_NO_UPPER_CLASS_FILTERS 0x40000000
|
||||
#define DNF_WAITING_FOR_FDO 0x80000000
|
||||
|
||||
//
|
||||
// Device Node User Flags
|
||||
//
|
||||
#define DNUF_WILL_BE_REMOVED 0x0001
|
||||
#define DNUF_DONT_SHOW_IN_UI 0x0002
|
||||
#define DNUF_NEED_RESTART 0x0004
|
||||
#define DNUF_NOT_DISABLEABLE 0x0008
|
||||
#define DNUF_SHUTDOWN_QUERIED 0x0010
|
||||
#define DNUF_SHUTDOWN_SUBTREE_DONE 0x0020
|
||||
|
||||
//
|
||||
// Internal Option Flags
|
||||
|
@ -815,6 +824,8 @@ typedef struct _IO_CLIENT_EXTENSION
|
|||
PVOID ClientIdentificationAddress;
|
||||
} IO_CLIENT_EXTENSION, *PIO_CLIENT_EXTENSION;
|
||||
|
||||
#define DEVNODE_HISTORY_SIZE 20
|
||||
|
||||
//
|
||||
// Device Node
|
||||
//
|
||||
|
@ -829,7 +840,7 @@ typedef struct _DEVICE_NODE
|
|||
PO_IRP_MANAGER PoIrpManager;
|
||||
PNP_DEVNODE_STATE State;
|
||||
PNP_DEVNODE_STATE PreviousState;
|
||||
PNP_DEVNODE_STATE StateHistory[20];
|
||||
PNP_DEVNODE_STATE StateHistory[DEVNODE_HISTORY_SIZE];
|
||||
ULONG StateHistoryEntry;
|
||||
NTSTATUS CompletionStatus;
|
||||
PIRP PendingIrp;
|
||||
|
|
Loading…
Reference in a new issue