//==================== NTSTATUS BulkUsb_DispatchDevCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { ULONG code; PVOID ioBuffer; ULONG inputBufferLength; ULONG outputBufferLength; ULONG info; NTSTATUS ntStatus; PTDeviceExtension deviceExtension; PIO_STACK_LOCATION irpStack; info = 0; irpStack = IoGetCurrentIrpStackLocation(Irp); code = irpStack->Parameters.DeviceIoControl.IoControlCode; deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension; ioBuffer = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; if(deviceExtension->DeviceState != WORKING) { BulkUsb_DbgPrint(1, ("file bulkdev: Invalid device state\n")); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchDevCtrl::")); BulkUsb_IoIncrement(deviceExtension); BulkUsb_DbgPrint(3, ("file bulkdev: Waiting on the IdleReqPendEvent\n")); if(deviceExtension->SSEnable) { KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL); } switch(code) { case IOCTL_BULKUSB_RESET_PIPE: { PFILE_OBJECT fileObject; PUSBD_PIPE_INFORMATION pipe; pipe = NULL; fileObject = irpStack->FileObject; if(fileObject == NULL) { ntStatus = STATUS_INVALID_PARAMETER; break; } pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext; if(pipe == NULL) ntStatus = STATUS_INVALID_PARAMETER; else ntStatus = BulkUsb_ResetPipe(DeviceObject, pipe); break; } case IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR: { ULONG length; if(deviceExtension->UsbConfigurationDescriptor) { length = deviceExtension->UsbConfigurationDescriptor->wTotalLength; if(outputBufferLength >= length) { RtlCopyMemory(ioBuffer, deviceExtension->UsbConfigurationDescriptor, length); info = length; ntStatus = STATUS_SUCCESS; } else ntStatus = STATUS_BUFFER_TOO_SMALL; } else ntStatus = STATUS_UNSUCCESSFUL; break; } case IOCTL_BULKUSB_RESET_DEVICE: ntStatus = BulkUsb_ResetDevice(DeviceObject); break; default : ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("file bulkdev: BulkUsb_DispatchDevCtrl::")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; }
NTSTATUS BulkUsb_DispatchDevCtrl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Dispatch routine for IRP_MJ_DEVICE_CONTROL Arguments: DeviceObject - pointer to device object Irp - I/O request packet Return Value: NT status value --*/ { ULONG code; PVOID ioBuffer; ULONG inputBufferLength; ULONG outputBufferLength; ULONG info; NTSTATUS ntStatus; PDEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; // // initialize variables // info = 0; irpStack = IoGetCurrentIrpStackLocation(Irp); code = irpStack->Parameters.DeviceIoControl.IoControlCode; deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; ioBuffer = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; if(deviceExtension->DeviceState != Working) { BulkUsb_DbgPrint(1, ("Invalid device state\n")); Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; } BulkUsb_DbgPrint(3, ("BulkUsb_DispatchDevCtrl::")); BulkUsb_IoIncrement(deviceExtension); // // It is true that the client driver cancelled the selective suspend // request in the dispatch routine for create. // But there is no guarantee that it has indeed been completed. // so wait on the NoIdleReqPendEvent and proceed only if this event // is signalled. // BulkUsb_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n")); // // make sure that the selective suspend request has been completed. // if(deviceExtension->SSEnable) { KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL); } switch(code) { case IOCTL_BULKUSB_RESET_PIPE: { PFILE_OBJECT fileObject; PUSBD_PIPE_INFORMATION pipe; pipe = NULL; fileObject = NULL; // // FileObject is the address of the kernel file object to // which the IRP is directed. Drivers use the FileObject // to correlate IRPs in a queue. // fileObject = irpStack->FileObject; if(fileObject == NULL) { ntStatus = STATUS_INVALID_PARAMETER; break; } pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext; if(pipe == NULL) { ntStatus = STATUS_INVALID_PARAMETER; } else { ntStatus = BulkUsb_ResetPipe(DeviceObject, pipe); } break; } case IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR: { ULONG length; if(deviceExtension->UsbConfigurationDescriptor) { length = deviceExtension->UsbConfigurationDescriptor->wTotalLength; if(outputBufferLength >= length) { RtlCopyMemory(ioBuffer, deviceExtension->UsbConfigurationDescriptor, length); info = length; ntStatus = STATUS_SUCCESS; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } } else { ntStatus = STATUS_UNSUCCESSFUL; } break; } case IOCTL_BULKUSB_RESET_DEVICE: ntStatus = BulkUsb_ResetDevice(DeviceObject); break; default : ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Status = ntStatus; Irp->IoStatus.Information = info; IoCompleteRequest(Irp, IO_NO_INCREMENT); BulkUsb_DbgPrint(3, ("BulkUsb_DispatchDevCtrl::")); BulkUsb_IoDecrement(deviceExtension); return ntStatus; }