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

📄 fatsa.cxx

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

Copyright (c) 1990-2000 Microsoft Corporation

Module Name:

    fatsa.cxx

Environment:

        ULIB, User Mode

--*/

#include "pch.cxx"

#define _UFAT_MEMBER_
#include "ufat.hxx"

#include "cmem.hxx"
#include "error.hxx"
#include "rtmsg.h"
#include "drive.hxx"


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

#if !defined(_AUTOCHECK_) && !defined(_SETUP_LOADER_) && !defined( _EFICHECK_ )
#include "timeinfo.hxx"
#endif


// Control-C handling is not necessary for autocheck.
#if !defined( _AUTOCHECK_ ) && !defined(_SETUP_LOADER_) && !defined( _EFICHECK_ )

#include "keyboard.hxx"

#endif

#define CSEC_FAT32MEG                   65536
#define CSEC_FAT16BIT                   32680
#define CSEC_FAT32BIT                  (1024*1024)


#define MIN_CLUS_BIG    4085    // Minimum clusters for a big FAT.
#define MAX_CLUS_BIG    65525   // Maximum + 1 clusters for big FAT.

#define MIN_CLUS_FAT32  65536




DEFINE_EXPORTED_CONSTRUCTOR( FAT_SA, SUPERAREA, UFAT_EXPORT );

VOID
FAT_SA::Construct (
        )
/*++

Routine Description:

    Constructor for FAT_SA.

Arguments:

    None.

Return Value:

        None.

--*/
{
    _fat = NULL;
    _dir = NULL;
    _dirF32 = NULL;
    _hmem_F32 = NULL;

}


UFAT_EXPORT
FAT_SA::~FAT_SA(
    )
/*++

Routine Description:

    Destructor for FAT_SA.

Arguments:

    None.

Return Value:

    None.

--*/
{
    Destroy();
}

BOOLEAN
FAT_SA::RecoverFile(
    IN      PCWSTRING   FullPathFileName,
    IN OUT  PMESSAGE    Message
    )
/*++

Routine Description:

    This routine runs through the clusters for the file described by
    'FileName' and takes out bad sectors.

Arguments:

    FullPathFileName    - Supplies a full path name of the file to recover.
    Message             - Supplies an outlet for messages.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
#if defined( _SETUP_LOADER_ )

    return FALSE;

#else // _SETUP_LOADER_


    HMEM        hmem;
    ULONG       clus;
    BOOLEAN     changes;
    PFATDIR     fatdir;
    BOOLEAN     need_delete;
    FAT_DIRENT  dirent;
    ULONG       old_file_size;
    ULONG       new_file_size;

    if ((clus = QueryFileStartingCluster(FullPathFileName,
                                         &hmem,
                                         &fatdir,
                                         &need_delete,
                                         &dirent)) == 1) {
        Message->Set(MSG_FILE_NOT_FOUND);
        Message->Display("%W", FullPathFileName);
        return FALSE;
    }

    if (clus == 0xFFFFFFFF) {
        Message->Set(MSG_CHK_NO_MEMORY);
        Message->Display("");
        return FALSE;
    }

    if (clus == 0) {
        Message->Set(MSG_FILE_NOT_FOUND);
        Message->Display("%W", FullPathFileName);
        return FALSE;
    }

    if (dirent.IsDirectory()) {
        old_file_size = _drive->QuerySectorSize()*
                        QuerySectorsPerCluster()*
                        _fat->QueryLengthOfChain(clus);
    } else {
        old_file_size = dirent.QueryFileSize();
    }

    if (!RecoverChain(&clus, &changes)) {
        Message->Set(MSG_CHK_NO_MEMORY);
        Message->Display("");
        return FALSE;
    }

    if (dirent.IsDirectory() || changes) {
        new_file_size = _drive->QuerySectorSize()*
                        QuerySectorsPerCluster()*
                        _fat->QueryLengthOfChain(clus);
    } else {
        new_file_size = old_file_size;
    }

    if (changes) {


// Autochk doesn't need control C handling.
#if !defined( _AUTOCHECK_ ) && !defined( _EFICHECK_ )

        // Disable contol-C handling and

        if (!KEYBOARD::EnableBreakHandling()) {
            Message->Set(MSG_CANT_LOCK_THE_DRIVE);
            Message->Display("");
            return FALSE;
        }

#endif


        // Lock the drive in preparation for writes.

        if (!_drive->Lock()) {
            Message->Set(MSG_CANT_LOCK_THE_DRIVE);
            Message->Display("");
            return FALSE;
        }

        dirent.SetStartingCluster(clus);

        dirent.SetFileSize(new_file_size);

        if (!fatdir->Write()) {
            return FALSE;
        }

        if (!Write(Message)) {
            return FALSE;
        }


// Autochk doesn't need control C handling.
#if !defined( _AUTOCHECK_ ) && !defined( _EFICHECK_ )

        KEYBOARD::DisableBreakHandling();

#endif


    }

    Message->Set(MSG_RECOV_BYTES_RECOVERED);
    Message->Display("%d%d", new_file_size, old_file_size);


    if (need_delete) {
        DELETE(fatdir);
    }

    return TRUE;

#endif // _SETUP_LOADER_
}


SECTORCOUNT
FAT_SA::QueryFreeSectors(
    ) CONST
/*++

Routine Description:

    This routine computes the number of unused sectors on disk.

Arguments:

    None.

Return Value:

    The number of free sectors on disk.

--*/
{
    if (!_fat) {
        perrstk->push(ERR_NOT_READ, QueryClassId());
        return 0;
    }

    return _fat->QueryFreeClusters()*QuerySectorsPerCluster();
}


FATTYPE
FAT_SA::QueryFatType(
    ) CONST
/*++

Routine Description:

    This routine computes the FATTYPE of the FAT for this volume.

Arguments:

    None.

Return Value:

    The FATTYPE for the FAT.

--*/
{
    return _ft;
}



#if !defined( _AUTOCHECK_ ) && !defined(_SETUP_LOADER_) && !defined( _EFICHECK_ )

BOOLEAN
FAT_SA::QueryLabel(
    OUT PWSTRING    Label
    ) CONST
/*++

Routine Description:

    This routine queries the label from the FAT superarea.
    If the label is not present then 'Label' will return the null-string.
    If the label is invalid then FALSE will be returned.

Arguments:

    Label   - Returns a volume label.

Return Value:

    FALSE   - The label is invalid.
    TRUE    - The label is valid.

--*/
{
    return QueryLabel(Label, NULL);
}


BOOLEAN
FAT_SA::QueryLabel(
    OUT PWSTRING    Label,
    OUT PTIMEINFO   TimeInfo
    ) CONST
/*++

Routine Description:

    This routine queries the label from the FAT superarea.
    If the label is not present then 'Label' will return the null-string.
    If the label is invalid then FALSE will be returned.

Arguments:

    Label   - Returns a volume label.

Return Value:

    FALSE   - The label is invalid.
    TRUE    - The label is valid.

--*/
{
    INT         i;
    FAT_DIRENT  dirent;
    FILETIME    TimeStamp;
    PFATDIR     _fat_dir;
    UCHAR       FatType;

    if (!_dirF32) {

        DebugAssert(_dir);
        _fat_dir = _dir;
        FatType = FAT_TYPE_EAS_OKAY;

    } else {

        _fat_dir = _dirF32;
        FatType = FAT_TYPE_FAT32;
    }

    for (i = 0; ; i++) {
        if (!dirent.Initialize(_fat_dir->GetDirEntry(i), FatType) ||
            dirent.IsEndOfDirectory()) {
            return Label->Initialize("");
        }

        if (!dirent.IsErased() && dirent.IsVolumeLabel()) {
            break;
        }
    }

    dirent.QueryName(Label);

    if ( TimeInfo ) {
        return ( dirent.QueryLastWriteTime( (LARGE_INTEGER *)&TimeStamp ) &&
                 TimeInfo->Initialize( &TimeStamp ) );
    }

    return TRUE;
}

#else // _AUTOCHECK_ or _SETUP_LOADER_ is defined

BOOLEAN
FAT_SA::QueryLabel(
    OUT PWSTRING    Label
    ) CONST
{
    INT         i;
    FAT_DIRENT  dirent;

    PFATDIR     _fat_dir;

    if (!_dirF32) {

        DebugAssert(_dir);
        _fat_dir = _dir;

    } else {

        _fat_dir = _dirF32;
    }

    for (i = 0; ; i++) {
        if (!dirent.Initialize(_fat_dir->GetDirEntry(i)) ||
            dirent.IsEndOfDirectory()) {
            return Label->Initialize("");
        }

        if (!dirent.IsErased() && dirent.IsVolumeLabel()) {
            break;
        }
    }

    dirent.QueryName(Label);

    return TRUE;
}


#endif // _AUTOCHECK_


BOOLEAN
FAT_SA::SetLabel(
    IN  PCWSTRING   NewLabel
    )
/*++

Routine Description:

    This routine sets the label for a FAT partition.

Arguments:

    NewLabel    - Supplies the new volume label.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
    FAT_DIRENT  dirent;
    INT         i;
    DSTRING     label;
    PFATDIR     _fat_dir;
    UCHAR       FatType;

    if (!_dir) {

        if (!_dirF32) {
            return FALSE;
        }

        _fat_dir = _dirF32;
        FatType = FAT_TYPE_FAT32;

    } else {
        _fat_dir = _dir;
        FatType = FAT_TYPE_EAS_OKAY;
    }

    if (!label.Initialize(NewLabel)) {
        return FALSE;
    }

    if (!label.Strupr()) {
        return FALSE;
    }

    if (!IsValidString(&label)) {
        return FALSE;
    }

    for (i = 0; dirent.Initialize(_fat_dir->GetDirEntry(i), FatType); i++) {

        if (dirent.IsEndOfDirectory()) {
            break;
        }

        if (dirent.IsErased()) {
            continue;
        }

        if (dirent.IsVolumeLabel()) {
            if (!label.QueryChCount()) {
                dirent.SetErased();
                return TRUE;
            }

            return (BOOLEAN) (dirent.SetLastWriteTime() &&
                              dirent.SetName(&label));
        }
    }

    if (!label.QueryChCount()) {
        return TRUE;
    }

    if (!dirent.Initialize(_fat_dir->GetFreeDirEntry(), FatType)) {
        return FALSE;
    }

    dirent.Clear();
    dirent.SetVolumeLabel();

    return (BOOLEAN) (dirent.SetLastWriteTime() && dirent.SetName(&label));
}


UFAT_EXPORT
ULONG
FAT_SA::QueryFileStartingCluster(
    IN  PCWSTRING   FullPathFileName,
    OUT PHMEM       Hmem,
    OUT PPFATDIR    Directory,
    OUT PBOOLEAN    DeleteDirectory,
    OUT PFAT_DIRENT DirEntry
    )
/*++

⌨️ 快捷键说明

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