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

📄 drivevolume.cpp

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        Info.Attributes.Compressed = (FindData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)    ? 1 : 0;
        Info.Attributes.Directory  = (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)     ? 1 : 0;
        Info.Attributes.Encrypted  = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED)     ? 1 : 0;
        Info.Attributes.Hidden     = (FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)        ? 1 : 0;
        Info.Attributes.Normal     = (FindData.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)        ? 1 : 0;
        Info.Attributes.Offline    = (FindData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE)       ? 1 : 0;
        Info.Attributes.ReadOnly   = (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)      ? 1 : 0;
        Info.Attributes.Reparse    = (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0;
        Info.Attributes.Sparse     = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE)   ? 1 : 0;
        Info.Attributes.System     = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)        ? 1 : 0;
        Info.Attributes.Temporary  = (FindData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)     ? 1 : 0;
        Info.Attributes.AccessDenied = 0;
        Info.Attributes.Unmovable    = 0;
        Info.Attributes.Process      = 1;

        Info.Clusters = 0;
        if (GetClusterInfo (Info, Handle))
        {
            uint64 TotalClusters = 0;

            for (int i = 0; i < Info.Fragments.size(); i++)
            {
                TotalClusters += Info.Fragments[i].Length;
            }

            Info.Clusters = TotalClusters;
        }
        else
        {
            Info.Attributes.Unmovable = 1;
            Info.Attributes.Process = 0;
        }

        if (Info.Attributes.Process == 1)
            Info.Attributes.Process = ShouldProcess (Info.Attributes) ? 1 : 0;

        // Run the user-defined callback function
        CallbackResult = Callback (Info, Handle, UserData);

        if (Handle != INVALID_HANDLE_VALUE)
            CloseHandle (Handle);

        if (!CallbackResult)
            break;

        // If directory, perform recursion
        if (Info.Attributes.Directory == 1)
        {
            wstring Dir;

            Dir = GetDBDir (Info.DirIndice);
            Dir += Info.Name;
            Dir += L"\\";

            Directories.push_back (Dir);
            ScanDirectory (Dir, Callback, UserData);
        }

    } while (FindNextFile (FindHandle, &FindData) == TRUE);

    FindClose (FindHandle);
    return (false);
}


bool DriveVolume::ShouldProcess (FileAttr Attr)
{
    if (Attr.Offline == 1  ||  Attr.Reparse == 1  ||  Attr.Temporary == 1)
    {
        return (false);
    }

    return (true);
}


// Gets info on a file and returns a valid handle for read/write access
// Name, FullName, Clusters, Attributes, and Size should already be filled out.
// This function fills in the Fragments vector
bool DriveVolume::GetClusterInfo (FileInfo &Info, HANDLE &HandleResult)
{
    BOOL     Result;
    HANDLE   Handle;
    wstring   FullName;
    BY_HANDLE_FILE_INFORMATION FileInfo;

    Info.Fragments.resize (0);

    /*
    if (Info.Attributes.Directory == 1)
        return (false);
    */

    FullName = GetDBDir (Info.DirIndice) + Info.Name;

    Handle = CreateFile
    (
        FullName.c_str(),
        0, //GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        (Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0,
        NULL
    );

    if (Handle == INVALID_HANDLE_VALUE)
    {
	    LPVOID lpMsgBuf;
 
	    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
					    NULL, GetLastError(), 
					    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
					    (LPTSTR) &lpMsgBuf, 0, NULL );
	    

        Info.Attributes.AccessDenied = 1;
	    LocalFree( lpMsgBuf );
        return (false);
    }

    ZeroMemory (&FileInfo, sizeof (FileInfo));
    Result = GetFileInformationByHandle (Handle, &FileInfo);

    if (Result == FALSE)
    {
        Info.Attributes.AccessDenied = 1;
        wprintf (L"GetFileInformationByHandle ('%s%s') failed\n", GetDBDir (Info.DirIndice).c_str(), 
            Info.Name.c_str());

        CloseHandle (Handle);
        return (false);
    }

    // Get cluster allocation information
    STARTING_VCN_INPUT_BUFFER  StartingVCN;
    RETRIEVAL_POINTERS_BUFFER *Retrieval;
    uint64                     RetSize;
    uint64                     Extents;
    DWORD                      BytesReturned;

    // Grab info one extent at a time, until it's done grabbing all the extent data
    // Yeah, well it doesn't give us a way to ask L"how many extents?" that I know of ...
    // btw, the Extents variable tends to only reflect memory usage, so when we have
    // all the extents we look at the structure Win32 gives us for the REAL count!
    Extents = 10;
    Retrieval = NULL;
    RetSize = 0;
    StartingVCN.StartingVcn.QuadPart = 0;

    do
    {
        Extents *= 2;
        RetSize = sizeof (RETRIEVAL_POINTERS_BUFFER) + ((Extents - 1) * sizeof (LARGE_INTEGER) * 2);

        if (Retrieval != NULL)
            Retrieval = (RETRIEVAL_POINTERS_BUFFER *) realloc (Retrieval, RetSize);
        else
            Retrieval = (RETRIEVAL_POINTERS_BUFFER *) malloc (RetSize);

        Result = DeviceIoControl
        (
            Handle,
            FSCTL_GET_RETRIEVAL_POINTERS,
            &StartingVCN,
            sizeof (StartingVCN),
            Retrieval,
            RetSize,
            &BytesReturned,
            NULL
        );

        if (Result == FALSE)
        {
            if (GetLastError() != ERROR_MORE_DATA)
            {
                Info.Clusters = 0;
                Info.Attributes.AccessDenied = 1;
                Info.Attributes.Process = 0;
                Info.Fragments.clear ();
                CloseHandle (Handle);
                free (Retrieval);

                return (false);
            }

            Extents++;
        }
    } while (Result == FALSE);

    // Readjust extents, as it only reflects how much memory was allocated and may not
    // be accurate
    Extents = Retrieval->ExtentCount;

    // Ok, we have the info. Now translate it. hrmrmr
    int i;
    Info.Fragments.clear ();
    for (i = 0; i < Extents; i++)
    {
        Extent Add;

        Add.StartLCN = Retrieval->Extents[i].Lcn.QuadPart;
        if (i != 0)
            Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->Extents[i - 1].NextVcn.QuadPart;
        else
            Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->StartingVcn.QuadPart;

        Info.Fragments.push_back (Add);
    }

    free (Retrieval);
    HandleResult = Handle;
    return (true);
}


bool DriveVolume::FindFreeRange (uint64 StartLCN, uint64 ReqLength, uint64 &LCNResult)
{
    uint64 Max;
    uint64 i;
    uint64 j;

    // Make sure we don't spill over our array
    Max = VolInfo.ClusterCount - ReqLength;

    for (i = StartLCN; i < Max; i++)
    {
        bool Found = true;

        // First check the first cluster
        if (IsClusterUsed (i))
            Found = false;
        else
        // THen check the last cluster
        if (IsClusterUsed (i + ReqLength - 1))
            Found = false;
        else
        // Check the whole darn range.
        for (j = (i + 1); j < (i + ReqLength - 2); j++)
        {
            if (IsClusterUsed (j) == true)
            {
                Found = false;
                break;
            }
        }

        if (!Found)
            continue;
        else
        {
            LCNResult = i;
            return (true);
        }
    }

    return (false);
}


// btw we have to move each fragment of the file, as per the Win32 API
bool DriveVolume::MoveFileDumb (uint32 FileIndice, uint64 NewLCN)
{
    bool ReturnVal = false;
    FileInfo Info;
    HANDLE FileHandle;
    wstring FullName;
    MOVE_FILE_DATA MoveData;
    uint64 CurrentLCN;
    uint64 CurrentVCN;

    // Set up variables
    Info = GetDBFile (FileIndice);
    FullName = GetDBDir (Info.DirIndice);
    FullName += Info.Name;
    CurrentLCN = NewLCN;
    CurrentVCN = 0;

    /*
    if (Info.Attributes.Directory == 1)
    {
        //
    }
    */

    // Open file
    FileHandle = CreateFile
    (
        FullName.c_str (),
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        (Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0,
        NULL
    );

    if (FileHandle == INVALID_HANDLE_VALUE)
    {
        //
	    LPVOID lpMsgBuf;

	    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
					    NULL, GetLastError(), 
					    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
					    (LPTSTR) &lpMsgBuf, 0, NULL );
	    

	    LocalFree (lpMsgBuf);
        //

        ReturnVal = false;
    }
    else
    {
        ReturnVal = true; // innocent until proven guilty ...

        for (uint32 i = 0; i < Info.Fragments.size(); i++)
        {
            BOOL Result;
            DWORD BytesReturned;

            //wprintf (L"%3u", i);

            MoveData.ClusterCount = Info.Fragments[i].Length;
            MoveData.StartingLcn.QuadPart = CurrentLCN;
            MoveData.StartingVcn.QuadPart = CurrentVCN;

            MoveData.FileHandle = FileHandle;

            /*
            wprintf (L"\n");
            wprintf (L"StartLCN: %I64u\n", MoveData.StartingLcn.QuadPart);
            wprintf (L"StartVCN: %I64u\n", MoveData.StartingVcn.QuadPart);
            wprintf (L"Clusters: %u (%I64u-%I64u --> %I64u-%I64u)\n", MoveData.ClusterCount,
                Info.Fragments[i].StartLCN,
                Info.Fragments[i].StartLCN + MoveData.ClusterCount,
                MoveData.StartingLcn.QuadPart,
                MoveData.StartingLcn.QuadPart + MoveData.ClusterCount - 1);
            wprintf (L"\n");
            */

            Result = DeviceIoControl
            (
                Handle,
                FSCTL_MOVE_FILE,
                &MoveData,
                sizeof (MoveData),
                NULL,
                0,
                &BytesReturned,
                NULL
            );

            //wprintf (L"\b\b\b");

            if (Result == FALSE)
            {
                //
	            LPVOID lpMsgBuf;
 
	            FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
					            NULL, GetLastError(), 
					            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
					            (LPTSTR) &lpMsgBuf, 0, NULL );
	            

	            LocalFree( lpMsgBuf );
                //

                ReturnVal = false;
                goto FinishUp;  // yeah, bite me
            }

            // Ok good. Now update our drive bitmap and file infos.
            uint64 j;
            for (j = 0; 
                 j < Info.Fragments[i].Length;
                 j++)
            {
                SetClusterUsed (Info.Fragments[i].StartLCN + j, false);
                SetClusterUsed (CurrentLCN + j, true);
                //BitmapDetail[Info.Fragments[i].StartLCN + j].Allocated = false;
                //BitmapDetail[CurrentLCN + j].Allocated = true;
            }

            CurrentLCN += Info.Fragments[i].Length;
            CurrentVCN += Info.Fragments[i].Length;
        }

        // Update file info either way
    FinishUp:
        CloseHandle (FileHandle);
        FileHandle = INVALID_HANDLE_VALUE;
        GetClusterInfo (Files[FileIndice], FileHandle);
        CloseHandle (FileHandle);
    }

    return (ReturnVal);
}


⌨️ 快捷键说明

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