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

📄 fatsachk.cxx

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

Copyright (c) 1991-2001 Microsoft Corporation

Module Name:

    fatsachk.cxx

--*/

#include <pch.cxx>

#include "bitvect.hxx"
#include "error.hxx"
#include "rtmsg.h"
#include "ifsentry.hxx"

// Timeinfo is full of windows stuff.
#if !defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ ) && !defined( _EFICHECK_ )

#include "timeinfo.hxx"

#endif

#define UCHAR_SP        ' '

typedef struct _VISIT_DIR *PVISIT_DIR;
typedef struct _VISIT_DIR {
    PVISIT_DIR Next;
    PWSTRING Path;
    ULONG Cluster;
} VISIT_DIR;

#if !defined( _EFICHECK_ )
extern "C" {
    #include <stdio.h>
}
#endif

extern VOID InsertSeparators(
                  LPCWSTR OutWNumber,
                  char * InANumber,
                  ULONG  Width
                );

VOID
dofmsg(
    IN      PMESSAGE    Message,
    IN OUT  PBOOLEAN    NeedErrorsMessage
    )
{
    if (*NeedErrorsMessage) {
        Message->Set(MSG_CORRECTIONS_WILL_NOT_BE_WRITTEN, NORMAL_MESSAGE, TEXT_MESSAGE);
        Message->Display();
        *NeedErrorsMessage = FALSE;
    }
}

BOOLEAN
CheckAndFixFileName(
    PVOID       DirEntry,
    PBOOLEAN    Changes
)
{
    PUCHAR      p = (PUCHAR)DirEntry;

#if 1
    //
    // Should not correct case error within file name because
    // different language build translates differently.  On a
    // dual boot machine containing build of two different languages,
    // the chkdsk from one build may not like what the second build
    // put onto the disk.
    //
    return TRUE;
#else

    memcpy(backup_copy, p, 11);

    first_char_replaced = (0x5 == p[0]);

    if (first_char_replaced)
        p[0] = 0xe5;

    ntstatus = RtlOemToUnicodeN(unicode_string,
                                sizeof(unicode_string),
                                &unicode_string_length,
                                (PCHAR)p,
                                11);

    if (!NT_SUCCESS(ntstatus)) {
        DebugPrintTrace(("UFAT: Error in RtlOemToUnicodeN, 0x%x\n", ntstatus));
        memcpy(p, backup_copy, 11);
        return FALSE;
    }

    ntstatus = RtlUpcaseUnicodeToOemN((PCHAR)p,
                                      11,
                                      NULL,
                                      unicode_string,
                                      unicode_string_length);

    if (!NT_SUCCESS(ntstatus)) {
        DebugPrintTrace(("UFAT: Error in RtlUpcaseUnicodeToOemN, 0x%x\n", ntstatus));
        memcpy(p, backup_copy, 11);
        return FALSE;
    }

    if (first_char_replaced) {
        if (0xe5 == p[0]) {
            p[0] = 0x5;
        } else {
            DebugPrintTrace(("UFAT: First byte changed to 0x%x unexpectedly\n", p[0]));
            memcpy(p, backup_copy, 11);
            return FALSE;
        }
    }

    *Changes = (memcmp(p, backup_copy, 11) != 0);

    return TRUE;
#endif
}

BOOLEAN
IsFileNameMatch(
    PFATDIR     Dir,
    UCHAR       FatType,
    ULONG       CurrentIndex,
    ULONG       MatchingIndexCount,
    PULONG      MatchingIndexArray
)
{
    ULONG   j;

    for (j = 0; j < MatchingIndexCount; j++) {

        FAT_DIRENT fd;
        ULONG      indx = MatchingIndexArray[j];

        if (!fd.Initialize(Dir->GetDirEntry(indx), FatType) ||
            fd.IsVolumeLabel()) {
            continue;
        }

        if (!memcmp(Dir->GetDirEntry(indx), Dir->GetDirEntry(CurrentIndex), 11)) {
            return TRUE;    // there is a match
        }
    }
    return FALSE;   // no match
}

BOOLEAN
RenameFileName(
    PULONG  Positions,
    PVOID   DirEntry
)
{
    PUCHAR  p = (PUCHAR)DirEntry;
    INT     i;

    if (*Positions == 0) {   // if first rename
        // find out the first char in the extension that is real
        for (i = 10; i > 7; i--)
            if (p[i] != UCHAR_SP)
                break;
        if (i >= 7 && i < 10) {  // fill the unused extension space with dashes
            for (i++; i < 10; i++)
                p[i] = '-';
        }
        *Positions = 1;
        if (p[10] != '0') {
            p[10] = '0';    // the last char of the extension gets a zero
            return TRUE;
        }
    }

    // extension chars are all in use now
    // check to see if renaming is already in progress

    for (i=10; i>=0; i--) {
        if (!(*Positions & (1 << (10-i)))) {
            *Positions |= (1 << (10-i));
            if (p[i] != '0') {
                p[i] = '0';
                return TRUE;
            }
        }
        if (p[i] >= '0' && p[i] < '9') {
            p[i]++;
            return TRUE;
        } else if (p[i] == '9') {
            p[i] = '0';
        }
    }

    // if we get here that means we have exhausted all possible name
    // shouldn't be as there are more combination than the max number
    // of files that can be in a FAT directory (65536)

    return FALSE;
}

BOOLEAN
PushVisitDir(
    IN OUT PVISIT_DIR *VisitDirStack,
    IN     ULONG Cluster,
    IN     PWSTRING DirectoryPath
    )
{
    PVISIT_DIR visit_dir;

    visit_dir = (PVISIT_DIR)MALLOC( sizeof( VISIT_DIR ) );
    if( visit_dir == NULL ){
        return FALSE;
    }

    visit_dir->Path = DirectoryPath;
    visit_dir->Cluster = Cluster;
    visit_dir->Next = *VisitDirStack;
    *VisitDirStack = visit_dir;

    return TRUE;
}

BOOLEAN
PopVisitDir(
    IN OUT PVISIT_DIR *VisitDirStack,
    OUT    PULONG Cluster OPTIONAL,
    OUT    PWSTRING *DirectoryPath OPTIONAL
    )
{
    PVISIT_DIR visit_dir;

    visit_dir = *VisitDirStack;
    if( visit_dir == NULL ){
        return FALSE;
    }
    *VisitDirStack = visit_dir->Next;

    if( ARGUMENT_PRESENT( Cluster ) ){
        *Cluster = visit_dir->Cluster;
    }

    if( ARGUMENT_PRESENT( DirectoryPath ) ){
        *DirectoryPath = visit_dir->Path;
    }

    FREE( visit_dir );
    return TRUE;
}

STATIC VOID
EraseAssociatedLongName(
    PFATDIR Dir,
    INT     FirstLongEntry,
    INT     ShortEntry
    )
{
    FAT_DIRENT dirent;

    for (int j = FirstLongEntry; j < ShortEntry; ++j) {
        dirent.Initialize(Dir->GetDirEntry(j));
        dirent.SetErased();
    }
}

STATIC BOOLEAN
IsString8Dot3(
    PCWSTRING   s
    )
/*++

Routine Description:

    This routine is used to ensure that lfn's legally correspond
    to their short names.  The given string is examined to see if it
    is a legal fat 8.3 name.

Arguments:

    s -- lfn to examine.

Return Value:

    TRUE            - The string is a legal 8.3 name.
    FALSE           - Not legal.

--*/
{
    USHORT i;
    BOOLEAN extension_present = FALSE;
    WCHAR c;

    //
    // The name can't be more than 12 characters (including a single dot).
    //

    if (s->QueryChCount() > 12) {
        return FALSE;
    }

    for (i = 0; i < s->QueryChCount(); ++i) {

        c = s->QueryChAt(i);

#if 0
        if (!FsRtlIsAnsiCharLegalFat(c, FALSE)) {
            return FALSE;
        }
#endif

        if (c == '.') {

            //
            // We stepped onto a period.  We require the following things:
            //
            //      - it can't be the first character
            //      - there can be only one
            //      - there can't be more than 3 characters following it
            //      - the previous character can't be a space
            //

            if (i == 0 ||
                extension_present ||
                s->QueryChCount() - (i + 1) > 3 ||
                s->QueryChAt(i - 1) == ' ') {

                return FALSE;
            }
            extension_present = TRUE;
        }

        //
        // The base part of the name can't be more than 8 characters long.
        //

        if (i >= 8 && !extension_present) {
            return FALSE;
        }

    }

    //
    // The name cannot end in a space or a period.
    //

    if (c == ' ' || c == '.') {
        return FALSE;
    }

    return TRUE;
}

STATIC PMESSAGE      _pvfMessage = NULL;
STATIC BOOLEAN       _Verbose = FALSE;

VOID
FreeSpaceInBitmap(
    IN      ULONG       StartingCluster,
    IN      PCFAT       Fat,
    IN OUT  PBITVECTOR  FatBitMap
    );

BOOLEAN
FAT_SA::VerifyAndFix(
    IN      FIX_LEVEL   FixLevel,
    IN OUT  PMESSAGE    Message,
    IN      ULONG       Flags,
    IN      ULONG       LogFileSize,
    OUT     PULONG      ExitStatus,
    IN      PCWSTRING   DriveLetter
    )
/*++

Routine Description:

    This routine verifies the FAT superarea and if neccessary fixes
    it to a correct state.

Arguments:

    FixLevel        - Supplies the level of fixes that may be performed on
                      the disk.
    Message         - Supplies an outlet for messages.
    Flags           - Supplies flags to control the behavior of chkdsk
                      (see ulib\inc\ifsserv.hxx for details)
    LogFileSize     - ignored
    ExitStatus      - Returns an indication of the result of the check
    DriveLetter     - For autocheck, supplies the letter of the volume
                      being checked

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    FAT_DIRENT      eadent;
    ULONG           cluster_size;
    ULONG           ea_clus_num;
    USHORT          num_eas, save_num_eas;
    PEA_INFO        ea_infos;
    ULONG           cluster_count;
    HMEM            ea_header_mem;
    EA_HEADER       ea_header;
    BOOLEAN         changes = FALSE;
    BITVECTOR       fat_bitmap;
    FATCHK_REPORT   report;
    PUSHORT         p;
    VOLID           volid;
    ULONG           free_count, bad_count, total_count;
    BOOLEAN         fmsg;
    DSTRING         label;
    DSTRING         eafilename;
    DSTRING         eafilepath;
    BOOLEAN         tmp_bool;
    ULONG           tmp_ulong;
    DSTRING         date;
    DSTRING         time;
    UCHAR           dirty_byte, media_byte;

    BOOLEAN         Verbose = (BOOLEAN)(Flags & CHKDSK_VERBOSE);
    BOOLEAN         OnlyIfDirty = (BOOLEAN)(Flags & CHKDSK_CHECK_IF_DIRTY);
    BOOLEAN         EnableUpgrade = (BOOLEAN)(Flags & CHKDSK_ENABLE_UPGRADE);
    BOOLEAN         EnableDowngrade = (BOOLEAN)(Flags & CHKDSK_DOWNGRADE);
    BOOLEAN         RecoverFree = (BOOLEAN)(Flags & CHKDSK_RECOVER_FREE_SPACE);
    BOOLEAN         RecoverAlloc = (BOOLEAN)(Flags & CHKDSK_RECOVER_ALLOC_SPACE);

    _pvfMessage = Message;
    _Verbose = Verbose;

    memset(&report, 0, sizeof(FATCHK_REPORT));

    fmsg = FALSE;

    if (FixLevel != CheckOnly) {
        fmsg = TRUE;
    }

    if (NULL == ExitStatus) {
        ExitStatus = &report.ExitStatus;
    }
    report.ExitStatus = CHKDSK_EXIT_SUCCESS;
    *ExitStatus = CHKDSK_EXIT_COULD_NOT_CHK;

    if (EnableUpgrade || EnableDowngrade) {
        Message->Set(MSG_CHK_CANNOT_UPGRADE_DOWNGRADE_FAT);
        Message->Display();
        _Verbose = FALSE;
        _pvfMessage = NULL;
        return FALSE;
    }

    //
    // Check to see if the dirty bit is set.
    //
    dirty_byte = QueryVolumeFlags();
    if (OnlyIfDirty) {
        if ((dirty_byte &
             (FAT_BPB_RESERVED_DIRTY | FAT_BPB_RESERVED_TEST_SURFACE)) == 0) {
            Message->Set(MSG_CHK_VOLUME_CLEAN);
            Message->Display();
            Message->SetLoggingEnabled(FALSE);
            *ExitStatus = CHKDSK_EXIT_SUCCESS;
            _Verbose = FALSE;
            _pvfMessage = NULL;

⌨️ 快捷键说明

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