在Vista/Win7系统中,由于UAC和UIPI的存在,低权限的进程是无法向高权限的进程发送任何高于WMUSER的消息,而低于WMUSER的消息一部分也会因为安全原因被禁止。详情可见:《UAC的前世今生》 。但这样就会带来很多麻烦,比如文件拖曳的操作在管理员权限的进程中就无法进行。
解决这个问题的方法大致有两种:
回到正题:管理员权限的进程之所以无法进行拖曳文件的操作就是因为explorer.exe本身的权限低于它,WMDROPFILES的消息被堵塞了。所以只要在程序或者窗口初始化的时候调用ChangeWindowMessageFilter这个API就可以了。 ChangeWindowMessageFilter(WMDROPFILES, MSGFLT_ADD);
嗯,这样就OK了?把这代码往自己的程序中一拷,却发现被坑爹了:还是不行。正确的做法应该是需要放行以下三条消息:
ChangeWindowMessageFilter(WMDROPFILES, MSGFLTADD); ChangeWindowMessageFilter(WMCOPYDATA, MSGFLTADD); ChangeWindowMessageFilter(WMCOPYGLOBALDATA , MSGFLTADD);
其中WMCOPYGLOBALDATA在winodws.h中并没有相应的定义,也可以直接用它的数值0×0049来代替。至于为啥要这么做,并没有很明确的官方文档说明,不过也可以猜出个大概:WMCOPYDATA和WM_COPYGLOBALDATA是用于explorer.exe和当前进程进行进程通信的消息。不过MSDN上并不推荐使用这个方法,因为这个方法杀伤范围太大,影响的是当前整个进程,更推荐使用ChangeWindowMessageFilterEx,对某个特地窗口进行消息过滤:这样减少了filter对程序的影响,保证了安全又不至于无法实现某些特定功能。