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 { 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 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 138 START_TEST(WndProc) 139 { 140 #ifdef __RUNTIME_CHECKS__ 141 skip("This test breaks MSVC runtime checks!\n"); 142 return; 143 #endif /* __RUNTIME_CHECKS__ */ 144 145 test_wndproc(); 146 } 147