Fix APC problems. Thanks to Arty for finding this. This makes vncviewer work
Modified: trunk/reactos/ntoskrnl/ke/wait.c

Modified: trunk/reactos/ntoskrnl/ke/wait.c
--- trunk/reactos/ntoskrnl/ke/wait.c	2005-02-10 03:58:03 UTC (rev 13483)
+++ trunk/reactos/ntoskrnl/ke/wait.c	2005-02-10 05:13:43 UTC (rev 13484)
@@ -1,4 +1,4 @@
-/* $Id:$
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS project
@@ -489,6 +489,7 @@
    NTSTATUS Status;
    KIRQL OldIrql;
    BOOLEAN Abandoned;
+   NTSTATUS WaitStatus;
 
    DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
           "PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread());
@@ -540,40 +541,32 @@
          OldIrql = KeAcquireDispatcherDatabaseLock ();
       }
 
-      /* Alertability 101 
-       * ----------------
-       * A Wait can either be Alertable, or Non-Alertable.
-       * An Alertable Wait means that APCs can "Wake" the Thread, also called UnWaiting
-       * If an APC is Pending however, we must refuse an Alertable Wait. Such a wait would
-       * be pointless since an APC is just about to be delivered.
-       *
-       * There are many ways to check if it's safe to be alertable, and these are the ones
-       * that I could think of:
-       *         - The Thread is already Alerted. So someone beat us to the punch and we bail out.
-       *         - The Thread is Waiting in User-Mode, the APC Queue is not-empty.
-       *           It's defintely clear that we have incoming APCs, so we need to bail out and let the system
-       *           know that there are Pending User APCs (so they can be Delivered and maybe we can try again)
-       *
-       * Furthermore, wether or not we want to be Alertable, if the Thread is waiting in User-Mode, and there
-       * are Pending User APCs, we should bail out, since APCs will be delivered any second.
-       */
-	if (Alertable) {
-		if (CurrentThread->Alerted[(int)WaitMode]) {
-			CurrentThread->Alerted[(int)WaitMode] = FALSE;
-			DPRINT("Alertability failed\n");
-        		KeReleaseDispatcherDatabaseLock(OldIrql);
-			return (STATUS_ALERTED);
-		} else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && (WaitMode == UserMode)) {
-			DPRINT1("Alertability failed\n");
-			CurrentThread->ApcState.UserApcPending = TRUE;
-        		KeReleaseDispatcherDatabaseLock(OldIrql);
-        		return (STATUS_USER_APC);
-		}
-	} else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode != KernelMode)) {
-		DPRINT1("Alertability failed\n");
-        	KeReleaseDispatcherDatabaseLock(OldIrql);
-        	return (STATUS_USER_APC);
-	}
+    /* Get the current Wait Status */
+    WaitStatus = CurrentThread->WaitStatus;
+   
+    if (Alertable) {
+    
+        /* If the Thread is Alerted, set the Wait Status accordingly */    
+        if (CurrentThread->Alerted[(int)WaitMode]) {
+            
+            CurrentThread->Alerted[(int)WaitMode] = FALSE;
+            DPRINT("Thread was Alerted\n");
+            WaitStatus = STATUS_ALERTED;
+            
+        /* If there are User APCs Pending, then we can't really be alertable */
+        } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) && 
+                   (WaitMode == UserMode)) {
+            
+            DPRINT1("APCs are Pending\n");
+            CurrentThread->ApcState.UserApcPending = TRUE;
+            WaitStatus = STATUS_USER_APC;
+        }
+        
+    /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */
+    } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode == UserMode)) {
+            DPRINT1("APCs are Pending\n");
+            WaitStatus = STATUS_USER_APC;
+    }
 
       /*
        * Check if the wait is (already) satisfied
@@ -659,7 +652,7 @@
       /*
        * Set up the wait
        */
-      CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
+      CurrentThread->WaitStatus = WaitStatus;;
 
       for (i = 0; i < Count; i++)
       {