question of function IOcancelIrp()

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.

  1. 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.

  2. Stop transferring by calling function IsoUsb_StreamObjectCleanup() that will cancel the IRP by calling IOCancelIRP()

  3. 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);
}
}

adroit@ms4.hinet.net wrote:

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.

  1. 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.

  2. Stop transferring by calling function IsoUsb_StreamObjectCleanup() that will cancel the IRP by calling IOCancelIRP()

  3. 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.

IoCancelIrp is just a polite request to whatever driver holds the IRP.
If the lower driver doesn’t check for a cancellation request after you
call IoCancelIrp, then it will never be cancelled.

Are you sure the IRPs aren’t already completed by the time you cancel them?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Dear Tim,
Thanks for your reply, and I am quite sure the IRP cannot be completed when I call IoCancellIRP() because in Windebug, when I call IoCancellIRP(), I can see the flag is set to 1, but when I move to next statement, It will be reset to zero, and as mentioned before, I only happens under Windows XP, but not under Vista. That’s Why I am wondering.