From d5cab2a058c3ae70bc6fceb9e1b52c471295418c Mon Sep 17 00:00:00 2001 From: Ove Kaaven Date: Sat, 29 Jul 2000 14:34:45 +0000 Subject: [PATCH] Added support for the Win32 Console interface to the main DOSVM event loop. Cleaned up event dispatching code a bit. --- include/dosexe.h | 2 +- loader/dos/dosvm.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 85 insertions(+), 13 deletions(-) diff --git a/include/dosexe.h b/include/dosexe.h index e9484c1d1ed..fe6a9aee657 100644 --- a/include/dosexe.h +++ b/include/dosexe.h @@ -32,7 +32,7 @@ typedef struct _DOSTASK { HANDLE hReadPipe,hXPipe,hConInput,hConOutput; int read_pipe,write_pipe; pid_t task; - int sig_sent; + int sig_sent,entered,idling; struct _DOSEVENT *pending,*current; DOSSYSTEM *sys; } DOSTASK, *LPDOSTASK; diff --git a/loader/dos/dosvm.c b/loader/dos/dosvm.c index 34851e4d3f2..755ce811221 100644 --- a/loader/dos/dosvm.c +++ b/loader/dos/dosvm.c @@ -22,9 +22,11 @@ #include "wine/winbase16.h" #include "wine/exception.h" #include "windef.h" +#include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "winnt.h" +#include "wincon.h" #include "callback.h" #include "msdos.h" @@ -196,7 +198,7 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86* LPDOSTASK lpDosTask = MZ_Current(); LPDOSEVENT event, cur, prev; - if (lpDosTask) { + if (lpDosTask && lpDosTask->entered) { event = malloc(sizeof(DOSEVENT)); if (!event) { ERR_(int)("out of memory allocating event entry\n"); @@ -216,14 +218,26 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86* if (prev) prev->next = event; else lpDosTask->pending = event; - /* get dosmod's attention to the new event, except for irq==0 where we already have it */ - if (irq && !lpDosTask->sig_sent) { + /* get dosmod's attention to the new event, if necessary */ + if (!lpDosTask->sig_sent) { TRACE_(int)("new event queued, signalling dosmod\n"); kill(lpDosTask->task,SIGUSR2); lpDosTask->sig_sent++; } else { TRACE_(int)("new event queued\n"); } + } else { + /* DOS subsystem not running */ + /* (this probably means that we're running a win16 app + * which uses DPMI to thunk down to DOS services) */ + if (irq<0) { + /* callback event, perform it with dummy context */ + CONTEXT86 context; + memset(&context,0,sizeof(context)); + (*relay)(lpDosTask,&context,data); + } else { + ERR_(int)("IRQ without DOS task: should not happen"); + } } } @@ -266,6 +280,7 @@ 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++; DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL); } if (lpDosTask->pending) { @@ -277,7 +292,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig, TRACE_(int)("no events are pending, clearing Pending flag\n"); CLR_PEND(&context); } - if (sig==SIGUSR2) lpDosTask->sig_sent--; + lpDosTask->sig_sent--; } else if ((sig==SIGHUP) || (sig==SIGILL) || (sig==SIGSEGV)) { do_exception( sig, &context ); @@ -320,11 +335,36 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig, return ret; } -void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg) +static void DOSVM_ProcessConsole(LPDOSTASK lpDosTask) +{ + INPUT_RECORD msg; + DWORD res; + BYTE scan; + + if (ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE),&msg,1,&res)) { + switch (msg.EventType) { + case KEY_EVENT: + scan = msg.Event.KeyEvent.wVirtualScanCode; + if (!msg.Event.KeyEvent.bKeyDown) scan |= 0x80; + + /* check whether extended bit is set, + * and if so, queue the extension prefix */ + if (msg.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY) { + INT_Int09SendScan(0xE0,0); + } + INT_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar); + break; + default: + FIXME_(int)("unhandled console event: %d\n", msg.EventType); + } + } +} + +static void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg) { BYTE scan = 0; - fprintf(stderr,"got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam); + TRACE_(int)("got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam); if ((msg->message>=WM_MOUSEFIRST)&& (msg->message<=WM_MOUSELAST)) { INT_Int33Message(msg->message,msg->wParam,msg->lParam); @@ -354,8 +394,13 @@ 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]=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)) { @@ -365,6 +410,15 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject ) Callout.DispatchMessageA(&msg); got_msg = TRUE; } + if (!got_msg) { + /* check for console input */ + INPUT_RECORD msg; + DWORD num; + if (PeekConsoleInputA(objs[0],&msg,1,&num) && num) { + DOSVM_ProcessConsole(lpDosTask); + got_msg = TRUE; + } + } if (read_pipe == -1) { if (got_msg) break; } else { @@ -376,15 +430,16 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject ) if (select(read_pipe+1,&readfds,NULL,NULL,&timeout)>0) break; } - /* check for data from win32 console device */ - /* nothing yet, block while waiting for something to do */ - waitret=MsgWaitForMultipleObjects(1,&hObject,FALSE,INFINITE,QS_ALLINPUT); + waitret=MsgWaitForMultipleObjects(objc,objs,FALSE,INFINITE,QS_ALLINPUT); if (waitret==(DWORD)-1) { ERR_(module)("dosvm wait error=%ld\n",GetLastError()); } - if (read_pipe != -1) { - if (waitret==WAIT_OBJECT_0) break; + if ((read_pipe != -1) && hObject) { + if (waitret==(WAIT_OBJECT_0+1)) break; + } + if (waitret==WAIT_OBJECT_0) { + DOSVM_ProcessConsole(lpDosTask); } } while (TRUE); } @@ -424,7 +479,9 @@ int DOSVM_Enter( CONTEXT86 *context ) } /* main exchange loop */ + lpDosTask->entered++; do { + TRACE_(module)("thread is: %lx\n",GetCurrentThreadId()); stat = VM86_ENTER; errno = 0; /* transmit VM86 structure to dosmod task */ @@ -449,6 +506,10 @@ int DOSVM_Enter( CONTEXT86 *context ) return -1; } 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 (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) { @@ -471,6 +532,7 @@ int DOSVM_Enter( CONTEXT86 *context ) } else sig=0; /* got response */ } while (DOSVM_Process(lpDosTask,stat,sig,&VM86)>=0); + lpDosTask->entered--; if (context) { #define CP(x,y) y##_reg(context) = VM86.regs.x @@ -616,6 +678,16 @@ 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)(LPDOSTASK,CONTEXT86*,void*), void *data) +{ + if (irq<0) { + /* callback event, perform it with dummy context */ + CONTEXT86 context; + memset(&context,0,sizeof(context)); + (*relay)(lpDosTask,&context,data); + } else { + ERR_(int)("IRQ without DOS task: should not happen"); + } +} #endif -- 2.11.4.GIT