问题
在一次开发中,需要使用到WM_COPYDATA方式来实现两个进程之间的数据传输。在网络上可以找到很多关于WM_COPYDATA的示例代码,而且代码结构也比较简单易懂,所以WM_COPYDATA的示例代码不是今天要详细讨论的内容。
今天的问题存在于两个不同权限的进程,例如发送端进程运行在普通用户账户下,而接收端进程则运行在管理员账户下。在这种情况下,发送端发送的WM_COPYDATA消息,将不会被目标进程的窗口所接收到。
我们先来简单看一下WM_COPYDATA的发送端和接收端的示例代码
发送端代码
![8e22fdcb3bacb824a521362554881963.png](https://i-blog.csdnimg.cn/blog_migrate/b012bfac8f5629f28fe9d5f33d3a02de.jpeg)
接收端代码
![ea8fb278822b28ba3f04f7a23bd73cd6.png](https://i-blog.csdnimg.cn/blog_migrate/21eeb8c4fd01ae4420d234878600b3f2.jpeg)
解决方法
Windows Vista开始,微软引入一个安全机制:UIPI(User Interface Privilege Isolation)。此安全机制阻止低级别权限进程发送消息至高权限进程。但是,“只读”类消息不受此安全机制影响,例如用于获取目标窗口文本的消息WM_GETTEXT可以发送,但是用于设置文本的消息WM_SETEXT则会受到UIPI的影响。
为了解决上述WM_COPYDATA在高权限进程中收不到的问题,可以在接收端进程中调用ChangeWindowMessageFilterEx函数允许WM_COPYDATA通过目标窗口的消息过滤器。
具体调用方式如下所示:
ChangeWindowMessageFilterEx(hTargetWnd, WM_COPYDATA, MSGFLT_ALLOW, NULL);
此函数的作用:修改UIPI(User Interface Privilege Isolation)消息过滤器。
第一个参数:目标窗口句柄,表示此窗口的消息过滤器即将被修改。
第二个参数:标识具体是哪一个消息被允许或阻止,这里是WM_COPYDATA。
第三个参数:标识修改类型:允许/阻止/重置。
第四个参数:一个指向CHANGEFILTERSTRUCT结构体的指针,此结构体可以用来返回一些关于执行结果的信息。
总结
使用WM_COPYDATA消息,需要注意以下几点:
1) 使用WM_COPYDATA发送的数据中,不可以包含目标进程访问不了的对象指针或者引用。
2) 在发送WM_COPYDATA时,发送的数据不应该被发送进程的另一个线程修改。
3) 接收端进程应该视WM_COPYDATA携带的数据为只读,原则上,接收端进程不应该修改WM_COPYDATA携带的数据。
4) 发送端需要使用SendMessage函数来进行同步发送,防止数据离开作用域后销毁,进而导致接收端收到无效数据。
5) 建议接收端收到WM_COPYDATA携带的数据后,将其拷贝到本地缓冲区中,防止发送端数据无效。
![1c700438a61166a3470923e335277abd.png](https://i-blog.csdnimg.cn/blog_migrate/2574142c4123d008d38a40b1f9843fe4.jpeg)