Unique device ID from kernel to user mode

Hello,

I have upper class device filter driver. I am hooked to IRPs coming to devices. For each coming IRP I need to decide whether to allow it or block according to predefine rule set. This decision making I do in user mode application, which filter driver queries.

Now my question is what device’s unique information should I sent from driver to app, in order that app can gain device info and compare it with rules? I found instance ID as good candidate. In user mode app it can be put to SetupDiXXX functions and device registry properties can be read out. But I can not find reliable documented way to get it in kernel filter IRP hook function. I can send from filter IRP_MN_QUERY_ID with BusQueryInstanceID but it needn’t to return unique Instance Id per machine if bus driver is unable to (http://msdn.microsoft.com/en-us/library/windows/hardware/ff551679(v=vs.85).aspx). Other possibility is to use DeviceNode pointer in _DEVOBJ_EXTENSION struct which is part of DEVICE_OBJECT for PDO, but DeviceNode pointer is not officially documented in _DEVOBJ_EXTENSION. Then from DEVICE_NODE I can get InstancePath, but again DEVICE_NODE struct is not officially documented. So how can I get Instance ID in driver for PDO?

Thanks.

Register a device interface on the stack. The device interface string will be unique and constant across reboots. You don’t to have interface as a way to open a handle, just for the unique string.
much better than reaching into undocumented data structures that change underneath you.

d

debt from my phone


From: xxxxx@centrum.cz
Sent: 10/18/2011 6:14 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Unique device ID from kernel to user mode

Hello,

I have upper class device filter driver. I am hooked to IRPs coming to devices. For each coming IRP I need to decide whether to allow it or block according to predefine rule set. This decision making I do in user mode application, which filter driver queries.

Now my question is what device’s unique information should I sent from driver to app, in order that app can gain device info and compare it with rules? I found instance ID as good candidate. In user mode app it can be put to SetupDiXXX functions and device registry properties can be read out. But I can not find reliable documented way to get it in kernel filter IRP hook function. I can send from filter IRP_MN_QUERY_ID with BusQueryInstanceID but it needn’t to return unique Instance Id per machine if bus driver is unable to (http://msdn.microsoft.com/en-us/library/windows/hardware/ff551679(v=vs.85).aspx). Other possibility is to use DeviceNode pointer in _DEVOBJ_EXTENSION struct which is part of DEVICE_OBJECT for PDO, but DeviceNode pointer is not officially documented in _DEVOBJ_EXTENSION. Then from DEVICE_NODE I can get InstancePath, but again DEVICE_NODE struct is not officially documented. So how can I get Instance ID in driver for PDO?

Thanks.


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

Sorry I don’t know if I understood well. Should I register new interface for PDO in my filter driver and then send this interface string to my user mode app? Then from interface string to cut off interface GUID and the rest will be instance ID? In app I need to have instance ID to call SetupDiGetClassDevs.

On 18-Oct-2011 16:46, xxxxx@centrum.cz wrote:

Sorry I don’t know if I understood well. Should I register new interface for PDO in my filter driver and then send this interface string to my user mode app?

Make an unique interface GUID, *which your app should know*.

Then from interface string to cut off interface GUID and the rest will be instance ID? In app I need to have instance ID to call SetupDiGetClassDevs.

Yes, register this interface on device instances interesting for you.
Then your app can enumerate these instances using SetupDiGetClassDevs,
by that interface GUID. No need to cut off anything, you can use the
whole string as is.
– pa

>Yes, register this interface on device instances interesting for you. Then your app can enumerate these instances using SetupDiGetClassDevs, by that interface GUID. No need to cut off anything, you can use the whole string as is.

So my app enumerates all instances of my interface class. In calling from driver to app I send interface string, so app can match appropriate device instance in output list of SetupDiGetClassDevs.

I found also another solution. Call IoOpenDeviceRegistryKey on PDO to get handle, then ObReferenceObjectByHandle to get object and finally ObQueryNameString to get registry key string like this:
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Enum\USB\Vid_145f&Pid_016f&MI_00\6&b3d006d&0&0000\Device Parameters
then to extract USB\Vid_145f&Pid_016f&MI_00\6&b3d006d&0&0000. InstanceID is part between "\Enum" and last "". Could be this be reliable way?

No, it is not a reliable way. The device instance oath is purposefully NOT exposed to drivers. There are other ways to uniquely id a device, I gave you one of them. Why are you fixated on instance id? Are you storing your rules under this path? If so, you can store your rules under the device interface instance as well, there are documented user and kernel APIs that take a device interface instance and return an HKEY

d

debt from my phone


From: xxxxx@centrum.cz
Sent: 10/19/2011 1:48 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Unique device ID from kernel to user mode

I found also another solution. Call IoOpenDeviceRegistryKey on PDO to get handle, then ObReferenceObjectByHandle to get object and finally ObQueryNameString to get registry key string like this:
\REGISTRY\MACHINE\SYSTEM\ControlSet001\Enum\USB\Vid_145f&Pid_016f&MI_00\6&b3d006d&0&0000\Device Parameters
then to extract USB\Vid_145f&Pid_016f&MI_00\6&b3d006d&0&0000. InstanceID is part between "\Enum" and last "". Could be this be reliable way?


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

In fact I needn’t to be fixated on Instance Id. I need some unique device ID, which filter driver sends to my app and based on this ID app retrieves info for device, compares with rules and replies to driver if to block or allow it.

I tried your solution. I registered interface {e768c1e7-986a-404d-bbf3-748b5dce914a} for USB web camera device in my filter driver. Then from driver I send to my app instance string ??\USB#Vid_145f&Pid_016f&MI_00#6&b3d006d&0&0000#{e768c1e7-986a-404d-bbf3-748b5dce914a} returned by IoRegisterDeviceInterface in driver. My app enumerates all interface instances by that interface GUID and for each one compares interface instance string from SetupDiGetDeviceInterfaceDetail e.g.:
\?\USB#Vid_145f&Pid_016f&MI_00#6&b3d006d&0&0000#{e768c1e7-986a-404d-bbf3-748b5dce914a}
with one coming from my driver. They are nearly identical except the beginning \?\ and ??\ (user mode and kernel mode interface instance strings differ in 2nd. character), so still I can not compare whole strings, but I need to compare only part of strings to find match, so interpret them somehow. If MS changes structure of interface instance strings in future, then I could have problem.

?? Is the km equivalent of \?. When sending the string up to your app, just modify the output buffer (ie the copy) to start with \?

d

debt from my phone


From: xxxxx@centrum.cz
Sent: 10/19/2011 6:54 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Unique device ID from kernel to user mode

In fact I needn’t to be fixated on Instance Id. I need some unique device ID, which filter driver sends to my app and based on this ID app retrieves info for device, compares with rules and replies to driver if to block or allow it.

I tried your solution. I registered interface {e768c1e7-986a-404d-bbf3-748b5dce914a} for USB web camera device in my filter driver. Then from driver I send to my app instance string ??\USB#Vid_145f&Pid_016f&MI_00#6&b3d006d&0&0000#{e768c1e7-986a-404d-bbf3-748b5dce914a} returned by IoRegisterDeviceInterface in driver. My app enumerates all interface instances by that interface GUID and for each one compares interface instance string from SetupDiGetDeviceInterfaceDetail e.g.:
\?\USB#Vid_145f&Pid_016f&MI_00#6&b3d006d&0&0000#{e768c1e7-986a-404d-bbf3-748b5dce914a}
with one coming from my driver. They are nearly identical except the beginning \?\ and ??\ (user mode and kernel mode interface instance strings differ in 2nd. character), so still I can not compare whole strings, but I need to compare only part of strings to find match, so interpret them somehow. If MS changes structure of interface instance strings in future, then I could have problem.


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

>app can gain device info and compare it with rules? I found instance ID as good candidate.

Use PnP device interface symlink name instead, it is accessible in kmode too (at the moment of creation).

Look at Disk/ClassPnP driver source from the WDK, at the code which implements IOCTL_MOUNTDEV_QUERY_ID for removable media disks.


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

>GUID and the rest will be instance ID? In app I need to have instance ID to call

SetupDiGetClassDevs.

No need in the instance ID.


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