The Uniqueness of IOCTL_MOUNTDEV_QUERY_UNIQUE_ID - winapi

The documentation on IOCTL_MOUNTDEV_QUERY_UNIQUE_ID is a bit confusing... exactly what kind of ID should be returned in the MOUNTDEV_UNIQUE_ID structure?
The documentation for
typedef struct _MOUNTDEV_UNIQUE_ID {
USHORT UniqueIdLength;
UCHAR UniqueId[1];
} MOUNTDEV_UNIQUE_ID, *PMOUNTDEV_UNIQUE_ID;
says:
UniqueIdLength
Contains the length of unique volume ID.
UniqueId
Contains the unique volume ID. The format for unique volume names is "\??\Volume{GUID}\", where GUID is a globally unique identifier that identifies the volume.
However, there's something weird here: What should be the exact format of UniqueId? If it's meant to be in the \??\Volume{GUID}\ format, then what's the point of the UniqueIdLength field -- aren't they all the same size? Otherwise, what format does the device ID need to be in?
Furthermore, is this a device ID or a volume ID? In other words, is this supposed to be unique per medium (e.g. CD) or per device (CD drive)?

This kind of struct is pretty common in MS APIs - the UniqueID[1] variable is just a placeholder, in reality it's used as a UniqueId[UniqueIdLength] variable.
The ID is unique both per medium and per device - it depends on whether you're talking to a volume driver or a device class driver. The ID is intended to identify "something that can be mounted" - so e.g. a CD-ROM device, a fixed disk partition or an unpartitioned removable disk. The mount manager uses the ID a.o. to lookup where this particular volume was mounted before, and remount it at the same point.

From MSDN
Maybe there is misunderstanding about this structure.
I called DeviceIoControl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID) and got a string as the similar format to Device Interface Path, but it is just different of the prefix 4 characters, and then it saved in registry \HKLM\SYSTEM\MountedDevices.

MOUNTDEV_UNIQUE_ID is acquired upon a volume arrival notification where mountmgr!MountMgrMountedDeviceArrival invokes mountmgr!QueryDeviceInformation, which sends a IOCTL_MOUNTDEV_QUERY_UNIQUE_ID IRP to the volume PDO stack, which volmgr picks up, and I'm not sure what routine it is but in XP's ftdisk it was ftdisk!FtpQueryUniqueIdBuffer that determined whether to set the UniqueID member to a GPT partition GUID, a MBR signature + offset, or the symbolic link like STORAGE#RemovableMedia.... The symbolic link is based on the name of devnode that the volume PDO is part of, and the symbolic link was generated by IoRegisterDeviceInterface, which was then stored in the volume extension before alerting mountmgr of the volume arrival in the first place (alerting is done by IoSetDeviceInterfaceState Enable). On Windows 7 the volume PDO devnode name is STORAGE\Volume\_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_B lade&Rev_1.27#4C530399920812105355&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}, the symbolic link is STORAGE#Volume#_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_Blade&Rev_1.27#4C530399920812105355&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b} but the MountedDevices data is _??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_Blade&Rev_1.27#4C530399920812105355&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}. The symbolic link that is created is always to the volume PDO name, because the volume PDO is supplied to the call, which is \Device\HarddiskVolumeX.
FtpQueryUniqueIdBuffer uses the MBR signature and partition offset if it's an MBR disk, and uses the GPT partition GUID if it's a GPT disk, and uses the symbolic link if it's neither, which tends to be a regular USB drive mass storage volume that doesn't have a boot sector, and ftdisk considers a disk without a boot sector to be a 'superfloppy', so it looks for that flag on the volume extension. So that's how unique it is, MBR signature and GPT GUID uniqueness speak for themselves, but the symlink doesn't so I'll elaborate: it contains the DIID of the USBSTOR device, which includes the USB serial number, or if it doesn't have one, a system wide unique number determine according to the following scheme.
Mountmgr creates further symbolic links between the drive letter and volume device name, and the volume GUID and the volume device name, and then puts them in the MountedDevices database but uses the unique ID instead of the volume device name. The volume GUID \??\Volume{GUID}\ it generates using ExUuidCreate. IOCTL_MOUNTMGR_QUERY_POINTS shows each symbolic link for a mounted device, so it will show \DosDevices\C: -> \Device\HarddiskVolumeX and \??\Volume{GUID}\ -> \Device\HarddiskVolumeX and the unique ID of the mounted device and the name of the mounted device. It does not however show the symbolic link to \Device\HarddiskVolumeX created by IoRegisterDeviceInterface because the symbolic link wasn't created by mount manager, so it doesn't know about it.

Related

How to identify a HID after it's moved to a different port on Windows

I'm on Windows and am trying to store calibration data for game controllers connected via USB and am trying to find a value which uniquely identifies them in a port independent way.
There is the HidD_GetSerialNumberString function but i've read here that it's uncommon for devices to have serial numbers and indeed when i try to read one f.e. from a PS4 controller HidD_GetSerialNumberString returns FALSE and GetLastError returns ERROR_INVALID_PARAMETER.
Is there any other data available which can be accessed to achieve this?
You can try to use instance ID for your HID device (call CM_Get_Device_Interface_Property with device interface path and DEVPKEY_Device_InstanceId property and use string after last & char). It should be unique and persistent per system restarts. But it is not guaranteed if serial number is not provided (in this case instance ID will be different if device is plugged into different usb port)...
More info on this here: https://stackoverflow.com/a/56885175/1795050

Getting USB data for OS X /dev/tty.* entry

I am trying to (programatically in Java, though running external scripts is a possibility) get the USB idProduct, idVendor and ideally the string descriptors for the manufacturer and product for a USB device.
The device has (and it is all I am provided with in the beginning) a /dev/tty.usbmodem entry, and I need some way to reliably map that back to the USB information, but I can't find anything that relates one to the other (or rather I don't know where to look).
The device in question has the /dev entry of:
crw-rw-rw- 1 root wheel 10, 2 18 Jul 15:08 /dev/tty.usbmodem9f31
system_profiler gives me the following USB information for the device:
<dict>
<key>_name</key>
<string>Stk500v2</string>
<key>a_product_id</key>
<string>0xa662</string>
<key>b_vendor_id</key>
<string>0x0403 (Future Technology Devices International Limited)</string>
<key>c_bcd_device</key>
<string> 1.80</string>
<key>e_device_speed</key>
<string>full_speed</string>
<key>f_manufacturer</key>
<string>www.cpustick.com</string>
<key>g_location_id</key>
<string>0x9f300000</string>
<key>h_bus_power</key>
<string>500</string>
<key>j_bus_power_used</key>
<string>500</string>
</dict>
I can see the prefix of 0x9f3 for the g_location_id matching the start of the dev entry's suffix of 9f31, but I don't know a) how reliable that would be, and b) what the "1" would represent at the end, and how that would be affected by having multiple of the same device on the same bus, and how you would differentiate between them.
I have other devices I need to do this with as well, and they don't all follow the same naming rules. One of them uses the USB serial number field for the suffix. Other potential ones (that I don't have control over at all) could do it differently again I guess.
So basically I need some way of mapping the textual device name /dev/tty.whatever to a physical USB device entry that I can then pull the data I need from. On Linux I do it by traversing the /sys tree from /sys/class/tty through to /sys/devices/pci...blahblah/usb[x]/wherever but I can find no similar facility on OS X.
You can use IOKit to get the USB vendor ID and product ID of a serial port on Mac OS X.
Also, there is a library called libserialport that you could use:
http://sigrok.org/wiki/Libserialport

Get Volume GUID from Partition number in windows

I am looking for some kind help regarding below query.
I am trying to write (using WriteFile()) to a windows disk partition within a Windows PE environment by opening a disk handle and seeking to the partition starting offset.
WriteFile() is returning error code 5 (ACCESS DENIED).
I believe it is because the application has not locked the volume before writing to the volume.
My application has only the partition number as input. The ioctl FSCTL_LOCK_VOLUME needs a volume handle which is returned by CreateFile() and this needs a volume GUID as parameter.
So how do I get the volume GUID via the partition number?
Regards.

Windows HID Device Name Format

There are various ways to retrieve the Windows "Device Name" of a HID device, GetRawInputDeviceInfo with RIDI_DEVICENAME being one way to do it.
Given the example name:
\?\HID#VID_FEED&PID_DEAD#6&3559c8ea&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}
I'm wondering if there is any documentation whatsoever on what is what in this string?
\?\HID#VID_AAAA&PID_BBBB#C&DDDDDD&E&FFFF#{GUID}
So the obvious ones are A(VID), B(PID) and the GUID on the end. What I'm wondering is what EXACTLY are C, D, E and F?
It seems that C and D are unique even if you plug in two of the exact same HID devices which is great for my problem, but I'd feel more comfortable if I could know exactly how this is determined on a per OS basis, or at least that it follows some known format.
I have been googling like a madman trying to figure this out, am I missing something obvious?
Thanks in advance
According to a similar MSDN post, the value represents a unique device instance ID:
the device instance ID is unique and constant for the physical
location the device is plugged into, but it is also opaque and should
not be parsed. that means it can be used for string comparison, but
not for interpretation.
It is actually device interface instance id (symbolic link name). And yes, its unique and persists across system restart. Some details also here.
You can use CM_Get_Device_Interface_Property or SetupDiGetDeviceInterfaceProperty on interface instance id with DEVPKEY_Device_InstanceId to get device instance id (one device can have multiple interfaces).
In your example - you have a HID device. Its device id format is described here.
Info on general USB devices id format is here.
After you have device instance id you can use CM_Get_DevNode_Property or SetupDiGetDeviceProperty with DEVPKEY_NAME to get localized friendly name of a device (which is shown in Device Manager).
To sum up:
\\?\HID#VID_203A&PID_FFFC&MI_01#7&2de99099&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd} - is device interface id (also referred as "device interface path" or "device name" in docs). This is path in virtual device file system.
{378de44c-56ef-11d1-bc8c-00a0c91405dd} - device interface class guid (GUID_DEVINTERFACE_MOUSE in this case. It determines which IOCTLs can be called on this device. IOCTL_MOUSE_QUERY_ATTRIBUTES in this case)
HID\VID_203A&PID_FFFC&MI_01\7&2de99099&0&0000 - is device instance id
NOTE: exact device interface id format is not documented, each device interface can generate file name it want. I don't recommend you to parse it - it could be changed in later Windows version, better aquire device instance id - it is documents at least.

ext4 pointers from in-memory inode

I'm trying to retrieve in a kernel module the direct/indirect etc addresses in an ext4 file system inode. I understand that I need to look into ext_inode_info struct (I do this via container_of using the relevant vfs_inode).
But to which field am I supposed to look into?
Where can I find for example the first direct pointer? I thought it was stored in i_data array (it is in ext3_inode_info).
But for an ext4 inode when I examine the first entry in i_data, I get a sector address that is not remotely similar to the real sector holding the address of the first data block.
Any help will be appreciated.
==EDIT==
ok, so I seemed to have understood the basic problem. I have an extent-based ext4 file system. Wasn't aware of this change, and that this is enabled by default. So is there a simple way to extract the physical addresses of blocks by offset? I'm trying again as verification to look at the first physical block (logical 0), by looking at the first extent, but I get some gibberish numbers (though consistent and unique for every inode/file, so some progress was made).

Resources