The Unofficial Newsletter of Delphi Users - by Robert
Vivrette
Getting to the Bottom of FAT32
by Angus Johnson - ajohnson@rpi.net.au
Some time ago I created a Win95 utility which displayed disk drive and directory space
usage. It also displayed the wasted drive space, or slack. This slack results from the
fact that when files are stored on disk, they are stored in clusters or "file
allocation units". A cluster cannot be used by more than one file. Therefore, if a
file is only a couple of bytes long it will still own the the whole cluster (commonly 32k)
on your hard disk, and the remainder of the cluster
cannot be used by another file. With many small files on a disk the slack can run into
hundreds of megabytes.
Drive Slack := (No clusters used * cluster size) - (the sum of the size of all files on drive).
The API function - GetDiskFreeSpace - retrieved most of the relevant data I needed for
my utility : BytesPerSector, SectorsPerCluster, TotalNumberOfClusters and
TotalNumberOfFreeClusters. Cluster Size := BytesPerSector * SectorsPerCluster; Clusters
used := TotalNumberOfClusters - TotalNumberOfFreeClusters;
(A recursive function not relevant to this discussion added up all the file sizes on the
drive.)
The utility worked well until Win95 OSR2. GetDiskFreeSpace no longer works on FAT32
drives - reporting incorrect cluster sizes and disk sizes. Microsoft created another
function - GetDiskFreeSpaceEx - to replace the old one. This new function can now read the
total disk size and disk free space on FAT32
disks > 2gigs (as long as it is not networked). I have noticed that this new function
does not work on NETWORKED FAT32 disks - reporting 2 gig disks sizes for FAT32
volumes > 2gig! Even explorer gets the wrong sizes. I would call this a Microsoft bug.
Anyhow, I presume Microsoft in its wisdom decided that programers no longer needed to be
concerned with cluster sizes because the new function does not return cluster sizes!
ScanDisk & ChkDsk in OSR2 still
reports cluster size (on local drives) so I assumed it was still possible to get cluster
size if I dug a little deeper.
A search of Microsoft Developers Network (MSDN) for FAT32 revealed a new DOS interrupt function - Int 21h Function 7303h Get_ExtFreeSpace (FAT32) which returned all the the information in the old GetDiskFreeSpace...
From MSDN ...
--------------------------------------------------------------------
:Int 21h Function 7303h Get_ExtFreeSpace (FAT32)
:[Windows 95 only.]
:Returns the total disk space and the free disk space.
:mov dx, seg Buffer
:mov es, dx
:mov di, offset Buffer ;See below
:mov es:[di].ExtGetDskFreSpcStruc.ExtFree_Level, ExpectLevel
:mov cx, BufferSize ;See below
:mov dx, seg DriveName ;See below
:mov ds, dx
:mov dx, offset DriveName ;See below
:mov ax, 7303h ;Get_ExtFreeSpace
:int 21h
:jc error_handler ;carry set means error
:Parameters
:Buffer:-
:The address of the buffer at ES:DI that will receive the disk space
:information.
:BufferSize:-
:The size (in bytes) of the buffer.
:DriveName:-
:The address of a null terminated string at DS:DX. In real mode, this
must
:be in standard form ("C:\"). In Windows, either the
standard name or a
:universal naming convention form ("\\Server\Share") is
acceptable.
:Return Values:-
:Clears the carry flag and returns the total disk space and the free
disk
:space of the specified drive, in the form of an ExtGetDskFreSpcStruc
:(FAT32) structure, to a buffer at ES:DI. It is recommended to
initialize
:the buffer to the level value the application expects to receive.
:Remarks:-
:When calling this function with DeviceIoControl, the dwloControlCode
:parameter must be set to VWIN32_DIOC_DOS_IOCTL (defined as 6 in
VWIN32.H).
:For more information on this, see Using VWIN32 to Carry Out MS-DOS
:Functions.
:⌐ 1997 Microsoft Corporation. All rights reserved. Terms of Use.
--------------------------------------------------------------------
The relevant structure used by Get_ExtFreeSpace is (from MSDN) ...
--------------------------------------------------------------------
:ExtGetDskFreSpcStruc STRUC
:
ExtFree_Size
DW ?
:
ExtFree_Level
DW ?
:
ExtFree_SectorsPerCluster
DD ?
:
ExtFree_BytesPerSector
DD ?
:
ExtFree_AvailableClusters
DD ?
:
ExtFree_TotalClusters
DD ?
:
ExtFree_AvailablePhysSectors DD ?
:
ExtFree_TotalPhysSectors
DD ?
: ExtFree_AvailableAllocationUnits
DD ?
:
ExtFree_TotalAllocationUnits DD ?
:
ExtFree_Rsvd
DD 2 DUP (?)
:ExtGetDskFreSpcStruc ENDS
--------------------------------------------------------------------
Not having tried to call DOS interrupts in Delphi before, it took a little effort to work out how to do this. (See also - Learning To Drive by Grahame Marsh - UNDU Issue #20.) However, I now have a function which is a wrapper for Get_ExtFreeSpace which returns the same information as GetDiskFreeSpace for FAT32.
The following program (which bears little resemblance to my utility) demonstrates my new function - GetDiskFreeSpaceFAT32. You can download it by clicking here.
Hope you find this useful!