FORCEINLINE ULONG FxIrp::GetParameterIoctlCodeBufferMethod( VOID ) { return METHOD_FROM_CTL_CODE(GetParameterIoctlCode()); }
NTSTATUS DMDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { NTSTATUS status; PIO_STACK_LOCATION IrpStack; PVOID InputBuffer; ULONG InputLength; PVOID OutputBuffer; ULONG OutputLength; PDEVICE_ENTRY DevEntry; ULONG IoControlCode; ENTER_DISPATCH; IrpStack = IoGetCurrentIrpStackLocation(Irp); IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; if ( DeviceObject == g_pDeviceObject ) { InputBuffer = Irp->AssociatedIrp.SystemBuffer; InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; OutputBuffer = Irp->AssociatedIrp.SystemBuffer; if ( METHOD_FROM_CTL_CODE(IoControlCode) == METHOD_NEITHER ) { OutputBuffer = Irp->UserBuffer; } status = DMDeviceIoCtl(Irp, InputBuffer, InputLength, OutputBuffer, OutputLength, IoControlCode); } else { DevEntry = LookupEntryByDevObj(DeviceObject); if ( DevEntry && g_bStartMon) { //log it KdPrint(("%u-%u: %s\n", DevEntry->DiskNumber, DevEntry->PartitionNumber, "IRP_MJ_DEVICE_CONTROL")); } status = DefaultDispatch(DeviceObject, Irp); // hook new dev if (IoControlCode == IOCTL_DISK_FIND_NEW_DEVICES || IoControlCode == IOCTL_DISK_SET_DRIVE_LAYOUT) { if ( NT_SUCCESS(status) ) { HookDispatch(DeviceObject->DriverObject, 0); } } } LEAVE_DISPATCH; return status; }
NTSTATUS WDFEXPORT(WdfDmaTransactionInitializeUsingRequest)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFDMATRANSACTION DmaTransaction, __in WDFREQUEST Request, __in PFN_WDF_PROGRAM_DMA EvtProgramDmaFunction, __in WDF_DMA_DIRECTION DmaDirection ) { NTSTATUS status; FxDmaTransactionBase* pDmaTrans; FxRequest* pReqObj; MDL* mdl = NULL; PIO_STACK_LOCATION stack; ULONG reqLength; PFX_DRIVER_GLOBALS pFxDriverGlobals; FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals), DmaTransaction, FX_TYPE_DMA_TRANSACTION, (PVOID *) &pDmaTrans, &pFxDriverGlobals); FxPointerNotNull(pFxDriverGlobals, EvtProgramDmaFunction); if (DmaDirection != WdfDmaDirectionReadFromDevice && DmaDirection != WdfDmaDirectionWriteToDevice) { status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Initialization of WDFDMATRANSACTION 0x%p using WDFREQUEST %p, " "DmaDirection 0x%x is an invalid value, %!STATUS!", DmaTransaction, Request, DmaDirection, status); return status; } FxObjectHandleGetPtr(pFxDriverGlobals, Request, FX_TYPE_REQUEST, (PVOID *) &pReqObj); reqLength = 0; stack = pReqObj->GetFxIrp()->GetCurrentIrpStackLocation(); // // Get the MDL and Length from the request. // switch (stack->MajorFunction) { case IRP_MJ_READ: if (DmaDirection != WdfDmaDirectionReadFromDevice) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Dma direction %!WDF_DMA_DIRECTION! of WDFTRANSACTION " "0x%p doesn't match with the WDFREQUEST 0x%p type " "%!WDF_REQUEST_TYPE! %!STATUS!", DmaDirection, DmaTransaction, Request, stack->MajorFunction, status); return status; } reqLength = stack->Parameters.Read.Length; status = pReqObj->GetMdl(&mdl); break; case IRP_MJ_WRITE: if (DmaDirection != WdfDmaDirectionWriteToDevice) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Dma direction %!WDF_DMA_DIRECTION! of WDFTRANSACTION " "0x%p doesn't match with the WDFREQUEST 0x%p type " "%!WDF_REQUEST_TYPE! %!STATUS!", DmaDirection, DmaTransaction, Request, stack->MajorFunction, status); return status; } reqLength = stack->Parameters.Write.Length; status = pReqObj->GetMdl(&mdl); break; case IRP_MJ_DEVICE_CONTROL: case IRP_MJ_INTERNAL_DEVICE_CONTROL: switch (METHOD_FROM_CTL_CODE(stack->Parameters.DeviceIoControl.IoControlCode)) { case METHOD_BUFFERED: if (DmaDirection == WdfDmaDirectionWriteToDevice) { reqLength = stack->Parameters.DeviceIoControl.InputBufferLength; } else { reqLength = stack->Parameters.DeviceIoControl.OutputBufferLength; } // // In this case both input buffer and output buffer map // to the same MDL and it's probed for read & write access. // So it's okay for DMA transfer in either direction. // status = pReqObj->GetMdl(&mdl); break; case METHOD_IN_DIRECT: // // For this type, the output buffer is probed for read access. // So the direction of DMA transfer is WdfDmaDirectionWriteToDevice. // if (DmaDirection != WdfDmaDirectionWriteToDevice) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Dma direction %!WDF_DMA_DIRECTION! of WDFTRANSACTION " "0x%p doesn't match with WDFREQUEST 0x%p ioctl type " "METHOD_IN_DIRECT %!STATUS!", DmaDirection, DmaTransaction, Request, status); return status; } reqLength = stack->Parameters.DeviceIoControl.OutputBufferLength; status = pReqObj->GetDeviceControlOutputMdl(&mdl); break; case METHOD_OUT_DIRECT: // // For this type, the output buffer is probed for write access. // So the direction of DMA transfer is WdfDmaDirectionReadFromDevice. // if (DmaDirection != WdfDmaDirectionReadFromDevice) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Dma direction %!WDF_DMA_DIRECTION! of WDFTRANSACTION " "0x%p doesn't match with WDFREQUEST 0x%p ioctl type " "METHOD_OUT_DIRECT %!STATUS!", DmaDirection, DmaTransaction, Request, status); return status; } reqLength = stack->Parameters.DeviceIoControl.OutputBufferLength; status = pReqObj->GetDeviceControlOutputMdl(&mdl); break; default: status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Invalid ioctl code in WDFREQUEST 0x%p %!STATUS!", Request, status); FxVerifierDbgBreakPoint(pFxDriverGlobals); break; }// End of switch(ioctType) break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } if (!NT_SUCCESS(status)) { DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Couldn't retrieve mdl from WDFREQUEST 0x%p for " "WDFTRANSACTION 0x%p %!STATUS!", Request, DmaTransaction, status); return status; } if (reqLength == 0) { status = STATUS_INVALID_DEVICE_REQUEST; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "Zero length request, %!STATUS!", status); return status; } // // If the DMA enabler is packet based, make sure the virtual address and // the length of transfer are within bounds. Basically, we are checking // to see if the length of data to be transferred doesn't span multiple // MDLs, because packet based DMA doesn't support chained MDLs. // if (pDmaTrans->GetDmaEnabler()->SupportsChainedMdls() == FALSE) { ULONG length; length = MmGetMdlByteCount(mdl); if (reqLength > length) { status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "WDFREQUEST %p transfer length (%d) is out of bounds of MDL " "Byte count (%d), %!STATUS!", Request, reqLength, length, status); return status; } } // // Parms appear OK, so initialize this instance. // status = pDmaTrans->Initialize(EvtProgramDmaFunction, DmaDirection, mdl, 0, reqLength); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA, "WDFTANSACTION 0x%p initialization failed: " "%!STATUS!", DmaTransaction, status); return status; } // // Set this Request in the new DmaTransaction. The request will // take a reference on this request when it starts executing. // pDmaTrans->SetRequest(pReqObj); return STATUS_SUCCESS; }
//----- (08001F19) -------------------------------------------------------- NTSTATUS DMDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) { PIO_STACK_LOCATION IrpStack; PVOID OutputBuffer; PVOID InputBuffer; ULONG InputLength; ULONG OutputLength; NTSTATUS status; PDEVICE_ENTRY DevEntry; LARGE_INTEGER CurrentTime; LARGE_INTEGER PerfCount; ULONG seq; char IoctlName[64] = ""; PCHAR pIoCtlName; ULONG IoControlCode; IrpStack = IoGetCurrentIrpStackLocation(Irp); IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; if ( DeviceObject == g_pDeviceObject ) { InputBuffer = Irp->AssociatedIrp.SystemBuffer; InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; OutputBuffer = Irp->AssociatedIrp.SystemBuffer; if ( METHOD_FROM_CTL_CODE(IoControlCode) == METHOD_NEITHER ) { OutputBuffer = Irp->UserBuffer; } status = DMDeviceIoCtl(Irp, InputBuffer, InputLength, OutputBuffer, OutputLength, IoControlCode); } else { if ( g_bUsePerfCounter ) { CurrentTime.QuadPart = 0; PerfCount = KeQueryPerformanceCounter(0); } else { KeQuerySystemTime(&CurrentTime); PerfCount.QuadPart = 0; } seq = InterlockedIncrement(&Sequence); DevEntry = LookupEntryByDevObj(DeviceObject); if ( DevEntry ) { pIoCtlName = GetIoctlName(IoctlName, IrpStack->Parameters.DeviceIoControl.IoControlCode); LogRecord( seq, &CurrentTime, DevEntry->DiskNumber, "%s(%s)", IrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? "IRP_MJ_DEVICE_CONTROL" : "IRP_MJ_INTERNAL_DEVICE_CONTROL", IoctlName); } status = DefaultDispatch(DeviceObject, Irp, seq, g_bUsePerfCounter, &PerfCount); if ( IoControlCode == IOCTL_DISK_FIND_NEW_DEVICES || IoControlCode == IOCTL_DISK_SET_DRIVE_LAYOUT ) { if ( NT_SUCCESS(status) ) { HookDispatch(DeviceObject->DriverObject, 0); } } } return status; }
VOID XferCtrl ( __in WDFQUEUE Queue, __in WDFREQUEST Request, __in size_t InputBufferLength, __in size_t OutputBufferLength) { NTSTATUS status; PDEVICE_CONTEXT deviceContext; PREQUEST_CONTEXT requestContext; WDFMEMORY transferMemory; PWDF_USB_CONTROL_SETUP_PACKET setupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; WDFMEMORY_OFFSET _transferOffset; PWDFMEMORY_OFFSET transferOffset = &_transferOffset; UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(OutputBufferLength); deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); requestContext = GetRequestContext(Request); setupPacket = (PWDF_USB_CONTROL_SETUP_PACKET)&requestContext->IoControlRequest.control; USBDBG("bmDir=%s bmType=%s bmRecipient=%s bmReserved=%03u bRequest=%u wIndex=%u wValue=%u wLength=%u\n", GetBmRequestDirString(setupPacket->Packet.bm.Request.Dir), GetBmRequestTypeString(setupPacket->Packet.bm.Request.Type), GetBmRequestRecipientString(setupPacket->Packet.bm.Request.Recipient), setupPacket->Packet.bm.Request.Reserved, setupPacket->Packet.bRequest, setupPacket->Packet.wIndex.Value, setupPacket->Packet.wValue.Value, setupPacket->Packet.wLength); // If the device and config descriptor requests are not handled they will be the "true" // descriptors directly from the device. i.e. if the device has two unassociated interfaces // the composite layer will split it into two but each virtual device interface would show // both interface deacriptors. // if (setupPacket->Packet.bm.Request.Dir == BMREQUEST_DEVICE_TO_HOST && setupPacket->Packet.bm.Request.Type == BMREQUEST_STANDARD && setupPacket->Packet.bRequest == USB_REQUEST_GET_DESCRIPTOR) { UCHAR descriptorType = setupPacket->Packet.wValue.Bytes.HiByte; // UCHAR descriptorIndex = setupPacket->Packet.wValue.Bytes.LowByte; ULONG descriptorSize = 0; PVOID descriptorIn = NULL; PVOID outputBuffer = NULL; size_t outputBufferLength = 0; if (requestContext->IoControlCode == LIBUSB_IOCTL_GET_DESCRIPTOR) { switch(descriptorType) { case USB_DESCRIPTOR_TYPE_DEVICE: descriptorSize = sizeof(deviceContext->UsbDeviceDescriptor); descriptorIn = &deviceContext->UsbDeviceDescriptor; break; case USB_DESCRIPTOR_TYPE_CONFIGURATION: if (setupPacket->Packet.wValue.Bytes.LowByte == 0) { descriptorSize = deviceContext->ConfigurationDescriptorSize; descriptorIn = deviceContext->UsbConfigurationDescriptor; } else { // we only support the one for now. ;) WdfRequestCompleteWithInformation(Request, STATUS_NO_MORE_ENTRIES, 0); return; } break; } if (descriptorIn && descriptorSize) { // handle (or fail) this standard request here. status = WdfRequestRetrieveOutputBuffer(Request, 2, &outputBuffer, &outputBufferLength); if (NT_SUCCESS(status)) { descriptorSize = (ULONG)min(descriptorSize, outputBufferLength); RtlCopyMemory(outputBuffer, descriptorIn, descriptorSize); WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, descriptorSize); return; } USBERR("WdfRequestRetrieveOutputBuffer failed. status=%Xh\n", status); WdfRequestCompleteWithInformation(Request, status, 0); return; } } } if (METHOD_FROM_CTL_CODE(requestContext->IoControlCode) == METHOD_BUFFERED && requestContext->RequestType == WdfRequestTypeWrite) { // support for some of the legacy LIBUSB_IOCTL codes which place the data input // buffer at the end of the libusb_request structure. status = WdfRequestRetrieveInputMemory(Request, &transferMemory); if (!NT_SUCCESS(status)) { USBERR("WdfRequestRetrieveInputMemory failed. status=%Xh\n", status); goto Exit; } if (requestContext->Length < sizeof(libusb_request)) { // this can never happen because the input buffer length is checked for // this by the default IoControl event. status = STATUS_BUFFER_TOO_SMALL; USBERR("input buffer length is less than sizeof(libusb_request) status=%Xh\n", status); goto Exit; } transferOffset->BufferOffset = sizeof(libusb_request); transferOffset->BufferLength = requestContext->Length - sizeof(libusb_request); if (transferOffset->BufferLength == 0) { // this is okay but no input data means transferOffset->BufferOffset is pointing // to invalid memory; because the length is also zero it is still most likely safe. transferOffset = NULL; transferMemory = NULL; } } else { // native control transfers are direct; data comes from/goes to the out buffer whether reading or writing. transferOffset = NULL; status = WdfRequestRetrieveOutputMemory(Request, &transferMemory); if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) { USBERR("WdfRequestRetrieveOutputMemory failed. status=%Xh\n", status); goto Exit; } if (status == STATUS_BUFFER_TOO_SMALL) { // zero length transfer buffer, this is okay. transferMemory = NULL; USBMSG("zero-length transfer buffer\n"); } } status = WdfUsbTargetDeviceFormatRequestForControlTransfer( deviceContext->WdfUsbTargetDevice, Request, setupPacket, transferMemory, transferOffset); if (!NT_SUCCESS(status)) { USBERR("WdfUsbTargetDeviceFormatRequestForControlTransfer failed. status=%Xh\n", status); goto Exit; } WdfRequestSetCompletionRoutine(Request, XferCtrlComplete, NULL); WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, 0); status = SetRequestTimeout(requestContext, Request, &sendOptions); if (!NT_SUCCESS(status)) { USBERR("SetRequestTimeout failed. status=%Xh\n", status); goto Exit; } if (!WdfRequestSend(Request, WdfUsbTargetDeviceGetIoTarget(deviceContext->WdfUsbTargetDevice), &sendOptions)) { status = WdfRequestGetStatus(Request); USBERR("WdfRequestSend failed. status=%Xh\n", status); } else { USBMSGN("[Ok] status=%Xh", status); return; } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); } return; }
NTSTATUS DriverControlUtilityHandler( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { NTSTATUS nsStatus = STATUS_INVALID_DEVICE_REQUEST; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (Irp); ULONG IOCTL = IrpSp->Parameters.DeviceIoControl.IoControlCode; PVOID pInBuffer = NULL; PVOID pOutBuffer = NULL; ULONG ulInformation = 0; ULONG ulIOCTLIndex = 0; ULONG ulInBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; ULONG ulOutBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength; switch(METHOD_FROM_CTL_CODE(IOCTL)) { case METHOD_BUFFERED: { pInBuffer = Irp->AssociatedIrp.SystemBuffer; pOutBuffer= Irp->AssociatedIrp.SystemBuffer; } break; case METHOD_NEITHER: { pInBuffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; pOutBuffer= Irp->UserBuffer; } break; default: { ASSERT(FALSE); nsStatus = STATUS_INVALID_PARAMETER; } } if ( ExGetPreviousMode () == UserMode && g_osVersionCheck < WINDOWS_VERSION_8 ) { for (ulIOCTLIndex = 0; ulIOCTLIndex < _countof(aIOCTLHandlers); ++ulIOCTLIndex) { if ( (ULONG)aIOCTLHandlers[ulIOCTLIndex].IOCTL == IOCTL ) { nsStatus = aIOCTLHandlers[ulIOCTLIndex].IoctlFunc( DeviceObject, pInBuffer, ulInBufferLength, pOutBuffer, ulOutBufferLength, &ulInformation ); if ( pOutBuffer != NULL && ulInformation > 0 ) { ((PCOMMON_HEAD_OUT)pOutBuffer)->IoStatus.Status = nsStatus; ((PCOMMON_HEAD_OUT)pOutBuffer)->IoStatus.Information = ulInformation; } break; } } } nsStatus = (nsStatus == STATUS_PENDING)? nsStatus : STATUS_SUCCESS; Irp->IoStatus.Status = nsStatus; Irp->IoStatus.Information = ulInformation; return nsStatus; }
static VOID UsbChief_EvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { NTSTATUS Status; size_t Length = 0; PIOCTL_DATA data; PDEVICE_CONTEXT pDeviceContext; UCHAR test[4096]; UCHAR *config; WORD *version; URB Urb; WDF_USB_INTERFACE_SELECT_SETTING_PARAMS interfaceParams; ULONG i; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(Queue); PAGED_CODE(); pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); Length = 0; switch(IoControlCode) { case IOCTL_VENDOR_WRITE: if (InputBufferLength != sizeof(*data)) { UsbChief_DbgPrint(0, ("Invalid InputBuffer Size: %d/%d\n", InputBufferLength, sizeof(*data))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } Status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &data, &Length); if (!NT_SUCCESS(Status)) goto out; UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtIoDeviceControl: IOCTL_VENDOR_WRITE %x, Index %x, Value %x, Max Length %d, Buf %p\n", data->Request, data->Index, data->Value, data->Length, data->Buffer)); if (Length != sizeof(*data)) { UsbChief_DbgPrint(0, ("Failed to retrieve buffer: %d/%d\n", Length, sizeof(*data))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } memset(&Urb, 0, sizeof(Urb)); Urb.UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE; Urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); Urb.UrbControlVendorClassRequest.RequestTypeReservedBits = 0x40; Urb.UrbControlVendorClassRequest.TransferBufferLength = data->Length; Urb.UrbControlVendorClassRequest.TransferBuffer = (PVOID)data->Buffer; Urb.UrbControlVendorClassRequest.Request = data->Request; Urb.UrbControlVendorClassRequest.Value = data->Value; Urb.UrbControlVendorClassRequest.Index = data->Index; if (DebugLevel & DEBUG_IOCTL) { for(i = 0; i < data->Length; i++) DbgPrint("%02X ", ((PUCHAR)data->Buffer)[i]); DbgPrint("\n"); } Status = WdfUsbTargetDeviceSendUrbSynchronously(pDeviceContext->WdfUsbTargetDevice, NULL, NULL, &Urb); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfUsbTargetDeviceSendControlTransferSynchronously failed\n")); } break; case IOCTL_VENDOR_READ: if (InputBufferLength != sizeof(*data)) { UsbChief_DbgPrint(0, ("Invalid InputBuffer Size: %d/%d\n", InputBufferLength, sizeof(*data))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } Status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &data, &Length); if (!NT_SUCCESS(Status)) goto out; UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtIoDeviceControl: IOCTL_VENDOR_READ %x, Index %x, Value %x, Max Length %d, Buf %p\n", data->Request, data->Index, data->Value, data->Length, data->Buffer)); if (Length != sizeof(*data)) { UsbChief_DbgPrint(0, ("Failed to retrieve buffer: %d/%d\n", Length, sizeof(*data))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } if (data->Length > sizeof(test)) { Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } memset(&Urb, 0, sizeof(Urb)); Urb.UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE; Urb.UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST); Urb.UrbControlVendorClassRequest.RequestTypeReservedBits = 0xc0; Urb.UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK; Urb.UrbControlVendorClassRequest.TransferBufferLength = data->Length; Urb.UrbControlVendorClassRequest.TransferBuffer = test; Urb.UrbControlVendorClassRequest.Request = data->Request; Urb.UrbControlVendorClassRequest.Value = data->Value; Urb.UrbControlVendorClassRequest.Index = data->Index; Status = WdfUsbTargetDeviceSendUrbSynchronously(pDeviceContext->WdfUsbTargetDevice, NULL, NULL, &Urb); if (DebugLevel & DEBUG_IOCTL && NT_SUCCESS(Status)) { for(i = 0; i < Urb.UrbControlVendorClassRequest.TransferBufferLength; i++) DbgPrint("%02X ", ((PUCHAR)test)[i]); DbgPrint("\n"); } if (Urb.UrbControlVendorClassRequest.TransferBufferLength) memcpy((PVOID)data->Buffer, test, Urb.UrbControlVendorClassRequest.TransferBufferLength); Length = Urb.UrbControlVendorClassRequest.TransferBufferLength; break; case IOCTL_SELECT_CONFIGURATION: if (InputBufferLength != sizeof(*config)) { UsbChief_DbgPrint(0, ("Invalid InputBuffer Size: %d/%d\n", InputBufferLength, sizeof(*config))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } config = 0; Status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, (PVOID)&config, &Length); if (!NT_SUCCESS(Status)) goto out; if (Length != sizeof(*config)) { UsbChief_DbgPrint(0, ("Invalid Length: %d/%d\n", Length, sizeof(*config))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtDeviceControl: IOCTL_SELECT_CONFIGURATION %x\n", *config)); if (!pDeviceContext->UsbInterface) { Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING (&interfaceParams, *config); Status = WdfUsbInterfaceSelectSetting(pDeviceContext->UsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &interfaceParams); break; case IOCTL_GET_FIRMWARE_VERSION: UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtDeviceControl: GET_FIRMWARE_VERSION\n")); Status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &version, &Length); if (!NT_SUCCESS(Status)) goto out; if (Length != sizeof(*version)) { UsbChief_DbgPrint(0, ("Invalid Length: %d/%d\n", Length, sizeof(*version))); Status = STATUS_INVALID_DEVICE_REQUEST; goto out; } *version = pDeviceContext->UsbDeviceDescriptor.bcdDevice; break; default: UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtDeviceControl %08x (Device %x, Method %x) unknown\n", IoControlCode, DEVICE_TYPE_FROM_CTL_CODE(IoControlCode), METHOD_FROM_CTL_CODE(IoControlCode))); Status = STATUS_INVALID_DEVICE_REQUEST; break; } out: UsbChief_DbgPrint(DEBUG_IOCTL, ("EvtDeviceControl: Status %08x, Length %d\n", Status, Length)); WdfRequestCompleteWithInformation(Request, Status, Length); }