kernel32: In CreateFile, when trying to open the CON special DOS file, force OPEN_EXI...
[wine] / dlls / kernel32 / tests / atom.c
1 /*
2  * Unit tests for atom functions
3  *
4  * Copyright (c) 2002 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "winuser.h"
29
30 #define DOUBLE(x)       (WCHAR)((x<<8)|(x))
31
32 static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
33 static const WCHAR FOOBARW[] = {'F','O','O','B','A','R',0};
34 static const WCHAR _foobarW[] = {'_','f','o','o','b','a','r',0};
35 static const WCHAR integfmt[] = {'#','%','d',0};
36
37 static void do_initA(char* tmp, const char* pattern, int len)
38 {
39     const char* p = pattern;
40
41     while (len--)
42     {
43         *tmp++ = *p++;
44         if (!*p) p = pattern;
45     }
46     *tmp = '\0';
47 }
48
49 static void do_initW(WCHAR* tmp, const char* pattern, int len)
50 {
51     const char* p = pattern;
52
53     while (len--)
54     {
55         *tmp++ = *p++;
56         if (!*p) p = pattern;
57     }
58     *tmp = '\0';
59 }
60
61 static BOOL unicode_OS;
62
63 static void test_add_atom(void)
64 {
65     ATOM atom, w_atom;
66     INT_PTR i;
67
68     SetLastError( 0xdeadbeef );
69     atom = GlobalAddAtomA( "foobar" );
70     ok( atom >= 0xc000, "bad atom id %x\n", atom );
71     ok( GetLastError() == 0xdeadbeef, "GlobalAddAtomA set last error\n" );
72
73     /* Verify that it can be found (or not) appropriately */
74     ok( GlobalFindAtomA( "foobar" ) == atom, "could not find atom foobar\n" );
75     ok( GlobalFindAtomA( "FOOBAR" ) == atom, "could not find atom FOOBAR\n" );
76     ok( !GlobalFindAtomA( "_foobar" ), "found _foobar\n" );
77
78     /* Add the same atom, specifying string as unicode; should
79      * find the first one, not add a new one */
80     SetLastError( 0xdeadbeef );
81     w_atom = GlobalAddAtomW( foobarW );
82     if (w_atom && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
83         unicode_OS = TRUE;
84     else
85         trace("WARNING: Unicode atom APIs are not supported on this platform\n");
86
87     if (unicode_OS)
88     {
89         ok( w_atom == atom, "Unicode atom does not match ASCII\n" );
90         ok( GetLastError() == 0xdeadbeef, "GlobalAddAtomW set last error\n" );
91     }
92
93     /* Verify that it can be found (or not) appropriately via unicode name */
94     if (unicode_OS)
95     {
96         ok( GlobalFindAtomW( foobarW ) == atom, "could not find atom foobar\n" );
97         ok( GlobalFindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR\n" );
98         ok( !GlobalFindAtomW( _foobarW ), "found _foobar\n" );
99     }
100
101     /* Test integer atoms
102      * (0x0001 .. 0xbfff) should be valid;
103      * (0xc000 .. 0xffff) should be invalid */
104
105     SetLastError( 0xdeadbeef );
106     ok( GlobalAddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" );
107     if (unicode_OS)
108     {
109         SetLastError( 0xdeadbeef );
110         ok( GlobalAddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" );
111     }
112
113     SetLastError( 0xdeadbeef );
114     for (i = 1; i <= 0xbfff; i++)
115     {
116         SetLastError( 0xdeadbeef );
117         ok( GlobalAddAtomA((LPCSTR)i) == i && GetLastError() == 0xdeadbeef,
118             "failed to add atom %lx\n", i );
119         if (unicode_OS)
120         {
121             SetLastError( 0xdeadbeef );
122             ok( GlobalAddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef,
123                 "failed to add atom %lx\n", i );
124         }
125     }
126
127     for (i = 0xc000; i <= 0xffff; i++)
128     {
129         ok( !GlobalAddAtomA((LPCSTR)i), "succeeded adding %lx\n", i );
130         if (unicode_OS)
131             ok( !GlobalAddAtomW((LPCWSTR)i), "succeeded adding %lx\n", i );
132     }
133 }
134
135 static void test_get_atom_name(void)
136 {
137     char buf[10];
138     WCHAR bufW[10];
139     int i;
140     UINT len;
141     static const WCHAR resultW[] = {'f','o','o','b','a','r',0,'.','.','.'};
142     char in[257], out[257];
143     WCHAR inW[257], outW[257];
144
145     ATOM atom = GlobalAddAtomA( "foobar" );
146
147     /* Get the name of the atom we added above */
148     memset( buf, '.', sizeof(buf) );
149     len = GlobalGetAtomNameA( atom, buf, 10 );
150     ok( len == strlen("foobar"), "bad length %d\n", len );
151     ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents\n" );
152
153     /* Repeat, unicode-style */
154     if (unicode_OS)
155     {
156         for (i = 0; i < 10; i++) bufW[i] = '.';
157         SetLastError( 0xdeadbeef );
158         len = GlobalGetAtomNameW( atom, bufW, 10 );
159         ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" );
160         ok( len == lstrlenW(foobarW), "bad length %d\n", len );
161         ok( !memcmp( bufW, resultW, 10*sizeof(WCHAR) ), "bad buffer contents\n" );
162     }
163
164     /* Check error code returns */
165     memset(buf, '.', 10);
166     ok( !GlobalGetAtomNameA( atom, buf,  0 ), "succeeded\n" );
167     ok( !memcmp( buf, "..........", 10 ), "should not touch buffer\n" );
168
169     if (unicode_OS)
170     {
171         static const WCHAR sampleW[10] = {'.','.','.','.','.','.','.','.','.','.'};
172
173         for (i = 0; i < 10; i++) bufW[i] = '.';
174         ok( !GlobalGetAtomNameW( atom, bufW, 0 ), "succeeded\n" );
175         ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer\n" );
176     }
177
178     /* Test integer atoms */
179     for (i = 0; i <= 0xbfff; i++)
180     {
181         memset( buf, 'a', 10 );
182         len = GlobalGetAtomNameA( (ATOM)i, buf, 10 );
183         if (i)
184         {
185             char res[20];
186             ok( (len > 1) && (len < 7), "bad length %d\n", len );
187             sprintf( res, "#%d", i );
188             memset( res + strlen(res) + 1, 'a', 10 );
189             ok( !memcmp( res, buf, 10 ), "bad buffer contents %s\n", buf );
190             if (len <= 1 || len >= 7) break;  /* don't bother testing all of them */
191         }
192         else
193             ok( !len, "bad length %d\n", len );
194
195         SetLastError(0xdeadbeef);
196         len = GlobalGetAtomNameA( (ATOM)i, buf, 2);
197         if (!len) /* the NT way */
198         {
199             ok(GetLastError() == (i ? ERROR_MORE_DATA : ERROR_INVALID_PARAMETER) ||
200                GetLastError() == 0xdeadbeef,  /* the Win 9x way */
201                "wrong error conditions %u for %u\n", GetLastError(), i);
202         }
203         else /* the Win 9x way */
204         {
205             ok(GetLastError() == 0xdeadbeef,
206                "wrong error conditions %u for %u\n", GetLastError(), i);
207         }
208     }
209
210     memset( buf, '.', sizeof(buf) );
211     len = GlobalGetAtomNameA( atom, buf, 6 );
212     ok( len == 0 ||
213         len == 5, /* win9x */
214         "bad length %d\n", len );
215     ok( !memcmp( buf, "fooba\0....", 10 ), "bad buffer contents\n");
216     if (unicode_OS)
217     {
218         static const WCHAR resW[] = {'f','o','o','b','a','r','.','.','.','.'};
219         for (len = 0; len < 10; len++) bufW[len] = '.';
220         SetLastError(0xdeadbeef);
221         len = GlobalGetAtomNameW( atom, bufW, 6 );
222         ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" );
223         ok( len == lstrlenW(foobarW), "bad length %d\n", len );
224         ok( !memcmp( bufW, resW, 10*sizeof(WCHAR) ), "bad buffer contents\n" );
225     }
226
227     /* test string limits & overflow */
228     do_initA(in, "abcdefghij", 255);
229     atom = GlobalAddAtomA(in);
230     ok(atom, "couldn't add atom for %s\n", in);
231     len = GlobalGetAtomNameA(atom, out, sizeof(out));
232     ok(len == 255, "length mismatch (%u instead of 255)\n", len);
233     for (i = 0; i < 255; i++)
234     {
235         ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
236     }
237     ok(out[255] == '\0', "wrong end of string\n");
238     memset(out, '.', sizeof(out));
239     SetLastError(0xdeadbeef);
240     len = GlobalGetAtomNameA(atom, out, 10);
241     if (!len) /* the NT way */
242     {
243         ok(GetLastError() == ERROR_MORE_DATA, "wrong error code (%u instead of %u)\n", GetLastError(), ERROR_MORE_DATA);
244     }
245     else /* the Win9x way */
246     {
247         ok(GetLastError() == 0xdeadbeef, "wrong error code (%u instead of %u)\n", GetLastError(), 0xdeadbeef);
248     }
249     for (i = 0; i < 9; i++)
250     {
251         ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
252     }
253     ok(out[9] == '\0', "wrong end of string\n");
254     ok(out[10] == '.', "wrote after end of buf\n");
255     do_initA(in, "abcdefghij", 256);
256     atom = GlobalAddAtomA(in);
257     ok(!atom, "succeeded\n");
258     if (unicode_OS)
259     {
260         /* test integral atoms */
261         for (i = 0; i <= 0xbfff; i++)
262         {
263             memset(outW, 'a', sizeof(outW));
264             len = GlobalGetAtomNameW( (ATOM)i, outW, 10 );
265             if (i)
266             {
267                 WCHAR res[20];
268                 
269                 ok( (len > 1) && (len < 7), "bad length %d\n", len );
270                 wsprintfW( res, integfmt, i );
271                 memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR));
272                 ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i );
273                 if (len <= 1 || len >= 7) break;  /* don't bother testing all of them */
274             }
275             else
276                 ok( !len, "bad length %d\n", len );
277
278             memset(outW, '.', sizeof(outW));
279             SetLastError(0xdeadbeef);
280             len = GlobalGetAtomNameW( (ATOM)i, outW, 1);
281             if (i)
282             {
283                 /* len == 0 with ERROR_MORE_DATA is on NT3.51 */
284                 ok(len == 1 || (len == 0 && GetLastError() == ERROR_MORE_DATA),
285                          "0x%04x: got %u with %d (excepted '1' or '0' with "
286                          "ERROR_MORE_DATA)\n", i, len, GetLastError());
287                 ok(outW[1] == DOUBLE('.'), "buffer overwrite\n");
288             }
289             else ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "0 badly handled\n");
290         }
291
292         do_initW(inW, "abcdefghij", 255);
293         atom = GlobalAddAtomW(inW);
294         ok(atom, "couldn't add atom for %s\n", in);
295         len = GlobalGetAtomNameW(atom, outW, sizeof(outW)/sizeof(outW[0]));
296         ok(len == 255, "length mismatch (%u instead of 255)\n", len);
297         for (i = 0; i < 255; i++)
298         {
299             ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
300         }
301         ok(outW[255] == '\0', "wrong end of string\n");
302         memset(outW, '.', sizeof(outW));
303         len = GlobalGetAtomNameW(atom, outW, 10);
304         ok(len == 10, "succeeded\n");
305         for (i = 0; i < 10; i++)
306         {
307             ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
308         }
309         ok(outW[10] == DOUBLE('.'), "wrote after end of buf\n");
310         do_initW(inW, "abcdefghij", 256);
311         atom = GlobalAddAtomW(inW);
312         ok(!atom, "succeeded\n");
313         ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error code\n");
314     }
315 }
316
317 static void test_error_handling(void)
318 {
319     char buffer[260];
320     WCHAR bufferW[260];
321     int i;
322
323     memset( buffer, 'a', 256 );
324     buffer[256] = 0;
325     ok( !GlobalAddAtomA(buffer), "add succeeded\n" );
326     ok( !GlobalFindAtomA(buffer), "find succeeded\n" );
327
328     if (unicode_OS)
329     {
330         for (i = 0; i < 256; i++) bufferW[i] = 'b';
331         bufferW[256] = 0;
332         ok( !GlobalAddAtomW(bufferW), "add succeeded\n" );
333         ok( !GlobalFindAtomW(bufferW), "find succeeded\n" );
334     }
335 }
336
337 static void test_local_add_atom(void)
338 {
339     ATOM atom, w_atom;
340     INT_PTR i;
341
342     SetLastError( 0xdeadbeef );
343     atom = AddAtomA( "foobar" );
344     ok( atom >= 0xc000, "bad atom id %x\n", atom );
345     ok( GetLastError() == 0xdeadbeef, "AddAtomA set last error\n" );
346
347     /* Verify that it can be found (or not) appropriately */
348     ok( FindAtomA( "foobar" ) == atom, "could not find atom foobar\n" );
349     ok( FindAtomA( "FOOBAR" ) == atom, "could not find atom FOOBAR\n" );
350     ok( !FindAtomA( "_foobar" ), "found _foobar\n" );
351
352     /* Add the same atom, specifying string as unicode; should
353      * find the first one, not add a new one */
354     SetLastError( 0xdeadbeef );
355     w_atom = AddAtomW( foobarW );
356     if (w_atom && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
357         unicode_OS = TRUE;
358     else
359         trace("WARNING: Unicode atom APIs are not supported on this platform\n");
360
361     if (unicode_OS)
362     {
363         ok( w_atom == atom, "Unicode atom does not match ASCII\n" );
364         ok( GetLastError() == 0xdeadbeef, "AddAtomW set last error\n" );
365     }
366
367     /* Verify that it can be found (or not) appropriately via unicode name */
368     if (unicode_OS)
369     {
370         ok( FindAtomW( foobarW ) == atom, "could not find atom foobar\n" );
371         ok( FindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR\n" );
372         ok( !FindAtomW( _foobarW ), "found _foobar\n" );
373     }
374
375     /* Test integer atoms
376      * (0x0001 .. 0xbfff) should be valid;
377      * (0xc000 .. 0xffff) should be invalid */
378
379     SetLastError( 0xdeadbeef );
380     ok( AddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" );
381     if (unicode_OS)
382     {
383         SetLastError( 0xdeadbeef );
384         ok( AddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" );
385     }
386
387     SetLastError( 0xdeadbeef );
388     for (i = 1; i <= 0xbfff; i++)
389     {
390         SetLastError( 0xdeadbeef );
391         ok( AddAtomA((LPCSTR)i) == i && GetLastError() == 0xdeadbeef,
392             "failed to add atom %lx\n", i );
393         if (unicode_OS)
394         {
395             SetLastError( 0xdeadbeef );
396             ok( AddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef,
397                 "failed to add atom %lx\n", i );
398         }
399     }
400
401     for (i = 0xc000; i <= 0xffff; i++)
402     {
403         ok( !AddAtomA((LPCSTR)i), "succeeded adding %lx\n", i );
404         if (unicode_OS)
405             ok( !AddAtomW((LPCWSTR)i), "succeeded adding %lx\n", i );
406     }
407 }
408
409 static void test_local_get_atom_name(void)
410 {
411     char buf[10], in[257], out[257];
412     WCHAR bufW[10], inW[257], outW[257];
413     int i;
414     UINT len;
415     static const WCHAR resultW[] = {'f','o','o','b','a','r',0,'.','.','.'};
416
417     ATOM atom = AddAtomA( "foobar" );
418
419     /* Get the name of the atom we added above */
420     memset( buf, '.', sizeof(buf) );
421     len = GetAtomNameA( atom, buf, 10 );
422     ok( len == strlen("foobar"), "bad length %d\n", len );
423     ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents\n" );
424
425     /* Repeat, unicode-style */
426     if (unicode_OS)
427     {
428         for (i = 0; i < 10; i++) bufW[i] = '.';
429         SetLastError( 0xdeadbeef );
430         len = GetAtomNameW( atom, bufW, 10 );
431         ok( len && GetLastError() == 0xdeadbeef, "GetAtomNameW failed\n" );
432         ok( len == lstrlenW(foobarW), "bad length %d\n", len );
433         ok( !memcmp( bufW, resultW, 10*sizeof(WCHAR) ), "bad buffer contents\n" );
434     }
435
436     /* Get the name of the atom we added above */
437     memset( buf, '.', sizeof(buf) );
438     len = GetAtomNameA( atom, buf, 6 );
439     ok( len == 5, "bad length %d\n", len );
440     ok( !memcmp( buf, "fooba\0....", 10 ), "bad buffer contents\n" );
441  
442     /* Repeat, unicode-style */
443     if (unicode_OS)
444     {
445         WCHAR resW[] = {'f','o','o','b','a','\0','.','.','.','.'};
446         for (i = 0; i < 10; i++) bufW[i] = '.';
447         SetLastError( 0xdeadbeef );
448         len = GetAtomNameW( atom, bufW, 6 );
449         ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" );
450         ok( len == 5, "bad length %d\n", len );
451         ok( !memcmp( bufW, resW, 10*sizeof(WCHAR) ), "bad buffer contents\n" );
452     }
453  
454     /* Check error code returns */
455     memset(buf, '.', 10);
456     ok( !GetAtomNameA( atom, buf,  0 ), "succeeded\n" );
457     ok( !memcmp( buf, "..........", 10 ), "should not touch buffer\n" );
458
459     if (unicode_OS)
460     {
461         static const WCHAR sampleW[10] = {'.','.','.','.','.','.','.','.','.','.'};
462
463         for (i = 0; i < 10; i++) bufW[i] = '.';
464         ok( !GetAtomNameW( atom, bufW, 0 ), "succeeded\n" );
465         ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer\n" );
466     }
467
468     /* Test integer atoms */
469     for (i = 0; i <= 0xbfff; i++)
470     {
471         memset( buf, 'a', 10 );
472         len = GetAtomNameA( (ATOM)i, buf, 10 );
473         if (i)
474         {
475             char res[20];
476             ok( (len > 1) && (len < 7), "bad length %d for %s\n", len, buf );
477             sprintf( res, "#%d", i );
478             memset( res + strlen(res) + 1, 'a', 10 );
479             ok( !memcmp( res, buf, 10 ), "bad buffer contents %s\n", buf );
480         }
481         else
482             ok( !len, "bad length %d\n", len );
483
484         len = GetAtomNameA( (ATOM)i, buf, 1);
485         ok(!len, "succeed with %u for %u\n", len, i);
486
487         /* ERROR_MORE_DATA is on nt3.51 sp5 */
488         if (i)
489             ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
490                GetLastError() == ERROR_MORE_DATA ||
491                GetLastError() == 0xdeadbeef, /* the Win 9x way */
492                "wrong error conditions %u for %u\n", GetLastError(), i);
493         else
494             ok(GetLastError() == ERROR_INVALID_PARAMETER ||
495                GetLastError() == ERROR_MORE_DATA ||
496                GetLastError() == 0xdeadbeef, /* the Win 9x way */
497                "wrong error conditions %u for %u\n", GetLastError(), i);
498     }
499     /* test string limits & overflow */
500     do_initA(in, "abcdefghij", 255);
501     atom = AddAtomA(in);
502     ok(atom, "couldn't add atom for %s\n", in);
503     len = GetAtomNameA(atom, out, sizeof(out));
504     ok(len == 255, "length mismatch (%u instead of 255)\n", len);
505     for (i = 0; i < 255; i++)
506     {
507         ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
508     }
509     ok(out[255] == '\0', "wrong end of string\n");
510     memset(out, '.', sizeof(out));
511     len = GetAtomNameA(atom, out, 10);
512     ok(len == 9, "succeeded %d\n", len);
513     for (i = 0; i < 9; i++)
514     {
515         ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
516     }
517     ok(out[9] == '\0', "wrong end of string\n");
518     ok(out[10] == '.', "buffer overwrite\n");
519     do_initA(in, "abcdefghij", 256);
520     atom = AddAtomA(in);
521     ok(!atom, "succeeded\n");
522
523     /* ERROR_MORE_DATA is on nt3.51 sp5 */
524     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
525        GetLastError() == ERROR_MORE_DATA ||
526        GetLastError() == 0xdeadbeef, /* the Win 9x way */
527        "wrong error code (%u)\n", GetLastError());
528
529     if (unicode_OS)
530     {
531         /* test integral atoms */
532         for (i = 0; i <= 0xbfff; i++)
533         {
534             memset(outW, 'a', sizeof(outW));
535             len = GetAtomNameW( (ATOM)i, outW, 10 );
536             if (i)
537             {
538                 WCHAR res[20];
539                 
540                 ok( (len > 1) && (len < 7), "bad length %d\n", len );
541                 wsprintfW( res, integfmt, i );
542                 memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR));
543                 ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i );
544             }
545             else
546                 ok( !len, "bad length %d\n", len );
547
548             len = GetAtomNameW( (ATOM)i, outW, 1);
549             ok(!len, "succeed with %u for %u\n", len, i);
550
551             /* ERROR_MORE_DATA is on nt3.51 sp5 */
552             ok(GetLastError() == ERROR_MORE_DATA ||
553                GetLastError() == (i ? ERROR_INSUFFICIENT_BUFFER : ERROR_INVALID_PARAMETER),
554                "wrong error conditions %u for %u\n", GetLastError(), i);
555         }
556         do_initW(inW, "abcdefghij", 255);
557         atom = AddAtomW(inW);
558         ok(atom, "couldn't add atom for %s\n", in);
559         len = GetAtomNameW(atom, outW, sizeof(outW)/sizeof(outW[0]));
560         ok(len == 255, "length mismatch (%u instead of 255)\n", len);
561         for (i = 0; i < 255; i++)
562         {
563             ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
564         }
565         ok(outW[255] == '\0', "wrong end of string\n");
566         memset(outW, '.', sizeof(outW));
567         len = GetAtomNameW(atom, outW, 10);
568         ok(len == 9, "succeeded %d\n", len);
569         for (i = 0; i < 9; i++)
570         {
571             ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
572         }
573         ok(outW[9] == '\0', "wrong end of string\n");
574         ok(outW[10] == DOUBLE('.'), "buffer overwrite\n");
575         do_initW(inW, "abcdefghij", 256);
576         atom = AddAtomW(inW);
577         ok(!atom, "succeeded\n");
578
579         /* ERROR_MORE_DATA is on nt3.51 sp5 */
580         ok(GetLastError() == ERROR_INVALID_PARAMETER ||
581            GetLastError() == ERROR_MORE_DATA,
582            "wrong error code (%u)\n", GetLastError());
583     }
584 }
585
586 static void test_local_error_handling(void)
587 {
588     char buffer[260];
589     WCHAR bufferW[260];
590     int i;
591
592     memset( buffer, 'a', 256 );
593     buffer[256] = 0;
594     ok( !AddAtomA(buffer), "add succeeded\n" );
595     ok( !FindAtomA(buffer), "find succeeded\n" );
596
597     if (unicode_OS)
598     {
599         for (i = 0; i < 256; i++) bufferW[i] = 'b';
600         bufferW[256] = 0;
601         ok( !AddAtomW(bufferW), "add succeeded\n" );
602         ok( !FindAtomW(bufferW), "find succeeded\n" );
603     }
604 }
605
606 START_TEST(atom)
607 {
608     /* Global atom table seems to be available to GUI apps only in
609        Win7, so let's turn this app into a GUI app */
610     GetDesktopWindow();
611
612     test_add_atom();
613     test_get_atom_name();
614     test_error_handling();
615     test_local_add_atom();
616     test_local_get_atom_name();
617     test_local_error_handling();
618 }