⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatsachk.cxx

📁 EFI(Extensible Firmware Interface)是下一代BIOS
💻 CXX
📖 第 1 页 / 共 5 页
字号:

        // Remove all unused EAs from EA file.

        if (!PurgeEaFile(ea_infos, num_eas, &fat_bitmap, FixLevel, Message,
                         &fmsg)) {
            // DELETE( ea_infos );
            delete [] ea_infos; ea_infos = NULL;
            _Verbose = FALSE;
            _pvfMessage = NULL;
            return FALSE;
        }


        // Rebuild header portion of EA file.

        if (!ea_header_mem.Initialize() ||
            !RebuildEaHeader(&ea_clus_num, ea_infos, num_eas,
                             &ea_header_mem, &ea_header, &fat_bitmap,
                             FixLevel, Message, &fmsg)) {
            // DELETE( ea_infos );
            delete [] ea_infos; ea_infos = NULL;
            _Verbose = FALSE;
            _pvfMessage = NULL;
            return FALSE;
        }

        if (ea_clus_num) {
            eadent.SetStartingCluster(ea_clus_num);
            eadent.SetFileSize(cluster_size*
                               _fat->QueryLengthOfChain(ea_clus_num));
        } else {
            dofmsg(Message, &fmsg);
            Message->Set(MSG_CHK_EMPTY_EA_FILE);
            Message->Display();

            //
            // 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);
        }
        *ExitStatus = CHKDSK_EXIT_ERRS_FIXED;
    }

    //
    // If WalkDirectoryTree deleted any files, we need to sync the
    // FAT_EXTENSIONS up with the FAT again.
    //
    if (!VerifyFatExtensions(FixLevel, Message, &fmsg)) {
        // DELETE(ea_infos);
        delete [] ea_infos; ea_infos = NULL;
        _Verbose = FALSE;
        _pvfMessage = NULL;
        return FALSE;
    }

    if (!RecoverOrphans(&fat_bitmap, FixLevel, Message, &fmsg, &report, &changes)) {
        // DELETE(ea_infos);
        delete [] ea_infos; ea_infos = NULL;
        _Verbose = FALSE;
        _pvfMessage = NULL;
        return FALSE;
    }

    //
    // RecoverOrphans may have cleared faulty entries from the FAT,
    // and now we need to sync the FAT_EXTENSIONS again.
    //
    if (!VerifyFatExtensions(FixLevel, Message, &fmsg)) {
        // DELETE(ea_infos);
        delete [] ea_infos; ea_infos = NULL;
        _Verbose = FALSE;
        _pvfMessage = NULL;
        return FALSE;
    }

    // If requested, validate all of the free space on the volume.

    if (RecoverFree && !RecoverFreeSpace(Message)) {
        // DELETE(ea_infos);
        delete [] ea_infos; ea_infos = NULL;
        _Verbose = FALSE;
        _pvfMessage = NULL;
        return FALSE;
    }

    total_count = cluster_count - FirstDiskCluster;

    if (changes) {
        report.ExitStatus = CHKDSK_EXIT_ERRS_FIXED;
    }

    *ExitStatus = report.ExitStatus;

    switch (*ExitStatus) {
      case CHKDSK_EXIT_SUCCESS:
        Message->DisplayMsg(MSG_CHK_NO_PROBLEM_FOUND);
        break;

      case CHKDSK_EXIT_ERRS_FIXED:
        Message->DisplayMsg((FixLevel != CheckOnly) ? MSG_CHK_ERRORS_FIXED : MSG_CHK_NEED_F_PARAMETER);
        break;

      case CHKDSK_EXIT_COULD_NOT_CHK:
//    case CHKDSK_EXIT_ERRS_NOT_FIXED:
//    case CHKDSK_EXIT_COULD_NOT_FIX:
        Message->DisplayMsg(MSG_CHK_ERRORS_NOT_FIXED);
        break;

    }

    BIG_INT temp_big_int;
    ULONG   temp_ulong;
    MSGID   message_id;
    BOOLEAN KSize;
    DSTRING wdNum1;
    char    wdAstr[14];
    DSTRING wdNum2;


    if (!wdNum1.Initialize("             ") ||
        !wdNum2.Initialize("             ")   ) {

        Message->Set(MSG_CHK_NO_MEMORY);
        Message->Display();
        _Verbose = FALSE;
        _pvfMessage = NULL;
        return FALSE;
    }

    temp_big_int = cluster_size;
    temp_big_int = temp_big_int * total_count;

    // NOTE: The magic number 4095MB comes from Win9x's GUI SCANDISK utility

    if (temp_big_int.GetHighPart() || (temp_big_int.GetLowPart() > (4095ul*1024ul*1024ul))) {
        temp_ulong = (temp_big_int / 1024ul).GetLowPart();
        message_id = MSG_TOTAL_KILOBYTES;
        KSize = TRUE;
    } else {
        temp_ulong = temp_big_int.GetLowPart();
        message_id = MSG_TOTAL_DISK_SPACE;
        KSize = FALSE;
    }

    Message->Set(message_id);
    sprintf(wdAstr, "%u", temp_ulong);
    InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);
    Message->Display("%ws", wdNum1.GetWSTR());

    if (report.HiddenEntriesCount) {
        temp_big_int = cluster_size;
        temp_big_int = temp_big_int * report.HiddenClusters;
        if (KSize) {
            temp_ulong = (temp_big_int / 1024ul).GetLowPart();
            message_id = MSG_KILOBYTES_IN_HIDDEN_FILES;
        } else {
            temp_ulong = temp_big_int.GetLowPart();
            message_id = MSG_HIDDEN_FILES;
        }
        Message->Set(message_id);

        sprintf(wdAstr, "%u", temp_ulong);
        InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);

        sprintf(wdAstr, "%d", report.HiddenEntriesCount);
        InsertSeparators(wdNum2.GetWSTR(),wdAstr, 0);

        Message->Display("%ws%ws", wdNum1.GetWSTR(), wdNum2.GetWSTR());
    }

    if (report.DirEntriesCount) {
        temp_big_int = cluster_size;
        temp_big_int = temp_big_int * report.DirClusters;
        if (KSize) {
            temp_ulong = (temp_big_int / 1024ul).GetLowPart();
            message_id = MSG_KILOBYTES_IN_DIRECTORIES;
        } else {
            temp_ulong = temp_big_int.GetLowPart();
            message_id = MSG_DIRECTORIES;
        }
        Message->Set(message_id);

        sprintf(wdAstr, "%u", temp_ulong);
        InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);

        sprintf(wdAstr, "%d", report.DirEntriesCount);
        InsertSeparators(wdNum2.GetWSTR(),wdAstr, 0);

        Message->Display("%ws%ws", wdNum1.GetWSTR(), wdNum2.GetWSTR());
    }

    if (report.FileEntriesCount) {

        temp_big_int = cluster_size;
        temp_big_int = temp_big_int * report.FileClusters;
        if (KSize) {
            temp_ulong = (temp_big_int / 1024ul).GetLowPart();
            message_id = MSG_KILOBYTES_IN_USER_FILES;
        } else {
            temp_ulong = temp_big_int.GetLowPart();
            message_id = MSG_USER_FILES;
        }
        Message->Set(message_id);

        sprintf(wdAstr, "%u", temp_ulong);
        InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);

        sprintf(wdAstr, "%d", report.FileEntriesCount);
        InsertSeparators(wdNum2.GetWSTR(),wdAstr, 0);

        Message->Display("%ws%ws", wdNum1.GetWSTR(), wdNum2.GetWSTR());
    }

    if (bad_count = _fat->QueryBadClusters()) {
        temp_big_int = bad_count;
        temp_big_int = temp_big_int * cluster_size;
        if (KSize) {
            temp_ulong = (temp_big_int / 1024ul).GetLowPart();
            message_id = MSG_CHK_NTFS_BAD_SECTORS_REPORT_IN_KB;
        } else {
            temp_ulong = temp_big_int.GetLowPart();
            message_id = MSG_BAD_SECTORS;
        }
        Message->Set(message_id);
        sprintf(wdAstr, "%u", temp_ulong);
        InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);
        Message->Display("%ws", wdNum1.GetWSTR());
    }

    if (ea_infos) {
        Message->Set(MSG_CHK_EA_SIZE);

        sprintf(wdAstr, "%u", cluster_size*_fat->QueryLengthOfChain(ea_clus_num));
        InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);
        Message->Display("%ws", wdNum1.GetWSTR());
    }

    free_count = _fat->QueryFreeClusters();

    temp_big_int = free_count;
    temp_big_int = temp_big_int * cluster_size;
    if (KSize) {
        temp_ulong = (temp_big_int / 1024ul).GetLowPart();
        message_id = MSG_AVAILABLE_KILOBYTES;
    } else {
        temp_ulong = temp_big_int.GetLowPart();
        message_id = MSG_AVAILABLE_DISK_SPACE;
    }
    Message->Set(message_id);
    sprintf(wdAstr, "%u", temp_ulong);
    InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);
    Message->Display("%ws", wdNum1.GetWSTR());

    Message->Set(MSG_ALLOCATION_UNIT_SIZE);
    sprintf(wdAstr, "%u", cluster_size);
    InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);
    Message->Display("%ws", wdNum1.GetWSTR());

    Message->Set(MSG_TOTAL_ALLOCATION_UNITS);
    sprintf(wdAstr, "%u", total_count);
    InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);
    Message->Display("%ws", wdNum1.GetWSTR());

    Message->Set(MSG_AVAILABLE_ALLOCATION_UNITS);
    sprintf(wdAstr, "%u", free_count);
    InsertSeparators(wdNum1.GetWSTR(),wdAstr, 13);
    Message->Display("%ws", wdNum1.GetWSTR());

    if (FixLevel != CheckOnly && ea_infos && !ea_header.Write()) {
        // DELETE(ea_infos);
        delete [] ea_infos; ea_infos = NULL;
        _Verbose = FALSE;
        _pvfMessage = NULL;
        return FALSE;
    }

    // Clear the dirty bit.
    //
    if( RecoverAlloc ) {
        SetVolumeFlags(FAT_BPB_RESERVED_DIRTY | FAT_BPB_RESERVED_TEST_SURFACE,
                       TRUE);
    } else {
        SetVolumeFlags(FAT_BPB_RESERVED_DIRTY, TRUE);
    }


    if (FixLevel != CheckOnly && !Write(Message)) {
        // DELETE(ea_infos);
        delete [] ea_infos; ea_infos = NULL;
        _Verbose = FALSE;
        _pvfMessage = NULL;
        return FALSE;
    }

    // DELETE(ea_infos);
    delete [] ea_infos; ea_infos = NULL;
    _Verbose = FALSE;
    _pvfMessage = NULL;
    return TRUE;
}

BOOLEAN
FAT_SA::VerifyAndFixFat32RootDir (
    IN OUT  PBITVECTOR      FatBitMap,
    IN      PMESSAGE        Message,
    IN OUT  PFATCHK_REPORT  Report,
    IN OUT  PBOOLEAN        NeedErrorMessage
    )

/*++

Routine Description:

    This routine verifies the FAT32 root directory which is not an integral
    part of the super area buffer. The method employed to verify and fix the
    root directory is very similar to the one used to verify and fix regular
    directory structure.

Arguments:

    BitVector - Supplies a bit map for cross/bad links detection. The whole
                map should be zeroed when it is passed in this method.
    Message   - Supplies an outlet for messages.
    Report    - Supplies the fat chkdsk report structures for storing the
                actions performed by this method.
    NeedErrorsMessage   - Supplies whether or not an error has occurred
                          under check only conditions.

Return Values:

    TRUE  - Success.
    FALSE - Failed.

--*/
{

    BOOLEAN crosslink_detected = FALSE;
    BOOLEAN changes_made = FALSE;
    ULONG   starting_cluster;
    ULONG   dummy;

    starting_cluster = QueryFat32RootDirStartingCluster();
    _fat->ScrubChain( starting_cluster,
                      FatBitMap,
                      &changes_made,
                      &crosslink_detected,
                      &dummy );
    //
    // Root dir is the only component marked in the
    // bitmap so far.
    //

    DebugAssert(!crosslink_detected);

    if (changes_made) {
        dofmsg(Message, NeedErrorMessage);
        Message->Set(MSG_BAD_LINK);
        Message->Display("%s", "\\");
        Report->ExitStatus = CHKDSK_EXIT_ERRS_FIXED;

        //
        //  We have to reinitialized the root directory.
        //

        if (!_hmem_F32->Initialize() ||
            !_dirF32->Initialize( _hmem_F32, _drive, this,
                                  _fat, starting_cluster)) {
            Message->Set(MSG_CHK_NO_MEMORY);
            Message->Display();
            return FALSE;
        }

        //
        //  Force a re-reading of the root directory.
        //  We don't care if it fails, subsequent code can fix that.
        //

        _dirF32->Read();
    }

    //
    // Validate the readability of the root chain
    //

    //
    // We don't want replacement clusters becuase the replacement given
    // by RecoverChain will be zeroed which, according to the spec., means
    // it contains the end of the directory structure and WalkDirectoryTree
    // will just go ahead and erase all the 'good' directory entries that comes
    // after the replaced cluster. Not a really nice thing to do to the root
    // directory IMHO.
    //
    if(!RecoverChain(&starting_cluster, &changes_made, 0, FALSE)){
        dofmsg(Message, NeedErrorMessage);
        Message->Set(MSG_CHK_NO_MEMORY);
        Message->Display();
        return FALSE;
    }

    if (changes_made) {

        if ( starting_cluster ) {

            if ( starting_cluster != _dirF32->QueryStartingCluster() ) {
                SetFat32RootDirStartingCluster( starting_cluster );
            }

            //
            // Should reinitialize the root directory
            //
            if (!_hmem_F32->Initialize() ||
                !_dirF32->Initialize( _hmem_F32, _drive, this,
                                      _fat, starting_cluster)) {
                Message->Set(MSG_CHK_NO_MEMORY);
                Message->Display();
                return FALSE;
            }


        } else {

            if(!RelocateNewFat32RootDirectory( Report, FatBitMap, Message )) {
                return FALSE;
            }

        }


        //
        //  Reread the root directory
        //
        if (!_dirF32->Read()) {
            //
            //  Shouldn't fail.
            //
            DebugAbort("Failed to read the FAT32 root directory despite all the fixing.\n");

        }
        dofmsg(Message, NeedErrorMessage);
        Message->Set(MSG_CHK_NTFS_CORRECTING_ERROR_IN_DIRECTORY);
        Message->Display("%s", "\\");
        //
        // Erasing the root will totally destroy the disk
        // so we just leave it partially corrupted and
        // hopefully WalkDirectoryTree will be able to fix it.
        //
        Report->ExitStatus = CHKDSK_EXIT_ERRS_FIXED;
    }

    return TRUE;
}

BOOLEAN
FAT_SA::RelocateNewFat32RootDirectory (
    IN OUT PFATCHK_REPORT   Report,
    IN OUT PBITVECTOR       FatBitMap,
    IN     PMESSAGE         Message
    )
/*++

Routine Description:

    This routine relocates a FAT32 root directory

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -