added kernel32 wine tests Added: trunk/reactos/regtests/winetests/kernel32/ Added: trunk/reactos/regtests/winetests/kernel32/alloc.c Added: trunk/reactos/regtests/winetests/kernel32/atom.c Added: trunk/reactos/regtests/winetests/kernel32/change.c Added: trunk/reactos/regtests/winetests/kernel32/codepage.c Added: trunk/reactos/regtests/winetests/kernel32/comm.c Added: trunk/reactos/regtests/winetests/kernel32/console.c Added: trunk/reactos/regtests/winetests/kernel32/directory.c Added: trunk/reactos/regtests/winetests/kernel32/drive.c Added: trunk/reactos/regtests/winetests/kernel32/environ.c Added: trunk/reactos/regtests/winetests/kernel32/file.c Added: trunk/reactos/regtests/winetests/kernel32/format_msg.c Added: trunk/reactos/regtests/winetests/kernel32/heap.c Added: trunk/reactos/regtests/winetests/kernel32/kernel32_test.xml Added: trunk/reactos/regtests/winetests/kernel32/locale.c Added: trunk/reactos/regtests/winetests/kernel32/mailslot.c Added: trunk/reactos/regtests/winetests/kernel32/module.c Added: trunk/reactos/regtests/winetests/kernel32/path.c Added: trunk/reactos/regtests/winetests/kernel32/pipe.c Added: trunk/reactos/regtests/winetests/kernel32/process.c Added: trunk/reactos/regtests/winetests/kernel32/profile.c Added: trunk/reactos/regtests/winetests/kernel32/sync.c Added: trunk/reactos/regtests/winetests/kernel32/testlist.c Added: trunk/reactos/regtests/winetests/kernel32/thread.c Added: trunk/reactos/regtests/winetests/kernel32/time.c Added: trunk/reactos/regtests/winetests/kernel32/timer.c Added: trunk/reactos/regtests/winetests/kernel32/virtual.c _____
Added: trunk/reactos/regtests/winetests/kernel32/alloc.c --- trunk/reactos/regtests/winetests/kernel32/alloc.c 2005-08-07 03:00:44 UTC (rev 17136) +++ trunk/reactos/regtests/winetests/kernel32/alloc.c 2005-08-07 03:14:17 UTC (rev 17137) @@ -0,0 +1,406 @@
+/* + * Unit test suite for memory allocation functions. + * + * Copyright 2002 Geoffrey Hausheer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdarg.h> + +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + + + /* The following functions don't have tests, because either I don't know how + to test them, or they are WinNT only, or require multiple threads. + Since the last two issues shouldn't really stop the tests from being + written, assume for now that it is all due to the first case + HeapCompact + HeapLock + HeapQueryInformation + HeapSetInformation + HeapUnlock + HeapValidate + HeapWalk +*/ +/* In addition, these features aren't being tested + HEAP_NO_SERIALIZE + HEAP_GENERATE_EXCEPTIONS + STATUS_ACCESS_VIOLATION (error code from HeapAlloc) +*/ + +static void test_Heap(void) +{ + SYSTEM_INFO sysInfo; + ULONG memchunk; + HANDLE heap; + LPVOID mem1,mem1a,mem3; + UCHAR *mem2,*mem2a; + UINT error,i; + DWORD dwSize; + +/* Retrieve the page size for this system */ + sysInfo.dwPageSize=0; + GetSystemInfo(&sysInfo); + ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n"); + +/* Create a Heap with a minimum and maximum size */ +/* Note that Windows and Wine seem to behave a bit differently with respect + to memory allocation. In Windows, you can't access all the memory + specified in the heap (due to overhead), so choosing a reasonable maximum + size for the heap was done mostly by trial-and-error on Win2k. It may need + more tweaking for otherWindows variants. +*/ + memchunk=10*sysInfo.dwPageSize; + heap=HeapCreate(0,2*memchunk,5*memchunk); + +/* Check that HeapCreate allocated the right amount of ram */ + todo_wine { + /* Today HeapCreate seems to return a memory block larger than specified. + MSDN says the maximum heap size should be dwMaximumSize rounded up to the + nearest page boundary + */ + mem1=HeapAlloc(heap,0,5*memchunk+1); + ok(mem1==NULL,"HeapCreate allocated more Ram than it should have\n"); + HeapFree(heap,0,mem1); + } + +/* Check that a normal alloc works */ + mem1=HeapAlloc(heap,0,memchunk); + ok(mem1!=NULL,"HeapAlloc failed\n"); + if(mem1) { + ok(HeapSize(heap,0,mem1)>=memchunk, "HeapAlloc should return a big enough memory block\n"); + } + +/* Check that a 'zeroing' alloc works */ + mem2=HeapAlloc(heap,HEAP_ZERO_MEMORY,memchunk); + ok(mem2!=NULL,"HeapAlloc failed\n"); + if(mem2) { + ok(HeapSize(heap,0,mem2)>=memchunk,"HeapAlloc should return a big enough memory block\n"); + error=0; + for(i=0;i<memchunk;i++) { + if(mem2[i]!=0) { + error=1; + } + } + ok(!error,"HeapAlloc should have zeroed out it's allocated memory\n"); + } + +/* Check that HeapAlloc returns NULL when requested way too much memory */ + mem3=HeapAlloc(heap,0,5*memchunk); + ok(mem3==NULL,"HeapAlloc should return NULL\n"); + if(mem3) { + ok(HeapFree(heap,0,mem3),"HeapFree didn't pass successfully\n"); + } + +/* Check that HeapRealloc works */ + mem2a=HeapReAlloc(heap,HEAP_ZERO_MEMORY,mem2,memchunk+5*sysInfo.dwPageSi ze); + ok(mem2a!=NULL,"HeapReAlloc failed\n"); + if(mem2a) { + ok(HeapSize(heap,0,mem2a)>=memchunk+5*sysInfo.dwPageSize,"HeapReAlloc failed\n"); + error=0; + for(i=0;i<5*sysInfo.dwPageSize;i++) { + if(mem2a[memchunk+i]!=0) { + error=1; + } + } + ok(!error,"HeapReAlloc should have zeroed out it's allocated memory\n"); + } + +/* Check that HeapRealloc honours HEAP_REALLOC_IN_PLACE_ONLY */ + error=0; + mem1a=HeapReAlloc(heap,HEAP_REALLOC_IN_PLACE_ONLY,mem1,memchunk+sysInfo. dwPageSize); + if(mem1a!=NULL) { + if(mem1a!=mem1) { + error=1; + } + } + ok(mem1a==NULL || error==0,"HeapReAlloc didn't honour HEAP_REALLOC_IN_PLACE_ONLY\n"); + +/* Check that HeapFree works correctly */ + if(mem1a) { + ok(HeapFree(heap,0,mem1a),"HeapFree failed\n"); + } else { + ok(HeapFree(heap,0,mem1),"HeapFree failed\n"); + } + if(mem2a) { + ok(HeapFree(heap,0,mem2a),"HeapFree failed\n"); + } else { + ok(HeapFree(heap,0,mem2),"HeapFree failed\n"); + } + + /* 0-length buffer */ + mem1 = HeapAlloc(heap, 0, 0); + ok(mem1 != NULL, "Reserved memory\n"); + + dwSize = HeapSize(heap, 0, mem1); + /* should work with 0-length buffer */ + ok((dwSize >= 0) && (dwSize < 0xFFFFFFFF), + "The size of the 0-length buffer\n"); + ok(HeapFree(heap, 0, mem1), "Freed the 0-length buffer\n"); + +/* Check that HeapDestry works */ + ok(HeapDestroy(heap),"HeapDestroy failed\n"); +} + +/* The following functions don't have tests, because either I don't know how + to test them, or they are WinNT only, or require multiple threads. + Since the last two issues shouldn't really stop the tests from being + written, assume for now that it is all due to the first case + GlobalFlags + GlobalMemoryStatus + GlobalMemoryStatusEx +*/ +/* In addition, these features aren't being tested + GMEM_DISCADABLE + GMEM_NOCOMPACT +*/ +static void test_Global(void) +{ + ULONG memchunk; + HGLOBAL mem1,mem2,mem2a,mem2b; + UCHAR *mem2ptr; + UINT error,i; + memchunk=100000; + + SetLastError(NO_ERROR); +/* Check that a normal alloc works */ + mem1=GlobalAlloc(0,memchunk); + ok(mem1!=NULL,"GlobalAlloc failed\n"); + if(mem1) { + ok(GlobalSize(mem1)>=memchunk, "GlobalAlloc should return a big enough memory block\n"); + } + +/* Check that a 'zeroing' alloc works */ + mem2=GlobalAlloc(GMEM_ZEROINIT,memchunk); + ok(mem2!=NULL,"GlobalAlloc failed: error=%ld\n",GetLastError()); + if(mem2) { + ok(GlobalSize(mem2)>=memchunk,"GlobalAlloc should return a big enough memory block\n"); + mem2ptr=GlobalLock(mem2); + ok(mem2ptr==mem2,"GlobalLock should have returned the same memory as was allocated\n"); + if(mem2ptr) { + error=0; + for(i=0;i<memchunk;i++) { + if(mem2ptr[i]!=0) { + error=1; + } + } + ok(!error,"GlobalAlloc should have zeroed out it's allocated memory\n"); + } + } +/* Check that GlobalReAlloc works */ +/* Check that we can change GMEM_FIXED to GMEM_MOVEABLE */ + mem2a=GlobalReAlloc(mem2,0,GMEM_MODIFY | GMEM_MOVEABLE); + if(mem2a!=NULL) { + mem2=mem2a; + mem2ptr=GlobalLock(mem2a); + ok(mem2ptr!=NULL && !GlobalUnlock(mem2a)&&GetLastError()==NO_ERROR, + "Converting from FIXED to MOVEABLE didn't REALLY work\n"); + } + +/* Check that ReAllocing memory works as expected */ + mem2a=GlobalReAlloc(mem2,2*memchunk,GMEM_MOVEABLE | GMEM_ZEROINIT); + ok(mem2a!=NULL,"GlobalReAlloc failed\n"); + if(mem2a) { + ok(GlobalSize(mem2a)>=2*memchunk,"GlobalReAlloc failed\n"); + mem2ptr=GlobalLock(mem2a); + ok(mem2ptr!=NULL,"GlobalLock Failed\n"); + if(mem2ptr) { + error=0; + for(i=0;i<memchunk;i++) { + if(mem2ptr[memchunk+i]!=0) { + error=1; + } + } + ok(!error,"GlobalReAlloc should have zeroed out it's allocated memory\n"); + +/* Check that GlobalHandle works */ + mem2b=GlobalHandle(mem2ptr); + ok(mem2b==mem2a,"GlobalHandle didn't return the correct memory handle\n"); + +/* Check that we can't discard locked memory */ + mem2b=GlobalDiscard(mem2a); + if(mem2b==NULL) { + ok(!GlobalUnlock(mem2a) && GetLastError()==NO_ERROR,"GlobalUnlock Failed\n"); + } + } + } + if(mem1) { + ok(GlobalFree(mem1)==NULL,"GlobalFree failed\n"); + } + if(mem2a) { + ok(GlobalFree(mem2a)==NULL,"GlobalFree failed\n"); + } else { + ok(GlobalFree(mem2)==NULL,"GlobalFree failed\n"); + } +} + + +/* The following functions don't have tests, because either I don't know how + to test them, or they are WinNT only, or require multiple threads. + Since the last two issues shouldn't really stop the tests from being + written, assume for now that it is all due to the first case + LocalDiscard + LocalFlags +*/ +/* In addition, these features aren't being tested + LMEM_DISCADABLE + LMEM_NOCOMPACT +*/ +static void test_Local(void) +{ + ULONG memchunk; + HLOCAL mem1,mem2,mem2a,mem2b; + UCHAR *mem2ptr; + UINT error,i; + memchunk=100000; + +/* Check that a normal alloc works */ + mem1=LocalAlloc(0,memchunk); + ok(mem1!=NULL,"LocalAlloc failed: error=%ld\n",GetLastError()); + if(mem1) { + ok(LocalSize(mem1)>=memchunk, "LocalAlloc should return a big enough memory block\n"); + } + +/* Check that a 'zeroing' and lock alloc works */ + mem2=LocalAlloc(LMEM_ZEROINIT|LMEM_MOVEABLE,memchunk); + ok(mem2!=NULL,"LocalAlloc failed: error=%ld\n",GetLastError()); + if(mem2) { + ok(LocalSize(mem2)>=memchunk,"LocalAlloc should return a big enough memory block\n"); + mem2ptr=LocalLock(mem2); + ok(mem2ptr!=NULL,"LocalLock: error=%ld\n",GetLastError()); + if(mem2ptr) { + error=0; + for(i=0;i<memchunk;i++) { + if(mem2ptr[i]!=0) { + error=1; + } + } + ok(!error,"LocalAlloc should have zeroed out it's allocated memory\n"); + SetLastError(0); + error=LocalUnlock(mem2); + ok(error==0 && GetLastError()==NO_ERROR, + "LocalUnlock Failed: rc=%d err=%ld\n",error,GetLastError()); + } + } + mem2a=LocalFree(mem2); + ok(mem2a==NULL, "LocalFree failed: %p\n",mem2a); + +/* Reallocate mem2 as moveable memory */ + mem2=LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,memchunk); + ok(mem2!=NULL, "LocalAlloc failed to create moveable memory, error=%ld\n",GetLastError()); + +/* Check that ReAllocing memory works as expected */ + mem2a=LocalReAlloc(mem2,2*memchunk,LMEM_MOVEABLE | LMEM_ZEROINIT); + ok(mem2a!=NULL,"LocalReAlloc failed, error=%ld\n",GetLastError()); + if(mem2a) { + ok(LocalSize(mem2a)>=2*memchunk,"LocalReAlloc failed\n"); + mem2ptr=LocalLock(mem2a); + ok(mem2ptr!=NULL,"LocalLock Failed\n"); + if(mem2ptr) { + error=0; + for(i=0;i<memchunk;i++) { + if(mem2ptr[memchunk+i]!=0) { + error=1; + } + } + ok(!error,"LocalReAlloc should have zeroed out it's allocated memory\n"); +/* Check that LocalHandle works */ + mem2b=LocalHandle(mem2ptr); + ok(mem2b==mem2a,"LocalHandle didn't return the correct memory handle\n"); +/* Check that we can't discard locked memory */ + mem2b=LocalDiscard(mem2a); + ok(mem2b==NULL,"Discarded memory we shouldn't have\n"); + SetLastError(NO_ERROR); + ok(!LocalUnlock(mem2a) && GetLastError()==NO_ERROR, "LocalUnlock Failed\n"); + } + } + if(mem1) { + ok(LocalFree(mem1)==NULL,"LocalFree failed\n"); + } + if(mem2a) { + ok(LocalFree(mem2a)==NULL,"LocalFree failed\n"); + } else { + ok(LocalFree(mem2)==NULL,"LocalFree failed\n"); + } +} + +/* The Virtual* routines are not tested as thoroughly, + since I don't really understand how to use them correctly :) + The following routines are not tested at all + VirtualAllocEx + VirtualFreeEx + VirtualLock + VirtualProtect + VirtualProtectEx + VirtualQuery + VirtualQueryEx + VirtualUnlock + And the only features (flags) being tested are + MEM_COMMIT + MEM_RELEASE + PAGE_READWRITE + Testing the rest requires using exceptions, which I really don't + understand well +*/ +static void test_Virtual(void) +{ + SYSTEM_INFO sysInfo; + ULONG memchunk; + UCHAR *mem1; + UINT error,i; + +/* Retrieve the page size for this system */ + sysInfo.dwPageSize=0; + GetSystemInfo(&sysInfo); + ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n"); + +/* Choose a reasonable allocation size */ + memchunk=10*sysInfo.dwPageSize; + +/* Check that a normal alloc works */ + mem1=VirtualAlloc(NULL,memchunk,MEM_COMMIT,PAGE_READWRITE); + ok(mem1!=NULL,"VirtualAlloc failed\n"); + if(mem1) { +/* check that memory is initialized to 0 */ + error=0; + for(i=0;i<memchunk;i++) { + if(mem1[i]!=0) { + error=1; + } + } + ok(!error,"VirtualAlloc did not initialize memory to '0's\n"); +/* Check that we can read/write to memory */ + error=0; + for(i=0;i<memchunk;i+=100) { + mem1[i]='a'; + if(mem1[i]!='a') { + error=1; + } + } + ok(!error,"Virtual memory was not writable\n"); + } + ok(VirtualFree(mem1,0,MEM_RELEASE),"VirtualFree failed\n"); +} +START_TEST(alloc) +{ + test_Heap(); + test_Global(); + test_Local(); + test_Virtual(); +} Property changes on: trunk/reactos/regtests/winetests/kernel32/alloc.c ___________________________________________________________________ Name: svn:executable + * _____
Added: trunk/reactos/regtests/winetests/kernel32/atom.c --- trunk/reactos/regtests/winetests/kernel32/atom.c 2005-08-07 03:00:44 UTC (rev 17136) +++ trunk/reactos/regtests/winetests/kernel32/atom.c 2005-08-07 03:14:17 UTC (rev 17137) @@ -0,0 +1,346 @@
+/* + * Unit tests for atom functions + * + * Copyright (c) 2002 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdarg.h> +#include <stdio.h> + +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +static const WCHAR foobarW[] = {'f','o','o','b','a','r',0}; +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; + int i; + + SetLastError( 0xdeadbeef ); + atom = GlobalAddAtomA( "foobar" ); + ok( atom >= 0xc000, "bad atom id %x\n", atom ); + ok( GetLastError() == 0xdeadbeef, "GlobalAddAtomA set last error\n" ); + + /* Verify that it can be found (or not) appropriately */ + ok( GlobalFindAtomA( "foobar" ) == atom, "could not find atom foobar\n" ); + ok( GlobalFindAtomA( "FOOBAR" ) == atom, "could not find atom FOOBAR\n" ); + ok( !GlobalFindAtomA( "_foobar" ), "found _foobar\n" ); + + /* Add the same atom, specifying string as unicode; should + * find the first one, not add a new one */ + SetLastError( 0xdeadbeef ); + w_atom = GlobalAddAtomW( foobarW ); + if (w_atom && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + unicode_OS = TRUE; + else + trace("WARNING: Unicode atom APIs are not supported on this platform\n"); + + if (unicode_OS) + { + ok( w_atom == atom, "Unicode atom does not match ASCII\n" ); + ok( GetLastError() == 0xdeadbeef, "GlobalAddAtomW set last error\n" ); + } + + /* Verify that it can be found (or not) appropriately via unicode name */ + if (unicode_OS) + { + ok( GlobalFindAtomW( foobarW ) == atom, "could not find atom foobar\n" ); + ok( GlobalFindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR\n" ); + ok( !GlobalFindAtomW( _foobarW ), "found _foobar\n" ); + } + + /* Test integer atoms + * (0x0001 .. 0xbfff) should be valid; + * (0xc000 .. 0xffff) should be invalid */ + + SetLastError( 0xdeadbeef ); + ok( GlobalAddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" ); + if (unicode_OS) + { + SetLastError( 0xdeadbeef ); + ok( GlobalAddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" ); + } + + SetLastError( 0xdeadbeef ); + for (i = 1; i <= 0xbfff; i++) + { + SetLastError( 0xdeadbeef ); + ok( GlobalAddAtomA((LPCSTR)i) == i && GetLastError() == 0xdeadbeef, + "failed to add atom %x\n", i ); + if (unicode_OS) + { + SetLastError( 0xdeadbeef ); + ok( GlobalAddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef, + "failed to add atom %x\n", i ); + } + } + + for (i = 0xc000; i <= 0xffff; i++) + { + ok( !GlobalAddAtomA((LPCSTR)i), "succeeded adding %x\n", i ); + if (unicode_OS) + ok( !GlobalAddAtomW((LPCWSTR)i), "succeeded adding %x\n", i ); + } +} + +static void test_get_atom_name(void) +{ + char buf[10]; + WCHAR bufW[10]; + int i; + UINT len; + static const WCHAR resultW[] = {'f','o','o','b','a','r',0,'.','.','.'}; + + ATOM atom = GlobalAddAtomA( "foobar" ); + + /* Get the name of the atom we added above */ + memset( buf, '.', sizeof(buf) ); + len = GlobalGetAtomNameA( atom, buf, 10 ); + ok( len == strlen("foobar"), "bad length %d\n", len ); + ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents\n" ); + + /* Repeat, unicode-style */ + if (unicode_OS) + { + for (i = 0; i < 10; i++) bufW[i] = '.'; + SetLastError( 0xdeadbeef ); + len = GlobalGetAtomNameW( atom, bufW, 10 ); + ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" ); + ok( len == lstrlenW(foobarW), "bad length %d\n", len ); + ok( !memcmp( bufW, resultW, 10*sizeof(WCHAR) ), "bad buffer contents\n" ); + } + + /* Check error code returns */ + memset(buf, '.', 10); + ok( !GlobalGetAtomNameA( atom, buf, 0 ), "succeeded\n" ); + ok( !memcmp( buf, "..........", 10 ), "should not touch buffer\n" ); + + if (unicode_OS) + { + static const WCHAR sampleW[10] = {'.','.','.','.','.','.','.','.','.','.'}; + + for (i = 0; i < 10; i++) bufW[i] = '.'; + ok( !GlobalGetAtomNameW( atom, bufW, 0 ), "succeeded\n" ); + ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer\n" ); + } + + /* Test integer atoms */ + for (i = 0; i <= 0xbfff; i++) + { + memset( buf, 'a', 10 ); + len = GlobalGetAtomNameA( (ATOM)i, buf, 10 ); + if (i) + { + char res[20]; + ok( (len > 1) && (len < 7), "bad length %d\n", len ); + sprintf( res, "#%d", i ); + memset( res + strlen(res) + 1, 'a', 10 ); + ok( !memcmp( res, buf, 10 ), "bad buffer contents %s\n", buf ); + } + else + ok( !len, "bad length %d\n", len ); + } +} + +static void test_error_handling(void) +{ + char buffer[260]; + WCHAR bufferW[260]; + int i; + + memset( buffer, 'a', 256 ); + buffer[256] = 0; + ok( !GlobalAddAtomA(buffer), "add succeeded\n" ); + ok( !GlobalFindAtomA(buffer), "find succeeded\n" ); + + if (unicode_OS) + { + for (i = 0; i < 256; i++) bufferW[i] = 'b'; + bufferW[256] = 0; + ok( !GlobalAddAtomW(bufferW), "add succeeded\n" ); + ok( !GlobalFindAtomW(bufferW), "find succeeded\n" ); + } +} + +static void test_local_add_atom(void) +{ + ATOM atom, w_atom; + int i; + + SetLastError( 0xdeadbeef ); + atom = AddAtomA( "foobar" ); + ok( atom >= 0xc000, "bad atom id %x\n", atom ); + ok( GetLastError() == 0xdeadbeef, "AddAtomA set last error\n" ); + + /* Verify that it can be found (or not) appropriately */ + ok( FindAtomA( "foobar" ) == atom, "could not find atom foobar\n" ); + ok( FindAtomA( "FOOBAR" ) == atom, "could not find atom FOOBAR\n" ); + ok( !FindAtomA( "_foobar" ), "found _foobar\n" ); + + /* Add the same atom, specifying string as unicode; should + * find the first one, not add a new one */ + SetLastError( 0xdeadbeef ); + w_atom = AddAtomW( foobarW ); + if (w_atom && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + unicode_OS = TRUE; + else + trace("WARNING: Unicode atom APIs are not supported on this platform\n"); + + if (unicode_OS) + { + ok( w_atom == atom, "Unicode atom does not match ASCII\n" ); + ok( GetLastError() == 0xdeadbeef, "AddAtomW set last error\n" ); + } + + /* Verify that it can be found (or not) appropriately via unicode name */ + if (unicode_OS) + { + ok( FindAtomW( foobarW ) == atom, "could not find atom foobar\n" ); + ok( FindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR\n" ); + ok( !FindAtomW( _foobarW ), "found _foobar\n" ); + } + + /* Test integer atoms + * (0x0001 .. 0xbfff) should be valid; + * (0xc000 .. 0xffff) should be invalid */ + + SetLastError( 0xdeadbeef ); + ok( AddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" ); + if (unicode_OS) + { + SetLastError( 0xdeadbeef ); + ok( AddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0\n" ); + } + + SetLastError( 0xdeadbeef ); + for (i = 1; i <= 0xbfff; i++) + { + SetLastError( 0xdeadbeef ); + ok( AddAtomA((LPCSTR)i) == i && GetLastError() == 0xdeadbeef, + "failed to add atom %x\n", i ); + if (unicode_OS) + { + SetLastError( 0xdeadbeef ); + ok( AddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef, + "failed to add atom %x\n", i ); + } + } + + for (i = 0xc000; i <= 0xffff; i++) + { + ok( !AddAtomA((LPCSTR)i), "succeeded adding %x\n", i ); + if (unicode_OS) + ok( !AddAtomW((LPCWSTR)i), "succeeded adding %x\n", i ); + } +} + +static void test_local_get_atom_name(void) +{ + char buf[10]; + WCHAR bufW[10]; + int i; + UINT len; + static const WCHAR resultW[] = {'f','o','o','b','a','r',0,'.','.','.'}; + + ATOM atom = AddAtomA( "foobar" ); + + /* Get the name of the atom we added above */ + memset( buf, '.', sizeof(buf) ); + len = GetAtomNameA( atom, buf, 10 ); + ok( len == strlen("foobar"), "bad length %d\n", len ); + ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents\n" ); + + /* Repeat, unicode-style */ + if (unicode_OS) + { + for (i = 0; i < 10; i++) bufW[i] = '.'; + SetLastError( 0xdeadbeef ); + len = GetAtomNameW( atom, bufW, 10 ); + ok( len && GetLastError() == 0xdeadbeef, "GetAtomNameW failed\n" ); + ok( len == lstrlenW(foobarW), "bad length %d\n", len ); + ok( !memcmp( bufW, resultW, 10*sizeof(WCHAR) ), "bad buffer contents\n" ); + } + + /* Check error code returns */ + memset(buf, '.', 10); + ok( !GetAtomNameA( atom, buf, 0 ), "succeeded\n" ); + ok( !memcmp( buf, "..........", 10 ), "should not touch buffer\n" ); + + if (unicode_OS) + { + static const WCHAR sampleW[10] = {'.','.','.','.','.','.','.','.','.','.'}; + + for (i = 0; i < 10; i++) bufW[i] = '.'; + ok( !GetAtomNameW( atom, bufW, 0 ), "succeeded\n" ); + ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer\n" ); + } + + /* Test integer atoms */ + for (i = 0; i <= 0xbfff; i++) + { + memset( buf, 'a', 10 ); + len = GetAtomNameA( (ATOM)i, buf, 10 ); + if (i) + { + char res[20]; + ok( (len > 1) && (len < 7), "bad length %d\n", len ); + sprintf( res, "#%d", i ); + memset( res + strlen(res) + 1, 'a', 10 ); + ok( !memcmp( res, buf, 10 ), "bad buffer contents %s\n", buf ); + } + else + ok( !len, "bad length %d\n", len ); + } +} + +static void test_local_error_handling(void) +{ + char buffer[260]; + WCHAR bufferW[260]; + int i; + + memset( buffer, 'a', 256 ); + buffer[256] = 0; + ok( !AddAtomA(buffer), "add succeeded\n" ); + ok( !FindAtomA(buffer), "find succeeded\n" ); + + if (unicode_OS) + { + for (i = 0; i < 256; i++) bufferW[i] = 'b'; + bufferW[256] = 0; + ok( !AddAtomW(bufferW), "add succeeded\n" ); + ok( !FindAtomW(bufferW), "find succeeded\n" ); + } +} + + +START_TEST(atom) +{ + test_add_atom(); + test_get_atom_name(); + test_error_handling(); + test_local_add_atom(); + test_local_get_atom_name(); + test_local_error_handling(); +} Property changes on: trunk/reactos/regtests/winetests/kernel32/atom.c ___________________________________________________________________ Name: svn:executable + * _____
Added: trunk/reactos/regtests/winetests/kernel32/change.c --- trunk/reactos/regtests/winetests/kernel32/change.c 2005-08-07 03:00:44 UTC (rev 17136) +++ trunk/reactos/regtests/winetests/kernel32/change.c 2005-08-07 03:14:17 UTC (rev 17137) @@ -0,0 +1,242 @@
+/* + * Tests for file change notification functions + * + * Copyright (c) 2004 Hans Leidekker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* TODO: - security attribute changes + * - compound filter and multiple notifications + * - subtree notifications + * - non-documented flags FILE_NOTIFY_CHANGE_LAST_ACCESS and + * FILE_NOTIFY_CHANGE_CREATION + */ + +#include <stdarg.h> +#include <stdio.h> + +#include "wine/test.h" +#include <windef.h> +#include <winbase.h> + +static DWORD CALLBACK NotificationThread(LPVOID arg) +{ + HANDLE change = (HANDLE) arg; + BOOL ret = FALSE; + DWORD status; + + status = WaitForSingleObject(change, 100); + + if (status == WAIT_OBJECT_0 ) { + ret = FindNextChangeNotification(change); + } + + ret = FindCloseChangeNotification(change); + ok( ret, "FindCloseChangeNotification error: %ld\n", + GetLastError()); + + ExitThread((DWORD)ret); +} + +static HANDLE StartNotificationThread(LPCSTR path, BOOL subtree, DWORD flags) +{ + HANDLE change, thread; + DWORD threadId; + + change = FindFirstChangeNotificationA(path, subtree, flags); + ok(change != INVALID_HANDLE_VALUE, "FindFirstChangeNotification error: %ld\n", GetLastError()); + + thread = CreateThread(NULL, 0, NotificationThread, (LPVOID)change, + 0, &threadId); + ok(thread != INVALID_HANDLE_VALUE, "CreateThread error: %ld\n", GetLastError()); + + return thread; +} + +static DWORD FinishNotificationThread(HANDLE thread) +{ + DWORD status, exitcode; + + status = WaitForSingleObject(thread, 5000); + ok(status == WAIT_OBJECT_0, "WaitForSingleObject status %ld error %ld\n", status, GetLastError()); + + ok(GetExitCodeThread(thread, &exitcode), "Could not retrieve thread exit code\n"); + + return exitcode; +} + +static void test_FindFirstChangeNotification(void) +{ + HANDLE change, file, thread; + DWORD attributes, count; + BOOL ret; + + char workdir[MAX_PATH], dirname1[MAX_PATH], dirname2[MAX_PATH]; + char filename1[MAX_PATH], filename2[MAX_PATH]; + static const char prefix[] = "FCN"; + char buffer[2048]; + + /* pathetic checks */ + + change = FindFirstChangeNotificationA("not-a-file", FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); + ok(change == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND, + "FindFirstChangeNotification error: %ld\n", GetLastError()); + + if (0) /* This documents win2k behavior. It crashes on win98. */ + { + change = FindFirstChangeNotificationA(NULL, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); + ok(change == NULL && GetLastError() == ERROR_PATH_NOT_FOUND, + "FindFirstChangeNotification error: %ld\n", GetLastError()); + } + + ret = FindNextChangeNotification(NULL); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "FindNextChangeNotification error: %ld\n", + GetLastError()); + + ret = FindCloseChangeNotification(NULL); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, "FindCloseChangeNotification error: %ld\n", + GetLastError()); + + ret = GetTempPathA(MAX_PATH, workdir); + ok(ret, "GetTempPathA error: %ld\n", GetLastError()); + + lstrcatA(workdir, "testFileChangeNotification"); + + ret = CreateDirectoryA(workdir, NULL); + ok(ret, "CreateDirectoryA error: %ld\n", GetLastError()); + + ret = GetTempFileNameA(workdir, prefix, 0, filename1); + ok(ret, "GetTempFileNameA error: %ld\n", GetLastError()); + + file = CreateFileA(filename1, GENERIC_WRITE|GENERIC_READ, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + ok(file != INVALID_HANDLE_VALUE, "CreateFileA error: %ld\n", GetLastError()); + ret = CloseHandle(file); + ok( ret, "CloseHandle error: %ld\n", GetLastError()); + + /* Try to register notification for a file. win98 and win2k behave differently here */ + change = FindFirstChangeNotificationA(filename1, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); + ok(change == INVALID_HANDLE_VALUE && (GetLastError() == ERROR_DIRECTORY || + GetLastError() == ERROR_FILE_NOT_FOUND), + "FindFirstChangeNotification error: %ld\n", GetLastError()); + + lstrcpyA(dirname1, filename1); + lstrcatA(dirname1, "dir"); + + ret = CreateDirectoryA(dirname1, NULL); + ok(ret, "CreateDirectoryA error: %ld\n", GetLastError()); + + /* What if we remove the directory we registered notification for? */ + thread = StartNotificationThread(dirname1, FALSE, FILE_NOTIFY_CHANGE_DIR_NAME); + ret = RemoveDirectoryA(dirname1); + ok(ret, "RemoveDirectoryA error: %ld\n", GetLastError()); + + /* win98 and win2k behave differently here */ + ret = FinishNotificationThread(thread); + ok(ret || !ret, "You'll never read this\n"); + + /* functional checks */ + + /* Create a directory */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_DIR_NAME); + ret = CreateDirectoryA(dirname1, NULL); + ok(ret, "CreateDirectoryA error: %ld\n", GetLastError()); + ok(FinishNotificationThread(thread), "Missed notification\n"); + + lstrcpyA(dirname2, dirname1); + lstrcatA(dirname2, "new"); + + /* Rename a directory */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_DIR_NAME); + ret = MoveFileA(dirname1, dirname2); + ok(ret, "MoveFileA error: %ld\n", GetLastError()); + ok(FinishNotificationThread(thread), "Missed notification\n"); + + /* Delete a directory */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_DIR_NAME); + ret = RemoveDirectoryA(dirname2); + ok(ret, "RemoveDirectoryA error: %ld\n", GetLastError()); + ok(FinishNotificationThread(thread), "Missed notification\n"); + + lstrcpyA(filename2, filename1); + lstrcatA(filename2, "new"); + + /* Rename a file */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); + ret = MoveFileA(filename1, filename2); + ok(ret, "MoveFileA error: %ld\n", GetLastError()); + ok(FinishNotificationThread(thread), "Missed notification\n"); + + /* Delete a file */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); + ret = DeleteFileA(filename2); + ok(ret, "DeleteFileA error: %ld\n", GetLastError()); + ok(FinishNotificationThread(thread), "Missed notification\n"); + + /* Create a file */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); + file = CreateFileA(filename2, GENERIC_WRITE|GENERIC_READ, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + ok(file != INVALID_HANDLE_VALUE, "CreateFileA error: %ld\n", GetLastError()); + ret = CloseHandle(file); + ok( ret, "CloseHandle error: %ld\n", GetLastError()); + ok(FinishNotificationThread(thread), "Missed notification\n"); + + attributes = GetFileAttributesA(filename2); + ok(attributes != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA error: %ld\n", GetLastError()); + attributes &= FILE_ATTRIBUTE_READONLY; + + /* Change file attributes */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_ATTRIBUTES); + ret = SetFileAttributesA(filename2, attributes); + ok(ret, "SetFileAttributesA error: %ld\n", GetLastError()); + ok(FinishNotificationThread(thread), "Missed notification\n"); + + /* Change last write time by writing to a file */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE); + file = CreateFileA(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + ok(file != INVALID_HANDLE_VALUE, "CreateFileA error: %ld\n", GetLastError()); + ret = WriteFile(file, buffer, sizeof(buffer), &count, NULL); + ok(ret && count == sizeof(buffer), "WriteFile error: %ld\n", GetLastError()); + ret = CloseHandle(file); + ok( ret, "CloseHandle error: %ld\n", GetLastError()); + ok(FinishNotificationThread(thread), "Missed notification\n"); + + /* Change file size by truncating a file */ + thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_SIZE); + file = CreateFileA(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + ok(file != INVALID_HANDLE_VALUE, "CreateFileA error: %ld\n", GetLastError()); + ret = WriteFile(file, buffer, sizeof(buffer) / 2, &count, NULL); + ok(ret && count == sizeof(buffer) / 2, "WriteFileA error: %ld\n", GetLastError()); [truncated at 1000 lines; 12413 more skipped]