Commit 2b54cf91 authored by Martin Wilck's avatar Martin Wilck Committed by Alexandre Julliard

Fix the behavior of GetOverlappedResult() and WSAGetOverlappedResult()

with non-manual-reset (auto-reset) events in the OVERLAPPED structures.
parent 3e2887a9
......@@ -3266,9 +3266,19 @@ 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;
......@@ -3276,12 +3286,18 @@ BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
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 ) );
case STATUS_PENDING:
WSASetLastError ( WSA_IO_INCOMPLETE );
if (fWait) ERR ("PENDING status after waiting!\n");
return FALSE;
default:
WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
return FALSE;
}
}
......
......@@ -1554,19 +1554,43 @@ BOOL WINAPI GetOverlappedResult(
return FALSE;
}
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, bWait?INFINITE:0, TRUE);
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;
}
}
/***********************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment