⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vhidmini.c

📁 winddk src目录下的WDM源码压缩!
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Routine Description:

    Handles all the internal ioctls

Arguments:

    DeviceObject - Pointer to the device object.

    Irp - Pointer to the request packet.

Return Value:

    NT Status code

--*/
{
    NTSTATUS            ntStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION  IrpStack;

    DebugPrint(("Enter InternalIoctl (DO=0x%x,Irp=0x%x)\n",
                DeviceObject, Irp));

    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    switch(IrpStack->Parameters.DeviceIoControl.IoControlCode)
    {
    case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
        //
        // Retrieves the device's HID descriptor. 
        //
        DebugPrint(("IOCTL_HID_GET_DEVICE_DESCRIPTOR\n"));
        ntStatus = GetHidDescriptor(DeviceObject, Irp);
        break;
    case IOCTL_HID_GET_REPORT_DESCRIPTOR:
        //
        //Obtains the report descriptor for the HID device.
        //
        DebugPrint(("IOCTL_HID_GET_REPORT_DESCRIPTOR\n"));
        ntStatus = GetReportDescriptor(DeviceObject, Irp);
        break;
    case IOCTL_HID_READ_REPORT:
        //
        //Return a report from the device into a class driver-supplied buffer.
        //
        DebugPrint(("IOCTL_HID_READ_REPORT\n"));
        ntStatus = ReadReport(DeviceObject, Irp);
        return ntStatus;
        
    case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
        //
        //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure.
        //
        DebugPrint(("IOCTL_HID_GET_DEVICE_ATTRIBUTES\n"));
        ntStatus = GetDeviceAttributes(DeviceObject, Irp);
        break;
    case IOCTL_HID_WRITE_REPORT:
        //
        //Transmits a class driver-supplied report to the device.
        //
        DebugPrint(("IOCTL_HID_WRITE_REPORT\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
    case IOCTL_HID_SET_FEATURE:
        //
        // This sends a HID class feature report to a top-level collection of 
        // a HID class device.
        //
        DebugPrint(("IOCTL_HID_SET_FEATURE\n"));
        ntStatus = GetSetFeature(DeviceObject, Irp);                
        break;
    case IOCTL_HID_GET_FEATURE:
        //
        // returns a feature report associated with a top-level collection
        //
        DebugPrint(("IOCTL_HID_GET_FEATURE\n"));
        ntStatus = GetSetFeature(DeviceObject, Irp);
        break;
/* Following two ioctls are not defined in the Win2K HIDCLASS.H headerfile        
    case IOCTL_HID_GET_INPUT_REPORT:
        //
        // returns a HID class input report associated with a top-level 
        // collection of a HID class device.
        //
        DebugPrint(("IOCTL_HID_GET_INPUT_REPORT\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
    case IOCTL_HID_SET_OUTPUT_REPORT:
        //
        // sends a HID class output report to a top-level collection of a HID
        // class device.
        //
        DebugPrint(("IOCTL_HID_SET_OUTPUT_REPORT\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
*/        
    case IOCTL_HID_GET_STRING:
        //
        //Requests that the HID minidriver retrieve a human-readable string 
        //for either the manufacturer ID, the product ID, or the serial number
        //from the string descriptor of the device. The minidriver must send 
        //a Get String Descriptor request to the device, in order to retrieve 
        //the string descriptor, then it must extract the string at the 
        //appropriate index from the string descriptor and return it in the 
        //output buffer indicated by the IRP. Before sending the Get String 
        //Descriptor request, the minidriver must retrieve the appropriate 
        //index for the manufacturer ID, the product ID or the serial number
        //from the device extension of a top level collection associated with
        //the device. 
        //
        DebugPrint(("IOCTL_HID_GET_STRING\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
    case IOCTL_HID_ACTIVATE_DEVICE:
        //
        //Makes the device ready for I/O operations.
        //
        DebugPrint(("IOCTL_HID_ACTIVATE_DEVICE\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
    case IOCTL_HID_DEACTIVATE_DEVICE:
        //
        //Causes the device to cease operations and terminate all outstanding
        //I/O requests.
        //
        DebugPrint(("IOCTL_HID_DEACTIVATE_DEVICE\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
    //case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
    //    DebugPrint(("IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST\n"));
    //    ntStatus = STATUS_NOT_SUPPORTED;
    //    break;
    default:
        DebugPrint(("Unknown or unsupported IOCTL (%x)\n",
        IrpStack->Parameters.DeviceIoControl.IoControlCode));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
    }
    //
    //Set real return status in Irp
    //
    Irp->IoStatus.Status = ntStatus;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    ntStatus = STATUS_SUCCESS;

    return ntStatus;
} 


NTSTATUS
GetSetFeature(
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp
    )
/*++

Routine Description:

    Handles Ioctls for Get and Set feature for all the collection. 
    For control collection (custom defined collection) it handles 
    the user-defined control codes for sideband communication 
    
Arguments:

    DeviceObject - pointer to a device object.

    Irp - Pointer to Interrupt Request Packet.

Return Value:

    NT status code.

--*/
{
    NTSTATUS            ntStatus = STATUS_SUCCESS;
    PIO_STACK_LOCATION  IrpStack;
    PHID_XFER_PACKET    transferPacket = NULL;

    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    transferPacket = (PHID_XFER_PACKET)Irp->UserBuffer;

    if(!transferPacket->reportBufferLen){
        ntStatus = STATUS_BUFFER_TOO_SMALL;
        return ntStatus;
    }

    switch(IrpStack->Parameters.DeviceIoControl.IoControlCode) 
    {
    case IOCTL_HID_GET_FEATURE:
        //
        // IOCTL_HID_GET_FEATURE is being used to send user-defined 
        // HIDMINI_CONTROL_CODE_Xxxx request to a custom collection
        // defined especially for this purpose
        // 

        if(CONTROL_COLLECTION_REPORT_ID == transferPacket->reportId){
            //
            //This is a special HIDMINI_CONTROL_CODE_Xxxx Type request
            //

            ntStatus = HandleControlRequests(transferPacket);
            break;
        }
        //
        // If collection ID is not for control collection then handle
        // this request just as you would for a regular collection.
        //
        // fall thru
        //
    case IOCTL_HID_SET_FEATURE:
        //
        // not handled, fall thru
        //
    default:
    
        ntStatus = STATUS_NOT_SUPPORTED;
        break;            
    }

    return ntStatus;
    
}


NTSTATUS
HandleControlRequests(
    PHID_XFER_PACKET TransferPacket
    )
/*++

Routine Description:

    Handles HIDMINI_CONTROLCODE_Xxxx type requests

Arguments:

    TransferPacket - pointer to HID_XFER_PACKET.

Return Value:

    NT status code.

--*/

{
    NTSTATUS                   ntStatus = STATUS_SUCCESS;
    PHIDMINI_CONTROL_INFO      controlInfo = NULL;
    PHID_DEVICE_ATTRIBUTES     deviceAttributes = NULL;

    if(TransferPacket->reportBufferLen < sizeof(HIDMINI_CONTROL_INFO))
    {
        ntStatus = STATUS_BUFFER_TOO_SMALL;
        return ntStatus;
    }

    controlInfo = (PHIDMINI_CONTROL_INFO)TransferPacket->reportBuffer;

    switch(controlInfo->ControlCode)
    {
    case HIDMINI_CONTROL_CODE_GET_ATTRIBUTES:

        DebugPrint(("Control Code HIDMINI_CONTROL_CODE_GET_ATTRIBUTES\n"));

        if(TransferPacket->reportBufferLen 
                         < (sizeof(HID_DEVICE_ATTRIBUTES) 
                         + sizeof(HIDMINI_CONTROL_INFO))) 
        {
            ntStatus = STATUS_BUFFER_TOO_SMALL;
            return ntStatus;
        }

        deviceAttributes = (PHID_DEVICE_ATTRIBUTES) controlInfo->ControlBuffer;

        deviceAttributes->Size = sizeof (HID_DEVICE_ATTRIBUTES);
        deviceAttributes->VendorID = HIDMINI_VID;
        deviceAttributes->ProductID = HIDMINI_PID;
        deviceAttributes->VersionNumber = HIDMINI_VERSION;

        break;

    case HIDMINI_CONTROL_CODE_DUMMY1:

        DebugPrint(("Control Code HIDMINI_CONTROL_CODE_DUMMY1\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
     
    case HIDMINI_CONTROL_CODE_DUMMY2:
        
        DebugPrint(("Control Code HIDMINI_CONTROL_CODE_DUMMY2\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
        
    default:

        DebugPrint(("Unknown control Code\n"));
        ntStatus = STATUS_NOT_SUPPORTED;
        break;
    }

    return ntStatus;         
}


NTSTATUS 
GetHidDescriptor(
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp
    )
/*++

Routine Description:

    Finds the HID descriptor and copies it into the buffer provided by the Irp.

Arguments:

    DeviceObject - pointer to a device object.

    Irp - Pointer to Interrupt Request Packet.

Return Value:

    NT status code.

--*/
{
    NTSTATUS            ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION   deviceInfo;
    PIO_STACK_LOCATION  IrpStack;
    ULONG               bytesToCopy;

    DebugPrint(("GetHIDDescriptor Entry\n"));

    //
    // Get a pointer to the current location in the Irp
    //

    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // Get a pointer to the device extension
    //

    deviceInfo = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);

    //
    // Copy device descriptor to HIDCLASS buffer
    //

    DebugPrint(("HIDCLASS Buffer = 0x%x, Buffer length = 0x%x\n", 
                Irp->UserBuffer, 
                IrpStack->Parameters.DeviceIoControl.OutputBufferLength));

    //
    // Copy MIN (OutputBufferLength, DeviceExtension->HidDescriptor->bLength)
    //

    bytesToCopy = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

    if(!bytesToCopy) {
        return STATUS_BUFFER_TOO_SMALL;
    }

    //
    // Since HidDescriptor.bLength could be >= sizeof(HID_DESCRIPTOR) we 
    // just check for HidDescriptor.bLength and 
    // copy MIN (OutputBufferLength, DeviceExtension->HidDescriptor->bLength)
    //
    
    if (bytesToCopy > deviceInfo->HidDescriptor.bLength) {
        bytesToCopy = deviceInfo->HidDescriptor.bLength;
    }

    DebugPrint(("Copying %d bytes to HIDCLASS buffer\n", 
                bytesToCopy));

    RtlCopyMemory((PUCHAR) Irp->UserBuffer, 
                (PUCHAR) &deviceInfo->HidDescriptor, 
                bytesToCopy);                

    DebugPrint(("   bLength: 0x%x \n"
                "   bDescriptorType: 0x%x \n"
                "   bcdHID: 0x%x \n"
                "   bCountry: 0x%x \n"
                "   bNumDescriptors: 0x%x \n"
                "   bReportType: 0x%x \n"
                "   wReportLength: 0x%x \n",
                deviceInfo->HidDescriptor.bLength, 
                deviceInfo->HidDescriptor.bDescriptorType,
                deviceInfo->HidDescriptor.bcdHID,
                deviceInfo->HidDescriptor.bCountry,
                deviceInfo->HidDescriptor.bNumDescriptors,
                deviceInfo->HidDescriptor.DescriptorList[0].bReportType,
                deviceInfo->HidDescriptor.DescriptorList[0].wReportLength
                ));

    //
    // Report how many bytes were copied
    //
    Irp->IoStatus.Information = bytesToCopy;

    DebugPrint(("HidMiniGetHIDDescriptor Exit = 0x%x\n", ntStatus));

    return ntStatus;
}

NTSTATUS 
ReadReport(
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp
    )
/*++

Routine Description:

    Creates reports and sends it back to the requester.

Arguments:

    DeviceObject - pointer to a device object.

    Irp - Pointer to Interrupt Request Packet.

Return Value:

    NT status code.

--*/
{
    NTSTATUS ntStatus = STATUS_PENDING;
    PDEVICE_EXTENSION   deviceInfo;
    PIO_STACK_LOCATION  IrpStack;
    LARGE_INTEGER timeout;
    PREAD_TIMER    readTimerStruct;

    DebugPrint(("ReadReport Entry\n"));
    //
    // Get a pointer to the device extension
    //
    deviceInfo = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);

    //
    // Allocate the Timer structure
    //
    readTimerStruct = ExAllocatePoolWithTag(NonPagedPool, 
                                            sizeof(READ_TIMER), 
                                            VHID_POOL_TAG
                                            );

    if(!readTimerStruct){
        DebugPrint(("Mem allocation for readTimerStruct failed\n"));
        Irp->IoStatus.Status = ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }
    else{

        RtlZeroMemory(readTimerStruct, sizeof(READ_TIMER));
        //
        // Since the IRP will be completed later in the DPC,
        // mark the IRP pending and return STATUS_PENDING.
        //
        IoMarkIrpPending(Irp);
        
        //
        //remember the Irp
        //
        readTimerStruct->Irp = Irp;

        //
        // Initialize the DPC structure and Timer
        //
        
        KeInitializeDpc(&readTimerStruct->ReadTimerDpc,
                        ReadTimerDpcRoutine,
                        (PVOID)readTimerStruct
                        );

        KeInitializeTimer(&readTimerStruct->ReadTimer);

        //
        // Queue the timer DPC  
        //
        timeout.HighPart = -1;
        timeout.LowPart = -(LONG)(10*1000*5000);  //in 100 ns.total 5 sec
        KeSetTimer(&readTimerStruct->ReadTimer,
                   timeout,
                   &readTimerStruct->ReadTimerDpc
                   );
    }
    DebugPrint(("ReadReport Exit = 0x%x\n", ntStatus));

    return ntStatus;
}


VOID 
ReadTimerDpcRoutine(   
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    )
{
    NTSTATUS              ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION     deviceInfo;
    PIRP                  Irp;
    PIO_STACK_LOCATION    IrpStack;
    PREAD_TIMER           readTimerStruct;
    ULONG                 bytesToCopy = INPUT_REPORT_BYTES + 1;
    UCHAR                 readReport[INPUT_REPORT_BYTES + 1];


    DebugPrint(("ReadTimerDpcRoutine Entry\n"));

    //
    // Get the Irp from context 
    //
    readTimerStruct = (PREAD_TIMER)DeferredContext;
    Irp = readTimerStruct->Irp;

    //
    // Get a pointer to the current location in the Irp
    //
    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    //
    //First check the size of the output buffer (there is no input buffer)
    //

    if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < bytesToCopy)
    {
        DebugPrint(("ReadReport: Buffer too small, output=0x%x need=0x%x\n", 
                    IrpStack->Parameters.DeviceIoControl.OutputBufferLength, 
                    bytesToCopy
                    ));

        ntStatus = STATUS_BUFFER_TOO_SMALL;
    }
    else
    {
        //
        //Create input report
        //
        readReport[0] = CONTROL_FEATURE_REPORT_ID;
        readReport[1] = 'K';

        //
        // Copy input report to the Irp buffer

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -