Files
3fe5b8b0bb [SDK][WDF][USBDEX][NTOSKRNL_VISTA] Fully enable KMDF (#8396)
[SDK][WDFLDR] Add kmdf loader driver
[SDK][WDF] Add kmdf drver init static library
[SDK][WDF] Modify kmdf driver for working with wdfldr driver
[SDK][CDROM] Cdrom driver dynamically linking with kmdf
[SDK][WDF] Add kmdfdriver module type
[SDK][WDF][USBDEX][NTOSKRNL_VISTA] Fully enable KMDF
[KMDF][WDFLDR][WDF01000] Fix Windows 10 Compatibility WDFLDR and WDF01000
[WDF01000] NO_KERNEL_LIST_ENTRY_CHECKS for wdf01000 3rd party code

This PR is an accumulation of three peoples work, with the goal of the trying to get WDF to work like it should.
This has been tested in combination with some extra NT6+ ntoskrnl against multiple drivers.

---------

Co-authored-by: Max Korostil <[email protected]>
Co-authored-by: Victor Perevertkin <[email protected]>
Co-authored-by: Adam Słaboń <[email protected]>
Co-authored-by: Hermès BÉLUSCA - MAÏTO <[email protected]>
2025-11-03 06:38:52 -08:00

1448 lines
40 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxUsbDeviceAPI.cpp
Abstract:
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#include "fxusbpch.hpp"
extern "C" {
#if defined(EVENT_TRACING)
#include "FxUsbDeviceAPI.tmh"
#endif
}
//
// Extern "C" all APIs
//
extern "C" {
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
FxUsbTargetDeviceCreate(
__in
PFX_DRIVER_GLOBALS FxDriverGlobals,
__in
FxDeviceBase* Device,
__in
ULONG USBDClientContractVersion,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__out
WDFUSBDEVICE* UsbDevice
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Device - FxDeviceBase object
USBDClientContractVersion - The USBD Client Contract version of the client driver
UsbDevice - Pointer which will receive the created handle
Return Value:
STATUS_SUCCESS - success
STATUS_INSUFFICIENT_RESOURCES - no memory available
...
--*/
{
FxUsbDevice* pUsbDevice;
NTSTATUS status;
//
// Basic parameter validation
//
FxPointerNotNull(FxDriverGlobals, UsbDevice);
*UsbDevice = NULL;
status = FxVerifierCheckIrqlLevel(FxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateObjectAttributes(FxDriverGlobals,
Attributes,
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
if (!NT_SUCCESS(status)) {
return status;
}
pUsbDevice = new(FxDriverGlobals, Attributes) FxUsbDevice(FxDriverGlobals);
if (pUsbDevice == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Perform all init and handle creation functions. Check for error at the
// end and clean up there.
//
status = pUsbDevice->Init(Device);
if (NT_SUCCESS(status)) {
WDFOBJECT device;
device = NULL;
status = pUsbDevice->InitDevice(USBDClientContractVersion);
if (NT_SUCCESS(status)) {
status = pUsbDevice->CreateInterfaces();
}
if (NT_SUCCESS(status)) {
status = Device->AddIoTarget(pUsbDevice);
}
if (NT_SUCCESS(status)) {
status = pUsbDevice->Commit(Attributes, &device, Device);
}
if (NT_SUCCESS(status)) {
*UsbDevice = (WDFUSBDEVICE) device;
}
}
if (!NT_SUCCESS(status)) {
//
// And now free it
//
pUsbDevice->DeleteFromFailedCreate();
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceCreate)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFDEVICE Device,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__out
WDFUSBDEVICE* UsbDevice
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Device - WDFDEVICE handle to which we are attaching the WDFUSBDEVICE handle
to
PUsbDevice - Pointer which will receive the created handle
Return Value:
STATUS_SUCCESS - success
STATUS_INSUFFICIENT_RESOURCES - no memory available
...
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxDeviceBase* pDevice;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Device,
FX_TYPE_DEVICE_BASE,
(PVOID*)&pDevice,
&pFxDriverGlobals);
return FxUsbTargetDeviceCreate(pFxDriverGlobals,
pDevice,
USBD_CLIENT_CONTRACT_VERSION_INVALID,
Attributes,
UsbDevice);
}
__checkReturn
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceCreateWithParameters)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFDEVICE Device,
__in
PWDF_USB_DEVICE_CREATE_CONFIG Config,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__out
WDFUSBDEVICE* UsbDevice
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Device - WDFDEVICE handle to which we are attaching the WDFUSBDEVICE handle
to
PUsbDevice - Pointer which will receive the created handle
Return Value:
STATUS_SUCCESS - success
STATUS_INSUFFICIENT_RESOURCES - no memory available
...
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxDeviceBase* pDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Device,
FX_TYPE_DEVICE_BASE,
(PVOID*)&pDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, Config);
if (Config->Size != sizeof(WDF_USB_DEVICE_CREATE_CONFIG)) {
status = STATUS_INFO_LENGTH_MISMATCH;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDF_USB_DEVICE_CREATE_CONFIG Size 0x%x, expected 0x%x, %!STATUS!",
Config->Size, sizeof(WDF_USB_DEVICE_CREATE_CONFIG), status);
return status;
}
return FxUsbTargetDeviceCreate(pFxDriverGlobals,
pDevice,
Config->USBDClientContractVersion,
Attributes,
UsbDevice);
}
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceRetrieveInformation)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__out
PWDF_USB_DEVICE_INFORMATION Information
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, Information);
if (Information->Size != sizeof(WDF_USB_DEVICE_INFORMATION)) {
status = STATUS_INFO_LENGTH_MISMATCH;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Information size %d, expected %d %!STATUS!",
Information->Size, sizeof(WDF_USB_DEVICE_INFORMATION),
status);
return status;
}
pUsbDevice->GetInformation(Information);
return STATUS_SUCCESS;
}
__drv_maxIRQL(PASSIVE_LEVEL)
VOID
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceGetDeviceDescriptor)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__out
PUSB_DEVICE_DESCRIPTOR UsbDeviceDescriptor
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, UsbDeviceDescriptor);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return;
}
pUsbDevice->CopyDeviceDescriptor(UsbDeviceDescriptor);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceRetrieveConfigDescriptor)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__out_bcount_part_opt(*ConfigDescriptorLength, *ConfigDescriptorLength)
PVOID ConfigDescriptor,
__inout
PUSHORT ConfigDescriptorLength
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ConfigDescriptorLength);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
return pUsbDevice->GetConfigDescriptor(ConfigDescriptor,
ConfigDescriptorLength);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceQueryString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
WDFREQUEST Request,
__in_opt
PWDF_REQUEST_SEND_OPTIONS RequestOptions,
__out_ecount_opt(*NumCharacters)
PUSHORT String,
__inout
PUSHORT NumCharacters,
__in
UCHAR StringIndex,
__in_opt
USHORT LangID
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, NumCharacters);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
if (!NT_SUCCESS(status)) {
return status;
}
status = pUsbDevice->GetString(String,
NumCharacters,
StringIndex,
LangID,
Request,
RequestOptions);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceAllocAndQueryString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
PWDF_OBJECT_ATTRIBUTES StringMemoryAttributes,
__out
WDFMEMORY* StringMemory,
__out_opt
PUSHORT NumCharacters,
__in
UCHAR StringIndex,
__in_opt
USHORT LangID
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
WDFMEMORY hMemory;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
USHORT numChars = 0;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, StringMemory);
*StringMemory = NULL;
if (NumCharacters != NULL) {
*NumCharacters = 0;
}
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateObjectAttributes(pFxDriverGlobals, StringMemoryAttributes);
if (!NT_SUCCESS(status)) {
return status;
}
status = pUsbDevice->GetString(NULL, &numChars, StringIndex, LangID);
if (NT_SUCCESS(status) && numChars > 0) {
FxMemoryObject* pBuffer;
status = FxMemoryObject::_Create(pFxDriverGlobals,
StringMemoryAttributes,
NonPagedPool,
pFxDriverGlobals->Tag,
numChars * sizeof(WCHAR),
&pBuffer);
if (!NT_SUCCESS(status)) {
return STATUS_INSUFFICIENT_RESOURCES;
}
status = pBuffer->Commit(StringMemoryAttributes,
(WDFOBJECT*)&hMemory);
if (NT_SUCCESS(status)) {
status = pUsbDevice->GetString((PUSHORT) pBuffer->GetBuffer(),
&numChars,
StringIndex,
LangID);
if (NT_SUCCESS(status)) {
if (NumCharacters != NULL) {
*NumCharacters = numChars;
}
*StringMemory = hMemory;
}
}
if (!NT_SUCCESS(status)) {
//
// There can only be one context on this object right now,
// so just clear out the one.
//
pBuffer->DeleteFromFailedCreate();
}
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
NTAPI
WDFEXPORT(WdfUsbTargetDeviceFormatRequestForString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
WDFREQUEST Request,
__in
WDFMEMORY Memory,
__in_opt
PWDFMEMORY_OFFSET Offset,
__in
UCHAR StringIndex,
__in_opt
USHORT LangID
)
/*++
Routine Description:
Formats a request so that it can be used to query for a string from the
device.
Arguments:
UsbDevice - device to be queried
Request - request to format
Memory - memory to write the string into
Return Value:
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
IFxMemory* pMemory;
FxUsbDevice* pUsbDevice;
FxRequestBuffer buf;
FxRequest* pRequest;
NTSTATUS status;
size_t bufferSize;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p, StringIndex %d, LandID 0x%x",
UsbDevice, Request, Memory, StringIndex, LangID);
FxObjectHandleGetPtr(pFxDriverGlobals,
Memory,
IFX_TYPE_MEMORY,
(PVOID*) &pMemory);
FxObjectHandleGetPtr(pFxDriverGlobals,
Request,
FX_TYPE_REQUEST,
(PVOID*) &pRequest);
status = pMemory->ValidateMemoryOffsets(Offset);
if (!NT_SUCCESS(status)) {
return status;
}
buf.SetMemory(pMemory, Offset);
bufferSize = buf.GetBufferLength();
//
// the string descriptor is array of WCHARs so the buffer being used must be
// of an integral number of them.
//
if ((bufferSize % sizeof(WCHAR)) != 0) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFMEMORY %p length must be even number of WCHARs, but is %I64d in "
"length, %!STATUS!",
Memory, bufferSize, status);
return status;
}
//
// While the length in the descriptor (bLength) is a byte, so the requested
// buffer cannot be bigger then that, do not check the bufferSize < 0xFF.
// We don't check because the driver can be using the WDFMEMORY as a part
// of a larger structure.
//
//
// Format the request
//
status = pUsbDevice->FormatStringRequest(pRequest, &buf, StringIndex, LangID);
if (NT_SUCCESS(status)) {
FxUsbDeviceStringContext* pContext;
pContext = (FxUsbDeviceStringContext*) pRequest->GetContext();
pContext->m_UsbParameters.Parameters.DeviceString.Buffer = Memory;
pContext->m_UsbParameters.Parameters.DeviceString.StringIndex = StringIndex;
pContext->m_UsbParameters.Parameters.DeviceString.LangID = LangID;
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p, %!STATUS!",
UsbDevice, Request, Memory, status);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceSelectConfig)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
PWDF_OBJECT_ATTRIBUTES PipesAttributes,
__inout
PWDF_USB_DEVICE_SELECT_CONFIG_PARAMS Params
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, Params);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
if (Params->Size != sizeof(WDF_USB_DEVICE_SELECT_CONFIG_PARAMS)) {
status = STATUS_INFO_LENGTH_MISMATCH;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Params size %d, expected %d %!STATUS!",
Params->Size, sizeof(WDF_USB_DEVICE_SELECT_CONFIG_PARAMS),
status);
return status;
}
//
// Sanity check the Type value as well to be in range.
//
if (Params->Type < WdfUsbTargetDeviceSelectConfigTypeDeconfig
||
Params->Type > WdfUsbTargetDeviceSelectConfigTypeUrb) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Params Type %d not a valid value, %!STATUS!",
Params->Size, status);
return status;
}
#if (FX_CORE_MODE == FX_CORE_USER_MODE)
if ((Params->Type == WdfUsbTargetDeviceSelectConfigTypeDeconfig) ||
(Params->Type == WdfUsbTargetDeviceSelectConfigTypeUrb) ||
(Params->Type == WdfUsbTargetDeviceSelectConfigTypeInterfacesDescriptor)) {
status = STATUS_NOT_SUPPORTED;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Params Type %d not supported for UMDF, %!STATUS!",
Params->Type, status);
return status;
}
#endif
status = FxValidateObjectAttributes(pFxDriverGlobals,
PipesAttributes,
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
if (!NT_SUCCESS(status)) {
return status;
}
if (pUsbDevice->HasMismatchedInterfacesInConfigDescriptor()) {
//
// Config descriptor reported zero interfaces, but we found an
// interface descriptor in it.
//
status = STATUS_INVALID_DEVICE_REQUEST;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p number of interfaces found in the config descriptor "
"does not match bNumInterfaces in config descriptor, failing config "
"operation %!WdfUsbTargetDeviceSelectConfigType!, %!STATUS!",
UsbDevice, Params->Type, status);
return status;
}
else if (pUsbDevice->GetNumInterfaces() == 0) {
//
// Special case the zero interface case and exit early
//
status = STATUS_SUCCESS;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p succeeding config operation "
"%!WdfUsbTargetDeviceSelectConfigType! on zero interfaces "
"immediately, %!STATUS!", UsbDevice, Params->Type, status);
return status;
}
switch (Params->Type) {
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
case WdfUsbTargetDeviceSelectConfigTypeDeconfig:
status = pUsbDevice->Deconfig();
break;
case WdfUsbTargetDeviceSelectConfigTypeInterfacesDescriptor:
if (Params->Types.Descriptor.InterfaceDescriptors == NULL ||
Params->Types.Descriptor.NumInterfaceDescriptors == 0) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Either InterfaceDescriptor is NULL or NumInterfaceDescriptors is zero "
"WDFUSBDEVICE %p InterfaceDescriptor %p NumInterfaceDescriptors 0x%x"
"%!WdfUsbTargetDeviceSelectConfigType! %!STATUS!", UsbDevice,
Params->Types.Descriptor.InterfaceDescriptors,
Params->Types.Descriptor.NumInterfaceDescriptors,
Params->Type,
status);
}
else {
status = pUsbDevice->SelectConfigDescriptor(
PipesAttributes,
Params);
}
break;
case WdfUsbTargetDeviceSelectConfigTypeUrb:
//
// Since the USBD macro's dont include the USBD_PIPE_INFORMATION for 0 EP's,
// make the length check to use
// sizeof(struct _URB_SELECT_CONFIGURATION) - sizeof(USBD_PIPE_INFORMATION)
//
if (Params->Types.Urb.Urb == NULL ||
Params->Types.Urb.Urb->UrbHeader.Function != URB_FUNCTION_SELECT_CONFIGURATION ||
Params->Types.Urb.Urb->UrbHeader.Length <
(sizeof(struct _URB_SELECT_CONFIGURATION) - sizeof(USBD_PIPE_INFORMATION))) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Either URB passed in was NULL or the URB Function or Length was invalid "
" WDFUSBDEVICE %p Urb 0x%p "
"%!WdfUsbTargetDeviceSelectConfigType!"
" %!STATUS!", UsbDevice,
Params->Types.Urb.Urb,
Params->Type,
status);
}
else {
status = pUsbDevice->SelectConfig(
PipesAttributes,
Params->Types.Urb.Urb,
FxUrbTypeLegacy,
NULL);
}
break;
#endif
case WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs:
if (Params->Types.MultiInterface.Pairs == NULL) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p SettingPairs Array passed is NULL, %!STATUS!",
pUsbDevice->GetHandle(),status);
break;
}
else if (Params->Types.MultiInterface.NumberInterfaces !=
pUsbDevice->GetNumInterfaces()) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p MultiInterface.NumberInterfaces %d != %d "
"(reported num interfaces), %!STATUS!",
pUsbDevice->GetHandle(),
Params->Types.MultiInterface.NumberInterfaces,
pUsbDevice->GetNumInterfaces(), status);
break;
}
// || || Fall through || ||
// \/ \/ \/ \/
case WdfUsbTargetDeviceSelectConfigTypeMultiInterface:
//
// Validate SettingIndexes passed-in
//
for (ULONG i = 0;
i < Params->Types.MultiInterface.NumberInterfaces;
i++) {
PWDF_USB_INTERFACE_SETTING_PAIR pair;
FxUsbInterface * pUsbInterface;
UCHAR numSettings;
pair = &(Params->Types.MultiInterface.Pairs[i]);
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
pair->UsbInterface,
FX_TYPE_USB_INTERFACE,
(PVOID*) &pUsbInterface);
numSettings = pUsbInterface->GetNumSettings();
if (pair->SettingIndex >= numSettings) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p SettingPairs contains invalid SettingIndex"
" for WDFUSBINTERFACE %p. Setting index passed in: %d, "
"max index: %d, returning %!STATUS!",
pUsbDevice->GetHandle(),
pair->UsbInterface,
pair->SettingIndex,
pUsbInterface->GetNumSettings() - 1,
status);
return status;
}
}
status = pUsbDevice->SelectConfigMulti(
PipesAttributes,
Params);
break;
case WdfUsbTargetDeviceSelectConfigTypeSingleInterface:
status = pUsbDevice->SelectConfigSingle( //vm changed name from SelectConfigAuto
PipesAttributes,
Params);
break;
default:
status = STATUS_INVALID_PARAMETER;
}
return status;
}
__drv_maxIRQL(DISPATCH_LEVEL)
UCHAR
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceGetNumInterfaces)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice
)
{
DDI_ENTRY();
FxUsbDevice* pUsbDevice;
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice);
return pUsbDevice->GetNumInterfaces();
}
__drv_maxIRQL(DISPATCH_LEVEL)
USBD_CONFIGURATION_HANDLE
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceWdmGetConfigurationHandle)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice
)
{
DDI_ENTRY();
FxUsbDevice* pUsbDevice;
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice);
return pUsbDevice->GetConfigHandle();
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
NTAPI
WDFEXPORT(WdfUsbTargetDeviceSendControlTransferSynchronously)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
WDFREQUEST Request,
__in_opt
PWDF_REQUEST_SEND_OPTIONS RequestOptions,
__in
PWDF_USB_CONTROL_SETUP_PACKET SetupPacket,
__in_opt
PWDF_MEMORY_DESCRIPTOR MemoryDescriptor,
__out_opt
PULONG BytesTransferred
)
/*++
Routine Description:
Synchronously sends a control transfer to the default control pipe on the
device.
Arguments:
UsbDevice - the target representing the device
Request - Request whose PIRP to use
RequestOptions - options to use when sending the request
SetupPacket - control setup packet to be used in the transfer
MemoryDescriptor - memory to use in the transfer after the setup packet
BytesTransferred - number of bytes sent to or by the device
Return Value:
NTSTATUS
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxRequestBuffer buf;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
FxUsbDeviceControlContext context(FxUrbTypeLegacy);
FxSyncRequest request(pFxDriverGlobals, &context, Request);
//
// FxSyncRequest always succeesds for KM but can fail for UM.
//
status = request.Initialize();
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"Failed to initialize FxSyncRequest");
return status;
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p control transfer sync", UsbDevice);
FxPointerNotNull(pFxDriverGlobals, SetupPacket);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateRequestOptions(pFxDriverGlobals, RequestOptions);
if (!NT_SUCCESS(status)) {
return status;
}
status = buf.ValidateMemoryDescriptor(
pFxDriverGlobals,
MemoryDescriptor,
MemoryDescriptorNullAllowed | MemoryDescriptorNoBufferAllowed
);
if (!NT_SUCCESS(status)) {
return status;
}
status = pUsbDevice->FormatControlRequest(request.m_TrueRequest,
SetupPacket,
&buf);
if (NT_SUCCESS(status)) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, WDFREQUEST %p being submitted",
UsbDevice, request.m_TrueRequest->GetTraceObjectHandle());
status = pUsbDevice->SubmitSync(request.m_TrueRequest, RequestOptions);
if (BytesTransferred != NULL) {
if (NT_SUCCESS(status)) {
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
*BytesTransferred = context.m_Urb->TransferBufferLength;
#elif (FX_CORE_MODE == FX_CORE_USER_MODE)
*BytesTransferred = context.m_UmUrb.UmUrbControlTransfer.TransferBufferLength;
#endif
}
else {
*BytesTransferred = 0;
}
}
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, %!STATUS!", UsbDevice, status);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
NTAPI
WDFEXPORT(WdfUsbTargetDeviceFormatRequestForControlTransfer)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
WDFREQUEST Request,
__in
PWDF_USB_CONTROL_SETUP_PACKET SetupPacket,
__in_opt
WDFMEMORY TransferMemory,
__in_opt
PWDFMEMORY_OFFSET TransferOffset
)
/*++
Routine Description:
Formats a request so that a control transfer can be sent to the device
after this call returns successfully.
Arguments:
UsbDevice - the target representing the device
Request - Request to format
SetupPacket - control setup packet to be used in the transfer
TransferMemory - memory to use in the transfer after the setup packet
TransferOffset - offset into TransferMemory and size override for transfer
length
Return Value:
NTSTATUS
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
IFxMemory* pMemory;
FxUsbDevice* pUsbDevice;
FxRequestBuffer buf;
FxRequest* pRequest;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"WDFUSBDEVICE %p, WDFREQUEST %p, WDFMEMORY %p",
UsbDevice, Request, TransferMemory);
FxPointerNotNull(pFxDriverGlobals, SetupPacket);
if (TransferMemory != NULL) {
FxObjectHandleGetPtr(pFxDriverGlobals,
TransferMemory,
IFX_TYPE_MEMORY,
(PVOID*) &pMemory);
status = pMemory->ValidateMemoryOffsets(TransferOffset);
if (!NT_SUCCESS(status)) {
return status;
}
buf.SetMemory(pMemory, TransferOffset);
}
else {
pMemory = NULL;
}
FxObjectHandleGetPtr(pFxDriverGlobals,
Request,
FX_TYPE_REQUEST,
(PVOID*) &pRequest);
status = pUsbDevice->FormatControlRequest(pRequest, SetupPacket, &buf);
if (NT_SUCCESS(status)) {
FxUsbDeviceControlContext* pContext;
pContext = (FxUsbDeviceControlContext*) pRequest->GetContext();
RtlCopyMemory(
&pContext->m_UsbParameters.Parameters.DeviceControlTransfer.SetupPacket,
SetupPacket,
sizeof(*SetupPacket)
);
if (pMemory != NULL) {
pContext->m_UsbParameters.Parameters.DeviceControlTransfer.Buffer =
TransferMemory;
}
}
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIOTARGET,
"format control request WDFUSBDEVICE %p, WDFREQWUEST %p, WDFMEMORY %p, %!STATUS!",
UsbDevice, Request, TransferMemory, status);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceResetPortSynchronously)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = pUsbDevice->Reset();
return status;
}
#pragma warning(disable:28285)
__checkReturn
__drv_maxIRQL(DISPATCH_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceCreateIsochUrb)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in_opt
PWDF_OBJECT_ATTRIBUTES Attributes,
__in
ULONG NumberOfIsochPackets,
__out
WDFMEMORY* UrbMemory,
__deref_opt_out_bcount(GET_ISOCH_URB_SIZE(NumberOfIsochPackets))
PURB* Urb
)
/*++
Routine Description:
Creates a WDFUSBDEVICE handle for the client.
Arguments:
Attributes - Attributes associated with this object
NumberOfIsochPacket - Maximum number of Isoch packets that will be programmed into this Urb
UrbMemory - The returned handle to the caller for the allocated Urb
Urb - (opt) Pointer to the associated urb buffer.
Return Value:
STATUS_INVALID_PARAMETER - any required parameters are not present/invalid
STATUS_INVALID_DEVICE_STATE - If the client did not specify a client contract verion while
creating the WDFUSBDEVICE
STATUS_INSUFFICIENT_RESOURCES - could not allocated the object that backs
the handle
STATUS_SUCCESS - success
...
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
//
// Basic parameter validation
//
FxPointerNotNull(pFxDriverGlobals, UrbMemory);
if (pUsbDevice->GetUSBDHandle() == NULL) {
status = STATUS_INVALID_DEVICE_STATE;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"USBDEVICE Must have been created with Client Contract Verion Info, %!STATUS!",
status);
return status;
}
status = pUsbDevice->CreateIsochUrb(Attributes,
NumberOfIsochPackets,
UrbMemory,
Urb);
return status;
}
__drv_maxIRQL(DISPATCH_LEVEL)
WDFUSBINTERFACE
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceGetInterface)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
UCHAR InterfaceIndex
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
FxUsbInterface *pUsbInterface;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
pUsbInterface = pUsbDevice->GetInterfaceFromIndex(InterfaceIndex);
if (pUsbInterface != NULL) {
return pUsbInterface->GetHandle();
}
else {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
"WDFUSBDEVICE %p has %d interfaces, index %d requested, returning "
"NULL handle",
UsbDevice, pUsbDevice->GetNumInterfaces(), InterfaceIndex);
return NULL;
}
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
WDFAPI
NTAPI
WDFEXPORT(WdfUsbTargetDeviceQueryUsbCapability)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFUSBDEVICE UsbDevice,
__in
CONST GUID* CapabilityType,
__in
ULONG CapabilityBufferLength,
__drv_when(CapabilityBufferLength == 0, __out_opt)
__drv_when(CapabilityBufferLength != 0 && ResultLength == NULL, __out_bcount(CapabilityBufferLength))
__drv_when(CapabilityBufferLength != 0 && ResultLength != NULL, __out_bcount_part_opt(CapabilityBufferLength, *ResultLength))
PVOID CapabilityBuffer,
__out_opt
__drv_when(ResultLength != NULL,__deref_out_range(<=,CapabilityBufferLength))
PULONG ResultLength
)
/*++
Routine Description:
Queries USB capability for the device. Such capabilities are available
only with USB 3.0 stack. On earlier stacks this API will fail with
STATUS_NOT_IMPLEMENTED
Arguments:
UsbDevice - Device whose capability is to be queried.
CapabilityType - Type of capability as defined by
IOCTL_INTERNAL_USB_GET_USB_CAPABILITY
CapabilityBufferLength - Length of Capability buffer
CapabilityBuffer - Buffer for capability. Can be NULL if
CapabilitiyBufferLength is 0
ResultLength - Actual length of the capability. This parameter is optional.
Return Value:
STATUS_SUCCESS - success
STATUS_NOT_IMPLEMENTED - Capabilties are not supported by USB stack
STATUS_INSUFFICIENT_RESOURCES - no memory available
...
--*/
{
DDI_ENTRY();
NTSTATUS status;
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxUsbDevice* pUsbDevice;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
UsbDevice,
FX_TYPE_IO_TARGET_USB_DEVICE,
(PVOID*) &pUsbDevice,
&pFxDriverGlobals);
if (CapabilityBufferLength > 0) {
FxPointerNotNull(pFxDriverGlobals, CapabilityBuffer);
}
status = pUsbDevice->QueryUsbCapability(CapabilityType,
CapabilityBufferLength,
CapabilityBuffer,
ResultLength);
return status;
}
} // extern "C"