VOID FilterForwardRequest( IN WDFREQUEST Request, IN WDFIOTARGET Target ) /*++ Routine Description: Passes a request on to the lower driver. --*/ { WDF_REQUEST_SEND_OPTIONS options; BOOLEAN ret; NTSTATUS status; // // We are not interested in post processing the IRP so // fire and forget. // WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); ret = WdfRequestSend(Request, Target, &options); if (ret == FALSE) { status = WdfRequestGetStatus (Request); KdPrint( ("WdfRequestSend failed: 0x%x\n", status)); WdfRequestComplete(Request, status); } return; }
static VOID XenVbd_StopRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend) { PXENVBD_FILTER_DATA xvfd = (PXENVBD_FILTER_DATA)xvdd->xvfd; NTSTATUS status; WDFREQUEST request; WDF_REQUEST_SEND_OPTIONS send_options; IO_STACK_LOCATION stack; SCSI_REQUEST_BLOCK srb; SRB_IO_CONTROL sic; FUNCTION_ENTER(); /* send a 'stop' down if we are suspending */ if (suspend) { status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request); FUNCTION_MSG("WdfRequestCreate = %08x\n", status); RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION)); stack.MajorFunction = IRP_MJ_SCSI; stack.MinorFunction = IRP_MN_SCSI_CLASS; stack.Parameters.Scsi.Srb = &srb; RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE); srb.SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; srb.Length = SCSI_REQUEST_BLOCK_SIZE; srb.PathId = 0; srb.TargetId = 0; srb.Lun = 0; srb.OriginalRequest = WdfRequestWdmGetIrp(request); srb.Function = SRB_FUNCTION_IO_CONTROL; srb.DataBuffer = &sic; RtlZeroMemory(&sic, sizeof(SRB_IO_CONTROL)); sic.HeaderLength = sizeof(SRB_IO_CONTROL); memcpy(sic.Signature, XENVBD_CONTROL_SIG, 8); sic.Timeout = 60; sic.ControlCode = XENVBD_CONTROL_STOP; WdfRequestWdmFormatUsingStackLocation(request, &stack); WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) { FUNCTION_MSG("Request was _NOT_ sent\n"); } #if DBG status = WdfRequestGetStatus(request); FUNCTION_MSG("Request Status = %08x\n", status); FUNCTION_MSG("SRB Status = %08x\n", srb.SrbStatus); #endif WdfObjectDelete(request); } status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosing); FUNCTION_EXIT(); }
void MouseTrapEvtIoInternalDeviceControl(WDFQUEUE queue, WDFREQUEST request, size_t outputBufferLength, size_t inputBufferLength, ULONG ioControlCode) { UNREFERENCED_PARAMETER(outputBufferLength); UNREFERENCED_PARAMETER(inputBufferLength); NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // Ensure paging is allowed in current IRQL // Get extension data WDFDEVICE hDevice = WdfIoQueueGetDevice(queue); PDEVICE_CONTEXT context = DeviceGetContext(hDevice); if(ioControlCode == IOCTL_INTERNAL_MOUSE_CONNECT) { // Only allow one connection. if(context->UpperConnectData.ClassService == NULL) { // Copy the connection parameters to the device extension. PCONNECT_DATA connectData; size_t length; status = WdfRequestRetrieveInputBuffer(request, sizeof(CONNECT_DATA), &connectData, &length); if(NT_SUCCESS(status)) { // Hook into the report chain (I am not sure this is correct) context->UpperConnectData = *connectData; connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice); #pragma warning(push) #pragma warning(disable:4152) connectData->ClassService = MouseTrapServiceCallback; #pragma warning(pop) } else { DebugPrint(("[MouseTrap] WdfRequestRetrieveInputBuffer failed %x\n", status)); } } else { status = STATUS_SHARING_VIOLATION; } } else if(ioControlCode == IOCTL_INTERNAL_MOUSE_DISCONNECT) { status = STATUS_NOT_IMPLEMENTED; } // Complete on error if(!NT_SUCCESS(status)) { WdfRequestComplete(request, status); return; } // Dispatch to higher level driver WDF_REQUEST_SEND_OPTIONS options; WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); if(WdfRequestSend(request, WdfDeviceGetIoTarget(hDevice), &options) == FALSE) { NTSTATUS status = WdfRequestGetStatus(request); DebugPrint(("[MouseTrap] WdfRequestSend failed: 0x%x\n", status)); WdfRequestComplete(request, status); } }
// Bulk管道写操作 // VOID BulkWrite(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { NTSTATUS status = STATUS_SUCCESS; WDFMEMORY hMem = NULL; WDFDEVICE hDevice = NULL; WDFUSBPIPE BulkOutputPipe = NULL; UCHAR* lpBuf; UNREFERENCED_PARAMETER(Length); KDBG(DPFLTR_INFO_LEVEL, "[BulkWrite] size: %d", Length); // 获取管道句柄 hDevice = WdfIoQueueGetDevice(Queue); BulkOutputPipe = GetBulkPipe(FALSE, hDevice); if(NULL == BulkOutputPipe) { KDBG(DPFLTR_ERROR_LEVEL, "BulkOutputPipe = NULL"); WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); return; } status = WdfRequestRetrieveInputMemory(Request, &hMem); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_ERROR_LEVEL, "WdfRequestRetrieveInputMemory failed(status = 0x%0.8x)!!!", status); WdfRequestComplete(Request, status); return; } // 打印出offset值。 // 在写缓冲的前两个字节中存有write offset的值 lpBuf = (UCHAR*)WdfMemoryGetBuffer(hMem, 0); KDBG(DPFLTR_TRACE_LEVEL, "write offset: %hd", *(WORD*)lpBuf); // 把当前的Request对象进行重利用,发送给USB总线。 // 格式化Request对象,设置Pipe句柄、完成函数等。 status = WdfUsbTargetPipeFormatRequestForWrite(BulkOutputPipe, Request, hMem, NULL); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_ERROR_LEVEL, "WdfUsbTargetPipeFormatRequestForWrite(status 0x%0.8x)!!!", status); WdfRequestComplete(Request, status); return; } WdfRequestSetCompletionRoutine(Request, BulkWriteComplete, BulkOutputPipe); if(FALSE == WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(BulkOutputPipe), NULL)) { status = WdfRequestGetStatus(Request); KDBG(DPFLTR_ERROR_LEVEL, "WdfRequestSend failed with status 0x%0.8x\n", status); WdfRequestComplete(Request, status); } }
VOID EvtIoRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { WDFUSBPIPE pipe; NTSTATUS status; WDFMEMORY reqMemory; PDEVICE_CONTEXT pDeviceContext; BOOLEAN ret; UNREFERENCED_PARAMETER(Length); pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkReadPipe; status = WdfRequestRetrieveOutputMemory(Request, &reqMemory); if(!NT_SUCCESS(status)){ goto Exit; } status = WdfUsbTargetPipeFormatRequestForRead(pipe, Request, reqMemory, NULL // Offsets ); if (!NT_SUCCESS(status)) { goto Exit; } WdfRequestSetCompletionRoutine( Request, EvtRequestReadCompletionRoutine, pipe); ret = WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS); if (ret == FALSE) { status = WdfRequestGetStatus(Request); goto Exit; } else { return; } Exit: WdfRequestCompleteWithInformation(Request, status, 0); return; }
VOID SimSensorIoInternalDeviceControl ( WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode) /*++ Description: The system uses IoInternalDeviceControl requests to communicate with the ACPI driver on the device stack. For proper operation of thermal zones, these requests must be forwarded unless the driver knows how to handle them. --*/ { WDF_REQUEST_SEND_OPTIONS RequestSendOptions; BOOLEAN Return; NTSTATUS Status; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(IoControlCode); DebugEnter(); WdfRequestFormatRequestUsingCurrentType(Request); WDF_REQUEST_SEND_OPTIONS_INIT( &RequestSendOptions, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); Return = WdfRequestSend( Request, WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)), &RequestSendOptions); if (Return == FALSE) { Status = WdfRequestGetStatus(Request); DebugPrint(SIMSENSOR_WARN, "WdfRequestSend() Failed. Request Status=0x%x\n", Status); WdfRequestComplete(Request, Status); } DebugExit(); }
/////////////////////////////////////////////////////////////////////////////// // // CDFilterEvtRead // // This routine is called by the framework for read requests // being sent to the device we're filtering // // INPUTS: // // Queue - Our default queue // // Request - A read request // // Length - The length of the read operation // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // This routine is called at IRQL <= DISPATCH_LEVEL // // NOTES: // // /////////////////////////////////////////////////////////////////////////////// VOID CDFilterEvtRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length) { NTSTATUS status; PFILTER_DEVICE_CONTEXT devContext; #if DBG DbgPrint("CDFilterEvtRead: Processing read. Length = 0x%x\n", Length); #endif // // Get the context that we setup during DeviceAdd processing // devContext = CDFilterGetDeviceContext(WdfIoQueueGetDevice(Queue)); // // Setup the request for the next driver // WdfRequestFormatRequestUsingCurrentType(Request); // // Set the completion routine... // WdfRequestSetCompletionRoutine(Request, CDFilterReadComplete, NULL); // // And send it! // if (!WdfRequestSend(Request, devContext->TargetToSendRequestsTo, WDF_NO_SEND_OPTIONS)) { // // Oops! Something bad happened, complete the request // status = WdfRequestGetStatus(Request); #if DBG DbgPrint("WdfRequestSend failed - 0x%x\n", status); #endif WdfRequestComplete(Request, status); } return; }
// Bulk管道读操作 // VOID BulkRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_CONTEXT pContext = NULL; WDFUSBPIPE BulkInputPipe; WDFMEMORY hMem; WDFDEVICE hDevice = WdfIoQueueGetDevice(Queue); KDBG(DPFLTR_INFO_LEVEL, "[BulkRead] size: %d", Length); // 取管道 pContext = GetDeviceContext(hDevice); BulkInputPipe = GetBulkPipe(TRUE, hDevice); if(NULL == BulkInputPipe){ WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); return; } status = WdfRequestRetrieveOutputMemory(Request, &hMem); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_INFO_LEVEL, "WdfRequestRetrieveOutputMemory failed with status 0x%0.8x!!!", status); WdfRequestComplete(Request, status); return; } // 和写一样,仍然是对Request对象的重利用 // 除了重利用外,也可以新建一个Request对象。新建的方法在本工程其他地方用得较多。 status = WdfUsbTargetPipeFormatRequestForRead(BulkInputPipe, Request, hMem, NULL); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_INFO_LEVEL, "WdfUsbTargetPipeFormatRequestForRead failed with status 0x%08x\n", status); WdfRequestComplete(Request, status); return; } WdfRequestSetCompletionRoutine(Request, BulkReadComplete, BulkInputPipe); if(FALSE == WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pContext->UsbBulkInPipe), NULL)) { status = WdfRequestGetStatus(Request); KDBG(DPFLTR_INFO_LEVEL, "WdfRequestSend failed with status 0x%08x\n", status); WdfRequestComplete(Request, status); } }
VOID ForwardRequestToIoTarget( _In_ WDFQUEUE queue, _In_ WDFREQUEST request, _In_ size_t length) { TraceEntry(); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! - Queue 0x%p, Request 0x%p Length %Iu", queue, request, length); auto device = WdfIoQueueGetDevice(queue); auto context = GetDeviceContext(device); if (length > context->MaxLengthInBytesForRWTransfers) { TraceError("%!FUNC! - Buffer Length to big %Iu, Max is %Iu. Status - %!STATUS!", length, context->MaxLengthInBytesForRWTransfers, STATUS_BUFFER_OVERFLOW); WdfRequestCompleteWithInformation(request, STATUS_BUFFER_OVERFLOW, NULL); return; } auto targetDevice = WdfDeviceGetIoTarget(device); WdfRequestFormatRequestUsingCurrentType(request); WDF_REQUEST_SEND_OPTIONS options; WDF_REQUEST_SEND_OPTIONS_INIT( &options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS | WDF_REQUEST_SEND_OPTION_TIMEOUT); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&options, WDF_ABS_TIMEOUT_IN_SEC(10)); auto sendSuccess = WdfRequestSend(request, targetDevice, &options); auto status = WdfRequestGetStatus(request); if (!sendSuccess || !NT_SUCCESS(status)) { TraceError("%!FUNC! - WdfRequestSend returned %d with status: %!STATUS!", sendSuccess, status); WdfRequestCompleteWithInformation(request, status, NULL); return; } WdfRequestComplete(request, status); }
/////////////////////////////////////////////////////////////////////////////// // SmplFilterCompletionRoutineRead /////////////////////////////////////////////////////////////////////////////// void SmplFilterCompletionRoutineRead( __in WDFREQUEST Request, __in WDFIOTARGET Target, __in PWDF_REQUEST_COMPLETION_PARAMS Params, __in WDFCONTEXT Context ) { size_t CountByte; PKEYBOARD_INPUT_DATA pKeyboardInputData; NTSTATUS Status; DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterCompletionRoutineRead\n"); Status = WdfRequestRetrieveOutputBuffer(Request, sizeof(KEYBOARD_INPUT_DATA), &pKeyboardInputData, &CountByte); if (NT_SUCCESS (Status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "Size of data: %d.\n", CountByte); if (CountByte < sizeof(KEYBOARD_INPUT_DATA)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "Buffer too small.\n"); } else { DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "Unit: %x MakCode: %x, Flags: %x ExtraInformation %x.\n", pKeyboardInputData->UnitId, pKeyboardInputData->MakeCode, pKeyboardInputData->Flags, pKeyboardInputData->ExtraInformation); } } else { DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "WdfRequestRetrieveOutputBuffer() failed.\n"); } WdfRequestComplete(Request, WdfRequestGetStatus(Request)); } // end SmplFilterCompletionRoutineRead
VOID FilterForwardRequestWithCompletionRoutine( IN WDFREQUEST Request, IN WDFIOTARGET Target ) /*++ Routine Description: This routine forwards the request to a lower driver with a completion so that when the request is completed by the lower driver, it can regain control of the request and look at the result. --*/ { BOOLEAN ret; NTSTATUS status; // // The following funciton essentially copies the content of // current stack location of the underlying IRP to the next one. // WdfRequestFormatRequestUsingCurrentType(Request); WdfRequestSetCompletionRoutine(Request, FilterRequestCompletionRoutine, WDF_NO_CONTEXT); ret = WdfRequestSend(Request, Target, WDF_NO_SEND_OPTIONS); if (ret == FALSE) { status = WdfRequestGetStatus (Request); KdPrint( ("WdfRequestSend failed: 0x%x\n", status)); WdfRequestComplete(Request, status); } return; }
static VOID XenVbd_SendEventComplete(WDFREQUEST request, WDFIOTARGET target, PWDF_REQUEST_COMPLETION_PARAMS params, WDFCONTEXT context) { WDFDEVICE device = WdfIoTargetGetDevice(target); PXENVBD_FILTER_DATA xvfd = GetXvfd(device); NTSTATUS status; PSCSI_REQUEST_BLOCK srb = context; LARGE_INTEGER systemtime; ULONGLONG elapsed; UNREFERENCED_PARAMETER(params); UNREFERENCED_PARAMETER(context); status = WdfRequestGetStatus(request); if (status != 0 || srb->SrbStatus != SRB_STATUS_SUCCESS) { FUNCTION_MSG("Request Status = %08x, SRB Status = %08x\n", status, srb->SrbStatus); } KeQuerySystemTime(&systemtime); elapsed = systemtime.QuadPart - ((PLARGE_INTEGER)((PUCHAR)context + sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL)))->QuadPart; elapsed = elapsed / 10000; // now in ms if (elapsed > 1000) { FUNCTION_MSG("Event took %d ms\n", (ULONG)elapsed); } ExFreePoolWithTag(context, XENVBD_POOL_TAG); WdfObjectDelete(request); for (;;) { if (InterlockedCompareExchange(&xvfd->event_state, 0, 1) == 1) { /* no pending event, and we cleared outstanding flag */ break; } if (InterlockedCompareExchange(&xvfd->event_state, 1, 2) == 2) { /* there was a pending event, and we set the flag back to outstanding */ //FUNCTION_MSG("sending pended event\n"); XenVbd_SendEvent(device); break; } /* event_state changed while we were looking at it, go round again */ } }
VOID MouFilter_DispatchPassThrough( __in WDFREQUEST Request, __in WDFIOTARGET Target ) /*++ Routine Description: Passes a request on to the lower driver. --*/ { // // Pass the IRP to the target // WDF_REQUEST_SEND_OPTIONS options; BOOLEAN ret; NTSTATUS status = STATUS_SUCCESS; // // We are not interested in post processing the IRP so // fire and forget. // WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); ret = WdfRequestSend(Request, Target, &options); if (ret == FALSE) { status = WdfRequestGetStatus (Request); DebugPrint( ("WdfRequestSend failed: 0x%x\n", status)); WdfRequestComplete(Request, status); } return; }
/////////////////////////////////////////////////////////////////////////////// // SmplFilterEvtIoDefault /////////////////////////////////////////////////////////////////////////////// VOID SmplFilterEvtIoDefault( __in WDFQUEUE Queue, __in WDFREQUEST Request ) { WDF_REQUEST_PARAMETERS RequestParameters; BOOLEAN bResult; WDF_REQUEST_PARAMETERS_INIT(&RequestParameters); WdfRequestGetParameters(Request, &RequestParameters); if(WdfRequestTypeRead == RequestParameters.Type) { DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterEvtIoDefault WdfRequestTypeRead\n"); WdfRequestFormatRequestUsingCurrentType(Request); WdfRequestSetCompletionRoutine(Request, SmplFilterCompletionRoutineRead, NULL); bResult = WdfRequestSend(Request, WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)), NULL); } else { WDF_REQUEST_SEND_OPTIONS Options; WDF_REQUEST_SEND_OPTIONS_INIT(&Options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterEvtIoDefault other Request type\n"); bResult = WdfRequestSend(Request, WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)), &Options); } if(FALSE == bResult) { DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "WdfRequestSend failed!\n"); WdfRequestComplete(Request, WdfRequestGetStatus(Request)); } } // end SmplFilterEvtIoDefault
VOID MouFilter_DispatchPassThrough(_In_ WDFREQUEST Request, _In_ WDFIOTARGET Target) /*++ Routine Description: Passes a request on to the lower driver. --*/ { WDF_REQUEST_SEND_OPTIONS options; BOOLEAN ret; NTSTATUS status = STATUS_SUCCESS; WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); ret = WdfRequestSend(Request, Target, &options); if (ret == FALSE) { status = WdfRequestGetStatus (Request); DebugPrint( ("WdfRequestSend failed: 0x%x\n", status)); WdfRequestComplete(Request, status); } return; }
static VOID XenUsb_EvtIoInternalDeviceControl( WDFQUEUE queue, WDFREQUEST request, size_t output_buffer_length, size_t input_buffer_length, ULONG io_control_code) { WDFDEVICE device = WdfIoQueueGetDevice(queue); PXENUSB_DEVICE_DATA xudd = GetXudd(device); //WDF_REQUEST_PARAMETERS wrp; //pvusb_urb_t *urb; UNREFERENCED_PARAMETER(input_buffer_length); UNREFERENCED_PARAMETER(output_buffer_length); FUNCTION_ENTER(); //WDF_REQUEST_PARAMETERS_INIT(&wrp); //WdfRequestGetParameters(request, &wrp); switch(io_control_code) { case IOCTL_INTERNAL_PVUSB_SUBMIT_URB: FUNCTION_MSG("IOCTL_INTERNAL_PVUSB_SUBMIT_URB\n"); //urb = (pvusb_urb_t *)wrp.Parameters.Others.Arg1; //FUNCTION_MSG("urb = %p\n", urb); WdfRequestForwardToIoQueue(request, xudd->pvurb_queue); break; default: FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code); WdfRequestComplete(request, WdfRequestGetStatus(request)); break; } FUNCTION_EXIT(); }
NTSTATUS RequestIssueShutdownFlush( _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PIRP Irp ) /*++ Routine Description: issue SRB function Flush/Shutdown command. Arguments: DeviceExtension - device context Irp - the irp Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb; PIO_STACK_LOCATION currentStack = NULL; ULONG transferSize = 0; BOOLEAN shouldRetry = TRUE; ULONG timesAlreadyRetried = 0; LONGLONG retryIn100nsUnits = 0; currentStack = IoGetCurrentIrpStackLocation(Irp); ScratchBuffer_BeginUse(DeviceExtension); // no retry needed. { ScratchBuffer_SetupSrb(DeviceExtension, NULL, transferSize, FALSE); // Set up the SRB/CDB srb->QueueTag = SP_UNTAGGED; srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; srb->TimeOutValue = TimeOutValueGetCapValue(DeviceExtension->TimeOutValue, 4); srb->CdbLength = 0; if (currentStack->MajorFunction == IRP_MJ_SHUTDOWN) { srb->Function = SRB_FUNCTION_SHUTDOWN; } else { srb->Function = SRB_FUNCTION_FLUSH; } ScratchBuffer_SendSrb(DeviceExtension, TRUE, NULL); shouldRetry = RequestSenseInfoInterpretForScratchBuffer(DeviceExtension, timesAlreadyRetried, &status, &retryIn100nsUnits); UNREFERENCED_PARAMETER(shouldRetry); //defensive coding, avoid PREFAST warning. UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning. // retrieve the real status from the request. status = WdfRequestGetStatus(DeviceExtension->ScratchContext.ScratchRequest); } ScratchBuffer_EndUse(DeviceExtension); return status; }
NTSTATUS kmdf1394_SubmitIrpAsync ( IN WDFIOTARGET IoTarget, IN WDFREQUEST Request, IN WDFMEMORY Memory) /*++ Routine Description: Asynchronous request submission routine Arguments: IoTarget - I/O Target object Request - current request object Irb - 1394 I/O Request Block to submit Return Value: NTSTATUS value --*/ { NTSTATUS ntStatus = STATUS_SUCCESS; ENTER("kmdf1394_SubmitIrpAsync"); ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL); ASSERT (Memory); if (!NT_SUCCESS (ntStatus)) { return ntStatus; } ntStatus = WdfIoTargetFormatRequestForInternalIoctlOthers ( IoTarget, Request, IOCTL_1394_CLASS, Memory, NULL, NULL, NULL, NULL, NULL); if (!NT_SUCCESS (ntStatus)) { TRACE( TL_ERROR, ("WdfIoTargetFormatRequestForInternalIoctlOthers failed " "with status %x\n", ntStatus)); return ntStatus; } if (FALSE == (WdfRequestSend (Request, IoTarget, NULL))) { ntStatus = WdfRequestGetStatus (Request); } EXIT("kmdf1394_SubmitIrpAsync", ntStatus); return ntStatus; } // kmdf1394_SubmitIrpAsync
NTSTATUS BthEchoSharedSendBrbAsync( _In_ WDFIOTARGET IoTarget, _In_ WDFREQUEST Request, _In_ PBRB Brb, _In_ size_t BrbSize, _In_ PFN_WDF_REQUEST_COMPLETION_ROUTINE ComplRoutine, _In_opt_ WDFCONTEXT Context ) /*++ Routine Description: This routine formats a request with brb and sends it asynchronously Arguments: IoTarget - Target to send the brb to Request - request object to be formatted with brb Brb - Brb to be sent BrbSize - size of the Brb data structure ComplRoutine - WDF completion routine for the request This must be specified because we are formatting the request and hence not using SEND_AND_FORGET flag Context - (optional) context to be passed in to the completion routine Return Value: Success implies that request was sent correctly and completion routine will be called for it, failure implies it was not sent and caller should complete the request Notes: This routine does not call WdfRequestReuse on the Request passed in. Caller must do so before passing in the request, if it is reusing the request. This routine does not complete the request in case of failure. Caller must complete the request in case of failure. --*/ { NTSTATUS status = BTH_ERROR_SUCCESS; WDF_OBJECT_ATTRIBUTES attributes; WDFMEMORY memoryArg1 = NULL; if (BrbSize <= 0) { TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, "BrbSize has invalid value: %I64d\n", BrbSize ); status = STATUS_INVALID_PARAMETER; goto exit; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = Request; status = WdfMemoryCreatePreallocated( &attributes, Brb, BrbSize, &memoryArg1 ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL, "Creating preallocted memory for Brb 0x%p failed, Request to be formatted 0x%p, " "Status code %!STATUS!\n", Brb, Request, status ); goto exit; } status = WdfIoTargetFormatRequestForInternalIoctlOthers( IoTarget, Request, IOCTL_INTERNAL_BTH_SUBMIT_BRB, memoryArg1, NULL, //OtherArg1Offset NULL, //OtherArg2 NULL, //OtherArg2Offset NULL, //OtherArg4 NULL //OtherArg4Offset ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL, "Formatting request 0x%p with Brb 0x%p failed, Status code %!STATUS!\n", Request, Brb, status ); goto exit; } // // Set a CompletionRoutine callback function. // WdfRequestSetCompletionRoutine( Request, ComplRoutine, Context ); if (FALSE == WdfRequestSend( Request, IoTarget, NULL )) { status = WdfRequestGetStatus(Request); TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL, "Request send failed for request 0x%p, Brb 0x%p, Status code %!STATUS!\n", Request, Brb, status ); goto exit; } exit: return status; }
NTSTATUS BthEchoRepeatReaderSubmit( _In_ PBTHECHOSAMPLE_DEVICE_CONTEXT_HEADER DevCtxHdr, _In_ PBTHECHO_REPEAT_READER RepeatReader ) /*++ Description: This routine submits the repeat reader. In case of failure it invoked contreader failed callback Arguments: DevCtxHdr - Device context header RepeatReader - Repeat reader to submit Return Value: NTSTATUS Status code. --*/ { NTSTATUS status, statusReuse; WDF_REQUEST_REUSE_PARAMS reuseParams; struct _BRB_L2CA_ACL_TRANSFER *brb = &RepeatReader->TransferBrb; DevCtxHdr->ProfileDrvInterface.BthReuseBrb((PBRB)brb, BRB_L2CA_ACL_TRANSFER); WDF_REQUEST_REUSE_PARAMS_INIT(&reuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_UNSUCCESSFUL); statusReuse = WdfRequestReuse(RepeatReader->RequestPendingRead, &reuseParams); NT_ASSERT(NT_SUCCESS(statusReuse)); UNREFERENCED_PARAMETER(statusReuse); // // Check if we are stopping, if yes set StopEvent and exit. // // After this point request is eligible for cancellation, so if this // flag gets set after we check it, request will be cancelled for stopping // the repeat reader and next time around we will stop when we are invoked // again upon completion of cancelled request. // if (RepeatReader->Stopping) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONT_READER, "Continuos reader 0x%p stopping", RepeatReader); KeSetEvent(&RepeatReader->StopEvent, 0, FALSE); status = STATUS_SUCCESS; goto exit; } // // Format request for L2CA IN transfer // status = BthEchoConnectionObjectFormatRequestForL2CaTransfer( RepeatReader->Connection, RepeatReader->RequestPendingRead, &brb, RepeatReader->MemoryPendingRead, ACL_TRANSFER_DIRECTION_IN | ACL_SHORT_TRANSFER_OK ); if (!NT_SUCCESS(status)) { goto exit; } // // Set a CompletionRoutine callback function. // WdfRequestSetCompletionRoutine( RepeatReader->RequestPendingRead, BthEchoRepeatReaderPendingReadCompletion, RepeatReader ); // // Clear the stop event before sending the request // This is relevant only on start of the repeat reader // (i.e. the first submission) // this event eventually gets set only when repeat reader stops // and not on every resubmission. // KeClearEvent(&RepeatReader->StopEvent); if (FALSE == WdfRequestSend( RepeatReader->RequestPendingRead, DevCtxHdr->IoTarget, NULL )) { status = WdfRequestGetStatus(RepeatReader->RequestPendingRead); TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, "Request send failed for request 0x%p, Brb 0x%p, Status code %!STATUS!\n", RepeatReader->RequestPendingRead, brb, status ); goto exit; } else { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONT_READER, "Resubmited pending read with request 0x%p, Brb 0x%p", RepeatReader->RequestPendingRead, brb ); } exit: if (!NT_SUCCESS(status)) { // // Invoke the reader failed callback before setting the event // to ensure that the connection object is alive during this callback // RepeatReader->Connection->ContinuousReader.BthEchoConnectionObjectContReaderFailedCallback( RepeatReader->Connection->DevCtxHdr, RepeatReader->Connection ); // // If we failed to send pending read, set the event since // we will not get completion callback // KeSetEvent(&RepeatReader->StopEvent, 0, FALSE); } return status; }
/////////////////////////////////////////////////////////////////////////////// // // BasicUsbEvtRead // // This routine is called by the framework when there is a // read request for us to process // // INPUTS: // // Queue - Our default queue // // Request - A read request // // Length - The length of the read operation // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // This routine is called at IRQL == PASSIVE_LEVEL, due to // our PASSIVE_LEVEL execution level contraint // // NOTES: // // /////////////////////////////////////////////////////////////////////////////// VOID BasicUsbEvtRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length) { PBASICUSB_DEVICE_CONTEXT devContext; WDFMEMORY requestMemory; NTSTATUS status; WDF_REQUEST_PARAMETERS requestParams; WDF_REQUEST_SEND_OPTIONS sendOptions; UNREFERENCED_PARAMETER(Length); #if DBG DbgPrint("BasicUsbEvtRead\n"); #endif devContext = BasicUsbGetContextFromDevice( WdfIoQueueGetDevice(Queue) ); // // The purpose of this routine will be to convert the read that // we received from the user into a USB request and send it to // the underlying bus driver. // // // First thing to do is get the output memory associated // with the request (only because it's a required parameter // to WdfUsbTargetPipeFormatRequestForRead) // status = WdfRequestRetrieveOutputMemory(Request, &requestMemory); if(!NT_SUCCESS(status)){ #if DBG DbgPrint("WdfRequestRetrieveOutputMemory failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); return; } // // Take the user Read request and format it into a Bulk // IN request. // status = WdfUsbTargetPipeFormatRequestForRead(devContext->BulkInPipe, Request, requestMemory, NULL); if(!NT_SUCCESS(status)){ #if DBG DbgPrint("WdfUsbTargetPipeFormatRequestForRead failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); return; } // // We'd like to asynchronously send this newly formatted request // to the underlying bus driver. In order to do that, we *must* // supply a completion routine that calls WdfRequestComplete. // Failure to do so is not architecturally defined, which means // it ain't gonna work. // // Note that because we have modified the request, we are not // allowed to use the WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET // flag as a cheap shortcut, we MUST supply the completion // routine. // WdfRequestSetCompletionRoutine( Request, BasicUsbEvtRequestReadCompletionRoutine, NULL); // // Send the request! // if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(devContext->BulkInPipe), NULL)) { // // Bad news. The target didn't get the request, so get the // failure status and complete the request ourselves.. // status = WdfRequestGetStatus(Request); #if DBG DbgPrint("WdfRequestSend failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); return; } return; }
VOID UsbSamp_EvtReadWriteCompletion( _In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, _In_ WDFCONTEXT Context ) /*++ Routine Description: This is the completion routine for reads/writes If the irp completes with success, we check if we need to recirculate this irp for another stage of transfer. Arguments: Context - Driver supplied context Device - Device handle Request - Request handle Params - request completion params Return Value: None --*/ { WDFUSBPIPE pipe; ULONG stageLength = 0; NTSTATUS status; PREQUEST_CONTEXT rwContext; ULONG bytesReadWritten; WDFMEMORY_OFFSET offset; PCHAR operation; PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams; PPIPE_CONTEXT pipeContext; WDF_USB_PIPE_INFORMATION pipeInfo; ULONG maxTransferSize; PDEVICE_CONTEXT deviceContext; usbCompletionParams = CompletionParams->Parameters.Usb.Completion; rwContext = GetRequestContext(Request); deviceContext = Context; if (rwContext->Read) { operation = "Read"; bytesReadWritten = (ULONG)usbCompletionParams->Parameters.PipeRead.Length; } else { operation = "Write"; bytesReadWritten = (ULONG)usbCompletionParams->Parameters.PipeWrite.Length; } pipe = (WDFUSBPIPE) Target; pipeContext = GetPipeContext(pipe); WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe,&pipeInfo); status = CompletionParams->IoStatus.Status; if (!NT_SUCCESS(status)){ // // Queue a workitem to reset the pipe because the completion could be // running at DISPATCH_LEVEL. // TODO: preallocate per pipe workitem to avoid allocation failure. QueuePassiveLevelCallback(WdfIoTargetGetDevice(Target), pipe); goto End; } rwContext->Numxfer += bytesReadWritten; // // If there is anything left to transfer. // if (rwContext->Length == 0) { // // this is the last transfer // WdfRequestSetInformation(Request, rwContext->Numxfer); goto End; } // // Start another transfer // UsbSamp_DbgPrint(3, ("Stage next %s transfer...\n", operation)); // // The transfer request is for totalLength. // We can perform a max of maxTransfersize in each stage. // maxTransferSize = GetMaxTransferSize(pipe, deviceContext); if (rwContext->Length > maxTransferSize) { stageLength = maxTransferSize; } else { stageLength = rwContext->Length; } offset.BufferOffset = rwContext->Numxfer; offset.BufferLength = stageLength; rwContext->Length -= stageLength; if (rwContext->Read) { status = WdfUsbTargetPipeFormatRequestForRead( pipe, Request, usbCompletionParams->Parameters.PipeRead.Buffer, &offset); } else { status = WdfUsbTargetPipeFormatRequestForWrite( pipe, Request, usbCompletionParams->Parameters.PipeWrite.Buffer, &offset); } if (!NT_SUCCESS(status)) { UsbSamp_DbgPrint(1, ("WdfUsbTargetPipeFormat%sRequest failed 0x%x\n", operation, status)); goto End; } #if (NTDDI_VERSION >= NTDDI_WIN8) // // If the request is for a super speed bulk pipe with streams, // configure its urb's PipeHandle with its associated stream's PipeHandle // if(WdfUsbPipeTypeBulk == pipeInfo.PipeType && pipeContext->StreamConfigured == TRUE) { ConfigureStreamPipeHandleForRequest(Request, pipe); } #endif WdfRequestSetCompletionRoutine( Request, UsbSamp_EvtReadWriteCompletion, deviceContext); // // Send the request asynchronously. // if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) { UsbSamp_DbgPrint(1, ("WdfRequestSend for %s failed\n", operation)); status = WdfRequestGetStatus(Request); goto End; } // // Else when the request completes, this completion routine will be // called again. // return; End: // // We are here because the request failed or some other call failed. // Dump the request context, complete the request and return. // DbgPrintRWContext(rwContext); UsbSamp_DbgPrint(3, ("%s request completed with status 0x%x\n", operation, status)); WdfRequestComplete(Request, status); return; }
VOID OsrFxEvtIoRead( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length ) /*++ Routine Description: Called by the framework when it receives Read or Write requests. Arguments: Queue - Default queue handle Request - Handle to the read/write request Lenght - Length of the data buffer associated with the request. The default property of the queue is to not dispatch zero lenght read & write requests to the driver and complete is with status success. So we will never get a zero length request. Return Value: --*/ { WDFUSBPIPE pipe; NTSTATUS status; WDFMEMORY reqMemory; PDEVICE_CONTEXT pDeviceContext; GUID activity = RequestToActivityId(Request); UNREFERENCED_PARAMETER(Queue); // // Log read start event, using IRP activity ID if available or request // handle otherwise. // EventWriteReadStart(&activity, WdfIoQueueGetDevice(Queue), (ULONG)Length); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "-->OsrFxEvtIoRead\n"); // // First validate input parameters. // if (Length > TEST_BOARD_TRANSFER_BUFFER_SIZE) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Transfer exceeds %d\n", TEST_BOARD_TRANSFER_BUFFER_SIZE); status = STATUS_INVALID_PARAMETER; goto Exit; } pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkReadPipe; status = WdfRequestRetrieveOutputMemory(Request, &reqMemory); if(!NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestRetrieveOutputMemory failed %!STATUS!\n", status); goto Exit; } // // The format call validates to make sure that you are reading or // writing to the right pipe type, sets the appropriate transfer flags, // creates an URB and initializes the request. // status = WdfUsbTargetPipeFormatRequestForRead(pipe, Request, reqMemory, NULL // Offsets ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfUsbTargetPipeFormatRequestForRead failed 0x%x\n", status); goto Exit; } WdfRequestSetCompletionRoutine( Request, EvtRequestReadCompletionRoutine, pipe); // // Send the request asynchronously. // if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) { // // Framework couldn't send the request for some reason. // TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestSend failed\n"); status = WdfRequestGetStatus(Request); goto Exit; } Exit: if (!NT_SUCCESS(status)) { // // log event read failed // EventWriteReadFail(&activity, WdfIoQueueGetDevice(Queue), status); WdfRequestCompleteWithInformation(Request, status, 0); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "<-- OsrFxEvtIoRead\n"); return; }
/*++ Routine Description: This is the completion routine for reads/writes If the irp completes with success, we check if we need to recirculate this irp for another stage of transfer. Arguments: Context - Driver supplied context Device - Device handle Request - Request handle Params - request completion params Return Value: None --*/ VOID ReadWriteCompletion(IN WDFREQUEST Request, IN WDFIOTARGET Target, PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, IN WDFCONTEXT Context) { PMDL requestMdl; WDFUSBPIPE pipe; ULONG stageLength; NTSTATUS status; PREQUEST_CONTEXT rwContext; PURB urb; PCHAR operation; ULONG bytesReadWritten; UNREFERENCED_PARAMETER(Context); rwContext = GetRequestContext(Request); PSDrv_DbgPrint(3, ("ReadWriteCompletion - begins\n")); if (rwContext->Read) { operation = "Read"; } else { operation = "Write"; } pipe = (WDFUSBPIPE)Target; status = CompletionParams->IoStatus.Status; if (!NT_SUCCESS(status)) { goto End; } urb = (PURB)WdfMemoryGetBuffer(rwContext->UrbMemory, NULL); bytesReadWritten = urb->UrbBulkOrInterruptTransfer.TransferBufferLength; rwContext->Numxfer += bytesReadWritten; // If there is anything left to transfer. if (rwContext->Length == 0) { // this is the last transfer WdfRequestSetInformation(Request, rwContext->Numxfer); goto End; } // Start another transfer PSDrv_DbgPrint(3, ("Stage next %s transfer...\n", operation)); if (rwContext->Length > MAX_TRANSFER_SIZE) { stageLength = MAX_TRANSFER_SIZE; } else { stageLength = rwContext->Length; } // Following call is required to free any mapping made on the partial MDL and reset internal MDL state. MmPrepareMdlForReuse(rwContext->Mdl); if (rwContext->Read) { status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl for Read failed! (Status = %x)\n", status)); goto End; } } else { status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl for Write failed! (Status = %x)\n", status)); goto End; } } IoBuildPartialMdl(requestMdl, rwContext->Mdl, (PVOID)rwContext->VirtualAddress, stageLength); // Reinitialize the urb urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stageLength; rwContext->VirtualAddress += stageLength; rwContext->Length -= stageLength; // Format the request to send a URB to a USB pipe. status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, rwContext->UrbMemory, NULL); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfUsbTargetPipeFormatRequestForUrb failed! (Status = %x)\n", status)); status = STATUS_INSUFFICIENT_RESOURCES; goto End; } WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL); // Send the request asynchronously. if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) { PSDrv_DbgPrint(1, ("WdfRequestSend for %s failed!\n", operation)); status = WdfRequestGetStatus(Request); goto End; } // Else when the request completes, this completion routine will be called again. PSDrv_DbgPrint(3, ("ReadWriteCompletion - ends 1\n")); return; End: // Dump the request context, complete the request and return. PSDrv_DbgPrint(3, ("rwContext->UrbMemory = %p\n", rwContext->UrbMemory)); PSDrv_DbgPrint(3, ("rwContext->Mdl = %p\n", rwContext->Mdl)); PSDrv_DbgPrint(3, ("rwContext->Length = %d\n", rwContext->Length)); PSDrv_DbgPrint(3, ("rwContext->Numxfer = %d\n", rwContext->Numxfer)); PSDrv_DbgPrint(3, ("rwContext->VirtualAddress = %p\n", rwContext->VirtualAddress)); IoFreeMdl(rwContext->Mdl); PSDrv_DbgPrint(3, ("Bulk or Interrupt %s request has finished. (Status = %x)\n", operation, status)); WdfRequestComplete(Request, status); PSDrv_DbgPrint(3, ("ReadWriteCompletion - ends 2\n")); return; }
/*++ Routine Description: This callback is invoked when the framework received WdfRequestTypeRead or WdfRequestTypeWrite request. This read/write is performed in stages of MAX_TRANSFER_SIZE. Once a stage of transfer is complete, then the request is circulated again, until the requested length of transfer is performed. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. This one represents the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework. Length - Length of the input/output buffer. Return Value: VOID --*/ VOID ReadWriteBulkEndPoints(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG Length, IN WDF_REQUEST_TYPE RequestType) { PMDL newMdl = NULL; PMDL requestMdl = NULL; PURB urb = NULL; WDFMEMORY urbMemory; ULONG totalLength = Length; ULONG stageLength = 0; ULONG urbFlags = 0; NTSTATUS status; ULONG_PTR virtualAddress = 0; PREQUEST_CONTEXT rwContext = NULL; PFILE_CONTEXT fileContext = NULL; WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; WDF_OBJECT_ATTRIBUTES objectAttribs; USBD_PIPE_HANDLE usbdPipeHandle; PDEVICE_CONTEXT deviceContext; WDF_REQUEST_SEND_OPTIONS sendOptions; PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - begins\n")); // First validate input parameters. deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); if (totalLength > deviceContext->MaximumTransferSize) { PSDrv_DbgPrint(1, ("Transfer length (%d) is bigger then MaximumTransferSize (%d)!\n", totalLength, deviceContext->MaximumTransferSize)); status = STATUS_INVALID_PARAMETER; goto Exit; } if ((RequestType != WdfRequestTypeRead) && (RequestType != WdfRequestTypeWrite)) { PSDrv_DbgPrint(1, ("RequestType has to be either Read or Write! (RequestType = %d)\n", RequestType)); status = STATUS_INVALID_PARAMETER; goto Exit; } // Get the pipe associate with this request. fileContext = GetFileContext(WdfRequestGetFileObject(Request)); pipe = fileContext->Pipe; WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe, &pipeInfo); if((WdfUsbPipeTypeBulk != pipeInfo.PipeType) && (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType)) { PSDrv_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt! (PipeType = %d)\n", pipeInfo.PipeType)); status = STATUS_INVALID_DEVICE_REQUEST; goto Exit; } rwContext = GetRequestContext(Request); if(RequestType == WdfRequestTypeRead) { status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed! (Status = %x)\n", status)); goto Exit; } urbFlags |= USBD_TRANSFER_DIRECTION_IN; rwContext->Read = TRUE; PSDrv_DbgPrint(3, ("This is a read operation...\n")); } else { status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed! (Status = %x)\n", status)); goto Exit; } urbFlags |= USBD_TRANSFER_DIRECTION_OUT; rwContext->Read = FALSE; PSDrv_DbgPrint(3, ("This is a write operation...\n")); } urbFlags |= USBD_SHORT_TRANSFER_OK; virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl); // The transfer request is for totalLength. We can perform a max of MAX_TRANSFER_SIZE in each stage. if (totalLength > MAX_TRANSFER_SIZE) { stageLength = MAX_TRANSFER_SIZE; } else { stageLength = totalLength; } newMdl = IoAllocateMdl((PVOID)virtualAddress, totalLength, FALSE, FALSE, NULL); if (newMdl == NULL) { PSDrv_DbgPrint(1, ("IoAllocateMdl failed! (newMdl is NULL)\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } // Map the portion of user-buffer described by an mdl to another mdl IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress, stageLength); WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); objectAttribs.ParentObject = Request; status = WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), &urbMemory, (PVOID*)&urb); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfMemoryCreate for urbMemory failed! (Status = %x)\n", status)); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe); UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, urbFlags, NULL); status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL); if (!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfUsbTargetPipeFormatRequestForUrb failed! (Status = %x)\n", status)); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL); // Set REQUEST_CONTEXT parameters. rwContext->UrbMemory = urbMemory; rwContext->Mdl = newMdl; rwContext->Length = totalLength - stageLength; rwContext->Numxfer = 0; rwContext->VirtualAddress = virtualAddress + stageLength; // Set the timeout if (fileContext->nTimeOut != 0) { WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(fileContext->nTimeOut)); PSDrv_DbgPrint(3, ("Pipe timeout is set to: %d\n", fileContext->nTimeOut)); if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), &sendOptions)) { status = WdfRequestGetStatus(Request); ASSERT(!NT_SUCCESS(status)); } } else { if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) { status = WdfRequestGetStatus(Request); ASSERT(!NT_SUCCESS(status)); } } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); if (newMdl != NULL) { IoFreeMdl(newMdl); } } PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - ends\n")); return; }
VOID ReadWriteBulkEndPoints( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ ULONG Length, _In_ WDF_REQUEST_TYPE RequestType ) /*++ Routine Description: This callback is invoked when the framework received WdfRequestTypeRead or RP_MJ_WRITE request. This read/write is performed in stages of maximum transfer size. Once a stage of transfer is complete, then the request is circulated again, until the requested length of transfer is performed. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. This one represents the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework. Length - Length of the input/output buffer. Return Value: VOID --*/ { size_t totalLength = Length; size_t stageLength = 0; NTSTATUS status; PVOID virtualAddress = 0; PREQUEST_CONTEXT rwContext = NULL; PFILE_CONTEXT fileContext = NULL; WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; WDFMEMORY reqMemory; WDFMEMORY_OFFSET offset; WDF_OBJECT_ATTRIBUTES objectAttribs; PDEVICE_CONTEXT deviceContext; PPIPE_CONTEXT pipeContext; ULONG maxTransferSize; UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - begins\n")); // // First validate input parameters. // deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); if (totalLength > deviceContext->MaximumTransferSize) { UsbSamp_DbgPrint(1, ("Transfer length > circular buffer\n")); status = STATUS_INVALID_PARAMETER; goto Exit; } if ((RequestType != WdfRequestTypeRead) && (RequestType != WdfRequestTypeWrite)) { UsbSamp_DbgPrint(1, ("RequestType has to be either Read or Write\n")); status = STATUS_INVALID_PARAMETER; goto Exit; } // // Get the pipe associate with this request. // fileContext = GetFileContext(WdfRequestGetFileObject(Request)); pipe = fileContext->Pipe; pipeContext = GetPipeContext(pipe); WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe, &pipeInfo); rwContext = GetRequestContext(Request); if (RequestType == WdfRequestTypeRead) { status = WdfRequestRetrieveOutputBuffer(Request, Length, &virtualAddress, &totalLength); rwContext->Read = TRUE; } else { //Write status = WdfRequestRetrieveInputBuffer(Request, Length, &virtualAddress, &totalLength); rwContext->Read = FALSE; } if (!NT_SUCCESS(status)){ UsbSamp_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n")); goto Exit; } // // The transfer request is for totalLength. // We can perform a max of maxTransfersize in each stage. // maxTransferSize = GetMaxTransferSize(pipe, deviceContext); if (totalLength > maxTransferSize) { stageLength = maxTransferSize; } else { stageLength = totalLength; } WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); objectAttribs.ParentObject = Request; status = WdfMemoryCreatePreallocated(&objectAttribs, virtualAddress, totalLength, &reqMemory); if (!NT_SUCCESS(status)){ UsbSamp_DbgPrint(1, ("WdfMemoryCreatePreallocated failed\n")); goto Exit; } offset.BufferOffset = 0; offset.BufferLength = stageLength; // // The framework format call validates to make sure that you are reading or // writing to the right pipe type, sets the appropriate transfer flags, // creates an URB and initializes the request. // if (RequestType == WdfRequestTypeRead) { UsbSamp_DbgPrint(3, ("Read operation\n")); status = WdfUsbTargetPipeFormatRequestForRead(pipe, Request, reqMemory, &offset); } else { UsbSamp_DbgPrint(3, ("Write operation\n")); status = WdfUsbTargetPipeFormatRequestForWrite(pipe, Request, reqMemory, &offset); } if (!NT_SUCCESS(status)) { UsbSamp_DbgPrint(1, ("WdfUsbTargetPipeFormatRequest failed 0x%x\n", status)); goto Exit; } #if (NTDDI_VERSION >= NTDDI_WIN8) // // If the request is for a super speed bulk pipe with streams, // configure its urb's PipeHandle with its associated stream's PipeHandle // if(WdfUsbPipeTypeBulk == pipeInfo.PipeType && pipeContext->StreamConfigured == TRUE) { ConfigureStreamPipeHandleForRequest(Request, pipe); } #endif WdfRequestSetCompletionRoutine( Request, UsbSamp_EvtReadWriteCompletion, deviceContext); // // set REQUEST_CONTEXT parameters. // rwContext->Length = (ULONG)totalLength - (ULONG)stageLength; rwContext->Numxfer = 0; // // Send the request asynchronously. // if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) { UsbSamp_DbgPrint(1, ("WdfRequestSend failed\n")); status = WdfRequestGetStatus(Request); goto Exit; } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); } UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - ends\n")); return; }
NTSTATUS ToastMon_PostWriteRequests( IN WDFIOTARGET IoTarget ) /*++ Routine Description: Called by the timer callback to send a write request to the target device. Return Value: NT Status code - only failure expected is STATUS_INSUFFICIENT_RESOURCES --*/ { WDFREQUEST request; NTSTATUS status; PTARGET_DEVICE_INFO targetInfo; WDFMEMORY memory; WDF_OBJECT_ATTRIBUTES attributes; targetInfo = GetTargetDeviceInfo(IoTarget); request = targetInfo->WriteRequest; // // Allocate memory for write. Ideally I should have allocated the memory upfront along // with the request because the sizeof the memory buffer is constant. // But for demonstration, I have choosen to allocate a memory // object everytime I send a request down and delete it when the request // is completed. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); status = WdfMemoryCreate( &attributes, NonPagedPool, DRIVER_TAG, WRITE_BUF_SIZE, &memory, NULL); // buffer pointer if (!NT_SUCCESS(status)) { KdPrint(("WdfMemoryCreate failed 0x%x\n", status)); return status; } status = WdfIoTargetFormatRequestForWrite( IoTarget, request, memory, NULL, // Buffer offset NULL); // OutputBufferOffset if (!NT_SUCCESS(status)) { KdPrint(("WdfIoTargetFormatRequestForWrite failed 0x%x\n", status)); return status; } WdfRequestSetCompletionRoutine(request, Toastmon_WriteRequestCompletionRoutine, targetInfo); // // Clear the WriteRequest field in the context to avoid // being reposted even before the reqeuest completes. // This will be reset in the complete routine when the request completes. // targetInfo->WriteRequest = NULL; if(WdfRequestSend(request, IoTarget, WDF_NO_SEND_OPTIONS) == FALSE) { status = WdfRequestGetStatus(request); KdPrint(("WdfRequestSend failed 0x%x\n", status)); targetInfo->WriteRequest = request; } return status; }
VOID UsbSamp_EvtReadWriteCompletion( _In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, _In_ WDFCONTEXT Context ) /*++ Routine Description: This is the completion routine for reads/writes If the irp completes with success, we check if we need to recirculate this irp for another stage of transfer. Arguments: Context - Driver supplied context Device - Device handle Request - Request handle Params - request completion params Return Value: None --*/ { PMDL requestMdl; WDFUSBPIPE pipe; ULONG stageLength; NTSTATUS status; PREQUEST_CONTEXT rwContext; PURB urb; PCHAR operation; ULONG bytesReadWritten; ULONG maxTransferSize; PDEVICE_CONTEXT deviceContext; rwContext = GetRequestContext(Request); deviceContext = Context; if (rwContext->Read) { operation = "Read"; } else { operation = "Write"; } pipe = (WDFUSBPIPE) Target ; status = CompletionParams->IoStatus.Status; if (!NT_SUCCESS(status)){ // // Queue a workitem to reset the pipe because the completion could be // running at DISPATCH_LEVEL. // QueuePassiveLevelCallback(WdfIoTargetGetDevice(Target), pipe); goto End; } urb = (PURB) WdfMemoryGetBuffer(rwContext->UrbMemory, NULL); bytesReadWritten = urb->UrbBulkOrInterruptTransfer.TransferBufferLength; rwContext->Numxfer += bytesReadWritten; // // If there is anything left to transfer. // if (rwContext->Length == 0) { // // this is the last transfer // WdfRequestSetInformation(Request, rwContext->Numxfer); goto End; } // // Start another transfer // UsbSamp_DbgPrint(3, ("Stage next %s transfer...\n", operation)); // // The transfer request is for totalLength. // We can perform a max of maxTransfersize in each stage. // maxTransferSize = GetMaxTransferSize(pipe, deviceContext); if (rwContext->Length > maxTransferSize) { stageLength = maxTransferSize; } else { stageLength = rwContext->Length; } // // Following call is required to free any mapping made on the partial MDL // and reset internal MDL state. // MmPrepareMdlForReuse(rwContext->Mdl); if (rwContext->Read) { status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl); if (!NT_SUCCESS(status)){ UsbSamp_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl for Read failed %x\n", status)); goto End; } } else { status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl); if (!NT_SUCCESS(status)){ UsbSamp_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl for Write failed %x\n", status)); goto End; } } IoBuildPartialMdl(requestMdl, rwContext->Mdl, (PVOID) rwContext->VirtualAddress, stageLength); // // reinitialize the urb // urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stageLength; rwContext->VirtualAddress += stageLength; rwContext->Length -= stageLength; // // Format the request to send a URB to a USB pipe. // status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, rwContext->UrbMemory, NULL); if (!NT_SUCCESS(status)) { UsbSamp_DbgPrint(1, ("Failed to format requset for urb\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto End; } WdfRequestSetCompletionRoutine(Request, UsbSamp_EvtReadWriteCompletion, deviceContext); // // Send the request asynchronously. // if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) { UsbSamp_DbgPrint(1, ("WdfRequestSend for %s failed\n", operation)); status = WdfRequestGetStatus(Request); goto End; } // // Else when the request completes, this completion routine will be // called again. // return; End: // // We are here because the request failed or some other call failed. // Dump the request context, complete the request and return. // DbgPrintRWContext(rwContext); IoFreeMdl(rwContext->Mdl); UsbSamp_DbgPrint(3, ("%s request completed with status 0x%x\n", operation, status)); WdfRequestComplete(Request, status); return; }
VOID SerialEvtCanceledOnQueue( IN WDFQUEUE Queue, IN WDFREQUEST Request ) /*++ Routine Description: Called when the request is cancelled while it's waiting on the queue. This callback is used instead of EvtCleanupCallback on the request because this one will be called with the presentation lock held. Arguments: Queue - Queue in which the request currently waiting Request - Request being cancelled Return Value: None. --*/ { PSERIAL_DEVICE_EXTENSION extension = NULL; PREQUEST_CONTEXT reqContext; UNREFERENCED_PARAMETER(Queue); reqContext = SerialGetRequestContext(Request); extension = reqContext->Extension; // // If this is a write request then take the amount of characters // to write and subtract it from the count of characters to write. // if (reqContext->MajorFunction == IRP_MJ_WRITE) { extension->TotalCharsQueued -= reqContext->Length; } else if (reqContext->MajorFunction == IRP_MJ_DEVICE_CONTROL) { // // If it's an immediate then we need to decrement the // count of chars queued. If it's a resize then we // need to deallocate the pool that we're passing on // to the "resizing" routine. // if (( reqContext->IoctlCode == IOCTL_SERIAL_IMMEDIATE_CHAR) || (reqContext->IoctlCode == IOCTL_SERIAL_XOFF_COUNTER)) { extension->TotalCharsQueued--; } else if (reqContext->IoctlCode == IOCTL_SERIAL_SET_QUEUE_SIZE) { // // We shoved the pointer to the memory into the // the type 3 buffer pointer which we KNOW we // never use. // ASSERT(reqContext->Type3InputBuffer); ExFreePool(reqContext->Type3InputBuffer); reqContext->Type3InputBuffer = NULL; } } SerialCompleteRequest(Request, WdfRequestGetStatus(Request), 0); }
VOID ReadWriteBulkEndPoints( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ ULONG Length, _In_ WDF_REQUEST_TYPE RequestType ) /*++ Routine Description: This callback is invoked when the framework received WdfRequestTypeRead or WdfRequestTypeWrite request. This read/write is performed in stages of maximum transfer size. Once a stage of transfer is complete, then the request is circulated again, until the requested length of transfer is performed. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. This one represents the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework. Length - Length of the input/output buffer. Return Value: VOID --*/ { PMDL newMdl=NULL, requestMdl = NULL; PURB urb = NULL; WDFMEMORY urbMemory; ULONG totalLength = Length; ULONG stageLength = 0; ULONG urbFlags = 0; NTSTATUS status; ULONG_PTR virtualAddress = 0; PREQUEST_CONTEXT rwContext = NULL; PFILE_CONTEXT fileContext = NULL; WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; WDF_OBJECT_ATTRIBUTES objectAttribs; USBD_PIPE_HANDLE usbdPipeHandle; PDEVICE_CONTEXT deviceContext; ULONG maxTransferSize; PPIPE_CONTEXT pipeContext; UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - begins\n")); // // First validate input parameters. // deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); if (totalLength > deviceContext->MaximumTransferSize) { UsbSamp_DbgPrint(1, ("Transfer length > circular buffer\n")); status = STATUS_INVALID_PARAMETER; goto Exit; } if ((RequestType != WdfRequestTypeRead) && (RequestType != WdfRequestTypeWrite)) { UsbSamp_DbgPrint(1, ("RequestType has to be either Read or Write\n")); status = STATUS_INVALID_PARAMETER; goto Exit; } // // Get the pipe associate with this request. // fileContext = GetFileContext(WdfRequestGetFileObject(Request)); pipe = fileContext->Pipe; pipeContext = GetPipeContext(pipe); WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe, &pipeInfo); if ((WdfUsbPipeTypeBulk != pipeInfo.PipeType) && (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType)) { UsbSamp_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt\n")); status = STATUS_INVALID_DEVICE_REQUEST; goto Exit; } rwContext = GetRequestContext(Request); if (RequestType == WdfRequestTypeRead) { status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl); if (!NT_SUCCESS(status)){ UsbSamp_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed %x\n", status)); goto Exit; } urbFlags |= USBD_TRANSFER_DIRECTION_IN; rwContext->Read = TRUE; UsbSamp_DbgPrint(3, ("Read operation\n")); } else { status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl); if (!NT_SUCCESS(status)){ UsbSamp_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed %x\n", status)); goto Exit; } urbFlags |= USBD_TRANSFER_DIRECTION_OUT; rwContext->Read = FALSE; UsbSamp_DbgPrint(3, ("Write operation\n")); } urbFlags |= USBD_SHORT_TRANSFER_OK; virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl); // // The transfer request is for totalLength. // We can perform a max of maxTransfersize in each stage. // maxTransferSize = GetMaxTransferSize(pipe, deviceContext); if (totalLength > maxTransferSize) { stageLength = maxTransferSize; } else { stageLength = totalLength; } newMdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL); if (newMdl == NULL) { UsbSamp_DbgPrint(1, ("Failed to alloc mem for mdl\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } // // map the portion of user-buffer described by an mdl to another mdl // IoBuildPartialMdl(requestMdl, newMdl, (PVOID) virtualAddress, stageLength); WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); objectAttribs.ParentObject = Request; status = WdfUsbTargetDeviceCreateUrb(deviceContext->WdfUsbTargetDevice, &objectAttribs, &urbMemory, &urb); if (!NT_SUCCESS(status)) { UsbSamp_DbgPrint(1, ("WdfUsbTargetDeviceCreateUrb failed %x\n", status)); goto Exit; } #if (NTDDI_VERSION >= NTDDI_WIN8) if(WdfUsbPipeTypeBulk == pipeInfo.PipeType && pipeContext->StreamConfigured == TRUE) { // // For super speed bulk pipe with streams, we specify one of its associated // usbd pipe handles to format an URB for sending or receiving data. // The usbd pipe handle is returned by the HCD via sucessful open-streams request // usbdPipeHandle = GetStreamPipeHandleFromBulkPipe(pipe); } else { usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe); } #else usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe); #endif UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, urbFlags, NULL); status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL ); if (!NT_SUCCESS(status)) { UsbSamp_DbgPrint(1, ("Failed to format requset for urb\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } WdfRequestSetCompletionRoutine(Request, UsbSamp_EvtReadWriteCompletion, deviceContext); // // set REQUEST_CONTEXT parameters. // rwContext->UrbMemory = urbMemory; rwContext->Mdl = newMdl; rwContext->Length = totalLength - stageLength; rwContext->Numxfer = 0; rwContext->VirtualAddress = virtualAddress + stageLength; if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) { status = WdfRequestGetStatus(Request); NT_ASSERT(!NT_SUCCESS(status)); } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); if (newMdl != NULL) { IoFreeMdl(newMdl); } } UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - ends\n")); return; }