I wrote a driver that is not allowing a console application which is blocked
on a synchronous ReadFile() to be killed
(ctrl-C or taskmanager). Nor can I remove the driver with out rebooting the
system. What am I doing wrong -- details below.
I have created a pure software driver that reads and writes from an internal
buffer. If data is available the read IRP
it will complete immedately, else it will PEND. A Device I/O Control is used
to indicate that data is available, and
if a read IRP is pending will complete it.
I have tested with a TestRead.exe that syncrhonously reads the device and a
TestRelease program that writes
and sends the IOCTL_RELEASE_READ. Things work fine with the test program
interaction, immediately reading or blocking until data is availalbe.
HOWEVER, when I run the TestRead and it blocks I can not Ctrl-C the program
or use the TaskManager to kill the program. Why is this? I understood that
the I/O Manager was support to clean all the synchronous calls/Reads and
allow exit of the program, but this is not happening. What am I missing?
Below are what I believe to be the critical pieces:
NTSTATUS DispatchRead (IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
[ declarations ...]
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDevObj->DeviceExtension;
if (pDevExt->bDataReady) {
[fill read buffer ...]
// Now complete the IRP
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = nBytes; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return status;
} else {
pDevExt->pIrpPendingRead = pIrp; // save pointer to IRP
status = STATUS_PENDING;
IoMarkIrpPending(pIrp);
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0; // bytes xfered
return status;
}
}
NTSTATUS DispatchIoControl(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp ) {
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDevObj->DeviceExtension;
// Release read is send when data is available
if (pIrpStack->Parameters.DeviceIoControl.IoControlCode
== IOCTL_RELEASE_READ ) {
if (pDevExt->pIrpPendingRead == NULL) {
pDevExt->bDataReady = TRUE
} else {
// The stack location contains the user buffer info
PIO_STACK_LOCATION pPendingIrpStack =
IoGetCurrentIrpStackLocation( pDevExt->pIrpPendingRead );
[decls and read Irp buffer copy stuff ...]
// Complete Pending Read IRP
pDevExt->pIrpPendingRead->IoStatus.Information = nBytes;
pDevExt->pIrpPendingRead->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( pDevExt->pIrpPendingRead, IO_NO_INCREMENT );
pDevExt->pIrpPendingRead = NULL; // "remove from queue of one"
}
// Complete Device IO Irp
pIrp->IoStatus.Information = pDevExt->bSetPendingRead;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
} else {
[ not implemented completion of IRP ...]
return status;
}
}