diff --git a/include/dosexe.h b/include/dosexe.h index de4f3b6cd58..6188c661278 100644 --- a/include/dosexe.h +++ b/include/dosexe.h @@ -11,38 +11,13 @@ #include "winbase.h" /* for LPSTARTUPINFO32A */ #include "winnt.h" /* for PCONTEXT */ -typedef struct _DOSSYSTEM { - int id; - void *data; - struct _DOSSYSTEM *next; -} DOSSYSTEM; - struct _DOSEVENT; typedef struct _DOSTASK { - LPVOID img; - unsigned img_ofs; - WORD psp_seg,load_seg; - WORD init_cs,init_ip,init_ss,init_sp; - WORD xms_seg; - WORD dpmi_seg,dpmi_sel,dpmi_flag; - char mm_name[128]; - int mm_fd; - HANDLE hReadPipe,hXPipe,hConInput,hConOutput; - int read_pipe,write_pipe; - pid_t task; - int sig_sent,entered,idling; - struct _DOSEVENT *pending,*current; - DOSSYSTEM *sys; + WORD psp_seg; + WORD dpmi_flag; } DOSTASK, *LPDOSTASK; -typedef struct _DOSEVENT { - int irq,priority; - void (*relay)(LPDOSTASK,CONTEXT86*,void*); - void *data; - struct _DOSEVENT *next; -} DOSEVENT, *LPDOSEVENT; - #define DOS_PRIORITY_REALTIME 0 /* IRQ0 */ #define DOS_PRIORITY_KEYBOARD 1 /* IRQ1 */ #define DOS_PRIORITY_VGA 2 /* IRQ9 */ @@ -50,26 +25,19 @@ typedef struct _DOSEVENT { #define DOS_PRIORITY_SERIAL 10 /* IRQ4 */ #if defined(linux) && defined(__i386__) - #define MZ_SUPPORTED - -extern BOOL MZ_InitTask( LPDOSTASK lpDosTask ); -extern void MZ_KillTask( LPDOSTASK lpDosTask ); -extern LPDOSTASK MZ_AllocDPMITask( void ); - #endif /* linux-i386 */ #define V86_FLAG 0x00020000 extern BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ); extern LPDOSTASK MZ_Current( void ); +extern LPDOSTASK MZ_AllocDPMITask( void ); extern int DOSVM_Enter( CONTEXT86 *context ); extern void DOSVM_Wait( int read_pipe, HANDLE hObject ); -extern void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data ); +extern void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data ); extern void DOSVM_PIC_ioport_out( WORD port, BYTE val ); extern void DOSVM_SetTimer( unsigned ticks ); extern unsigned DOSVM_GetTimer( void ); -extern void DOSVM_SetSystemData( int id, void *data ); -extern void* DOSVM_GetSystemData( int id ); #endif /* __WINE_DOSEXE_H */ diff --git a/include/ldt.h b/include/ldt.h index c6ae65c2f26..d600042da7e 100644 --- a/include/ldt.h +++ b/include/ldt.h @@ -60,6 +60,8 @@ extern ldt_copy_entry ldt_copy[LDT_SIZE]; #define PTR_SEG_OFF_TO_LIN(seg,off) \ ((void*)(GET_SEL_BASE(seg) + (unsigned int)(off))) +#define PTR_REAL_TO_LIN(seg,off) \ + ((void*)(((unsigned int)(seg) << 4) + LOWORD(off))) #define PTR_SEG_TO_LIN(ptr) \ PTR_SEG_OFF_TO_LIN(SELECTOROF(ptr),OFFSETOF(ptr)) #define PTR_SEG_OFF_TO_SEGPTR(seg,off) \ diff --git a/include/miscemu.h b/include/miscemu.h index 78074862dd9..32fed3c6337 100644 --- a/include/miscemu.h +++ b/include/miscemu.h @@ -128,8 +128,11 @@ extern BYTE * DOSMEM_BiosSys(); extern DWORD DOSMEM_CollateTable; -extern DWORD DOSMEM_ErrorCall; -extern DWORD DOSMEM_ErrorBuffer; +/* various real-mode code stubs */ +extern WORD DOSMEM_wrap_seg; +extern WORD DOSMEM_xms_seg; +extern WORD DOSMEM_dpmi_seg; +extern WORD DOSMEM_dpmi_sel; extern DWORD DOS_LOLSeg; extern struct _DOS_LISTOFLISTS * DOSMEM_LOL(); @@ -249,7 +252,7 @@ extern void ASPI_DOS_HandleInt(CONTEXT86 *context); * a *32-bit* general register as third parameter, e.g. * CTX_SEG_OFF_TO_LIN( context, DS_reg(context), EDX_reg(context) ) * This will generate a linear pointer in all three cases: - * Real-Mode: Seg*16 + LOWORD(Offset) + V86BASE + * Real-Mode: Seg*16 + LOWORD(Offset) * 16-bit: convert (Seg, LOWORD(Offset)) to linear * 32-bit: use Offset as linear address (DeviceIoControl!) * @@ -258,8 +261,8 @@ extern void ASPI_DOS_HandleInt(CONTEXT86 *context); * (0 counts also as 32-bit segment). */ #define CTX_SEG_OFF_TO_LIN(context,seg,off) \ - (ISV86(context) ? (void*)(V86BASE(context)+((seg)<<4)+(off&0xffff)) : \ - (!seg || IS_SELECTOR_SYSTEM(seg))? (void *)off : PTR_SEG_OFF_TO_LIN(seg,off&0xffff)) + (ISV86(context) ? PTR_REAL_TO_LIN((seg),(off)) : \ + (!seg || IS_SELECTOR_SYSTEM(seg))? (void *)(off) : PTR_SEG_OFF_TO_LIN((seg),LOWORD(off))) #define INT_BARF(context,num) \ ERR( "int%x: unknown/not implemented parameters:\n" \ diff --git a/include/winnt.h b/include/winnt.h index cc0a550ac91..b175a22a133 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -730,7 +730,6 @@ typedef HANDLE *PHANDLE; #define RESET_ZFLAG(context) (EFL_reg(context) &= ~0x0040) #define ISV86(context) (EFL_reg(context) & 0x00020000) -#define V86BASE(context) DOSMEM_MemoryBase() /* Macros to retrieve the current context */ diff --git a/loader/dos/dosvm.c b/loader/dos/dosvm.c index 790b5d33276..241f669879f 100644 --- a/loader/dos/dosvm.c +++ b/loader/dos/dosvm.c @@ -58,6 +58,21 @@ DECLARE_DEBUG_CHANNEL(relay) #undef TRY_PICRETURN +typedef struct _DOSEVENT { + int irq,priority; + void (*relay)(CONTEXT86*,void*); + void *data; + struct _DOSEVENT *next; +} DOSEVENT, *LPDOSEVENT; + +static struct _DOSEVENT *pending_event, *current_event; +static int sig_sent, entered; + +/* from module.c */ +extern int read_pipe, write_pipe; +extern HANDLE hReadPipe; +extern pid_t dosmod_pid; + static void do_exception( int signal, CONTEXT86 *context ) { EXCEPTION_RECORD rec; @@ -77,10 +92,8 @@ static void do_exception( int signal, CONTEXT86 *context ) EXC_RtlRaiseException( &rec, context ); } -static void DOSVM_Dump( LPDOSTASK lpDosTask, int fn, int sig, - struct vm86plus_struct*VM86 ) +static void DOSVM_Dump( int fn, int sig, struct vm86plus_struct*VM86 ) { - unsigned iofs; BYTE*inst; int x; @@ -106,20 +119,17 @@ static void DOSVM_Dump( LPDOSTASK lpDosTask, int fn, int sig, fprintf(stderr,"CS=%04X DS=%04X ES=%04X SS=%04X\n",REGS.cs,REGS.ds,REGS.es,REGS.ss); fprintf(stderr,"IP=%04lX EFLAGS=%08lX\n",REGS.eip,REGS.eflags); - iofs=((DWORD)REGS.cs<<4)+REGS.eip; + inst = PTR_REAL_TO_LIN( REGS.cs, REGS.eip ); #undef REGS - inst=(BYTE*)lpDosTask->img+iofs; printf("Opcodes:"); for (x=0; x<8; x++) printf(" %02x",inst[x]); printf("\n"); } -static int DOSVM_Int( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask ) +static int DOSVM_Int( int vect, CONTEXT86 *context ) { - extern UINT16 DPMI_wrap_seg; - if (vect==0x31) { - if (CS_reg(context)==DPMI_wrap_seg) { + if (CS_reg(context)==DOSMEM_wrap_seg) { /* exit from real-mode wrapper */ return -1; } @@ -129,7 +139,7 @@ static int DOSVM_Int( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask ) return 0; } -static void DOSVM_SimulateInt( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask ) +static void DOSVM_SimulateInt( int vect, CONTEXT86 *context ) { FARPROC16 handler=INT_GetRMHandler(vect); @@ -137,7 +147,7 @@ static void DOSVM_SimulateInt( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask /* if internal interrupt, call it directly */ INT_RealModeInterrupt(vect,context); } else { - WORD*stack=(WORD*)(V86BASE(context)+(((DWORD)SS_reg(context))<<4)+LOWORD(ESP_reg(context))); + WORD*stack= PTR_REAL_TO_LIN( context->SegSs, context->Esp ); WORD flag=LOWORD(EFL_reg(context)); if (IF_ENABLED(context)) flag|=IF_MASK; @@ -154,51 +164,50 @@ static void DOSVM_SimulateInt( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask } #define SHOULD_PEND(x) \ - (x && ((!lpDosTask->current) || (x->priority < lpDosTask->current->priority))) + (x && ((!current_event) || (x->priority < current_event->priority))) -static void DOSVM_SendQueuedEvent(CONTEXT86 *context, LPDOSTASK lpDosTask) +static void DOSVM_SendQueuedEvent(CONTEXT86 *context) { - LPDOSEVENT event = lpDosTask->pending; + LPDOSEVENT event = pending_event; if (SHOULD_PEND(event)) { /* remove from "pending" list */ - lpDosTask->pending = event->next; + pending_event = event->next; /* process event */ if (event->irq>=0) { /* it's an IRQ, move it to "current" list */ - event->next = lpDosTask->current; - lpDosTask->current = event; + event->next = current_event; + current_event = event; TRACE_(int)("dispatching IRQ %d\n",event->irq); /* note that if DOSVM_SimulateInt calls an internal interrupt directly, - * lpDosTask->current might be cleared (and event freed) in this very call! */ - DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context,lpDosTask); + * current_event might be cleared (and event freed) in this very call! */ + DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context); } else { /* callback event */ TRACE_(int)("dispatching callback event\n"); - (*event->relay)(lpDosTask,context,event->data); + (*event->relay)(context,event->data); free(event); } } - if (!SHOULD_PEND(lpDosTask->pending)) { + if (!SHOULD_PEND(pending_event)) { TRACE_(int)("clearing Pending flag\n"); CLR_PEND(context); } } -static void DOSVM_SendQueuedEvents(CONTEXT86 *context, LPDOSTASK lpDosTask) +static void DOSVM_SendQueuedEvents(CONTEXT86 *context) { /* we will send all queued events as long as interrupts are enabled, * but IRQ events will disable interrupts again */ while (IS_PEND(context) && IF_ENABLED(context)) - DOSVM_SendQueuedEvent(context,lpDosTask); + DOSVM_SendQueuedEvent(context); } -void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data) +void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data) { - LPDOSTASK lpDosTask = MZ_Current(); LPDOSEVENT event, cur, prev; - if (lpDosTask && lpDosTask->entered) { + if (entered) { event = malloc(sizeof(DOSEVENT)); if (!event) { ERR_(int)("out of memory allocating event entry\n"); @@ -209,20 +218,20 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86* /* insert event into linked list, in order *after* * all earlier events of higher or equal priority */ - cur = lpDosTask->pending; prev = NULL; + cur = pending_event; prev = NULL; while (cur && cur->priority<=priority) { prev = cur; cur = cur->next; } event->next = cur; if (prev) prev->next = event; - else lpDosTask->pending = event; + else pending_event = event; /* get dosmod's attention to the new event, if necessary */ - if (!lpDosTask->sig_sent) { + if (!sig_sent) { TRACE_(int)("new event queued, signalling dosmod\n"); - kill(lpDosTask->task,SIGUSR2); - lpDosTask->sig_sent++; + kill(dosmod_pid,SIGUSR2); + sig_sent++; } else { TRACE_(int)("new event queued\n"); } @@ -234,7 +243,7 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86* /* callback event, perform it with dummy context */ CONTEXT86 context; memset(&context,0,sizeof(context)); - (*relay)(lpDosTask,&context,data); + (*relay)(&context,data); } else { ERR_(int)("IRQ without DOS task: should not happen"); } @@ -247,8 +256,7 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86* CP(ss,SS); CP(fs,FS); CP(gs,GS); \ CP(eip,EIP); CP(eflags,EFL) -static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig, - struct vm86plus_struct*VM86 ) +static int DOSVM_Process( int fn, int sig, struct vm86plus_struct*VM86 ) { CONTEXT86 context; int ret=0; @@ -270,7 +278,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig, } #else /* linux doesn't preserve pending flag on return */ - if (SHOULD_PEND(lpDosTask->pending)) { + if (SHOULD_PEND(pending_event)) { SET_PEND(&context); } #endif @@ -280,48 +288,48 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig, TRACE_(int)("DOS module caught signal %d\n",sig); if ((sig==SIGALRM) || (sig==SIGUSR2)) { if (sig==SIGALRM) { - lpDosTask->sig_sent++; + sig_sent++; DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL); } - if (lpDosTask->pending) { + if (pending_event) { TRACE_(int)("setting Pending flag, interrupts are currently %s\n", IF_ENABLED(&context) ? "enabled" : "disabled"); SET_PEND(&context); - DOSVM_SendQueuedEvents(&context,lpDosTask); + DOSVM_SendQueuedEvents(&context); } else { TRACE_(int)("no events are pending, clearing Pending flag\n"); CLR_PEND(&context); } - lpDosTask->sig_sent--; + sig_sent--; } else if ((sig==SIGHUP) || (sig==SIGILL) || (sig==SIGSEGV)) { do_exception( sig, &context ); } else { - DOSVM_Dump(lpDosTask,fn,sig,VM86); + DOSVM_Dump(fn,sig,VM86); ret=-1; } break; case VM86_UNKNOWN: /* unhandled GPF */ - DOSVM_Dump(lpDosTask,fn,sig,VM86); + DOSVM_Dump(fn,sig,VM86); do_exception( SIGSEGV, &context ); break; case VM86_INTx: if (TRACE_ON(relay)) DPRINTF("Call DOS int 0x%02x (EAX=%08lx) ret=%04lx:%04lx\n",VM86_ARG(fn),context.Eax,context.SegCs,context.Eip); - ret=DOSVM_Int(VM86_ARG(fn),&context,lpDosTask); + ret=DOSVM_Int(VM86_ARG(fn),&context); if (TRACE_ON(relay)) DPRINTF("Ret DOS int 0x%02x (EAX=%08lx) ret=%04lx:%04lx\n",VM86_ARG(fn),context.Eax,context.SegCs,context.Eip); break; case VM86_STI: case VM86_PICRETURN: TRACE_(int)("DOS task enabled interrupts with events pending, sending events\n"); - DOSVM_SendQueuedEvents(&context,lpDosTask); + DOSVM_SendQueuedEvents(&context); break; case VM86_TRAP: do_exception( SIGTRAP, &context ); break; default: - DOSVM_Dump(lpDosTask,fn,sig,VM86); + DOSVM_Dump(fn,sig,VM86); ret=-1; } @@ -335,7 +343,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig, return ret; } -static void DOSVM_ProcessConsole(LPDOSTASK lpDosTask) +static void DOSVM_ProcessConsole(void) { INPUT_RECORD msg; DWORD res; @@ -360,7 +368,7 @@ static void DOSVM_ProcessConsole(LPDOSTASK lpDosTask) } } -static void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg) +static void DOSVM_ProcessMessage(MSG *msg) { BYTE scan = 0; @@ -391,21 +399,20 @@ static void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg) void DOSVM_Wait( int read_pipe, HANDLE hObject ) { - LPDOSTASK lpDosTask = MZ_Current(); MSG msg; DWORD waitret; HANDLE objs[2]; int objc; BOOL got_msg = FALSE; - objs[0]=lpDosTask->hConInput; + objs[0]=GetStdHandle(STD_INPUT_HANDLE); objs[1]=hObject; objc=hObject?2:1; do { /* check for messages (waste time before the response check below) */ while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) { /* got a message */ - DOSVM_ProcessMessage(lpDosTask,&msg); + DOSVM_ProcessMessage(&msg); /* we don't need a TranslateMessage here */ Callout.DispatchMessageA(&msg); got_msg = TRUE; @@ -415,7 +422,7 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject ) INPUT_RECORD msg; DWORD num; if (PeekConsoleInputA(objs[0],&msg,1,&num) && num) { - DOSVM_ProcessConsole(lpDosTask); + DOSVM_ProcessConsole(); got_msg = TRUE; } } @@ -439,63 +446,42 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject ) if (waitret==(WAIT_OBJECT_0+1)) break; } if (waitret==WAIT_OBJECT_0) { - DOSVM_ProcessConsole(lpDosTask); + DOSVM_ProcessConsole(); } } while (TRUE); } int DOSVM_Enter( CONTEXT86 *context ) { - LPDOSTASK lpDosTask = MZ_Current(); struct vm86plus_struct VM86; int stat,len,sig; - if (!lpDosTask) { - /* MZ_CreateProcess or MZ_AllocDPMITask should have been called first */ - ERR_(module)("dosmod has not been initialized!"); - return -1; - } - - if (context) { #define CP(x,y) VM86.regs.x = y##_reg(context) CV; #undef CP if (VM86.regs.eflags & IF_MASK) VM86.regs.eflags |= VIF_MASK; - } else { -/* initial setup */ - /* registers */ - memset(&VM86,0,sizeof(VM86)); - VM86.regs.cs=lpDosTask->init_cs; - VM86.regs.eip=lpDosTask->init_ip; - VM86.regs.ss=lpDosTask->init_ss; - VM86.regs.esp=lpDosTask->init_sp; - VM86.regs.ds=lpDosTask->psp_seg; - VM86.regs.es=lpDosTask->psp_seg; - VM86.regs.eflags=VIF_MASK; - /* hmm, what else do we need? */ - } /* main exchange loop */ - lpDosTask->entered++; + entered++; do { TRACE_(module)("thread is: %lx\n",GetCurrentThreadId()); stat = VM86_ENTER; errno = 0; /* transmit VM86 structure to dosmod task */ - if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { - ERR_(module)("dosmod sync lost, errno=%d, fd=%d, pid=%d\n",errno,lpDosTask->write_pipe,getpid()); + if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { + ERR_(module)("dosmod sync lost, errno=%d, fd=%d, pid=%d\n",errno,write_pipe,getpid()); return -1; } - if (write(lpDosTask->write_pipe,&VM86,sizeof(VM86))!=sizeof(VM86)) { + if (write(write_pipe,&VM86,sizeof(VM86))!=sizeof(VM86)) { ERR_(module)("dosmod sync lost, errno=%d\n",errno); return -1; } /* wait for response, doing other things in the meantime */ - DOSVM_Wait(lpDosTask->read_pipe, lpDosTask->hReadPipe); + DOSVM_Wait(read_pipe, hReadPipe); /* read response */ while (1) { - if ((len=read(lpDosTask->read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break; + if ((len=read(read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break; if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) { WARN_(module)("rereading dosmod return code due to errno=%d, result=%d\n",errno,len); continue; @@ -505,11 +491,10 @@ int DOSVM_Enter( CONTEXT86 *context ) } TRACE_(module)("dosmod return code=%d\n",stat); if (stat==DOSMOD_LEFTIDLE) { - lpDosTask->idling--; continue; } while (1) { - if ((len=read(lpDosTask->read_pipe,&VM86,sizeof(VM86)))==sizeof(VM86)) break; + if ((len=read(read_pipe,&VM86,sizeof(VM86)))==sizeof(VM86)) break; if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) { WARN_(module)("rereading dosmod VM86 structure due to errno=%d, result=%d\n",errno,len); continue; @@ -519,7 +504,7 @@ int DOSVM_Enter( CONTEXT86 *context ) } if ((stat&0xff)==DOSMOD_SIGNAL) { while (1) { - if ((len=read(lpDosTask->read_pipe,&sig,sizeof(sig)))==sizeof(sig)) break; + if ((len=read(read_pipe,&sig,sizeof(sig)))==sizeof(sig)) break; if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) { WARN_(module)("rereading dosmod signal due to errno=%d, result=%d\n",errno,len); continue; @@ -529,8 +514,8 @@ int DOSVM_Enter( CONTEXT86 *context ) } while (0); } else sig=0; /* got response */ - } while (DOSVM_Process(lpDosTask,stat,sig,&VM86)>=0); - lpDosTask->entered--; + } while (DOSVM_Process(stat,sig,&VM86)>=0); + entered--; if (context) { #define CP(x,y) y##_reg(context) = VM86.regs.x @@ -542,27 +527,25 @@ int DOSVM_Enter( CONTEXT86 *context ) void DOSVM_PIC_ioport_out( WORD port, BYTE val) { - LPDOSTASK lpDosTask = MZ_Current(); - LPDOSEVENT event; + LPDOSEVENT event; - if (lpDosTask) { if ((port==0x20) && (val==0x20)) { - if (lpDosTask->current) { + if (current_event) { /* EOI (End Of Interrupt) */ TRACE_(int)("received EOI for current IRQ, clearing\n"); - event = lpDosTask->current; - lpDosTask->current = event->next; + event = current_event; + current_event = event->next; if (event->relay) - (*event->relay)(lpDosTask,NULL,event->data); + (*event->relay)(NULL,event->data); free(event); - if (lpDosTask->pending && - !lpDosTask->sig_sent) { + if (pending_event && + !sig_sent) { /* another event is pending, which we should probably * be able to process now, so tell dosmod about it */ TRACE_(int)("another event pending, signalling dosmod\n"); - kill(lpDosTask->task,SIGUSR2); - lpDosTask->sig_sent++; + kill(dosmod_pid,SIGUSR2); + sig_sent++; } } else { WARN_(int)("EOI without active IRQ\n"); @@ -570,27 +553,25 @@ void DOSVM_PIC_ioport_out( WORD port, BYTE val) } else { FIXME_(int)("unrecognized PIC command %02x\n",val); } - } } void DOSVM_SetTimer( unsigned ticks ) { - LPDOSTASK lpDosTask = MZ_Current(); int stat=DOSMOD_SET_TIMER; struct timeval tim; - if (lpDosTask) { + if (MZ_Current()) { /* the PC clocks ticks at 1193180 Hz */ tim.tv_sec=0; tim.tv_usec=((unsigned long long)ticks*1000000)/1193180; /* sanity check */ if (!tim.tv_usec) tim.tv_usec=1; - if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { + if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { ERR_(module)("dosmod sync lost, errno=%d\n",errno); return; } - if (write(lpDosTask->write_pipe,&tim,sizeof(tim))!=sizeof(tim)) { + if (write(write_pipe,&tim,sizeof(tim))!=sizeof(tim)) { ERR_(module)("dosmod sync lost, errno=%d\n",errno); return; } @@ -600,18 +581,17 @@ void DOSVM_SetTimer( unsigned ticks ) unsigned DOSVM_GetTimer( void ) { - LPDOSTASK lpDosTask = MZ_Current(); int stat=DOSMOD_GET_TIMER; struct timeval tim; - if (lpDosTask) { - if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { + if (MZ_Current()) { + if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { ERR_(module)("dosmod sync lost, errno=%d\n",errno); return 0; } /* read response */ while (1) { - if (read(lpDosTask->read_pipe,&tim,sizeof(tim))==sizeof(tim)) break; + if (read(read_pipe,&tim,sizeof(tim))==sizeof(tim)) break; if ((errno==EINTR)||(errno==EAGAIN)) continue; ERR_(module)("dosmod sync lost, errno=%d\n",errno); return 0; @@ -621,47 +601,6 @@ unsigned DOSVM_GetTimer( void ) return 0; } -void DOSVM_SetSystemData( int id, void *data ) -{ - LPDOSTASK lpDosTask = MZ_Current(); - DOSSYSTEM *sys, *prev; - - if (lpDosTask) { - sys = lpDosTask->sys; - prev = NULL; - while (sys && (sys->id != id)) { - prev = sys; - sys = sys->next; - } - if (sys) { - free(sys->data); - sys->data = data; - } else { - sys = malloc(sizeof(DOSSYSTEM)); - sys->id = id; - sys->data = data; - sys->next = NULL; - if (prev) prev->next = sys; - else lpDosTask->sys = sys; - } - } else free(data); -} - -void* DOSVM_GetSystemData( int id ) -{ - LPDOSTASK lpDosTask = MZ_Current(); - DOSSYSTEM *sys; - - if (lpDosTask) { - sys = lpDosTask->sys; - while (sys && (sys->id != id)) - sys = sys->next; - if (sys) - return sys->data; - } - return NULL; -} - #else /* !MZ_SUPPORTED */ int DOSVM_Enter( CONTEXT86 *context ) @@ -674,15 +613,13 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject) {} void DOSVM_PIC_ioport_out( WORD port, BYTE val) {} void DOSVM_SetTimer( unsigned ticks ) {} unsigned DOSVM_GetTimer( void ) { return 0; } -void DOSVM_SetSystemData( int id, void *data ) { free(data); } -void* DOSVM_GetSystemData( int id ) { return NULL; } -void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data) +void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data) { if (irq<0) { /* callback event, perform it with dummy context */ CONTEXT86 context; memset(&context,0,sizeof(context)); - (*relay)(NULL,&context,data); + (*relay)(&context,data); } else { ERR_(int)("IRQ without DOS task: should not happen"); } diff --git a/loader/dos/module.c b/loader/dos/module.c index f75d85ac13e..3636cb4c86a 100644 --- a/loader/dos/module.c +++ b/loader/dos/module.c @@ -37,6 +37,8 @@ DEFAULT_DEBUG_CHANNEL(module); +static LPDOSTASK dos_current; + #ifdef MZ_SUPPORTED #ifdef HAVE_SYS_MMAN_H @@ -48,15 +50,21 @@ DEFAULT_DEBUG_CHANNEL(module); #undef MZ_MAPSELF #define BIOS_DATA_SEGMENT 0x40 -#define START_OFFSET 0 #define PSP_SIZE 0x10 #define SEG16(ptr,seg) ((LPVOID)((BYTE*)ptr+((DWORD)(seg)<<4))) #define SEGPTR16(ptr,segptr) ((LPVOID)((BYTE*)ptr+((DWORD)SELECTOROF(segptr)<<4)+OFFSETOF(segptr))) -static LPDOSTASK dos_current; +static WORD init_cs,init_ip,init_ss,init_sp; +static char mm_name[128]; + +int read_pipe, write_pipe; +HANDLE hReadPipe, hWritePipe; +pid_t dosmod_pid; static void MZ_Launch(void); +static BOOL MZ_InitTask(void); +static void MZ_KillTask(void); static void MZ_CreatePSP( LPVOID lpPSP, WORD env ) { @@ -107,68 +115,18 @@ static char int08[]={ 0xCF /* iret */ }; -static void MZ_InitHandlers( LPDOSTASK lpDosTask ) +static void MZ_InitHandlers(void) { WORD seg; LPBYTE start=DOSMEM_GetBlock(sizeof(int08),&seg); memcpy(start,int08,sizeof(int08)); /* INT 08: point it at our tick-incrementing handler */ - ((SEGPTR*)(lpDosTask->img))[0x08]=PTR_SEG_OFF_TO_SEGPTR(seg,0); + ((SEGPTR*)0)[0x08]=PTR_SEG_OFF_TO_SEGPTR(seg,0); /* INT 1C: just point it to IRET, we don't want to handle it ourselves */ - ((SEGPTR*)(lpDosTask->img))[0x1C]=PTR_SEG_OFF_TO_SEGPTR(seg,sizeof(int08)-1); + ((SEGPTR*)0)[0x1C]=PTR_SEG_OFF_TO_SEGPTR(seg,sizeof(int08)-1); } -static char enter_xms[]={ -/* XMS hookable entry point */ - 0xEB,0x03, /* jmp entry */ - 0x90,0x90,0x90, /* nop;nop;nop */ - /* entry: */ -/* real entry point */ -/* for simplicity, we'll just use the same hook as DPMI below */ - 0xCD,0x31, /* int $0x31 */ - 0xCB /* lret */ -}; - -static void MZ_InitXMS( LPDOSTASK lpDosTask ) -{ - LPBYTE start=DOSMEM_GetBlock(sizeof(enter_xms),&(lpDosTask->xms_seg)); - memcpy(start,enter_xms,sizeof(enter_xms)); -} - -static char enter_pm[]={ - 0x50, /* pushw %ax */ - 0x52, /* pushw %dx */ - 0x55, /* pushw %bp */ - 0x89,0xE5, /* movw %sp,%bp */ -/* get return CS */ - 0x8B,0x56,0x08, /* movw 8(%bp),%dx */ -/* just call int 31 here to get into protected mode... */ -/* it'll check whether it was called from dpmi_seg... */ - 0xCD,0x31, /* int $0x31 */ -/* we are now in the context of a 16-bit relay call */ -/* need to fixup our stack; - * 16-bit relay return address will be lost, but we won't worry quite yet */ - 0x8E,0xD0, /* movw %ax,%ss */ - 0x66,0x0F,0xB7,0xE5, /* movzwl %bp,%esp */ -/* set return CS */ - 0x89,0x56,0x08, /* movw %dx,8(%bp) */ - 0x5D, /* popw %bp */ - 0x5A, /* popw %dx */ - 0x58, /* popw %ax */ - 0xCB /* lret */ -}; - -static void MZ_InitDPMI( LPDOSTASK lpDosTask ) -{ - unsigned size=sizeof(enter_pm); - LPBYTE start=DOSMEM_GetBlock(size,&(lpDosTask->dpmi_seg)); - - lpDosTask->dpmi_sel = SELECTOR_AllocBlock( start, size, SEGMENT_CODE, FALSE, FALSE ); - - memcpy(start,enter_pm,sizeof(enter_pm)); -} - -static WORD MZ_InitEnvironment( LPDOSTASK lpDosTask, LPCSTR env, LPCSTR name ) +static WORD MZ_InitEnvironment( LPCSTR env, LPCSTR name ) { unsigned sz=0; WORD seg; @@ -191,39 +149,33 @@ static WORD MZ_InitEnvironment( LPDOSTASK lpDosTask, LPCSTR env, LPCSTR name ) return seg; } -static BOOL MZ_InitMemory( LPDOSTASK lpDosTask ) +static BOOL MZ_InitMemory(void) { - if (lpDosTask->img) return TRUE; /* already allocated */ + int mm_fd; + void *img_base; - /* allocate 1MB+64K shared memory */ - lpDosTask->img_ofs=START_OFFSET; -#ifdef MZ_MAPSELF - lpDosTask->img=VirtualAlloc(NULL,0x110000,MEM_COMMIT,PAGE_READWRITE); - /* make sure mmap accepts it */ - ((char*)lpDosTask->img)[0x10FFFF]=0; -#else - tmpnam(lpDosTask->mm_name); -/* strcpy(lpDosTask->mm_name,"/tmp/mydosimage"); */ - lpDosTask->mm_fd=open(lpDosTask->mm_name,O_RDWR|O_CREAT /* |O_TRUNC */,S_IRUSR|S_IWUSR); - if (lpDosTask->mm_fd<0) ERR("file %s could not be opened\n",lpDosTask->mm_name); - /* expand file to 1MB+64K */ - ftruncate(lpDosTask->mm_fd,0x110000); - /* map it in */ - lpDosTask->img=mmap(NULL,0x110000-START_OFFSET,PROT_READ|PROT_WRITE,MAP_SHARED,lpDosTask->mm_fd,0); -#endif - if (lpDosTask->img==(LPVOID)-1) { - ERR("could not map shared memory, error=%s\n",strerror(errno)); - return FALSE; - } - TRACE("DOS VM86 image mapped at %08lx\n",(DWORD)lpDosTask->img); + /* initialize the memory */ + TRACE("Initializing DOS memory structures\n"); + DOSMEM_Init(TRUE); - /* initialize the memory */ - TRACE("Initializing DOS memory structures\n"); - DOSMEM_Init(TRUE); - MZ_InitHandlers(lpDosTask); - MZ_InitXMS(lpDosTask); - MZ_InitDPMI(lpDosTask); - return TRUE; + /* allocate 1MB+64K shared memory */ + tmpnam(mm_name); + /* strcpy(mm_name,"/tmp/mydosimage"); */ + mm_fd = open(mm_name,O_RDWR|O_CREAT /* |O_TRUNC */,S_IRUSR|S_IWUSR); + if (mm_fd < 0) ERR("file %s could not be opened\n",mm_name); + /* fill the file with the DOS memory */ + if (write( mm_fd, NULL, 0x110000 ) != 0x110000) ERR("cannot write DOS mem\n"); + /* map it in */ + img_base = mmap(NULL,0x110000,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED|MAP_FIXED,mm_fd,0); + close( mm_fd ); + + if (img_base) + { + ERR("could not map shared memory, error=%s\n",strerror(errno)); + return FALSE; + } + MZ_InitHandlers(); + return TRUE; } BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ) @@ -235,7 +187,7 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ) BYTE*psp_start,*load_start; int x, old_com=0, alloc=0; SEGPTR reloc; - WORD env_seg; + WORD env_seg, load_seg; DWORD len; win_hdr->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; @@ -244,7 +196,6 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ) if (!lpDosTask) { alloc=1; lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK)); - lpDosTask->mm_fd = -1; dos_current = lpDosTask; } @@ -269,10 +220,10 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ) max_size=image_size+((DWORD)mz_header.e_maxalloc<<4)+(PSP_SIZE<<4); } - MZ_InitMemory(lpDosTask); + MZ_InitMemory(); /* allocate environment block */ - env_seg=MZ_InitEnvironment(lpDosTask,GetEnvironmentStringsA(),filename); + env_seg=MZ_InitEnvironment(GetEnvironmentStringsA(),filename); /* allocate memory for the executable */ TRACE("Allocating DOS memory (min=%ld, max=%ld)\n",min_size,max_size); @@ -289,7 +240,7 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ) SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto load_error; } - lpDosTask->load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE); + load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE); load_start=psp_start+(PSP_SIZE<<4); MZ_CreatePSP(psp_start, env_seg); @@ -311,19 +262,19 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ) SetLastError(ERROR_BAD_FORMAT); goto load_error; } - *(WORD*)SEGPTR16(load_start,reloc)+=lpDosTask->load_seg; + *(WORD*)SEGPTR16(load_start,reloc)+=load_seg; } } - lpDosTask->init_cs=lpDosTask->load_seg+mz_header.e_cs; - lpDosTask->init_ip=mz_header.e_ip; - lpDosTask->init_ss=lpDosTask->load_seg+mz_header.e_ss; - lpDosTask->init_sp=mz_header.e_sp; + init_cs = load_seg+mz_header.e_cs; + init_ip = mz_header.e_ip; + init_ss = load_seg+mz_header.e_ss; + init_sp = mz_header.e_sp; - TRACE("entry point: %04x:%04x\n",lpDosTask->init_cs,lpDosTask->init_ip); + TRACE("entry point: %04x:%04x\n",init_cs,init_ip); - if (!MZ_InitTask(lpDosTask)) { - MZ_KillTask(lpDosTask); + if (!MZ_InitTask()) { + MZ_KillTask(); SetLastError(ERROR_GEN_FAILURE); return FALSE; } @@ -333,12 +284,7 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ) load_error: if (alloc) { dos_current = NULL; - if (lpDosTask->mm_name[0]!=0) { - if (lpDosTask->img!=NULL) munmap(lpDosTask->img,0x110000-START_OFFSET); - if (lpDosTask->mm_fd>=0) close(lpDosTask->mm_fd); - unlink(lpDosTask->mm_name); - } else - if (lpDosTask->img!=NULL) VirtualFree(lpDosTask->img,0x110000,MEM_RELEASE); + if (mm_name[0]!=0) unlink(mm_name); } return FALSE; @@ -349,14 +295,14 @@ LPDOSTASK MZ_AllocDPMITask( void ) LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK)); if (lpDosTask) { - lpDosTask->mm_fd = -1; dos_current = lpDosTask; - MZ_InitMemory(lpDosTask); + MZ_InitMemory(); + MZ_InitTask(); } return lpDosTask; } -static void MZ_InitTimer( LPDOSTASK lpDosTask, int ver ) +static void MZ_InitTimer( int ver ) { if (ver<1) { /* can't make timer ticks */ @@ -367,55 +313,42 @@ static void MZ_InitTimer( LPDOSTASK lpDosTask, int ver ) /* start dosmod timer at 55ms (18.2Hz) */ func=DOSMOD_SET_TIMER; tim.tv_sec=0; tim.tv_usec=54925; - write(lpDosTask->write_pipe,&func,sizeof(func)); - write(lpDosTask->write_pipe,&tim,sizeof(tim)); + write(write_pipe,&func,sizeof(func)); + write(write_pipe,&tim,sizeof(tim)); } } -BOOL MZ_InitTask( LPDOSTASK lpDosTask ) +static BOOL MZ_InitTask(void) { int write_fd[2],x_fd; pid_t child; - char *fname,*farg,arg[16],fproc[64],path[256],*fpath; + char path[256],*fpath; - if (!lpDosTask) return FALSE; /* create pipes */ - if (!CreatePipe(&(lpDosTask->hReadPipe),&(lpDosTask->hXPipe),NULL,0)) return FALSE; + if (!CreatePipe(&hReadPipe,&hWritePipe,NULL,0)) return FALSE; if (pipe(write_fd)<0) { - CloseHandle(lpDosTask->hReadPipe); - CloseHandle(lpDosTask->hXPipe); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); return FALSE; } - lpDosTask->read_pipe = FILE_GetUnixHandle( lpDosTask->hReadPipe, GENERIC_READ ); - x_fd = FILE_GetUnixHandle( lpDosTask->hXPipe, GENERIC_WRITE ); + read_pipe = FILE_GetUnixHandle( hReadPipe, GENERIC_READ ); + x_fd = FILE_GetUnixHandle( hWritePipe, GENERIC_WRITE ); TRACE("win32 pipe: read=%d, write=%d, unix pipe: read=%d, write=%d\n", - lpDosTask->hReadPipe,lpDosTask->hXPipe,lpDosTask->read_pipe,x_fd); + hReadPipe,hWritePipe,read_pipe,x_fd); TRACE("outbound unix pipe: read=%d, write=%d, pid=%d\n",write_fd[0],write_fd[1],getpid()); - lpDosTask->write_pipe=write_fd[1]; - - lpDosTask->hConInput=GetStdHandle(STD_INPUT_HANDLE); - lpDosTask->hConOutput=GetStdHandle(STD_OUTPUT_HANDLE); - - /* if we have a mapping file, use it */ - fname=lpDosTask->mm_name; farg=NULL; - if (!fname[0]) { - /* otherwise, map our own memory image */ - sprintf(fproc,"/proc/%d/mem",getpid()); - sprintf(arg,"%ld",(unsigned long)lpDosTask->img); - fname=fproc; farg=arg; - } + write_pipe=write_fd[1]; TRACE("Loading DOS VM support module\n"); if ((child=fork())<0) { close(write_fd[0]); - close(lpDosTask->read_pipe); - close(lpDosTask->write_pipe); + close(read_pipe); + close(write_pipe); close(x_fd); - CloseHandle(lpDosTask->hReadPipe); - CloseHandle(lpDosTask->hXPipe); + CloseHandle(hReadPipe); + CloseHandle(hWritePipe); return FALSE; } if (child!=0) { @@ -424,21 +357,21 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask ) close(write_fd[0]); close(x_fd); - lpDosTask->task=child; + dosmod_pid = child; /* wait for child process to signal readiness */ while (1) { - if (read(lpDosTask->read_pipe,&ret,sizeof(ret))==sizeof(ret)) break; + if (read(read_pipe,&ret,sizeof(ret))==sizeof(ret)) break; if ((errno==EINTR)||(errno==EAGAIN)) continue; /* failure */ ERR("dosmod has failed to initialize\n"); - if (lpDosTask->mm_name[0]!=0) unlink(lpDosTask->mm_name); + if (mm_name[0]!=0) unlink(mm_name); return FALSE; } /* the child has now mmaped the temp file, it's now safe to unlink. * do it here to avoid leaving a mess in /tmp if/when Wine crashes... */ - if (lpDosTask->mm_name[0]!=0) unlink(lpDosTask->mm_name); + if (mm_name[0]!=0) unlink(mm_name); /* start simulated system timer */ - MZ_InitTimer(lpDosTask,ret); + MZ_InitTimer(ret); if (ret<2) { ERR("dosmod version too old! Please install newer dosmod properly\n"); ERR("If you don't, the new dosmod event handling system will not work\n"); @@ -446,8 +379,8 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask ) /* all systems are now go */ } else { /* child process */ - close(lpDosTask->read_pipe); - close(lpDosTask->write_pipe); + close(read_pipe); + close(write_pipe); /* put our pipes somewhere dosmod can find them */ dup2(write_fd[0],0); /* stdin */ dup2(x_fd,1); /* stdout */ @@ -457,16 +390,16 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask ) fpath=strrchr(strcpy(path,full_argv0),'/'); if (fpath) { strcpy(fpath,"/dosmod"); - execl(path,fname,farg,NULL); + execl(path,mm_name,NULL); strcpy(fpath,"/loader/dos/dosmod"); - execl(path,fname,farg,NULL); + execl(path,mm_name,NULL); } /* okay, it wasn't there, try in the path */ - execlp("dosmod",fname,farg,NULL); + execlp("dosmod",mm_name,NULL); /* last desperate attempts: current directory */ - execl("dosmod",fname,farg,NULL); + execl("dosmod",mm_name,NULL); /* and, just for completeness... */ - execl("loader/dos/dosmod",fname,farg,NULL); + execl("loader/dos/dosmod",mm_name,NULL); /* if failure, exit */ ERR("Failed to spawn dosmod, error=%s\n",strerror(errno)); exit(1); @@ -477,53 +410,29 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask ) static void MZ_Launch(void) { LPDOSTASK lpDosTask = MZ_Current(); - BYTE *psp_start = (BYTE*)lpDosTask->img + ((DWORD)lpDosTask->psp_seg << 4); + CONTEXT context; + TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); + BYTE *psp_start = PTR_REAL_TO_LIN( lpDosTask->psp_seg, 0 ); MZ_FillPSP(psp_start, GetCommandLineA()); + pTask->flags |= TDBF_WINOLDAP; - DOSVM_Enter(NULL); + memset( &context, 0, sizeof(context) ); + context.SegCs = init_cs; + context.Eip = init_ip; + context.SegSs = init_ss; + context.Esp = init_sp; + context.SegDs = lpDosTask->psp_seg; + context.SegEs = lpDosTask->psp_seg; + context.EFlags = 0x00080000; /* virtual interrupt flag */ + DOSVM_Enter( &context ); } -void MZ_KillTask( LPDOSTASK lpDosTask ) +static void MZ_KillTask(void) { - DOSEVENT *event,*p_event; - DOSSYSTEM *sys,*p_sys; - TRACE("killing DOS task\n"); VGA_Clean(); - if (lpDosTask->mm_name[0]!=0) { - munmap(lpDosTask->img,0x110000-START_OFFSET); - close(lpDosTask->mm_fd); - } else VirtualFree(lpDosTask->img,0x110000,MEM_RELEASE); - close(lpDosTask->read_pipe); - close(lpDosTask->write_pipe); - CloseHandle(lpDosTask->hReadPipe); - CloseHandle(lpDosTask->hXPipe); - kill(lpDosTask->task,SIGTERM); -/* free memory allocated for events and systems */ -#define DFREE(var,pvar,svar) \ - var = lpDosTask->svar; \ - while (var) { \ - if (var->data) free(var->data); \ - pvar = var->next; free(var); var = pvar; \ - } - - DFREE(event,p_event,pending) - DFREE(event,p_event,current) - DFREE(sys,p_sys,sys) - -#undef DFREE - -#if 0 - /* FIXME: this seems to crash */ - if (lpDosTask->dpmi_sel) - SELECTOR_FreeBlock(lpDosTask->dpmi_sel, 1); -#endif -} - -LPDOSTASK MZ_Current( void ) -{ - return dos_current; + kill(dosmod_pid,SIGTERM); } #else /* !MZ_SUPPORTED */ @@ -535,9 +444,15 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename ) return FALSE; } -LPDOSTASK MZ_Current( void ) +LPDOSTASK MZ_AllocDPMITask( void ) { - return NULL; + ERR("Actual real-mode calls not supported on this architecture!\n"); + return NULL; } -#endif +#endif /* !MZ_SUPPORTED */ + +LPDOSTASK MZ_Current( void ) +{ + return dos_current; +} diff --git a/loader/task.c b/loader/task.c index adcee6a05b4..6b29425e53b 100644 --- a/loader/task.c +++ b/loader/task.c @@ -29,13 +29,13 @@ #include "winsock.h" #include "syslevel.h" #include "debugtools.h" -#include "dosexe.h" #include "services.h" #include "server.h" -DEFAULT_DEBUG_CHANNEL(task) -DECLARE_DEBUG_CHANNEL(relay) -DECLARE_DEBUG_CHANNEL(toolhelp) + +DEFAULT_DEBUG_CHANNEL(task); +DECLARE_DEBUG_CHANNEL(relay); +DECLARE_DEBUG_CHANNEL(toolhelp); /* Min. number of thunks allocated when creating a new segment */ #define MIN_THUNKS 32 @@ -243,7 +243,6 @@ BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline, /* NOTE: for 16-bit tasks, the instance handles are updated later on in NE_InitProcess */ } - if (MZ_Current() && MZ_Current()->load_seg) pTask->flags |= TDBF_WINOLDAP; pTask->version = pModule->expected_version; pTask->hModule = pModule->self; diff --git a/memory/instr.c b/memory/instr.c index 39b439ba49c..34fbda80913 100644 --- a/memory/instr.c +++ b/memory/instr.c @@ -29,7 +29,7 @@ inline static void add_stack( CONTEXT86 *context, int offset ) inline static void *make_ptr( CONTEXT86 *context, DWORD seg, DWORD off, int long_addr ) { - if (ISV86(context)) return DOSMEM_MemoryBase() + (seg << 4) + LOWORD(off); + if (ISV86(context)) return PTR_REAL_TO_LIN( seg, off ); if (IS_SELECTOR_SYSTEM(seg)) return (void *)off; if (!long_addr) off = LOWORD(off); return PTR_SEG_OFF_TO_LIN( seg, off ); @@ -38,7 +38,7 @@ inline static void *make_ptr( CONTEXT86 *context, DWORD seg, DWORD off, int long inline static void *get_stack( CONTEXT86 *context ) { if (ISV86(context)) - return DOSMEM_MemoryBase() + (context->SegSs << 4) + LOWORD(context->Esp); + return PTR_REAL_TO_LIN( context->SegSs, context->Esp ); if (IS_SELECTOR_SYSTEM(context->SegSs)) return (void *)context->Esp; if (IS_SELECTOR_32BIT(context->SegSs)) diff --git a/msdos/devices.c b/msdos/devices.c index a3d08639d5b..3fcccba26dd 100644 --- a/msdos/devices.c +++ b/msdos/devices.c @@ -47,8 +47,9 @@ typedef struct { #define CON_BUFFER 128 -#define SYSTEM_STRATEGY_NUL 0x0100 -#define SYSTEM_STRATEGY_CON 0x0101 +enum strategy { SYSTEM_STRATEGY_NUL, SYSTEM_STRATEGY_CON, NB_SYSTEM_STRATEGIES }; + +static void *strategy_data[NB_SYSTEM_STRATEGIES]; #define NONEXT ((DWORD)-1) @@ -150,20 +151,19 @@ static void do_lret(CONTEXT86*ctx) static void do_strategy(CONTEXT86*ctx, int id, int extra) { REQUEST_HEADER *hdr = CTX_SEG_OFF_TO_LIN(ctx, ES_reg(ctx), EBX_reg(ctx)); - void **hdr_ptr = DOSVM_GetSystemData(id); + void **hdr_ptr = strategy_data[id]; if (!hdr_ptr) { hdr_ptr = calloc(1,sizeof(void *)+extra); - DOSVM_SetSystemData(id, hdr_ptr); + strategy_data[id] = hdr_ptr; } - *hdr_ptr = hdr; do_lret(ctx); } static REQUEST_HEADER * get_hdr(int id, void**extra) { - void **hdr_ptr = DOSVM_GetSystemData(id); + void **hdr_ptr = strategy_data[id]; if (extra) *extra = hdr_ptr ? (void*)(hdr_ptr+1) : (void *)NULL; return hdr_ptr ? *hdr_ptr : (void *)NULL; @@ -209,7 +209,6 @@ static void WINAPI con_interrupt(CONTEXT86*ctx) BYTE *curbuffer = (lol->offs_unread_CON) ? (((BYTE*)dataseg) + lol->offs_unread_CON) : (BYTE*)NULL; DOS_DEVICE_HEADER *con = dataseg->dev; - LPDOSTASK lpDosTask = MZ_Current(); switch (hdr->command) { case CMD_INPUT: @@ -301,7 +300,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx) /* a character */ if ((len+1)hConOutput, &linebuffer[len++], 1, NULL, NULL); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &linebuffer[len++], 1, NULL, NULL); } /* else beep, but I don't like noise */ } @@ -309,7 +308,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx) case '\b': if (len>0) { len--; - WriteFile(lpDosTask->hConOutput, "\b \b", 3, NULL, NULL); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\b \b", 3, NULL, NULL); } break; } @@ -377,7 +376,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx) SELECTOROF(io->buffer), (DWORD)OFFSETOF(io->buffer)); DWORD result = 0; - WriteFile(lpDosTask->hConOutput, buffer, io->count, &result, NULL); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buffer, io->count, &result, NULL); io->count = result; hdr->status = STAT_DONE; } diff --git a/msdos/dosmem.c b/msdos/dosmem.c index ac4134008e6..cf632eb7cef 100644 --- a/msdos/dosmem.c +++ b/msdos/dosmem.c @@ -5,30 +5,33 @@ * Copyright 1996 Marcus Meissner */ +#include "config.h" + #include #include #include +#ifdef HAVE_SYS_MMAN_H +# include +#endif + #include "winbase.h" #include "wine/winbase16.h" + #include "global.h" #include "ldt.h" +#include "selectors.h" #include "miscemu.h" #include "vga.h" #include "dosexe.h" #include "debugtools.h" -DEFAULT_DEBUG_CHANNEL(dosmem) -DECLARE_DEBUG_CHANNEL(selector) +DEFAULT_DEBUG_CHANNEL(dosmem); +DECLARE_DEBUG_CHANNEL(selector); HANDLE16 DOSMEM_BiosDataSeg; /* BIOS data segment at 0x40:0 */ HANDLE16 DOSMEM_BiosSysSeg; /* BIOS ROM segment at 0xf000:0 */ -static char *DOSMEM_dosmem; - - DWORD DOSMEM_CollateTable; - - DWORD DOSMEM_ErrorCall; - DWORD DOSMEM_ErrorBuffer; +DWORD DOSMEM_CollateTable; /* use 2 low bits of 'size' for the housekeeping */ @@ -57,6 +60,17 @@ typedef struct { #define VM_STUB(x) (0x90CF00CD|(x<<8)) /* INT x; IRET; NOP */ #define VM_STUB_SEGMENT 0xf000 /* BIOS segment */ +/* DOS memory base */ +static char *DOSMEM_dosmem; +/* bios area; normally at offset 0x400, but can be moved to trap NULL pointers */ +static void *DOSMEM_biosdata; + +/* various real-mode code stubs */ +WORD DOSMEM_wrap_seg; +WORD DOSMEM_xms_seg; +WORD DOSMEM_dpmi_seg; +WORD DOSMEM_dpmi_sel; + /*********************************************************************** * DOSMEM_MemoryBase * @@ -64,12 +78,7 @@ typedef struct { */ char *DOSMEM_MemoryBase(void) { - LPDOSTASK lpDosTask = MZ_Current(); - - if (lpDosTask && lpDosTask->img) - return lpDosTask->img; - else - return DOSMEM_dosmem; + return DOSMEM_dosmem; } /*********************************************************************** @@ -79,7 +88,7 @@ char *DOSMEM_MemoryBase(void) */ static char *DOSMEM_MemoryTop(void) { - return DOSMEM_MemoryBase()+0x9FFFC; /* 640K */ + return DOSMEM_dosmem+0x9FFFC; /* 640K */ } /*********************************************************************** @@ -89,7 +98,7 @@ static char *DOSMEM_MemoryTop(void) */ static dosmem_info *DOSMEM_InfoBlock(void) { - return (dosmem_info*)(DOSMEM_MemoryBase()+0x10000); /* 64K */ + return (dosmem_info*)(DOSMEM_dosmem+0x10000); /* 64K */ } /*********************************************************************** @@ -118,7 +127,7 @@ static dosmem_entry *DOSMEM_RootBlock(void) */ static void DOSMEM_FillIsrTable(void) { - SEGPTR *isr = (SEGPTR*)DOSMEM_MemoryBase(); + SEGPTR *isr = (SEGPTR*)DOSMEM_dosmem; DWORD *stub = (DWORD*)((char*)isr + (VM_STUB_SEGMENT << 4)); int x; @@ -133,24 +142,66 @@ static void DOSMEM_FillIsrTable(void) */ static void DOSMEM_InitDPMI(void) { - extern UINT16 DPMI_wrap_seg; - static char wrap_code[]={ + LPSTR ptr; + + static const char wrap_code[]={ 0xCD,0x31, /* int $0x31 */ 0xCB /* lret */ }; - LPSTR wrapper = (LPSTR)DOSMEM_GetBlock(sizeof(wrap_code), &DPMI_wrap_seg); - memcpy(wrapper, wrap_code, sizeof(wrap_code)); + static const char enter_xms[]= + { + /* XMS hookable entry point */ + 0xEB,0x03, /* jmp entry */ + 0x90,0x90,0x90, /* nop;nop;nop */ + /* entry: */ + /* real entry point */ + /* for simplicity, we'll just use the same hook as DPMI below */ + 0xCD,0x31, /* int $0x31 */ + 0xCB /* lret */ + }; + + static const char enter_pm[]= + { + 0x50, /* pushw %ax */ + 0x52, /* pushw %dx */ + 0x55, /* pushw %bp */ + 0x89,0xE5, /* movw %sp,%bp */ + /* get return CS */ + 0x8B,0x56,0x08, /* movw 8(%bp),%dx */ + /* just call int 31 here to get into protected mode... */ + /* it'll check whether it was called from dpmi_seg... */ + 0xCD,0x31, /* int $0x31 */ + /* we are now in the context of a 16-bit relay call */ + /* need to fixup our stack; + * 16-bit relay return address will be lost, but we won't worry quite yet */ + 0x8E,0xD0, /* movw %ax,%ss */ + 0x66,0x0F,0xB7,0xE5, /* movzwl %bp,%esp */ + /* set return CS */ + 0x89,0x56,0x08, /* movw %dx,8(%bp) */ + 0x5D, /* popw %bp */ + 0x5A, /* popw %dx */ + 0x58, /* popw %ax */ + 0xCB /* lret */ + }; + + ptr = DOSMEM_GetBlock( sizeof(wrap_code), &DOSMEM_wrap_seg ); + memcpy( ptr, wrap_code, sizeof(wrap_code) ); + ptr = DOSMEM_GetBlock( sizeof(enter_xms), &DOSMEM_xms_seg ); + memcpy( ptr, enter_xms, sizeof(enter_xms) ); + ptr = DOSMEM_GetBlock( sizeof(enter_pm), &DOSMEM_dpmi_seg ); + memcpy( ptr, enter_pm, sizeof(enter_pm) ); + DOSMEM_dpmi_sel = SELECTOR_AllocBlock( ptr, sizeof(enter_pm), SEGMENT_CODE, FALSE, FALSE ); } BIOSDATA * DOSMEM_BiosData() { - return (BIOSDATA *)(DOSMEM_MemoryBase()+0x400); + return (BIOSDATA *)DOSMEM_biosdata; } BYTE * DOSMEM_BiosSys() { - return DOSMEM_MemoryBase()+0xf0000; + return DOSMEM_dosmem+0xf0000; } struct _DOS_LISTOFLISTS * DOSMEM_LOL() @@ -293,6 +344,7 @@ static void DOSMEM_InitCollateTable() */ static void DOSMEM_InitErrorTable() { +#if 0 /* no longer used */ DWORD x; char *call; @@ -336,7 +388,7 @@ static void DOSMEM_InitErrorTable() call = DOSMEM_MapRealToLinear(DOSMEM_ErrorCall); memset(call, 0, SIZE_TO_ALLOCATE); - +#endif /* Fixme - Copy assembly into buffer here */ } @@ -368,28 +420,56 @@ static void DOSMEM_InitMemory(void) ; } -/*********************************************************************** - * DOSMEM_MovePointers +/********************************************************************** + * setup_dos_mem * - * Relocates any pointers into DOS memory to a new address space. + * Setup the first megabyte for DOS memory access */ -static void DOSMEM_MovePointers(LPVOID dest, LPVOID src, DWORD size) +static void setup_dos_mem( int dos_init ) { - unsigned long delta = (char *) dest - (char *) src; - unsigned cnt; - ldt_entry ent; + int bios_offset = 0x400; + int page_size = VIRTUAL_GetPageSize(); + void *addr = VIRTUAL_mmap( -1, (void *)page_size, 0x110000-page_size, 0, + PROT_READ | PROT_WRITE | PROT_EXEC, 0 ); + if (addr == (void *)page_size) /* we got what we wanted */ + { + /* now map from address 0 */ + addr = VIRTUAL_mmap( -1, NULL, 0x110000, 0, + PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED ); + if (addr) + { + ERR("MAP_FIXED failed at address 0 for DOS address space\n" ); + ExitProcess(1); + } - /* relocate base addresses of any selectors pointing into memory */ - for (cnt=FIRST_LDT_ENTRY_TO_ALLOC; cnt= (unsigned long)src) && \ - (ent.base < ((unsigned long)src + size))) { - ent.base += delta; - LDT_SetEntry(cnt, &ent); + /* inform the memory manager that there is a mapping here */ + VirtualAlloc( addr, 0x110000, MEM_RESERVE | MEM_SYSTEM, PAGE_EXECUTE_READWRITE ); + + /* protect the first 64K to catch NULL pointers */ + if (!dos_init) + { + VirtualProtect( addr, 0x10000, PAGE_NOACCESS, NULL ); + /* move the BIOS data from 0x400 to 0xf0400 */ + bios_offset += 0xf0000; + } } - } + else + { + ERR("Cannot use first megabyte for DOS address space, please report\n" ); + if (dos_init) ExitProcess(1); + /* allocate the DOS area somewhere else */ + addr = VirtualAlloc( NULL, 0x110000, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + if (!addr) + { + ERR( "Cannot allocate DOS memory\n" ); + ExitProcess(1); + } + } + DOSMEM_dosmem = addr; + DOSMEM_biosdata = (char *)addr + bios_offset; } + /*********************************************************************** * DOSMEM_Init * @@ -398,44 +478,41 @@ static void DOSMEM_MovePointers(LPVOID dest, LPVOID src, DWORD size) */ BOOL DOSMEM_Init(BOOL dos_init) { - LPVOID base = DOSMEM_MemoryBase(); - BOOL do_init = dos_init && !DOSMEM_dosmem; + static int already_done; - if (!base) + if (!already_done) { - /* Allocate 1 MB dosmemory - */ - DOSMEM_dosmem = VirtualAlloc( NULL, 0x100000, MEM_COMMIT, - PAGE_EXECUTE_READWRITE ); - if (!DOSMEM_dosmem) - { - WARN("Could not allocate DOS memory.\n" ); - return FALSE; - } - DOSMEM_BiosDataSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_dosmem+0x400, - 0x100, 0, FALSE, FALSE, FALSE ); - DOSMEM_BiosSysSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_dosmem+0xf0000, - 0x10000, 0, FALSE, FALSE, FALSE ); - base = DOSMEM_dosmem; - do_init = TRUE; - } + setup_dos_mem( dos_init ); - if (do_init) { - DOSMEM_FillIsrTable(); + DOSMEM_BiosDataSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_biosdata, + 0x100, 0, FALSE, FALSE, FALSE ); + DOSMEM_BiosSysSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_dosmem+0xf0000, + 0x10000, 0, FALSE, FALSE, FALSE ); DOSMEM_FillBiosSegments(); DOSMEM_InitMemory(); DOSMEM_InitCollateTable(); DOSMEM_InitErrorTable(); DOSMEM_InitDPMI(); - DOSDEV_InstallDOSDevices(); + DOSDEV_InstallDOSDevices(); + already_done = 1; } else if (dos_init) { - /* bootstrap the new V86 task with a copy of the "system" memory */ - memcpy(base, DOSMEM_dosmem, 0x100000); - /* then move existing selectors to it */ - DOSMEM_MovePointers(base, DOSMEM_dosmem, 0x100000); + if (DOSMEM_dosmem) + { + ERR( "Needs access to the first megabyte for DOS mode\n" ); + ExitProcess(1); + } + MESSAGE( "Warning: unprotecting the first 64KB of memory to allow real-mode calls.\n" + " NULL pointer accesses will no longer be caught.\n" ); + VirtualProtect( NULL, 0x10000, PAGE_EXECUTE_READWRITE, NULL ); + /* copy the BIOS area down to 0x400 */ + memcpy( DOSMEM_dosmem + 0x400, DOSMEM_biosdata, 0x100 ); + DOSMEM_biosdata = DOSMEM_dosmem + 0x400; + SetSelectorBase( DOSMEM_BiosDataSeg, 0x400 ); } + /* interrupt table is at addr 0, so only do this when setting up DOS mode */ + if (dos_init) DOSMEM_FillIsrTable(); return TRUE; } @@ -513,7 +590,7 @@ LPVOID DOSMEM_GetBlock(UINT size, UINT16* pseg) info_block->blocks++; info_block->free -= dm->size; - if( pseg ) *pseg = (block - DOSMEM_MemoryBase()) >> 4; + if( pseg ) *pseg = (block - DOSMEM_dosmem) >> 4; #ifdef __DOSMEM_DEBUG__ dm->size |= DM_BLOCK_DEBUG; #endif @@ -535,7 +612,7 @@ BOOL DOSMEM_FreeBlock(void* ptr) if( ptr >= (void*)(((char*)DOSMEM_RootBlock()) + sizeof(dosmem_entry)) && ptr < (void*)DOSMEM_MemoryTop() && !((((char*)ptr) - - DOSMEM_MemoryBase()) & 0xf) ) + - DOSMEM_dosmem) & 0xf) ) { dosmem_entry *dm = (dosmem_entry*)(((char*)ptr) - sizeof(dosmem_entry)); @@ -565,11 +642,11 @@ LPVOID DOSMEM_ResizeBlock(void* ptr, UINT size, UINT16* pseg) if( ptr >= (void*)(((char*)DOSMEM_RootBlock()) + sizeof(dosmem_entry)) && ptr < (void*)DOSMEM_MemoryTop() && !((((char*)ptr) - - DOSMEM_MemoryBase()) & 0xf) ) + - DOSMEM_dosmem) & 0xf) ) { dosmem_entry *dm = (dosmem_entry*)(((char*)ptr) - sizeof(dosmem_entry)); - if( pseg ) *pseg = ((char*)ptr - DOSMEM_MemoryBase()) >> 4; + if( pseg ) *pseg = ((char*)ptr - DOSMEM_dosmem) >> 4; if( !(dm->size & (DM_BLOCK_FREE | DM_BLOCK_TERMINAL)) ) @@ -689,9 +766,9 @@ UINT DOSMEM_Available(void) */ UINT DOSMEM_MapLinearToDos(LPVOID ptr) { - if (((char*)ptr >= DOSMEM_MemoryBase()) && - ((char*)ptr < DOSMEM_MemoryBase() + 0x100000)) - return (UINT)ptr - (UINT)DOSMEM_MemoryBase(); + if (((char*)ptr >= DOSMEM_dosmem) && + ((char*)ptr < DOSMEM_dosmem + 0x100000)) + return (UINT)ptr - (UINT)DOSMEM_dosmem; return (UINT)ptr; } @@ -703,7 +780,7 @@ UINT DOSMEM_MapLinearToDos(LPVOID ptr) */ LPVOID DOSMEM_MapDosToLinear(UINT ptr) { - if (ptr < 0x100000) return (LPVOID)(ptr + (UINT)DOSMEM_MemoryBase()); + if (ptr < 0x100000) return (LPVOID)(ptr + (UINT)DOSMEM_dosmem); return (LPVOID)ptr; } @@ -717,7 +794,7 @@ LPVOID DOSMEM_MapRealToLinear(DWORD x) { LPVOID lin; - lin=DOSMEM_MemoryBase()+(x&0xffff)+(((x&0xffff0000)>>16)*16); + lin=DOSMEM_dosmem+(x&0xffff)+(((x&0xffff0000)>>16)*16); TRACE_(selector)("(0x%08lx) returns 0x%p.\n", x, lin ); return lin; } diff --git a/msdos/dpmi.c b/msdos/dpmi.c index be2a5964b35..d116467db21 100644 --- a/msdos/dpmi.c +++ b/msdos/dpmi.c @@ -62,7 +62,6 @@ typedef struct tagRMCB { static RMCB *FirstRMCB = NULL; -UINT16 DPMI_wrap_seg; /********************************************************************** * DPMI_xalloc @@ -261,7 +260,7 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag ) DWORD esp,edi; INT_SetRealModeContext((REALMODECALL *)PTR_SEG_OFF_TO_LIN( rmcb->regs_sel, rmcb->regs_ofs ), context); - ss = SELECTOR_AllocBlock( DOSMEM_MemoryBase() + (DWORD)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, FALSE, FALSE ); + ss = SELECTOR_AllocBlock( (void *)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, FALSE, FALSE ); esp = ESP_reg(context); FIXME("untested!\n"); @@ -354,17 +353,12 @@ callrmproc_again: CurrRMCB = CurrRMCB->next; if (!(CurrRMCB || lpDosTask)) { -#ifdef MZ_SUPPORTED FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n"); TRACE("creating VM86 task\n"); - if (!MZ_InitTask( lpDosTask = MZ_AllocDPMITask() )) { + if (!(lpDosTask = MZ_AllocDPMITask() )) { ERR("could not setup VM86 task\n"); return 1; } -#else - ERR("Actual real-mode calls not supported on this architecture!\n"); - return 1; -#endif } if (!already) { if (!SS_reg(context)) { @@ -388,7 +382,7 @@ callrmproc_again: *stack16 = LOWORD(EFL_reg(context)); } /* push return address (return to interrupt wrapper) */ - *(--stack16) = DPMI_wrap_seg; + *(--stack16) = DOSMEM_wrap_seg; *(--stack16) = 0; /* adjust stack */ ESP_reg(context) -= 2*sizeof(WORD); @@ -399,21 +393,16 @@ callrmproc_again: /* RMCB call, invoke protected-mode handler directly */ DPMI_CallRMCBProc(context, CurrRMCB, lpDosTask ? lpDosTask->dpmi_flag : 0); /* check if we returned to where we thought we would */ - if ((CS_reg(context) != DPMI_wrap_seg) || + if ((CS_reg(context) != DOSMEM_wrap_seg) || (LOWORD(EIP_reg(context)) != 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 { -#ifdef MZ_SUPPORTED TRACE("entering real mode...\n"); DOSVM_Enter( context ); TRACE("returned from real-mode call\n"); -#else - /* we should never get here, but... */ - ERR("cannot perform real-mode call\n"); -#endif } if (alloc) DOSMEM_FreeBlock( addr ); return 0; @@ -585,16 +574,14 @@ void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc ) } -#ifdef MZ_SUPPORTED -/* (see loader/dos/module.c, function MZ_InitDPMI) */ +/* (see dosmem.c, function DOSMEM_InitDPMI) */ static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask ) { - char *base = DOSMEM_MemoryBase(); UINT16 cs, ss, ds, es; CONTEXT86 pm_ctx; DWORD psp_ofs = (DWORD)(lpDosTask->psp_seg<<4); - PDB16 *psp = (PDB16 *)(base + psp_ofs); + PDB16 *psp = (PDB16 *)psp_ofs; HANDLE16 env_seg = psp->environment; int is32; @@ -602,22 +589,22 @@ static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask ) lpDosTask->dpmi_flag = AX_reg(context); is32 = lpDosTask->dpmi_flag & 1; /* our mode switch wrapper have placed the desired CS into DX */ - cs = SELECTOR_AllocBlock( base + (DWORD)(DX_reg(context)<<4), 0x10000, SEGMENT_CODE, FALSE, FALSE ); + cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, SEGMENT_CODE, FALSE, FALSE ); /* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing 32-bit code using this stack. */ - ss = SELECTOR_AllocBlock( base + (DWORD)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, is32, FALSE ); + ss = SELECTOR_AllocBlock( (void *)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, is32, FALSE ); /* do the same for the data segments, just in case */ if (DS_reg(context) == SS_reg(context)) ds = ss; - else ds = SELECTOR_AllocBlock( base + (DWORD)(DS_reg(context)<<4), 0x10000, SEGMENT_DATA, is32, FALSE ); - es = SELECTOR_AllocBlock( base + psp_ofs, 0x100, SEGMENT_DATA, is32, FALSE ); + else ds = SELECTOR_AllocBlock( (void *)(DS_reg(context)<<4), 0x10000, SEGMENT_DATA, is32, FALSE ); + es = SELECTOR_AllocBlock( psp, 0x100, SEGMENT_DATA, is32, FALSE ); /* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */ - psp->environment = SELECTOR_AllocBlock( base + (DWORD)(env_seg<<4), + psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4), 0x10000, SEGMENT_DATA, FALSE, FALSE ); pm_ctx = *context; - CS_reg(&pm_ctx) = lpDosTask->dpmi_sel; + CS_reg(&pm_ctx) = DOSMEM_dpmi_sel; /* our mode switch wrapper expects the new CS in DX, and the new SS in AX */ EAX_reg(&pm_ctx) = ss; EDX_reg(&pm_ctx) = cs; @@ -697,26 +684,6 @@ void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context ) } #endif -#else -#if 0 -void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context ) -{ - ERR("don't even think about DPMI raw mode switch without DOS support!\n"); - ExitProcess(1); -} -#endif -#endif - -#define DOS_APP_ISDOS(addr,base) ((addr) < 0x110000) -#define DOS_WINE_ISDOS(addr,base) (((addr) >= (base)) && ((addr) < (base) + 0x110000)) -#define DOS_UC_APPTOWINE(addr,base) ((addr) + (base)) -#define DOS_UC_WINETOAPP(addr,base) ((addr) - (base)) -#define DOS_APPTOWINE(addr,base) (DOS_APP_ISDOS(addr,base) ? DOS_UC_APPTOWINE(addr,base) : (addr)) -#define DOS_WINETOAPP(addr,base) (DOS_WINE_ISDOS(addr,base) ? DOS_UC_WINETOAPP(addr,base) : (addr)) -#define DOS_BADLIMIT(addr,base,limit) \ - ((limit == 0xffffffff) || /* disallow "fat DS" for now */ \ - (DOS_WINE_ISDOS(addr,base) && \ - ((addr) + (limit) > (base) + 0x110000))) /********************************************************************** * INT_Int31Handler @@ -738,16 +705,15 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) LPDOSTASK lpDosTask = MZ_Current(); -#ifdef MZ_SUPPORTED if (ISV86(context) && lpDosTask) { /* Called from real mode, check if it's our wrapper */ TRACE("called from real mode\n"); - if (CS_reg(context)==lpDosTask->dpmi_seg) { + if (CS_reg(context)==DOSMEM_dpmi_seg) { /* This is the protected mode switch */ StartPM(context,lpDosTask); return; } else - if (CS_reg(context)==lpDosTask->xms_seg) { + if (CS_reg(context)==DOSMEM_xms_seg) { /* This is the XMS driver entry point */ XMS_Handler(context); return; @@ -766,7 +732,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) } } } -#endif RESET_CFLAG(context); switch(AX_reg(context)) @@ -849,12 +814,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) } else { -#ifdef MZ_SUPPORTED - if (lpDosTask) { - DWORD base = (DWORD)DOSMEM_MemoryBase(); - dw = DOS_WINETOAPP(dw, base); - } -#endif CX_reg(context) = HIWORD(W32S_WINE2APP(dw, offset)); DX_reg(context) = LOWORD(W32S_WINE2APP(dw, offset)); } @@ -865,40 +824,12 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) BX_reg(context), W32S_APP2WINE(MAKELONG(DX_reg(context),CX_reg(context)), offset)); dw = W32S_APP2WINE(MAKELONG(DX_reg(context), CX_reg(context)), offset); -#ifdef MZ_SUPPORTED - if (lpDosTask) { - DWORD base = (DWORD)DOSMEM_MemoryBase(); - dw = DOS_APPTOWINE(dw, base); - } -#endif SetSelectorBase(BX_reg(context), dw); break; case 0x0008: /* Set selector limit */ TRACE("set selector limit (0x%04x,0x%08lx)\n",BX_reg(context),MAKELONG(DX_reg(context),CX_reg(context))); dw = MAKELONG( DX_reg(context), CX_reg(context) ); -#ifdef MZ_SUPPORTED - if (lpDosTask) { - DWORD base = (DWORD)DOSMEM_MemoryBase(); - DWORD sbase = GetSelectorBase( BX_reg(context) ); - if (!sbase) { - /* the app has set the limit without setting the base, - * it must be relying on that the default should be DOS space; - * so set the base address now */ - SetSelectorBase( BX_reg(context), sbase = base ); - if (dw == 0xffffffff) { - /* djgpp does this without checking (in _dos_ds setup, crt1.c), - * so we have to override the limit here */ - dw = 0x110000; - } - } - if (DOS_BADLIMIT(sbase, base, dw)) { - AX_reg(context) = 0x8021; /* invalid value */ - SET_CFLAG(context); - break; - } - } -#endif SetSelectorLimit16( BX_reg(context), dw ); break; @@ -921,12 +852,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) { ldt_entry entry; LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry ); -#ifdef MZ_SUPPORTED - if (lpDosTask) { - DWORD base = (DWORD)DOSMEM_MemoryBase(); - entry.base = DOS_WINETOAPP(entry.base, base); - } -#endif entry.base = W32S_WINE2APP(entry.base, offset); /* FIXME: should use ES:EDI for 32-bit clients */ @@ -942,18 +867,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( ES_reg(context), DI_reg(context) ), &entry ); entry.base = W32S_APP2WINE(entry.base, offset); -#ifdef MZ_SUPPORTED - if (lpDosTask) { - DWORD base = (DWORD)DOSMEM_MemoryBase(); - entry.base = DOS_APPTOWINE(entry.base, base); - if (DOS_BADLIMIT(entry.base, base, entry.limit)) { - AX_reg(context) = 0x8021; /* invalid value */ - SET_CFLAG(context); - break; - } - } -#endif - LDT_SetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry ); } break; @@ -1032,7 +945,7 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) /* we probably won't need this kind of state saving */ AX_reg(context) = 0; /* real mode: just point to the lret */ - BX_reg(context) = DPMI_wrap_seg; + BX_reg(context) = DOSMEM_wrap_seg; ECX_reg(context) = 2; /* protected mode: don't have any handler yet... */ FIXME("no protected-mode dummy state save/restore handler yet\n"); @@ -1042,18 +955,12 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context ) case 0x0306: /* Get Raw Mode Switch Addresses */ TRACE("get raw mode switch addresses\n"); - if (lpDosTask) { - /* real mode, point to standard DPMI return wrapper */ - BX_reg(context) = DPMI_wrap_seg; - ECX_reg(context) = 0; - /* protected mode, point to DPMI call wrapper */ - SI_reg(context) = lpDosTask->dpmi_sel; - EDI_reg(context) = 8; /* offset of the INT 0x31 call */ - } else { - ERR("win app attempting to get raw mode switch!\n"); - AX_reg(context) = 0x8001; /* unsupported function */ - SET_CFLAG(context); - } + /* real mode, point to standard DPMI return wrapper */ + BX_reg(context) = DOSMEM_wrap_seg; + ECX_reg(context) = 0; + /* protected mode, point to DPMI call wrapper */ + SI_reg(context) = DOSMEM_dpmi_sel; + EDI_reg(context) = 8; /* offset of the INT 0x31 call */ break; case 0x0400: /* Get DPMI version */ TRACE("get DPMI version\n"); diff --git a/msdos/int09.c b/msdos/int09.c index f232b8d4709..6a527e3dccb 100644 --- a/msdos/int09.c +++ b/msdos/int09.c @@ -15,9 +15,11 @@ DEFAULT_DEBUG_CHANNEL(int); #define QUEUELEN 31 -typedef struct { +static struct +{ BYTE queuelen,queue[QUEUELEN],ascii[QUEUELEN]; -} KBDSYSTEM; +} kbdinfo; + /********************************************************************** * INT_Int09Handler @@ -58,48 +60,35 @@ void WINAPI INT_Int09Handler( CONTEXT86 *context ) DOSVM_PIC_ioport_out(0x20, 0x20); /* send EOI */ } -static void KbdRelay( LPDOSTASK lpDosTask, CONTEXT86 *context, void *data ) +static void KbdRelay( CONTEXT86 *context, void *data ) { - KBDSYSTEM *sys = (KBDSYSTEM *)DOSVM_GetSystemData(0x09); - - if (sys && sys->queuelen) { + if (kbdinfo.queuelen) { /* cleanup operation, called from DOSVM_PIC_ioport_out: * we'll remove current scancode from keyboard buffer here, * rather than in ReadScan, because some DOS apps depend on * the scancode being available for reading multiple times... */ - if (--sys->queuelen) { - memmove(sys->queue,sys->queue+1,sys->queuelen); - memmove(sys->ascii,sys->ascii+1,sys->queuelen); + if (--kbdinfo.queuelen) { + memmove(kbdinfo.queue,kbdinfo.queue+1,kbdinfo.queuelen); + memmove(kbdinfo.ascii,kbdinfo.ascii+1,kbdinfo.queuelen); } } } void WINAPI INT_Int09SendScan( BYTE scan, BYTE ascii ) { - KBDSYSTEM *sys = (KBDSYSTEM *)DOSVM_GetSystemData(0x09); - if (!sys) { - sys = calloc(1,sizeof(KBDSYSTEM)); - DOSVM_SetSystemData(0x09,sys); - } - if (sys->queuelen == QUEUELEN) { + if (kbdinfo.queuelen == QUEUELEN) { ERR("keyboard queue overflow\n"); return; } /* add scancode to queue */ - sys->queue[sys->queuelen] = scan; - sys->ascii[sys->queuelen++] = ascii; + kbdinfo.queue[kbdinfo.queuelen] = scan; + kbdinfo.ascii[kbdinfo.queuelen++] = ascii; /* tell app to read it by triggering IRQ 1 (int 09) */ DOSVM_QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL); } BYTE WINAPI INT_Int09ReadScan( BYTE*ascii ) { - KBDSYSTEM *sys = (KBDSYSTEM *)DOSVM_GetSystemData(0x09); - if (sys) { - if (ascii) *ascii = sys->ascii[0]; - return sys->queue[0]; - } else { - if (ascii) *ascii = 0; - return 0; - } + if (ascii) *ascii = kbdinfo.ascii[0]; + return kbdinfo.queue[0]; } diff --git a/msdos/int2f.c b/msdos/int2f.c index dca31b574e4..43a014aaffc 100644 --- a/msdos/int2f.c +++ b/msdos/int2f.c @@ -115,9 +115,7 @@ void WINAPI INT_Int2fHandler( CONTEXT86 *context ) break; case 0x10: /* XMS v2+ get driver address */ { - LPDOSTASK lpDosTask = MZ_Current(); - - ES_reg(context) = lpDosTask ? lpDosTask->xms_seg : 0; + ES_reg(context) = DOSMEM_xms_seg; BX_reg(context) = 0; break; } @@ -349,15 +347,13 @@ static void do_int2f_16( CONTEXT86 *context ) #endif { SYSTEM_INFO si; - LPDOSTASK lpDosTask = MZ_Current(); - GetSystemInfo(&si); AX_reg(context) = 0x0000; /* DPMI Installed */ BX_reg(context) = 0x0001; /* 32bits available */ CL_reg(context) = si.wProcessorLevel; DX_reg(context) = 0x005a; /* DPMI major/minor 0.90 */ SI_reg(context) = 0; /* # of para. of DOS extended private data */ - ES_reg(context) = lpDosTask ? lpDosTask->dpmi_seg : 0; + ES_reg(context) = DOSMEM_dpmi_seg; DI_reg(context) = 0; /* ES:DI is DPMI switch entry point */ break; } @@ -402,9 +398,8 @@ static void MSCDEX_Dump(char* pfx, BYTE* req, int dorealmode) case 3: case 12: ptr += sprintf(ptr, "\n\t\t\t\tIO_struct => "); - ios = (dorealmode) ? - DOSMEM_MapRealToLinear(MAKELONG(PTR_AT(req, 14, WORD), PTR_AT(req, 16, WORD))) : - PTR_SEG_OFF_TO_LIN(PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD)); + ios = (dorealmode) ? PTR_REAL_TO_LIN( PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD)) : + PTR_SEG_OFF_TO_LIN(PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD)); for (i = 0; i < PTR_AT(req, 18, WORD); i++) { ptr += sprintf(ptr, "%02x ", ios[i]); @@ -476,9 +471,7 @@ static void MSCDEX_Handler(CONTEXT86* context) BYTE Error = 255; /* No Error */ int dorealmode = ISV86(context); - driver_request = (dorealmode) ? - DOSMEM_MapRealToLinear(MAKELONG(BX_reg(context), ES_reg(context))) : - PTR_SEG_OFF_TO_LIN(ES_reg(context), BX_reg(context)); + driver_request = CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx); if (!driver_request) { /* FIXME - to be deleted ?? */ @@ -517,7 +510,7 @@ static void MSCDEX_Handler(CONTEXT86* context) switch (driver_request[2]) { case 3: io_stru = (dorealmode) ? - DOSMEM_MapRealToLinear(MAKELONG(PTR_AT(driver_request, 14, WORD), PTR_AT(driver_request, 16, WORD))) : + PTR_REAL_TO_LIN( PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD) ) : PTR_SEG_OFF_TO_LIN(PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)); TRACE(" --> IOCTL INPUT <%d>\n", io_stru[0]); @@ -682,7 +675,7 @@ static void MSCDEX_Handler(CONTEXT86* context) case 12: io_stru = (dorealmode) ? - DOSMEM_MapRealToLinear(MAKELONG(PTR_AT(driver_request, 14, WORD), PTR_AT(driver_request, 16, WORD))) : + PTR_REAL_TO_LIN( PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)) : PTR_SEG_OFF_TO_LIN(PTR_AT(driver_request, 16, WORD), PTR_AT(driver_request, 14, WORD)); TRACE(" --> IOCTL OUTPUT <%d>\n", io_stru[0]); diff --git a/msdos/int33.c b/msdos/int33.c index abbc6418d07..10d2f67521e 100644 --- a/msdos/int33.c +++ b/msdos/int33.c @@ -13,11 +13,12 @@ DEFAULT_DEBUG_CHANNEL(int) -typedef struct { +static struct +{ DWORD x, y, but; FARPROC16 callback; WORD callmask; -} MOUSESYSTEM; +} mouse_info; /********************************************************************** * INT_Int33Handler @@ -26,15 +27,12 @@ typedef struct { */ void WINAPI INT_Int33Handler( CONTEXT86 *context ) { - MOUSESYSTEM *sys = (MOUSESYSTEM *)DOSVM_GetSystemData(0x33); - switch (AX_reg(context)) { case 0x00: TRACE("Reset mouse driver and request status\n"); AX_reg(context) = 0xFFFF; /* installed */ BX_reg(context) = 3; /* # of buttons */ - sys = calloc(1,sizeof(MOUSESYSTEM)); - DOSVM_SetSystemData(0x33, sys); + memset( &mouse_info, 0, sizeof(mouse_info) ); break; case 0x01: FIXME("Show mouse cursor\n"); @@ -44,9 +42,9 @@ void WINAPI INT_Int33Handler( CONTEXT86 *context ) break; case 0x03: TRACE("Return mouse position and button status\n"); - BX_reg(context) = sys->but; - CX_reg(context) = sys->x; - DX_reg(context) = sys->y; + BX_reg(context) = mouse_info.but; + CX_reg(context) = mouse_info.x; + DX_reg(context) = mouse_info.y; break; case 0x04: FIXME("Position mouse cursor\n"); @@ -65,8 +63,8 @@ void WINAPI INT_Int33Handler( CONTEXT86 *context ) break; case 0x0C: TRACE("Define mouse interrupt subroutine\n"); - sys->callmask = CX_reg(context); - sys->callback = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR(ES_reg(context), DX_reg(context)); + mouse_info.callmask = CX_reg(context); + mouse_info.callback = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR(ES_reg(context), DX_reg(context)); break; case 0x10: FIXME("Define screen region for update\n"); @@ -81,7 +79,7 @@ typedef struct { WORD mask,but,x,y,mx,my; } MCALLDATA; -static void MouseRelay(LPDOSTASK lpDosTask,CONTEXT86 *context,void *mdata) +static void MouseRelay(CONTEXT86 *context,void *mdata) { MCALLDATA *data = (MCALLDATA *)mdata; CONTEXT86 ctx = *context; @@ -100,58 +98,56 @@ static void MouseRelay(LPDOSTASK lpDosTask,CONTEXT86 *context,void *mdata) void WINAPI INT_Int33Message(UINT message,WPARAM wParam,LPARAM lParam) { - MOUSESYSTEM *sys = (MOUSESYSTEM *)DOSVM_GetSystemData(0x33); WORD mask = 0; unsigned Height, Width, SX=1, SY=1; - if (!sys) return; if (!VGA_GetMode(&Height,&Width,NULL)) { /* may need to do some coordinate scaling */ SX = 640/Width; if (!SX) SX=1; } - sys->x = LOWORD(lParam) * SX; - sys->y = HIWORD(lParam) * SY; + mouse_info.x = LOWORD(lParam) * SX; + mouse_info.y = HIWORD(lParam) * SY; switch (message) { case WM_MOUSEMOVE: mask |= 0x01; break; case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: - sys->but |= 0x01; + mouse_info.but |= 0x01; mask |= 0x02; break; case WM_LBUTTONUP: - sys->but &= ~0x01; + mouse_info.but &= ~0x01; mask |= 0x04; break; case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: - sys->but |= 0x02; + mouse_info.but |= 0x02; mask |= 0x08; break; case WM_RBUTTONUP: - sys->but &= ~0x02; + mouse_info.but &= ~0x02; mask |= 0x10; break; case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: - sys->but |= 0x04; + mouse_info.but |= 0x04; mask |= 0x20; break; case WM_MBUTTONUP: - sys->but &= ~0x04; + mouse_info.but &= ~0x04; mask |= 0x40; break; } - if ((mask & sys->callmask) && sys->callback) { + if ((mask & mouse_info.callmask) && mouse_info.callback) { MCALLDATA *data = calloc(1,sizeof(MCALLDATA)); - data->proc = sys->callback; - data->mask = mask & sys->callmask; - data->but = sys->but; - data->x = sys->x; - data->y = sys->y; + data->proc = mouse_info.callback; + data->mask = mask & mouse_info.callmask; + data->but = mouse_info.but; + data->x = mouse_info.x; + data->y = mouse_info.y; DOSVM_QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data); } }