技术开发 频道

VS与Win7 共舞:用户界面特权隔离

  现在,我们可以调用ShellExecute,以不同的特权等级运行这个应用程序,他们虽然处于不同的特权等级,但是由于我们使用ChangeWindowMessageFilter将自定义的消息添加进了白名单,他们都可以处理这个自定义的消息了。

    // 应用程序名称
       LPCTSTR exeName = _T("UIPIDemo.exe");
    
// 以不同的特权等级运行同一个应用程序
      
// 更高权限
    HINSTANCE h1 = ShellExecute(NULL, _T("runas"), exeName, NULL, NULL, SW_SHOWDEFAULT);
    
// 中等权限
       HINSTANCE h2 = ShellExecute(NULL, _T("open"), exeName, NULL, NULL, SW_SHOWDEFAULT);

  在Windows 7中,为了更加灵活地控制消息的传入,它引入了一个新的函数ChangeWindowMessageFilterEx,这个新的扩展函数可以为某个特定的窗口制定消息白名单,而不是像ChangeWindowMessageFilter一样为整个进程制定白名单。

// Windows 7新引入的函数
BOOL ChangeWindowMessageFilterEx(
    HWND hWnd, UINT message, DWORD action,
    PCHANGEFILTERSTRUCT pChangeFilterStruct
);

  在这个函数中,参数action表示这个函数的动作,它可以是MSGFLT_ALLOW (类似于 MSGFLT_ADD),MSGFLT_DISALLOW (类似于 MSGFLT_REMOVE), 和 MSGFLT_RESET,表示将窗口设置为它的默认过滤器。

  托管代码中绕过UIPI

  以上的例子演示了在非托管代码中调用ChangeWindowMessageFilter实现消息过滤白名单,允许消息通过用户界面特权隔离的过程。在托管代码中,我们还是使用这个API函数。为了便于使用,我们对这个API函数做一些包装。在托管代码中,我们用一个类来封装所有我们所需要的API函数:

// 用类封装对API函数的调用
internal static class NativeWrappers {
        [DllImport(
"user32")]
        
public static extern uint RegisterWindowMessage(string msg);

        [DllImport(
"user32")]
        
public static extern bool PostMessage(IntPtr hWnd,
                    
uint msg, IntPtr wParam, IntPtr lParam);

        
public enum ChangeWindowMessageFilterFlags : uint {
            Add
= 1, Remove = 2
        };

        [DllImport(
"user32")]
        
public static extern bool ChangeWindowMessageFilter(uint msg,
                     ChangeWindowMessageFilterFlags flags);
    }

  完成API的封装后,我们就可以在主程序中直接使用这个类,完成进程消息过滤器白名单的设置。

public PingPongForm() {
            InitializeComponent();

                      
// 注册消息
            _message = NativeWrappers.RegisterWindowMessage("BALL");
            
if(_message == 0)
                Close();
            
else {
                            
// 添加可以通过的消息
                NativeWrappers.ChangeWindowMessageFilter(_message,
                                     NativeWrappers.ChangeWindowMessageFilterFlags.Add);
                            
// 发送消息
                NativeWrappers.PostMessage(Program.hOtherForm,
                                     _message, Handle, IntPtr.Zero);
            }
        }

  用户特权等级隔离,就像进程窗口的门神,把不受欢迎的Windows消息隔离在外,把列在客人名单上的Windows消息请进来。门神守候,家宅无忧!

  图3  门神守候,家宅无忧

系列文章索引:

        VS与Win7共舞:系统服务的Session 0隔离

        VS与Win7共舞:UAC惹祸 如何进行安装程序检测?

        VS2010与Win7共舞:UAC与数据重定向

        VS2010与Win7共舞:ETW自定义程序日志

        VS与Win7共舞:性能计数器进行性能分析

        VS2010与Windows7共舞:对库进行编程

        VS与Windows 7共舞:库(Library)

        VS2010与Win7共舞:响应Ribbon控件消息

        VS与Win7共舞:用XML文件定义Ribbon界面

        VS 2010与Windows7共舞:又见Ribbon

        VS2010与Win7共舞 :任务栏状态提示

        VS2010与Win7共舞 :任务栏缩略图

        VS2010与Windows 7共舞:Jumplist

0
相关文章