revert 17709 for it break streach for windows mode. That why I did only got black...
[reactos.git] / reactos / regtests / winetests / ntdll / 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 #define _WIN32_WINNT 0x0501
25
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include "ntstatus.h"
29 #define WIN32_NO_STATUS
30 #include "windows.h"
31 #include "wine/test.h"
32 #include "wine/unicode.h"
33 #include "winternl.h"
34
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);
45
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};
50
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};
53
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};
57
58 static void InitFunctionPtr(void)
59 {
60 hntdll = LoadLibraryA("ntdll.dll");
61 ok(hntdll != 0, "Unable to load ntdll.dll\n");
62
63 if (hntdll)
64 {
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");
73 }
74 }
75
76 static DWORD RtlAtomTestThread(LPVOID Table)
77 {
78 RTL_ATOM_TABLE AtomTable = *(PRTL_ATOM_TABLE)Table;
79 RTL_ATOM Atom;
80 NTSTATUS res;
81 ULONG RefCount = 0, PinCount = 0, Len = 0;
82 WCHAR Name[64];
83
84 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &Atom);
85 ok(!res, "Unable to find atom from another thread, retval: %lx\n", res);
86
87 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &Atom);
88 ok(!res, "Unable to lookup pinned atom in table, retval: %lx\n", res);
89
90 res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name, &Len);
91 ok(res == STATUS_BUFFER_TOO_SMALL, "We got wrong retval: %lx\n", res);
92
93 Len = 64;
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);
100
101 Len = 64;
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);
106
107 res = pRtlPinAtomInAtomTable(AtomTable, Atom);
108 ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
109
110 return 0;
111 }
112
113 static void test_NtAtom(void)
114 {
115 RTL_ATOM_TABLE AtomTable = NULL;
116 NTSTATUS res;
117 RTL_ATOM Atom1, Atom2, Atom3, testEAtom, testAtom;
118 HANDLE testThread;
119 ULONG RefCount = 0, PinCount = 0, Len = 0;
120 WCHAR Name[64];
121
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");
126
127 if (!res)
128 {
129 res = pRtlDestroyAtomTable(AtomTable);
130 ok(!res, "We could create the atom table, but we couldn't destroy it! retval: %lx\n", res);
131 }
132
133 AtomTable = NULL;
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);
136 if (!res)
137 {
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);
140
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");
144
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");
148
149 res = pRtlAddAtomToAtomTable(AtomTable, EmptyAtom, &testEAtom);
150 ok(res == STATUS_OBJECT_NAME_INVALID, "Got wrong retval, retval: %lx\n", res);
151
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");
155
156 res = pRtlAddAtomToAtomTable(AtomTable, testAtom2, &Atom2);
157 ok(!res, "Unable to add other legitimate atom to table, retval: %lx\n", res);
158
159 res = pRtlPinAtomInAtomTable(AtomTable, Atom2);
160 ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
161
162 testThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RtlAtomTestThread, &AtomTable, 0, NULL);
163 WaitForSingleObject(testThread, INFINITE);
164
165 Len = 64;
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);
172
173 res = pRtlEmptyAtomTable(AtomTable, FALSE);
174 ok(!res, "Unable to empty atom table, retval %lx\n", res);
175
176 Len = 64;
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);
183
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");
187
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);
190
191 res = pRtlAddAtomToAtomTable(AtomTable, testAtom3, &Atom3);
192 ok(!res, "Unable to add atom to table, retval: %lx\n", res);
193
194 res = pRtlEmptyAtomTable(AtomTable, TRUE);
195 ok(!res, "Unable to empty atom table, retval: %lx\n", res);
196
197 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
198 ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "The pinned atom should be removed, retval: %lx\n", res);
199
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);
202
203 res = pRtlDestroyAtomTable(AtomTable);
204 ok(!res, "Can't destroy atom table, retval: %lx\n", res);
205 }
206
207 AtomTable = NULL;
208 res = pRtlCreateAtomTable(37, &AtomTable);
209 ok(!res, "Unable to create atom table, retval: %lx\n", res);
210
211 if (!res)
212 {
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);
215
216 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
217 ok(!res, "Unable to add atom to atom table, retval %lx\n", res);
218
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);
222
223 res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
224 ok(!res, "Unable to delete atom from table, retval: %lx\n", res);
225
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);
228
229 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
230 ok(!res, "Unable to add atom to atom table, retval: %lx\n", res);
231
232 Len = 0;
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);
236
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));
241
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");
249
250 res = pRtlPinAtomInAtomTable(AtomTable, Atom1);
251 ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
252
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");
256
257 res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
258 ok(res == STATUS_WAS_LOCKED, "Unable to delete atom from table, retval: %lx\n", res);
259
260 res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
261 ok(!res, "Able to find deleted atom in table\n");
262
263 res = pRtlDestroyAtomTable(AtomTable);
264 ok(!res, "Unable to destroy atom table\n");
265 }
266 }
267
268 /* Test Adding integer atoms to atom table */
269 static void test_NtIntAtom(void)
270 {
271 NTSTATUS res;
272 RTL_ATOM_TABLE AtomTable;
273 RTL_ATOM testAtom;
274 ULONG RefCount = 0, PinCount = 0;
275 int i;
276 WCHAR Name[64];
277 ULONG Len;
278
279 AtomTable = NULL;
280 res = pRtlCreateAtomTable(37, &AtomTable);
281 ok(!res, "Unable to create atom table, %lx\n", res);
282
283 if (!res)
284 {
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++)
290 {
291 res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)i, &testAtom);
292 ok(!res, "Unable to add valid integer atom %i, retval: %lx\n", i, res);
293 }
294
295 for (i = 1; i <= 0xbfff; i++)
296 {
297 res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)i, &testAtom);
298 ok(!res, "Unable to find int atom %i, retval: %lx\n", i, res);
299 if (!res)
300 {
301 res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
302 ok(!res, "Unable to pin int atom %i, retval: %lx\n", i, res);
303 }
304 }
305
306 for (i = 0xc000; i <= 0xffff; i++)
307 {
308 res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)i, &testAtom);
309 ok(res, "Able to illeageal integer atom %i, retval: %lx\n", i, res);
310 }
311
312 res = pRtlDestroyAtomTable(AtomTable);
313 ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
314 }
315
316 AtomTable = NULL;
317 res = pRtlCreateAtomTable(37, &AtomTable);
318 ok(!res, "Unable to create atom table, %lx\n", res);
319 if (!res)
320 {
321 res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)123, &testAtom);
322 ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
323
324 res = pRtlAddAtomToAtomTable(AtomTable, testAtomInt, &testAtom);
325 ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
326
327 res = pRtlAddAtomToAtomTable(AtomTable, testAtomIntInv, &testAtom);
328 ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
329
330 res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
331 ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
332
333 res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
334 ok(!res, "Unable to re-add int atom to table, retval: %lx\n", res);
335
336 Len = 64;
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);
343
344 res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
345 ok(!res, "Unable to pin int atom, retval: %lx\n", res);
346
347 res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
348 ok(!res, "Unable to pin int atom, retval: %lx\n", res);
349
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);
354
355 res = pRtlDestroyAtomTable(AtomTable);
356 ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
357 }
358 }
359
360 /* Tests to see how the pincount and refcount actually works */
361 static void test_NtRefPinAtom(void)
362 {
363 RTL_ATOM_TABLE AtomTable;
364 RTL_ATOM Atom;
365 ULONG PinCount = 0, RefCount = 0;
366 NTSTATUS res;
367
368 AtomTable = NULL;
369 res = pRtlCreateAtomTable(37, &AtomTable);
370 ok(!res, "Unable to create atom table, %lx\n", res);
371
372 if (!res)
373 {
374 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
375 ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
376
377 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
378 ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
379
380 res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
381 ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
382
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);
387
388 res = pRtlPinAtomInAtomTable(AtomTable, Atom);
389 ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
390
391 res = pRtlPinAtomInAtomTable(AtomTable, Atom);
392 ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
393
394 res = pRtlPinAtomInAtomTable(AtomTable, Atom);
395 ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
396
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);
401
402 res = pRtlDestroyAtomTable(AtomTable);
403 ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
404 }
405 }
406
407 START_TEST(atom)
408 {
409 InitFunctionPtr();
410 if (pRtlCreateAtomTable)
411 {
412 test_NtAtom();
413 test_NtIntAtom();
414 test_NtRefPinAtom();
415 }
416 }