Sometimes you need to find a list of all existing physical drives, so you can access them through Win32 device namespace for direct access.
There is currently no WinApi call to do this, so device list has to be retrieved through QueryDosDevice call and then enumerated to find all PhysicalDisks. Here is an example in C#:
// Native WINAPI functions to retrieve list of devices
private const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint QueryDosDevice(string lpDeviceName, IntPtr lpTargetPath, int ucchMax);
/// <summary>
/// Retrieves list of all "PhysicalDrive" identifiers on the system, depicting plugged in PhysicalDrives
/// </summary>
/// List of "PhysicalDriveX" strings of plugged in drives
private static List<string> GetPhysicalDriveList()
{
uint returnSize = 0;
// Arbitrary initial buffer size
int maxResponseSize = 100;
IntPtr response = IntPtr.Zero;
string allDevices = null;
string[] devices = null;
while (returnSize == 0)
{
// Allocate response buffer for native call
response = Marshal.AllocHGlobal(maxResponseSize);
// Check out of memory condition
if (response != IntPtr.Zero)
{
try
{
// List DOS devices
returnSize = QueryDosDevice(null, response, maxResponseSize);
// List success
if (returnSize != 0)
{
// Result is returned as null-char delimited multistring
// Dereference it from ANSI charset
allDevices = Marshal.PtrToStringAnsi(response, maxResponseSize);
}
// The response buffer is too small, reallocate it exponentially and retry
else if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
{
maxResponseSize = (int)(maxResponseSize * 5);
}
// Fatal error has occured, throw exception
else
{
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
}
}
finally
{
// Always free the allocated response buffer
Marshal.FreeHGlobal(response);
}
}
else
{
throw new OutOfMemoryException("Out of memory when allocating space for QueryDosDevice command!");
}
}
// Split zero-character delimited multi-string
devices = allDevices.Split('\0');
// QueryDosDevices lists alot of devices, return only PhysicalDrives
return devices.Where(device => device.StartsWith("PhysicalDrive")).ToList<string>();
}
This returns list of PhysicalDriveX
strings which represent all physical drives (CD-ROMs excluded) present on the system, including those, that have no mounted volumes.