/////////////////////////////////////////////////////////////////////////////
// CClusterSize
// ------------
// This class can be used to find the cluster size on any Windows95 or 98
// computers. I have not been able to test it under Windows NT, but my guess
// is that it wouldn't work, or wouldn't be applicable.
//
// Author: Daniel Hirsch
// danielh@comports.com
//
// You may use this code freely, but please keep my name and email address
// with it. I also request that if you do use it, send me some email and
// tell me so. I spent quite a while figuring this out, so I would love
// to hear if anybody appreciates my work.
/////////////////////////////////////////////////////////////////////////////
// ClusterSize.cpp: implementation of the CClusterSize class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ClusterSize.h"
#include <ctype.h> // for isalpha()
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CClusterSize::CClusterSize()
{
m_strDrive = "";
}
CClusterSize::CClusterSize(CString strDrive)
{
m_strDrive = "";
SetDrive(strDrive);
}
CClusterSize::~CClusterSize()
{
}
/////////////////////////////////////////////////////////////////////////////
// SetDrive
// --------
// Sets the current drive to strDrive. strDrive should be in the form of
// C:\ for the class to get the cluster size on drive C. In order to get the
// cluster size of the drive, you should either pass the drive to the constructor
// or call this function before calling GetClusterSize().
//
// Returns: true if the string is a valid path format (does not check to see
// if the drive is valid), otherwise false.
/////////////////////////////////////////////////////////////////////////////
bool CClusterSize::SetDrive(CString strDrive)
{
TRACE("SetDrive passed the following parameter: %s", strDrive);
if(strDrive.GetLength() < 3)
{
TRACE("Drive length is less than 3, returning false\n");
return false;
}
if(!isalpha(strDrive[0]))
{
TRACE("First character of drive string is not alpha\n");
return false;
}
if(strDrive[1] != ':')
{
TRACE("Second character of drive string is not :\n");
return false;
}
if(strDrive[2] != '\\')
{
TRACE("Third character of drive string is not \\\n");
return false;
}
m_strDrive = strDrive;
return true;
}
/////////////////////////////////////////////////////////////////////////////
// GetClusterSize
// --------------
// Determines the cluster size for the current drive, which is set either using
// SetDrive or the second constructor. It uses the DeviceIoControl to set and
// poll the registers to execute Int 21h Function 7303h which is only valid
// if the system is running OSR2 or greater.
/////////////////////////////////////////////////////////////////////////////
DWORD CClusterSize::GetClusterSize()
{
if(m_strDrive.IsEmpty())
return 0;
bool OSR2 = false;; //Running OSR2 or not
OSVERSIONINFO os;
DWORD SectorsPerCluster;
DWORD BytesPerSector;
DWORD BytesPerCluster;
// determine the OS version
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;
}
//If it's not OSR2, this is easy
if(!OSR2)
{
GetDiskFreeSpace((LPCTSTR)m_strDrive,&SectorsPerCluster,
&BytesPerSector,NULL,NULL);
BytesPerCluster = SectorsPerCluster * BytesPerSector;
return BytesPerCluster;
}
else // otherwise, use the int 21h function
{
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);
// check the error status
if(!bResult || (reg.reg_Flags & 0x0001) )
{
return 0;
}
else
{
BytesPerCluster = spc.ExtFree_SectorsPerCluster * spc.ExtFree_BytesPerSector;
return BytesPerCluster;
}
}
}
评论0