Hello
I live a contradiction how to use IoCsqRemoveNextIrp, DPC and DriverStartIo.
1-) In that example:
https://secure.codeproject.com/KB/system/KernelToUserMode.aspx
a. NTSTATUS DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PFDO_DATA deviceExtension = (PFDO_DATA)DeviceObject->DeviceExtension;
// Insert IRP in our read queue. The IRQ handling routines will remove it from the queue.
IoCsqInsertIrp(&deviceExtension->CSReadQueue, Irp, NULL);
return STATUS_PENDING;
}
b.VOID DpcForIsrRoutine(PKDPC pDpc, PVOID pContext, PVOID pArg1, PVOID pArg2)
{
PFDO_DATA deviceExtension = (PFDO_DATA)pContext;
PIO_STACK_LOCATION IrpStack;
PIRP Irp;
PUCHAR Buffer;
ULONG NumberOfBytesPutInTheBuffer;
// Get an IRP from the queue.
Irp = IoCsqRemoveNextIrp(&deviceExtension->CSReadQueue, NULL);
if (Irp != NULL)
{
IrpStack = IoGetCurrentIrpStackLocation(Irp);
// Get access to user buffer.
Buffer = (PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
// Put something into the buffer. The size of the buffer is in IrpStack->Parameters.Read.Length
NumberOfBytesPutInTheBuffer = IrpStack->Parameters.Read.Length;
RtlFillMemory(Buffer, NumberOfBytesPutInTheBuffer, 0xaa);
// Complete the IRP and return the number of bytes we actually put into the buffer.
Irp->IoStatus.Information = NumberOfBytesPutInTheBuffer;
Irp->IoStatus.Status = STATUS_SUCCESS;
KeFlushIoBuffers(Irp->MdlAddress, TRUE, FALSE);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
// DCP routine finished, enable interrupts again.
EnableIRQ(deviceExtension);
}
Dispatch Read function just queue the IRP into a CSQ and when an IRQ arrives, queue DPC routine with KeInsertQueueDpc() and in DPC routine:
a. Call IoCsqRemoveNextIrp() to get the IRP that queued in the Read dispatch routine.
b. Get access to the user buffer.
2-) Second approach use a driver-supplied locking mechanism and include a Cancel routine.
a.First call DispatchReadWrite
b.DispatchReadWrite calls DriverStartIo()
c. StartIo calls KeSynchronizeExecution(pdx->InterruptObject, (PKSYNCHRONIZE_ROUTINE) TransferFirst, pdx);
d. TransferFirst makes the operation(IN/OUT)
e.DpcForIsr just calls StartNextPacket.
I know using a driver-supplied locking mechanism and include a Cancel routine and using the cancel-safe IRP queuing mechanism (IoCsqXxx) are different.
My questions are:
1-)Is just making transfer operation in DPC routine enough for cancel-safe IRP queuing mechanism? No StartIo, no Transferfunction routine which is called from StartIo
2-)If not how must we code our DpcForIsr routine, (and make relation with DriverStartIo routine) when using the cancel-safe IRP queuing mechanism?
Thanks…