// Pass request down without additional processing
NTSTATUS status;
status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);
// Handle usage notification specially in order to track power pageable
// flag correctly. We need to avoid allowing a non-pageable handler to be
// layered on top of a pageable handler.
if (fcn == IRP_MN_DEVICE_USAGE_NOTIFICATION)
{ // 用法报告
if (!fido->AttachedDevice || (fido->AttachedDevice->Flags & DO_POWER_PAGABLE))
fido->Flags |= DO_POWER_PAGABLE;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) UsageNotificationCompletionRoutine,
(PVOID) pdx, TRUE, TRUE, TRUE);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
}
// Handle start device specially in order to correctly inherit
// FILE_REMOVABLE_MEDIA
if (fcn == IRP_MN_START_DEVICE)
{ //设备开始
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) StartDeviceCompletionRoutine,
(PVOID) pdx, TRUE, TRUE, TRUE);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
}
// Handle remove device specially in order to cleanup device stack
if (fcn == IRP_MN_REMOVE_DEVICE)
{ //移除设备
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
RemoveDevice(fido);
return status;
}
// Simply forward any other type of PnP request
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
}
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
NTSTATUS UsageNotificationCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx)
{
if (Irp->PendingReturned)
IoMarkIrpPending(Irp);
// If lower driver cleared pageable flag, we must do the same
if (!(pdx->LowerDeviceObject->Flags & DO_POWER_PAGABLE))
fido->Flags &= ~DO_POWER_PAGABLE;
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return STATUS_SUCCESS;
} // UsageNotificationCompletionRoutine
// Pass request down without additional processing
NTSTATUS status;
status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);
// Handle usage notification specially in order to track power pageable
// flag correctly. We need to avoid allowing a non-pageable handler to be
// layered on top of a pageable handler.
if (fcn == IRP_MN_DEVICE_USAGE_NOTIFICATION)
{ // 用法报告
if (!fido->AttachedDevice || (fido->AttachedDevice->Flags & DO_POWER_PAGABLE))
fido->Flags |= DO_POWER_PAGABLE;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) UsageNotificationCompletionRoutine,
(PVOID) pdx, TRUE, TRUE, TRUE);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
}
// Handle start device specially in order to correctly inherit
// FILE_REMOVABLE_MEDIA
if (fcn == IRP_MN_START_DEVICE)
{ //设备开始
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) StartDeviceCompletionRoutine,
(PVOID) pdx, TRUE, TRUE, TRUE);
return IoCallDriver(pdx->LowerDeviceObject, Irp);
}
// Handle remove device specially in order to cleanup device stack
if (fcn == IRP_MN_REMOVE_DEVICE)
{ //移除设备
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp);
RemoveDevice(fido);
return status;
}
// Simply forward any other type of PnP request
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
}
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
NTSTATUS UsageNotificationCompletionRoutine(PDEVICE_OBJECT fido, PIRP Irp, PDEVICE_EXTENSION pdx)
{
if (Irp->PendingReturned)
IoMarkIrpPending(Irp);
// If lower driver cleared pageable flag, we must do the same
if (!(pdx->LowerDeviceObject->Flags & DO_POWER_PAGABLE))
fido->Flags &= ~DO_POWER_PAGABLE;
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return STATUS_SUCCESS;
} // UsageNotificationCompletionRoutine