c++cwinapidrive

Listing All Physical Drives (Windows)


How can I get all the physical drive paths (\\.\PhysicalDriveX) on a Windows computer, with C/C++?

The answers in this question suggest getting the logical drive letter, and then getting the physical drive corresponding to that mounted drive. The problem is, I want to get all physical drives connected to the computer, including drives that are not mounted.

Other answers suggest incrementing a value from 0-15 and checking if a drive exists there (\\.\PhysicalDrive0, \\.\PhysicalDrive1, ...) or calling WMIC to list all the drives.[

As these seem like they would work, they seem like they are not the best approach to be taking. Is there not a simple function such as GetPhysicalDrives that simply returns a vector of std::string's containing the paths of all the physical drives?


Solution

  • You can use QueryDosDevice. Based on the description, you'd expect this to list things like C: and D:, but it will also lists things like PhysicalDrive0, PhysicalDrive1 and so on.

    The major shortcoming is that it will also list a lot of other device names you probably don't care about, so (for example) on my machine, I get a list of almost 600 device names, of which only a fairly small percentage is related to what you care about.

    Just in case you care, some (old) sample code:

    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    
    #include <iostream>
    
    int main(int argc, char **argv) {
    
        char physical[65536];
        char logical[65536];
    
        if ( argc > 1) {
            for (int i=1; i<argc; i++) {
                QueryDosDevice(argv[i],logical, sizeof(logical));
                std::cout << argv[i] << " : \t" << logical << std::endl << std::endl;
            }
            return 0;
        }
    
        QueryDosDevice(NULL, physical, sizeof(physical));
    
        std::cout << "devices: " << std::endl;
    
        for (char *pos = physical; *pos; pos+=strlen(pos)+1) {
            QueryDosDevice(pos, logical, sizeof(logical));
            std::cout << pos << " : \t" << logical << std::endl << std::endl;
        }    
    
        return 0;
    }    
    

    However, if I run this like `devlist | grep "^Physical", it lists the physical drives.