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