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[] = {'.','.','.','.','.','.','.','.','.','.'};
172 
173         for (i = 0; i < 10; i++) bufW[i] = '.';
174         ok( !GlobalGetAtomNameW( atom, bufW, 0 ), "succeeded\n" );
175         ok( !memcmp( bufW, sampleW, sizeof(sampleW) ), "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         ok(!len, "bad length %d\n", len);
198 	ok(GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INVALID_PARAMETER,
199             "wrong error conditions %u for %u\n", GetLastError(), i);
200     }
201 
202     memset( buf, '.', sizeof(buf) );
203     len = GlobalGetAtomNameA( atom, buf, 6 );
204     ok( len == 0, "bad length %d\n", len );
205     ok( !memcmp( buf, "fooba\0....", 10 ), "bad buffer contents\n");
206     if (unicode_OS)
207     {
208         static const WCHAR resW[] = {'f','o','o','b','a','r','.','.','.','.'};
209         for (len = 0; len < 10; len++) bufW[len] = '.';
210 	SetLastError(0xdeadbeef);
211         len = GlobalGetAtomNameW( atom, bufW, 6 );
212         ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" );
213         ok( len == lstrlenW(foobarW), "bad length %d\n", len );
214         ok( !memcmp( bufW, resW, 10*sizeof(WCHAR) ), "bad buffer contents\n" );
215     }
216 
217     /* test string limits & overflow */
218     do_initA(in, "abcdefghij", 255);
219     atom = GlobalAddAtomA(in);
220     ok(atom, "couldn't add atom for %s\n", in);
221     len = GlobalGetAtomNameA(atom, out, sizeof(out));
222     ok(len == 255, "length mismatch (%u instead of 255)\n", len);
223     for (i = 0; i < 255; i++)
224     {
225         ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
226     }
227     ok(out[255] == '\0', "wrong end of string\n");
228     memset(out, '.', sizeof(out));
229     SetLastError(0xdeadbeef);
230     len = GlobalGetAtomNameA(atom, out, 10);
231     ok(!len, "bad length %d\n", len);
232     ok(GetLastError() == ERROR_MORE_DATA, "wrong error code (%u instead of %u)\n", GetLastError(), ERROR_MORE_DATA);
233     for (i = 0; i < 9; 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[9] == '\0', "wrong end of string\n");
238     ok(out[10] == '.', "wrote after end of buf\n");
239     do_initA(in, "abcdefghij", 256);
240     atom = GlobalAddAtomA(in);
241     ok(!atom, "succeeded\n");
242     if (unicode_OS)
243     {
244         /* test integral atoms */
245         for (i = 0; i <= 0xbfff; i++)
246         {
247             memset(outW, 'a', sizeof(outW));
248             len = GlobalGetAtomNameW( (ATOM)i, outW, 10 );
249             if (i)
250             {
251                 WCHAR res[20];
252 
253                 ok( (len > 1) && (len < 7), "bad length %d\n", len );
254                 wsprintfW( res, integfmt, i );
255                 memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR));
256                 ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i );
257                 if (len <= 1 || len >= 7) break;  /* don't bother testing all of them */
258             }
259             else
260                 ok( !len, "bad length %d\n", len );
261 
262             memset(outW, '.', sizeof(outW));
263             SetLastError(0xdeadbeef);
264             len = GlobalGetAtomNameW( (ATOM)i, outW, 1);
265             if (i)
266             {
267                 /* len == 0 with ERROR_MORE_DATA is on NT3.51 */
268                 ok(len == 1 || (len == 0 && GetLastError() == ERROR_MORE_DATA),
269                          "0x%04x: got %u with %d (expected '1' or '0' with "
270                          "ERROR_MORE_DATA)\n", i, len, GetLastError());
271                 ok(outW[1] == DOUBLE('.'), "buffer overwrite\n");
272             }
273             else ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "0 badly handled\n");
274         }
275 
276         do_initW(inW, "abcdefghij", 255);
277         atom = GlobalAddAtomW(inW);
278         ok(atom, "couldn't add atom for %s\n", in);
279         len = GlobalGetAtomNameW(atom, outW, sizeof(outW)/sizeof(outW[0]));
280         ok(len == 255, "length mismatch (%u instead of 255)\n", len);
281         for (i = 0; i < 255; i++)
282         {
283             ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
284         }
285         ok(outW[255] == '\0', "wrong end of string\n");
286         memset(outW, '.', sizeof(outW));
287         len = GlobalGetAtomNameW(atom, outW, 10);
288         ok(len == 10, "succeeded\n");
289         for (i = 0; i < 10; i++)
290         {
291             ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
292         }
293         ok(outW[10] == DOUBLE('.'), "wrote after end of buf\n");
294         do_initW(inW, "abcdefghij", 256);
295         atom = GlobalAddAtomW(inW);
296         ok(!atom, "succeeded\n");
297         ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error code\n");
298     }
299 }
300 
301 static void test_error_handling(void)
302 {
303     char buffer[260];
304     WCHAR bufferW[260];
305     int i;
306 
307     memset( buffer, 'a', 256 );
308     buffer[256] = 0;
309     ok( !GlobalAddAtomA(buffer), "add succeeded\n" );
310     ok( !GlobalFindAtomA(buffer), "find succeeded\n" );
311 
312     if (unicode_OS)
313     {
314         for (i = 0; i < 256; i++) bufferW[i] = 'b';
315         bufferW[256] = 0;
316         ok( !GlobalAddAtomW(bufferW), "add succeeded\n" );
317         ok( !GlobalFindAtomW(bufferW), "find succeeded\n" );
318     }
319 }
320 
321 static void test_local_add_atom(void)
322 {
323     ATOM atom, w_atom;
324     INT_PTR i;
325 
326     SetLastError( 0xdeadbeef );
327     atom = AddAtomA( "foobar" );
328     ok( atom >= 0xc000, "bad atom id %x\n", atom );
329     ok( GetLastError() == 0xdeadbeef, "AddAtomA set last error\n" );
330 
331     /* Verify that it can be found (or not) appropriately */
332     ok( FindAtomA( "foobar" ) == atom, "could not find atom foobar\n" );
333     ok( FindAtomA( "FOOBAR" ) == atom, "could not find atom FOOBAR\n" );
334     ok( !FindAtomA( "_foobar" ), "found _foobar\n" );
335 
336     /* Add the same atom, specifying string as unicode; should
337      * find the first one, not add a new one */
338     SetLastError( 0xdeadbeef );
339     w_atom = AddAtomW( foobarW );
340     if (w_atom && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
341         unicode_OS = TRUE;
342     else
343         trace("WARNING: Unicode atom APIs are not supported on this platform\n");
344 
345     if (unicode_OS)
346     {
347         ok( w_atom == atom, "Unicode atom does not match ASCII\n" );
348         ok( GetLastError() == 0xdeadbeef, "AddAtomW set last error\n" );
349     }
350 
351     /* Verify that it can be found (or not) appropriately via unicode name */
352     if (unicode_OS)
353     {
354         ok( FindAtomW( foobarW ) == atom, "could not find atom foobar\n" );
355         ok( FindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR\n" );
356         ok( !FindAtomW( _foobarW ), "found _foobar\n" );
357     }
358 
359     /* Test integer atoms
360      * (0x0001 .. 0xbfff) should be valid;
361      * (0xc000 .. 0xffff) should be invalid */
362 
363     SetLastError( 0xdeadbeef );
364     ok( AddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" );
365     if (unicode_OS)
366     {
367         SetLastError( 0xdeadbeef );
368         ok( AddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" );
369     }
370 
371     SetLastError( 0xdeadbeef );
372     for (i = 1; i <= 0xbfff; i++)
373     {
374         SetLastError( 0xdeadbeef );
375         ok( AddAtomA((LPCSTR)i) == i && GetLastError() == 0xdeadbeef,
376             "failed to add atom %lx\n", i );
377         if (unicode_OS)
378         {
379             SetLastError( 0xdeadbeef );
380             ok( AddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef,
381                 "failed to add atom %lx\n", i );
382         }
383     }
384 
385     for (i = 0xc000; i <= 0xffff; i++)
386     {
387         ok( !AddAtomA((LPCSTR)i), "succeeded adding %lx\n", i );
388         if (unicode_OS)
389             ok( !AddAtomW((LPCWSTR)i), "succeeded adding %lx\n", i );
390     }
391 }
392 
393 static void test_local_get_atom_name(void)
394 {
395     char buf[10], in[257], out[257];
396     WCHAR bufW[10], inW[257], outW[257];
397     int i;
398     UINT len;
399     static const WCHAR resultW[] = {'f','o','o','b','a','r',0,'.','.','.'};
400 
401     ATOM atom = AddAtomA( "foobar" );
402 
403     /* Get the name of the atom we added above */
404     memset( buf, '.', sizeof(buf) );
405     len = GetAtomNameA( atom, buf, 10 );
406     ok( len == strlen("foobar"), "bad length %d\n", len );
407     ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents\n" );
408 
409     /* Repeat, unicode-style */
410     if (unicode_OS)
411     {
412         for (i = 0; i < 10; i++) bufW[i] = '.';
413         SetLastError( 0xdeadbeef );
414         len = GetAtomNameW( atom, bufW, 10 );
415         ok( len && GetLastError() == 0xdeadbeef, "GetAtomNameW failed\n" );
416         ok( len == lstrlenW(foobarW), "bad length %d\n", len );
417         ok( !memcmp( bufW, resultW, 10*sizeof(WCHAR) ), "bad buffer contents\n" );
418     }
419 
420     /* Get the name of the atom we added above */
421     memset( buf, '.', sizeof(buf) );
422     len = GetAtomNameA( atom, buf, 6 );
423     ok( len == 5, "bad length %d\n", len );
424     ok( !memcmp( buf, "fooba\0....", 10 ), "bad buffer contents\n" );
425 
426     /* Repeat, unicode-style */
427     if (unicode_OS)
428     {
429         WCHAR resW[] = {'f','o','o','b','a','\0','.','.','.','.'};
430         for (i = 0; i < 10; i++) bufW[i] = '.';
431         SetLastError( 0xdeadbeef );
432         len = GetAtomNameW( atom, bufW, 6 );
433         ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" );
434         ok( len == 5, "bad length %d\n", len );
435         ok( !memcmp( bufW, resW, 10*sizeof(WCHAR) ), "bad buffer contents\n" );
436     }
437 
438     /* Check error code returns */
439     memset(buf, '.', 10);
440     ok( !GetAtomNameA( atom, buf,  0 ), "succeeded\n" );
441     ok( !memcmp( buf, "..........", 10 ), "should not touch buffer\n" );
442 
443     if (unicode_OS)
444     {
445         static const WCHAR sampleW[] = {'.','.','.','.','.','.','.','.','.','.'};
446 
447         for (i = 0; i < 10; i++) bufW[i] = '.';
448         ok( !GetAtomNameW( atom, bufW, 0 ), "succeeded\n" );
449         ok( !memcmp( bufW, sampleW, sizeof(sampleW) ), "should not touch buffer\n" );
450     }
451 
452     /* Test integer atoms */
453     for (i = 0; i <= 0xbfff; i++)
454     {
455         memset( buf, 'a', 10 );
456         len = GetAtomNameA( (ATOM)i, buf, 10 );
457         if (i)
458         {
459             char res[20];
460             ok( (len > 1) && (len < 7), "bad length %d for %s\n", len, buf );
461             sprintf( res, "#%d", i );
462             memset( res + strlen(res) + 1, 'a', 10 );
463             ok( !memcmp( res, buf, 10 ), "bad buffer contents %s\n", buf );
464         }
465         else
466             ok( !len, "bad length %d\n", len );
467 
468         len = GetAtomNameA( (ATOM)i, buf, 1);
469         ok(!len, "succeed with %u for %u\n", len, i);
470 
471         /* ERROR_MORE_DATA is on nt3.51 sp5 */
472         if (i)
473             ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
474                GetLastError() == ERROR_MORE_DATA,
475                "wrong error conditions %u for %u\n", GetLastError(), i);
476         else
477             ok(GetLastError() == ERROR_INVALID_PARAMETER ||
478                GetLastError() == ERROR_MORE_DATA,
479                "wrong error conditions %u for %u\n", GetLastError(), i);
480     }
481     /* test string limits & overflow */
482     do_initA(in, "abcdefghij", 255);
483     atom = AddAtomA(in);
484     ok(atom, "couldn't add atom for %s\n", in);
485     len = GetAtomNameA(atom, out, sizeof(out));
486     ok(len == 255, "length mismatch (%u instead of 255)\n", len);
487     for (i = 0; i < 255; i++)
488     {
489         ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
490     }
491     ok(out[255] == '\0', "wrong end of string\n");
492     memset(out, '.', sizeof(out));
493     len = GetAtomNameA(atom, out, 10);
494     ok(len == 9, "succeeded %d\n", len);
495     for (i = 0; i < 9; i++)
496     {
497         ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
498     }
499     ok(out[9] == '\0', "wrong end of string\n");
500     ok(out[10] == '.', "buffer overwrite\n");
501     do_initA(in, "abcdefghij", 256);
502     atom = AddAtomA(in);
503     ok(!atom, "succeeded\n");
504 
505     /* ERROR_MORE_DATA is on nt3.51 sp5 */
506     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
507        GetLastError() == ERROR_MORE_DATA,
508        "wrong error code (%u)\n", GetLastError());
509 
510     if (unicode_OS)
511     {
512         /* test integral atoms */
513         for (i = 0; i <= 0xbfff; i++)
514         {
515             memset(outW, 'a', sizeof(outW));
516             len = GetAtomNameW( (ATOM)i, outW, 10 );
517             if (i)
518             {
519                 WCHAR res[20];
520 
521                 ok( (len > 1) && (len < 7), "bad length %d\n", len );
522                 wsprintfW( res, integfmt, i );
523                 memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR));
524                 ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i );
525             }
526             else
527                 ok( !len, "bad length %d\n", len );
528 
529             len = GetAtomNameW( (ATOM)i, outW, 1);
530             ok(!len, "succeed with %u for %u\n", len, i);
531 
532             /* ERROR_MORE_DATA is on nt3.51 sp5 */
533             ok(GetLastError() == ERROR_MORE_DATA ||
534                GetLastError() == (i ? ERROR_INSUFFICIENT_BUFFER : ERROR_INVALID_PARAMETER),
535                "wrong error conditions %u for %u\n", GetLastError(), i);
536         }
537         do_initW(inW, "abcdefghij", 255);
538         atom = AddAtomW(inW);
539         ok(atom, "couldn't add atom for %s\n", in);
540         len = GetAtomNameW(atom, outW, sizeof(outW)/sizeof(outW[0]));
541         ok(len == 255, "length mismatch (%u instead of 255)\n", len);
542         for (i = 0; i < 255; i++)
543         {
544             ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
545         }
546         ok(outW[255] == '\0', "wrong end of string\n");
547         memset(outW, '.', sizeof(outW));
548         len = GetAtomNameW(atom, outW, 10);
549         ok(len == 9, "succeeded %d\n", len);
550         for (i = 0; i < 9; i++)
551         {
552             ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
553         }
554         ok(outW[9] == '\0', "wrong end of string\n");
555         ok(outW[10] == DOUBLE('.'), "buffer overwrite\n");
556         do_initW(inW, "abcdefghij", 256);
557         atom = AddAtomW(inW);
558         ok(!atom, "succeeded\n");
559 
560         /* ERROR_MORE_DATA is on nt3.51 sp5 */
561         ok(GetLastError() == ERROR_INVALID_PARAMETER ||
562            GetLastError() == ERROR_MORE_DATA,
563            "wrong error code (%u)\n", GetLastError());
564     }
565 }
566 
567 static void test_local_error_handling(void)
568 {
569     char buffer[260];
570     WCHAR bufferW[260];
571     int i;
572 
573     memset( buffer, 'a', 256 );
574     buffer[256] = 0;
575     ok( !AddAtomA(buffer), "add succeeded\n" );
576     ok( !FindAtomA(buffer), "find succeeded\n" );
577 
578     if (unicode_OS)
579     {
580         for (i = 0; i < 256; i++) bufferW[i] = 'b';
581         bufferW[256] = 0;
582         ok( !AddAtomW(bufferW), "add succeeded\n" );
583         ok( !FindAtomW(bufferW), "find succeeded\n" );
584     }
585 }
586 
587 START_TEST(atom)
588 {
589     /* Global atom table seems to be available to GUI apps only in
590        Win7, so let's turn this app into a GUI app */
591     GetDesktopWindow();
592 
593     test_add_atom();
594     test_get_atom_name();
595     test_error_handling();
596     test_local_add_atom();
597     test_local_get_atom_name();
598     test_local_error_handling();
599 }
600