bb096217b69fe1092425fb89a5234ce85f2bdf6f
[reactos.git] / rostests / apitests / win32nt / ntuser / NtUserCreateWindowEx.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for NtUserCreateWindowEx
5 */
6
7 #include <win32nt.h>
8
9 static
10 inline
11 HWND
12 CreateWnd(HINSTANCE hinst,
13 PLARGE_STRING clsName,
14 PLARGE_STRING clsVer,
15 PLARGE_STRING wndName)
16 {
17 return NtUserCreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
18 clsName,
19 clsVer,
20 wndName,
21 WS_CAPTION,
22 CW_USEDEFAULT,
23 CW_USEDEFAULT,
24 100,
25 100,
26 NULL,
27 NULL,
28 hinst,
29 0,
30 0,
31 NULL);
32 }
33
34 /* WndProc for class1 */
35
36 LRESULT CALLBACK wndProc1(HWND hwnd, UINT msg, WPARAM wPrm, LPARAM lPrm)
37 {
38 return DefWindowProc(hwnd, msg, wPrm, lPrm);
39 }
40
41 /* WndProc for class2 */
42 LRESULT CALLBACK wndProc2(HWND hwnd, UINT msg, WPARAM wPrm, LPARAM lPrm)
43 {
44 return DefWindowProc(hwnd, msg, wPrm, lPrm);
45 }
46
47
48 START_TEST(NtUserCreateWindowEx)
49 {
50 HINSTANCE hinst = GetModuleHandle(NULL);
51 WNDCLASSEXW wclex = {0};
52 WNDCLASSEXW wclex2 = {0};
53 WNDCLASSEXW res = {0};
54
55 /* Unicode strings for NtRegisterClassExWOW */
56 UNICODE_STRING cls = {14, 32, L"MyClass"};
57 UNICODE_STRING ver_cls = {12, 32, L"v2test"};
58 UNICODE_STRING another_cls = {10, 32, L"Dummy"};
59 UNICODE_STRING menu = {10, 10, L"MuMnu"};
60 UNICODE_STRING null_cls = {2, 2, L""};
61
62 /* LARGE_STRING for NtUserCreateWindowEx */
63 LARGE_STRING l_dummy = {14, 32, 0, L"DummyMe"};
64 LARGE_STRING l_wndName = {32, 32, 0, L""};
65 LARGE_STRING l_cls = {cls.Length, 32, 0, cls.Buffer};
66 LARGE_STRING l_ver_cls = {ver_cls.Length, 32, 0, ver_cls.Buffer};
67 WCHAR bufMe[255] = {0};
68 UNICODE_STRING capture = {255, 255, bufMe};
69 PWSTR pwstr = NULL;
70 CLSMENUNAME clsMenuName, outClsMnu = {0};
71 ATOM atom, atom2, atom3;
72 HWND hwnd;
73
74 clsMenuName.pszClientAnsiMenuName = "MuMnu";
75 clsMenuName.pwszClientUnicodeMenuName = menu.Buffer;
76 clsMenuName.pusMenuName = &menu;
77
78 wclex.cbSize = sizeof(WNDCLASSEXW);
79 wclex.style = 0;
80 wclex.lpfnWndProc = wndProc1;
81 wclex.cbClsExtra = 2;
82 wclex.cbWndExtra = 4;
83 wclex.hInstance = hinst;
84 wclex.hIcon = NULL;
85 wclex.hCursor = NULL;
86 wclex.hbrBackground = CreateSolidBrush(RGB(4,7,5));
87 wclex.lpszMenuName = menu.Buffer;
88 wclex.lpszClassName = cls.Buffer;
89 wclex.hIconSm = NULL;
90 memcpy(&wclex2, &wclex, sizeof(wclex));
91 wclex2.lpfnWndProc = wndProc2;
92
93 /* Register our first version */
94 atom = NtUserRegisterClassExWOW(&wclex, /* wndClass */
95 &cls, /* ClassName */
96 &cls, /* Version */
97 &clsMenuName, /* MenuName */
98 0,
99 0,
100 NULL);
101 TEST(atom != 0);
102
103 /* Register second version */
104 atom2 = NtUserRegisterClassExWOW(&wclex2, /* wndClass */
105 &cls, /* ClassName */
106 &ver_cls, /* Version */
107 &clsMenuName, /* MenuName */
108 0,
109 0,
110 NULL);
111
112 atom3 = NtUserRegisterClassExWOW(&wclex2, /* wndClass */
113 &another_cls, /* ClassName */
114 &another_cls, /* Version */
115 &clsMenuName, /* MenuName */
116 0,
117 0,
118 NULL);
119
120 TEST(NtUserRegisterClassExWOW(&wclex2, /* wndClass */
121 &cls, /* ClassName */
122 NULL, /* Version */
123 &clsMenuName, /* MenuName */
124 0,
125 0,
126 NULL) == 0);
127
128 TEST(NtUserRegisterClassExWOW(&wclex2, /* wndClass */
129 &cls, /* ClassName */
130 &null_cls, /* Version */
131 &clsMenuName, /* MenuName */
132 0,
133 0,
134 NULL) == 0);
135
136 TEST(NtUserGetWOWClass(hinst, &ver_cls) != 0);
137 TEST(NtUserGetWOWClass(hinst, &ver_cls) != NtUserGetWOWClass(hinst, &cls)); TEST(atom2 != 0);
138 TEST(atom == atom2 && (atom | atom2) != 0);
139
140 /* Create a window without versioned class */
141 TEST(CreateWnd(hinst, &l_cls, NULL, &l_wndName) == 0);
142 TEST(CreateWnd(hinst, &l_cls, &l_wndName, &l_wndName) == 0);
143
144 /* Now, create our first window */
145 hwnd = CreateWnd(hinst, &l_cls, &l_cls, &l_wndName);
146 TEST(hwnd != 0);
147 if(hwnd)
148 {
149 /* Test some settings about the window */
150 TEST((WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == wndProc1);
151
152 /* Check class name isn't versioned */
153 TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0);
154 TEST(wcscmp(capture.Buffer, cls.Buffer) == 0);
155 TEST(wcscmp(capture.Buffer, ver_cls.Buffer) != 0);
156 ZeroMemory(capture.Buffer, 255);
157
158 /* Check what return GetClassLong */
159 TEST(GetClassLong(hwnd, GCW_ATOM) == atom);
160 TEST(NtUserSetClassLong(hwnd, GCW_ATOM, atom3, FALSE) == atom);
161 NtUserGetClassName(hwnd, TRUE, &capture);
162 TEST(wcscmp(capture.Buffer, another_cls.Buffer) == 0);
163
164 /* Finally destroy it */
165 DestroyWindow(hwnd);
166 }
167
168 /* Create our second version */
169 hwnd = CreateWnd(hinst, &l_cls, &l_ver_cls, &l_wndName);
170 TEST(hwnd != 0);
171 if (hwnd)
172 {
173 /* Test settings about window */
174 TEST((WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == wndProc2);
175
176 /* Check class name isn't versioned */
177 TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0);
178 TEST(wcscmp(capture.Buffer, cls.Buffer) == 0);
179 TEST(wcscmp(capture.Buffer, ver_cls.Buffer) != 0);
180 ZeroMemory(capture.Buffer, 255);
181
182 /* Check what return GetClassLong */
183 TEST(GetClassLong(hwnd, GCW_ATOM) == atom);
184
185 /* Finally destroy it */
186 DestroyWindow(hwnd);
187 }
188
189 /* Create a nonexistent window */
190 hwnd = CreateWnd(hinst, &l_cls, &l_dummy, &l_wndName);
191 TEST(hwnd == 0);
192 if (hwnd) DestroyWindow(hwnd);
193
194 /* Get non-versioned class info */
195 res.cbSize = sizeof(res);
196 SetLastError(0);
197 TEST(NtUserGetClassInfo(hinst, &cls, &res, &pwstr, 0) != 0);
198 TEST(GetLastError() == 0);
199 TEST(res.cbSize == wclex.cbSize);
200 TEST(res.style == wclex.style);
201 TEST(res.lpfnWndProc == wclex.lpfnWndProc);
202 TEST(res.cbClsExtra == wclex.cbClsExtra);
203 TEST(res.cbWndExtra == wclex.cbWndExtra);
204 TEST(res.hInstance == wclex.hInstance);
205 TEST(res.hIcon == wclex.hIcon);
206 TEST(res.hCursor == wclex.hCursor);
207 TEST(res.hbrBackground == wclex.hbrBackground);
208 TEST(res.lpszMenuName == 0);
209 TEST(res.lpszClassName == 0);
210 TEST(res.hIconSm == wclex.hIconSm);
211
212 /* Get versioned class info */
213 TEST(NtUserGetClassInfo(hinst, &ver_cls, &res, &pwstr, 0) != 0);
214 TEST(GetLastError() == 0);
215 TEST(res.cbSize == wclex2.cbSize);
216 TEST(res.style == wclex2.style);
217 TEST(res.lpfnWndProc == wclex2.lpfnWndProc);
218 TEST(res.cbClsExtra == wclex2.cbClsExtra);
219 TEST(res.cbWndExtra == wclex2.cbWndExtra);
220 TEST(res.hInstance == wclex2.hInstance);
221 TEST(res.hIcon == wclex2.hIcon);
222 TEST(res.hCursor == wclex2.hCursor);
223 TEST(res.hbrBackground == wclex2.hbrBackground);
224 TEST(res.lpszMenuName == 0);
225 TEST(res.lpszClassName == 0);
226 TEST(res.hIconSm == wclex2.hIconSm);
227
228 /* Create a new window from our old class. Since we set a new class atom,
229 * it should be set to our new atom
230 */
231 hwnd = NULL;
232 hwnd = CreateWnd(hinst, &l_cls, &l_cls, &l_wndName);
233 TEST(hwnd != NULL);
234 if (hwnd)
235 {
236 TEST(GetClassLong(hwnd, GCW_ATOM) == atom3);
237 TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0);
238 TEST(wcscmp(capture.Buffer, another_cls.Buffer) == 0);
239 DestroyWindow(hwnd);
240 }
241
242 /* Test class destruction */
243 TEST(NtUserUnregisterClass(&cls, hinst, (PCLSMENUNAME)0xbad) != 0);
244 TEST(NtUserUnregisterClass(&ver_cls, hinst, &outClsMnu) != 0);
245 TEST(NtUserUnregisterClass(&another_cls, hinst, &outClsMnu) != 0);
246 TEST(NtUserUnregisterClass(&menu, hinst, &outClsMnu) == 0);
247
248 }