Пример #1
0
static DWORD WINAPI MZ_DOSVM( LPVOID lpExtra )
{
  CONTEXT context;
  INT ret;

  dosvm_pid = getpid();

  memset( &context, 0, sizeof(context) );
  context.SegCs  = init_cs;
  context.Eip    = init_ip;
  context.SegSs  = init_ss;
  context.Esp    = init_sp;
  context.SegDs  = DOSVM_psp;
  context.SegEs  = DOSVM_psp;
  context.EFlags = V86_FLAG | VIF_MASK;
  DOSVM_SetTimer(0x10000);
  ret = DOSVM_Enter( &context );
  if (ret == -1)
  {
      /* fetch the app name from the environment */
      PDB16 *psp = PTR_REAL_TO_LIN( DOSVM_psp, 0 );
      char *env = PTR_REAL_TO_LIN( psp->environment, 0 );
      while (*env) env += strlen(env) + 1;
      env += 1 + sizeof(WORD);

      if (GetLastError() == ERROR_NOT_SUPPORTED)
          MESSAGE( "wine: Cannot start DOS application %s\n"
                   "      because vm86 mode is not supported on this platform.\n",
                   debugstr_a(env) );
      else
          FIXME( "vm86 mode failed error %u\n", GetLastError() );
  }
  dosvm_pid = 0;
  return ret != 0;
}
Пример #2
0
/**********************************************************************
 *	    DOSVM_RawModeSwitchHandler
 *
 * DPMI Raw Mode Switch handler
 */
void WINAPI DOSVM_RawModeSwitchHandler( CONTEXT86 *context )
{
  CONTEXT86 rm_ctx;
  int ret;

  /* initialize real-mode context as per spec */
  memset(&rm_ctx, 0, sizeof(rm_ctx));
  rm_ctx.SegDs  = AX_reg(context);
  rm_ctx.SegEs  = CX_reg(context);
  rm_ctx.SegSs  = DX_reg(context);
  rm_ctx.Esp    = context->Ebx;
  rm_ctx.SegCs  = SI_reg(context);
  rm_ctx.Eip    = context->Edi;
  rm_ctx.Ebp    = context->Ebp;
  rm_ctx.SegFs  = 0;
  rm_ctx.SegGs  = 0;

  /* Copy interrupt state. */
  if (NtCurrentTeb()->dpmi_vif)
      rm_ctx.EFlags = V86_FLAG | VIF_MASK;
  else
      rm_ctx.EFlags = V86_FLAG;

  /* enter real mode again */
  TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip);
  ret = DOSVM_Enter( &rm_ctx );
  /* when the real-mode stuff call its mode switch address,
     DOSVM_Enter will return and we will continue here */

  if (ret<0) {
    ERR("Sync lost!\n");
    /* if the sync was lost, there's no way to recover */
    ExitProcess(1);
  }

  /* alter protected-mode context as per spec */
  context->SegDs   = LOWORD(rm_ctx.Eax);
  context->SegEs   = LOWORD(rm_ctx.Ecx);
  context->SegSs   = LOWORD(rm_ctx.Edx);
  context->Esp     = rm_ctx.Ebx;
  context->SegCs   = LOWORD(rm_ctx.Esi);
  context->Eip     = rm_ctx.Edi;
  context->Ebp     = rm_ctx.Ebp;
  context->SegFs   = 0;
  context->SegGs   = 0;

  /* Copy interrupt state. */
  if (rm_ctx.EFlags & VIF_MASK)
      NtCurrentTeb()->dpmi_vif = 1;
  else
      NtCurrentTeb()->dpmi_vif = 0;

  /* Return to new address and hope that we didn't mess up */
  TRACE("re-entering protected mode at %04lx:%08lx\n",
      context->SegCs, context->Eip);
}
Пример #3
0
static DWORD WINAPI MZ_DOSVM( LPVOID lpExtra )
{
  CONTEXT context;
  DWORD ret;

  dosvm_pid = getpid();

  memset( &context, 0, sizeof(context) );
  context.SegCs  = init_cs;
  context.Eip    = init_ip;
  context.SegSs  = init_ss;
  context.Esp    = init_sp;
  context.SegDs  = DOSVM_psp;
  context.SegEs  = DOSVM_psp;
  context.EFlags = V86_FLAG | VIF_MASK;
  DOSVM_SetTimer(0x10000);
  ret = DOSVM_Enter( &context );

  dosvm_pid = 0;
  return ret;
}
Пример #4
0
/**********************************************************************
 *	    DPMI_CallRMProc
 *
 * This routine does the hard work of calling a real mode procedure.
 */
int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret )
{
    LPWORD stack16;
    LPVOID addr = NULL; /* avoid gcc warning */
    RMCB *CurrRMCB;
    int alloc = 0, already = 0;
    BYTE *code;

    TRACE("EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
                 context->Eax, context->Ebx, context->Ecx, context->Edx );
    TRACE("ESI=%08lx EDI=%08lx ES=%04lx DS=%04lx CS:IP=%04lx:%04x, %d WORD arguments, %s\n",
                 context->Esi, context->Edi, context->SegEs, context->SegDs,
                 context->SegCs, LOWORD(context->Eip), args, iret?"IRET":"FAR" );

callrmproc_again:

/* there might be some code that just jumps to RMCBs or the like,
   in which case following the jumps here might get us to a shortcut */
    code = CTX_SEG_OFF_TO_LIN(context, context->SegCs, context->Eip);
    switch (*code) {
    case 0xe9: /* JMP NEAR */
      context->Eip += 3 + *(WORD *)(code+1);
      /* yeah, I know these gotos don't look good... */
      goto callrmproc_again;
    case 0xea: /* JMP FAR */
      context->Eip = *(WORD *)(code+1);
      context->SegCs = *(WORD *)(code+3);
      /* ...but since the label is there anyway... */
      goto callrmproc_again;
    case 0xeb: /* JMP SHORT */
      context->Eip += 2 + *(signed char *)(code+1);
      /* ...because of other gotos below, so... */
      goto callrmproc_again;
    }

/* shortcut for chaining to internal interrupt handlers */
    if ((context->SegCs == 0xF000) && iret)
    {
        DOSVM_CallBuiltinHandler( context, LOWORD(context->Eip)/4 );
        return 0;
    }

/* shortcut for RMCBs */
    CurrRMCB = FirstRMCB;

    while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
        CurrRMCB = CurrRMCB->next;

    if (!CurrRMCB && !MZ_Current())
    {
        FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
        TRACE("creating VM86 task\n");
        MZ_AllocDPMITask();
    }
    if (!already) {
        if (!context->SegSs) {
            alloc = 1; /* allocate default stack */
            stack16 = addr = DOSMEM_AllocBlock( 64, (UINT16 *)&(context->SegSs) );
            context->Esp = 64-2;
            stack16 += 32-1;
            if (!addr) {
                ERR("could not allocate default stack\n");
                return 1;
            }
        } else {
            stack16 = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
        }
        context->Esp -= (args + (iret?1:0)) * sizeof(WORD);
        stack16 -= args;
        if (args) memcpy(stack16, stack, args*sizeof(WORD) );
        /* push flags if iret */
        if (iret) {
            stack16--; args++;
            *stack16 = LOWORD(context->EFlags);
        }
        /* push return address (return to interrupt wrapper) */
        *(--stack16) = DOSVM_dpmi_segments->wrap_seg;
        *(--stack16) = 0;
        /* adjust stack */
        context->Esp -= 2*sizeof(WORD);
        already = 1;
    }

    if (CurrRMCB) {
        /* RMCB call, invoke protected-mode handler directly */
        DPMI_CallRMCBProc(context, CurrRMCB, dpmi_flag);
        /* check if we returned to where we thought we would */
        if ((context->SegCs != DOSVM_dpmi_segments->wrap_seg) ||
            (LOWORD(context->Eip) != 0)) {
            /* we need to continue at different address in real-mode space,
               so we need to set it all up for real mode again */
            goto callrmproc_again;
        }
    } else {
        TRACE("entering real mode...\n");
        DOSVM_Enter( context );
        TRACE("returned from real-mode call\n");
    }
    if (alloc) DOSMEM_FreeBlock( addr );
    return 0;
}