Reputation: 2035
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)
Upvotes: 3
Views: 7567
Reputation: 999
This is Michael's code that was rejected as an edit. It seg faults on the free ()
unless a dummy variable 'singleDriveString' is inserted thus:
#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));
if (driveStrings == NULL)
{
return -1;
}
// 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)
wchar_t * singleDriveString = driveStrings;
while (*singleDriveString)
{
// Dump drive information
driveType = GetDriveType(singleDriveString);
GetDiskFreeSpaceEx(singleDriveString, &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", singleDriveString, driveTypeString,
freeSpace.QuadPart / 1024 / 1024 / 1024);
// Move to next drive string
// +1 is to move past the null at the end of the string.
singleDriveString += lstrlen(singleDriveString) + 1;
}
free(driveStrings);
return 0;
}
Upvotes: 3
Reputation: 55445
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));
if (driveStrings == NULL)
{
return -1;
}
// 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;
}
free(driveStrings);
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
Upvotes: 8
Reputation: 61398
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<26;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.
Upvotes: 5