Fix the behavior of GetOverlappedResult() and WSAGetOverlappedResult()
with non-manual-reset (auto-reset) events in the OVERLAPPED structures.
This commit is contained in:
parent
3e2887a929
commit
2b54cf91fc
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
42
files/file.c
42
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;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in New Issue