📄 fatsachk.cxx
字号:
return TRUE;
}
// We need to re-initialize the fatsa object to include the whole
// super area
if (!Initialize(_drive, Message, TRUE)) {
Message->Set(MSG_CHK_NO_MEMORY);
Message->Display();
*ExitStatus = CHKDSK_EXIT_COULD_NOT_CHK;
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
if (!Read(Message)) {
Message->Set(MSG_CHK_NO_MEMORY);
Message->Display();
*ExitStatus = CHKDSK_EXIT_COULD_NOT_CHK;
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
// If the second bit of the dirty byte is set then
// also perform a full recovery of the free and allocated
// space.
if (dirty_byte & FAT_BPB_RESERVED_TEST_SURFACE) {
RecoverFree = TRUE;
RecoverAlloc = TRUE;
}
}
//
// NOTE that this check must follow the above "if (OnlyIfDirty)" because in the
// OnlyIfDirty case only the first part of the FAT_SA object is in memory
// until the above if gets executed.
//
if (QueryLength() <= SecPerBoot()) {
Message->Set(MSG_NOT_FAT);
Message->Display();
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
//
// The volume is not clean, so if we're autochecking we want to
// make sure that we're printing real messages on the console
// instead of just dots.
//
#if defined(_AUTOCHECK_)
if (Message->SetDotsOnly(FALSE)) {
Message->SetLoggingEnabled(FALSE);
if (NULL != DriveLetter) {
Message->Set(MSG_CHK_RUNNING);
Message->Display("%W", DriveLetter);
}
Message->Set(MSG_FILE_SYSTEM_TYPE);
Message->Display("%s", _ft == LARGE32 ? "FAT32" : "FAT");
Message->SetLoggingEnabled();
}
if (Message->IsInAutoChk()) {
ULONG timeout;
if (!VOL_LIODPDRV::QueryAutochkTimeOut(&timeout)) {
timeout = AUTOCHK_TIMEOUT;
}
if (timeout > MAX_AUTOCHK_TIMEOUT_VALUE)
timeout = AUTOCHK_TIMEOUT;
if (timeout != 0) {
if (dirty_byte & (FAT_BPB_RESERVED_DIRTY | FAT_BPB_RESERVED_TEST_SURFACE))
Message->Set(MSG_CHK_AUTOCHK_SKIP_WARNING);
else
Message->Set(MSG_CHK_USER_AUTOCHK_SKIP_WARNING);
Message->Display();
if (Message->IsKeyPressed(MSG_CHK_ABORT_AUTOCHK, timeout)) {
Message->SetLoggingEnabled(FALSE);
Message->Set(MSG_CHK_AUTOCHK_ABORTED);
Message->Display();
*ExitStatus = CHKDSK_EXIT_SUCCESS;
return TRUE;
} else {
Message->Set(MSG_CHK_AUTOCHK_RESUMED);
Message->Display();
}
} else if ((dirty_byte & (FAT_BPB_RESERVED_DIRTY | FAT_BPB_RESERVED_TEST_SURFACE))) {
Message->Set(MSG_CHK_VOLUME_IS_DIRTY);
Message->Display();
}
} else {
DebugAssert(Message->IsInSetup());
if (dirty_byte & (FAT_BPB_RESERVED_DIRTY | FAT_BPB_RESERVED_TEST_SURFACE)) {
Message->Set(MSG_CHK_VOLUME_IS_DIRTY);
Message->Display();
}
}
#endif // _AUTOCHECK_
//
// The BPB's Media Byte must be in the set accepted
// by the file system.
//
media_byte = QueryMediaByte();
#if defined(FE_SB) && defined(_X86_)
if ((media_byte != 0x00) && /* FMR */
(media_byte != 0x01) && /* FMR */
(media_byte != 0xf0) &&
#else
if ((media_byte != 0xf0) &&
#endif
(media_byte != 0xf8) &&
(media_byte != 0xf9) &&
#if defined(FE_SB) && defined(_X86_)
(media_byte != 0xfa) && /* FMR */
(media_byte != 0xfb) && /* FMR */
#endif
(media_byte != 0xfc) &&
(media_byte != 0xfd) &&
(media_byte != 0xfe) &&
(media_byte != 0xff)) {
SetMediaByte(_drive->QueryMediaByte());
}
// First print out the label and volume serial number.
// We won't bother printing this message under autocheck.
#if !defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ ) && !defined( _EFICHECK_ )
TIMEINFO timeinfo;
if ((QueryLabel(&label, &timeinfo) || label.Initialize("")) &&
label.QueryChCount() &&
timeinfo.QueryDate(&date) &&
timeinfo.QueryTime(&time)) {
Message->Set(MSG_VOLUME_LABEL_AND_DATE);
Message->Display("%W%W%W", &label, &date, &time);
}
#else
#if defined(_EFICHECK_)
if (QueryLabel(&label) && label.QueryChCount() > 0) {
Message->Set(MSG_VOLUME_LABEL_AND_DATE); // date is !!not!! displayed for EFI, since timeinfo is not implemented.
Message->Display("%W", &label);
}
#endif
#endif // !_AUTOCHECK_ && !_SETUP_LOADER_
if (volid = QueryVolId()) {
p = (PUSHORT) &volid;
Message->Set(MSG_VOLUME_SERIAL_NUMBER);
Message->Display("%04X%04X", p[1], p[0]);
}
// Validate the FAT.
if (_dirF32 == NULL)
_fat->Scrub(&changes);
if (changes) {
dofmsg(Message, &fmsg);
Message->Set(MSG_CHK_ERRORS_IN_FAT);
Message->Display();
}
//
// Make sure that the media type in the BPB is the same as at
// the beginning of the FAT.
//
if (QueryMediaByte() != _fat->QueryMediaByte()) {
#if defined(FE_SB) // MO & OEM FAT Support
BOOLEAN bPrintError = TRUE;
#if defined(_X86_)
if (IsPC98_N()) {
// PC98 Nov.01.1994
// to help the early NEC DOS
if(_drive->QueryMediaType() == FixedMedia &&
QueryMediaByte() == 0xf8 && _fat->QueryMediaByte() == 0xfe) {
bPrintError = FALSE;
}
}
#endif
if (bPrintError == TRUE &&
(_drive->QueryMediaType() == F3_128Mb_512 ||
_drive->QueryMediaType() == F3_230Mb_512 )) {
// We won't to recognized as illegal in following case.
//
// Some OpticalDisk might have 0xf0 as media in BPB, but it also has 0xF8 in FAT.
//
if (QueryMediaByte() == 0xf0 && _fat->QueryMediaByte() == 0xf8) {
bPrintError = FALSE;
}
}
if( bPrintError ) {
#endif
dofmsg(Message, &fmsg);
Message->Set(MSG_PROBABLE_NON_DOS_DISK);
Message->Display();
if (!Message->IsYesResponse(FALSE)) {
report.ExitStatus = CHKDSK_EXIT_SUCCESS;
_Verbose = FALSE;
_pvfMessage = NULL;
return TRUE;
}
#if defined(FE_SB) // REAL_FAT_SA::Create():Optical disk support
//
// Here is a table of Optical Disk (MO) format on OEM DOS.
//
// 128MB | NEC | IBM | Fujitsu |
// -----------+-------+-------+---------+
// BPB.Media | 0xF0 | 0xF0 | 0xF0 |
// -----------+-------+-------+---------+
// FAT.DiskID | 0xF0 | 0xF8 | 0xF8 |
// -----------+-------+-------+---------+
//
// 230MB | NEC | IBM | Fujitsu |
// -----------+-------+-------+---------+
// BPB.Media | 0xF0 | 0xF0 | 0xF0 |
// -----------+-------+-------+---------+
// FAT.DiskID | 0xF8 | 0xF8 | 0xF8 |
// -----------+-------+-------+---------+
//
// We will take NEC's way....
if (_drive->QueryMediaType() == F3_230Mb_512) {
DebugAssert(QueryMediaByte() == (UCHAR) 0xF0);
_fat->SetEarlyEntries((UCHAR) 0xF8);
} else {
_fat->SetEarlyEntries(QueryMediaByte());
}
}
#else
_fat->SetEarlyEntries(QueryMediaByte());
#endif
}
// Compute the cluster size and the number of clusters on disk.
cluster_size = _drive->QuerySectorSize()*QuerySectorsPerCluster();
cluster_count = QueryClusterCount();
// No EAs have been detected yet.
ea_infos = NULL;
num_eas = 0;
// Create an EA file name string.
if (!eafilename.Initialize("EA DATA. SF") ||
!eafilepath.Initialize("\\EA DATA. SF")) {
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
//
// This bitmap will be reinitialized before 'WalkDirectoryTree'.
// Its contents will be ignored until then.
//
if (!fat_bitmap.Initialize(cluster_count)) {
Message->Set(MSG_CHK_NO_MEMORY);
Message->Display();
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
// If there is an EA file on disk then...
// FAT32 volume does not support EA.
if (_dir != NULL && // <-- If this is not a FAT32 volume.
eadent.Initialize(_dir->SearchForDirEntry(&eafilename), FAT_TYPE_EAS_OKAY)) {
// Validate the EA file directory entry.
if (!ValidateDirent(&eadent, &eafilepath, FixLevel, FALSE, Message,
&fmsg, &fat_bitmap, &tmp_bool, &tmp_ulong,
ExitStatus)) {
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
// If the EA file directory entry was valid then...
// FATDIR::SearchForDirEntry will not return an erased dirent, but whatever...
if (!eadent.IsErased()) {
// The EA file should not have an EA handle.
if (eadent.QueryEaHandle()) {
dofmsg(Message, &fmsg);
Message->Set(MSG_CHK_EAFILE_HAS_HANDLE);
Message->Display();
eadent.SetEaHandle(0);
*ExitStatus = CHKDSK_EXIT_ERRS_FIXED;
}
// Compute the EA file's starting cluster.
ea_clus_num = eadent.QueryStartingCluster();
//
// Perform any log operations recorded at the beginning
// of the EA file.
//
if (!PerformEaLogOperations(ea_clus_num, FixLevel,
Message, &fmsg)) {
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
//
// Validate the EA file's EA sets and return an array of
// information about them.
//
ea_infos = RecoverEaSets(ea_clus_num, &num_eas, FixLevel,
Message, &fmsg);
//
// If there are no valid EAs in the EA file then erase
// the EA file.
//
if (!ea_infos) {
if (num_eas) {
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
eadent.SetErased();
dofmsg(Message, &fmsg);
Message->Set(MSG_CHK_EMPTY_EA_FILE);
Message->Display();
*ExitStatus = CHKDSK_EXIT_ERRS_FIXED;
}
}
}
// Initialize FAT bitmap to be used in detection of cross-links.
if (!fat_bitmap.Initialize(cluster_count)) {
Message->Set(MSG_CHK_NO_MEMORY);
Message->Display();
// DELETE(ea_infos);
delete [] ea_infos; ea_infos = NULL;
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
if (!CheckSectorHeapAllocation(FixLevel, Message, &fmsg)) {
// DELETE(ea_infos);
delete [] ea_infos; ea_infos = NULL;
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
if (!VerifyFatExtensions(FixLevel, Message, &fmsg)) {
// DELETE(ea_infos);
delete [] ea_infos; ea_infos = NULL;
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
//
// Should probably add another function to perform the following task.
//
if (_dirF32 != NULL) {
if (!VerifyAndFixFat32RootDir( &fat_bitmap, Message, &report, &fmsg)) {
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
}
// Validate all of the files on the disk.
save_num_eas = num_eas;
if (!WalkDirectoryTree(ea_infos, &num_eas, &fat_bitmap, &report,
FixLevel, RecoverAlloc, Message, Verbose, &fmsg)) {
// DELETE(ea_infos);
delete [] ea_infos; ea_infos = NULL;
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
if (save_num_eas != num_eas && ea_infos) {
if (!EraseEaHandle(ea_infos, num_eas, save_num_eas, FixLevel, Message)) {
_Verbose = FALSE;
_pvfMessage = NULL;
return FALSE;
}
if (!num_eas) {
delete [] ea_infos;
ea_infos = NULL;
//
// Note that the following two steps cause the EA file chain to get recovered
// as a lost cluster chain since all this does is erase the dirent, not the
// cluster chain.
//
eadent.SetErased();
FreeSpaceInBitmap(eadent.QueryStartingCluster(), _fat,
&fat_bitmap);
dofmsg(Message, &fmsg);
Message->Set(MSG_CHK_EMPTY_EA_FILE);
Message->Display();
*ExitStatus = CHKDSK_EXIT_ERRS_FIXED;
}
}
// If there are EAs on the disk then...
if (ea_infos) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -