I’m trying to more or less implement https://community.osr.com/discussion/51051 except for the system power irp case.
- Receive a DispatchPower call
- Add a completion routine and pass IRP down (all documentation says I can’t block)
- Completion routine gets called, allocates a new write IRP, sets a second completion routine, then sends it down
- When the write IRP completes, its completion routine will complete the power irp.
I’ve been reading docs all week long and I can’t figure out what’s wrong.
NSTATUS TestDispatchPower(IN PDEVICE_OBJECT, IN PIRP)
{
PDEVICE_EXTENSION pDeviceExtension;
PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);
//NTSTATUS ntStatus = STATUS_SUCCESS;
pDeviceExtension = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension;
if (pIoStack->MinorFunction == IRP_MN_SET_POWER &&
pIoStack->Parameters.Power.Type == SystemPowerState &&
pIoStack->Parameters.Power.State.SystemState == PowerSystemShutdown) )
{
pDeviceExtension->pPowerOffIrp = pIrp;
IoCopyCurrentIrpStackLocationToNext(pIrp);
IoSetCompletionRoutine(pIrp, PowerOffIrpCompletionTest, pDeviceExtension, TRUE, TRUE, TRUE);
IoCallDriver(pDeviceExtension->TargetDeviceObject, pIrp);
return STATUS_PENDING;
}
...
// defaults
}
NTSTATUS
PowerOffIrpCompletionTest(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID pContext
)
{
PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION) pDeviceObject->DeviceExtension;
PIRP pWriteIrp = NULL;
if(pIrp->PendingReturned) {
IoMarkIrpPending(pIrp);
}
pWriteIrp = CreateWriteIrp(/*magic*/);
IoSetCompletionRoutine(pWriteIrp, BitmapWrite_Completion,
pContext, TRUE, TRUE, TRUE);
IoCallDriver(pDeviceExtension->TargetDeviceObject,
pWriteIrp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
BitmapWrite_Completion(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp,
IN PVOID pContext
)
{
PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION) pContext;
UNREFERENCED_PARAMETER(pDeviceObject);
//cleanup write IRP
DestroyWriteIrp(pIrp, TRUE);
// finish power off IRP
IoReleaseRemoveLock(&pDeviceExtension->RemoveLock, NULL);
pDeviceExtension->pPowerOffIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pDeviceExtension->pPowerOffIrp, IO_NO_INCREMENT);
return STATUS_MORE_PROCESSING_REQUIRED;
}
Is there anything fundamentally wrong with this design? Right now it hangs on shutdown. No bluescreen code, just a hang.