diff -u cvs/hq/wine/dlls/kernel/tests/atom.c wine/dlls/kernel/tests/atom.c --- cvs/hq/wine/dlls/kernel/tests/atom.c Mon Sep 9 13:26:55 2002 +++ wine/dlls/kernel/tests/atom.c Thu Oct 3 20:38:14 2002 @@ -28,6 +28,8 @@ static const WCHAR FOOBARW[] = {'F','O','O','B','A','R',0}; static const WCHAR _foobarW[] = {'_','f','o','o','b','a','r',0}; +static BOOL unicode_OS; + static void test_add_atom(void) { ATOM atom, w_atom; @@ -47,41 +49,67 @@ * find the first one, not add a new one */ SetLastError( 0xdeadbeef ); w_atom = GlobalAddAtomW( foobarW ); - ok( w_atom == atom, "Unicode atom does not match ASCII" ); - ok( GetLastError() == 0xdeadbeef, "GlobalAddAtomW set last error" ); + if (w_atom && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + unicode_OS = TRUE; + + trace("Unicode APIs are %ssupported\n", unicode_OS ? "" : "NOT "); + + if (unicode_OS) + { + ok( w_atom == atom, "Unicode atom does not match ASCII" ); + ok( GetLastError() == 0xdeadbeef, "GlobalAddAtomW set last error" ); + } /* Verify that it can be found (or not) appropriately via unicode name */ - ok( GlobalFindAtomW( foobarW ) == atom, "could not find atom foobar" ); - ok( GlobalFindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR" ); - ok( !GlobalFindAtomW( _foobarW ), "found _foobar" ); + if (unicode_OS) + { + ok( GlobalFindAtomW( foobarW ) == atom, "could not find atom foobar" ); + ok( GlobalFindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR" ); + ok( !GlobalFindAtomW( _foobarW ), "found _foobar" ); + } /* Test integer atoms - * (0x0000 .. 0xbfff) should be valid; + * (0x0001 .. 0xbfff) should be valid; * (0xc000 .. 0xffff) should be invalid */ - todo_wine + + SetLastError( 0xdeadbeef ); + ok( GlobalAddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0" ); + if (unicode_OS) { SetLastError( 0xdeadbeef ); - ok( GlobalAddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "failed to add atom 0" ); - SetLastError( 0xdeadbeef ); - ok( GlobalAddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "failed to add atom 0" ); + ok( GlobalAddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0" ); } + SetLastError( 0xdeadbeef ); for (i = 1; i <= 0xbfff; i++) { SetLastError( 0xdeadbeef ); ok( GlobalAddAtomA((LPCSTR)i) == i && GetLastError() == 0xdeadbeef, "failed to add atom %x", i ); - ok( GlobalAddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef, - "failed to add atom %x", i ); + if (unicode_OS) + { + SetLastError( 0xdeadbeef ); + ok( GlobalAddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef, + "failed to add atom %x", i ); + } } + for (i = 0xc000; i <= 0xffff; i++) { SetLastError( 0xdeadbeef ); - ok( !GlobalAddAtomA((LPCSTR)i) && (GetLastError() == ERROR_INVALID_PARAMETER), - "succeeded adding %x", i ); - SetLastError( 0xdeadbeef ); - ok( !GlobalAddAtomW((LPCWSTR)i) && (GetLastError() == ERROR_INVALID_PARAMETER), - "succeeded adding %x", i ); + if (unicode_OS) + ok( !GlobalAddAtomA((LPCSTR)i) && GetLastError() == ERROR_INVALID_PARAMETER, + "succeeded adding %x", i ); + else + ok( !GlobalAddAtomA((LPCSTR)i) && GetLastError() == 0xdeadbeef, + "succeeded adding %x", i ); + + if (unicode_OS) + { + SetLastError( 0xdeadbeef ); + ok( !GlobalAddAtomW((LPCWSTR)i) && (GetLastError() == ERROR_INVALID_PARAMETER), + "succeeded adding %x", i ); + } } } @@ -90,7 +118,7 @@ char buf[10]; WCHAR bufW[10]; int i, len; - static const char resultW[] = {'f','o','o','b','a','r',0,'.','.','.'}; + static const WCHAR resultW[] = {'f','o','o','b','a','r',0,'.','.','.'}; ATOM atom = GlobalAddAtomA( "foobar" ); @@ -99,52 +127,118 @@ len = GlobalGetAtomNameA( atom, buf, 10 ); ok( len == strlen("foobar"), "bad length %d", len ); ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents" ); - ok( !GlobalGetAtomNameA( atom, buf, 3 ), "GlobalGetAtomNameA succeeded on short buffer" ); + + memset( buf, '.', sizeof(buf) ); + SetLastError( 0xdeadbeef ); + if (unicode_OS) + { + ok( !GlobalGetAtomNameA( atom, buf, 3 ) && GetLastError() == ERROR_MORE_DATA, + "GlobalGetAtomNameA succeeded on short buffer" ); + ok( !memcmp( buf, "fo\0.......", 10 ), "bad buffer contents: %.10s", buf ); + } + else + { + len = GlobalGetAtomNameA( atom, buf, 3 ); + ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameA failed on short buffer" ); + ok( len == 2, "bad length %d", len ); + ok( !memcmp( buf, "fo\0.......", 10 ), "bad buffer contents: %.10s", buf ); + } /* Repeat, unicode-style */ - for (i = 0; i < 10; i++) bufW[i] = '.'; - len = GlobalGetAtomNameW( atom, bufW, 10 ); - ok( len == lstrlenW(foobarW), "bad length %d", len ); - todo_wine + if (unicode_OS) { + static const WCHAR sampleW[10] = {'f','o','o','.','.','.','.','.','.','.'}; + + for (i = 0; i < 10; i++) bufW[i] = '.'; + SetLastError( 0xdeadbeef ); + len = GlobalGetAtomNameW( atom, bufW, 10 ); + ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed" ); + ok( len == lstrlenW(foobarW), "bad length %d", len ); ok( !memcmp( bufW, resultW, 10*sizeof(WCHAR) ), "bad buffer contents" ); + + for (i = 0; i < 10; i++) bufW[i] = '.'; + SetLastError( 0xdeadbeef ); + len = GlobalGetAtomNameW( atom, bufW, 3 ); + ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed on short buffer" ); + ok( len == 3, "bad length %d", len ); + ok( !memcmp( bufW, sampleW, 10*sizeof(WCHAR) ), "bad buffer contents" ); } - ok( !GlobalGetAtomNameW( atom, bufW, 3 ), "GlobalGetAtomNameW succeeded on short buffer" ); /* Check error code returns */ + memset(buf, '.', 10); SetLastError( 0xdeadbeef ); - ok( !GlobalGetAtomNameA( atom, buf, 0 ) && GetLastError() == ERROR_MORE_DATA, "succeded" ); - SetLastError( 0xdeadbeef ); - ok( !GlobalGetAtomNameA( atom, buf, -1 ) && GetLastError() == ERROR_MORE_DATA, "succeded" ); - SetLastError( 0xdeadbeef ); - ok( !GlobalGetAtomNameW( atom, bufW, 0 ) && GetLastError() == ERROR_MORE_DATA, "succeded" ); + if (unicode_OS) + { + ok( !GlobalGetAtomNameA( atom, buf, 0 ) && GetLastError() == ERROR_MORE_DATA, "succeded" ); + ok( !memcmp( buf, "..........", 10 ), "should not touch buffer" ); + } + else + { + ok( !GlobalGetAtomNameA( atom, buf, 0 ) && GetLastError() == 0xdeadbeef, "succeded" ); + ok( !memcmp( buf, "..........", 10 ), "should not touch buffer: %.10s", buf ); + } + + memset(buf, '.', 10); SetLastError( 0xdeadbeef ); - ok( !GlobalGetAtomNameW( atom, bufW, -1 ) && GetLastError() == ERROR_MORE_DATA, "succeded" ); + if (unicode_OS) + { + len = GlobalGetAtomNameA( atom, buf, -1 ); + ok( len && GetLastError() == 0xdeadbeef, "failed" ); + ok( len == strlen("foobar"), "bad length %d", len ); + ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents %.10s", buf ); + } + else + { + len = GlobalGetAtomNameA( atom, buf, -1 ); + ok( !len && GetLastError() == ERROR_INVALID_PARAMETER, "succeded: len %d, error %ld", len, GetLastError() ); + ok( !memcmp( buf, "..........", 10 ), "should not touch buffer: %.10s", buf ); + } + + if (unicode_OS) + { + static const WCHAR sampleW[10] = {'.','.','.','.','.','.','.','.','.','.'}; + + for (i = 0; i < 10; i++) bufW[i] = '.'; + SetLastError( 0xdeadbeef ); + ok( !GlobalGetAtomNameW( atom, bufW, 0 ) && GetLastError() == ERROR_MORE_DATA, "succeded" ); + ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer" ); + + for (i = 0; i < 10; i++) bufW[i] = '.'; + SetLastError( 0xdeadbeef ); + ok( !GlobalGetAtomNameW( atom, bufW, -1 ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "succeded" ); + ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer" ); + } /* Test integer atoms */ for (i = 0; i <= 0xbfff; i++) { memset( buf, 'a', 10 ); - len = GlobalGetAtomNameA( i, buf, 10 ); + len = GlobalGetAtomNameA( (ATOM)i, buf, 10 ); if (i) { char res[20]; - ok( (len > 1) && (len < 7), "bad length %d", len ); + ok( (len > 1) && (len < 7), "%04x: bad length %d", i, len ); sprintf( res, "#%d", i ); memset( res + strlen(res) + 1, 'a', 10 ); - ok( !memcmp( res, buf, 10 ), "bad buffer contents %s", buf ); + ok( !memcmp( res, buf, 10 ), "%04x: bad buffer contents %.10s", i, buf ); } - else todo_wine + else { - char res[20]; - ok( (len > 1) && (len < 7), "bad length %d", len ); - sprintf( res, "#%d", i ); - memset( res + strlen(res) + 1, 'a', 10 ); - ok( !memcmp( res, buf, 10 ), "bad buffer contents %s", buf ); + char res[10]; + ok( !len, "bad length %d", len ); + memset( res, 'a', 10 ); + if (unicode_OS) + ok( !memcmp( res, buf, 10 ), "%04x: bad buffer contents %.10s", i, buf ); + else + { + res[0] = 0; + ok( !memcmp( res, buf, 10 ), "%04x: bad buffer contents %.10s", i, buf ); + } } } } +/* Note: GlobalDeleteAtom behaviour is completely broken under 9x/Me */ static void test_delete_atom(void) { ATOM atom; @@ -152,18 +246,34 @@ /* First make sure it doesn't exist */ atom = GlobalAddAtomA( "foobar" ); - while (!GlobalDeleteAtom( atom )); + + i = 100; + do + { + SetLastError(ERROR_SUCCESS); + ok( !GlobalDeleteAtom( atom ), "expected to always return 0" ); + if (!--i) + { + ok( 0, "infinite loop" ); + break; + } + } while (GetLastError() == ERROR_SUCCESS); /* Now add it a number of times */ for (i = 0; i < 10; i++) atom = GlobalAddAtomA( "foobar" ); /* Make sure it's here */ ok( GlobalFindAtomA( "foobar" ), "foobar not found" ); - ok( GlobalFindAtomW( foobarW ), "foobarW not found" ); + if (unicode_OS) + ok( GlobalFindAtomW( foobarW ), "foobarW not found" ); /* That many deletions should succeed */ for (i = 0; i < 10; i++) - ok( !GlobalDeleteAtom( atom ), "delete atom failed" ); + { + SetLastError(ERROR_SUCCESS); + ok( !GlobalDeleteAtom( atom ) && GetLastError() == ERROR_SUCCESS, + "delete atom failed" ); + } /* It should be gone now */ ok( !GlobalFindAtomA( "foobar" ), "still found it" ); @@ -171,8 +281,8 @@ /* So this one should fail */ SetLastError( 0xdeadbeef ); - ok( GlobalDeleteAtom( atom ) == atom && GetLastError() == ERROR_INVALID_HANDLE, - "delete failed" ); + ok( !GlobalDeleteAtom( atom ) && GetLastError() == ERROR_INVALID_HANDLE, + "delete atom succeded" ); } static void test_error_handling(void) @@ -189,20 +299,30 @@ buffer[255] = 'a'; buffer[256] = 0; SetLastError( 0xdeadbeef ); - ok( !GlobalAddAtomA(buffer) && GetLastError() == ERROR_INVALID_PARAMETER, "add succeded" ); - SetLastError( 0xdeadbeef ); - ok( !GlobalFindAtomA(buffer) && GetLastError() == ERROR_INVALID_PARAMETER, "find succeded" ); + if (unicode_OS) + ok( !GlobalAddAtomA(buffer) && GetLastError() == ERROR_INVALID_PARAMETER, "add succeded" ); + else + ok( !GlobalAddAtomA(buffer) && GetLastError() == 0xdeadbeef, "add succeded" ); + SetLastError( 0xdeadbeef ); + if (unicode_OS) + ok( !GlobalFindAtomA(buffer) && GetLastError() == ERROR_INVALID_PARAMETER, "find succeded" ); + else + ok( !GlobalFindAtomA(buffer) && GetLastError() == 0xdeadbeef, "find succeded" ); - for (i = 0; i < 255; i++) bufferW[i] = 'b'; - bufferW[255] = 0; - ok( atom = GlobalAddAtomW( bufferW ), "add failed" ); - ok( !GlobalDeleteAtom( atom ), "delete failed" ); - bufferW[255] = 'b'; - bufferW[256] = 0; - SetLastError( 0xdeadbeef ); - ok( !GlobalAddAtomW(bufferW) && GetLastError() == ERROR_INVALID_PARAMETER, "add succeded" ); - SetLastError( 0xdeadbeef ); - ok( !GlobalFindAtomW(bufferW) && GetLastError() == ERROR_INVALID_PARAMETER, "find succeded" ); + if (unicode_OS) + { + for (i = 0; i < 255; i++) bufferW[i] = 'b'; + bufferW[255] = 0; + ok( atom = GlobalAddAtomW( bufferW ), "add failed" ); + SetLastError(ERROR_SUCCESS); + ok( !GlobalDeleteAtom( atom ) && GetLastError() == ERROR_SUCCESS, "delete failed" ); + bufferW[255] = 'b'; + bufferW[256] = 0; + SetLastError( 0xdeadbeef ); + ok( !GlobalAddAtomW(bufferW) && GetLastError() == ERROR_INVALID_PARAMETER, "add succeded" ); + SetLastError( 0xdeadbeef ); + ok( !GlobalFindAtomW(bufferW) && GetLastError() == ERROR_INVALID_PARAMETER, "find succeded" ); + } } START_TEST(atom) diff -u cvs/hq/wine/memory/atom.c wine/memory/atom.c --- cvs/hq/wine/memory/atom.c Sun Sep 1 16:39:24 2002 +++ wine/memory/atom.c Thu Oct 3 17:33:49 2002 @@ -131,7 +131,7 @@ } if (*atomstr) return FALSE; } - if (!atom || (atom >= MAXINTATOM)) + if (atom >= MAXINTATOM) { SetLastError( ERROR_INVALID_PARAMETER ); atom = 0; @@ -158,7 +158,7 @@ } if (*atomstr) return FALSE; } - if (!atom || (atom >= MAXINTATOM)) + if (atom >= MAXINTATOM) { SetLastError( ERROR_INVALID_PARAMETER ); atom = 0; @@ -502,18 +502,19 @@ static ATOM ATOM_DeleteAtom( ATOM atom, BOOL local) { TRACE( "(%s) %x\n", local ? "local" : "global", atom ); - if (atom < MAXINTATOM) atom = 0; - else + if (atom >= MAXINTATOM) { + int ret; SERVER_START_REQ( delete_atom ) { req->atom = atom; req->local = local; - if (!wine_server_call_err( req )) atom = 0; + if ((ret = wine_server_call_err( req ))) + SetLastError( RtlNtStatusToDosError(ret) ); } SERVER_END_REQ; } - return atom; + return 0; } @@ -649,7 +650,7 @@ { INT len; - if (count <= 0) + if (!count) { SetLastError( ERROR_MORE_DATA ); return 0; @@ -677,6 +678,7 @@ wine_server_set_reply( req, full_name, sizeof(full_name) ); if (!wine_server_call_err( req )) { + if (count < 0) count = 0x7fffffff; len = WideCharToMultiByte( CP_ACP, 0, full_name, wine_server_reply_size(reply) / sizeof(WCHAR), buffer, count - 1, NULL, NULL ); @@ -737,7 +739,7 @@ { INT len; - if (count <= 0) + if (!count) { SetLastError( ERROR_MORE_DATA ); return 0; @@ -767,18 +769,28 @@ if (!wine_server_call_err( req )) { len = wine_server_reply_size(reply) / sizeof(WCHAR); - if (count > len) count = len + 1; - memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) ); - buffer[count-1] = 0; + if (count > 0) + { + if (count > len) + { + memcpy( buffer, full_name, len * sizeof(WCHAR) ); + buffer[len] = 0; + } + else + { + len = count; + memcpy( buffer, full_name, len * sizeof(WCHAR) ); + } + } + else + { + len = 0; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } } } SERVER_END_REQ; if (!len) return 0; - } - if (count <= len) - { - SetLastError( ERROR_MORE_DATA ); - return 0; } TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) ); return len;