NTSTATUS PciDtfDeviceGetInfo(IN WDFDEVICE Device, IN WDFREQUEST Request) { PCIDTF_DEV_INFO *ReqData; ULONG Value, Length; NTSTATUS Status = STATUS_SUCCESS; __try { Status = WdfRequestRetrieveOutputBuffer(Request, sizeof(PCIDTF_DEV_INFO), (PVOID *) & ReqData, NULL); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status); __leave; } Status = WdfDeviceQueryProperty(Device, DevicePropertyBusNumber, sizeof(Value), &Value, &Length); if (!NT_SUCCESS(Status)) { TRACE_ERR ("WdfDeviceQueryProperty(DevicePropertyBusNumber)", Status); __leave; } ReqData->bus = (UINT8) Value; Status = WdfDeviceQueryProperty(Device, DevicePropertyAddress, sizeof(Value), &Value, &Length); if (!NT_SUCCESS(Status)) { TRACE_ERR ("WdfDeviceQueryProperty(DevicePropertyAddress)", Status); __leave; } ReqData->devfn = (UINT8) Value; ReqData->reg_count = (int) WdfCollectionGetCount(GetDeviceData(Device)->RegSpaces); TRACE_MSG(TRACE_LEVEL_VERBOSE, TRACE_FLAG_QUEUE, "bus=0x%X, devfn=0x%X, reg_count=%d\n", ReqData->bus, ReqData->devfn, ReqData->reg_count); WdfRequestSetInformation(Request, sizeof(PCIDTF_DEV_INFO)); } __finally { WdfRequestComplete(Request, Status); } return Status; }
// // Internal Function: UartCtlGetChars // VOID UartCtlGetChars( _In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength ) { NTSTATUS status = STATUS_UNSUCCESSFUL; PUART_DEVICE_EXTENSION pDevExt = UartGetDeviceExtension(Device); PSERIAL_CHARS pSpecialChars = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); FuncEntry(TRACE_FLAG_CONTROL); status = WdfRequestRetrieveOutputBuffer(Request, sizeof(SERIAL_CHARS), (PVOID*)(& pSpecialChars), NULL); if (!NT_SUCCESS(status)) { TraceMessage( TRACE_LEVEL_ERROR, TRACE_FLAG_CONTROL, "Failed to retrieve output buffer for WDFREQUEST %p - " "%!STATUS!", Request, status); } if (NT_SUCCESS(status)) { *pSpecialChars = pDevExt->SpecialChars; WdfRequestSetInformation(Request, sizeof(SERIAL_CHARS)); } TraceMessage(TRACE_LEVEL_INFORMATION, TRACE_FLAG_CONTROL, "WdfRequestComplete( %!HANDLE! => %!STATUS! )", Request, status); WdfRequestComplete(Request, status); FuncExit(TRACE_FLAG_CONTROL); }
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!"); }
/* ** Driver TODO: ** ** Implement this function to handle the initial handshake IOCTL for Windows.Devices.PointOfService API <-> Driver communication. ** This sample will likely work for most cases. */ NTSTATUS ProcessGetDeviceBasicsRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information) { if (Information == nullptr || Request == nullptr) { return STATUS_INVALID_PARAMETER; } UINT32* runtimeVersion; PosDeviceBasicsType* outputData; NTSTATUS status = WdfRequestRetrieveInputBuffer( Request, sizeof(UINT32), (PVOID*)&runtimeVersion, nullptr); if (!NT_SUCCESS(status)) { return status; } status = WdfRequestRetrieveOutputBuffer( Request, sizeof(PosDeviceBasicsType), (PVOID*)&outputData, nullptr); if (!NT_SUCCESS(status)) { return status; } // Tell the runtime what version of the POS IOCTL interface this driver supports so that // it won't send IOCTLs that the driver doesn't support. outputData->Version = POS_DRIVER_VERSION; // This is a magnetic stripe reader driver outputData->DeviceType = PosDeviceType::PosDeviceType_MagneticStripeReader; // This value will be used to set the initial ReadFile buffer size. A small size that is // likely to cover most of the data events is suggested. The runtime will grow the ReadFile // buffer size as needed. outputData->RecommendedBufferSize = 128; *Information = sizeof(PosDeviceBasicsType); return STATUS_SUCCESS; }
// 中断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!!!"); } }
static VOID XenBus_ProcessReadRequest(WDFQUEUE queue, WDFREQUEST request, size_t length) { NTSTATUS status; WDFFILEOBJECT file_object = WdfRequestGetFileObject(request); PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object); ULONG dst_length = (ULONG)length; ULONG dst_offset = 0; ULONG copy_length; xenbus_read_queue_item_t *list_entry; PVOID buffer; UNREFERENCED_PARAMETER(queue); status = WdfRequestRetrieveOutputBuffer(request, length, &buffer, NULL); if (!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME, " WdfRequestRetrieveOutputBuffer failed status = %08x\n", status)); WdfRequestSetInformation(request, 0); return; } ASSERT(NT_SUCCESS(status)); // lazy? while(dst_offset < dst_length && (list_entry = (xenbus_read_queue_item_t *)RemoveHeadList(&xpdid->xenbus.read_list_head)) != (xenbus_read_queue_item_t *)&xpdid->xenbus.read_list_head) { copy_length = min(list_entry->length - list_entry->offset, dst_length - dst_offset); memcpy((PUCHAR)buffer + dst_offset, (PUCHAR)list_entry->data + list_entry->offset, copy_length); list_entry->offset += copy_length; dst_offset += copy_length; if (list_entry->offset == list_entry->length) { ExFreePoolWithTag(list_entry->data, XENPCI_POOL_TAG); ExFreePoolWithTag(list_entry, XENPCI_POOL_TAG); } else { InsertHeadList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry); } } WdfRequestSetInformation(request, dst_offset); FUNCTION_EXIT(); }
/////////////////////////////////////////////////////////////////////////////// // 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 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); }
NTSTATUS PciDtfDeviceGetDma(IN WDFDEVICE Device, IN WDFREQUEST Request) { PDEVICE_DATA DeviceData = GetDeviceData(Device); PCIDTF_DMA_INFO *ReqData; WDFCOMMONBUFFER CommonBuffer; NTSTATUS Status = STATUS_SUCCESS; __try { Status = WdfRequestRetrieveInputBuffer(Request, sizeof(PCIDTF_DMA_INFO), (PVOID *) & ReqData, NULL); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfRequestRetrieveInputBuffer", Status); __leave; } Status = WdfRequestRetrieveOutputBuffer(Request, sizeof(PCIDTF_DMA_INFO), (PVOID *) & ReqData, NULL); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status); __leave; } CommonBuffer = PciDtfCommonBufferFind(DeviceData, ReqData->id, FALSE); if (CommonBuffer == NULL) { Status = STATUS_INVALID_PARAMETER; __leave; } ReqData->addr = WdfCommonBufferGetAlignedLogicalAddress (CommonBuffer).QuadPart; ReqData->len = (int)WdfCommonBufferGetLength(CommonBuffer); WdfRequestSetInformation(Request, sizeof(PCIDTF_DMA_INFO)); } __finally { WdfRequestComplete(Request, Status); } return Status; }
VOID VirtRngEvtIoRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { PDEVICE_CONTEXT context = GetDeviceContext(WdfIoQueueGetDevice(Queue)); NTSTATUS status; PVOID buffer; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> %!FUNC! Queue: %p Request: %p Length: %d", Queue, Request, (ULONG)Length); status = WdfRequestRetrieveOutputBuffer(Request, Length, &buffer, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestRetrieveOutputBuffer failed: %!STATUS!", status); WdfRequestComplete(Request, status); return; } status = WdfRequestMarkCancelableEx(Request, VirtRngEvtRequestCancel); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestMarkCancelableEx failed: %!STATUS!", status); WdfRequestComplete(Request, status); return; } status = VirtQueueAddBuffer(context, Request, Length); if (!NT_SUCCESS(status)) { if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED) { WdfRequestComplete(Request, status); } } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- %!FUNC!"); }
// // Assumes trace fifo already locked // NTSTATUS __BusDogFufillRequestWithTraces( IN WDFREQUEST Request, OUT size_t* bytesWritten ) { PVOID outputBuffer = NULL; size_t realLength; NTSTATUS status = STATUS_SUCCESS; *bytesWritten = 0; // // Get the output buffer... // status = WdfRequestRetrieveOutputBuffer(Request, sizeof(BUSDOG_FILTER_TRACE), &outputBuffer, &realLength); if (NT_SUCCESS(status)) { // // Fill buffer with traces // status = __BusDogFillBufferWithTraces(outputBuffer, realLength, bytesWritten); } else { BusDogPrint(BUSDOG_DEBUG_ERROR, "WdfRequestRetrieveOutputBuffer failed - 0x%x\n", status); } return status; }
NTSTATUS PciDtfDeviceAllocDma(IN WDFDEVICE Device, IN WDFREQUEST Request) { PDEVICE_DATA DeviceData = GetDeviceData(Device); PCIDTF_DMA_INFO *ReqData; WDF_OBJECT_ATTRIBUTES ObjectAttributes; WDFCOMMONBUFFER CommonBuffer = NULL; PCOMMON_BUFFER_DATA CommonBufferData; NTSTATUS Status = STATUS_SUCCESS; __try { Status = WdfRequestRetrieveInputBuffer(Request, sizeof(PCIDTF_DMA_INFO), (PVOID *) & ReqData, NULL); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfRequestRetrieveInputBuffer", Status); __leave; } Status = WdfRequestRetrieveOutputBuffer(Request, sizeof(PCIDTF_DMA_INFO), (PVOID *) & ReqData, NULL); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status); __leave; } WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ObjectAttributes, COMMON_BUFFER_DATA); Status = WdfCommonBufferCreate(DeviceData->DmaEnabler, ReqData->len, &ObjectAttributes, &CommonBuffer); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfCommonBufferCreate", Status); __leave; } CommonBufferData = GetCommonBufferData(CommonBuffer); CommonBufferData->ID = PciDtfCommonBufferAssignId(DeviceData); Status = WdfCollectionAdd(DeviceData->CommonBuffers, CommonBuffer); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfCollectionAdd", Status); __leave; } ReqData->id = CommonBufferData->ID; ReqData->addr = WdfCommonBufferGetAlignedLogicalAddress (CommonBuffer).QuadPart; WdfRequestSetInformation(Request, sizeof(PCIDTF_DMA_INFO)); TRACE_MSG(TRACE_LEVEL_VERBOSE, TRACE_FLAG_QUEUE, "va 0x%p, pa 0x%llX, len 0x%X\n", WdfCommonBufferGetAlignedVirtualAddress(CommonBuffer), WdfCommonBufferGetAlignedLogicalAddress (CommonBuffer).QuadPart, WdfCommonBufferGetLength(CommonBuffer)); } __finally { if (!NT_SUCCESS(Status) && CommonBuffer != NULL) { WdfObjectDelete(CommonBuffer); } WdfRequestComplete(Request, Status); } return Status; }
/* ** Driver TODO: Add code to ProcessCheckHealthRequest to handle different health check cases. The result should be a localized string that is returned to the user in the output buffer of the IOCTL. ** ** Implement this function to handle health check requests. */ NTSTATUS ProcessCheckHealthRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information) { if (Information == nullptr || Request == nullptr) { return STATUS_INVALID_PARAMETER; } DriverUnifiedPosHealthCheckLevel* level; NTSTATUS status = WdfRequestRetrieveInputBuffer( Request, sizeof(DriverUnifiedPosHealthCheckLevel), (PVOID*)&level, nullptr); if (!NT_SUCCESS(status)) { return status; } PosStringType* outputBuffer; size_t outputBufferLength; status = WdfRequestRetrieveOutputBuffer( Request, sizeof(PosStringType), (void**)(&outputBuffer), &outputBufferLength ); if (!NT_SUCCESS(status)) { return status; } switch (*level) { case DriverUnifiedPosHealthCheckLevel::POSInternal: case DriverUnifiedPosHealthCheckLevel::External: case DriverUnifiedPosHealthCheckLevel::Interactive: { // Handle the specific health check level, depending on the applicability to your device. // Return the result as a string that the user can use to determine whether the device is // operational or needs attention. LPCWSTR result = L"OK"; size_t lengthInBytes = wcslen(result) * sizeof(WCHAR); status = RtlSizeTToUInt32(lengthInBytes, &(outputBuffer->DataLengthInBytes)); if (NT_SUCCESS(status)) { *Information = sizeof(PosStringType); if (outputBufferLength >= sizeof(PosStringType)+outputBuffer->DataLengthInBytes) { void* outputStringStart = (void*)(outputBuffer + 1); memcpy(outputStringStart, result, outputBuffer->DataLengthInBytes); *Information += outputBuffer->DataLengthInBytes; } else { status = STATUS_BUFFER_OVERFLOW; } } } break; default: return STATUS_INVALID_PARAMETER; } return STATUS_SUCCESS; }
/* ** Driver TODO: Replace the data in the ProcessRetrieveStatisticsRequest with your own statistics data ** ** Implement this function to handle retrieve statistics requests. */ NTSTATUS ProcessRetrieveStatisticsRequest(_In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _Inout_ ULONG_PTR* Information) { if (Information == nullptr || Request == nullptr) { return STATUS_INVALID_PARAMETER; } struct { PosStatisticsHeader Header; PosValueStatisticsEntry Entries[1]; } StatisticsData; // Initialize statics data so header data are identical for the same requested RtlZeroMemory(&StatisticsData, sizeof(StatisticsData)); StatisticsData.Header.DataLength = sizeof(StatisticsData); wcscpy_s(StatisticsData.Header.DeviceInformation.DeviceCategory, L"MSR"); wcscpy_s(StatisticsData.Header.DeviceInformation.FirmwareRevision, L"<eg, 1.1>"); wcscpy_s(StatisticsData.Header.DeviceInformation.InstallationDate, L"<installation date>"); wcscpy_s(StatisticsData.Header.DeviceInformation.Interface, L"<eg, USB>"); wcscpy_s(StatisticsData.Header.DeviceInformation.ManufactureDate, L"<eg, 2015/03/17>"); wcscpy_s(StatisticsData.Header.DeviceInformation.ManufacturerName, L"<eg, Conteso>"); wcscpy_s(StatisticsData.Header.DeviceInformation.MechanicalRevision, L"<eg, 2.0a>"); wcscpy_s(StatisticsData.Header.DeviceInformation.ModelName, L"<eg, MSR Model M>"); wcscpy_s(StatisticsData.Header.DeviceInformation.SerialNumber, L"<eg, 12345>"); wcscpy_s(StatisticsData.Header.DeviceInformation.UnifiedPOSVersion, L"1.14"); StatisticsData.Header.EntryCount = 1; wcscpy_s(StatisticsData.Entries[0].EntryName, L"<device specific statistics value>"); StatisticsData.Entries[0].Value = (LONG)1; // This IOCTL is called twice by the Windows.Devices.PointOfService APIs // The first time will just retrieve the header to determine how big the buffer needs to be. PVOID outputBuffer; NTSTATUS status = WdfRequestRetrieveOutputBuffer( Request, sizeof(PosStatisticsHeader), &outputBuffer, nullptr ); if (!NT_SUCCESS(status)) { *Information = sizeof(StatisticsData); return status; } if (OutputBufferLength == sizeof(PosStatisticsHeader)) { memcpy(outputBuffer, &(StatisticsData.Header), sizeof(PosStatisticsHeader)); *Information = sizeof(PosStatisticsHeader); } else if (OutputBufferLength < sizeof(StatisticsData)) { *Information = sizeof(StatisticsData); status = STATUS_BUFFER_TOO_SMALL; } else { memcpy(outputBuffer, &StatisticsData, sizeof(StatisticsData)); *Information = sizeof(StatisticsData); } return status; }
VOID VIOSerialPortRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue)); PVIOSERIAL_PORT pport = pdoData->port; size_t length; NTSTATUS status; PVOID systemBuffer; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "-->%s\n", __FUNCTION__); status = WdfRequestRetrieveOutputBuffer(Request, Length, &systemBuffer, &length); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } WdfSpinLockAcquire(pport->InBufLock); if (!VIOSerialPortHasDataLocked(pport)) { if (!pport->HostConnected) { status = STATUS_INSUFFICIENT_RESOURCES; length = 0; } else { ASSERT (pport->PendingReadRequest == NULL); status = WdfRequestMarkCancelableEx(Request, VIOSerialPortReadRequestCancel); if (!NT_SUCCESS(status)) { length = 0; } else { pport->PendingReadRequest = Request; Request = NULL; } } } else { length = (ULONG)VIOSerialFillReadBufLocked(pport, systemBuffer, length); if (!length) { status = STATUS_INSUFFICIENT_RESOURCES; } } WdfSpinLockRelease(pport->InBufLock); if (Request != NULL) { // we are completing the request right here, either because of // an error or because data was available in the input buffer WdfRequestCompleteWithInformation(Request, status, (ULONG_PTR)length); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,"<-- %s\n", __FUNCTION__); }
// IO控制 VOID EvtIoDeviceControl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) { NTSTATUS status; PVOID inBuf; // 输入缓冲区地址 PVOID outBuf; // 输出缓冲区地址 CHAR offset; // 指针移动量 switch( IoControlCode ) { // 移动文件指针 case IOSample_IOCTL_FILE_SEEK: // 检查输入参数 if( 0 == InputBufferLength || 0 == OutputBufferLength ) { WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } // 获取输入缓冲区地址 status = WdfRequestRetrieveInputBuffer(Request, 1, &inBuf, NULL); if( !NT_SUCCESS(status) ) { KdPrint(("[EvtIoDeviceControl] WdfRequestRetrieveInputBuffer failed!")); WdfRequestComplete(Request, status); return ; } // 获取输出缓冲区地址 status = WdfRequestRetrieveOutputBuffer(Request, 1, &outBuf, NULL); if( !NT_SUCCESS(status) ) { KdPrint(("[EvtIoDeviceControl] WdfRequestRetrieveOutputBuffer failed!")); WdfRequestComplete(Request, status); return ; } offset = *(CHAR*)inBuf; // 移动文件指针 if( gFilePointer + offset < 0 ) gFilePointer = 0; else if( gFilePointer + offset > IO_BUFFER_SIZE ) gFilePointer = IO_BUFFER_SIZE; else gFilePointer = gFilePointer + offset; // 新的文件指针位置 *(CHAR*)outBuf = gFilePointer; WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 1); break; default: WdfRequestCompleteWithInformation(Request, STATUS_INVALID_DEVICE_REQUEST, 0); break; } }
VOID HidFx2CompleteReadReport( WDFDEVICE Device ) /*++ Routine Description This method handles the completion of the pended request for the IOCTL_HID_READ_REPORT Arguments: Device - Handle to a framework device. Return Value: None. --*/ { NTSTATUS status = STATUS_SUCCESS; WDFREQUEST request; PDEVICE_EXTENSION pDevContext = NULL; size_t bytesReturned = 0; #ifndef USE_ALTERNATE_HID_REPORT_DESCRIPTOR UCHAR toggledSwitch = 0; #endif // USE_ALTERNATE_HID_REPORT_DESCRIPTOR ULONG bytesToCopy = 0; PHIDFX2_INPUT_REPORT inputReport = NULL; pDevContext = GetDeviceContext(Device); // // Check if there are any pending requests in the Interrupt Message Queue. // If a request is found then complete the pending request. // status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request); if (NT_SUCCESS(status)) { // // IOCTL_HID_READ_REPORT is METHOD_NEITHER so WdfRequestRetrieveOutputBuffer // will correctly retrieve buffer from Irp->UserBuffer. Remember that // HIDCLASS provides the buffer in the Irp->UserBuffer field // irrespective of the ioctl buffer type. However, framework is very // strict about type checking. You cannot get Irp->UserBuffer by using // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER // internal ioctl. // bytesToCopy = sizeof(HIDFX2_INPUT_REPORT); status = WdfRequestRetrieveOutputBuffer(request, bytesToCopy, &inputReport, &bytesReturned);// BufferLength if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfRequestRetrieveOutputBuffer failed with status: 0x%x\n", status); } else { #ifndef USE_ALTERNATE_HID_REPORT_DESCRIPTOR // // Map switch pack state. The lower 7 bits of switch pack // state are mapped to usages in consumer control collection // while the highest one bit is mapped to sleep usage in system // control collection // toggledSwitch = pDevContext->LatestToggledSwitch; if (toggledSwitch & CONSUMER_CONTROL_BUTTONS_BIT_MASK) { // //these are consumer control buttons // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "Consumer control SwitchState: 0x%x\n", toggledSwitch); inputReport->ReportId = CONSUMER_CONTROL_REPORT_ID; inputReport->SwitchStateAsByte = toggledSwitch; bytesReturned = bytesToCopy; } else if (toggledSwitch & SYSTEM_CONTROL_BUTTONS_BIT_MASK) { // // these are system control buttons // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "System Control SwitchState: 0x%x\n", toggledSwitch); inputReport->ReportId = SYSTEM_CONTROL_REPORT_ID; inputReport->SwitchStateAsByte = toggledSwitch; bytesReturned = bytesToCopy; } else { // // We can't be here since we already rejected the switch // state with no swicthes turned on // ASSERT(FALSE); } #else // // Using vendor collection reports instead of HID collections that integrate // into consumer and system control // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "Vendor SwitchState: 0x%x\n", pDevContext->CurrentSwitchState); inputReport->ReportId = DIP_SWITCHES_REPORT_ID; inputReport->SwitchStateAsByte = pDevContext->CurrentSwitchState; bytesReturned = bytesToCopy; #endif // USE_ALTERNATE_HID_REPORT_DESCRIPTOR } WdfRequestCompleteWithInformation(request, status, bytesReturned); } else if (status != STATUS_NO_MORE_ENTRIES) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfIoQueueRetrieveNextRequest status %08x\n", status); } return; }
VOID FileEvtIoRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_READ requests. We will just read the file. 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. Queue is by default configured to fail zero length read & write requests. Return Value: None. --*/ { NTSTATUS status = STATUS_SUCCESS; PVOID outBuf; IO_STATUS_BLOCK ioStatus; PCONTROL_DEVICE_EXTENSION devExt; FILE_POSITION_INFORMATION position; ULONG_PTR bytesRead = 0; size_t bufLength; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_RW, "FileEvtIoRead: Request: 0x%p, Queue: 0x%p\n", Request, Queue); PAGED_CODE (); // // Get the request buffer. Since the device is set to do buffered // I/O, this function will retrieve Irp->AssociatedIrp.SystemBuffer. // status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufLength); if(!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } devExt = ControlGetData(WdfIoQueueGetDevice(Queue)); if(devExt->FileHandle) { // // Set the file position to the beginning of the file. // position.CurrentByteOffset.QuadPart = 0; status = ZwSetInformationFile(devExt->FileHandle, &ioStatus, &position, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation); if (NT_SUCCESS(status)) { status = ZwReadFile (devExt->FileHandle, NULL,// Event, NULL,// PIO_APC_ROUTINE ApcRoutine NULL,// PVOID ApcContext &ioStatus, outBuf, (ULONG)Length, 0, // ByteOffset NULL // Key ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_RW, "ZwReadFile failed with status 0x%x", status); } status = ioStatus.Status; bytesRead = ioStatus.Information; } } WdfRequestCompleteWithInformation(Request, status, bytesRead); }
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 VIOSerialPortRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue)); size_t length; NTSTATUS status; PVOID systemBuffer; BOOLEAN nonBlock; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "-->%s\n", __FUNCTION__); nonBlock = ((WdfFileObjectGetFlags(WdfRequestGetFileObject(Request)) & FO_SYNCHRONOUS_IO) != FO_SYNCHRONOUS_IO); status = WdfRequestRetrieveOutputBuffer(Request, Length, &systemBuffer, &length); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } WdfSpinLockAcquire(pdoData->port->InBufLock); if (!VIOSerialPortHasDataLocked(pdoData->port)) { if (!pdoData->port->HostConnected) { WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); } else { ASSERT (pdoData->port->PendingReadRequest == NULL); status = WdfRequestMarkCancelableEx(Request, VIOSerialPortReadRequestCancel); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); } else { pdoData->port->PendingReadRequest = Request; } } } else { length = (ULONG)VIOSerialFillReadBufLocked(pdoData->port, systemBuffer, length); if (length) { WdfRequestCompleteWithInformation(Request, status, (ULONG_PTR)length); } else { WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); } } WdfSpinLockRelease(pdoData->port->InBufLock); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,"<-- %s\n", __FUNCTION__); return; }
/*++ PCIEDeviceIoCtrl handles IRP from user-mode application and upper driver. Note: IRQL: <= DISPATCH_LEVEL unless device's or driver's WDF_OBJECT_ATTRIBUTES struct is set to WdfExecutionLevelPassive. --*/ VOID PCIEDeviceIoCtrl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) { NTSTATUS Status = STATUS_SUCCESS; HRESULT hRes = S_OK; PDEVICE_EXTENSION pDevExt; PVOID pInputBuffer; PVOID pOutputBuffer; size_t InputBufferSize; size_t OutputBufferSize; ULONG RetInfo = 0; //KIRQL Irql = KeGetCurrentIrql(); // // Get the device extension. // pDevExt = PCIEGetDeviceContext(WdfIoQueueGetDevice( Queue )); if (InputBufferLength > 0) { Status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &pInputBuffer, &InputBufferSize); if( !NT_SUCCESS(Status) ) { WdfRequestComplete(Request, Status); return; } } else { pInputBuffer = NULL; InputBufferSize = 0; } if (OutputBufferLength > 0) { Status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &pOutputBuffer, &OutputBufferSize); if( !NT_SUCCESS(Status) ) { WdfRequestComplete(Request, Status); return; } } else { pOutputBuffer = NULL; OutputBufferSize = 0; } // // Handle this request's specific code. // switch (IoControlCode) { case __IOCTL_REQUEST_RADIOS: hRes = PCIEHandleRadiosReq( pDevExt, pInputBuffer, InputBufferSize, pOutputBuffer, OutputBufferSize); RetInfo = sizeof(LIST_ENTRY); break; case IOCTL_DUMP_RADIO_RX: { ULONG radioIndex = (*(ULONG*)pInputBuffer); ULONG nWritten; DbgPrint("[DUMP] Output buffer size %08x, address=%08x, radioIndex=%08x\n", OutputBufferSize, pOutputBuffer, radioIndex); RadioManagerDumpRX( &pDevExt->RadioManager.__radio_pool[radioIndex], pOutputBuffer, OutputBufferSize, &nWritten); RetInfo = nWritten; } break; case __IOCTL_RELEASE_RADIOS: { LIST_ENTRY* head; head = (LIST_ENTRY*)pInputBuffer; if (head) { LIST_ENTRY* entry; for(entry = head->Flink; entry != head; entry = entry->Flink) { SORA_RADIO* radio; radio = CONTAINING_RECORD(entry, SORA_RADIO, RadiosList); pDevExt->RadioMask &= ~(1<<radio->__radio_no); } } } break; case __IOCTL_MAP_SORA_REGISTER: hRes = PCIEMapSoraRegister( pDevExt, pInputBuffer, InputBufferSize, pOutputBuffer, OutputBufferSize, &RetInfo); break; case __IOCTL_RELEASE_RESOURCE: hRes = PCIEReleaseResource( pDevExt, pInputBuffer, InputBufferSize, pOutputBuffer, OutputBufferSize, &RetInfo); break; case __IOCTL_ACQUIRE_RADIO_MANAGER: { if (OutputBufferLength >= sizeof(PSORA_RADIO_MANAGER*)) { PSORA_RADIO_MANAGER* sora_radio_manager; sora_radio_manager = (PSORA_RADIO_MANAGER*)pOutputBuffer; *sora_radio_manager = &pDevExt->RadioManager; pDevExt->RadioManagerRef ++; RetInfo = sizeof(PSORA_RADIO_MANAGER*); Status = STATUS_SUCCESS; } else { RetInfo = 0; Status = STATUS_BUFFER_TOO_SMALL; } } break; case __IOCTL_RELEASE_RADIO_MANAGER: { pDevExt->RadioManagerRef --; RetInfo = 0; Status = STATUS_SUCCESS; } break; default: Status = STATUS_INVALID_PARAMETER; break; } if (Status != STATUS_PENDING) { WdfRequestCompleteWithInformation(Request, Status, RetInfo); } }
VOID OsrUsbIoctlGetInterruptMessage( _In_ WDFDEVICE Device, _In_ NTSTATUS ReaderStatus ) /*++ Routine Description This method handles the completion of the pended request for the IOCTL IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE. Arguments: Device - Handle to a framework device. Return Value: None. --*/ { NTSTATUS status; WDFREQUEST request; PDEVICE_CONTEXT pDevContext; size_t bytesReturned = 0; PSWITCH_STATE switchState = NULL; pDevContext = GetDeviceContext(Device); do { // // Check if there are any pending requests in the Interrupt Message Queue. // If a request is found then complete the pending request. // status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request); if (NT_SUCCESS(status)) { status = WdfRequestRetrieveOutputBuffer(request, sizeof(SWITCH_STATE), &switchState, NULL);// BufferLength if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n"); bytesReturned = sizeof(SWITCH_STATE); } else { // // Copy the state information saved by the continuous reader. // if (NT_SUCCESS(ReaderStatus)) { switchState->SwitchesAsUChar = pDevContext->CurrentSwitchState; bytesReturned = sizeof(SWITCH_STATE); } else { bytesReturned = 0; } } // // Complete the request. If we failed to get the output buffer then // complete with that status. Otherwise complete with the status from the reader. // WdfRequestCompleteWithInformation(request, NT_SUCCESS(status) ? ReaderStatus : status, bytesReturned); status = STATUS_SUCCESS; } else if (status != STATUS_NO_MORE_ENTRIES) { KdPrint(("WdfIoQueueRetrieveNextRequest status %08x\n", status)); } request = NULL; } while (status == STATUS_SUCCESS); return; }
VOID OsrFxEvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. 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 --*/ { WDFDEVICE device; PDEVICE_CONTEXT pDevContext; size_t bytesReturned = 0; PBAR_GRAPH_STATE barGraphState = NULL; PSWITCH_STATE switchState = NULL; PUCHAR sevenSegment = NULL; BOOLEAN requestPending = FALSE; NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(OutputBufferLength); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "--> OsrFxEvtIoDeviceControl\n"); // // initialize variables // device = WdfIoQueueGetDevice(Queue); pDevContext = GetDeviceContext(device); switch(IoControlCode) { case IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR: { PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL; USHORT requiredSize = 0; // // First get the size of the config descriptor // status = WdfUsbTargetDeviceRetrieveConfigDescriptor( pDevContext->UsbDevice, NULL, &requiredSize); if (status != STATUS_BUFFER_TOO_SMALL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfUsbTargetDeviceRetrieveConfigDescriptor failed 0x%x\n", status); break; } // // Get the buffer - make sure the buffer is big enough // status = WdfRequestRetrieveOutputBuffer(Request, (size_t)requiredSize, // MinimumRequired &configurationDescriptor, NULL); if(!NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); break; } status = WdfUsbTargetDeviceRetrieveConfigDescriptor( pDevContext->UsbDevice, configurationDescriptor, &requiredSize); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfUsbTargetDeviceRetrieveConfigDescriptor failed 0x%x\n", status); break; } bytesReturned = requiredSize; } break; case IOCTL_OSRUSBFX2_RESET_DEVICE: status = ResetDevice(device); break; case IOCTL_OSRUSBFX2_REENUMERATE_DEVICE: // // Otherwise, call our function to reenumerate the // device // status = ReenumerateDevice(pDevContext); bytesReturned = 0; break; case IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY: // // Make sure the caller's output buffer is large enough // to hold the state of the bar graph // status = WdfRequestRetrieveOutputBuffer(Request, sizeof(BAR_GRAPH_STATE), &barGraphState, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n"); break; } // // Call our function to get the bar graph state // status = GetBarGraphState(pDevContext, barGraphState); // // If we succeeded return the user their data // if (NT_SUCCESS(status)) { bytesReturned = sizeof(BAR_GRAPH_STATE); } else { bytesReturned = 0; } break; case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY: status = WdfRequestRetrieveInputBuffer(Request, sizeof(BAR_GRAPH_STATE), &barGraphState, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's input buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n"); break; } // // Call our routine to set the bar graph state // status = SetBarGraphState(pDevContext, barGraphState); // // There's no data returned for this call // bytesReturned = 0; break; case IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY: status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UCHAR), &sevenSegment, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting an UCHAR\n"); break; } // // Call our function to get the 7 segment state // status = GetSevenSegmentState(pDevContext, sevenSegment); // // If we succeeded return the user their data // if (NT_SUCCESS(status)) { bytesReturned = sizeof(UCHAR); } else { bytesReturned = 0; } break; case IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY: status = WdfRequestRetrieveInputBuffer(Request, sizeof(UCHAR), &sevenSegment, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's input buffer is too small for this IOCTL, expecting an UCHAR\n"); bytesReturned = sizeof(UCHAR); break; } // // Call our routine to set the 7 segment state // status = SetSevenSegmentState(pDevContext, sevenSegment); // // There's no data returned for this call // bytesReturned = 0; break; case IOCTL_OSRUSBFX2_READ_SWITCHES: status = WdfRequestRetrieveOutputBuffer(Request, sizeof(SWITCH_STATE), &switchState, NULL);// BufferLength if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n"); bytesReturned = sizeof(SWITCH_STATE); break; } // // Call our routine to get the state of the switches // status = GetSwitchState(pDevContext, switchState); // // If successful, return the user their data // if (NT_SUCCESS(status)) { bytesReturned = sizeof(SWITCH_STATE); } else { // // Don't return any data // bytesReturned = 0; } break; case IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE: // // Forward the request to an interrupt message queue and dont complete // the request until an interrupt from the USB device occurs. // status = WdfRequestForwardToIoQueue(Request, pDevContext->InterruptMsgQueue); if (NT_SUCCESS(status)) { requestPending = TRUE; } break; default : status = STATUS_INVALID_DEVICE_REQUEST; break; } if (requestPending == FALSE) { WdfRequestCompleteWithInformation(Request, status, bytesReturned); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "<-- OsrFxEvtIoDeviceControl\n"); return; }
static VOID XenUsb_EvtIoDeviceControl( WDFQUEUE queue, WDFREQUEST request, size_t output_buffer_length, size_t input_buffer_length, ULONG io_control_code) { NTSTATUS status; WDFDEVICE device = WdfIoQueueGetDevice(queue); PXENUSB_DEVICE_DATA xudd = GetXudd(device); UNREFERENCED_PARAMETER(queue); UNREFERENCED_PARAMETER(input_buffer_length); UNREFERENCED_PARAMETER(output_buffer_length); FUNCTION_ENTER(); status = STATUS_BAD_INITIAL_PC; // these are in api\usbioctl.h switch(io_control_code) { case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION: FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n"); break; case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION: FUNCTION_MSG("IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n"); break; case IOCTL_USB_GET_NODE_CONNECTION_NAME: FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_NAME\n"); break; case IOCTL_USB_DIAG_IGNORE_HUBS_ON: FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_ON\n"); break; case IOCTL_USB_DIAG_IGNORE_HUBS_OFF: FUNCTION_MSG("IOCTL_USB_DIAG_IGNORE_HUBS_OFF\n"); break; case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME: FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n"); break; case IOCTL_USB_GET_HUB_CAPABILITIES: FUNCTION_MSG("IOCTL_USB_GET_HUB_CAPABILITIES\n"); break; case IOCTL_USB_HUB_CYCLE_PORT: FUNCTION_MSG("IOCTL_USB_HUB_CYCLE_PORT\n"); break; case IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES: FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES\n"); break; case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX: FUNCTION_MSG("IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX\n"); break; case IOCTL_USB_GET_ROOT_HUB_NAME: { PUSB_HCD_DRIVERKEY_NAME uhdn; size_t length; ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME); FUNCTION_MSG("IOCTL_USB_GET_ROOT_HUB_NAME\n"); FUNCTION_MSG(" output_buffer_length = %d\n", output_buffer_length); if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) { status = STATUS_BUFFER_TOO_SMALL; } else { status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length); if (NT_SUCCESS(status)) { WDFSTRING symbolic_link_wdfstring; UNICODE_STRING symbolic_link; uhdn->DriverKeyName[0] = 0; status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolic_link_wdfstring); if (NT_SUCCESS(status)) { status = WdfDeviceRetrieveDeviceInterfaceString(xudd->root_hub_device, &GUID_DEVINTERFACE_USB_HUB, NULL, symbolic_link_wdfstring); if (NT_SUCCESS(status)) { WdfStringGetUnicodeString(symbolic_link_wdfstring, &symbolic_link); /* remove leading \??\ from name */ symbolic_link.Buffer += 4; symbolic_link.Length -= 4 * sizeof(WCHAR); required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + symbolic_link.Length + sizeof(WCHAR); FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length); FUNCTION_MSG("required_length = %d\n", required_length); if (output_buffer_length >= required_length) { uhdn->ActualLength = required_length; memcpy(uhdn->DriverKeyName, symbolic_link.Buffer, symbolic_link.Length); uhdn->DriverKeyName[symbolic_link.Length / 2] = 0; WdfRequestSetInformation(request, required_length); } else { uhdn->ActualLength = required_length; uhdn->DriverKeyName[0] = 0; status = STATUS_SUCCESS; WdfRequestSetInformation(request, output_buffer_length); } } else { FUNCTION_MSG("WdfStringCreate = %08x\n", status); } } else { FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString = %08x\n", status); status = STATUS_INVALID_PARAMETER; } } else { FUNCTION_MSG("WdfRequestRetrieveOutputBuffer = %08x\n", status); } FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength); FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName); } break; } case IOCTL_GET_HCD_DRIVERKEY_NAME: { PUSB_HCD_DRIVERKEY_NAME uhdn; size_t length; ULONG required_length = sizeof(USB_HCD_DRIVERKEY_NAME); ULONG key_length; FUNCTION_MSG("IOCTL_GET_HCD_DRIVERKEY_NAME\n"); FUNCTION_MSG(" output_buffer_length = %d\n", output_buffer_length); if (output_buffer_length < sizeof(USB_HCD_DRIVERKEY_NAME)) { FUNCTION_MSG("Buffer too small (%d < %d)\n", output_buffer_length, sizeof(USB_HCD_DRIVERKEY_NAME)); status = STATUS_BUFFER_TOO_SMALL; break; } status = WdfRequestRetrieveOutputBuffer(request, output_buffer_length, (PVOID *)&uhdn, &length); if (!NT_SUCCESS(status)) { FUNCTION_MSG("WdfRequestRetrieveOutputBuffer = %08x\n", status); break; } status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, 0, NULL, &key_length); if (!NT_SUCCESS(status)) { FUNCTION_MSG("WdfDeviceQueryProperty = %08x\n", status); break; } FUNCTION_MSG(" key_length = %d\n", key_length); required_length = FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + key_length + 2; uhdn->ActualLength = required_length; FUNCTION_MSG("output_buffer_length = %d\n", output_buffer_length); FUNCTION_MSG("required_length = %d\n", required_length); if (output_buffer_length >= required_length) { status = WdfDeviceQueryProperty(device, DevicePropertyDriverKeyName, required_length - FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName), uhdn->DriverKeyName, &key_length); WdfRequestSetInformation(request, required_length); } else { uhdn->DriverKeyName[0] = 0; status = STATUS_SUCCESS; WdfRequestSetInformation(request, output_buffer_length); } FUNCTION_MSG(" uhdn->ActualLength = %d\n", uhdn->ActualLength); FUNCTION_MSG(" uhdn->DriverKeyName = %S\n", uhdn->DriverKeyName); break; } #if 0 case IOCTL_USB_RESET_HUB: FUNCTION_MSG("IOCTL_USB_RESET_HUB\n"); break; #endif default: FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code); break; } FUNCTION_MSG("Calling WdfRequestComplete with status = %08x\n", status); WdfRequestComplete(request, status); FUNCTION_EXIT(); }
/*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. 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 --*/ VOID PSDrv_EvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { WDFDEVICE device; PVOID ioBuffer; size_t bufLength; NTSTATUS status; PDEVICE_CONTEXT pDevContext; PFILE_CONTEXT pFileContext; ULONG length = 0; PSUSBDRV_PIPE_PROPERTY* pPipeProp; PSUSBDRV_CONTROL_TRANSFER* pControlTransfer; PSUSBDRV_DRIVER_VERSION* pDriverVersion; PSUSBDRV_INTERFACE_PROPERTY* pInterfaceProperty; unsigned int* pnDeviceSpeed; WDFMEMORY WdfMem = NULL; PUCHAR pControlBuffer; WDFMEMORY WdfMemOut = NULL; WDF_USB_INTERFACE_SELECT_SETTING_PARAMS selectSettingParams; UNREFERENCED_PARAMETER(InputBufferLength); PSDrv_DbgPrint(3, ("PSDrv_EvtIoDeviceControl - begins\n")); PAGED_CODE(); // initialize variables device = WdfIoQueueGetDevice(Queue); pDevContext = GetDeviceContext(device); switch(IoControlCode) { case IOCTL_PSDRV_RESET_PIPE: PSDrv_DbgPrint(3, ("IOControl: ResetPipe\n")); pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = ResetPipe(pFileContext->Pipe); } break; case IOCTL_PSDRV_ABORT_PIPE: PSDrv_DbgPrint(3, ("IOControl: AbortPipe\n")); pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = AbortPipe(pFileContext->Pipe); } break; case IOCTL_PSDRV_GET_CONFIG_DESCRIPTOR: PSDrv_DbgPrint(3, ("IOControl: GetConfigDescriptor\n")); if (pDevContext->UsbConfigurationDescriptor) { length = pDevContext->UsbConfigurationDescriptor->wTotalLength; status = WdfRequestRetrieveOutputBuffer(Request, length, &ioBuffer, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } RtlCopyMemory(ioBuffer, pDevContext->UsbConfigurationDescriptor, length); status = STATUS_SUCCESS; } else { PSDrv_DbgPrint(3, ("UsbConfigurationDescriptor is NULL!\n")); status = STATUS_INVALID_DEVICE_STATE; } break; case IOCTL_PSDRV_RESET_DEVICE: PSDrv_DbgPrint(3, ("IOControl: ResetDevice\n")); status = ResetDevice(device); break; case IOCTL_PSDRV_CONTROL_TRANSFER: PSDrv_DbgPrint(3, ("IOControl: ControlTransfer\n")); //Get a pointer to the input buffer status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pControlTransfer = WdfMemoryGetBuffer(WdfMem, NULL); if (pControlTransfer == NULL) { PSDrv_DbgPrint(1, ("pControlTransfer is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } //Get a pointer to the output buffer if (OutputBufferLength != 0) { status = WdfRequestRetrieveOutputMemory(Request, &WdfMemOut); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMemOut == NULL) { PSDrv_DbgPrint(1, ("WdfMemOut is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pControlBuffer = WdfMemoryGetBuffer(WdfMemOut, NULL); if (pControlBuffer == NULL) { PSDrv_DbgPrint(1, ("pControlBuffer is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } } else { PSDrv_DbgPrint(1, ("This control request has no buffer...\n")); pControlBuffer = NULL; } // Call the control transfer function status = ControlTransfer(pDevContext, pControlTransfer, pControlBuffer, OutputBufferLength, &length); break; case IOCTL_PSDRV_SET_PIPE_PROPERTY: PSDrv_DbgPrint(3, ("IOControl: SetPipeProperty\n")); status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pPipeProp = WdfMemoryGetBuffer(WdfMem, NULL); if (pPipeProp == NULL) { PSDrv_DbgPrint(1, ("pPipeProp is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = SetPipeProperty(pFileContext, pPipeProp); } break; case IOCTL_PSDRV_SET_INTERFACE: PSDrv_DbgPrint(3, ("IOControl: SetInterface\n")); status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pInterfaceProperty = WdfMemoryGetBuffer(WdfMem, NULL); if (pInterfaceProperty == NULL) { PSDrv_DbgPrint(1, ("pInterfaceProperty is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } PSDrv_DbgPrint(3, ("SetInterface: Going to change AltIF to %d...\n", pInterfaceProperty->nAltIF)); WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&selectSettingParams, pInterfaceProperty->nAltIF); status = WdfUsbInterfaceSelectSetting(pDevContext->UsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &selectSettingParams); if (status == STATUS_SUCCESS) { pDevContext->nCurrIf = 0; pDevContext->nCurrAltIf = pInterfaceProperty->nAltIF; PSDrv_DbgPrint(3, ("SetInterface: AltIF is now %d...\n", pInterfaceProperty->nAltIF)); } break; case IOCTL_PSDRV_GET_INTERFACE: PSDrv_DbgPrint(3, ("IOControl: GetInterface\n")); length = sizeof(PSUSBDRV_INTERFACE_PROPERTY); status = WdfRequestRetrieveOutputBuffer(Request, length, &pInterfaceProperty, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } pInterfaceProperty->nIF = pDevContext->nCurrIf; pInterfaceProperty->nAltIF = pDevContext->nCurrAltIf; status = STATUS_SUCCESS; break; case IOCTL_PSDRV_GET_DRIVER_VERSION: PSDrv_DbgPrint(3, ("IOControl: GetDriverVersion\n")); length = sizeof(PSUSBDRV_DRIVER_VERSION); status = WdfRequestRetrieveOutputBuffer(Request, length, &pDriverVersion, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } pDriverVersion->nMajor = PSUSBDRV_MAJOR_VERSION; pDriverVersion->nMinor = PSUSBDRV_MINOR_VERSION; pDriverVersion->nMaintenance = PSUSBDRV_MAINTENANCE_VERSION; pDriverVersion->nBuild = PSUSBDRV_BUILD_VERSION; status = STATUS_SUCCESS; break; case IOCTL_PSDRV_GET_DEVICE_SPEED: PSDrv_DbgPrint(3, ("IOControl: GetDeviceSpeed\n")); length = sizeof(unsigned int); status = WdfRequestRetrieveOutputBuffer(Request, length, &pnDeviceSpeed, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (pDevContext->IsDeviceHighSpeed == TRUE) { *pnDeviceSpeed = PSUSBDRV_DEVICE_HIGH_SPEED; } else { *pnDeviceSpeed = PSUSBDRV_DEVICE_FULL_SPEED; } break; default: PSDrv_DbgPrint(3, ("Unknown IOControl! (ControlCode = %x)\n", IoControlCode)); status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, length); PSDrv_DbgPrint(3, ("PSDrv_EvtIoDeviceControl - ends\n")); return; }
/* ** Driver TODO: Add code to handle various get-property cases. ** ** Implement this function to handle property get requests. */ NTSTATUS ProcessGetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information) { if (Information == nullptr || Request == nullptr || InputBufferLength < sizeof(PosPropertyId)) { return STATUS_INVALID_PARAMETER; } // POS properties are identified by the property ID that's transmitted in the input buffer. PosPropertyId* propertyId; NTSTATUS status = WdfRequestRetrieveInputBuffer( Request, sizeof(PosPropertyId), reinterpret_cast<PVOID*>(&propertyId), nullptr ); if (!NT_SUCCESS(status)) { return status; } // All get properties will need access to the output buffer in order to return results. // The minimum size returned is a UINT32 void* outputBuffer; size_t outputBufferLength; status = WdfRequestRetrieveOutputBuffer( Request, sizeof(UINT32), &outputBuffer, &outputBufferLength ); if (!NT_SUCCESS(status)) { return status; } // Handle this set of readable properties switch (*propertyId) { case PosPropertyId::IsEnabled: // BOOL result, true when the app has called SetProperty(IsEnabled) = TRUE { BOOL isEnabled = TRUE; // Get this value from device context or by querying the device *((BOOL*)outputBuffer) = isEnabled; *Information = sizeof(BOOL); } break; case PosPropertyId::IsDisabledOnDataReceived: // BOOL result, true when the app has called SetProperty(IsDisabledOnDataReceived) = TRUE { BOOL isDisabledOnDataReceived = TRUE; // Get this value from device context or by querying the device *((BOOL*)outputBuffer) = isDisabledOnDataReceived; *Information = sizeof(BOOL); } break; case PosPropertyId::MagneticStripeReaderIsDecodeDataEnabled: // BOOL result, true when the app has called SetProperty(MagneticStripeReaderIsDecodeDataEnabled) = TRUE { BOOL isDecodeDataEnabled = TRUE; // Get this value from device context or by querying the device *((BOOL*)outputBuffer) = isDecodeDataEnabled; *Information = sizeof(BOOL); } break; case PosPropertyId::MagneticStripeReaderCapabilities: { // PosMagneticStripeReaderCapabilitiesType result // These capabilities are likely hard-coded for the specific device. In this case, example values are provided and should // be replaced with values that match your hardware PosMagneticStripeReaderCapabilitiesType capabilities; capabilities.PowerReportingType = DriverUnifiedPosPowerReportingType::Standard; capabilities.IsStatisticsReportingSupported = TRUE; capabilities.IsStatisticsUpdatingSupported = TRUE; capabilities.CardAuthenticationLength = 0; capabilities.SupportedEncryptionAlgorithms = MsrDataEncryption::MsrDataEncryption_AES; capabilities.AuthenticationLevel = DriverMagneticStripeReaderAuthenticationLevel::Optional; capabilities.IsIsoSupported = TRUE; capabilities.IsJisOneSupported = TRUE; capabilities.IsJisTwoSupported = TRUE; capabilities.IsTrackDataMaskingSupported = TRUE; capabilities.IsTransmitSentinelsSupported = TRUE; size_t bytesToCopy = sizeof(PosMagneticStripeReaderCapabilitiesType); if (outputBufferLength < bytesToCopy) { bytesToCopy = outputBufferLength; status = STATUS_BUFFER_OVERFLOW; } memcpy(outputBuffer, &capabilities, bytesToCopy); *Information = bytesToCopy; } break; case PosPropertyId::MagneticStripeReaderSupportedCardTypes: { // Supported card types. The API understands Bank and AAMVA, but additional, device-specific values can be added as well // This property is typically hard coded based on the device type MSR_SUPPORTED_CARD_TYPES supportedCardTypes; RtlZeroMemory(&supportedCardTypes, sizeof(MSR_SUPPORTED_CARD_TYPES)); supportedCardTypes.Count = 2; supportedCardTypes.CardTypes[0] = (unsigned int)MsrCardType::MsrCardType_Bank; supportedCardTypes.CardTypes[1] = (unsigned int)MsrCardType::MsrCardType_Aamva; size_t bytesToCopy = sizeof(MSR_SUPPORTED_CARD_TYPES); if (outputBufferLength < bytesToCopy) { bytesToCopy = outputBufferLength; status = STATUS_BUFFER_OVERFLOW; } memcpy(outputBuffer, &supportedCardTypes, bytesToCopy); *Information = bytesToCopy; } break; case PosPropertyId::MagneticStripeReaderDeviceAuthenticationProtocol: { // Returns whether the device supports challenge/response authentication or not. *((MsrAuthenticationProtocolType*)outputBuffer) = MsrAuthenticationProtocolType::MsrAuthenticationProtocolType_ChallengeResponse; *Information = sizeof(MsrAuthenticationProtocolType); } break; case PosPropertyId::MagneticStripeReaderErrorReportingType: { // Returns whether the device should report errors at the card or track level. // This value is typically retrieved from the device context based on a prior SetProperty(MagneticStripeReaderErrorReportingType) *((MsrErrorReportingType*)outputBuffer) = MsrErrorReportingType::MsrErrorReportingType_CardLevel; *Information = sizeof(MsrErrorReportingType); } break; case PosPropertyId::MagneticStripeReaderTracksToRead: { // typically this value is saved in the device context to track which tracks the application wants to read from the card MsrTrackIds tracksToRead = (MsrTrackIds)(MsrTrackIds::MsrTrackIds_Track1 | MsrTrackIds::MsrTrackIds_Track2); *((MsrTrackIds*)outputBuffer) = tracksToRead; *Information = sizeof(MsrTrackIds); } break; case PosPropertyId::MagneticStripeReaderIsTransmitSentinelsEnabled: { // BOOL property. True if the data that is sent to the application will include start/end sentinals or not // This property can return STATUS_NOT_SUPPORTED if the IsTransmitSentinelsSupported capability is FALSE // Otherwise, the boolean that's returned should be captured from the device context or from the device itself BOOL isTransmitSentinelsEnabled = TRUE; *((BOOL*)outputBuffer) = isTransmitSentinelsEnabled; *Information = sizeof(BOOL); } break; case PosPropertyId::MagneticStripeReaderIsDeviceAuthenticated: { // BOOL property. True if the the authentication process has been successful // This value should come from the device context or from the device itself BOOL isAuthenticated = TRUE; *((BOOL*)outputBuffer) = isAuthenticated; *Information = sizeof(BOOL); } break; case PosPropertyId::MagneticStripeReaderDataEncryptionAlgorithm: { // Returns the encryption algorithm used to decrypt the card data // If the device supports multiple algorithms, it should store the current one in the device context and use that value here // (or retrieve the value from the device itself) MsrDataEncryption currentEncryptionAlgorithm = MsrDataEncryption::MsrDataEncryption_AES; *((MsrDataEncryption*)outputBuffer) = currentEncryptionAlgorithm; } break; default: // no other readable properties for magnetic stripe reader return STATUS_INVALID_PARAMETER; } return STATUS_SUCCESS; }
VOID VIOSerialPortDeviceControl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue)); size_t length = 0; NTSTATUS status = STATUS_SUCCESS; PVIRTIO_PORT_INFO pport_info = NULL; size_t name_size = 0; PAGED_CODE(); UNREFERENCED_PARAMETER( InputBufferLength ); UNREFERENCED_PARAMETER( OutputBufferLength ); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> %s\n", __FUNCTION__); switch (IoControlCode) { case IOCTL_GET_INFORMATION: { status = WdfRequestRetrieveOutputBuffer(Request, sizeof(VIRTIO_PORT_INFO), (PVOID*)&pport_info, &length); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestRetrieveInputBuffer failed 0x%x\n", status); WdfRequestComplete(Request, status); return; } if (pdoData->port->NameString.Buffer) { name_size = pdoData->port->NameString.MaximumLength; } if (length < sizeof (VIRTIO_PORT_INFO) + name_size) { status = STATUS_BUFFER_TOO_SMALL; TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Buffer too small. get = %d, expected = %d\n", length, sizeof (VIRTIO_PORT_INFO) + name_size); length = sizeof (VIRTIO_PORT_INFO) + name_size; break; } RtlZeroMemory(pport_info, sizeof(VIRTIO_PORT_INFO)); pport_info->Id = pdoData->port->PortId; pport_info->OutVqFull = pdoData->port->OutVqFull; pport_info->HostConnected = pdoData->port->HostConnected; pport_info->GuestConnected = pdoData->port->GuestConnected; if (pdoData->port->NameString.Buffer) { RtlZeroMemory(pport_info->Name, name_size); status = RtlStringCbCopyA(pport_info->Name, name_size - 1, pdoData->port->NameString.Buffer); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "RtlStringCbCopyA failed 0x%x\n", status); name_size = 0; } } status = STATUS_SUCCESS; length = sizeof (VIRTIO_PORT_INFO) + name_size; break; } default: status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, length); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- %s\n", __FUNCTION__); }
VOID FileEvtIoDeviceControl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. 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 --*/ { NTSTATUS status = STATUS_SUCCESS;// Assume success PCHAR inBuf = NULL, outBuf = NULL; // pointer to Input and output buffer PCHAR data = "this String is from Device Driver !!!"; ULONG datalen = (ULONG) strlen(data)+1;//Length of data including null PCHAR buffer = NULL; PREQUEST_CONTEXT reqContext = NULL; size_t bufSize; UNREFERENCED_PARAMETER( Queue ); PAGED_CODE(); if(!OutputBufferLength || !InputBufferLength) { WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } // // Determine which I/O control code was specified. // switch (IoControlCode) { case IOCTL_NONPNP_METHOD_BUFFERED: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_BUFFERED\n"); // // For bufffered ioctls WdfRequestRetrieveInputBuffer & // WdfRequestRetrieveOutputBuffer return the same buffer // pointer (Irp->AssociatedIrp.SystemBuffer), so read the // content of the buffer before writing to it. // status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); if(!NT_SUCCESS(status)) { status = STATUS_INSUFFICIENT_RESOURCES; break; } ASSERT(bufSize == InputBufferLength); // // Read the input buffer content. // We are using the following function to print characters instead // TraceEvents with %s format because the string we get may or // may not be null terminated. The buffer may contain non-printable // characters also. // Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", log_xstr(inBuf, (USHORT)InputBufferLength))); PrintChars(inBuf, InputBufferLength ); status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufSize); if(!NT_SUCCESS(status)) { status = STATUS_INSUFFICIENT_RESOURCES; break; } ASSERT(bufSize == OutputBufferLength); // // Writing to the buffer over-writes the input buffer content // RtlCopyMemory(outBuf, data, OutputBufferLength); Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", log_xstr(outBuf, (USHORT)datalen))); PrintChars(outBuf, datalen ); // // Assign the length of the data copied to IoStatus.Information // of the request and complete the request. // WdfRequestSetInformation(Request, OutputBufferLength < datalen? OutputBufferLength:datalen); // // When the request is completed the content of the SystemBuffer // is copied to the User output buffer and the SystemBuffer is // is freed. // break; case IOCTL_NONPNP_METHOD_IN_DIRECT: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_IN_DIRECT\n"); // // Get the Input buffer. WdfRequestRetrieveInputBuffer returns // Irp->AssociatedIrp.SystemBuffer. // status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); if(!NT_SUCCESS(status)) { status = STATUS_INSUFFICIENT_RESOURCES; break; } ASSERT(bufSize == InputBufferLength); Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", log_xstr(inBuf, (USHORT)InputBufferLength))); PrintChars(inBuf, InputBufferLength); // // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe // on the Irp->MdlAddress and returns the system address. // Oddity: For this method, this buffer is intended for transfering data // from the application to the driver. // status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize); if(!NT_SUCCESS(status)) { break; } ASSERT(bufSize == OutputBufferLength); Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User in OutputBuffer: %!HEXDUMP!\n", log_xstr(buffer, (USHORT)OutputBufferLength))); PrintChars(buffer, OutputBufferLength); // // Return total bytes read from the output buffer. // Note OutputBufferLength = MmGetMdlByteCount(Irp->MdlAddress) // WdfRequestSetInformation(Request, OutputBufferLength); // // NOTE: Changes made to the SystemBuffer are not copied // to the user input buffer by the I/O manager // break; case IOCTL_NONPNP_METHOD_OUT_DIRECT: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_OUT_DIRECT\n"); // // Get the Input buffer. WdfRequestRetrieveInputBuffer returns // Irp->AssociatedIrp.SystemBuffer. // status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); if(!NT_SUCCESS(status)) { status = STATUS_INSUFFICIENT_RESOURCES; break; } ASSERT(bufSize == InputBufferLength); Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", log_xstr(inBuf, (USHORT)InputBufferLength))); PrintChars(inBuf, InputBufferLength); // // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe // on the Irp->MdlAddress and returns the system address. // For this method, this buffer is intended for transfering data from the // driver to the application. // status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize); if(!NT_SUCCESS(status)) { break; } ASSERT(bufSize == OutputBufferLength); // // Write data to be sent to the user in this buffer // RtlCopyMemory(buffer, data, OutputBufferLength); Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", log_xstr(buffer, (USHORT)datalen))); PrintChars(buffer, datalen); WdfRequestSetInformation(Request, OutputBufferLength < datalen? OutputBufferLength: datalen); // // NOTE: Changes made to the SystemBuffer are not copied // to the user input buffer by the I/O manager // break; case IOCTL_NONPNP_METHOD_NEITHER: { size_t inBufLength, outBufLength; // // The NonPnpEvtDeviceIoInCallerContext has already probe and locked the // pages and mapped the user buffer into system address space and // stored memory buffer pointers in the request context. We can get the // buffer pointer by calling WdfMemoryGetBuffer. // TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_NEITHER\n"); reqContext = GetRequestContext(Request); inBuf = WdfMemoryGetBuffer(reqContext->InputMemoryBuffer, &inBufLength); outBuf = WdfMemoryGetBuffer(reqContext->OutputMemoryBuffer, &outBufLength); if(inBuf == NULL || outBuf == NULL) { status = STATUS_INVALID_PARAMETER; } ASSERT(inBufLength == InputBufferLength); ASSERT(outBufLength == OutputBufferLength); // // Now you can safely read the data from the buffer in any arbitrary // context. // Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", log_xstr(inBuf, (USHORT)inBufLength))); PrintChars(inBuf, inBufLength); // // Write to the buffer in any arbitrary context. // RtlCopyMemory(outBuf, data, outBufLength); Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", log_xstr(outBuf, (USHORT)datalen))); PrintChars(outBuf, datalen); // // Assign the length of the data copied to IoStatus.Information // of the Irp and complete the Irp. // WdfRequestSetInformation(Request, outBufLength < datalen? outBufLength:datalen); break; } default: // // The specified I/O control code is unrecognized by this driver. // status = STATUS_INVALID_DEVICE_REQUEST; TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ERROR: unrecognized IOCTL %x\n", IoControlCode); break; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Completing Request %p with status %X", Request, status ); WdfRequestComplete( Request, status); }
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; }
/////////////////////////////////////////////////////////////////////////////// // // BasicUsbInterruptPipeReadComplete // // This is the callback we supplied for the continuous reader // on the interrupt IN pipe. It is called whenever the user // changes the state of the switches on the switch pack // // INPUTS: // // Pipe - Our interrupt IN pipe // // Buffer - The WDFMEMORY object associated with the // transfer. The buffer of thie memory contains // the state of the switch pack // // NumBytesTransferred - Self explanatory // // Context - One of our per device context structures // (passed as a parameter to // WDF_USB_CONTINUOUS_READER_CONFIG_INIT) // // OUTPUTS: // // None. // // RETURNS: // // STATUS_SUCCESS, otherwise an error indicating why the driver could not // load. // // IRQL: // // This routine is called at IRQL <= DISPATCH_LEVEL. // // NOTES: // // Even though we've applied a PASSIVE_LEVEL execution // level constraint on our device, this callback falls // outstide of the callbacks that the constraint is // enforced on. // /////////////////////////////////////////////////////////////////////////////// VOID BasicUsbInterruptPipeReadComplete( IN WDFUSBPIPE Pipe, IN WDFMEMORY Buffer, IN size_t NumBytesTransferred, IN WDFCONTEXT Context ) { PUCHAR dataBuffer; WDFREQUEST stateChangeRequest; PBASICUSB_DEVICE_CONTEXT devContext; PUCHAR userBuffer; NTSTATUS status; UNREFERENCED_PARAMETER(Pipe); UNREFERENCED_PARAMETER(NumBytesTransferred); UNREFERENCED_PARAMETER(Context); // // Someone toggled the switch pack. Complete a pending user // request if there is one. // devContext = (PBASICUSB_DEVICE_CONTEXT)Context; dataBuffer = (PUCHAR)WdfMemoryGetBuffer(Buffer, NULL); #if DBG DbgPrint("Interrupt read complete. Bytes transferred = 0x%x, Data = 0x%x\n", (ULONG)NumBytesTransferred, *dataBuffer); #endif // // See if there is anyone waiting to be notified of the state // change. // status = WdfIoQueueRetrieveNextRequest( devContext->SwitchPackStateChangeQueue, &stateChangeRequest); if (NT_SUCCESS(status)) { #if DBG DbgPrint("State change request 0x%p pending\n", stateChangeRequest); #endif // // Yup, someone waiting. Complete their request with the switch // pack state. // status = WdfRequestRetrieveOutputBuffer(stateChangeRequest, sizeof(UCHAR), (PVOID *)&userBuffer, NULL); if (NT_SUCCESS(status)) { // // Stuff the value into the buffer... // *userBuffer = *dataBuffer; // // And complete the request, indicating the proper number of // bytes transferred. // WdfRequestCompleteWithInformation(stateChangeRequest, STATUS_SUCCESS, sizeof(UCHAR)); } else { #if DBG DbgPrint("Failed to get user buffer ofState change request 0x%x\n", status); #endif WdfRequestComplete(stateChangeRequest, status); } } else { #if DBG DbgPrint("No state change requests pending? (0x%x)\n", status); #endif } return; }