WPF 調用 ChangeWindowMessageFilterEx 修改指定窗口 (UIPI) 消息篩選器的用戶界面特權隔離
一、回顧
上一篇博客:記錄一下 WPF進程 SendMessage 發送窗口消息進行進程間通信,存在進程權限無法接受消息的問題 - wuty007 - 博客園
說到了 發送端是普通權限的窗體 給 接收端是 管理員權限的窗體,通過 Win32 API的方式調用 SendMessage 發送窗口消息,管理員權限的窗體的鉤子消息回傳接受不到發送端的數據。
如下圖所示:

這是由于 Windows系統在Windows NT6.0 開始,引入了受保護模式,阻止進程將所選窗口消息和其他 USER API 發送到運行完整性較高的進程
詳情請看微軟的詳細說明:
受保護的模式 - Win32 apps | Microsoft Learn
Windows 完整性機制設計 | Microsoft Learn
二、函數說明
針對于以上的問題,微軟也提供了相對應的接口來規避: ChangeWindowMessageFilterEx
ChangeWindowMessageFilterEx 函數 (winuser.h)
修改指定窗口 (UIPI) 消息篩選器的用戶界面特權隔離。
語法
BOOL ChangeWindowMessageFilterEx( [in] HWND hwnd, [in] UINT message, [in] DWORD action, [in, out, optional] PCHANGEFILTERSTRUCT pChangeFilterStruct );
參數
[in] hwnd
類型:HWND
要修改其 UIPI 消息篩選器的窗口的句柄。
[in] message
類型: UINT
消息篩選器允許通過 或 阻止的消息。
[in] action
類型:DWORD
要執行的操作,可以采用以下值之一:
| 值 | 含義 |
|---|---|
|
允許消息通過篩選器。 這使 hWnd 能夠接收消息,無論消息的來源如何,即使消息來自較低特權進程也是如此。 |
|
阻止消息從較低特權進程傳遞到 hWnd ,除非使用 ChangeWindowMessageFilter 函數或全局允許該消息在進程范圍內傳遞。 |
|
將 hWnd 的窗口消息篩選器重置為默認值。 允許全局或進程范圍內的任何消息都將通過,但任何未包含在這兩個類別中以及來自較低特權進程的消息都將被阻止。 |
[in, out, optional] pChangeFilterStruct
類型: PCHANGEFILTERSTRUCT
指向 CHANGEFILTERSTRUCT 結構的可選指針。
返回值
類型: BOOL
如果函數成功,則返回 TRUE;否則,它將返回 FALSE。 要獲得更多的錯誤信息,請調用 GetLastError。
注解
UIPI 是一項安全功能,可防止從較低完整性級別的發件人接收消息。 可以使用此函數允許將特定消息傳遞到窗口,即使消息源自較低完整性級別的進程也是如此。 與控制進程消息篩選器的 ChangeWindowMessageFilter 函數不同, ChangeWindowMessageFilterEx 函數控制窗口消息篩選器。
應用程序可以使用 ChangeWindowMessageFilter 函數以進程范圍的方式允許或阻止消息。 如果進程消息篩選器或窗口消息篩選器允許該消息,則會將其傳遞到窗口。
請注意,不允許 SECURITY_MANDATORY_LOW_RID 或以下的進程更改消息篩選器。 如果這些進程調用此函數,它將失敗并生成擴展錯誤代碼, ERROR_ACCESS_DENIED。
無論篩選器設置如何,值小于 WM_USER 的某些消息都需要通過篩選器傳遞。 嘗試使用此函數允許或阻止此類消息時,將不起作用。
三、如何使用
1、WPF 的接受端窗口增加 對 ChangeWindowMessageFilterEx 函數的定義和封裝
// 定義MessageFilterAction 結構體 public enum MessageFilterAction : uint { MSGFLT_RESET = 0, // 重置過濾器 MSGFLT_ALLOW = 1, // 允許消息 MSGFLT_DISALLOW = 2 // 禁止消息 } // 定義 消息過濾器狀態結構體 [StructLayout(LayoutKind.Sequential)] public struct CHANGEFILTERSTRUCT { public uint cbSize; public uint ExtStatus; } // 導入 user32.dll 中的函數 [DllImport("user32.dll", SetLastError = true)] private static extern bool ChangeWindowMessageFilterEx( IntPtr hWnd, uint msg, MessageFilterAction action, ref CHANGEFILTERSTRUCT pChangeFilterStruct); /// <summary> /// 設置消息過濾 /// </summary> /// <param name="hWnd"></param> /// <param name="message"></param> /// <param name="action"></param> /// <returns></returns> /// <exception cref="System.ComponentModel.Win32Exception"></exception> public static bool SetMessageFilter(IntPtr hWnd, uint message, MessageFilterAction action) { // 初始化結構體 CHANGEFILTERSTRUCT changeFilter = new CHANGEFILTERSTRUCT { cbSize = (uint)Marshal.SizeOf(typeof(CHANGEFILTERSTRUCT)), ExtStatus = 0 }; // 調用 API bool result = ChangeWindowMessageFilterEx(hWnd, message, action, ref changeFilter); if (!result) { // 獲取錯誤信息(可選) int error = Marshal.GetLastWin32Error(); throw new System.ComponentModel.Win32Exception(error); } return result; }
2、在接收數據的 FramworkReceieve 窗口 的Loaded時間調用 SetMessageFilter,最主要的是第三個參數需要設置:MessageFilterAction.MSGFLT_ALLOW
private void MainWindow_Loaded(object sender, RoutedEventArgs e) { _customMessageId = RegisterWindowMessage("MyApp"); // 獲取窗口句柄并添加消息鉤子 _hwndSource = PresentationSource.FromVisual(this) as HwndSource; if (_hwndSource != null) { var handle = _hwndSource.Handle; SetMessageFilter(handle, WM_COPYDATA, MessageFilterAction.MSGFLT_ALLOW); _hwndSource.AddHook(WndProc); } }
3、完整代碼如下:
消息發送端:
<Window x:Class="FramworkSender.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:FramworkSender" mc:Ignorable="d" Title="FramworkSender" Height="450" Width="800"> <Grid> <Button Width="100" Height="100" Content="發送" Click="ButtonBase_OnClick"></Button> </Grid> </Window>
namespace FramworkSender { /// <summary> /// MainWindow.xaml 的交互邏輯 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { // 獲取接收窗口的句柄 IntPtr hwnd = FindWindow(null, "FramworkReceieve"); if (hwnd == IntPtr.Zero) { MessageBox.Show("找不到窗口"); } else { SendMessageString(hwnd, "123"); } } #region CopyData [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam); [DllImport("user32.dll" 主站蜘蛛池模板: 亚亚洲视频一区二区三区| 在线 国产 欧美 专区| 亚洲成人av在线资源| 国产成人精品午夜2022| 国产真人无遮挡免费视频| 在线高清理伦片a| 国产成人午夜精品永久免费| 国产精品免费看久久久| 亚洲第一精品一二三区| 无码一区中文字幕| 成人乱码一区二区三区四区| 2021国产精品一卡2卡三卡4卡| 人妻av中文字幕无码专区 | 伊人成人在线视频免费| 国产精品视频免费一区二区三区| 国产成人精品一区二三区在线观看| 成人午夜在线观看刺激| 国产精品香港三级国产av| 国产视频有码字幕一区二区| 推油少妇久久99久久99久久| 国产欧美日韩精品第二区| 国产日韩综合av在线| 国产精品亚洲а∨天堂2021 | 家庭乱码伦区中文字幕在线| 九九色这里只有精品国产 | 色伦专区97中文字幕| 日日碰狠狠添天天爽五月婷| 欧美激情精品久久久久久| 国内揄拍国内精品对久久| 亚洲avav天堂av在线网爱情| 麻豆人人妻人人妻人人片av| 自拍第一区视频在线观看| 亚洲男人第一无码av网站| 国产偷窥熟女高潮精品视频| 亚洲一区二区三区丝袜| 老鸭窝在钱视频| 久久天天躁夜夜躁狠狠85| 舟曲县| 国产不卡免费一区二区| 亚洲性日韩精品一区二区| 岛国大片在线免费播放|
