Device unique ID (hardware serial ID vs volume serial ID) Windows - c++

I've been messing around with the Windows API (I've been told to stay away from WMI as it's unreliable), trying to get device serial numbers for my HDs and attached USB devices. But it seems that the majority of the functionality is designed to access Volume Serial IDs and not the actual manufacturer's unique serial number of the device. These Volume Serials seem to be calculated based on the last date and time the drive was formatted.
Well, this won't do for the application I want to develop - if a device is formatted and the same info copied to that device, then when they start my application, it needs to be able to treat the internal info (identified via the serial number) as belonging to that device, which if I use the Volume Serial ID will be lost.
I looked at the code for http://www.winsim.com/diskid32/ but that seems to just return the volume serial ID. EDIT: Actually, this value is different to the volume serial, as you can see in the below output:
Vol Name is Hellblazer
Vol Serial is 3358611714
Max Filelength is 255 chars
Filesystem is NTFS
202020202020202020205a204339464a38305345
Z9CJF08ES
The serial in the first bit of code (using GetVolumeInformation) is the decimal version of the hexidecimal value you get for the drive when typing 'vol' in the command prompt - so this is the Volume serial. The below number is what gets returned from DeviceIoControl(hwDrive, IOCTL_STORAGE_QUERY_PROPERTY.... It's the same ID the programmer of diskid32 gets for my drive, yet different to the actual serial below. Perplexing.
For USB drives:
Using a PSP_DEVICE_INTERFACE_DETAIL_DATA struct, I can get access to the GUID device enumeration, which looks like this for my USB drive:
\?\usbstor#disk&ven_toshiba&prod_mk5059gsxp&rev_gn00#203216187542__&0#{53f563
07-b6bf-11d0-94f2-00a0c91efb8b}
This part of that device information is the serial, supposedly:
203216187542__
Additionally, I loaded up diskpart.exe (a cmd line partition program) and had a look at the drive details of my system HDD and an external USB drive and neither of them matched any of the values I'm getting above:
TOSHIBA MK5055GSXF ATA Device Disk ID: 00005B9E
TOSHIBA MK5059GSXP USB Device Disk ID: 51260D08
What could be going on here? Where, and how can I gain access to the actual manufacture serial number of the actual device?
Any help would be greatly appreciated!

Related

Detecting USB Storage connection using WINAPI

I'm basically trying to detect a simple USB detection and retrieve certain information from it.
Doing so, for a regular USB FLASH drive is quite simple, as most of the MSDN samples show.
HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
hDevNotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
and later on, wait for a WM_DEVICECHANGE message with DBT_DEVICEARRIVAL
i actually get 2 sequential messages:
dbcc_name of the first message :
\\?\USB#VID_0781&PID_5597#4C530001210518100555#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
dbcc_name of the second message:
\\?\USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_Glide_3.0&Rev_1.00#4C530001210518100555&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
From this one, i can actually retrieve the friendaly name and so on.
Now, my problem occurs when i try to do the same with phone connection.
When i plug my phone using a regular USB cable, i get
\\?\USB#VID_18D1&PID_4EE2#00c5c6f0839a25d4#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
SetupDiGetDeviceRegistryProperty with SPDRP_DEVICEDESC returns USB Composite Device
And when i grant file transfer storage permissions on my mobile, i get a second message with:
\\?\USB#VID_18D1&PID_4EE2#00c5c6f0839a25d4#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
without a friendly name, using the
SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData,
SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize)
function.
So couple of questions here:
How does windows recognize this as a mobile device, and even shows its name in the notifications bar (Nexus 5x, Select to choose what happens with this device)?
Lets say i would like to copy certain files from or to it. how do i get device handle or device path for WriteFile / CreateFile
How come GetLogicalDrivesStrings retrieves a new drive("c:\\\0d:\\\0") for a regular USB flash drive but doesn't do the same for mobile connection?
Look at the dialog on your phone. You probably picked an option named "MTP". This is a file sharing protocol. On the other hand, the USB stick uses a block storage protocol. That's why you get the USBSTOR announcement.
Block storage allows for dumb devices, and requires intelligence on the host (Windows). It's just a few million 512-byte sectors. Turning that into files is the responsibility of the FAT (or NTFS) driver.
Since block storage uses the FAT driver, it gets a drive letter just like internal hard disks, and can be accessed via CopyFile. Since MTP devices aren't managed by the file system, they don't have drive letters.
Why do mobile phones use MTP then? The big advantage is that MTP allows the phone to be much more in control. It can decide on a file by file basis whether to show it to the USB host.
(Disclosure: you can do that with FAT as well, but my former employer may still have a patent on that. Search for "Data storage access device patent TomTom" if this matters to you)
when a smartphone is connected it appears at first as a SCSI device. then USB protocol supports several attributes (beside vendorID and productID) from that an operating system can get informations like the device name (NEXUS 5x,...) for this especially the attribute fields manufacturer and product
so windows does not 'know' it is a smartphone
the following is the output of udevadm info -a -p /sys/class/scsi_host/... on linux:
looking at device '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3:1.0/host42/scsi_host/host42':
KERNEL=="host42"
SUBSYSTEM=="scsi_host"
DRIVER==""
ATTR{unique_id}=="0"
ATTR{host_busy}=="0"
ATTR{cmd_per_lun}=="1"
ATTR{can_queue}=="1"
ATTR{sg_tablesize}=="65535"
ATTR{sg_prot_tablesize}=="0"
ATTR{unchecked_isa_dma}=="0"
ATTR{proc_name}=="usb-storage"
ATTR{state}=="running"
ATTR{supported_mode}=="Initiator"
ATTR{active_mode}=="Initiator"
ATTR{prot_capabilities}=="0"
ATTR{prot_guard_type}=="0"
looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3:1.0/host42':
KERNELS=="host42"
SUBSYSTEMS=="scsi"
DRIVERS==""
looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3:1.0':
KERNELS=="1-3:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="usb-storage"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bNumEndpoints}=="02"
ATTRS{bInterfaceClass}=="08"
ATTRS{bInterfaceSubClass}=="06"
ATTRS{bInterfaceProtocol}=="50"
ATTRS{supports_autosuspend}=="1"
ATTRS{interface}=="Mass Storage"
looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-3':
KERNELS=="1-3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{configuration}==""
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bmAttributes}=="c0"
ATTRS{bMaxPower}=="500mA"
ATTRS{urbnum}=="195"
ATTRS{idVendor}=="feed"
ATTRS{idProduct}=="2002"
ATTRS{bcdDevice}=="ffff"
ATTRS{bDeviceClass}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bNumConfigurations}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{speed}=="480"
ATTRS{busnum}=="1"
ATTRS{devnum}=="34"
ATTRS{devpath}=="3"
ATTRS{version}==" 2.00"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{authorized}=="1"
ATTRS{manufacturer}=="MediaTek"
ATTRS{product}=="X5"
ATTRS{serial}=="0123456789ABCDEF"
then it depends what function you activate on your smartphone. if you want to activate tethering windows will get notified by the android device and load the RNDIS driver. the notification mechanism is a rest of the USB connection
if you want to write or read files from the androids mass storage you have to activate the mass storage option and windows will get notified and 'mount' the android as a file system
so an android has implemented multiple interfaces / USB device classes in its USB structure and the user has to choose which interface to activate (tethering -> RNDIS, storage -> USB mass storage class,...)
this is also the reason why no new drive c:\\\0d:\\\0 appears when you connect the android to windows. At first the android appears as a SCSI device with no specified function (SCSI Target)
For communication with the android in SCSI mode see http://www.stackoverflow.com/questions/3316284/sending-a-specific-scsi-command-to-a-scsi-device-in-windows
if you want to read or write the phones (internal, SD card) activate the mass storage option and you can use the normal USB mass storage interface (like USB memory stick)
for getting the dbcc_name maybe see http://www.stackoverflow.com/questions/2208722/how-to-get-friendly-device-name-from-dev-broadcast-deviceinterface-and-device-in

Converting multipath devices to its equivalent physical disk

In linux/unix I want to get the physical disk name given the multipathed device name.
For Eg: if the multipath device name is /dev/mpath/mpath0 where mpath0 is the multipathed device and is mapped to say disk /dev/sdc. Here when I input mpath0 I want sdc as the output.
When you do a 'multipath -ll' you get a list of multipathed devices and its corresponding physical disks but if the list is too large its difficult to parse and get the right information. Is there a way to do this programmatically in C or C++ ?
Thanks

Windows C++: Get driver device ID

I'm writing a C++ program that should check Driver Device ID.
My input is the driver name as it should appear in the Device Manager.
I tried to Google, and I figured that:
I could get the driver pointer using this sample code http://msdn.microsoft.com/en-us/library/ms682619%28VS.85%29.aspx
I should use IRP_MN_QUERY_ID function to get the device ID- http://msdn.microsoft.com/en-us/library/windows/hardware/ff551679(v=vs.85).aspx.
However, I couldn't find any examples or code snippets for how to actually do it, and how those two functions connect?
I have no experience in drivers, sample code will be very appreciated...
On windows there are no device ids (as name =) ). Device matches by hardware id and compatible ids. From this ids system generate instance id - uniquely identifies the device on specific port on bus. You can get hardware/compatible id without sending IRPs, by using IoGetDeviceProperty function (http://msdn.microsoft.com/en-us/library/windows/hardware/ff549203(v=vs.85).aspx), it`s more easy than roll up your own IRP.

Duplicate USB virtual serial ports being created - what might cause this?

I've got a strange problem with some code I inherited from another programmer who's left the company, and need some guidance on how to even begin to solve it.
The problem is this - on a semi-regular basis, we are finding that duplicate USB virtual comm ports are being created. For example, on my PC, when I view the Ports in Device Manager, and select "View Hidden Devices", I have two entries for the same device - one on COM6, and one on COM8.
Unfortunately, we cannot reliably re-create the problem. We suspect it may happen when someone quickly disconnects and reconnects the USB cable when our software is running, but that needs to be confirmed.
As far as I can tell, the code was written assuming that no one would ever unplug a cable. I see no logic whatsoever to detect this condition after the SW is started. And it fails when you re-plug the cable - silently generating read and write errors even after the cable is plugged back in. You have to restart the program before it will work again.
I have very little serial and USB experience, and am at a bit of a loss as to how to even get started on fixing this.
Can anyone suggest why this might be happening?
Misc. details, in case they might be relevant:
USB serial code is in a C++ DLL
VS2008
FTDIBUS USB/Serial drivers
Windows XP and Win7
Screen shot of duplicate Registry entries (note the value of the selected key!)
As explained on Raymond Chen's blog, the Old New Thing, here, and by commenters above:
https://blogs.msdn.com/b/oldnewthing/archive/2004/11/10/255047.aspx
To summarize:
Devices which are unplugged and plugged in again are tracked so they are not treated as a new device every time.
Usually this uses the device serial number to detect whether a device is the same one.
However not every device has a serial number. These devices are treated as the same device only if they have the same vendor ID and product ID and are plugged into the same port. If they are plugged into a different port they are treated as a different device.
Some manufacturers do not understand the word "Serial" in "Serial Number" and give all devices the same number instead of giving them numbers serially... To cope with this there is a registry setting which can be used to force these devices to be treated as if they have no serial number.
Therefore, if a device with no serial number or which is flagged in the Windows Registry as having duplicate serial numbers is plugged in to a serial port it has not been plugged into before, it will be treated as a new device rather than a reconnection of an old device. This will result in "Ghost" devices as you describe.
Some FTDI devices are specifically called out as having this problem by the manufacturer:
http://www.ftdichip.com/Support/Knowledgebase/index.html?ignorehardwareserialnumber.htm

how to get USB harddisk physical serial number ,vendor id ,product id

I would like to get USB hard disk serial number ,vendor id ,product id without WMI,I found the
USBSTOR\Disk&Ven_ST932042&Prod___5VJ101RR&Rev_SDM1\222256410122&0
the serial number is 5VJ101RR but it show in the product id which is wrong,
how can i get the correct USB disk vendor id,product id, serial number
My develop environment is visual c++ 2008
thanks
A simple way to get VID and PID would be to load the devices INI file from %WINDOWS%\System32, I think that is where the INIs are usually copied. If you know the name of the INI file then it is trivial. If you are looking for a programmatic method, you can enumerate the USB bus using the Win32 Setup API.
If you have installed the Wnidows Driver Kit on your machine, take a look at the USBVIEW sample application. It demonstrates how you can enumerate the USB bus and get a list of all devices including their PID and VID.
To get the serial number, look at the GetVolumeInformation() system call.