通过SendMessage执行IPC时,如何处理32位/64位不匹配? < >我有一段C++代码,它使用窗口消息读取树项(如在一个平面中包含的文本)。接收mesage的树视图处于不同的进程中,因此我使用了一点共享内存作为窗口消息的一个参数所指向的结构。我必须做这项工作,因为远程进程不在我的控制之下(我正在编写一个类似于Spy++的应用程序)
这在原则上运行良好,但在目标流程实质上不同的情况下失败:通过SendMessage执行IPC时,如何处理32位/64位不匹配? < >我有一段C++代码,它使用窗口消息读取树项(如在一个平面中包含的文本)。接收mesage的树视图处于不同的进程中,因此我使用了一点共享内存作为窗口消息的一个参数所指向的结构。我必须做这项工作,因为远程进程不在我的控制之下(我正在编写一个类似于Spy++的应用程序),c++,windows,winapi,sendmessage,C++,Windows,Winapi,Sendmessage,这在原则上运行良好,但在目标流程实质上不同的情况下失败: 如果目标进程的代码是使用UNICODE定义构建的,但我自己的代码不是,那么这两个进程将对进程中字符串成员的结构有不同的想法。我已经通过一个调用解决了这个问题,然后明确地发送了TVM\u GETITEMA或TVM\u GETITEMW(如果需要,记录结果) 如果调用进程是以32位模式构建的,而目标进程是64位(或者反过来),那么结构的布局(和大小)是不同的,因为指针的大小不同 我目前正试图找到解决第二个问题的好方法。这个特定的用例(获取树项
TVM\u GETITEMA
或TVM\u GETITEMW
(如果需要,记录结果)还有其他人必须解决类似的问题吗?有更简单的解决方案吗?我想有设计问题。我不知道你为什么要这样做,也许你不能完全控制所有部分。但从基本的MVC角度来看,您是在从视图中窥视值,而不是向模型询问值。我不熟悉这条特定消息,但是如果Windows TVM_GETITEM消息应该在多个进程中正常运行,然后Windows应该在调用方的地址空间中填充TVTItem结构,并为您处理任何需要的转换,而不需要您提供共享内存。如果不是,那么我怀疑你在这里看到的问题是很容易解决的,没有一些不舒服的扭曲
共享内存位让我困惑;通常,您必须使这两个进程明确地知道共享内存段,并且您没有提到DLL注入或类似的内容。被调用方如何确切地知道其地址空间中的共享内存部分,以及您如何使用它?你确定这个API需要它吗?我在运行时检查远程进程是32位还是64位,然后在发送消息之前将正确的结构写入共享内存 例如,下面是如何使用
TVM_GETITEM
消息,即使消息的调用者和接收者之间存在32位64位的混淆:
/* This template is basically a copy of the TVITEM struct except that
* all fields which return a pointer have a variable type. This allows
* creating different types for different pointer sizes.
*/
template <typename AddrType>
struct TVITEM_3264 {
UINT mask;
AddrType hItem;
UINT state;
UINT stateMask;
AddrType pszText;
int cchTextMax;
int iImage;
int iSelectedImage;
int cChildren;
AddrType lParam;
};
typedef TVITEM_3264<UINT32> TVITEM32;
typedef TVITEM_3264<UINT64> TVITEM64;
// .... later, I can then use the above template like this:
LPARAM _itemInfo;
DWORD pid;
::GetWindowThreadProcessId( treeViewWindow, &pid );
if ( is64BitProcess( pid ) ) {
TVITEM64 itemInfo;
ZeroMemory( &itemInfo, sizeof( itemInfo ) );
itemInfo.mask = TVIF_HANDLE | TVIF_TEXT;
itemInfo.hItem = (UINT64)m_item;
itemInfo.pszText = (UINT64)(LPTSTR)sharedMem->getSharedMemory( sizeof(itemInfo) );
itemInfo.cchTextMax = MaxTextLength;
_itemInfo = (LPARAM)sharedMem->write( &itemInfo, sizeof(itemInfo) );
} else {
TVITEM32 itemInfo;
ZeroMemory( &itemInfo, sizeof( itemInfo ) );
itemInfo.mask = TVIF_HANDLE | TVIF_TEXT;
itemInfo.hItem = (UINT32)m_item;
itemInfo.pszText = (UINT32)(LPTSTR)sharedMem->getSharedMemory( sizeof(itemInfo) );
itemInfo.cchTextMax = MaxTextLength;
_itemInfo = (LPARAM)sharedMem->write( &itemInfo, sizeof(itemInfo) );
}
/*此模板基本上是TVTItem结构的副本,除了
*返回指针的所有字段都具有变量类型。这允许
*为不同的指针大小创建不同的类型。
*/
模板
结构TVITEM_3264{
核弹头面罩;
AddrType-hItem;
乌因州;
UINT状态掩码;
添加类型pszText;
int-cchTextMax;
国际图像;
int ISelecteImage;
国际儿童;
添加类型LPRAM;
};
类型定义TVITEM_3264 TVITEM32;
类型定义TVTItem_3264 TVTItem64;
// .... 稍后,我可以像这样使用上述模板:
LPARAM_itemInfo;
德沃德pid;
::GetWindowThreadProcessId(TreeView、Windows和pid);
if(IS64位进程(pid)){
tviitem64项目信息;
零内存(&itemInfo,sizeof(itemInfo));
itemInfo.mask=TVIF_句柄| TVIF_文本;
itemInfo.hItem=(UINT64)m_项;
itemInfo.pszText=(UINT64)(LPTSTR)sharedMem->getSharedMemory(sizeof(itemInfo));
itemInfo.cchTextMax=MaxTextLength;
_itemInfo=(LPARAM)sharedMem->write(&itemInfo,sizeof(itemInfo));
}否则{
tviitem32项目信息;
零内存(&itemInfo,sizeof(itemInfo));
itemInfo.mask=TVIF_句柄| TVIF_文本;
itemInfo.hItem=(UINT32)m_项;
itemInfo.pszText=(UINT32)(LPTSTR)sharedMem->getSharedMemory(sizeof(itemInfo));
itemInfo.cchTextMax=MaxTextLength;
_itemInfo=(LPARAM)sharedMem->write(&itemInfo,sizeof(itemInfo));
}
sharedMem->getSharedMemory
函数是一个小助手函数,用于获取指向共享内存区域的指针;可选函数参数指定偏移量值。重要的是,共享内存区域应始终位于32位地址空间中(这样即使是32位远程进程也可以访问它)。我必须完成所有这些工作,因为接收进程确实不在我的控制之下。我正在开发一个类似Spy++的应用程序。对不起,我应该在前面提到这个问题,我相应地补充了这个问题。不幸的是,只有16位窗口(如LB_GETTEXT
)可用的窗口消息才能在进程间正常工作。系统在后台进程之间复制数据。Th