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/>