PE文件格式详解(下)
2006-07-20 11:43:35 来源:WEB开发网既然语言ID结点是树中最后的目录结点,那么入口结构的OffsetToData域就是到一个叶子结点(即前面提到过的IMAGE_RESOURCE_DATA_ENTRY结构)的偏移量。
再回过头来参考图2,你会发现每个语言目录入口都对应着一个数据入口。这个结点仅仅表示了资源数据的尺寸以及资源数据的相对虚拟地址。
在资源数据段(.rsrc)之中拥有这么多结构有一个好处,就是你可以不存取资源本身而直接可以从这个段收集很多信息。例如,你可以获得有多少种资源、哪些资源(如果有的话)使用了特别的语言ID、特定的资源是否存在以及单独种类资源的尺寸。为了示范如何利用这一信息,以下的函数说明了如何决定一个文件中包含的不同种类的资源: // PEFILE.C
这个函数将一个资源种类名称的列表写入了由pszResTypes标识的变量中。请注意,在这个函数的核心部分,LoadString是使用各自资源种类目录入口的Name域来作为字符串ID的。如果你查看PEFILE.RC,你会发现我定义了一系列的资源种类的字符串,并且它们的ID与它们在目录入口中的定义完全相同。PEFILE.DLL还有有一个函数,它返回了.rsrc段中的资源对象总数。这样一来,从这个段中提取其它的信息,借助这些函数或另外编写函数就方便多了。
int WINAPI GetListOfResourceTypes(LPVOID lpFile, HANDLE hHeap, char **pszResTypes)
{
PIMAGE_RESOURCE_DIRECTORY prdRoot;
PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
char *pMem;
int nCnt, i;
/* 获得资源树的根目录 */
if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY)ImageDirectoryOffset
(lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
return 0;
/* 在堆上分配足够的空间来包括所有类型 */
nCnt = prdRoot->NumberOfIdEntries * (MAXRESOURCENAME + 1);
*pszResTypes = (char *)HeapAlloc(hHeap, HEAP_ZERO_MEMORY,
nCnt);
if ((pMem = *pszResTypes) == NULL)
return 0;
/* 将指针指向第一个资源种类的入口 */
prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdRoot +
sizeof (IMAGE_RESOURCE_DIRECTORY));
/* 在所有的资源目录入口类型中循环 */
for (i = 0; i < prdRoot->NumberOfIdEntries; i++)
{
if (LoadString(hDll, prde->Name, pMem, MAXRESOURCENAME))
pMem += strlen(pMem) + 1;
prde++;
}
return nCnt;
}
更多精彩
赞助商链接