From 35ef5df76cf9d282f3df36eec24b3876039650a3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 4 Jun 2007 23:03:15 +0200 Subject: [PATCH] kernel32: Rewrite GetOverlappedResult for the new async I/O behavior. --- dlls/kernel32/file.c | 67 +++++++++----------------------------- dlls/kernel32/tests/file.c | 2 -- 2 files changed, 15 insertions(+), 54 deletions(-) diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c index be8ca638acd..a3d6942a087 100644 --- a/dlls/kernel32/file.c +++ b/dlls/kernel32/file.c @@ -539,17 +539,11 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, * * If successful (and relevant) lpTransferred will hold the number of * bytes transferred during the async operation. - * - * BUGS - * - * Currently only works for WaitCommEvent, ReadFile, WriteFile - * with communications ports. - * */ BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpTransferred, BOOL bWait) { - DWORD r = WAIT_OBJECT_0; + NTSTATUS status; TRACE( "(%p %p %p %x)\n", hFile, lpOverlapped, lpTransferred, bWait ); @@ -558,57 +552,26 @@ BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, ERR("lpOverlapped was null\n"); return FALSE; } - if ( bWait ) + + status = lpOverlapped->Internal; + if (status == STATUS_PENDING) { - if ( lpOverlapped->hEvent ) + if (!bWait) { - do - { - TRACE( "waiting on %p\n", lpOverlapped ); - r = WaitForSingleObjectEx( lpOverlapped->hEvent, INFINITE, TRUE ); - TRACE( "wait on %p returned %d\n", lpOverlapped, r ); - } while ( r == WAIT_IO_COMPLETION ); - } - else - { - /* busy loop */ - while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING ) - Sleep( 10 ); + SetLastError( ERROR_IO_INCOMPLETE ); + return FALSE; } + + if (WaitForSingleObject( lpOverlapped->hEvent ? lpOverlapped->hEvent : hFile, + INFINITE ) == WAIT_FAILED) + return FALSE; + status = lpOverlapped->Internal; } - else if ( lpOverlapped->Internal == STATUS_PENDING ) - { - /* Wait in order to give APCs a chance to run. */ - /* This is cheating, so we must set the event again in case of success - - it may be a non-manual reset event. */ - do - { - TRACE( "waiting on %p\n", lpOverlapped ); - r = WaitForSingleObjectEx( lpOverlapped->hEvent, 0, TRUE ); - TRACE( "wait on %p returned %d\n", lpOverlapped, r ); - } while ( r == WAIT_IO_COMPLETION ); - if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent ) - NtSetEvent( lpOverlapped->hEvent, NULL ); - } - if ( r == WAIT_FAILED ) - { - WARN("wait operation failed\n"); - return FALSE; - } + if (lpTransferred) *lpTransferred = lpOverlapped->InternalHigh; - switch ( lpOverlapped->Internal ) - { - case STATUS_SUCCESS: - return TRUE; - case STATUS_PENDING: - SetLastError( ERROR_IO_INCOMPLETE ); - if ( bWait ) ERR("PENDING status after waiting!\n"); - return FALSE; - default: - SetLastError( RtlNtStatusToDosError( lpOverlapped->Internal ) ); - return FALSE; - } + if (status) SetLastError( RtlNtStatusToDosError(status) ); + return !status; } /*********************************************************************** diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index 89cf0a2f196..e9f97f5a6f4 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -1768,9 +1768,7 @@ static void test_overlapped(void) ov.Internal = STATUS_PENDING; ov.InternalHigh = 0xabcd; r = GetOverlappedResult(0, &ov, &result, 0); - todo_wine { ok( GetLastError() == ERROR_IO_INCOMPLETE, "wrong error %u\n", GetLastError() ); - } ok( r == FALSE, "should return false\n"); ok( result == 0, "wrong result %u\n", result );