winedos / Fix DOSVM_Wait in protected mode

Jukka Heinonen jhei at iki.fi
Sat Jun 14 12:22:29 CDT 2003


Last patch broke DOSVM_Wait in protected mode because
it corrected IRQ priorities and DOSVM_Wait tried to call 
real mode timer IRQ handler using protected mode stack...
This patch fixes the problem and also does a small cleanup of
dosvm.c.




Changelog:
    Make DOSVM_Wait work in protected mode.
    Replace SHOULD_PEND macro with a function.




Index: dlls/winedos/dosvm.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/dosvm.c,v
retrieving revision 1.38
diff -u -r1.38 dosvm.c
--- dlls/winedos/dosvm.c	13 Jun 2003 16:28:49 -0000	1.38
+++ dlls/winedos/dosvm.c	14 Jun 2003 17:06:17 -0000
@@ -91,14 +91,33 @@
 static int sig_sent;
 static HANDLE event_notifier;
 
-#define SHOULD_PEND(x) \
-  (x && ((!current_event) || (x->priority < current_event->priority)))
+
+/***********************************************************************
+ *              DOSVM_HasPendingEvents
+ *
+ * Return true if there are pending events that are not
+ * blocked by currently active event.
+ */
+static BOOL DOSVM_HasPendingEvents( void )
+{   
+    if (!pending_event)
+        return FALSE;
+
+    if (!current_event)
+        return TRUE;
+
+    if (pending_event->priority < current_event->priority)
+        return TRUE;
+
+    return FALSE;
+}
+
 
 static void DOSVM_SendQueuedEvent(CONTEXT86 *context)
 {
   LPDOSEVENT event = pending_event;
 
-  if (SHOULD_PEND(event)) {
+  if (DOSVM_HasPendingEvents()) {
     /* remove from "pending" list */
     pending_event = event->next;
     /* process event */
@@ -118,7 +137,7 @@
       free(event);
     }
   }
-  if (!SHOULD_PEND(pending_event)) {
+  if (!DOSVM_HasPendingEvents()) {
     TRACE("clearing Pending flag\n");
     CLR_PEND(context);
   }
@@ -268,13 +287,31 @@
  */
 void WINAPI DOSVM_Wait( CONTEXT86 *waitctx )
 {
-    if (SHOULD_PEND(pending_event)) 
+    if (DOSVM_HasPendingEvents())
     {
         /*
-         * FIXME: This does not work in protected mode DOS programs.
          * FIXME: Critical section locking is broken.
          */
         CONTEXT86 context = *waitctx;
+        
+        /*
+         * If DOSVM_Wait is called from protected mode we emulate
+         * interrupt reflection and convert context into real mode context.
+         * This is actually the correct thing to do as long as DOSVM_Wait
+         * is only called from those interrupt functions that DPMI reflects
+         * to real mode.
+         *
+         * FIXME: Need to think about where to place real mode stack.
+         * FIXME: If DOSVM_Wait calls are nested stack gets corrupted.
+         *        Can this really happen?
+         */
+        if (!ISV86(&context))
+        {
+            context.EFlags |= 0x00020000;
+            context.SegSs = 0xffff;
+            context.Esp = 0;
+        }
+
         IF_SET(&context);
         SET_PEND(&context);
         context.SegCs = 0;
@@ -473,7 +510,7 @@
 	(*event->relay)(NULL,event->data);
 	free(event);
 
-	if (pending_event) {
+	if (DOSVM_HasPendingEvents()) {
 	  /* another event is pending, which we should probably
 	   * be able to process now */
 	  TRACE("another event pending, setting flag\n");




-- 
Jukka Heinonen <http://www.iki.fi/jhei/>



More information about the wine-patches mailing list