[USER32_APITEST:WNDPROC] Improve failure handling
[reactos.git] / modules / rostests / apitests / user32 / WndProc.c
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 */
24 static LRESULT WINAPI redraw_window_procA(
25 HWND hwnd,
26 UINT msg,
27 WPARAM wparam,
28 LPARAM lparam,
29 DWORD ExtraData,
30 DWORD ExtraData1,
31 DWORD ExtraData2,
32 DWORD ExtraData3)
33 {
34 switch (msg)
35 {
36 case WM_PAINT:
37 WMPAINT_count++;
38 trace("Doing WM_PAINT %d/%d\n", WMPAINT_count, WMPAINT_COUNT_THRESHOLD);
39
40 if (WMPAINT_count > WMPAINT_COUNT_THRESHOLD && redrawComplete == 0)
41 {
42 PAINTSTRUCT ps;
43
44 trace("Calling *Paint()\n");
45 BeginPaint(hwnd, &ps);
46 EndPaint(hwnd, &ps);
47 return 1;
48 }
49
50 // This will force one stack corruption "ret" fault with normal window
51 // procedure callback.
52 #ifdef __MINGW32__
53 trace("Executing __MINGW32__ stack corruption code\n");
54 asm ("movl $0, %eax\n\t"
55 "leave\n\t"
56 "ret");
57 #elif defined(_M_IX86)
58 //#ifdef _MSC_VER
59 trace("Executing MSVC x86 stack corruption code\n");
60 __asm
61 {
62 mov eax, 0
63 leave
64 ret
65 }
66 #else
67 ok(FALSE, "FIXME: stack corruption code is unimplemented\n");
68 #endif
69
70 break;
71 default:
72 trace("Doing empty default: msg = %u\n", msg);
73 }
74
75 trace("Calling DefWindowProc()\n");
76 return DefWindowProc(hwnd, msg, wparam, lparam);
77 }
78
79 static void test_wndproc(void)
80 {
81 WNDCLASSA cls;
82 ATOM clsAtom;
83 HWND hwndMain;
84
85 cls.style = CS_DBLCLKS;
86 cls.lpfnWndProc = (WNDPROC)redraw_window_procA;
87 cls.cbClsExtra = 0;
88 cls.cbWndExtra = 0;
89 cls.hInstance = GetModuleHandleA(NULL);
90 cls.hIcon = NULL;
91 cls.hCursor = LoadCursorA(NULL, IDC_ARROW);
92 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
93 cls.lpszMenuName = NULL;
94 cls.lpszClassName = "RedrawWindowClass";
95
96 clsAtom = RegisterClassA(&cls);
97 ok(clsAtom != 0, "RegisterClassA() failed: LastError = %lu\n", GetLastError());
98
99 if (clsAtom == 0)
100 {
101 skip("No Class atom\n");
102 return;
103 }
104
105 hwndMain = CreateWindowA(cls.lpszClassName, "Main Window", WS_OVERLAPPEDWINDOW,
106 CW_USEDEFAULT, 0, 100, 100, NULL, NULL, NULL, NULL);
107 ok(hwndMain != NULL, "CreateWindowA() failed: LastError = %lu\n", GetLastError());
108
109 ok(WMPAINT_count == 0,
110 "Multiple unexpected WM_PAINT calls = %d\n", WMPAINT_count);
111
112 if (hwndMain == NULL)
113 {
114 skip("No Window\n");
115 ok(UnregisterClassA(cls.lpszClassName, cls.hInstance) != 0,
116 "UnregisterClassA() failed: LastError = %lu\n", GetLastError());
117 return;
118 }
119
120 ShowWindow(hwndMain, SW_SHOW);
121 ok(WMPAINT_count == 0,
122 "Multiple unexpected WM_PAINT calls = %d\n", WMPAINT_count);
123
124 RedrawWindow(hwndMain, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
125 ok(WMPAINT_count == 1 || broken(WMPAINT_count == 0), /* sometimes on win9x */
126 "Multiple unexpected WM_PAINT calls = %d\n", WMPAINT_count);
127
128 redrawComplete = TRUE;
129 ok(WMPAINT_count < WMPAINT_COUNT_THRESHOLD,
130 "RedrawWindow (RDW_UPDATENOW) never completed (%d/%d)\n",
131 WMPAINT_count, WMPAINT_COUNT_THRESHOLD);
132
133 ok(DestroyWindow(hwndMain) != 0,
134 "DestroyWindow() failed: LastError = %lu\n", GetLastError());
135
136 ok(UnregisterClassA(cls.lpszClassName, cls.hInstance) != 0,
137 "UnregisterClassA() failed: LastError = %lu\n", GetLastError());
138 }
139
140 START_TEST(WndProc)
141 {
142 #ifdef __RUNTIME_CHECKS__
143 skip("This test breaks MSVC runtime checks!\n");
144 return;
145 #endif /* __RUNTIME_CHECKS__ */
146
147 test_wndproc();
148 }