How to list physical disks?

How to list physical disks in Windows? For a list of available "\\\\.\PhysicalDrive0" .

+63
c windows winapi hard-drive
Nov 29 '08 at 17:18
source share
14 answers

WMIC

wmic is a very complete tool

 wmic diskdrive list 

provide (too many) detailed list e.g.

for less information

 wmic diskdrive list brief 

FROM

Sebastian Godele mentions in comments :

In C:

 system("wmic diskdrive list"); 

As already noted, you can also call WinAPI, but ... as shown in the section " How to get data from WMI using the C application? ", This is quite complicated (and usually runs with C ++, not C).

Powerhell

Or with PowerShell:

 Get-WmiObject Win32_DiskDrive 
+58
Nov 29 '08 at 17:24
source share

One way to do this:

  • List logical drives using GetLogicalDrives

  • For each logical drive, open a file named "\\.\X:" (without quotes), where X is the letter of the logical drive.

  • Call DeviceIoControl , passing the handle to the file opened in the previous step, and the dwIoControlCode parameter dwIoControlCode set to IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS :

     HANDLE hHandle; VOLUME_DISK_EXTENTS diskExtents; DWORD dwSize; [...] iRes = DeviceIoControl( hHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, (LPVOID) &diskExtents, (DWORD) sizeof(diskExtents), (LPDWORD) &dwSize, NULL); 

This returns the physical location of the logical volume in the form of a VOLUME_DISK_EXTENTS structure.

In the simple case, when the volume is on the same physical disk, the physical disk number is available in diskExtents.Extents[0].DiskNumber

+40
Jul 27 '12 at 8:09
source share

It may be 5 years too late :). But so far I do not see an answer to this by adding this.

We can use the installation API to get a list of drives, i.e. Devices on the system that implement GUID_DEVINTERFACE_DISK .

As soon as we have a way to them, we can release IOCTL_STORAGE_GET_DEVICE_NUMBER to build "\\.\PHYSICALDRIVE%d" with STORAGE_DEVICE_NUMBER.DeviceNumber

See also the SetupDiGetClassDevs function

 #include <Windows.h> #include <Setupapi.h> #include <Ntddstor.h> #pragma comment( lib, "setupapi.lib" ) #include <iostream> #include <string> using namespace std; #define START_ERROR_CHK() \ DWORD error = ERROR_SUCCESS; \ DWORD failedLine; \ string failedApi; #define CHK( expr, api ) \ if ( !( expr ) ) { \ error = GetLastError( ); \ failedLine = __LINE__; \ failedApi = ( api ); \ goto Error_Exit; \ } #define END_ERROR_CHK() \ error = ERROR_SUCCESS; \ Error_Exit: \ if ( ERROR_SUCCESS != error ) { \ cout << failedApi << " failed at " << failedLine << " : Error Code - " << error << endl; \ } int main( int argc, char **argv ) { HDEVINFO diskClassDevices; GUID diskClassDeviceInterfaceGuid = GUID_DEVINTERFACE_DISK; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData; DWORD requiredSize; DWORD deviceIndex; HANDLE disk = INVALID_HANDLE_VALUE; STORAGE_DEVICE_NUMBER diskNumber; DWORD bytesReturned; START_ERROR_CHK(); // // Get the handle to the device information set for installed // disk class devices. Returns only devices that are currently // present in the system and have an enabled disk device // interface. // diskClassDevices = SetupDiGetClassDevs( &diskClassDeviceInterfaceGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); CHK( INVALID_HANDLE_VALUE != diskClassDevices, "SetupDiGetClassDevs" ); ZeroMemory( &deviceInterfaceData, sizeof( SP_DEVICE_INTERFACE_DATA ) ); deviceInterfaceData.cbSize = sizeof( SP_DEVICE_INTERFACE_DATA ); deviceIndex = 0; while ( SetupDiEnumDeviceInterfaces( diskClassDevices, NULL, &diskClassDeviceInterfaceGuid, deviceIndex, &deviceInterfaceData ) ) { ++deviceIndex; SetupDiGetDeviceInterfaceDetail( diskClassDevices, &deviceInterfaceData, NULL, 0, &requiredSize, NULL ); CHK( ERROR_INSUFFICIENT_BUFFER == GetLastError( ), "SetupDiGetDeviceInterfaceDetail - 1" ); deviceInterfaceDetailData = ( PSP_DEVICE_INTERFACE_DETAIL_DATA ) malloc( requiredSize ); CHK( NULL != deviceInterfaceDetailData, "malloc" ); ZeroMemory( deviceInterfaceDetailData, requiredSize ); deviceInterfaceDetailData->cbSize = sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA ); CHK( SetupDiGetDeviceInterfaceDetail( diskClassDevices, &deviceInterfaceData, deviceInterfaceDetailData, requiredSize, NULL, NULL ), "SetupDiGetDeviceInterfaceDetail - 2" ); disk = CreateFile( deviceInterfaceDetailData->DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); CHK( INVALID_HANDLE_VALUE != disk, "CreateFile" ); CHK( DeviceIoControl( disk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &diskNumber, sizeof( STORAGE_DEVICE_NUMBER ), &bytesReturned, NULL ), "IOCTL_STORAGE_GET_DEVICE_NUMBER" ); CloseHandle( disk ); disk = INVALID_HANDLE_VALUE; cout << deviceInterfaceDetailData->DevicePath << endl; cout << "\\\\?\\PhysicalDrive" << diskNumber.DeviceNumber << endl; cout << endl; } CHK( ERROR_NO_MORE_ITEMS == GetLastError( ), "SetupDiEnumDeviceInterfaces" ); END_ERROR_CHK(); Exit: if ( INVALID_HANDLE_VALUE != diskClassDevices ) { SetupDiDestroyDeviceInfoList( diskClassDevices ); } if ( INVALID_HANDLE_VALUE != disk ) { CloseHandle( disk ); } return error; } 
+27
Aug 12 '13 at 9:02
source share

I modified an open source program called "dskwipe" to pull this information out of it. Dskwipe is written in C, and you can get this function out of it. Binary and source available here: dskwipe 0.3 released

The returned information will look something like this:

 Device Name Size Type Partition Type ------------------------------ --------- --------- -------------------- \\.\PhysicalDrive0 40.0 GB Fixed \\.\PhysicalDrive1 80.0 GB Fixed \Device\Harddisk0\Partition0 40.0 GB Fixed \Device\Harddisk0\Partition1 40.0 GB Fixed NTFS \Device\Harddisk1\Partition0 80.0 GB Fixed \Device\Harddisk1\Partition1 80.0 GB Fixed NTFS \\.\C: 80.0 GB Fixed NTFS \\.\D: 2.1 GB Fixed FAT32 \\.\E: 40.0 GB Fixed NTFS 
+12
Dec 08 '08 at 17:55
source share

The answer is much simpler than all the above answers. The list of physical disks is actually stored in a registry key, which also gives device mapping.

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ drive \ Enum

Counting is the number of PhysicalDrive #, and each numbered registry value is a corresponding physical drive.

For example, a registry value of "0" is PhysicalDrive0. The value is the actual device on which the physical disk is mapped. The value contained here can be passed to CM_Locate_DevNode in the pDeviceID parameter to use the plug and play services. This will allow you to collect a lot of information on the device. For example, device manager properties such as "Friendly Display Name" if you need a drive name, serial numbers, etc.

There is no need for WMI services that may not run on the system or other hackers, and this functionality has been present on Windows since at least 2000 and continues to run on Windows 10.

+12
May 20 '16 at 12:34
source share

The only sure way to do this is to call CreateFile() on all \\.\Physicaldiskx , where x is from 0 to 15 (16 is the maximum number of disks allowed). Check the descriptor return value. If the GetLastError() check is invalid for ERROR_FILE_NOT_FOUND . If it returns something else, then the disk exists, but for some reason you cannot access it.

+9
Apr 19 '12 at 12:26
source share

GetLogicalDrives () lists all mounted disk partitions, not physical hard drives.

You can list the drive letters with or without GetLogicalDrives, and then call QueryDosDevice () to find out which drive the drive will be mapped to.

In addition, you can decode registry information at HKEY_LOCAL_MACHINE \ SYSTEM \ MountedDevices. However, binary data encodings are not obvious there. If you have a copy of Russinovich and Solomon's book on Microsoft Windows Internals, this registry hive is discussed in Chapter 10.

+8
Nov 29 '08 at 18:11
source share

The only correct answer is the one that was @Grodriguez, and here is the code that he was too lazy to write:

 #include <windows.h> #include <iostream> #include <bitset> #include <vector> using namespace std; typedef struct _DISK_EXTENT { DWORD DiskNumber; LARGE_INTEGER StartingOffset; LARGE_INTEGER ExtentLength; } DISK_EXTENT, *PDISK_EXTENT; typedef struct _VOLUME_DISK_EXTENTS { DWORD NumberOfDiskExtents; DISK_EXTENT Extents[ANYSIZE_ARRAY]; } VOLUME_DISK_EXTENTS, *PVOLUME_DISK_EXTENTS; #define CTL_CODE(DeviceType, Function, Method, Access) \ (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) #define IOCTL_VOLUME_BASE ((DWORD)'V') #define METHOD_BUFFERED 0 #define FILE_ANY_ACCESS 0x00000000 #define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS CTL_CODE(IOCTL_VOLUME_BASE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) int main() { bitset<32> drives(GetLogicalDrives()); vector<char> goodDrives; for (char c = 'A'; c <= 'Z'; ++c) { if (drives[c - 'A']) { if (GetDriveType((c + string(":\\")).c_str()) == DRIVE_FIXED) { goodDrives.push_back(c); } } } for (auto & drive : goodDrives) { string s = string("\\\\.\\") + drive + ":"; HANDLE h = CreateFileA( s.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS, NULL ); if (h == INVALID_HANDLE_VALUE) { cerr << "Drive " << drive << ":\\ cannot be opened"; continue; } DWORD bytesReturned; VOLUME_DISK_EXTENTS vde; if (!DeviceIoControl( h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &vde, sizeof(vde), &bytesReturned, NULL )) { cerr << "Drive " << drive << ":\\ cannot be mapped into physical drive"; continue; } cout << "Drive " << drive << ":\\ is on the following physical drives: "; for (int i = 0; i < vde.NumberOfDiskExtents; ++i) { cout << vde.Extents[i].DiskNumber << ' '; } cout << endl; } } 

I think that installing a set of drivers for Windows is a rather lengthy process, so I have included the declarations that DeviceIoControl needs to use for this task.

+8
Feb 16 '15 at 21:33
source share

Thic WMIC command combination works fine:

 wmic volume list brief 
+2
Jun 20 '13 at 21:51
source share

You might want to include the old A: and B: drives because you never know who can use them! I'm tired of USB sticks running into two SDHC drives that are only for Readyboost. I assigned them to the High letters Z: Y: using a utility that will assign drive letters to the devices of your choice. I wondered ... Can I make a letter with the letter A :? YES! Can I put the second letter of the SDHC drive as B :? YES!

I used floppy drives that day, I never thought A: or B: Readyboost would come in handy.

My point is, do not assume that A: and B: will not use anyone. You can even find the old SUBST command!

+2
Jan 01 '14 at 9:47
source share

I just ran into this in my RSS reader today. I have a cleaner solution for you. This example is in Delphi, but it can be easily converted to C / C ++ (all of this is Win32).

Request all value names from the following registry key: HKLM \ SYSTEM \ MountedDevices

Pass them one by one to the next function, and the device name will be returned to you. Pretty clean and simple! I found this code on the blog here.

 function VolumeNameToDeviceName(const VolName: String): String; var s: String; TargetPath: Array[0..MAX_PATH] of WideChar; bSucceeded: Boolean; begin Result := "; // VolumeName has a format like this: \\?\Volume{c4ee0265-bada-11dd-9cd5-806e6f6e6963}\ // We need to strip this to Volume{c4ee0265-bada-11dd-9cd5-806e6f6e6963} s := Copy(VolName, 5, Length(VolName) - 5); bSucceeded := QueryDosDeviceW(PWideChar(WideString(s)), TargetPath, MAX_PATH) <> 0; if bSucceeded then begin Result := TargetPath; end else begin // raise exception end; end; 
+1
Dec 10 '08 at 16:31
source share

If you need β€œphysical” access, we are developing this API, which will ultimately allow you to communicate with storage devices. It is open source and you can see the current code for some information. Check for additional features: https://github.com/virtium/vtStor

+1
Apr 27 '15 at
source share

Here is a new solution to do this using WMI calls.
Then all you have to do is just call:

 queryAndPrintResult(L"SELECT * FROM Win32_DiskDrive", L"Name"); 
+1
Feb 12 '18 at 9:25
source share

Make a list of all the letters in the English alphabet by skipping a and b. "CDEFGHIJKLMNOPQRSTUVWXYZ". Open each of these disks with CreateFile , for example. CreateFile("\\.\C:") . If it does not return INVALID_HANDLE_VALUE , then you will get a "good" drive. Then grab this handle and run it through DeviceIoControl to get drive #. See my answer for more details .

-2
Feb 18 '12 at 8:12
source share



All Articles