[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:
Victor Perevertkin 2020-12-10 03:19:31 +03:00
parent b704292808
commit 798fc13b48
No known key found for this signature in database
GPG key ID: C750B7222E9C7830
12 changed files with 723 additions and 967 deletions

View file

@ -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
//

View file

@ -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

View file

@ -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));

View file

@ -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;
}

View file

@ -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
View 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;
}

View file

@ -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,

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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;