用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)吗?这样会很慢吧?!
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)吗?这样会很慢吧?!
找到
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
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;
}
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序号。
// 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