Windows DevCenter    
 Published on Windows DevCenter (http://www.windowsdevcenter.com/)
 See this if you're having trouble printing code examples


Date: Nov 22 1999
From: Olivier Philippe
To: ron@oreilly.com
Subject: Free Disk Space Available

Hi,

I want to know how to get the total amount of available free disk space if my disk has more than a 2-gigabyte capacity.

Thanks a lot for answering.

Sincerely,

Olivier


Hello Olivier,

Visual Basic 6.0 offers a comparatively new and very accessible (and still comparatively unknown) method for determining the amount of free space available on a local drive: the FreeSpace property of the Drive object, which is part of the file system object model included with the Scripting Runtime library. The following code fragment, for instance, retrieves the number of free bytes on drive C:

Dim oFS As New FileSystemObject
Dim lngBytes As Long

lngBytes = oFS.Drives("C").FreeSpace

As your question suggests, though, the FreeSpace property has one very significant limitation: it is unable to report free storage space in excess of about 2 gigabytes.

The alternative is to use the Win32 API from Visual Basic. However, GetDiskFreeSpace, the standard Win32 API function for determining free space on a drive, suffers from the same limitation: it fails to report free storage space in excess of about 2GB. This is hardly a coincidence: the FreeSpace property of the Drive object merely wraps a call to the GetDiskFreeSpace function in Kernel32.dll. Nor is this surprising: until recently, hard drives with more than 2GB of total space were rare.

Historically, Microsoft has chosen to enhance the Win32 API by adding a variety of "extended" functions. In some cases, these extended functions simply address difficulties that developers were having using the original function. For instance, the Win32 GetVersionEx function is much easier to use than the original GetVersion function. In other cases, though, the extended function reflects some technical change in Windows' hardware support or in the design of the Windows family of operating systems. For example, the RegQueryValue function retrieves the default value of a registry key, whereas the RegQueryValueEx function retrieves the named value of an open registry key. In view of this, it's not surprising that the increasingly obsolete GetDiskFreeSpace function has been supplemented by a new function named GetDiskFreeSpaceEx.

The syntax of GetDiskFreeSpaceEx is: (Click here for code example)

Its parameters are: (Click here for code example)

Like all Win32 prototypes, this prototype assumes that a C or C++ programmer is calling the function. But what about a VB programmer? The first parameter, lpDirectoryName, is fairly straightforward; it calls for a pointer to a standard null-terminated C string. This simply requires that we pass our string by value to the GetDiskFreeSpaceEx function.

The remaining parameters are somewhat problematic. All three parameters are of type PULARGE_INTEGER, which means that they are pointers to unsigned large integers. This poses two difficulties for the Visual Basic programmer. First, large (64-bit) integers are a fairly new data type to the Win32 API that aren't supported by VB. Second, except for the Byte data type, VB doesn't support unsigned data types.

However, PULARGE_INTEGER is not a native C/C++ data type. Instead, it is defined as

struct {
    DWORD LowPart;
    DWORD HighPart;
} ;

This means that we can define it in Visual Basic as a user-defined type that we'll call LargeInt and that consists of two long integers, as follows:

Public Type LargeInt
   lngLower As Long
   lngUpper As Long
End Type

Note that the lower-order word precedes the high-order word in memory, which seems counter-intuitive. Since we can use the LargeInt structure, that leaves only the signed/unsigned problem, which we'll have to address in code. So we can use the following Declare statement in order to call the GetDiskFreeSpaceEx function: (Click here for code example)

We can then enumerate available drives (or at least the non-removable ones -- this prevents an error from occurring if the media in non-removable drives are not present) and calculate their free storage space with a code fragment like the following, which adds the drive letter and its free space to a list box: (Click here for code example)

The only thing that really needs comment here is our handling of the 64-bit integer user-defined type. The highest-order bit of each of the Longs that forms a LargeInt variable is a sign bit. The sign bit not only indicates to VB that a long integer is negative, but it produces a value that is 4,294,967,296 less than the unsigned representation of the same value. (That's because the highest-order byte is the byte in the 31st position, and 2^31 is 2,147,483,648. That bit is interpreted as being equal to -2,147,483,648 in a signed representation and 2,147,483,648 in an unsigned one, a difference of 4,294,967,296.) For all practical purposes, we don't need to be concerned with the sign of the high-order word, since drives now (and probably for all time) simply aren't that large. Finally, the value of the high-order word is 2^32, or 4,294,967,296 greater than the low-order word. Because of its greater range, we assign the result of our manipulation of the two members of a LargeInt variable to a variable of type Double.

The GetDiskFreeSpaceEx function is available on Windows 95 SR2 or later and on Windows NT 4.0 or later. You can download a sample program that illustrates the use of the function and compares the results with the traditional methods of calculating free disk space.

Thanks for submitting this question. Until it arrived, I had never noticed that the FreeSpace property and the GetDiskFreeSpace function inaccurately reported available free space on drives with over 2GB free space.

--Ron

Return to: Ron's Archive

Copyright © 2009 O'Reilly Media, Inc.