tags:

views:

133

answers:

2

I know you can use a combination of GetLogicalDrives() and GetDiskFreeSpaceEx() to get the list of drives and their sizes. I've been using GetDiskFreeSpaceEx() with no problem but when I try to use GetLogicalDrives() I ran into a problem: I don't want to have to check each possible letter to see whether it exists or not before passing it to GetDiskFreeSpaceEx().

Is there a simpler way to get the list of drives (disk) on the system and what their sizes are? I am using C, on Windows.

I want to make something clear, I KNOW it might be easier using C# and WMI, I have no interest on that so please do not post that as a possible solution. If you want to point to how is done in C and WMI, go for it. NO C++ or C# thanks! (like someone did in my previous question)

+3  A: 

You can use GetLogicalDriveStrings - this returns a buffer containing all valid drive letters on the system.

UPDATE:

Here is sample program I wrote that enumerates the drives using GetLogicalDriveStrings and outputs some basic information about them.

#include <windows.h>
#include <malloc.h>
#include <stdio.h>

int __cdecl main()
{
    DWORD cchBuffer;
    WCHAR* driveStrings;
    UINT driveType;
    PWSTR driveTypeString;
    ULARGE_INTEGER freeSpace;

    // Find out how big a buffer we need
    cchBuffer = GetLogicalDriveStrings(0, NULL);

    driveStrings = (WCHAR*)malloc((cchBuffer + 1) * sizeof(TCHAR));

    // Fetch all drive strings    
    GetLogicalDriveStrings(cchBuffer, driveStrings);

    // Loop until we find the final '\0'
    // driveStrings is a double null terminated list of null terminated strings)
    while (*driveStrings)
    {
        // Dump drive information
        driveType = GetDriveType(driveStrings);
        GetDiskFreeSpaceEx(driveStrings, &freeSpace, NULL, NULL);

        switch (driveType)
        {
        case DRIVE_FIXED:
            driveTypeString = L"Hard disk";
            break;

        case DRIVE_CDROM:
            driveTypeString = L"CD/DVD";
            break;

        case DRIVE_REMOVABLE:
            driveTypeString = L"Removable";
            break;

        case DRIVE_REMOTE:
            driveTypeString = L"Network";
            break;

        default:
            driveTypeString = L"Unknown";
            break;
        }

        printf("%S - %S - %I64u GB free\n", driveStrings, driveTypeString,
                  freeSpace.QuadPart / 1024 / 1024 / 1024);

        // Move to next drive string
        // +1 is to move past the null at the end of the string.
        driveStrings += lstrlen(driveStrings) + 1;
    }

    return 0;

}

On my machine this outputs:

C:\ - Hard disk - 181 GB free
D:\ - CD/DVD - 0 GB free
E:\ - Hard disk - 806 GB free
Michael
thanks, but I can't get it to work... it crashes when I tried to send the each string to GetDiskFreeSpaceEx. Any chance you can post a snippet of code?
Jessica
@Jessica - Updated with some code.
Michael
A: 

GetLogicalDrives() is the system-provided API for that. A simple for() loop will translate its result into drive letters, like this:

DWORD d = GetLogicalDrives();
int i;
TCHAR Drive[] = _T("A:\");
for(i=0;i<32;i++)
{
    if(d & (1<<i))
    {
        Drive[0] = _T('A')+i;
        GetDiskFreeSpaceEx(Drive, .....);
    }
}

And if you're not satisfied with the level of service that Stack Overflow provides, feel free to ask for your money back.

Seva Alekseyev
It's not that I am not satisfied. it's that people DO NOT PAY attention to the question and tags. It's not the first time it happens. If I asked something SPECIFICALLY in C why would you answer in VB?Thanks for the answer
Jessica