rpcrt4: Fix embedded pointers in arrays by taking into account the iteration when...
[wine] / dlls / ntdll / tests / atom.c
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "wine/test.h"
38 #include "wine/unicode.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* pNtQueryInformationAtom)(RTL_ATOM,DWORD,void*,ULONG,PULONG);
59
60 static const WCHAR EmptyAtom[] = {0};
61 static const WCHAR testAtom1[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
62 static const WCHAR testAtom2[] = {'H','e','l','l','o',' ','W','o','r','l','d','2',0};
63 static const WCHAR testAtom3[] = {'H','e','l','l','o',' ','W','o','r','l','d','3',0};
64
65 static const WCHAR testAtom1Cap[] = {'H','E','L','L','O',' ','W','O','R','L','D',0};
66 static const WCHAR testAtom1Low[] = {'h','e','l','l','o',' ','w','o','r','l','d',0};
67
68 static const WCHAR testAtomInt[] = {'#','1','3','2',0};
69 static const WCHAR testAtomIntInv[] = {'#','2','3','4','z',0};
70 static const WCHAR testAtomOTT[] = {'#','1','2','3',0};
71
72 static void InitFunctionPtr(void)
73 {
74     hntdll = LoadLibraryA("ntdll.dll");
75     ok(hntdll != 0, "Unable to load ntdll.dll\n");
76
77     if (hntdll)
78     {
79         pRtlCreateAtomTable = (void *)GetProcAddress(hntdll, "RtlCreateAtomTable");
80         pRtlDestroyAtomTable = (void *)GetProcAddress(hntdll, "RtlDestroyAtomTable");
81         pRtlEmptyAtomTable = (void *)GetProcAddress(hntdll, "RtlEmptyAtomTable");
82         pRtlAddAtomToAtomTable = (void *)GetProcAddress(hntdll, "RtlAddAtomToAtomTable");
83         pRtlDeleteAtomFromAtomTable = (void *)GetProcAddress(hntdll, "RtlDeleteAtomFromAtomTable");
84         pRtlLookupAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlLookupAtomInAtomTable");
85         pRtlPinAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlPinAtomInAtomTable");
86         pRtlQueryAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlQueryAtomInAtomTable");
87
88         pNtAddAtom = (void *)GetProcAddress(hntdll, "NtAddAtom");
89         pNtQueryInformationAtom = (void *)GetProcAddress(hntdll, "NtQueryInformationAtom");
90     }
91 }
92
93 static DWORD RtlAtomTestThread(LPVOID Table)
94 {
95     RTL_ATOM_TABLE AtomTable = *(PRTL_ATOM_TABLE)Table;
96     RTL_ATOM Atom;
97     NTSTATUS res;
98     ULONG RefCount = 0, PinCount = 0, Len = 0;
99     WCHAR Name[64];
100
101     res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &Atom);
102     ok(!res, "Unable to find atom from another thread, retval: %lx\n", res);
103
104     res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &Atom);
105     ok(!res, "Unable to lookup pinned atom in table, retval: %lx\n", res);
106
107     res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len);
108     ok(res == STATUS_BUFFER_TOO_SMALL, "We got wrong retval: %lx\n", res);
109
110     Len = 64;
111     res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len);
112     ok(!res, "Failed with longenough buffer, retval: %lx\n", res);
113     ok(RefCount == 1, "Refcount was not 1 but %lx\n", RefCount);
114     ok(PinCount == 1, "Pincount was not 1 but %lx\n", PinCount);
115     ok(!strcmpW(Name, testAtom2), "We found wrong atom!!\n");
116     ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
117
118     Len = 64;
119     res = pRtlQueryAtomInAtomTable(AtomTable, Atom, NULL, NULL, Name, &Len);
120     ok(!res, "RtlQueryAtomInAtomTable with optional args invalid failed, retval: %lx\n", res);
121     ok(!strcmpW(Name, testAtom2), "Found Wrong atom!\n");
122     ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
123
124     res = pRtlPinAtomInAtomTable(AtomTable, Atom);
125     ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
126
127     return 0;
128 }
129
130 static void test_NtAtom(void)
131 {
132     RTL_ATOM_TABLE AtomTable = NULL;
133     NTSTATUS res;
134     RTL_ATOM Atom1, Atom2, Atom3, testEAtom, testAtom;
135     HANDLE testThread;
136     ULONG RefCount = 0, PinCount = 0, Len = 0;
137     WCHAR Name[64];
138
139     /* If we pass a non-null string to create atom table, then it thinks that we
140      * have passed it an already allocated atom table */
141     res = pRtlCreateAtomTable(0, &AtomTable);
142     ok(!res, "RtlCreateAtomTable should succeed with an atom table size of 0\n");
143
144     if (!res)
145     {
146         res = pRtlDestroyAtomTable(AtomTable);
147         ok(!res, "We could create the atom table, but we couldn't destroy it! retval: %lx\n", res);
148     }
149
150     AtomTable = NULL;
151     res = pRtlCreateAtomTable(37, &AtomTable);
152     ok(!res, "We're unable to create an atom table with a valid table size retval: %lx\n", res);
153     if (!res)
154     {
155         res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
156         ok(!res, "We were unable to add a simple atom to the atom table, retval: %lx\n", res);
157
158         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Cap, &testAtom);
159         ok(!res, "We were unable to find capital version of the atom, retval: %lx\n", res);
160         ok(Atom1 == testAtom, "Found wrong atom in table when querying capital atom\n");
161
162         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Low, &testAtom);
163         ok(!res, "Unable to find lowercase version of the atom, retval: %lx\n", res);
164         ok(testAtom == Atom1, "Found wrong atom when querying lowercase atom\n");
165
166         res = pRtlAddAtomToAtomTable(AtomTable, EmptyAtom, &testEAtom);
167         ok(res == STATUS_OBJECT_NAME_INVALID, "Got wrong retval, retval: %lx\n", res);
168
169         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
170         ok(!res, "Failed to find totally legitimate atom, retval: %lx\n", res);
171         ok(testAtom == Atom1, "Found wrong atom!\n");
172
173         res = pRtlAddAtomToAtomTable(AtomTable, testAtom2, &Atom2);
174         ok(!res, "Unable to add other legitimate atom to table, retval: %lx\n", res);
175
176         res = pRtlPinAtomInAtomTable(AtomTable, Atom2);
177         ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
178
179         testThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RtlAtomTestThread, &AtomTable, 0, NULL);
180         WaitForSingleObject(testThread, INFINITE);
181
182         Len = 64;
183         res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, &RefCount, &PinCount, Name, &Len);
184         ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
185         ok(RefCount == 1, "RefCount is not 1 but %lx\n", RefCount);
186         ok(PinCount == 1, "PinCount is not 1 but %lx\n", PinCount);
187         ok(!strcmpW(Name, testAtom2), "We found wrong atom\n");
188         ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
189
190         res = pRtlEmptyAtomTable(AtomTable, FALSE);
191         ok(!res, "Unable to empty atom table, retval %lx\n", res);
192
193         Len = 64;
194         res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, &RefCount, &PinCount, Name, &Len);
195         ok(!res, "It seems RtlEmptyAtomTable deleted our pinned atom eaven though we asked it not to, retval: %lx\n", res);
196         ok(RefCount == 1, "RefCount is not 1 but %lx\n", RefCount);
197         ok(PinCount == 1, "PinCount is not 1 but %lx\n", PinCount);
198         ok(!strcmpW(Name, testAtom2), "We found wrong atom\n");
199         ok((strlenW(testAtom2) * sizeof(WCHAR)) == Len, "Returned wrong length %ld\n", Len);
200
201         Len = 8;
202         Name[0] = Name[1] = Name[2] = Name[3] = Name[4] = 0x55AA;
203         res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, NULL, NULL, Name, &Len);
204         ok(!res, "query atom %lx\n", res);
205         ok(Len == 6, "wrong length %lu\n", Len);
206         ok(!memcmp(Name, testAtom2, Len), "wrong atom string\n");
207         ok(!Name[3], "wrong string termination\n");
208         ok(Name[4] == 0x55AA, "buffer overwrite\n");
209
210         Len = lstrlenW(testAtom2) * sizeof(WCHAR);
211         memset(Name, '.', sizeof(Name));
212         res = pRtlQueryAtomInAtomTable( AtomTable, Atom2, NULL, NULL, Name, &Len );
213         ok(!res, "query atom %lx\n", res);
214         ok(Len == (lstrlenW(testAtom2) - 1) * sizeof(WCHAR), "wrong length %lu\n", Len);
215         ok(!memcmp(testAtom2, Name, (lstrlenW(testAtom2) - 1) * sizeof(WCHAR)), "wrong atom name\n");
216         ok(Name[lstrlenW(testAtom2) - 1] == '\0', "wrong char\n");
217         ok(Name[lstrlenW(testAtom2)] == ('.' << 8) + '.', "wrong char\n");
218
219         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
220         ok(!res, "We can't find our pinned atom!! retval: %lx\n", res);
221         ok(testAtom == Atom2, "We found wrong atom!!!\n");
222
223         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
224         ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "We found the atom in our table eaven though we asked RtlEmptyAtomTable to remove it, retval: %lx\n", res);
225
226         res = pRtlAddAtomToAtomTable(AtomTable, testAtom3, &Atom3);
227         ok(!res, "Unable to add atom to table, retval: %lx\n", res);
228
229         res = pRtlEmptyAtomTable(AtomTable, TRUE);
230         ok(!res, "Unable to empty atom table, retval: %lx\n", res);
231
232         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
233         ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "The pinned atom should be removed, retval: %lx\n", res);
234
235         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom3, &testAtom);
236         ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Non pinned atom should also be removed, retval: %lx\n", res);
237
238         res = pRtlDestroyAtomTable(AtomTable);
239         ok(!res, "Can't destroy atom table, retval: %lx\n", res);
240     }
241
242     AtomTable = NULL;
243     res = pRtlCreateAtomTable(37, &AtomTable);
244     ok(!res, "Unable to create atom table, retval: %lx\n", res);
245
246     if (!res)
247     {
248         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
249         ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Didn't get expected retval with querying an empty atom table, retval: %lx\n", res);
250
251         res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
252         ok(!res, "Unable to add atom to atom table, retval %lx\n", res);
253
254         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
255         ok(!res, "Can't find previously added atom in table, retval: %lx\n", res);
256         ok(testAtom == Atom1, "Found wrong atom! retval: %lx\n", res);
257
258         res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
259         ok(!res, "Unable to delete atom from table, retval: %lx\n", res);
260
261         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
262         ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Able to find previously deleted atom in table, retval: %lx\n", res);
263
264         res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
265         ok(!res, "Unable to add atom to atom table, retval: %lx\n", res);
266
267         Len = 0;
268         res = pRtlQueryAtomInAtomTable(AtomTable, Atom1, NULL, NULL, Name, &Len);
269         ok(res == STATUS_BUFFER_TOO_SMALL, "Got wrong retval, retval: %lx\n", res);
270         ok((strlenW(testAtom1) * sizeof(WCHAR)) == Len, "Got wrong length %lx\n", Len);
271
272         res = pRtlPinAtomInAtomTable(AtomTable, Atom1);
273         ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
274
275         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
276         ok(!res, "Unable to find atom in atom table, retval: %lx\n", res);
277         ok(testAtom == Atom1, "Wrong atom found\n");
278
279         res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
280         ok(res == STATUS_WAS_LOCKED, "Unable to delete atom from table, retval: %lx\n", res);
281
282         res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
283         ok(!res, "Able to find deleted atom in table\n");
284
285         res = pRtlDestroyAtomTable(AtomTable);
286         ok(!res, "Unable to destroy atom table\n");
287     }
288 }
289
290 /* Test Adding integer atoms to atom table */
291 static void test_NtIntAtom(void)
292 {
293     NTSTATUS res;
294     RTL_ATOM_TABLE AtomTable;
295     RTL_ATOM testAtom;
296     ULONG RefCount = 0, PinCount = 0;
297     int i;
298     WCHAR Name[64];
299     ULONG Len;
300
301     AtomTable = NULL;
302     res = pRtlCreateAtomTable(37, &AtomTable);
303     ok(!res, "Unable to create atom table, %lx\n", res);
304
305     if (!res)
306     {
307         /* According to the kernel32 functions, integer atoms are only allowd from
308          * 0x0001 to 0xbfff and not 0xc000 to 0xffff, which is correct */
309         res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)0, &testAtom);
310         ok(res == STATUS_INVALID_PARAMETER, "Didn't get expected result from adding 0 int atom, retval: %lx\n", res);
311         for (i = 1; i <= 0xbfff; i++)
312         {
313             res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)i, &testAtom);
314             ok(!res, "Unable to add valid integer atom %i, retval: %lx\n", i, res);
315         }
316
317         for (i = 1; i <= 0xbfff; i++)
318         {
319             res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)i, &testAtom);
320             ok(!res, "Unable to find int atom %i, retval: %lx\n", i, res);
321             if (!res)
322             {
323                 res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
324                 ok(!res, "Unable to pin int atom %i, retval: %lx\n", i, res);
325             }
326         }
327
328         for (i = 0xc000; i <= 0xffff; i++)
329         {
330             res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)i, &testAtom);
331             ok(res, "Able to illeageal integer atom %i, retval: %lx\n", i, res);
332         }
333
334         res = pRtlDestroyAtomTable(AtomTable);
335         ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
336     }
337
338     AtomTable = NULL;
339     res = pRtlCreateAtomTable(37, &AtomTable);
340     ok(!res, "Unable to create atom table, %lx\n", res);
341     if (!res)
342     {
343         res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)123, &testAtom);
344         ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
345
346         res = pRtlAddAtomToAtomTable(AtomTable, testAtomInt, &testAtom);
347         ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
348
349         res = pRtlAddAtomToAtomTable(AtomTable, testAtomIntInv, &testAtom);
350         ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
351
352         res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
353         ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
354
355         res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
356         ok(!res, "Unable to re-add int atom to table, retval: %lx\n", res);
357
358         Len = 64;
359         res = pRtlQueryAtomInAtomTable(AtomTable, testAtom, &RefCount, &PinCount, Name, &Len);
360         ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
361         ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
362         ok(RefCount == 1, "Expected refcount 1 but got %lx\n", RefCount);
363         ok(!strcmpW(testAtomOTT, Name), "Got wrong atom name\n");
364         ok((strlenW(testAtomOTT) * sizeof(WCHAR)) == Len, "Got wrong len %ld\n", Len);
365
366         res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
367         ok(!res, "Unable to pin int atom, retval: %lx\n", res);
368
369         res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
370         ok(!res, "Unable to pin int atom, retval: %lx\n", res);
371
372         res = pRtlQueryAtomInAtomTable(AtomTable, testAtom, &RefCount, &PinCount, NULL, NULL);
373         ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
374         ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
375         ok(RefCount == 1, "Expected refcount 1 but got %lx\n", RefCount);
376
377         res = pRtlDestroyAtomTable(AtomTable);
378         ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
379     }
380 }
381
382 /* Tests to see how the pincount and refcount actually works */
383 static void test_NtRefPinAtom(void)
384 {
385     RTL_ATOM_TABLE AtomTable;
386     RTL_ATOM Atom;
387     ULONG PinCount = 0, RefCount = 0;
388     NTSTATUS res;
389
390     AtomTable = NULL;
391     res = pRtlCreateAtomTable(37, &AtomTable);
392     ok(!res, "Unable to create atom table, %lx\n", res);
393
394     if (!res)
395     {
396         res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
397         ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
398
399         res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
400         ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
401
402         res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
403         ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
404
405         res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, NULL, NULL);
406         ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
407         ok(PinCount == 0, "Expected pincount 0 but got %lx\n", PinCount);
408         ok(RefCount == 3, "Expected refcount 3 but got %lx\n", RefCount); 
409
410         res = pRtlPinAtomInAtomTable(AtomTable, Atom);
411         ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
412
413         res = pRtlPinAtomInAtomTable(AtomTable, Atom);
414         ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
415
416         res = pRtlPinAtomInAtomTable(AtomTable, Atom);
417         ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
418
419         res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, NULL, NULL);
420         ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
421         ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
422         ok(RefCount == 3, "Expected refcount 3 but got %lx\n", RefCount);
423
424         res = pRtlDestroyAtomTable(AtomTable);
425         ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
426     }
427 }
428
429 static void test_Global(void)
430 {
431     NTSTATUS    res;
432     RTL_ATOM    atom;
433     char        ptr[sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR)];
434     ATOM_BASIC_INFORMATION*     abi = (ATOM_BASIC_INFORMATION*)ptr;
435     ULONG       ptr_size = sizeof(ATOM_BASIC_INFORMATION) + 255 * sizeof(WCHAR);
436
437     res = pNtAddAtom(testAtom1, lstrlenW(testAtom1) * sizeof(WCHAR), &atom);
438     ok(!res, "Added atom (%lx)\n", res);
439
440     memset(abi->Name, 0x55, 255 * sizeof(WCHAR));
441     res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
442     ok(!res, "atom lookup\n");
443     ok(!lstrcmpW(abi->Name, testAtom1), "ok strings\n");
444     ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n");
445     ok(abi->Name[lstrlenW(testAtom1)] == 0, "wrong string termination %x\n", abi->Name[lstrlenW(testAtom1)]);
446     ok(abi->Name[lstrlenW(testAtom1) + 1] == 0x5555, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]);
447
448     ptr_size = sizeof(ATOM_BASIC_INFORMATION);
449     res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
450     ok(res == STATUS_BUFFER_TOO_SMALL, "wrong return status (%lx)\n", res);
451     ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "ok string length\n");
452
453     memset(abi->Name, 0x55, lstrlenW(testAtom1) * sizeof(WCHAR));
454     ptr_size = sizeof(ATOM_BASIC_INFORMATION) + lstrlenW(testAtom1) * sizeof(WCHAR);
455     res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
456     ok(!res, "atom lookup %lx\n", res);
457     ok(!lstrcmpW(abi->Name, testAtom1), "strings don't match\n");
458     ok(abi->NameLength == lstrlenW(testAtom1) * sizeof(WCHAR), "wrong string length\n");
459     ok(abi->Name[lstrlenW(testAtom1)] == 0, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1)]);
460     ok(abi->Name[lstrlenW(testAtom1) + 1] == 0x5555, "buffer overwrite %x\n", abi->Name[lstrlenW(testAtom1) + 1]);
461
462     ptr_size = sizeof(ATOM_BASIC_INFORMATION) + 4 * sizeof(WCHAR);
463     abi->Name[0] = abi->Name[1] = abi->Name[2] = abi->Name[3] = '\0';
464     res = pNtQueryInformationAtom( atom, AtomBasicInformation, (void*)ptr, ptr_size, NULL );
465     ok(!res, "couldn't find atom\n");
466     ok(abi->NameLength == 8, "wrong string length %u\n", abi->NameLength);
467     ok(!memcmp(abi->Name, testAtom1, 8), "strings don't match\n");
468 }
469
470 START_TEST(atom)
471 {
472     InitFunctionPtr();
473     if (pRtlCreateAtomTable)
474     {
475         test_NtAtom();
476         test_NtIntAtom();
477         test_NtRefPinAtom();
478         test_Global();
479     }
480 }