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_empty = {0, 0, 0, L""}; 65 LARGE_STRING l_wndName = {32, 32, 0, L""}; 66 LARGE_STRING l_cls = {cls.Length, 32, 0, cls.Buffer}; 67 LARGE_STRING l_ver_cls = {ver_cls.Length, 32, 0, ver_cls.Buffer}; 68 WCHAR bufMe[255] = {0}; 69 UNICODE_STRING capture = {255, 255, bufMe}; 70 PWSTR pwstr = NULL; 71 CLSMENUNAME clsMenuName, outClsMnu = {0}; 72 ATOM atom, atom2, atom3; 73 HWND hwnd; 74 75 clsMenuName.pszClientAnsiMenuName = "MuMnu"; 76 clsMenuName.pwszClientUnicodeMenuName = menu.Buffer; 77 clsMenuName.pusMenuName = &menu; 78 79 wclex.cbSize = sizeof(WNDCLASSEXW); 80 wclex.style = 0; 81 wclex.lpfnWndProc = wndProc1; 82 wclex.cbClsExtra = 2; 83 wclex.cbWndExtra = 4; 84 wclex.hInstance = hinst; 85 wclex.hIcon = NULL; 86 wclex.hCursor = NULL; 87 wclex.hbrBackground = CreateSolidBrush(RGB(4,7,5)); 88 wclex.lpszMenuName = menu.Buffer; 89 wclex.lpszClassName = cls.Buffer; 90 wclex.hIconSm = NULL; 91 memcpy(&wclex2, &wclex, sizeof(wclex)); 92 wclex2.lpfnWndProc = wndProc2; 93 94 /* Register our first version */ 95 atom = NtUserRegisterClassExWOW(&wclex, /* wndClass */ 96 &cls, /* ClassName */ 97 &cls, /* Version */ 98 &clsMenuName, /* MenuName */ 99 0, 100 0, 101 NULL); 102 TEST(atom != 0); 103 104 /* Register second version */ 105 atom2 = NtUserRegisterClassExWOW(&wclex2, /* wndClass */ 106 &cls, /* ClassName */ 107 &ver_cls, /* Version */ 108 &clsMenuName, /* MenuName */ 109 0, 110 0, 111 NULL); 112 113 atom3 = NtUserRegisterClassExWOW(&wclex2, /* wndClass */ 114 &another_cls, /* ClassName */ 115 &another_cls, /* Version */ 116 &clsMenuName, /* MenuName */ 117 0, 118 0, 119 NULL); 120 121 TEST(NtUserRegisterClassExWOW(&wclex2, /* wndClass */ 122 &cls, /* ClassName */ 123 NULL, /* Version */ 124 &clsMenuName, /* MenuName */ 125 0, 126 0, 127 NULL) == 0); 128 129 TEST(NtUserRegisterClassExWOW(&wclex2, /* wndClass */ 130 &cls, /* ClassName */ 131 &null_cls, /* Version */ 132 &clsMenuName, /* MenuName */ 133 0, 134 0, 135 NULL) == 0); 136 137 TEST(NtUserGetWOWClass(hinst, &ver_cls) != 0); 138 TEST(NtUserGetWOWClass(hinst, &ver_cls) != NtUserGetWOWClass(hinst, &cls)); TEST(atom2 != 0); 139 TEST(atom == atom2 && (atom | atom2) != 0); 140 141 /* Create a window without versioned class */ 142 TEST(CreateWnd(hinst, &l_cls, NULL, &l_wndName) == 0); 143 TEST(CreateWnd(hinst, &l_cls, &l_wndName, &l_wndName) == 0); 144 145 /* Now, create our first window */ 146 hwnd = CreateWnd(hinst, &l_cls, &l_cls, &l_wndName); 147 TEST(hwnd != 0); 148 if(hwnd) 149 { 150 /* Test some settings about the window */ 151 TEST((WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == wndProc1); 152 153 /* Check class name isn't versioned */ 154 TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0); 155 TEST(wcscmp(capture.Buffer, cls.Buffer) == 0); 156 TEST(wcscmp(capture.Buffer, ver_cls.Buffer) != 0); 157 ZeroMemory(capture.Buffer, 255); 158 159 /* Check what return GetClassLong */ 160 TEST(GetClassLong(hwnd, GCW_ATOM) == atom); 161 TEST(NtUserSetClassLong(hwnd, GCW_ATOM, atom3, FALSE) == atom); 162 NtUserGetClassName(hwnd, TRUE, &capture); 163 TEST(wcscmp(capture.Buffer, another_cls.Buffer) == 0); 164 165 /* Finally destroy it */ 166 DestroyWindow(hwnd); 167 } 168 169 /* Create our second version */ 170 hwnd = CreateWnd(hinst, &l_cls, &l_ver_cls, &l_wndName); 171 TEST(hwnd != 0); 172 if (hwnd) 173 { 174 /* Test settings about window */ 175 TEST((WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == wndProc2); 176 177 /* Check class name isn't versioned */ 178 TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0); 179 TEST(wcscmp(capture.Buffer, cls.Buffer) == 0); 180 TEST(wcscmp(capture.Buffer, ver_cls.Buffer) != 0); 181 ZeroMemory(capture.Buffer, 255); 182 183 /* Check what return GetClassLong */ 184 TEST(GetClassLong(hwnd, GCW_ATOM) == atom); 185 186 TEST(NtUserFindWindowEx(NULL, NULL, &cls, (UNICODE_STRING*)&l_empty, 0) == hwnd); 187 188 /* Finally destroy it */ 189 DestroyWindow(hwnd); 190 } 191 192 /* Create a nonexistent window */ 193 hwnd = CreateWnd(hinst, &l_cls, &l_dummy, &l_wndName); 194 TEST(hwnd == 0); 195 if (hwnd) DestroyWindow(hwnd); 196 197 /* Get non-versioned class info */ 198 res.cbSize = sizeof(res); 199 SetLastError(0); 200 TEST(NtUserGetClassInfo(hinst, &cls, &res, &pwstr, 0) != 0); 201 TEST(GetLastError() == 0); 202 TEST(res.cbSize == wclex.cbSize); 203 TEST(res.style == wclex.style); 204 TEST(res.lpfnWndProc == wclex.lpfnWndProc); 205 TEST(res.cbClsExtra == wclex.cbClsExtra); 206 TEST(res.cbWndExtra == wclex.cbWndExtra); 207 TEST(res.hInstance == wclex.hInstance); 208 TEST(res.hIcon == wclex.hIcon); 209 TEST(res.hCursor == wclex.hCursor); 210 TEST(res.hbrBackground == wclex.hbrBackground); 211 TEST(res.lpszMenuName == 0); 212 TEST(res.lpszClassName == 0); 213 TEST(res.hIconSm == wclex.hIconSm); 214 215 /* Get versioned class info */ 216 TEST(NtUserGetClassInfo(hinst, &ver_cls, &res, &pwstr, 0) == atom2); 217 TEST(GetLastError() == 0); 218 TEST(res.cbSize == wclex2.cbSize); 219 TEST(res.style == wclex2.style); 220 TEST(res.lpfnWndProc == wclex2.lpfnWndProc); 221 TEST(res.cbClsExtra == wclex2.cbClsExtra); 222 TEST(res.cbWndExtra == wclex2.cbWndExtra); 223 TEST(res.hInstance == wclex2.hInstance); 224 TEST(res.hIcon == wclex2.hIcon); 225 TEST(res.hCursor == wclex2.hCursor); 226 TEST(res.hbrBackground == wclex2.hbrBackground); 227 TEST(res.lpszMenuName == 0); 228 TEST(res.lpszClassName == 0); 229 TEST(res.hIconSm == wclex2.hIconSm); 230 231 /* Create a new window from our old class. Since we set a new class atom, 232 * it should be set to our new atom 233 */ 234 hwnd = NULL; 235 hwnd = CreateWnd(hinst, &l_cls, &l_cls, &l_wndName); 236 TEST(hwnd != NULL); 237 if (hwnd) 238 { 239 TEST(GetClassLong(hwnd, GCW_ATOM) == atom3); 240 TEST(NtUserGetClassName(hwnd, TRUE, &capture) != 0); 241 TEST(wcscmp(capture.Buffer, another_cls.Buffer) == 0); 242 DestroyWindow(hwnd); 243 } 244 245 /* Test class destruction */ 246 TEST(NtUserUnregisterClass(&cls, hinst, (PCLSMENUNAME)0xbad) != 0); 247 TEST(NtUserUnregisterClass(&ver_cls, hinst, &outClsMnu) != 0); 248 TEST(NtUserUnregisterClass(&another_cls, hinst, &outClsMnu) != 0); 249 TEST(NtUserUnregisterClass(&menu, hinst, &outClsMnu) == 0); 250 251 /* Make sure that the classes got destroyed */ 252 TEST(NtUserGetWOWClass(hinst, &cls) == 0); 253 TEST(NtUserGetWOWClass(hinst, &ver_cls) == 0); 254 TEST(NtUserGetWOWClass(hinst, &another_cls) == 0); 255 } 256