📄 rfatsa.cxx
字号:
USHORT sec_per_clus = 0; // Sectors per cluster
ULONG cluster_size = 0; // Size of each cluster in bytes.
VALIDATION_STATUS result; // Return code from ValidateClusterSize.
ULONG fat_size; // Size of each fat in number of
// sectors.
#if DBG
BIG_INT data_offset; // the offset to first data cluster
#endif
//
// Call DosSaSeetBpb to perform some very rudimentary bpb setup.
//
if (!DosSaSetBpb()) {
DebugPrintTrace(("Could not do a REAL_FAT_SA::DosSaSetBpb.\n"));
return FALSE;
}
//
// A volume cannot have more than 4gig sectors.
//
DebugAssert(_drive->QuerySectors().GetHighPart() == 0);
sectors = _drive->QuerySectors().GetLowPart();
sector_size = _drive->QuerySectorSize();
PCHAR fattypestr;
if (!BackwardCompatible) {
//
// If BackwardCompatible is false, then the user must have
// specified the /fs:FAT32 switch or the existing volume
// must be a FAT32 volume when a quik format is performed.
//
_ft = LARGE32;
fattypestr = "FAT32";
} else {
//
// At this moment, we don't know whether FAT16 or FAt12
// is appropriate for this volume.
//
_ft = INVALID_FATTYPE;
fattypestr = "FAT16/12";
}
if (_drive->QuerySectors().GetHighPart() != 0) {
Message->Set(MSG_FMT_VOL_TOO_BIG);
Message->Display("%s", fattypestr);
return FALSE;
}
//
// The boot area of a FAt32 volume is at least 32 sectors large
// and at least 32 * 512 bytes in size.
//
if (_ft == LARGE32) {
_sec_per_boot = max((32 * 512) / sector_size,32);
}
//
// Set up the number of reserved sectors and the number of
// FATs in the boot sector. Note that ValidateClusterSize and
// ComputeDefaultClusterSize depend on these values so don't move
// the following lines to anywhere else.
//
_sector_zero.Bpb.ReservedSectors = (USHORT)_sec_per_boot;
_sector_zero.Bpb.Fats = 2;
//
// Try to honor the cluster size provided by the user.
//
if (ClusterSize) {
//
// If the cluster size specified by the user is not
// of the form sector_size * 2^n where n is an integer
// then choose a cluster size which is of the form 2^n
// * sector size and is just bigger than the cluster
// size specified by the user.
//
cluster_size = sector_size;
sec_per_clus = 1;
//
// Check that the user specified cluster size is at least as big as
// the minimum allowed cluster size as determined by the sector size.
//
if (ClusterSize < cluster_size) {
Message->Set(MSG_FMT_CLUSTER_SIZE_TOO_SMALL_MIN);
Message->Display("%u", sector_size);
return FALSE;
}
while (cluster_size < ClusterSize && sec_per_clus < 256) {
cluster_size *= 2;
sec_per_clus *= 2;
}
//
// Make sure that the cluster size provided by the user
// is not too big.
//
if ( sec_per_clus > MaxSecPerClus) {
Message->Set(MSG_FMT_CLUSTER_SIZE_TOO_BIG);
Message->Display("%s", fattypestr);
return FALSE;
}
//
// Issue a warning if the cluster size computed is not
// equal to the cluster size provided by the user.
//
if ( cluster_size != ClusterSize ) {
Message->Set(MSG_FMT_CLUSTER_SIZE_MISMATCH);
Message->Display("%u", cluster_size);
if (!Message->IsYesResponse(FALSE)) {
return FALSE;
}
}
}
_sector_zero.Bpb.RootEntries = (USHORT)ComputeRootEntries();
if (cluster_size) {
//
// Make sure that the cluster size is valid for a
// FAT volume.
//
result = ValidateClusterSize( cluster_size,
sectors,
sector_size,
NUMBER_OF_FATS,
&_ft,
&fat_size,
&_ClusterCount );
//
// Tell the user the cluster size specified is invalid
// for the FAT type chosen.
//
switch (result) {
case TOO_SMALL:
Message->Set(MSG_FMT_CLUSTER_SIZE_TOO_SMALL);
Message->Display("%s", fattypestr);
return FALSE;
case TOO_BIG:
Message->Set(MSG_FMT_CLUSTER_SIZE_TOO_BIG);
Message->Display("%s", fattypestr);
return FALSE;
}
}
if (BackwardCompatible && _ft == INVALID_FATTYPE) {
//
// Use CSEC_16BIT as a cut-off point for determining
// whether the FAT should be 16-bit or 12-bit.
//
if (sectors < CSEC_FAT16BIT) {
_ft = SMALL;
} else {
_ft = LARGE16;
}
}
//
// If the user doesn't provide a cluster size, we have
// to compute a default cluster size.
//
if (!cluster_size) {
cluster_size = ComputeDefaultClusterSize( sectors,
sector_size,
_sector_zero.Bpb.ReservedSectors,
NUMBER_OF_FATS,
_drive->QueryMediaType(),
_ft,
&fat_size,
&_ClusterCount);
if (cluster_size == 0) {
Message->Set(MSG_FMT_VOL_TOO_SMALL);
Message->Display("%s", fattypestr);
return FALSE;
} else if (cluster_size > 128 * sector_size) {
Message->Set(MSG_FMT_VOL_TOO_BIG);
Message->Display("%s", fattypestr);
return FALSE;
}
}
//
// Check for volume limits.
//
// If volume is > 32Gig, say we won't do FAT
// If cluster size is 64k warn about compatibility issues
//
if((sectors / ((1024 * 1024) / sector_size)) > (32 * 1024)) {
Message->Set(MSG_FMT_VOL_TOO_BIG);
Message->Display("%s", fattypestr);
return FALSE;
}
if(cluster_size >= (64 * 1024)) {
Message->Set(MSG_FMT_CLUSTER_SIZE_64K);
Message->Display("");
if (!Message->IsYesResponse(TRUE)) {
return FALSE;
}
}
//
// Compute the number of sectors per clusters.
//
_sector_zero.Bpb.SectorsPerCluster = (UCHAR) (cluster_size / sector_size);
if (_ft == LARGE32) {
_sector_zero.Bpb.SectorsPerFat = 0;
_sector_zero.Bpb.BigSectorsPerFat = fat_size;
} else {
_sector_zero.Bpb.SectorsPerFat = (USHORT)fat_size;
_sector_zero.Bpb.BigSectorsPerFat = 0;
}
if (_ft == SMALL) {
memcpy(_sector_zero.SystemIdText, "FAT12 ", cSYSID);
} else if (_ft == LARGE32) {
memcpy(_sector_zero.SystemIdText, "FAT32 ", cSYSID);
} else {
memcpy(_sector_zero.SystemIdText, "FAT16 ", cSYSID);
}
memcpy(_sector_zero.Label, "NO NAME ", cLABEL);
_sector_zero.CurrentHead = 0;
//
// Initialize the additional fields in the FAT32 boot
// sector.
//
if (_ft == LARGE32) {
//
// Recompute RootEntries, _sec_per_boot, and ReservedSectors
// in case _ft changes
//
_sector_zero.Bpb.RootEntries = (USHORT)ComputeRootEntries();
_sec_per_boot = max((32 * 512) / _drive->QuerySectorSize(), 32);
_sector_zero.Bpb.ReservedSectors = (USHORT)_sec_per_boot;
_sector_zero.Bpb.ExtFlags = 0;
_sector_zero.Bpb.FS_Version = 0;
_sector_zero.Bpb.RootDirStrtClus = 2;
_sector_zero.Bpb.FSInfoSec = 1;
_sector_zero.Bpb.BkUpBootSec = max(6, (USHORT)((6 * 512) / sector_size));
DebugAssert(_AdditionalReservedSectors != MAXULONG);
_sec_per_boot += _AdditionalReservedSectors;
_sector_zero.Bpb.ReservedSectors = (USHORT)_sec_per_boot;
}
#if DBG
data_offset = ((BIG_INT)(fat_size*NUMBER_OF_FATS + _sec_per_boot))*sector_size +
(_sector_zero.Bpb.RootEntries*BytesPerDirent);
DebugAssert (_drive->IsFloppy() ||
((data_offset.GetLowPart() & (FAT_FIRST_DATA_CLUSTER_ALIGNMENT - 1)) == 0));
#endif
return TRUE;
#endif // _SETUP_LOADER_
}
#if defined( _AUTOCHECK_ ) || defined( _EFICHECK_ )
#define LOCALE_STHOUSAND 0x0000000F // thousand separator
typedef unsigned int UINT;
typedef unsigned int *PUINT;
typedef unsigned int *LPUINT;
int
ChkGetLocaleInfoW(
UINT Locale,
UINT LCType,
LPWSTR lpLCData,
int cchData)
{
//
// For AUTOCHK we do not do thousand seperators. The NLS APIs are not
// around, and the registry isn't really set up either so there is no standard
// language place available to determine what the thousand seperator is.
//
return 0;
}
UINT
ChkGetUserDefaultLCID(void)
{
return 0;
}
#else
#define ChkGetLocaleInfoW GetLocaleInfoW
#define ChkGetUserDefaultLCID GetUserDefaultLCID
#endif
VOID
InsertSeparators(
LPCWSTR OutWNumber,
char * InANumber,
ULONG Width
)
{
WCHAR szSeparator[10];
WCHAR Separator;
LPWSTR lpWNumber;
lpWNumber = (LPWSTR)OutWNumber;
if (0 != ChkGetLocaleInfoW(
ChkGetUserDefaultLCID(),
LOCALE_STHOUSAND,
szSeparator,
10
))
{
Separator = szSeparator[0];
}
else
{
Separator = L'\0'; // If we can't get the thousand separator, do not use one.
}
WCHAR Buffer[100];
ULONG cchNumber = strlen((LPCSTR)InANumber);
UINT Triples = 0;
Buffer[99] = L'\0';
PWCHAR pch = &Buffer[98];
while (cchNumber > 0)
{
*pch-- = InANumber[--cchNumber];
++Triples;
if ( (Separator != L'\0') && (0 == (Triples % 3)) && (cchNumber > 0) )
{
*pch-- = Separator;
}
}
cchNumber = wcslen((pch + 1));
if(cchNumber < Width) {
UINT i;
cchNumber = Width - cchNumber;
for(i = 0; i < cchNumber; i++) {
lpWNumber[i] = L' ';
}
} else {
cchNumber = 0;
}
wcscpy(lpWNumber + cchNumber, pch + 1); // the Number buffer better be able to handle it!
}
#if 0
BOOLEAN
REAL_FAT_SA::Create(
IN PCNUMBER_SET BadSectors,
IN OUT PMESSAGE Message,
IN PCWSTRING Label,
IN BOOLEAN BackwardCompatible,
IN ULONG ClusterSize,
IN ULONG VirtualSize
)
/*++
Routine Description:
This routine initializes the FAT file system.
Arguments:
BadSectors - Supplies a list of the bad sectors on the volume.
Message - Supplies an outlet for messages.
Label - Supplies an optional label.
Return Value:
FALSE - Failure.
TRUE - Success.
Notes: FAT32 root directory uses the FILEDIR structure as
opposed to the ROOTDIR structure used in FAT16/12.
--*/
{
#if defined( _SETUP_LOADER_ )
return FALSE;
#else
USHORT sector_size; // Number of bytes per sector, this is directly
// queried from the drive
SECTORCOUNT sec_per_root; // Number of sectors for the root directory
CONT_MEM cmem; // This acts as a pointer to various
PUSHORT p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -