IoCsqRemoveNextIrp in DPC

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…

I’ve never used the StartIo/IoStartNextPacket interface in a driver and
never intend to. I suggest that you should not bother with queuing interface
either. It should generally be considered obsolete. Just use your own cancel
safe queues.
Mark Roddy

On Wed, Dec 10, 2008 at 6:05 AM, wrote:

> 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…
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>