none
Sending Zero Length Packet RRS feed

  • Question

  • Hi,

    I am trying to change a usb driver to send a zero length packet whenever the buffer length of a urb is a multiple of 64. I set a variable zeroLengthPacket = 1 whenever a packet with multiple of 64 comes into my readwrite function and in the completeasynccall function below i create a zero length urb and submit it if zeroLengthPacket = 1. But my driver crashes with 0xa at the  IoCompleteRequest(pIrp, IO_NO_INCREMENT); statement. It would be great if someone could help me figure out what i am doing wrong. Thanks.

    CompleteAsyncCall(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
    {
       NTSTATUS          ntStatus = STATUS_SUCCESS;
       PURB              pAsyncUrb;
       PASYNC_IO_CONTEXT pContext = Context;
       PDEVICE_OBJECT    pDo;
       PDEVICE_EXTENSION pDx;
       PUSBD_INTERFACE_INFORMATION   pInterfaceObject = NULL;
       PUSBD_PIPE_INFORMATION  pPipeInfo = NULL;
       USBD_PIPE_HANDLE        PipeHandle = NULL;
       ULONG                   transferFlags = USBD_SHORT_TRANSFER_OK;
       char *            pStr = "Wr Cmplt";

       ASSERT( pContext->aicDeviceObject );
       if( pContext->aicDeviceObject ) {
          //
          // We have to get the deviceObject from the context, since the DeviceObject passed in
          //  here belongs to the next lower driver in the stack because we were invoked via
          //  IoCallDriver in AeReadWrite()
          //
          pDo = pContext->aicDeviceObject;
          pContext->aicDeviceObject = 0;
          pDx = pDo->DeviceExtension;

          ASSERT( pContext->aicIrp == pIrp );
          if( pContext->aicIrp == pIrp ) {
             //
             // If the lower driver returned PENDING, mark our stack location as pending also.
             //
             if ( pIrp->PendingReturned ) {
                IoMarkIrpPending(pIrp);
             }

             pAsyncUrb = pContext->aicUrb;
             if(pAsyncUrb) {
                pContext->aicUrb = 0;

                //
                // IoCallDriver has been called on this Irp;
                // Set the length based on the TransferBufferLength
                // value in the URB
                //
                pIrp->IoStatus.Information =
                   pAsyncUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;

                //
                // If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the
                // URB status in the device extension.  After a failure, another IOCTL,
                // IOCTL_AaEcmUsbGET_LAST_ERROR can be used to retrieve the URB status
                // for the most recently failed URB.  Of course, this status gets
                // overwritten by subsequent failures, but it's better than nothing.
                //
                pIrp->IoStatus.Status = STATUS_SUCCESS;
                if (!(USBD_SUCCESS(pAsyncUrb->UrbHeader.Status))) {
                   pDx->LastFailedUrbStatus = pAsyncUrb->UrbHeader.Status;
                   pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
                }


                pContext->aicIrp = 0;

                ExFreePool(pAsyncUrb);
                AaUsbKdPrint (("Ex Pool Freed\n"));
                //
                // Mark the IRP as complete
                //
       AaUsbKdPrint (("pIrp Address is %x\n", pIrp));
       IoCompleteRequest(pIrp, IO_NO_INCREMENT);
             }  //end if(pAsyncUrb)
          }  //end if( pContext->aicIrp == pIrp )
       }  //end if( pContext->aicDeviceObject )


       //
       // Tell the I/O mangler not to diddle with the current IRP
       //
       if(zeroLengthPacket)
       {
      
          PURB pAsyncUrb = NULL;
       PIRP Irp = NULL;
       PIO_STACK_LOCATION nextStack;
       Irp = IoAllocateIrp(pDeviceObject->StackSize, FALSE);
       pAsyncUrb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
      
       UsbBuildInterruptOrBulkTransferRequest(
             pAsyncUrb,    //ptr to urb
             (USHORT) sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), //size of urb
             NULL,         //usbd pipe handle
             0,            //TransferBuffer
             NULL,             //mdl
             NULL,              //bufferlength
             transferFlags,   //flags
             NULL);
         
       nextStack = IoGetNextIrpStackLocation(Irp);
          ASSERT(nextStack != NULL);

          //
          // pass the URB to the USB driver stack
          //
          //AaUsbKdPrint(("Sending zero-length packet\n"));
          nextStack->Parameters.Others.Argument1 = pAsyncUrb;
          nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
          nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
          AaUsbKdPrint(("Sending zero-length packet\n"));

       pContext->aicDeviceObject = pDeviceObject;
          pContext->aicUrb = pAsyncUrb;
          pContext->aicIrp = Irp;

       IoSetCompletionRoutine(
                               Irp,
                               AeCompleteAsyncCall,
                               pContext,    // pass context pointer to completion routine
                               TRUE,     // invoke on success
                               TRUE,     // invoke on error
                               TRUE);     // invoke on cancellation of the Irp

          //
          // Post the request to the system driver
          //
          AaUsbKdPrint(("IoSetCompletion\n"));
          AaUsbKdPrint(("out\n"));
       AaUsbKdPrint (("ZeroLength Address is %x\n", Irp));
          ntStatus = IoCallDriver(pDx->TopOfStackDeviceObject, Irp);
      
          AaUsbKdPrint(("Called Driver\n"));
          if(ntStatus != STATUS_PENDING) {
             //
             //    This is a bug trap
             //
             AaUsbKdPrint (("AeReadWrite: Bug Alert!!! IoCallDriver returned (%x);%d\n", ntStatus));
       }

    IoFreeIrp(Irp)

       }
       return STATUS_MORE_PROCESSING_REQUIRED;
    }

    Wednesday, October 10, 2012 10:21 PM

All replies

  • show the output of !analyze -v. you cannot complete a pirp that you allocated. is AeCompleteAsyncCall the same a CompleteAsyncCall at the top of your code snippet? if yes, this is an irp you allocated and you should IoFreeIrp it instead

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, October 11, 2012 4:56 AM
  • Hi,

    Thanks for the reply. I changed my code and replaced the complete call with IoFreeIrp like shown below but now the driver crashes. I have the analyze part of windbg inlcuded in the post. Any help would be greatly appreciated. 4

    Code:

    NTSTATUS
    AeCompleteAsyncCall(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
    {
       NTSTATUS          ntStatus = STATUS_SUCCESS;
       PURB              pAsyncUrb;
       PASYNC_IO_CONTEXT pContext = Context;
       PDEVICE_OBJECT    pDo;
       PDEVICE_EXTENSION pDx;
       PUSBD_INTERFACE_INFORMATION   pInterfaceObject = NULL;
       PUSBD_PIPE_INFORMATION  pPipeInfo = NULL;
       USBD_PIPE_HANDLE        PipeHandle = NULL;
       ULONG                   transferFlags = USBD_SHORT_TRANSFER_OK;
       char *            pStr = "Wr Cmplt";

       ASSERT( pContext->aicDeviceObject );
       if( pContext->aicDeviceObject ) {
          //
          // We have to get the deviceObject from the context, since the DeviceObject passed in
          //  here belongs to the next lower driver in the stack because we were invoked via
          //  IoCallDriver in AeReadWrite()
          //
          pDo = pContext->aicDeviceObject;
          pContext->aicDeviceObject = 0;
          pDx = pDo->DeviceExtension;

          ASSERT( pContext->aicIrp == pIrp );
          if( pContext->aicIrp == pIrp ) {
             //
             // If the lower driver returned PENDING, mark our stack location as pending also.
             //
             if ( pIrp->PendingReturned ) {
                IoMarkIrpPending(pIrp);
             }

             pAsyncUrb = pContext->aicUrb;
             if(pAsyncUrb) {
                pContext->aicUrb = 0;

    #ifdef FULL_DEBUG
                if(pAsyncUrb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN) {
                   pStr = "Rd Cmplt";
                }
                AaUsbKdPrint(("%s: Lt: 0x%04X; St 0x%08X;\n",
                pStr,
                pAsyncUrb->UrbBulkOrInterruptTransfer.TransferBufferLength,
                pAsyncUrb->UrbHeader.Status));
    #endif

                //
                // IoCallDriver has been called on this Irp;
                // Set the length based on the TransferBufferLength
                // value in the URB
                //
                pIrp->IoStatus.Information =
                   pAsyncUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;

                //
                // If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the
                // URB status in the device extension.  After a failure, another IOCTL,
                // IOCTL_AaEcmUsbGET_LAST_ERROR can be used to retrieve the URB status
                // for the most recently failed URB.  Of course, this status gets
                // overwritten by subsequent failures, but it's better than nothing.
                //
                pIrp->IoStatus.Status = STATUS_SUCCESS;
                if (!(USBD_SUCCESS(pAsyncUrb->UrbHeader.Status))) {
                   pDx->LastFailedUrbStatus = pAsyncUrb->UrbHeader.Status;
                   pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
                }


                pContext->aicIrp = 0;

                ExFreePool(pAsyncUrb);
                AaUsbKdPrint (("Ex Pool Freed\n"));
                //
                // Mark the IRP as complete
                //
       AaUsbKdPrint (("pIrp Address is %x\n", pIrp));
       IoCompleteRequest(pIrp, IO_NO_INCREMENT);
       AaUsbKdPrint (("pIrp Completion\n"));

       if(zeroLengthPacket)
       {
      
          PURB pAsyncUrb = NULL;
       PIRP Irp = NULL;
          PIO_STACK_LOCATION nextStack;
       zeroLengthPacket = 0;
       freeLocation = 1;
       Irp = IoAllocateIrp(pDeviceObject->StackSize, FALSE);
       pAsyncUrb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
      
       UsbBuildInterruptOrBulkTransferRequest(
             pAsyncUrb,    //ptr to urb
             (USHORT) sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), //size of urb
             NULL,         //usbd pipe handle
             0,            //TransferBuffer
             NULL,             //mdl
             NULL,              //bufferlength
             transferFlags,   //flags
             NULL);
         
       nextStack = IoGetNextIrpStackLocation(Irp);
          ASSERT(nextStack != NULL);

          //
          // pass the URB to the USB driver stack
          //
          //AaUsbKdPrint(("Sending zero-length packet\n"));
          nextStack->Parameters.Others.Argument1 = pAsyncUrb;
          nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
          nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
          AaUsbKdPrint(("Sending zero-length packet\n"));

       pContext->aicDeviceObject = pDeviceObject;
          pContext->aicUrb = pAsyncUrb;
          pContext->aicIrp = Irp;

       /*IoSetCompletionRoutine(
                               Irp,
                               AeCompleteAsyncCall,
                               pContext,    // pass context pointer to completion routine
                               TRUE,     // invoke on success
                               TRUE,     // invoke on error
                               TRUE);     // invoke on cancellation of the Irp

          //
          // Post the request to the system driver
          */
          AaUsbKdPrint(("IoSetCompletion\n"));
          AaUsbKdPrint(("out\n"));
       AaUsbKdPrint (("ZeroLength Address is %x\n", Irp));
          ntStatus = IoCallDriver(pDx->TopOfStackDeviceObject, Irp);
      
          AaUsbKdPrint(("Called Driver\n"));
          if(ntStatus != STATUS_PENDING) {
             //
             //    This is a bug trap
             //
          AaUsbKdPrint (("AeReadWrite: Bug Alert!!! IoCallDriver returned (%x);%d\n", ntStatus));
       ExFreePool(pAsyncUrb);
       IoFreeIrp(Irp);
       }
       }

            
             }  //end if(pAsyncUrb)
          }  //end if( pContext->aicIrp == pIrp )
       }  //end if( pContext->aicDeviceObject )

       //
       // Tell the I/O mangler not to diddle with the current IRP
       //
      
       return STATUS_MORE_PROCESSING_REQUIRED;
    }

    Output from Windbg:

    *** Fatal System Error: 0x0000000a
                           (0x00000166,0x00000002,0x00000000,0x804FA726)

    Break instruction exception - code 80000003 (first chance)

    A fatal system error has occurred.
    Debugger entered on first try; Bugcheck callbacks have not been invoked.

    A fatal system error has occurred.

    Connected to Windows XP 2600 x86 compatible target at (Fri Oct 12 10:22:51.313 2012 (UTC - 7:00)), ptr64 FALSE
    Loading Kernel Symbols
    ...............................................................
    .......................................
    Loading User Symbols
    .............................
    Loading unloaded module list
    ................
    *******************************************************************************
    *                                                                             *
    *                        Bugcheck Analysis                                    *
    *                                                                             *
    *******************************************************************************

    Use !analyze -v to get detailed debugging information.

    BugCheck A, {166, 2, 0, 804fa726}

    Probably caused by : AriumUsb.sys ( AriumUsb!AeCompleteAsyncCall+30d )

    Followup: MachineOwner
    ---------

    nt!RtlpBreakWithStatusInstruction:
    80526da8 cc              int     3
    kd> !analyze -v
    *******************************************************************************
    *                                                                             *
    *                        Bugcheck Analysis                                    *
    *                                                                             *
    *******************************************************************************

    IRQL_NOT_LESS_OR_EQUAL (a)
    An attempt was made to access a pageable (or completely invalid) address at an
    interrupt request level (IRQL) that is too high.  This is usually
    caused by drivers using improper addresses.
    If a kernel debugger is available get the stack backtrace.
    Arguments:
    Arg1: 00000166, memory referenced
    Arg2: 00000002, IRQL
    Arg3: 00000000, bitfield :
     bit 0 : value 0 = read operation, 1 = write operation
     bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
    Arg4: 804fa726, address which referenced memory

    Debugging Details:
    ------------------


    READ_ADDRESS:  00000166

    CURRENT_IRQL:  2

    FAULTING_IP:
    nt!KeInsertQueueApc+22
    804fa726 389e66010000    cmp     byte ptr [esi+166h],bl

    DEFAULT_BUCKET_ID:  INTEL_CPU_MICROCODE_ZERO

    BUGCHECK_STR:  0xA

    PROCESS_NAME:  sp.exe

    TAG_NOT_DEFINED_c000000f:  FFFFFFFFF7A16000

    TRAP_FRAME:  f7a15c5c -- (.trap 0xfffffffff7a15c5c)
    ErrCode = 00000000
    eax=00000002 ebx=00000000 ecx=00000002 edx=f7a15cdc esi=00000000 edi=863aa770
    eip=804fa726 esp=f7a15cd0 ebp=f7a15ce8 iopl=0         nv up ei pl zr na pe nc
    cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010246
    nt!KeInsertQueueApc+0x22:
    804fa726 389e66010000    cmp     byte ptr [esi+166h],bl     ds:0023:00000166=??
    Resetting default scope

    LAST_CONTROL_TRANSFER:  from 804f780d to 80526da8

    STACK_TEXT: 
    f7a15810 804f780d 00000003 f7a15b6c 00000000 nt!RtlpBreakWithStatusInstruction
    f7a1585c 804f83fa 00000003 00000166 804fa726 nt!KiBugCheckDebugBreak+0x19
    f7a15c3c 8053f853 0000000a 00000166 00000002 nt!KeBugCheck2+0x574
    f7a15c3c 804fa726 0000000a 00000166 00000002 nt!KiTrap0E+0x233
    f7a15ce8 804f0498 863aa770 00000000 00000000 nt!KeInsertQueueApc+0x22
    f7a15d1c f7241090 8644d0ec f7a15d58 f7252e5b nt!IopfCompleteRequest+0x1d8
    f7a15d28 f7252e5b 86327030 863aa730 c000000d USBPORT!USBPORT_CompleteIrp+0x2a
    f7a15d58 f7257dfe 86327030 72726555 00000090 USBPORT!USBPORT_ProcessURB+0x4f3
    f7a15d78 f72411e2 86327030 863aa730 863aa730 USBPORT!USBPORT_PdoInternalDeviceControlIrp+0x7e
    f7a15d9c 804eddf9 863aa7e8 86327188 863d9730 USBPORT!USBPORT_Dispatch+0x148
    f7a15dac f775e50a f7a15dd4 f77622d9 863aa730 nt!IopfCallDriver+0x31
    f7a15db4 f77622d9 863aa730 86327030 863aa730 usbhub!USBH_PassIrp+0x18
    f7a15dd4 f7762afa 863350e8 863aa730 863ad39f usbhub!USBH_PdoUrbFilter+0xbd
    f7a15df0 f77601d8 863d9730 863aa730 f7a15e4c usbhub!USBH_PdoDispatch+0x202
    f7a15e00 804eddf9 86231dc0 863aa730 863ad308 usbhub!USBH_HubDispatch+0x48
    f7a15e10 f79f227a 863d9730 863aa7e8 863aa730 nt!IopfCallDriver+0x31
    f7a15e4c 804f0362 864616f0 863ad308 86461808 AriumUsb!AeCompleteAsyncCall+0x30d [C:\Users\jochens.ARIUM\AA\AaEcmUsb\AaEcmUsb\Src_6.0\AaEcmUsb.c @ 2675]
    f7a15e7c f7248ee5 863ad308 863eb748 8644d028 nt!IopfCompleteRequest+0xa2
    f7a15ee4 f7249b57 863d9730 00000000 8644d7d8 USBPORT!USBPORT_CompleteTransfer+0x373
    f7a15f14 f724a754 026e6f44 8644d0e0 8644d0e0 USBPORT!USBPORT_DoneTransfer+0x137
    f7a15f4c f724bf6a 8644d028 805418a8 8644d230 USBPORT!USBPORT_FlushDoneTransferList+0x16c
    f7a15f78 f7259fb0 8644d028 805418a8 8644d028 USBPORT!USBPORT_DpcWorker+0x224
    f7a15fb4 f725a128 8644d028 00000001 3f013c90 USBPORT!USBPORT_IsrDpcWorker+0x37e
    f7a15fd0 80540d5d 8644d64c 6b755044 00000000 USBPORT!USBPORT_IsrDpc+0x166
    f7a15ff4 80540a2a f6bec85c 00000000 00000000 nt!KiRetireDpcList+0x46
    f7a15ff8 f6bec85c 00000000 00000000 00000000 nt!KiDispatchInterrupt+0x2a
    WARNING: Frame IP not in any known module. Following frames may be wrong.
    80540a2a 00000000 00000009 bb835675 00000128 0xf6bec85c


    STACK_COMMAND:  kb

    FOLLOWUP_IP:
    AriumUsb!AeCompleteAsyncCall+30d [C:\Users\jochens.ARIUM\AA\AaEcmUsb\AaEcmUsb\Src_6.0\AaEcmUsb.c @ 2675]
    f79f227a 8945d8          mov     dword ptr [ebp-28h],eax

    FAULTING_SOURCE_LINE:  C:\Users\jochens.ARIUM\AA\AaEcmUsb\AaEcmUsb\Src_6.0\AaEcmUsb.c

    FAULTING_SOURCE_FILE:  C:\Users\jochens.ARIUM\AA\AaEcmUsb\AaEcmUsb\Src_6.0\AaEcmUsb.c

    FAULTING_SOURCE_LINE_NUMBER:  2675

    FAULTING_SOURCE_CODE: 
      2671:       */
      2672:       AaUsbKdPrint(("IoSetCompletion\n"));
      2673:       AaUsbKdPrint(("out\n"));
      2674:    AaUsbKdPrint (("ZeroLength Address is %x\n", Irp));
    > 2675:       ntStatus = IoCallDriver(pDx->TopOfStackDeviceObject, Irp);
      2676:   
      2677:       AaUsbKdPrint(("Called Driver\n"));
      2678:       if(ntStatus != STATUS_PENDING) {
      2679:          //
      2680:          //    This is a bug trap

    Friday, October 12, 2012 5:33 PM
  • you need to debug this further. a couple of things

    1) if you allocated the irp, you can't mark it as pending because it touches the current stack location which in a self allocated irp,does not exist

          if( pContext->aicIrp == pIrp ) {
             //
             // If the lower driver returned PENDING, mark our stack location as pending also.
             //
             if ( pIrp->PendingReturned ) {
                IoMarkIrpPending(pIrp); <== don't do this if you allocated the irp yourself
              }

    2) this means a null deref

    Arg1: 00000166, memory referenced

    in the completion path, this particular bug means the io manager is trying to finalize the completion of an irp and because it is not a threaded irp, the thread deref fails and you blow up. this means either

    a) you did not set a completion routine at all

    or

    b) you returned something other than STATUS_MORE_PROCESSING_REQUIRED.

    please enable your own logging and when you crash, look at the logging to be more self sufficient in diagnosing the bug


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Friday, October 12, 2012 6:07 PM
  • looking at your code, I see it is case a), you are not setting a completion routine, you have commented out the following code

           pContext->aicIrp = Irp;

       /*IoSetCompletionRoutine(  <== boom, this needs to be real code
                                Irp,
                                AeCompleteAsyncCall,
                                pContext,    // pass context pointer to completion routine
                                TRUE,     // invoke on success
                                TRUE,     // invoke on error
                                TRUE);     // invoke on cancellation of the Irp

          //
           // Post the request to the system driver
           */

    if this is the user's request, this is fine. if this is a self allocated request, you can't do this.

        AaUsbKdPrint (("pIrp Address is %x\n", pIrp));
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        AaUsbKdPrint (("pIrp Completion\n"));

    personal opinion: overall, this code is a complete mess. completely unreadable and unmaitainable. you basically have two or more state machines here. I would use a different completion routine to do the segmentation vs the final ZLP. make it more composable and clear


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    • Marked as answer by Doron Holan [MSFT] Friday, October 12, 2012 6:24 PM
    • Unmarked as answer by Jochen12 Tuesday, November 20, 2012 11:06 PM
    Friday, October 12, 2012 6:23 PM
  • I tried to split the zero length package function and came up with this: My driver is still crashing and I am not sure what to do. I would like to use a new irp but it crashes when i do the following. Thanks for the help.

    Irp = IoAllocate(DeviceObject->StackSize, FALSE)

     irpStack = IoGetCurrentIrpStackLocation (Irp);
     pFileObject = irpStack->FileObject;
     pChnl = pFileObject->FsContext;

    /**************************************************************************************
     *
     * Function Name: NTSTATUS AeReadWrite(
     *                                     IN PDEVICE_OBJECT pFdo,
     *             IN PIRP Irp
     *             )
     *
     *
     * Parameters: IN PDEVICE_OBJECT pFdo  =  pointer to the device object.
     *             IN PIRP Irp             =  pointer to I/O request packet.
     *
     * Returns: STATUS_SUCCESS if successful, else one of the following error codes
     *          from ntstatus.h:
     *          STATUS_INVALID_PARAMETER_3:   The Endpoint Index does not specify
     *                                        an IN pipe
     *          STATUS_NO_MEMORY: Insufficient data memory was supplied
     *                            to perform the READ
     *
     * Description:
     *
     * AeReadWrite performs all I/O requests asynchronously.  We allow one I/O
     * request for each pipe of the given channel.
     *
     **************************************************************************************
     */

    NTSTATUS
    AeReadWrite(IN  PDEVICE_OBJECT pFdo, IN  PIRP Irp)
    {
       PDEVICE_EXTENSION       pDx = pFdo->DeviceExtension;
       NTSTATUS                ntStatus;
       PIO_STACK_LOCATION      irpStack = IoGetCurrentIrpStackLocation (Irp);
       PIO_STACK_LOCATION      nextStack;
       PBULK_TRANSFER_CONTROL  bulkControl =
                               (PBULK_TRANSFER_CONTROL)Irp->AssociatedIrp.SystemBuffer;
       ULONG                   bufferLength =
                               irpStack->Parameters.DeviceIoControl.OutputBufferLength;
       ULONG                   urbSize = 0;
       ULONG                   transferFlags = 0;
       ULONG                   PipeNo = 0;
       PFILE_OBJECT            pFileObject;
       PAAECM_CHANNEL          pChnl;
       PUSBD_INTERFACE_INFORMATION   pInterfaceObject = NULL;
       PUSBD_PIPE_INFORMATION  pPipeInfo = NULL;
       USBD_PIPE_HANDLE        PipeHandle = NULL;
       PURB                    pAsyncUrb = NULL;
       PASYNC_IO_CONTEXT       pContext = NULL;
       PIRP tIrp;

    #ifdef FULL_DEBUG
       AaUsbKdPrint(("enter AeReadWrite()\n"));
       AaUsbKdPrint(("ReadWrite IRP Address %x\n", Irp));
    #endif

       //
       // verify that the selected pipe is valid, and get a handle to it. If anything
       // is wrong, return an error
       //
       pInterfaceObject = pDx->pUsbInterface;

       if (!pInterfaceObject) {
          AaUsbKdPrint(("AeReadWrite() no interface info - Exiting\n"));
          ntStatus = STATUS_INVALID_DISPOSITION;
          goto rwErrXit;
       }
      
       //
       // Get the channel info associated with this channel...
       //
       irpStack = IoGetCurrentIrpStackLocation (Irp);
       pFileObject = irpStack->FileObject;
       pChnl = pFileObject->FsContext;

       //
       // Validate I/O request and derive the index into channel block array
       //
       PipeNo = bulkControl->pipeNum;
       if(pChnl->ChnlNo == ECT_WDB_SESSION) {
          //
          // We only allow the app to specify pipe 0 or pipe 1 on channel 0
          //
          //
          if((PipeNo != 0) && (PipeNo != 1) || (!pChnl->ChnlRead && (PipeNo == 1))) {
             AaUsbKdPrint(("AeReadWrite() invalid pipe - Exiting\n"));
             ntStatus = STATUS_INVALID_PARAMETER_1;
             goto rwErrXit;
          }
          //
          // Channel 0 has three pipes
          //
          if(pChnl->ChnlRead) {
    #ifdef FULL_DEBUG
             AaUsbKdPrint(("Rd req\n"));
    #endif
    #ifdef ENABLE_INT_ENDPOINT  //!!!Debug Alert
             PipeNo = (PipeNo == 0) ? EET_BULK_READ : EET_INT_READ;
    #else
             PipeNo = EET_BULK_READ;
    #endif
          }
          else {
    #ifdef FULL_DEBUG
             AaUsbKdPrint(("Wr req\n"));
    #endif
             //
             // Select write endpoint
             //
             PipeNo = EET_BULK_WRITE;
          }

       } //end if(pChnl->ChnlNo == 0)
       else {
          //
          // Note that we ignore the pipe parameter for channel 1
          //
          PipeNo = (pChnl->ChnlRead) ? EET_BULK_READ : EET_BULK_WRITE;
       }
       //
       // Verify that the pipe is not busy
       //
       pContext = &(pChnl->ChnlIosPending[PipeNo]);
       if(pContext->aicDeviceObject != 0) {
          AaUsbKdPrint(("AeReadWrite() pipe busy - Exiting\n"));
          ntStatus = STATUS_PIPE_BUSY;
          goto rwErrXit;
       }
       pPipeInfo = pChnl->ChnlPipes[PipeNo];
       PipeHandle = pPipeInfo->PipeHandle;  


       //
       // Verify we have a pipe handle
       //
       if (!PipeHandle) {
          AaUsbKdPrint(("AeReadWrite() invalid pipe - Exiting\n"));
          ntStatus = STATUS_INVALID_PIPE_STATE;
          goto rwErrXit;
       }

       //
       // Validate the requested transfer size
       //
       if (bufferLength > pPipeInfo->MaximumTransferSize) {
          AaUsbKdPrint(("AeReadWrite() invalid transfer size - Exiting\n"));
          ntStatus = STATUS_INVALID_PARAMETER_2;
          goto rwErrXit;
       }
       AaUsbKdPrint(("BufferLength is %x\n", bufferLength));
      
       //
       // allocate and fill in the Usb request (URB)
       //
       urbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);

       pAsyncUrb = ExAllocatePool(NonPagedPool,urbSize);

       if (!pAsyncUrb) {
          AaUsbKdPrint(("AeReadWrite() unable to alloc URB - Exiting\n"));
          ntStatus = STATUS_NO_MEMORY;
          goto rwErrXit;
       }
      
       transferFlags = USBD_SHORT_TRANSFER_OK;

       //
       // Set the direction according to the requested operation.
       //
       if(pChnl->ChnlRead) {
       transferFlags |= USBD_TRANSFER_DIRECTION_IN;
       }

       if (zeroLength == 1)
       {
       UsbBuildInterruptOrBulkTransferRequest(
             pAsyncUrb,    //ptr to urb
             (USHORT) urbSize,  //size of urb
             PipeHandle,    //usbd pipe handle
             NULL,     //TransferBuffer
             Irp->MdlAddress,  //mdl
             0,   //bufferlength
             transferFlags,   //flags
             NULL);
       }
       else
       {

       UsbBuildInterruptOrBulkTransferRequest(
             pAsyncUrb,    //ptr to urb
             (USHORT) urbSize,  //size of urb
             PipeHandle,    //usbd pipe handle
             NULL,     //TransferBuffer
             Irp->MdlAddress,  //mdl
             bufferLength,   //bufferlength
             transferFlags,   //flags
             NULL);     //link

       }
       //
       // Call the USB Stack.
       //
       //ntStatus = AeAsyncCallUSBD(pFdo, urb);

       //
       // Prepare for calling the USB driver stack
       //
       nextStack = IoGetNextIrpStackLocation(Irp);
       ASSERT(nextStack != NULL);

       //
       // pass the URB to the USB driver stack
       //

       nextStack->Parameters.Others.Argument1 = pAsyncUrb;
       nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
       nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

       //
       // Set up the context block for the completion routine
       //
        pContext->aicDeviceObject = pFdo;
        pContext->aicUrb = pAsyncUrb;
        pContext->aicIrp = Irp;

       //
       // Set our completion routine for this operation
       //
      
       IoSetCompletionRoutine(
                               Irp,
                               AeCompleteAsyncCall,
                               pContext,    // pass context pointer to completion routine
                               TRUE,     // invoke on success
                               TRUE,     // invoke on error
                               TRUE);     // invoke on cancellation of the Irp

       //
       // Post the request to the system driver
       //
      
      
       //zeroLength = 0;
       ntStatus = IoCallDriver(pDx->TopOfStackDeviceObject, Irp);
       if (((bufferLength % 0x40) == 0) && (PipeNo == EET_BULK_WRITE))
          zeroLength = 1;
       if(ntStatus != STATUS_PENDING) {
          //
          // This is a bug trap
          //
          AaUsbKdPrint (("AeReadWrite: Bug Alert!!! IoCallDriver returned (%x);%d\n", ntStatus));
       }
    #ifdef FULL_DEBUG
       else {
          AaUsbKdPrint (("AeReadWrite: St(%x);\n", ntStatus));
       }
    #endif

         return ntStatus;

    rwErrXit:
       Irp->IoStatus.Status = ntStatus;
       Irp->IoStatus.Information = 0;
       IoCompleteRequest (Irp,IO_NO_INCREMENT);
       return ntStatus;
    }


    /**************************************************************************************
     *
     * Function Name: NTSTATUS AeCompleteAsyncCall(
     *                                              IN PDEVICE_OBJECT pDeviceObject,
     *                                              IN PIRP pIrp,
     *                                              IN PVOID Context
     *                                              )
     *
     *
     * Parameters: IN PDEVICE_OBJECT pFdo  =  pointer to the device object.
     *             IN PIRP Irp             =  pointer to completed I/O request packet.
     *             IN PVOID Context        =  our context block
     *
     * Returns: STATUS_SUCCESS if successful,
     *                            else the final status from the operation.
     *
     * Description:
     *
     * Completion routine for AeReadWrite initiated asynchronous I/O requests.
     *
     **************************************************************************************
     */

    NTSTATUS
    AeCompleteAsyncCall(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
    {
       NTSTATUS          ntStatus = STATUS_SUCCESS;
       PURB              pAsyncUrb;
       PASYNC_IO_CONTEXT pContext = Context;
       PDEVICE_OBJECT    pDo;
       PDEVICE_EXTENSION pDx;
       char *            pStr = "Wr Cmplt";
       AaUsbKdPrint(("AeCompleteAsyncCallt\n"));
       ASSERT( pContext->aicDeviceObject );
       if( pContext->aicDeviceObject) {
          //
          // We have to get the deviceObject from the context, since the DeviceObject passed in
          //  here belongs to the next lower driver in the stack because we were invoked via
          //  IoCallDriver in AeReadWrite()
          //
          pDo = pContext->aicDeviceObject;
          pContext->aicDeviceObject = 0;
          pDx = pDo->DeviceExtension;

          ASSERT( pContext->aicIrp == pIrp );
          if( pContext->aicIrp == pIrp ) {
             //
             // If the lower driver returned PENDING, mark our stack location as pending also.
             //
             if ( pIrp->PendingReturned ) {
                IoMarkIrpPending(pIrp);
             }
            
             pAsyncUrb = pContext->aicUrb;
             if(pAsyncUrb) {
                pContext->aicUrb = 0;

    #ifdef FULL_DEBUG
                if(pAsyncUrb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN) {
                   pStr = "Rd Cmplt";
                }
                AaUsbKdPrint(("%s: Lt: 0x%04X; St 0x%08X;\n",
                pStr,
                pAsyncUrb->UrbBulkOrInterruptTransfer.TransferBufferLength,
                pAsyncUrb->UrbHeader.Status));
    #endif

                //
                // IoCallDriver has been called on this Irp;
                // Set the length based on the TransferBufferLength
                // value in the URB
                //
                pIrp->IoStatus.Information =
                   pAsyncUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;

                //
                // If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the
                // URB status in the device extension.  After a failure, another IOCTL,
                // IOCTL_AaEcmUsbGET_LAST_ERROR can be used to retrieve the URB status
                // for the most recently failed URB.  Of course, this status gets
                // overwritten by subsequent failures, but it's better than nothing.
                //
                pIrp->IoStatus.Status = STATUS_SUCCESS;
                if (!(USBD_SUCCESS(pAsyncUrb->UrbHeader.Status))) {
                   pDx->LastFailedUrbStatus = pAsyncUrb->UrbHeader.Status;
                   pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
                }


                pContext->aicIrp = 0;

              
       
       
       //
       // Mark the IRP as complete
       //
       if(zeroLength == 1)
       {
          ExFreePool(pAsyncUrb);
          AaUsbKdPrint(("Before Complet\n"));
          //IoCompleteRequest(pIrp, IO_NO_INCREMENT);
          AeZlp(pDeviceObject, pIrp);
          //IoCompleteRequest(pIrp, IO_NO_INCREMENT);
                   AaUsbKdPrint(("After Complete\n"));
       }
       else
       {
          ExFreePool(pAsyncUrb);
          AaUsbKdPrint(("IRP AeC Address %x\n", pIrp));
          IoCompleteRequest(pIrp, IO_NO_INCREMENT);
       }
       
             }
       }  //end if( pContext->aicIrp == pIrp )
       }  //end if( pContext->aicDeviceObject )


       //
       // Tell the I/O mangler not to diddle with the current IRP
       //
       return STATUS_MORE_PROCESSING_REQUIRED;
    }

    /**************************************************************************************
     *
     * Function Name: NTSTATUS AeCompleteAsyncCall(
     *                                              IN PDEVICE_OBJECT pDeviceObject,
     *                                              IN PIRP pIrp,
     *                                              IN PVOID Context
     *                                              )
     *
     *
     * Parameters: IN PDEVICE_OBJECT pFdo  =  pointer to the device object.
     *             IN PIRP Irp             =  pointer to completed I/O request packet.
     *             IN PVOID Context        =  our context block
     *
     * Returns: STATUS_SUCCESS if successful,
     *                            else the final status from the operation.
     *
     * Description:
     *
     * Completion routine for AeReadWrite initiated asynchronous I/O requests.
     *
     **************************************************************************************
     */

    NTSTATUS
    AeZlp(IN PDEVICE_OBJECT pFdo, IN PIRP Irp)
    {
       PDEVICE_EXTENSION       pDx = pFdo->DeviceExtension;
       NTSTATUS                ntStatus;
       PIO_STACK_LOCATION      irpStack; // = IoGetCurrentIrpStackLocation (Irp);
       PIO_STACK_LOCATION      nextStack;
       PBULK_TRANSFER_CONTROL  bulkControl; //= (BULK_TRANSFER_CONTROL)Irp->AssociatedIrp.SystemBuffer;
       ULONG                   bufferLength = 0;
                               //irpStack->Parameters.DeviceIoControl.OutputBufferLength;
       ULONG                   urbSize = 0;
       ULONG                   transferFlags = 0;
       ULONG                   PipeNo = 0;
       PFILE_OBJECT            pFileObject;
       PAAECM_CHANNEL          pChnl;
       PUSBD_INTERFACE_INFORMATION   pInterfaceObject = NULL;
       PUSBD_PIPE_INFORMATION  pPipeInfo = NULL;
       USBD_PIPE_HANDLE        PipeHandle = NULL;
       PURB                    pAsyncUrb = NULL;
       //PIRP Irp;
       PASYNC_IO_CONTEXT       pContext = NULL;
       //zeroLength = 0;
       //Irp = IoAllocateIrp(pFdo->StackSize, FALSE);
      
    #ifdef FULL_DEBUG
       AaUsbKdPrint(("enter ZLP()\n"));
       AaUsbKdPrint(("ZLP IRP Address %x\n", Irp));
    #endif

       //
       // verify that the selected pipe is valid, and get a handle to it. If anything
       // is wrong, return an error
       //
       pInterfaceObject = pDx->pUsbInterface;

       if (!pInterfaceObject) {
          AaUsbKdPrint(("AeReadWrite() no interface info - Exiting\n"));
          ntStatus = STATUS_INVALID_DISPOSITION;
          goto rwErrXit;
       }
      
       //
       // Get the channel info associated with this channel...
       //
       irpStack = IoGetCurrentIrpStackLocation (Irp);
       pFileObject = irpStack->FileObject;
       pChnl = pFileObject->FsContext;

       //
       // Validate I/O request and derive the index into channel block array
       //
       bulkControl = (PBULK_TRANSFER_CONTROL)Irp->AssociatedIrp.SystemBuffer;
       PipeNo = bulkControl->pipeNum;
       if(pChnl->ChnlNo == ECT_WDB_SESSION) {
          //
          // We only allow the app to specify pipe 0 or pipe 1 on channel 0
          //
          //
          if((PipeNo != 0) && (PipeNo != 1) || (!pChnl->ChnlRead && (PipeNo == 1))) {
             AaUsbKdPrint(("AeReadWrite() invalid pipe - Exiting\n"));
             ntStatus = STATUS_INVALID_PARAMETER_1;
             goto rwErrXit;
          }
          //
          // Channel 0 has three pipes
          //
          if(pChnl->ChnlRead) {
    #ifdef FULL_DEBUG
             AaUsbKdPrint(("Rd req\n"));
    #endif
    #ifdef ENABLE_INT_ENDPOINT  //!!!Debug Alert
             PipeNo = (PipeNo == 0) ? EET_BULK_READ : EET_INT_READ;
    #else
             PipeNo = EET_BULK_READ;
    #endif
          }
          else {
    #ifdef FULL_DEBUG
             AaUsbKdPrint(("Wr req\n"));
    #endif
             //
             // Select write endpoint
             //
             PipeNo = EET_BULK_WRITE;
          }

       } //end if(pChnl->ChnlNo == 0)
       else {
          //
          // Note that we ignore the pipe parameter for channel 1
          //
          PipeNo = (pChnl->ChnlRead) ? EET_BULK_READ : EET_BULK_WRITE;
       }
       //
       // Verify that the pipe is not busy
       //
       pContext = &(pChnl->ChnlIosPending[PipeNo]);
       if(pContext->aicDeviceObject != 0) {
          AaUsbKdPrint(("AeReadWrite() pipe busy - Exiting\n"));
          ntStatus = STATUS_PIPE_BUSY;
          goto rwErrXit;
       }
       pPipeInfo = pChnl->ChnlPipes[PipeNo];
       PipeHandle = pPipeInfo->PipeHandle;  


       //
       // Verify we have a pipe handle
       //
       if (!PipeHandle) {
          AaUsbKdPrint(("AeReadWrite() invalid pipe - Exiting\n"));
          ntStatus = STATUS_INVALID_PIPE_STATE;
          goto rwErrXit;
       }

       //
       // Validate the requested transfer size
       //
       if (bufferLength > pPipeInfo->MaximumTransferSize) {
          AaUsbKdPrint(("AeReadWrite() invalid transfer size - Exiting\n"));
          ntStatus = STATUS_INVALID_PARAMETER_2;
          goto rwErrXit;
       }
       //
       // allocate and fill in the Usb request (URB)
       //
       urbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);

       pAsyncUrb = ExAllocatePool(NonPagedPool,urbSize);

       if (!pAsyncUrb) {
          AaUsbKdPrint(("AeReadWrite() unable to alloc URB - Exiting\n"));
          ntStatus = STATUS_NO_MEMORY;
          goto rwErrXit;
       }
      
       transferFlags = USBD_SHORT_TRANSFER_OK;

       //
       // Set the direction according to the requested operation.
       //
       if(pChnl->ChnlRead) {
       transferFlags |= USBD_TRANSFER_DIRECTION_IN;
       }

       UsbBuildInterruptOrBulkTransferRequest(
             pAsyncUrb,    //ptr to urb
             (USHORT) urbSize,  //size of urb
             PipeHandle,    //usbd pipe handle
             Irp->MdlAddress,     //TransferBuffer
             NULL,  //mdl
             0,                     //bufferlength
             transferFlags,   //flags
             NULL);     //link

       //
       // Call the USB Stack.
       //
       //ntStatus = AeAsyncCallUSBD(pFdo, urb);

       //
       // Prepare for calling the USB driver stack
       //
       AaUsbKdPrint((" St 0x%08X;\n",pAsyncUrb->UrbHeader.Status));
       nextStack = IoGetNextIrpStackLocation(Irp);
       ASSERT(nextStack != NULL);

       //
       // pass the URB to the USB driver stack
       //

       nextStack->Parameters.Others.Argument1 = pAsyncUrb;
       nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
       nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

       //
       // Set up the context block for the completion routine
       //
        pContext->aicDeviceObject = pFdo;
        pContext->aicUrb = pAsyncUrb;
        pContext->aicIrp = Irp;

       //
       // Set our completion routine for this operation
       //
       IoSetCompletionRoutine(
                               Irp,
                               AeZlpComplete,
                               pContext,    // pass context pointer to completion routine
                               TRUE,     // invoke on success
                               TRUE,     // invoke on error
                               TRUE);     // invoke on cancellation of the Irp

       //
       // Post the request to the system driver
       //
      
       ntStatus = IoCallDriver(pDx->TopOfStackDeviceObject, Irp);
       if(ntStatus != STATUS_PENDING) {
          //
          // This is a bug trap
          //
          AaUsbKdPrint (("AeReadWrite: Bug Alert!!! IoCallDriver returned (%x);%d\n", ntStatus));
       }
    #ifdef FULL_DEBUG
       else {
          AaUsbKdPrint (("AeReadWriteZLP: St(%x);\n", ntStatus));
       }
    #endif

       return ntStatus;

    rwErrXit:
       Irp->IoStatus.Status = ntStatus;
       Irp->IoStatus.Information = 0;
       IoCompleteRequest (Irp,IO_NO_INCREMENT);
       return ntStatus;
    }

    /**************************************************************************************
     *
     * Function Name: NTSTATUS AeZlpCompleteAsyncCall(
     *                                              IN PDEVICE_OBJECT pDeviceObject,
     *                                              IN PIRP pIrp,
     *                                              IN PVOID Context
     *                                              )
     *
     *
     * Parameters: IN PDEVICE_OBJECT pFdo  =  pointer to the device object.
     *             IN PIRP Irp             =  pointer to completed I/O request packet.
     *             IN PVOID Context        =  our context block
     *
     * Returns: STATUS_SUCCESS if successful,
     *                            else the final status from the operation.
     *
     * Description:
     *
     * Completion routine for AeReadWrite initiated asynchronous I/O requests.
     *
     **************************************************************************************
     */

    NTSTATUS
    AeZlpComplete(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
    {
       NTSTATUS          ntStatus = STATUS_SUCCESS;
       PURB              pAsyncUrb;
       PASYNC_IO_CONTEXT pContext = Context;
       PDEVICE_OBJECT    pDo;
       PDEVICE_EXTENSION pDx;
       char *            pStr = "Wr Cmplt";
       AaUsbKdPrint(("AeCompleteAsyncCallt\n"));
       ASSERT( pContext->aicDeviceObject );
       if( pContext->aicDeviceObject) {
          //
          // We have to get the deviceObject from the context, since the DeviceObject passed in
          //  here belongs to the next lower driver in the stack because we were invoked via
          //  IoCallDriver in AeReadWrite()
          //
          pDo = pContext->aicDeviceObject;
          pContext->aicDeviceObject = 0;
          pDx = pDo->DeviceExtension;

          ASSERT( pContext->aicIrp == pIrp );
          if( pContext->aicIrp == pIrp ) {
             //
             // If the lower driver returned PENDING, mark our stack location as pending also.
             //
             if ( pIrp->PendingReturned ) {
                IoMarkIrpPending(pIrp);
             }
            
             pAsyncUrb = pContext->aicUrb;
             if(pAsyncUrb) {
                pContext->aicUrb = 0;

    #ifdef FULL_DEBUG
                if(pAsyncUrb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN) {
                   pStr = "Rd Cmplt";
                }
       AaUsbKdPrint(("ZLP Completion\n"));
                AaUsbKdPrint(("%s: Lt: 0x%04X; St 0x%08X;\n",
                pStr,
                pAsyncUrb->UrbBulkOrInterruptTransfer.TransferBufferLength,
                pAsyncUrb->UrbHeader.Status));
    #endif

                //
                // IoCallDriver has been called on this Irp;
                // Set the length based on the TransferBufferLength
                // value in the URB
                //
                pIrp->IoStatus.Information =
                   pAsyncUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;

                //
                // If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the
                // URB status in the device extension.  After a failure, another IOCTL,
                // IOCTL_AaEcmUsbGET_LAST_ERROR can be used to retrieve the URB status
                // for the most recently failed URB.  Of course, this status gets
                // overwritten by subsequent failures, but it's better than nothing.
                //
                pIrp->IoStatus.Status = STATUS_SUCCESS;
                if (!(USBD_SUCCESS(pAsyncUrb->UrbHeader.Status))) {
                   pDx->LastFailedUrbStatus = pAsyncUrb->UrbHeader.Status;
                   pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
                }


                pContext->aicIrp = 0;

              
       
       
       //
       // Mark the IRP as complete
       //
          ExFreePool(pAsyncUrb);
          AaUsbKdPrint(("IRP ZlpC Address %x\n", pIrp));
          IoCompleteRequest(pIrp, IO_NO_INCREMENT);
      }
       }  //end if( pContext->aicIrp == pIrp )
       }  //end if( pContext->aicDeviceObject )

       //
       // Tell the I/O mangler not to diddle with the current IRP
       //
       return STATUS_MORE_PROCESSING_REQUIRED;
    }

    Windbg output:

    AaEcmUsb.SYS: IRP ZlpC Address 8561ca50
    AaEcmUsb.SYS: AeCompleteAsyncCallt
    AaEcmUsb.SYS: Rd Cmplt: Lt: 0x0264; St 0x00000000;
    AaEcmUsb.SYS: Before Complet
    AaEcmUsb.SYS: enter ZLP()
    AaEcmUsb.SYS: ZLP IRP Address 854aacd8
    AaEcmUsb.SYS: Wr req
    AaEcmUsb.SYS:  St 0x00000000;
    AaEcmUsb.SYS: AeReadWriteZLP: St(103);
    AaEcmUsb.SYS: After Complete
    AaEcmUsb.SYS: AeCompleteAsyncCallt
    AaEcmUsb.SYS: ZLP Completion
    AaEcmUsb.SYS: Wr Cmplt: Lt: 0x0000; St 0x00000000;
    AaEcmUsb.SYS: IRP ZlpC Address 854aacd8
    enter AeReadWrite()
    AaEcmUsb.SYS: ReadWrite IRP Address 8561ca50
    Access violation - code c0000005 (!!! second chance !!!)
    *** ERROR: Module load completed but symbols could not be loaded for AriumUsb.sys
    AriumUsb+0x3a51:
    f788fa51 8b5118          mov     edx,dword ptr [ecx+18h]

    Tuesday, November 20, 2012 11:23 PM
  • i don't have time to read over all of your code, you need to do some debugging on your own. some observations

    1)

    >Irp = IoAllocate(DeviceObject->StackSize, FALSE)

    >irpStack = IoGetCurrentIrpStackLocation (Irp);

    there is no current irp stack location when you allocate an irp, so the IoGetCurrentIrpStackLocation call and subsequent assignment corruptmemory

    2)

    >         if ( pIrp->PendingReturned ) {
    >            IoMarkIrpPending(pIrp);
    >         }

    same as 1).  IoMarkIrpPending touches the current stack location. for an irp you allocated, this corrupts memory.

    3)      AaUsbKdPrint (("AeReadWrite: Bug Alert!!! IoCallDriver returned (%x);%d\n", ntStatus));

    this also corrupts memory, you are not passing the same number of parameters as specified in the format list

    4)

    >AriumUsb+0x3a51:

    this means you have not loaded symbols for your driver. you need to fix that before you can effectively debug.

    >f788fa51 8b5118          mov     edx,dword ptr [ecx+18h]

    run !analyze -v, that will tell you what is going on, what value ecx is, etc


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Wednesday, November 21, 2012 3:56 AM