f0108e0f3bad4758cf0d738054f8462e76466ee6
[reactos.git] / rostests / apitests / user32 / CreateWindowEx.c
1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for CreateWindowEx
5 * PROGRAMMERS: Thomas Faber <thomas.faber@reactos.org>
6 * Mark Jansen
7 */
8
9 #include <apitest.h>
10 #include <winuser.h>
11 #include <msgtrace.h>
12 #include <user32testhelpers.h>
13
14 static void Test_Params(void)
15 {
16 HWND hWnd;
17 DWORD dwError;
18
19 SetLastError(0x1234);
20 hWnd = CreateWindowExW(0, L"BUTTON", NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
21 dwError = GetLastError();
22 ok(hWnd != NULL, "hWnd = %p\n", hWnd);
23 ok(dwError == 0, "error = %lu\n", dwError);
24 DestroyWindow(hWnd);
25
26 SetLastError(0x1234);
27 hWnd = CreateWindowExW(0, L"BUTTON", NULL, 0, 0, 0, 0, 0, (HWND)(LONG_PTR)-1, NULL, NULL, NULL);
28 dwError = GetLastError();
29 ok(hWnd == NULL, "hWnd = %p\n", hWnd);
30 ok(dwError == ERROR_INVALID_WINDOW_HANDLE, "error = %lu\n", dwError);
31
32 SetLastError(0x1234);
33 hWnd = CreateWindowExW(0, L"BUTTON", NULL, WS_CHILD, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
34 dwError = GetLastError();
35 ok(hWnd == NULL, "hWnd = %p\n", hWnd);
36 ok(dwError == ERROR_TLW_WITH_WSCHILD, "error = %lu\n", dwError);
37
38 SetLastError(0x1234);
39 hWnd = CreateWindowExW(0, L"BUTTON", NULL, WS_CHILD, 0, 0, 0, 0, (HWND)(LONG_PTR)-1, NULL, NULL, NULL);
40 dwError = GetLastError();
41 ok(hWnd == NULL, "hWnd = %p\n", hWnd);
42 ok(dwError == ERROR_INVALID_WINDOW_HANDLE, "error = %lu\n", dwError);
43
44 SetLastError(0x1234);
45 hWnd = CreateWindowExW(0, L"BUTTON", NULL, WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
46 dwError = GetLastError();
47 ok(hWnd != NULL, "hWnd = %p\n", hWnd);
48 ok(dwError == 0, "error = %lu\n", dwError);
49 DestroyWindow(hWnd);
50
51 SetLastError(0x1234);
52 hWnd = CreateWindowExW(0, L"BUTTON", NULL, WS_POPUP, 0, 0, 0, 0, (HWND)(LONG_PTR)-1, NULL, NULL, NULL);
53 dwError = GetLastError();
54 ok(hWnd == NULL, "hWnd = %p\n", hWnd);
55 ok(dwError == ERROR_INVALID_WINDOW_HANDLE, "error = %lu\n", dwError);
56
57 SetLastError(0x1234);
58 hWnd = CreateWindowExW(0, L"BUTTON", NULL, WS_CHILD|WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
59 dwError = GetLastError();
60 ok(hWnd != NULL, "hWnd = %p\n", hWnd);
61 ok(dwError == 0, "error = %lu\n", dwError);
62 DestroyWindow(hWnd);
63
64 SetLastError(0x1234);
65 hWnd = CreateWindowExW(0, L"BUTTON", NULL, WS_CHILD|WS_POPUP, 0, 0, 0, 0, (HWND)(LONG_PTR)-1, NULL, NULL, NULL);
66 dwError = GetLastError();
67 ok(hWnd == NULL, "hWnd = %p\n", hWnd);
68 ok(dwError == ERROR_INVALID_WINDOW_HANDLE, "error = %lu\n", dwError);
69 }
70
71 HWND g_TestWindow = NULL;
72
73 static int get_iwnd(HWND hWnd)
74 {
75 if (!g_TestWindow)
76 g_TestWindow = hWnd;
77
78 return hWnd == g_TestWindow ? 1 : 0;
79 }
80
81 DWORD g_FaultLine = 0;
82 DWORD g_NcExpectStyle = 0;
83 DWORD g_NcExpectExStyle = 0;
84 DWORD g_ExpectStyle = 0;
85 DWORD g_ExpectExStyle = 0;
86
87 #define ok_hex_(expression, result) \
88 do { \
89 int _value = (expression); \
90 ok_(__FILE__, g_FaultLine)(_value == (result), "Wrong value for '%s', expected: " #result " (0x%x), got: 0x%x\n", \
91 #expression, (int)(result), _value); \
92 } while (0)
93
94
95
96 static int g_ChangeStyle = 0;
97 static LRESULT CALLBACK MSGTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
98 {
99 LRESULT lRet;
100 int iwnd = get_iwnd(hWnd);
101
102 if(message > WM_USER || !iwnd || IsDWmMsg(message) || IseKeyMsg(message))
103 return DefWindowProc(hWnd, message, wParam, lParam);
104
105 switch(message)
106 {
107 case WM_IME_SETCONTEXT:
108 case WM_IME_NOTIFY:
109 case WM_GETICON:
110 case WM_GETTEXT:
111 return DefWindowProc(hWnd, message, wParam, lParam);
112 break;
113 case WM_NCCREATE:
114 {
115 LPCREATESTRUCT create = (LPCREATESTRUCT)lParam;
116 RECORD_MESSAGE(iwnd, message, SENT, 0, 0);
117 ok_hex_(create->style, g_NcExpectStyle);
118 ok_hex_(create->dwExStyle, g_NcExpectExStyle);
119 if (g_ChangeStyle)
120 {
121 DWORD dwStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
122 dwStyle &= ~(WS_EX_CLIENTEDGE);
123 SetWindowLong(hWnd, GWL_EXSTYLE, dwStyle);
124 RECORD_MESSAGE(iwnd, message, MARKER, 0, 0);
125 SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
126 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME);
127
128 RECORD_MESSAGE(iwnd, message, MARKER, 0, 0);
129 ok_hex_(create->style, g_NcExpectStyle);
130 ok_hex_(create->dwExStyle, g_NcExpectExStyle);
131 }
132 }
133 break;
134 case WM_CREATE:
135 {
136 LPCREATESTRUCT create = (LPCREATESTRUCT)lParam;
137 RECORD_MESSAGE(iwnd, message, SENT, 0, 0);
138 ok_hex_(create->style, g_ExpectStyle);
139 ok_hex_(create->dwExStyle, g_ExpectExStyle);
140 }
141 break;
142 case WM_NCCALCSIZE:
143 case WM_STYLECHANGING:
144 case WM_STYLECHANGED:
145 case WM_SIZE:
146 RECORD_MESSAGE(iwnd, message, SENT, wParam, 0);
147 break;
148 case WM_WINDOWPOSCHANGING:
149 case WM_WINDOWPOSCHANGED:
150 ok(wParam == 0,"expected wParam=0\n");
151 RECORD_MESSAGE(iwnd, message, SENT, ((WINDOWPOS*)lParam)->flags, 0);
152 break;
153 default:
154 RECORD_MESSAGE(iwnd, message, SENT, 0, 0);
155 break;
156 }
157 lRet = DefWindowProc(hWnd, message, wParam, lParam);
158 RECORD_MESSAGE(iwnd, message, SENT_RET, 0, 0);
159 return lRet;
160 }
161
162 MSG_ENTRY create_chain[] =
163 {
164 { 1, WM_GETMINMAXINFO, SENT },
165 { 1, WM_GETMINMAXINFO, SENT_RET },
166 { 1, WM_NCCREATE, SENT },
167 { 1, WM_NCCREATE, SENT_RET },
168 { 1, WM_NCCALCSIZE, SENT },
169 { 1, WM_NCCALCSIZE, SENT_RET },
170 { 1, WM_CREATE, SENT },
171 { 1, WM_CREATE, SENT_RET },
172 { 0, 0 }
173 };
174
175 MSG_ENTRY create_chain_modify[] =
176 {
177 { 1, WM_GETMINMAXINFO, SENT },
178 { 1, WM_GETMINMAXINFO, SENT_RET },
179 { 1, WM_NCCREATE, SENT },
180 { 1, WM_STYLECHANGING, SENT, GWL_EXSTYLE },
181 { 1, WM_STYLECHANGING, SENT_RET },
182 { 1, WM_STYLECHANGED, SENT, GWL_EXSTYLE },
183 { 1, WM_STYLECHANGED, SENT_RET },
184 { 1, WM_NCCREATE, MARKER },
185 { 1, WM_WINDOWPOSCHANGING, SENT, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED },
186 { 1, WM_WINDOWPOSCHANGING, SENT_RET },
187 { 1, WM_NCCALCSIZE, SENT, TRUE },
188 { 1, WM_NCCALCSIZE, SENT_RET },
189 { 1, WM_WINDOWPOSCHANGED, SENT, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED },
190 { 1, WM_MOVE, SENT },
191 { 1, WM_MOVE, SENT_RET },
192 { 1, WM_SIZE, SENT },
193 { 1, WM_SIZE, SENT_RET },
194 { 1, WM_WINDOWPOSCHANGED, SENT_RET },
195 { 1, WM_NCCREATE, MARKER },
196 { 1, WM_NCCREATE, SENT_RET },
197 { 1, WM_NCCALCSIZE, SENT },
198 { 1, WM_NCCALCSIZE, SENT_RET },
199 { 1, WM_CREATE, SENT },
200 { 1, WM_CREATE, SENT_RET },
201 { 0, 0 }
202 };
203
204 MSG_ENTRY create_chain_modify_below8_nonsrv[] =
205 {
206 { 1, WM_GETMINMAXINFO, SENT },
207 { 1, WM_GETMINMAXINFO, SENT_RET },
208 { 1, WM_NCCREATE, SENT },
209 { 1, WM_STYLECHANGING, SENT, GWL_EXSTYLE },
210 { 1, WM_STYLECHANGING, SENT_RET },
211 { 1, WM_STYLECHANGED, SENT, GWL_EXSTYLE },
212 { 1, WM_STYLECHANGED, SENT_RET },
213 { 1, WM_NCCREATE, MARKER },
214 { 1, WM_WINDOWPOSCHANGING, SENT, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED },
215 { 1, WM_WINDOWPOSCHANGING, SENT_RET },
216 { 1, WM_NCCALCSIZE, SENT, TRUE },
217 { 1, WM_NCCALCSIZE, SENT_RET },
218 { 1, WM_WINDOWPOSCHANGED, SENT, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED },
219 { 1, WM_MOVE, SENT },
220 { 1, WM_MOVE, SENT_RET },
221 { 1, WM_SIZE, SENT },
222 { 1, WM_SIZE, SENT_RET },
223 { 1, WM_WINDOWPOSCHANGED, SENT_RET },
224 { 1, WM_NCCALCSIZE, SENT, TRUE },
225 { 1, WM_NCCALCSIZE, SENT_RET },
226 { 1, WM_NCCREATE, MARKER },
227 { 1, WM_NCCREATE, SENT_RET },
228 { 1, WM_NCCALCSIZE, SENT },
229 { 1, WM_NCCALCSIZE, SENT_RET },
230 { 1, WM_CREATE, SENT },
231 { 1, WM_CREATE, SENT_RET },
232 { 0, 0 }
233 };
234
235
236 static BOOL
237 IsWindowsServer()
238 {
239 OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0, 0, VER_NT_WORKSTATION };
240 DWORDLONG const dwlConditionMask = VerSetConditionMask( 0, VER_PRODUCT_TYPE, VER_EQUAL );
241
242 return !VerifyVersionInfoW(&osvi, VER_PRODUCT_TYPE, dwlConditionMask);
243 }
244
245
246 static BOOL
247 IsWindows8OrGreater()
248 {
249 OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
250 DWORDLONG const dwlConditionMask = VerSetConditionMask(VerSetConditionMask(
251 VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
252 VER_MINORVERSION, VER_GREATER_EQUAL),
253 VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
254
255 osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_WIN8);
256 osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_WIN8);
257
258 return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
259 }
260
261 static void Test_Messages(void)
262 {
263 HWND hWnd;
264 BOOL Below8NonServer = !IsWindows8OrGreater() && !IsWindowsServer();
265
266 RegisterSimpleClass(MSGTestProc, L"Test_Message_Window_XX");
267
268 g_ExpectStyle = g_NcExpectStyle = 0;
269 g_ExpectExStyle = g_NcExpectExStyle = WS_EX_CLIENTEDGE;
270 g_FaultLine = __LINE__ + 1;
271 hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Test_Message_Window_XX", L"", 0, 10, 20,
272 200, 210, NULL, NULL, 0, NULL);
273
274 ok(hWnd == g_TestWindow, "We are testing with %p instead of %p\n", g_TestWindow, hWnd);
275 COMPARE_CACHE(create_chain);
276 DestroyWindow(hWnd);
277 g_TestWindow = NULL;
278 EMPTY_CACHE();
279
280 g_ExpectStyle = g_NcExpectStyle = WS_OVERLAPPEDWINDOW;
281 g_ExpectExStyle = g_NcExpectExStyle = WS_EX_OVERLAPPEDWINDOW;
282 g_FaultLine = __LINE__ + 1;
283 hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Test_Message_Window_XX", L"", WS_OVERLAPPEDWINDOW, 10, 20,
284 200, 210, NULL, NULL, 0, NULL);
285
286 ok(hWnd == g_TestWindow, "We are testing with %p instead of %p\n", g_TestWindow, hWnd);
287 COMPARE_CACHE(create_chain);
288 DestroyWindow(hWnd);
289 g_TestWindow = NULL;
290 EMPTY_CACHE();
291
292 g_ChangeStyle = 1;
293
294 g_ExpectStyle = g_NcExpectStyle = 0;
295 g_ExpectExStyle = g_NcExpectExStyle = WS_EX_CLIENTEDGE;
296 g_FaultLine = __LINE__ + 1;
297 hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Test_Message_Window_XX", L"", 0, 10, 20,
298 200, 210, NULL, NULL, 0, NULL);
299
300 ok(hWnd == g_TestWindow, "We are testing with %p instead of %p\n", g_TestWindow, hWnd);
301 COMPARE_CACHE(Below8NonServer ? create_chain_modify_below8_nonsrv : create_chain_modify);
302 DestroyWindow(hWnd);
303 g_TestWindow = NULL;
304 EMPTY_CACHE();
305
306 g_ExpectStyle = g_NcExpectStyle = WS_OVERLAPPEDWINDOW;
307 g_ExpectExStyle = g_NcExpectExStyle = WS_EX_OVERLAPPEDWINDOW;
308 g_FaultLine = __LINE__ + 1;
309 hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Test_Message_Window_XX", L"", WS_OVERLAPPEDWINDOW, 10, 20,
310 200, 210, NULL, NULL, 0, NULL);
311
312 ok(hWnd == g_TestWindow, "We are testing with %p instead of %p\n", g_TestWindow, hWnd);
313 COMPARE_CACHE(Below8NonServer ? create_chain_modify_below8_nonsrv : create_chain_modify);
314 DestroyWindow(hWnd);
315 g_TestWindow = NULL;
316 EMPTY_CACHE();
317 }
318
319
320 START_TEST(CreateWindowEx)
321 {
322 Test_Params();
323 Test_Messages();
324 }