INFO: Understanding and Using GetDiskFreeSpace and GetDiskFreeSpaceExID: Q231497
|
Win32 programs use GetDiskFreeSpaceEx or GetDiskFreeSpace to determine the total size of a volume and how much free space can be allocated by the caller. Because some Windows platforms have features such as enforceable disk quotas while others don't, applications that use these APIs must interpret the returned sizes correctly. In addition, because most Windows platforms support volumes larger than 4 gigabytes (GB), Win32 programs must use 64-bit integer math with these APIs. This article explains how to use GetDiskFreeSpaceEx and GetDiskFreeSpace in a way that works on all Win32 platforms.
Generally, Win32 programs should use GetDiskFreeSpaceEx to determine the
total size of a volume and the amount of free space that the caller can use. The one case where this isn't possible is when the program runs on retail Windows 95 (build 950.6) because GetDiskFreeSpaceEx was introduced to Windows 95 in OEM Service Release 2 (OSR2).
If your program can run on retail Windows 95, you should not directly call
GetDiskFreeSpaceEx because this function is not implemented in retail Windows 95, and calling it directly will prevent your program from loading. Instead, you should dynamically link to it via GetProcAddress. If the returned pointer is non-NULL, then your application can safely call GetDiskFreeSpaceEx through the pointer; if the returned pointer is NULL, then you should revert to GetDiskFreeSpace. The example code later in this article demonstrates how to do this.
/*
Determines the amount of free space available for the caller.
Runs on Windows 95 retail and later, and on Windows 4.0 and later.
Uses GetDiskFreeSpaceEx if available, otherwise reverts to
GetDiskFreeSpace.
To determine the amount of available space correctly:
* Use 64-bit math with the return values of both GetDiskFreeSpace
and GetDiskFreeSpaceEx so that you can determine the sizes of
volumes that are larger than 2GB.
Programs that need to determine how much free space the current user
can have (such as whether there is enough space to complete an
installation) have an additional requirement:
* Use the lpFreeBytesAvailableToCaller value from
GetDiskFreeSpaceEx rather than lpTotalNumberOfFreeBytes.
This is because Windows 2000 has disk quota management that
administrators may use to limit the amount of disk space that
users may use.
*/
#include <windows.h>
#include <stdio.h>
typedef BOOL (WINAPI *P_GDFSE)(LPCTSTR, PULARGE_INTEGER,
PULARGE_INTEGER, PULARGE_INTEGER);
void main (int argc, char **argv)
{
BOOL fResult;
char *pszDrive = NULL,
szDrive[4];
DWORD dwSectPerClust,
dwBytesPerSect,
dwFreeClusters,
dwTotalClusters;
P_GDFSE pGetDiskFreeSpaceEx = NULL;
unsigned __int64 i64FreeBytesToCaller,
i64TotalBytes,
i64FreeBytes;
/*
Command line parsing.
If the drive is a drive letter and not a UNC path, append a
trailing backslash to the drive letter and colon. This is
required on Windows 95 and 98.
*/
if (argc != 2)
{
printf ("usage: %s <drive|UNC path>\n", argv[0]);
printf ("\texample: %s C:\\\n", argv[0]);
return;
}
pszDrive = argv[1];
if (pszDrive[1] == ':')
{
szDrive[0] = pszDrive[0];
szDrive[1] = ':';
szDrive[2] = '\\';
szDrive[3] = '\0';
pszDrive = szDrive;
}
/*
Use GetDiskFreeSpaceEx if available; otherwise, use
GetDiskFreeSpace.
Note: Since GetDiskFreeSpaceEx is not in Windows 95 Retail, we
dynamically link to it and only call it if it is present. We
don't need to call LoadLibrary on KERNEL32.DLL because it is
already loaded into every Win32 process's address space.
*/
pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress (
GetModuleHandle ("kernel32.dll"),
"GetDiskFreeSpaceExA");
if (pGetDiskFreeSpaceEx)
{
fResult = pGetDiskFreeSpaceEx (pszDrive,
(PULARGE_INTEGER)&i64FreeBytesToCaller,
(PULARGE_INTEGER)&i64TotalBytes,
(PULARGE_INTEGER)&i64FreeBytes);
if (fResult)
{
printf ("\n\nGetDiskFreeSpaceEx reports\n\n");
printf ("Available space to caller = %I64u MB\n",
i64FreeBytesToCaller / (1024*1024));
printf ("Total space = %I64u MB\n",
i64TotalBytes / (1024*1024));
printf ("Free space on drive = %I64u MB\n",
i64FreeBytes / (1024*1024));
}
}
else
{
fResult = GetDiskFreeSpace (pszDrive,
&dwSectPerClust,
&dwBytesPerSect,
&dwFreeClusters,
&dwTotalClusters);
if (fResult)
{
/* force 64-bit math */
i64TotalBytes = (__int64)dwTotalClusters * dwSectPerClust *
dwBytesPerSect;
i64FreeBytes = (__int64)dwFreeClusters * dwSectPerClust *
dwBytesPerSect;
printf ("GetDiskFreeSpace reports\n\n");
printf ("Free space = %I64u MB\n",
i64FreeBytes / (1024*1024));
printf ("Total space = %I64u MB\n",
i64TotalBytes / (1024*1024));
}
}
if (!fResult)
printf ("error: %lu: could not get free space for \"%s\"\n",
GetLastError(), argv[1]);
}
i64TotalBytes = (__int64)dwTotalClusters * dwSectPerClust *
dwBytesPerSect;
The first multiply is of a 64-bit integer with a 32-bit integer; the result
is a 64-bit integer, which is then multiplied by another 32-bit integer,
resulting in a 64-bit product.
liTotalBytes.QuadPart = (__int64)dwTotalClusters * dwSectPerClust
* dwBytesPerSect;
Additional query words: available drive volume unused setup empty
Keywords : kbAPI kbFileIO kbKernBase kbSDKPlatform kbSDKWin32
Version : winnt:3.51,4.0,4.0 SP4
Platform : winnt
Issue type : kbinfo
Last Reviewed: May 21, 1999