1 /* Unit test suite for Ntdll atom API functions
3 * Copyright 2003 Gyorgy 'Nog' Jeney
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.
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.
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
20 * We use function pointers here as there is no import library for NTDLL on
24 #define _WIN32_WINNT 0x0501
29 #define WIN32_NO_STATUS
31 #include "wine/test.h"
32 #include "wine/unicode.h"
35 /* Function pointers for ntdll calls */
36 static HMODULE hntdll
= 0;
37 static NTSTATUS (WINAPI
*pRtlCreateAtomTable
)(ULONG
,PRTL_ATOM_TABLE
);
38 static NTSTATUS (WINAPI
*pRtlDestroyAtomTable
)(RTL_ATOM_TABLE
);
39 static NTSTATUS (WINAPI
*pRtlEmptyAtomTable
)(RTL_ATOM_TABLE
,BOOLEAN
);
40 static NTSTATUS (WINAPI
*pRtlAddAtomToAtomTable
)(RTL_ATOM_TABLE
,PCWSTR
,PRTL_ATOM
);
41 static NTSTATUS (WINAPI
*pRtlDeleteAtomFromAtomTable
)(RTL_ATOM_TABLE
,RTL_ATOM
);
42 static NTSTATUS (WINAPI
*pRtlLookupAtomInAtomTable
)(RTL_ATOM_TABLE
,PCWSTR
,PRTL_ATOM
);
43 static NTSTATUS (WINAPI
*pRtlPinAtomInAtomTable
)(RTL_ATOM_TABLE
,RTL_ATOM
);
44 static NTSTATUS (WINAPI
*pRtlQueryAtomInAtomTable
)(RTL_ATOM_TABLE
,RTL_ATOM
,PULONG
,PULONG
,PWSTR
,PULONG
);
46 static const WCHAR EmptyAtom
[] = {0};
47 static const WCHAR testAtom1
[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
48 static const WCHAR testAtom2
[] = {'H','e','l','l','o',' ','W','o','r','l','d','2',0};
49 static const WCHAR testAtom3
[] = {'H','e','l','l','o',' ','W','o','r','l','d','3',0};
51 static const WCHAR testAtom1Cap
[] = {'H','E','L','L','O',' ','W','O','R','L','D',0};
52 static const WCHAR testAtom1Low
[] = {'h','e','l','l','o',' ','w','o','r','l','d',0};
54 static const WCHAR testAtomInt
[] = {'#','1','3','2',0};
55 static const WCHAR testAtomIntInv
[] = {'#','2','3','4','z',0};
56 static const WCHAR testAtomOTT
[] = {'#','1','2','3',0};
58 static void InitFunctionPtr(void)
60 hntdll
= LoadLibraryA("ntdll.dll");
61 ok(hntdll
!= 0, "Unable to load ntdll.dll\n");
65 pRtlCreateAtomTable
= (void *)GetProcAddress(hntdll
, "RtlCreateAtomTable");
66 pRtlDestroyAtomTable
= (void *)GetProcAddress(hntdll
, "RtlDestroyAtomTable");
67 pRtlEmptyAtomTable
= (void *)GetProcAddress(hntdll
, "RtlEmptyAtomTable");
68 pRtlAddAtomToAtomTable
= (void *)GetProcAddress(hntdll
, "RtlAddAtomToAtomTable");
69 pRtlDeleteAtomFromAtomTable
= (void *)GetProcAddress(hntdll
, "RtlDeleteAtomFromAtomTable");
70 pRtlLookupAtomInAtomTable
= (void *)GetProcAddress(hntdll
, "RtlLookupAtomInAtomTable");
71 pRtlPinAtomInAtomTable
= (void *)GetProcAddress(hntdll
, "RtlPinAtomInAtomTable");
72 pRtlQueryAtomInAtomTable
= (void *)GetProcAddress(hntdll
, "RtlQueryAtomInAtomTable");
76 static DWORD
RtlAtomTestThread(LPVOID Table
)
78 RTL_ATOM_TABLE AtomTable
= *(PRTL_ATOM_TABLE
)Table
;
81 ULONG RefCount
= 0, PinCount
= 0, Len
= 0;
84 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1
, &Atom
);
85 ok(!res
, "Unable to find atom from another thread, retval: %lx\n", res
);
87 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom2
, &Atom
);
88 ok(!res
, "Unable to lookup pinned atom in table, retval: %lx\n", res
);
90 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom
, &RefCount
, &PinCount
, Name
, &Len
);
91 ok(res
== STATUS_BUFFER_TOO_SMALL
, "We got wrong retval: %lx\n", res
);
94 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom
, &RefCount
, &PinCount
, Name
, &Len
);
95 ok(!res
, "Failed with longenough buffer, retval: %lx\n", res
);
96 ok(RefCount
== 1, "Refcount was not 1 but %lx\n", RefCount
);
97 ok(PinCount
== 1, "Pincount was not 1 but %lx\n", PinCount
);
98 ok(!strcmpW(Name
, testAtom2
), "We found wrong atom!!\n");
99 ok((strlenW(testAtom2
) * sizeof(WCHAR
)) == Len
, "Returned wrong length %ld\n", Len
);
102 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom
, NULL
, NULL
, Name
, &Len
);
103 ok(!res
, "RtlQueryAtomInAtomTable with optional args invalid failed, retval: %lx\n", res
);
104 ok(!strcmpW(Name
, testAtom2
), "Found Wrong atom!\n");
105 ok((strlenW(testAtom2
) * sizeof(WCHAR
)) == Len
, "Returned wrong length %ld\n", Len
);
107 res
= pRtlPinAtomInAtomTable(AtomTable
, Atom
);
108 ok(!res
, "Unable to pin atom in atom table, retval: %lx\n", res
);
113 static void test_NtAtom(void)
115 RTL_ATOM_TABLE AtomTable
= NULL
;
117 RTL_ATOM Atom1
, Atom2
, Atom3
, testEAtom
, testAtom
;
119 ULONG RefCount
= 0, PinCount
= 0, Len
= 0;
122 /* If we pass a non-null string to create atom table, then it thinks that we
123 * have passed it an already allocated atom table */
124 res
= pRtlCreateAtomTable(0, &AtomTable
);
125 ok(!res
, "RtlCreateAtomTable should succeed with an atom table size of 0\n");
129 res
= pRtlDestroyAtomTable(AtomTable
);
130 ok(!res
, "We could create the atom table, but we couldn't destroy it! retval: %lx\n", res
);
134 res
= pRtlCreateAtomTable(37, &AtomTable
);
135 ok(!res
, "We're unable to create an atom table with a valid table size retval: %lx\n", res
);
138 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtom1
, &Atom1
);
139 ok(!res
, "We were unable to add a simple atom to the atom table, retval: %lx\n", res
);
141 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1Cap
, &testAtom
);
142 ok(!res
, "We were unable to find capital version of the atom, retval: %lx\n", res
);
143 ok(Atom1
== testAtom
, "Found wrong atom in table when querying capital atom\n");
145 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1Low
, &testAtom
);
146 ok(!res
, "Unable to find lowercase version of the atom, retval: %lx\n", res
);
147 ok(testAtom
== Atom1
, "Found wrong atom when querying lowercase atom\n");
149 res
= pRtlAddAtomToAtomTable(AtomTable
, EmptyAtom
, &testEAtom
);
150 ok(res
== STATUS_OBJECT_NAME_INVALID
, "Got wrong retval, retval: %lx\n", res
);
152 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1
, &testAtom
);
153 ok(!res
, "Failed to find totally legitimate atom, retval: %lx\n", res
);
154 ok(testAtom
== Atom1
, "Found wrong atom!\n");
156 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtom2
, &Atom2
);
157 ok(!res
, "Unable to add other legitimate atom to table, retval: %lx\n", res
);
159 res
= pRtlPinAtomInAtomTable(AtomTable
, Atom2
);
160 ok(!res
, "Unable to pin atom in atom table, retval: %lx\n", res
);
162 testThread
= CreateThread(NULL
, 0, (LPTHREAD_START_ROUTINE
)RtlAtomTestThread
, &AtomTable
, 0, NULL
);
163 WaitForSingleObject(testThread
, INFINITE
);
166 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom2
, &RefCount
, &PinCount
, Name
, &Len
);
167 ok(!res
, "Unable to query atom in atom table, retval: %lx\n", res
);
168 ok(RefCount
== 1, "RefCount is not 1 but %lx\n", RefCount
);
169 ok(PinCount
== 1, "PinCount is not 1 but %lx\n", PinCount
);
170 ok(!strcmpW(Name
, testAtom2
), "We found wrong atom\n");
171 ok((strlenW(testAtom2
) * sizeof(WCHAR
)) == Len
, "Returned wrong length %ld\n", Len
);
173 res
= pRtlEmptyAtomTable(AtomTable
, FALSE
);
174 ok(!res
, "Unable to empty atom table, retval %lx\n", res
);
177 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom2
, &RefCount
, &PinCount
, Name
, &Len
);
178 ok(!res
, "It seems RtlEmptyAtomTable deleted our pinned atom eaven though we asked it not to, retval: %lx\n", res
);
179 ok(RefCount
== 1, "RefCount is not 1 but %lx\n", RefCount
);
180 ok(PinCount
== 1, "PinCount is not 1 but %lx\n", PinCount
);
181 ok(!strcmpW(Name
, testAtom2
), "We found wrong atom\n");
182 ok((strlenW(testAtom2
) * sizeof(WCHAR
)) == Len
, "Returned wrong length %ld\n", Len
);
184 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom2
, &testAtom
);
185 ok(!res
, "We can't find our pinned atom!! retval: %lx\n", res
);
186 ok(testAtom
== Atom2
, "We found wrong atom!!!\n");
188 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1
, &testAtom
);
189 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
);
191 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtom3
, &Atom3
);
192 ok(!res
, "Unable to add atom to table, retval: %lx\n", res
);
194 res
= pRtlEmptyAtomTable(AtomTable
, TRUE
);
195 ok(!res
, "Unable to empty atom table, retval: %lx\n", res
);
197 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom2
, &testAtom
);
198 ok(res
== STATUS_OBJECT_NAME_NOT_FOUND
, "The pinned atom should be removed, retval: %lx\n", res
);
200 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom3
, &testAtom
);
201 ok(res
== STATUS_OBJECT_NAME_NOT_FOUND
, "Non pinned atom should also be removed, retval: %lx\n", res
);
203 res
= pRtlDestroyAtomTable(AtomTable
);
204 ok(!res
, "Can't destroy atom table, retval: %lx\n", res
);
208 res
= pRtlCreateAtomTable(37, &AtomTable
);
209 ok(!res
, "Unable to create atom table, retval: %lx\n", res
);
213 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1
, &testAtom
);
214 ok(res
== STATUS_OBJECT_NAME_NOT_FOUND
, "Didn't get expected retval with querying an empty atom table, retval: %lx\n", res
);
216 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtom1
, &Atom1
);
217 ok(!res
, "Unable to add atom to atom table, retval %lx\n", res
);
219 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1
, &testAtom
);
220 ok(!res
, "Can't find previously added atom in table, retval: %lx\n", res
);
221 ok(testAtom
== Atom1
, "Found wrong atom! retval: %lx\n", res
);
223 res
= pRtlDeleteAtomFromAtomTable(AtomTable
, Atom1
);
224 ok(!res
, "Unable to delete atom from table, retval: %lx\n", res
);
226 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1
, &testAtom
);
227 ok(res
== STATUS_OBJECT_NAME_NOT_FOUND
, "Able to find previously deleted atom in table, retval: %lx\n", res
);
229 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtom1
, &Atom1
);
230 ok(!res
, "Unable to add atom to atom table, retval: %lx\n", res
);
233 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom1
, NULL
, NULL
, Name
, &Len
);
234 ok(res
== STATUS_BUFFER_TOO_SMALL
, "Got wrong retval, retval: %lx\n", res
);
235 ok((strlenW(testAtom1
) * sizeof(WCHAR
)) == Len
, "Got wrong length %lx\n", Len
);
237 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom1
, NULL
, NULL
, NULL
, &Len
);
238 ok(!res
, "Failed to retrieve atom length, retval: %lx\n", res
);
239 ok(Len
== strlenW(testAtom1
) * sizeof(WCHAR
), "Invalid atom length got %lu expected %u\n",
240 Len
, strlenW(testAtom1
) * sizeof(WCHAR
));
242 Len
= strlenW(testAtom1
) * sizeof(WCHAR
);
243 Name
[strlenW(testAtom1
)] = '*';
244 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom1
, NULL
, NULL
, Name
, &Len
);
245 ok(!res
, "Failed with exactly long enough buffer, retval: %lx\n", res
);
246 ok(Name
[strlenW(testAtom1
)] == '*', "Writing outside buffer\n");
247 ok(0 == memcmp(Name
, testAtom1
, (strlenW(testAtom1
) - 1) * sizeof(WCHAR
)),
248 "We found wrong atom!!\n");
250 res
= pRtlPinAtomInAtomTable(AtomTable
, Atom1
);
251 ok(!res
, "Unable to pin atom in atom table, retval: %lx\n", res
);
253 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1
, &testAtom
);
254 ok(!res
, "Unable to find atom in atom table, retval: %lx\n", res
);
255 ok(testAtom
== Atom1
, "Wrong atom found\n");
257 res
= pRtlDeleteAtomFromAtomTable(AtomTable
, Atom1
);
258 ok(res
== STATUS_WAS_LOCKED
, "Unable to delete atom from table, retval: %lx\n", res
);
260 res
= pRtlLookupAtomInAtomTable(AtomTable
, testAtom1
, &testAtom
);
261 ok(!res
, "Able to find deleted atom in table\n");
263 res
= pRtlDestroyAtomTable(AtomTable
);
264 ok(!res
, "Unable to destroy atom table\n");
268 /* Test Adding integer atoms to atom table */
269 static void test_NtIntAtom(void)
272 RTL_ATOM_TABLE AtomTable
;
274 ULONG RefCount
= 0, PinCount
= 0;
280 res
= pRtlCreateAtomTable(37, &AtomTable
);
281 ok(!res
, "Unable to create atom table, %lx\n", res
);
285 /* According to the kernel32 functions, integer atoms are only allowd from
286 * 0x0001 to 0xbfff and not 0xc000 to 0xffff, which is correct */
287 res
= pRtlAddAtomToAtomTable(AtomTable
, (PWSTR
)0, &testAtom
);
288 ok(res
== STATUS_INVALID_PARAMETER
, "Didn't get expected result from adding 0 int atom, retval: %lx\n", res
);
289 for (i
= 1; i
<= 0xbfff; i
++)
291 res
= pRtlAddAtomToAtomTable(AtomTable
, (PWSTR
)i
, &testAtom
);
292 ok(!res
, "Unable to add valid integer atom %i, retval: %lx\n", i
, res
);
295 for (i
= 1; i
<= 0xbfff; i
++)
297 res
= pRtlLookupAtomInAtomTable(AtomTable
, (PWSTR
)i
, &testAtom
);
298 ok(!res
, "Unable to find int atom %i, retval: %lx\n", i
, res
);
301 res
= pRtlPinAtomInAtomTable(AtomTable
, testAtom
);
302 ok(!res
, "Unable to pin int atom %i, retval: %lx\n", i
, res
);
306 for (i
= 0xc000; i
<= 0xffff; i
++)
308 res
= pRtlAddAtomToAtomTable(AtomTable
, (PWSTR
)i
, &testAtom
);
309 ok(res
, "Able to illeageal integer atom %i, retval: %lx\n", i
, res
);
312 res
= pRtlDestroyAtomTable(AtomTable
);
313 ok(!res
, "Unable to destroy atom table, retval: %lx\n", res
);
317 res
= pRtlCreateAtomTable(37, &AtomTable
);
318 ok(!res
, "Unable to create atom table, %lx\n", res
);
321 res
= pRtlLookupAtomInAtomTable(AtomTable
, (PWSTR
)123, &testAtom
);
322 ok(!res
, "Unable to query atom in atom table, retval: %lx\n", res
);
324 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtomInt
, &testAtom
);
325 ok(!res
, "Unable to add int atom to table, retval: %lx\n", res
);
327 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtomIntInv
, &testAtom
);
328 ok(!res
, "Unable to add int atom to table, retval: %lx\n", res
);
330 res
= pRtlAddAtomToAtomTable(AtomTable
, (PWSTR
)123, &testAtom
);
331 ok(!res
, "Unable to add int atom to table, retval: %lx\n", res
);
333 res
= pRtlAddAtomToAtomTable(AtomTable
, (PWSTR
)123, &testAtom
);
334 ok(!res
, "Unable to re-add int atom to table, retval: %lx\n", res
);
337 res
= pRtlQueryAtomInAtomTable(AtomTable
, testAtom
, &RefCount
, &PinCount
, Name
, &Len
);
338 ok(!res
, "Unable to query atom in atom table, retval: %lx\n", res
);
339 ok(PinCount
== 1, "Expected pincount 1 but got %lx\n", PinCount
);
340 ok(RefCount
== 1, "Expected refcount 1 but got %lx\n", RefCount
);
341 ok(!strcmpW(testAtomOTT
, Name
), "Got wrong atom name\n");
342 ok((strlenW(testAtomOTT
) * sizeof(WCHAR
)) == Len
, "Got wrong len %ld\n", Len
);
344 res
= pRtlPinAtomInAtomTable(AtomTable
, testAtom
);
345 ok(!res
, "Unable to pin int atom, retval: %lx\n", res
);
347 res
= pRtlPinAtomInAtomTable(AtomTable
, testAtom
);
348 ok(!res
, "Unable to pin int atom, retval: %lx\n", res
);
350 res
= pRtlQueryAtomInAtomTable(AtomTable
, testAtom
, &RefCount
, &PinCount
, NULL
, NULL
);
351 ok(!res
, "Unable to query atom in atom table, retval: %lx\n", res
);
352 ok(PinCount
== 1, "Expected pincount 1 but got %lx\n", PinCount
);
353 ok(RefCount
== 1, "Expected refcount 1 but got %lx\n", RefCount
);
355 res
= pRtlDestroyAtomTable(AtomTable
);
356 ok(!res
, "Unable to destroy atom table, retval: %lx\n", res
);
360 /* Tests to see how the pincount and refcount actually works */
361 static void test_NtRefPinAtom(void)
363 RTL_ATOM_TABLE AtomTable
;
365 ULONG PinCount
= 0, RefCount
= 0;
369 res
= pRtlCreateAtomTable(37, &AtomTable
);
370 ok(!res
, "Unable to create atom table, %lx\n", res
);
374 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtom1
, &Atom
);
375 ok(!res
, "Unable to add our atom to the atom table, retval: %lx\n", res
);
377 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtom1
, &Atom
);
378 ok(!res
, "Unable to add our atom to the atom table, retval: %lx\n", res
);
380 res
= pRtlAddAtomToAtomTable(AtomTable
, testAtom1
, &Atom
);
381 ok(!res
, "Unable to add our atom to the atom table, retval: %lx\n", res
);
383 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom
, &RefCount
, &PinCount
, NULL
, NULL
);
384 ok(!res
, "Unable to query atom in atom table, retval: %lx\n", res
);
385 ok(PinCount
== 0, "Expected pincount 0 but got %lx\n", PinCount
);
386 ok(RefCount
== 3, "Expected refcount 3 but got %lx\n", RefCount
);
388 res
= pRtlPinAtomInAtomTable(AtomTable
, Atom
);
389 ok(!res
, "Unable to pin atom in atom table, retval: %lx\n", res
);
391 res
= pRtlPinAtomInAtomTable(AtomTable
, Atom
);
392 ok(!res
, "Unable to pin atom in atom table, retval: %lx\n", res
);
394 res
= pRtlPinAtomInAtomTable(AtomTable
, Atom
);
395 ok(!res
, "Unable to pin atom in atom table, retval: %lx\n", res
);
397 res
= pRtlQueryAtomInAtomTable(AtomTable
, Atom
, &RefCount
, &PinCount
, NULL
, NULL
);
398 ok(!res
, "Unable to query atom in atom table, retval: %lx\n", res
);
399 ok(PinCount
== 1, "Expected pincount 1 but got %lx\n", PinCount
);
400 ok(RefCount
== 3, "Expected refcount 3 but got %lx\n", RefCount
);
402 res
= pRtlDestroyAtomTable(AtomTable
);
403 ok(!res
, "Unable to destroy atom table, retval: %lx\n", res
);
410 if (pRtlCreateAtomTable
)