Search code examples
c#windowswinapidisk-partitioning

Repartition a USB device using DiskPart


I would like to repartition a USB drive using DiskPart from a C# application. This seems reasonably simple: I collect data about plugged disks using the Win32_DiskDrive class and then use DiskPart to run a script that will change the partitions. Critical point seems to be that of mapping the entry I select from Win32_DiskDrive to a disk number in DiskPart. For instance, this is the output of DiskPart:

DISKPART> list disk

  Disk ###  Status         Size     Free     Dyn  Gpt
  --------  -------------  -------  -------  ---  ---
* Disk 0    Online          100 GB      0 B
  Disk 1    Online           14 GB      0 B

I need to select the disk by its number. But where do I get that number from data retrieved using Win32_DiskDrive? I guess the answer is using the "DeviceID" field, which returns this "\\.\PHYSICALDRIVE0". The index at the end seems to be the one I need to match the entry from Win32_DiskDrive to the related entry from DiskPart. Is this correct? Critical question is: is there any place in the official docs where this is stated without doubts? I will then format the device so I cannot do anything wrong here. Thanks.


Solution

  • you need use uint32 Index;

    Physical drive number of the given drive. This property is filled by the STORAGE_DEVICE_NUMBER structure returned from the IOCTL_STORAGE_GET_DEVICE_NUMBER control code. A value of 0xffffffff indicates that the given drive does not map to a physical drive.


    about DiskPart disk numbers - i not found in documentation clear stating what is disk number mean here. however i look under debugger, how diskpart format line for disk - internal function

    long ListDiskLine(IVdsDisk *)
    

    called for this.

    enter image description here

    it used IVdsDisk interface for get disk properties. the IVdsDisk::GetProperties method called for get VDS_DISK_PROP structure and then used pwszName member:

    pwszName: The null-terminated Unicode name that the operating system uses to identify the disk. If present, a client can use this property to determine the disk's PNP device number. This is the number obtained from the DeviceNumber member of STORAGE_DEVICE_NUMBER (see [MSDN-STRGEDEVNUM]). For a hard disk, this name has the format \\?\PhysicalDriveN, where N signifies the device number of the disk. For a DVD/CD drive, this name has the format \\?\CdRomN, where N signifies the device number of the DVD/CD drive. A client can use this property to identify the disk.

    for hard disk used next code for get N:

    enter image description here

    or if translate this to c/c++

    esi = _wtol(pvdp->pwszName + RTL_NUMBER_OF("\\\\?\\PhysicalDrive") - 1);
    

    the 0x22 is 0x11*sizeof(WCHAR) and exactly 0x11 (17) symbols in \\?\PhysicalDrive prefix.

    so diskpart retriever N from \\?\PhysicalDriveN and this is the number obtained from the DeviceNumber member of STORAGE_DEVICE_NUMBER (so equal to Win32_DiskDrive.Index)

    and finally esi (where stored N) used as:

    StringCchPrintf(sz, 0x400, L"%s Disk %-3lu  %-13.13s  %7s  %7s   %s    %s\r\n", *, esi, ..);
    ConsolePrintf(sz);
    

    enter image description here