static void DOSDEV_DoReq(void*req, DWORD dev) { REQUEST_HEADER *hdr = (REQUEST_HEADER *)req; DOS_DEVICE_HEADER *dhdr; CONTEXT86 ctx; char *phdr; dhdr = PTR_REAL_TO_LIN(SELECTOROF(dev),OFFSETOF(dev)); phdr = ((char*)DOSMEM_LOL()) + DOS_DATASEG_OFF(req); /* copy request to request scratch area */ memcpy(phdr, req, hdr->size); /* prepare to call device driver */ memset(&ctx, 0, sizeof(ctx)); ctx.EFlags |= V86_FLAG; /* ES:BX points to request for strategy routine */ ctx.SegEs = HIWORD(DOS_LOLSeg); ctx.Ebx = DOS_DATASEG_OFF(req); /* call strategy routine */ ctx.SegCs = SELECTOROF(dev); ctx.Eip = dhdr->strategy; DPMI_CallRMProc(&ctx, 0, 0, 0); /* call interrupt routine */ ctx.SegCs = SELECTOROF(dev); ctx.Eip = dhdr->interrupt; DPMI_CallRMProc(&ctx, 0, 0, 0); /* completed, copy request back */ memcpy(req, phdr, hdr->size); if (hdr->status & STAT_ERROR) { switch (hdr->status & STAT_MASK) { case 0x0F: /* invalid disk change */ /* this error seems to fit the bill */ SetLastError(ERROR_NOT_SAME_DEVICE); break; default: SetLastError((hdr->status & STAT_MASK) + 0x13); break; } } }
static void MouseRelay(CONTEXT *context,void *mdata) { MCALLDATA *data = mdata; CONTEXT ctx = *context; if (!ISV86(&ctx)) { ctx.EFlags |= V86_FLAG; ctx.SegSs = 0; /* Allocate new stack. */ } ctx.Eax = data->mask; ctx.Ebx = data->but; ctx.Ecx = data->x; ctx.Edx = data->y; ctx.Esi = data->mx; ctx.Edi = data->my; ctx.SegCs = SELECTOROF(data->proc); ctx.Eip = OFFSETOF(data->proc); HeapFree(GetProcessHeap(), 0, data); DPMI_CallRMProc(&ctx, NULL, 0, 0); }
/********************************************************************** * CallRMProc (WINEDOS.@) */ void WINAPI DOSVM_CallRMProc( CONTEXT86 *context, int iret ) { REALMODECALL *p = CTX_SEG_OFF_TO_LIN( context, context->SegEs, context->Edi ); CONTEXT86 context16; TRACE("RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", p->eax, p->ebx, p->ecx, p->edx); TRACE(" ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s\n", p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context), iret?"IRET":"FAR" ); if (!(p->cs) && !(p->ip)) { /* remove this check if Int21/6501 case map function has been implemented */ SET_CFLAG(context); return; } INT_GetRealModeContext(p, &context16); DPMI_CallRMProc( &context16, ((LPWORD)MapSL(MAKESEGPTR(context->SegSs, LOWORD(context->Esp))))+3, CX_reg(context), iret ); INT_SetRealModeContext(p, &context16); }
/********************************************************************** * CallRMInt (WINEDOS.@) */ void WINAPI DOSVM_CallRMInt( CONTEXT86 *context ) { CONTEXT86 realmode_ctx; FARPROC16 rm_int = DOSVM_GetRMHandler( BL_reg(context) ); REALMODECALL *call = CTX_SEG_OFF_TO_LIN( context, context->SegEs, context->Edi ); INT_GetRealModeContext( call, &realmode_ctx ); /* we need to check if a real-mode program has hooked the interrupt */ if (HIWORD(rm_int)!=0xF000) { /* yup, which means we need to switch to real mode... */ realmode_ctx.SegCs = HIWORD(rm_int); realmode_ctx.Eip = LOWORD(rm_int); if (DPMI_CallRMProc( &realmode_ctx, NULL, 0, TRUE)) SET_CFLAG(context); } else { RESET_CFLAG(context); /* use the IP we have instead of BL_reg, in case some apps decide to move interrupts around for whatever reason... */ DOSVM_CallBuiltinHandler( &realmode_ctx, LOWORD(rm_int)/4 ); } INT_SetRealModeContext( call, &realmode_ctx ); }
/*********************************************************************** * 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() ); } } }