static LONG WINAPI exception_handler(EXCEPTION_POINTERS *eptr) { EXCEPTION_RECORD *rec = eptr->ExceptionRecord; CONTEXT *context = eptr->ContextRecord; int arg = rec->ExceptionInformation[0]; BOOL ret; switch(rec->ExceptionCode) { case EXCEPTION_VM86_INTx: TRACE_(relay)("Call DOS int 0x%02x ret=%04x:%04x\n" " eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n" " ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x\n", arg, context->SegCs, context->Eip, context->Eax, context->Ebx, context->Ecx, context->Edx, context->Esi, context->Edi, context->Ebp, context->Esp, context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->EFlags ); ret = DOSVM_EmulateInterruptRM( context, arg ); TRACE_(relay)("Ret DOS int 0x%02x ret=%04x:%04x\n" " eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n" " ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x\n", arg, context->SegCs, context->Eip, context->Eax, context->Ebx, context->Ecx, context->Edx, context->Esi, context->Edi, context->Ebp, context->Esp, context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->EFlags ); return ret ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER; case EXCEPTION_VM86_STI: /* case EXCEPTION_VM86_PICRETURN: */ if (!ISV86(context)) ERR( "Protected mode STI caught by real mode handler!\n" ); DOSVM_SendQueuedEvents(context); return EXCEPTION_CONTINUE_EXECUTION; case EXCEPTION_SINGLE_STEP: ret = DOSVM_EmulateInterruptRM( context, 1 ); return ret ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER; case EXCEPTION_BREAKPOINT: ret = DOSVM_EmulateInterruptRM( context, 3 ); return ret ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER; } return EXCEPTION_CONTINUE_SEARCH; }
/********************************************************************** * dpmi_exception_handler * * Handle EXCEPTION_VM86_STI exceptions generated * when there are pending asynchronous events. */ static LONG WINAPI dpmi_exception_handler(EXCEPTION_POINTERS *eptr) { EXCEPTION_RECORD *rec = eptr->ExceptionRecord; CONTEXT *context = eptr->ContextRecord; if (rec->ExceptionCode == EXCEPTION_VM86_STI) { if (ISV86(context)) ERR( "Real mode STI caught by protected mode handler!\n" ); DOSVM_SendQueuedEvents(context); return EXCEPTION_CONTINUE_EXECUTION; } else if (rec->ExceptionCode == EXCEPTION_VM86_INTx) { if (ISV86(context)) ERR( "Real mode INTx caught by protected mode handler!\n" ); DPMI_retval = (BYTE)rec->ExceptionInformation[0]; return EXCEPTION_EXECUTE_HANDLER; } return EXCEPTION_CONTINUE_SEARCH; }
/********************************************************************** * dpmi_exception_handler * * Handle EXCEPTION_VM86_STI exceptions generated * when there are pending asynchronous events. */ static WINE_EXCEPTION_FILTER(dpmi_exception_handler) { #ifdef __i386__ EXCEPTION_RECORD *rec = GetExceptionInformation()->ExceptionRecord; CONTEXT *context = GetExceptionInformation()->ContextRecord; if (rec->ExceptionCode == EXCEPTION_VM86_STI) { if (ISV86(context)) ERR( "Real mode STI caught by protected mode handler!\n" ); DOSVM_SendQueuedEvents(context); return EXCEPTION_CONTINUE_EXECUTION; } else if (rec->ExceptionCode == EXCEPTION_VM86_INTx) { if (ISV86(context)) ERR( "Real mode INTx caught by protected mode handler!\n" ); DPMI_retval = (BYTE)rec->ExceptionInformation[0]; return EXCEPTION_EXECUTE_HANDLER; } #endif return EXCEPTION_CONTINUE_SEARCH; }
/*********************************************************************** * DOSVM_Wait * * Wait for asynchronous events. This routine temporarily enables * interrupts and waits until some asynchronous event has been * processed. */ void WINAPI DOSVM_Wait( CONTEXT86 *waitctx ) { if (DOSVM_HasPendingEvents()) { 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 |= V86_FLAG; context.SegSs = 0xffff; context.Esp = 0; } context.EFlags |= VIF_MASK; context.SegCs = 0; context.Eip = 0; DOSVM_SendQueuedEvents(&context); if(context.SegCs || context.Eip) DPMI_CallRMProc( &context, NULL, 0, TRUE ); } else { HANDLE objs[2]; int objc = DOSVM_IsWin16() ? 2 : 1; DWORD waitret; objs[0] = event_notifier; objs[1] = GetStdHandle(STD_INPUT_HANDLE); waitret = MsgWaitForMultipleObjects( objc, objs, FALSE, INFINITE, QS_ALLINPUT ); if (waitret == WAIT_OBJECT_0) { /* * New pending event has been queued, we ignore it * here because it will be processed on next call to * DOSVM_Wait. */ } else if (objc == 2 && waitret == WAIT_OBJECT_0 + 1) { DOSVM_ProcessConsole(); } else if (waitret == WAIT_OBJECT_0 + objc) { MSG msg; while (PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) { /* got a message */ DOSVM_ProcessMessage(&msg); /* we don't need a TranslateMessage here */ DispatchMessageA(&msg); } } else { ERR_(module)( "dosvm wait error=%d\n", GetLastError() ); } } }