dmgrdisp.c

来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· C语言 代码 · 共 535 行 · 第 1/2 页

C
535
字号
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < 8)
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    status = STATUS_SUCCESS;
                    buf_size = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
                    RtlCopyMemory(&gddr, irp->AssociatedIrp.SystemBuffer, sizeof(GET_DEV_DESC_REQ));
                    pusb_desc_header = irp->AssociatedIrp.SystemBuffer;

                    if (gddr.desc_type != USB_DT_CONFIG && gddr.desc_type != USB_DT_DEVICE)
                    {
                        EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
                    }

                    if (usb_query_and_lock_dev(dev_mgr, gddr.dev_handle, &pdev) != STATUS_SUCCESS)
                    {
                        EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp);
                    }

                    lock_dev(pdev, FALSE);
                    if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
                    {
                        status = STATUS_INVALID_DEVICE_STATE;
                        goto ERROR_OUT;
                    }
                    if (dev_state(pdev) != USB_DEV_STATE_ADDRESSED &&
                        dev_state(pdev) != USB_DEV_STATE_CONFIGURED)
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT;
                    }

                    if (pdev->pusb_dev_desc == NULL)
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT;
                    }

                    if (gddr.desc_type == USB_DT_DEVICE)
                    {
                        RtlCopyMemory(pusb_desc_header,
                                      pdev->pusb_dev_desc,
                                      buf_size > sizeof(USB_DEVICE_DESC)
                                      ? sizeof(USB_DEVICE_DESC) : buf_size);

                        irp->IoStatus.Information =
                            buf_size >= sizeof(USB_DEVICE_DESC) ? sizeof(USB_DEVICE_DESC) : buf_size;
                    }
                    else if (gddr.desc_type == USB_DT_CONFIG)
                    {
                        PUSB_CONFIGURATION_DESC pusb_config_desc;
                        if (pdev->pusb_dev_desc->bNumConfigurations <= gddr.desc_idx)
                        {
                            status = STATUS_INVALID_PARAMETER;
                            goto ERROR_OUT;
                        }

                        pusb_config_desc = usb_find_config_desc_by_idx((PUCHAR) & pdev->pusb_dev_desc[1],
                                                                       gddr.desc_idx,
                                                                       pdev->pusb_dev_desc->
                                                                       bNumConfigurations);

                        if (pusb_config_desc == NULL)
                        {
                            status = STATUS_DEVICE_NOT_READY;
                            goto ERROR_OUT;
                        }

                        RtlCopyMemory(pusb_desc_header,
                                      pusb_config_desc,
                                      buf_size >= pusb_config_desc->wTotalLength
                                      ? pusb_config_desc->wTotalLength : buf_size);

                        irp->IoStatus.Information =
                            buf_size >= pusb_config_desc->wTotalLength
                            ? pusb_config_desc->wTotalLength : buf_size;
                    }
                  ERROR_OUT:
                    unlock_dev(pdev, FALSE);
                    usb_unlock_dev(pdev);
                    EXIT_DISPATCH(status, irp);
                }
            case IOCTL_SUBMIT_URB_RD:
            case IOCTL_SUBMIT_URB_WR:
            case IOCTL_SUBMIT_URB_NOIO:
                {
                    PURB purb;
                    ULONG endp_idx, if_idx, user_buffer_length = 0;
                    PUCHAR user_buffer = NULL;
                    PUSB_DEV pdev;
                    DEV_HANDLE endp_handle;
                    PUSB_ENDPOINT pendp;

                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    purb = (PURB) irp->AssociatedIrp.SystemBuffer;
                    endp_handle = purb->endp_handle;

                    if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
                    {
                        if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
                        {
                            user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
                            if (user_buffer_length == 0)
                                EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                            user_buffer = MmGetSystemAddressForMdl(irp->MdlAddress);
                        }
                        else
                        {
                            if (purb->data_buffer == NULL || purb->data_length == 0)
                                EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                            user_buffer_length = purb->data_length;
                            user_buffer = purb->data_buffer;
                        }
                    }

                    if (usb_query_and_lock_dev(dev_mgr, endp_handle & ~0xffff, &pdev) != STATUS_SUCCESS)
                    {
                        EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp);
                    }


                    lock_dev(pdev, FALSE);
                    if (dev_state(pdev) == USB_DEV_STATE_ZOMB || (dev_state(pdev) < USB_DEV_STATE_ADDRESSED))

                    {
                        status = STATUS_INVALID_DEVICE_STATE;
                        goto ERROR_OUT1;
                    }

                    if (dev_state(pdev) == USB_DEV_STATE_ADDRESSED && !default_endp_handle(endp_handle))
                    {
                        status = STATUS_DEVICE_NOT_READY;
                        goto ERROR_OUT1;
                    }

                    if_idx = if_idx_from_handle(endp_handle);
                    endp_idx = endp_idx_from_handle(endp_handle);

                    //if_idx exceeds the upper limit
                    if (pdev->usb_config)
                    {
                        if (if_idx >= pdev->usb_config->if_count
                            || endp_idx >= pdev->usb_config->interf[if_idx].endp_count)
                        {
                            if (!default_endp_handle(endp_handle))
                            {
                                status = STATUS_INVALID_DEVICE_STATE;
                                goto ERROR_OUT1;
                            }
                        }
                    }

                    endp_from_handle(pdev, endp_handle, pendp);
                    // FIXME: don't know what evil will let loose
                    if (endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL)
                    {
                        if (user_buffer_length > 0x100000)
                        {
                            status = STATUS_INVALID_PARAMETER;
                            goto ERROR_OUT1;
                        }
                    }

                    purb->pirp = irp;
                    purb->context = dev_mgr;
                    purb->reference = ctrl_code;

                    if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
                    {
                        if (ctrl_code == IOCTL_SUBMIT_URB_RD)
                            KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE);
                        else
                            KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);

                        purb->data_buffer = user_buffer;
                        purb->data_length = user_buffer_length;
                        purb->completion = disp_urb_completion;
                    }
                    else
                    {
                        purb->completion = disp_noio_urb_completion;
                    }

                    unlock_dev(pdev, FALSE);

                    // we have to mark irp before the urb is scheduled to
                    // avoid race condition
                    IoMarkIrpPending(irp);
                    ASSERT(dev_mgr_register_irp(dev_mgr, irp, purb));
                    status = usb_submit_urb(dev_mgr, purb);
                    if (status != STATUS_PENDING)
                    {
                        IoGetCurrentIrpStackLocation((irp))->Control &= ~SL_PENDING_RETURNED;
                        dev_mgr_remove_irp(dev_mgr, irp);
                    }
                    usb_unlock_dev(pdev);
                    if (status != STATUS_PENDING)
                    {
                        irp->IoStatus.Status = status;
                        IoCompleteRequest(irp, IO_NO_INCREMENT);
                    }
                    return status;
                  ERROR_OUT1:
                    unlock_dev(pdev, FALSE);
                    usb_unlock_dev(pdev);
                    irp->IoStatus.Information = 0;
                    EXIT_DISPATCH(status, irp);
                }
            default:
                {
                    irp->IoStatus.Information = 0;
                    EXIT_DISPATCH(STATUS_NOT_IMPLEMENTED, irp);
                }
            }
        }
    default:
        {
            irp->IoStatus.Information = 0;
            break;
        }
    }
    EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
}

/*#define IOCTL_GET_DEV_COUNT		CTL_CODE( FILE_HCD_DEV_TYPE, 4093, METHOD_BUFFERED, FILE_ANY_ACCESS )
//input_buffer and input_buffer_length is zero, output_buffer is to receive a dword value of the
//dev count, output_buffer_length must be no less than sizeof( long ).

#define IOCTL_ENUM_DEVICES 		CTL_CODE( FILE_HCD_DEV_TYPE, 4094, METHOD_BUFFERED, FILE_ANY_ACCESS )
//input_buffer is a dword value to indicate the count of elements in the array 
//input_buffer_length is sizeof( long ), output_buffer is to receive a
//structure ENUM_DEV_ARRAY where dev_count is the elements hold in this array.

#define IOCTL_GET_DEV_DESC		CTL_CODE( FILE_HCD_DEV_TYPE, 4095, METHOD_BUFFERED, FILE_ANY_ACCESS )
//input_buffer is a structure GET_DEV_DESC_REQ, and the input_buffer_length is
//no less than sizeof( input_buffer ), output_buffer is a buffer to receive the
//requested dev's desc, and output_buffer_length specifies the length of the
//buffer

#define IOCTL_SUBMIT_URB_RD		CTL_CODE( FILE_HCD_DEV_TYPE, 4096, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
#define IOCTL_SUBMIT_URB_WR 	CTL_CODE( FILE_HCD_DEV_TYPE, 4097, METHOD_OUT_DIRECT, FILE_ANY_ACCESS )
// input_buffer is a URB, and input_buffer_length is equal to or greater than 
// sizeof( URB ); the output_buffer is a buffer to receive data from or send data
// to device. only the following urb fields can be accessed, others must be zeroed.
//  DEV_HANDLE 			endp_handle;
//	UCHAR             	setup_packet[8];   	//for control pipe
// the choosing of IOCTL_SUBMIT_URB_RD or IOCTL_SUBMIT_URB_WR should be determined
// by the current URB, for example, a request string from device will use XXX_RD, 
// and a write to the bulk endpoint will use XXX_WR

#define IOCTL_SUBMIT_URB_NOIO	CTL_CODE( FILE_HCD_DEV_TYPE, 4098, METHOD_BUFFERED,	FILE_ANY_ACCESS )
// input_buffer is a URB, and input_buffer_length is equal to or greater than 
// sizeof( URB ); the output_buffer is null and no output_buffer_length,
// only the following fields in urb can be accessed, others must be zeroed.
//  DEV_HANDLE 			endp_handle;
//	UCHAR             	setup_packet[8];   	//for control pipe
*/

⌨️ 快捷键说明

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