Handle non-hardware X events correctly with native USER
(removed reference to MESSAGEQUEUE from KERNEL code).
Handle Expose events with native USER.

diff --git a/loader/task.c b/loader/task.c
index 6310e88..c0acb3c 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -653,11 +653,12 @@
  *   
  *       It must not call functions that may yield control.
  */
-void TASK_Reschedule(void)
+BOOL32 TASK_Reschedule(void)
 {
     TDB *pOldTask = NULL, *pNewTask;
     HTASK16 hTask = 0;
     STACK16FRAME *newframe16;
+    BOOL32 pending = FALSE;
 
     /* Get the initial task up and running */
     if (!hCurrentTask && GetCurrentTask())
@@ -683,7 +684,7 @@
         hCurrentTask = GetCurrentTask();
         pNewTask = (TDB *)GlobalLock16( hCurrentTask );
         pNewTask->ss_sp = pNewTask->thdb->cur_stack;
-        return;
+        return FALSE;
     }
 
     /* NOTE: As we are entered from 16-bit code, we hold the Win16Lock.
@@ -720,7 +721,7 @@
 
     /* extract hardware events only! */
 
-    if (!hTask) EVENT_WaitNetEvent( FALSE, TRUE );
+    if (!hTask) pending = EVENT_WaitNetEvent( FALSE, TRUE );
 
     while (!hTask)
     {
@@ -739,6 +740,10 @@
         if (hLockedTask && (hTask != hLockedTask)) hTask = 0;
         if (hTask) break;
 
+        /* If a non-hardware event is pending, return to TASK_YieldToSystem
+           temporarily to process it safely */
+        if (pending) return TRUE;
+
         /* No task found, wait for some events to come in */
 
         /* NOTE: We release the Win16Lock while waiting for events. This is to enable
@@ -747,14 +752,14 @@
                  TASK_Reschedule anyway, there should be no re-entrancy problem ... */
 
         SYSLEVEL_ReleaseWin16Lock();
-        EVENT_WaitNetEvent( TRUE, TRUE );
+        pending = EVENT_WaitNetEvent( TRUE, TRUE );
         SYSLEVEL_RestoreWin16Lock();
     }
 
     if (hTask == hCurrentTask) 
     {
        TRACE(task, "returning to the current task(%04x)\n", hTask );
-       return;  /* Nothing to do */
+       return FALSE;  /* Nothing to do */
     }
     pNewTask = (TDB *)GlobalLock16( hTask );
     TRACE(task, "Switching to task %04x (%.8s)\n",
@@ -797,6 +802,8 @@
     pNewTask->ss_sp = pNewTask->thdb->cur_stack;
 
     SYSLEVEL_RestoreWin16Lock();
+
+    return FALSE;
 }
 
 
@@ -808,26 +815,30 @@
  */
 void TASK_YieldToSystem(TDB* pTask)
 {
-  MESSAGEQUEUE*		pQ;
-
-  if ( !THREAD_IsWin16( THREAD_Current() ) )
-  {
-    FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
-    return;
-  }
-
-  Callbacks->CallTaskRescheduleProc();
-
-  if( pTask )
-  {
-    pQ = (MESSAGEQUEUE*)GlobalLock16(pTask->hQueue);
-    if( pQ && pQ->flags & QUEUE_FLAG_XEVENT &&
-	    !(pQ->wakeBits & (QS_SENDMESSAGE | QS_SMRESULT)) )
+    if ( !THREAD_IsWin16( THREAD_Current() ) )
     {
-      pQ->flags &= ~QUEUE_FLAG_XEVENT;
-      EVENT_WaitNetEvent( FALSE, FALSE );
+        FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
+        return;
     }
-  }
+
+    if ( Callbacks->CallTaskRescheduleProc() )
+    {
+        /* NOTE: We get here only when no task has an event. This means also
+                 the current task, so we shouldn't actually return to the
+                 caller here. But, we need to do so, as the EVENT_WaitNetEvent
+                 call could lead to a complex series of inter-task SendMessage
+                 calls which might leave this task in a state where it again
+                 has no event, but where its queue's wakeMask is also reset
+                 to zero. Reentering TASK_Reschedule in this state would be 
+                 suicide.  Hence, we do return to the caller after processing
+                 non-hardware events. Actually, this should not hurt anyone,
+                 as the caller must be WaitEvent, and thus the QUEUE_WaitBits
+                 loop in USER. Should there actually be no message pending 
+                 for this task after processing non-hardware events, that loop
+                 will simply return to WaitEvent.  */
+                 
+        EVENT_WaitNetEvent( FALSE, FALSE );
+    }
 }