NTSTATUS EXTERNAL HbtnInternalIoctl( IN PDEVICE_OBJECT DevObj, IN PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION devext = GET_MINIDRIVER_DEVICE_EXTENSION(DevObj); PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp); TEnter(Func,("(DevObj=%p,Irp=%p,IrpSp=%p,Ioctl=%s)\n", DevObj, Irp, irpsp, LookupName(irpsp->Parameters.DeviceIoControl.IoControlCode, HidIoctlNames))); Irp->IoStatus.Information = 0; status = IoAcquireRemoveLock(&devext->RemoveLock, Irp); if (!NT_SUCCESS(status)) { LogError(ERRLOG_DEVICE_REMOVED, status, UNIQUE_ERRID(0x10), NULL, NULL); TWarn(("received IRP after device was removed.\n")); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } else if (!(devext->dwfHBtn & HBTNF_DEVICE_STARTED)) { IoReleaseRemoveLock(&devext->RemoveLock, Irp); status = STATUS_DEVICE_NOT_READY; LogError(ERRLOG_DEVICE_NOT_STARTED, status, UNIQUE_ERRID(0x20), NULL, NULL); TWarn(("digitizer is not started.\n")); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } else { switch(irpsp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: status = GetDeviceDescriptor(devext, Irp); break; case IOCTL_HID_GET_REPORT_DESCRIPTOR: status = GetReportDescriptor(devext, Irp); break; case IOCTL_HID_READ_REPORT: status = ReadReport(devext, Irp); break; case IOCTL_HID_WRITE_REPORT: status = OemWriteReport(devext, Irp); break; case IOCTL_HID_GET_STRING: status = GetString(devext, Irp); break; case IOCTL_HID_GET_DEVICE_ATTRIBUTES: status = GetAttributes(devext, Irp); break; case IOCTL_HID_ACTIVATE_DEVICE: case IOCTL_HID_DEACTIVATE_DEVICE: status = STATUS_SUCCESS; break; default: status = STATUS_NOT_SUPPORTED; LogError(ERRLOG_NOT_SUPPORTED, status, UNIQUE_ERRID(0x30), NULL, NULL); TWarn(("unsupported (IOCTL=%x).\n", irpsp->Parameters.DeviceIoControl.IoControlCode)); break; } if (status != STATUS_PENDING) { IoReleaseRemoveLock(&devext->RemoveLock, Irp); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } else { IoMarkIrpPending(Irp); } } TExit(Func,("=%x\n", status)); return status; } //HbtnInternalIoctl
VOID EvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) /*++ Routine Description: This event callback function is called when the driver receives an (KMDF) IOCTL_HID_Xxx code when handlng IRP_MJ_INTERNAL_DEVICE_CONTROL (UMDF) IOCTL_HID_Xxx, IOCTL_UMDF_HID_Xxx when handling IRP_MJ_DEVICE_CONTROL Arguments: Queue - A handle to the queue object that is associated with the I/O request Request - A handle to a framework request object. OutputBufferLength - The length, in bytes, of the request's output buffer, if an output buffer is available. InputBufferLength - The length, in bytes, of the request's input buffer, if an input buffer is available. IoControlCode - The driver or system defined IOCTL associated with the request Return Value: NTSTATUS --*/ { NTSTATUS status; BOOLEAN completeRequest = TRUE; WDFDEVICE device = WdfIoQueueGetDevice(Queue); PDEVICE_CONTEXT deviceContext = NULL; PQUEUE_CONTEXT queueContext = GetQueueContext(Queue); UNREFERENCED_PARAMETER (OutputBufferLength); UNREFERENCED_PARAMETER (InputBufferLength); deviceContext = GetDeviceContext(device); switch (IoControlCode) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: // METHOD_NEITHER // // Retrieves the device's HID descriptor. // _Analysis_assume_(deviceContext->HidDescriptor.bLength != 0); status = RequestCopyFromBuffer(Request, &deviceContext->HidDescriptor, deviceContext->HidDescriptor.bLength); break; case IOCTL_HID_GET_DEVICE_ATTRIBUTES: // METHOD_NEITHER // //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure. // status = RequestCopyFromBuffer(Request, &queueContext->DeviceContext->HidDeviceAttributes, sizeof(HID_DEVICE_ATTRIBUTES)); break; case IOCTL_HID_GET_REPORT_DESCRIPTOR: // METHOD_NEITHER // //Obtains the report descriptor for the HID device. // status = RequestCopyFromBuffer(Request, deviceContext->ReportDescriptor, deviceContext->HidDescriptor.DescriptorList[0].wReportLength); break; case IOCTL_HID_READ_REPORT: // METHOD_NEITHER // // Returns a report from the device into a class driver-supplied // buffer. // status = ReadReport(queueContext, Request, &completeRequest); break; case IOCTL_HID_WRITE_REPORT: // METHOD_NEITHER // // Transmits a class driver-supplied report to the device. // status = WriteReport(queueContext, Request); break; #ifdef _KERNEL_MODE case IOCTL_HID_GET_FEATURE: // METHOD_OUT_DIRECT status = GetFeature(queueContext, Request); break; case IOCTL_HID_SET_FEATURE: // METHOD_IN_DIRECT status = SetFeature(queueContext, Request); break; case IOCTL_HID_GET_INPUT_REPORT: // METHOD_OUT_DIRECT status = GetInputReport(queueContext, Request); break; case IOCTL_HID_SET_OUTPUT_REPORT: // METHOD_IN_DIRECT status = SetOutputReport(queueContext, Request); break; #else // UMDF specific // // HID minidriver IOCTL uses HID_XFER_PACKET which contains an embedded pointer. // // typedef struct _HID_XFER_PACKET { // PUCHAR reportBuffer; // ULONG reportBufferLen; // UCHAR reportId; // } HID_XFER_PACKET, *PHID_XFER_PACKET; // // UMDF cannot handle embedded pointers when marshalling buffers between processes. // Therefore a special driver mshidumdf.sys is introduced to convert such IRPs to // new IRPs (with new IOCTL name like IOCTL_UMDF_HID_Xxxx) where: // // reportBuffer - passed as one buffer inside the IRP // reportId - passed as a second buffer inside the IRP // // The new IRP is then passed to UMDF host and driver for further processing. // case IOCTL_UMDF_HID_GET_FEATURE: // METHOD_NEITHER status = GetFeature(queueContext, Request); break; case IOCTL_UMDF_HID_SET_FEATURE: // METHOD_NEITHER status = SetFeature(queueContext, Request); break; case IOCTL_UMDF_HID_GET_INPUT_REPORT: // METHOD_NEITHER status = GetInputReport(queueContext, Request); break; case IOCTL_UMDF_HID_SET_OUTPUT_REPORT: // METHOD_NEITHER status = SetOutputReport(queueContext, Request); break; #endif // _KERNEL_MODE case IOCTL_HID_GET_STRING: // METHOD_NEITHER status = GetString(Request); break; case IOCTL_HID_GET_INDEXED_STRING: // METHOD_OUT_DIRECT status = GetIndexedString(Request); break; case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: // METHOD_NEITHER // // This has the USBSS Idle notification callback. If the lower driver // can handle it (e.g. USB stack can handle it) then pass it down // otherwise complete it here as not inplemented. For a virtual // device, idling is not needed. // // Not implemented. fall through... // case IOCTL_HID_ACTIVATE_DEVICE: // METHOD_NEITHER case IOCTL_HID_DEACTIVATE_DEVICE: // METHOD_NEITHER case IOCTL_GET_PHYSICAL_DESCRIPTOR: // METHOD_OUT_DIRECT // // We don't do anything for these IOCTLs but some minidrivers might. // // Not implemented. fall through... // default: status = STATUS_NOT_IMPLEMENTED; break; } // // Complete the request. Information value has already been set by request // handlers. // if (completeRequest) { WdfRequestComplete(Request, status); } }