Example #1
0
/**********************************************************************
 *         DOSVM_EmulateInterruptRM
 *
 * Emulate software interrupt in real mode.
 * Called from VM86 emulation when intXX opcode is executed. 
 *
 * Either calls directly builtin handler or pushes interrupt frame to 
 * stack and changes instruction pointer to interrupt handler.
 *
 * Returns FALSE if this interrupt was caused by return 
 * from real mode wrapper.
 */
BOOL WINAPI DOSVM_EmulateInterruptRM( CONTEXT86 *context, BYTE intnum ) 
{
    TRACE_(relay)("Call DOS int 0x%02x ret=%04lx:%08lx\n"
                  "  eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx\n"
                  "  esi=%08lx edi=%08lx ebp=%08lx esp=%08lx \n"
                  "  ds=%04lx es=%04lx fs=%04lx gs=%04lx ss=%04lx flags=%08lx\n",
                  intnum, 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->SegSs, context->EFlags );

    /* check for our real-mode hooks */
    if (intnum == 0x31)
    {
        /* is this exit from real-mode wrapper */
        if (context->SegCs == DOSVM_dpmi_segments->wrap_seg)
            return FALSE;

        if (DOSVM_CheckWrappers( context ))
            return TRUE;
    }

    /* check if the call is from our fake BIOS interrupt stubs */
    if (context->SegCs==0xf000)
    {
        /* Restore original flags stored into the stack by the caller. */
        WORD *stack = CTX_SEG_OFF_TO_LIN(context, 
                                         context->SegSs, context->Esp);
        context->EFlags = (DWORD)MAKELONG( stack[2], HIWORD(context->EFlags) );

        if (intnum != context->Eip / DOSVM_STUB_RM)
            WARN( "interrupt stub has been modified "
                  "(interrupt is %02x, interrupt stub is %02lx)\n",
                  intnum, context->Eip/DOSVM_STUB_RM );

        TRACE( "builtin interrupt %02x has been branched to\n", intnum );
        
        DOSVM_CallBuiltinHandler( context, intnum );

        /* Real mode stubs use IRET so we must put flags back into stack. */
        stack[2] = LOWORD(context->EFlags);
    }
    else
    {
        DOSVM_HardwareInterruptRM( context, intnum );
    }

    return TRUE;
}
Example #2
0
/***********************************************************************
 *              DOSVM_SendOneEvent
 *
 * Process single pending event.
 *
 * This function should be called with queue critical section locked. 
 * The function temporarily releases the critical section if it is 
 * possible that internal interrupt handler or user procedure will 
 * be called. This is because we may otherwise get a deadlock if
 * another thread is waiting for the same critical section.
 */
static void DOSVM_SendOneEvent( CONTEXT86 *context )
{
    LPDOSEVENT event = pending_event;

    /* Remove from pending events list. */
    pending_event = event->next;

    /* Process active event. */
    if (event->irq >= 0) 
    {
        BYTE intnum = (event->irq < 8) ?
            (event->irq + 8) : (event->irq - 8 + 0x70);
            
        /* Event is an IRQ, move it to current events list. */
        event->next = current_event;
        current_event = event;

        TRACE( "Dispatching IRQ %d.\n", event->irq );

        if (ISV86(context))
        {
            /* 
             * Note that if DOSVM_HardwareInterruptRM calls an internal 
             * interrupt directly, current_event might be cleared 
             * (and event freed) in this call.
             */
            LeaveCriticalSection(&qcrit);
            DOSVM_HardwareInterruptRM( context, intnum );
            EnterCriticalSection(&qcrit);
        }
        else
        {
            /*
             * This routine only modifies current context so it is
             * not necessary to release critical section.
             */
            DOSVM_HardwareInterruptPM( context, intnum );
        }
    } 
    else 
    {
        /* Callback event. */
        TRACE( "Dispatching callback event.\n" );

        if (ISV86(context))
        {
            /*
             * Call relay immediately in real mode.
             */
            LeaveCriticalSection(&qcrit);
            (*event->relay)( context, event->data );
            EnterCriticalSection(&qcrit);
        }
        else
        {
            /*
             * Force return to relay code. We do not want to
             * call relay directly because we may be inside a signal handler.
             */
            DOSVM_BuildCallFrame( context, event->relay, event->data );
        }

        free(event);
    }
}