static LRESULT CALLBACK button_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- static long defwndproc_counter = 0;
+ static LONG defwndproc_counter = 0;
LRESULT ret;
struct recvd_message msg;
static LRESULT CALLBACK static_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- static long defwndproc_counter = 0;
+ static LONG defwndproc_counter = 0;
LRESULT ret;
struct recvd_message msg;
static LRESULT CALLBACK combobox_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- static long defwndproc_counter = 0;
+ static LONG defwndproc_counter = 0;
LRESULT ret;
struct recvd_message msg;
{ WM_CONTEXTMENU, sent|lparam, /*hwnd*/0, (LPARAM)-1 },
{ 0 }
};
+static const struct message WmVkF10Seq[] = {
+ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */
+ { WM_SYSKEYDOWN, wparam|lparam, VK_F10, 1 },
+ { WM_SYSKEYDOWN, sent|wparam|lparam, VK_F10, 0x00000001 },
+ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */
+ { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 },
+ { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 },
+ { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_KEYMENU },
+ { HCBT_SYSCOMMAND, hook },
+ { WM_ENTERMENULOOP, sent|defwinproc|wparam|lparam, 0, 0 },
+ { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 },
+ { WM_INITMENU, sent|defwinproc },
+ { EVENT_SYSTEM_MENUSTART, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
+ { WM_MENUSELECT, sent|defwinproc|wparam, MAKEWPARAM(0,MF_SYSMENU|MF_POPUP|MF_HILITE) },
+ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 1 },
+
+ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0x10000001 }, /* XP */
+
+ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 1 }, /* XP */
+ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
+ { EVENT_SYSTEM_CAPTUREEND, winevent_hook|wparam|lparam, 0, 0, },
+ { WM_CAPTURECHANGED, sent|defwinproc },
+ { WM_MENUSELECT, sent|defwinproc|wparam|optional, MAKEWPARAM(0,0xffff) },
+ { EVENT_SYSTEM_MENUEND, winevent_hook|wparam|lparam, OBJID_SYSMENU, 0 },
+ { WM_EXITMENULOOP, sent|defwinproc },
+ { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_F10, 0xc0000001 }, /* XP */
+ { WM_SYSKEYUP, wparam|lparam, VK_F10, 0xc0000001 },
+ { WM_SYSKEYUP, sent|wparam|lparam, VK_F10, 0xc0000001 },
+ { 0 }
+};
static void pump_msg_loop(HWND hwnd, HACCEL hAccel)
{
pump_msg_loop(hwnd, 0);
ok_sequence(WmVkAppsSeq, "VK_APPS press/release", FALSE);
+ trace("testing VK_F10 press/release\n");
+ keybd_event(VK_F10, 0, 0, 0);
+ keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0);
+ keybd_event(VK_F10, 0, 0, 0);
+ keybd_event(VK_F10, 0, KEYEVENTF_KEYUP, 0);
+ pump_msg_loop(hwnd, 0);
+ ok_sequence(WmVkF10Seq, "VK_F10 press/release", TRUE);
+
trace("testing Shift+MouseButton press/release\n");
/* first, move mouse pointer inside of the window client area */
GetClientRect(hwnd, &rc);
{
}
+static VOID CALLBACK tfunc_crash(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime)
+{
+ /* Crash on purpose */
+ *(volatile int *)0 = 2;
+}
+
#define TIMER_ID 0x19
static DWORD WINAPI timer_thread_proc(LPVOID x)
{
struct timer_info info;
DWORD id;
+ MSG msg;
info.hWnd = CreateWindow ("TestWindowClass", NULL,
WS_OVERLAPPEDWINDOW ,
ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
+
+ /* Test timer callback with crash */
+ SetLastError(0xdeadbeef);
+ info.hWnd = CreateWindowW(testWindowClassW, NULL,
+ WS_OVERLAPPEDWINDOW ,
+ CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
+ NULL, NULL, 0);
+ if ((!info.hWnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) || /* Win9x/Me */
+ (!pGetMenuInfo)) /* Win95/NT4 */
+ {
+ win_skip("Test would crash on Win9x/WinMe/NT4\n");
+ DestroyWindow(info.hWnd);
+ return;
+ }
+ info.id = SetTimer(info.hWnd, TIMER_ID, 0, tfunc_crash);
+ ok(info.id, "SetTimer failed\n");
+ Sleep(150);
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
+
+ ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
}
static int count = 0;
static LRESULT CALLBACK edit_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- static long defwndproc_counter = 0;
+ static LONG defwndproc_counter = 0;
LRESULT ret;
struct recvd_message msg;
DestroyWindow( hwnd);
}
+#define clear_clipboard(hwnd) clear_clipboard_(__LINE__, (hwnd))
+static void clear_clipboard_(int line, HWND hWnd)
+{
+ BOOL succ;
+ succ = OpenClipboard(hWnd);
+ ok_(__FILE__, line)(succ, "OpenClipboard failed, err=%u\n", GetLastError());
+ succ = EmptyClipboard();
+ ok_(__FILE__, line)(succ, "EmptyClipboard failed, err=%u\n", GetLastError());
+ succ = CloseClipboard();
+ ok_(__FILE__, line)(succ, "CloseClipboard failed, err=%u\n", GetLastError());
+}
+
+#define expect_HWND(expected, got) expect_HWND_(__LINE__, (expected), (got))
+static void expect_HWND_(int line, HWND expected, HWND got)
+{
+ ok_(__FILE__, line)(got==expected, "Expected %p, got %p\n", expected, got);
+}
+
+static WNDPROC pOldViewerProc;
+
+static LRESULT CALLBACK recursive_viewer_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static BOOL recursion_guard;
+
+ if (message == WM_DRAWCLIPBOARD && !recursion_guard)
+ {
+ recursion_guard = TRUE;
+ clear_clipboard(hWnd);
+ recursion_guard = FALSE;
+ }
+ return CallWindowProcA(pOldViewerProc, hWnd, message, wParam, lParam);
+}
+
+static void test_clipboard_viewers(void)
+{
+ static struct message wm_change_cb_chain[] =
+ {
+ { WM_CHANGECBCHAIN, sent|wparam|lparam, 0, 0 },
+ { 0 }
+ };
+ static const struct message wm_clipboard_destroyed[] =
+ {
+ { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 },
+ { 0 }
+ };
+ static struct message wm_clipboard_changed[] =
+ {
+ { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 },
+ { 0 }
+ };
+ static struct message wm_clipboard_changed_and_owned[] =
+ {
+ { WM_DESTROYCLIPBOARD, sent|wparam|lparam, 0, 0 },
+ { WM_DRAWCLIPBOARD, sent|wparam|lparam, 0, 0 },
+ { 0 }
+ };
+
+ HINSTANCE hInst = GetModuleHandleA(NULL);
+ HWND hWnd1, hWnd2, hWnd3;
+ HWND hOrigViewer;
+ HWND hRet;
+
+ hWnd1 = CreateWindowExA(0, "TestWindowClass", "Clipboard viewer test wnd 1",
+ WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ GetDesktopWindow(), NULL, hInst, NULL);
+ hWnd2 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 2",
+ WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ GetDesktopWindow(), NULL, hInst, NULL);
+ hWnd3 = CreateWindowExA(0, "SimpleWindowClass", "Clipboard viewer test wnd 3",
+ WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ GetDesktopWindow(), NULL, hInst, NULL);
+ trace("clipbd viewers: hWnd1=%p, hWnd2=%p, hWnd3=%p\n", hWnd1, hWnd2, hWnd3);
+ assert(hWnd1 && hWnd2 && hWnd3);
+
+ flush_sequence();
+
+ /* Test getting the clipboard viewer and setting the viewer to NULL. */
+ hOrigViewer = GetClipboardViewer();
+ hRet = SetClipboardViewer(NULL);
+ ok_sequence(WmEmptySeq, "set viewer to NULL", FALSE);
+ expect_HWND(hOrigViewer, hRet);
+ expect_HWND(NULL, GetClipboardViewer());
+
+ /* Test registering hWnd1 as a viewer. */
+ hRet = SetClipboardViewer(hWnd1);
+ wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner();
+ ok_sequence(wm_clipboard_changed, "set viewer NULL->1", FALSE);
+ expect_HWND(NULL, hRet);
+ expect_HWND(hWnd1, GetClipboardViewer());
+
+ /* Test that changing the clipboard actually refreshes the registered viewer. */
+ clear_clipboard(hWnd1);
+ wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner();
+ ok_sequence(wm_clipboard_changed, "clear clipbd (viewer=owner=1)", FALSE);
+
+ /* Again, but with different owner. */
+ clear_clipboard(hWnd2);
+ wm_clipboard_changed_and_owned[1].wParam = (WPARAM) GetClipboardOwner();
+ ok_sequence(wm_clipboard_changed_and_owned, "clear clipbd (viewer=1, owner=2)", FALSE);
+
+ /* Test re-registering same window. */
+ hRet = SetClipboardViewer(hWnd1);
+ wm_clipboard_changed[0].wParam = (WPARAM) GetClipboardOwner();
+ ok_sequence(wm_clipboard_changed, "set viewer 1->1", FALSE);
+ expect_HWND(hWnd1, hRet);
+ expect_HWND(hWnd1, GetClipboardViewer());
+
+ /* Test ChangeClipboardChain. */
+ ChangeClipboardChain(hWnd2, hWnd3);
+ wm_change_cb_chain[0].wParam = (WPARAM) hWnd2;
+ wm_change_cb_chain[0].lParam = (LPARAM) hWnd3;
+ ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=3)", FALSE);
+ expect_HWND(hWnd1, GetClipboardViewer());
+
+ ChangeClipboardChain(hWnd2, NULL);
+ wm_change_cb_chain[0].wParam = (WPARAM) hWnd2;
+ wm_change_cb_chain[0].lParam = 0;
+ ok_sequence(wm_change_cb_chain, "change chain (viewer=1, remove=2, next=NULL)", FALSE);
+ expect_HWND(hWnd1, GetClipboardViewer());
+
+ ChangeClipboardChain(NULL, hWnd2);
+ ok_sequence(WmEmptySeq, "change chain (viewer=1, remove=NULL, next=2)", TRUE);
+ expect_HWND(hWnd1, GetClipboardViewer());
+
+ /* Actually change clipboard viewer with ChangeClipboardChain. */
+ ChangeClipboardChain(hWnd1, hWnd2);
+ ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=2)", FALSE);
+ expect_HWND(hWnd2, GetClipboardViewer());
+
+ /* Test that no refresh messages are sent when viewer has unregistered. */
+ clear_clipboard(hWnd2);
+ ok_sequence(WmEmptySeq, "clear clipd (viewer=2, owner=1)", FALSE);
+
+ /* Register hWnd1 again. */
+ ChangeClipboardChain(hWnd2, hWnd1);
+ ok_sequence(WmEmptySeq, "change chain (viewer=remove=2, next=1)", FALSE);
+ expect_HWND(hWnd1, GetClipboardViewer());
+
+ /* Subclass hWnd1 so that when it receives a WM_DRAWCLIPBOARD message, it
+ * changes the clipboard. When this happens, the system shouldn't send
+ * another WM_DRAWCLIPBOARD (as this could cause an infinite loop).
+ */
+ pOldViewerProc = (WNDPROC) SetWindowLongPtrA(hWnd1, GWLP_WNDPROC, (LONG_PTR) recursive_viewer_proc);
+ clear_clipboard(hWnd2);
+ /* The clipboard owner is changed in recursive_viewer_proc: */
+ wm_clipboard_changed[0].wParam = (WPARAM) hWnd2;
+ ok_sequence(wm_clipboard_changed, "recursive clear clipbd (viewer=1, owner=2)", TRUE);
+
+ /* Test unregistering. */
+ ChangeClipboardChain(hWnd1, NULL);
+ ok_sequence(WmEmptySeq, "change chain (viewer=remove=1, next=NULL)", FALSE);
+ expect_HWND(NULL, GetClipboardViewer());
+
+ clear_clipboard(hWnd1);
+ ok_sequence(wm_clipboard_destroyed, "clear clipbd (no viewer, owner=1)", FALSE);
+
+ DestroyWindow(hWnd1);
+ DestroyWindow(hWnd2);
+ DestroyWindow(hWnd3);
+ SetClipboardViewer(hOrigViewer);
+}
+
static void test_PostMessage(void)
{
static const struct
START_TEST(msg)
{
BOOL ret;
- FARPROC pIsWinEventHookInstalled = 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
+ BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
init_procs();
test_menu_messages();
test_paintingloop();
test_defwinproc();
+ test_clipboard_viewers();
/* keep it the last test, under Windows it tends to break the tests
* which rely on active/foreground windows being correct.
*/