mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[NTOS:PNP] Misc IoInvalidateDeviceState fixes
- Add a check for correct PDO before doing anything
- Process the request only for started devices
- Send the request synchronously during the start sequence
This makes Windows' i8042prt.sys work on ReactOS.
Addendum to cf0bc1c132
This commit is contained in:
parent
17154c94c1
commit
505ac6565a
3 changed files with 87 additions and 75 deletions
|
@ -1502,6 +1502,72 @@ done:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes the IoInvalidateDeviceState request
|
||||||
|
*
|
||||||
|
* Sends IRP_MN_QUERY_PNP_DEVICE_STATE request and sets device node's flags
|
||||||
|
* according to the result.
|
||||||
|
* Tree reenumeration should be started upon a successful return of the function.
|
||||||
|
*
|
||||||
|
* @todo Do not return STATUS_SUCCESS if nothing is changed.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
PiUpdateDeviceState(
|
||||||
|
_In_ PDEVICE_NODE DeviceNode)
|
||||||
|
{
|
||||||
|
PNP_DEVICE_STATE PnPFlags;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = PiIrpQueryPnPDeviceState(DeviceNode, &PnPFlags);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
|
||||||
|
DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
|
||||||
|
else
|
||||||
|
DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
|
||||||
|
|
||||||
|
if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI)
|
||||||
|
DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
|
||||||
|
else
|
||||||
|
DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
|
||||||
|
|
||||||
|
if (PnPFlags & PNP_DEVICE_REMOVED || PnPFlags & PNP_DEVICE_DISABLED)
|
||||||
|
{
|
||||||
|
PiSetDevNodeProblem(DeviceNode,
|
||||||
|
PnPFlags & PNP_DEVICE_DISABLED
|
||||||
|
? CM_PROB_HARDWARE_DISABLED
|
||||||
|
: CM_PROB_DEVICE_NOT_THERE);
|
||||||
|
|
||||||
|
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
||||||
|
}
|
||||||
|
else if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
|
||||||
|
{
|
||||||
|
// Query resource rebalance
|
||||||
|
|
||||||
|
if (PnPFlags & PNP_DEVICE_FAILED)
|
||||||
|
DeviceNode->Flags &= DNF_NON_STOPPED_REBALANCE;
|
||||||
|
else
|
||||||
|
DeviceNode->Flags |= DNF_NON_STOPPED_REBALANCE;
|
||||||
|
|
||||||
|
// Clear DNF_NO_RESOURCE_REQUIRED just in case (will be set back if needed)
|
||||||
|
DeviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
|
||||||
|
|
||||||
|
// This will be caught up later by enumeration
|
||||||
|
DeviceNode->Flags |= DNF_RESOURCE_REQUIREMENTS_CHANGED;
|
||||||
|
}
|
||||||
|
else if (PnPFlags & PNP_DEVICE_FAILED)
|
||||||
|
{
|
||||||
|
PiSetDevNodeProblem(DeviceNode, CM_PROB_FAILED_POST_START);
|
||||||
|
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PiStartDeviceFinal(
|
PiStartDeviceFinal(
|
||||||
|
@ -1553,7 +1619,7 @@ PiStartDeviceFinal(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query the device state (IRP_MN_QUERY_PNP_DEVICE_STATE)
|
// Query the device state (IRP_MN_QUERY_PNP_DEVICE_STATE)
|
||||||
PiQueueDeviceAction(DeviceNode->PhysicalDeviceObject, PiActionQueryState, NULL, NULL);
|
PiUpdateDeviceState(DeviceNode);
|
||||||
|
|
||||||
DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
|
DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
|
||||||
IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
|
IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
|
||||||
|
@ -2025,72 +2091,6 @@ IopRemoveDevice(PDEVICE_NODE DeviceNode)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Processes the IoInvalidateDeviceState request
|
|
||||||
*
|
|
||||||
* Sends IRP_MN_QUERY_PNP_DEVICE_STATE request and sets device node's flags
|
|
||||||
* according to the result.
|
|
||||||
* Tree reenumeration should be started upon a successful return of the function.
|
|
||||||
*
|
|
||||||
* @todo Do not return STATUS_SUCCESS if nothing is changed.
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
NTSTATUS
|
|
||||||
PiUpdateDeviceState(
|
|
||||||
_In_ PDEVICE_NODE DeviceNode)
|
|
||||||
{
|
|
||||||
PNP_DEVICE_STATE PnPFlags;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
Status = PiIrpQueryPnPDeviceState(DeviceNode, &PnPFlags);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
|
|
||||||
DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
|
|
||||||
else
|
|
||||||
DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
|
|
||||||
|
|
||||||
if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI)
|
|
||||||
DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
|
|
||||||
else
|
|
||||||
DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
|
|
||||||
|
|
||||||
if (PnPFlags & PNP_DEVICE_REMOVED || PnPFlags & PNP_DEVICE_DISABLED)
|
|
||||||
{
|
|
||||||
PiSetDevNodeProblem(DeviceNode,
|
|
||||||
PnPFlags & PNP_DEVICE_DISABLED
|
|
||||||
? CM_PROB_HARDWARE_DISABLED
|
|
||||||
: CM_PROB_DEVICE_NOT_THERE);
|
|
||||||
|
|
||||||
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
|
||||||
}
|
|
||||||
else if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
|
|
||||||
{
|
|
||||||
// Query resource rebalance
|
|
||||||
|
|
||||||
if (PnPFlags & PNP_DEVICE_FAILED)
|
|
||||||
DeviceNode->Flags &= DNF_NON_STOPPED_REBALANCE;
|
|
||||||
else
|
|
||||||
DeviceNode->Flags |= DNF_NON_STOPPED_REBALANCE;
|
|
||||||
|
|
||||||
// Clear DNF_NO_RESOURCE_REQUIRED just in case (will be set back if needed)
|
|
||||||
DeviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
|
|
||||||
|
|
||||||
// This will be caught up later by enumeration
|
|
||||||
DeviceNode->Flags |= DNF_RESOURCE_REQUIREMENTS_CHANGED;
|
|
||||||
}
|
|
||||||
else if (PnPFlags & PNP_DEVICE_FAILED)
|
|
||||||
{
|
|
||||||
PiSetDevNodeProblem(DeviceNode, CM_PROB_FAILED_POST_START);
|
|
||||||
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
PiEnumerateDevice(
|
PiEnumerateDevice(
|
||||||
|
@ -2386,6 +2386,7 @@ PiDevNodeStateMachine(
|
||||||
break;
|
break;
|
||||||
case DeviceNodeStartPostWork:
|
case DeviceNodeStartPostWork:
|
||||||
DPRINT("DeviceNodeStartPostWork %wZ\n", ¤tNode->InstancePath);
|
DPRINT("DeviceNodeStartPostWork %wZ\n", ¤tNode->InstancePath);
|
||||||
|
// TODO: inspect the status
|
||||||
status = PiStartDeviceFinal(currentNode);
|
status = PiStartDeviceFinal(currentNode);
|
||||||
doProcessAgain = TRUE;
|
doProcessAgain = TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -2599,13 +2600,20 @@ PipDeviceActionWorker(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PiActionQueryState:
|
case PiActionQueryState:
|
||||||
// First, do a IRP_MN_QUERY_PNP_DEVICE_STATE request,
|
// This action is only valid for started devices. If the device is not yet
|
||||||
// it will update node's flags and then do enumeration if something changed
|
// started, the PnP manager issues IRP_MN_QUERY_PNP_DEVICE_STATE by itself.
|
||||||
status = PiUpdateDeviceState(deviceNode);
|
if (deviceNode->State == DeviceNodeStarted)
|
||||||
if (NT_SUCCESS(status))
|
|
||||||
{
|
{
|
||||||
PiDevNodeStateMachine(deviceNode);
|
// Issue a IRP_MN_QUERY_PNP_DEVICE_STATE request: it will update node's flags
|
||||||
|
// and then do enumeration if something has changed
|
||||||
|
status = PiUpdateDeviceState(deviceNode);
|
||||||
|
if (NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
PiDevNodeStateMachine(deviceNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: Windows may return STATUS_DELETE_PENDING here
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -288,8 +288,7 @@ PiIrpQueryPnPDeviceState(
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
ASSERT(DeviceNode);
|
ASSERT(DeviceNode);
|
||||||
ASSERT(DeviceNode->State == DeviceNodeResourcesAssigned ||
|
ASSERT(DeviceNode->State == DeviceNodeStartPostWork ||
|
||||||
DeviceNode->State == DeviceNodeStartPostWork ||
|
|
||||||
DeviceNode->State == DeviceNodeStarted);
|
DeviceNode->State == DeviceNodeStarted);
|
||||||
|
|
||||||
ULONG_PTR longState;
|
ULONG_PTR longState;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* FILE: ntoskrnl/io/pnpmgr/pnpmgr.c
|
* FILE: ntoskrnl/io/pnpmgr/pnpmgr.c
|
||||||
* PURPOSE: Initializes the PnP manager
|
* PURPOSE: Initializes the PnP manager
|
||||||
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||||
* Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
|
* Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
@ -2418,5 +2418,10 @@ NTAPI
|
||||||
IoInvalidateDeviceState(
|
IoInvalidateDeviceState(
|
||||||
IN PDEVICE_OBJECT DeviceObject)
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
|
if (!IopIsValidPhysicalDeviceObject(DeviceObject))
|
||||||
|
{
|
||||||
|
KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)DeviceObject, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
PiQueueDeviceAction(DeviceObject, PiActionQueryState, NULL, NULL);
|
PiQueueDeviceAction(DeviceObject, PiActionQueryState, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue