dmgrdisp.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· 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 + -
显示快捷键?