用API枚举字符串资源请各位高手帮忙:我想枚举PE文件里的String Table的一个个String。只要枚举出ID即可。我用EnumResourceName来做如下枚举:
EnumResourceNames(hMyDll, RT_STRING, EnumStrResFunc, (LONG_PTR)&UserData);结果用一个有十来个字符串的DLL来试验,枚举回调函数才被调了4次?!而且每次送来的lpszName的值根本就不能用!MSDN上说lpszName的值,不是字符串形式的资源名,就是直接的ID值。可回调函数送来的值好像什么也不是!我不知道该怎样利用这个值。我试着用 FindResource -> LoadResource -> LockResource 从回调函数送来的lpszType和lpszName获得一个void*指针,结果查看指针地址,发现里面只有一些乱七八糟的字符串,不是我想要的。请问该如何用Win32 API来枚举(搜索)一个DLL或exe里面的所有字符串资源?就好像资源修改器所做的那样。难道要用 for(i = 1~65535) LoadString(i)吗?这样会很慢吧?!

解决方案 »

  1.   

    参考MSDN例程
    找到
    hResInfo = FindResourceEx(hModule, lpType, lpName, wLang);
    这个语句,在后面加上
    HGLOBAL hg = LoadResource(hModule, hResInfo);
    LPVOID lp = LockResource(hg);
    你看看lp指向的地址里边写的是什么。:)例程
    http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/resources/introductiontoresources/usingresources.asp?frame=true#_win32_Creating_a_Resource_List
      

  2.   

    下面的代码在VS2005下测试可用。不过因为MSDN上代码可能太老了,将就改的,可读性不是很强。
    CWinApp theApp;using namespace std;#include <strsafe.h>
    #pragma comment (lib, strsafe.lib)
    char szBuffer[80]; // print buffer for EnumResourceTypes 
    DWORD cbWritten;   // number of bytes written to res. info. file 
    size_t cbString;      // length of string in sprintf
    HRESULT hResult;HMODULE hExe = LoadLibraryA("hand.exe"); 
    HANDLE hFile = CreateFileA("resinfo.txt",      // name of file 
    GENERIC_READ | GENERIC_WRITE,      // access mode 
    0,                                 // share mode 
    (LPSECURITY_ATTRIBUTES) NULL,      // default security 
    CREATE_ALWAYS,                     // create flags 
    FILE_ATTRIBUTE_NORMAL,             // file attributes 
    (HANDLE) NULL);                    // no template // Declare callback functions. 
    BOOL EnumTypesFunc( 
       HANDLE hModule, 
       LPTSTR lpType, 
       LONG lParam); BOOL EnumNamesFunc( 
       HMODULE hModule, 
       LPCTSTR lpType, 
       LPTSTR lpName, 
       LONG lParam); BOOL EnumLangsFunc( 
       HMODULE hModule, 
       LPCTSTR lpType, 
       LPCTSTR lpName, 
       WORD wLang, 
       LONG lParam); 
    //    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 

    size_t cbString;
    HRESULT hResult; // Write the resource type to a resource information file. 
    // The type may be a string or an unsigned decimal 
    // integer, so test before printing. 
    if ((ULONG)lpType & 0xFFFF0000) 

    hResult = StringCchPrintfA(szBuffer, 80/sizeof(TCHAR), "Type: %s\n", lpType);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;
    }
    // cbString = sprintf(szBuffer, "Type: %s\n", lpType); 

    else 
    {
    hResult = StringCchPrintfA(szBuffer, 80/sizeof(TCHAR), "Type: %u\n", (USHORT)lpType);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;
    }
    //        cbString = sprintf(szBuffer, "Type: %u\n", (USHORT)lpType); 

    hResult = StringCchLengthA(szBuffer, 80/sizeof(TCHAR), &cbString);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;

    WriteFile(hFile, szBuffer, (DWORD) cbString, 
    &cbWritten, NULL); 
    // Find the names of all resources of type lpType. 
    EnumResourceNames((HMODULE)hModule, 
    lpType, 
    (ENUMRESNAMEPROC)EnumNamesFunc, 
    0);  return TRUE; 
    } //    FUNCTION: EnumNamesFunc(HANDLE, LPSTR, LPSTR, LONG) 
    // 
    //    PURPOSE:  Resource name callback 
    BOOL EnumNamesFunc( 
       HMODULE 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 

    size_t cbString; 
    HRESULT hResult; // Write the resource name to a resource information file. 
    // The name may be a string or an unsigned decimal 
    // integer, so test before printing. 
    if ((ULONG)lpName & 0xFFFF0000) 
    {
    hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), "\tName: %s\n", lpName);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;
    }
    //        cbString = sprintf(szBuffer, "\tName: %s\n", lpName); 

    else 
    {
    hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), "\tName: %u\n", (USHORT)lpName);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;

    //        cbString = sprintf(szBuffer, "\tName: %u\n", 
    //(USHORT)lpName); 
    }
    hResult = StringCchLength(szBuffer, 80/sizeof(TCHAR), &cbString);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;
    }  WriteFile(hFile, szBuffer, (DWORD) cbString, 
    &cbWritten, NULL); 
    // Find the languages of all resources of type 
    // lpType and name lpName. 
    EnumResourceLanguages(hModule, 
    lpType, 
    lpName, 
    (ENUMRESLANGPROC)EnumLangsFunc, 
    0);  return TRUE; 
    } //    FUNCTION: EnumLangsFunc(HANDLE, LPSTR, LPSTR, WORD, LONG) 
    // 
    //    PURPOSE:  Resource language callback 
    BOOL EnumLangsFunc( 
       HMODULE 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 

    HRSRC hResInfo; 
    char szBuffer[80]; 
    size_t cbString = 0; 
    HRESULT hResult; hResInfo = FindResourceEx(hModule, lpType, lpName, wLang);
    HGLOBAL hg = LoadResource(hModule, hResInfo);
    LPVOID lp = LockResource(hg);
    // Write the resource language to the resource information file.
    hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR), "\t\tLanguage: %u\n", (USHORT) wLang);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;
    }
    hResult = StringCchLength(szBuffer, 80/sizeof(TCHAR), &cbString);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;

    //    cbString = sprintf(szBuffer, "\t\tLanguage: %u\n", (USHORT)wLang); 
    WriteFile(hFile, szBuffer, (DWORD) cbString, 
    &cbWritten, NULL); 
    // Write the resource handle and size to buffer. 
    cbString = sprintf(szBuffer, 
    "\t\thResInfo == %lx,  Size == %lu\n\n", 
    hResInfo, 
    SizeofResource(hModule, (HRSRC)hResInfo)); 
    WriteFile(hFile, szBuffer, (DWORD) cbString, 
    &cbWritten, NULL); 
    return TRUE; 
    } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    int nRetCode = 0; // 初始化 MFC 并在失败时显示错误
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
    // TODO: 更改错误代码以符合您的需要
    _tprintf(_T("错误: MFC 初始化失败\n"));
    nRetCode = 1;
    }
    else
    {
    // TODO: 在此处为应用程序的行为编写代码。
    // Load the .EXE whose resources you want to list. 
    if (hExe == NULL) 
    {
    // Add code to fail as securely as possible.
    return 0;
    }  // Create a file to contain the resource info. 
    if (hFile == INVALID_HANDLE_VALUE) { 
    // ErrorHandler("Could not open file."); 
    }  // Find all of the loaded file's resources.
    hResult = StringCchPrintf(szBuffer, 80/sizeof(TCHAR),  
    // cbString = sprintf(szBuffer, 
    "The file contains the following resources:\n\n");
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;
    }
    hResult = StringCchLength(szBuffer, 80/sizeof(TCHAR), &cbString);
    if (FAILED(hResult))
    {
    // Add code to fail as securely as possible.
    return 0;

    WriteFile(hFile,           // file to hold resource info. 
    szBuffer,              // what to write to the file 
    (DWORD) cbString,      // number of bytes in szBuffer 
    &cbWritten,            // number of bytes written 
    NULL);                 // no overlapped I/O  EnumResourceTypes(hExe,              // module handle 
    (ENUMRESTYPEPROC)EnumTypesFunc,  // callback function 
    0);                              // extra parameter 
    // Unload the executable file whose resources were 
    // enumerated and close the file created to contain 
    // the resource information. 
    FreeLibrary(hExe); 
    CloseHandle(hFile); 
    } return nRetCode;
    }
      

  3.   

    试过字符串资源了。呵呵
    msdn上说,【String resources are stored in sections of up to 16 strings per section. The strings in each section are stored as a sequence of counted (not null-terminated) Unicode strings.】,EnumNamesFunc里边的lpName要么是一个字符指针,以#开头,后面是section序号,要么是一个最高位为0的整形数据(强制转换一下为ULONG),也是这个Section序号。
      

  4.   

                        // 
                        // Stablupd.exe Manipulate String Resources in an Executable
                        // Article ID : 196774  
                        //
                        http://support.microsoft.com/kb/q196774/                    //          
                        // The format of string resources
                        // 
                        http://blogs.msdn.com/oldnewthing/archive/2004/01/30/65013.aspx
      

  5.   

    哦,闹了半天EnumResourceNames枚举出来的是String Table的区段啊?那MSDN上专门解释该API的文档可是一点都没有提,它怎么这么不负责啊,真他妈孙子!!!感谢各位高手指点!感谢。