Getting Disc Free Space on Windows 95

Environment: VC6 , win9x

When you want to determine disc free space, what function do you use?

GetDiskFreeSpace() or GetDiskFreeSpaceEx()?

Well if you read the documentation for GetDiskFreeSpace(), the following comment will make you want to use GetDiskFreeSpaceEx():

The GetDiskFreeSpace function returns incorrect values for volumes that are larger than 2 gigabytes. The function caps the values stored into *lpNumberOfFreeClusters and *lpTotalNumberOfClusters so as to never report volume sizes that are greater than 2 gigabytes. Even on volumes that are smaller than 2 gigabytes, the values stored into *lpSectorsPerCluster, *lpNumberOfFreeClusters, and *lpTotalNumberOfClusters values may be incorrect. That is because the operating system manipulates the values so that computations with them yield the correct volume size.

However, if you read the documentation for GetDiskFreeSpaceEx(), you will notice there is a small problem when targeting Windows95: You cannot guarantee that GetDiskFreeSpaceEx() is available. (Prior to OSR2, you only get GetDiskFreeSpace().)

This means if you need to target Windows95, you need to determine on the fly whether GetDiskFreeSpaceEx() is available or not. If it is, great...if not, you have to use GetDiskFreeSpace().

One way of doing this on the fly, is to load the Kernel32 DLL and determine whether GetDiskFreeSpaceEx() exists or not. If we get a pointer to the function, we can call it...if not, we know we have to use GetDiskFreeSpace():



BOOL GetDiscFreeSpace(LPCTSTR lpszPath, DWORDLONG* pnFree)
{
	BOOL bRet = FALSE;

	// We need to determine whether GetDiskFreeSpaceEx is available by calling LoadLibrary
	// or LoadLibraryEx, to load Kernel32.DLL, and then calling the GetProcAddress to
	// obtain an address for GetDiskFreeSpaceEx.  If GetProcAddress fails, or if
	// GetDiskFreeSpaceEx fails with the ERROR_CALL_NOT_IMPLEMENTED code, we use the
	// GetDiskFreeSpace function instead.	
	HINSTANCE hInstance = LoadLibrary("KERNEL32.DLL");

	if(hInstance)	// If we got the library
	{		
		FARPROC lpfnDLLProc = NULL;
		
		lpfnDLLProc = GetProcAddress(hInstance, "GetDiskFreeSpaceExA");
		
		if(lpfnDLLProc)	// If we got an address to the function
		{	
			ULARGE_INTEGER nTotalBytes, nTotalFreeBytes, nTotalAvailable;

			if((*lpfnDLLProc)(lpszPath, &nTotalAvailable, &nTotalBytes, &nTotalFreeBytes))
			{
				*pnFree = nTotalAvailable.QuadPart;
				bRet = TRUE;
			}		
		}

		FreeLibrary(hInstance);
	}

	if(!bRet)	// We have to try and use GetDiskFreeSpace()	
	{
		ULONG secpercluster, bytespersec, nooffreeclusters, totalnoofclusters;	

		if(GetDiskFreeSpace(lpszPath, &secpercluster, &bytespersec,
			&nooffreeclusters, &totalnoofclusters))
		{
			*pnFree = (nooffreeclusters * secpercluster * bytespersec);
			bRet = TRUE;
		}				
	}

	return bRet;
}

History