为什么窗口挂钩被阻止调用SendMessage

huangapple go评论49阅读模式
英文:

why is window hook blocked from calling SendMessage

问题

I'm having problems with communicating between a window called from hook and my main app using SendMessage.
The code is basically a global hook defined as:

hookCallWndProc = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, ModuleFromAddress(CallWndProc), 0);

and when the event occurs globally, the callback function CallWndProc is called from which I use SendMessage(callbackWindowHandle, 12345, NULL, NULL);

and the message is received on my message-only window under the 12345 code for all windows except Firefox. But the code in CallWndProc for Firefox gets executed also because I tested it by calling SetWindowPos and was able to change the position of the window.

LRESULT CALLBACK CallWndProc(int code, WPARAM wparam, LPARAM lparam) 
{ 	
	if (code >= 0) 	
	{
 		CWPSTRUCT* pCwpStruct = (CWPSTRUCT*)lparam;
 		switch (pCwpStruct->message)
 		{ 		
			case WM_WINDOWPOSCHANGED:
 			{ 			
				WINDOWPOS* pWindowPosStruct = (WINDOWPOS*)pCwpStruct->lParam;
 				SendMessage(callbackWindowHandle, 12345, NULL, NULL);
 				SetWindowPos(pCwpStruct->hwnd, NULL, 600, 200, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
 				break;
 			}
 		}
 	}
 	return CallNextHookEx(hookCallWndProc, code, wparam, lparam);
}

Another hook that doesn't work for the Firefox window is the global CBT hook:

hookCbt = SetWindowsHookEx(WH_CBT, CBTProc, ModuleFromAddress(CBTProc), 0);

where CBTProc is defined:

LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	switch (nCode)
	{
		case HCBT_ACTIVATE:
			SendMessage(callbackWindowHandle, 12346, NULL, NULL);
			break;
	}
	return CallNextHookEx(hookCbt, nCode, wParam, lParam);
}

Why does the SendMessage function call not work for the Firefox window? Is there any other way to communicate with another process from the hook callback beside SendMessage?

I tried subclassing the Firefox window, which succeeds, but SendMessage/PostMessage/NotifyMessage don't work.

英文:

I'm having problems with communicating between a window called from hook and my main app using SendMessage.
The code is basically a global hook defined as:

hookCallWndProc = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, ModuleFromAddress(CallWndProc), 0);

and when event occurs globally the callback function CallWndProc is called from which I use SendMessage(callbackWindowHandle, 12345, NULL, NULL);
and the message is received on my message-only window under 12345 code for all windows except firefox.
but the code in CallWndProc for firefox gets executed also because I tested it by calling SetWindowPos and was able to change the position of window.

LRESULT CALLBACK CallWndProc(int code, WPARAM wparam, LPARAM lparam) 
{ 	
	if (code >= 0) 	
	{
 		CWPSTRUCT* pCwpStruct = (CWPSTRUCT*)lparam;
 		switch (pCwpStruct->message)
 		{ 		case WM_WINDOWPOSCHANGED:
 		{ 			WINDOWPOS* pWindowPosStruct = (WINDOWPOS*)pCwpStruct->lParam;
 			SendMessage(callbackWindowHandle, 12345, NULL, NULL);
 			SetWindowPos(pCwpStruct->hwnd, NULL, 600, 200, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
 			break;
 		}
 		}
 	}
 	return CallNextHookEx(hookCallWndProc, code, wparam, lparam); }

Another hook that doesnt work for firefox window is global CBT hook:
hookCbt = SetWindowsHookEx(WH_CBT, CBTProc, ModuleFromAddress(CBTProc), 0);
where CBTProc is defined:

LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	switch (nCode)
	{
	case HCBT_ACTIVATE:
		SendMessage(callbackWindowHandle, 12346, NULL, NULL);
		break;
	}
	return CallNextHookEx(hookCbt, nCode, wParam, lParam);
}

why does SendMessage function call not work for firefox window? Is there any other way to communicate with another process from hook callback beside SendMessage?

I tried subclassing firefox window which succeeds but SendMessage/PostMessage/NotifyMessage don't work.

答案1

得分: 1

解决方案是使用ChangeWindowMessageFilterEx,将消息参数设置为12345,将操作参数设置为MSGFLT_ALLOW,据推测,Firefox会过滤所有消息,只允许自己使用的消息以及从其进程空间(或窗口)发送的消息。

您的解决方案是正确的,但您的推理是错误的。

FireFox(以及其他网络浏览器)通常作为低完整性进程运行,出于安全目的(即通过隔离浏览器来保护计算机免受不受欢迎的互联网危险)。因此,当您的挂钩运行在Firefox(或其他网络浏览器)进程内,并尝试向较高完整性进程发送窗口消息,例如您的主应用程序时,UIPI默认情况下会阻止该消息。如果您的代码检查SendMessage()的失败情况,就会了解到这一点,根据其文档

消息发送受到UIPI的限制。进程的线程只能向较低或等完整性级别的进程中的线程的消息队列发送消息。

...

当消息被UIPI阻止时,通过GetLastError检索到的最后一个错误代码被设置为5(拒绝访问)。

在您的应用程序内调用ChangeWindowMessageFilterEx()允许您告诉UIPI允许来自较低完整性进程(如FireFox)的自定义消息传递。

英文:

> Solution was to use ChangeWindowMessageFilterEx and pass 12345 for message parameter and MSGFLT_ALLOW for action parameter, presumably firefox filters all messages but ones it uses and to be sent out from its process space (or window).

Your solution is correct, but your reasoning is not.

FireFox (and other web browsers) are typically run as low-integrity processes, for security/safety purposes (ie, to sandbox the browser to protect your machine from unwanted Internet dangers).

As such, when your hook runs inside of a Firefox (or other web browser) process, and it tries to send out a window message to a higher-integrity process, such as your main app, UIPI blocks the message by default. Which you would have known had your code been checking SendMessage() for failure, per its documentation:

> Message sending is subject to UIPI. The thread of a process can send messages only to message queues of threads in processes of lesser or equal integrity level.
>
> ...
>
> When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).

Calling ChangeWindowMessageFilterEx() inside of your app lets you tell UIPI to allow your custom message to come through from lower-integrity processes, like FireFox.

huangapple
  • 本文由 发表于 2023年3月12日 16:34:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75711925.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定