4

自己解凍型 PE ファイルがどのように機能するかを理解しようとしています。誰かが私のコードが機能しない理由を説明したり、main() 部分を修正したりできますか?

#include <iostream>
#include <Windows.h>

using namespace std;

void ExtractResource(const HINSTANCE hInstance, WORD resourceID, const char* outputFilename);

int main()
{
    HINSTANCE hInst = GetModuleHandle (0);
    ExtractResource(hInst, 101, "101.dll");
    ExtractResource(hInst, 102, "102.dll");
    ExtractResource(hInst, 103, "103.dll");
    ExtractResource(hInst, 104, "104.dll");
    cout << "Files are now extracted!";
    Sleep(INFINITE);
}


void ExtractResource(const HINSTANCE hInstance, WORD resourceID, const char* outputFilename){

        // First find and load the required resource          

        HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(resourceID), "BINARY");

        if(hResource==NULL)

                return;

        HGLOBAL hFileResource = LoadResource(hInstance, hResource);



        // Now open and map this to a disk file          

        LPVOID lpFile = LockResource(hFileResource);          

        DWORD dwSize = SizeofResource(hInstance, hResource);            



        // Open the file and filemap          

        HANDLE hFile = CreateFileA(outputFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,

                FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY, NULL);          

        HANDLE hFilemap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwSize, NULL);            

        LPVOID lpBaseAddress = MapViewOfFile(hFilemap, FILE_MAP_WRITE, 0, 0, 0);            



        // Write the file

        CopyMemory(lpBaseAddress, lpFile, dwSize);            



        // Unmap the file and close the handles

        UnmapViewOfFile(lpBaseAddress);

        CloseHandle(hFilemap);

        CloseHandle(hFile);

}

リソースに 4 つの dll ファイルがありますが、これを使用してそれらを抽出できません。リソース ID は正しいはずです。リソース ヘッダーから確認しました。

問題はありますか、hInstそれとも他に何が間違っている可能性がありますか? 誰かが私を助けてくれることを願っています:) 私はちょうど1〜1か月前にCとC ++の学習を開始したので、許してください。

4

2 に答える 2

3

関数の戻り値をチェックせず、何か問題が発生したときに適切なメッセージを出力しないこと以外に、コードに問題はありません。また、hInstance を nullptr に置き換えることができ、それでも機能することに注意してください。

また、追加の権限が必要な場所に展開する場合は、プログラムを管理者として実行するか、管理者権限を強制的に要求するマニフェストを追加する必要がある場合があることに注意してください。

個人的には、リソース アプリケーションのいずれかでこれらを使用します。

    bool ExtractResource(std::uint16_t ResourceID, std::string OutputFileName, const char* ResType)
    {
        try
        {
            HRSRC hResource = FindResource(nullptr, MAKEINTRESOURCE(ResourceID), ResType);
            if (hResource == nullptr)
            {
                return false;
            }

            HGLOBAL hFileResource = LoadResource(nullptr, hResource);
            if (hFileResource == nullptr)
            {
                return false;
            }

            void* lpFile = LockResource(hFileResource);
            if (lpFile == nullptr)
            {
                return false;
            }

            std::uint32_t dwSize = SizeofResource(nullptr, hResource);
            if (dwSize == 0)
            {
                return false;
            }

            HANDLE hFile = CreateFile(OutputFileName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
            HANDLE hFilemap = CreateFileMapping(hFile, nullptr, PAGE_READWRITE, 0, dwSize, nullptr);
            if (hFilemap == nullptr)
            {
                return false;
            }

            void* lpBaseAddress = MapViewOfFile(hFilemap, FILE_MAP_WRITE, 0, 0, 0);
            CopyMemory(lpBaseAddress, lpFile, dwSize);
            UnmapViewOfFile(lpBaseAddress);
            CloseHandle(hFilemap);
            CloseHandle(hFile);

            return true;
        }
        catch (...) {}
        return false;
    }

Main.cpp:

#include "Resource.h"

bool Extract(HWND WindowHandle) //WindowHandle for MessageBox parent.
{
    return ExtractResource(101,"101.dll", "BINARY");
}

int main()
{
    std::cout<<"Extracted Successfully: "<<std::boolalpha<<Extract(GetModuleHandle(0));
}

繰り返しになりますが、リソースが埋め込まれているかどうかに関係なく CONSOLE アプリケーションを使用していることに十分注意してください。

于 2013-09-21T01:50:12.803 に答える
0

ほとんどの場合、受け入れられた回答は非常にうまく機能しますが、x86 システムに非常に大きなファイルがある場合は失敗する可能性があります。MapViewOfFileこの場合、 はNULLポインターをGetLastError返し、 を返しますERROR_NOT_ENOUGH_MEMORY

この問題を克服するために、コードを変更してファイルをチャンクで書き込み、同じ問題が発生した場合に備えてここに追加します。

bool ExtractResource(std::uint16_t ResourceID, std::wstring OutputFileName, LPCWSTR ResType)
{
    try
    {
        HRSRC hResource = FindResource(nullptr, MAKEINTRESOURCE(ResourceID), ResType);
        if (hResource == nullptr)
        {
            return false;
        }

        HGLOBAL hFileResource = LoadResource(nullptr, hResource);
        if (hFileResource == nullptr)
        {
            return false;
        }

        void* lpFile = LockResource(hFileResource);
        if (lpFile == nullptr)
        {
            return false;
        }

        std::uint32_t dwSize = SizeofResource(nullptr, hResource);
        if (dwSize == 0)
        {
            return false;
        }

        HANDLE hFile = CreateFile(OutputFileName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
        HANDLE hFilemap = CreateFileMapping(hFile, nullptr, PAGE_READWRITE, 0, dwSize, nullptr);
        if (hFilemap == nullptr)
        {
            return false;
        }
        
        ULONG ulChunkSize(65536);
        if (ULONG n = (ULONG)((dwSize + (ulChunkSize - 1)) / ulChunkSize))
        {
            LARGE_INTEGER offset = {};
            do
            {
                SIZE_T nBytes = (--n ? ulChunkSize : dwSize % ulChunkSize);
                void* lpBaseAddress = MapViewOfFile(hFilemap, FILE_MAP_WRITE, offset.HighPart, offset.LowPart, nBytes);
                if (lpBaseAddress != 0)
                {
                    CopyMemory(lpBaseAddress, lpFile, nBytes);
                    UnmapViewOfFile(lpBaseAddress);
                    lpFile = static_cast<char*>(lpFile) + nBytes;
                }
                else
                    return false;
            } while (offset.QuadPart += ulChunkSize, n);
            CloseHandle(hFilemap);
            CloseHandle(hFile);

            return true;

        }
    }
    catch (...) {}
    return false;
}
于 2021-01-25T12:25:45.327 に答える