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
InitFunctionPtr(void)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
RtlAtomTestThread(LPVOID Table)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
test_NtAtom(void)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 */
test_NtIntAtom(void)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 */
test_NtRefPinAtom(void)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
test_Global(void)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
START_TEST(atom)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