PC Review
Forums
Newsgroups
Windows XP
Windows XP Logo
OpenHCI bug on Win2k?
Forums
Newsgroups
Windows XP
Windows XP Logo
OpenHCI bug on Win2k?
![]() |
OpenHCI bug on Win2k? |
|
|
Thread Tools | Rate Thread |
|
|
#1 |
|
Guest
Posts: n/a
|
"Alexander Grigoriev" <alegr@earthlink.net> wrote in message
news:u0bmWZivEHA.3320@TK2MSFTNGP14.phx.gbl... > Can you post code where you initialize URB and IRP? > The code to init IRP and URB are given below. I am wondering if OpenHCI will handle data buffers bigger than the max packet size on the pipes. It appears that it also does not like the buffer (512 bytes) I pass to the interrupt pipe (with max packet size of 8 bytes). The usbport.sys, which my driver calls on XP, handles bigger buffers just fine. Now MS document on UsbBuildInterruptOrBulkTransferRequest does not put size limit on the data buffer used. However, I am also highly suspicious that this bug happens under special circustance--a bug like this would have been spotted long time ago. // routine to init and send URB // Note: the call to read the response failed with STATUS_INVALID_PARAMETER--the input buffer size ( // pReply->BufferSize is 0x120 (while my max packet size for the input pipe is 64 bytes). NTSTATUS PcscSendSmartcardCommand( PSMARTCARD_EXTENSION SmartcardExtension) { NTSTATUS status = STATUS_SUCCESS; PSMARTCARD_REPLY pReply = &SmartcardExtension->SmartcardReply; PSMARTCARD_REQUEST pRequest = &SmartcardExtension->SmartcardRequest; PDEVICE_OBJECT fdo = (PDEVICE_OBJECT)SmartcardExtension->OsData->DeviceObject; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension; #ifdef DEBUG SmartcardDebug(DEBUG_INFO, ("%s!PcscSendSmartcardCommand: cmd = ", DRIVERNAME)); for (ULONG j = 0; j < pRequest->BufferLength; j++) { SmartcardDebug(DEBUG_INFO, ("/x%02X", pRequest->Buffer[j])); } SmartcardDebug(DEBUG_INFO, ("\n")); #endif URB urb; // init URB to send command via bulk out pipe UsbBuildInterruptOrBulkTransferRequest( &urb, // URB to build sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), // pdx->houtpipe, // pipe handle pRequest->Buffer, // transfer buffer NULL, // MDL pRequest->BufferLength, // transfer buffer length USBD_TRANSFER_DIRECTION_OUT, // transfer flags NULL); // // Send URB status = SendAwaitUrb(fdo, &urb); if (status == STATUS_SUCCESS) { // Read response from bulk in pipe // init URB to read response from bulk in pipe UsbBuildInterruptOrBulkTransferRequest( &urb, // URB to build sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), // pdx->hinpipe, // pipe handle pReply->Buffer, // transfer buffer NULL, // MDL pReply->BufferSize, // transfer buffer length USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, // transfer flags NULL); // // Send URB status = SendAwaitUrb(fdo, &urb); if (status == STATUS_SUCCESS) { pReply->BufferLength = urb.UrbBulkOrInterruptTransfer.TransferBufferLength; #ifdef DEBUG SmartcardDebug(DEBUG_INFO, ("%s!PcscSendSmartcardCommand: resp = ", DRIVERNAME)); for (ULONG j = 0; j < pReply->BufferLength; j++) { SmartcardDebug(DEBUG_INFO, ("/x%02X", pReply->Buffer[j])); } SmartcardDebug(DEBUG_INFO, ("\n")); #endif } else { SmartcardDebug(DEBUG_ERROR, ("%s!PcscSendSmartcardCommand: error reading resp (%lX)\n", DRIVERNAME, status)); } } else { SmartcardDebug(DEBUG_ERROR, ("%s!PcscSendSmartcardCommand: error writing cmd (%lX)\n", DRIVERNAME, status)); } return (status); } // routine to init and send IRP NTSTATUS SendAwaitUrb(PDEVICE_OBJECT fdo, PURB urb) { // SendAwaitUrb PAGED_CODE(); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; KEVENT event; KeInitializeEvent(&event, NotificationEvent, FALSE); IO_STATUS_BLOCK iostatus; PIRP Irp = IoBuildDeviceIoControlRequest( IOCTL_INTERNAL_USB_SUBMIT_URB, pdx->LowerDeviceObject, NULL, 0, NULL, 0, TRUE, &event, &iostatus); if (!Irp) { KdPrint((DRIVERNAME " - Unable to allocate IRP for sending URB\n")); return STATUS_INSUFFICIENT_RESOURCES; } // Set up our completion routine IoSetCompletionRoutine(Irp, SendUrbComplete, (PVOID)&event, TRUE, TRUE, TRUE); PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp); stack->Parameters.Others.Argument1 = (PVOID) urb; // We will wait for 1 min before the reader returns LARGE_INTEGER timeOut; // 1 min = 60 sec, in units of 100 nano sec timeOut.QuadPart = -60 * 1000 * 1000 * 10; // Send URB to USBD NTSTATUS status = IoCallDriver(pdx->LowerDeviceObject, Irp); if (status == STATUS_PENDING) { status = KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, &timeOut); if (status == STATUS_TIMEOUT) { SmartcardDebug(DEBUG_INFO, ("%s!SendAwaitUrb: cmd time out, cancelling IRP\n", DRIVERNAME)); // We timed out, need to cancel the IRP IoCancelIrp(Irp); // Now wait for our completion routine to signal us KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL); } else { // Since our completion routine returned STATUS_MORE_PROCESSING_NEEDED that // prevents USBD to finish the IRP, we need to do it here IoCompleteRequest(Irp, IO_NO_INCREMENT); } } else { iostatus.Status = status; } status = iostatus.Status; if (status != STATUS_SUCCESS) SmartcardDebug(DEBUG_INFO, ("%s!SendAwaitUrb: err 0x%x\n", DRIVERNAME, status)); return status; } // SendAwaitUrb I traced the driver stack and found that the parameter validation happens in openhci.sys. Here a dump from SoftICE: :u openhci_queuetransfer l200 _OpenHCI_QueueTransfer 0008:EB6C3B3C PUSH EBP 0008:EB6C3B3D MOV EBP,ESP 0008:EB6C3B3F PUSH ECX 0008:EB6C3B40 PUSH ECX 0008:EB6C3B41 MOV EAX,[EBP+08] 0008:EB6C3B44 PUSH EBX 0008:EB6C3B45 PUSH ESI 0008:EB6C3B46 PUSH EDI 0008:EB6C3B47 MOV EDI,[EBP+0C] ; edi = IRP 0008:EB6C3B4A MOV EAX,[EAX+28] 0008:EB6C3B4D MOV DWORD PTR [EBP-04],00000103 0008:EB6C3B54 MOV [EBP-08],EAX 0008:EB6C3B57 MOV ECX,[EDI+60] ; ecx = IO_stack 0008:EB6C3B5A MOV ESI,[ECX+04] ; esi = URB 0008:EB6C3B5D MOV EBX,[ESI+28] ; HCA area, opapue to driver 0008:EB6C3B60 MOV [ESI+2C],EDI 0008:EB6C3B63 PUSH DWORD PTR [EAX+00000174] 0008:EB6C3B69 CALL [__imp__READ_REGISTER_ULONG] 0008:EB6C3B6F CMP EAX,-01 0008:EB6C3B72 JNZ EB6C3B85 0008:EB6C3B74 MOV DWORD PTR [EBP-04],C00000C0 ; STATUS_DEVICE_DOES_NOT_EXIST 0008:EB6C3B7B PUSH 80000500 0008:EB6C3B80 JMP EB6C3C09 0008:EB6C3B85 TEST BYTE PTR [EBX+10],02 0008:EB6C3B89 JZ EB6C3BA9 0008:EB6C3B8B TEST ESI,ESI 0008:EB6C3B8D JZ EB6C3CC5 0008:EB6C3B93 PUSH EBX 0008:EB6C3B94 PUSH ESI 0008:EB6C3B95 PUSH EDI 0008:EB6C3B96 PUSH DWORD PTR [EBP-08] 0008:EB6C3B99 PUSH DWORD PTR [EBP+08] 0008:EB6C3B9C CALL _OpenHCI_RootHubStartXfer 0008:EB6C3BA1 MOV ESI,[ESI+24] 0008:EB6C3BA4 MOV [EBP-04],EAX 0008:EB6C3BA7 JMP EB6C3B8B 0008:EB6C3BA9 CMP BYTE PTR [EBX+30],01 0008:EB6C3BAD JNZ EB6C3BF5 0008:EB6C3BAF TEST BYTE PTR [ESI+14],04 0008:EB6C3BB3 JNZ EB6C3BF5 0008:EB6C3BB5 PUSH DWORD PTR [EBP-08] 0008:EB6C3BB8 CALL _Get32BitFrameNumber 0008:EB6C3BBD MOV ECX,[ESI+48] 0008:EB6C3BC0 PUSH DWORD PTR [EBP-08] 0008:EB6C3BC3 SUB ECX,EAX 0008:EB6C3BC5 TEST ECX,ECX 0008:EB6C3BC7 JLE EB6C3BD5 0008:EB6C3BC9 CALL _Get32BitFrameNumber 0008:EB6C3BCE MOV ECX,[ESI+48] 0008:EB6C3BD1 SUB ECX,EAX 0008:EB6C3BD3 JMP EB6C3BDF 0008:EB6C3BD5 CALL _Get32BitFrameNumber 0008:EB6C3BDA MOV ECX,EAX 0008:EB6C3BDC SUB ECX,[ESI+48] 0008:EB6C3BDF CMP ECX,00000400 0008:EB6C3BE5 JLE EB6C3BF5 0008:EB6C3BE7 MOV DWORD PTR [EBP-04],C000000D ; STATUS_INVALID_PARAMETER 0008:EB6C3BEE PUSH C0000A00 0008:EB6C3BF3 JMP EB6C3C09 0008:EB6C3BF5 MOV EAX,[ESI+18] ;; NOTE: eax = input buffer size = 0x120 0008:EB6C3BF8 CMP EAX,[EBX+4C] ;; [ebx + 4c] = 0x40, ie 64 bytes, possibly the max packet size for the pipe? 0008:EB6C3BFB JBE EB6C3C14 (NO JUMP) 0008:EB6C3BFD MOV DWORD PTR [EBP-04],C000000D ; STATUS_INVALID_PARAMETER <= error code returned to IdtSp3Usb 0008:EB6C3C04 PUSH 80000300 0008:EB6C3C09 PUSH ESI 0008:EB6C3C0A CALL _OpenHCI_SetTranferError 0008:EB6C3C0F JMP EB6C3CC5 0008:EB6C3C14 LEA EAX,[EBP+0C] 0008:EB6C3C17 PUSH EAX 0008:EB6C3C18 CALL [__imp__IoAcquireCancelSpinLock] 0008:EB6C3C1E LEA ECX,[EBX+40] 0008:EB6C3C21 CALL [__imp_@KfAcquireSpinLock] 0008:EB6C3C27 CMP BYTE PTR [EDI+24],00 0008:EB6C3C2B MOV [EBP+08],AL 0008:EB6C3C2E JZ EB6C3C39 0008:EB6C3C30 MOV DWORD PTR [EBP-04],C0000120 ; STATUS_CANCELLED 0008:EB6C3C37 JMP EB6C3C46 0008:EB6C3C39 TEST BYTE PTR [EBX+10],01 0008:EB6C3C3D JZ EB6C3C5E 0008:EB6C3C3F MOV DWORD PTR [EBP-04],C000020F ; STATUS_TRANSACTION_ABORTED 0008:EB6C3C46 XOR EDX,EDX 0008:EB6C3C48 LEA ECX,[EDI+38] 0008:EB6C3C4B CALL [__imp_@InterlockedExchange] 0008:EB6C3C51 PUSH 00010000 0008:EB6C3C56 PUSH ESI 0008:EB6C3C57 CALL _OpenHCI_SetTranferError 0008:EB6C3C5C JMP EB6C3CA7 0008:EB6C3C5E TEST ESI,ESI 0008:EB6C3C60 JZ EB6C3C8B 0008:EB6C3C62 LEA ECX,[EBX+18] 0008:EB6C3C65 LEA EAX,[ESI+38] 0008:EB6C3C68 MOV [ESI+3C],EAX 0008:EB6C3C6B MOV [EAX],EAX 0008:EB6C3C6D MOV DWORD PTR [ESI+04],40404003 0008:EB6C3C74 MOV EDX,[ECX+04] 0008:EB6C3C77 LEA EAX,[ESI+30] 0008:EB6C3C7A MOV [ESI+34],EDX 0008:EB6C3C7D MOV [EAX],ECX 0008:EB6C3C7F MOV [EDX],EAX 0008:EB6C3C81 MOV [ECX+04],EAX 0008:EB6C3C84 MOV ESI,[ESI+24] 0008:EB6C3C87 TEST ESI,ESI 0008:EB6C3C89 JNZ EB6C3C65 0008:EB6C3C8B MOV EAX,[EDI+60] 0008:EB6C3C8E MOV DWORD PTR [EDI+18],00000103 0008:EB6C3C95 MOV EDX,_OpenHCI_CancelTransfer 0008:EB6C3C9A LEA ECX,[EDI+38] 0008:EB6C3C9D OR BYTE PTR [EAX+03],01 0008:EB6C3CA1 CALL [__imp_@InterlockedExchange] 0008:EB6C3CA7 MOV DL,[EBP+08] 0008:EB6C3CAA LEA ECX,[EBX+40] 0008:EB6C3CAD CALL [__imp_@KfReleaseSpinLock] 0008:EB6C3CB3 PUSH DWORD PTR [EBP+0C] 0008:EB6C3CB6 CALL [__imp__IoReleaseCancelSpinLock] 0008:EB6C3CBC PUSH EBX 0008:EB6C3CBD PUSH DWORD PTR [EBP-08] 0008:EB6C3CC0 CALL _OpenHCI_ProcessEndpoint 0008:EB6C3CC5 MOV EAX,[EBP-04] 0008:EB6C3CC8 POP EDI 0008:EB6C3CC9 POP ESI 0008:EB6C3CCA POP EBX 0008:EB6C3CCB LEAVE 0008:EB6C3CCC RET 0008 0008:EB6C3CCF INT 3 > "WT" <wyt168@earthlink.net> wrote in message > news:Vgugd.5799$kM.5639@newsread3.news.pas.earthlink.net... >>I developed a USB driver for smartcard reader and it was running fine on >>WinXP. It works fine on Win2k too if my reader is connected through a >>hispeed hub. However, if I connect the reader to the root hub directly, >>the driver would fail to load. I snooped around with SoftICE into the >>driver stack and discovered that it is in OpenHCI that my IRP, or URB, >>failed a parameter validation. Turns out that it does not take a buffer >>with size greater than 64 bytes (possibly because the max packet size of >>of my bulk input pipe is 64 bytess) and rejected my URB with >>STATUS_INVALID_PARAMETER (0xc000000D). >> When a reader is connected through a hub, openhci is not involved. My >> driver passes the URB to usbport.sys instead. >> Anybody out there experienced the same problem? I can provide more >> details if anybody is interested. >> Winston |
|
![]() |
|
| Thread Tools | |
| Rate This Thread | |
|
|

Main Page 

