Determining Cluster Size

Occasionally, your program may need more low-level information about the computer it's running on than is readily available with MFC. Usually, this can be solved by a simple API call, which, with a small amount of practice and patience, can become as easy to deal with as MFC. This appears to be the case with determining the cluster size of a local hard disk. As you may know, hard drives are divided up into partitions, which can be in either the FAT16 or FAT32 format on a Windows/DOS machine. (There are more, including those used by Windows NT and other operating systems) Files in the partition are stored in clusters, which are a set size depending on the type (16 or 32) and the size of the partition. The number of clusters a file uses can be figured using this formula: File Size / Cluster Size, rounded up. For example, a 20,000 byte file on a partition with 4,096 byte clusters would use 5 clusters becuase 20000 / 4096 = 4.8, rounded = 5.

Problem

As mentioned earlier, it would seem that getting the cluster size under Windows95/98 is an easy task. The Win32 API provides the ::GetDiskFreeSpace() function, which returns the cluster size of the drive you pass to it, along with other information about it. However, things aren't that simple when you start dealing with newer hardware. As of Windows95 OSR2, there is a new partition format available, called FAT32. FAT32 breaks FAT16's 2GB partition size limit, which makes it particularly useful for today's high capacity drives. However, the ::GetDiskFreeSpace() function does not return correct values for partitions larger than 2GB. There is a replacement function provided in the KERNEL32.DLL included with OSR2+ (including Windows98) called ::GetDiskFreeSpaceEx(). However, this function was made to simplify getting disk space values and no longer returns cluster size as one of its parameters. So begins the ponderence of how to get the cluster size on drives larger than 2GB.

Solution

Unfortunately, there is no other API function to deal with the disk like this. Instead, you must delve deeper into the operating system to find the answer. Hidden in the volumes of documentation with Developer Studio is a list of new FAT32 functions. But these are not functions like you're used to seeing, unless you are an experienced Assembly language programmer. The specific function we will make use of is Int 21h Function 7303h Get_ExtFreeSpace (FAT32) which you can lookup in Developer Studio. This is an interrupt call to the operating system that returns a structure containing lots of information about the disk, including cluster size. But implementing this function is not what you might call a simple task. Rather, you need to make a few definitions, and then do some rather low-level messing around. But, because you are reading this it obviously means I have gone through this work for you, and you get this function wrapped up in a nice class and member function. But if you would like to know more about it, read on. If not, skip to the end and download!

First, you need a few defintions to work with. Part of making an Int 21 call invloves setting some CPU registers explicitly, so we need a structure to work with. Although it would seem these structures *should* be defined somewhere, I could not find them, so I put them in the .H file. The following allows us to work with all the applicable registers:

typedef struct _DIOC_REGISTERS 
{
	DWORD reg_EBX;
	DWORD reg_EDX;
	DWORD reg_ECX;
	DWORD reg_EAX;
	DWORD reg_EDI;
	DWORD reg_ESI;
	DWORD reg_Flags;
} DIOC_REGISTERS, *PDIOC_REGISTERS;
Next, we need to define the strucure the function will return the data to use in. It needs to be packed on 1 byte boundaries, and we also define the DeviceIoControl (more on this later) parameter constant which again, was *supposed* to be defined already.
#pragma pack(1)
typedef struct _ExtGetDskFreSpcStruc
{
	WORD ExtFree_Size;
	WORD ExtFree_Level;
	DWORD ExtFree_SectorsPerCluster;
	DWORD ExtFree_BytesPerSector;
	DWORD ExtFree_AvailableClusters;
	DWORD ExtFree_TotalClusters;
	DWORD ExtFree_AvailablePhysSectors;
	DWORD ExtFree_TotalPhysSectors;
	DWORD ExtFree_AvailableAllocationUnits;
	DWORD ExtFree_TotalAllocationUnits;
	DWORD ExtFree_Rsvd[2];
} ExtGetDskFreSpcStruc, *pExtGetDskFreSpcStruc;
#pragma pack()
Thats it for definitions. Now the implementation. One of the first things to do is decide if we even need to use the Int 21 function. If this is NOT an OSR2+ machine, we can still use the ::GetDiskFreeSpace() function, and save some work. The following checks the OS version and sets the flag for OSR2.
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&os);
if(os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
	if(LOWORD(os.dwBuildNumber) > 1000)		// is it OSR2 or newer?
		OSR2 = true;
}
Now, if it turns out that this IS an OSR2+ machine, we have to use the Int 21 function. To do this, first you have to create a device handle to the VWIN32 device, which basically makes all this possible. It creates a sort of virtual machine that these calls can be made though, behaving much more like a DOS environment than Windows. Once that device is created, you initialize the registers structure to tell it exactly what to do and where to put the data. The EAX member is like using the AX register, so the actual function number gets put in there (0x7303). Setting the structure does not change the CPU registers though. This happens once DeviceIoControl() is called. What DeviceIoControl() does is perform the Interrupt operation after copying our registers structure. It then takes the state of the CPU registers AFTER the call, and returns them in the same structure.
HANDLE hDevice;
DIOC_REGISTERS reg;
ExtGetDskFreSpcStruc spc;
BOOL bResult;
DWORD cb;

const char *sz[] = { (LPCTSTR) m_strDrive };
spc.ExtFree_Level = 0;  //Must initialize before using the structure
hDevice = CreateFile("\\\\.\\vwin32",0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);

// initialize the registers to call the correct function
reg.reg_EDI = (DWORD)&spc;
reg.reg_ECX = sizeof(ExtGetDskFreSpcStruc);
reg.reg_EDX = (DWORD)(LPCTSTR)m_strDrive;
reg.reg_EAX = 0x7303;
reg.reg_Flags = 0x0001;

// copies the structure into the registers, performs the function,
// and returns the new registers in the structure
bResult = DeviceIoControl(hDevice, VWIN32_DIOC_DOS_DRIVEINFO,
	®, sizeof(reg), ®, sizeof(reg), &cb, 0);
CloseHandle(hDevice);
More important than the new register states, is if the operation went correctly, our ExtGetDskFreSpcStruc should be filled with correct values. All that's left to do if find the cluster size by multiplying the Sectors Per Cluster by the Bytes per Sector. (Of course, they couldn't even make THAT easy on us)

Conclusion

That's about it for getting the cluster size. However, I DID leave out some code on this page. In order to use this, you SHOULD download the full code (come on, it's only 2 files). There is also a simply sample application that shows an easy way of implementing this using the class I created, CClusterSize. To use this in your project, simply add "ClusterSize.h" and "ClusterSize.cpp" to your project, include the .H file appropriately, use either the 1 or 2 step initialization (see the header file), and call GetClusterSize().

Download demo project - 13 KB

Download source - 4 KB



Comments

  • you can find the super clarisonic in myer

    Posted by iouwanzi on 06/06/2013 02:30am

    [url=http://www.miaclarisonicaustralia.org/]clarisonic mia[/url] vous vous rendrez probablement compte généralement le type ghd pink styler, à qui les rend étanches tête de cheveux ou de style et de défriser les cheveux crépus même.Nous ne sommes pas nécessairement à vous informer de vos solutions parce que j’ai consommera jamais. (Ouais, donner Document il temps de séché mes cheveux crépus en plein air et que j’ai des vagues saines alors zéro doivent avoir de tels dispositifs pour le personnel). [url=http://www.australiaclarisonic.com/clarisonic-classic]clarisonic classic[/url] Sur la photo précédemment mentionné, la chose est qu’il y a exclusivement un interrupteur marche/arrêt. Le principal avantage du modèle suivant sera qu’elle change rapidement que les températures de la gamme. Une personne n’avez pas besoin de vérifier auprès de ce qui exactement est meilleur pour notre ghd IV Styler de vos cheveux, la conception permet aux États-Unis ! La température moyenne autour de chaque ghd IV Styler est située à 180 ° d. Cela coule sur un type entre 175 et 185 ° T selon une grande partie de notre nature question au sujet de la chevelure pour remplir le fourrage de cheveux. [url=http://www.australiaclarisonic.com/clarisonic-pro]clarisonic pro[/url] Mon conjoint et j’ai très certainement besoin personne se produit et en outre choisir de me donner personnellement un Styler F HI-DEF en ce qui concerne la période des fêtes… donc si il l’homme devrions vraiment besoin pour gagner me réjoui, mon conjoint et moi obtenir la connexion pointe GHD Gold Styler et Document a parlé du fait que le Styler juste est au prix de 179 kilos, ainsi que la boîte proverbiale coûte 215 euros nuit gamme. (Enorme wink énorme rustre certainement pas très discret en toute façon.

    Reply
  • GetDiskFreeSpace still works on partitions > 2GB for cluster info...

    Posted by Legacy on 06/06/2003 12:00am

    Originally posted by: taby

    GetDiskFreeSpace still works on partitions > 2GB for cluster info... Just don't use it if you want a reliable result for the disk space.

    Reply
  • Who can solve the the trouble? I very very thank you!

    Posted by Legacy on 02/13/2003 12:00am

    Originally posted by: flying

    How can I get the position of cluster and sector where a file locate? I mean that I want to get the position of a file in a partition.But the position must use "cluster" and
    sector to appear.
    At last please use English to answer!Or I can't understand.

    Reply
  • DIOC

    Posted by Legacy on 01/05/2003 12:00am

    Originally posted by: Brian

    Read the 11th and 12th bytes of the MBR which is how many bytes are in each sector.

    Lets say its 512.

    then you have to read the 13th byte of the MBR which is how many sectors are in a cluster.

    lets say its 64.

    ByteClusterSize = 512 * 64 = 32768

    But either way, you would have to use VWIN32_DIOC unless you want to use some ASM

    Reply
  • Is it possible to see partition size?

    Posted by Legacy on 06/12/2002 12:00am

    Originally posted by: Ken

    Is it possible to see all drive partition sizes if one of the partition is not formatted (FAT-16, FAT-32, or NTFS)?

    Reply
  • Requirements

    Posted by Legacy on 06/04/2002 12:00am

    Originally posted by: knok

    Hello! May I know what is the requirement to compile/link the source code? Do I need Windows SDK? Thanks

    Regards,
    Kelly

    Reply
  • how to get the total hard disk space

    Posted by Legacy on 10/10/2001 12:00am

    Originally posted by: sujeet

    hi i m looking for code in C
    ot get the total hard disk space in a drive
    can u please send me the same.


    and also how to get the system up time
    a sample code for this also in C

    Reply
  • easier way?

    Posted by Legacy on 10/02/2001 12:00am

    Originally posted by: Robert

    Why not read the boot sector and get the cluster size from there?

    Reply
  • Re DeviceIoControl

    Posted by Legacy on 07/27/2001 12:00am

    Originally posted by: Farouk

    It would be very enlightening if you can wite a code that uses DeviceIoControl,to get the _EA_DEVICEPARAMETERS structure informations.
    I found some inline assembly code to do that.
    I am not familiar with assembly,and I wonder if it's possible to have the arguments of the function
    DeviceIoControl in order to call it.
    Thanks

    Reply
  • Re DeviceIoControl

    Posted by Legacy on 07/27/2001 12:00am

    Originally posted by: Farouk

    It would be very enlightening if you can wite a code that uses DeviceIoControl,to get the _EA_DEVICEPARAMETERS structure informations.
    I found some inline assembly code to do that.
    I am not familiar with assembly,and I wonder if it's possible to have the arguments of the function
    DeviceIoControl in order to call it.
    Thanks

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Targeted attacks and advanced threats are customized to infiltrate your unique IT infrastructure, evade conventional defenses, and remain hidden while stealing your corporate data. To detect these criminal intrusions, analysts and security experts agree that organizations should deploy advanced threat protection as part of an expanded security monitoring strategy. For this comparative analysis of breach detection systems, product analysis reports and comparative analysis reports are used to create the security …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds