1 /* Unit test suite for Ntdll atom API functions 2 * 3 * Copyright 2003 Gyorgy 'Nog' Jeney 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 * 19 * NOTES 20 * We use function pointers here as there is no import library for NTDLL on 21 * windows. 22 */ 23 24 #include <stdio.h> 25 #include <stdarg.h> 26 27 #include "ntstatus.h" 28 /* Define WIN32_NO_STATUS so MSVC does not give us duplicate macro 29 * definition errors when we get to winnt.h 30 */ 31 #define WIN32_NO_STATUS 32 33 #include "windef.h" 34 #include "winbase.h" 35 #include "winreg.h" 36 #include "winnls.h" 37 #include "winuser.h" 38 #include "wine/test.h" 39 #include "winternl.h" 40 41 #ifndef __WINE_WINTERNL_H 42 typedef unsigned short RTL_ATOM, *PRTL_ATOM; 43 typedef struct atom_table *RTL_ATOM_TABLE, **PRTL_ATOM_TABLE; 44 #endif 45 46 /* Function pointers for ntdll calls */ 47 static HMODULE hntdll = 0; 48 static NTSTATUS (WINAPI *pRtlCreateAtomTable)(ULONG,PRTL_ATOM_TABLE); 49 static NTSTATUS (WINAPI *pRtlDestroyAtomTable)(RTL_ATOM_TABLE); 50 static NTSTATUS (WINAPI *pRtlEmptyAtomTable)(RTL_ATOM_TABLE,BOOLEAN); 51 static NTSTATUS (WINAPI *pRtlAddAtomToAtomTable)(RTL_ATOM_TABLE,PCWSTR,PRTL_ATOM); 52 static NTSTATUS (WINAPI *pRtlDeleteAtomFromAtomTable)(RTL_ATOM_TABLE,RTL_ATOM); 53 static NTSTATUS (WINAPI *pRtlLookupAtomInAtomTable)(RTL_ATOM_TABLE,PCWSTR,PRTL_ATOM); 54 static NTSTATUS (WINAPI *pRtlPinAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM); 55 static NTSTATUS (WINAPI *pRtlQueryAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM,PULONG,PULONG,PWSTR,PULONG); 56 57 static NTSTATUS (WINAPI* pNtAddAtom)(LPCWSTR,ULONG,RTL_ATOM*); 58 static NTSTATUS (WINAPI* pNtAddAtomNT4)(LPCWSTR,RTL_ATOM*); 59 static NTSTATUS (WINAPI* pNtQueryInformationAtom)(RTL_ATOM,DWORD,void*,ULONG,PULONG); 60 61 static const WCHAR EmptyAtom[] = {0}; 62 static const WCHAR testAtom1[] = {'H','e','l','l','o',' ','W','o','r','l','d',0}; 63 static const WCHAR testAtom2[] = {'H','e','l','l','o',' ','W','o','r','l','d','2',0}; 64 static const WCHAR testAtom3[] = {'H','e','l','l','o',' ','W','o','r','l','d','3',0}; 65 66 static const WCHAR testAtom1Cap[] = {'H','E','L','L','O',' ','W','O','R','L','D',0}; 67 static const WCHAR testAtom1Low[] = {'h','e','l','l','o',' ','w','o','r','l','d',0}; 68 69 static const WCHAR testAtomInt[] = {'#','1','3','2',0}; 70 static const WCHAR testAtomIntInv[] = {'#','2','3','4','z',0}; 71 static const WCHAR testAtomOTT[] = {'#','1','2','3',0}; 72 73 static void InitFunctionPtr(void) 74 { 75 hntdll = LoadLibraryA("ntdll.dll"); 76 ok(hntdll != 0, "Unable to load ntdll.dll\n"); 77 78 if (hntdll) 79 { 80 pRtlCreateAtomTable = (void *)GetProcAddress(hntdll, "RtlCreateAtomTable"); 81 pRtlDestroyAtomTable = (void *)GetProcAddress(hntdll, "RtlDestroyAtomTable"); 82 pRtlEmptyAtomTable = (void *)GetProcAddress(hntdll, "RtlEmptyAtomTable"); 83 pRtlAddAtomToAtomTable = (void *)GetProcAddress(hntdll, "RtlAddAtomToAtomTable"); 84 pRtlDeleteAtomFromAtomTable = (void *)GetProcAddress(hntdll, "RtlDeleteAtomFromAtomTable"); 85 pRtlLookupAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlLookupAtomInAtomTable"); 86 pRtlPinAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlPinAtomInAtomTable"); 87 pRtlQueryAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlQueryAtomInAtomTable"); 88 89 pNtAddAtom = (void *)GetProcAddress(hntdll, "NtAddAtom"); 90 pNtQueryInformationAtom = (void *)GetProcAddress(hntdll, "NtQueryInformationAtom"); 91 } 92 } 93 94 static DWORD WINAPI RtlAtomTestThread(LPVOID Table) 95 { 96 RTL_ATOM_TABLE AtomTable = *(PRTL_ATOM_TABLE)Table; 97 RTL_ATOM Atom; 98 NTSTATUS res; 99 ULONG RefCount = 0, PinCount = 0, Len = 0; 100 WCHAR Name[64]; 101 102 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &Atom); 103 ok(!res, "Unable to find atom from another thread, retval: %x\n", res); 104 105 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &Atom); 106 ok(!res, "Unable to lookup pinned atom in table, retval: %x\n", res); 107 108 res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len); 109 ok(res == STATUS_BUFFER_TOO_SMALL, "We got wrong retval: %x\n", res); 110 111 Len = 64; 112 res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len); 113 ok(!res, "Failed with long enough buffer, retval: %x\n", res); 114 ok(RefCount == 1, "Refcount was not 1 but %x\n", RefCount); 115 ok(PinCount == 1, "Pincount was not 1 but %x\n", PinCount); 116 ok(!lstrcmpW(Name, testAtom2), "We found wrong atom!!\n"); 117 ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %d\n", Len); 118 119 Len = 64; 120 res = pRtlQueryAtomInAtomTable(AtomTable, Atom, NULL, NULL, Name, &Len); 121 ok(!res, "RtlQueryAtomInAtomTable with optional args invalid failed, retval: %x\n", res); 122 ok(!lstrcmpW(Name, testAtom2), "Found Wrong atom!\n"); 123 ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %d\n", Len); 124 125 res = pRtlPinAtomInAtomTable(AtomTable, Atom); 126 ok(!res, "Unable to pin atom in atom table, retval: %x\n", res); 127 128 return 0; 129 } 130 131 static void test_NtAtom(void) 132 { 133 RTL_ATOM_TABLE AtomTable = NULL; 134 NTSTATUS res; 135 RTL_ATOM Atom1, Atom2, Atom3, testEAtom, testAtom; 136 HANDLE testThread; 137 ULONG RefCount = 0, PinCount = 0, Len = 0; 138 WCHAR Name[64]; 139 140 /* If we pass a non-null string to create atom table, then it thinks that we 141 * have passed it an already allocated atom table */ 142 res = pRtlCreateAtomTable(0, &AtomTable); 143 ok(!res, "RtlCreateAtomTable should succeed with an atom table size of 0\n"); 144 145 if (!res) 146 { 147 res = pRtlDestroyAtomTable(AtomTable); 148 ok(!res, "We could create the atom table, but we couldn't destroy it! retval: %x\n", res); 149 } 150 151 AtomTable = NULL; 152 res = pRtlCreateAtomTable(37, &AtomTable); 153 ok(!res, "We're unable to create an atom table with a valid table size retval: %x\n", res); 154 if (!res) 155 { 156 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1); 157 ok(!res, "We were unable to add a simple atom to the atom table, retval: %x\n", res); 158 159 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Cap, &testAtom); 160 ok(!res, "We were unable to find capital version of the atom, retval: %x\n", res); 161 ok(Atom1 == testAtom, "Found wrong atom in table when querying capital atom\n"); 162 163 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Low, &testAtom); 164 ok(!res, "Unable to find lowercase version of the atom, retval: %x\n", res); 165 ok(testAtom == Atom1, "Found wrong atom when querying lowercase atom\n"); 166 167 res = pRtlAddAtomToAtomTable(AtomTable, EmptyAtom, &testEAtom); 168 ok(res == STATUS_OBJECT_NAME_INVALID, "Got wrong retval, retval: %x\n", res); 169 170 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom); 171 ok(!res, "Failed to find totally legitimate atom, retval: %x\n", res); 172 ok(testAtom == Atom1, "Found wrong atom!\n"); 173 174 res = pRtlAddAtomToAtomTable(AtomTable, testAtom2, &Atom2); 175 ok(!res, "Unable to add other legitimate atom to table, retval: %x\n", res); 176 177 res = pRtlPinAtomInAtomTable(AtomTable, Atom2); 178 ok(!res, "Unable to pin atom in atom table, retval: %x\n", res); 179 180 testThread = CreateThread(NULL, 0, RtlAtomTestThread, &AtomTable, 0, NULL); 181 WaitForSingleObject(testThread, INFINITE); 182 CloseHandle(testThread); 183 184 Len = 64; 185 res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, &RefCount, &PinCount, Name, &Len); 186 ok(!res, "Unable to query atom in atom table, retval: %x\n", res); 187 ok(RefCount == 1, "RefCount is not 1 but %x\n", RefCount); 188 ok(PinCount == 1, "PinCount is not 1 but %x\n", PinCount); 189 ok(!lstrcmpW(Name, testAtom2), "We found wrong atom\n"); 190 ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %d\n", Len); 191 192 res = pRtlEmptyAtomTable(AtomTable, FALSE); 193 ok(!res, "Unable to empty atom table, retval %x\n", res); 194 195 Len = 64; 196 res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, &RefCount, &PinCount, Name, &Len); 197 ok(!res, "It seems RtlEmptyAtomTable deleted our pinned atom eaven though we asked it not to, retval: %x\n", res); 198 ok(RefCount == 1, "RefCount is not 1 but %x\n", RefCount); 199 ok(PinCount == 1, "PinCount is not 1 but %x\n", PinCount); 200 ok(!lstrcmpW(Name, testAtom2), "We found wrong atom\n"); 201 ok((lstrlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %d\n", Len); 202 203 Len = 8; 204 Name[0] = Name[1] = Name[2] = Name[3] = Name[4] = 0x1337; 205 res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, NULL, NULL, Name, &Len); 206 ok(!res, "query atom %x\n", res); 207 ok(Len == 6, "wrong length %u\n", Len); 208 ok(!memcmp(Name, testAtom2, Len), "wrong atom string\n"); 209 ok(!Name[3], "wrong string termination\n"); 210 ok(Name[4] == 0x1337, "buffer overwrite\n"); 211 212 Len = lstrlenW(testAtom2) * sizeof(WCHAR); 213 memset(Name, '.', sizeof(Name)); 214 res = pRtlQueryAtomInAtomTable( AtomTable, Atom2, NULL, NULL, Name, &Len ); 215 ok(!res, "query atom %x\n", res); 216 ok(Len == (lstrlenW(testAtom2) - 1) * sizeof(WCHAR), "wrong length %u\n", Len); 217 ok(!memcmp(testAtom2, Name, (lstrlenW(testAtom2) - 1) * sizeof(WCHAR)), "wrong atom name\n"); 218 ok(Name[lstrlenW(testAtom2) - 1] == '\0', "wrong char\n"); 219 ok(Name[lstrlenW(testAtom2)] == ('.' << 8) + '.', "wrong char\n"); 220 221 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom); 222 ok(!res, "We can't find our pinned atom!! retval: %x\n", res); 223 ok(testAtom == Atom2, "We found wrong atom!!!\n"); 224 225 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom); 226 ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "We found the atom in our table eaven though we asked RtlEmptyAtomTable to remove it, retval: %x\n", res); 227 228 res = pRtlAddAtomToAtomTable(AtomTable, testAtom3, &Atom3); 229 ok(!res, "Unable to add atom to table, retval: %x\n", res); 230 231 res = pRtlEmptyAtomTable(AtomTable, TRUE); 232 ok(!res, "Unable to empty atom table, retval: %x\n", res); 233 234 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom); 235 ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "The pinned atom should be removed, retval: %x\n", res); 236 237 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom3, &testAtom); 238 ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Non pinned atom should also be removed, retval: %x\n", res); 239 240 res = pRtlDestroyAtomTable(AtomTable); 241 ok(!res, "Can't destroy atom table, retval: %x\n", res); 242 } 243 244 AtomTable = NULL; 245 res = pRtlCreateAtomTable(37, &AtomTable); 246 ok(!res, "Unable to create atom table, retval: %x\n", res); 247 248 if (!res) 249 { 250 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom); 251 ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Didn't get expected retval with querying an empty atom table, retval: %x\n", res); 252 253 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1); 254 ok(!res, "Unable to add atom to atom table, retval %x\n", res); 255 256 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom); 257 ok(!res, "Can't find previously added atom in table, retval: %x\n", res); 258 ok(testAtom == Atom1, "Found wrong atom! retval: %x\n", res); 259 260 res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1); 261 ok(!res, "Unable to delete atom from table, retval: %x\n", res); 262 263 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom); 264 ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Able to find previously deleted atom in table, retval: %x\n", res); 265 266 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1); 267 ok(!res, "Unable to add atom to atom table, retval: %x\n", res); 268 269 Len = 0; 270 res = pRtlQueryAtomInAtomTable(AtomTable, Atom1, NULL, NULL, Name, &Len); 271 ok(res == STATUS_BUFFER_TOO_SMALL, "Got wrong retval, retval: %x\n", res); 272 ok((lstrlenW(testAtom1) * sizeof(WCHAR)) == Len || broken(!Len) /* nt4 */, "Got wrong length %x\n", Len); 273 if (!Len) pNtAddAtomNT4 = (void *)pNtAddAtom; 274 275 res = pRtlPinAtomInAtomTable(AtomTable, Atom1); 276 ok(!res, "Unable to pin atom in atom table, retval: %x\n", res); 277 278 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom); 279 ok(!res, "Unable to find atom in atom table, retval: %x\n", res); 280 ok(testAtom == Atom1, "Wrong atom found\n"); 281 282 res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1); 283 ok(res == STATUS_WAS_LOCKED, "Unable to delete atom from table, retval: %x\n", res); 284 285 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom); 286 ok(!res, "Able to find deleted atom in table\n"); 287 288 res = pRtlDestroyAtomTable(AtomTable); 289 ok(!res, "Unable to destroy atom table\n"); 290 } 291 } 292 293 /* Test Adding integer atoms to atom table */ 294 static void test_NtIntAtom(void) 295 { 296 NTSTATUS res; 297 RTL_ATOM_TABLE AtomTable; 298 RTL_ATOM testAtom; 299 ULONG RefCount = 0, PinCount = 0; 300 INT_PTR i; 301 WCHAR Name[64]; 302 ULONG Len; 303 304 AtomTable = NULL; 305 res = pRtlCreateAtomTable(37, &AtomTable); 306 ok(!res, "Unable to create atom table, %x\n", res); 307 308 if (!res) 309 { 310 /* According to the kernel32 functions, integer atoms are only allowed from 311 * 0x0001 to 0xbfff and not 0xc000 to 0xffff, which is correct */ 312 res = pRtlAddAtomToAtomTable(AtomTable, NULL, &testAtom); 313 ok(res == STATUS_INVALID_PARAMETER, "Didn't get expected result from adding 0 int atom, retval: %x\n", res); 314 for (i = 1; i <= 0xbfff; i++) 315 { 316 res = pRtlAddAtomToAtomTable(AtomTable, (LPWSTR)i, &testAtom); 317 ok(!res, "Unable to add valid integer atom %li, retval: %x\n", i, res); 318 } 319 320 for (i = 1; i <= 0xbfff; i++) 321 { 322 res = pRtlLookupAtomInAtomTable(AtomTable, (LPWSTR)i, &testAtom); 323 ok(!res, "Unable to find int atom %li, retval: %x\n", i, res); 324 if (!res) 325 { 326 res = pRtlPinAtomInAtomTable(AtomTable, testAtom); 327 ok(!res, "Unable to pin int atom %li, retval: %x\n", i, res); 328 } 329 } 330 331 for (i = 0xc000; i <= 0xffff; i++) 332 { 333 res = pRtlAddAtomToAtomTable(AtomTable, (LPWSTR)i, &testAtom); 334 ok(res, "Able to illeageal integer atom %li, retval: %x\n", i, res); 335 } 336 337 res = pRtlDestroyAtomTable(AtomTable); 338 ok(!res, "Unable to destroy atom table, retval: %x\n", res); 339 } 340 341 AtomTable = NULL; 342 res = pRtlCreateAtomTable(37, &AtomTable); 343 ok(!res, "Unable to create atom table, %x\n", res); 344 if (!res) 345 { 346 res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)123, &testAtom); 347 ok(!res, "Unable to query atom in atom table, retval: %x\n", res); 348 349 res = pRtlAddAtomToAtomTable(AtomTable, testAtomInt, &testAtom); 350 ok(!res, "Unable to add int atom to table, retval: %x\n", res); 351 352 res = pRtlAddAtomToAtomTable(AtomTable, testAtomIntInv, &testAtom); 353 ok(!res, "Unable to add int atom to table, retval: %x\n", res); 354 355 res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom); 356 ok(!res, "Unable to add int atom to table, retval: %x\n", res); 357 358 res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom); 359 ok(!res, "Unable to re-add int atom to table, retval: %x\n", res); 360 361 Len = 64; 362 res = pRtlQueryAtomInAtomTable(AtomTable, testAtom, &RefCount, &PinCount, Name, &Len); 363 ok(!res, "Unable to query atom in atom table, retval: %x\n", res); 364 ok(PinCount == 1, "Expected pincount 1 but got %x\n", PinCount); 365 ok(RefCount == 1, "Expected refcount 1 but got %x\n", RefCount); 366 ok(!lstrcmpW(testAtomOTT, Name), "Got wrong atom name\n"); 367 ok((lstrlenW(testAtomOTT) * sizeof(WCHAR)) == Len, "Got wrong len %d\n", Len); 368 369 res = pRtlPinAtomInAtomTable(AtomTable, testAtom); 370 ok(!res, "Unable to pin int atom, retval: %x\n", res); 371 372 res = pRtlPinAtomInAtomTable(AtomTable, testAtom); 373 ok(!res, "Unable to pin int atom, retval: %x\n", res); 374 375 res = pRtlQueryAtomInAtomTable(AtomTable, testAtom, &RefCount, &PinCount, NULL, NULL); 376 ok(!res, "Unable to query atom in atom table, retval: %x\n", res); 377 ok(PinCount == 1, "Expected pincount 1 but got %x\n", PinCount); 378 ok(RefCount == 1, "Expected refcount 1 but got %x\n", RefCount); 379 380 res = pRtlDestroyAtomTable(AtomTable); 381 ok(!res, "Unable to destroy atom table, retval: %x\n", res); 382 } 383 } 384 385 /* Tests to see how the pincount and refcount actually works */ 386 static void test_NtRefPinAtom(void) 387 { 388 RTL_ATOM_TABLE AtomTable; 389 RTL_ATOM Atom; 390 ULONG PinCount = 0, RefCount = 0; 391 NTSTATUS res; 392 393 AtomTable = NULL; 394 res = pRtlCreateAtomTable(37, &AtomTable); 395 ok(!res, "Unable to create atom table, %x\n", res); 396 397 if (!res) 398 { 399 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom); 400 ok(!res, "Unable to add our atom to the atom table, retval: %x\n", res); 401 402 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom); 403 ok(!res, "Unable to add our atom to the atom table, retval: %x\n", res); 404 405 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom); 406 ok(!res, "Unable to add our atom to the atom table, retval: %x\n", res); 407 408 res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, NULL, NULL); 409 ok(!res, "Unable to query atom in atom table, retval: %x\n", res); 410 ok(PinCount == 0, "Expected pincount 0 but got %x\n", PinCount); 411 ok(RefCount == 3, "Expected refcount 3 but got %x\n", RefCount); 412 413 res = pRtlPinAtomInAtomTable(AtomTable, Atom); 414 ok(!res, "Unable to pin atom in atom table, retval: %x\n", res); 415 416 res = pRtlPinAtomInAtomTable(AtomTable, Atom); 417 ok(!res, "Unable to pin atom in atom table, retval: %x\n", res); 418 419 res = pRtlPinAtomInAtomTable(AtomTable, Atom); 420 ok(!res, "Unable to pin atom in atom table, retval: %x\n", res); 421 422 res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, NULL, NULL); 423 ok(!res, "Unable to query atom in atom table, retval: %x\n", res); 424 ok(PinCount == 1, "Expected pincount 1 but got %x\n", PinCount); 425 ok(RefCount == 3, "Expected refcount 3 but got %x\n", RefCount); 426 427 res = pRtlDestroyAtomTable(AtomTable); 428 ok(!res, "Unable to destroy atom table, retval: %x\n", res); 429 } 430 } 431 432 static void test_Global(void) 433 { 434 NTSTATUS res; 435 RTL_ATOM atom; 436 ULONG ptr[(sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR)) / sizeof(ULONG)]; 437 ATOM_BASIC_INFORMATION* abi = (ATOM_BASIC_INFORMATION*)ptr; 438 ULONG ptr_size = sizeof(ptr); 439 440 if (pNtAddAtomNT4) 441 res = pNtAddAtomNT4(testAtom1, &atom); 442 else 443 res = pNtAddAtom(testAtom1, lstrlenW(testAtom1) * sizeof(WCHAR), &atom); 444 445 ok(!res, "Added atom (%x)\n", res); 446 447 memset( ptr, 0xcc, sizeof(ptr) ); 448 res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL ); 449 ok(!res, "atom lookup\n"); 450 ok(!lstrcmpW(abi->Name, testAtom1), "ok strings\n"); 451 ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n"); 452 ok(abi->Name[lstrlenW(testAtom1)] == 0, "wrong string termination %x\n", abi->Name[lstrlenW(testAtom1)]); 453 ok(abi->Name[lstrlenW(testAtom1) + 1] == 0xcccc, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]); 454 455 ptr_size = sizeof(ATOM_BASIC_INFORMATION); 456 res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL ); 457 ok(res == STATUS_BUFFER_TOO_SMALL, "wrong return status (%x)\n", res); 458 ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR) || broken(abi->NameLength == sizeof(WCHAR)), /* nt4 */ 459 "string length %u\n",abi->NameLength); 460 461 memset( ptr, 0xcc, sizeof(ptr) ); 462 ptr_size = sizeof(ATOM_BASIC_INFORMATION) + lstrlenW(testAtom1) * sizeof(WCHAR); 463 res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL ); 464 ok(!res, "atom lookup %x\n", res); 465 ok(!lstrcmpW(abi->Name, testAtom1), "strings don't match\n"); 466 ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n"); 467 ok(abi->Name[lstrlenW(testAtom1)] == 0, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1)]); 468 ok(abi->Name[lstrlenW(testAtom1) + 1] == 0xcccc, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]); 469 470 memset( ptr, 0xcc, sizeof(ptr) ); 471 ptr_size = sizeof(ATOM_BASIC_INFORMATION) + 4 * sizeof(WCHAR); 472 res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL ); 473 ok(!res, "couldn't find atom\n"); 474 ok(abi->NameLength == 8, "wrong string length %u\n", abi->NameLength); 475 ok(!memcmp(abi->Name, testAtom1, 8), "strings don't match\n"); 476 } 477 478 START_TEST(atom) 479 { 480 InitFunctionPtr(); 481 if (pRtlCreateAtomTable) 482 { 483 /* Global atom table seems to be available to GUI apps only in 484 Win7, so let's turn this app into a GUI app */ 485 GetDesktopWindow(); 486 487 test_NtAtom(); 488 test_NtIntAtom(); 489 test_NtRefPinAtom(); 490 test_Global(); 491 } 492 else 493 win_skip("Needed atom functions are not available\n"); 494 495 FreeLibrary(hntdll); 496 } 497