From: "Angus Johnson" Subject: Re: FAT and cluster size Date: 12 Jun 1999 00:00:00 GMT Message-ID: <7js8ma$bm116@forums.borland.com> References: <7jor8m$8kq38@forums.borland.com> Organization: Another Netscape Collabra Server User X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3155.0 Newsgroups: borland.public.delphi.winapi Deborah Pate wrote in message <7jor8m$8kq38@forums.borland.com>... >I'm trying to display drive usage, and in particular the amount of a >drive wasted by the FAT16 filing system. How can I determine the size >of the FAT and disc clusters under Windows 95? It doesn't seem to be >possible to use DeviceIOControl for this, except under NT. the GetDiskFreeSpace() function *is* reliable in deriving cluster size *if* it is a FAT16 drive. if it is a FAT32 drive, ie Win95b & Win98, then GetDiskFreeSpace() is not reliable. most FAT32 drives will be formatted to a 4k cluster size but *not all*. DeviceIOControl can be used to derive the cluster size, there are a couple of function codes which can be used... Get_ExtDPB and Get_ExtFreeSpace. see http://msdn.microsoft.com/library/sdkdoc/winbase/fat32_3fow.htm http://msdn.microsoft.com/library/sdkdoc/winbase/fat32_6y40.htm and http://www.undu.com/Articles/980525d.html to make a long story shorter... using Get_ExtFreeSpace is a little simpler (see my UNDU article) however there seems to be a bug with it when more than one hard drive resides on the local machine. i now use Get_ExtDPB. i've cut out a bit of my own code which should do what you want on FAT32 drives... (as you will see i'm only interested in the cluster size returned by this function call - Cluster Size := BytesPerSector * SectorsPerCluster) type //DeviceIoControl registers structure... TDevIoCtl_Registers = Record Reg_EBX : DWord; Reg_EDX : DWord; Reg_ECX : DWord; Reg_EAX : DWord; Reg_EDI : DWord; Reg_ESI : DWord; Reg_Flags : DWord; end; {the following structure def. thanks to : Geir Wikran - kran@online.no } TExtDPB = packed record { Extended Drive Parameter Block for FAT32: } DriveNumber : Byte; { Drive number (0=A, 1=B, and so } UnitNumber : Byte; { Drive unit number on device } SectorSize : Word; { Size of each sector in } ClusterMask : Byte; { Number of sectors per cluster minus } ClusterShift : Byte; { Number of sectors per cluster as power of 2. } FirstFAT : Word; { First sector for the File Allocation Table. } FATCount : Byte; { Number of FATs on the } RootEntries : Word; { Number of entries in root y. } FirstSector : Word; { First sector of the first } MaxCluster : Word; { Number of clusters on drive plus } { Field is undefined for FAT32 } FATSize : Word; { Number of sectors occupied by each } { Zero indicates a FAT32 } { Use ExtFATSize for FAT32 } DirSector : Word; { First sector for the root y. } { Field is undefined for FAT32 } Reserved2 : DWord; MediaID : Byte; { Media descriptor for the } Reserved : Byte; Reserved3 : DWord; NextFree : Word; { Most recently allocated cluster. Cluster at } { which to start search for free ters. } ExtFreeCount : DWord; { Number of free clusters on the } { FFFFFFFF if the number is } ExtFlags : Word; { Flags describing the } { bits 0-3: 0-based number of active } { bits 4-6: } { bit 7: FAT mirroring enabled if bit cleared } { bits 8-15: } ExtFSInfoSec : Word; { Sector containing information about the file } { system in TBifFATBootFSInfo ure. } { This field is set to 0FFFFh if there is } { FileSysInfo sector. Otherwise, this ue } { must be non-zero and less than the reserved } { sector } ExtBkUpBootSec : Word; { Sector containing the backup boot tor. } { This field is set to 0FFFFh if there is } { backup boot sector. Otherwise, this ue } { must be non-zero and less than the reserved } { sector } ExtFirstSector : DWord; { First sector of the first } ExtMaxCluster : DWord; { Number of clusters on drive plus } ExtFATSize : DWord; { Number of sectors occupied by each } ExtRootCluster : DWord; { First cluster in the root y. } ExtNextFree : DWord; { Most recently allocated cluster. Cluster at } { which to start search for free ters. } end; TDPBWithSize = packed record dpbSize: word; dpb : TExtDPB; end; {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} //My Delphi implimentation of - Int 21h Function 7302h Get_ExtDPB (FAT32) //to get cluster size... {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} function GetClusterSizeFAT32(Drive: PChar; var SperC, BperS: integer): boolean; const VWIN32_DIOC_DOS_DRIVEINFO = 6; var DevIoHandle : THandle; BytesReturned : DWord; Reg : TDevIoCtl_Registers; DPBWithSize: TDPBWithSize; DriveNum: DWord; begin DriveNum := byte(Drive^) - ord('@'); result := false; FillChar(DPBWithSize, sizeof(TDPBWithSize),0); FillChar(Reg, sizeof(TDevIoCtl_Registers),0); with Reg do begin reg_EAX := $7302; reg_EDX := DriveNum; //DS:DX Reg_EDI := DWord(@DPBWithSize); //ES:DI reg_ECX := sizeof(TDPBWithSize); reg_Flags := $00000001; //set carry flag to assume error. end; DevIoHandle := CreateFile('\\.\vwin32',0,0,nil,0,FILE_FLAG_DELETE_ON_CLOSE,0); if DevIoHandle <> Invalid_Handle_Value then begin result := DeviceIoControl(DevIoHandle, VWIN32_DIOC_DOS_DRIVEINFO, @Reg, SizeOf(Reg), @Reg, SizeOf(Reg), BytesReturned, nil); CloseHandle(DevIoHandle); if result and (Reg.reg_Flags and $1 = $0) then with DPBWithSize.dpb do begin BperS := SectorSize; SperC := ClusterMask+1; result := true; end; end; end; {GetClusterSizeFAT32} {=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=} Note: check in the initialization section (or formcreate method) if it is Win95b or later version of window as this function will *not* work on Win95a. var VI: TOsVersionInfo; begin // First check if Win95 OSR2 is running ... VI.dwOSVersionInfoSize := SizeOf(VI); GetVersionEx(VI); with VI do IsOSR2 := (LoWord(dwBuildNumber) > 1000) and (dwPlatformID = VER_PLATFORM_WIN32_WINDOWS); hope this helps aj