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