1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for mismatch with function prototype in window procedure callback.
5 * PROGRAMMERS:
6 */
7
8 #include "precomp.h"
9
10 /* Used wine Redraw test for proof in principle. */
11
12 #define WMPAINT_COUNT_THRESHOLD 10
13
14 /* Global variables to trigger exit from loop */
15 static int redrawComplete, WMPAINT_count;
16
17 /*
18 * Force stack corruption when calling from assumed window procedure callback.
19 * Adding (6 and) more will force exception faults and terminate the test program.
20 * The test is with five and this is safe for windows.
21 *
22 * But,,,, ReactOS compiled with GCC can handle this,,,,,,
23 */
redraw_window_procA(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)24 static LRESULT WINAPI redraw_window_procA(
25 HWND hwnd,
26 UINT msg,
27 WPARAM wparam,
28 LPARAM lparam)
29 {
30 switch (msg)
31 {
32 case WM_PAINT:
33 break;
34 WMPAINT_count++;
35 trace("Doing WM_PAINT %d/%d\n", WMPAINT_count, WMPAINT_COUNT_THRESHOLD);
36
37 if (WMPAINT_count > WMPAINT_COUNT_THRESHOLD && redrawComplete == 0)
38 {
39 PAINTSTRUCT ps;
40
41 trace("Calling *Paint()\n");
42 BeginPaint(hwnd, &ps);
43 EndPaint(hwnd, &ps);
44 return 1;
45 }
46
47 // This will force one stack corruption "ret" fault with normal window
48 // procedure callback.
49 #ifdef __MINGW32__
50 trace("Executing __MINGW32__ stack corruption code\n");
51 asm ("movl $0, %eax\n\t"
52 "leave\n\t"
53 "ret");
54 #elif defined(_M_IX86)
55 //#ifdef _MSC_VER
56 trace("Executing MSVC x86 stack corruption code\n");
57 __asm
58 {
59 mov eax, 0
60 leave
61 ret
62 }
63 #else
64 ok(FALSE, "FIXME: stack corruption code is unimplemented\n");
65 #endif
66
67 break;
68 default:
69 trace("Doing empty default: msg = %u\n", msg);
70 }
71
72 trace("Calling DefWindowProc()\n");
73 return DefWindowProc(hwnd, msg, wparam, lparam);
74 }
75
test_wndproc(void)76 static void test_wndproc(void)
77 {
78 WNDCLASSA cls;
79 ATOM clsAtom;
80 HWND hwndMain;
81
82 cls.style = CS_DBLCLKS;
83 cls.lpfnWndProc = redraw_window_procA;
84 cls.cbClsExtra = 0;
85 cls.cbWndExtra = 0;
86 cls.hInstance = GetModuleHandleA(NULL);
87 cls.hIcon = NULL;
88 cls.hCursor = LoadCursorA(NULL, IDC_ARROW);
89 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
90 cls.lpszMenuName = NULL;
91 cls.lpszClassName = "RedrawWindowClass";
92
93 clsAtom = RegisterClassA(&cls);
94 ok(clsAtom != 0, "RegisterClassA() failed: LastError = %lu\n", GetLastError());
95
96 if (clsAtom == 0)
97 {
98 skip("No Class atom\n");
99 return;
100 }
101
102 hwndMain = CreateWindowA(cls.lpszClassName, "Main Window", WS_OVERLAPPEDWINDOW,
103 CW_USEDEFAULT, 0, 100, 100, NULL, NULL, NULL, NULL);
104
105 ok(hwndMain != NULL, "CreateWindowA() failed: LastError = %lu\n", GetLastError());
106
107 ok(WMPAINT_count == 0,
108 "Multiple unexpected WM_PAINT calls = %d\n", WMPAINT_count);
109
110 if (hwndMain == NULL)
111 {
112 skip("No Window\n");
113 ok(UnregisterClassA(cls.lpszClassName, cls.hInstance) != 0,
114 "UnregisterClassA() failed: LastError = %lu\n", GetLastError());
115 return;
116 }
117
118 ShowWindow(hwndMain, SW_SHOW);
119 ok(WMPAINT_count == 0,
120 "Multiple unexpected WM_PAINT calls = %d\n", WMPAINT_count);
121
122 RedrawWindow(hwndMain, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
123 ok(WMPAINT_count == 1 || broken(WMPAINT_count == 0), /* sometimes on win9x */
124 "Multiple unexpected WM_PAINT calls = %d\n", WMPAINT_count);
125
126 redrawComplete = TRUE;
127 ok(WMPAINT_count < WMPAINT_COUNT_THRESHOLD,
128 "RedrawWindow (RDW_UPDATENOW) never completed (%d/%d)\n",
129 WMPAINT_count, WMPAINT_COUNT_THRESHOLD);
130
131 ok(DestroyWindow(hwndMain) != 0,
132 "DestroyWindow() failed: LastError = %lu\n", GetLastError());
133
134 ok(UnregisterClassA(cls.lpszClassName, cls.hInstance) != 0,
135 "UnregisterClassA() failed: LastError = %lu\n", GetLastError());
136 }
137
test_get_wndproc(void)138 static void test_get_wndproc(void)
139 {
140 LONG_PTR ret;
141 SetLastError(0xfeedf00d);
142 ret = GetWindowLongPtrA(GetShellWindow(), GWLP_WNDPROC);
143 ok (ret == 0, "Should return NULL\n");
144 ok (GetLastError() == ERROR_ACCESS_DENIED, "Wrong return error!\n");
145 SetLastError(0xfeedf00d);
146 ret = GetWindowLongPtrW(GetShellWindow(), GWLP_WNDPROC);
147 ok (ret == 0, "Should return NULL\n");
148 ok (GetLastError() == ERROR_ACCESS_DENIED, "Wrong return error!\n");
149 SetLastError(0xfeedf00d);
150 ret = GetWindowLongPtrA(GetShellWindow(), GWLP_WNDPROC);
151 ok (ret == 0, "Should return NULL\n");
152 ok (GetLastError() == ERROR_ACCESS_DENIED, "Wrong return error!\n");
153 SetLastError(0xfeedf00d);
154 ret = GetWindowLongPtrW(GetShellWindow(), GWLP_WNDPROC);
155 ok (ret == 0, "Should return NULL\n");
156 ok (GetLastError() == ERROR_ACCESS_DENIED, "Wrong return error!\n");
157 }
158
START_TEST(WndProc)159 START_TEST(WndProc)
160 {
161 #ifdef __RUNTIME_CHECKS__
162 skip("This test breaks MSVC runtime checks!\n");
163 return;
164 #endif /* __RUNTIME_CHECKS__ */
165
166 test_get_wndproc();
167 test_wndproc();
168 }
169