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