Hi All,

I've written a bus enumerator driver and a "USB Stack" simulation
driver. My bus enumerator returns the appropriate device IDs in
response to IRP_MN_QUERY_ID PnP calls, and the system brings up the
wizard (first time) to load my USB stack driver. This works great.
However, when my USB stack driver discovers an actual USB device and
does an IoInvalidateDeviceRelations, I get the usual PnP queries about
the PDOs I've created for the USB devices, and I return a Hardware ID
like "USB\Vid_03f0&Pid_1217" and "USB\Vid_03f0&Pid_1217&Rev_0100"
(these are for an HP printer), but the system ignores these names. No
wizard, no device driver accessed. Nothing.

Here's the code for the bus enumerator (which succesfully loads my USB
host controller driver emulator):

NTSTATUS
Bus_FDO_Query_Bus_Relations
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack,
IN PFDO_DEVICE_DATA FdoData
)
{/*_begin( Bus_FDO_Query_Bus_Relations )*/

NTSTATUS status;
ULONG length;
ULONG prevcount;
ULONG numPdosPresent;
PDEVICE_RELATIONS relations;
PDEVICE_RELATIONS oldRelations;
PLIST_ENTRY entry;
PLIST_ENTRY listHead;
PLIST_ENTRY nextEntry;
PPDO_DEVICE_DATA pdoData;

debugf
((
"TBE/Bus_FDO_Query_Bus_Relations: Entry\n"
));


// Tell the plug and play system about all the PDOs.
//
// There might also be device relations below and above this FDO,
// so, be sure to propagate the relations from the upper drivers.
//
// No Completion routine is needed so long as the status is preset
// to success. (PDOs complete plug and play irps with the current
// IoStatus.Status and IoStatus.Information as the default.)

ExAcquireFastMutex (&FdoData->Mutex);

oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
if (oldRelations)
{
prevcount = oldRelations->Count;
if (!FdoData->NumPDOs)
{
// There is a device relations struct already present and
we have
// nothing to add to it, so just call IoSkip and IoCall

ExReleaseFastMutex (&FdoData->Mutex);
return STATUS_SUCCESS;
}
}
else
{
prevcount = 0;
}
debugf
((
"TBE/Bus_FDO_Query_Bus_Relations: prevcount = %d\n",
prevcount
));

// Calculate the number of PDOs actually present on the bus

numPdosPresent = 0;
for
(
entry = FdoData->ListOfPDOs.Flink;
entry != &FdoData->ListOfPDOs;
entry = entry->Flink
)
{
pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
if(pdoData->Present)
{
numPdosPresent++;
}
#if DBG

debugf
((
"TBE/Bus_FDO_Query_Bus_Relations:\n"
"\tFound PDO for '%ws' in list\n",
_ifx( pdoData->HardwareIDs, pdoData->HardwareIDs, L"" )
));


#endif

}
debugf
((
"TBE/Bus_FDO_Query_Bus_Relations: numPdosPresent = %d\n",
numPdosPresent
));

// Need to allocate a new relations structure and add our
// PDOs to it.
//
// ??? Why was the "-1" in the expression below?

length =
sizeof(DEVICE_RELATIONS) +
((numPdosPresent + prevcount /* - 1 */) * sizeof
(PDEVICE_OBJECT)) ;

relations = (PDEVICE_RELATIONS)
ExAllocatePoolWithTag
(
PagedPool,
length,
x('TBEE')
);

if (NULL == relations)
{
// Fail the IRP

ExReleaseFastMutex (&FdoData->Mutex);
Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
Bus_DecIoCount (FdoData);
return status;
}

// Copy in the device objects so far

if (prevcount)
{
RtlCopyMemory
(
relations->Objects,
oldRelations->Objects,
prevcount * sizeof (PDEVICE_OBJECT)
);
}

relations->Count = prevcount + numPdosPresent;

// For each PDO present on this bus add a pointer to the
// device relations buffer, being sure to take out a
// reference to that object. The Plug & Play system will
// dereference the object when it is done with it and free
// the device relations buffer.

for
(
entry = FdoData->ListOfPDOs.Flink;
entry != &FdoData->ListOfPDOs;
entry = entry->Flink
)
{
pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
if(pdoData->Present)
{
relations->Objects[prevcount] = pdoData->Self;
ObReferenceObject (pdoData->Self);
prevcount++;
debugf
((
"TBE/Bus_FDO_Query_Bus_Relations:\n"
"\tDevice Relation PDO for '%ws'\n",
_ifx( pdoData->HardwareIDs, pdoData->HardwareIDs, L""
)
));
}
else
{
pdoData->ReportedMissing = TRUE;
debugf
((
"TBE/Bus_FDO_Query_Bus_Relations:\n"
"\tPDO for '%ws' is not present\n",
_ifx( pdoData->HardwareIDs, pdoData->HardwareIDs, L""
)
));
}
}

debugf
((
"TBE/Bus_FDO_Query_Bus_Relations:\n"
"\t#PDOS present = %d\n"
"\t#PDOs reported = %d\n",
FdoData->NumPDOs,
relations->Count
));

// Replace the relations structure in the IRP with the new
// one.

if (oldRelations)
{
ExFreePool (oldRelations);
}
Irp->IoStatus.Information = (ULONG_PTR) relations;

ExReleaseFastMutex (&FdoData->Mutex);

return STATUS_SUCCESS;

}/*_end( Bus_FDO_Query_Bus_Relations )*/





And here is the code in the USB stack driver which, as best I can tell,
does exactly the same thing:

case IRP_MN_QUERY_DEVICE_RELATIONS:

debugf
(
(
"TUSB/FDO_PnP: QueryDeviceRelations Type: %s\n",
DbgDeviceRelationString
(
IrpStack->Parameters.QueryDeviceRelations.Type
)
)
);

// We don't support any other Device Relations

if
(
BusRelations !=
IrpStack->Parameters.QueryDeviceRelations.Type
)
break;

// Tell the plug and play system about all the PDOs.
//
// There might also be device relations below and above
this FDO,
// so, be sure to propagate the relations from the upper
drivers.
//
// No Completion routine is needed so long as the status is
preset
// to success. (PDOs complete plug and play irps with the
current
// IoStatus.Status and IoStatus.Information as the
default.)

ExAcquireFastMutex (&fdoData->Mutex);

oldRelations = (PDEVICE_RELATIONS)
Irp->IoStatus.Information;
if( oldRelations != NULL )
{
prevcount = oldRelations->Count;
if (!fdoData->NumPDOs)
{
// There is a device relations struct already
present
// and we have nothing to add to it, so just call
// IoSkip and IoCall

ExReleaseFastMutex (&fdoData->Mutex);
break;
}
}
else
{
prevcount = 0;
}

// Calculate the number of PDOs actually present on the
TROYUSB

numPdosPresent = 0;
for
(
entry = fdoData->ListOfPDOs.Flink;
entry != &fdoData->ListOfPDOs;
entry = entry->Flink
)
{
pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA,
Link);
if(pdoData->Present)
{
numPdosPresent++;
}
}

// Need to allocate a new relations structure and add our
// PDOs to it.
//
// ??? Why was the "-1" in the expression below?

length = sizeof(DEVICE_RELATIONS) +
(
(numPdosPresent + prevcount) *
sizeof (PDEVICE_OBJECT)
) /* - 1 */;

relations = (PDEVICE_RELATIONS)
ExAllocatePoolWithTag
(
PagedPool,
length,
x('USB0')
);

if (NULL == relations)
{
// Fail the IRP

ExReleaseFastMutex (&fdoData->Mutex);
Irp->IoStatus.Status = status =
STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
TROYUSB_DecIoCount (fdoData);
return( status );
}

// Copy in the device objects so far

if( prevcount )
{
RtlCopyMemory
(
relations->Objects,
oldRelations->Objects,
prevcount * sizeof (PDEVICE_OBJECT)
);
}

relations->Count = prevcount + numPdosPresent;


// For each PDO present on this TROYUSB add a pointer to
the
// device relations buffer, being sure to take out a
// reference to that object. The Plug & Play system will
// dereference the object when it is done with it and free
// the device relations buffer.


for
(
entry = fdoData->ListOfPDOs.Flink;
entry != &fdoData->ListOfPDOs;
entry = entry->Flink
)
{
pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA,
Link);
if(pdoData->Present)
{
debugf
((
"TUSB/FDO_PnP: QueryDeviceRelations, "
"Adding PDO 0x%x, data:0x%x\n"
" ID:'%ws'\n",
pdoData->Self,
pdoData,
pdoData->HardwareIDs
));
relations->Objects[prevcount] = pdoData->Self;
ObReferenceObject (pdoData->Self);
prevcount++;
}
else
{
pdoData->ReportedMissing = TRUE;
}
}

debugf
(
(
"TUSB/FDO_PnP: #PDOS present = %d #PDOs reported =
%d\n",
fdoData->NumPDOs,
relations->Count
)
);

// Replace the relations structure in the IRP with the new
// one.

if( oldRelations != NULL )
{
ExFreePool (oldRelations);
}
Irp->IoStatus.Information = (ULONG_PTR) relations;

ExReleaseFastMutex (&fdoData->Mutex);

// Set up and pass the IRP further down the stack

Irp->IoStatus.Status = STATUS_SUCCESS;
break;

// In the default case we merely call the next driver.
// We must not modify Irp->IoStatus.Status or complete the
IRP.
}

IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver (fdoData->NextLowerDriver, Irp);
TROYUSB_DecIoCount (fdoData);
debugf(( "TUSB/FDO_PnP: Exit, status=%x\n", status ));
return( status );
}/*_end( TROYUSB_FDO_PnP )*/



Any suggestions?
Thanks,
Randy Hyde

Re: Why Can't I Load a Device Driver? by Eliyas

Eliyas
Sun Sep 11 11:20:08 CDT 2005

My guess is that the device id you are reporting for the usb PDO is probably
malformed. Just to confirm that, try the same id you used for the bus
enumerator and see if the enumeration proceeds any further.

--
--
-Eliyas
This posting is provided "AS IS" with no warranties, and confers no rights.
http://www.microsoft.com/whdc/driver/default.mspx
http://www.microsoft.com/whdc/driver/kernel/KB-drv.mspx



<randyhyde@earthlink.net> wrote in message
news:1126206418.733744.180320@g47g2000cwa.googlegroups.com...
> Hi All,
>
> I've written a bus enumerator driver and a "USB Stack" simulation
> driver. My bus enumerator returns the appropriate device IDs in
> response to IRP_MN_QUERY_ID PnP calls, and the system brings up the
> wizard (first time) to load my USB stack driver. This works great.
> However, when my USB stack driver discovers an actual USB device and
> does an IoInvalidateDeviceRelations, I get the usual PnP queries about
> the PDOs I've created for the USB devices, and I return a Hardware ID
> like "USB\Vid_03f0&Pid_1217" and "USB\Vid_03f0&Pid_1217&Rev_0100"
> (these are for an HP printer), but the system ignores these names. No
> wizard, no device driver accessed. Nothing.
>
> Here's the code for the bus enumerator (which succesfully loads my USB
> host controller driver emulator):
>
> NTSTATUS
> Bus_FDO_Query_Bus_Relations
> (
> IN PDEVICE_OBJECT DeviceObject,
> IN PIRP Irp,
> IN PIO_STACK_LOCATION IrpStack,
> IN PFDO_DEVICE_DATA FdoData
> )
> {/*_begin( Bus_FDO_Query_Bus_Relations )*/
>
> NTSTATUS status;
> ULONG length;
> ULONG prevcount;
> ULONG numPdosPresent;
> PDEVICE_RELATIONS relations;
> PDEVICE_RELATIONS oldRelations;
> PLIST_ENTRY entry;
> PLIST_ENTRY listHead;
> PLIST_ENTRY nextEntry;
> PPDO_DEVICE_DATA pdoData;
>
> debugf
> ((
> "TBE/Bus_FDO_Query_Bus_Relations: Entry\n"
> ));
>
>
> // Tell the plug and play system about all the PDOs.
> //
> // There might also be device relations below and above this FDO,
> // so, be sure to propagate the relations from the upper drivers.
> //
> // No Completion routine is needed so long as the status is preset
> // to success. (PDOs complete plug and play irps with the current
> // IoStatus.Status and IoStatus.Information as the default.)
>
> ExAcquireFastMutex (&FdoData->Mutex);
>
> oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
> if (oldRelations)
> {
> prevcount = oldRelations->Count;
> if (!FdoData->NumPDOs)
> {
> // There is a device relations struct already present and
> we have
> // nothing to add to it, so just call IoSkip and IoCall
>
> ExReleaseFastMutex (&FdoData->Mutex);
> return STATUS_SUCCESS;
> }
> }
> else
> {
> prevcount = 0;
> }
> debugf
> ((
> "TBE/Bus_FDO_Query_Bus_Relations: prevcount = %d\n",
> prevcount
> ));
>
> // Calculate the number of PDOs actually present on the bus
>
> numPdosPresent = 0;
> for
> (
> entry = FdoData->ListOfPDOs.Flink;
> entry != &FdoData->ListOfPDOs;
> entry = entry->Flink
> )
> {
> pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
> if(pdoData->Present)
> {
> numPdosPresent++;
> }
> #if DBG
>
> debugf
> ((
> "TBE/Bus_FDO_Query_Bus_Relations:\n"
> "\tFound PDO for '%ws' in list\n",
> _ifx( pdoData->HardwareIDs, pdoData->HardwareIDs, L"" )
> ));
>
>
> #endif
>
> }
> debugf
> ((
> "TBE/Bus_FDO_Query_Bus_Relations: numPdosPresent = %d\n",
> numPdosPresent
> ));
>
> // Need to allocate a new relations structure and add our
> // PDOs to it.
> //
> // ??? Why was the "-1" in the expression below?
>
> length =
> sizeof(DEVICE_RELATIONS) +
> ((numPdosPresent + prevcount /* - 1 */) * sizeof
> (PDEVICE_OBJECT)) ;
>
> relations = (PDEVICE_RELATIONS)
> ExAllocatePoolWithTag
> (
> PagedPool,
> length,
> x('TBEE')
> );
>
> if (NULL == relations)
> {
> // Fail the IRP
>
> ExReleaseFastMutex (&FdoData->Mutex);
> Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
> IoCompleteRequest (Irp, IO_NO_INCREMENT);
> Bus_DecIoCount (FdoData);
> return status;
> }
>
> // Copy in the device objects so far
>
> if (prevcount)
> {
> RtlCopyMemory
> (
> relations->Objects,
> oldRelations->Objects,
> prevcount * sizeof (PDEVICE_OBJECT)
> );
> }
>
> relations->Count = prevcount + numPdosPresent;
>
> // For each PDO present on this bus add a pointer to the
> // device relations buffer, being sure to take out a
> // reference to that object. The Plug & Play system will
> // dereference the object when it is done with it and free
> // the device relations buffer.
>
> for
> (
> entry = FdoData->ListOfPDOs.Flink;
> entry != &FdoData->ListOfPDOs;
> entry = entry->Flink
> )
> {
> pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
> if(pdoData->Present)
> {
> relations->Objects[prevcount] = pdoData->Self;
> ObReferenceObject (pdoData->Self);
> prevcount++;
> debugf
> ((
> "TBE/Bus_FDO_Query_Bus_Relations:\n"
> "\tDevice Relation PDO for '%ws'\n",
> _ifx( pdoData->HardwareIDs, pdoData->HardwareIDs, L""
> )
> ));
> }
> else
> {
> pdoData->ReportedMissing = TRUE;
> debugf
> ((
> "TBE/Bus_FDO_Query_Bus_Relations:\n"
> "\tPDO for '%ws' is not present\n",
> _ifx( pdoData->HardwareIDs, pdoData->HardwareIDs, L""
> )
> ));
> }
> }
>
> debugf
> ((
> "TBE/Bus_FDO_Query_Bus_Relations:\n"
> "\t#PDOS present = %d\n"
> "\t#PDOs reported = %d\n",
> FdoData->NumPDOs,
> relations->Count
> ));
>
> // Replace the relations structure in the IRP with the new
> // one.
>
> if (oldRelations)
> {
> ExFreePool (oldRelations);
> }
> Irp->IoStatus.Information = (ULONG_PTR) relations;
>
> ExReleaseFastMutex (&FdoData->Mutex);
>
> return STATUS_SUCCESS;
>
> }/*_end( Bus_FDO_Query_Bus_Relations )*/
>
>
>
>
>
> And here is the code in the USB stack driver which, as best I can tell,
> does exactly the same thing:
>
> case IRP_MN_QUERY_DEVICE_RELATIONS:
>
> debugf
> (
> (
> "TUSB/FDO_PnP: QueryDeviceRelations Type: %s\n",
> DbgDeviceRelationString
> (
> IrpStack->Parameters.QueryDeviceRelations.Type
> )
> )
> );
>
> // We don't support any other Device Relations
>
> if
> (
> BusRelations !=
> IrpStack->Parameters.QueryDeviceRelations.Type
> )
> break;
>
> // Tell the plug and play system about all the PDOs.
> //
> // There might also be device relations below and above
> this FDO,
> // so, be sure to propagate the relations from the upper
> drivers.
> //
> // No Completion routine is needed so long as the status is
> preset
> // to success. (PDOs complete plug and play irps with the
> current
> // IoStatus.Status and IoStatus.Information as the
> default.)
>
> ExAcquireFastMutex (&fdoData->Mutex);
>
> oldRelations = (PDEVICE_RELATIONS)
> Irp->IoStatus.Information;
> if( oldRelations != NULL )
> {
> prevcount = oldRelations->Count;
> if (!fdoData->NumPDOs)
> {
> // There is a device relations struct already
> present
> // and we have nothing to add to it, so just call
> // IoSkip and IoCall
>
> ExReleaseFastMutex (&fdoData->Mutex);
> break;
> }
> }
> else
> {
> prevcount = 0;
> }
>
> // Calculate the number of PDOs actually present on the
> TROYUSB
>
> numPdosPresent = 0;
> for
> (
> entry = fdoData->ListOfPDOs.Flink;
> entry != &fdoData->ListOfPDOs;
> entry = entry->Flink
> )
> {
> pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA,
> Link);
> if(pdoData->Present)
> {
> numPdosPresent++;
> }
> }
>
> // Need to allocate a new relations structure and add our
> // PDOs to it.
> //
> // ??? Why was the "-1" in the expression below?
>
> length = sizeof(DEVICE_RELATIONS) +
> (
> (numPdosPresent + prevcount) *
> sizeof (PDEVICE_OBJECT)
> ) /* - 1 */;
>
> relations = (PDEVICE_RELATIONS)
> ExAllocatePoolWithTag
> (
> PagedPool,
> length,
> x('USB0')
> );
>
> if (NULL == relations)
> {
> // Fail the IRP
>
> ExReleaseFastMutex (&fdoData->Mutex);
> Irp->IoStatus.Status = status =
> STATUS_INSUFFICIENT_RESOURCES;
> IoCompleteRequest (Irp, IO_NO_INCREMENT);
> TROYUSB_DecIoCount (fdoData);
> return( status );
> }
>
> // Copy in the device objects so far
>
> if( prevcount )
> {
> RtlCopyMemory
> (
> relations->Objects,
> oldRelations->Objects,
> prevcount * sizeof (PDEVICE_OBJECT)
> );
> }
>
> relations->Count = prevcount + numPdosPresent;
>
>
> // For each PDO present on this TROYUSB add a pointer to
> the
> // device relations buffer, being sure to take out a
> // reference to that object. The Plug & Play system will
> // dereference the object when it is done with it and free
> // the device relations buffer.
>
>
> for
> (
> entry = fdoData->ListOfPDOs.Flink;
> entry != &fdoData->ListOfPDOs;
> entry = entry->Flink
> )
> {
> pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA,
> Link);
> if(pdoData->Present)
> {
> debugf
> ((
> "TUSB/FDO_PnP: QueryDeviceRelations, "
> "Adding PDO 0x%x, data:0x%x\n"
> " ID:'%ws'\n",
> pdoData->Self,
> pdoData,
> pdoData->HardwareIDs
> ));
> relations->Objects[prevcount] = pdoData->Self;
> ObReferenceObject (pdoData->Self);
> prevcount++;
> }
> else
> {
> pdoData->ReportedMissing = TRUE;
> }
> }
>
> debugf
> (
> (
> "TUSB/FDO_PnP: #PDOS present = %d #PDOs reported =
> %d\n",
> fdoData->NumPDOs,
> relations->Count
> )
> );
>
> // Replace the relations structure in the IRP with the new
> // one.
>
> if( oldRelations != NULL )
> {
> ExFreePool (oldRelations);
> }
> Irp->IoStatus.Information = (ULONG_PTR) relations;
>
> ExReleaseFastMutex (&fdoData->Mutex);
>
> // Set up and pass the IRP further down the stack
>
> Irp->IoStatus.Status = STATUS_SUCCESS;
> break;
>
> // In the default case we merely call the next driver.
> // We must not modify Irp->IoStatus.Status or complete the
> IRP.
> }
>
> IoSkipCurrentIrpStackLocation (Irp);
> status = IoCallDriver (fdoData->NextLowerDriver, Irp);
> TROYUSB_DecIoCount (fdoData);
> debugf(( "TUSB/FDO_PnP: Exit, status=%x\n", status ));
> return( status );
> }/*_end( TROYUSB_FDO_PnP )*/
>
>
>
> Any suggestions?
> Thanks,
> Randy Hyde
>