列出使用Win32 API存储在仅资源库(DLL)中的消息标识和符号名称 [英] Listing message IDs and symbolic names stored in a resource-only library (DLL) using Win32 API

查看:210
本文介绍了列出使用Win32 API存储在仅资源库(DLL)中的消息标识和符号名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们想列出嵌入在仅资源库(DLL)中的消息的内容(键/值对)



资源库定义为指定的在MSDN

  mc -s EventLogMsgs.mc 
rc EventLogMsgs.rc
link / DLL / SUBSYSTEM:WINDOWS / NOENTRY / MACHINE:x86 EventLogMsgs.Res

示例EventLogMsgs.mc可能是:

 ; //  -  Event categories  -  
; //类别必须从1开始连续编号。
; // ************************************************ ********

MessageId = 0x1
严重性=成功
SymbolicName = INSTALL_CATEGORY
语言=英语
安装


MessageId = 0x2
严重性=成功
SymbolicName = QUERY_CATEGORY
语言=英语
数据库查询


...

我们尝试使用EnumResourceTypes

  ... 
HMODULE hMod = NULL;
hMod = LoadLibraryA(C:\\temp\\EventLogMsgs.dll);
if(hMod!= NULL)
{
EnumResourceTypes(hMod,(ENUMRESTYPEPROC)TypesCallback,0);
FreeLibrary(hMod);
}
...

BOOL WINAPI TypesCallback(HMODULE hModule,LPTSTR lpType,LONG lParam)
{
char buffer [100]
if((ULONG)lpType& 0xFFFF0000)
sprintf(buffer,%s\\\
,lpType);
else
sprintf(buffer,%u\\\
,(USHORT)lpType);

cout<< Type:<<缓冲液< std :: endl;

EnumResourceNames(hModule,lpType,(ENUMRESNAMEPROC)NamesCallback,0);
return true;
}

BOOL WINAPI NamesCallback(HMODULE hModule,LPCTSTR lpType,LPTSTR lpName,LONG lParam)
{
char buffer [100]
if((ULONG)lpName& 0xFFFF0000)
sprintf(buffer,%s\\\
,lpName);
else
sprintf(buffer,%u\\\
,(USHORT)lpName);
cout<< Name:<<缓冲液< std :: endl;
return true;
}

结果是高级别的资源类型列表及其标识符,例如

  ... 
类型:11
名称:1

类型:16
名称:1

类型:24
名称:2
...

11(RT_MESSAGETABLE)是消息表资源类型(查看所有资源类型



理想情况下,我们希望列出 ALL 资源库中的实际消息的符号名称和标识符。



感谢

解决方案

您枚举了模块中的资源它告诉你一个特定类型的每个资源的名称。完成后,您需要加载资源以检查其内容。在你的case你需要类型 RT_MESSAGETABLE 的资源,名为 1



现在需要使用 FindResource LoadResource LockResource 获取指向消息表结构开头的指针。然后,您可以使用 MESSAGE_RESOURCE_DATA 结构,依次 MESSAGE_RESOURCE_BLOCK MESSAGE_RESOURCE_ENTRY 解包消息表的内容。本代码项目文章详细介绍了此过程。 / p>

这里是一个naff C程序,枚举你的消息表:

  #include< windows.h> 
#include< stdio.h>

int ProcessBlock(MESSAGE_RESOURCE_DATA * data,MESSAGE_RESOURCE_BLOCK * block)
{
MESSAGE_RESOURCE_ENTRY * entry =(MESSAGE_RESOURCE_ENTRY *)((unsigned char *)data + block-> OffsetToEntries) ;
for(DWORD id = block-> LowId; id <= block-> HighId; id ++)
{
if(entry-> Flags == 0x0001)// wide char
printf(%d,%ls,id,entry-> Text);
else if(entry-> Flags == 0x0000)// ANSI
printf(%d,%s,id,entry-> Text);
entry =(MESSAGE_RESOURCE_ENTRY *)((unsigned char *)entry + entry-> Length);
}
return 1;
}

int main(void)
{
HMODULE hMod = LoadLibrary(C:\\desktop\\EventLogMsgs.dll);
if(hMod == NULL)return 1;

HRSRC hRsrc = FindResource(hMod,MAKEINTRESOURCE(1),RT_MESSAGETABLE);
if(hRsrc == NULL)return 1;

HGLOBAL hGlobal = LoadResource(hMod,hRsrc);
if(hGlobal == NULL)return 1;

MESSAGE_RESOURCE_DATA * data =(MESSAGE_RESOURCE_DATA *)LockResource(hGlobal);
if(data == NULL)return 1;

for(DWORD block = 0; block< data-> NumberOfBlocks; block ++)
if(!ProcessBlock(data,& data-& b $ b return 1;

return 0;
}

输出

 
1,安装
2,数据库查询
3,数据刷新
1000,我的应用程序消息文本1000,从%1调用。
1002,我的英文通用信息消息,消息ID为1002.
1004,%% 5002的更新周期已完成。
5001,示例事件日志
5002,SVC_UPDATE.EXE
-2147482647,我的应用程序消息文本,英语,消息标识1001,从%1调用。
-2147482645,我的英文通用警告消息,消息ID为1003,从%1调用。
-2147482643,刷新操作未完成,因为无法建立与服务器%1的连接。

请原谅我骇人听闻的C.无论是C还是C ++都是我不熟悉的语言。但是,代码将至少显示如何提取您所需的信息。


We would like to list the contents (key/value pairs) of messages embedded in a resource-only library (DLL)

The resource library is defined as specified in MSDN.

mc -s EventLogMsgs.mc
rc EventLogMsgs.rc
link /DLL /SUBSYSTEM:WINDOWS /NOENTRY /MACHINE:x86 EventLogMsgs.Res 

A sample EventLogMsgs.mc may be:

; // - Event categories -
; // Categories must be numbered consecutively starting at 1.
; // ********************************************************

MessageId=0x1
Severity=Success
SymbolicName=INSTALL_CATEGORY
Language=English
Installation
.

MessageId=0x2
Severity=Success
SymbolicName=QUERY_CATEGORY
Language=English
Database Query
.

...

We tried to use EnumResourceTypes() Win32 API as following:

...
HMODULE hMod=NULL;
hMod = LoadLibraryA( "C:\\temp\\EventLogMsgs.dll" ); 
if (hMod != NULL) 
{
    EnumResourceTypes( hMod, (ENUMRESTYPEPROC)TypesCallback, 0) ;
    FreeLibrary(hMod);
}
...

BOOL WINAPI TypesCallback( HMODULE hModule, LPTSTR lpType, LONG lParam )
{
    char buffer[100];
    if ((ULONG)lpType & 0xFFFF0000) 
        sprintf( buffer, "%s\n", lpType); 
    else 
        sprintf(buffer, "%u\n", (USHORT)lpType); 

    cout << "Type: " << buffer << std::endl;

    EnumResourceNames( hModule, lpType, (ENUMRESNAMEPROC)NamesCallback, 0 );
    return true;
}

BOOL WINAPI NamesCallback( HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG lParam )
{
    char buffer[100];
    if ((ULONG)lpName & 0xFFFF0000) 
        sprintf(buffer,"%s\n", lpName); 
    else 
        sprintf(buffer, "%u\n",(USHORT)lpName); 
    cout << "Name: " << buffer << std::endl;
    return true;
}

The result is a high level listing of the resource types and their "names/identifiers", e.g.,

...
Type: 11
Name: 1

Type: 16
Name: 1

Type: 24
Name: 2
...

11 (RT_MESSAGETABLE) is the message table resource type (See all resource types)

Ideally we would want to list ALL the actual messages' symbolic names and identifiers in the resource library.

Thanks

解决方案

You've enumerated the resources in the module which tells you the name of each resource of a specific type. Once you've done that you need to load the resource to examine its content. In your case you need the resource of type RT_MESSAGETABLE that is named 1.

You now need to use FindResource, LoadResource and LockResource to get a pointer to the beginning of the message table structures. You can then use the MESSAGE_RESOURCE_DATA struct , and in turn MESSAGE_RESOURCE_BLOCK and MESSAGE_RESOURCE_ENTRY to unpack the content of the message table. This Code Project article goes into more detail on the process.

Here's a rather naff C program that enumerates your message table:

#include <windows.h>
#include <stdio.h>

int ProcessBlock(MESSAGE_RESOURCE_DATA* data, MESSAGE_RESOURCE_BLOCK* block)
{
    MESSAGE_RESOURCE_ENTRY* entry = (MESSAGE_RESOURCE_ENTRY*) ((unsigned char*)data + block->OffsetToEntries);
    for (DWORD id = block->LowId; id <= block->HighId; id++)
    {
        if (entry->Flags == 0x0001) // wide char
            printf("%d, %ls", id, entry->Text);
        else if (entry->Flags == 0x0000) // ANSI
            printf("%d, %s", id, entry->Text);
        entry = (MESSAGE_RESOURCE_ENTRY*) ((unsigned char*)entry + entry->Length);
    }
    return 1;
}

int main(void)
{
    HMODULE hMod = LoadLibrary("C:\\desktop\\EventLogMsgs.dll"); 
    if (hMod == NULL) return 1;

    HRSRC hRsrc = FindResource(hMod, MAKEINTRESOURCE(1), RT_MESSAGETABLE);
    if (hRsrc == NULL) return 1;

    HGLOBAL hGlobal = LoadResource(hMod, hRsrc);
    if (hGlobal == NULL) return 1;

    MESSAGE_RESOURCE_DATA* data = (MESSAGE_RESOURCE_DATA*)LockResource(hGlobal);
    if (data == NULL) return 1;

    for (DWORD block = 0; block < data->NumberOfBlocks; block++)
        if (!ProcessBlock(data, &data->Blocks[block]))
            return 1;

    return 0;
}

Output

1, Installation
2, Database Query
3, Data Refresh
1000, My application message text, in English, for message id 1000, called from %1.
1002, My generic information message in English, for message id 1002.
1004, The update cycle is complete for %%5002.
5001, Sample Event Log
5002, SVC_UPDATE.EXE
-2147482647, My application message text, in English, for message id 1001, called from %1.
-2147482645, My generic warning message in English, for message id 1003, called from %1.
-2147482643, The refresh operation did not complete because the connection to server %1 could not be established.

Please excuse my appalling C. Neither C nor C++ are languages that I am remotely fluent in. However, the code will at least show you how to extract the information you desire.

这篇关于列出使用Win32 API存储在仅资源库(DLL)中的消息标识和符号名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆