📄 fatsachk.cxx
字号:
if (need_write) {
if (FixLevel != CheckOnly && !easet.Write()) {
return 0;
}
}
return EaInfo->LastCn;
}
BOOLEAN
FAT_SA::EaSort(
IN OUT PEA_INFO EaInfos,
IN ULONG NumEas,
IN OUT PMESSAGE Message,
IN OUT PBOOLEAN NeedErrorsMessage
)
/*++
Routine Description:
This routine sorts the EaInfos array by 'OwnHandle' into ascending order.
It also edits the FAT with the changes in the EAs order.
Arguments:
EaInfos - Supplies the array of EA_INFOs to sort.
NumEas - Supplies the number of elements in the array.
Message - Supplies an outlet for messages.
NeedErrorsMessage - Supplies whether or not errors have occurred
under check only conditions.
Return Value:
FALSE - Failure.
TRUE - Success.
--*/
{
BOOLEAN done;
EA_INFO tmp;
ULONG clus;
ULONG i;
BOOLEAN change;
done = FALSE;
change = FALSE;
while (!done) {
done = TRUE;
for (i = 0; i < NumEas - 1; i++) {
if (EaInfos[i].OwnHandle > EaInfos[i + 1].OwnHandle) {
done = FALSE;
clus = _fat->RemoveChain(EaInfos[i + 1].PreceedingCn,
EaInfos[i + 1].LastCn);
_fat->InsertChain(clus,
EaInfos[i + 1].LastCn,
EaInfos[i].PreceedingCn);
EaInfos[i + 1].PreceedingCn = EaInfos[i].PreceedingCn;
EaInfos[i].PreceedingCn = EaInfos[i + 1].LastCn;
if (i + 2 < NumEas) {
EaInfos[i + 2].PreceedingCn = EaInfos[i].LastCn;
}
change = TRUE;
tmp = EaInfos[i];
EaInfos[i] = EaInfos[i + 1];
EaInfos[i + 1] = tmp;
}
}
}
if (change) {
dofmsg(Message, NeedErrorsMessage);
Message->Set(MSG_CHK_UNORDERED_EA_SETS);
Message->Display();
}
return TRUE;
}
BOOLEAN
FAT_SA::RebuildEaHeader(
IN OUT PULONG StartingCluster,
IN OUT PEA_INFO EaInfos,
IN ULONG NumEas,
IN OUT PMEM EaHeaderMem,
OUT PEA_HEADER EaHeader,
IN OUT PBITVECTOR FatBitMap,
IN FIX_LEVEL FixLevel,
IN OUT PMESSAGE Message,
IN OUT PBOOLEAN NeedErrorsMessage
)
/*++
Routine Description:
This routine rebuilds the header and tables of the EA file base on the
information in the 'EaInfos' array. The header log is set to zero,
and the header itself is relocated if any of the clusters are bad.
The starting cluster may be relocated if there are bad clusters.
Arguments:
StartingCluster - Supplies the first cluster of the EA file.
EaInfos - Supplies an array containing information for every
EA set.
NumberOfEas - Supplies the total number of EA sets.
EaHeaderMem - Supplies the memory for the EA header.
EaHeader - Returns the EA header.
FatBitMap - Supplies the cross-links bitmap.
FixLevel - Supplies the CHKDSK fix level.
Message - Supplies an outlet for messages.
NeedErrorsMessage - Supplies whether or not errors have occurred
under check only conditions.
Return Value:
FALSE - Failure.
TRUE - Success.
--*/
{
ULONG length;
ULONG cluster_size;
ULONG actual_length;
ULONG new_chain;
ULONG last_cluster;
BOOLEAN changes;
LONG i, j, k;
PEA_MAP_TBL table;
PEA_FILE_HEADER header;
LONG tmp;
BOOLEAN empty_ea_file;
ULONG clus;
// Compute the number of clusters necessary for the header portion of
// the EA file.
length = sizeof(EA_FILE_HEADER) +
BaseTableSize*sizeof(USHORT) +
EaInfos[NumEas - 1].OwnHandle*sizeof(USHORT);
cluster_size = _drive->QuerySectorSize()*QuerySectorsPerCluster();
if (length%cluster_size) {
length = length/cluster_size + 1;
} else {
length = length/cluster_size;
}
//
// Make sure that the header contains enough clusters to accomodate
// the size of the offset table.
//
last_cluster = EaInfos[0].PreceedingCn;
actual_length = _fat->QueryLengthOfChain(*StartingCluster, last_cluster);
if (length > actual_length) {
dofmsg(Message, NeedErrorsMessage);
Message->Set(MSG_CHK_NEED_MORE_HEADER_SPACE);
Message->Display();
new_chain = _fat->AllocChain((length - actual_length),
&last_cluster);
if (!new_chain) {
Message->Set(MSG_CHK_INSUFFICIENT_DISK_SPACE);
Message->Display();
return FALSE;
}
if (IsCompressed() && !AllocSectorsForChain(new_chain)) {
_fat->FreeChain(new_chain);
Message->Set(MSG_CHK_INSUFFICIENT_DISK_SPACE);
Message->Display();
return FALSE;
}
for (clus = new_chain;
!_fat->IsEndOfChain(clus);
clus = _fat->QueryEntry(clus)) {
FatBitMap->SetBit(clus);
}
FatBitMap->SetBit(clus);
_fat->InsertChain(new_chain, last_cluster, EaInfos[0].PreceedingCn);
EaInfos[0].PreceedingCn = last_cluster;
} else if (length < actual_length) {
dofmsg(Message, NeedErrorsMessage);
Message->Set(MSG_CHK_UNUSED_EA_PORTION);
Message->Display();
last_cluster = _fat->QueryNthCluster(*StartingCluster,
length - 1);
clus = _fat->RemoveChain(last_cluster, EaInfos[0].PreceedingCn);
EaInfos[0].PreceedingCn = last_cluster;
for (;
!_fat->IsEndOfChain(clus);
clus = _fat->QueryEntry(clus)) {
FatBitMap->ResetBit(clus);
}
FatBitMap->ResetBit(clus);
}
// Verify the cluster chain containing the header.
changes = FALSE;
if (FixLevel != CheckOnly &&
!RecoverChain(StartingCluster, &changes, last_cluster, TRUE)) {
dofmsg(Message, NeedErrorsMessage);
Message->Set(MSG_CHK_INSUFFICIENT_DISK_SPACE);
Message->Display();
return FALSE;
}
if (changes) {
dofmsg(Message, NeedErrorsMessage);
Message->Set(MSG_CHK_RELOCATED_EA_HEADER);
Message->Display();
}
// Compute the tables.
if (!EaHeader->Initialize(EaHeaderMem, _drive, this, _fat,
*StartingCluster, (USHORT) length) ||
!(table = EaHeader->GetMapTable()) ||
!(header = EaHeader->GetEaFileHeader())) {
Message->Set(MSG_CHK_NO_MEMORY);
Message->Display();
return FALSE;
}
if (!EaHeader->Read()) {
if (FixLevel == CheckOnly) {
dofmsg(Message, NeedErrorsMessage);
Message->Set(MSG_CHK_RELOCATED_EA_HEADER);
Message->Display();
} else {
return FALSE;
}
}
// Set the log in the header to zero.
header->Signature = HeaderSignature;
header->FormatType = 0;
header->LogType = 0;
header->Cluster1 = 0;
header->NewCValue1 = 0;
header->Cluster2 = 0;
header->NewCValue2 = 0;
header->Cluster3 = 0;
header->NewCValue3 = 0;
header->Handle = 0;
header->NewHOffset = 0;
// Reconcile the tables with the EaInfo information.
changes = FALSE;
for (i = 0; i < BaseTableSize; i++) {
table->BaseTab[i] = 0;
}
j = 0;
empty_ea_file = TRUE;
for (i = 0; i < (LONG) NumEas; i++) {
if (EaInfos[i].UsedCount != 1) {
continue;
}
empty_ea_file = FALSE;
for (; j < (LONG) EaInfos[i].OwnHandle; j++) {
if (table->OffTab[j] != InvalidHandle) {
table->OffTab[j] = InvalidHandle;
changes = TRUE;
}
}
length = _fat->QueryLengthOfChain(*StartingCluster,
EaInfos[i].PreceedingCn);
for (k = j>>7; k >= 0 && !table->BaseTab[k]; k--) {
table->BaseTab[k] = (USHORT) length;
}
tmp = length - table->BaseTab[j>>7];
if ((LONG)table->OffTab[j] != tmp) {
table->OffTab[j] = (USHORT) tmp;
changes = TRUE;
}
j++;
}
if (empty_ea_file) {
for (clus = *StartingCluster;
!_fat->IsEndOfChain(clus);
clus = _fat->QueryEntry(clus)) {
FatBitMap->ResetBit(clus);
}
FatBitMap->ResetBit(clus);
*StartingCluster = 0;
return TRUE;
}
tmp = _fat->QueryLengthOfChain(*StartingCluster);
for (k = ((j - 1)>>7) + 1; k < BaseTableSize; k++) {
table->BaseTab[k] = (USHORT) tmp;
}
for (; j < (LONG) EaHeader->QueryOffTabSize(); j++) {
if (table->OffTab[j] != InvalidHandle) {
table->OffTab[j] = InvalidHandle;
changes = TRUE;
}
}
if (changes) {
dofmsg(Message, NeedErrorsMessage);
Message->Set(MSG_CHK_ERROR_IN_EA_HEADER);
Message->Display();
}
return TRUE;
}
VOID
FreeSpaceInBitmap(
IN ULONG StartingCluster,
IN PCFAT Fat,
IN OUT PBITVECTOR FatBitMap
)
{
if (!StartingCluster) {
return;
}
while (!Fat->IsEndOfChain(StartingCluster)) {
FatBitMap->ResetBit(StartingCluster);
StartingCluster = Fat->QueryEntry(StartingCluster);
}
FatBitMap->ResetBit(StartingCluster);
}
ULONG
ComputeFileNameHashValue(
IN PVOID FileName
)
{
ULONG h;
BYTE i;
PUCHAR p;
p = (PUCHAR) FileName;
h = 0;
for (i=0; i<11; i++) {
h = (h << 2) ^ p[i];
}
for (i=0; i<2; i++) {
h = (h << 2) ^ p[i];
}
return h;
}
STATIC ULONG _Twinkle = 0;
STATIC LONG64 _LastTwnkTime = 0;
STATIC ULONG _LastPercent = 0xFFFFFFFF;
BOOLEAN
DisplayTwnkPercent(
ULONG percent
)
{
BIG_INT currenttime;
#if !defined( _EFICHECK_ )
NtQuerySystemTime((_LARGE_INTEGER *)¤ttime);
#else
EfiQuerySystemTime((_LARGE_INTEGER *)¤ttime);
#endif
// The above clock counts in 1/10,000ths of a second
if((percent != _LastPercent) ||
((currenttime.GetQuadPart() - _LastTwnkTime) >= (6 * 100 * 10000)))
{
if(percent > 100) {
percent = 100;
}
if((_Twinkle > 5) || _Verbose) {
_Twinkle = 0;
}
if(_Verbose && (percent == _LastPercent)) {
return TRUE;
}
_LastPercent = percent;
_LastTwnkTime = currenttime.GetQuadPart();
if(_pvfMessage) {
STR dots[6];
dots[5] = '\0';
dots[4] = ' ';
dots[3] = ' ';
dots[2] = ' ';
dots[1] = ' ';
dots[0] = ' ';
switch(_Twinkle) {
case 5:
default:
dots[4] = '.';
case 4:
dots[3] = '.';
case 3:
dots[2] = '.';
case 2:
dots[1] = '.';
case 1:
dots[0] = '.';
case 0:
;
}
if(!_Verbose) {
_Twinkle++;
}
_pvfMessage->Set(MSG_PERCENT_COMPLETE2);
if (!_pvfMessage->Display("%d%s", percent, &dots[0])) {
return FALSE;
}
if(_Verb
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -