Weird Return on IOcontrol

Ok, i need some help here. I’m doing something wrong in my driver. I try to obtain the name of the USB hostcontroller i’m connected to. I want this because i’m trying to get the USB-device tree. And the tree is needed for my application in my endproduct.

I have made an functions that should get the name for me.

The weird thing is that de returned size is 204 (so it looks like it has found a string of 204 chars) but the returned string in my debugprint is only ''
my debug print looks like this:
“HostCtrlr Name: \ (204 chars)!”
if i try to display char by char i get an BSOD.

Below is my function. I think i’m doing something wrong but i dont see it.

VOID GenerateUSBTree ( PDEVICE_OBJECT Device )
{
PIRP Irp = NULL;
IO_STATUS_BLOCK iostatus;
PIO_STACK_LOCATION stack = NULL;
KEVENT event;
NTSTATUS status = STATUS_SUCCESS;
ULONG ulNewLength = 0;
PUSB_HUB_NAME pHostControllerName, pHostControllerForLength;

pHostControllerForLength = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _USB_HUB_NAME), ‘TAGG’);
// Initialize the event to the non-signalled state
KeInitializeEvent ( &event, NotificationEvent, FALSE );
Irp = IoBuildDeviceIoControlRequest ( IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME,
Device,
NULL, 0,
NULL, 0,
TRUE,
&event,
&iostatus );
if ( !Irp )
{
DebugPrint(“Unable to allocate IRP for getting controller name”);
KeClearEvent ( &event );
return;
}

/*
IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME
Input
Parameters.Others.Argument1 should be a pointer to a USB_HUB_NAME structure that will be filled in with the name of the host controller.
Parameters.Others.Argument2 should be a ULONG specifying the length of the buffer (in bytes) in Parameters.Others.Argument1.
*/

// Set up the stack for the IRP
stack = IoGetNextIrpStackLocation ( Irp );

stack->Parameters.Others.Argument1 = pHostControllerForLength;
stack->Parameters.Others.Argument2 = (PVOID) sizeof(struct _USB_HUB_NAME);

// Send it down and wait for a response
status = IoCallDriver ( Device, Irp );

if ( status == STATUS_PENDING )
{
DebugPrint(“Waiting”);
KeWaitForSingleObject ( &event, Executive, KernelMode, FALSE, NULL );
DebugPrint(“Done Wait!”);
status = iostatus.Status;
}

ulNewLength = pHostControllerForLength->ActualLength;
pHostControllerName = ExAllocatePoolWithTag(NonPagedPool, ulNewLength, ‘TAGG’);

// Re-Initialize the event to the non-signalled state
KeClearEvent ( &event );
KeInitializeEvent ( &event, NotificationEvent, FALSE );
Irp = IoBuildDeviceIoControlRequest ( IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME,
Device,
NULL, 0,
NULL, 0,
TRUE,
&event,
&iostatus );
if ( !Irp )
{
DebugPrint(“Unable to allocate IRP for getting controller name”);
KeClearEvent ( &event );
return;
}

/*
IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME
Input
Parameters.Others.Argument1 should be a pointer to a USB_HUB_NAME structure that will be filled in with the name of the host controller.
Parameters.Others.Argument2 should be a ULONG specifying the length of the buffer (in bytes) in Parameters.Others.Argument1.
*/

// Set up the stack for the IRP
stack = IoGetNextIrpStackLocation ( Irp );

stack->Parameters.Others.Argument1 = pHostControllerName;
stack->Parameters.Others.Argument2 = (PVOID) &ulNewLength;

// Send it down and wait for a response

status = IoCallDriver ( Device, Irp );

if ( status == STATUS_PENDING )
{
DebugPrint(“Waiting”);
KeWaitForSingleObject ( &event, Executive, KernelMode, FALSE, NULL );
DebugPrint(“Done Wait!”);
status = iostatus.Status;
}

if ( !NT_SUCCESS(status) )
{
DebugPrint(“Unable to determine controller name (%s)”, NTStatusToString(status) );
// return;
}

KeClearEvent ( &event );
DebugPrint(“HostCtrlr Name: %s (%d chars)!”, pHostControllerName->HubName, pHostControllerName->ActualLength );
return;
}

Regards,

Rik van der Heijden

The returned value is a WCHAR string not CHAR string. See the
definition of USB_HUB_NAME.

Mark Roddy

On Fri, Mar 13, 2009 at 4:30 AM, wrote:
> Ok, i need some help here. I’m doing something wrong in my driver. I try to obtain the name of the USB hostcontroller i’m connected to. I want this because i’m trying to get the USB-device tree. And the tree is needed for my application in my endproduct.
>
> I have made an functions that should get the name for me.
>
> The weird thing is that de returned size is 204 (so it looks like it has found a string of 204 chars) but the returned string in my debugprint is only ''
> my debug print looks like this:
> “HostCtrlr Name: \ (204 chars)!”
> if i try to display char by char i get an BSOD.
>
> Below is my function. I think i’m doing something wrong but i dont see it.
>
> VOID GenerateUSBTree ( PDEVICE_OBJECT Device )
> {
> ? ?PIRP ? ? ? ? ? ? ? ?Irp = NULL;
> ? ?IO_STATUS_BLOCK ? ? iostatus;
> ? ?PIO_STACK_LOCATION ?stack = NULL;
> ? ?KEVENT ? ? ? ? ? ? ?event;
> ? ?NTSTATUS ? ? ? ? ? ?status = STATUS_SUCCESS;
> ? ?ULONG ? ? ? ? ? ? ? ulNewLength = 0;
> ? ?PUSB_HUB_NAME ? ? ? pHostControllerName, pHostControllerForLength;
>
> ? ?pHostControllerForLength = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _USB_HUB_NAME), ‘TAGG’);
> ? ?// Initialize the event to the non-signalled state
> ? ?KeInitializeEvent ( &event, NotificationEvent, FALSE );
> ? ?Irp = IoBuildDeviceIoControlRequest ( IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Device,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NULL, 0,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NULL, 0,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?TRUE,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&event,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&iostatus );
> ? ?if ( !Irp )
> ? ?{
> ? ? ? ?DebugPrint(“Unable to allocate IRP for getting controller name”);
> ? ? ? ?KeClearEvent ( &event );
> ? ? ? ?return;
> ? ?}
>
> ? ?/
> ? ? ? ?IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME
> ? ? ? ?Input
> ? ? ? ?Parameters.Others.Argument1 should be a pointer to a USB_HUB_NAME structure that will be filled in with the name of the host controller.
> ? ? ? ?Parameters.Others.Argument2 should be a ULONG specifying the length of the buffer (in bytes) in Parameters.Others.Argument1.
> ? ?
/
>
> ? ?// Set up the stack for the IRP
> ? ?stack = IoGetNextIrpStackLocation ( Irp );
>
> ? ?stack->Parameters.Others.Argument1 = pHostControllerForLength;
> ? ?stack->Parameters.Others.Argument2 = (PVOID) sizeof(struct _USB_HUB_NAME);
>
> ? ?// Send it down and wait for a response
> ? ?status = IoCallDriver ( Device, Irp );
>
> ? ?if ( status == STATUS_PENDING )
> ? ?{
> ? ? ? ?DebugPrint(“Waiting”);
> ? ? ? ?KeWaitForSingleObject ( &event, Executive, KernelMode, FALSE, NULL );
> ? ? ? ?DebugPrint(“Done Wait!”);
> ? ? ? ?status = iostatus.Status;
> ? ?}
>
> ? ?ulNewLength = pHostControllerForLength->ActualLength;
> ? ?pHostControllerName = ExAllocatePoolWithTag(NonPagedPool, ulNewLength, ‘TAGG’);
>
> ? ?// Re-Initialize the event to the non-signalled state
> ? ?KeClearEvent ( &event );
> ? ?KeInitializeEvent ( &event, NotificationEvent, FALSE );
> ? ?Irp = IoBuildDeviceIoControlRequest ( IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Device,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NULL, 0,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NULL, 0,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?TRUE,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&event,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&iostatus );
> ? ?if ( !Irp )
> ? ?{
> ? ? ? ?DebugPrint(“Unable to allocate IRP for getting controller name”);
> ? ? ? ?KeClearEvent ( &event );
> ? ? ? ?return;
> ? ?}
>
> ? ?/
> ? ? ? ?IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME
> ? ? ? ?Input
> ? ? ? ?Parameters.Others.Argument1 should be a pointer to a USB_HUB_NAME structure that will be filled in with the name of the host controller.
> ? ? ? ?Parameters.Others.Argument2 should be a ULONG specifying the length of the buffer (in bytes) in Parameters.Others.Argument1.
> ? ?
/
>
> ? ?// Set up the stack for the IRP
> ? ?stack = IoGetNextIrpStackLocation ( Irp );
>
> ? ?stack->Parameters.Others.Argument1 = pHostControllerName;
> ? ?stack->Parameters.Others.Argument2 = (PVOID) &ulNewLength;
>
> ? ?// Send it down and wait for a response
>
> ? ?status = IoCallDriver ( Device, Irp );
>
> ? ?if ( status == STATUS_PENDING )
> ? ?{
> ? ? ? ?DebugPrint(“Waiting”);
> ? ? ? ?KeWaitForSingleObject ( &event, Executive, KernelMode, FALSE, NULL );
> ? ? ? ?DebugPrint(“Done Wait!”);
> ? ? ? ?status = iostatus.Status;
> ? ?}
>
> ? ?if ( !NT_SUCCESS(status) )
> ? ?{
> ? ? ? ?DebugPrint(“Unable to determine controller name (%s)”, NTStatusToString(status) );
> ? ? ? // return;
> ? ?}
>
> ? ?KeClearEvent ( &event );
> ? ?DebugPrint(“HostCtrlr Name: %s (%d chars)!”, pHostControllerName->HubName, pHostControllerName->ActualLength );
> ? ?return;
> }
>
> Regards,
>
> Rik van der Heijden
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

I’ve seen that. But i supposed that i could interpret it als an normal charstring.

And why does deliver a read of for example pHostControllerName->HubName[4] a BSOD on my system?

> I’ve seen that. But i supposed that i could interpret it als an normal charstring.

All strings in Windows kernel are in Unicode, with the exception of things required by the external spec like FAT’s file names.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

xxxxx@gmail.com wrote:

I’ve seen that. But i supposed that i could interpret it als an normal charstring.

Surely you have heard of Unicode?

If you want to DebugPrint a Unicode string, use %S instead of %s.

And why does deliver a read of for example pHostControllerName->HubName[4] a BSOD on my system?

I’m guessing you tried something like this:

DebugPrint(“HostCtrlr Name: %s!”, pHostControllerName->HubName[4] );

Am I right? If so, that’s a simple C gaffe. HubName[4] is a Unicode
character, and you’re passing it to an API that expects an address. Boom.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

xxxxx@gmail.com wrote:

Ok, i need some help here. I’m doing something wrong in my driver. I try to obtain the name of the USB hostcontroller i’m connected to. I want this because i’m trying to get the USB-device tree. And the tree is needed for my application in my endproduct.

No, it’s not. Your marketing department might WANT the device tree, but
it’s not NEEDED.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Yes its needed. I’m needing to enumerate the devices by an specific order. Because i know that for example Device A is connected to Motor A and Device B is connected to MotorB. Both devices are identical but the port/hub and depth in Hubs is needed to know wich device is on wich motor.

And there is also no option to put a name into an device. because the devices needs to be hot-swappable, and the devices must maintain their ‘adress’.

The tree is not going to the outside for the user. Only for internal use in the software.

xxxxx@gmail.com wrote:

Yes its needed. I’m needing to enumerate the devices by an specific order. Because i know that for example Device A is connected to Motor A and Device B is connected to MotorB. Both devices are identical but the port/hub and depth in Hubs is needed to know wich device is on wich motor.

And there is also no option to put a name into an device. because the devices needs to be hot-swappable, and the devices must maintain their ‘adress’.

The tree is not going to the outside for the user. Only for internal use in the software.

This still seems like a broken design, especially if they are
hot-swappable… The RIGHT way to solve this is to have serial numbers
in the devices, then have some kind of configuration utility that
associates a serial number to a motor. If a serial number changes, you
can put up a dialog saying “the configuration has changed, please tell
me which is which”.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Here at the plant this design already worked for over 10 years. And the people who manage the machines don’t know anything about the machine and configuration. The software must take care for it itself. Thats why there was chosen for an static order for the machines. And to enumerate in that way.

> And there is also no option to put a name into an device. because the devices needs to be hot-

swappable

And this means - you cannot distinguish them by using the hub address too.

Also, you cannot say what downstream hub port corresponds to what address - the wiring inside the hub can be any.

If we are speaking about root hub ports, which are on the front and rear sides of the case - then you do not know what is the port number of each of them, this is too motherboard-specific.

To distinguish the 2 motors, you should have some LED on each of them, and the “Identify device” button in your app’s UI. When you press the button in the app, the motor’s LED should blink.

Also you can probably use the motor’s movement instead of LED for the same purpose.

All other schemed are unreliable. The notion of “port number” in USB is a bit virtual :slight_smile:

Note that, in Windows, if your USB devices have the unique ID in their config descriptors - then Windows will remember their settings in the registry and retain them across device unplug/replug, regardless of the particular port it is plugged in. So, relying on USB port numbers for device identification is evil, since it breaks the above scheme.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>itself. Thats why there was chosen for an static order for the machines.

So, if somebody will swap the USB wires in the ports, or attach the USB wire to port it was never attached before - everything will be broken?

Windows and PnP provides you with the more reliable way of doing things, where the set of settings/parameters and the “device number” (device interface number actually, as a “…#1” suffix) itself depends upon unique ID embedded to the device itself, not to the port it is connected too.

This thing is by far lesser prone to break due to human errors - swapping and switching of USB wires will not change anything.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Also not an option. The Application is not an cunsumer application. This is for use on big machines who assamble products like BC574’s. The motherboard is always the same. And the machineconfiguration is also alays static. :wink:

Greetings,

Rik van der Heijden