update the winetest framework to 0.9.14 and sync some tests. Untested on ReactOS but at least it builds. More tests will come later. Fsck subversion

svn path=/trunk/; revision=22053
This commit is contained in:
Steven Edwards 2006-05-26 16:20:53 +00:00
parent 6e538fae59
commit a8373ada71
48 changed files with 16647 additions and 221 deletions

View file

@ -15,14 +15,15 @@
*
* 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
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_TEST_H
#define __WINE_TEST_H
#include <stdarg.h>
#include "windows.h"
#include <stdlib.h>
#include <windows.h>
/* prototype for dbgprint */
ULONG CDECL DbgPrint(IN PCH Format,IN ...);
@ -42,7 +43,14 @@ extern int winetest_loop_todo(void);
extern void winetest_end_todo( const char* platform );
extern int winetest_get_mainargs( char*** pargv );
#ifdef STANDALONE
#define START_TEST(name) \
static void func_##name(void); \
const struct test winetest_testlist[] = { { #name, func_##name }, { 0, 0 } }; \
static void func_##name(void)
#else
#define START_TEST(name) void func_##name(void)
#endif
#ifdef __GNUC__
@ -67,6 +75,7 @@ extern void winetest_trace( const char *msg, ... );
winetest_end_todo(platform))
#define todo_wine todo("wine")
#ifdef NONAMELESSUNION
# define U(x) (x).u
# define U1(x) (x).u1
@ -105,6 +114,7 @@ extern void winetest_trace( const char *msg, ... );
# define S5(x) (x)
#endif
/************************************************************************/
/* Below is the implementation of the various functions, to be included
* directly into the generated testlist.c file.
@ -112,7 +122,17 @@ extern void winetest_trace( const char *msg, ... );
* different includes or flags if needed.
*/
#ifdef WINETEST_WANT_MAIN
#ifdef STANDALONE
#include <stdio.h>
struct test
{
const char *name;
void (*func)(void);
};
extern const struct test winetest_testlist[];
/* debug level */
int winetest_debug = 1;
@ -204,14 +224,13 @@ int winetest_ok( int condition, const char *msg, ... )
{
fprintf( stdout, "%s:%d: Test succeeded inside todo block",
data->current_file, data->current_line );
if (msg && msg[0])
if (msg[0])
{
va_start(valist, msg);
fprintf(stdout,": ");
vfprintf(stdout, msg, valist);
va_end(valist);
}
fputc( '\n', stdout );
InterlockedIncrement(&todo_failures);
return 0;
}
@ -223,7 +242,7 @@ int winetest_ok( int condition, const char *msg, ... )
{
fprintf( stdout, "%s:%d: Test failed",
data->current_file, data->current_line );
if (msg && msg[0])
if (msg[0])
{
char string[1024];
va_start(valist, msg);
@ -265,7 +284,6 @@ void winetest_trace( const char *msg, ... )
fprintf( stdout, "%s:%d:", data->current_file, data->current_line );
va_start(valist, msg);
vfprintf(stdout, msg, valist);
vsprintf(string, msg, valist);
DbgPrint( "%s:%d: %s", data->current_file, data->current_line, string);
va_end(valist);
}
@ -322,6 +340,16 @@ static const struct test *find_test( const char *name )
}
/* Display list of valid tests */
static void list_tests(void)
{
const struct test *test;
fprintf( stdout, "Valid test names:\n" );
for (test = winetest_testlist; test->name; test++) fprintf( stdout, " %s\n", test->name );
}
/* Run a named test, and return exit status */
static int run_test( const char *name )
{
@ -353,11 +381,8 @@ static int run_test( const char *name )
/* Display usage and exit */
static void usage( const char *argv0 )
{
const struct test *test;
fprintf( stdout, "Usage: %s test_name\n", argv0 );
fprintf( stdout, "\nValid test names:\n" );
for (test = winetest_testlist; test->name; test++) fprintf( stdout, " %s\n", test->name );
fprintf( stdout, "Usage: %s test_name\n\n", argv0 );
list_tests();
exit_process(1);
}
@ -367,18 +392,29 @@ int main( int argc, char **argv )
{
char *p;
setvbuf (stdout, NULL, _IONBF, 0);
winetest_argc = argc;
winetest_argv = argv;
if ((p = getenv( "WINETEST_PLATFORM" ))) winetest_platform = p;
if ((p = getenv( "WINETEST_PLATFORM" ))) winetest_platform = strdup(p);
if ((p = getenv( "WINETEST_DEBUG" ))) winetest_debug = atoi(p);
if ((p = getenv( "WINETEST_INTERACTIVE" ))) winetest_interactive = atoi(p);
if ((p = getenv( "WINETEST_REPORT_SUCCESS"))) report_success = atoi(p);
if (!argv[1]) usage( argv[0] );
if (!argv[1])
{
if (winetest_testlist[0].name && !winetest_testlist[1].name) /* only one test */
return run_test( winetest_testlist[0].name );
usage( argv[0] );
}
if (!strcmp( argv[1], "--list" ))
{
list_tests();
return 0;
}
return run_test(argv[1]);
}
#endif /* WINETEST_WANT_MAIN */
#endif /* STANDALONE */
#endif /* __WINE_TEST_H */

View file

@ -1,27 +1,29 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_crypt(void);
extern void func_crypt_lmhash(void);
extern void func_crypt_md4(void);
extern void func_crypt_md5(void);
extern void func_crypt_sha(void);
extern void func_lsa(void);
extern void func_registry(void);
extern void func_security(void);
struct test
const struct test winetest_testlist[] =
{
const char *name;
void (*func)(void);
};
static const struct test winetest_testlist[] =
{
{ "registry", func_registry },
/* { "crypt", func_crypt },
{ "crypt_lmhash", func_crypt_lmhash },
{ "crypt_md4", func_crypt_md4 },
{ "crypt_md5", func_crypt_md5 },
{ "crypt_sha", func_crypt_sha },
{ "lsa", func_lsa },
*/ { "registry", func_registry },
{ "security", func_security },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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.dwPageSize);
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();
}

View file

@ -0,0 +1,624 @@
/*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winuser.h"
#define DOUBLE(x) (WCHAR)((x<<8)|(x))
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 void do_initA(char* tmp, const char* pattern, int len)
{
const char* p = pattern;
while (len--)
{
*tmp++ = *p++;
if (!*p) p = pattern;
}
*tmp = '\0';
}
static void do_initW(WCHAR* tmp, const char* pattern, int len)
{
const char* p = pattern;
while (len--)
{
*tmp++ = *p++;
if (!*p) p = pattern;
}
*tmp = '\0';
}
static void print_integral( WCHAR* buffer, int atom )
{
BOOL first = TRUE;
#define X(v) { if (atom >= v) {*buffer++ = '0' + atom / v; first = FALSE; } else if (!first || v == 1) *buffer++ = '0'; atom %= v; }
*buffer++ = '#';
X(10000);
X(1000);
X(100);
X(10);
X(1);
*buffer = '\0';
#undef X
}
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,'.','.','.'};
char in[257], out[257];
WCHAR inW[257], outW[257];
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 );
SetLastError(0xdeadbeef);
len = GlobalGetAtomNameA( (ATOM)i, buf, 2);
if (!len) /* the NT way */
{
ok(GetLastError() == (i ? ERROR_MORE_DATA : ERROR_INVALID_PARAMETER) ||
GetLastError() == 0xdeadbeef, /* the Win 9x way */
"wrong error conditions %lu for %u\n", GetLastError(), i);
}
else /* the Win 9x way */
{
ok(GetLastError() == 0xdeadbeef,
"wrong error conditions %lu for %u\n", GetLastError(), i);
}
}
memset( buf, '.', sizeof(buf) );
len = GlobalGetAtomNameA( atom, buf, 6 );
ok( len == 0, "bad length %d\n", len );
ok( !memcmp( buf, "fooba\0....", 10 ), "bad buffer contents\n");
if (unicode_OS)
{
static const WCHAR resW[] = {'f','o','o','b','a','r','.','.','.','.'};
for (len = 0; len < 10; len++) bufW[len] = '.';
SetLastError(0xdeadbeef);
len = GlobalGetAtomNameW( atom, bufW, 6 );
ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" );
ok( len == lstrlenW(foobarW), "bad length %d\n", len );
ok( !memcmp( bufW, resW, 10*sizeof(WCHAR) ), "bad buffer contents\n" );
}
/* test string limits & overflow */
do_initA(in, "abcdefghij", 255);
atom = GlobalAddAtomA(in);
ok(atom, "couldn't add atom for %s\n", in);
len = GlobalGetAtomNameA(atom, out, sizeof(out));
ok(len == 255, "length mismatch (%u instead of 255)\n", len);
for (i = 0; i < 255; i++)
{
ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
}
ok(out[255] == '\0', "wrong end of string\n");
memset(out, '.', sizeof(out));
SetLastError(0xdeadbeef);
len = GlobalGetAtomNameA(atom, out, 10);
if (!len) /* the NT way */
{
ok(GetLastError() == ERROR_MORE_DATA, "wrong error code (%lu instead of %u)\n", GetLastError(), ERROR_MORE_DATA);
}
else /* the Win9x way */
{
ok(GetLastError() == 0xdeadbeef, "wrong error code (%lu instead of %u)\n", GetLastError(), 0xdeadbeef);
}
for (i = 0; i < 9; i++)
{
ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
}
ok(out[9] == '\0', "wrong end of string\n");
ok(out[10] == '.', "wrote after end of buf\n");
do_initA(in, "abcdefghij", 256);
atom = GlobalAddAtomA(in);
ok(!atom, "succeeded\n");
if (unicode_OS)
{
/* test integral atoms */
for (i = 0; i <= 0xbfff; i++)
{
memset(outW, 'a', sizeof(outW));
len = GlobalGetAtomNameW( (ATOM)i, outW, 10 );
if (i)
{
WCHAR res[20];
ok( (len > 1) && (len < 7), "bad length %d\n", len );
print_integral( res, i );
memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR));
ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i );
}
else
ok( !len, "bad length %d\n", len );
memset(outW, '.', sizeof(outW));
SetLastError(0xdeadbeef);
len = GlobalGetAtomNameW( (ATOM)i, outW, 1);
if (i)
{
/* len == 0 with ERROR_MORE_DATA is on NT3.51 */
ok(len == 1 || (len == 0 && GetLastError() == ERROR_MORE_DATA),
"0x%04x: got %u with %ld (excepted '1' or '0' with " \
"ERROR_MORE_DATA)\n", i, len, GetLastError());
ok(outW[1] == DOUBLE('.'), "buffer overwrite\n");
}
else ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "0 badly handled\n");
}
do_initW(inW, "abcdefghij", 255);
atom = GlobalAddAtomW(inW);
ok(atom, "couldn't add atom for %s\n", in);
len = GlobalGetAtomNameW(atom, outW, sizeof(outW));
ok(len == 255, "length mismatch (%u instead of 255)\n", len);
for (i = 0; i < 255; i++)
{
ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
}
ok(outW[255] == '\0', "wrong end of string\n");
memset(outW, '.', sizeof(outW));
len = GlobalGetAtomNameW(atom, outW, 10);
ok(len == 10, "succeeded\n");
for (i = 0; i < 10; i++)
{
ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
}
ok(outW[10] == DOUBLE('.'), "wrote after end of buf\n");
do_initW(inW, "abcdefghij", 256);
atom = GlobalAddAtomW(inW);
ok(!atom, "succeeded\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error code\n");
}
}
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], in[257], out[257];
WCHAR bufW[10], inW[257], outW[257];
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" );
}
/* Get the name of the atom we added above */
memset( buf, '.', sizeof(buf) );
len = GetAtomNameA( atom, buf, 6 );
ok( len == 5, "bad length %d\n", len );
ok( !memcmp( buf, "fooba\0....", 10 ), "bad buffer contents\n" );
/* Repeat, unicode-style */
if (unicode_OS)
{
WCHAR resW[] = {'f','o','o','b','a','\0','.','.','.','.'};
for (i = 0; i < 10; i++) bufW[i] = '.';
SetLastError( 0xdeadbeef );
len = GetAtomNameW( atom, bufW, 6 );
ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" );
ok( len == 5, "bad length %d\n", len );
ok( !memcmp( bufW, resW, 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 for %s\n", len, buf );
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 );
len = GetAtomNameA( (ATOM)i, buf, 1);
ok(!len, "succeed with %u for %u\n", len, i);
/* ERROR_MORE_DATA is on nt3.51 sp5 */
if (i)
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
GetLastError() == ERROR_MORE_DATA ||
GetLastError() == 0xdeadbeef, /* the Win 9x way */
"wrong error conditions %lu for %u\n", GetLastError(), i);
else
ok(GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_MORE_DATA ||
GetLastError() == 0xdeadbeef, /* the Win 9x way */
"wrong error conditions %lu for %u\n", GetLastError(), i);
}
/* test string limits & overflow */
do_initA(in, "abcdefghij", 255);
atom = AddAtomA(in);
ok(atom, "couldn't add atom for %s\n", in);
len = GetAtomNameA(atom, out, sizeof(out));
ok(len == 255, "length mismatch (%u instead of 255)\n", len);
for (i = 0; i < 255; i++)
{
ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
}
ok(out[255] == '\0', "wrong end of string\n");
memset(out, '.', sizeof(out));
len = GetAtomNameA(atom, out, 10);
ok(len == 9, "succeeded %d\n", len);
for (i = 0; i < 9; i++)
{
ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]);
}
ok(out[9] == '\0', "wrong end of string\n");
ok(out[10] == '.', "buffer overwrite\n");
do_initA(in, "abcdefghij", 256);
atom = AddAtomA(in);
ok(!atom, "succeeded\n");
/* ERROR_MORE_DATA is on nt3.51 sp5 */
ok(GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_MORE_DATA ||
GetLastError() == 0xdeadbeef, /* the Win 9x way */
"wrong error code (%lu)\n", GetLastError());
if (unicode_OS)
{
/* test integral atoms */
for (i = 0; i <= 0xbfff; i++)
{
memset(outW, 'a', sizeof(outW));
len = GetAtomNameW( (ATOM)i, outW, 10 );
if (i)
{
WCHAR res[20];
ok( (len > 1) && (len < 7), "bad length %d\n", len );
print_integral( res, i );
memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR));
ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i );
}
else
ok( !len, "bad length %d\n", len );
len = GetAtomNameW( (ATOM)i, outW, 1);
ok(!len, "succeed with %u for %u\n", len, i);
/* ERROR_MORE_DATA is on nt3.51 sp5 */
ok(GetLastError() == ERROR_MORE_DATA ||
GetLastError() == (i ? ERROR_INSUFFICIENT_BUFFER : ERROR_INVALID_PARAMETER),
"wrong error conditions %lu for %u\n", GetLastError(), i);
}
do_initW(inW, "abcdefghij", 255);
atom = AddAtomW(inW);
ok(atom, "couldn't add atom for %s\n", in);
len = GetAtomNameW(atom, outW, sizeof(outW));
ok(len == 255, "length mismatch (%u instead of 255)\n", len);
for (i = 0; i < 255; i++)
{
ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
}
ok(outW[255] == '\0', "wrong end of string\n");
memset(outW, '.', sizeof(outW));
len = GetAtomNameW(atom, outW, 10);
ok(len == 9, "succeeded %d\n", len);
for (i = 0; i < 9; i++)
{
ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]);
}
ok(outW[9] == '\0', "wrong end of string\n");
ok(outW[10] == DOUBLE('.'), "buffer overwrite\n");
do_initW(inW, "abcdefghij", 256);
atom = AddAtomW(inW);
ok(!atom, "succeeded\n");
/* ERROR_MORE_DATA is on nt3.51 sp5 */
ok(GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_MORE_DATA,
"wrong error code (%lu)\n", GetLastError());
}
}
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();
}

View file

@ -0,0 +1,713 @@
/*
* Tests for file change notification functions
*
* Copyright (c) 2004 Hans Leidekker
* Copyright 2006 Mike McCormack for CodeWeavers
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/test.h"
#include <windef.h>
#include <winbase.h>
#include <winternl.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");
lstrcpyA(dirname2, dirname1);
lstrcatA(dirname2, "new");
ret = CreateDirectoryA(dirname1, NULL);
ok(ret, "CreateDirectoryA error: %ld\n", GetLastError());
/* What if we move the directory we registered notification for? */
thread = StartNotificationThread(dirname1, FALSE, FILE_NOTIFY_CHANGE_DIR_NAME);
ret = MoveFileA(dirname1, dirname2);
ok(ret, "MoveFileA error: %ld\n", GetLastError());
ok(FinishNotificationThread(thread), "Missed notification\n");
/* What if we remove the directory we registered notification for? */
thread = StartNotificationThread(dirname2, FALSE, FILE_NOTIFY_CHANGE_DIR_NAME);
ret = RemoveDirectoryA(dirname2);
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");
/* 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());
ret = CloseHandle(file);
ok( ret, "CloseHandle error: %ld\n", GetLastError());
ok(FinishNotificationThread(thread), "Missed notification\n");
/* clean up */
ret = DeleteFileA(filename2);
ok(ret, "DeleteFileA error: %ld\n", GetLastError());
ret = RemoveDirectoryA(workdir);
ok(ret, "RemoveDirectoryA error: %ld\n", GetLastError());
}
/* this test concentrates more on the wait behaviour of the handle */
static void test_ffcn(void)
{
DWORD filter;
HANDLE handle;
LONG r;
WCHAR path[MAX_PATH], subdir[MAX_PATH];
static const WCHAR szBoo[] = { '\\','b','o','o',0 };
static const WCHAR szHoo[] = { '\\','h','o','o',0 };
r = GetTempPathW( MAX_PATH, path );
ok( r != 0, "temp path failed\n");
if (!r)
return;
lstrcatW( path, szBoo );
lstrcpyW( subdir, path );
lstrcatW( subdir, szHoo );
RemoveDirectoryW( subdir );
RemoveDirectoryW( path );
r = CreateDirectoryW(path, NULL);
ok( r == TRUE, "failed to create directory\n");
filter = FILE_NOTIFY_CHANGE_FILE_NAME;
filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
handle = FindFirstChangeNotificationW( path, 1, filter);
ok( handle != INVALID_HANDLE_VALUE, "invalid handle\n");
r = WaitForSingleObject( handle, 0 );
ok( r == STATUS_TIMEOUT, "should time out\n");
r = CreateDirectoryW( subdir, NULL );
ok( r == TRUE, "failed to create subdir\n");
r = WaitForSingleObject( handle, 0 );
ok( r == WAIT_OBJECT_0, "should be ready\n");
r = WaitForSingleObject( handle, 0 );
ok( r == WAIT_OBJECT_0, "should be ready\n");
r = FindNextChangeNotification(handle);
ok( r == TRUE, "find next failed\n");
r = WaitForSingleObject( handle, 0 );
ok( r == STATUS_TIMEOUT, "should time out\n");
r = RemoveDirectoryW( subdir );
ok( r == TRUE, "failed to remove subdir\n");
r = WaitForSingleObject( handle, 0 );
ok( r == WAIT_OBJECT_0, "should be ready\n");
r = WaitForSingleObject( handle, 0 );
ok( r == WAIT_OBJECT_0, "should be ready\n");
r = FindNextChangeNotification(handle);
ok( r == TRUE, "find next failed\n");
r = FindNextChangeNotification(handle);
ok( r == TRUE, "find next failed\n");
r = FindCloseChangeNotification(handle);
ok( r == TRUE, "should succeed\n");
r = RemoveDirectoryW( path );
ok( r == TRUE, "failed to remove dir\n");
}
typedef BOOL (WINAPI *fnReadDirectoryChangesW)(HANDLE,LPVOID,DWORD,BOOL,DWORD,
LPDWORD,LPOVERLAPPED,LPOVERLAPPED_COMPLETION_ROUTINE);
fnReadDirectoryChangesW pReadDirectoryChangesW;
static void test_readdirectorychanges(void)
{
HANDLE hdir;
char buffer[0x1000];
DWORD fflags, filter = 0, r, dwCount;
OVERLAPPED ov;
WCHAR path[MAX_PATH], subdir[MAX_PATH], subsubdir[MAX_PATH];
static const WCHAR szBoo[] = { '\\','b','o','o',0 };
static const WCHAR szHoo[] = { '\\','h','o','o',0 };
static const WCHAR szGa[] = { '\\','h','o','o','\\','g','a',0 };
PFILE_NOTIFY_INFORMATION pfni;
if (!pReadDirectoryChangesW)
return;
r = GetTempPathW( MAX_PATH, path );
ok( r != 0, "temp path failed\n");
if (!r)
return;
lstrcatW( path, szBoo );
lstrcpyW( subdir, path );
lstrcatW( subdir, szHoo );
lstrcpyW( subsubdir, path );
lstrcatW( subsubdir, szGa );
RemoveDirectoryW( subsubdir );
RemoveDirectoryW( subdir );
RemoveDirectoryW( path );
r = CreateDirectoryW(path, NULL);
ok( r == TRUE, "failed to create directory\n");
SetLastError(0xd0b00b00);
r = pReadDirectoryChangesW(NULL,NULL,0,FALSE,0,NULL,NULL,NULL);
ok(GetLastError()==ERROR_INVALID_PARAMETER,"last error wrong\n");
ok(r==FALSE, "should return false\n");
fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE|FILE_LIST_DIRECTORY,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, fflags, NULL);
ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
ov.hEvent = CreateEvent( NULL, 1, 0, NULL );
SetLastError(0xd0b00b00);
r = pReadDirectoryChangesW(hdir,NULL,0,FALSE,0,NULL,NULL,NULL);
ok(GetLastError()==ERROR_INVALID_PARAMETER,"last error wrong\n");
ok(r==FALSE, "should return false\n");
SetLastError(0xd0b00b00);
r = pReadDirectoryChangesW(hdir,NULL,0,FALSE,0,NULL,&ov,NULL);
ok(GetLastError()==ERROR_INVALID_PARAMETER,"last error wrong\n");
ok(r==FALSE, "should return false\n");
filter = FILE_NOTIFY_CHANGE_FILE_NAME;
filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
filter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
filter |= FILE_NOTIFY_CHANGE_SIZE;
filter |= FILE_NOTIFY_CHANGE_LAST_WRITE;
filter |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
filter |= FILE_NOTIFY_CHANGE_CREATION;
filter |= FILE_NOTIFY_CHANGE_SECURITY;
SetLastError(0xd0b00b00);
ov.Internal = 0;
ov.InternalHigh = 0;
memset( buffer, 0, sizeof buffer );
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,-1,NULL,&ov,NULL);
ok(GetLastError()==ERROR_INVALID_PARAMETER,"last error wrong\n");
ok(r==FALSE, "should return false\n");
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,0,NULL,&ov,NULL);
ok(GetLastError()==ERROR_INVALID_PARAMETER,"last error wrong\n");
ok(r==FALSE, "should return false\n");
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,TRUE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
r = WaitForSingleObject( ov.hEvent, 10 );
ok( r == STATUS_TIMEOUT, "should timeout\n" );
r = CreateDirectoryW( subdir, NULL );
ok( r == TRUE, "failed to create directory\n");
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "event should be ready\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x12, "ov.InternalHigh wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
ok( pfni->FileNameLength == 6, "len wrong\n" );
ok( !memcmp(pfni->FileName,&szHoo[1],6), "name wrong\n" );
ResetEvent(ov.hEvent);
SetLastError(0xd0b00b00);
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,0,NULL,NULL,NULL);
ok(GetLastError()==ERROR_INVALID_PARAMETER,"last error wrong\n");
ok(r==FALSE, "should return false\n");
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,0,NULL,&ov,NULL);
ok(GetLastError()==ERROR_INVALID_PARAMETER,"last error wrong\n");
ok(r==FALSE, "should return false\n");
filter = FILE_NOTIFY_CHANGE_SIZE;
SetEvent(ov.hEvent);
ov.Internal = 1;
ov.InternalHigh = 1;
S(U(ov)).Offset = 0;
S(U(ov)).OffsetHigh = 0;
memset( buffer, 0, sizeof buffer );
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
ok( ov.Internal == STATUS_PENDING, "ov.Internal wrong\n");
ok( ov.InternalHigh == 1, "ov.InternalHigh wrong\n");
r = WaitForSingleObject( ov.hEvent, 0 );
ok( r == STATUS_TIMEOUT, "should timeout\n" );
r = RemoveDirectoryW( subdir );
ok( r == TRUE, "failed to remove directory\n");
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x12, "ov.InternalHigh wrong\n");
r = GetOverlappedResult( hdir, &ov, &dwCount, TRUE );
ok( r == TRUE, "getoverlappedresult failed\n");
ok( dwCount == 0x12, "count wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
ok( pfni->Action == FILE_ACTION_REMOVED, "action wrong\n" );
ok( pfni->FileNameLength == 6, "len wrong\n" );
ok( !memcmp(pfni->FileName,&szHoo[1],6), "name wrong\n" );
/* what happens if the buffer is too small? */
r = pReadDirectoryChangesW(hdir,buffer,0x10,FALSE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
r = CreateDirectoryW( subdir, NULL );
ok( r == TRUE, "failed to create directory\n");
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
ok( ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0, "ov.InternalHigh wrong\n");
/* test the recursive watch */
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
r = CreateDirectoryW( subsubdir, NULL );
ok( r == TRUE, "failed to create directory\n");
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x18, "ov.InternalHigh wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
ok( pfni->FileNameLength == 0x0c, "len wrong\n" );
ok( !memcmp(pfni->FileName,&szGa[1],6), "name wrong\n" );
r = RemoveDirectoryW( subsubdir );
ok( r == TRUE, "failed to remove directory\n");
ov.Internal = 1;
ov.InternalHigh = 1;
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
r = RemoveDirectoryW( subdir );
ok( r == TRUE, "failed to remove directory\n");
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
ok( pfni->Action == FILE_ACTION_REMOVED, "action wrong\n" );
ok( pfni->FileNameLength == 0x0c, "len wrong\n" );
ok( !memcmp(pfni->FileName,&szGa[1],6), "name wrong\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x18, "ov.InternalHigh wrong\n");
CloseHandle(hdir);
r = RemoveDirectoryW( path );
ok( r == TRUE, "failed to remove directory\n");
}
/* show the behaviour when a null buffer is passed */
static void test_readdirectorychanges_null(void)
{
NTSTATUS r;
HANDLE hdir;
char buffer[0x1000];
DWORD fflags, filter = 0;
OVERLAPPED ov;
WCHAR path[MAX_PATH], subdir[MAX_PATH];
static const WCHAR szBoo[] = { '\\','b','o','o',0 };
static const WCHAR szHoo[] = { '\\','h','o','o',0 };
PFILE_NOTIFY_INFORMATION pfni;
if (!pReadDirectoryChangesW)
return;
r = GetTempPathW( MAX_PATH, path );
ok( r != 0, "temp path failed\n");
if (!r)
return;
lstrcatW( path, szBoo );
lstrcpyW( subdir, path );
lstrcatW( subdir, szHoo );
RemoveDirectoryW( subdir );
RemoveDirectoryW( path );
r = CreateDirectoryW(path, NULL);
ok( r == TRUE, "failed to create directory\n");
fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE|FILE_LIST_DIRECTORY,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, fflags, NULL);
ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
ov.hEvent = CreateEvent( NULL, 1, 0, NULL );
filter = FILE_NOTIFY_CHANGE_FILE_NAME;
filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
SetLastError(0xd0b00b00);
ov.Internal = 0;
ov.InternalHigh = 0;
memset( buffer, 0, sizeof buffer );
r = pReadDirectoryChangesW(hdir,NULL,0,FALSE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
r = WaitForSingleObject( ov.hEvent, 0 );
ok( r == STATUS_TIMEOUT, "should timeout\n" );
r = CreateDirectoryW( subdir, NULL );
ok( r == TRUE, "failed to create directory\n");
r = WaitForSingleObject( ov.hEvent, 0 );
ok( r == WAIT_OBJECT_0, "event should be ready\n" );
ok( ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0, "ov.InternalHigh wrong\n");
ov.Internal = 0;
ov.InternalHigh = 0;
S(U(ov)).Offset = 0;
S(U(ov)).OffsetHigh = 0;
memset( buffer, 0, sizeof buffer );
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,FALSE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
r = WaitForSingleObject( ov.hEvent, 0 );
ok( r == STATUS_TIMEOUT, "should timeout\n" );
r = RemoveDirectoryW( subdir );
ok( r == TRUE, "failed to remove directory\n");
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "should be ready\n" );
ok( ov.Internal == STATUS_NOTIFY_ENUM_DIR, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0, "ov.InternalHigh wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
CloseHandle(hdir);
r = RemoveDirectoryW( path );
ok( r == TRUE, "failed to remove directory\n");
}
static void test_readdirectorychanges_filedir(void)
{
NTSTATUS r;
HANDLE hdir, hfile;
char buffer[0x1000];
DWORD fflags, filter = 0;
OVERLAPPED ov;
WCHAR path[MAX_PATH], subdir[MAX_PATH], file[MAX_PATH];
static const WCHAR szBoo[] = { '\\','b','o','o',0 };
static const WCHAR szHoo[] = { '\\','h','o','o',0 };
static const WCHAR szFoo[] = { '\\','f','o','o',0 };
PFILE_NOTIFY_INFORMATION pfni;
r = GetTempPathW( MAX_PATH, path );
ok( r != 0, "temp path failed\n");
if (!r)
return;
lstrcatW( path, szBoo );
lstrcpyW( subdir, path );
lstrcatW( subdir, szHoo );
lstrcpyW( file, path );
lstrcatW( file, szFoo );
DeleteFileW( file );
RemoveDirectoryW( subdir );
RemoveDirectoryW( path );
r = CreateDirectoryW(path, NULL);
ok( r == TRUE, "failed to create directory\n");
fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE|FILE_LIST_DIRECTORY,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, fflags, NULL);
ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
ov.hEvent = CreateEvent( NULL, 0, 0, NULL );
filter = FILE_NOTIFY_CHANGE_FILE_NAME;
r = pReadDirectoryChangesW(hdir,buffer,sizeof buffer,TRUE,filter,NULL,&ov,NULL);
ok(r==TRUE, "should return true\n");
r = WaitForSingleObject( ov.hEvent, 10 );
ok( r == WAIT_TIMEOUT, "should timeout\n" );
r = CreateDirectoryW( subdir, NULL );
ok( r == TRUE, "failed to create directory\n");
hfile = CreateFileW( file, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );
ok( hfile != INVALID_HANDLE_VALUE, "failed to create file\n");
ok( CloseHandle(hfile), "failed toc lose file\n");
r = WaitForSingleObject( ov.hEvent, 1000 );
ok( r == WAIT_OBJECT_0, "event should be ready\n" );
ok( ov.Internal == STATUS_SUCCESS, "ov.Internal wrong\n");
ok( ov.InternalHigh == 0x12, "ov.InternalHigh wrong\n");
pfni = (PFILE_NOTIFY_INFORMATION) buffer;
ok( pfni->NextEntryOffset == 0, "offset wrong\n" );
ok( pfni->Action == FILE_ACTION_ADDED, "action wrong\n" );
ok( pfni->FileNameLength == 6, "len wrong\n" );
ok( !memcmp(pfni->FileName,&szFoo[1],6), "name wrong\n" );
r = DeleteFileW( file );
ok( r == TRUE, "failed to delete file\n");
r = RemoveDirectoryW( subdir );
ok( r == TRUE, "failed to remove directory\n");
CloseHandle(hdir);
r = RemoveDirectoryW( path );
ok( r == TRUE, "failed to remove directory\n");
}
START_TEST(change)
{
HMODULE hkernel32 = GetModuleHandle("kernel32");
pReadDirectoryChangesW = (fnReadDirectoryChangesW)
GetProcAddress(hkernel32, "ReadDirectoryChangesW");
test_FindFirstChangeNotification();
test_ffcn();
test_readdirectorychanges();
test_readdirectorychanges_null();
test_readdirectorychanges_filedir();
}

View file

@ -0,0 +1,90 @@
/*
* Unit tests for code page to/from unicode translations
*
* Copyright (c) 2002 Dmitry Timoshkov
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
static void test_null_source(void)
{
int len;
DWORD GLE;
SetLastError(0);
len = WideCharToMultiByte(CP_ACP, 0, NULL, 0, NULL, 0, NULL, NULL);
GLE = GetLastError();
ok(!len && GLE == ERROR_INVALID_PARAMETER,
"WideCharToMultiByte returned %d with GLE=%ld (expected 0 with ERROR_INVALID_PARAMETER)\n",
len, GLE);
}
/* lstrcmpW is not supported on Win9x! */
static int mylstrcmpW(const WCHAR* str1, const WCHAR* str2)
{
while (*str1 && *str1==*str2) {
str1++;
str2++;
}
return *str1-*str2;
}
static void test_negative_source_length(void)
{
int len;
char buf[10];
WCHAR bufW[10];
static const WCHAR foobarW[] = {'f','o','o','b','a','r',0};
/* Test, whether any negative source length works as strlen() + 1 */
SetLastError( 0xdeadbeef );
memset(buf,'x',sizeof(buf));
len = WideCharToMultiByte(CP_ACP, 0, foobarW, -2002, buf, 10, NULL, NULL);
ok(len == 7 && !lstrcmpA(buf, "foobar") && GetLastError() == 0xdeadbeef,
"WideCharToMultiByte(-2002): len=%d error=%ld\n",len,GetLastError());
SetLastError( 0xdeadbeef );
memset(bufW,'x',sizeof(bufW));
len = MultiByteToWideChar(CP_ACP, 0, "foobar", -2002, bufW, 10);
ok(len == 7 && !mylstrcmpW(bufW, foobarW) && GetLastError() == 0xdeadbeef,
"MultiByteToWideChar(-2002): len=%d error=%ld\n",len,GetLastError());
}
static void test_overlapped_buffers(void)
{
static const WCHAR strW[] = {'j','u','s','t',' ','a',' ','t','e','s','t',0};
static const char strA[] = "just a test";
char buf[256];
int ret;
lstrcpyW((WCHAR *)(buf + 1), strW);
ret = WideCharToMultiByte(CP_ACP, 0, (WCHAR *)(buf + 1), -1, buf, sizeof(buf), NULL, NULL);
ok(ret == sizeof(strA), "unexpected ret %d != %d\n", ret, sizeof(strA));
ok(!memcmp(buf, strA, sizeof(strA)), "conversion failed: %s\n", buf);
}
START_TEST(codepage)
{
test_null_source();
test_negative_source_length();
test_overlapped_buffers();
}

View file

@ -1,31 +1,41 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_comboex(void);
extern void func_dpa(void);
extern void func_header(void);
extern void func_imagelist(void);
extern void func_monthcal(void);
extern void func_mru(void);
extern void func_progress(void);
extern void func_propsheet(void);
extern void func_subclass(void);
extern void func_tab(void);
extern void func_toolbar(void);
extern void func_tooltips(void);
extern void func_treeview(void);
extern void func_updown(void);
struct test
{
const char *name;
void (*func)(void);
};
static const struct test winetest_testlist[] =
const struct test winetest_testlist[] =
{
// { "comboex", func_comboex },
{ "dpa", func_dpa },
// { "header", func_header },
// { "imagelist", func_imagelist },
// { "monthcal", func_monthcal },
{ "mru", func_mru },
// { "progress", func_progress },
// { "propsheet", func_propsheet },
{ "subclass", func_subclass },
{ "tab", func_tab },
// { "toolbar", func_toolbar },
// { "tooltips", func_tooltips },
// { "treeview", func_treeview },
// { "updown", func_updown },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,593 @@
/*
* Unit tests for console API
*
* Copyright (c) 2003,2004 Eric Pouech
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/test.h"
#include <windows.h>
#include <stdio.h>
/* DEFAULT_ATTRIB is used for all initial filling of the console.
* all modifications are made with TEST_ATTRIB so that we could check
* what has to be modified or not
*/
#define TEST_ATTRIB (BACKGROUND_BLUE | FOREGROUND_GREEN)
#define DEFAULT_ATTRIB (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED)
/* when filling the screen with non-blank chars, this macro defines
* what character should be at position 'c'
*/
#define CONTENT(c) ('A' + (((c).Y * 17 + (c).X) % 23))
#define okCURSOR(hCon, c) do { \
CONSOLE_SCREEN_BUFFER_INFO __sbi; \
BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
__sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
(c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
} while (0)
#define okCHAR(hCon, c, ch, attr) do { \
char __ch; WORD __attr; DWORD __len; BOOL expect; \
expect = ReadConsoleOutputCharacter((hCon), &__ch, 1, (c), &__len) == 1 && __len == 1 && __ch == (ch); \
ok(expect, "At (%d,%d): expecting char '%c'/%02x got '%c'/%02x\n", (c).X, (c).Y, (ch), (ch), __ch, __ch); \
expect = ReadConsoleOutputAttribute((hCon), &__attr, 1, (c), &__len) == 1 && __len == 1 && __attr == (attr); \
ok(expect, "At (%d,%d): expecting attr %04x got %04x\n", (c).X, (c).Y, (attr), __attr); \
} while (0)
/* FIXME: this could be optimized on a speed point of view */
static void resetContent(HANDLE hCon, COORD sbSize, BOOL content)
{
COORD c;
WORD attr = DEFAULT_ATTRIB;
char ch;
DWORD len;
for (c.X = 0; c.X < sbSize.X; c.X++)
{
for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
{
ch = (content) ? CONTENT(c) : ' ';
WriteConsoleOutputAttribute(hCon, &attr, 1, c, &len);
WriteConsoleOutputCharacterA(hCon, &ch, 1, c, &len);
}
}
}
static void testCursor(HANDLE hCon, COORD sbSize)
{
COORD c;
c.X = c.Y = 0;
ok(SetConsoleCursorPosition(0, c) == 0, "No handle\n");
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %lu\n",
ERROR_INVALID_HANDLE, GetLastError());
c.X = c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
okCURSOR(hCon, c);
c.X = sbSize.X - 1;
c.Y = sbSize.Y - 1;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in lower-right\n");
okCURSOR(hCon, c);
c.X = sbSize.X;
c.Y = sbSize.Y - 1;
ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
ERROR_INVALID_PARAMETER, GetLastError());
c.X = sbSize.X - 1;
c.Y = sbSize.Y;
ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
ERROR_INVALID_PARAMETER, GetLastError());
c.X = -1;
c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
ERROR_INVALID_PARAMETER, GetLastError());
c.X = 0;
c.Y = -1;
ok(SetConsoleCursorPosition(hCon, c) == 0, "Cursor is outside\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError: expecting %u got %lu\n",
ERROR_INVALID_PARAMETER, GetLastError());
}
static void testWriteSimple(HANDLE hCon, COORD sbSize)
{
COORD c;
DWORD len;
const char* mytest = "abcdefg";
const int mylen = strlen(mytest);
/* single line write */
c.X = c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
c.Y = 0;
for (c.X = 0; c.X < mylen; c.X++)
{
okCHAR(hCon, c, mytest[c.X], TEST_ATTRIB);
}
okCURSOR(hCon, c);
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
}
static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize)
{
COORD c;
DWORD len, mode;
const char* mytest = "123";
const int mylen = strlen(mytest);
int ret;
int p;
ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode & ~(ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT)),
"clearing wrap at EOL & processed output\n");
/* write line, wrapping disabled, buffer exceeds sb width */
c.X = sbSize.X - 3; c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
ret = WriteConsole(hCon, mytest, mylen, &len, NULL);
ok(ret != 0 && len == mylen, "Couldn't write, ret = %d, len = %ld\n", ret, len);
c.Y = 0;
for (p = mylen - 3; p < mylen; p++)
{
c.X = sbSize.X - 3 + p % 3;
okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
}
c.X = 0; c.Y = 1;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
p = sbSize.X - 3 + mylen % 3;
c.X = p; c.Y = 0;
/* write line, wrapping disabled, strings end on end of line */
c.X = sbSize.X - mylen; c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
}
static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
{
COORD c;
DWORD len, mode;
const char* mytest = "abcd\nf\tg";
const int mylen = strlen(mytest);
const int mylen2 = strchr(mytest, '\n') - mytest;
int p;
ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, (mode | ENABLE_PROCESSED_OUTPUT) & ~ENABLE_WRAP_AT_EOL_OUTPUT),
"clearing wrap at EOL & setting processed output\n");
/* write line, wrapping disabled, buffer exceeds sb width */
c.X = sbSize.X - 5; c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-5\n");
ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
c.Y = 0;
for (c.X = sbSize.X - 5; c.X < sbSize.X - 1; c.X++)
{
okCHAR(hCon, c, mytest[c.X - sbSize.X + 5], TEST_ATTRIB);
}
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
c.X = 0; c.Y++;
okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
for (c.X = 1; c.X < 8; c.X++)
okCHAR(hCon, c, ' ', TEST_ATTRIB);
okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
c.X++;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
okCURSOR(hCon, c);
/* write line, wrapping disabled, strings end on end of line */
c.X = sbSize.X - 4; c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4\n");
ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
c.Y = 0;
for (c.X = sbSize.X - 4; c.X < sbSize.X; c.X++)
{
okCHAR(hCon, c, mytest[c.X - sbSize.X + 4], TEST_ATTRIB);
}
c.X = 0; c.Y++;
okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
for (c.X = 1; c.X < 8; c.X++)
okCHAR(hCon, c, ' ', TEST_ATTRIB);
okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
c.X++;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
okCURSOR(hCon, c);
/* write line, wrapping disabled, strings end after end of line */
c.X = sbSize.X - 3; c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4\n");
ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
c.Y = 0;
for (p = mylen2 - 3; p < mylen2; p++)
{
c.X = sbSize.X - 3 + p % 3;
okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
}
c.X = 0; c.Y = 1;
okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
for (c.X = 1; c.X < 8; c.X++)
okCHAR(hCon, c, ' ', TEST_ATTRIB);
okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
c.X++;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
okCURSOR(hCon, c);
}
static void testWriteWrappedNotProcessed(HANDLE hCon, COORD sbSize)
{
COORD c;
DWORD len, mode;
const char* mytest = "abcd\nf\tg";
const int mylen = strlen(mytest);
int p;
ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon,(mode | ENABLE_WRAP_AT_EOL_OUTPUT) & ~(ENABLE_PROCESSED_OUTPUT)),
"setting wrap at EOL & clearing processed output\n");
/* write line, wrapping enabled, buffer doesn't exceed sb width */
c.X = sbSize.X - 9; c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n");
ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
c.Y = 0;
for (p = 0; p < mylen; p++)
{
c.X = sbSize.X - 9 + p;
okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
}
c.X = sbSize.X - 9 + mylen;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
c.X = 0; c.Y = 1;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
/* write line, wrapping enabled, buffer does exceed sb width */
c.X = sbSize.X - 3; c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
c.Y = 1;
c.X = mylen - 3;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
}
static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize)
{
COORD c;
DWORD len, mode;
const char* mytest = "abcd\nf\tg";
const int mylen = strlen(mytest);
int p;
ok(GetConsoleMode(hCon, &mode) && SetConsoleMode(hCon, mode | (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)),
"setting wrap at EOL & processed output\n");
/* write line, wrapping enabled, buffer doesn't exceed sb width */
c.X = sbSize.X - 9; c.Y = 0;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n");
ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
for (p = 0; p < 4; p++)
{
c.X = sbSize.X - 9 + p;
okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
}
c.X = sbSize.X - 9 + p;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
c.X = 0; c.Y++;
okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
for (c.X = 1; c.X < 8; c.X++)
okCHAR(hCon, c, ' ', TEST_ATTRIB);
okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
c.X++;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
okCURSOR(hCon, c);
/* write line, wrapping enabled, buffer does exceed sb width */
c.X = sbSize.X - 3; c.Y = 2;
ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
for (p = 0; p < 3; p++)
{
c.X = sbSize.X - 3 + p;
okCHAR(hCon, c, mytest[p], TEST_ATTRIB);
}
c.X = 0; c.Y++;
okCHAR(hCon, c, mytest[3], TEST_ATTRIB);
c.X++;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
c.X = 0; c.Y++;
okCHAR(hCon, c, mytest[5], TEST_ATTRIB);
for (c.X = 1; c.X < 8; c.X++)
okCHAR(hCon, c, ' ', TEST_ATTRIB);
okCHAR(hCon, c, mytest[7], TEST_ATTRIB);
c.X++;
okCHAR(hCon, c, ' ', DEFAULT_ATTRIB);
okCURSOR(hCon, c);
}
static void testWrite(HANDLE hCon, COORD sbSize)
{
/* FIXME: should in fact insure that the sb is at least 10 character wide */
ok(SetConsoleTextAttribute(hCon, TEST_ATTRIB), "Setting default text color\n");
resetContent(hCon, sbSize, FALSE);
testWriteSimple(hCon, sbSize);
resetContent(hCon, sbSize, FALSE);
testWriteNotWrappedNotProcessed(hCon, sbSize);
resetContent(hCon, sbSize, FALSE);
testWriteNotWrappedProcessed(hCon, sbSize);
resetContent(hCon, sbSize, FALSE);
testWriteWrappedNotProcessed(hCon, sbSize);
resetContent(hCon, sbSize, FALSE);
testWriteWrappedProcessed(hCon, sbSize);
}
static void testScroll(HANDLE hCon, COORD sbSize)
{
SMALL_RECT scroll, clip;
COORD dst, c, tc;
CHAR_INFO ci;
#define W 11
#define H 7
#define IN_SRECT(r,c) ((r).Left <= (c).X && (c).X <= (r).Right && (r).Top <= (c).Y && (c).Y <= (r).Bottom)
#define IN_SRECT2(r,d,c) ((d).X <= (c).X && (c).X <= (d).X + (r).Right - (r).Left && (d).Y <= (c).Y && (c).Y <= (d).Y + (r).Bottom - (r).Top)
/* no clipping, src & dst rect don't overlap */
resetContent(hCon, sbSize, TRUE);
scroll.Left = 0;
scroll.Right = W - 1;
scroll.Top = 0;
scroll.Bottom = H - 1;
dst.X = W + 3;
dst.Y = H + 3;
ci.Char.UnicodeChar = '#';
ci.Attributes = TEST_ATTRIB;
clip.Left = 0;
clip.Right = sbSize.X - 1;
clip.Top = 0;
clip.Bottom = sbSize.Y - 1;
ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
{
for (c.X = 0; c.X < sbSize.X; c.X++)
{
if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
{
tc.X = c.X - dst.X;
tc.Y = c.Y - dst.Y;
okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
}
else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c))
okCHAR(hCon, c, '#', TEST_ATTRIB);
else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
}
}
/* no clipping, src & dst rect do overlap */
resetContent(hCon, sbSize, TRUE);
scroll.Left = 0;
scroll.Right = W - 1;
scroll.Top = 0;
scroll.Bottom = H - 1;
dst.X = W /2;
dst.Y = H / 2;
ci.Char.UnicodeChar = '#';
ci.Attributes = TEST_ATTRIB;
clip.Left = 0;
clip.Right = sbSize.X - 1;
clip.Top = 0;
clip.Bottom = sbSize.Y - 1;
ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
{
for (c.X = 0; c.X < sbSize.X; c.X++)
{
if (dst.X <= c.X && c.X < dst.X + W && dst.Y <= c.Y && c.Y < dst.Y + H)
{
tc.X = c.X - dst.X;
tc.Y = c.Y - dst.Y;
okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
}
else if (c.X < W && c.Y < H) okCHAR(hCon, c, '#', TEST_ATTRIB);
else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
}
}
/* clipping, src & dst rect don't overlap */
resetContent(hCon, sbSize, TRUE);
scroll.Left = 0;
scroll.Right = W - 1;
scroll.Top = 0;
scroll.Bottom = H - 1;
dst.X = W + 3;
dst.Y = H + 3;
ci.Char.UnicodeChar = '#';
ci.Attributes = TEST_ATTRIB;
clip.Left = W / 2;
clip.Right = min(W + W / 2, sbSize.X - 1);
clip.Top = H / 2;
clip.Bottom = min(H + H / 2, sbSize.Y - 1);
ok(ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci), "Scrolling SB\n");
for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
{
for (c.X = 0; c.X < sbSize.X; c.X++)
{
if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
{
tc.X = c.X - dst.X;
tc.Y = c.Y - dst.Y;
okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
}
else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c))
okCHAR(hCon, c, '#', TEST_ATTRIB);
else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
}
}
/* clipping, src & dst rect do overlap */
resetContent(hCon, sbSize, TRUE);
scroll.Left = 0;
scroll.Right = W - 1;
scroll.Top = 0;
scroll.Bottom = H - 1;
dst.X = W / 2 - 3;
dst.Y = H / 2 - 3;
ci.Char.UnicodeChar = '#';
ci.Attributes = TEST_ATTRIB;
clip.Left = W / 2;
clip.Right = min(W + W / 2, sbSize.X - 1);
clip.Top = H / 2;
clip.Bottom = min(H + H / 2, sbSize.Y - 1);
ok(ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci), "Scrolling SB\n");
for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
{
for (c.X = 0; c.X < sbSize.X; c.X++)
{
if (IN_SRECT2(scroll, dst, c) && IN_SRECT(clip, c))
{
tc.X = c.X - dst.X;
tc.Y = c.Y - dst.Y;
okCHAR(hCon, c, CONTENT(tc), DEFAULT_ATTRIB);
}
else if (IN_SRECT(scroll, c) && IN_SRECT(clip, c))
okCHAR(hCon, c, '#', TEST_ATTRIB);
else okCHAR(hCon, c, CONTENT(c), DEFAULT_ATTRIB);
}
}
}
static int mch_count;
/* we need the event as Wine console event generation isn't synchronous
* (ie GenerateConsoleCtrlEvent returns before all ctrl-handlers in all
* processes have been called).
*/
static HANDLE mch_event;
static BOOL WINAPI mch(DWORD event)
{
mch_count++;
SetEvent(mch_event);
return TRUE;
}
static void testCtrlHandler(void)
{
ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %lu\n", GetLastError());
ok(SetConsoleCtrlHandler(mch, TRUE), "Couldn't set handler\n");
/* wine requires the event for the test, as we cannot insure, so far, that event
* are processed synchronously in GenerateConsoleCtrlEvent()
*/
mch_event = CreateEventA(NULL, TRUE, FALSE, NULL);
mch_count = 0;
ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n");
#if 0 /* FIXME: it isn't synchronous on wine but it can still happen before we test */
todo_wine ok(mch_count == 1, "Event isn't synchronous\n");
#endif
ok(WaitForSingleObject(mch_event, 3000) == WAIT_OBJECT_0, "event sending didn't work\n");
CloseHandle(mch_event);
/* Turning off ctrl-c handling doesn't work on win9x such way ... */
ok(SetConsoleCtrlHandler(NULL, TRUE), "Couldn't turn off ctrl-c handling\n");
mch_event = CreateEventA(NULL, TRUE, FALSE, NULL);
mch_count = 0;
if(!(GetVersion() & 0x80000000))
/* ... and next line leads to an unhandled exception on 9x. Avoid it on 9x. */
ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n");
ok(WaitForSingleObject(mch_event, 3000) == WAIT_TIMEOUT && mch_count == 0, "Event shouldn't have been sent\n");
CloseHandle(mch_event);
ok(SetConsoleCtrlHandler(mch, FALSE), "Couldn't remove handler\n");
ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %lu\n", GetLastError());
}
START_TEST(console)
{
HANDLE hConIn, hConOut;
BOOL ret;
CONSOLE_SCREEN_BUFFER_INFO sbi;
/* be sure we have a clean console (and that's our own)
* FIXME: this will make the test fail (currently) if we don't run
* under X11
* Another solution would be to rerun the test under wineconsole with
* the curses backend
*/
/* first, we detach and open a fresh console to play with */
FreeConsole();
ok(AllocConsole(), "Couldn't alloc console\n");
hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
/* now verify everything's ok */
ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
ok(ret = GetConsoleScreenBufferInfo(hConOut, &sbi), "Getting sb info\n");
if (!ret) return;
/* Non interactive tests */
testCursor(hConOut, sbi.dwSize);
/* will test wrapped (on/off) & processed (on/off) strings output */
testWrite(hConOut, sbi.dwSize);
/* will test line scrolling at the bottom of the screen */
/* testBottomScroll(); */
/* will test all the scrolling operations */
testScroll(hConOut, sbi.dwSize);
/* will test sb creation / modification... */
/* testScreenBuffer() */
testCtrlHandler();
/* still to be done: access rights & access on objects */
}

View file

@ -0,0 +1,482 @@
/*
* Unit test suite for directory functions.
*
* Copyright 2002 Dmitry Timoshkov
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
/* If you change something in these tests, please do the same
* for GetSystemDirectory tests.
*/
static void test_GetWindowsDirectoryA(void)
{
UINT len, len_with_null;
char buf[MAX_PATH];
len_with_null = GetWindowsDirectoryA(NULL, 0);
ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH\n");
lstrcpyA(buf, "foo");
len_with_null = GetWindowsDirectoryA(buf, 1);
ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
lstrcpyA(buf, "foo");
len = GetWindowsDirectoryA(buf, len_with_null - 1);
ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
ok(len == len_with_null, "GetWindowsDirectoryW returned %d, expected %d\n",
len, len_with_null);
lstrcpyA(buf, "foo");
len = GetWindowsDirectoryA(buf, len_with_null);
ok(lstrcmpA(buf, "foo") != 0, "should touch the buffer\n");
ok(len == strlen(buf), "returned length should be equal to the length of string\n");
ok(len == len_with_null-1, "GetWindowsDirectoryA returned %d, expected %d\n",
len, len_with_null-1);
}
static void test_GetWindowsDirectoryW(void)
{
UINT len, len_with_null;
WCHAR buf[MAX_PATH];
static const WCHAR fooW[] = {'f','o','o',0};
len_with_null = GetWindowsDirectoryW(NULL, 0);
if (len_with_null==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
return;
ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH\n");
lstrcpyW(buf, fooW);
len = GetWindowsDirectoryW(buf, 1);
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok(len == len_with_null, "GetWindowsDirectoryW returned %d, expected %d\n",
len, len_with_null);
lstrcpyW(buf, fooW);
len = GetWindowsDirectoryW(buf, len_with_null - 1);
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok(len == len_with_null, "GetWindowsDirectoryW returned %d, expected %d\n",
len, len_with_null);
lstrcpyW(buf, fooW);
len = GetWindowsDirectoryW(buf, len_with_null);
ok(lstrcmpW(buf, fooW) != 0, "should touch the buffer\n");
ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
ok(len == len_with_null-1, "GetWindowsDirectoryW returned %d, expected %d\n",
len, len_with_null-1);
}
/* If you change something in these tests, please do the same
* for GetWindowsDirectory tests.
*/
static void test_GetSystemDirectoryA(void)
{
UINT len, len_with_null;
char buf[MAX_PATH];
len_with_null = GetSystemDirectoryA(NULL, 0);
ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH\n");
lstrcpyA(buf, "foo");
len = GetSystemDirectoryA(buf, 1);
ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
ok(len == len_with_null, "GetSystemDirectoryA returned %d, expected %d\n",
len, len_with_null);
lstrcpyA(buf, "foo");
len = GetSystemDirectoryA(buf, len_with_null - 1);
ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
ok(len == len_with_null, "GetSystemDirectoryA returned %d, expected %d\n",
len, len_with_null);
lstrcpyA(buf, "foo");
len = GetSystemDirectoryA(buf, len_with_null);
ok(lstrcmpA(buf, "foo") != 0, "should touch the buffer\n");
ok(len == strlen(buf), "returned length should be equal to the length of string\n");
ok(len == len_with_null-1, "GetSystemDirectoryW returned %d, expected %d\n",
len, len_with_null-1);
}
static void test_GetSystemDirectoryW(void)
{
UINT len, len_with_null;
WCHAR buf[MAX_PATH];
static const WCHAR fooW[] = {'f','o','o',0};
len_with_null = GetSystemDirectoryW(NULL, 0);
if (len_with_null==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
return;
ok(len_with_null <= MAX_PATH, "should fit into MAX_PATH\n");
lstrcpyW(buf, fooW);
len = GetSystemDirectoryW(buf, 1);
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok(len == len_with_null, "GetSystemDirectoryW returned %d, expected %d\n",
len, len_with_null);
lstrcpyW(buf, fooW);
len = GetSystemDirectoryW(buf, len_with_null - 1);
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok(len == len_with_null, "GetSystemDirectoryW returned %d, expected %d\n",
len, len_with_null);
lstrcpyW(buf, fooW);
len = GetSystemDirectoryW(buf, len_with_null);
ok(lstrcmpW(buf, fooW) != 0, "should touch the buffer\n");
ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
ok(len == len_with_null-1, "GetSystemDirectoryW returned %d, expected %d\n",
len, len_with_null-1);
}
static void test_CreateDirectoryA(void)
{
char tmpdir[MAX_PATH];
BOOL ret;
ret = CreateDirectoryA(NULL, NULL);
ok(ret == FALSE && (GetLastError() == ERROR_PATH_NOT_FOUND ||
GetLastError() == ERROR_INVALID_PARAMETER),
"CreateDirectoryA(NULL): ret=%d err=%ld\n", ret, GetLastError());
ret = CreateDirectoryA("", NULL);
ok(ret == FALSE && (GetLastError() == ERROR_BAD_PATHNAME ||
GetLastError() == ERROR_PATH_NOT_FOUND),
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
ret = GetSystemDirectoryA(tmpdir, MAX_PATH);
ok(ret < MAX_PATH, "System directory should fit into MAX_PATH\n");
ret = SetCurrentDirectoryA(tmpdir);
ok(ret == TRUE, "could not chdir to the System directory\n");
ret = CreateDirectoryA(".", NULL);
ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
ret = CreateDirectoryA("..", NULL);
ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
GetTempPathA(MAX_PATH, tmpdir);
tmpdir[3] = 0; /* truncate the path */
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == FALSE && (GetLastError() == ERROR_ALREADY_EXISTS ||
GetLastError() == ERROR_ACCESS_DENIED),
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE, "CreateDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS,
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
lstrcatA(tmpdir, "?");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == FALSE && (GetLastError() == ERROR_INVALID_NAME ||
GetLastError() == ERROR_PATH_NOT_FOUND),
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
RemoveDirectoryA(tmpdir);
tmpdir[lstrlenA(tmpdir) - 1] = '*';
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == FALSE && (GetLastError() == ERROR_INVALID_NAME ||
GetLastError() == ERROR_PATH_NOT_FOUND),
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
RemoveDirectoryA(tmpdir);
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me/Please Remove Me");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND,
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
RemoveDirectoryA(tmpdir);
/* Test behavior with a trailing dot.
* The directory should be created without the dot.
*/
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me.");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE,
"CreateDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
lstrcatA(tmpdir, "/Please Remove Me");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE,
"CreateDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me");
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
/* Test behavior with two trailing dots.
* The directory should be created without the trailing dots.
*/
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me..");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE,
"CreateDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
lstrcatA(tmpdir, "/Please Remove Me");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE || /* On Win98 */
(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND), /* On NT! */
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
if (ret == TRUE)
{
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
}
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me");
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
/* Test behavior with a trailing space.
* The directory should be created without the trailing space.
*/
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me ");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE,
"CreateDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
lstrcatA(tmpdir, "/Please Remove Me");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE || /* On Win98 */
(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND), /* On NT! */
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
if (ret == TRUE)
{
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
}
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me");
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
/* Test behavior with a trailing space.
* The directory should be created without the trailing spaces.
*/
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me ");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE,
"CreateDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
lstrcatA(tmpdir, "/Please Remove Me");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE || /* On Win98 */
(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND), /* On NT! */
"CreateDirectoryA(%s): ret=%d err=%ld\n", tmpdir, ret, GetLastError());
if (ret == TRUE)
{
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
}
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me");
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE,
"RemoveDirectoryA(%s) failed err=%ld\n", tmpdir, GetLastError());
}
static void test_CreateDirectoryW(void)
{
WCHAR tmpdir[MAX_PATH];
BOOL ret;
static const WCHAR empty_strW[] = { 0 };
static const WCHAR tmp_dir_name[] = {'P','l','e','a','s','e',' ','R','e','m','o','v','e',' ','M','e',0};
static const WCHAR dotW[] = {'.',0};
static const WCHAR slashW[] = {'/',0};
static const WCHAR dotdotW[] = {'.','.',0};
static const WCHAR questionW[] = {'?',0};
ret = CreateDirectoryW(NULL, NULL);
if (!ret && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
return;
ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND, "should not create NULL path\n");
ret = CreateDirectoryW(empty_strW, NULL);
ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND, "should not create empty path\n");
ret = GetSystemDirectoryW(tmpdir, MAX_PATH);
ok(ret < MAX_PATH, "System directory should fit into MAX_PATH\n");
ret = SetCurrentDirectoryW(tmpdir);
ok(ret == TRUE, "could not chdir to the System directory\n");
ret = CreateDirectoryW(dotW, NULL);
ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path\n");
ret = CreateDirectoryW(dotdotW, NULL);
ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path\n");
GetTempPathW(MAX_PATH, tmpdir);
tmpdir[3] = 0; /* truncate the path */
ret = CreateDirectoryW(tmpdir, NULL);
ok(ret == FALSE && GetLastError() == ERROR_ACCESS_DENIED, "should deny access to the drive root\n");
GetTempPathW(MAX_PATH, tmpdir);
lstrcatW(tmpdir, tmp_dir_name);
ret = CreateDirectoryW(tmpdir, NULL);
ok(ret == TRUE, "CreateDirectoryW should always succeed\n");
ret = CreateDirectoryW(tmpdir, NULL);
ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path\n");
ret = RemoveDirectoryW(tmpdir);
ok(ret == TRUE, "RemoveDirectoryW should always succeed\n");
lstrcatW(tmpdir, questionW);
ret = CreateDirectoryW(tmpdir, NULL);
ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
"CreateDirectoryW with ? wildcard name should fail with error 183, ret=%s error=%ld\n",
ret ? " True" : "False", GetLastError());
ret = RemoveDirectoryW(tmpdir);
tmpdir[lstrlenW(tmpdir) - 1] = '*';
ret = CreateDirectoryW(tmpdir, NULL);
ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
"CreateDirectoryW with * wildcard name should fail with error 183, ret=%s error=%ld\n",
ret ? " True" : "False", GetLastError());
ret = RemoveDirectoryW(tmpdir);
GetTempPathW(MAX_PATH, tmpdir);
lstrcatW(tmpdir, tmp_dir_name);
lstrcatW(tmpdir, slashW);
lstrcatW(tmpdir, tmp_dir_name);
ret = CreateDirectoryW(tmpdir, NULL);
ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND,
"CreateDirectoryW with multiple nonexistent directories in path should fail\n");
ret = RemoveDirectoryW(tmpdir);
}
static void test_RemoveDirectoryA(void)
{
char tmpdir[MAX_PATH];
BOOL ret;
GetTempPathA(MAX_PATH, tmpdir);
lstrcatA(tmpdir, "Please Remove Me");
ret = CreateDirectoryA(tmpdir, NULL);
ok(ret == TRUE, "CreateDirectoryA should always succeed\n");
ret = RemoveDirectoryA(tmpdir);
ok(ret == TRUE, "RemoveDirectoryA should always succeed\n");
lstrcatA(tmpdir, "?");
ret = RemoveDirectoryA(tmpdir);
ok(ret == FALSE && (GetLastError() == ERROR_INVALID_NAME ||
GetLastError() == ERROR_PATH_NOT_FOUND),
"RemoveDirectoryA with ? wildcard name should fail, ret=%s error=%ld\n",
ret ? " True" : "False", GetLastError());
tmpdir[lstrlenA(tmpdir) - 1] = '*';
ret = RemoveDirectoryA(tmpdir);
ok(ret == FALSE && (GetLastError() == ERROR_INVALID_NAME ||
GetLastError() == ERROR_PATH_NOT_FOUND),
"RemoveDirectoryA with * wildcard name should fail, ret=%s error=%ld\n",
ret ? " True" : "False", GetLastError());
}
static void test_RemoveDirectoryW(void)
{
WCHAR tmpdir[MAX_PATH];
BOOL ret;
static const WCHAR tmp_dir_name[] = {'P','l','e','a','s','e',' ','R','e','m','o','v','e',' ','M','e',0};
static const WCHAR questionW[] = {'?',0};
GetTempPathW(MAX_PATH, tmpdir);
lstrcatW(tmpdir, tmp_dir_name);
ret = CreateDirectoryW(tmpdir, NULL);
if (!ret && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
return;
ok(ret == TRUE, "CreateDirectoryW should always succeed\n");
ret = RemoveDirectoryW(tmpdir);
ok(ret == TRUE, "RemoveDirectoryW should always succeed\n");
lstrcatW(tmpdir, questionW);
ret = RemoveDirectoryW(tmpdir);
ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
"RemoveDirectoryW with wildcard should fail with error 183, ret=%s error=%ld\n",
ret ? " True" : "False", GetLastError());
tmpdir[lstrlenW(tmpdir) - 1] = '*';
ret = RemoveDirectoryW(tmpdir);
ok(ret == FALSE && GetLastError() == ERROR_INVALID_NAME,
"RemoveDirectoryW with * wildcard name should fail with error 183, ret=%s error=%ld\n",
ret ? " True" : "False", GetLastError());
}
static void test_SetCurrentDirectoryA(void)
{
SetLastError(0);
ok( !SetCurrentDirectoryA( "\\some_dummy_dir" ), "SetCurrentDirectoryA succeeded\n" );
ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %ld\n", GetLastError() );
ok( !SetCurrentDirectoryA( "\\some_dummy\\subdir" ), "SetCurrentDirectoryA succeeded\n" );
ok( GetLastError() == ERROR_PATH_NOT_FOUND, "wrong error %ld\n", GetLastError() );
}
START_TEST(directory)
{
test_GetWindowsDirectoryA();
test_GetWindowsDirectoryW();
test_GetSystemDirectoryA();
test_GetSystemDirectoryW();
test_CreateDirectoryA();
test_CreateDirectoryW();
test_RemoveDirectoryA();
test_RemoveDirectoryW();
test_SetCurrentDirectoryA();
}

View file

@ -0,0 +1,209 @@
/*
* Unit test suite for drive functions.
*
* Copyright 2002 Dmitry Timoshkov
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
static DWORD (WINAPI *pGetDiskFreeSpaceExA)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
static void test_GetDriveTypeA(void)
{
char drive[] = "?:\\";
DWORD logical_drives;
UINT type;
logical_drives = GetLogicalDrives();
ok(logical_drives != 0, "GetLogicalDrives error %ld\n", GetLastError());
for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
{
type = GetDriveTypeA(drive);
ok(type > 0 && type <= 6, "not a valid drive %c: type %u\n", drive[0], type);
if (!(logical_drives & 1))
ok(type == DRIVE_NO_ROOT_DIR,
"GetDriveTypeA should return DRIVE_NO_ROOT_DIR for inexistant drive %c: but not %u\n",
drive[0], type);
logical_drives >>= 1;
}
}
static void test_GetDriveTypeW(void)
{
WCHAR drive[] = {'?',':','\\',0};
DWORD logical_drives;
UINT type;
logical_drives = GetLogicalDrives();
ok(logical_drives != 0, "GetLogicalDrives error %ld\n", GetLastError());
for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
{
type = GetDriveTypeW(drive);
if (type == DRIVE_UNKNOWN && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
{
/* Must be Win9x which doesn't support the Unicode functions */
return;
}
ok(type > 0 && type <= 6, "not a valid drive %c: type %u\n", drive[0], type);
if (!(logical_drives & 1))
ok(type == DRIVE_NO_ROOT_DIR,
"GetDriveTypeW should return DRIVE_NO_ROOT_DIR for inexistant drive %c: but not %u\n",
drive[0], type);
logical_drives >>= 1;
}
}
static void test_GetDiskFreeSpaceA(void)
{
BOOL ret;
DWORD sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters;
char drive[] = "?:\\";
DWORD logical_drives;
ret = GetDiskFreeSpaceA(NULL, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
ok(ret, "GetDiskFreeSpaceA error %ld\n", GetLastError());
ret = GetDiskFreeSpaceA("", &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME),
"GetDiskFreeSpaceA(\"\"): ret=%d GetLastError=%ld\n",
ret, GetLastError());
ret = GetDiskFreeSpaceA("\\", &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
ok(ret, "GetDiskFreeSpaceA error %ld\n", GetLastError());
ret = GetDiskFreeSpaceA("/", &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
ok(ret, "GetDiskFreeSpaceA error %ld\n", GetLastError());
logical_drives = GetLogicalDrives();
ok(logical_drives != 0, "GetLogicalDrives error %ld\n", GetLastError());
for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
{
UINT drivetype = GetDriveTypeA(drive);
/* Skip floppy drives because NT pops up a MessageBox if no
* floppy is present
*/
if (drivetype != DRIVE_REMOVABLE && drivetype != DRIVE_NO_ROOT_DIR)
{
ret = GetDiskFreeSpaceA(drive, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
if (!(logical_drives & 1))
ok(!ret && (GetLastError() == ERROR_PATH_NOT_FOUND || GetLastError() == ERROR_INVALID_DRIVE),
"GetDiskFreeSpaceA(%s): ret=%d GetLastError=%ld\n",
drive, ret, GetLastError());
else
{
ok(ret ||
(!ret && (GetLastError() == ERROR_NOT_READY || GetLastError() == ERROR_INVALID_DRIVE)),
"GetDiskFreeSpaceA(%s): ret=%d GetLastError=%ld\n",
drive, ret, GetLastError());
if( GetVersion() & 0x80000000)
/* win3.0 thru winME */
ok( total_clusters <= 65535,
"total clusters is %ld > 65535\n", total_clusters);
else if (pGetDiskFreeSpaceExA) {
/* NT, 2k, XP : GetDiskFreeSpace shoud be accurate */
ULARGE_INTEGER totEx, tot, d;
tot.QuadPart = sectors_per_cluster;
tot.QuadPart = (tot.QuadPart * bytes_per_sector) * total_clusters;
ret = pGetDiskFreeSpaceExA( drive, &d, &totEx, NULL);
ok( ret || (!ret && ERROR_NOT_READY == GetLastError()),
"GetDiskFreeSpaceExA( %s ) failed. GetLastError=%ld\n", drive, GetLastError());
ok( bytes_per_sector == 0 || /* empty cd rom drive */
totEx.QuadPart <= tot.QuadPart,
"GetDiskFreeSpaceA should report at least as much bytes on disk %s as GetDiskFreeSpaceExA\n", drive);
}
}
}
logical_drives >>= 1;
}
}
static void test_GetDiskFreeSpaceW(void)
{
BOOL ret;
DWORD sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters;
WCHAR drive[] = {'?',':','\\',0};
DWORD logical_drives;
static const WCHAR empty_pathW[] = { 0 };
static const WCHAR root_pathW[] = { '\\', 0 };
static const WCHAR unix_style_root_pathW[] = { '/', 0 };
ret = GetDiskFreeSpaceW(NULL, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
if (ret == 0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
{
/* Must be Win9x which doesn't support the Unicode functions */
return;
}
ok(ret, "GetDiskFreeSpaceW error %ld\n", GetLastError());
ret = GetDiskFreeSpaceW(empty_pathW, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
"GetDiskFreeSpaceW(\"\"): ret=%d GetLastError=%ld\n",
ret, GetLastError());
ret = GetDiskFreeSpaceW(root_pathW, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
ok(ret, "GetDiskFreeSpaceW(\"\") error %ld\n", GetLastError());
ret = GetDiskFreeSpaceW(unix_style_root_pathW, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
ok(ret, "GetDiskFreeSpaceW error %ld\n", GetLastError());
logical_drives = GetLogicalDrives();
ok(logical_drives != 0, "GetLogicalDrives error %ld\n", GetLastError());
for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
{
UINT drivetype = GetDriveTypeW(drive);
/* Skip floppy drives because NT4 pops up a MessageBox if no floppy is present */
if (drivetype != DRIVE_REMOVABLE && drivetype != DRIVE_NO_ROOT_DIR)
{
ret = GetDiskFreeSpaceW(drive, &sectors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters);
if (!(logical_drives & 1))
ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND,
"GetDiskFreeSpaceW(%c): ret=%d GetLastError=%ld\n",
drive[0], ret, GetLastError());
else
ok(ret || GetLastError() == ERROR_NOT_READY,
"GetDiskFreeSpaceW(%c): ret=%d GetLastError=%ld\n",
drive[0], ret, GetLastError());
}
logical_drives >>= 1;
}
}
START_TEST(drive)
{
HANDLE hkernel32 = GetModuleHandleA("kernel32");
pGetDiskFreeSpaceExA = (void *) GetProcAddress(hkernel32, "GetDiskFreeSpaceExA");
test_GetDriveTypeA();
test_GetDriveTypeW();
test_GetDiskFreeSpaceA();
test_GetDiskFreeSpaceW();
}

View file

@ -0,0 +1,232 @@
/*
* Unit test suite for environment functions.
*
* Copyright 2002 Dmitry Timoshkov
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
static void test_GetSetEnvironmentVariableA(void)
{
char buf[256];
BOOL ret;
DWORD ret_size;
static const char name[] = "SomeWildName";
static const char name_cased[] = "sOMEwILDnAME";
static const char value[] = "SomeWildValue";
ret = SetEnvironmentVariableA(name, value);
ok(ret == TRUE,
"unexpected error in SetEnvironmentVariableA, GetLastError=%ld\n",
GetLastError());
/* Try to retrieve the environment variable we just set */
ret_size = GetEnvironmentVariableA(name, NULL, 0);
ok(ret_size == strlen(value) + 1,
"should return length with terminating 0 ret_size=%ld\n", ret_size);
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value));
ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
ok(ret_size == strlen(value) + 1,
"should return length with terminating 0 ret_size=%ld\n", ret_size);
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == strlen(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name_cased, buf, lstrlenA(value) + 1);
ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == strlen(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
/* Remove that environment variable */
ret = SetEnvironmentVariableA(name_cased, NULL);
ok(ret == TRUE, "should erase existing variable\n");
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer\n");
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
/* Check behavior of SetEnvironmentVariableA(name, "") */
ret = SetEnvironmentVariableA(name, value);
ok(ret == TRUE,
"unexpected error in SetEnvironmentVariableA, GetLastError=%ld\n",
GetLastError());
lstrcpyA(buf, "foo");
ret_size = GetEnvironmentVariableA(name_cased, buf, lstrlenA(value) + 1);
ok(lstrcmpA(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == strlen(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
ret = SetEnvironmentVariableA(name_cased, "");
ok(ret == TRUE,
"should not fail with empty value but GetLastError=%ld\n", GetLastError());
lstrcpyA(buf, "foo");
SetLastError(0);
ret_size = GetEnvironmentVariableA(name, buf, lstrlenA(value) + 1);
ok(ret_size == 0 &&
((GetLastError() == 0 && lstrcmpA(buf, "") == 0) ||
(GetLastError() == ERROR_ENVVAR_NOT_FOUND)),
"%s should be set to \"\" (NT) or removed (Win9x) but ret_size=%ld GetLastError=%ld and buf=%s\n",
name, ret_size, GetLastError(), buf);
/* Test the limits */
ret_size = GetEnvironmentVariableA(NULL, NULL, 0);
ok(ret_size == 0 && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ret_size = GetEnvironmentVariableA(NULL, buf, lstrlenA(value) + 1);
ok(ret_size == 0 && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ret_size = GetEnvironmentVariableA("", buf, lstrlenA(value) + 1);
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
}
static void test_GetSetEnvironmentVariableW(void)
{
WCHAR buf[256];
BOOL ret;
DWORD ret_size;
static const WCHAR name[] = {'S','o','m','e','W','i','l','d','N','a','m','e',0};
static const WCHAR value[] = {'S','o','m','e','W','i','l','d','V','a','l','u','e',0};
static const WCHAR name_cased[] = {'s','O','M','E','w','I','L','D','n','A','M','E',0};
static const WCHAR empty_strW[] = { 0 };
static const WCHAR fooW[] = {'f','o','o',0};
ret = SetEnvironmentVariableW(name, value);
if (ret == FALSE && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
{
/* Must be Win9x which doesn't support the Unicode functions */
return;
}
ok(ret == TRUE,
"unexpected error in SetEnvironmentVariableW, GetLastError=%ld\n",
GetLastError());
/* Try to retrieve the environment variable we just set */
ret_size = GetEnvironmentVariableW(name, NULL, 0);
ok(ret_size == lstrlenW(value) + 1,
"should return length with terminating 0 ret_size=%ld\n",
ret_size);
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value));
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok(ret_size == lstrlenW(value) + 1,
"should return length with terminating 0 ret_size=%ld\n", ret_size);
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == lstrlenW(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name_cased, buf, lstrlenW(value) + 1);
ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == lstrlenW(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
/* Remove that environment variable */
ret = SetEnvironmentVariableW(name_cased, NULL);
ok(ret == TRUE, "should erase existing variable\n");
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
ok(lstrcmpW(buf, fooW) == 0, "should not touch the buffer\n");
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
/* Check behavior of SetEnvironmentVariableW(name, "") */
ret = SetEnvironmentVariableW(name, value);
ok(ret == TRUE,
"unexpected error in SetEnvironmentVariableW, GetLastError=%ld\n",
GetLastError());
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
ok(lstrcmpW(buf, value) == 0, "should touch the buffer\n");
ok(ret_size == lstrlenW(value),
"should return length without terminating 0 ret_size=%ld\n", ret_size);
ret = SetEnvironmentVariableW(name_cased, empty_strW);
ok(ret == TRUE, "should not fail with empty value but GetLastError=%ld\n", GetLastError());
lstrcpyW(buf, fooW);
ret_size = GetEnvironmentVariableW(name, buf, lstrlenW(value) + 1);
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ok(lstrcmpW(buf, empty_strW) == 0, "should copy an empty string\n");
/* Test the limits */
ret_size = GetEnvironmentVariableW(NULL, NULL, 0);
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ret_size = GetEnvironmentVariableW(NULL, buf, lstrlenW(value) + 1);
ok(ret_size == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"should not find variable but ret_size=%ld GetLastError=%ld\n",
ret_size, GetLastError());
ret = SetEnvironmentVariableW(NULL, NULL);
ok(ret == FALSE && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_ENVVAR_NOT_FOUND),
"should fail with NULL, NULL but ret=%d and GetLastError=%ld\n",
ret, GetLastError());
}
static void test_ExpandEnvironmentStringsA(void)
{
char buf[256], buf1[256];
DWORD ret_size, ret_size1;
ret_size1 = GetWindowsDirectoryA(buf1,256);
ok ((ret_size1 >0) && (ret_size1<256), "GetWindowsDirectory Failed\n");
ret_size = ExpandEnvironmentStringsA("%SystemRoot%",buf,sizeof(buf));
if (ERROR_ENVVAR_NOT_FOUND == GetLastError())
return;
ok(!strcmp(buf, buf1), "ExpandEnvironmentStrings failed %s vs %s. ret_size = %ld\n", buf, buf1, ret_size);
}
START_TEST(environ)
{
test_GetSetEnvironmentVariableA();
test_GetSetEnvironmentVariableW();
test_ExpandEnvironmentStringsA();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,49 @@
cp ~/wine/source/dlls/dnsapi
cp ~/wine/source/dlls/wininet
cp ~/wine/source/dlls/dsound
cp ~/wine/source/dlls/msi
cp ~/wine/source/dlls/version
cp ~/wine/source/dlls/winspool
cp ~/wine/source/dlls/msacm32
cp ~/wine/source/dlls/oleaut32
cp ~/wine/source/dlls/ntdll
cp ~/wine/source/dlls/ws2_32
cp ~/wine/source/dlls/msvcrtd
cp ~/wine/source/dlls/psapi
cp ~/wine/source/dlls/mlang
cp ~/wine/source/dlls/netapi32
cp ~/wine/source/dlls/quartz
cp ~/wine/source/dlls/gdi
cp ~/wine/source/dlls/shdocvw
cp ~/wine/source/dlls/advapi32
cp ~/wine/source/dlls/d3d8
cp ~/wine/source/dlls/winmm
cp ~/wine/source/dlls/dinput
cp ~/wine/source/dlls/setupapi
cp ~/wine/source/dlls/usp10
cp ~/wine/source/dlls/rsabase
cp ~/wine/source/dlls/lz32
cp ~/wine/source/dlls/msxml3
cp ~/wine/source/dlls/rpcrt4
cp ~/wine/source/dlls/ole32
cp ~/wine/source/dlls/mapi32
cp ~/wine/source/dlls/iphlpapi
cp ~/wine/source/dlls/advpack
cp ~/wine/source/dlls/mscms
cp ~/wine/source/dlls/comctl32
cp ~/wine/source/dlls/mshtml
cp ~/wine/source/dlls/rsaenh
cp ~/wine/source/dlls/kernel
cp ~/wine/source/dlls/d3d9
cp ~/wine/source/dlls/shell32
cp ~/wine/source/dlls/urlmon
cp ~/wine/source/dlls/cabinet
cp ~/wine/source/dlls/msvcrt
cp ~/wine/source/dlls/winspool.drv
cp ~/wine/source/dlls/ddraw
cp ~/wine/source/dlls/shlwapi
cp ~/wine/source/dlls/secur32
cp ~/wine/source/dlls/user
cp ~/wine/source/dlls/riched20
cp ~/wine/source/dlls/crypt32

View file

@ -0,0 +1,226 @@
/* Unit test suite for FormatMessageA
*
* Copyright 2002 Mike McCormack for CodeWeavers
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
/* #define ok(cond,failstr) if(!(cond)) {printf("line %d : %s\n",__LINE__,failstr);exit(1);} */
static DWORD doit(DWORD flags, LPCVOID src, DWORD msg_id, DWORD lang_id,
LPSTR out, DWORD outsize, ... )
{
va_list list;
DWORD r;
va_start(list, outsize);
r = FormatMessageA(flags, src, msg_id,
lang_id, out, outsize, &list);
va_end(list);
return r;
}
static void test_message_from_string(void)
{
CHAR out[0x100] = {0};
DWORD r;
static const WCHAR szwTest[] = { 't','e','s','t',0};
/* the basics */
r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test", 0,
0, out, sizeof(out)/sizeof(CHAR),NULL);
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* using the format feature */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!s!", 0,
0, out, sizeof(out)/sizeof(CHAR), "test");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* no format */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
0, out, sizeof(out)/sizeof(CHAR), "test");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* two pieces */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%2", 0,
0, out, sizeof(out)/sizeof(CHAR), "te","st");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* three pieces */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1%3%2%1", 0,
0, out, sizeof(out)/sizeof(CHAR), "t","s","e");
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* s doesn't seem to work in format strings */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%!s!", 0,
0, out, sizeof(out)/sizeof(CHAR), "test");
ok(!strcmp("!s!", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%ld\n",r);
/* S is unicode */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!S!", 0,
0, out, sizeof(out)/sizeof(CHAR), szwTest);
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* as characters */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!c!%2!c!%3!c!%1!c!", 0,
0, out, sizeof(out)/sizeof(CHAR), 't','e','s');
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* some numbers */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!d!%2!d!%3!d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 1,2,3);
ok(!strcmp("123", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%ld\n",r);
/* a single digit with some spacing */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 1);
ok(!strcmp(" 1", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a single digit, left justified */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 1);
ok(!strcmp("1 ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* two digit decimal number */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 11);
ok(!strcmp(" 11", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a hex number */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4x!", 0,
0, out, sizeof(out)/sizeof(CHAR), 11);
ok(!strcmp(" b", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a hex number, upper case */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0,
0, out, sizeof(out)/sizeof(CHAR), 11);
ok(!strcmp(" B", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a hex number, upper case, left justified */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!-4X!", 0,
0, out, sizeof(out)/sizeof(CHAR), 11);
ok(!strcmp("B ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* a long hex number, upper case */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!4X!", 0,
0, out, sizeof(out)/sizeof(CHAR), 0x1ab);
ok(!strcmp(" 1AB", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* two percent... */
r = doit(FORMAT_MESSAGE_FROM_STRING, " %%%% ", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp(" %% ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* periods are special cases */
r = doit(FORMAT_MESSAGE_FROM_STRING, " %.%. %1!d!", 0,
0, out, sizeof(out)/sizeof(CHAR), 0x1ab);
ok(!strcmp(" .. 427", out),"failed out=[%s]\n",out);
ok(r==7,"failed: r=%ld\n",r);
/* %0 ends the line */
r = doit(FORMAT_MESSAGE_FROM_STRING, "test%0test", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("test", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* %! prints an exclaimation */
r = doit(FORMAT_MESSAGE_FROM_STRING, "yah%!%0 ", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("yah!", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* %space */
r = doit(FORMAT_MESSAGE_FROM_STRING, "% % ", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("hi\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING, "hi\r\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("hi\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING, "\r", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("\r\n", out),"failed out=[%s]\n",out);
ok(r==2,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING, "\r\r\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("\r\n\r\n", out),"failed out=[%s]\n",out);
ok(r==4,"failed: r=%ld\n",r);
/* change of pace... test the low byte of dwflags */
/* line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("hi ", out) || !strcmp("hi\r\n", out),"failed out=[%s]\n",out);
ok(r==3 || r==4,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "hi\r\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp("hi ", out),"failed out=[%s]\n",out);
ok(r==3,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==1,"failed: r=%ld\n",r);
/* carriage return line feed */
r = doit(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_MAX_WIDTH_MASK, "\r\r\n", 0,
0, out, sizeof(out)/sizeof(CHAR));
ok(!strcmp(" ", out),"failed out=[%s]\n",out);
ok(r==2,"failed: r=%ld\n",r);
}
START_TEST(format_msg)
{
test_message_from_string();
}

View file

@ -1,29 +1,35 @@
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_bitmap(void);
extern void func_brush(void);
extern void func_clipping(void);
extern void func_dc(void);
extern void func_font(void);
extern void func_gdiobj(void);
extern void func_generated(void);
extern void func_mapping(void);
extern void func_metafile(void);
extern void func_palette(void);
extern void func_pen(void);
struct test
{
const char *name;
void (*func)(void);
};
static const struct test winetest_testlist[] =
const struct test winetest_testlist[] =
{
{ "bitmap", func_bitmap },
{ "brush", func_brush },
// { "clipping", func_clipping },
// { "dc", func_dc },
// { "font", func_font },
{ "gdiobj", func_gdiobj },
// { "generated", func_generated },
// { "mapping", func_mapping },
{ "metafile", func_metafile },
// { "palette", func_palette },
// { "pen", func_pen },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,282 @@
/*
* Unit test suite for heap functions
*
* Copyright 2003 Dimitrie O. Paun
* Copyright 2006 Detlef Riekenberg
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wine/test.h"
#define MAGIC_DEAD 0xdeadbeef
static SIZE_T resize_9x(SIZE_T size)
{
DWORD dwSizeAligned = (size + 3) & ~3;
return max(dwSizeAligned, 12); /* at least 12 bytes */
}
START_TEST(heap)
{
LPVOID mem;
LPVOID msecond;
DWORD res;
UINT flags;
HGLOBAL gbl;
HGLOBAL hsecond;
SIZE_T size;
/* Heap*() functions */
mem = HeapAlloc(GetProcessHeap(), 0, 0);
ok(mem != NULL, "memory not allocated for size 0\n");
mem = HeapReAlloc(GetProcessHeap(), 0, NULL, 10);
ok(mem == NULL, "memory allocated by HeapReAlloc\n");
for (size = 0; size <= 256; size++)
{
SIZE_T heap_size;
mem = HeapAlloc(GetProcessHeap(), 0, size);
heap_size = HeapSize(GetProcessHeap(), 0, mem);
ok(heap_size == size || heap_size == resize_9x(size),
"HeapSize returned %lu instead of %lu or %lu\n", heap_size, size, resize_9x(size));
HeapFree(GetProcessHeap(), 0, mem);
}
/* Global*() functions */
gbl = GlobalAlloc(GMEM_MOVEABLE, 0);
ok(gbl != NULL, "global memory not allocated for size 0\n");
gbl = GlobalReAlloc(gbl, 10, GMEM_MOVEABLE);
ok(gbl != NULL, "Can't realloc global memory\n");
size = GlobalSize(gbl);
ok(size >= 10 && size <= 16, "Memory not resized to size 10, instead size=%ld\n", size);
gbl = GlobalReAlloc(gbl, 0, GMEM_MOVEABLE);
ok(gbl != NULL, "GlobalReAlloc should not fail on size 0\n");
size = GlobalSize(gbl);
ok(size == 0, "Memory not resized to size 0, instead size=%ld\n", size);
ok(GlobalFree(gbl) == NULL, "Memory not freed\n");
size = GlobalSize(gbl);
ok(size == 0, "Memory should have been freed, size=%ld\n", size);
gbl = GlobalReAlloc(0, 10, GMEM_MOVEABLE);
ok(gbl == NULL, "global realloc allocated memory\n");
/* GlobalLock / GlobalUnlock with a valid handle */
gbl = GlobalAlloc(GMEM_MOVEABLE, 256);
SetLastError(MAGIC_DEAD);
mem = GlobalLock(gbl); /* #1 */
ok(mem != NULL, "returned %p with %ld (expected '!= NULL')\n", mem, GetLastError());
SetLastError(MAGIC_DEAD);
flags = GlobalFlags(gbl);
ok( flags == 1, "returned 0x%04x with %ld (expected '0x0001')\n",
flags, GetLastError());
SetLastError(MAGIC_DEAD);
msecond = GlobalLock(gbl); /* #2 */
ok( msecond == mem, "returned %p with %ld (expected '%p')\n",
msecond, GetLastError(), mem);
SetLastError(MAGIC_DEAD);
flags = GlobalFlags(gbl);
ok( flags == 2, "returned 0x%04x with %ld (expected '0x0002')\n",
flags, GetLastError());
SetLastError(MAGIC_DEAD);
SetLastError(MAGIC_DEAD);
res = GlobalUnlock(gbl); /* #1 */
ok(res, "returned %ld with %ld (expected '!= 0')\n", res, GetLastError());
SetLastError(MAGIC_DEAD);
flags = GlobalFlags(gbl);
ok( flags , "returned 0x%04x with %ld (expected '!= 0')\n",
flags, GetLastError());
SetLastError(MAGIC_DEAD);
res = GlobalUnlock(gbl); /* #0 */
/* NT: ERROR_SUCCESS (documented on MSDN), 9x: untouched */
ok(!res && ((GetLastError() == ERROR_SUCCESS) || (GetLastError() == MAGIC_DEAD)),
"returned %ld with %ld (expected '0' with: ERROR_SUCCESS or " \
"MAGIC_DEAD)\n", res, GetLastError());
SetLastError(MAGIC_DEAD);
flags = GlobalFlags(gbl);
ok( !flags , "returned 0x%04x with %ld (expected '0')\n",
flags, GetLastError());
/* Unlock an already unlocked Handle */
SetLastError(MAGIC_DEAD);
res = GlobalUnlock(gbl);
/* NT: ERROR_NOT_LOCKED, 9x: untouched */
ok( !res &&
((GetLastError() == ERROR_NOT_LOCKED) || (GetLastError() == MAGIC_DEAD)),
"returned %ld with %ld (expected '0' with: ERROR_NOT_LOCKED or " \
"MAGIC_DEAD)\n", res, GetLastError());
GlobalFree(gbl);
/* invalid handles are catched in windows: */
SetLastError(MAGIC_DEAD);
hsecond = GlobalFree(gbl); /* invalid handle: free memory twice */
ok( (hsecond == gbl) && (GetLastError() == ERROR_INVALID_HANDLE),
"returned %p with 0x%08lx (expected %p with ERROR_INVALID_HANDLE)\n",
hsecond, GetLastError(), gbl);
SetLastError(MAGIC_DEAD);
flags = GlobalFlags(gbl);
ok( (flags == GMEM_INVALID_HANDLE) && (GetLastError() == ERROR_INVALID_HANDLE),
"returned 0x%04x with 0x%08lx (expected GMEM_INVALID_HANDLE with " \
"ERROR_INVALID_HANDLE)\n", flags, GetLastError());
SetLastError(MAGIC_DEAD);
size = GlobalSize(gbl);
ok( (size == 0) && (GetLastError() == ERROR_INVALID_HANDLE),
"returned %ld with 0x%08lx (expected '0' with ERROR_INVALID_HANDLE)\n",
size, GetLastError());
SetLastError(MAGIC_DEAD);
mem = GlobalLock(gbl);
ok( (mem == NULL) && (GetLastError() == ERROR_INVALID_HANDLE),
"returned %p with 0x%08lx (expected NULL with ERROR_INVALID_HANDLE)\n",
mem, GetLastError());
/* documented on MSDN: GlobalUnlock() return FALSE on failure.
Win9x and wine return FALSE with ERROR_INVALID_HANDLE, but on
NT 3.51 and XPsp2, TRUE with ERROR_INVALID_HANDLE is returned.
The similar Test for LocalUnlock() works on all Systems */
SetLastError(MAGIC_DEAD);
res = GlobalUnlock(gbl);
ok(GetLastError() == ERROR_INVALID_HANDLE,
"returned %ld with %ld (expected ERROR_INVALID_HANDLE)\n",
res, GetLastError());
/* ####################################### */
/* Local*() functions */
gbl = LocalAlloc(LMEM_MOVEABLE, 0);
ok(gbl != NULL, "local memory not allocated for size 0\n");
gbl = LocalReAlloc(gbl, 10, LMEM_MOVEABLE);
ok(gbl != NULL, "Can't realloc local memory\n");
size = LocalSize(gbl);
ok(size >= 10 && size <= 16, "Memory not resized to size 10, instead size=%ld\n", size);
gbl = LocalReAlloc(gbl, 0, LMEM_MOVEABLE);
ok(gbl != NULL, "LocalReAlloc should not fail on size 0\n");
size = LocalSize(gbl);
ok(size == 0, "Memory not resized to size 0, instead size=%ld\n", size);
ok(LocalFree(gbl) == NULL, "Memory not freed\n");
size = LocalSize(gbl);
ok(size == 0, "Memory should have been freed, size=%ld\n", size);
gbl = LocalReAlloc(0, 10, LMEM_MOVEABLE);
ok(gbl == NULL, "local realloc allocated memory\n");
/* LocalLock / LocalUnlock with a valid handle */
gbl = LocalAlloc(LMEM_MOVEABLE, 256);
SetLastError(MAGIC_DEAD);
mem = LocalLock(gbl); /* #1 */
ok(mem != NULL, "returned %p with %ld (expected '!= NULL')\n", mem, GetLastError());
SetLastError(MAGIC_DEAD);
flags = LocalFlags(gbl);
ok( flags == 1, "returned 0x%04x with %ld (expected '0x0001')\n",
flags, GetLastError());
SetLastError(MAGIC_DEAD);
msecond = LocalLock(gbl); /* #2 */
ok( msecond == mem, "returned %p with %ld (expected '%p')\n",
msecond, GetLastError(), mem);
SetLastError(MAGIC_DEAD);
flags = LocalFlags(gbl);
ok( flags == 2, "returned 0x%04x with %ld (expected '0x0002')\n",
flags, GetLastError());
SetLastError(MAGIC_DEAD);
SetLastError(MAGIC_DEAD);
res = LocalUnlock(gbl); /* #1 */
ok(res, "returned %ld with %ld (expected '!= 0')\n", res, GetLastError());
SetLastError(MAGIC_DEAD);
flags = LocalFlags(gbl);
ok( flags , "returned 0x%04x with %ld (expected '!= 0')\n",
flags, GetLastError());
SetLastError(MAGIC_DEAD);
res = LocalUnlock(gbl); /* #0 */
/* NT: ERROR_SUCCESS (documented on MSDN), 9x: untouched */
ok(!res && ((GetLastError() == ERROR_SUCCESS) || (GetLastError() == MAGIC_DEAD)),
"returned %ld with %ld (expected '0' with: ERROR_SUCCESS or " \
"MAGIC_DEAD)\n", res, GetLastError());
SetLastError(MAGIC_DEAD);
flags = LocalFlags(gbl);
ok( !flags , "returned 0x%04x with %ld (expected '0')\n",
flags, GetLastError());
/* Unlock an already unlocked Handle */
SetLastError(MAGIC_DEAD);
res = LocalUnlock(gbl);
/* NT: ERROR_NOT_LOCKED, 9x: untouched */
ok( !res &&
((GetLastError() == ERROR_NOT_LOCKED) || (GetLastError() == MAGIC_DEAD)),
"returned %ld with %ld (expected '0' with: ERROR_NOT_LOCKED or " \
"MAGIC_DEAD)\n", res, GetLastError());
LocalFree(gbl);
/* invalid handles are catched in windows: */
SetLastError(MAGIC_DEAD);
hsecond = LocalFree(gbl); /* invalid handle: free memory twice */
ok( (hsecond == gbl) && (GetLastError() == ERROR_INVALID_HANDLE),
"returned %p with 0x%08lx (expected %p with ERROR_INVALID_HANDLE)\n",
hsecond, GetLastError(), gbl);
SetLastError(MAGIC_DEAD);
flags = LocalFlags(gbl);
ok( (flags == LMEM_INVALID_HANDLE) && (GetLastError() == ERROR_INVALID_HANDLE),
"returned 0x%04x with 0x%08lx (expected LMEM_INVALID_HANDLE with " \
"ERROR_INVALID_HANDLE)\n", flags, GetLastError());
SetLastError(MAGIC_DEAD);
size = LocalSize(gbl);
ok( (size == 0) && (GetLastError() == ERROR_INVALID_HANDLE),
"returned %ld with 0x%08lx (expected '0' with ERROR_INVALID_HANDLE)\n",
size, GetLastError());
SetLastError(MAGIC_DEAD);
mem = LocalLock(gbl);
ok( (mem == NULL) && (GetLastError() == ERROR_INVALID_HANDLE),
"returned %p with 0x%08lx (expected NULL with ERROR_INVALID_HANDLE)\n",
mem, GetLastError());
/* This Test works the same on all Systems (GlobalUnlock() is different) */
SetLastError(MAGIC_DEAD);
res = LocalUnlock(gbl);
ok(!res && (GetLastError() == ERROR_INVALID_HANDLE),
"returned %ld with %ld (expected '0' with ERROR_INVALID_HANDLE)\n",
res, GetLastError());
/* trying to lock empty memory should give an error */
gbl = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,0);
ok(gbl != NULL, "returned NULL\n");
SetLastError(MAGIC_DEAD);
mem = GlobalLock(gbl);
/* NT: ERROR_DISCARDED, 9x: untouched */
ok( (mem == NULL) &&
((GetLastError() == ERROR_DISCARDED) || (GetLastError() == MAGIC_DEAD)),
"returned %p with 0x%lx/%ld (expected 'NULL' with: ERROR_DISCARDED or " \
"MAGIC_DEAD)\n", mem, GetLastError(), GetLastError());
GlobalFree(gbl);
}

View file

@ -1,5 +1,8 @@
/* Automatically generated file; DO NOT EDIT!! */
#define STANDALONE
#include "wine/test.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@ -32,12 +35,6 @@ extern void func_time(void);
extern void func_timer(void);
extern void func_virtual(void);
struct test
{
const char *name;
void (*func)(void);
};
const struct test winetest_testlist[] =
{
{ "alloc", func_alloc },
@ -67,6 +64,3 @@ const struct test winetest_testlist[] =
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,290 @@
/*
* Mailslot regression test
*
* Copyright 2003 Mike McCormack
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <windef.h>
#include <winbase.h>
#include "wine/test.h"
static const char szmspath[] = "\\\\.\\mailslot\\wine_mailslot_test";
static int mailslot_test(void)
{
HANDLE hSlot, hSlot2, hWriter, hWriter2;
unsigned char buffer[16];
DWORD count, dwMax, dwNext, dwMsgCount, dwTimeout;
/* sanity check on GetMailslotInfo */
dwMax = dwNext = dwMsgCount = dwTimeout = 0;
ok( !GetMailslotInfo( INVALID_HANDLE_VALUE, &dwMax, &dwNext,
&dwMsgCount, &dwTimeout ), "getmailslotinfo succeeded\n");
/* open a mailslot that doesn't exist */
hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter == INVALID_HANDLE_VALUE, "nonexistent mailslot\n");
/* open a mailslot without the right name */
hSlot = CreateMailslot( "blah", 0, 0, NULL );
ok( hSlot == INVALID_HANDLE_VALUE,
"Created mailslot with invalid name\n");
ok( GetLastError() == ERROR_INVALID_NAME,
"error should be ERROR_INVALID_NAME\n");
/* open a mailslot with a null name */
hSlot = CreateMailslot( NULL, 0, 0, NULL );
ok( hSlot == INVALID_HANDLE_VALUE,
"Created mailslot with invalid name\n");
ok( GetLastError() == ERROR_PATH_NOT_FOUND,
"error should be ERROR_PATH_NOT_FOUND\n");
/* valid open, but with wacky parameters ... then check them */
hSlot = CreateMailslot( szmspath, -1, -1, NULL );
ok( hSlot != INVALID_HANDLE_VALUE , "mailslot with valid name failed\n");
dwMax = dwNext = dwMsgCount = dwTimeout = 0;
ok( GetMailslotInfo( hSlot, &dwMax, &dwNext, &dwMsgCount, &dwTimeout ),
"getmailslotinfo failed\n");
ok( dwMax == ~0U, "dwMax incorrect\n");
ok( dwNext == MAILSLOT_NO_MESSAGE, "dwNext incorrect\n");
ok( dwMsgCount == 0, "dwMsgCount incorrect\n");
ok( dwTimeout == ~0U, "dwTimeout incorrect\n");
ok( GetMailslotInfo( hSlot, NULL, NULL, NULL, NULL ),
"getmailslotinfo failed\n");
ok( CloseHandle(hSlot), "failed to close mailslot\n");
/* now open it for real */
hSlot = CreateMailslot( szmspath, 0, 0, NULL );
ok( hSlot != INVALID_HANDLE_VALUE , "valid mailslot failed\n");
/* try and read/write to it */
count = 0;
memset(buffer, 0, sizeof buffer);
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"slot read\n");
ok( !WriteFile( hSlot, buffer, sizeof buffer, &count, NULL),
"slot write\n");
/* now try and openthe client, but with the wrong sharing mode */
hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter == INVALID_HANDLE_VALUE, "bad sharing mode\n");
ok( GetLastError() == ERROR_SHARING_VIOLATION,
"error should be ERROR_SHARING_VIOLATION\n");
/* now open the client with the correct sharing mode */
hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter != INVALID_HANDLE_VALUE, "existing mailslot\n");
/*
* opening a client should make no difference to
* whether we can read or write the mailslot
*/
ok( !ReadFile( hSlot, buffer, sizeof buffer/2, &count, NULL),
"slot read\n");
ok( !WriteFile( hSlot, buffer, sizeof buffer/2, &count, NULL),
"slot write\n");
/*
* we can't read from this client,
* but we should be able to write to it
*/
ok( !ReadFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
"can read client\n");
ok( WriteFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
"can't write client\n");
ok( !ReadFile( hWriter, buffer, sizeof buffer/2, &count, NULL),
"can read client\n");
/*
* seeing as there's something in the slot,
* we should be able to read it once
*/
ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"slot read\n");
ok( count == (sizeof buffer/2), "short read\n" );
/* but not again */
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"slot read\n");
/* now try open another writer... should fail */
hWriter2 = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 == INVALID_HANDLE_VALUE, "two writers\n");
/* now try open another as a reader ... also fails */
hWriter2 = CreateFile(szmspath, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 == INVALID_HANDLE_VALUE, "writer + reader\n");
/* now try open another as a writer ... still fails */
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 == INVALID_HANDLE_VALUE, "writer\n");
/* now open another one */
hSlot2 = CreateMailslot( szmspath, 0, 0, NULL );
ok( hSlot2 == INVALID_HANDLE_VALUE , "opened two mailslots\n");
/* close the client again */
ok( CloseHandle( hWriter ), "closing the client\n");
/*
* now try reopen it with slightly different permissions ...
* shared writing
*/
hWriter = CreateFile(szmspath, GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter != INVALID_HANDLE_VALUE, "sharing writer\n");
/*
* now try open another as a writer ...
* but don't share with the first ... fail
*/
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 == INVALID_HANDLE_VALUE, "greedy writer succeeded\n");
/* now try open another as a writer ... and share with the first */
hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
ok( hWriter2 != INVALID_HANDLE_VALUE, "2nd sharing writer\n");
/* check the mailslot info */
dwMax = dwNext = dwMsgCount = dwTimeout = 0;
ok( GetMailslotInfo( hSlot, &dwMax, &dwNext, &dwMsgCount, &dwTimeout ),
"getmailslotinfo failed\n");
ok( dwNext == MAILSLOT_NO_MESSAGE, "dwNext incorrect\n");
ok( dwMax == 0, "dwMax incorrect\n");
ok( dwMsgCount == 0, "dwMsgCount incorrect\n");
ok( dwTimeout == 0, "dwTimeout incorrect\n");
/* check there's still no data */
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL), "slot read\n");
/* write two messages */
buffer[0] = 'a';
ok( WriteFile( hWriter, buffer, 1, &count, NULL), "1st write failed\n");
/* check the mailslot info */
dwNext = dwMsgCount = 0;
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
ok( dwNext == 1, "dwNext incorrect\n");
ok( dwMsgCount == 1, "dwMsgCount incorrect\n");
buffer[0] = 'b';
buffer[1] = 'c';
ok( WriteFile( hWriter2, buffer, 2, &count, NULL), "2nd write failed\n");
/* check the mailslot info */
dwNext = dwMsgCount = 0;
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
ok( dwNext == 1, "dwNext incorrect\n");
todo_wine {
ok( dwMsgCount == 2, "dwMsgCount incorrect\n");
}
/* write a 3rd message with zero size */
ok( WriteFile( hWriter2, buffer, 0, &count, NULL), "3rd write failed\n");
/* check the mailslot info */
dwNext = dwMsgCount = 0;
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
ok( dwNext == 1, "dwNext incorrect\n");
todo_wine {
ok( dwMsgCount == 3, "dwMsgCount incorrect\n");
}
buffer[0]=buffer[1]=0;
/*
* then check that they come out with the correct order and size,
* then the slot is empty
*/
ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"1st slot read failed\n");
ok( count == 1, "failed to get 1st message\n");
ok( buffer[0] == 'a', "1st message wrong\n");
/* check the mailslot info */
dwNext = dwMsgCount = 0;
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
ok( dwNext == 2, "dwNext incorrect\n");
todo_wine {
ok( dwMsgCount == 2, "dwMsgCount incorrect\n");
}
/* read the second message */
ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"2nd slot read failed\n");
ok( count == 2, "failed to get 2nd message\n");
ok( ( buffer[0] == 'b' ) && ( buffer[1] == 'c' ), "2nd message wrong\n");
/* check the mailslot info */
dwNext = dwMsgCount = 0;
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
todo_wine {
ok( dwNext == 0, "dwNext incorrect\n");
ok( dwMsgCount == 1, "dwMsgCount incorrect\n");
}
/* read the 3rd (zero length) message */
todo_wine {
ok( ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"3rd slot read failed\n");
}
ok( count == 0, "failed to get 3rd message\n");
/*
* now there should be no more messages
* check the mailslot info
*/
dwNext = dwMsgCount = 0;
ok( GetMailslotInfo( hSlot, NULL, &dwNext, &dwMsgCount, NULL ),
"getmailslotinfo failed\n");
ok( dwNext == MAILSLOT_NO_MESSAGE, "dwNext incorrect\n");
ok( dwMsgCount == 0, "dwMsgCount incorrect\n");
/* check that reads fail */
ok( !ReadFile( hSlot, buffer, sizeof buffer, &count, NULL),
"3rd slot read succeeded\n");
/* finally close the mailslot and its client */
ok( CloseHandle( hWriter2 ), "closing 2nd client\n");
ok( CloseHandle( hWriter ), "closing the client\n");
ok( CloseHandle( hSlot ), "closing the mailslot\n");
return 0;
}
START_TEST(mailslot)
{
mailslot_test();
}

View file

@ -0,0 +1,184 @@
/*
* Unit tests for module/DLL/library API
*
* Copyright (c) 2004 Eric Pouech
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/test.h"
#include <windows.h>
static BOOL is_unicode_enabled = TRUE;
static BOOL cmpStrAW(const char* a, const WCHAR* b, DWORD lenA, DWORD lenB)
{
WCHAR aw[1024];
DWORD len = MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
a, lenA, aw, sizeof(aw) / sizeof(aw[0]) );
if (len != lenB) return FALSE;
return memcmp(aw, b, len * sizeof(WCHAR)) == 0;
}
static void testGetModuleFileName(const char* name)
{
HMODULE hMod;
char bufA[MAX_PATH];
WCHAR bufW[MAX_PATH];
DWORD len1A, len1W = 0, len2A, len2W = 0;
hMod = (name) ? GetModuleHandle(name) : NULL;
/* first test, with enough space in buffer */
memset(bufA, '-', sizeof(bufA));
len1A = GetModuleFileNameA(hMod, bufA, sizeof(bufA));
ok(len1A > 0, "Getting module filename for handle %p\n", hMod);
if (is_unicode_enabled)
{
memset(bufW, '-', sizeof(bufW));
len1W = GetModuleFileNameW(hMod, bufW, sizeof(bufW) / sizeof(WCHAR));
ok(len1W > 0, "Getting module filename for handle %p\n", hMod);
}
ok(len1A == strlen(bufA), "Unexpected length of GetModuleFilenameA (%ld/%d)\n", len1A, strlen(bufA));
if (is_unicode_enabled)
{
ok(len1W == lstrlenW(bufW), "Unexpected length of GetModuleFilenameW (%ld/%d)\n", len1W, lstrlenW(bufW));
ok(cmpStrAW(bufA, bufW, len1A, len1W), "Comparing GetModuleFilenameAW results\n");
}
/* second test with a buffer too small */
memset(bufA, '-', sizeof(bufA));
len2A = GetModuleFileNameA(hMod, bufA, len1A / 2);
ok(len2A > 0, "Getting module filename for handle %p\n", hMod);
if (is_unicode_enabled)
{
memset(bufW, '-', sizeof(bufW));
len2W = GetModuleFileNameW(hMod, bufW, len1W / 2);
ok(len2W > 0, "Getting module filename for handle %p\n", hMod);
ok(cmpStrAW(bufA, bufW, len2A, len2W), "Comparing GetModuleFilenameAW results with buffer too small\n" );
ok(len1W / 2 == len2W, "Correct length in GetModuleFilenameW with buffer too small (%ld/%ld)\n", len1W / 2, len2W);
}
ok(len1A / 2 == len2A ||
len1A / 2 == len2A + 1, /* Win9x */
"Correct length in GetModuleFilenameA with buffer too small (%ld/%ld)\n", len1A / 2, len2A);
}
static void testGetModuleFileName_Wrong(void)
{
char bufA[MAX_PATH];
WCHAR bufW[MAX_PATH];
/* test wrong handle */
if (is_unicode_enabled)
{
bufW[0] = '*';
ok(GetModuleFileNameW((void*)0xffffffff, bufW, sizeof(bufW) / sizeof(WCHAR)) == 0, "Unexpected success in module handle\n");
ok(bufW[0] == '*', "When failing, buffer shouldn't be written to\n");
}
bufA[0] = '*';
ok(GetModuleFileNameA((void*)0xffffffff, bufA, sizeof(bufA)) == 0, "Unexpected success in module handle\n");
ok(bufA[0] == '*' ||
bufA[0] == 0 /* Win9x */,
"When failing, buffer shouldn't be written to\n");
}
static void testLoadLibraryA(void)
{
HMODULE hModule, hModule1;
FARPROC fp;
SetLastError(0xdeadbeef);
hModule = LoadLibraryA("kernel32.dll");
ok( hModule != NULL, "kernel32.dll should be loadable\n");
ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %08lx\n", GetLastError());
fp = GetProcAddress(hModule, "CreateFileA");
ok( fp != NULL, "CreateFileA should be there\n");
ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %08lx\n", GetLastError());
SetLastError(0xdeadbeef);
hModule1 = LoadLibraryA("kernel32 ");
/* Only winNT does this */
if (GetLastError() != ERROR_DLL_NOT_FOUND)
{
ok( hModule1 != NULL, "\"kernel32 \" should be loadable\n");
ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %08lx\n", GetLastError());
ok( hModule == hModule1, "Loaded wrong module\n");
FreeLibrary(hModule1);
}
FreeLibrary(hModule);
}
static void testLoadLibraryA_Wrong(void)
{
HMODULE hModule;
/* Try to load a nonexistent dll */
SetLastError(0xdeadbeef);
hModule = LoadLibraryA("non_ex_pv.dll");
ok( !hModule, "non_ex_pv.dll should be not loadable\n");
ok( GetLastError() == ERROR_MOD_NOT_FOUND || GetLastError() == ERROR_DLL_NOT_FOUND,
"Expected ERROR_MOD_NOT_FOUND or ERROR_DLL_NOT_FOUND (win9x), got %08lx\n", GetLastError());
/* Just in case */
FreeLibrary(hModule);
}
static void testGetProcAddress_Wrong(void)
{
FARPROC fp;
SetLastError(0xdeadbeef);
fp = GetProcAddress(NULL, "non_ex_call");
ok( !fp, "non_ex_call should not be found\n");
ok( GetLastError() == ERROR_PROC_NOT_FOUND || GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_PROC_NOT_FOUND or ERROR_INVALID_HANDLE(win9x), got %08lx\n", GetLastError());
SetLastError(0xdeadbeef);
fp = GetProcAddress((HMODULE)0xdeadbeef, "non_ex_call");
ok( !fp, "non_ex_call should not be found\n");
ok( GetLastError() == ERROR_MOD_NOT_FOUND || GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_HANDLE(win9x), got %08lx\n", GetLastError());
}
START_TEST(module)
{
WCHAR filenameW[MAX_PATH];
/* Test if we can use GetModuleFileNameW */
SetLastError(0xdeadbeef);
GetModuleFileNameW(NULL, filenameW, MAX_PATH);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
trace("GetModuleFileNameW not existing on this platform, skipping W-calls\n");
is_unicode_enabled = FALSE;
}
testGetModuleFileName(NULL);
testGetModuleFileName("kernel32.dll");
testGetModuleFileName_Wrong();
testLoadLibraryA();
testLoadLibraryA_Wrong();
testGetProcAddress_Wrong();
}

View file

@ -1,34 +1,29 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_cpp(void);
extern void func_dir(void);
extern void func_environ(void);
extern void func_file(void);
extern void func_headers(void);
extern void func_heap(void);
extern void func_printf(void);
extern void func_scanf(void);
extern void func_string(void);
extern void func_time(void);
struct test
{
const char *name;
void (*func)(void);
};
static const struct test winetest_testlist[] =
const struct test winetest_testlist[] =
{
{ "cpp", func_cpp },
{ "dir", func_dir },
{ "environ", func_environ },
{ "file", func_file },
// { "headers", func_headers },
{ "heap", func_heap },
{ "printf", func_printf },
{ "scanf", func_scanf },
@ -36,6 +31,3 @@ static const struct test winetest_testlist[] =
{ "time", func_time },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -1,19 +1,22 @@
/* Automatically generated file; DO NOT EDIT!! */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_atom(void);
extern void func_change(void);
extern void func_env(void);
extern void func_error(void);
extern void func_exception(void);
extern void func_generated(void);
extern void func_info(void);
extern void func_large_int(void);
extern void func_om(void);
extern void func_path(void);
extern void func_port(void);
extern void func_reg(void);
extern void func_rtl(void);
extern void func_rtlbitmap(void);
@ -21,22 +24,19 @@ extern void func_rtlstr(void);
extern void func_string(void);
extern void func_time(void);
struct test
{
const char *name;
void (*func)(void);
};
const struct test winetest_testlist[] =
{
{ "atom", func_atom },
// { "change", func_change },
{ "env", func_env },
{ "error", func_error },
// { "exception", func_exception },
// { "generated", func_generated },
{ "info", func_info },
{ "large_int", func_large_int },
{ "om", func_om },
{ "path", func_path },
// { "port", func_port },
{ "reg", func_reg },
{ "rtl", func_rtl },
{ "rtlbitmap", func_rtlbitmap },
@ -45,7 +45,3 @@ const struct test winetest_testlist[] =
{ "time", func_time },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -0,0 +1,942 @@
/*
* Unit test suite for Get*PathNamesA and (Get|Set)CurrentDirectoryA.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winerror.h"
#include "winnls.h"
#define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
#define LONGFILE "Long File test.path"
#define SHORTFILE "pathtest.pth"
#define SHORTDIR "shortdir"
#define LONGDIR "Long Directory"
#define NONFILE_SHORT "noexist.pth"
#define NONFILE_LONG "NonExistent File"
#define NONDIR_SHORT "notadir"
#define NONDIR_LONG "NonExistent Directory"
#define NOT_A_VALID_DRIVE '@'
/* the following characters don't work well with GetFullPathNameA
in Win98. I don't know if this is a FAT thing, or if it is an OS thing
but I don't test these characters now.
NOTE: Win2k allows GetFullPathNameA to work with them though
|<>"
*/
static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
static const CHAR is_char_ok[] ="11111110111111111011";
static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
/* a structure to deal with wine todos somewhat cleanly */
typedef struct {
DWORD shortlen;
DWORD shorterror;
DWORD s2llen;
DWORD s2lerror;
DWORD longlen;
DWORD longerror;
} SLpassfail;
/* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
/* NOTE: the passfail structure is used to allow cutomizeable todo checking
for wine. It is not very pretty, but it sure beats duplicating this
function lots of times
*/
static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
{
CHAR tmpstr[MAX_PATH],
fullpath[MAX_PATH], /*full path to the file (not short/long) */
subpath[MAX_PATH], /*relative path to the file */
fullpathshort[MAX_PATH], /*absolue path to the file (short format) */
fullpathlong[MAX_PATH], /*absolute path to the file (long format) */
curdirshort[MAX_PATH], /*absolute path to the current dir (short) */
curdirlong[MAX_PATH]; /*absolute path to the current dir (long) */
LPSTR strptr; /*ptr to the filename portion of the path */
DWORD len;
/* if passfail is NULL, we can perform all checks within this function,
otherwise, we will return the relevant data in the passfail struct, so
we must initialize it first
*/
if(passfail!=NULL) {
passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
}
/* GetLongPathNameA is only supported on Win2k+ and Win98+ */
if(pGetLongPathNameA) {
ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
"%s: GetLongPathNameA failed\n",errstr);
/*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
ok(! HAS_TRAIL_SLASH_A(curdirlong),
"%s: GetLongPathNameA should not have a trailing \\\n",errstr);
}
ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
"%s: GetShortPathNameA failed\n",errstr);
/*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
ok(! HAS_TRAIL_SLASH_A(curdirshort),
"%s: GetShortPathNameA should not have a trailing \\\n",errstr);
/* build relative and absolute paths from inputs */
if(lstrlenA(subdir)) {
sprintf(subpath,"%s\\%s",subdir,filename);
} else {
lstrcpyA(subpath,filename);
}
sprintf(fullpath,"%s\\%s",curdir,subpath);
sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
/* Test GetFullPathNameA functionality */
len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
if(HAS_TRAIL_SLASH_A(subpath)) {
ok(strptr==NULL,
"%s: GetFullPathNameA should not return a filename ptr\n",errstr);
ok(lstrcmpiA(fullpath,tmpstr)==0,
"%s: GetFullPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpath);
} else {
ok(lstrcmpiA(strptr,filename)==0,
"%s: GetFullPathNameA returned '%s' instead of '%s'\n",
errstr,strptr,filename);
ok(lstrcmpiA(fullpath,tmpstr)==0,
"%s: GetFullPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpath);
}
/* Test GetShortPathNameA functionality */
SetLastError(0);
len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
if(passfail==NULL) {
ok(len, "%s: GetShortPathNameA failed\n",errstr);
} else {
passfail->shortlen=len;
passfail->shorterror=GetLastError();
}
/* Test GetLongPathNameA functionality
We test both conversion from GetFullPathNameA and from GetShortPathNameA
*/
if(pGetLongPathNameA) {
if(len!=0) {
SetLastError(0);
len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
if(passfail==NULL) {
ok(len,
"%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
"%s: GetLongPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpathlong);
} else {
passfail->s2llen=len;
passfail->s2lerror=GetLastError();
}
}
SetLastError(0);
len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
if(passfail==NULL) {
ok(len, "%s: GetLongPathNameA failed\n",errstr);
if(HAS_TRAIL_SLASH_A(fullpath)) {
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
"%s: GetLongPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpathlong);
} else {
ok(lstrcmpiA(fullpathlong,tmpstr)==0,
"%s: GetLongPathNameA returned '%s' instead of '%s'\n",
errstr,tmpstr,fullpathlong);
}
} else {
passfail->longlen=len;
passfail->longerror=GetLastError();
}
}
}
/* split path into leading directory, and 8.3 filename */
static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
int done,error;
int ext,fil;
int len,i;
len=lstrlenA(path);
ext=len; fil=len; done=0; error=0;
/* walk backwards over path looking for '.' or '\\' separators */
for(i=len-1;(i>=0) && (!done);i--) {
if(path[i]=='.')
if(ext!=len) error=1; else ext=i;
else if(path[i]=='\\') {
if(i==len-1) {
error=1;
} else {
fil=i;
done=1;
}
}
}
/* Check that we didn't find a trailing '\\' or multiple '.' */
ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
/* Separate dir, root, and extension */
if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
if(fil!=len) {
lstrcpynA(eight,path+fil+1,ext-fil);
lstrcpynA(dir,path,fil+1);
} else {
lstrcpynA(eight,path,ext+1);
lstrcpyA(dir,"");
}
/* Validate that root and extension really are 8.3 */
ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
"GetShortPathNAmeA did not return an 8.3 path\n");
}
/* Check that GetShortPathNameA returns a valid 8.3 path */
static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
const CHAR *ext,const CHAR *errstr) {
CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
test_SplitShortPathA(teststr,dir,eight,three);
ok(lstrcmpiA(dir,goodstr)==0,
"GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
ok(lstrcmpiA(three,ext)==0,
"GetShortPathNameA returned '%s' with incorrect extension\n",three);
}
/* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
characters in the filename.
'valid' indicates whether this would be an allowed filename
'todo' indicates that wine doesn't get this right yet.
NOTE: We always call this routine with a nonexistent filename, so
Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
should.
*/
static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
{
CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
SLpassfail passfail;
test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
if(valid) {
sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
ok((passfail.shortlen==0 &&
(passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
(passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
"%s: GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
errstr,passfail.shortlen,passfail.shorterror,tmpstr);
} else {
ok(passfail.shortlen==0 &&
(passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
"%s: GetShortPathA should have failed len=%ld, error=%ld\n",
errstr,passfail.shortlen,passfail.shorterror);
}
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
if(valid) {
ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
"%s: GetLongPathA returned %ld and not %d\n",
errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
} else {
ok(passfail.longerror==ERROR_INVALID_NAME ||
passfail.longerror==ERROR_FILE_NOT_FOUND,
"%s: GetLongPathA returned %ld and not %d or %d'\n",
errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
}
}
}
/* Routine to test that SetCurrentDirectory behaves as expected. */
static void test_setdir(CHAR *olddir,CHAR *newdir,
CHAR *cmprstr, INT pass, const CHAR *errstr)
{
CHAR tmppath[MAX_PATH], *dirptr;
DWORD val,len,chklen;
val=SetCurrentDirectoryA(newdir);
len=GetCurrentDirectoryA(MAX_PATH,tmppath);
/* if 'pass' then the SetDirectoryA was supposed to pass */
if(pass) {
dirptr=(cmprstr==NULL) ? newdir : cmprstr;
chklen=lstrlenA(dirptr);
ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
ok(len==chklen,
"%s: SetCurrentDirectory did not change the directory, though it passed\n",
errstr);
ok(lstrcmpiA(dirptr,tmppath)==0,
"%s: SetCurrentDirectory did not change the directory, though it passed\n",
errstr);
ok(SetCurrentDirectoryA(olddir),
"%s: Couldn't set directory to it's original value\n",errstr);
} else {
/* else thest that it fails correctly */
chklen=lstrlenA(olddir);
ok(val==0,
"%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
ok(len==chklen,
"%s: SetCurrentDirectory changed the directory, though it failed\n",
errstr);
ok(lstrcmpiA(olddir,tmppath)==0,
"%s: SetCurrentDirectory changed the directory, though it failed\n",
errstr);
}
}
static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
{
CHAR tmppath[MAX_PATH], /*path to TEMP */
tmpstr[MAX_PATH],
tmpstr1[MAX_PATH];
DWORD len,len1,drives;
INT id;
HANDLE hndl;
BOOL bRes;
*curDrive = *otherDrive = NOT_A_VALID_DRIVE;
/* Get the current drive letter */
if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
*curDrive = tmpstr[0];
else
trace( "Unable to discover current drive, some tests will not be conducted.\n");
/* Test GetTempPathA */
len=GetTempPathA(MAX_PATH,tmppath);
ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
ok(HAS_TRAIL_SLASH_A(tmppath),
"GetTempPathA returned a path that did not end in '\\'\n");
lstrcpyA(tmpstr,"aaaaaaaa");
len1=GetTempPathA(len,tmpstr);
ok(len1==len+1,
"GetTempPathA should return string length %ld instead of %ld\n",len+1,len1);
/* Test GetTmpFileNameA
The only test we do here is whether GetTempFileNameA passes or not.
We do not thoroughly test this function yet (specifically, whether
it behaves correctly when 'unique' is non zero)
*/
ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
"GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
newdir,tmpstr,tmpstr1,id);
ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
id=GetTempFileNameA(tmppath,NULL,0,newdir);
/* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
if (id)
{
sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
sprintf(tmpstr1,"%x.tmp",id & 0xffff);
ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
"GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
newdir,tmpstr,tmpstr1,id);
ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
}
/* Find first valid drive letter that is neither newdir[0] nor curDrive */
drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
if( *curDrive != NOT_A_VALID_DRIVE)
drives &= ~(1<<(*curDrive-'A'));
if( drives)
for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
else
trace( "Could not find alternative drive, some tests will not be conducted.\n");
/* Do some CreateDirectoryA tests */
/* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
really understand how they work.
More formal tests should be done along with CreateFile tests
*/
ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
ok(CreateDirectoryA(newdir,NULL)==0,
"CreateDirectoryA succeeded even though a file of the same name exists\n");
ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
/* Create some files to test other functions. Note, we will test CreateFileA
at some later point
*/
sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
bRes = CreateDirectoryA("c:",NULL);
ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
GetLastError() == ERROR_ALREADY_EXISTS),
"CreateDirectoryA(\"c:\" should have failed (%ld)\n", GetLastError());
bRes = CreateDirectoryA("c:\\",NULL);
ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
GetLastError() == ERROR_ALREADY_EXISTS),
"CreateDirectoryA(\"c:\\\" should have failed (%ld)\n", GetLastError());
sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
ok(CloseHandle(hndl),"CloseHandle failed\n");
sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
ok(CloseHandle(hndl),"CloseHandle failed\n");
sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
ok(CloseHandle(hndl),"CloseHandle failed\n");
sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
ok(CloseHandle(hndl),"CloseHandle failed\n");
}
/* Test GetCurrentDirectory & SetCurrentDirectory */
static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
{
CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
DWORD len,len1;
/* Save the original directory, so that we can return to it at the end
of the test
*/
len=GetCurrentDirectoryA(MAX_PATH,origdir);
ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
/* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
buffer size is too small to hold the current directory
*/
lstrcpyA(tmpstr,"aaaaaaa");
len1=GetCurrentDirectoryA(len,tmpstr);
ok(len1==len+1, "GetCurrentDirectoryA returned %ld instead of %ld\n",len1,len+1);
ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
"GetCurrentDirectoryA should not have modified the buffer\n");
/* SetCurrentDirectoryA shouldn't care whether the string has a
trailing '\\' or not
*/
sprintf(tmpstr,"%s\\",newdir);
test_setdir(origdir,tmpstr,newdir,1,"check 1");
test_setdir(origdir,newdir,NULL,1,"check 2");
/* Set the directory to the working area. We just tested that this works,
so why check it again.
*/
SetCurrentDirectoryA(newdir);
/* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
test_setdir(newdir,tmpstr,NULL,0,"check 3");
/* Check that SetCurrentDirectory fails for a nonexistent lond directory */
sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
test_setdir(newdir,tmpstr,NULL,0,"check 4");
/* Check that SetCurrentDirectory passes with a long directory */
sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
test_setdir(newdir,tmpstr,NULL,1,"check 5");
/* Check that SetCurrentDirectory passes with a short relative directory */
sprintf(tmpstr,"%s",SHORTDIR);
sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
/* starting with a '.' */
sprintf(tmpstr,".\\%s",SHORTDIR);
test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
/* Check that SetCurrentDirectory passes with a short relative directory */
sprintf(tmpstr,"%s",LONGDIR);
sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
/* starting with a '.' */
sprintf(tmpstr,".\\%s",LONGDIR);
test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
}
/* Cleanup the mess we made while executing these tests */
static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
{
CHAR tmpstr[MAX_PATH];
sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
}
/* This routine will test Get(Full|Short|Long)PathNameA */
static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
{
CHAR curdir_short[MAX_PATH],
longdir_short[MAX_PATH];
CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
LPSTR strptr; /*ptr to the filename portion of the path */
DWORD len;
INT i;
CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
SLpassfail passfail;
/* Get the short form of the current directory */
ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
"GetShortPathNameA failed\n");
ok(!HAS_TRAIL_SLASH_A(curdir_short),
"GetShortPathNameA should not have a trailing \\\n");
/* Get the short form of the absolute-path to LONGDIR */
sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
"GetShortPathNameA failed\n");
ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
"GetShortPathNameA should not have a trailing \\\n");
if (pGetLongPathNameA) {
DWORD rc1,rc2;
sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
rc2=(*pGetLongPathNameA)(curdir,NULL,0);
ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
"GetLongPathNameA: wrong return code, %ld instead of %d\n",
rc1, strlen(tmpstr)+1);
sprintf(dir,"%c:",curDrive);
rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
ok(strcmp(dir,tmpstr)==0,
"GetLongPathNameA: returned '%s' instead of '%s' (rc=%ld)\n",
tmpstr,dir,rc1);
}
/* Check the cases where both file and directory exist first */
/* Start with a 8.3 directory, 8.3 filename */
test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
ok(lstrcmpiA(tmpstr,tmpstr1)==0,
"GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
/* Now try a 8.3 directory, long file name */
test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
/* Next is a long directory, 8.3 file */
test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
ok(lstrcmpiA(tmpstr,tmpstr1)==0,
"GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
/*Lastly a long directory, long file */
test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
/* Now check all of the invalid file w/ valid directory combinations */
/* Start with a 8.3 directory, 8.3 filename */
test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
ok((passfail.shortlen==0 &&
(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
(passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
"GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
passfail.shortlen,passfail.shorterror,tmpstr);
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
}
/* Now try a 8.3 directory, long file name */
test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND ||
!passfail.shorterror,
"GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
}
/* Next is a long directory, 8.3 file */
test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
strcat(tmpstr1,"\\" NONFILE_SHORT);
ok((passfail.shortlen==0 &&
(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
(passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
"GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
passfail.shortlen,passfail.shorterror,tmpstr);
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
}
/*Lastly a long directory, long file */
test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND ||
!passfail.shorterror,
"GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
}
/* Now try again with directories that don't exist */
/* 8.3 directory, 8.3 filename */
test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
ok((passfail.shortlen==0 &&
(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
(passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
"GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
passfail.shortlen,passfail.shorterror,tmpstr);
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
passfail.longerror);
}
/* Now try a 8.3 directory, long file name */
test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND ||
!passfail.shorterror,
"GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
passfail.shorterror);
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
passfail.longerror);
}
/* Next is a long directory, 8.3 file */
test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND ||
!passfail.shorterror,
"GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
passfail.shorterror);
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
passfail.longerror);
}
/*Lastly a long directory, long file */
test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND ||
!passfail.shorterror,
"GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
passfail.shorterror);
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
passfail.longerror);
}
/* Next try directories ending with '\\' */
/* Existing Directories */
sprintf(tmpstr,"%s\\",SHORTDIR);
test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
sprintf(tmpstr,"%s\\",LONGDIR);
test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
/* Nonexistent directories */
sprintf(tmpstr,"%s\\",NONDIR_SHORT);
test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
ok((passfail.shortlen==0 &&
(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
(passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
"GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
passfail.shortlen,passfail.shorterror,tmpstr);
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetLongPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
passfail.longerror);
}
sprintf(tmpstr,"%s\\",NONDIR_LONG);
test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
passfail.shorterror==ERROR_FILE_NOT_FOUND ||
!passfail.shorterror,
"GetShortPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
passfail.shorterror);
if(pGetLongPathNameA) {
ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
"GetLongPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
passfail.longerror);
}
/* Test GetFullPathNameA with drive letters */
if( curDrive != NOT_A_VALID_DRIVE) {
sprintf(tmpstr,"%c:",curdir[0]);
ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
"GetFullPathNameA(%c:) failed\n", curdir[0]);
GetCurrentDirectoryA(MAX_PATH,tmpstr);
sprintf(tmpstr1,"%s\\",tmpstr);
ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
"GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
curdir[0],tmpstr2,tmpstr,tmpstr1);
sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
ok(lstrcmpiA(tmpstr,tmpstr1)==0,
"GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
ok(lstrcmpiA(SHORTFILE,strptr)==0,
"GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
}
/* Without a leading slash, insert the current directory if on the current drive */
sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
ok(lstrcmpiA(tmpstr,tmpstr1)==0,
"GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
ok(lstrcmpiA(SHORTFILE,strptr)==0,
"GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
/* Otherwise insert the missing leading slash */
if( otherDrive != NOT_A_VALID_DRIVE) {
sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
ok(lstrcmpiA(tmpstr,tmpstr1)==0,
"GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
ok(lstrcmpiA(SHORTFILE,strptr)==0,
"GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
}
/* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
So test for them. */
if( curDrive != NOT_A_VALID_DRIVE) {
sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
ok(lstrcmpiA(tmpstr,tmpstr1)==0,
"GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
ok(lstrcmpiA(SHORTFILE,strptr)==0,
"GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
}
/**/
sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
ok(lstrcmpiA(tmpstr,tmpstr1)==0,
"GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
ok(lstrcmpiA(SHORTFILE,strptr)==0,
"GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
/* Windows will insert a drive letter in front of an absolute UNIX path */
sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
ok(lstrcmpiA(tmpstr,tmpstr1)==0,
"GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
/* This passes in Wine because it still contains the pointer from the previous test */
ok(lstrcmpiA(SHORTFILE,strptr)==0,
"GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
/* Now try some relative paths */
ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
test_SplitShortPathA(tmpstr,dir,eight,three);
if(pGetLongPathNameA) {
ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
"GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
}
sprintf(tmpstr,".\\%s",LONGDIR);
ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
test_SplitShortPathA(tmpstr1,dir,eight,three);
ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
"GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
if(pGetLongPathNameA) {
ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
tmpstr);
ok(lstrcmpiA(tmpstr1,tmpstr)==0,
"GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
}
/* Check out Get*PathNameA on some funny characters */
for(i=0;i<lstrlenA(funny_chars);i++) {
INT valid;
valid=(is_char_ok[i]=='0') ? 0 : 1;
sprintf(tmpstr1,"check%d-1",i);
sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
sprintf(tmpstr1,"check%d-2",i);
sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
sprintf(tmpstr1,"check%d-3",i);
sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
sprintf(tmpstr1,"check%d-4",i);
sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
sprintf(tmpstr1,"check%d-5",i);
sprintf(tmpstr,"Long %c File",funny_chars[i]);
test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
sprintf(tmpstr1,"check%d-6",i);
sprintf(tmpstr,"%c Long File",funny_chars[i]);
test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
sprintf(tmpstr1,"check%d-7",i);
sprintf(tmpstr,"Long File %c",funny_chars[i]);
test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
}
}
static void test_GetTempPathA(char* tmp_dir)
{
DWORD len, len_with_null;
char buf[MAX_PATH];
len_with_null = strlen(tmp_dir) + 1;
lstrcpyA(buf, "foo");
len = GetTempPathA(MAX_PATH, buf);
ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
ok(len == strlen(buf), "returned length should be equal to the length of string\n");
/* Some versions of Windows touch the buffer, some don't so we don't
* test that. Also, NT sometimes exagerates the required buffer size
* so we cannot test for an exact match. Finally, the
* 'len_with_null - 1' case is so buggy on Windows it's not testable.
* For instance in some cases Win98 returns len_with_null - 1 instead
* of len_with_null.
*/
len = GetTempPathA(1, buf);
ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
len = GetTempPathA(0, NULL);
ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
/* The call above gave us the buffer size that Windows thinks is needed
* so the next call should work
*/
lstrcpyA(buf, "foo");
len = GetTempPathA(len, buf);
ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
ok(len == strlen(buf), "returned length should be equal to the length of string\n");
}
static void test_GetTempPathW(char* tmp_dir)
{
DWORD len, len_with_null;
WCHAR buf[MAX_PATH];
WCHAR tmp_dirW[MAX_PATH];
static const WCHAR fooW[] = {'f','o','o',0};
MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
len_with_null = lstrlenW(tmp_dirW) + 1;
/* This one is different from ANSI version: ANSI version doesn't
* touch the buffer, unicode version usually truncates the buffer
* to zero size. NT still exagerates the required buffer size
* sometimes so we cannot test for an exact match. Finally, the
* 'len_with_null - 1' case is so buggy on Windows it's not testable.
* For instance on NT4 it will sometimes return a path without the
* trailing '\\' and sometimes return an error.
*/
lstrcpyW(buf, fooW);
len = GetTempPathW(MAX_PATH, buf);
if (len==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
return;
ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
lstrcpyW(buf, fooW);
len = GetTempPathW(1, buf);
ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
len = GetTempPathW(0, NULL);
ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
lstrcpyW(buf, fooW);
len = GetTempPathW(len, buf);
ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
}
static void test_GetTempPath(void)
{
char save_TMP[MAX_PATH];
char windir[MAX_PATH];
char buf[MAX_PATH];
GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP));
/* test default configuration */
trace("TMP=%s\n", save_TMP);
strcpy(buf,save_TMP);
if (buf[strlen(buf)-1]!='\\')
strcat(buf,"\\");
test_GetTempPathA(buf);
test_GetTempPathW(buf);
/* TMP=C:\WINDOWS */
GetWindowsDirectoryA(windir, sizeof(windir));
SetEnvironmentVariableA("TMP", windir);
GetEnvironmentVariableA("TMP", buf, sizeof(buf));
trace("TMP=%s\n", buf);
strcat(windir,"\\");
test_GetTempPathA(windir);
test_GetTempPathW(windir);
/* TMP=C:\ */
GetWindowsDirectoryA(windir, sizeof(windir));
windir[3] = 0;
SetEnvironmentVariableA("TMP", windir);
GetEnvironmentVariableA("TMP", buf, sizeof(buf));
trace("TMP=%s\n", buf);
test_GetTempPathA(windir);
test_GetTempPathW(windir);
/* TMP=C: i.e. use current working directory of the specified drive */
GetWindowsDirectoryA(windir, sizeof(windir));
SetCurrentDirectoryA(windir);
windir[2] = 0;
SetEnvironmentVariableA("TMP", windir);
GetEnvironmentVariableA("TMP", buf, sizeof(buf));
trace("TMP=%s\n", buf);
GetWindowsDirectoryA(windir, sizeof(windir));
strcat(windir,"\\");
test_GetTempPathA(windir);
test_GetTempPathW(windir);
SetEnvironmentVariableA("TMP", save_TMP);
}
START_TEST(path)
{
CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
"GetLongPathNameA" );
test_InitPathA(curdir, &curDrive, &otherDrive);
test_CurrentDirectoryA(origdir,curdir);
test_PathNameA(curdir, curDrive, otherDrive);
test_CleanupPathA(origdir,curdir);
test_GetTempPath();
}

View file

@ -0,0 +1,781 @@
/*
* Unit tests for named pipe functions in Wine
*
* Copyright (c) 2002 Dan Kegel
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <windef.h>
#include <winbase.h>
#include <winsock.h>
#include <wtypes.h>
#include <winerror.h>
#include "wine/test.h"
#define PIPENAME "\\\\.\\PiPe\\tests_pipe.c"
#define NB_SERVER_LOOPS 8
static HANDLE alarm_event;
static void test_CreateNamedPipe(int pipemode)
{
HANDLE hnp;
HANDLE hFile;
static const char obuf[] = "Bit Bucket";
static const char obuf2[] = "More bits";
char ibuf[32], *pbuf;
DWORD written;
DWORD readden;
DWORD avail;
DWORD lpmode;
if (pipemode == PIPE_TYPE_BYTE)
trace("test_CreateNamedPipe starting in byte mode\n");
else
trace("test_CreateNamedPipe starting in message mode\n");
/* Bad parameter checks */
hnp = CreateNamedPipe("not a named pipe", PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
if (hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
/* Is this the right way to notify user of skipped tests? */
ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
"CreateNamedPipe not supported on this platform, skipping tests.\n");
return;
}
ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_NAME,
"CreateNamedPipe should fail if name doesn't start with \\\\.\\pipe\n");
hnp = CreateNamedPipe(NULL,
PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
1, 1024, 1024, NMPWAIT_USE_DEFAULT_WAIT, NULL);
ok(hnp == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
"CreateNamedPipe should fail if name is NULL\n");
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile == INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND,
"connecting to nonexistent named pipe should fail with ERROR_FILE_NOT_FOUND\n");
/* Functional checks */
hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, pipemode | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
ok(WaitNamedPipeA(PIPENAME, 2000), "WaitNamedPipe failed (%08lx)\n", GetLastError());
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%08lx)\n", GetLastError());
/* don't try to do i/o if one side couldn't be opened, as it hangs */
if (hFile != INVALID_HANDLE_VALUE) {
HANDLE hFile2;
/* Make sure we can read and write a few bytes in both directions */
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
ok(written == sizeof(obuf), "write file len 1\n");
ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
ok(readden == sizeof(obuf), "peek 1 got %ld bytes\n", readden);
ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf), "read 1 got %ld bytes\n", readden);
ok(memcmp(obuf, ibuf, written) == 0, "content 1 check\n");
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
ok(written == sizeof(obuf2), "write file len 2\n");
ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
ok(readden == sizeof(obuf2), "peek 2 got %ld bytes\n", readden);
ok(PeekNamedPipe(hnp, (LPVOID)1, 0, NULL, &readden, NULL), "Peek\n");
ok(readden == sizeof(obuf2), "peek 2 got %ld bytes\n", readden);
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf2), "read 2 got %ld bytes\n", readden);
ok(memcmp(obuf2, ibuf, written) == 0, "content 2 check\n");
/* Test reading of multiple writes */
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
ok(written == sizeof(obuf), "write file len 3a\n");
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile3b\n");
ok(written == sizeof(obuf2), "write file len 3b\n");
ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
if (pipemode == PIPE_TYPE_BYTE) {
todo_wine {
/* should return all 23 bytes */
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes\n", readden);
}
}
else
ok(readden == sizeof(obuf), "peek3 got %ld bytes\n", readden);
if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %ld bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 3a check\n");
if (pipemode == PIPE_TYPE_BYTE) {
todo_wine {
pbuf += sizeof(obuf);
ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 3b check\n");
}
}
ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf) + sizeof(obuf2), "read 3 got %ld bytes\n", readden);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 3a check\n");
pbuf += sizeof(obuf);
ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 3b check\n");
/* Multiple writes in the reverse direction */
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile4a\n");
ok(written == sizeof(obuf), "write file len 4a\n");
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile4b\n");
ok(written == sizeof(obuf2), "write file len 4b\n");
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
if (pipemode == PIPE_TYPE_BYTE) {
todo_wine {
/* should return all 23 bytes */
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %ld bytes\n", readden);
}
}
else
ok(readden == sizeof(obuf), "peek4 got %ld bytes\n", readden);
if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %ld bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "pipe content 4a check\n");
if (pipemode == PIPE_TYPE_BYTE) {
todo_wine {
pbuf += sizeof(obuf);
ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "pipe content 4b check\n");
}
}
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
if (pipemode == PIPE_TYPE_BYTE) {
ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %ld bytes\n", readden);
}
else {
todo_wine {
ok(readden == sizeof(obuf), "read 4 got %ld bytes\n", readden);
}
}
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
if (pipemode == PIPE_TYPE_BYTE) {
pbuf += sizeof(obuf);
ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 4b check\n");
}
/* Test reading of multiple writes after a mode change
(CreateFile always creates a byte mode pipe) */
lpmode = PIPE_READMODE_MESSAGE;
if (pipemode == PIPE_TYPE_BYTE) {
/* trying to change the client end of a byte pipe to message mode should fail */
ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
}
else {
todo_wine {
ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
}
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
ok(written == sizeof(obuf), "write file len 3a\n");
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
ok(written == sizeof(obuf2), "write file len 3b\n");
ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
ok(readden == sizeof(obuf), "peek5 got %ld bytes\n", readden);
if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %ld bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
todo_wine {
ok(readden == sizeof(obuf), "read 5 got %ld bytes\n", readden);
}
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
/* Multiple writes in the reverse direction */
/* the write of obuf2 from write4 should still be in the buffer */
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
todo_wine {
ok(readden == sizeof(obuf2), "peek6a got %ld bytes\n", readden);
ok(avail == sizeof(obuf2), "peek6a got %ld bytes available\n", avail);
}
if (avail > 0) {
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf2), "read 6a got %ld bytes\n", readden);
pbuf = ibuf;
ok(memcmp(obuf2, pbuf, sizeof(obuf2)) == 0, "content 6a check\n");
}
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile6a\n");
ok(written == sizeof(obuf), "write file len 6a\n");
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
ok(written == sizeof(obuf2), "write file len 6b\n");
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
ok(readden == sizeof(obuf), "peek6 got %ld bytes\n", readden);
if (avail != sizeof(obuf)) /* older Linux kernels only return the first write here */
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %ld bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
todo_wine {
ok(readden == sizeof(obuf), "read 6b got %ld bytes\n", readden);
}
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
}
/* Picky conformance tests */
/* Verify that you can't connect to pipe again
* until server calls DisconnectNamedPipe+ConnectNamedPipe
* or creates a new pipe
* case 1: other client not yet closed
*/
hFile2 = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile2 == INVALID_HANDLE_VALUE,
"connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
ok(GetLastError() == ERROR_PIPE_BUSY,
"connecting to named pipe before other client closes should fail with ERROR_PIPE_BUSY\n");
ok(CloseHandle(hFile), "CloseHandle\n");
/* case 2: other client already closed */
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile == INVALID_HANDLE_VALUE,
"connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
ok(GetLastError() == ERROR_PIPE_BUSY,
"connecting to named pipe after other client closes but before DisconnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
/* case 3: server has called DisconnectNamedPipe but not ConnectNamed Pipe */
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile == INVALID_HANDLE_VALUE,
"connecting to named pipe after other client closes but before DisconnectNamedPipe should fail\n");
ok(GetLastError() == ERROR_PIPE_BUSY,
"connecting to named pipe after other client closes but before ConnectNamedPipe should fail with ERROR_PIPE_BUSY\n");
/* to be complete, we'd call ConnectNamedPipe here and loop,
* but by default that's blocking, so we'd either have
* to turn on the uncommon nonblocking mode, or
* use another thread.
*/
}
ok(CloseHandle(hnp), "CloseHandle\n");
trace("test_CreateNamedPipe returning\n");
}
static void test_CreateNamedPipe_instances_must_match(void)
{
HANDLE hnp, hnp2;
/* Check no mismatch */
hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 2,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 2,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp2 != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
ok(CloseHandle(hnp), "CloseHandle\n");
ok(CloseHandle(hnp2), "CloseHandle\n");
/* Check nMaxInstances */
hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp2 == INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_PIPE_BUSY, "nMaxInstances not obeyed\n");
ok(CloseHandle(hnp), "CloseHandle\n");
/* Check PIPE_ACCESS_* */
hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 2,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
hnp2 = CreateNamedPipe(PIPENAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp2 == INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_ACCESS_DENIED, "PIPE_ACCESS_* mismatch allowed\n");
ok(CloseHandle(hnp), "CloseHandle\n");
/* etc, etc */
}
/** implementation of alarm() */
static DWORD CALLBACK alarmThreadMain(LPVOID arg)
{
DWORD timeout = (DWORD) arg;
trace("alarmThreadMain\n");
if (WaitForSingleObject( alarm_event, timeout ) == WAIT_TIMEOUT)
{
ok(FALSE, "alarm\n");
ExitProcess(1);
}
return 1;
}
HANDLE hnp = INVALID_HANDLE_VALUE;
/** Trivial byte echo server - disconnects after each session */
static DWORD CALLBACK serverThreadMain1(LPVOID arg)
{
int i;
trace("serverThreadMain1 start\n");
/* Set up a simple echo server */
hnp = CreateNamedPipe(PIPENAME "serverThreadMain1", PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
for (i = 0; i < NB_SERVER_LOOPS; i++) {
char buf[512];
DWORD written;
DWORD readden;
DWORD success;
/* Wait for client to connect */
trace("Server calling ConnectNamedPipe...\n");
ok(ConnectNamedPipe(hnp, NULL)
|| GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
trace("ConnectNamedPipe returned.\n");
/* Echo bytes once */
memset(buf, 0, sizeof(buf));
trace("Server reading...\n");
success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
trace("Server done reading.\n");
ok(success, "ReadFile\n");
ok(readden, "short read\n");
trace("Server writing...\n");
ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
trace("Server done writing.\n");
ok(written == readden, "write file len\n");
/* finish this connection, wait for next one */
ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
trace("Server done flushing.\n");
ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
trace("Server done disconnecting.\n");
}
return 0;
}
/** Trivial byte echo server - closes after each connection */
static DWORD CALLBACK serverThreadMain2(LPVOID arg)
{
int i;
HANDLE hnpNext = 0;
trace("serverThreadMain2\n");
/* Set up a simple echo server */
hnp = CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 2,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
for (i = 0; i < NB_SERVER_LOOPS; i++) {
char buf[512];
DWORD written;
DWORD readden;
DWORD success;
/* Wait for client to connect */
trace("Server calling ConnectNamedPipe...\n");
ok(ConnectNamedPipe(hnp, NULL)
|| GetLastError() == ERROR_PIPE_CONNECTED, "ConnectNamedPipe\n");
trace("ConnectNamedPipe returned.\n");
/* Echo bytes once */
memset(buf, 0, sizeof(buf));
trace("Server reading...\n");
success = ReadFile(hnp, buf, sizeof(buf), &readden, NULL);
trace("Server done reading.\n");
ok(success, "ReadFile\n");
trace("Server writing...\n");
ok(WriteFile(hnp, buf, readden, &written, NULL), "WriteFile\n");
trace("Server done writing.\n");
ok(written == readden, "write file len\n");
/* finish this connection, wait for next one */
ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
/* Set up next echo server */
hnpNext =
CreateNamedPipe(PIPENAME "serverThreadMain2", PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 2,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnpNext != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
ok(CloseHandle(hnp), "CloseHandle\n");
hnp = hnpNext;
}
return 0;
}
/** Trivial byte echo server - uses overlapped named pipe calls */
static DWORD CALLBACK serverThreadMain3(LPVOID arg)
{
int i;
HANDLE hEvent;
trace("serverThreadMain3\n");
/* Set up a simple echo server */
hnp = CreateNamedPipe(PIPENAME "serverThreadMain3", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
hEvent = CreateEvent(NULL, /* security attribute */
TRUE, /* manual reset event */
FALSE, /* initial state */
NULL); /* name */
ok(hEvent != NULL, "CreateEvent\n");
for (i = 0; i < NB_SERVER_LOOPS; i++) {
char buf[512];
DWORD written;
DWORD readden;
DWORD dummy;
DWORD success;
OVERLAPPED oOverlap;
int letWFSOEwait = (i & 2);
int letGORwait = (i & 1);
DWORD err;
memset(&oOverlap, 0, sizeof(oOverlap));
oOverlap.hEvent = hEvent;
/* Wait for client to connect */
trace("Server calling overlapped ConnectNamedPipe...\n");
success = ConnectNamedPipe(hnp, &oOverlap);
err = GetLastError();
ok(success || err == ERROR_IO_PENDING
|| err == ERROR_PIPE_CONNECTED, "overlapped ConnectNamedPipe\n");
trace("overlapped ConnectNamedPipe returned.\n");
if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait ConnectNamedPipe\n");
success = GetOverlappedResult(hnp, &oOverlap, &dummy, letGORwait);
if (!letGORwait && !letWFSOEwait && !success) {
ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
success = GetOverlappedResult(hnp, &oOverlap, &dummy, TRUE);
}
ok(success, "GetOverlappedResult ConnectNamedPipe\n");
trace("overlapped ConnectNamedPipe operation complete.\n");
/* Echo bytes once */
memset(buf, 0, sizeof(buf));
trace("Server reading...\n");
success = ReadFile(hnp, buf, sizeof(buf), NULL, &oOverlap);
trace("Server ReadFile returned...\n");
err = GetLastError();
ok(success || err == ERROR_IO_PENDING, "overlapped ReadFile\n");
trace("overlapped ReadFile returned.\n");
if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait ReadFile\n");
success = GetOverlappedResult(hnp, &oOverlap, &readden, letGORwait);
if (!letGORwait && !letWFSOEwait && !success) {
ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
success = GetOverlappedResult(hnp, &oOverlap, &readden, TRUE);
}
trace("Server done reading.\n");
ok(success, "overlapped ReadFile\n");
trace("Server writing...\n");
success = WriteFile(hnp, buf, readden, NULL, &oOverlap);
trace("Server WriteFile returned...\n");
err = GetLastError();
ok(success || err == ERROR_IO_PENDING, "overlapped WriteFile\n");
trace("overlapped WriteFile returned.\n");
if (!success && (err == ERROR_IO_PENDING) && letWFSOEwait)
ok(WaitForSingleObjectEx(hEvent, INFINITE, TRUE) == 0, "wait WriteFile\n");
success = GetOverlappedResult(hnp, &oOverlap, &written, letGORwait);
if (!letGORwait && !letWFSOEwait && !success) {
ok(GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult\n");
success = GetOverlappedResult(hnp, &oOverlap, &written, TRUE);
}
trace("Server done writing.\n");
ok(success, "overlapped WriteFile\n");
ok(written == readden, "write file len\n");
/* finish this connection, wait for next one */
ok(FlushFileBuffers(hnp), "FlushFileBuffers\n");
ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe\n");
}
return 0;
}
static void exercizeServer(const char *pipename, HANDLE serverThread)
{
int i;
trace("exercizeServer starting\n");
for (i = 0; i < NB_SERVER_LOOPS; i++) {
HANDLE hFile=INVALID_HANDLE_VALUE;
static const char obuf[] = "Bit Bucket";
char ibuf[32];
DWORD written;
DWORD readden;
int loop;
for (loop = 0; loop < 3; loop++) {
DWORD err;
trace("Client connecting...\n");
/* Connect to the server */
hFile = CreateFileA(pipename, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
break;
err = GetLastError();
if (loop == 0)
ok(err == ERROR_PIPE_BUSY || err == ERROR_FILE_NOT_FOUND, "connecting to pipe\n");
else
ok(err == ERROR_PIPE_BUSY, "connecting to pipe\n");
trace("connect failed, retrying\n");
Sleep(200);
}
ok(hFile != INVALID_HANDLE_VALUE, "client opening named pipe\n");
/* Make sure it can echo */
memset(ibuf, 0, sizeof(ibuf));
trace("Client writing...\n");
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile to client end of pipe\n");
ok(written == sizeof(obuf), "write file len\n");
trace("Client reading...\n");
ok(ReadFile(hFile, ibuf, sizeof(obuf), &readden, NULL), "ReadFile from client end of pipe\n");
ok(readden == sizeof(obuf), "read file len\n");
ok(memcmp(obuf, ibuf, written) == 0, "content check\n");
trace("Client closing...\n");
ok(CloseHandle(hFile), "CloseHandle\n");
}
ok(WaitForSingleObject(serverThread,INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject\n");
CloseHandle(hnp);
trace("exercizeServer returning\n");
}
static void test_NamedPipe_2(void)
{
HANDLE serverThread;
DWORD serverThreadId;
HANDLE alarmThread;
DWORD alarmThreadId;
trace("test_NamedPipe_2 starting\n");
/* Set up a ten second timeout */
alarm_event = CreateEvent( NULL, TRUE, FALSE, NULL );
alarmThread = CreateThread(NULL, 0, alarmThreadMain, (void *) 10000, 0, &alarmThreadId);
/* The servers we're about to exercize do try to clean up carefully,
* but to reduce the change of a test failure due to a pipe handle
* leak in the test code, we'll use a different pipe name for each server.
*/
/* Try server #1 */
serverThread = CreateThread(NULL, 0, serverThreadMain1, (void *)8, 0, &serverThreadId);
ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");
exercizeServer(PIPENAME "serverThreadMain1", serverThread);
/* Try server #2 */
serverThread = CreateThread(NULL, 0, serverThreadMain2, 0, 0, &serverThreadId);
ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");
exercizeServer(PIPENAME "serverThreadMain2", serverThread);
if( 0 ) /* overlapped pipe server doesn't work yet - it randomly fails */
{
/* Try server #3 */
serverThread = CreateThread(NULL, 0, serverThreadMain3, 0, 0, &serverThreadId);
ok(serverThread != INVALID_HANDLE_VALUE, "CreateThread\n");
exercizeServer(PIPENAME "serverThreadMain3", serverThread);
}
ok(SetEvent( alarm_event ), "SetEvent\n");
CloseHandle( alarm_event );
trace("test_NamedPipe_2 returning\n");
}
static int test_DisconnectNamedPipe(void)
{
HANDLE hnp;
HANDLE hFile;
static const char obuf[] = "Bit Bucket";
char ibuf[32];
DWORD written;
DWORD readden;
hnp = CreateNamedPipe(PIPENAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT,
/* nMaxInstances */ 1,
/* nOutBufSize */ 1024,
/* nInBufSize */ 1024,
/* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
/* lpSecurityAttrib */ NULL);
if (INVALID_HANDLE_VALUE == hnp) {
trace ("Seems we have no named pipes.\n");
return 1;
}
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL) == 0
&& GetLastError() == ERROR_PIPE_LISTENING, "WriteFile to not-yet-connected pipe\n");
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
&& GetLastError() == ERROR_PIPE_LISTENING, "ReadFile from not-yet-connected pipe\n");
hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed\n");
/* don't try to do i/o if one side couldn't be opened, as it hangs */
if (hFile != INVALID_HANDLE_VALUE) {
/* see what happens if server calls DisconnectNamedPipe
* when there are bytes in the pipe
*/
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
ok(written == sizeof(obuf), "write file len\n");
ok(DisconnectNamedPipe(hnp), "DisconnectNamedPipe while messages waiting\n");
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL) == 0
&& GetLastError() == ERROR_PIPE_NOT_CONNECTED, "WriteFile to disconnected pipe\n");
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL) == 0
&& GetLastError() == ERROR_PIPE_NOT_CONNECTED,
"ReadFile from disconnected pipe with bytes waiting\n");
ok(CloseHandle(hFile), "CloseHandle\n");
}
ok(CloseHandle(hnp), "CloseHandle\n");
return 0;
}
static void test_CreatePipe(void)
{
SECURITY_ATTRIBUTES pipe_attr;
HANDLE piperead, pipewrite;
DWORD written;
DWORD read;
char readbuf[32];
pipe_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
pipe_attr.bInheritHandle = TRUE;
pipe_attr.lpSecurityDescriptor = NULL;
ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %ld bytes instead of %d\n", written,sizeof(PIPENAME));
ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from non empty pipe failed\n");
ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %ld bytes instead of %d\n", read, sizeof(PIPENAME));
/* Now write another chunk*/
ok(CreatePipe(&piperead, &pipewrite, &pipe_attr, 0) != 0, "CreatePipe failed\n");
ok(WriteFile(pipewrite,PIPENAME,sizeof(PIPENAME), &written, NULL), "Write to anonymous pipe failed\n");
ok(written == sizeof(PIPENAME), "Write to anonymous pipe wrote %ld bytes instead of %d\n", written,sizeof(PIPENAME));
/* and close the write end, read should still succeed*/
ok(CloseHandle(pipewrite), "CloseHandle for the Write Pipe failed\n");
ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL), "Read from broken pipe withe with pending data failed\n");
ok(read == sizeof(PIPENAME), "Read from anonymous pipe got %ld bytes instead of %d\n", read, sizeof(PIPENAME));
/* But now we need to get informed that the pipe is closed */
ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
}
START_TEST(pipe)
{
trace("test 1 of 6:\n");
if (test_DisconnectNamedPipe())
return;
trace("test 2 of 6:\n");
test_CreateNamedPipe_instances_must_match();
trace("test 3 of 6:\n");
test_NamedPipe_2();
trace("test 4 of 6:\n");
test_CreateNamedPipe(PIPE_TYPE_BYTE);
trace("test 5 of 6\n");
test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
trace("test 6 of 6\n");
test_CreatePipe();
trace("all tests done\n");
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,142 @@
/*
* Unit tests for profile functions
*
* Copyright (c) 2003 Stefan Leichter
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "windows.h"
#define KEY "ProfileInt"
#define SECTION "Test"
#define TESTFILE ".\\testwine.ini"
#define TESTFILE2 ".\\testwine2.ini"
struct _profileInt {
LPCSTR section;
LPCSTR key;
LPCSTR value;
LPCSTR iniFile;
INT defaultVal;
UINT result;
UINT result9x;
};
static void test_profile_int(void)
{
struct _profileInt profileInt[]={
{ NULL, NULL, NULL, NULL, 70, 0 , 0}, /* 0 */
{ NULL, NULL, NULL, TESTFILE, -1, 4294967295U, 0},
{ NULL, NULL, NULL, TESTFILE, 1, 1 , 0},
{ SECTION, NULL, NULL, TESTFILE, -1, 4294967295U, 0},
{ SECTION, NULL, NULL, TESTFILE, 1, 1 , 0},
{ NULL, KEY, NULL, TESTFILE, -1, 4294967295U, 0}, /* 5 */
{ NULL, KEY, NULL, TESTFILE, 1, 1 , 0},
{ SECTION, KEY, NULL, TESTFILE, -1, 4294967295U, 4294967295U},
{ SECTION, KEY, NULL, TESTFILE, 1, 1 , 1},
{ SECTION, KEY, "-1", TESTFILE, -1, 4294967295U, 4294967295U},
{ SECTION, KEY, "-1", TESTFILE, 1, 4294967295U, 4294967295U}, /* 10 */
{ SECTION, KEY, "1", TESTFILE, -1, 1 , 1},
{ SECTION, KEY, "1", TESTFILE, 1, 1 , 1},
{ SECTION, KEY, "+1", TESTFILE, -1, 1 , 0},
{ SECTION, KEY, "+1", TESTFILE, 1, 1 , 0},
{ SECTION, KEY, "4294967296", TESTFILE, -1, 0 , 0}, /* 15 */
{ SECTION, KEY, "4294967296", TESTFILE, 1, 0 , 0},
{ SECTION, KEY, "4294967297", TESTFILE, -1, 1 , 1},
{ SECTION, KEY, "4294967297", TESTFILE, 1, 1 , 1},
{ SECTION, KEY, "-4294967297", TESTFILE, -1, 4294967295U, 4294967295U},
{ SECTION, KEY, "-4294967297", TESTFILE, 1, 4294967295U, 4294967295U}, /* 20 */
{ SECTION, KEY, "42A94967297", TESTFILE, -1, 42 , 42},
{ SECTION, KEY, "42A94967297", TESTFILE, 1, 42 , 42},
{ SECTION, KEY, "B4294967297", TESTFILE, -1, 0 , 0},
{ SECTION, KEY, "B4294967297", TESTFILE, 1, 0 , 0},
};
int i, num_test = (sizeof(profileInt)/sizeof(struct _profileInt));
UINT res;
DeleteFileA( TESTFILE);
for (i=0; i < num_test; i++) {
if (profileInt[i].value)
WritePrivateProfileStringA(SECTION, KEY, profileInt[i].value,
profileInt[i].iniFile);
res = GetPrivateProfileIntA(profileInt[i].section, profileInt[i].key,
profileInt[i].defaultVal, profileInt[i].iniFile);
ok((res == profileInt[i].result) || (res == profileInt[i].result9x),
"test<%02d>: ret<%010u> exp<%010u><%010u>\n",
i, res, profileInt[i].result, profileInt[i].result9x);
}
DeleteFileA( TESTFILE);
}
static void test_profile_string(void)
{
HANDLE h;
int ret;
DWORD count;
char buf[100];
char *p;
/* test that lines without an '=' will not be enumerated */
/* in the case below, name2 is a key while name3 is not. */
char content[]="[s]\r\nname1=val1\r\nname2=\r\nname3\r\nname4=val4\r\n";
DeleteFileA( TESTFILE2);
h = CreateFileA( TESTFILE2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", TESTFILE2);
if( h == INVALID_HANDLE_VALUE) return;
WriteFile( h, content, sizeof(content), &count, NULL);
CloseHandle( h);
/* enumerate the keys */
ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf),
TESTFILE2);
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
p[-1] = ',';
/* and test */
ok( ret == 18 && !strcmp( buf, "name1,name2,name4"), "wrong keys returned(%d): %s\n", ret,
buf);
ret=GetPrivateProfileSectionA("s", buf, sizeof(buf), TESTFILE2);
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
p[-1] = ',';
/* and test */
ok( ret == 35 && !strcmp( buf, "name1=val1,name2=,name3,name4=val4"), "wrong section returned(%d): %s\n",
ret, buf);
/* add a new key to test that the file is quite usable */
WritePrivateProfileStringA( "s", "name5", "val5", TESTFILE2);
ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf),
TESTFILE2);
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
p[-1] = ',';
ok( ret == 24 && !strcmp( buf, "name1,name2,name4,name5"), "wrong keys returned(%d): %s\n",
ret, buf);
DeleteFileA( TESTFILE2);
}
START_TEST(profile)
{
test_profile_int();
test_profile_string();
}

View file

@ -1,25 +1,15 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
extern void func_module(void);
#define STANDALONE
#include "wine/test.h"
struct test
extern void func_psapi_main(void);
const struct test winetest_testlist[] =
{
const char *name;
void (*func)(void);
};
static const struct test winetest_testlist[] =
{
{ "module", func_module },
// { "psapi_main", func_psapi_main },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -1,25 +1,19 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_parser(void);
extern void func_query(void);
extern void func_stringtable(void);
struct test
{
const char *name;
void (*func)(void);
};
static const struct test winetest_testlist[] =
const struct test winetest_testlist[] =
{
// { "parser", func_parser },
// { "query", func_query },
{ "stringtable", func_stringtable },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -1,12 +1,12 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_generated(void);
extern void func_shelllink(void);
extern void func_shellpath(void);
extern void func_shlexec(void);
@ -14,15 +14,9 @@ extern void func_shlfileop(void);
extern void func_shlfolder(void);
extern void func_string(void);
struct test
{
const char *name;
void (*func)(void);
};
const struct test winetest_testlist[] =
{
// { "generated", func_generated },
{ "shelllink", func_shelllink },
{ "shellpath", func_shellpath },
{ "shlexec", func_shlexec },
@ -31,6 +25,3 @@ const struct test winetest_testlist[] =
{ "string", func_string },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -1,32 +1,27 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_clist(void);
extern void func_clsid(void);
extern void func_generated(void);
extern void func_ordinal(void);
extern void func_path(void);
extern void func_shreg(void);
extern void func_string(void);
struct test
{
const char *name;
void (*func)(void);
};
const struct test winetest_testlist[] =
{
{ "clist", func_clist },
// { "clsid", func_clsid },
// { "generated", func_generated },
{ "ordinal", func_ordinal },
// { "path", func_path },
{ "shreg", func_shreg },
{ "string", func_string },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -0,0 +1,132 @@
/*
* Synchronization tests
*
* Copyright 2005 Mike McCormack for CodeWeavers
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <windef.h>
#include <winbase.h>
#include "wine/test.h"
static void test_signalandwait(void)
{
DWORD (WINAPI *pSignalObjectAndWait)(HANDLE, HANDLE, DWORD, BOOL);
HMODULE kernel32;
DWORD r;
int i;
HANDLE event[2], maxevents[MAXIMUM_WAIT_OBJECTS], semaphore[2], file;
kernel32 = GetModuleHandle("kernel32");
pSignalObjectAndWait = (void*) GetProcAddress(kernel32, "SignalObjectAndWait");
if (!pSignalObjectAndWait)
return;
/* invalid parameters */
r = pSignalObjectAndWait(NULL, NULL, 0, 0);
if (r == ERROR_INVALID_FUNCTION)
{
trace("SignalObjectAndWait not implemented, skipping tests\n");
return; /* Win98/ME */
}
ok( r == WAIT_FAILED, "should fail\n");
event[0] = CreateEvent(NULL, 0, 0, NULL);
event[1] = CreateEvent(NULL, 1, 1, NULL);
ok( event[0] && event[1], "failed to create event flags\n");
r = pSignalObjectAndWait(event[0], NULL, 0, FALSE);
ok( r == WAIT_FAILED, "should fail\n");
r = pSignalObjectAndWait(NULL, event[0], 0, FALSE);
ok( r == WAIT_FAILED, "should fail\n");
/* valid parameters */
r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
/* event[0] is now signalled */
r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
/* event[0] is not signalled */
r = WaitForSingleObject(event[0], 0);
ok( r == WAIT_TIMEOUT, "event was signalled\n");
r = pSignalObjectAndWait(event[0], event[0], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
/* clear event[1] and check for a timeout */
ok(ResetEvent(event[1]), "failed to clear event[1]\n");
r = pSignalObjectAndWait(event[0], event[1], 0, FALSE);
ok( r == WAIT_TIMEOUT, "should timeout\n");
CloseHandle(event[0]);
CloseHandle(event[1]);
/* create the maximum number of events and make sure
* we can wait on that many */
for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
{
maxevents[i] = CreateEvent(NULL, 1, 1, NULL);
ok( maxevents[i] != 0, "should create enough events\n");
}
r = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, maxevents, 0, 0);
ok( r != WAIT_FAILED && r != WAIT_TIMEOUT, "should succeed\n");
for (i=0; i<MAXIMUM_WAIT_OBJECTS; i++)
if (maxevents[i]) CloseHandle(maxevents[i]);
/* semaphores */
semaphore[0] = CreateSemaphore( NULL, 0, 1, NULL );
semaphore[1] = CreateSemaphore( NULL, 1, 1, NULL );
ok( semaphore[0] && semaphore[1], "failed to create semaphore\n");
r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
ok( r == WAIT_OBJECT_0, "should succeed\n");
r = pSignalObjectAndWait(semaphore[0], semaphore[1], 0, FALSE);
ok( r == WAIT_FAILED, "should fail\n");
r = ReleaseSemaphore(semaphore[0],1,NULL);
ok( r == FALSE, "should fail\n");
r = ReleaseSemaphore(semaphore[1],1,NULL);
ok( r == TRUE, "should succeed\n");
CloseHandle(semaphore[0]);
CloseHandle(semaphore[1]);
/* try a registry key */
file = CreateFile("x", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
r = pSignalObjectAndWait(file, file, 0, FALSE);
ok( r == WAIT_FAILED, "should fail\n");
ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
CloseHandle(file);
}
START_TEST(sync)
{
test_signalandwait();
}

View file

@ -0,0 +1,67 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_alloc(void);
extern void func_atom(void);
extern void func_change(void);
extern void func_codepage(void);
extern void func_comm(void);
extern void func_console(void);
extern void func_directory(void);
extern void func_drive(void);
extern void func_environ(void);
extern void func_file(void);
extern void func_format_msg(void);
extern void func_generated(void);
extern void func_heap(void);
extern void func_locale(void);
extern void func_module(void);
extern void func_mailslot(void);
extern void func_path(void);
extern void func_pipe(void);
extern void func_process(void);
extern void func_profile(void);
extern void func_sync(void);
extern void func_thread(void);
extern void func_time(void);
extern void func_timer(void);
extern void func_toolhelp(void);
extern void func_virtual(void);
extern void func_volume(void);
const struct test winetest_testlist[] =
{
{ "alloc", func_alloc },
{ "atom", func_atom },
{ "change", func_change },
{ "codepage", func_codepage },
{ "comm", func_comm },
{ "console", func_console },
{ "directory", func_directory },
{ "drive", func_drive },
{ "environ", func_environ },
{ "file", func_file },
{ "format_msg", func_format_msg },
{ "generated", func_generated },
{ "heap", func_heap },
{ "locale", func_locale },
{ "module", func_module },
{ "mailslot", func_mailslot },
{ "path", func_path },
{ "pipe", func_pipe },
{ "process", func_process },
{ "profile", func_profile },
{ "sync", func_sync },
{ "thread", func_thread },
{ "time", func_time },
{ "timer", func_timer },
{ "toolhelp", func_toolhelp },
{ "virtual", func_virtual },
{ "volume", func_volume },
{ 0, 0 }
};

View file

@ -0,0 +1,749 @@
/*
* Unit test suite for directory 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */
#define _WIN32_WINNT 0x0500
#include <stdarg.h>
#include "wine/test.h"
#include <windef.h>
#include <winbase.h>
#include <winnt.h>
#include <winerror.h>
/* Specify the number of simultaneous threads to test */
#define NUM_THREADS 4
/* Specify whether to test the extended priorities for Win2k/XP */
#define USE_EXTENDED_PRIORITIES 0
/* Specify whether to test the stack allocation in CreateThread */
#define CHECK_STACK 0
/* Set CHECK_STACK to 1 if you want to try to test the stack-limit from
CreateThread. So far I have been unable to make this work, and
I am in doubt as to how portable it is. Also, according to MSDN,
you shouldn't mix C-run-time-libraries (i.e. alloca) with CreateThread.
Anyhow, the check is currently commented out
*/
#if CHECK_STACK
# ifdef __try
# define __TRY __try
# define __EXCEPT __except
# define __ENDTRY
# else
# include "wine/exception.h"
# endif
#endif
typedef BOOL (WINAPI *GetThreadPriorityBoost_t)(HANDLE,PBOOL);
static GetThreadPriorityBoost_t pGetThreadPriorityBoost=NULL;
typedef HANDLE (WINAPI *OpenThread_t)(DWORD,BOOL,DWORD);
static OpenThread_t pOpenThread=NULL;
typedef BOOL (WINAPI *QueueUserWorkItem_t)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
static QueueUserWorkItem_t pQueueUserWorkItem=NULL;
typedef DWORD (WINAPI *SetThreadIdealProcessor_t)(HANDLE,DWORD);
static SetThreadIdealProcessor_t pSetThreadIdealProcessor=NULL;
typedef BOOL (WINAPI *SetThreadPriorityBoost_t)(HANDLE,BOOL);
static SetThreadPriorityBoost_t pSetThreadPriorityBoost=NULL;
/* Functions not tested yet:
AttachThreadInput
CreateRemoteThread
SetThreadContext
SwitchToThread
In addition there are no checks that the inheritance works properly in
CreateThread
*/
DWORD tlsIndex;
typedef struct {
int threadnum;
HANDLE *event;
DWORD *threadmem;
} t1Struct;
/* WinME supports OpenThread but doesn't know about access restrictions so
we require them to be either completely ignored or always obeyed.
*/
INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
#define obey_ar(x) \
(obeying_ars == 0 \
? ((x) \
? (obeying_ars = +1) \
: ((obeying_ars = -1), \
trace("not restricted, assuming consistent behaviour\n"))) \
: (obeying_ars < 0) \
? ok(!(x), "access restrictions obeyed\n") \
: ok( (x), "access restrictions not obeyed\n"))
/* Basic test that simultaneous threads can access shared memory,
that the thread local storage routines work correctly, and that
threads actually run concurrently
*/
static DWORD WINAPI threadFunc1(LPVOID p)
{
t1Struct *tstruct = (t1Struct *)p;
int i;
/* write our thread # into shared memory */
tstruct->threadmem[tstruct->threadnum]=GetCurrentThreadId();
ok(TlsSetValue(tlsIndex,(LPVOID)(tstruct->threadnum+1))!=0,
"TlsSetValue failed\n");
/* The threads synchronize before terminating. This is done by
Signaling an event, and waiting for all events to occur
*/
SetEvent(tstruct->event[tstruct->threadnum]);
WaitForMultipleObjects(NUM_THREADS,tstruct->event,TRUE,INFINITE);
/* Double check that all threads really did run by validating that
they have all written to the shared memory. There should be no race
here, since all threads were synchronized after the write.*/
for(i=0;i<NUM_THREADS;i++) {
while(tstruct->threadmem[i]==0) ;
}
/* lstrlenA contains an exception handler so this makes sure exceptions work in threads */
ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
/* Check that noone changed our tls memory */
ok((int)TlsGetValue(tlsIndex)-1==tstruct->threadnum,
"TlsGetValue failed\n");
return NUM_THREADS+tstruct->threadnum;
}
static DWORD WINAPI threadFunc2(LPVOID p)
{
return 99;
}
static DWORD WINAPI threadFunc3(LPVOID p)
{
HANDLE thread;
thread=GetCurrentThread();
SuspendThread(thread);
return 99;
}
static DWORD WINAPI threadFunc4(LPVOID p)
{
HANDLE event = (HANDLE)p;
if(event != NULL) {
SetEvent(event);
}
Sleep(99000);
return 0;
}
#if CHECK_STACK
static DWORD WINAPI threadFunc5(LPVOID p)
{
DWORD *exitCode = (DWORD *)p;
SYSTEM_INFO sysInfo;
sysInfo.dwPageSize=0;
GetSystemInfo(&sysInfo);
*exitCode=0;
__TRY
{
alloca(2*sysInfo.dwPageSize);
}
__EXCEPT(1) {
*exitCode=1;
}
__ENDTRY
return 0;
}
#endif
/* Check basic funcationality of CreateThread and Tls* functions */
static VOID test_CreateThread_basic(void)
{
HANDLE thread[NUM_THREADS],event[NUM_THREADS];
DWORD threadid[NUM_THREADS],curthreadId;
DWORD threadmem[NUM_THREADS];
DWORD exitCode;
t1Struct tstruct[NUM_THREADS];
int error;
DWORD i,j;
DWORD GLE, ret;
/* lstrlenA contains an exception handler so this makes sure exceptions work in the main thread */
ok( lstrlenA( (char *)0xdeadbeef ) == 0, "lstrlenA: unexpected success\n" );
/* Retrieve current Thread ID for later comparisons */
curthreadId=GetCurrentThreadId();
/* Allocate some local storage */
ok((tlsIndex=TlsAlloc())!=TLS_OUT_OF_INDEXES,"TlsAlloc failed\n");
/* Create events for thread synchronization */
for(i=0;i<NUM_THREADS;i++) {
threadmem[i]=0;
/* Note that it doesn't matter what type of event we chose here. This
test isn't trying to thoroughly test events
*/
event[i]=CreateEventA(NULL,TRUE,FALSE,NULL);
tstruct[i].threadnum=i;
tstruct[i].threadmem=threadmem;
tstruct[i].event=event;
}
/* Test that passing arguments to threads works okay */
for(i=0;i<NUM_THREADS;i++) {
thread[i] = CreateThread(NULL,0,threadFunc1,
&tstruct[i],0,&threadid[i]);
ok(thread[i]!=NULL,"Create Thread failed\n");
}
/* Test that the threads actually complete */
for(i=0;i<NUM_THREADS;i++) {
error=WaitForSingleObject(thread[i],5000);
ok(error==WAIT_OBJECT_0, "Thread did not complete within timelimit\n");
if(error!=WAIT_OBJECT_0) {
TerminateThread(thread[i],i+NUM_THREADS);
}
ok(GetExitCodeThread(thread[i],&exitCode),"Could not retrieve ext code\n");
ok(exitCode==i+NUM_THREADS,"Thread returned an incorrect exit code\n");
}
/* Test that each thread executed in its parent's address space
(it was able to change threadmem and pass that change back to its parent)
and that each thread id was independant). Note that we prove that the
threads actually execute concurrently by having them block on each other
in threadFunc1
*/
for(i=0;i<NUM_THREADS;i++) {
error=0;
for(j=i+1;j<NUM_THREADS;j++) {
if (threadmem[i]==threadmem[j]) {
error=1;
}
}
ok(!error && threadmem[i]==threadid[i] && threadmem[i]!=curthreadId,
"Thread did not execute successfully\n");
ok(CloseHandle(thread[i])!=0,"CloseHandle failed\n");
}
ok(TlsFree(tlsIndex)!=0,"TlsFree failed\n");
/* Test how passing NULL as a pointer to threadid works */
SetLastError(0xFACEaBAD);
thread[0] = CreateThread(NULL,0,threadFunc2,NULL,0,NULL);
GLE = GetLastError();
if (thread[0]) { /* NT */
ok(GLE==0xFACEaBAD, "CreateThread set last error to %ld, expected 4207848365\n", GLE);
ret = WaitForSingleObject(thread[0],100);
ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
ret = GetExitCodeThread(thread[0],&exitCode);
ok(ret!=0, "GetExitCodeThread returned %ld (expected nonzero)\n", ret);
ok(exitCode==99, "threadFunc2 exited with code: %ld (expected 99)\n", exitCode);
ok(CloseHandle(thread[0])!=0,"Error closing thread handle\n");
}
else { /* 9x */
ok(GLE==ERROR_INVALID_PARAMETER, "CreateThread set last error to %ld, expected 87\n", GLE);
}
}
/* Check that using the CREATE_SUSPENDED flag works */
static VOID test_CreateThread_suspended(void)
{
HANDLE thread;
DWORD threadId;
int error;
thread = CreateThread(NULL,0,threadFunc2,NULL,
CREATE_SUSPENDED,&threadId);
ok(thread!=NULL,"Create Thread failed\n");
/* Check that the thread is suspended */
ok(SuspendThread(thread)==1,"Thread did not start suspended\n");
ok(ResumeThread(thread)==2,"Resume thread returned an invalid value\n");
/* Check that resume thread didn't actually start the thread. I can't think
of a better way of checking this than just waiting. I am not sure if this
will work on slow computers.
*/
ok(WaitForSingleObject(thread,1000)==WAIT_TIMEOUT,
"ResumeThread should not have actually started the thread\n");
/* Now actually resume the thread and make sure that it actually completes*/
ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
"Thread did not resume\n");
if(error!=WAIT_OBJECT_0) {
TerminateThread(thread,1);
}
ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
}
/* Check that SuspendThread and ResumeThread work */
static VOID test_SuspendThread(void)
{
HANDLE thread,access_thread;
DWORD threadId,exitCode,error;
int i;
thread = CreateThread(NULL,0,threadFunc3,NULL,
0,&threadId);
ok(thread!=NULL,"Create Thread failed\n");
/* Check that the thread is suspended */
/* Note that this is a polling method, and there is a race between
SuspendThread being called (in the child, and the loop below timing out,
so the test could fail on a heavily loaded or slow computer.
*/
error=0;
for(i=0;error==0 && i<100;i++) {
error=SuspendThread(thread);
ResumeThread(thread);
if(error==0) {
Sleep(50);
i++;
}
}
ok(error==1,"SuspendThread did not work\n");
/* check that access restrictions are obeyed */
if (pOpenThread) {
access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_SUSPEND_RESUME),
0,threadId);
ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
if (access_thread!=NULL) {
obey_ar(SuspendThread(access_thread)==~0U);
obey_ar(ResumeThread(access_thread)==~0U);
ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
}
}
/* Double check that the thread really is suspended */
ok((error=GetExitCodeThread(thread,&exitCode))!=0 && exitCode==STILL_ACTIVE,
"Thread did not really suspend\n");
/* Resume the thread, and make sure it actually completes */
ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
ok((error=WaitForSingleObject(thread,1000))==WAIT_OBJECT_0,
"Thread did not resume\n");
if(error!=WAIT_OBJECT_0) {
TerminateThread(thread,1);
}
/* Trying to suspend a terminated thread should fail */
error=SuspendThread(thread);
ok(error==~0U, "wrong return code: %ld\n", error);
ok(GetLastError()==ERROR_ACCESS_DENIED || GetLastError()==ERROR_NO_MORE_ITEMS, "unexpected error code: %ld\n", GetLastError());
ok(CloseHandle(thread)!=0,"CloseHandle Failed\n");
}
/* Check that TerminateThread works properly
*/
static VOID test_TerminateThread(void)
{
HANDLE thread,access_thread,event;
DWORD threadId,exitCode;
event=CreateEventA(NULL,TRUE,FALSE,NULL);
thread = CreateThread(NULL,0,threadFunc4,
(LPVOID)event, 0,&threadId);
ok(thread!=NULL,"Create Thread failed\n");
/* TerminateThread has a race condition in Wine. If the thread is terminated
before it starts, it leaves a process behind. Therefore, we wait for the
thread to signal that it has started. There is no easy way to force the
race to occur, so we don't try to find it.
*/
ok(WaitForSingleObject(event,5000)==WAIT_OBJECT_0,
"TerminateThread didn't work\n");
/* check that access restrictions are obeyed */
if (pOpenThread) {
access_thread=pOpenThread(THREAD_ALL_ACCESS & (~THREAD_TERMINATE),
0,threadId);
ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
if (access_thread!=NULL) {
obey_ar(TerminateThread(access_thread,99)==0);
ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
}
}
/* terminate a job and make sure it terminates */
ok(TerminateThread(thread,99)!=0,"TerminateThread failed\n");
ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
"TerminateThread didn't work\n");
ok(GetExitCodeThread(thread,&exitCode)!=STILL_ACTIVE,
"TerminateThread should not leave the thread 'STILL_ACTIVE'\n");
ok(exitCode==99, "TerminateThread returned invalid exit code\n");
ok(CloseHandle(thread)!=0,"Error Closing thread handle\n");
}
/* Check if CreateThread obeys the specified stack size. This code does
not work properly, and is currently disabled
*/
static VOID test_CreateThread_stack(void)
{
#if CHECK_STACK
/* The only way I know of to test the stack size is to use alloca
and __try/__except. However, this is probably not portable,
and I couldn't get it to work under Wine anyhow. However, here
is the code which should allow for testing that CreateThread
respects the stack-size limit
*/
HANDLE thread;
DWORD threadId,exitCode;
SYSTEM_INFO sysInfo;
sysInfo.dwPageSize=0;
GetSystemInfo(&sysInfo);
ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
thread = CreateThread(NULL,sysInfo.dwPageSize,
threadFunc5,&exitCode,
0,&threadId);
ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
"TerminateThread didn't work\n");
ok(exitCode==1,"CreateThread did not obey stack-size-limit\n");
ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
#endif
}
/* Check whether setting/retrieving thread priorities works */
static VOID test_thread_priority(void)
{
HANDLE curthread,access_thread;
DWORD curthreadId,exitCode;
int min_priority=-2,max_priority=2;
BOOL disabled,rc;
int i;
curthread=GetCurrentThread();
curthreadId=GetCurrentThreadId();
/* Check thread priority */
/* NOTE: on Win2k/XP priority can be from -7 to 6. All other platforms it
is -2 to 2. However, even on a real Win2k system, using thread
priorities beyond the -2 to 2 range does not work. If you want to try
anyway, enable USE_EXTENDED_PRIORITIES
*/
ok(GetThreadPriority(curthread)==THREAD_PRIORITY_NORMAL,
"GetThreadPriority Failed\n");
if (pOpenThread) {
/* check that access control is obeyed */
access_thread=pOpenThread(THREAD_ALL_ACCESS &
(~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
0,curthreadId);
ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
if (access_thread!=NULL) {
obey_ar(SetThreadPriority(access_thread,1)==0);
obey_ar(GetThreadPriority(access_thread)==THREAD_PRIORITY_ERROR_RETURN);
obey_ar(GetExitCodeThread(access_thread,&exitCode)==0);
ok(CloseHandle(access_thread),"Error Closing thread handle\n");
}
#if USE_EXTENDED_PRIORITIES
min_priority=-7; max_priority=6;
#endif
}
for(i=min_priority;i<=max_priority;i++) {
ok(SetThreadPriority(curthread,i)!=0,
"SetThreadPriority Failed for priority: %d\n",i);
ok(GetThreadPriority(curthread)==i,
"GetThreadPriority Failed for priority: %d\n",i);
}
ok(SetThreadPriority(curthread,THREAD_PRIORITY_TIME_CRITICAL)!=0,
"SetThreadPriority Failed\n");
ok(GetThreadPriority(curthread)==THREAD_PRIORITY_TIME_CRITICAL,
"GetThreadPriority Failed\n");
ok(SetThreadPriority(curthread,THREAD_PRIORITY_IDLE)!=0,
"SetThreadPriority Failed\n");
ok(GetThreadPriority(curthread)==THREAD_PRIORITY_IDLE,
"GetThreadPriority Failed\n");
ok(SetThreadPriority(curthread,0)!=0,"SetThreadPriority Failed\n");
/* Check thread priority boost */
if (!pGetThreadPriorityBoost || !pSetThreadPriorityBoost)
return; /* Win9x */
SetLastError(0xdeadbeef);
rc=pGetThreadPriorityBoost(curthread,&disabled);
if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
return; /* WinME */
/* check that access control is obeyed */
access_thread=pOpenThread(THREAD_ALL_ACCESS &
(~THREAD_QUERY_INFORMATION) & (~THREAD_SET_INFORMATION),
0,curthreadId);
ok(access_thread!=NULL,"OpenThread returned an invalid handle\n");
if (access_thread!=NULL) {
obey_ar(pSetThreadPriorityBoost(access_thread,1)==0);
obey_ar(pGetThreadPriorityBoost(access_thread,&disabled)==0);
ok(CloseHandle(access_thread),"Error Closing thread handle\n");
}
todo_wine {
ok(rc!=0,"error=%ld\n",GetLastError());
rc = pSetThreadPriorityBoost(curthread,1);
ok( rc != 0, "error=%ld\n",GetLastError());
rc=pGetThreadPriorityBoost(curthread,&disabled);
ok(rc!=0 && disabled==1,
"rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
rc = pSetThreadPriorityBoost(curthread,0);
ok( rc != 0, "error=%ld\n",GetLastError());
rc=pGetThreadPriorityBoost(curthread,&disabled);
ok(rc!=0 && disabled==0,
"rc=%d error=%ld disabled=%d\n",rc,GetLastError(),disabled);
}
}
/* check the GetThreadTimes function */
static VOID test_GetThreadTimes(void)
{
HANDLE thread,access_thread=NULL;
FILETIME creationTime,exitTime,kernelTime,userTime;
DWORD threadId;
int error;
thread = CreateThread(NULL,0,threadFunc2,NULL,
CREATE_SUSPENDED,&threadId);
ok(thread!=NULL,"Create Thread failed\n");
/* check that access control is obeyed */
if (pOpenThread) {
access_thread=pOpenThread(THREAD_ALL_ACCESS &
(~THREAD_QUERY_INFORMATION), 0,threadId);
ok(access_thread!=NULL,
"OpenThread returned an invalid handle\n");
}
ok(ResumeThread(thread)==1,"Resume thread returned an invalid value\n");
ok(WaitForSingleObject(thread,5000)==WAIT_OBJECT_0,
"ResumeThread didn't work\n");
creationTime.dwLowDateTime=99; creationTime.dwHighDateTime=99;
exitTime.dwLowDateTime=99; exitTime.dwHighDateTime=99;
kernelTime.dwLowDateTime=99; kernelTime.dwHighDateTime=99;
userTime.dwLowDateTime=99; userTime.dwHighDateTime=99;
/* GetThreadTimes should set all of the parameters passed to it */
error=GetThreadTimes(thread,&creationTime,&exitTime,
&kernelTime,&userTime);
if (error!=0 || GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
ok(error!=0,"GetThreadTimes failed\n");
ok(creationTime.dwLowDateTime!=99 || creationTime.dwHighDateTime!=99,
"creationTime was invalid\n");
ok(exitTime.dwLowDateTime!=99 || exitTime.dwHighDateTime!=99,
"exitTime was invalid\n");
ok(kernelTime.dwLowDateTime!=99 || kernelTime.dwHighDateTime!=99,
"kernelTimewas invalid\n");
ok(userTime.dwLowDateTime!=99 || userTime.dwHighDateTime!=99,
"userTime was invalid\n");
ok(CloseHandle(thread)!=0,"CloseHandle failed\n");
if(access_thread!=NULL)
{
error=GetThreadTimes(access_thread,&creationTime,&exitTime,
&kernelTime,&userTime);
obey_ar(error==0);
}
}
if(access_thread!=NULL) {
ok(CloseHandle(access_thread)!=0,"CloseHandle Failed\n");
}
}
/* Check the processor affinity functions */
/* NOTE: These functions should also be checked that they obey access control
*/
static VOID test_thread_processor(void)
{
HANDLE curthread,curproc;
DWORD processMask,systemMask;
SYSTEM_INFO sysInfo;
int error=0;
sysInfo.dwNumberOfProcessors=0;
GetSystemInfo(&sysInfo);
ok(sysInfo.dwNumberOfProcessors>0,
"GetSystemInfo failed to return a valid # of processors\n");
/* Use the current Thread/process for all tests */
curthread=GetCurrentThread();
ok(curthread!=NULL,"GetCurrentThread failed\n");
curproc=GetCurrentProcess();
ok(curproc!=NULL,"GetCurrentProcess failed\n");
/* Check the Affinity Mask functions */
ok(GetProcessAffinityMask(curproc,&processMask,&systemMask)!=0,
"GetProcessAffinityMask failed\n");
ok(SetThreadAffinityMask(curthread,processMask)==processMask,
"SetThreadAffinityMask failed\n");
ok(SetThreadAffinityMask(curthread,processMask+1)==0,
"SetThreadAffinityMask passed for an illegal processor\n");
/* NOTE: This only works on WinNT/2000/XP) */
if (pSetThreadIdealProcessor) {
todo_wine {
SetLastError(0);
error=pSetThreadIdealProcessor(curthread,0);
if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
ok(error!=-1, "SetThreadIdealProcessor failed\n");
}
}
if (GetLastError()!=ERROR_CALL_NOT_IMPLEMENTED) {
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS+1);
ok(error==-1,
"SetThreadIdealProcessor succeeded with an illegal processor #\n");
todo_wine {
error=pSetThreadIdealProcessor(curthread,MAXIMUM_PROCESSORS);
ok(error==0, "SetThreadIdealProcessor returned an incorrect value\n");
}
}
}
}
static VOID test_GetThreadExitCode(void)
{
DWORD exitCode, threadid;
DWORD GLE, ret;
HANDLE thread;
ret = GetExitCodeThread((HANDLE)0x2bad2bad,&exitCode);
ok(ret==0, "GetExitCodeThread returned non zero value: %ld\n", ret);
GLE = GetLastError();
ok(GLE==ERROR_INVALID_HANDLE, "GetLastError returned %ld (expected 6)\n", GLE);
thread = CreateThread(NULL,0,threadFunc2,NULL,0,&threadid);
ret = WaitForSingleObject(thread,100);
ok(ret==WAIT_OBJECT_0, "threadFunc2 did not exit during 100 ms\n");
ret = GetExitCodeThread(thread,&exitCode);
ok(ret==exitCode || ret==1,
"GetExitCodeThread returned %ld (expected 1 or %ld)\n", ret, exitCode);
ok(exitCode==99, "threadFunc2 exited with code %ld (expected 99)\n", exitCode);
ok(CloseHandle(thread)!=0,"Error closing thread handle\n");
}
#ifdef __i386__
static int test_value = 0;
static HANDLE event;
static void WINAPI set_test_val( int val )
{
test_value += val;
}
static DWORD WINAPI threadFunc6(LPVOID p)
{
SetEvent( event );
Sleep( 1000 );
test_value *= (int)p;
return 0;
}
static void test_SetThreadContext(void)
{
CONTEXT ctx;
int *stack;
HANDLE thread;
DWORD threadid;
DWORD prevcount;
SetLastError(0xdeadbeef);
event = CreateEvent( NULL, TRUE, FALSE, NULL );
thread = CreateThread( NULL, 0, threadFunc6, (void *)2, 0, &threadid );
ok( thread != NULL, "CreateThread failed : (%ld)\n", GetLastError() );
if (!thread)
{
trace("Thread creation failed, skipping rest of test\n");
return;
}
WaitForSingleObject( event, INFINITE );
SuspendThread( thread );
CloseHandle( event );
ctx.ContextFlags = CONTEXT_FULL;
SetLastError(0xdeadbeef);
ok( GetThreadContext( thread, &ctx ), "GetThreadContext failed : (%ld)\n", GetLastError() );
/* simulate a call to set_test_val(10) */
stack = (int *)ctx.Esp;
stack[-1] = 10;
stack[-2] = ctx.Eip;
ctx.Esp -= 2 * sizeof(int *);
ctx.Eip = (DWORD)set_test_val;
SetLastError(0xdeadbeef);
ok( SetThreadContext( thread, &ctx ), "SetThreadContext failed : (%ld)\n", GetLastError() );
SetLastError(0xdeadbeef);
prevcount = ResumeThread( thread );
ok ( prevcount == 1, "Previous suspend count (%ld) instead of 1, last error : (%ld)\n",
prevcount, GetLastError() );
WaitForSingleObject( thread, INFINITE );
ok( test_value == 20, "test_value %d instead of 20\n", test_value );
}
#endif /* __i386__ */
static HANDLE finish_event;
static LONG times_executed;
static DWORD CALLBACK work_function(void *p)
{
LONG executed = InterlockedIncrement(&times_executed);
if (executed == 100)
SetEvent(finish_event);
return 0;
}
static void test_QueueUserWorkItem(void)
{
int i;
DWORD wait_result;
DWORD before, after;
/* QueueUserWorkItem not present on win9x */
if (!pQueueUserWorkItem) return;
finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
before = GetTickCount();
for (i = 0; i < 100; i++)
{
BOOL ret = pQueueUserWorkItem(work_function, (void *)i, WT_EXECUTEDEFAULT);
ok(ret, "QueueUserWorkItem failed with error %ld\n", GetLastError());
}
wait_result = WaitForSingleObject(finish_event, 10000);
after = GetTickCount();
trace("100 QueueUserWorkItem calls took %ldms\n", after - before);
ok(wait_result == WAIT_OBJECT_0, "wait failed with error 0x%lx\n", wait_result);
ok(times_executed == 100, "didn't execute all of the work items\n");
}
START_TEST(thread)
{
HINSTANCE lib;
/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
so that the compile passes
*/
lib=GetModuleHandleA("kernel32.dll");
ok(lib!=NULL,"Couldn't get a handle for kernel32.dll\n");
pGetThreadPriorityBoost=(GetThreadPriorityBoost_t)GetProcAddress(lib,"GetThreadPriorityBoost");
pOpenThread=(OpenThread_t)GetProcAddress(lib,"OpenThread");
pQueueUserWorkItem=(QueueUserWorkItem_t)GetProcAddress(lib,"QueueUserWorkItem");
pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
pSetThreadPriorityBoost=(SetThreadPriorityBoost_t)GetProcAddress(lib,"SetThreadPriorityBoost");
test_CreateThread_basic();
test_CreateThread_suspended();
test_SuspendThread();
test_TerminateThread();
test_CreateThread_stack();
test_thread_priority();
test_GetThreadTimes();
test_thread_processor();
test_GetThreadExitCode();
#ifdef __i386__
test_SetThreadContext();
#endif
test_QueueUserWorkItem();
}

View file

@ -0,0 +1,454 @@
/*
* Unit test suite for time functions
*
* Copyright 2004 Uwe Bonnes
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/test.h"
#include "winbase.h"
#define SECSPERMIN 60
#define SECSPERDAY 86400
/* 1601 to 1970 is 369 years plus 89 leap days */
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC)
#define NEWYEAR_1980_HI 0x01a8e79f
#define NEWYEAR_1980_LO 0xe1d58000
#define MAYDAY_2002_HI 0x01c1f107
#define MAYDAY_2002_LO 0xb82b6000
#define ATIME_HI 0x1c2349b
#define ATIME_LOW 0x580716b0
#define LOCAL_ATIME_HI 0x01c23471
#define LOCAL_ATIME_LOW 0x6f310eb0
#define DOS_DATE(y,m,d) ( (((y)-1980)<<9) | ((m)<<5) | (d) )
#define DOS_TIME(h,m,s) ( ((h)<<11) | ((m)<<5) | ((s)>>1) )
#define SETUP_1980(st) \
(st).wYear = 1980; \
(st).wMonth = 1; \
(st).wDay = 1; \
(st).wHour = 0; \
(st).wMinute = 0; \
(st).wSecond = 0; \
(st).wMilliseconds = 0;
#define SETUP_2002(st) \
(st).wYear = 2002; \
(st).wMonth = 5; \
(st).wDay = 1; \
(st).wHour = 12; \
(st).wMinute = 0; \
(st).wSecond = 0; \
(st).wMilliseconds = 0;
#define SETUP_ATIME(st) \
(st).wYear = 2002; \
(st).wMonth = 7; \
(st).wDay = 26; \
(st).wHour = 11; \
(st).wMinute = 55; \
(st).wSecond = 32; \
(st).wMilliseconds = 123;
static void test_conversions(void)
{
FILETIME ft;
SYSTEMTIME st;
memset(&ft,0,sizeof ft);
SETUP_ATIME(st)
ok (SystemTimeToFileTime(&st,&ft), "Conversion Failed ATIME\n");
ok( (!((ft.dwHighDateTime != ATIME_HI) || (ft.dwLowDateTime!=ATIME_LOW))),
"Wrong time for ATIME: %08lx %08lx (correct %08x %08x)\n",
ft.dwLowDateTime, ft.dwHighDateTime, ATIME_LOW, ATIME_HI);
SETUP_2002(st)
ok (SystemTimeToFileTime(&st, &ft), "Conversion failed 2002\n");
ok( (!((ft.dwHighDateTime != MAYDAY_2002_HI) ||
(ft.dwLowDateTime!=MAYDAY_2002_LO))),
"Wrong time for 2002 %08lx %08lx (correct %08x %08x)\n", ft.dwLowDateTime,
ft.dwHighDateTime, MAYDAY_2002_LO, MAYDAY_2002_HI);
SETUP_1980(st)
ok((SystemTimeToFileTime(&st, &ft)), "Conversion failed 1980\n");
ok( (!((ft.dwHighDateTime!=NEWYEAR_1980_HI) ||
(ft.dwLowDateTime!=NEWYEAR_1980_LO))) ,
"Wrong time for 1980 %08lx %08lx (correct %08x %08x)\n", ft.dwLowDateTime,
ft.dwHighDateTime, NEWYEAR_1980_LO,NEWYEAR_1980_HI );
ok(DosDateTimeToFileTime(DOS_DATE(1980,1,1),DOS_TIME(0,0,0),&ft),
"DosDateTimeToFileTime() failed\n");
ok( (!((ft.dwHighDateTime!=NEWYEAR_1980_HI) ||
(ft.dwLowDateTime!=NEWYEAR_1980_LO))),
"Wrong time DosDateTimeToFileTime %08lx %08lx (correct %08x %08x)\n",
ft.dwHighDateTime, ft.dwLowDateTime, NEWYEAR_1980_HI, NEWYEAR_1980_LO);
}
static void test_invalid_arg(void)
{
FILETIME ft;
SYSTEMTIME st;
/* Invalid argument checks */
memset(&ft,0,sizeof ft);
ok( DosDateTimeToFileTime(DOS_DATE(1980,1,1),DOS_TIME(0,0,0),&ft), /* this is 1 Jan 1980 00:00:00 */
"DosDateTimeToFileTime() failed\n");
ok( (ft.dwHighDateTime==NEWYEAR_1980_HI) && (ft.dwLowDateTime==NEWYEAR_1980_LO),
"filetime for 1/1/80 00:00:00 was %08lx %08lx\n", ft.dwHighDateTime, ft.dwLowDateTime);
/* now check SystemTimeToFileTime */
memset(&ft,0,sizeof ft);
/* try with a bad month */
SETUP_1980(st)
st.wMonth = 0;
ok( !SystemTimeToFileTime(&st, &ft), "bad month\n");
/* with a bad hour */
SETUP_1980(st)
st.wHour = 24;
ok( !SystemTimeToFileTime(&st, &ft), "bad hour\n");
/* with a bad minute */
SETUP_1980(st)
st.wMinute = 60;
ok( !SystemTimeToFileTime(&st, &ft), "bad minute\n");
}
static void test_GetTimeZoneInformation(void)
{
TIME_ZONE_INFORMATION tzinfo, tzinfo1;
DWORD res = GetTimeZoneInformation(&tzinfo);
ok(res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
ok(SetEnvironmentVariableA("TZ","GMT0") != 0,
"SetEnvironmentVariableA failed\n");
res = GetTimeZoneInformation(&tzinfo1);
ok(res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
ok(((tzinfo.Bias == tzinfo1.Bias) &&
(tzinfo.StandardBias == tzinfo1.StandardBias) &&
(tzinfo.DaylightBias == tzinfo1.DaylightBias)),
"Bias influenced by TZ variable\n");
ok(SetEnvironmentVariableA("TZ",NULL) != 0,
"SetEnvironmentVariableA failed\n");
}
static void test_FileTimeToSystemTime(void)
{
FILETIME ft;
SYSTEMTIME st;
ULONGLONG time = (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
BOOL ret;
ft.dwHighDateTime = 0;
ft.dwLowDateTime = 0;
ret = FileTimeToSystemTime(&ft, &st);
ok( ret,
"FileTimeToSystemTime() failed with Error 0x%08lx\n",GetLastError());
ok(((st.wYear == 1601) && (st.wMonth == 1) && (st.wDay == 1) &&
(st.wHour == 0) && (st.wMinute == 0) && (st.wSecond == 0) &&
(st.wMilliseconds == 0)),
"Got Year %4d Month %2d Day %2d\n", st.wYear, st.wMonth, st.wDay);
ft.dwHighDateTime = (UINT)(time >> 32);
ft.dwLowDateTime = (UINT)time;
ret = FileTimeToSystemTime(&ft, &st);
ok( ret,
"FileTimeToSystemTime() failed with Error 0x%08lx\n",GetLastError());
ok(((st.wYear == 1970) && (st.wMonth == 1) && (st.wDay == 1) &&
(st.wHour == 0) && (st.wMinute == 0) && (st.wSecond == 1) &&
(st.wMilliseconds == 0)),
"Got Year %4d Month %2d Day %2d Hour %2d Min %2d Sec %2d mSec %3d\n",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
st.wMilliseconds);
}
static void test_FileTimeToLocalFileTime(void)
{
FILETIME ft, lft;
SYSTEMTIME st;
TIME_ZONE_INFORMATION tzinfo;
DWORD res = GetTimeZoneInformation(&tzinfo);
ULONGLONG time = (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970 +
(LONGLONG)(tzinfo.Bias +
( res == TIME_ZONE_ID_STANDARD ? tzinfo.StandardBias :
( res == TIME_ZONE_ID_DAYLIGHT ? tzinfo.DaylightBias : 0 ))) *
SECSPERMIN *TICKSPERSEC;
BOOL ret;
ok( res != TIME_ZONE_ID_INVALID , "GetTimeZoneInformation failed\n");
ft.dwHighDateTime = (UINT)(time >> 32);
ft.dwLowDateTime = (UINT)time;
ret = FileTimeToLocalFileTime(&ft, &lft);
ok( ret,
"FileTimeToLocalFileTime() failed with Error 0x%08lx\n",GetLastError());
FileTimeToSystemTime(&lft, &st);
ok(((st.wYear == 1970) && (st.wMonth == 1) && (st.wDay == 1) &&
(st.wHour == 0) && (st.wMinute == 0) && (st.wSecond == 1) &&
(st.wMilliseconds == 0)),
"Got Year %4d Month %2d Day %2d Hour %2d Min %2d Sec %2d mSec %3d\n",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
st.wMilliseconds);
ok(SetEnvironmentVariableA("TZ","GMT") != 0,
"SetEnvironmentVariableA failed\n");
ok(res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n");
ret = FileTimeToLocalFileTime(&ft, &lft);
ok( ret,
"FileTimeToLocalFileTime() failed with Error 0x%08lx\n",GetLastError());
FileTimeToSystemTime(&lft, &st);
ok(((st.wYear == 1970) && (st.wMonth == 1) && (st.wDay == 1) &&
(st.wHour == 0) && (st.wMinute == 0) && (st.wSecond == 1) &&
(st.wMilliseconds == 0)),
"Got Year %4d Month %2d Day %2d Hour %2d Min %2d Sec %2d mSec %3d\n",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond,
st.wMilliseconds);
ok(SetEnvironmentVariableA("TZ",NULL) != 0,
"SetEnvironmentVariableA failed\n");
}
/* test TzSpecificLocalTimeToSystemTime and SystemTimeToTzSpecificLocalTime
* these are in winXP and later */
typedef HANDLE (WINAPI *fnTzSpecificLocalTimeToSystemTime)( LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
typedef HANDLE (WINAPI *fnSystemTimeToTzSpecificLocalTime)( LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME);
typedef struct {
int nr; /* test case number for easier lookup */
TIME_ZONE_INFORMATION *ptz; /* ptr to timezone */
SYSTEMTIME slt; /* system/local time to convert */
WORD ehour; /* expected hour */
} TZLT2ST_case;
static void test_TzSpecificLocalTimeToSystemTime(void)
{
HMODULE hKernel = GetModuleHandle("kernel32");
fnTzSpecificLocalTimeToSystemTime pTzSpecificLocalTimeToSystemTime;
fnSystemTimeToTzSpecificLocalTime pSystemTimeToTzSpecificLocalTime = NULL;
TIME_ZONE_INFORMATION tzE, tzW, tzS;
SYSTEMTIME result;
int i, j, year;
pTzSpecificLocalTimeToSystemTime = (fnTzSpecificLocalTimeToSystemTime) GetProcAddress( hKernel, "TzSpecificLocalTimeToSystemTime");
if(pTzSpecificLocalTimeToSystemTime)
pSystemTimeToTzSpecificLocalTime = (fnTzSpecificLocalTimeToSystemTime) GetProcAddress( hKernel, "SystemTimeToTzSpecificLocalTime");
if( !pSystemTimeToTzSpecificLocalTime)
return;
ZeroMemory( &tzE, sizeof(tzE));
ZeroMemory( &tzW, sizeof(tzW));
ZeroMemory( &tzS, sizeof(tzS));
/* timezone Eastern hemisphere */
tzE.Bias=-600;
tzE.StandardBias=0;
tzE.DaylightBias=-60;
tzE.StandardDate.wMonth=10;
tzE.StandardDate.wDayOfWeek=0; /*sunday */
tzE.StandardDate.wDay=5; /* last (sunday) of the month */
tzE.StandardDate.wHour=3;
tzE.DaylightDate.wMonth=3;
tzE.DaylightDate.wDay=5;
tzE.DaylightDate.wHour=2;
/* timezone Western hemisphere */
tzW.Bias=240;
tzW.StandardBias=0;
tzW.DaylightBias=-60;
tzW.StandardDate.wMonth=10;
tzW.StandardDate.wDayOfWeek=0; /*sunday */
tzW.StandardDate.wDay=4; /* 4th (sunday) of the month */
tzW.StandardDate.wHour=2;
tzW.DaylightDate.wMonth=4;
tzW.DaylightDate.wDay=1;
tzW.DaylightDate.wHour=2;
/* timezone Eastern hemisphere */
tzS.Bias=240;
tzS.StandardBias=0;
tzS.DaylightBias=-60;
tzS.StandardDate.wMonth=4;
tzS.StandardDate.wDayOfWeek=0; /*sunday */
tzS.StandardDate.wDay=1; /* 1st (sunday) of the month */
tzS.StandardDate.wHour=2;
tzS.DaylightDate.wMonth=10;
tzS.DaylightDate.wDay=4;
tzS.DaylightDate.wHour=2;
/*tests*/
/* TzSpecificLocalTimeToSystemTime */
{ TZLT2ST_case cases[] = {
/* standard->daylight transition */
{ 1, &tzE, {2004,3,-1,28,1,0,0,0}, 15 },
{ 2, &tzE, {2004,3,-1,28,1,59,59,999}, 15},
{ 3, &tzE, {2004,3,-1,28,2,0,0,0}, 15},
/* daylight->standard transition */
{ 4, &tzE, {2004,10,-1,31,2,0,0,0} , 15 },
{ 5, &tzE, {2004,10,-1,31,2,59,59,999}, 15 },
{ 6, &tzE, {2004,10,-1,31,3,0,0,0}, 17 },
/* West and with fixed weekday of the month */
{ 7, &tzW, {2004,4,-1,4,1,0,0,0}, 5},
{ 8, &tzW, {2004,4,-1,4,1,59,59,999}, 5},
{ 9, &tzW, {2004,4,-1,4,2,0,0,0}, 5},
{ 10, &tzW, {2004,10,-1,24,1,0,0,0}, 4},
{ 11, &tzW, {2004,10,-1,24,1,59,59,999}, 4},
{ 12, &tzW, {2004,10,-1,24,2,0,0,0 }, 6},
/* and now south */
{ 13, &tzS, {2004,4,-1,4,1,0,0,0}, 4},
{ 14, &tzS, {2004,4,-1,4,1,59,59,999}, 4},
{ 15, &tzS, {2004,4,-1,4,2,0,0,0}, 6},
{ 16, &tzS, {2004,10,-1,24,1,0,0,0}, 5},
{ 17, &tzS, {2004,10,-1,24,1,59,59,999}, 5},
{ 18, &tzS, {2004,10,-1,24,2,0,0,0}, 5},
{0}
};
/* days of transitions to put into the cases array */
int yeardays[][6]=
{
{28,31,4,24,4,24} /* 1999 */
, {26,29,2,22,2,22} /* 2000 */
, {25,28,1,28,1,28} /* 2001 */
, {31,27,7,27,7,27} /* 2002 */
, {30,26,6,26,6,26} /* 2003 */
, {28,31,4,24,4,24} /* 2004 */
, {27,30,3,23,3,23} /* 2005 */
, {26,29,2,22,2,22} /* 2006 */
, {25,28,1,28,1,28} /* 2007 */
, {30,26,6,26,6,26} /* 2008 */
, {29,25,5,25,5,25} /* 2009 */
, {28,31,4,24,4,24} /* 2010 */
, {27,30,3,23,3,23} /* 2011 */
, {25,28,1,28,1,28} /* 2012 */
, {31,27,7,27,7,27} /* 2013 */
, {30,26,6,26,6,26} /* 2014 */
, {29,25,5,25,5,25} /* 2015 */
, {27,30,3,23,3,23} /* 2016 */
, {26,29,2,22,2,22} /* 2017 */
, {25,28,1,28,1,28} /* 2018 */
, {31,27,7,27,7,27} /* 2019 */
,{0}
};
for( j=0 , year = 1999; yeardays[j][0] ; j++, year++) {
for (i=0; cases[i].nr; i++) {
if(i) cases[i].nr += 18;
cases[i].slt.wYear = year;
cases[i].slt.wDay = yeardays[j][i/3];
pTzSpecificLocalTimeToSystemTime( cases[i].ptz, &(cases[i].slt), &result);
ok( result.wHour == cases[i].ehour,
"Test TzSpecificLocalTimeToSystemTime #%d. Got %4d-%02d-%02d %02d:%02d. Expect hour = %02d\n",
cases[i].nr, result.wYear, result.wMonth, result.wDay,
result.wHour, result.wMinute, cases[i].ehour);
}
}
}
/* SystemTimeToTzSpecificLocalTime */
{ TZLT2ST_case cases[] = {
/* standard->daylight transition */
{ 1, &tzE, {2004,3,-1,27,15,0,0,0}, 1 },
{ 2, &tzE, {2004,3,-1,27,15,59,59,999}, 1},
{ 3, &tzE, {2004,3,-1,27,16,0,0,0}, 3},
/* daylight->standard transition */
{ 4, &tzE, {2004,10,-1,30,15,0,0,0}, 2 },
{ 5, &tzE, {2004,10,-1,30,15,59,59,999}, 2 },
{ 6, &tzE, {2004,10,-1,30,16,0,0,0}, 2 },
/* West and with fixed weekday of the month */
{ 7, &tzW, {2004,4,-1,4,5,0,0,0}, 1},
{ 8, &tzW, {2004,4,-1,4,5,59,59,999}, 1},
{ 9, &tzW, {2004,4,-1,4,6,0,0,0}, 3},
{ 10, &tzW, {2004,10,-1,24,4,0,0,0}, 1},
{ 11, &tzW, {2004,10,-1,24,4,59,59,999}, 1},
{ 12, &tzW, {2004,10,-1,24,5,0,0,0 }, 1},
/* and now south */
{ 13, &tzS, {2004,4,-1,4,4,0,0,0}, 1},
{ 14, &tzS, {2004,4,-1,4,4,59,59,999}, 1},
{ 15, &tzS, {2004,4,-1,4,5,0,0,0}, 1},
{ 16, &tzS, {2004,10,-1,24,5,0,0,0}, 1},
{ 17, &tzS, {2004,10,-1,24,5,59,59,999}, 1},
{ 18, &tzS, {2004,10,-1,24,6,0,0,0}, 3},
{0}
};
/* days of transitions to put into the cases array */
int yeardays[][6]=
{
{27,30,4,24,4,24} /* 1999 */
, {25,28,2,22,2,22} /* 2000 */
, {24,27,1,28,1,28} /* 2001 */
, {30,26,7,27,7,27} /* 2002 */
, {29,25,6,26,6,26} /* 2003 */
, {27,30,4,24,4,24} /* 2004 */
, {26,29,3,23,3,23} /* 2005 */
, {25,28,2,22,2,22} /* 2006 */
, {24,27,1,28,1,28} /* 2007 */
, {29,25,6,26,6,26} /* 2008 */
, {28,24,5,25,5,25} /* 2009 */
, {27,30,4,24,4,24} /* 2010 */
, {26,29,3,23,3,23} /* 2011 */
, {24,27,1,28,1,28} /* 2012 */
, {30,26,7,27,7,27} /* 2013 */
, {29,25,6,26,6,26} /* 2014 */
, {28,24,5,25,5,25} /* 2015 */
, {26,29,3,23,3,23} /* 2016 */
, {25,28,2,22,2,22} /* 2017 */
, {24,27,1,28,1,28} /* 2018 */
, {30,26,7,27,7,27} /* 2019 */
};
for( j=0 , year = 1999; yeardays[j][0] ; j++, year++) {
for (i=0; cases[i].nr; i++) {
if(i) cases[i].nr += 18;
cases[i].slt.wYear = year;
cases[i].slt.wDay = yeardays[j][i/3];
pSystemTimeToTzSpecificLocalTime( cases[i].ptz, &(cases[i].slt), &result);
ok( result.wHour == cases[i].ehour,
"Test SystemTimeToTzSpecificLocalTime #%d. Got %4d-%02d-%02d %02d:%02d. Expect hour = %02d\n",
cases[i].nr, result.wYear, result.wMonth, result.wDay,
result.wHour, result.wMinute, cases[i].ehour);
}
}
}
}
START_TEST(time)
{
test_conversions();
test_invalid_arg();
test_GetTimeZoneInformation();
test_FileTimeToSystemTime();
test_FileTimeToLocalFileTime();
test_TzSpecificLocalTimeToSystemTime();
}

View file

@ -0,0 +1,71 @@
/*
* Unit test suite for time functions
*
* Copyright 2004 Mike McCormack
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define _WIN32_WINNT 0x0501
#include "wine/test.h"
#include "winbase.h"
typedef HANDLE (WINAPI *fnCreateWaitableTimerA)( SECURITY_ATTRIBUTES*, BOOL, LPSTR );
typedef BOOL (WINAPI *fnSetWaitableTimer)(HANDLE, LARGE_INTEGER*, LONG, PTIMERAPCROUTINE, LPVOID, BOOL);
static void test_timer(void)
{
HMODULE hker = GetModuleHandle("kernel32");
fnCreateWaitableTimerA pCreateWaitableTimerA;
fnSetWaitableTimer pSetWaitableTimer;
HANDLE handle;
BOOL r;
LARGE_INTEGER due;
pCreateWaitableTimerA = (fnCreateWaitableTimerA) GetProcAddress( hker, "CreateWaitableTimerA");
if( !pCreateWaitableTimerA )
return;
pSetWaitableTimer = (fnSetWaitableTimer) GetProcAddress( hker, "SetWaitableTimer");
if( !pSetWaitableTimer )
return;
/* try once with a positive number */
handle = pCreateWaitableTimerA( NULL, 0, NULL );
ok( handle != NULL, "failed to create waitable timer with no name\n" );
due.QuadPart = 10000;
r = pSetWaitableTimer( handle, &due, 0x1f4, NULL, NULL, FALSE );
ok( r, "failed to set timer\n");
CloseHandle( handle );
/* try once with a negative number */
handle = pCreateWaitableTimerA( NULL, 0, NULL );
ok( handle != NULL, "failed to create waitable timer with no name\n" );
due.QuadPart = -10000;
r = pSetWaitableTimer( handle, &due, 0x1f4, NULL, NULL, FALSE );
ok( r, "failed to set timer\n");
CloseHandle( handle );
}
START_TEST(timer)
{
test_timer();
}

View file

@ -0,0 +1,341 @@
/*
* Toolhelp
*
* Copyright 2005 Eric Pouech
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <windef.h>
#include <winbase.h>
#include "tlhelp32.h"
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
static char selfname[MAX_PATH];
/* Some functions are only in later versions of kernel32.dll */
static HANDLE (WINAPI *pCreateToolhelp32Snapshot)(DWORD, DWORD);
static BOOL (WINAPI *pModule32First)(HANDLE, LPMODULEENTRY32);
static BOOL (WINAPI *pModule32Next)(HANDLE, LPMODULEENTRY32);
static BOOL (WINAPI *pProcess32First)(HANDLE, LPPROCESSENTRY32);
static BOOL (WINAPI *pProcess32Next)(HANDLE, LPPROCESSENTRY32);
static BOOL (WINAPI *pThread32First)(HANDLE, LPTHREADENTRY32);
static BOOL (WINAPI *pThread32Next)(HANDLE, LPTHREADENTRY32);
/* 1 minute should be more than enough */
#define WAIT_TIME (60 * 1000)
static DWORD WINAPI sub_thread(void* pmt)
{
DWORD w = WaitForSingleObject((HANDLE)pmt, WAIT_TIME);
return w;
}
/******************************************************************
* init
*
* generates basic information like:
* selfname: the way to reinvoke ourselves
* returns:
* -1 on error
* 0 if parent
* doesn't return if child
*/
static int init(void)
{
int argc;
char** argv;
HANDLE ev1, ev2, ev3, hThread;
DWORD w;
argc = winetest_get_mainargs( &argv );
strcpy(selfname, argv[0]);
switch (argc)
{
case 2: /* the test program */
return 0;
case 4: /* the sub-process */
ev1 = (HANDLE)atoi(argv[2]);
ev2 = (HANDLE)atoi(argv[3]);
ev3 = CreateEvent(NULL, FALSE, FALSE, NULL);
if (ev3 == NULL) ExitProcess(WAIT_ABANDONED);
hThread = CreateThread(NULL, 0, sub_thread, ev3, 0, NULL);
if (hThread == NULL) ExitProcess(WAIT_ABANDONED);
if (!LoadLibraryA("shell32.dll")) ExitProcess(WAIT_ABANDONED);
/* signal init of sub-process is done */
SetEvent(ev1);
/* wait for parent to have done all its queries */
w = WaitForSingleObject(ev2, WAIT_TIME);
if (w != WAIT_OBJECT_0) ExitProcess(w);
/* signal sub-thread to terminate */
SetEvent(ev3);
w = WaitForSingleObject(hThread, WAIT_TIME);
if (w != WAIT_OBJECT_0) ExitProcess(w);
GetExitCodeThread(hThread, &w);
ExitProcess(w);
default:
return -1;
}
}
static void test_process(DWORD curr_pid, DWORD sub_pcs_pid)
{
HANDLE hSnapshot;
PROCESSENTRY32 pe;
THREADENTRY32 te;
MODULEENTRY32 me;
unsigned found = 0;
int num = 0;
hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
ok(hSnapshot != NULL, "Cannot create snapshot\n");
/* check that this current process is enumerated */
pe.dwSize = sizeof(pe);
if (pProcess32First( hSnapshot, &pe ))
{
do
{
if (pe.th32ProcessID == curr_pid) found++;
if (pe.th32ProcessID == sub_pcs_pid) found++;
trace("PID=%lx %s\n", pe.th32ProcessID, pe.szExeFile);
num++;
} while (pProcess32Next( hSnapshot, &pe ));
}
ok(found == 2, "couldn't find self and/or sub-process in process list\n");
/* check that first really resets the enumeration */
found = 0;
if (pProcess32First( hSnapshot, &pe ))
{
do
{
if (pe.th32ProcessID == curr_pid) found++;
if (pe.th32ProcessID == sub_pcs_pid) found++;
trace("PID=%lx %s\n", pe.th32ProcessID, pe.szExeFile);
num--;
} while (pProcess32Next( hSnapshot, &pe ));
}
ok(found == 2, "couldn't find self and/or sub-process in process list\n");
ok(!num, "mismatch in counting\n");
te.dwSize = sizeof(te);
ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
me.dwSize = sizeof(me);
ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
CloseHandle(hSnapshot);
ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
}
static void test_thread(DWORD curr_pid, DWORD sub_pcs_pid)
{
HANDLE hSnapshot;
PROCESSENTRY32 pe;
THREADENTRY32 te;
MODULEENTRY32 me;
int num = 0;
unsigned curr_found = 0;
unsigned sub_found = 0;
hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
ok(hSnapshot != NULL, "Cannot create snapshot\n");
/* check that this current process is enumerated */
te.dwSize = sizeof(te);
if (pThread32First( hSnapshot, &te ))
{
do
{
if (te.th32OwnerProcessID == curr_pid) curr_found++;
if (te.th32OwnerProcessID == sub_pcs_pid) sub_found++;
trace("PID=%lx TID=%lx %ld\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
num++;
} while (pThread32Next( hSnapshot, &te ));
}
ok(curr_found == 1, "couldn't find self in thread list\n");
ok(sub_found == 2, "couldn't find sub-process thread's in thread list\n");
/* check that first really resets enumeration */
curr_found = 0;
sub_found = 0;
if (pThread32First( hSnapshot, &te ))
{
do
{
if (te.th32OwnerProcessID == curr_pid) curr_found++;
if (te.th32OwnerProcessID == sub_pcs_pid) sub_found++;
trace("PID=%lx TID=%lx %ld\n", te.th32OwnerProcessID, te.th32ThreadID, te.tpBasePri);
num--;
} while (pThread32Next( hSnapshot, &te ));
}
ok(curr_found == 1, "couldn't find self in thread list\n");
ok(sub_found == 2, "couldn't find sub-process thread's in thread list\n");
pe.dwSize = sizeof(pe);
ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
me.dwSize = sizeof(me);
ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
CloseHandle(hSnapshot);
ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
}
static const char* curr_expected_modules[] =
{
"kernel32.dll",
"kernel32_test.exe"
/* FIXME: could test for ntdll on NT and Wine */
};
static const char* sub_expected_modules[] =
{
"kernel32.dll",
"kernel32_test.exe",
"shell32.dll"
/* FIXME: could test for ntdll on NT and Wine */
};
#define NUM_OF(x) (sizeof(x) / sizeof(x[0]))
static void test_module(DWORD pid, const char* expected[], unsigned num_expected)
{
HANDLE hSnapshot;
PROCESSENTRY32 pe;
THREADENTRY32 te;
MODULEENTRY32 me;
unsigned found[32];
int i, num = 0;
ok(NUM_OF(found) >= num_expected, "Internal: bump found[] size\n");
hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pid );
ok(hSnapshot != NULL, "Cannot create snapshot\n");
for (i = 0; i < num_expected; i++) found[i] = 0;
me.dwSize = sizeof(me);
if (pModule32First( hSnapshot, &me ))
{
do
{
trace("PID=%lx base=%p size=%lx %s %s\n",
me.th32ProcessID, me.modBaseAddr, me.modBaseSize, me.szExePath, me.szModule);
ok(me.th32ProcessID == pid, "wrong returned process id\n");
for (i = 0; i < num_expected; i++)
if (!lstrcmpi(expected[i], me.szModule)) found[i]++;
num++;
} while (pModule32Next( hSnapshot, &me ));
}
for (i = 0; i < num_expected; i++)
ok(found[i] == 1, "Module %s is %s\n",
expected[i], found[i] ? "listed more than once" : "not listed");
/* check that first really resets the enumeration */
for (i = 0; i < num_expected; i++) found[i] = 0;
me.dwSize = sizeof(me);
if (pModule32First( hSnapshot, &me ))
{
do
{
trace("PID=%lx base=%p size=%lx %s %s\n",
me.th32ProcessID, me.modBaseAddr, me.modBaseSize, me.szExePath, me.szModule);
for (i = 0; i < num_expected; i++)
if (!lstrcmpi(expected[i], me.szModule)) found[i]++;
num--;
} while (pModule32Next( hSnapshot, &me ));
}
for (i = 0; i < num_expected; i++)
ok(found[i] == 1, "Module %s is %s\n",
expected[i], found[i] ? "listed more than once" : "not listed");
ok(!num, "mismatch in counting\n");
pe.dwSize = sizeof(pe);
ok(!pProcess32First( hSnapshot, &pe ), "shouldn't return a process\n");
me.dwSize = sizeof(me);
ok(!pThread32First( hSnapshot, &te ), "shouldn't return a thread\n");
CloseHandle(hSnapshot);
ok(!pModule32First( hSnapshot, &me ), "shouldn't return a module\n");
}
START_TEST(toolhelp)
{
DWORD pid = GetCurrentProcessId();
int r;
char buffer[MAX_PATH];
SECURITY_ATTRIBUTES sa;
PROCESS_INFORMATION info;
STARTUPINFOA startup;
HANDLE ev1, ev2;
DWORD w;
HANDLE hkernel32 = GetModuleHandleA("kernel32");
pCreateToolhelp32Snapshot = (VOID *) GetProcAddress(hkernel32, "CreateToolhelp32Snapshot");
pModule32First = (VOID *) GetProcAddress(hkernel32, "Module32First");
pModule32Next = (VOID *) GetProcAddress(hkernel32, "Module32Next");
pProcess32First = (VOID *) GetProcAddress(hkernel32, "Process32First");
pProcess32Next = (VOID *) GetProcAddress(hkernel32, "Process32Next");
pThread32First = (VOID *) GetProcAddress(hkernel32, "Thread32First");
pThread32Next = (VOID *) GetProcAddress(hkernel32, "Thread32Next");
if (!pCreateToolhelp32Snapshot ||
!pModule32First || !pModule32Next ||
!pProcess32First || !pProcess32Next ||
!pThread32First || !pThread32Next) return;
r = init();
ok(r == 0, "Basic init of sub-process test\n");
if (r != 0) return;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
ev1 = CreateEvent(&sa, FALSE, FALSE, NULL);
ev2 = CreateEvent(&sa, FALSE, FALSE, NULL);
ok (ev1 != NULL && ev2 != NULL, "Couldn't create events\n");
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = SW_SHOWNORMAL;
sprintf(buffer, "%s tests/toolhelp.c %lu %lu", selfname, (DWORD)ev1, (DWORD)ev2);
ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to be initialized */
w = WaitForSingleObject(ev1, WAIT_TIME);
ok(w == WAIT_OBJECT_0, "Failed to wait on sub-process startup\n");
test_process(pid, info.dwProcessId);
test_thread(pid, info.dwProcessId);
test_module(pid, curr_expected_modules, NUM_OF(curr_expected_modules));
test_module(info.dwProcessId, sub_expected_modules, NUM_OF(sub_expected_modules));
SetEvent(ev2);
w = WaitForSingleObject(info.hProcess, WAIT_TIME);
ok(w == WAIT_OBJECT_0, "Failed to wait on sub-process termination\n");
ok(GetExitCodeProcess(info.hProcess, &w), "couldn't get process exit code\n");
ok(w == WAIT_OBJECT_0, "Sub-Process failed to terminate properly\n");
}

View file

@ -19,9 +19,7 @@
*/
#include "wine/test.h"
#include "winbase.h"
#include "winerror.h"
#include "winuser.h"
#include "windows.h"
static BOOL is_win9x = FALSE;

View file

@ -21,11 +21,7 @@
#include <assert.h>
#include "wine/test.h"
#include "winbase.h"
#include "winuser.h"
#include "dde.h"
#include "ddeml.h"
#include "winerror.h"
#include "windows.h"
static const WCHAR TEST_DDE_SERVICE[] = {'T','e','s','t','D','D','E','S','e','r','v','i','c','e',0};

View file

@ -34,9 +34,7 @@
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "windows.h"
#define MAXHWNDS 1024
static HWND hwnd [MAXHWNDS];

View file

@ -49,7 +49,7 @@
#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "windows.h"
#include "wine/test.h"

View file

@ -27,11 +27,7 @@
#define WINVER 0x0500
#define _WIN32_WINNT 0x0501 /* For WM_CHANGEUISTATE,QS_RAWINPUT */
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "windows.h"
#include "wine/test.h"

View file

@ -1,17 +1,10 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
struct test
{
const char *name;
void (*func)(void);
};
#define STANDALONE
#include "wine/test.h"
extern void func_class(void);
extern void func_clipboard(void);
@ -19,6 +12,7 @@ extern void func_dce(void);
extern void func_dde(void);
extern void func_dialog(void);
extern void func_edit(void);
extern void func_generated(void);
extern void func_input(void);
extern void func_listbox(void);
extern void func_menu(void);
@ -39,6 +33,7 @@ const struct test winetest_testlist[] =
{ "dde", func_dde },
{ "dialog", func_dialog },
{ "edit", func_edit },
// { "generated", func_generated },
{ "input", func_input },
{ "listbox", func_listbox },
{ "menu", func_menu },
@ -52,6 +47,3 @@ const struct test winetest_testlist[] =
{ "wsprintf", func_wsprintf },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -20,9 +20,7 @@
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "windows.h"
static void wsprintfATest(void)
{

View file

@ -1,25 +1,17 @@
/* Automatically generated file; DO NOT EDIT!! */
/* stdarg.h is needed for Winelib */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_info(void);
extern void func_install(void);
struct test
{
const char *name;
void (*func)(void);
};
static const struct test winetest_testlist[] =
const struct test winetest_testlist[] =
{
{ "info", func_info },
// { "install", func_install },
{ 0, 0 }
};
#define WINETEST_WANT_MAIN
#include "wine/test.h"

View file

@ -0,0 +1,268 @@
/*
* Unit test suite for Virtual* family of APIs.
*
* Copyright 2004 Dmitry Timoshkov
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/test.h"
static void test_VirtualAlloc(void)
{
void *addr1, *addr2;
DWORD old_prot;
MEMORY_BASIC_INFORMATION info;
SetLastError(0xdeadbeef);
addr1 = VirtualAlloc(0, 0, MEM_RESERVE, PAGE_NOACCESS);
ok(addr1 == NULL, "VirtualAlloc should fail on zero-sized allocation\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER /* NT */ ||
GetLastError() == ERROR_NOT_ENOUGH_MEMORY, /* Win9x */
"got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError());
addr1 = VirtualAlloc(0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
ok(addr1 != NULL, "VirtualAlloc failed\n");
/* test a not committed memory */
ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
"VirtualQuery failed\n");
ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
ok(info.AllocationProtect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.AllocationProtect);
ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
ok(info.State == MEM_RESERVE, "%lx != MEM_RESERVE\n", info.State);
/* NT reports Protect == 0 for a not committed memory block */
ok(info.Protect == 0 /* NT */ ||
info.Protect == PAGE_NOACCESS, /* Win9x */
"%lx != PAGE_NOACCESS\n", info.Protect);
ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type);
SetLastError(0xdeadbeef);
ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
"VirtualProtect should fail on a not committed memory\n");
ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
"got %ld, expected ERROR_INVALID_ADDRESS\n", GetLastError());
addr2 = VirtualAlloc(addr1, 0x1000, MEM_COMMIT, PAGE_NOACCESS);
ok(addr1 == addr2, "VirtualAlloc failed\n");
/* test a committed memory */
ok(VirtualQuery(addr1, &info, sizeof(info)) == sizeof(info),
"VirtualQuery failed\n");
ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
ok(info.AllocationProtect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.AllocationProtect);
ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State);
/* this time NT reports PAGE_NOACCESS as well */
ok(info.Protect == PAGE_NOACCESS, "%lx != PAGE_NOACCESS\n", info.Protect);
ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type);
/* this should fail, since not the whole range is committed yet */
SetLastError(0xdeadbeef);
ok(!VirtualProtect(addr1, 0xFFFC, PAGE_READONLY, &old_prot),
"VirtualProtect should fail on a not committed memory\n");
ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
"got %ld, expected ERROR_INVALID_ADDRESS\n", GetLastError());
ok(VirtualProtect(addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtect failed\n");
ok(old_prot == PAGE_NOACCESS,
"wrong old protection: got %04lx instead of PAGE_NOACCESS\n", old_prot);
ok(VirtualProtect(addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtect failed\n");
ok(old_prot == PAGE_READONLY,
"wrong old protection: got %04lx instead of PAGE_READONLY\n", old_prot);
ok(!VirtualFree(addr1, 0x10000, 0), "VirtualFree should fail with type 0\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError());
ok(VirtualFree(addr1, 0x10000, MEM_DECOMMIT), "VirtualFree failed\n");
/* if the type is MEM_RELEASE, size must be 0 */
ok(!VirtualFree(addr1, 1, MEM_RELEASE), "VirtualFree should fail\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"got %ld, expected ERROR_INVALID_PARAMETER\n", GetLastError());
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
}
static void test_MapViewOfFile(void)
{
static const char testfile[] = "testfile.xxx";
HANDLE file, mapping;
void *ptr;
file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
SetFilePointer( file, 4096, NULL, FILE_BEGIN );
SetEndOfFile( file );
/* read/write mapping */
mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
ok( mapping != 0, "CreateFileMapping failed\n" );
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile FILE_MAPE_READ failed\n" );
UnmapViewOfFile( ptr );
/* this fails on win9x but succeeds on NT */
ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
if (ptr) UnmapViewOfFile( ptr );
else ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %lx\n", GetLastError() );
ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile 0 failed\n" );
UnmapViewOfFile( ptr );
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE failed\n" );
UnmapViewOfFile( ptr );
CloseHandle( mapping );
/* read-only mapping */
mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
ok( mapping != 0, "CreateFileMapping failed\n" );
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ failed\n" );
UnmapViewOfFile( ptr );
/* this fails on win9x but succeeds on NT */
ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
if (ptr) UnmapViewOfFile( ptr );
else ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %lx\n", GetLastError() );
ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile 0 failed\n" );
UnmapViewOfFile( ptr );
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %lx\n", GetLastError() );
CloseHandle( mapping );
/* copy-on-write mapping */
mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
ok( mapping != 0, "CreateFileMapping failed\n" );
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ failed\n" );
UnmapViewOfFile( ptr );
ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_COPY failed\n" );
UnmapViewOfFile( ptr );
ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile 0 failed\n" );
UnmapViewOfFile( ptr );
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %lx\n", GetLastError() );
CloseHandle( mapping );
/* no access mapping */
mapping = CreateFileMappingA( file, NULL, PAGE_NOACCESS, 0, 4096, NULL );
/* fails on NT but succeeds on win9x */
if (!mapping) ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %lx\n", GetLastError() );
else
{
ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ failed\n" );
UnmapViewOfFile( ptr );
ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 4096 );
ok( !ptr, "MapViewOfFile FILE_MAP_COPY succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %lx\n", GetLastError() );
ptr = MapViewOfFile( mapping, 0, 0, 0, 4096 );
ok( ptr != NULL, "MapViewOfFile 0 failed\n" );
UnmapViewOfFile( ptr );
ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 4096 );
ok( !ptr, "MapViewOfFile FILE_MAP_WRITE succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER, "Wrong error %lx\n", GetLastError() );
CloseHandle( mapping );
}
CloseHandle( file );
/* now try read-only file */
file = CreateFileA( testfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %lx\n", GetLastError() );
mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
ok( mapping != 0, "CreateFileMapping PAGE_WRITECOPY failed\n" );
CloseHandle( mapping );
mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
ok( mapping != 0, "CreateFileMapping PAGE_READONLY failed\n" );
CloseHandle( mapping );
CloseHandle( file );
/* now try no access file */
file = CreateFileA( testfile, 0, 0, NULL, OPEN_EXISTING, 0, 0 );
ok( file != INVALID_HANDLE_VALUE, "Failed to create test file\n" );
mapping = CreateFileMappingA( file, NULL, PAGE_READWRITE, 0, 4096, NULL );
ok( !mapping, "CreateFileMapping PAGE_READWRITE succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %lx\n", GetLastError() );
mapping = CreateFileMappingA( file, NULL, PAGE_WRITECOPY, 0, 4096, NULL );
ok( !mapping, "CreateFileMapping PAGE_WRITECOPY succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %lx\n", GetLastError() );
mapping = CreateFileMappingA( file, NULL, PAGE_READONLY, 0, 4096, NULL );
ok( !mapping, "CreateFileMapping PAGE_READONLY succeeded\n" );
ok( GetLastError() == ERROR_INVALID_PARAMETER ||
GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %lx\n", GetLastError() );
CloseHandle( file );
CloseHandle( file );
DeleteFileA( testfile );
}
START_TEST(virtual)
{
test_VirtualAlloc();
test_MapViewOfFile();
}

View file

@ -0,0 +1,51 @@
/*
* Unit test suite
*
* Copyright 2006 Stefan Leichter
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/test.h"
#include "winbase.h"
#define CDROM "CDROM"
#define FLOPPY "FLOPPY"
#define HARDISK "HARDDISK"
#define LANMAN "LANMANREDIRECTOR"
#define RAMDISK "RAMDISK"
static void test_query_dos_deviceA(void)
{
char drivestr[] = "a:";
char *p, buffer[2000];
DWORD ret;
for (;drivestr[0] <= 'z'; drivestr[0]++) {
ret = QueryDosDeviceA( drivestr, buffer, sizeof(buffer));
if(ret) {
for (p = buffer; *p; p++) *p = toupper(*p);
todo_wine
ok( strstr( buffer, CDROM) || strstr( buffer, FLOPPY) ||
strstr( buffer, HARDISK) || strstr( buffer, LANMAN) ||
strstr( buffer, RAMDISK), "expect the string %s contains %s,%s,%s,%s or %s\n",
buffer, CDROM, FLOPPY, HARDISK, LANMAN, RAMDISK);
}
}
}
START_TEST(volume)
{
test_query_dos_deviceA();
}