Fix the behavior of GetOverlappedResult() and WSAGetOverlappedResult()

with non-manual-reset (auto-reset) events in the OVERLAPPED structures.
This commit is contained in:
Martin Wilck 2002-09-12 17:56:30 +00:00 committed by Alexandre Julliard
parent 3e2887a929
commit 2b54cf91fc
2 changed files with 58 additions and 18 deletions

View file

@ -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;
}
}

View file

@ -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;
}
}
/***********************************************************************