0

我有一些仅限资源的 dll,我想将它们转换为十六进制格式的 *.cpp 文件。稍后从 *.cpp 文件中获取资源。但是,我不知道该怎么做。

这是 *.cpp 格式(示例格式)?

unsigned long g_XXXResourceMap[172] = 
{
    0x7725,0xa,0x0,0xd21,0x7726, 0xa,0xd21,0xf99,0x7727, 0xa,0x1cba,0xe15,0x7728, 0xa,0x2acf,0xd7f,
    0x7729,0xa,0x384e,0xcf2,0x772a, 0xa,0x4540,0xc75,0x772b, 0xa,0x51b5,0x128a,0x772c, 0xa,0x643f,0xda1,
    0x772d,0xa,0x71e0,0xf51,0x7744, 0xa,0x8131,0xda5,0x7745, 0xa,0x8ed6,0xcc2,0x7746, 0xa,0x9b98,0xe18,
};

unsigned char g_XXXResourceArray[55001] = 
{
    0x78,0x9c,0x1,0x16,0xd,0xe9,0xf2,0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,
    0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0x18,
    0x8,0x6,0x0,0x0,0x0,0xe0,0x77,0x3d,0xf8,0x0,0x0,0x0,0x9,0x70,0x48,0x59,
    0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,
};
4

1 回答 1

1

看看这个,我花了几个小时来实现它。注意:代码使用 C++ 11、STL 和 Lambda。我用Visual Studio 2010编译,代码如下:

#include "stdafx.h"
#include "function.h"

/*
0: type
1: name
2: Lang
*/
typedef std::tuple<VARIANT, VARIANT, DWORD> resInfoTuple;

// Declare callback functions. 
BOOL EnumTypesFunc( 
    HANDLE hModule, 
    LPTSTR lpType, 
    LONG lParam); 

BOOL EnumNamesFunc( 
    HANDLE hModule, 
    LPCTSTR lpType, 
    LPTSTR lpName, 
    LONG lParam); 

BOOL EnumLangsFunc( 
    HANDLE hModule, 
    LPCTSTR lpType, 
    LPCTSTR lpName, 
    WORD wLang, 
    LONG lParam); 

void rawData2Hex(
    CCodec_ModuleMgr*,
    HMODULE hRes, 
    std::wofstream& wofs, 
    const wchar_t* wsInxAryName, 
    const wchar_t* wsDataAryName, 
    std::vector<resInfoTuple>& vecResInfo
    );

namespace omg
{
    int res2C(
        const wchar_t* szFileName, 
        const wchar_t* wsInxAryName, 
        const wchar_t* wsDataAryName,
        const wchar_t* outFileName
        ) 
    {
        // Load the .EXE whose resources you want to list. 
        auto hRes = LoadLibrary(szFileName); 
        if (hRes == NULL) 
        {
            // Add code to fail as securely as possible.
            return -1;
        } 

        std::wofstream wofs;
        std::vector<resInfoTuple>vecResInfo;

        CCodec_ModuleMgr *  pCodecModuleMgr = nullptr;
        CPDF_Document*      pDoc = nullptr;
        CPDF_Parser*        pParser = nullptr;

        //initialization
        pCodecModuleMgr = CCodec_ModuleMgr::Create();
        CFX_GEModule::Create();
        CFX_GEModule::Get()->SetCodecModule(pCodecModuleMgr);
        CPDF_ModuleMgr::Create();
        CPDF_ModuleMgr* pModule = CPDF_ModuleMgr::Get();
        if (pModule)
        {
            pModule->SetCodecModule(pCodecModuleMgr);
            pModule->InitPageModule();
            pModule->InitRenderModule();
        }

        auto bRes = EnumResourceTypes(hRes,  // module handle 
            (ENUMRESTYPEPROC)EnumTypesFunc,  // callback function 
            (LONG_PTR)&vecResInfo);          // extra parameter 
        if(!bRes) return -1;

        wofs.open(outFileName, std::ios_base::ate/* | std::ios_base::binary*/);
        rawData2Hex(pCodecModuleMgr, hRes, wofs, wsInxAryName, wsDataAryName, vecResInfo);

        // Unload the executable file whose resources were 
        // enumerated and close the file created to contain 
        // the resource information. 
        FreeLibrary(hRes); 

        wofs.close();

        pCodecModuleMgr->Destroy();
        CFX_GEModule::Destroy();
        CPDF_ModuleMgr::Destroy();

        return 0;
    }//--end res2C

}//--end namespace::omg

//    FUNCTION: EnumTypesFunc(HANDLE, LPSTR, LONG) 
// 
//    PURPOSE:  Resource type callback 
BOOL EnumTypesFunc( 
    HANDLE hModule,   // module handle 
    LPTSTR lpType,    // address of resource type 
    LONG lParam)      // extra parameter, could be 
    // used for error checking 
{ 
    // Find the names of all resources of type lpType. 
    EnumResourceNames((HMODULE)hModule, 
        lpType, 
        (ENUMRESNAMEPROC)EnumNamesFunc, 
        lParam); 

    return TRUE; 
} 

//    FUNCTION: EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG) 
// 
//    PURPOSE:  Resource name callback 
BOOL EnumNamesFunc( 
    HANDLE hModule,   // module handle 
    LPCTSTR lpType,   // address of resource type 
    LPTSTR lpName,    // address of resource name 
    LONG lParam)      // extra parameter, could be 
    // used for error checking 
{ 
    // Find the languages of all resources of type 
    // lpType and name lpName. 
    EnumResourceLanguages((HMODULE)hModule, 
        lpType, 
        lpName, 
        (ENUMRESLANGPROC)EnumLangsFunc, 
        lParam); 

    return TRUE; 
} 

//    FUNCTION: EnumLangsFunc(HANDLE, LPSTR, LPSTR, WORD, LONG) 
// 
//    PURPOSE:  Resource language callback 
BOOL EnumLangsFunc( 
    HANDLE hModule,  // module handle 
    LPCTSTR lpType,  // address of resource type 
    LPCTSTR lpName,  // address of resource name 
    WORD wLang,      // resource language 
    LONG lParam)     // extra parameter, could be 
    // used for error checking 
{
    std::vector<resInfoTuple>& vecResInfo = *(std::vector<resInfoTuple>*)lParam;
    HANDLE hResInfo; 
    size_t cbString = 0; 

    hResInfo = FindResourceEx((HMODULE)hModule, lpType, lpName, wLang); 

    VARIANT varType = {0};
    VARIANT varName = {0};
    if ((ULONG)lpType & 0xFFFF0000) 
    {
        varType.vt = VT_BSTR;
        varType.bstrVal = _bstr_t(lpType);
    }
    else 
    {
        varType.vt = VT_UI2;
        varType.uiVal = (USHORT)lpType;
    }

    if ((ULONG)lpName & 0xFFFF0000) 
    {
        varName.vt = VT_BSTR;
        varName.bstrVal = _bstr_t(lpName);
    }
    else 
    {
        varName.vt = VT_UI2;
        varName.uiVal = (USHORT)lpName;
    }
    vecResInfo.push_back(std::make_tuple(varType, varName, wLang));

    return TRUE; 
} 

void rawData2Hex(
    CCodec_ModuleMgr* pCodecModuleMgr,
    HMODULE hRes, 
    std::wofstream& wofs, 
    const wchar_t* wsInxAryName, 
    const wchar_t* wsDataAryName,
    std::vector<resInfoTuple>& vecResInfo)
{
    using namespace std;
    unsigned __int64  offset = 0;
    size_t lineFeedFlag = 1;

    wstringstream wss;
    wss << endl;
    std::vector<FX_BYTE> vecBytes;
    wss << L"unsigned long " << wsInxAryName << L"[" 
        //<< vecResInfo.size() * 4
        << "] = " << endl << "{" << endl;

    auto inxAry2Hex = 
    [pCodecModuleMgr, &wss, &vecBytes, &hRes, &lineFeedFlag, &offset]
    (resInfoTuple& param, const wchar_t* format) mutable -> void
    {
        auto varType = std::get<0>(param);
        auto varName = std::get<1>(param);
        auto wLang = std::get<2>(param);

        bool bRawData = (VT_BSTR == varType.vt);
        HRSRC hResInfo = nullptr;       
        hResInfo = FindResourceEx((HMODULE)hRes, 
            bRawData ? (LPCTSTR)varType.bstrVal : (LPCTSTR)varType.uiVal, 
            (VT_BSTR == varName.vt) ? (LPCTSTR)varName.bstrVal : (LPCTSTR)varName.uiVal, wLang); 

        CString strOut;
        auto srcSize = SizeofResource(hRes, hResInfo);
        auto hData = LoadResource((HMODULE)hRes, hResInfo);
        auto pSrcData = (unsigned char*)LockResource(hData);

        FX_LPBYTE pDestBuf = nullptr;
        FX_DWORD destSize = 0;
        if(2 != varType.uiVal)
            FlateEncode(pSrcData, srcSize, pDestBuf, destSize);
        else
        {
            auto pBasicModule = pCodecModuleMgr->GetBasicModule();
            ASSERT(nullptr != pBasicModule);
            pBasicModule->RunLengthEncode(pSrcData, srcSize, pDestBuf, destSize);
        }

        vecBytes.insert(vecBytes.end(), pDestBuf, pDestBuf + destSize);

        UnlockResource(pSrcData);
        FreeResource(hData);

        /*name / id, type, offset, size*/
        strOut.Format(format, varName.uiVal, bRawData ? 10 : varType.uiVal, offset, destSize);
        if(1 == lineFeedFlag)
            wss << '\t';
        wss << strOut.GetBuffer();
        if(0 == lineFeedFlag % 2)
        {
            lineFeedFlag = 1;
            wss << std::endl;
        }else
            ++lineFeedFlag;

        offset += destSize;
    };
    if(vecResInfo.size() > 0)
    {
        auto& param = *vecResInfo.begin();
        inxAry2Hex(param, _T("0x%08x, 0x%08x, 0x%08llx, 0x%08x"));
    }

    for(auto iter = vecResInfo.begin() + 1; iter != vecResInfo.end(); ++iter)
    {
        auto& param = *iter;
        inxAry2Hex(param, _T(", 0x%08x, 0x%08x, 0x%08llx, 0x%08x"));
    }//--end for each(auto& param in vecResInfo)    
    wss << endl << L"};" << endl << endl;

    lineFeedFlag = 1;
    wss << L"unsigned char " << wsDataAryName << L"["
        //<< vecBytes.size() 
        << "] = " << endl << "{" << endl;

    if(vecBytes.size() > 0)
    {
        FX_BYTE param = *vecBytes.begin();
        CString strOut;
        strOut.Format(_T("0x%02x"), param);

        wss << '\t' << strOut.GetBuffer();

        ++lineFeedFlag;
    }
    for_each(vecBytes.begin() + 1, vecBytes.end(), 
        [lineFeedFlag, &wss](FX_BYTE param) mutable
    {
        CString strOut;
        strOut.Format(_T(", 0x%02x"), param);
        if(1 == lineFeedFlag)
            wss << '\t';
        wss << strOut.GetBuffer();
        if(0 == lineFeedFlag % 21)
        {
            lineFeedFlag = 1;
            wss << std::endl;
        }else
            ++lineFeedFlag;
    }
    );//--end for_each

    wss << endl << L"};";

    wofs << L"extern const size_t " << wsInxAryName << L"Cnt = " 
        << vecResInfo.size() * 4 << L";" << endl;

    wofs << L"extern const size_t " << wsDataAryName << L"Cnt = " 
        << vecBytes.size() << L";" << endl;

    wofs << wss.str();
}
于 2013-07-23T13:33:39.200 回答