From 2b54cf91fcbf6f956e90b987e19c5ff66565b547 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 12 Sep 2002 17:56:30 +0000 Subject: [PATCH] Fix the behavior of GetOverlappedResult() and WSAGetOverlappedResult() with non-manual-reset (auto-reset) events in the OVERLAPPED structures. --- dlls/winsock/socket.c | 34 +++++++++++++++++++++++++--------- files/file.c | 42 +++++++++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/dlls/winsock/socket.c b/dlls/winsock/socket.c index 81e8d002324..12f38a99166 100644 --- a/dlls/winsock/socket.c +++ b/dlls/winsock/socket.c @@ -3266,22 +3266,38 @@ BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped, return FALSE; } - do { - r = WaitForSingleObjectEx (lpOverlapped->hEvent, fWait ? INFINITE : 0, TRUE); - } while (r == STATUS_USER_APC); - + if ( fWait ) + { + while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC ); + } + 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. */ + while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC ); + if ( r == WAIT_OBJECT_0 ) + NtSetEvent ( lpOverlapped->hEvent, NULL ); + } + if ( lpcbTransfer ) *lpcbTransfer = lpOverlapped->InternalHigh; if ( lpdwFlags ) *lpdwFlags = lpOverlapped->Offset; - if ( r == WAIT_OBJECT_0 ) + switch ( lpOverlapped->Internal ) + { + case STATUS_SUCCESS: return TRUE; - - WSASetLastError ( lpOverlapped->Internal == STATUS_PENDING ? - WSA_IO_INCOMPLETE : NtStatusToWSAError ( lpOverlapped->Internal ) ); - return FALSE; + case STATUS_PENDING: + WSASetLastError ( WSA_IO_INCOMPLETE ); + if (fWait) ERR ("PENDING status after waiting!\n"); + return FALSE; + default: + WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal )); + return FALSE; + } } diff --git a/files/file.c b/files/file.c index 831a7c4e684..9cf09962b86 100644 --- a/files/file.c +++ b/files/file.c @@ -1554,19 +1554,43 @@ BOOL WINAPI GetOverlappedResult( return FALSE; } - do { - TRACE("waiting on %p\n",lpOverlapped); - r = WaitForSingleObjectEx(lpOverlapped->hEvent, bWait?INFINITE:0, TRUE); - TRACE("wait on %p returned %ld\n",lpOverlapped,r); - } while (r==STATUS_USER_APC); + if ( bWait ) + { + do { + TRACE("waiting on %p\n",lpOverlapped); + r = WaitForSingleObjectEx(lpOverlapped->hEvent, INFINITE, TRUE); + TRACE("wait on %p returned %ld\n",lpOverlapped,r); + } while (r==STATUS_USER_APC); + } + 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, INFINITE, TRUE); + TRACE("wait on %p returned %ld\n",lpOverlapped,r); + } while (r==STATUS_USER_APC); + if ( r == WAIT_OBJECT_0 ) + NtSetEvent ( lpOverlapped->hEvent, NULL ); + } if(lpTransferred) *lpTransferred = lpOverlapped->InternalHigh; - SetLastError ( lpOverlapped->Internal == STATUS_PENDING ? - ERROR_IO_INCOMPLETE : RtlNtStatusToDosError ( lpOverlapped->Internal ) ); - - return (r==WAIT_OBJECT_0); + 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; + } } /***********************************************************************