Dear All,
I have a question for you guys about IOCancelIrp(). I have implemented a USB streaming driver based on DDK sample ISOUSB, but I encounted a problem that if this driver is run under Windows XP, IOCanelIrp take no effect because the return status of IRP has no chance be STATUS_CANCELLED. If this driver is run under Vista ( x86 or X64 ), it will work properly as expected. The following is the code and I would like to know if I did something wrong.
-
Starting transfer by invoking function IsoUsb_StartTransfer() that will generate 2 IRPs and set a completion roution to resend the IRPs or cancel the IRP.
-
Stop transferring by calling function IsoUsb_StreamObjectCleanup() that will cancel the IRP by calling IOCancelIRP()
-
completion routine will check the status of IRP to see if it is cancelled. If so, it will free the IRPs and return STATUS_MORE_PROCESSING_REQUIRED. If not, it will resent the IRPs and return STATUS_MORE_PROCESSING_REQUIRED.
Best Regards,
FengChang
NTSTATUS
IsoUsb_StartTransfer(
IN PDEVICE_OBJECT DeviceObject,
IN PISOUSB_STREAM_OBJECT StreamObject,
IN ULONG Index
)
{
irp = IoAllocateIrp(stackSize, FALSE);
transferObject->Irp = irp;
IsoUsb_InitializeStreamUrb(DeviceObject, transferObject);
StreamObject->TransferObjectList[Index] = transferObject;
InterlockedIncrement(&StreamObject->PendingIrps);
nextStack = IoGetNextIrpStackLocation(irp);
nextStack->Parameters.Others.Argument1 = transferObject->Urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
IoSetCompletionRoutine(irp,
IsoUsb_IsoIrp_Complete,
transferObject,
TRUE,
TRUE,
TRUE);
…
ntStatus = IoCallDriver(deviceExtension-TopOfStackDeviceObject,
irp);
IsoUsb_IsoIrp_Complete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
…
ntStatus = IsoUsb_ProcessTransfer(transferObject);
…
if((ntStatus == STATUS_CANCELLED) ||
(ntStatus == STATUS_DEVICE_NOT_CONNECTED)) {
);
…
transferObject->Irp = NULL;
IoFreeIrp(Irp);
…
return STATUS_MORE_PROCESSING_REQUIRED;
}
//
// otherwise circulate the irps.
//
…
ntStatus = IoCallDriver(deviceExtension
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
IsoUsb_StreamObjectCleanup(
IN PISOUSB_STREAM_OBJECT StreamObject,
IN PDEVICE_EXTENSION DeviceExtension
)
{
//
// cancel transferobject irps/urb pair
// safe to touch these irps because the
// completion routine always returns
// STATUS_MORE_PRCESSING_REQUIRED
//
//
for(i = 0; i < ISOUSB_MAX_IRP; i++) {
if(StreamObject->TransferObjectList[i] &&
StreamObject->TransferObjectList[i]->Irp) {
IoCancelIrp(StreamObject->TransferObjectList[i]->Irp);
}
}