From: Paul Gofman pgofman@codeweavers.com
--- dlls/kernel32/tests/file.c | 189 +++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 83766dfaaa2..e4ec612d487 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -38,6 +38,7 @@ #include "ddk/ntifs.h"
static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD); +static BOOL (WINAPI *pGetOverlappedResultEx)(HANDLE, OVERLAPPED *, DWORD *, DWORD, BOOL); static BOOL (WINAPI *pReplaceFileW)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, LPVOID, LPVOID); static UINT (WINAPI *pGetSystemWindowsDirectoryA)(LPSTR, UINT); static BOOL (WINAPI *pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD); @@ -93,6 +94,7 @@ static void InitFunctionPointers(void) pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
pFindFirstFileExA=(void*)GetProcAddress(hkernel32, "FindFirstFileExA"); + pGetOverlappedResultEx =(void*)GetProcAddress(hkernel32, "GetOverlappedResultEx"); pReplaceFileW=(void*)GetProcAddress(hkernel32, "ReplaceFileW"); pGetSystemWindowsDirectoryA=(void*)GetProcAddress(hkernel32, "GetSystemWindowsDirectoryA"); pGetVolumeNameForVolumeMountPointA = (void *) GetProcAddress(hkernel32, "GetVolumeNameForVolumeMountPointA"); @@ -3739,6 +3741,7 @@ static void test_overlapped(void) { OVERLAPPED ov; DWORD r, result; + HANDLE event;
/* GetOverlappedResult crashes if the 2nd or 3rd param are NULL */ if (0) /* tested: WinXP */ @@ -3810,6 +3813,192 @@ static void test_overlapped(void)
r = CloseHandle( ov.hEvent ); ok( r == TRUE, "close handle failed\n"); + + if (!pGetOverlappedResultEx) + { + win_skip( "GetOverlappedResultEx is not available, skipping tests.\n" ); + return; + } + + event = CreateEventW(NULL, FALSE, FALSE, NULL); + + result = 0xdeadbeef; + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + r = pGetOverlappedResultEx(event, &ov, &result, 1, FALSE); + ok(!r && GetLastError() == WAIT_TIMEOUT, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + r = GetOverlappedResult(event, &ov, &result, FALSE); + ok(!r && GetLastError() == ERROR_IO_INCOMPLETE, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + SetLastError( 0xdeadbeef ); + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + QueueUserAPC( user_apc, GetCurrentThread(), 0 ); + r = GetOverlappedResult(event, &ov, &result, FALSE); + ok(!r && GetLastError() == ERROR_IO_INCOMPLETE, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + SetEvent(event); + QueueUserAPC( user_apc, GetCurrentThread(), 0 ); + r = GetOverlappedResult(event, &ov, &result, TRUE); + ok(r, "got %lu, error %lu.\n", r, GetLastError()); + r = WaitForSingleObject(event, 0); + ok(r == WAIT_TIMEOUT, "got %#lx.\n", r); + ok( result == 0xabcd, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + SetLastError( 0xdeadbeef ); + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + r = pGetOverlappedResultEx(event, &ov, &result, 0, FALSE); + ok(!r && GetLastError() == ERROR_IO_INCOMPLETE, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + SetLastError( 0xdeadbeef ); + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + SetEvent(event); + r = pGetOverlappedResultEx(event, &ov, &result, 0, FALSE); + ok(!r && GetLastError() == ERROR_IO_INCOMPLETE, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + r = WaitForSingleObject(event, 0); + ok(r == WAIT_OBJECT_0, "got %#lx.\n", r); + + result = 0xdeadbeef; + SetLastError( 0xdeadbeef ); + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + r = pGetOverlappedResultEx(event, &ov, &result, 1, FALSE); + ok(!r && GetLastError() == WAIT_TIMEOUT, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + SetLastError( 0xdeadbeef ); + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = (HANDLE)0xdeadbeef; + r = pGetOverlappedResultEx(event, &ov, &result, 1, FALSE); + ok(!r && GetLastError() == ERROR_INVALID_HANDLE, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + SetLastError( 0xdeadbeef ); + ov.Internal = STATUS_PENDING; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + SetEvent(event); + r = pGetOverlappedResultEx(event, &ov, &result, 1, FALSE); + ok(ov.Internal == STATUS_PENDING, "got %#Ix.\n", ov.Internal); + ok(r, "got %lu, error %lu.\n", r, GetLastError()); + todo_wine ok(GetLastError() == ERROR_IO_PENDING, "got %lu.\n", GetLastError()); + ok( result == 0xabcd, "wrong result %lu\n", result ); + r = WaitForSingleObject(event, 0); + ok(r == WAIT_TIMEOUT, "got %#lx.\n", r); + + /* Test event wait if status is not STATUS_PENDING. */ + + /* With GetOverlapped result wait is skipped. */ + result = 0xdeadbeef; + ov.Internal = STATUS_SUCCESS; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + r = GetOverlappedResult(event, &ov, &result, TRUE); + ok(r, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xabcd, "wrong result %lu\n", result ); + + /* Unlike GetOverlappedResult, GetOverlappedResultEx always waits for event unless timeout is 0 even if + * ov.Internal is not STATUS_PENDING. */ + result = 0xdeadbeef; + ov.Internal = STATUS_SUCCESS; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + QueueUserAPC( user_apc, GetCurrentThread(), 0 ); + r = pGetOverlappedResultEx(event, &ov, &result, INFINITE, TRUE); + todo_wine ok(!r && GetLastError() == WAIT_IO_COMPLETION, "got %lu, error %lu.\n", r, GetLastError()); + + SetLastError(0xdeadbeef); + result = 0xdeadbeef; + ov.Internal = STATUS_SUCCESS; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + r = pGetOverlappedResultEx(event, &ov, &result, 0, 0); + todo_wine ok(GetLastError() == ERROR_SUCCESS, "got %lu.\n", GetLastError()); + ok(r, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xabcd, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + ov.Internal = STATUS_SUCCESS; + ov.InternalHigh = 0xabcd; + ov.hEvent = event; + r = pGetOverlappedResultEx(event, &ov, &result, 1, 0); + todo_wine ok(!r && GetLastError() == WAIT_TIMEOUT, "got %lu, error %lu.\n", r, GetLastError()); + todo_wine ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + ov.Internal = STATUS_SUCCESS; + ov.InternalHigh = 0xabcd; + ov.hEvent = NULL; + QueueUserAPC( user_apc, GetCurrentThread(), 0 ); + r = pGetOverlappedResultEx(event, &ov, &result, INFINITE, TRUE); + todo_wine ok(!r && GetLastError() == WAIT_IO_COMPLETION, "got %lu, error %lu.\n", r, GetLastError()); + todo_wine ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + SetLastError(0xdeadbeef); + result = 0xdeadbeef; + ov.Internal = STATUS_SUCCESS; + ov.InternalHigh = 0xabcd; + ov.hEvent = NULL; + r = pGetOverlappedResultEx(event, &ov, &result, 0, 0); + todo_wine ok(GetLastError() == ERROR_SUCCESS, "got %lu.\n", GetLastError()); + ok(r, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xabcd, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + ov.Internal = STATUS_SUCCESS; + ov.InternalHigh = 0xabcd; + ov.hEvent = NULL; + r = pGetOverlappedResultEx(event, &ov, &result, 1, 0); + todo_wine ok(!r && GetLastError() == WAIT_TIMEOUT, "got %lu, error %lu.\n", r, GetLastError()); + todo_wine ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + ov.Internal = STATUS_UNEXPECTED_IO_ERROR; + ov.InternalHigh = 0xabcd; + ov.hEvent = NULL; + r = pGetOverlappedResultEx(event, &ov, &result, 1, 0); + todo_wine ok(!r && GetLastError() == WAIT_TIMEOUT, "got %lu, error %lu.\n", r, GetLastError()); + todo_wine ok( result == 0xdeadbeef, "wrong result %lu\n", result ); + + result = 0xdeadbeef; + ov.Internal = STATUS_UNEXPECTED_IO_ERROR; + ov.InternalHigh = 0xabcd; + ov.hEvent = NULL; + SetEvent(event); + r = pGetOverlappedResultEx(event, &ov, &result, 1, 0); + ok(!r && GetLastError() == ERROR_IO_DEVICE, "got %lu, error %lu.\n", r, GetLastError()); + ok( result == 0xabcd, "wrong result %lu\n", result ); + r = WaitForSingleObject(event, 0); + todo_wine ok(r == WAIT_TIMEOUT, "got %#lx.\n", r); + + CloseHandle(event); }
static void test_RemoveDirectory(void)