Fix the behavior of GetOverlappedResult() and WSAGetOverlappedResult()
with non-manual-reset (auto-reset) events in the OVERLAPPED structures.

diff --git a/dlls/winsock/socket.c b/dlls/winsock/socket.c
index 81e8d00..12f38a9 100644
--- a/dlls/winsock/socket.c
+++ b/dlls/winsock/socket.c
@@ -3266,22 +3266,38 @@
         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 831a7c4..9cf0996 100644
--- a/files/file.c
+++ b/files/file.c
@@ -1554,19 +1554,43 @@
         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;
+    }
 }
 
 /***********************************************************************