mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 19:26:32 +00:00
- Update kernel32_winetest to the Wine's CVS head
svn path=/trunk/; revision=21953
This commit is contained in:
@@ -67,6 +67,43 @@ 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
|
||||
# define U2(x) (x).u2
|
||||
# define U3(x) (x).u3
|
||||
# define U4(x) (x).u4
|
||||
# define U5(x) (x).u5
|
||||
# define U6(x) (x).u6
|
||||
# define U7(x) (x).u7
|
||||
# define U8(x) (x).u8
|
||||
#else
|
||||
# define U(x) (x)
|
||||
# define U1(x) (x)
|
||||
# define U2(x) (x)
|
||||
# define U3(x) (x)
|
||||
# define U4(x) (x)
|
||||
# define U5(x) (x)
|
||||
# define U6(x) (x)
|
||||
# define U7(x) (x)
|
||||
# define U8(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef NONAMELESSSTRUCT
|
||||
# define S(x) (x).s
|
||||
# define S1(x) (x).s1
|
||||
# define S2(x) (x).s2
|
||||
# define S3(x) (x).s3
|
||||
# define S4(x) (x).s4
|
||||
# define S5(x) (x).s5
|
||||
#else
|
||||
# define S(x) (x)
|
||||
# define S1(x) (x)
|
||||
# define S2(x) (x)
|
||||
# define S3(x) (x)
|
||||
# define S4(x) (x)
|
||||
# define S5(x) (x)
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* Below is the implementation of the various functions, to be included
|
||||
|
||||
@@ -25,11 +25,53 @@
|
||||
#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)
|
||||
@@ -111,6 +153,8 @@ static void test_get_atom_name(void)
|
||||
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" );
|
||||
|
||||
@@ -160,6 +204,123 @@ static void test_get_atom_name(void)
|
||||
}
|
||||
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 %lu)\n", GetLastError(), (DWORD)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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,8 +418,8 @@ static void test_local_add_atom(void)
|
||||
|
||||
static void test_local_get_atom_name(void)
|
||||
{
|
||||
char buf[10];
|
||||
WCHAR bufW[10];
|
||||
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,'.','.','.'};
|
||||
@@ -282,6 +443,24 @@ static void test_local_get_atom_name(void)
|
||||
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" );
|
||||
@@ -304,13 +483,113 @@ static void test_local_get_atom_name(void)
|
||||
if (i)
|
||||
{
|
||||
char res[20];
|
||||
ok( (len > 1) && (len < 7), "bad length %d\n", len );
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +613,6 @@ static void test_local_error_handling(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
START_TEST(atom)
|
||||
{
|
||||
test_add_atom();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* 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
|
||||
@@ -28,9 +29,12 @@
|
||||
#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)
|
||||
{
|
||||
@@ -136,12 +140,21 @@ static void test_FindFirstChangeNotification(void)
|
||||
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 remove the directory we registered notification for? */
|
||||
/* What if we move the directory we registered notification for? */
|
||||
thread = StartNotificationThread(dirname1, FALSE, FILE_NOTIFY_CHANGE_DIR_NAME);
|
||||
ret = RemoveDirectoryA(dirname1);
|
||||
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 */
|
||||
@@ -156,9 +169,6 @@ static void test_FindFirstChangeNotification(void)
|
||||
ok(ret, "CreateDirectoryA error: %ld\n", GetLastError());
|
||||
ok(FinishNotificationThread(thread), "Missed notification\n");
|
||||
|
||||
lstrcpyA(dirname2, dirname1);
|
||||
lstrcatA(dirname2, "new");
|
||||
|
||||
/* Rename a directory */
|
||||
thread = StartNotificationThread(workdir, FALSE, FILE_NOTIFY_CHANGE_DIR_NAME);
|
||||
ret = MoveFileA(dirname1, dirname2);
|
||||
@@ -236,7 +246,468 @@ static void test_FindFirstChangeNotification(void)
|
||||
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, INFINITE );
|
||||
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, INFINITE );
|
||||
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, INFINITE );
|
||||
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, INFINITE );
|
||||
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, INFINITE );
|
||||
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, INFINITE );
|
||||
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, INFINITE );
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,19 @@
|
||||
#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)
|
||||
{
|
||||
@@ -71,6 +84,7 @@ static void test_overlapped_buffers(void)
|
||||
|
||||
START_TEST(codepage)
|
||||
{
|
||||
test_null_source();
|
||||
test_negative_source_length();
|
||||
test_overlapped_buffers();
|
||||
}
|
||||
|
||||
@@ -37,12 +37,10 @@
|
||||
#define LOOPBACK_DTR_DSR FALSE /* Sub-D 9: Short 4-6 */
|
||||
#define LOOPBACK_DTR_RING FALSE /* Sub-D 9: Short 4-9 */
|
||||
#define LOOPBACK_DTR_DCD FALSE /* Sub-D 9: Short 4-1 */
|
||||
|
||||
/* SETBREAK seems to give instable results, MSDN mentions possible problems
|
||||
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcedebug5/\
|
||||
* html/wce50conSerialPortDriverTest.asp
|
||||
* but perhaps it's only a programming error, that causes it... */
|
||||
#define BROKEN_SETBREAK TRUE
|
||||
/* Many Linux serial drivers have the TIOCM_LOOP flag in the TIOCM_SET ioctl
|
||||
* available. For the 8250 this is equivalent to TXD->RXD, OUT2->DCD,
|
||||
* OUT1->RI, RTS->CTS and DTR->DSR
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -660,6 +658,8 @@ static HANDLE test_OpenComm(BOOL doOverlap)
|
||||
HANDLE hcom = INVALID_HANDLE_VALUE;
|
||||
char port_name[] = "COMx";
|
||||
static BOOL shown = FALSE;
|
||||
DWORD errors;
|
||||
COMSTAT comstat;
|
||||
|
||||
/* Try to find a port */
|
||||
for(port_name[3] = '1'; port_name[3] <= '9'; port_name[3]++)
|
||||
@@ -677,6 +677,13 @@ static HANDLE test_OpenComm(BOOL doOverlap)
|
||||
trace("Found Com port %s. Connected devices may disturbe results\n", port_name);
|
||||
/*shown = TRUE; */
|
||||
}
|
||||
if (hcom != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ok(ClearCommError(hcom,&errors,&comstat), "Unexpected errors on open\n");
|
||||
ok(comstat.cbInQue == 0, "Unexpected %ld chars in InQueue\n",comstat.cbInQue);
|
||||
ok(comstat.cbOutQue == 0, "Still pending %ld charcters in OutQueue\n", comstat.cbOutQue);
|
||||
ok(errors == 0, "Unexpected errors 0x%08lx\n", errors);
|
||||
}
|
||||
return hcom;
|
||||
}
|
||||
|
||||
@@ -705,6 +712,8 @@ static void test_ReadTimeOut(HANDLE hcom)
|
||||
dcb.BaudRate = FASTBAUD;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fRtsControl=RTS_CONTROL_ENABLE;
|
||||
dcb.fDtrControl=DTR_CONTROL_ENABLE;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
|
||||
|
||||
@@ -717,8 +726,8 @@ static void test_ReadTimeOut(HANDLE hcom)
|
||||
res = ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL);
|
||||
LastError = GetLastError();
|
||||
after = GetTickCount();
|
||||
todo_wine ok( res == TRUE, "A timed-out read should return TRUE\n");
|
||||
todo_wine ok( LastError == 0xdeadbeef, "err=%ld\n", LastError);
|
||||
ok( res == TRUE, "A timed-out read should return TRUE\n");
|
||||
ok( LastError == 0xdeadbeef, "err=%ld\n", LastError);
|
||||
timediff = after - before;
|
||||
ok( timediff > TIMEOUT>>2 && timediff < TIMEOUT *2,
|
||||
"Unexpected TimeOut %ld, expected %d\n", timediff, TIMEOUT);
|
||||
@@ -728,16 +737,19 @@ static void test_waittxempty(HANDLE hcom)
|
||||
{
|
||||
DCB dcb;
|
||||
COMMTIMEOUTS timeouts;
|
||||
char tbuf[]="Some Characters\n";
|
||||
char tbuf[]="test_waittxempty";
|
||||
DWORD before, after, written, timediff, evtmask = 0;
|
||||
BOOL res_write, res;
|
||||
DWORD baud = SLOWBAUD;
|
||||
|
||||
trace("test_waittxempty\n");
|
||||
/* set a low baud rate to have ample time*/
|
||||
ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
|
||||
dcb.BaudRate = baud;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fRtsControl=RTS_CONTROL_ENABLE;
|
||||
dcb.fDtrControl=DTR_CONTROL_ENABLE;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
|
||||
|
||||
@@ -762,8 +774,8 @@ static void test_waittxempty(HANDLE hcom)
|
||||
res = WaitCommEvent(hcom, &evtmask, NULL);
|
||||
after = GetTickCount();
|
||||
|
||||
todo_wine ok(res == TRUE, "WaitCommEvent failed\n");
|
||||
todo_wine ok(evtmask == EV_TXEMPTY,
|
||||
ok(res == TRUE, "WaitCommEvent failed\n");
|
||||
ok((evtmask & EV_TXEMPTY),
|
||||
"WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_TXEMPTY);
|
||||
|
||||
@@ -777,7 +789,6 @@ static void test_waittxempty(HANDLE hcom)
|
||||
nearly return immediate,
|
||||
while on wine the most time is spent here
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/* A new open handle should not return error or have bytes in the Queues */
|
||||
@@ -787,9 +798,22 @@ static void test_ClearCommErrors(HANDLE hcom)
|
||||
COMSTAT lpStat;
|
||||
|
||||
ok(ClearCommError(hcom, &errors, &lpStat), "ClearCommError failed\n");
|
||||
ok(lpStat.cbInQue == 0, "Unexpected %ld Bytes in InQueue\n", lpStat.cbInQue);
|
||||
ok(lpStat.cbOutQue == 0, "Unexpected %ld Bytes in OutQueue\n", lpStat.cbOutQue);
|
||||
ok(lpStat.cbInQue == 0, "Unexpected %ld chars in InQueue\n", lpStat.cbInQue);
|
||||
ok(lpStat.cbOutQue == 0, "Unexpected %ld chars in OutQueue\n", lpStat.cbOutQue);
|
||||
ok(errors == 0, "ClearCommErrors: Unexpected error 0x%08lx\n", errors);
|
||||
trace("test_ClearCommErrors done\n");
|
||||
}
|
||||
|
||||
static void test_non_pending_errors(HANDLE hcom)
|
||||
{
|
||||
DCB dcb;
|
||||
DWORD err;
|
||||
|
||||
ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
|
||||
dcb.ByteSize = 255; /* likely bogus */
|
||||
ok(!SetCommState(hcom, &dcb), "SetCommState should have failed\n");
|
||||
ok(ClearCommError(hcom, &err, NULL), "ClearCommError should succeed\n");
|
||||
ok(!(err & CE_MODE), "ClearCommError shouldn't set CE_MODE byte in this case (%lx)\n", err);
|
||||
}
|
||||
|
||||
/**/
|
||||
@@ -798,14 +822,17 @@ static void test_LoopbackRead(HANDLE hcom)
|
||||
DCB dcb;
|
||||
COMMTIMEOUTS timeouts;
|
||||
char rbuf[32];
|
||||
DWORD before, after, diff, read, written, evtmask=0;
|
||||
DWORD before, after, diff, read, read1, written, evtmask=0, i;
|
||||
BOOL res;
|
||||
char tbuf[]="Some Characters\n";
|
||||
char tbuf[]="test_LoopbackRead";
|
||||
|
||||
trace("Starting test_LoopbackRead\n");
|
||||
ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
|
||||
dcb.BaudRate = FASTBAUD;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fRtsControl=RTS_CONTROL_ENABLE;
|
||||
dcb.fDtrControl=DTR_CONTROL_ENABLE;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
|
||||
|
||||
@@ -815,29 +842,35 @@ static void test_LoopbackRead(HANDLE hcom)
|
||||
|
||||
ok(SetCommMask(hcom, EV_TXEMPTY), "SetCommMask failed\n");
|
||||
|
||||
before = GetTickCount();
|
||||
ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
|
||||
after = GetTickCount();
|
||||
ok(written == sizeof(tbuf),"WriteFile %ld bytes written, expected %d\n",
|
||||
written, sizeof(tbuf));
|
||||
diff = after -before;
|
||||
|
||||
/* make sure all bytes are written, so Readfile will succeed in one call*/
|
||||
todo_wine ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
|
||||
todo_wine ok(evtmask == EV_TXEMPTY,
|
||||
ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
|
||||
before = GetTickCount();
|
||||
ok(evtmask == EV_TXEMPTY,
|
||||
"WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_TXEMPTY);
|
||||
trace("Write %ld ms WaitCommEvent EV_TXEMPTY %ld ms\n", diff, before- after);
|
||||
|
||||
read=0;
|
||||
todo_wine ok(ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL), "Readfile failed\n");
|
||||
todo_wine ok(read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d\n", read, sizeof(tbuf));
|
||||
ok(ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL), "Readfile failed\n");
|
||||
ok(read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d \"%s\"\n", read, sizeof(tbuf),rbuf);
|
||||
|
||||
/* Now do the same withe a slow Baud rate.
|
||||
On XP, nothing should change, as WriteFile only returns
|
||||
after all Bytes have gone to the physical line
|
||||
/* Now do the same withe a slower Baud rate.
|
||||
As we request more characters then written, we will hit the timeout
|
||||
*/
|
||||
|
||||
ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
|
||||
dcb.BaudRate = 9600;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fRtsControl=RTS_CONTROL_ENABLE;
|
||||
dcb.fDtrControl=DTR_CONTROL_ENABLE;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
|
||||
|
||||
@@ -846,20 +879,44 @@ static void test_LoopbackRead(HANDLE hcom)
|
||||
ok(written == sizeof(tbuf),"WriteFile %ld bytes written, expected %d\n",
|
||||
written, sizeof(tbuf));
|
||||
|
||||
todo_wine ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
|
||||
todo_wine ok(evtmask == EV_RXCHAR, "WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
|
||||
trace("WaitCommEventEV_RXCHAR\n");
|
||||
ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
|
||||
ok(evtmask == EV_RXCHAR, "WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_RXCHAR);
|
||||
|
||||
before = GetTickCount();
|
||||
res = ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL);
|
||||
after = GetTickCount();
|
||||
todo_wine ok(res, "Readfile failed\n");
|
||||
todo_wine ok(read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d\n", read, sizeof(tbuf));
|
||||
ok(res, "Readfile failed\n");
|
||||
ok(read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d\n", read, sizeof(tbuf));
|
||||
diff = after - before;
|
||||
trace("Readfile for %d chars with %d avail took %ld ms\n",
|
||||
sizeof(rbuf), sizeof(tbuf), diff);
|
||||
ok( (diff > TIMEOUT - TIMEDELTA) && (diff < TIMEOUT + TIMEDELTA),
|
||||
"Timedout Wait took %ld ms, expected around %d\n", diff, TIMEOUT);
|
||||
|
||||
/* now do a plain read with slow speed
|
||||
* This will result in several low level reads and a timeout to happen
|
||||
*/
|
||||
dcb.BaudRate = SLOWBAUD;
|
||||
ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
|
||||
ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
|
||||
before = GetTickCount();
|
||||
read = 0;
|
||||
read1 =0;
|
||||
i=0;
|
||||
do
|
||||
{
|
||||
res = ReadFile(hcom, rbuf+read, sizeof(rbuf-read), &read1, NULL);
|
||||
ok(res, "Readfile failed\n");
|
||||
read += read1;
|
||||
i++;
|
||||
}
|
||||
while ((read < sizeof(tbuf)) && (i <10));
|
||||
after = GetTickCount();
|
||||
ok( read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d\n", read, sizeof(tbuf));
|
||||
trace("Plain Read for %d char at %d baud took %ld ms\n", sizeof(tbuf), SLOWBAUD, after-before);
|
||||
|
||||
}
|
||||
|
||||
static void test_LoopbackCtsRts(HANDLE hcom)
|
||||
@@ -891,7 +948,7 @@ static void test_LoopbackCtsRts(HANDLE hcom)
|
||||
{
|
||||
ok(EscapeCommFunction(hcom, SETRTS), "EscapeCommFunction failed to set RTS\n");
|
||||
ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
|
||||
todo_wine ok ((ModemStat & MS_CTS_ON) == MS_CTS_ON,
|
||||
ok ((ModemStat & MS_CTS_ON) == MS_CTS_ON,
|
||||
"CTS didn't react: 0x%04lx, expected 0x%04lx\n",
|
||||
ModemStat, (defaultStat | MS_CTS_ON));
|
||||
ok(EscapeCommFunction(hcom, CLRRTS), "EscapeCommFunction failed to clear RTS\n");
|
||||
@@ -930,7 +987,7 @@ static void test_LoopbackDtrDcd(HANDLE hcom)
|
||||
{
|
||||
ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
|
||||
ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
|
||||
todo_wine ok ((ModemStat & MS_RLSD_ON) == MS_RLSD_ON,
|
||||
ok ((ModemStat & MS_RLSD_ON) == MS_RLSD_ON,
|
||||
"RLSD didn't react: 0x%04lx, expected 0x%04lx\n",
|
||||
ModemStat, (defaultStat | MS_RLSD_ON));
|
||||
ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
|
||||
@@ -962,14 +1019,14 @@ static void test_LoopbackDtrDsr(HANDLE hcom)
|
||||
ModemStat, (defaultStat & ~MS_DSR_ON));
|
||||
ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to clear DTR\n");
|
||||
ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
|
||||
todo_wine ok (ModemStat == defaultStat, "Failed to restore DSR: 0x%04lx, expected 0x%04lx\n",
|
||||
ok (ModemStat == defaultStat, "Failed to restore DSR: 0x%04lx, expected 0x%04lx\n",
|
||||
ModemStat, defaultStat);
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
|
||||
ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
|
||||
todo_wine ok ((ModemStat & MS_DSR_ON) == MS_DSR_ON,
|
||||
ok ((ModemStat & MS_DSR_ON) == MS_DSR_ON,
|
||||
"CTS didn't react: 0x%04lx,expected 0x%04lx\n",
|
||||
ModemStat, (defaultStat | MS_DSR_ON));
|
||||
ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
|
||||
@@ -1008,7 +1065,7 @@ static void test_LoopbackDtrRing(HANDLE hcom)
|
||||
{
|
||||
ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
|
||||
ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
|
||||
todo_wine ok ((ModemStat & MS_RING_ON) == MS_RING_ON,
|
||||
ok ((ModemStat & MS_RING_ON) == MS_RING_ON,
|
||||
"RING didn't react: 0x%04lx,expected 0x%04lx\n",
|
||||
ModemStat, (defaultStat | MS_RING_ON));
|
||||
ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
|
||||
@@ -1019,9 +1076,10 @@ static void test_LoopbackDtrRing(HANDLE hcom)
|
||||
}
|
||||
|
||||
/*
|
||||
Set up a WaitCommEvent for anything in the receive buffer,
|
||||
then write to TX to put a character
|
||||
into the RX buffer via the Loopback
|
||||
* Set up a WaitCommEvent for anything in the receive buffer,
|
||||
* then write to TX to put a character
|
||||
* into the RX buffer
|
||||
* Need Loopback TX->RX
|
||||
*/
|
||||
|
||||
static void test_WaitRx(HANDLE hcom)
|
||||
@@ -1044,11 +1102,11 @@ static void test_WaitRx(HANDLE hcom)
|
||||
overlapped_w.hEvent = hComWriteEvent;
|
||||
|
||||
before = GetTickCount();
|
||||
todo_wine {success_wait = WaitCommEvent(hcom, &evtmask, &overlapped);}
|
||||
{success_wait = WaitCommEvent(hcom, &evtmask, &overlapped);}
|
||||
err_wait = GetLastError();
|
||||
after = GetTickCount();
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success_wait, err_wait, evtmask);
|
||||
todo_wine ok(success_wait || err_wait == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
ok(success_wait || err_wait == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
trace("overlapped WriteCommEvent returned.\n");
|
||||
|
||||
success_write= WriteFile(hcom, "X", 1, &written, &overlapped_w);
|
||||
@@ -1083,7 +1141,7 @@ static void test_WaitRx(HANDLE hcom)
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
|
||||
success_wait, err_wait, evtmask, after-before, after1-before);
|
||||
|
||||
todo_wine ok(evtmask & EV_RXCHAR, "Detect EV_RXCHAR: 0x%08lx, expected 0x%08x\n",
|
||||
ok(evtmask & EV_RXCHAR, "Detect EV_RXCHAR: 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_RXCHAR);
|
||||
diff = after1 - before;
|
||||
ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
@@ -1115,6 +1173,10 @@ static DWORD CALLBACK toggle_ctlLine(LPVOID arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for a change in CTS
|
||||
* Needs Loopback from DTR to CTS
|
||||
*/
|
||||
static void test_WaitCts(HANDLE hcom)
|
||||
{
|
||||
DCB dcb;
|
||||
@@ -1125,6 +1187,9 @@ static void test_WaitCts(HANDLE hcom)
|
||||
DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
|
||||
|
||||
ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
|
||||
dcb.fRtsControl=RTS_CONTROL_ENABLE;
|
||||
dcb.fDtrControl=DTR_CONTROL_ENABLE;
|
||||
ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
|
||||
if (dcb.fDtrControl == RTS_CONTROL_DISABLE)
|
||||
{
|
||||
trace("RTS_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
|
||||
@@ -1145,7 +1210,8 @@ static void test_WaitCts(HANDLE hcom)
|
||||
ok(hComPortEvent != 0, "CreateEvent failed\n");
|
||||
args[3] = (DWORD) hComPortEvent;
|
||||
alarmThread = CreateThread(NULL, 0, toggle_ctlLine, (void *) &args, 0, &alarmThreadId);
|
||||
Sleep(100);
|
||||
/* Wait a minimum to let the thread start up */
|
||||
Sleep(10);
|
||||
trace("Thread created\n");
|
||||
ok(alarmThread !=0 , "CreateThread Failed\n");
|
||||
|
||||
@@ -1157,27 +1223,27 @@ static void test_WaitCts(HANDLE hcom)
|
||||
after = GetTickCount();
|
||||
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
|
||||
todo_wine ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
trace("overlapped WriteCommEvent returned.\n");
|
||||
if (!success && (err == ERROR_IO_PENDING))
|
||||
todo_wine ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
"wait hComPortEvent failed\n");
|
||||
ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
"WaitCts hComPortEvent failed\n");
|
||||
success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
|
||||
err = GetLastError();
|
||||
after1 = GetTickCount();
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
|
||||
success, err, evtmask, after-before, after1-before);
|
||||
|
||||
todo_wine ok(evtmask & EV_CTS, "Failed to detect EV_CTS: 0x%08lx, expected 0x%08x\n",
|
||||
ok(evtmask & EV_CTS, "Failed to detect EV_CTS: 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_CTS);
|
||||
ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
|
||||
if(defaultStat & MS_CTS_ON)
|
||||
todo_wine ok((evtmask & MS_CTS_ON) == 0,"CTS didn't change state!\n");
|
||||
ok((evtmask & MS_CTS_ON) == 0,"CTS didn't change state!\n");
|
||||
else
|
||||
todo_wine ok((evtmask & MS_CTS_ON), "CTS didn't change state!\n");
|
||||
ok((evtmask & MS_CTS_ON), "CTS didn't change state!\n");
|
||||
|
||||
diff = after1 - before;
|
||||
todo_wine ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
"Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
|
||||
|
||||
/*restore RTS Settings*/
|
||||
@@ -1187,6 +1253,88 @@ static void test_WaitCts(HANDLE hcom)
|
||||
args[1] = CLRRTS;
|
||||
}
|
||||
|
||||
/* Change the Comm Mask while a Wait is going on
|
||||
WaitCommevent should return with a EVTMASK set to zero
|
||||
*/
|
||||
static DWORD CALLBACK reset_CommMask(LPVOID arg)
|
||||
{
|
||||
DWORD *args = (DWORD *) arg;
|
||||
DWORD timeout = args[0];
|
||||
HANDLE hcom = (HANDLE) args[1];
|
||||
|
||||
trace(" Changing CommMask on the fly for handle %p after timeout %ld\n",
|
||||
hcom, timeout);
|
||||
Sleep(timeout);
|
||||
ok(SetCommMask(hcom, 0),"SetCommMask %p failed\n", hcom);
|
||||
trace("SetCommMask changed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set up a Wait for a change on CTS. We don't toggle any line, but we
|
||||
reset the CommMask and expect the wait to return with a mask of 0
|
||||
No special port connections needed
|
||||
*/
|
||||
static void test_AbortWaitCts(HANDLE hcom)
|
||||
{
|
||||
DCB dcb;
|
||||
OVERLAPPED overlapped;
|
||||
HANDLE hComPortEvent;
|
||||
HANDLE alarmThread;
|
||||
DWORD args[2];
|
||||
DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
|
||||
|
||||
ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
|
||||
if (dcb.fDtrControl == RTS_CONTROL_DISABLE)
|
||||
{
|
||||
trace("RTS_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
|
||||
return;
|
||||
}
|
||||
args[0]= TIMEOUT >>1;
|
||||
args[1]=(DWORD) hcom;
|
||||
|
||||
trace("test_AbortWaitCts timeout %ld handle 0x%08lx\n",args[0], args[1]);
|
||||
|
||||
ok(SetCommMask(hcom, EV_CTS), "SetCommMask failed\n");
|
||||
hComPortEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||||
ok(hComPortEvent != 0, "CreateEvent failed\n");
|
||||
alarmThread = CreateThread(NULL, 0, reset_CommMask, (void *) &args, 0, &alarmThreadId);
|
||||
/* Wait a minimum to let the thread start up */
|
||||
Sleep(10);
|
||||
trace("Thread created\n");
|
||||
ok(alarmThread !=0 , "CreateThread Failed\n");
|
||||
|
||||
ZeroMemory( &overlapped, sizeof(overlapped));
|
||||
overlapped.hEvent = hComPortEvent;
|
||||
before = GetTickCount();
|
||||
success = WaitCommEvent(hcom, &evtmask, &overlapped);
|
||||
err = GetLastError();
|
||||
after = GetTickCount();
|
||||
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
|
||||
ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
trace("overlapped WriteCommEvent returned.\n");
|
||||
if (!success && (err == ERROR_IO_PENDING))
|
||||
ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
"AbortWaitCts hComPortEvent failed\n");
|
||||
success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
|
||||
err = GetLastError();
|
||||
after1 = GetTickCount();
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
|
||||
success, err, evtmask, after-before, after1-before);
|
||||
|
||||
ok(evtmask == 0, "Incorect EventMask 0x%08lx returned on Wait aborted bu SetCommMask, expected 0x%08x\n",
|
||||
evtmask, 0);
|
||||
ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
|
||||
diff = after1 - before;
|
||||
ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
"Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for a change in DSR
|
||||
* Needs Loopback from DTR to DSR
|
||||
*/
|
||||
static void test_WaitDsr(HANDLE hcom)
|
||||
{
|
||||
DCB dcb;
|
||||
@@ -1226,10 +1374,10 @@ static void test_WaitDsr(HANDLE hcom)
|
||||
after = GetTickCount();
|
||||
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
|
||||
todo_wine ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
trace("overlapped WriteCommEvent returned.\n");
|
||||
if (!success && (err == ERROR_IO_PENDING))
|
||||
todo_wine ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
"wait hComPortEvent failed\n");
|
||||
success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
|
||||
err = GetLastError();
|
||||
@@ -1237,16 +1385,16 @@ static void test_WaitDsr(HANDLE hcom)
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
|
||||
success, err, evtmask, after-before, after1-before);
|
||||
|
||||
todo_wine ok(evtmask & EV_DSR, "Failed to detect EV_DSR: 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_CTS);
|
||||
ok(evtmask & EV_DSR, "Failed to detect EV_DSR: 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_DSR);
|
||||
ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
|
||||
if(defaultStat & MS_DSR_ON)
|
||||
todo_wine ok((evtmask & MS_DSR_ON) == 0,"DTR didn't change state!\n");
|
||||
ok((evtmask & MS_DSR_ON) == 0,"DTR didn't change state!\n");
|
||||
else
|
||||
todo_wine ok((evtmask & MS_DSR_ON), "DTR didn't change state!\n");
|
||||
ok((evtmask & MS_DSR_ON), "DTR didn't change state!\n");
|
||||
|
||||
diff = after1 - before;
|
||||
todo_wine ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
"Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
|
||||
|
||||
/*restore RTS Settings*/
|
||||
@@ -1256,6 +1404,10 @@ static void test_WaitDsr(HANDLE hcom)
|
||||
args[1] = CLRDTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for a Ring
|
||||
* Needs Loopback from DTR to RING
|
||||
*/
|
||||
static void test_WaitRing(HANDLE hcom)
|
||||
{
|
||||
DCB dcb;
|
||||
@@ -1295,10 +1447,10 @@ static void test_WaitRing(HANDLE hcom)
|
||||
after = GetTickCount();
|
||||
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
|
||||
todo_wine ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
trace("overlapped WriteCommEvent returned.\n");
|
||||
if (!success && (err == ERROR_IO_PENDING))
|
||||
todo_wine ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
"wait hComPortEvent failed\n");
|
||||
success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
|
||||
err = GetLastError();
|
||||
@@ -1306,16 +1458,16 @@ static void test_WaitRing(HANDLE hcom)
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
|
||||
success, err, evtmask, after-before, after1-before);
|
||||
|
||||
todo_wine ok(evtmask & EV_RING, "Failed to detect EV_RING: 0x%08lx, expected 0x%08x\n",
|
||||
ok(evtmask & EV_RING, "Failed to detect EV_RING: 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_CTS);
|
||||
ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
|
||||
if(defaultStat & MS_RING_ON)
|
||||
todo_wine ok((evtmask & MS_RING_ON) == 0,"DTR didn't change state!\n");
|
||||
ok((evtmask & MS_RING_ON) == 0,"DTR didn't change state!\n");
|
||||
else
|
||||
todo_wine ok((evtmask & MS_RING_ON), "DTR didn't change state!\n");
|
||||
ok((evtmask & MS_RING_ON), "DTR didn't change state!\n");
|
||||
|
||||
diff = after1 - before;
|
||||
todo_wine ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
"Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
|
||||
|
||||
/*restore RTS Settings*/
|
||||
@@ -1324,7 +1476,10 @@ static void test_WaitRing(HANDLE hcom)
|
||||
else
|
||||
args[1] = CLRDTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for a change in DCD
|
||||
* Needs Loopback from DTR to DCD
|
||||
*/
|
||||
static void test_WaitDcd(HANDLE hcom)
|
||||
{
|
||||
DCB dcb;
|
||||
@@ -1364,10 +1519,10 @@ static void test_WaitDcd(HANDLE hcom)
|
||||
after = GetTickCount();
|
||||
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
|
||||
todo_wine ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
trace("overlapped WriteCommEvent returned.\n");
|
||||
if (!success && (err == ERROR_IO_PENDING))
|
||||
todo_wine ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
"wait hComPortEvent failed\n");
|
||||
success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
|
||||
err = GetLastError();
|
||||
@@ -1375,16 +1530,16 @@ static void test_WaitDcd(HANDLE hcom)
|
||||
trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
|
||||
success, err, evtmask, after-before, after1-before);
|
||||
|
||||
todo_wine ok(evtmask & EV_RLSD, "Failed to detect EV_RLSD: 0x%08lx, expected 0x%08x\n",
|
||||
ok(evtmask & EV_RLSD, "Failed to detect EV_RLSD: 0x%08lx, expected 0x%08x\n",
|
||||
evtmask, EV_CTS);
|
||||
ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
|
||||
if(defaultStat & MS_RLSD_ON)
|
||||
todo_wine ok((evtmask & MS_RLSD_ON) == 0,"DTR didn't change state!\n");
|
||||
ok((evtmask & MS_RLSD_ON) == 0,"DTR didn't change state!\n");
|
||||
else
|
||||
todo_wine ok((evtmask & MS_RLSD_ON), "DTR didn't change state!\n");
|
||||
ok((evtmask & MS_RLSD_ON), "DTR didn't change state!\n");
|
||||
|
||||
diff = after1 - before;
|
||||
todo_wine ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
"Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
|
||||
|
||||
/*restore RTS Settings*/
|
||||
@@ -1394,19 +1549,48 @@ static void test_WaitDcd(HANDLE hcom)
|
||||
args[1] = CLRDTR;
|
||||
}
|
||||
|
||||
/*
|
||||
Set Break after timeout
|
||||
*/
|
||||
static DWORD CALLBACK set_CommBreak(LPVOID arg)
|
||||
{
|
||||
DWORD *args = (DWORD *) arg;
|
||||
DWORD timeout = args[0];
|
||||
HANDLE hcom = (HANDLE) args[1];
|
||||
|
||||
trace("SetCommBreak for handle %p after timeout %ld\n",
|
||||
hcom, timeout);
|
||||
Sleep(timeout);
|
||||
ok(SetCommBreak(hcom),"SetCommBreak %p failed\n", hcom);
|
||||
trace("SetCommBreak done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Set the Break status after the given timeout to the given state
|
||||
Wait for the Break condition (TX resp. RX active)
|
||||
Needs Loopback TX-RX
|
||||
*/
|
||||
static void test_WaitBreak(HANDLE hcom)
|
||||
{
|
||||
OVERLAPPED overlapped;
|
||||
HANDLE hComPortEvent;
|
||||
DWORD before, after, after1, diff, success, err, written, evtmask=0;
|
||||
HANDLE alarmThread;
|
||||
DWORD args[2];
|
||||
DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
|
||||
|
||||
ok(SetCommMask(hcom, EV_BREAK), "SetCommMask failed\n");
|
||||
hComPortEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||||
ok(hComPortEvent != 0, "CreateEvent failed\n");
|
||||
|
||||
trace("test_WaitBreak\n");
|
||||
args[0]= TIMEOUT >>1;
|
||||
args[1]=(DWORD) hcom;
|
||||
alarmThread = CreateThread(NULL, 0, set_CommBreak, (void *) &args, 0, &alarmThreadId);
|
||||
/* Wait a minimum to let the thread start up */
|
||||
Sleep(10);
|
||||
trace("Thread created\n");
|
||||
ok(alarmThread !=0 , "CreateThread Failed\n");
|
||||
|
||||
ZeroMemory( &overlapped, sizeof(overlapped));
|
||||
overlapped.hEvent = hComPortEvent;
|
||||
before = GetTickCount();
|
||||
@@ -1418,17 +1602,6 @@ static void test_WaitBreak(HANDLE hcom)
|
||||
ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
|
||||
trace("overlapped WriteCommEvent returned.\n");
|
||||
|
||||
Sleep(TIMEOUT >>1);
|
||||
|
||||
ok(SetCommBreak(hcom), "SetCommBreak err 0x%08lx\n", GetLastError());
|
||||
trace("Break set\n");
|
||||
ok(ClearCommError(hcom, &err, NULL),"ClearCommError err 0x%08lx\n", GetLastError());
|
||||
ok((err & CE_BREAK)!= 0, "Break condition should be reported\n");
|
||||
ok(ClearCommBreak(hcom), "ClearCommBreak err 0x%08lx\n", GetLastError());
|
||||
trace("Break cleared\n");
|
||||
ok(ClearCommError(hcom, &err, NULL),"ClearCommError err 0x%08lx\n", GetLastError());
|
||||
ok((err & CE_BREAK)== 0, "Break should be cleared now\n");
|
||||
|
||||
if (!success && (err == ERROR_IO_PENDING))
|
||||
ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
|
||||
"wait hComPortEvent res 0x%08lx\n", GetLastError());
|
||||
@@ -1446,20 +1619,19 @@ static void test_WaitBreak(HANDLE hcom)
|
||||
ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
|
||||
"Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
|
||||
|
||||
ok(ClearCommBreak(hcom), "ClearCommBreak failed\n");
|
||||
}
|
||||
|
||||
START_TEST(comm)
|
||||
{
|
||||
HANDLE hcom;
|
||||
/* use variabel and not #define to compile the code */
|
||||
/* use variables and not #define to compile the code */
|
||||
BOOL loopback_txd_rxd = LOOPBACK_TXD_RXD;
|
||||
BOOL loopback_rts_cts = LOOPBACK_CTS_RTS;
|
||||
BOOL loopback_dtr_dsr = LOOPBACK_DTR_DSR;
|
||||
BOOL loopback_dtr_ring = LOOPBACK_DTR_RING;
|
||||
BOOL loopback_dtr_dcd = LOOPBACK_DTR_DCD;
|
||||
BOOL broken_setbreak = BROKEN_SETBREAK;
|
||||
|
||||
#if 1
|
||||
test_BuildCommDCB();
|
||||
hcom = test_OpenComm(FALSE);
|
||||
if (hcom != INVALID_HANDLE_VALUE)
|
||||
@@ -1472,9 +1644,16 @@ START_TEST(comm)
|
||||
hcom = test_OpenComm(FALSE);
|
||||
if (hcom != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Sleep(200); /* Give the laster character of test_waittxempty to drop into the receiver */
|
||||
test_ClearCommErrors(hcom);
|
||||
CloseHandle(hcom);
|
||||
}
|
||||
hcom = test_OpenComm(FALSE);
|
||||
if (hcom != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
test_non_pending_errors(hcom);
|
||||
CloseHandle(hcom);
|
||||
}
|
||||
if((loopback_txd_rxd) && ((hcom = test_OpenComm(FALSE))!=INVALID_HANDLE_VALUE))
|
||||
{
|
||||
test_LoopbackRead(hcom);
|
||||
@@ -1500,18 +1679,21 @@ START_TEST(comm)
|
||||
test_LoopbackDtrDcd(hcom);
|
||||
CloseHandle(hcom);
|
||||
}
|
||||
#endif
|
||||
if((loopback_txd_rxd) && ((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE))
|
||||
{
|
||||
test_WaitRx(hcom);
|
||||
CloseHandle(hcom);
|
||||
}
|
||||
#if 1
|
||||
if((loopback_rts_cts) && ((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE))
|
||||
{
|
||||
test_WaitCts(hcom);
|
||||
CloseHandle(hcom);
|
||||
}
|
||||
if((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
test_AbortWaitCts(hcom);
|
||||
CloseHandle(hcom);
|
||||
}
|
||||
if((loopback_dtr_dsr) && ((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE))
|
||||
{
|
||||
test_WaitDsr(hcom);
|
||||
@@ -1527,10 +1709,9 @@ START_TEST(comm)
|
||||
test_WaitDcd(hcom);
|
||||
CloseHandle(hcom);
|
||||
}
|
||||
if(!broken_setbreak && (hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE)
|
||||
if(loopback_txd_rxd && (hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
test_WaitBreak(hcom);
|
||||
CloseHandle(hcom);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -537,10 +537,14 @@ static void testCtrlHandler(void)
|
||||
#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;
|
||||
ok(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0), "Couldn't send ctrl-c event\n");
|
||||
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");
|
||||
@@ -563,7 +567,7 @@ START_TEST(console)
|
||||
|
||||
/* first, we detach and open a fresh console to play with */
|
||||
FreeConsole();
|
||||
AllocConsole();
|
||||
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);
|
||||
|
||||
@@ -581,7 +585,6 @@ START_TEST(console)
|
||||
/* will test line scrolling at the bottom of the screen */
|
||||
/* testBottomScroll(); */
|
||||
/* will test all the scrolling operations */
|
||||
/* this one is disabled for now, Wine's result are way too bad */
|
||||
testScroll(hConOut, sbi.dwSize);
|
||||
/* will test sb creation / modification... */
|
||||
/* testScreenBuffer() */
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
|
||||
static DWORD (WINAPI *pGetDiskFreeSpaceExA)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
|
||||
|
||||
static void test_GetDriveTypeA(void)
|
||||
{
|
||||
char drive[] = "?:\\";
|
||||
@@ -114,10 +116,29 @@ static void test_GetDiskFreeSpaceA(void)
|
||||
"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;
|
||||
}
|
||||
@@ -177,6 +198,9 @@ static void test_GetDiskFreeSpaceW(void)
|
||||
|
||||
START_TEST(drive)
|
||||
{
|
||||
HANDLE hkernel32 = GetModuleHandleA("kernel32");
|
||||
pGetDiskFreeSpaceExA = (void *) GetProcAddress(hkernel32, "GetDiskFreeSpaceExA");
|
||||
|
||||
test_GetDriveTypeA();
|
||||
test_GetDriveTypeW();
|
||||
|
||||
|
||||
@@ -918,8 +918,8 @@ static void test_offset_in_overlapped_structure(void)
|
||||
ok(done == sizeof(buf), "expected number of bytes written %lu\n", done);
|
||||
|
||||
memset(&ov, 0, sizeof(ov));
|
||||
ov.Offset = PATTERN_OFFSET;
|
||||
ov.OffsetHigh = 0;
|
||||
S(U(ov)).Offset = PATTERN_OFFSET;
|
||||
S(U(ov)).OffsetHigh = 0;
|
||||
rc=WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
|
||||
/* Win 9x does not support the overlapped I/O on files */
|
||||
if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
|
||||
@@ -929,8 +929,8 @@ static void test_offset_in_overlapped_structure(void)
|
||||
ok(SetFilePointer(hFile, 0, NULL, FILE_CURRENT) == (PATTERN_OFFSET + sizeof(pattern)),
|
||||
"expected file offset %d\n", PATTERN_OFFSET + sizeof(pattern));
|
||||
|
||||
ov.Offset = sizeof(buf) * 2;
|
||||
ov.OffsetHigh = 0;
|
||||
S(U(ov)).Offset = sizeof(buf) * 2;
|
||||
S(U(ov)).OffsetHigh = 0;
|
||||
ret = WriteFile(hFile, pattern, sizeof(pattern), &done, &ov);
|
||||
ok( ret, "WriteFile error %ld\n", GetLastError());
|
||||
ok(done == sizeof(pattern), "expected number of bytes written %lu\n", done);
|
||||
@@ -948,8 +948,8 @@ static void test_offset_in_overlapped_structure(void)
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(&ov, 0, sizeof(ov));
|
||||
ov.Offset = PATTERN_OFFSET;
|
||||
ov.OffsetHigh = 0;
|
||||
S(U(ov)).Offset = PATTERN_OFFSET;
|
||||
S(U(ov)).OffsetHigh = 0;
|
||||
rc=ReadFile(hFile, buf, sizeof(pattern), &done, &ov);
|
||||
/* Win 9x does not support the overlapped I/O on files */
|
||||
if (rc || GetLastError()!=ERROR_INVALID_PARAMETER) {
|
||||
@@ -1007,8 +1007,8 @@ static void test_LockFile(void)
|
||||
ok( !UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 again succeeded\n" );
|
||||
ok( UnlockFile( handle, 5, 0, 5, 0 ), "UnlockFile 5,5 failed\n" );
|
||||
|
||||
overlapped.Offset = 100;
|
||||
overlapped.OffsetHigh = 0;
|
||||
S(U(overlapped)).Offset = 100;
|
||||
S(U(overlapped)).OffsetHigh = 0;
|
||||
overlapped.hEvent = 0;
|
||||
|
||||
lockfileex_capable = dll_capable("kernel32", "LockFileEx");
|
||||
@@ -1024,7 +1024,7 @@ static void test_LockFile(void)
|
||||
}
|
||||
|
||||
/* overlapping shared locks are OK */
|
||||
overlapped.Offset = 150;
|
||||
S(U(overlapped)).Offset = 150;
|
||||
limited_UnLockFile || ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), "LockFileEx 150,100 failed\n" );
|
||||
|
||||
/* but exclusive is not */
|
||||
@@ -1037,7 +1037,7 @@ static void test_LockFile(void)
|
||||
{
|
||||
if (!UnlockFileEx( handle, 0, 100, 0, &overlapped ))
|
||||
{ /* UnLockFile is capable. */
|
||||
overlapped.Offset = 100;
|
||||
S(U(overlapped)).Offset = 100;
|
||||
ok( !UnlockFileEx( handle, 0, 100, 0, &overlapped ),
|
||||
"UnlockFileEx 150,100 again succeeded\n" );
|
||||
}
|
||||
@@ -1081,15 +1081,23 @@ static inline int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD ac
|
||||
if (!access1 || !access2) return 1;
|
||||
if ((access1 & GENERIC_READ) && !(sharing2 & FILE_SHARE_READ)) return 0;
|
||||
if ((access1 & GENERIC_WRITE) && !(sharing2 & FILE_SHARE_WRITE)) return 0;
|
||||
if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return 0;
|
||||
if ((access2 & GENERIC_READ) && !(sharing1 & FILE_SHARE_READ)) return 0;
|
||||
if ((access2 & GENERIC_WRITE) && !(sharing1 & FILE_SHARE_WRITE)) return 0;
|
||||
if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void test_file_sharing(void)
|
||||
{
|
||||
static const DWORD access_modes[4] = { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE };
|
||||
static const DWORD sharing_modes[4] = { 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE };
|
||||
static const DWORD access_modes[] =
|
||||
{ 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE,
|
||||
DELETE, GENERIC_READ|DELETE, GENERIC_WRITE|DELETE, GENERIC_READ|GENERIC_WRITE|DELETE };
|
||||
static const DWORD sharing_modes[] =
|
||||
{ 0, FILE_SHARE_READ,
|
||||
FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_DELETE,
|
||||
FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE };
|
||||
int a1, s1, a2, s2;
|
||||
int ret;
|
||||
HANDLE h, h2;
|
||||
@@ -1103,9 +1111,9 @@ static void test_file_sharing(void)
|
||||
}
|
||||
CloseHandle( h );
|
||||
|
||||
for (a1 = 0; a1 < 4; a1++)
|
||||
for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++)
|
||||
{
|
||||
for (s1 = 0; s1 < 4; s1++)
|
||||
for (s1 = 0; s1 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s1++)
|
||||
{
|
||||
h = CreateFileA( filename, access_modes[a1], sharing_modes[s1],
|
||||
NULL, OPEN_EXISTING, 0, 0 );
|
||||
@@ -1114,9 +1122,9 @@ static void test_file_sharing(void)
|
||||
ok(0,"couldn't create file \"%s\" (err=%ld)\n",filename,GetLastError());
|
||||
return;
|
||||
}
|
||||
for (a2 = 0; a2 < 4; a2++)
|
||||
for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
|
||||
{
|
||||
for (s2 = 0; s2 < 4; s2++)
|
||||
for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
|
||||
@@ -1305,8 +1313,8 @@ static void test_async_file_errors(void)
|
||||
HANDLE hFile;
|
||||
LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, 4096);
|
||||
OVERLAPPED ovl;
|
||||
ovl.Offset = 0;
|
||||
ovl.OffsetHigh = 0;
|
||||
S(U(ovl)).Offset = 0;
|
||||
S(U(ovl)).OffsetHigh = 0;
|
||||
ovl.hEvent = hSem;
|
||||
completion_count = 0;
|
||||
szFile[0] = '\0';
|
||||
@@ -1323,7 +1331,7 @@ static void test_async_file_errors(void)
|
||||
/*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/
|
||||
if (!res)
|
||||
break;
|
||||
ovl.Offset += 4096;
|
||||
S(U(ovl)).Offset += 4096;
|
||||
/* i/o completion routine only called if ReadFileEx returned success.
|
||||
* we only care about violations of this rule so undo what should have
|
||||
* been done */
|
||||
@@ -1369,6 +1377,10 @@ static void test_read_write(void)
|
||||
bytes == 10, /* Win9x */
|
||||
"bytes = %ld\n", bytes);
|
||||
|
||||
/* make sure the file contains data */
|
||||
WriteFile(hFile, "this is the test data", 21, &bytes, NULL);
|
||||
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
||||
|
||||
SetLastError(12345678);
|
||||
bytes = 12345678;
|
||||
ret = ReadFile(hFile, NULL, 0, &bytes, NULL);
|
||||
@@ -1390,6 +1402,87 @@ static void test_read_write(void)
|
||||
ok( ret, "DeleteFileA: error %ld\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_OpenFile_exists(void)
|
||||
{
|
||||
HFILE hFile;
|
||||
OFSTRUCT ofs;
|
||||
|
||||
static const char *file = "\\winver.exe";
|
||||
char buff[MAX_PATH];
|
||||
UINT length;
|
||||
|
||||
length = GetSystemDirectoryA(buff, MAX_PATH);
|
||||
|
||||
if ((length + lstrlen(file) < MAX_PATH))
|
||||
{
|
||||
lstrcat(buff, file);
|
||||
|
||||
hFile = OpenFile(buff, &ofs, OF_EXIST);
|
||||
ok( hFile == TRUE, "%s not found : %ld\n", buff, GetLastError());
|
||||
}
|
||||
|
||||
hFile = OpenFile(".\\foo-bar-foo.baz", &ofs, OF_EXIST);
|
||||
ok( hFile == HFILE_ERROR, "hFile != HFILE_ERROR : %ld\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_overlapped(void)
|
||||
{
|
||||
OVERLAPPED ov;
|
||||
DWORD r, result;
|
||||
|
||||
/* GetOverlappedResult crashes if the 2nd or 3rd param are NULL */
|
||||
|
||||
memset( &ov, 0, sizeof ov );
|
||||
result = 1;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok( r == TRUE, "should return false\n");
|
||||
ok( result == 0, "result wrong\n");
|
||||
|
||||
result = 0;
|
||||
ov.Internal = 0;
|
||||
ov.InternalHigh = 0xabcd;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok( r == TRUE, "should return false\n");
|
||||
ok( result == 0xabcd, "result wrong\n");
|
||||
|
||||
SetLastError( 0xb00 );
|
||||
result = 0;
|
||||
ov.Internal = STATUS_INVALID_HANDLE;
|
||||
ov.InternalHigh = 0xabcd;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok (GetLastError() == ERROR_INVALID_HANDLE, "error wrong\n");
|
||||
ok( r == FALSE, "should return false\n");
|
||||
ok( result == 0xabcd, "result wrong\n");
|
||||
|
||||
result = 0;
|
||||
ov.Internal = STATUS_PENDING;
|
||||
ov.InternalHigh = 0xabcd;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
todo_wine {
|
||||
ok (GetLastError() == ERROR_IO_INCOMPLETE, "error wrong\n");
|
||||
}
|
||||
ok( r == FALSE, "should return false\n");
|
||||
ok( result == 0, "result wrong\n");
|
||||
|
||||
ov.hEvent = CreateEvent( NULL, 1, 1, NULL );
|
||||
ov.Internal = STATUS_PENDING;
|
||||
ov.InternalHigh = 0xabcd;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok (GetLastError() == ERROR_IO_INCOMPLETE, "error wrong\n");
|
||||
ok( r == FALSE, "should return false\n");
|
||||
|
||||
ResetEvent( ov.hEvent );
|
||||
|
||||
ov.Internal = STATUS_PENDING;
|
||||
ov.InternalHigh = 0;
|
||||
r = GetOverlappedResult(0, &ov, &result, 0);
|
||||
ok (GetLastError() == ERROR_IO_INCOMPLETE, "error wrong\n");
|
||||
ok( r == FALSE, "should return false\n");
|
||||
|
||||
r = CloseHandle( ov.hEvent );
|
||||
ok( r == TRUE, "close handle failed\n");
|
||||
}
|
||||
|
||||
START_TEST(file)
|
||||
{
|
||||
test__hread( );
|
||||
@@ -1418,4 +1511,6 @@ START_TEST(file)
|
||||
test_GetFileType();
|
||||
test_async_file_errors();
|
||||
test_read_write();
|
||||
test_OpenFile_exists();
|
||||
test_overlapped();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
#include "winbase.h"
|
||||
#include "wine/test.h"
|
||||
|
||||
static SIZE_T resize_9x(SIZE_T size)
|
||||
{
|
||||
DWORD dwSizeAligned = (size + 3) & ~3;
|
||||
return max(dwSizeAligned, 12); /* at least 12 bytes */
|
||||
}
|
||||
|
||||
START_TEST(heap)
|
||||
{
|
||||
void *mem;
|
||||
@@ -43,7 +49,8 @@ START_TEST(heap)
|
||||
SIZE_T heap_size;
|
||||
mem = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
heap_size = HeapSize(GetProcessHeap(), 0, mem);
|
||||
ok(size == heap_size, "HeapSize returned %lu instead of %lu\n", heap_size, size);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -56,11 +63,8 @@ START_TEST(heap)
|
||||
size = GlobalSize(gbl);
|
||||
ok(size >= 10 && size <= 16, "Memory not resized to size 10, instead size=%ld\n", size);
|
||||
|
||||
todo_wine
|
||||
{
|
||||
gbl = GlobalReAlloc(gbl, 0, GMEM_MOVEABLE);
|
||||
ok(gbl != NULL, "GlobalReAlloc should not fail on size 0\n");
|
||||
}
|
||||
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);
|
||||
@@ -80,11 +84,8 @@ START_TEST(heap)
|
||||
size = LocalSize(gbl);
|
||||
ok(size >= 10 && size <= 16, "Memory not resized to size 10, instead size=%ld\n", size);
|
||||
|
||||
todo_wine
|
||||
{
|
||||
gbl = LocalReAlloc(gbl, 0, LMEM_MOVEABLE);
|
||||
ok(gbl != NULL, "LocalReAlloc should not fail on size 0\n");
|
||||
}
|
||||
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);
|
||||
@@ -95,4 +96,12 @@ START_TEST(heap)
|
||||
gbl = LocalReAlloc(0, 10, LMEM_MOVEABLE);
|
||||
ok(gbl == NULL, "local realloc allocated memory\n");
|
||||
|
||||
/* trying to lock empty memory should give an error */
|
||||
gbl = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,0);
|
||||
ok(gbl != NULL, "returned NULL\n");
|
||||
SetLastError(0xdeadbeef);
|
||||
mem = GlobalLock(gbl);
|
||||
ok( GetLastError() == ERROR_DISCARDED, "should return an error\n");
|
||||
ok( mem == NULL, "should return NULL\n");
|
||||
GlobalFree(gbl);
|
||||
}
|
||||
|
||||
@@ -1795,7 +1795,8 @@ static void test_FoldStringW(void)
|
||||
|
||||
ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
|
||||
/* Wine (correctly) maps all Unicode 4.0+ digits */
|
||||
isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF,
|
||||
isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF ||
|
||||
(ch >= 0x1369 && ch <= 0x1371),
|
||||
"MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,18 +103,28 @@ static void testGetModuleFileName_Wrong(void)
|
||||
|
||||
static void testLoadLibraryA(void)
|
||||
{
|
||||
HMODULE hModule;
|
||||
HMODULE hModule, hModule1;
|
||||
FARPROC fp;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
hModule = LoadLibraryA("ntdll.dll");
|
||||
ok( hModule != NULL, "ntdll.dll should be loadable\n");
|
||||
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, "NtCreateFile");
|
||||
ok( fp != NULL, "Call should be there\n");
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -305,6 +305,7 @@ static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
|
||||
DWORD len,len1,drives;
|
||||
INT id;
|
||||
HANDLE hndl;
|
||||
BOOL bRes;
|
||||
|
||||
*curDrive = *otherDrive = NOT_A_VALID_DRIVE;
|
||||
|
||||
@@ -334,9 +335,18 @@ static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
|
||||
sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
|
||||
ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
|
||||
lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
|
||||
"GetTempPath returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
|
||||
"GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
|
||||
newdir,tmpstr,tmpstr1,id);
|
||||
|
||||
ok((id=GetTempFileNameA(tmppath,NULL,0,newdir)),"GetTempFileNameA failed\n");
|
||||
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);
|
||||
|
||||
|
||||
/* Find first valid drive letter that is neither newdir[0] nor curDrive */
|
||||
drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
|
||||
if( *curDrive != NOT_A_VALID_DRIVE)
|
||||
@@ -362,6 +372,14 @@ static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
|
||||
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);
|
||||
|
||||
@@ -91,8 +91,10 @@ static void test_CreateNamedPipe(int pipemode)
|
||||
/* 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\n");
|
||||
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) {
|
||||
@@ -757,7 +759,7 @@ static void test_CreatePipe(void)
|
||||
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 */
|
||||
todo_wine ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
|
||||
ok(ReadFile(piperead,readbuf,sizeof(readbuf),&read, NULL) == 0, "Broken pipe not detected\n");
|
||||
}
|
||||
|
||||
START_TEST(pipe)
|
||||
|
||||
@@ -415,7 +415,7 @@ static int strCmp(const char* s1, const char* s2, BOOL sensitive)
|
||||
ok(strCmp(result, expect, 0) == 0, "%s:%s expected '%s', got '%s'\n", sect, key, expect, result); \
|
||||
} while (0)
|
||||
|
||||
/* using !expect insures that the test will fail if the sect/key isn't present
|
||||
/* using !expect ensures that the test will fail if the sect/key isn't present
|
||||
* in result file
|
||||
*/
|
||||
#define okChildInt(sect, key, expect) \
|
||||
@@ -693,9 +693,10 @@ static void test_Startup(void)
|
||||
|
||||
static void test_CommandLine(void)
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
char buffer[MAX_PATH], fullpath[MAX_PATH], *lpFilePart, *p;
|
||||
PROCESS_INFORMATION info;
|
||||
STARTUPINFOA startup;
|
||||
DWORD len;
|
||||
|
||||
memset(&startup, 0, sizeof(startup));
|
||||
startup.cb = sizeof(startup);
|
||||
@@ -740,6 +741,49 @@ static void test_CommandLine(void)
|
||||
okChildString("Arguments", "CommandLineA", buffer);
|
||||
release_memory();
|
||||
assert(DeleteFileA(resfile) != 0);
|
||||
|
||||
/* Test for Bug1330 to show that XP doesn't change '/' to '\\' in argv[0]*/
|
||||
get_file_name(resfile);
|
||||
sprintf(buffer, "./%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
/* child process has changed result file, so let profile functions know about it */
|
||||
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
|
||||
sprintf(buffer, "./%s", selfname);
|
||||
okChildString("Arguments", "argvA0", buffer);
|
||||
release_memory();
|
||||
assert(DeleteFileA(resfile) != 0);
|
||||
|
||||
get_file_name(resfile);
|
||||
sprintf(buffer, ".\\%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
/* child process has changed result file, so let profile functions know about it */
|
||||
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
|
||||
sprintf(buffer, ".\\%s", selfname);
|
||||
okChildString("Arguments", "argvA0", buffer);
|
||||
release_memory();
|
||||
assert(DeleteFileA(resfile) != 0);
|
||||
|
||||
get_file_name(resfile);
|
||||
len = GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
|
||||
assert ( lpFilePart != 0);
|
||||
*(lpFilePart -1 ) = 0;
|
||||
p = strrchr(fullpath, '\\');
|
||||
assert (p);
|
||||
sprintf(buffer, "..%s/%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", p, selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
/* child process has changed result file, so let profile functions know about it */
|
||||
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
|
||||
sprintf(buffer, "..%s/%s", p, selfname);
|
||||
okChildString("Arguments", "argvA0", buffer);
|
||||
release_memory();
|
||||
assert(DeleteFileA(resfile) != 0);
|
||||
|
||||
}
|
||||
|
||||
static void test_Directory(void)
|
||||
|
||||
@@ -106,21 +106,22 @@ static void test_profile_string(void)
|
||||
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( !strcmp( buf, "name1,name2,name4"), "wrong keys returned: %s\n",
|
||||
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( !strcmp( buf, "name1=val1,name2=,name3,name4=val4"), "wrong section returned: %s\n",
|
||||
buf);
|
||||
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);
|
||||
@@ -128,8 +129,9 @@ static void test_profile_string(void)
|
||||
TESTFILE2);
|
||||
for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
|
||||
p[-1] = ',';
|
||||
ok( !strcmp( buf, "name1,name2,name4,name5"), "wrong keys returned: %s\n",
|
||||
buf);
|
||||
ok( ret == 24 && !strcmp( buf, "name1,name2,name4,name5"), "wrong keys returned(%d): %s\n",
|
||||
ret, buf);
|
||||
|
||||
DeleteFileA( TESTFILE2);
|
||||
}
|
||||
|
||||
|
||||
@@ -109,9 +109,7 @@ static void test_signalandwait(void)
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
||||
r = pSignalObjectAndWait(file, file, 0, FALSE);
|
||||
ok( r == WAIT_FAILED, "should fail\n");
|
||||
todo_wine {
|
||||
ok( ERROR_INVALID_HANDLE == GetLastError(), "should return invalid handle error\n");
|
||||
}
|
||||
CloseHandle(file);
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ typedef struct {
|
||||
} t1Struct;
|
||||
|
||||
/* WinME supports OpenThread but doesn't know about access restrictions so
|
||||
we require them to be either completly ignored or always obeyed.
|
||||
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) \
|
||||
@@ -96,7 +96,7 @@ INT obeying_ars = 0; /* -1 == no, 0 == dunno yet, 1 == yes */
|
||||
? ok(!(x), "access restrictions obeyed\n") \
|
||||
: ok( (x), "access restrictions not obeyed\n"))
|
||||
|
||||
/* Basic test that simulatneous threads can access shared memory,
|
||||
/* Basic test that simultaneous threads can access shared memory,
|
||||
that the thread local storage routines work correctly, and that
|
||||
threads actually run concurrently
|
||||
*/
|
||||
@@ -119,7 +119,11 @@ static DWORD WINAPI threadFunc1(LPVOID p)
|
||||
for(i=0;i<NUM_THREADS;i++) {
|
||||
while(tstruct->threadmem[i]==0) ;
|
||||
}
|
||||
/* Check that noone cahnged our tls memory */
|
||||
|
||||
/* 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;
|
||||
@@ -178,6 +182,11 @@ static VOID test_CreateThread_basic(void)
|
||||
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 */
|
||||
@@ -228,6 +237,23 @@ static VOID test_CreateThread_basic(void)
|
||||
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 */
|
||||
@@ -323,7 +349,7 @@ static VOID test_TerminateThread(void)
|
||||
thread = CreateThread(NULL,0,threadFunc4,
|
||||
(LPVOID)event, 0,&threadId);
|
||||
ok(thread!=NULL,"Create Thread failed\n");
|
||||
/* Terminate thread has a race condition in Wine. If the thread is terminated
|
||||
/* 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.
|
||||
@@ -425,10 +451,10 @@ static VOID test_thread_priority(void)
|
||||
"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,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 */
|
||||
@@ -567,14 +593,99 @@ static VOID test_thread_processor(void)
|
||||
}
|
||||
}
|
||||
|
||||
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__ */
|
||||
|
||||
|
||||
START_TEST(thread)
|
||||
{
|
||||
HINSTANCE lib;
|
||||
/* Neither Cygwin nor mingW export OpenThread, so do a dynamic check
|
||||
so that the compile passes
|
||||
*/
|
||||
lib=LoadLibraryA("kernel32");
|
||||
ok(lib!=NULL,"Couldn't load kernel32.dll\n");
|
||||
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");
|
||||
pSetThreadIdealProcessor=(SetThreadIdealProcessor_t)GetProcAddress(lib,"SetThreadIdealProcessor");
|
||||
@@ -587,4 +698,8 @@ START_TEST(thread)
|
||||
test_thread_priority();
|
||||
test_GetThreadTimes();
|
||||
test_thread_processor();
|
||||
test_GetThreadExitCode();
|
||||
#ifdef __i386__
|
||||
test_SetThreadContext();
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user