WdfUsbTargetDeviceCreate fails in non-WDF driver

  • Thread starter Thread starter pgruebele
  • Start date Start date
P

pgruebele

Hi.

I am creating a WDM driver which uses WDF in order to access the WDF usb
functionality. I have successfully added the WDF coinstaller and am able to
load/unload my device. I am also able to create the WDF device using
WdfDeviceMiniportCreate(). This is based on msvad.

However, my call to WdfUsbTargetDeviceCreate() always fails with 0xC0000010.
I read and followed everything I could find regarding this subject. I don't
know what more to try so I'm hoping someone can help me. Someone who knows
what they are doing can probably tell right away why it's failing.....

Here is the debug output I am getting:

****** -> DriverEntry
****** <- DriverEntry
****** -> AddDevice
WdfDeviceMiniportCreate WdfDriver: 0x7bb25910 WdfDevice: 0x7bb4f7a8
UsbDevice: 0x0
****** <- AddDevice
****** -> StartDevice
****** -> CAdapterCommon::Init
InstallSubDevice T
****** -> CMiniportTopologyUSBT::CMiniportTopologyUSBT
****** -> CMiniportTopology::Init
****** -> CMiniportTopologyUSBT::Init
****** -> CMiniportTopologyUSBT::GetDescription
****** <- InstallSubdevice
InstallSubDevice W
****** -> CMiniportWaveCyclicUSBT::CMiniportWaveCyclicUSBT
****** -> CMiniportWaveCyclic::Init
****** -> CMiniportWaveCyclicUSBT::Init
****** -> CAdapterCommon::SetWaveServiceGroup
****** -> CMiniportWaveCyclicUSBT::GetDescription
****** <- InstallSubdevice
StartDevice1 WdfDriver: 0x7bb25910 WdfDevice: 0x7bb4f7a8 UsbDevice: 0x0
StartDevice2 WdfDriver: 0x7bb25910 WdfDevice: 0x7bb4f7a8 UsbDevice: 0x0
*****************************WdfUsbTargetDeviceCreate failed c0000010!
****** -> CMiniportTopology::~CMiniportTopology
****** -> CMiniportTopologyUSBT::~CMiniportTopologyUSBT
****** -> CMiniportWaveCyclic::~CMiniportWaveCyclic
****** -> CMiniportWaveCyclicUSBT::~CMiniportWaveCyclicUSBT
****** -> CAdapterCommon::~CAdapterCommon
****** -> DriverUnload
****** <- DriverUnload



Here is the relevant source file:

/*++

Copyright (c) 1997-2000 Microsoft Corporation All Rights Reserved

Module Name:

adapter.cpp

Abstract:

Setup and miniport installation. No resources are used by msvad.

--*/

#pragma warning (disable : 4127)

//
// All the GUIDS for all the miniports end up in this object.
//
#define PUT_GUIDS_HERE

#include <msvad.h>
#include "common.h"


PDEVICE_OBJECT FunctionalDeviceObject = 0;

//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------

// BUGBUG set this to number of miniports
#define MAX_MINIPORTS 3 // Number of maximum miniports.

//-----------------------------------------------------------------------------
// Externals
//-----------------------------------------------------------------------------

NTSTATUS CreateMiniportWaveCyclicUSBT(OUT PUNKNOWN *, IN REFCLSID, IN
PUNKNOWN, IN POOL_TYPE);

NTSTATUS CreateMiniportTopologyUSBT(OUT PUNKNOWN *, IN REFCLSID, IN
PUNKNOWN, IN POOL_TYPE);

//-----------------------------------------------------------------------------
// Referenced forward.
//-----------------------------------------------------------------------------

DRIVER_ADD_DEVICE AddDevice;

NTSTATUS StartDevice(IN PDEVICE_OBJECT, IN PIRP, IN PRESOURCELIST);

//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------

//=============================================================================
#pragma code_seg("INIT")

extern "C" DRIVER_INITIALIZE DriverEntry;
PDRIVER_UNLOAD oldDriverUnload;
//VOID DriverUnload(__in PDRIVER_OBJECT DriverObject);
DRIVER_UNLOAD DriverUnload;

extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN
PUNICODE_STRING RegistryPathName)
{
/*++

Routine Description:

Installable driver initialization entry point.
This entry point is called directly by the I/O system.

All audio adapter drivers can use this code without change.

Arguments:

DriverObject - pointer to the driver object

RegistryPath - pointer to a unicode string representing the path,
to driver-specific key in the registry.

Return Value:

STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise.

--*/
WDF_DRIVER_CONFIG config;
WDFDRIVER hDriver;
NTSTATUS ntStatus;

usbtDebugPrintEnter();

WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
//
// Set WdfDriverInitNoDispatchOverride flag to tell the framework
// not to provide dispatch routines for the driver. In other words,
// the framework must not intercept IRPs that the I/O manager has
// directed to the driver. In this case, it will be handled by NDIS
// port driver.
//
config.DriverInitFlags |= WdfDriverInitNoDispatchOverride;

ntStatus = WdfDriverCreate(DriverObject,
RegistryPathName,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
&hDriver);
if (!NT_SUCCESS(ntStatus))
{
usbtDebugPrint((__DBGERROR__, "WdfDriverCreate failed\n"));
return ntStatus;
}

// Tell the class driver to initialize the driver.
//
ntStatus = PcInitializeAdapterDriver(DriverObject, RegistryPathName,
(PDRIVER_ADD_DEVICE)AddDevice);

// override the default DriverUnload
oldDriverUnload = (DRIVER_UNLOAD*)DriverObject->DriverUnload;
DriverObject->DriverUnload = DriverUnload;

usbtDebugPrintExit();

return ntStatus;
} // DriverEntry
#pragma code_seg()

#pragma code_seg("PAGE")

VOID DriverUnload(__in PDRIVER_OBJECT DriverObject)
/*++

Routine Description:

The unload handler is called during driver unload to free up resources
acquired in DriverEntry. Note that an unload handler differs from
a MiniportHalt function in that the unload handler has a more global
scope, whereas the scope of the MiniportHalt function is restricted
to a particular miniport driver instance.

During an unload operation, an NDIS 6.0 miniport driver must deregister
the miniport driver by calling NdisMDeregisterMiniportDriver
and passing the MiniportDriverHandle as a parameter.
The driver obtained the MiniportDriverHandle when it called
NdisMRegisterMiniportDriver.

Runs at IRQL = PASSIVE_LEVEL.

Arguments:

DriverObject Not used

Return Value:

None

--*/
{
usbtDebugPrintEnter();

UNREFERENCED_PARAMETER(DriverObject);

PAGED_CODE();

if (GetMyExtension()->WdfDevice != 0)
WdfObjectDelete(GetMyExtension()->WdfDevice);
if (GetMyExtension()->UsbDevice != 0)
WdfObjectDelete(GetMyExtension()->UsbDevice);

WdfDriverMiniportUnload(WdfGetDriver());

#if DOT11_TRACE_ENABLED
// WPP_CLEANUP(DriverObject);
#endif

// call the default DriverUnload
oldDriverUnload(DriverObject);

usbtDebugPrintExit();
}

//=============================================================================

NTSTATUS AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT
PhysicalDeviceObject)
/*++

Routine Description:

The Plug & Play subsystem is handing us a brand new PDO, for which we
(by means of INF registration) have been asked to provide a driver.

We need to determine if we need to be in the driver stack for the device.
Create a function device object to attach to the stack
Initialize that device object
Return status success.

All audio adapter drivers can use this code without change.
Set MAX_MINIPORTS depending on the number of miniports that the driver
uses.

Arguments:

DriverObject - pointer to a driver object

PhysicalDeviceObject - pointer to a device object created by the
underlying bus driver.

Return Value:

NT status code.

--*/
{
PAGED_CODE();

NTSTATUS ntStatus;

usbtDebugPrintEnter();

// disable prefast warning 28152 because
// DO_DEVICE_INITIALIZING is cleared in PcAddAdapterDevice
#pragma warning(disable:28152)

FunctionalDeviceObject = IoGetAttachedDevice(PhysicalDeviceObject);
// Tell the class driver to add the device.
ntStatus = PcAddAdapterDevice(DriverObject, PhysicalDeviceObject,
PCPFNSTARTDEVICE(StartDevice), MAX_MINIPORTS, 128 + MY_EXTENSION_SIZE +
PORT_CLASS_DEVICE_EXTENSION_SIZE);

if (!NT_SUCCESS (ntStatus))
{
usbtDebugPrint((__DBGERROR__, "PcAddAdapterDevice failed (0x%x)\n",
ntStatus));
return ntStatus;
}

FunctionalDeviceObject = PhysicalDeviceObject->AttachedDevice;
FunctionalDeviceObject = IoGetAttachedDevice(PhysicalDeviceObject);

GetMyExtension()->WdfDriver = WdfGetDriver();
GetMyExtension()->WdfDevice = 0;
GetMyExtension()->UsbDevice = 0;

WDF_OBJECT_ATTRIBUTES attributes;
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WDF_DEVICE_INFO);
ntStatus = WdfDeviceMiniportCreate(GetMyExtension()->WdfDriver,
&attributes,
FunctionalDeviceObject,
PhysicalDeviceObject->AttachedDevice,
PhysicalDeviceObject,
&(GetMyExtension()->WdfDevice));
if (!NT_SUCCESS (ntStatus))
usbtDebugPrint((__DBGERROR__, "WdfDeviceMiniportCreate failed (0x%x)\n",
ntStatus));

usbtDebugPrint((__DBGERROR__, "WdfDeviceMiniportCreate WdfDriver: 0x%x
WdfDevice: 0x%x UsbDevice: 0x%x\n", GetMyExtension()->WdfDriver,
GetMyExtension()->WdfDevice, GetMyExtension()->UsbDevice));

usbtDebugPrintExit();

return ntStatus;
} // AddDevice

//=============================================================================
NTSTATUS InstallSubdevice(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp,
__in PWSTR Name, __in REFGUID PortClassId, __in REFGUID MiniportClassId,
__in_opt PFNCREATEINSTANCE MiniportCreate, __in_opt PUNKNOWN
UnknownAdapter, __in_opt PRESOURCELIST ResourceList, __in REFGUID
PortInterfaceId,
__out_opt PUNKNOWN *OutPortInterface, __out_opt PUNKNOWN *OutPortUnknown)
{
/*++

Routine Description:

This function creates and registers a subdevice consisting of a port
driver, a minport driver and a set of resources bound together. It will
also optionally place a pointer to an interface on the port driver in a
specified location before initializing the port driver. This is done so
that a common ISR can have access to the port driver during
initialization, when the ISR might fire.

Arguments:

DeviceObject - pointer to the driver object

Irp - pointer to the irp object.

Name - name of the miniport. Passes to PcRegisterSubDevice

PortClassId - port class id. Passed to PcNewPort.

MiniportClassId - miniport class id. Passed to PcNewMiniport.

MiniportCreate - pointer to a miniport creation function. If NULL,
PcNewMiniport is used.

UnknownAdapter - pointer to the adapter object.
Used for initializing the port.

ResourceList - pointer to the resource list.

PortInterfaceId - GUID that represents the port interface.

OutPortInterface - pointer to store the port interface

OutPortUnknown - pointer to store the unknown port interface.

Return Value:

NT status code.

--*/
PAGED_CODE();

ASSERT(DeviceObject);
ASSERT(Irp);
ASSERT(Name);

NTSTATUS ntStatus;
PPORT port = NULL;
PUNKNOWN miniport = NULL;

usbtDebugPrint((__DBGERROR__, "InstallSubDevice %s\n", Name));

// Create the port driver object
//
ntStatus = PcNewPort(&port, PortClassId);

// Create the miniport object
//
if (NT_SUCCESS(ntStatus))
{
if (MiniportCreate)
ntStatus = MiniportCreate(&miniport, MiniportClassId, NULL, NonPagedPool);
else
ntStatus = PcNewMiniport((PMINIPORT *) & miniport, MiniportClassId);
}

// Init the port driver and miniport in one go.
//
if (NT_SUCCESS(ntStatus))
{
ntStatus = port->Init(DeviceObject, Irp, miniport, UnknownAdapter,
ResourceList);

if (NT_SUCCESS(ntStatus))
// Register the subdevice (port/miniport combination).
ntStatus = PcRegisterSubdevice(DeviceObject, Name, port);

// We don't need the miniport any more. Either the port has it,
// or we've failed, and it should be deleted.
//
miniport->Release();
}

// Deposit the port interfaces if it's needed.
//
if (NT_SUCCESS(ntStatus))
{
if (OutPortUnknown)
ntStatus = port->QueryInterface(IID_IUnknown, (PVOID *)OutPortUnknown);

if (OutPortInterface)
ntStatus = port->QueryInterface(PortInterfaceId, (PVOID
*)OutPortInterface);
}

if (port)
port->Release();

usbtDebugPrintExit();

return ntStatus;
} // InstallSubDevice

//=============================================================================
NTSTATUS StartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN
PRESOURCELIST ResourceList)
{
/*++

Routine Description:

This function is called by the operating system when the device is
started.
It is responsible for starting the miniports. This code is specific to
the adapter because it calls out miniports for functions that are specific
to the adapter.

Arguments:

DeviceObject - pointer to the driver object

Irp - pointer to the irp

ResourceList - pointer to the resource list assigned by PnP manager

Return Value:

NT status code.

--*/
UNREFERENCED_PARAMETER(ResourceList);

PAGED_CODE();

ASSERT(DeviceObject);
ASSERT(Irp);
ASSERT(ResourceList);

NTSTATUS ntStatus = STATUS_SUCCESS;
PUNKNOWN unknownTopology = NULL;
PUNKNOWN unknownWave = NULL;
PADAPTERCOMMON pAdapterCommon = NULL;
PUNKNOWN pUnknownCommon = NULL;

usbtDebugPrintEnter();

// create a new adapter common object
ntStatus = NewAdapterCommon(&pUnknownCommon, IID_IAdapterCommon, NULL,
NonPagedPool);

if (NT_SUCCESS(ntStatus))
{
ntStatus = pUnknownCommon->QueryInterface(IID_IAdapterCommon, (PVOID *) &
pAdapterCommon);

if (NT_SUCCESS(ntStatus))
{
ntStatus = pAdapterCommon->Init(DeviceObject);

// register with PortCls for power-management services
if (NT_SUCCESS(ntStatus))
ntStatus = PcRegisterAdapterPowerManagement(PUNKNOWN(pAdapterCommon),
DeviceObject);
}
}

// install USBT topology miniport.
if (NT_SUCCESS(ntStatus))
ntStatus = InstallSubdevice(DeviceObject, Irp, L"Topology",
CLSID_PortTopology, CLSID_PortTopology, CreateMiniportTopologyUSBT,
pAdapterCommon, NULL, IID_IPortTopology, NULL, &unknownTopology);

// install USBT wavecyclic miniport.
if (NT_SUCCESS(ntStatus))
ntStatus = InstallSubdevice(DeviceObject, Irp, L"Wave",
CLSID_PortWaveCyclic, CLSID_PortWaveCyclic, CreateMiniportWaveCyclicUSBT,
pAdapterCommon, NULL, IID_IPortWaveCyclic,
pAdapterCommon->WavePortDriverDest(), &unknownWave);

if (unknownTopology && unknownWave)
{
// register wave <=> topology connections
// This will connect bridge pins of wavecyclic and topology
// miniports.
if ((TopologyPhysicalConnections.ulTopologyOut != (ULONG) - 1) &&
(TopologyPhysicalConnections.ulWaveIn != (ULONG) - 1))
ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownTopology,
TopologyPhysicalConnections.ulTopologyOut, unknownWave,
TopologyPhysicalConnections.ulWaveIn);

if (NT_SUCCESS(ntStatus))
if ((TopologyPhysicalConnections.ulWaveOut != (ULONG) - 1) &&
(TopologyPhysicalConnections.ulTopologyIn != (ULONG) - 1))
ntStatus = PcRegisterPhysicalConnection(DeviceObject, unknownWave,
TopologyPhysicalConnections.ulWaveOut, unknownTopology,
TopologyPhysicalConnections.ulTopologyIn);
}

// Release the adapter common object. It either has other references,
// or we need to delete it anyway.
//
if (pAdapterCommon)
pAdapterCommon->Release();

if (pUnknownCommon)
pUnknownCommon->Release();

if (unknownTopology)
unknownTopology->Release();

if (unknownWave)
unknownWave->Release();

usbtDebugPrint((__DBGERROR__, "StartDevice1 WdfDriver: 0x%x WdfDevice: 0x%x
UsbDevice: 0x%x\n", GetMyExtension()->WdfDriver, GetMyExtension()->WdfDevice,
GetMyExtension()->UsbDevice));

// allocate Usb device
WDF_OBJECT_ATTRIBUTES attributes;
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, USB_DEVICE_CONTEXT);
ntStatus = WdfUsbTargetDeviceCreate(GetMyExtension()->WdfDevice,
WDF_NO_OBJECT_ATTRIBUTES,//&attributes,
&GetMyExtension()->UsbDevice);

usbtDebugPrint((__DBGERROR__, "StartDevice2 WdfDriver: 0x%x WdfDevice: 0x%x
UsbDevice: 0x%x\n", GetMyExtension()->WdfDriver, GetMyExtension()->WdfDevice,
GetMyExtension()->UsbDevice));

if (!NT_SUCCESS(ntStatus))
{
usbtDebugPrint((__DBGERROR__,
"*****************************WdfUsbTargetDeviceCreate failed %x!\n",
ntStatus));
return ntStatus;
}

// WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
// WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams);
// ntStatus = WdfUsbTargetDeviceSelectConfig(GetMyExtension()->UsbDevice,
// WDF_NO_OBJECT_ATTRIBUTES,
// &configParams);

if (!NT_SUCCESS(ntStatus))
{
usbtDebugPrint((__DBGERROR__, "**************************
WdfUsbTargetDeviceSelectConfig failed %x!\n", ntStatus));
return ntStatus;
}

// PUSB_DEVICE_CONTEXT usbDeviceContext;
// usbDeviceContext = GetUsbDeviceContext(GetMyExtension()->UsbDevice);
// usbDeviceContext->UsbInterface =
configParams.Types.SingleInterface.ConfiguredUsbInterface;
// UCHAR numberConfiguredPipes =
configParams.Types.SingleInterface.NumberConfiguredPipes;
// usbtDebugPrint((__DBGERROR__, "************************** usb pipes
%d\n", numberConfiguredPipes));


usbtDebugPrintExit();

return ntStatus;
} // StartDevice
#pragma code_seg()
 
Never mind, I already figured it out:

WDF_OBJECT_ATTRIBUTES attributes;
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WDF_DEVICE_INFO);
ntStatus = WdfDeviceMiniportCreate(GetMyExtension()->WdfDriver,
&attributes,
FunctionalDeviceObject,
PhysicalDeviceObject->NextDevice,
PhysicalDeviceObject,
&(GetMyExtension()->WdfDevice));
 
Back
Top