📄 fatsa.cxx
字号:
Routine Description:
This routine computes the starting cluster number of the file described
by 'FileName' by tracing through the directories leading to the file.
Arguments:
FullPathFileName - Supplies a full path file name that starts with
a '\' (i.e. no drive spec).
Return Value:
The starting cluster for the file or 1 if the file is not found or
0xFFFFFFFF if there was an error.
--*/
{
CHNUM i, j, l;
DSTRING component;
ULONG clus;
FAT_DIRENT the_dirent;
PFILEDIR filedir;
PFAT_DIRENT dirent;
HMEM hmem;
PFATDIR _fat_dir;
UCHAR FatType;
DebugAssert(_dir || _dirF32);
if (_dir) {
_fat_dir = _dir;
FatType = FAT_TYPE_EAS_OKAY;
} else {
_fat_dir = _dirF32;
FatType = FAT_TYPE_FAT32;
}
DebugAssert(_fat);
filedir = NULL;
if (!Hmem) {
Hmem = &hmem;
}
if (DirEntry) {
dirent = DirEntry;
} else {
dirent = &the_dirent;
}
l = FullPathFileName->QueryChCount();
for (i = 0; i < l && FullPathFileName->QueryChAt(i) != '\\'; i++) {
/* NOTHING */
}
if (i == l) {
return 0xFFFFFFFF;
}
if (i == l - 1) { // root directory
return 0;
}
j = ++i;
for (; i < l && FullPathFileName->QueryChAt(i) != '\\'; i++) {
/* NOTHING */
}
if (!component.Initialize(FullPathFileName, j, i - j) ||
!component.Strupr()) {
return 1;
}
if (!dirent->Initialize(_fat_dir->SearchForDirEntry(&component), FatType)) {
return 1;
}
if (!(clus = dirent->QueryStartingCluster())) {
return 0;
}
while (i < l) {
if (!filedir &&
!(filedir = NEW FILEDIR)) {
return 0xFFFFFFFF;
}
if (!Hmem->Initialize() ||
!filedir->Initialize(Hmem, _drive, this, _fat, clus)) {
return 0xFFFFFFFF;
}
if (!filedir->Read()) {
return 1;
}
j = ++i;
for (; i < l && FullPathFileName->QueryChAt(i) != '\\'; i++) {
}
if (!component.Initialize(FullPathFileName, j, i - j) ||
!component.Strupr()) {
return 0xFFFFFFFF;
}
if (!dirent->Initialize(filedir->SearchForDirEntry(&component), FatType))
{
return 1;
}
if (!(clus = dirent->QueryStartingCluster())) {
return 1;
}
}
if (Directory) {
if (filedir) {
*Directory = filedir;
if (DeleteDirectory) {
*DeleteDirectory = TRUE;
}
} else {
*Directory = _dir;
if (DeleteDirectory) {
*DeleteDirectory = FALSE;
}
}
} else {
DELETE(filedir);
}
return clus;
}
VOID
FAT_SA::Destroy(
)
/*++
Routine Description:
This routine cleans up the local data in the fat super area.
Arguments:
None.
Return Value:
None.
--*/
{
DELETE(_fat);
DELETE(_dir);
DELETE(_dirF32);
}
FATTYPE
FAT_SA::ComputeFatType(
) CONST
/*++
Routine Description:
Given the total number of clusters on the disk, this routine computes
whether the FAT entries will be 12, 16, or 32 bits each.
Arguments:
ClusterCount - Supplies the number of clusters on the disk.
Return Value:
SMALL - A 12 bit FAT is required.
LARGE16 - A 16 bit FAT is required.
LARGE32 - A 32 bit FAT is required.
--*/
{
PARTITION_SYSTEM_ID id;
id = ComputeSystemId();
if (id == SYSID_FAT12BIT) {
return(SMALL);
} else if (id == SYSID_FAT32BIT) {
return(LARGE32);
} else {
return(LARGE16);
}
}
PARTITION_SYSTEM_ID
FAT_SA::ComputeSystemId(
) CONST
/*++
Routine Description:
This routine computes the system id for a FAT file system with
the given number of sectors.
Arguments:
None.
Return Value:
The correct system id for this partition.
--*/
{
#if 1
SECTORCOUNT disk_size;
switch (_drive->QueryMediaType()) {
case F3_720_512:
case F5_360_512:
case F5_320_512:
case F5_320_1024:
case F5_180_512:
case F5_160_512:
#if defined(FE_SB) && defined(_X86_)
case F5_720_512:
case F5_640_512:
case F3_640_512:
case F3_1Pt2_512:
case F8_256_128:
case F5_1Pt23_1024:
case F3_1Pt23_1024:
#endif
case F5_1Pt2_512:
case F3_1Pt44_512:
case F3_2Pt88_512:
case F3_20Pt8_512:
return SYSID_FAT12BIT;
case F3_120M_512:
return SYSID_FAT16BIT;
}
disk_size = QueryVirtualSectors();
if (_ft == INVALID_FATTYPE ) {
//
// If the _ft member is not initialized,
// use the sector count to determine the
// partition class. Note that this method of
// determining the partition class is not absolutely
// fool-proof but this method works at least as good
// as what we have in the past. The proper way of doing
// the system id computation is to make sure that
// the fat type is always computed before the
// partition id and always uses the fat type and,
// in some cases, the sector count to determine the
// partition id.
//
if (disk_size < CSEC_FAT32BIT) {
if ( disk_size < 65536 ) {
return SYSID_FAT16BIT;
} else {
return SYSID_FAT32MEG;
}
} else {
return SYSID_FAT32BIT;
}
} else {
if (_ft == LARGE32 ) {
return SYSID_FAT32BIT;
} else {
if ( disk_size < 65536 ) {
return SYSID_FAT16BIT;
} else {
return SYSID_FAT32MEG;
}
}
}
if (_drive->IsSuperFloppy()) {
return SYSID_FAT16BIT; // just return something other than SYSID_NONE
}
return SYSID_NONE;
#else // FUTURE_CODE
// BUGBUG for EFI we need to handle this differently
return 0xEF;
#endif // FUTURE_CODE
}
#if !defined(_SETUP_LOADER_)
ULONG
FAT_SA::ComputeRootEntries(
) CONST
/*++
Routine Description:
This routine uses the size of the disk and a standard table in
order to compute the required number of root directory entries.
Arguments:
None.
Return Value:
The required number of root directory entries.
--*/
{
switch (_drive->QueryMediaType()) {
case F3_720_512:
case F5_360_512:
case F5_320_512:
case F5_320_1024:
case F5_180_512:
case F5_160_512:
#if defined(FE_SB) && defined(_X86_)
case F5_720_512:
case F5_640_512:
case F3_640_512:
#endif
return 112;
case F5_1Pt2_512:
case F3_1Pt44_512:
#if defined(FE_SB) && defined(_X86_)
case F3_1Pt2_512:
#endif
return 224;
case F3_2Pt88_512:
case F3_20Pt8_512:
return 240;
#if defined(FE_SB) && defined(_X86_)
case F5_1Pt23_1024:
case F3_1Pt23_1024:
return 192;
case F8_256_128:
return 68;
case RemovableMedia:
return 512;
#endif
}
return 512;
}
USHORT
FAT_SA::ComputeSecClus(
IN SECTORCOUNT Sectors,
IN FATTYPE FatType,
#if defined(FE_SB) && defined(_X86_)
IN MEDIA_TYPE MediaType,
IN ULONG SectorSize
#else
IN MEDIA_TYPE MediaType
#endif
)
/*++
Routine Description:
This routine computes the number of sectors per cluster required
based on the actual number of sectors.
Arguments:
Sectors - Supplies the total number of sectors on the disk.
FatType - Supplies the type of FAT.
MediaType - Supplies the type of the media.
Return Value:
The required number of sectors per cluster.
--*/
{
USHORT sec_per_clus;
SECTORCOUNT threshold;
if (FatType == LARGE32) {
if (Sectors >= 64*1024*1024) {
sec_per_clus = 64; /* over 32GB -> 32K */
} else if (Sectors >= 32*1024*1024) {
sec_per_clus = 32; /* up to 32GB -> 16K */
} else if (Sectors >= 16*1024*1024) {
sec_per_clus = 16; /* up to 16GB -> 8K */
} else {
sec_per_clus = 8; /* up to 8GB -> 4K */
}
return sec_per_clus;
}
if (FatType == SMALL) {
threshold = MIN_CLUS_BIG;
sec_per_clus = 1;
} else {
threshold = MAX_CLUS_BIG;
sec_per_clus = 1;
}
while (Sectors >= threshold) {
sec_per_clus *= 2;
threshold *= 2;
}
switch (MediaType) {
case F5_320_512:
case F5_360_512:
case F3_720_512:
case F3_2Pt88_512:
#if defined(FE_SB) && defined(_X86_)
case F5_640_512:
case F3_640_512:
case F5_720_512:
#endif
sec_per_clus = 2;
break;
case F3_20Pt8_512:
#if defined(FE_SB)
case F3_128Mb_512:
#if defined(_X86_)
case F8_256_128:
#endif
#endif
sec_per_clus = 4;
break;
#if defined(FE_SB)
case F3_230Mb_512:
sec_per_clus = 8;
break;
#endif
default:
break;
}
return sec_per_clus;
}
#endif // _SETUP_LOADER_
BOOLEAN
FAT_SA::IsValidString(
IN PCWSTRING String
)
/*++
Routine Description:
This routine determines whether or not the given null-terminated string
has any invalid characters in it.
Arguments:
String - Supplies the string to validate.
Return Value:
FALSE - The string contains invalid characters.
TRUE - The string is free from invalid characters.
Notes:
The list of invalid characters is stricter than HPFS requires.
--*/
{
CHNUM i, l;
l = String->QueryChCount();
for (i = 0; i < l; i++) {
if (String->QueryChAt(i) < 32) {
return FALSE;
}
switch (String->QueryChAt(i)) {
case '*':
case '?':
case '/':
case '\\':
case '|':
case ',':
case ';':
case ':':
case '+':
case '=':
case '<':
case '>':
case '[':
case ']':
case '"':
case '.':
return FALSE;
}
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -