From the device manager, I have a USB device node. I extracted its "Physical Device Object name" (e.g. \Device\0000010f
).
Fighting for hours with NtOpenDirectoryObject
, NtQueryDirectoryObject
, NtOpenSymbolicLinkObject
, NtQuerySymbolicLinkObject
and QueryDosDevice
, I couldn't find a way to get from that "Physical Device Object name" to the actual drive-letter (C:
, D:
, ...).
I'm looking for any storage solution (USB/SATA/...). How do I do that?
(There are many similar questions, none of them answers e.g. how to get from Physical Device Object name to \Device\HarddiskVolumeXYZ
or to Volume{SOME_GUID}
)
Another possible solution for you, based on PowerShell and WMI alone:
what you view
\Device\0000010f
this is PDO (Physical Device Object) created by some bus driver (it have flagDO_BUS_ENUMERATED_DEVICE
)to it can be attached some FDO (Functional Device Object). if this is from storage stack (based on CompatibleIDs strings returned by bus device for this PDO ) typical FDO name have form
\Device\Harddisk%d\DR%d
and well known symbolic link to it\Device\Harddisk%d\Partition0
disk driver FDO enumerate partitions on volume and for every partition create PDO device object ( with well known symbolic link
\Device\Harddisk%d\Partition%d
where partition number always > 0, Partition0 is refer to whole disk FDO)usual partition is same as volume but not always (Partitions and Volumes) also note
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
- it return array ofDISK_EXTENT
structures - look here forDiskNumber -The number of the disk that contains this extent.
so volume can placed on several disks. but in 99%+IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
return to you only oneDISK_EXTENT
so what you can do if you have path to PDO in storage stack ?
ZwOpenFile
(of course this worked in user mode) we can use\Device\0000010f
as is. if we want use win32 api we need use prefix\\?\GLOBALROOT
for all names. really we open by this bus PDO but because disk FDO is attached to PDO all our requests will be send via FDO and handled here. desired access ?SYNCHRONIZE
is enough (in caseCreateFile
if we not setFILE_FLAG_OVERLAPPED
api implicity add this flag toDESIRED_ACCESS
)IOCTL_STORAGE_GET_DEVICE_NUMBER
to device. check thatDeviceType == FILE_DEVICE_DISK && sdn.PartitionNumber == 0
IOCTL_DISK_GET_DRIVE_LAYOUT_EX
for get a variable-sized array ofPARTITION_INFORMATION_EX
structuresDeviceNumber
(which we get at step 2) andPartitionNumber
(which we get at step 3) format symbolic link to partition PDO -\\?\GLOBALROOT\Device\Harddisk%d\Partition%d
SYNCHRONIZE
access (enough because all IOCTL which we use haveFILE_ANY_ACCESS
typeIOCTL_MOUNTDEV_QUERY_DEVICE_NAME
to partition\\.\MountPointManager
) for send himIOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
this IOCTL defined inmountmgr.h
in input it requireMOUNTDEV_NAME
which we get at step 6. on output we receiveMOUNTMGR_VOLUME_PATHS
structure (also defined inmountmgr.h
) alternatively we can useIOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
- if all ok we got list of drive letters likeC:
,D:
, etc..CM_Get_Device_ID_ListW
with{4d36e967-e325-11ce-bfc1-08002be10318}
filter, open every device instance byCM_Locate_DevNodeW
and finally query forDEVPKEY_Device_PDOName
by callCM_Get_DevNode_Property
ok, here the code example correct which do all this: