//读操作 VOID RamDiskEvtIoRead(IN WDFQUEUE Queue,IN WDFREQUEST Request,IN size_t Length) { PDEVICE_EXTENSION devExt = QueueGetExtension(Queue)->DeviceExtension; //从队列对象获得设备扩展 NTSTATUS Status = STATUS_INVALID_PARAMETER; WDF_REQUEST_PARAMETERS Parameters; LARGE_INTEGER ByteOffset; WDFMEMORY hMemory; //__analysis_assume(Length > 0); //参数清0 WDF_REQUEST_PARAMETERS_INIT(&Parameters); //从请求中获取信息 WdfRequestGetParameters(Request, &Parameters); //读取偏移 ByteOffset.QuadPart = Parameters.Parameters.Read.DeviceOffset; //检测读取是否合法 if (RamDiskCheckParameters(devExt, ByteOffset, Length)) { //获得内存状态 Status = WdfRequestRetrieveOutputMemory(Request, &hMemory); if(NT_SUCCESS(Status)) { // Destination # Offset into the destination # source Status = WdfMemoryCopyFromBuffer(hMemory,0, devExt->DiskImage + ByteOffset.LowPart, Length); } } WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length); }
VOID RamDiskEvtIoRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_READ request. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. Length - Length of the data buffer associated with the request. The default property of the queue is to not dispatch zero length read & write requests to the driver and complete is with status success. So we will never get a zero length request. Return Value: VOID --*/ { PDEVICE_EXTENSION devExt = QueueGetExtension(Queue)->DeviceExtension; NTSTATUS Status = STATUS_INVALID_PARAMETER; WDF_REQUEST_PARAMETERS Parameters; LARGE_INTEGER ByteOffset; WDFMEMORY hMemory; _Analysis_assume_(Length > 0); WDF_REQUEST_PARAMETERS_INIT(&Parameters); WdfRequestGetParameters(Request, &Parameters); ByteOffset.QuadPart = Parameters.Parameters.Read.DeviceOffset; if (RamDiskCheckParameters(devExt, ByteOffset, Length)) { Status = WdfRequestRetrieveOutputMemory(Request, &hMemory); if(NT_SUCCESS(Status)){ Status = WdfMemoryCopyFromBuffer(hMemory, // Destination 0, // Offset into the destination devExt->DiskImage + ByteOffset.LowPart, // source Length); } } WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length); }
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; }
// Finds the Report descriptor and copies it into the buffer provided by the Request. // NTSTATUS HidFx2GetReportDescriptor(_In_ WDFDEVICE hDevice, _In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; WDFMEMORY memory; PDEVICE_EXTENSION pDevContext = NULL; PVOID pBuffer = (PVOID)c_ButtonDescriptor; size_t cBytesToCopy = sizeof(c_ButtonDescriptor); TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); status = WdfRequestRetrieveOutputMemory(hRequest, &memory); if (NT_SUCCESS(status)) { pDevContext = GetDeviceContext(hDevice); if (pDevContext != NULL) { // Select a non default report descriptor switch (pDevContext->driverMode) { case DM_BUTTON_AND_LED: pBuffer = (PVOID)c_ButtonWithLedDescriptor; cBytesToCopy = sizeof(c_ButtonWithLedDescriptor); break; case DM_SLIDER_SWITCH: pBuffer = (PVOID)c_SliderSwitchDescriptor; cBytesToCopy = sizeof(c_SliderSwitchDescriptor); break; case DM_SLIDER_SWITCH_AND_LED: pBuffer = (PVOID)c_SliderSwitchWithLedDescriptor; cBytesToCopy = sizeof(c_SliderSwitchWithLedDescriptor); break; case DM_LED_ONLY: pBuffer = (PVOID)c_LedOnlyDescriptor; cBytesToCopy = sizeof(c_LedOnlyDescriptor); break; default: break; } } if (cBytesToCopy != 0) { status = WdfMemoryCopyFromBuffer(memory, 0, pBuffer, cBytesToCopy); if (NT_SUCCESS(status)) { // Report how many bytes were copied WdfRequestSetInformation(hRequest, cBytesToCopy); } else // WdfMemoryCopyFromBuffer failed { TraceErr(DBG_IOCTL, "(%!FUNC!) WdfMemoryCopyFromBuffer failed %!STATUS!\n", status); } } else // report length is zero { status = STATUS_INVALID_DEVICE_STATE; TraceErr(DBG_IOCTL, "(%!FUNC!) c_DefaultHidDescriptor's reportLength is zero, %!STATUS!\n", status); } } else // WdfRequestRetrieveOutputMemory failed { TraceErr(DBG_IOCTL, "(%!FUNC!)WdfRequestRetrieveOutputMemory failed %!STATUS!\n", status); } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit = %!STATUS!\n", status); return status; }
// Finds the HID descriptor and copies it into the buffer provided by the Request. // NTSTATUS HidFx2GetHidDescriptor(_In_ WDFDEVICE hDevice, _In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; size_t cBytesToCopy = 0; WDFMEMORY memory; PDEVICE_EXTENSION pDevContext = NULL; HID_DESCRIPTOR hidDescriptor; TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); status = WdfRequestRetrieveOutputMemory(hRequest, &memory); if (NT_SUCCESS(status)) { hidDescriptor.bLength= sizeof(hidDescriptor); // length of HID descriptor hidDescriptor.bDescriptorType= HID_HID_DESCRIPTOR_TYPE; // descriptor type == HID 0x21 hidDescriptor.bcdHID= HID_CLASS_SPEC_RELEASE_1_00; // hid spec release hidDescriptor.bCountry= HID_COUNTRY_NON_LOCALIZED; // country code hidDescriptor.bNumDescriptors= 0x01; // number of HID class descriptors hidDescriptor.DescriptorList[0].bReportType =HID_REPORT_DESCRIPTOR_TYPE; hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_ButtonDescriptor); pDevContext = GetDeviceContext(hDevice); if (pDevContext != NULL) { // Set length of non default report descriptor switch (pDevContext->driverMode) { case DM_BUTTON_AND_LED: hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_ButtonWithLedDescriptor); break; case DM_SLIDER_SWITCH: hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_SliderSwitchDescriptor); break; case DM_SLIDER_SWITCH_AND_LED: hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_SliderSwitchWithLedDescriptor); break; case DM_LED_ONLY: hidDescriptor.DescriptorList[0].wReportLength = sizeof(c_LedOnlyDescriptor); break; default: break; } } cBytesToCopy = hidDescriptor.bLength; if (cBytesToCopy != 0) { status = WdfMemoryCopyFromBuffer(memory, 0, (PVOID)&hidDescriptor, cBytesToCopy); if (NT_SUCCESS(status)) { // Report how many bytes were copied WdfRequestSetInformation(hRequest, cBytesToCopy); } else // WdfMemoryCopyFromBuffer failed { TraceErr(DBG_IOCTL, "(%!FUNC!) WdfMemoryCopyFromBuffer failed %!STATUS!\n", status); return status; } } else // length is zero { status = STATUS_INVALID_DEVICE_STATE; TraceErr(DBG_IOCTL, "(%!FUNC!) c_DefaultHidDescriptor is zero, %!STATUS!\n", status); return status; } } else // WdfRequestRetrieveOutputMemory failed { TraceErr(DBG_IOCTL, " (%!FUNC!) WdfRequestRetrieveOutputMemory failed %!STATUS!\n", status); return status; } TraceVerbose(DBG_IOCTL, " (%!FUNC!) HidFx2GetHidDescriptor Exit = %!STATUS!\n", status); return status; }
VOID tgwinkEvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) { WDFMEMORY mem; NTSTATUS status; WDFDEVICE dev; PDEVICE_CONTEXT context; void *uBase = NULL; LARGE_INTEGER offset; size_t size; dev = WdfIoQueueGetDevice(Queue); context = DeviceGetContext(dev); switch (IoControlCode) { case IOCTL_TGWINK_SAY_HELLO: if (OutputBufferLength != 4) { WdfRequestComplete(Request, STATUS_BAD_DATA); break; } status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfVerifierDbgBreakPoint(); WdfRequestComplete(Request, status); break; } *((DWORD32 *)(WdfMemoryGetBuffer(mem, NULL))) = 0x5a5aa5a5; WdfRequestComplete(Request, STATUS_SUCCESS); break; case IOCTL_TGWINK_MAP_BAR_0: if (sizeof(void *) > OutputBufferLength) { KdPrint("tgwinkEvtIoDeviceControl needs a larger buffer (%d > %d)!\n", sizeof(void *), OutputBufferLength); WdfRequestComplete(Request, STATUS_BUFFER_TOO_SMALL); break; } offset = context->bar[0].phyAddr; size = context->bar[0].length; status = ZwMapViewOfSection(context->hMemory, ZwCurrentProcess(), &uBase, 0, 0, &offset, &size, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not map view of section, status "); switch (status) { case STATUS_CONFLICTING_ADDRESSES: KdPrint("STATUS_CONFLICTING_ADDRESSES\n"); break; case STATUS_INVALID_PAGE_PROTECTION: KdPrint("STATUS_INVALID_PAGE_PROTECTION\n"); break; case STATUS_SECTION_PROTECTION: KdPrint("STATUS_SECTION_PROTECTION\n"); break; default: KdPrint("0x % x\n", status); break; } WdfRequestComplete(Request, status); break; } status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfVerifierDbgBreakPoint(); WdfRequestComplete(Request, status); break; } *((void **)(WdfMemoryGetBuffer(mem, NULL))) = uBase; WdfRequestComplete(Request, STATUS_SUCCESS); break; case IOCTL_TGWINK_READ_PHYS: { PVOID buf; ULONG_PTR page, ofs, vtgt = 0; SIZE_T vsz = 0; if (InputBufferLength != sizeof(PVOID)) { KdPrint("tgwinkEvtIoDeviceControl requires a %d-byte buffer for this ioctl (got %d)\n", sizeof(PVOID), OutputBufferLength); WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); break; } status = WdfRequestRetrieveInputBuffer(Request, sizeof(PVOID), &buf, NULL); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } ofs = *((ULONG_PTR *)buf); page = ofs & ~0xfff; vsz = OutputBufferLength + (page ^ ofs); buf = NULL; status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } status = ZwMapViewOfSection(context->hMemory, (HANDLE)-1, (PVOID *)&vtgt, 0, 0, (PLARGE_INTEGER)&page, &vsz, ViewUnmap, 0, PAGE_READONLY); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not map view of physical memory section, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } ofs -= page; status = WdfMemoryCopyFromBuffer(mem, 0, (PVOID)(vtgt + ofs), OutputBufferLength); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to copy data from memory to buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)vtgt); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to unmap view of physical memory section, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, OutputBufferLength); } break; case IOCTL_TGWINK_PEND_INTR: { WdfWaitLockAcquire(context->nnLock, NULL); if (context->notifyNext) { PINTERRUPT_CONTEXT pCtx = InterruptGetContext(context->hIrq); status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to retrieve output memory, status 0x%x\n", status); WdfRequestComplete(Request, status); } status = WdfMemoryCopyFromBuffer(mem, 0, &pCtx->serial, 8); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to copy interrupt number to buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); } WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 8); context->notifyNext = 0; KdPrint("tgwinkEvtIoDeviceControl satisfied interrupt notification request synchronously.\n"); //WdfInterruptEnable(context->hIrq); } else { KdPrint("tgwinkEvtIoDeviceControl forwarding PEND_INTR request to notification queue\n"); WdfRequestForwardToIoQueue(Request, context->NotificationQueue); } WdfWaitLockRelease(context->nnLock); } break; default: WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); } }
VOID KbFilter_EvtIoDeviceControlFromRawPdo( 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 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 --*/ { NTSTATUS status = STATUS_SUCCESS; WDFDEVICE hDevice; WDFMEMORY outputMemory; PDEVICE_EXTENSION devExt; size_t bytesTransferred = 0; UNREFERENCED_PARAMETER(InputBufferLength); DebugPrint(("Entered KbFilter_EvtIoInternalDeviceControl\n")); hDevice = WdfIoQueueGetDevice(Queue); devExt = FilterGetData(hDevice); // // Process the ioctl and complete it when you are done. // switch (IoControlCode) { case IOCTL_KBFILTR_GET_KEYBOARD_ATTRIBUTES: // // Buffer is too small, fail the request // if (OutputBufferLength < sizeof(KEYBOARD_ATTRIBUTES)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = WdfRequestRetrieveOutputMemory(Request, &outputMemory); if (!NT_SUCCESS(status)) { DebugPrint(("WdfRequestRetrieveOutputMemory failed %x\n", status)); break; } status = WdfMemoryCopyFromBuffer(outputMemory, 0, &devExt->KeyboardAttributes, sizeof(KEYBOARD_ATTRIBUTES)); if (!NT_SUCCESS(status)) { DebugPrint(("WdfMemoryCopyFromBuffer failed %x\n", status)); break; } bytesTransferred = sizeof(KEYBOARD_ATTRIBUTES); break; default: status = STATUS_NOT_IMPLEMENTED; break; } WdfRequestCompleteWithInformation(Request, status, bytesTransferred); return; }