I need to automate the initialization of a microSD on Windows10 (physical cleanup, special partitioning, format...). The initial information I have is the drive letter the OS assigns tho the drive, and I want to find related disk number and physycal device. This issue is discussed in many articles (e.g. Identify physical drive from drive letter), but all solutions I have tried fail when the disk is not formatted and not partitioned. It is a very special case: the device is registered as physical drive, the letter is assignet to a volume, but I cant't find a way to get link between these namespaces. Usual functions (e.g. powershell get-ciminstance / get-cimassociatedinstance) fail to detect an association between disk and volume. The only tool that seems to know the connection is Windows' disk manager, as it shows the empty disk and marks it with the corresponding drive letter. Is there a way to do the same programmatically (e.g. in powershell)?
Asked
Active
Viewed 64 times
0
-
What happens when you run `Get-Volume` or `Get-CimInstance Win32_Volume` (without trying to resolve the associated disk/partition)? Do they list the volume with the given drive letter/mount point? – Mathias R. Jessen Jul 14 '23 at 13:53
-
@MathiasR.Jessen Yes, I can see the volume and its drive letter. What I miss is a reference to the underlying physical support (disk number and related \\.\PHYSYCALDRIVE). Interestingly, volume size is "0". – Giuseppe Guerrini Jul 14 '23 at 14:37
-
Is `DeviceID` empty? It'd probably be easier to help you if you posted the ouput of `Get-CimInstance Win32_Volume -Filter "DriverLetter = '
:'" |Format-List * -Force` in your question :) – Mathias R. Jessen Jul 14 '23 at 14:39 -
@MathiasR.Jessen DeviceId is not empty ("\\?\Volume{bbdb1d8f-2216-11ee-9549-503eaa03bc43}\"), but I don't know how to use it. What is its relationship with physical support? – Giuseppe Guerrini Jul 14 '23 at 15:11
-
Is it really not partitioned? Usually creation of a volume is dependent on the existence of a partition. Did you look at [this answer](https://stackoverflow.com/a/47595325/3245749) while you were looking for solutions? – TheMadTechnician Jul 14 '23 at 16:52
-
@TheMadTechnician Yes, it may be unpartitioned. I'll study the answer you linked, although it seems to refer to partitioned drives. – Giuseppe Guerrini Jul 14 '23 at 17:21
-
This series of articles by Raymond Chen looks promising: https://devblogs.microsoft.com/oldnewthing/20201019-00/?p=104380 – Giuseppe Guerrini Jul 14 '23 at 22:39
1 Answers
0
Here the solution I eventually found. Raymond Chen's blog is the source of information (https://devblogs.microsoft.com/oldnewthing/20201019-00/?p=104380). I hope it can help. Here a minimal example (error check removed, multibyte only...):
// 1) Convert a path (F:\) in a volume path
// NOTE: we could skip this step, as root path
// and volume path are usually the same.
char volpath[MAX_PATH];
volpath[0] = '\0';
GetVolumePathName("f:\\", volpath, sizeof(volpath));
// 2) Get volume name from volume path
char name[MAX_PATH];
name[0] = '\0';
GetVolumeNameForVolumeMountPoint(volpath, name, sizeof(name));
// 3) Remove trailing \ to get volume objct name
int l = strlen(name);
if (name[l - 1] == '\\') {
name[l - 1] = '\0';
}
// 4) Open volume object
HANDLE handle = CreateFile(name,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
// 5) Get the list of underlying physical drives
// NOTE: we are assuming we are in the simplest case:
// a volume covering a single drive. In general, the
// service would fill an array of disk descriptors
// if the volume spanned over multiple drives.
VOLUME_DISK_EXTENTS singleExtent;
memset(&singleExtent, 0, sizeof(singleExtent));
DWORD bytesWritten = 0;
DeviceIoControl(handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL, 0,
&singleExtent, sizeof(singleExtent),
&bytesWritten,
NULL);
// 6) Enjoy the result.
printf("ndrive=%u, drive=%u len=%llu off=%llu\n",
singleExtent.NumberOfDiskExtents,
singleExtent.Extents[0].DiskNumber,
singleExtent.Extents[0].ExtentLength,
singleExtent.Extents[0].StartingOffset);
printf("Physical device is \\\\.\\PhysicalDrive%u\n",
singleExtent.Extents[0].DiskNumber);

Giuseppe Guerrini
- 4,274
- 17
- 32