📄 plugplay.cpp
字号:
// (We can now be stopped or working)
pdx->prevstate = pdx->state;
pdx->state = PENDINGREMOVE;
return DefaultPnpHandler(fdo, Irp);
} // HandleQueryRemove
///////////////////////////////////////////////////////////////////////////////
NTSTATUS HandleQueryStop(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleQueryStop
ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_QUERY_STOP_DEVICE);
Irp->IoStatus.Status = STATUS_SUCCESS; // flag that we handled this IRP
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// Boot devices may get this query before they even start, so check to see
// if we're in the WORKING state before doing anything.
if (pdx->state != WORKING)
return DefaultPnpHandler(fdo, Irp);
KdPrint((DRIVERNAME " - To PENDINGSTOP from %s\n", statenames[pdx->state]));
pdx->state = PENDINGSTOP;
return DefaultPnpHandler(fdo, Irp);
} // HandleQueryStop
///////////////////////////////////////////////////////////////////////////////
NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleRemoveDevice
ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_REMOVE_DEVICE);
Irp->IoStatus.Status = STATUS_SUCCESS; // flag that we handled this IRP
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// Cancel any queued IRPs and start rejecting new ones
// Disable all device interfaces. This triggers PnP notifications that will
// allow apps to close their handles.
DeregisterAllInterfaces(pdx);
// Release our I/O resources
StopDevice(fdo, pdx->state == WORKING);
KdPrint((DRIVERNAME " - To REMOVED from %s\n", statenames[pdx->state]));
pdx->state = REMOVED;
// Let lower-level drivers handle this request. Ignore whatever
// result eventuates.
NTSTATUS status = DefaultPnpHandler(fdo, Irp);
// Wait for all claims against this device to vanish before removing
// the device object.
IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
// Remove the device object
RemoveDevice(fdo);
return status; // lower-level completed IoStatus already
} // HandleRemoveDevice
///////////////////////////////////////////////////////////////////////////////
NTSTATUS HandleStartDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleStartDevice
ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_START_DEVICE);
Irp->IoStatus.Status = STATUS_SUCCESS; // flag that we handled this IRP
NTSTATUS status = ForwardAndWait(fdo, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status);
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
status = StartDevice(fdo);
// While we were in the stopped state, we were stalling incoming requests.
// Now we can release any pending IRPs and start processing new ones
if (NT_SUCCESS(status))
{ // started okay
// Enable all registered device interfaces.
EnableAllInterfaces(pdx, TRUE);
KdPrint((DRIVERNAME " - To WORKING from %s\n", statenames[pdx->state]));
pdx->state = WORKING;
} // started okay
return CompleteRequest(Irp, status);
} // HandleStartDevice
///////////////////////////////////////////////////////////////////////////////
NTSTATUS HandleStopDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleStopDevice
ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_STOP_DEVICE);
Irp->IoStatus.Status = STATUS_SUCCESS; // flag that we handled this IRP
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// We're supposed to always get a query before we're stopped, so
// we should already be in the PENDINGSTOP state. There's a Win98 bug that
// can sometimes cause us to get a STOP instead of a REMOVE, in which case
// we should start rejecting IRPs
if (pdx->state != PENDINGSTOP)
{ // no previous query
KdPrint((DRIVERNAME " - STOP with no previous QUERY_STOP!\n"));
} // no previous query
StopDevice(fdo, pdx->state == WORKING);
KdPrint((DRIVERNAME " - To STOPPED from %s\n", statenames[pdx->state]));
pdx->state = STOPPED;
return DefaultPnpHandler(fdo, Irp);
} // HandleStopDevice
///////////////////////////////////////////////////////////////////////////////
NTSTATUS HandleSurpriseRemoval(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{ // HandleSurpriseRemoval
ASSERT(IoGetCurrentIrpStackLocation(Irp)->MinorFunction == IRP_MN_SURPRISE_REMOVAL);
Irp->IoStatus.Status = STATUS_SUCCESS; // flag that we handled this IRP
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
// Cancel any queued IRPs and start rejecting new ones
EnableAllInterfaces(pdx, FALSE);
KdPrint((DRIVERNAME " - To SURPRISEREMOVED from %s\n", statenames[pdx->state]));
BOOLEAN oktouch = pdx->state == WORKING;
pdx->state = SURPRISEREMOVED;
StopDevice(fdo, oktouch);
return DefaultPnpHandler(fdo, Irp);
} // HandleSurpriseRemoval
///////////////////////////////////////////////////////////////////////////////
// AdjustDeviceCapabilities corrects the reported device capabilities to
// workaround the fact that many back-level bus drivers simply don't report
// them correctly. Cf. toaster.sys sample in the DDK and talk given by
// Adrian Oney (no relation) at WinHEC 2002.
#pragma PAGEDCODE
__inline SYSTEM_POWER_STATE& operator++(SYSTEM_POWER_STATE& ss) {ss = (SYSTEM_POWER_STATE) (ss + 1); return ss;}
__inline SYSTEM_POWER_STATE& operator--(SYSTEM_POWER_STATE& ss) {ss = (SYSTEM_POWER_STATE) (ss - 1); return ss;}
VOID AdjustDeviceCapabilities(PDEVICE_EXTENSION pdx, PDEVICE_CAPABILITIES pdc)
{ // AdjustDeviceCapabilities
// Adjust power capabilities to compensate for bus driver written to
// WDM 1.0 spec. First infer D1 and D2 capabilities from S->D state map.
for (SYSTEM_POWER_STATE sstate = PowerSystemSleeping1; sstate <= PowerSystemHibernate; ++sstate)
{ // for each S-state
if (pdc->DeviceState[sstate] == PowerDeviceD1)
pdc->DeviceD1 = TRUE;
if (pdc->DeviceState[sstate] == PowerDeviceD2)
pdc->DeviceD2 = TRUE;
} // for each S-state
// Set the WakeFromDx flags based on the reported DeviceWake state and
// on the D-state corresponding to the reported SystemWake state
AdjustWakeCapabilities(pdc, pdc->DeviceWake);
if (pdc->SystemWake != PowerSystemUnspecified)
AdjustWakeCapabilities(pdc, pdc->DeviceState[pdc->SystemWake]);
// Find the deepest D-state from which this device can wake the system
DEVICE_POWER_STATE wakestate = PowerDeviceD0; // assume no wakeup capability
if (pdc->WakeFromD3)
wakestate = PowerDeviceD3;
else if (pdc->WakeFromD2)
wakestate = PowerDeviceD2;
else if (pdc->WakeFromD1)
wakestate = PowerDeviceD1;
else if (pdc->WakeFromD0)
wakestate = PowerDeviceD0;
// If SystemWake is specified, the corresponding D-state had better be at
// least as powered as the state we just discovered, or else there's a bug
// in our bus driver...
if (pdc->SystemWake != PowerSystemUnspecified)
{
ASSERT(pdc->DeviceState[pdc->SystemWake] <= wakestate);
}
// If SystemWake wasn't specified, infer it from the S->D state map by
// finding the lowest S-state whose D-state is at least as powered as the
// lowest D-state from which wakeup is possible (I think I got that right...)
else if (wakestate != PowerDeviceD0 && wakestate != PowerDeviceUnspecified)
{ // infer system wake state
for (sstate = PowerSystemSleeping3; sstate >= PowerSystemWorking; --sstate)
{ // for each S-state
if (pdc->DeviceState[sstate] != PowerDeviceUnspecified
&& pdc->DeviceState[sstate] <= wakestate)
{ // found the S-state
KdPrint((DRIVERNAME " - Inferring that wakeup from S%d state possible\n", sstate - 1));
pdc->SystemWake = sstate;
break;
} // found the S-state
} // for each S-state
} // infer system wake state
} // AdjustDeviceCapabilities
///////////////////////////////////////////////////////////////////////////////
// AdjustWakeCapabilities adjusts the wakeup capabilities for a device.
VOID AdjustWakeCapabilities(PDEVICE_CAPABILITIES pdc, DEVICE_POWER_STATE dstate)
{ // AdjustWakeCapabilities
switch (dstate)
{ // select on D-state
case PowerDeviceUnspecified:
break;
case PowerDeviceD0:
pdc->WakeFromD0 = TRUE;
break;
case PowerDeviceD1:
pdc->DeviceD1 = TRUE;
pdc->WakeFromD1 = TRUE;
break;
case PowerDeviceD2:
pdc->DeviceD2 = TRUE;
pdc->WakeFromD2 = TRUE;
break;
case PowerDeviceD3:
pdc->WakeFromD3 = TRUE;
break;
default:
ASSERT(FALSE);
} // select on D-state
} // AdjustWakeCapabilities
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -