fdo->Flags |= DO_BUFFERED_IO;
dx->PowerIdleCounter = PoRegisterDeviceForIdleDetection(pdo, 30, 60, PowerDeviceD3);
return STATUS_SUCCESS;
}
Remove Device handler
The code that handles removing devices has been moved to
Listing 9.2 Wdm2 PnpRemoveDeviceHandler
NTSTATUS PnpRemoveDeviceHandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp) {
PWDM2_DEVICE_EXTENSION dx=(PWDM2_DEVICE_EXTENSION)fdo->DeviceExtension;
DebugPrintMsg('PnpRemoveDeviceHandler');
// Wait for I/O to complete and stop device
PnpStopDevice(dx);
// Pass down stack and carry on immediately
NTSTATUS status = PnpDefaultHandler(fdo, Irp);
// disable device interface
IoSetDeviceInterfaceState(&dx->ifSymLinkName, FALSE);
RtlFreeUnicodeString(&dx->ifSymLinkName);
// unattach from stack if (dx->NextStackDevice)
IoDetachDevice(dx->NextStackDevice);
// delete our fdo
IoDeleteDevice(fdo);
return status;
}
Main PnP IRP Handler
The main IRP_MJ_PNP dispatch routine,
Listing 9.3 Wdm2 Wdm2Pnp
NTSTATUS Wdm2Pnp(IN PDEVICE_OBJECT fdo, IN PIRP Irp) {
PWDM2_DEVICE_EXTENSION dx=(PWDM2_DEVICE_EXTENSION)fdo->DeviceExtension;
DebugPrint('PnP %I',Irp);
if (!LockDevice(dx)) return CompleteIrp(Irp, STATUS_DELETE_PENDING, 0);
// Remember minor function
PIO_STACK_LOCATION TrpStack = IoGetCurrentIrpStackLocation(Irp);
ULONG MinorFunction = IrpStack->MinorFunction;
NTSTATUS status = STATUS_SUCCESS;
switch (MinorFunction) {
case IRP_MN_START_DEVICE:
status = PnpStartDeviceHandler(fdo,Irp);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
status = PnpQueryRemoveDeviceHandler(fdo,Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
status = PnpSurpriseRemovalHandler(fdo, Irp);
break;
case IRP_MN_REMOVE_DEVICE:
status = PnpRemoveDeviceHandler(fdo,Irp);
return status;
case IRP_MN_QUERY_STOP_DEVICE:
dx->Paused = true;
dx->IODisabled = true;
status = PnpDefaultHandler(fdo,Irp);
break;
case IRP_MN_STOP_DEVICE:
status = PnpStopDeviceHandler(fdo,Irp);
break;
case IRP_MN_QUERY_CAPABILITIES:
status = PnpQueryCapabilitiesHandler(fdo.Irp);
break;
case IRP_MN_CANCEL_REMOVE_DEVICE: // fall thru case IRP_MN_CANCEL_STOP_DEVICE:
dx->Paused = false;
dx-> IODisabled = false;
status = PnpDefaultHandler(fdo,Irp);
break;
default:
status = PnpDefaultHandler(fdo,Irp);
}
UnlockDevice(dx);
#if DBG
if (status!=STATUS_SUCCESS) DebugPrint('PnP completed %x',status);
#endif
return status;
}
For
One IRP stack location is reserved for each possible device in a device stack. When an IRP is passed to the next driver, the next stack location must be set up for it. However, in this case, the Wdm2 driver is never going to need to look at the IRP or its stack location again.
You need to set up the next IRP stack location properly if you are going to inspect the IRP processing results or even simply wait for the IRP to complete. Use the routine