- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有没有办法得到 DisableUserModeCallbackFilter
(或类似)在 Windows 10 上工作?
它应该允许从用户模式代码引发的异常跨用户/内核边界传播,并且它在 Windows 7 之前的早期 Windows 版本上有一个修补程序,但我似乎无法让它在最近的版本上运行版本。
这是一个在 Windows 10 x64 上似乎出错的测试程序,但在 Windows XP x86 上却没有:
#include <tchar.h>
#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "user32")
WNDPROC oldproc = NULL;
LRESULT CALLBACK newproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
_ftprintf(stderr, _T("OMG\n"));
fflush(stderr);
throw 0;
return oldproc(hwnd, uMsg, wParam, lParam);
}
int _tmain(int argc, TCHAR *argv[])
{
HWND hWnd = CreateWindowEx(0, TEXT("STATIC"), TEXT("Name"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, NULL);
oldproc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)newproc);
try {
UpdateWindow(hWnd);
} catch (int ex) {
_ftprintf(stderr, _T("Error: %d\n"), ex);
fflush(stderr);
}
}
最佳答案
当调用窗口过程时 - 内核在内核堆栈和用户模式下推送额外的堆栈帧称为特殊“函数”(偶数标签比普通函数更快)KiUserCallbackDispatcher
,它调用窗口过程,最后通过特殊的api调用返回内核ZwCallbackReturn
弹出内核堆栈帧。请注意,通话后 ZwCallbackReturn
我们不会返回到它之后的下一条指令,而是从我们进入内核的地方返回,从那里将调用用户模式回调(通常来自 GetMessage
或 PeekMessage
)。
无论如何,我们必须弹出内核堆栈帧 - 所以调用 ZwCallbackReturn
.所以在 KiUserCallbackDispatcher
中出现展开异常的情况- 设计错误,不能工作。在这种情况下谁调用 ZwCallbackReturn
?如果它会从 __finally
调用KiUserCallbackDispatcher
中的处理程序- 这个中断展开过程(ZwCallbackReturn
我怎么说永不返回,但就像跳远一样 - 用另一个堆栈指针和所有寄存器将我们移动到另一个地方)。即使您手动调用ZwCallbackReturn
来自 catch
- 打完电话后你会在哪里?
所以需要在 KiUserCallbackDispatcher
之前处理异常SEH 处理程序或最小有多少 __finally
block ,如果需要取消分配一些资源。KiUserCallbackDispatcher
使用 SEH
调用处理程序 ZwCallbackReturn
即使异常将在回调中。然而,这个 SEH 处理程序的行为可能会受到 RTL_USER_PROCESS_PARAMETERS.Flags
中未记录的标志的影响。 :
伪代码:
void KiUserCallbackDispatcher(...)
{
__try {
//...
} __except(KiUserCallbackExceptionFilter(GetExceptionInformation())) {
KiUserCallbackDispatcherContinue:
ZwCallbackReturn(0, 0, 0);
}
}
void LdrpLogFatalUserCallbackException(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT ContextRecord);
int KiUserCallbackExceptionFilter(PEXCEPTION_POINTERS pep)
{
if ( NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->Flags & 0x80000)
{
return EXCEPTION_EXECUTE_HANDLER;
}
LdrpLogFatalUserCallbackException(pep->ExceptionRecord, pep->ContextRecord);
return EXCEPTION_CONTINUE_EXECUTION;
}
如果此标志 (
0x80000
) 未设置 (默认) -
LdrpLogFatalUserCallbackException
叫。它在内部调用
UnhandledExceptionFilter
如果它不返回
EXCEPTION_CONTINUE_EXECUTION
- 称为
ZwRaiseException
与
STATUS_FATAL_USER_CALLBACK_EXCEPTION
和
FirstChance = FALSE
(这意味着此异常未传递给应用程序 - 仅用于调试器作为最后机会异常)
EXCEPTION_EXECUTE_HANDLER
将从过滤器返回 -
RtlUnwindEx
将被调用(使用
TargetIp = KiUserCallbackDispatcherContinue
) - 结果为
__finally
处理程序将被调用,最后
ZwCallbackReturn(0, 0, 0);
在任何情况下,异常都不会在
的函数中传递给 SEH更高 在堆栈中,比
KiUserCallbackDispatcher
(因为这里会处理异常)
KiUserCallbackDispatcher
下面的堆栈中处理异常或将标志设置为
0x80000
- 在这种情况下,如果我们在
KiUserCallbackDispatcher
之前不处理异常- 我们的
__finally
block (如果存在)将在
ZwCallbackReturn
之前执行完成回调。
SetProcessUserModeExceptionPolicy
没有在最近的 Windows 版本中导出(从 win8 开始),但是这个 api 的年度代码是下一个(确切的代码):
#define PROCESS_CALLBACK_FILTER_ENABLED 0x1
BOOL WINAPI SetProcessUserModeExceptionPolicy(DWORD dwFlags)
{
PLONG pFlags = (PLONG)&NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->Flags;
if (dwFlags & PROCESS_CALLBACK_FILTER_ENABLED)
{
_bittestandset(pFlags, 19); // |= 0x80000
}
else
{
_bittestandreset(pFlags, 19); // &= ~0x80000
}
return TRUE;
}
测试:
WNDPROC oldproc;
LRESULT CALLBACK newproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)oldproc);
__try {
*(int*)0=0;
//RaiseException(STATUS_ACCESS_VIOLATION, 0, 0, 0);
} __finally {
DbgPrint("in finally\n");
CallWindowProc(oldproc, hwnd, uMsg, wParam, lParam);
}
return 0;
}
void test()
{
RtlGetCurrentPeb()->ProcessParameters->Flags |= 0x80000;
if (HWND hwnd = CreateWindowExW(0, WC_EDIT, L"***", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL, NULL))
{
oldproc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)newproc);
__try {
ShowWindow(hwnd, SW_SHOW);
}__except(EXCEPTION_EXECUTE_HANDLER){
DbgPrint("no sense. never will be called\n");
}
MSG msg;
while (0 < GetMessage(&msg, hwnd, 0, 0))
{
DispatchMessage(&msg);
}
}
}
尝试评论或取消评论
RtlGetCurrentPeb()->ProcessParameters->Flags |= 0x80000;
行(或
NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->Flags & 0x80000
相同)并比较效果。
关于c++ - 有没有办法让 DisableUserModeCallbackFilter 在 Windows 10 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49372987/
有没有办法得到 DisableUserModeCallbackFilter (或类似)在 Windows 10 上工作? 它应该允许从用户模式代码引发的异常跨用户/内核边界传播,并且它在 Window
我是一名优秀的程序员,十分优秀!