static VOID UsbChief_EvtIoWrite(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { UNREFERENCED_PARAMETER(Queue); PAGED_CODE(); UsbChief_DbgPrint(DEBUG_RW, ("EvtIoWrite %d\n", Length)); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_DEVICE_REQUEST, 0); }
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); }
VOID NICFreeQueuedSendPackets( IN PFDO_DATA FdoData ) /*++ Routine Description: Free and complete the pended sends on SendQueueHead Assumption: This function is called with the Send SPINLOCK held. Arguments: FdoData Pointer to our FdoData Return Value: None --*/ { WDFREQUEST request; NTSTATUS status; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> NICFreeQueuedSendPackets\n"); do { status = WdfIoQueueRetrieveNextRequest( FdoData->PendingWriteQueue, &request ); if(!NT_SUCCESS(status) ) { if(STATUS_NO_MORE_ENTRIES != status){ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "WdfIoQueueRetrieveNextRequest failed %x\n", status); } break; } FdoData->nWaitSend--; WdfSpinLockRelease(FdoData->SendLock); WdfRequestCompleteWithInformation(request, status, 0); WdfSpinLockAcquire(FdoData->SendLock); } WHILE (TRUE); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- NICFreeQueuedSendPackets\n"); }
VOID EvtRequestReadCompletionRoutine( 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 --*/ { NTSTATUS status; size_t bytesRead = 0; PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams; UNREFERENCED_PARAMETER(Target); UNREFERENCED_PARAMETER(Context); status = CompletionParams->IoStatus.Status; usbCompletionParams = CompletionParams->Parameters.Usb.Completion; bytesRead = usbCompletionParams->Parameters.PipeRead.Length; if (NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "Number of bytes read: %I64d\n", (INT64)bytesRead); } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Read failed - request status 0x%x UsbdStatus 0x%x\n", status, usbCompletionParams->UsbdStatus); } WdfRequestCompleteWithInformation(Request, status, bytesRead); return; }
VOID ToasterEvtIoRead ( WDFQUEUE Queue, WDFREQUEST Request, size_t Length ) /*++ Routine Description: Performs read from the toaster device. This event is called when the framework receives IRP_MJ_READ requests. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. Lenght - Length of the data buffer associated with the request. By default, the queue does not dispatch zero length read & write requests to the driver and instead to complete such requests with status success. So we will never get a zero length request. Return Value: None. --*/ { NTSTATUS status; ULONG_PTR bytesCopied =0; WDFMEMORY memory; UNREFERENCED_PARAMETER(Queue); UNREFERENCED_PARAMETER(Length); PAGED_CODE(); KdPrint(( "ToasterEvtIoRead: Request: 0x%p, Queue: 0x%p\n", Request, Queue)); // // Get the request memory and perform read operation here // status = WdfRequestRetrieveOutputMemory(Request, &memory); if(NT_SUCCESS(status) ) { // // Copy data into the memory buffer using WdfMemoryCopyFromBuffer // } WdfRequestCompleteWithInformation(Request, status, bytesCopied); }
VOID FireShockEvtIoWrite( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length ) { NTSTATUS status; PDEVICE_CONTEXT pDeviceContext; LPVOID buffer; size_t bufferLength; size_t transferred = 0; pDeviceContext = DeviceGetContext(WdfIoQueueGetDevice(Queue)); switch (pDeviceContext->DeviceType) { case DualShock3: status = WdfRequestRetrieveInputBuffer( Request, DS3_HID_OUTPUT_REPORT_SIZE, &buffer, &bufferLength); if (NT_SUCCESS(status) && Length == bufferLength) { status = SendControlRequest( pDeviceContext, BmRequestHostToDevice, BmRequestClass, SetReport, USB_SETUP_VALUE(HidReportRequestTypeOutput, HidReportRequestIdOne), 0, buffer, (ULONG)bufferLength); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "SendControlRequest failed with status %!STATUS!", status); break; } transferred = bufferLength; } break; default: status = STATUS_NOT_SUPPORTED; break; } WdfRequestCompleteWithInformation(Request, status, transferred); }
// 读回调 VOID EvtIoRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { NTSTATUS status; PVOID outBuf; // 输出缓冲区 size_t bufLength; // 输出缓冲区大小 ULONG_PTR bytesRead = 0; // 实际读取的字节数 // 获取输出缓冲区地址 status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufLength); if( !NT_SUCCESS(status) ) { KdPrint(("[EvtIoRead] WdfRequestRetrieveOutputBuffer failed!")); WdfRequestComplete(Request, status); return ; } // 实际读取的字节数与文件指针有关 bytesRead = ((IO_BUFFER_SIZE - gFilePointer) < Length ) ? IO_BUFFER_SIZE - gFilePointer : Length; // 检查参数 if( bufLength < bytesRead ) { WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } // 文件指针已经到末尾 if( 0 == bytesRead ) { WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 0); return; } // 拷贝内容到输出缓冲区 RtlCopyMemory(outBuf, gFileBuffer+gFilePointer, bytesRead); WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, bytesRead); }
__inline VOID MP_FREE_SEND_PACKET( IN PFDO_DATA FdoData, IN PMP_TCB pMpTcb, IN NTSTATUS Status ) /*++ Routine Description: Recycle a MP_TCB and complete the packet if necessary Assumption: This function is called with the Send SPINLOCK held. Arguments: FdoData Pointer to our FdoData pMpTcb Pointer to MP_TCB Return Value: None --*/ { WDFREQUEST request; WDFDMATRANSACTION dmaTransaction; size_t length; ASSERT(MP_TEST_FLAG(pMpTcb, fMP_TCB_IN_USE)); dmaTransaction = pMpTcb->DmaTransaction; pMpTcb->DmaTransaction = NULL; MP_CLEAR_FLAGS(pMpTcb); FdoData->CurrSendHead = FdoData->CurrSendHead->Next; FdoData->nBusySend--; request = WdfDmaTransactionGetRequest(dmaTransaction); length = WdfDmaTransactionGetBytesTransferred(dmaTransaction); WdfObjectDelete( dmaTransaction ); if (request) { WdfSpinLockRelease(FdoData->SendLock); WdfRequestCompleteWithInformation(request, Status, length); FdoData->BytesTransmitted += length; WdfSpinLockAcquire(FdoData->SendLock); } }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaEventsDequeue -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- // DtStatus DtaEventsDequeue( DtaDeviceData* pDvcData, DtFileObject* pFile, DtaEvents* pEvents) // If not NULL, we don't need the file object { WDF_REQUEST_PARAMETERS Params; WDFREQUEST Request; WDFREQUEST Request2; NTSTATUS NtStatus = STATUS_SUCCESS; size_t BufSize; DtaIoctlOutputData* pOutBuf; // Get all pending requests from queue for this file object while (NtStatus == STATUS_SUCCESS) { WDF_REQUEST_PARAMETERS_INIT(&Params); NtStatus = WdfIoQueueFindRequest(pDvcData->m_IalData.m_EventQueue, NULL, DtFileGetHandle(pFile), &Params, &Request); if (NtStatus != STATUS_SUCCESS) // Don't use the NT_SUCCESS macro here break; NtStatus = WdfIoQueueRetrieveFoundRequest(pDvcData->m_IalData.m_EventQueue, Request, &Request2); WdfObjectDereference(Request); if (!NT_SUCCESS(NtStatus)) continue; if (NT_SUCCESS(NtStatus)) { NtStatus = WdfRequestRetrieveOutputBuffer(Request2, Params.Parameters.DeviceIoControl.OutputBufferLength, &pOutBuf, &BufSize); } if (NT_SUCCESS(NtStatus)) { DtStatus Status; BufSize = sizeof(DtaIoctlGetEventOutput); Status = DtaEventsGet(pDvcData, pFile, pEvents, &pOutBuf->m_GetEvent.m_EventType, &pOutBuf->m_GetEvent.m_Value1, &pOutBuf->m_GetEvent.m_Value2); } if (!NT_SUCCESS(NtStatus)) BufSize = 0; // Complete request, use DtStatus in the driver-defined information field WdfRequestCompleteWithInformation(Request2, NtStatus, (ULONG_PTR)BufSize); } return DT_STATUS_OK; }
void AndroidUsbFileObject::OnEvtIoWrite(WDFREQUEST request, size_t length) { ASSERT_IRQL_LOW_OR_DISPATCH(); ASSERT(WdfRequestGetFileObject(request) == wdf_file()); // Complete zero writes with success if (0 == length) { WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, 0); return; } WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST); }
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 AndroidUsbPipeFileObject::OnCtlBulkRead(WDFREQUEST request, size_t output_buf_len, size_t input_buf_len) { ASSERT_IRQL_LOW_OR_DISPATCH(); // Make sure that this is an input pipe if (is_output_pipe()) { GoogleDbgPrint("\n!!!! Attempt to IOCTL read from output pipe %p", this); WdfRequestComplete(request, STATUS_ACCESS_DENIED); return; } // Make sure zero length I/O doesn't go through if (0 == output_buf_len) { WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, 0); return; } // Verify buffers ASSERT(input_buf_len >= sizeof(AdbBulkTransfer)); if (input_buf_len < sizeof(AdbBulkTransfer)) { WdfRequestComplete(request, STATUS_INVALID_BUFFER_SIZE); return; } // Get the input buffer NTSTATUS status; AdbBulkTransfer* transfer_param = reinterpret_cast<AdbBulkTransfer*>(InAddress(request, &status)); ASSERT(NT_SUCCESS(status) && (NULL != transfer_param)); if (!NT_SUCCESS(status)) { WdfRequestComplete(request, status); return; } // Get MDL for this request. PMDL request_mdl = NULL; status = WdfRequestRetrieveOutputWdmMdl(request, &request_mdl); ASSERT(NT_SUCCESS(status) && (NULL != request_mdl)); if (NT_SUCCESS(status)) { // Perform the read CommonBulkReadWrite(request, request_mdl, static_cast<ULONG>(output_buf_len), true, transfer_param->time_out, true); } else { WdfRequestComplete(request, status); } }
VOID tgwinkEvtIoRead( WDFQUEUE Queue, WDFREQUEST Request, size_t Length ) { NTSTATUS status; WDFMEMORY mem; WDF_REQUEST_PARAMETERS params; ULONG offset; ULONG result; PDEVICE_CONTEXT context; WDFDEVICE device; device = WdfIoQueueGetDevice(Queue); context = DeviceGetContext(device); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(Request, ¶ms); offset = (ULONG)params.Parameters.Read.DeviceOffset; status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoRead could not get request memory buffer, status 0x%x\n", status); WdfVerifierDbgBreakPoint(); WdfRequestCompleteWithInformation(Request, status, 0); return; } result = context->busInterface.GetBusData(context->busInterface.Context, PCI_WHICHSPACE_CONFIG, WdfMemoryGetBuffer(mem, NULL), offset, (ULONG)Length); WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)result); }
void AndroidUsbPipeFileObject::OnCtlGetEndpointInformation( WDFREQUEST request, size_t output_buf_len) { ASSERT_IRQL_LOW_OR_DISPATCH(); // Verify output buffer if (output_buf_len < sizeof(AdbEndpointInformation)) { WdfRequestCompleteWithInformation(request, STATUS_BUFFER_TOO_SMALL, sizeof(AdbEndpointInformation)); return; } // Get the output buffer NTSTATUS status; AdbEndpointInformation* ret_info = reinterpret_cast<AdbEndpointInformation*>(OutAddress(request, &status)); ASSERT(NT_SUCCESS(status) && (NULL != ret_info)); if (!NT_SUCCESS(status)) { WdfRequestComplete(request, status); return; } // Copy endpoint info to the output ret_info->max_packet_size = pipe_information_.MaximumPacketSize; ret_info->endpoint_address = pipe_information_.EndpointAddress; ret_info->polling_interval = pipe_information_.Interval; ret_info->setting_index = pipe_information_.SettingIndex; ret_info->endpoint_type = static_cast<AdbEndpointType>(pipe_information_.PipeType); ret_info->max_transfer_size = pipe_information_.MaximumTransferSize; WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, sizeof(AdbEndpointInformation)); }
VOID PVPanicEvtQueueDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; ULONG length = 0; PVOID buffer; size_t buffer_length; PAGED_CODE(); UNREFERENCED_PARAMETER(Queue); UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(OutputBufferLength); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> %!FUNC!"); switch (IoControlCode) { case IOCTL_GET_CRASH_DUMP_HEADER: { // Return the full result of KeInitializeCrashDumpHeader. status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &buffer_length); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed: %!STATUS!", status); break; } status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, // flags, must be 0 buffer, (ULONG)buffer_length, &length); if (status == STATUS_INVALID_PARAMETER_4) { status = STATUS_BUFFER_TOO_SMALL; } break; } } WdfRequestCompleteWithInformation(Request, status, NT_SUCCESS(status) ? length : 0); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- %!FUNC!"); }
VOID EvtIoDeviceControl( __in WDFQUEUE IoQueue, __in WDFREQUEST Request, __in size_t OutBufferLength, __in size_t InBufferLength, __in ULONG IoControlCode ) { PDEVICE_CONTEXT DeviceContext; ULONG_PTR Information; NTSTATUS Status; PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> EvtIoDeviceControl(%x)\n", IoControlCode); // // Get the pointer to the device's context area. // We are using the queue handle to get the device handle. // DeviceContext = GetDeviceContext(WdfIoQueueGetDevice(IoQueue)); Information = 0; switch(IoControlCode) { case IOCTL_SHOW_DATA: //Status = EraseFirstSector(WdfIoQueueGetDevice(IoQueue)); //ShowFwhRegisters(DeviceContext->Lpc); //ShowRcrbRegisters(DeviceContext->Rcrb); //ShowSpiRegisters(DeviceContext->Rcrb + SPIBAR_OFFSET); Status = STATUS_SUCCESS; break; default: Status = STATUS_INVALID_DEVICE_REQUEST; break; } // // Complete the I/O request // WdfRequestCompleteWithInformation(Request, Status, Information); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- EvtIoDeviceControl(%x)\n", IoControlCode); }
VOID EchoEvtRequestCancel( IN WDFREQUEST Request ) /*++ Routine Description: Called when an I/O request is cancelled after the driver has marked the request cancellable. This callback is automatically synchronized with the I/O callbacks since we have chosen to use frameworks Device level locking. Arguments: Request - Request being cancelled. Return Value: VOID --*/ { PQUEUE_CONTEXT queueContext = QueueGetContext(WdfRequestGetIoQueue(Request)); KdPrint(("EchoEvtRequestCancel called on Request 0x%p\n", Request)); // // The following is race free by the callside or DPC side // synchronizing completion by calling // WdfRequestMarkCancelable(Queue, Request, FALSE) before // completion and not calling WdfRequestComplete if the // return status == STATUS_CANCELLED. // WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); // // This book keeping is synchronized by the common // Queue presentation lock // ASSERT(queueContext->CurrentRequest == Request); queueContext->CurrentRequest = NULL; return; }
// 中断Pipe回调函数。这样一旦设备产生了中断信息,驱动就能够读取到。 // VOID InterruptRead(WDFUSBPIPE Pipe, WDFMEMORY Buffer, size_t NumBytesTransferred, WDFCONTEXT Context) { NTSTATUS status; size_t size = 0; PDEVICE_CONTEXT pContext = (PDEVICE_CONTEXT)Context; WDFREQUEST Request = NULL; CHAR *pchBuf = NULL; KDBG(DPFLTR_INFO_LEVEL, "[InterruptRead]"); UNREFERENCED_PARAMETER(Pipe); // Read数据缓冲区。注意到,缓冲区长度总是管道最大包长度的倍数。 // 我们这里只用缓冲区的第一个有效字节。 pchBuf = (CHAR*)WdfMemoryGetBuffer(Buffer, &size); if(pchBuf == NULL || size == 0) return; // 第一个字节为确认字节,一定是0xD4 //if(pchBuf[0] != 0xD4)return; // 从队列中提取一个未完成请求 status = WdfIoQueueRetrieveNextRequest(pContext->InterruptManualQueue, &Request); if(NT_SUCCESS(status)) { CHAR* pOutputBuffer = NULL; status = WdfRequestRetrieveOutputBuffer(Request, 1, &pOutputBuffer, NULL); if(NT_SUCCESS(status)) { // 把结果返回给应用程序 pOutputBuffer[0] = pchBuf[1]; WdfRequestCompleteWithInformation(Request, status, 1); } else { // 返回错误 WdfRequestComplete(Request, status); } KDBG(DPFLTR_INFO_LEVEL, "Get and finish an interrupt read request."); }else{ // 队列空,将放弃从设备获取的数据。 KDBG(DPFLTR_INFO_LEVEL, "Manual interrupt queue is empty!!!"); } }
VOID VIOSerialPortWriteRequestCancel(IN WDFREQUEST Request) { PVIOSERIAL_PORT Port = RawPdoSerialPortGetData( WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)))->port; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s Request: 0x%p\n", __FUNCTION__, Request); // synchronize with VIOSerialReclaimConsumedBuffers because the pending // request is not guaranteed to be alive after we return from this callback WdfSpinLockAcquire(Port->OutVqLock); Port->PendingWriteRequest = NULL; WdfSpinLockRelease(Port->OutVqLock); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID VIOSerialPortReadRequestCancel( IN WDFREQUEST Request ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request))); TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "-->%s called on request 0x%p\n", __FUNCTION__, Request); // synchronize with VIOSerialQueuesInterruptDpc because the pending // request is not guaranteed to be alive after we return from this callback WdfSpinLockAcquire(pdoData->port->InBufLock); pdoData->port->PendingReadRequest = NULL; WdfSpinLockRelease(pdoData->port->InBufLock); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID VIOSerialPortWriteRequestCancel(IN WDFREQUEST Request) { BOOLEAN cancel = FALSE; PVIOSERIAL_PORT Port = RawPdoSerialPortGetData( WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)))->port; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s Request: 0x%p\n", __FUNCTION__, Request); if (Port->PendingWriteRequest) { Port->PendingWriteRequest = NULL; cancel = TRUE; } if (cancel) { WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID EvtIoWrite( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { WDFMEMORY memory; NTSTATUS status; PMY_SERIAL_DEVICE_EXTENSION pContext; PUCHAR buffer; size_t buf_size; size_t i = 0; KdPrint((DRIVER_NAME "-->EvtIoWrite\n")); pContext = MySerialGetDeviceExtension(WdfIoQueueGetDevice(Queue)); status = WdfRequestRetrieveInputMemory(Request, &memory); if(!NT_SUCCESS(status)) { KdPrint((DRIVER_NAME "EvtIoWrite Could not get request memory buffer 0x%x\n", status)); WdfRequestComplete(Request, status); KdPrint((DRIVER_NAME "<-- EvtDeviceIoWrite\n")); return; } buffer = WdfMemoryGetBuffer(memory, &buf_size); KdPrint((DRIVER_NAME "Sending a buffer of %d bytes\n", buf_size)); while (i < buf_size) { while (UartGetBit(pContext, LSR, LSR_ETHR) == 0 ) {} UartWriteByte(pContext, buffer[i]); i++; } WdfRequestCompleteWithInformation(Request, status, i); KdPrint((DRIVER_NAME "<--EvtIoWrite\n")); }
static VOID UsbChief_EvtIoRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { PFILE_CONTEXT fileContext = NULL; WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; UNREFERENCED_PARAMETER(Queue); PAGED_CODE(); UsbChief_DbgPrint(DEBUG_RW, ("EvtIoRead %d\n", Length)); fileContext = GetFileContext(WdfRequestGetFileObject(Request)); pipe = fileContext->Pipe; if (pipe == NULL) { UsbChief_DbgPrint(0, ("pipe handle is NULL\n")); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe, &pipeInfo); UsbChief_ReadEndPoint(Queue, Request, (ULONG) Length); }
VOID XferCtrlComplete(__in WDFREQUEST Request, __in WDFIOTARGET Target, __in PWDF_REQUEST_COMPLETION_PARAMS Params, __in WDFCONTEXT Context) { NTSTATUS status = Params->IoStatus.Status; PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams = Params->Parameters.Usb.Completion; ULONG length = usbCompletionParams->Parameters.DeviceControlTransfer.Length; UNREFERENCED_PARAMETER(Target); UNREFERENCED_PARAMETER(Context); if (NT_SUCCESS(status)) { USBMSGN("[Ok] transferred=%u", length); WdfRequestCompleteWithInformation(Request, status, length); } else { USBERR("status=%Xh\n", status); WdfRequestComplete(Request, status); } }
VOID EchoEvtIoWrite( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) /*++ Routine Description: This event is invoked when the framework receives IRP_MJ_WRITE request. This routine allocates memory buffer, copies the data from the request to it, and stores the buffer pointer in the queue-context with the length variable representing the buffers length. The actual completion of the request is defered to the periodic timer dpc. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. Length - number of bytes to be read. 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: VOID --*/ { NTSTATUS Status; WDFMEMORY memory; PQUEUE_CONTEXT queueContext = QueueGetContext(Queue); PVOID writeBuffer = NULL; _Analysis_assume_(Length > 0); KdPrint(("EchoEvtIoWrite Called! Queue 0x%p, Request 0x%p Length %d\n", Queue,Request,Length)); if( Length > MAX_WRITE_LENGTH ) { KdPrint(("EchoEvtIoWrite Buffer Length to big %d, Max is %d\n", Length,MAX_WRITE_LENGTH)); WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_OVERFLOW, 0L); return; } // Get the memory buffer Status = WdfRequestRetrieveInputMemory(Request, &memory); if( !NT_SUCCESS(Status) ) { KdPrint(("EchoEvtIoWrite Could not get request memory buffer 0x%x\n", Status)); WdfVerifierDbgBreakPoint(); WdfRequestComplete(Request, Status); return; } // Release previous buffer if set if( queueContext->WriteMemory != NULL ) { WdfObjectDelete(queueContext->WriteMemory); queueContext->WriteMemory = NULL; } Status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES, NonPagedPool, 'sam1', Length, &queueContext->WriteMemory, &writeBuffer ); if(!NT_SUCCESS(Status)) { KdPrint(("EchoEvtIoWrite: Could not allocate %d byte buffer\n", Length)); WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); return; } // Copy the memory in Status = WdfMemoryCopyToBuffer( memory, 0, // offset into the source memory writeBuffer, Length ); if( !NT_SUCCESS(Status) ) { KdPrint(("EchoEvtIoWrite WdfMemoryCopyToBuffer failed 0x%x\n", Status)); WdfVerifierDbgBreakPoint(); WdfObjectDelete(queueContext->WriteMemory); queueContext->WriteMemory = NULL; WdfRequestComplete(Request, Status); return; } // Set transfer information WdfRequestSetInformation(Request, (ULONG_PTR)Length); // Specify the request is cancelable WdfRequestMarkCancelable(Request, EchoEvtRequestCancel); // Defer the completion to another thread from the timer dpc queueContext->CurrentRequest = Request; queueContext->CurrentStatus = Status; return; }
VOID EchoEvtIoRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_READ request. It will copy the content from the queue-context buffer to the request buffer. If the driver hasn't received any write request earlier, the read returns zero. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. Length - number of bytes to be read. 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: VOID --*/ { NTSTATUS Status; PQUEUE_CONTEXT queueContext = QueueGetContext(Queue); WDFMEMORY memory; size_t writeMemoryLength; _Analysis_assume_(Length > 0); KdPrint(("EchoEvtIoRead Called! Queue 0x%p, Request 0x%p Length %d\n", Queue,Request,Length)); // // No data to read // if( (queueContext->WriteMemory == NULL) ) { WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)0L); return; } // // Read what we have // WdfMemoryGetBuffer(queueContext->WriteMemory, &writeMemoryLength); _Analysis_assume_(writeMemoryLength > 0); if( writeMemoryLength < Length ) { Length = writeMemoryLength; } // // Get the request memory // Status = WdfRequestRetrieveOutputMemory(Request, &memory); if( !NT_SUCCESS(Status) ) { KdPrint(("EchoEvtIoRead Could not get request memory buffer 0x%x\n", Status)); WdfVerifierDbgBreakPoint(); WdfRequestCompleteWithInformation(Request, Status, 0L); return; } // Copy the memory out Status = WdfMemoryCopyFromBuffer( memory, // destination 0, // offset into the destination memory WdfMemoryGetBuffer(queueContext->WriteMemory, NULL), Length ); if( !NT_SUCCESS(Status) ) { KdPrint(("EchoEvtIoRead: WdfMemoryCopyFromBuffer failed 0x%x\n", Status)); WdfRequestComplete(Request, Status); return; } // Set transfer information WdfRequestSetInformation(Request, (ULONG_PTR)Length); // Mark the request is cancelable WdfRequestMarkCancelable(Request, EchoEvtRequestCancel); // Defer the completion to another thread from the timer dpc queueContext->CurrentRequest = Request; queueContext->CurrentStatus = Status; return; }
VOID FilterEvtIoDeviceControlFromRawPdo( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) /*++ Routine Description: This routine is the dispatch routine for internal device control requests. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - length of the request's output buffer, if an output buffer is available. InputBufferLength - length of the request's input buffer, if an input buffer is available. IoControlCode - the driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ { PFILTER_EXTENSION filterExt; NTSTATUS status = STATUS_SUCCESS; size_t bytesReturned = 0; WDFDEVICE device; BYTE* pDevInfoLen; // len retrieved from device BYTE* pDevInfoLenInput; // len input from app BYTE* pDevInfoData; // data retrieved from device UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); KdPrint(("--> FilterEvtIoDeviceControlFromRawPdo\n")); device = WdfIoQueueGetDevice(Queue); filterExt = FilterGetData(device); switch (IoControlCode) { // // Put your cases for handling IOCTLs here // case IOCTL_OSRUSBFX2_FILTER_GETDEVINFOLEN: KdPrint(("Entered IOCTL_OSRUSBFX2_FILTER_GETDEVINFOLEN\n")); // // Make sure the caller's output buffer is large enough // to hold the state of the bar graph // status = WdfRequestRetrieveOutputBuffer(Request, sizeof(BYTE), &pDevInfoLen, NULL); if (!NT_SUCCESS(status)) { KdPrint(("User's output buffer is too small for this IOCTL, expecting an BYTE\n")); break; } // // Call our function to get // status = GetDevInfoLength(filterExt, pDevInfoLen); // // If we succeeded return the user their data // if (NT_SUCCESS(status)) { bytesReturned = sizeof(BYTE); } else { bytesReturned = 0; } KdPrint(("Completed IOCTL_OSRUSBFX2_FILTER_GETDEVINFOLEN\n")); break; case IOCTL_OSRUSBFX2_FILTER_GETDEVINFODATA: KdPrint(("Entered IOCTL_OSRUSBFX2_FILTER_GETDEVINFODATA\n")); status = WdfRequestRetrieveInputBuffer(Request, sizeof(BYTE), &pDevInfoLenInput, NULL); if (!NT_SUCCESS(status)) { KdPrint(("User's input buffer is too small for this IOCTL, expecting a BYTE\n")); bytesReturned = 0; break; } KdPrint(("Input length is %d\n", *pDevInfoLenInput)); // // Make sure the caller's output buffer is large enough // to hold the state of the bar graph // status = WdfRequestRetrieveOutputBuffer(Request, *pDevInfoLenInput, &pDevInfoData, NULL); if (!NT_SUCCESS(status)) { KdPrint(("User's output buffer is too small for this IOCTL, expecting an BYTE\n")); bytesReturned = 0; break; } // // Call our function to get // status = GetDevInfoData(filterExt, *pDevInfoLenInput, pDevInfoData, &bytesReturned ); // // If we succeeded return the user their data // if (!NT_SUCCESS(status)) { bytesReturned = 0; } KdPrint(("Completed IOCTL_OSRUSBFX2_FILTER_GETDEVINFODATA\n")); break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation ( Request, status, bytesReturned ); KdPrint(("<-- FilterEvtIoDeviceControlFromRawPdo\n")); return; }
VOID SingleCompEvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) /*++ Routine Description: Callback invoked by WDFQUEUE for a Device Io Control request. Arguments: Queue - Device I/O control queue Request - Device I/O control request OutputBufferLength - Output buffer length for the I/O control InputBufferLength - Input buffer length for the I/O control IoControlCode - I/O control code --*/ { NTSTATUS status; PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer = NULL; WDFDEVICE device = NULL; ULONG componentData; ULONG_PTR information = 0; FDO_DATA *fdoContext = NULL; // // When we complete the request, make sure we don't get the I/O manager to // copy any more data to the client address space than what we write to the // output buffer. The only data that we write to the output buffer is the // component data and the C_ASSERT below ensures that the output buffer does // not have room to contain anything other than that. // C_ASSERT(sizeof(componentData) == sizeof(*outputBuffer)); UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); // // This is a power-managed queue. So our queue stop/start logic should have // ensured that we are in the active condition when a request is dispatched // from this queue. // device = WdfIoQueueGetDevice(Queue); fdoContext = FdoGetContext(device); if (FALSE == fdoContext->IsActive) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - IOCTL %d was dispatched from WDFQUEUE %p when the " "component was not in an active condition.", IOCTL_POWERFX_READ_COMPONENT, Queue); WdfVerifierDbgBreakPoint(); } // // Validate Ioctl code // if (IOCTL_POWERFX_READ_COMPONENT != IoControlCode) { status = STATUS_NOT_SUPPORTED; Trace(TRACE_LEVEL_ERROR, "%!FUNC! -Unsupported IoControlCode. Expected: %d. Actual: %d." " %!status!.", IOCTL_POWERFX_READ_COMPONENT, IoControlCode, status); goto exit; } // // Get the output buffer // status = WdfRequestRetrieveOutputBuffer(Request, sizeof(*outputBuffer), (PVOID*) &outputBuffer, NULL // Length ); if (FALSE == NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfRequestRetrieveOutputBuffer failed with %!status!.", status); goto exit; } // // Read the data from the component // componentData = HwSimReadComponent(device); outputBuffer->ComponentData = componentData; information = sizeof(*outputBuffer); status = STATUS_SUCCESS; exit: // // Complete the request // WdfRequestCompleteWithInformation(Request, status, information); return; }
VOID Bus_EvtIoDeviceControl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) /*++ Routine Description: Handle user mode PlugIn, UnPlug and device Eject requests. 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 IRP_MJ_DEVICE_CONTROL IRP received by the framework. OutputBufferLength - Length, in bytes, of the request's output buffer, if an output buffer is available. InputBufferLength - Length, in bytes, of the request's input buffer, if an input buffer is available. IoControlCode - Driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ { NTSTATUS status = STATUS_INVALID_PARAMETER; WDFDEVICE hDevice; size_t length = 0; PBUSENUM_PLUGIN_HARDWARE plugIn = NULL; PBUSENUM_UNPLUG_HARDWARE unPlug = NULL; PBUSENUM_EJECT_HARDWARE eject = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); PAGED_CODE (); hDevice = WdfIoQueueGetDevice(Queue); KdPrint(("Bus_EvtIoDeviceControl: 0x%p\n", hDevice)); switch (IoControlCode) { case IOCTL_BUSENUM_PLUGIN_HARDWARE: status = WdfRequestRetrieveInputBuffer (Request, sizeof (BUSENUM_PLUGIN_HARDWARE) + (sizeof(UNICODE_NULL) * 2), // 2 for double NULL termination (MULTI_SZ) &plugIn, &length); if( !NT_SUCCESS(status) ) { KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); break; } ASSERT(length == InputBufferLength); if (sizeof (BUSENUM_PLUGIN_HARDWARE) == plugIn->Size) { length = (InputBufferLength - sizeof (BUSENUM_PLUGIN_HARDWARE))/sizeof(WCHAR); // // Make sure the IDs is two NULL terminated. // if ((UNICODE_NULL != plugIn->HardwareIDs[length - 1]) || (UNICODE_NULL != plugIn->HardwareIDs[length - 2])) { status = STATUS_INVALID_PARAMETER; break; } status = Bus_PlugInDevice( hDevice, plugIn->HardwareIDs, length, plugIn->SerialNo ); } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: status = WdfRequestRetrieveInputBuffer( Request, sizeof(BUSENUM_UNPLUG_HARDWARE), &unPlug, &length ); if( !NT_SUCCESS(status) ) { KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); break; } if (unPlug->Size == InputBufferLength) { status= Bus_UnPlugDevice(hDevice, unPlug->SerialNo ); } break; case IOCTL_BUSENUM_EJECT_HARDWARE: status = WdfRequestRetrieveInputBuffer (Request, sizeof (BUSENUM_EJECT_HARDWARE), &eject, &length); if( !NT_SUCCESS(status) ) { KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); break; } if (eject->Size == InputBufferLength) { status= Bus_EjectDevice(hDevice, eject->SerialNo); } break; default: break; // default status is STATUS_INVALID_PARAMETER } WdfRequestCompleteWithInformation(Request, status, length); }
VOID NdisprotSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNET_BUFFER_LIST pNetBufferList, IN ULONG SendCompleteFlags ) /*++ Routine Description: NDIS entry point called to signify completion of a packet send. We pick up and complete the Write IRP corresponding to this packet. Arguments: ProtocolBindingContext - pointer to open context pNetBufferList - NetBufferList that completed send SendCompleteFlags - Specifies if the caller is at DISPATCH level Return Value: None --*/ { PNDISPROT_OPEN_CONTEXT pOpenContext; PNET_BUFFER_LIST CurrNetBufferList = NULL; PNET_BUFFER_LIST NextNetBufferList; NDIS_STATUS CompletionStatus; BOOLEAN DispatchLevel; WDFREQUEST request; PREQUEST_CONTEXT reqContext; pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext; NPROT_STRUCT_ASSERT(pOpenContext, oc); DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendCompleteFlags); for (CurrNetBufferList = pNetBufferList; CurrNetBufferList != NULL; CurrNetBufferList = NextNetBufferList) { NextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrNetBufferList); request = NPROT_REQUEST_FROM_SEND_NBL(CurrNetBufferList); reqContext = GetRequestContext(request); CompletionStatus = NET_BUFFER_LIST_STATUS(CurrNetBufferList); DEBUGP(DL_INFO, ("SendComplete: NetBufferList %p/IRP %p/Length %d " "completed with status %x\n", CurrNetBufferList, request, reqContext->Length, CompletionStatus)); // // We are done with the NDIS_PACKET: // NPROT_DEREF_SEND_NBL(CurrNetBufferList, DispatchLevel); CurrNetBufferList = NULL; if (CompletionStatus == NDIS_STATUS_SUCCESS) { WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, reqContext->Length); } else { WdfRequestCompleteWithInformation(request, STATUS_UNSUCCESSFUL, 0); } NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, DispatchLevel); pOpenContext->PendedSendCount--; if ((NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_CLOSING)) && (pOpenContext->PendedSendCount == 0)) { NPROT_ASSERT(pOpenContext->ClosingEvent != NULL); NPROT_SIGNAL_EVENT(pOpenContext->ClosingEvent); pOpenContext->ClosingEvent = NULL; } NPROT_RELEASE_LOCK(&pOpenContext->Lock, DispatchLevel); NPROT_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP } }