mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-21 17:09:06 -07:00
Add more tests for old style hooks and winevent hooks, make them pass
under Wine.
This commit is contained in:
parent
6b16f29fc0
commit
ed04d36b5d
4 changed files with 463 additions and 35 deletions
|
@ -124,6 +124,12 @@ static HHOOK set_windows_hook( INT id, HOOKPROC proc, HINSTANCE inst, DWORD tid,
|
|||
WCHAR module[MAX_PATH];
|
||||
DWORD len;
|
||||
|
||||
if (!proc)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_FILTER_PROC );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tid) /* thread-local hook */
|
||||
{
|
||||
if (id == WH_JOURNALRECORD ||
|
||||
|
@ -143,7 +149,7 @@ static HHOOK set_windows_hook( INT id, HOOKPROC proc, HINSTANCE inst, DWORD tid,
|
|||
if (id == WH_KEYBOARD_LL || id == WH_MOUSE_LL) inst = 0;
|
||||
else if (!inst || !(len = GetModuleFileNameW( inst, module, MAX_PATH )) || len >= MAX_PATH)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
SetLastError( ERROR_HOOK_NEEDS_HMOD );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4510,6 +4510,7 @@ static BOOL RegisterWindowClasses(void)
|
|||
}
|
||||
|
||||
static HHOOK hCBT_hook;
|
||||
static DWORD cbt_hook_thread_id;
|
||||
|
||||
static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
@ -4517,12 +4518,14 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
|
||||
|
||||
ok(cbt_hook_thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
|
||||
|
||||
if (nCode == HCBT_SYSCOMMAND)
|
||||
{
|
||||
struct message msg;
|
||||
|
||||
msg.message = nCode;
|
||||
msg.flags = hook;
|
||||
msg.flags = hook|wparam|lparam;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
add_message(&msg);
|
||||
|
@ -4535,16 +4538,17 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
|||
|
||||
if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
|
||||
{
|
||||
if (!strcmp(buf, "TestWindowClass") ||
|
||||
!strcmp(buf, "TestParentClass") ||
|
||||
!strcmp(buf, "TestPopupClass") ||
|
||||
!strcmp(buf, "SimpleWindowClass") ||
|
||||
!strcmp(buf, "TestDialogClass") ||
|
||||
!strcmp(buf, "MDI_frame_class") ||
|
||||
!strcmp(buf, "MDI_client_class") ||
|
||||
!strcmp(buf, "MDI_child_class") ||
|
||||
!strcmp(buf, "my_button_class") ||
|
||||
!strcmp(buf, "#32770"))
|
||||
if (!lstrcmpiA(buf, "TestWindowClass") ||
|
||||
!lstrcmpiA(buf, "TestParentClass") ||
|
||||
!lstrcmpiA(buf, "TestPopupClass") ||
|
||||
!lstrcmpiA(buf, "SimpleWindowClass") ||
|
||||
!lstrcmpiA(buf, "TestDialogClass") ||
|
||||
!lstrcmpiA(buf, "MDI_frame_class") ||
|
||||
!lstrcmpiA(buf, "MDI_client_class") ||
|
||||
!lstrcmpiA(buf, "MDI_child_class") ||
|
||||
!lstrcmpiA(buf, "my_button_class") ||
|
||||
!lstrcmpiA(buf, "static") ||
|
||||
!lstrcmpiA(buf, "#32770"))
|
||||
{
|
||||
struct message msg;
|
||||
|
||||
|
@ -4571,22 +4575,25 @@ static void CALLBACK win_event_proc(HWINEVENTHOOK hevent,
|
|||
trace("WEH:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
|
||||
hevent, event, hwnd, object_id, child_id, thread_id, event_time);
|
||||
|
||||
ok(thread_id == GetCurrentThreadId(), "we didn't ask for events from other threads\n");
|
||||
|
||||
/* ignore mouse cursor events */
|
||||
if (object_id == OBJID_CURSOR) return;
|
||||
|
||||
if (!hwnd || GetClassNameA(hwnd, buf, sizeof(buf)))
|
||||
{
|
||||
if (!hwnd ||
|
||||
!strcmp(buf, "TestWindowClass") ||
|
||||
!strcmp(buf, "TestParentClass") ||
|
||||
!strcmp(buf, "TestPopupClass") ||
|
||||
!strcmp(buf, "SimpleWindowClass") ||
|
||||
!strcmp(buf, "TestDialogClass") ||
|
||||
!strcmp(buf, "MDI_frame_class") ||
|
||||
!strcmp(buf, "MDI_client_class") ||
|
||||
!strcmp(buf, "MDI_child_class") ||
|
||||
!strcmp(buf, "my_button_class") ||
|
||||
!strcmp(buf, "#32770"))
|
||||
!lstrcmpiA(buf, "TestWindowClass") ||
|
||||
!lstrcmpiA(buf, "TestParentClass") ||
|
||||
!lstrcmpiA(buf, "TestPopupClass") ||
|
||||
!lstrcmpiA(buf, "SimpleWindowClass") ||
|
||||
!lstrcmpiA(buf, "TestDialogClass") ||
|
||||
!lstrcmpiA(buf, "MDI_frame_class") ||
|
||||
!lstrcmpiA(buf, "MDI_client_class") ||
|
||||
!lstrcmpiA(buf, "MDI_child_class") ||
|
||||
!lstrcmpiA(buf, "my_button_class") ||
|
||||
!lstrcmpiA(buf, "static") ||
|
||||
!lstrcmpiA(buf, "#32770"))
|
||||
{
|
||||
struct message msg;
|
||||
|
||||
|
@ -4751,6 +4758,9 @@ static void test_timers(void)
|
|||
|
||||
WaitForSingleObject(info.handles[1], INFINITE);
|
||||
|
||||
CloseHandle(info.handles[0]);
|
||||
CloseHandle(info.handles[1]);
|
||||
|
||||
ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
|
||||
|
||||
ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
|
||||
|
@ -4784,40 +4794,434 @@ static const struct message WmWinEventsSeq[] = {
|
|||
{ EVENT_SYSTEM_MINIMIZEEND, winevent_hook|wparam|lparam, OBJID_CARET, 8 },
|
||||
{ 0 }
|
||||
};
|
||||
static const struct message WmWinEventCaretSeq[] = {
|
||||
{ EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
|
||||
{ EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
|
||||
{ EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 2 */
|
||||
{ EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1 */
|
||||
{ 0 }
|
||||
};
|
||||
static const struct message WmWinEventCaretSeq_2[] = {
|
||||
{ EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
|
||||
{ EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
|
||||
{ EVENT_OBJECT_NAMECHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, /* hook 1/2 */
|
||||
{ 0 }
|
||||
};
|
||||
static const struct message WmWinEventAlertSeq[] = {
|
||||
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
static const struct message WmWinEventAlertSeq_2[] = {
|
||||
/* create window in the thread proc */
|
||||
{ EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_WINDOW, 2 },
|
||||
/* our test event */
|
||||
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_ALERT, 2 },
|
||||
{ 0 }
|
||||
};
|
||||
static const struct message WmGlobalHookSeq_1[] = {
|
||||
/* create window in the thread proc */
|
||||
{ HCBT_CREATEWND, hook|lparam, 0, 2 },
|
||||
/* our test events */
|
||||
{ HCBT_SETFOCUS, hook|lparam, 0, 2 }, /* SetFocus(0) */
|
||||
{ HCBT_ACTIVATE, hook|lparam, 0, 2 },
|
||||
{ HCBT_SETFOCUS, hook|lparam, 0, 2 }, /* SetFocus(hwnd) */
|
||||
{ 0 }
|
||||
};
|
||||
static const struct message WmGlobalHookSeq_2[] = {
|
||||
{ HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 0 }, /* old local hook */
|
||||
{ HCBT_SYSCOMMAND, hook|wparam|lparam, SC_NEXTWINDOW, 2 }, /* new global hook */
|
||||
{ HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 0 }, /* old local hook */
|
||||
{ HCBT_SYSCOMMAND, hook|wparam|lparam, SC_PREVWINDOW, 2 }, /* new global hook */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void test_winevents(void)
|
||||
static void CALLBACK win_event_global_hook_proc(HWINEVENTHOOK hevent,
|
||||
DWORD event,
|
||||
HWND hwnd,
|
||||
LONG object_id,
|
||||
LONG child_id,
|
||||
DWORD thread_id,
|
||||
DWORD event_time)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
trace("WEH_2:%p,event %08lx,hwnd %p,obj %08lx,id %08lx,thread %08lx,time %08lx\n",
|
||||
hevent, event, hwnd, object_id, child_id, thread_id, event_time);
|
||||
|
||||
if (GetClassNameA(hwnd, buf, sizeof(buf)))
|
||||
{
|
||||
if (!lstrcmpiA(buf, "TestWindowClass") ||
|
||||
!lstrcmpiA(buf, "static"))
|
||||
{
|
||||
struct message msg;
|
||||
|
||||
msg.message = event;
|
||||
msg.flags = winevent_hook|wparam|lparam;
|
||||
msg.wParam = object_id;
|
||||
msg.lParam = (thread_id == GetCurrentThreadId()) ? child_id : (child_id + 2);
|
||||
add_message(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static HHOOK hCBT_global_hook;
|
||||
static DWORD cbt_global_hook_thread_id;
|
||||
|
||||
static LRESULT CALLBACK cbt_global_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
trace("CBT_2: %d, %08x, %08lx\n", nCode, wParam, lParam);
|
||||
|
||||
if (nCode == HCBT_SYSCOMMAND)
|
||||
{
|
||||
struct message msg;
|
||||
|
||||
msg.message = nCode;
|
||||
msg.flags = hook|wparam|lparam;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
|
||||
add_message(&msg);
|
||||
|
||||
return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
/* Log also SetFocus(0) calls */
|
||||
if (!wParam) wParam = lParam;
|
||||
|
||||
if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
|
||||
{
|
||||
if (!lstrcmpiA(buf, "TestWindowClass") ||
|
||||
!lstrcmpiA(buf, "static"))
|
||||
{
|
||||
struct message msg;
|
||||
|
||||
msg.message = nCode;
|
||||
msg.flags = hook|wparam|lparam;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = (cbt_global_hook_thread_id == GetCurrentThreadId()) ? 1 : 2;
|
||||
add_message(&msg);
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(hCBT_global_hook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
static DWORD WINAPI win_event_global_thread_proc(void *param)
|
||||
{
|
||||
HWND hwnd;
|
||||
UINT i;
|
||||
const struct message *events = WmWinEventsSeq;
|
||||
MSG msg;
|
||||
HANDLE hevent = *(HANDLE *)param;
|
||||
HMODULE user32 = GetModuleHandleA("user32.dll");
|
||||
FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
|
||||
|
||||
if (!pNotifyWinEvent) return;
|
||||
assert(pNotifyWinEvent);
|
||||
|
||||
hwnd = CreateWindow ("TestWindowClass", NULL,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
|
||||
NULL, NULL, 0);
|
||||
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
|
||||
assert(hwnd);
|
||||
trace("created thread window %p\n", hwnd);
|
||||
|
||||
*(HWND *)param = hwnd;
|
||||
|
||||
flush_sequence();
|
||||
/* this event should be received only by our new hook proc,
|
||||
* an old one does not expect an event from another thread.
|
||||
*/
|
||||
pNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_ALERT, 0);
|
||||
SetEvent(hevent);
|
||||
|
||||
while (GetMessage(&msg, 0, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD WINAPI cbt_global_hook_thread_proc(void *param)
|
||||
{
|
||||
HWND hwnd;
|
||||
MSG msg;
|
||||
HANDLE hevent = *(HANDLE *)param;
|
||||
|
||||
flush_sequence();
|
||||
/* these events should be received only by our new hook proc,
|
||||
* an old one does not expect an event from another thread.
|
||||
*/
|
||||
|
||||
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL);
|
||||
assert(hwnd);
|
||||
trace("created thread window %p\n", hwnd);
|
||||
|
||||
*(HWND *)param = hwnd;
|
||||
|
||||
/* generate focus related CBT events */
|
||||
SetFocus(0);
|
||||
SetFocus(hwnd);
|
||||
|
||||
SetEvent(hevent);
|
||||
|
||||
while (GetMessage(&msg, 0, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_winevents(void)
|
||||
{
|
||||
MSG msg;
|
||||
HWND hwnd, hwnd2;
|
||||
UINT i;
|
||||
HANDLE hthread, hevent;
|
||||
DWORD tid;
|
||||
HWINEVENTHOOK hhook;
|
||||
const struct message *events = WmWinEventsSeq;
|
||||
HMODULE user32 = GetModuleHandleA("user32.dll");
|
||||
FARPROC pSetWinEventHook = 0;/*GetProcAddress(user32, "SetWinEventHook");*/
|
||||
FARPROC pUnhookWinEvent = 0;/*GetProcAddress(user32, "UnhookWinEvent");*/
|
||||
FARPROC pNotifyWinEvent = GetProcAddress(user32, "NotifyWinEvent");
|
||||
|
||||
hwnd = CreateWindowExA(0, "TestWindowClass", NULL,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
|
||||
NULL, NULL, 0);
|
||||
assert(hwnd);
|
||||
|
||||
/****** start of global hook test *************/
|
||||
hCBT_global_hook = SetWindowsHookExA(WH_CBT, cbt_global_hook_proc, GetModuleHandleA(0), 0);
|
||||
assert(hCBT_global_hook);
|
||||
|
||||
hevent = CreateEventA(NULL, 0, 0, NULL);
|
||||
assert(hevent);
|
||||
hwnd2 = (HWND)hevent;
|
||||
|
||||
hthread = CreateThread(NULL, 0, cbt_global_hook_thread_proc, &hwnd2, 0, &tid);
|
||||
ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
|
||||
|
||||
ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
|
||||
|
||||
ok_sequence(WmGlobalHookSeq_1, "global hook 1", FALSE);
|
||||
|
||||
flush_sequence();
|
||||
/* this one should be received only by old hook proc */
|
||||
DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_NEXTWINDOW, 0);
|
||||
/* this one should be received only by old hook proc */
|
||||
DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_PREVWINDOW, 0);
|
||||
|
||||
ok_sequence(WmGlobalHookSeq_2, "global hook 2", FALSE);
|
||||
|
||||
ok(UnhookWindowsHookEx(hCBT_global_hook), "UnhookWindowsHookEx error %ld", GetLastError());
|
||||
|
||||
PostThreadMessageA(tid, WM_QUIT, 0, 0);
|
||||
ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
|
||||
CloseHandle(hthread);
|
||||
CloseHandle(hevent);
|
||||
ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
|
||||
/****** end of global hook test *************/
|
||||
|
||||
if (!pSetWinEventHook || !pNotifyWinEvent || !pUnhookWinEvent)
|
||||
{
|
||||
ok(DestroyWindow(hwnd), "failed to destroy window\n");
|
||||
return;
|
||||
}
|
||||
|
||||
flush_sequence();
|
||||
|
||||
/* Windows ignores events with hwnd == 0 */
|
||||
#if 0 /* this test doesn't pass under Win9x */
|
||||
/* win2k ignores events with hwnd == 0 */
|
||||
SetLastError(0xdeadbeef);
|
||||
pNotifyWinEvent(events[0].message, 0, events[0].wParam, events[0].lParam);
|
||||
ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || /* Win2k */
|
||||
GetLastError() == 0xdeadbeef, /* Win9x */
|
||||
"unexpected error %ld\n", GetLastError());
|
||||
ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < sizeof(WmWinEventsSeq)/sizeof(WmWinEventsSeq[0]); i++)
|
||||
pNotifyWinEvent(events[i].message, hwnd, events[i].wParam, events[i].lParam);
|
||||
|
||||
ok_sequence(WmWinEventsSeq, "notify winevents", FALSE);
|
||||
|
||||
/****** start of event filtering test *************/
|
||||
hhook = (HWINEVENTHOOK)pSetWinEventHook(
|
||||
EVENT_OBJECT_SHOW, /* 0x8002 */
|
||||
EVENT_OBJECT_LOCATIONCHANGE, /* 0x800B */
|
||||
GetModuleHandleA(0), win_event_global_hook_proc,
|
||||
GetCurrentProcessId(), 0,
|
||||
WINEVENT_INCONTEXT);
|
||||
ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
|
||||
|
||||
hevent = CreateEventA(NULL, 0, 0, NULL);
|
||||
assert(hevent);
|
||||
hwnd2 = (HWND)hevent;
|
||||
|
||||
hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
|
||||
ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
|
||||
|
||||
ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
|
||||
|
||||
ok_sequence(WmWinEventAlertSeq, "alert winevent", FALSE);
|
||||
|
||||
flush_sequence();
|
||||
/* this one should be received only by old hook proc */
|
||||
pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
|
||||
pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
|
||||
/* this one should be received only by old hook proc */
|
||||
pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
|
||||
|
||||
ok_sequence(WmWinEventCaretSeq, "caret winevent", FALSE);
|
||||
|
||||
ok(pUnhookWinEvent(hhook), "UnhookWinEvent error %ld\n", GetLastError());
|
||||
|
||||
PostThreadMessageA(tid, WM_QUIT, 0, 0);
|
||||
ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
|
||||
CloseHandle(hthread);
|
||||
CloseHandle(hevent);
|
||||
ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
|
||||
/****** end of event filtering test *************/
|
||||
|
||||
/****** start of out of context event test *************/
|
||||
hhook = (HWINEVENTHOOK)pSetWinEventHook(
|
||||
EVENT_MIN, EVENT_MAX,
|
||||
0, win_event_global_hook_proc,
|
||||
GetCurrentProcessId(), 0,
|
||||
WINEVENT_OUTOFCONTEXT);
|
||||
ok(hhook != 0, "SetWinEventHook error %ld\n", GetLastError());
|
||||
|
||||
hevent = CreateEventA(NULL, 0, 0, NULL);
|
||||
assert(hevent);
|
||||
hwnd2 = (HWND)hevent;
|
||||
|
||||
flush_sequence();
|
||||
|
||||
hthread = CreateThread(NULL, 0, win_event_global_thread_proc, &hwnd2, 0, &tid);
|
||||
ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError());
|
||||
|
||||
ok(WaitForSingleObject(hevent, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
|
||||
|
||||
ok_sequence(WmEmptySeq, "empty notify winevents", FALSE);
|
||||
/* process pending winevent messages */
|
||||
ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
|
||||
ok_sequence(WmWinEventAlertSeq_2, "alert winevent for out of context proc", FALSE);
|
||||
|
||||
flush_sequence();
|
||||
/* this one should be received only by old hook proc */
|
||||
pNotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, 0); /* 0x8000 */
|
||||
pNotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, 0); /* 0x8002 */
|
||||
/* this one should be received only by old hook proc */
|
||||
pNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CARET, 0); /* 0x800C */
|
||||
|
||||
ok_sequence(WmWinEventCaretSeq_2, "caret winevent for incontext proc", FALSE);
|
||||
/* process pending winevent messages */
|
||||
ok(!PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "msg queue should be empty\n");
|
||||
ok_sequence(WmWinEventCaretSeq_2, "caret winevent for out of context proc", FALSE);
|
||||
|
||||
ok(pUnhookWinEvent(hhook), "UnhookWinEvent error %ld\n", GetLastError());
|
||||
|
||||
PostThreadMessageA(tid, WM_QUIT, 0, 0);
|
||||
ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
|
||||
CloseHandle(hthread);
|
||||
CloseHandle(hevent);
|
||||
ok(!IsWindow(hwnd2), "window should be destroyed on thread exit\n");
|
||||
/****** end of out of context event test *************/
|
||||
|
||||
ok(DestroyWindow(hwnd), "failed to destroy window\n");
|
||||
}
|
||||
|
||||
static void test_set_hook(void)
|
||||
{
|
||||
HHOOK hhook;
|
||||
HWINEVENTHOOK hwinevent_hook;
|
||||
HMODULE user32 = GetModuleHandleA("user32.dll");
|
||||
FARPROC pSetWinEventHook = 0;/*GetProcAddress(user32, "SetWinEventHook");*/
|
||||
FARPROC pUnhookWinEvent = GetProcAddress(user32, "UnhookWinEvent");
|
||||
|
||||
hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, GetModuleHandleA(0), GetCurrentThreadId());
|
||||
ok(hhook != 0, "local hook does not require hModule set to 0\n");
|
||||
UnhookWindowsHookEx(hhook);
|
||||
|
||||
#if 0 /* this test doesn't pass under Win9x: BUG! */
|
||||
SetLastError(0xdeadbeef);
|
||||
hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, 0);
|
||||
ok(!hhook, "global hook requires hModule != 0\n");
|
||||
ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD, "unexpected error %ld\n", GetLastError());
|
||||
#endif
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hhook = SetWindowsHookExA(WH_CBT, 0, GetModuleHandleA(0), GetCurrentThreadId());
|
||||
ok(!hhook, "SetWinEventHook with invalid proc should fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FILTER_PROC || /* Win2k */
|
||||
GetLastError() == 0xdeadbeef, /* Win9x */
|
||||
"unexpected error %ld\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!UnhookWindowsHookEx((HHOOK)0xdeadbeef), "UnhookWindowsHookEx succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HOOK_HANDLE || /* Win2k */
|
||||
GetLastError() == 0xdeadbeef, /* Win9x */
|
||||
"unexpected error %ld\n", GetLastError());
|
||||
|
||||
if (!pSetWinEventHook || !pUnhookWinEvent) return;
|
||||
|
||||
/* even process local incontext hooks require hmodule */
|
||||
SetLastError(0xdeadbeef);
|
||||
hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
|
||||
0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
||||
ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
|
||||
ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
|
||||
GetLastError() == 0xdeadbeef, /* Win9x */
|
||||
"unexpected error %ld\n", GetLastError());
|
||||
|
||||
/* even thread local incontext hooks require hmodule */
|
||||
SetLastError(0xdeadbeef);
|
||||
hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
|
||||
0, win_event_proc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT);
|
||||
ok(!hwinevent_hook, "WINEVENT_INCONTEXT requires hModule != 0\n");
|
||||
ok(GetLastError() == ERROR_HOOK_NEEDS_HMOD || /* Win2k */
|
||||
GetLastError() == 0xdeadbeef, /* Win9x */
|
||||
"unexpected error %ld\n", GetLastError());
|
||||
|
||||
#if 0 /* these 3 tests don't pass under Win9x */
|
||||
SetLastError(0xdeadbeef);
|
||||
hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(1, 0,
|
||||
0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
|
||||
ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %ld\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(-1, 1,
|
||||
0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
|
||||
ok(!hwinevent_hook, "SetWinEventHook with invalid event range should fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HOOK_FILTER, "unexpected error %ld\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
|
||||
0, win_event_proc, 0, 0xdeadbeef, WINEVENT_OUTOFCONTEXT);
|
||||
ok(!hwinevent_hook, "SetWinEventHook with invalid tid should fail\n");
|
||||
ok(GetLastError() == ERROR_INVALID_THREAD_ID, "unexpected error %ld\n", GetLastError());
|
||||
#endif
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(0, 0,
|
||||
0, win_event_proc, GetCurrentProcessId(), 0, WINEVENT_OUTOFCONTEXT);
|
||||
ok(hwinevent_hook != 0, "SetWinEventHook error %ld\n", GetLastError());
|
||||
ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
|
||||
ok(pUnhookWinEvent(hwinevent_hook), "UnhookWinEvent error %ld\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hwinevent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
|
||||
0, win_event_proc, 0xdeadbeef, 0, WINEVENT_OUTOFCONTEXT);
|
||||
ok(hwinevent_hook != 0, "SetWinEventHook error %ld\n", GetLastError());
|
||||
ok(GetLastError() == 0xdeadbeef, "unexpected error %ld\n", GetLastError());
|
||||
ok(pUnhookWinEvent(hwinevent_hook), "UnhookWinEvent error %ld\n", GetLastError());
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!pUnhookWinEvent((HWINEVENTHOOK)0xdeadbeef), "UnhookWinEvent succeeded\n");
|
||||
ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
|
||||
GetLastError() == 0xdeadbeef, /* Win9x */
|
||||
"unexpected error %ld\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(msg)
|
||||
{
|
||||
HMODULE user32 = GetModuleHandleA("user32.dll");
|
||||
|
@ -4829,22 +5233,28 @@ START_TEST(msg)
|
|||
|
||||
if (pSetWinEventHook)
|
||||
{
|
||||
UINT event;
|
||||
hEvent_hook = (HWINEVENTHOOK)pSetWinEventHook(EVENT_MIN, EVENT_MAX,
|
||||
GetModuleHandleA(0),
|
||||
win_event_proc,
|
||||
GetCurrentProcessId(),
|
||||
0,
|
||||
GetCurrentThreadId(),
|
||||
WINEVENT_INCONTEXT);
|
||||
assert(hEvent_hook);
|
||||
|
||||
if (pIsWinEventHookInstalled)
|
||||
{
|
||||
UINT event;
|
||||
for (event = EVENT_MIN; event <= EVENT_MAX; event++)
|
||||
ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event);
|
||||
}
|
||||
|
||||
/* Fix message sequences before removing 3 lines below */
|
||||
ok(pUnhookWinEvent(hEvent_hook), "UnhookWinEvent error %ld\n", GetLastError());
|
||||
pUnhookWinEvent = 0;
|
||||
hEvent_hook = 0;
|
||||
}
|
||||
|
||||
cbt_hook_thread_id = GetCurrentThreadId();
|
||||
hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
|
||||
assert(hCBT_hook);
|
||||
|
||||
|
@ -4856,6 +5266,7 @@ START_TEST(msg)
|
|||
test_message_conversion();
|
||||
test_accelerators();
|
||||
test_timers();
|
||||
test_set_hook();
|
||||
test_winevents();
|
||||
|
||||
UnhookWindowsHookEx(hCBT_hook);
|
||||
|
|
|
@ -320,7 +320,14 @@ DECL_HANDLER(remove_hook)
|
|||
{
|
||||
struct hook *hook;
|
||||
|
||||
if (req->handle) hook = get_user_object( req->handle, USER_HOOK );
|
||||
if (req->handle)
|
||||
{
|
||||
if (!(hook = get_user_object( req->handle, USER_HOOK )))
|
||||
{
|
||||
set_win32_error( ERROR_INVALID_HOOK_HANDLE );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!req->proc || req->id < WH_MINHOOK || req->id > WH_MAXHOOK)
|
||||
|
@ -329,9 +336,12 @@ DECL_HANDLER(remove_hook)
|
|||
return;
|
||||
}
|
||||
if (!(hook = find_hook( current, req->id - WH_MINHOOK, req->proc )))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (hook) remove_hook( hook );
|
||||
remove_hook( hook );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3210,6 +3210,7 @@ static const char *get_status_name( unsigned int status )
|
|||
NAME(TIMEOUT),
|
||||
NAME(USER_APC),
|
||||
NAME(WAS_LOCKED),
|
||||
NAME_WIN32(ERROR_INVALID_HOOK_HANDLE),
|
||||
NAME_WIN32(ERROR_INVALID_INDEX),
|
||||
NAME_WIN32(ERROR_NEGATIVE_SEEK),
|
||||
NAME_WIN32(ERROR_SEEK),
|
||||
|
|
Loading…
Reference in a new issue