Commit 5ec54495 authored by Alexandre Julliard's avatar Alexandre Julliard

krnl386: Remove support for DOS devices and event handling.

parent 0741d193
......@@ -8,7 +8,6 @@ C_SRCS = \
atom.c \
dma.c \
dosaspi.c \
dosdev.c \
dosmem.c \
dosvm.c \
error.c \
......@@ -16,17 +15,14 @@ C_SRCS = \
fpu.c \
global.c \
instr.c \
int09.c \
int10.c \
int13.c \
int15.c \
int16.c \
int21.c \
int25.c \
int26.c \
int2f.c \
int31.c \
int33.c \
int67.c \
interrupts.c \
ioports.c \
......@@ -43,7 +39,6 @@ C_SRCS = \
syslevel.c \
task.c \
thunk.c \
timer.c \
utthunk.c \
vga.c \
vxd.c \
......
......@@ -29,7 +29,6 @@
#include "wine/windef16.h"
#include "winbase.h"
#include "winnt.h" /* for PCONTEXT */
#include "wincon.h" /* for MOUSE_EVENT_RECORD */
#define MAX_DOS_DRIVES 26
......@@ -59,12 +58,6 @@ typedef void (*DOSRELAY)(CONTEXT*,void*);
typedef void (WINAPI *RMCBPROC)(CONTEXT*);
typedef void (WINAPI *INTPROC)(CONTEXT*);
#define DOS_PRIORITY_REALTIME 0 /* IRQ0 */
#define DOS_PRIORITY_KEYBOARD 1 /* IRQ1 */
#define DOS_PRIORITY_VGA 2 /* IRQ9 */
#define DOS_PRIORITY_MOUSE 5 /* IRQ12 */
#define DOS_PRIORITY_SERIAL 10 /* IRQ4 */
extern WORD DOSVM_psp DECLSPEC_HIDDEN; /* psp of current DOS task */
extern WORD DOSVM_retval DECLSPEC_HIDDEN; /* return value of previous DOS task */
extern struct DPMI_segments *DOSVM_dpmi_segments DECLSPEC_HIDDEN;
......@@ -223,22 +216,6 @@ typedef struct
/* Device driver header */
#define NONEXT ((DWORD)-1)
#define ATTR_STDIN 0x0001
#define ATTR_STDOUT 0x0002
#define ATTR_NUL 0x0004
#define ATTR_CLOCK 0x0008
#define ATTR_FASTCON 0x0010
#define ATTR_RAW 0x0020
#define ATTR_NOTEOF 0x0040
#define ATTR_DEVICE 0x0080
#define ATTR_REMOVABLE 0x0800
#define ATTR_NONIBM 0x2000 /* block devices */
#define ATTR_UNTILBUSY 0x2000 /* char devices */
#define ATTR_IOCTL 0x4000
#define ATTR_CHAR 0x8000
#include <pshpack1.h>
typedef struct
......@@ -252,94 +229,11 @@ typedef struct
#include <poppack.h>
/* DOS Device requests */
#define CMD_INIT 0
#define CMD_MEDIACHECK 1 /* block devices */
#define CMD_BUILDBPB 2 /* block devices */
#define CMD_INIOCTL 3
#define CMD_INPUT 4 /* read data */
#define CMD_SAFEINPUT 5 /* "non-destructive input no wait", char devices */
#define CMD_INSTATUS 6 /* char devices */
#define CMD_INFLUSH 7 /* char devices */
#define CMD_OUTPUT 8 /* write data */
#define CMD_SAFEOUTPUT 9 /* write data with verify */
#define CMD_OUTSTATUS 10 /* char devices */
#define CMD_OUTFLUSH 11 /* char devices */
#define CMD_OUTIOCTL 12
#define CMD_DEVOPEN 13
#define CMD_DEVCLOSE 14
#define CMD_REMOVABLE 15 /* block devices */
#define CMD_UNTILBUSY 16 /* output until busy */
#define STAT_MASK 0x00FF
#define STAT_DONE 0x0100
#define STAT_BUSY 0x0200
#define STAT_ERROR 0x8000
#include <pshpack1.h>
typedef struct {
BYTE size; /* length of header + data */
BYTE unit; /* unit (block devices only) */
BYTE command;
WORD status;
BYTE reserved[8];
} REQUEST_HEADER;
typedef struct {
REQUEST_HEADER hdr;
BYTE media; /* media descriptor from BPB */
SEGPTR buffer;
WORD count; /* byte/sector count */
WORD sector; /* starting sector (block devices) */
DWORD volume; /* volume ID (block devices) */
} REQ_IO;
typedef struct {
REQUEST_HEADER hdr;
BYTE data;
} REQ_SAFEINPUT;
/* WINE device driver thunk from RM */
typedef struct {
BYTE ljmp1;
FARPROC16 strategy;
BYTE ljmp2;
FARPROC16 interrupt;
} WINEDEV_THUNK;
#include <poppack.h>
/* Device driver info (used for initialization) */
typedef struct
{
char name[8];
WORD attr;
RMCBPROC strategy;
RMCBPROC interrupt;
} WINEDEV;
/* dosvm.c */
extern void DOSVM_SendQueuedEvents( CONTEXT * ) DECLSPEC_HIDDEN;
extern void WINAPI DOSVM_AcknowledgeIRQ( CONTEXT * ) DECLSPEC_HIDDEN;
extern INT DOSVM_Enter( CONTEXT *context ) DECLSPEC_HIDDEN;
extern void DOSVM_Exit( WORD retval ) DECLSPEC_HIDDEN;
extern void DOSVM_Wait( CONTEXT * ) DECLSPEC_HIDDEN;
extern DWORD DOSVM_Loop( HANDLE hThread ) DECLSPEC_HIDDEN;
extern void DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data ) DECLSPEC_HIDDEN;
extern void DOSVM_PIC_ioport_out( WORD port, BYTE val ) DECLSPEC_HIDDEN;
extern void DOSVM_SetTimer( UINT ticks ) DECLSPEC_HIDDEN;
extern LPVOID DOSVM_AllocDataUMB(DWORD, WORD *, WORD *) DECLSPEC_HIDDEN;
extern void DOSVM_InitSegments(void) DECLSPEC_HIDDEN;
/* devices.c */
extern void DOSDEV_InstallDOSDevices(void) DECLSPEC_HIDDEN;
extern void DOSDEV_SetupDevice(const WINEDEV * devinfo,
WORD seg, WORD off_dev, WORD off_thunk) DECLSPEC_HIDDEN;
extern void DOSDEV_SetSharingRetry(WORD delay, WORD count) DECLSPEC_HIDDEN;
extern SEGPTR DOSDEV_GetLOL(BOOL v86) DECLSPEC_HIDDEN;
/* dma.c */
extern int DMA_Transfer(int channel,int reqlength,void* buffer) DECLSPEC_HIDDEN;
extern void DMA_ioport_out( WORD port, BYTE val ) DECLSPEC_HIDDEN;
......@@ -365,11 +259,6 @@ extern void WINAPI DOSVM_Int3cHandler(CONTEXT*) DECLSPEC_HIDDEN;
extern void WINAPI DOSVM_Int3dHandler(CONTEXT*) DECLSPEC_HIDDEN;
extern void WINAPI DOSVM_Int3eHandler(CONTEXT*) DECLSPEC_HIDDEN;
/* int09.c */
extern void WINAPI DOSVM_Int09Handler(CONTEXT*) DECLSPEC_HIDDEN;
extern void DOSVM_Int09SendScan(BYTE scan,BYTE ascii) DECLSPEC_HIDDEN;
extern BYTE DOSVM_Int09ReadScan(BYTE*ascii) DECLSPEC_HIDDEN;
/* int10.c */
extern void WINAPI DOSVM_Int10Handler(CONTEXT*) DECLSPEC_HIDDEN;
extern void DOSVM_PutChar(BYTE ascii) DECLSPEC_HIDDEN;
......@@ -380,11 +269,6 @@ extern void WINAPI DOSVM_Int13Handler(CONTEXT*) DECLSPEC_HIDDEN;
/* int15.c */
extern void WINAPI DOSVM_Int15Handler(CONTEXT*) DECLSPEC_HIDDEN;
/* int16.c */
extern void WINAPI DOSVM_Int16Handler(CONTEXT*) DECLSPEC_HIDDEN;
extern BOOL DOSVM_Int16ReadChar( BYTE *, BYTE *, CONTEXT * ) DECLSPEC_HIDDEN;
extern BOOL DOSVM_Int16AddChar(BYTE ascii, BYTE scan) DECLSPEC_HIDDEN;
/* int21.c */
extern void WINAPI DOSVM_Int21Handler(CONTEXT*) DECLSPEC_HIDDEN;
......@@ -398,7 +282,6 @@ void WINAPI DOSVM_Int26Handler( CONTEXT * ) DECLSPEC_HIDDEN;
/* int2f.c */
extern void WINAPI DOSVM_Int2fHandler(CONTEXT*) DECLSPEC_HIDDEN;
extern void MSCDEX_InstallCDROM(void) DECLSPEC_HIDDEN;
/* int31.c */
extern void WINAPI DOSVM_Int31Handler(CONTEXT*) DECLSPEC_HIDDEN;
......@@ -408,11 +291,6 @@ extern FARPROC16 DPMI_AllocInternalRMCB(RMCBPROC) DECLSPEC_HIDDEN;
extern int DPMI_CallRMProc(CONTEXT*,LPWORD,int,int) DECLSPEC_HIDDEN;
extern BOOL DOSVM_CheckWrappers(CONTEXT*) DECLSPEC_HIDDEN;
/* int33.c */
extern void WINAPI DOSVM_Int33Handler(CONTEXT*) DECLSPEC_HIDDEN;
extern void DOSVM_Int33Message(UINT,WPARAM,LPARAM) DECLSPEC_HIDDEN;
extern void DOSVM_Int33Console(MOUSE_EVENT_RECORD*) DECLSPEC_HIDDEN;
/* int67.c */
extern void WINAPI DOSVM_Int67Handler(CONTEXT*) DECLSPEC_HIDDEN;
extern void EMS_Ioctl_Handler(CONTEXT*) DECLSPEC_HIDDEN;
......@@ -425,7 +303,6 @@ extern FARPROC16 DOSVM_GetPMHandler16( BYTE ) DECLSPEC_HIDDEN;
extern FARPROC48 DOSVM_GetPMHandler48( BYTE ) DECLSPEC_HIDDEN;
extern FARPROC16 DOSVM_GetRMHandler( BYTE ) DECLSPEC_HIDDEN;
extern void DOSVM_HardwareInterruptPM( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
extern void DOSVM_HardwareInterruptRM( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
extern void DOSVM_SetPMHandler16( BYTE, FARPROC16 ) DECLSPEC_HIDDEN;
extern void DOSVM_SetPMHandler48( BYTE, FARPROC48 ) DECLSPEC_HIDDEN;
extern void DOSVM_SetRMHandler( BYTE, FARPROC16 ) DECLSPEC_HIDDEN;
......@@ -442,7 +319,4 @@ void DOSVM_BuildCallFrame( CONTEXT *, DOSRELAY, LPVOID ) DECLSPEC_HIDDEN;
extern void SB_ioport_out( WORD port, BYTE val ) DECLSPEC_HIDDEN;
extern BYTE SB_ioport_in( WORD port ) DECLSPEC_HIDDEN;
/* timer.c */
extern void WINAPI DOSVM_Int08Handler(CONTEXT*) DECLSPEC_HIDDEN;
#endif /* __WINE_DOSEXE_H */
......@@ -89,178 +89,6 @@ struct DPMI_segments *DOSVM_dpmi_segments = NULL;
static DWORD DOSVM_umb_free = DOSVM_UMB_BOTTOM;
typedef struct _DOSEVENT {
int irq,priority;
DOSRELAY relay;
void *data;
struct _DOSEVENT *next;
} DOSEVENT, *LPDOSEVENT;
static struct _DOSEVENT *pending_event, *current_event;
static HANDLE event_notifier;
static CRITICAL_SECTION qcrit;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &qcrit,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": qcrit") }
};
static CRITICAL_SECTION qcrit = { &critsect_debug, -1, 0, 0, 0, 0 };
/***********************************************************************
* DOSVM_HasPendingEvents
*
* Return true if there are pending events that are not
* blocked by currently active event.
*/
static BOOL DOSVM_HasPendingEvents( void )
{
if (!pending_event)
return FALSE;
if (!current_event)
return TRUE;
if (pending_event->priority < current_event->priority)
return TRUE;
return FALSE;
}
/***********************************************************************
* 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( CONTEXT *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 );
}
HeapFree(GetProcessHeap(), 0, event);
}
}
/***********************************************************************
* DOSVM_SendQueuedEvents
*
* As long as context instruction pointer stays unmodified,
* process all pending events that are not blocked by currently
* active event.
*
* This routine assumes that caller has already cleared TEB.vm86_pending
* and checked that interrupts are enabled.
*/
void DOSVM_SendQueuedEvents( CONTEXT *context )
{
DWORD old_cs = context->SegCs;
DWORD old_ip = context->Eip;
EnterCriticalSection(&qcrit);
TRACE( "Called in %s mode %s events pending (time=%d)\n",
ISV86(context) ? "real" : "protected",
DOSVM_HasPendingEvents() ? "with" : "without",
GetTickCount() );
TRACE( "cs:ip=%04x:%08x, ss:sp=%04x:%08x\n",
context->SegCs, context->Eip, context->SegSs, context->Esp);
while (context->SegCs == old_cs &&
context->Eip == old_ip &&
DOSVM_HasPendingEvents())
{
DOSVM_SendOneEvent(context);
/*
* Event handling may have turned pending events flag on.
* We disable it here because this prevents some
* unnecessary calls to this function.
*/
get_vm86_teb_info()->vm86_pending = 0;
}
FIXME("No DOS .exe file support on this platform (yet)\n");
LeaveCriticalSection(&qcrit);
}
/***********************************************************************
* DOSVM_Enter
*/
INT DOSVM_Enter( CONTEXT *context )
{
SetLastError( ERROR_NOT_SUPPORTED );
return -1;
}
/**********************************************************************
* DOSVM_Exit
*/
......@@ -273,53 +101,6 @@ void DOSVM_Exit( WORD retval )
}
/***********************************************************************
* DOSVM_Wait
*/
void DOSVM_Wait( CONTEXT *waitctx ) { }
/***********************************************************************
* DOSVM_PIC_ioport_out
*/
void DOSVM_PIC_ioport_out( WORD port, BYTE val) {}
/***********************************************************************
* DOSVM_QueueEvent
*/
void DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data)
{
if (irq<0) {
/* callback event, perform it with dummy context */
CONTEXT context;
memset(&context,0,sizeof(context));
(*relay)(&context,data);
} else {
ERR("IRQ without DOS task: should not happen\n");
}
}
/**********************************************************************
* DOSVM_AcknowledgeIRQ
*
* This routine should be called by all internal IRQ handlers.
*/
void WINAPI DOSVM_AcknowledgeIRQ( CONTEXT *context )
{
/*
* Send EOI to PIC.
*/
DOSVM_PIC_ioport_out( 0x20, 0x20 );
/*
* Protected mode IRQ handlers are supposed
* to turn VIF flag on before they return.
*/
if (!ISV86(context))
get_vm86_teb_info()->dpmi_vif = 1;
}
/***********************************************************************
* DOSVM_AllocUMB
*
* Allocate upper memory block (UMB) from upper memory.
......@@ -563,6 +344,4 @@ void DOSVM_InitSegments(void)
* As we store code in UMB we should make sure it is executable
*/
VirtualProtect((void *)DOSVM_UMB_BOTTOM, DOSVM_UMB_TOP - DOSVM_UMB_BOTTOM, PAGE_EXECUTE_READWRITE, &old_prot);
event_notifier = CreateEventW(NULL, FALSE, FALSE, NULL);
}
......@@ -872,12 +872,6 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
case 0xfb: /* sti */
get_vm86_teb_info()->dpmi_vif = 1;
context->Eip += prefixlen + 1;
if (get_vm86_teb_info()->vm86_pending)
{
get_vm86_teb_info()->vm86_pending = 0;
rec->ExceptionCode = EXCEPTION_VM86_STI;
break; /* Handle the pending event. */
}
return ExceptionContinueExecution;
}
return ExceptionContinueSearch; /* Unable to emulate it */
......
/*
* DOS interrupt 09h handler (IRQ1 - KEYBOARD)
*
* Copyright 1999 Ove Kåven
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/debug.h"
#include "dosexe.h"
WINE_DEFAULT_DEBUG_CHANNEL(int);
#define QUEUELEN 31
static struct
{
BYTE queuelen,queue[QUEUELEN],ascii[QUEUELEN];
} kbdinfo;
/*
* Update the BIOS data segment's keyboard status flags (mem 0x40:0x17/0x18)
* if modifier/special keys have been pressed.
* FIXME: we merely toggle key status and don't actively set it instead,
* so we might be out of sync with the real current system status of these keys.
* Probably doesn't matter too much, though.
*/
static void DOSVM_Int09UpdateKbdStatusFlags(BYTE scan, BOOL extended, BIOSDATA *data, BOOL *modifier)
{
BYTE realscan = scan & 0x7f; /* remove 0x80 make/break flag */
BYTE bit1 = 255, bit2 = 255;
INPUT_RECORD msg;
DWORD res;
*modifier = TRUE;
switch (realscan)
{
case 0x36: /* r shift */
bit1 = 0;
break;
case 0x2a: /* l shift */
bit1 = 1;
break;
case 0x1d: /* l/r control */
bit1 = 2;
if (!extended) /* left control only */
bit2 = 0;
break;
case 0x37: /* SysRq inner parts */
/* SysRq scan code sequence: 38, e0, 37, e0, b7, b8 */
FIXME("SysRq not handled yet.\n");
break;
case 0x38: /* l/r menu/alt, SysRq outer parts */
bit1 = 3;
if (!extended) /* left alt only */
bit2 = 1;
break;
case 0x46: /* scroll lock */
bit1 = 4;
if (!extended) /* left ctrl only */
bit2 = 4;
break;
case 0x45: /* num lock, pause */
if (extended) /* distinguish from non-extended Pause key */
{ /* num lock */
bit1 = 5;
bit2 = 5;
}
else
{ /* pause */
if (!(scan & 0x80)) /* "make" code */
bit2 = 3;
}
break;
case 0x3a: /* caps lock */
bit1 = 6;
bit2 = 6;
break;
case 0x52: /* insert */
bit1 = 7;
bit2 = 7;
*modifier = FALSE; /* insert is no modifier: thus pass to int16 */
break;
}
/* now that we know which bits to set, update them */
if (!(scan & 0x80)) /* "make" code (keypress) */
{
if (bit2 != 255)
{
if (bit2 == 3)
{
data->KbdFlags2 |= 1 << bit2; /* set "Pause" flag */
TRACE("PAUSE key, sleeping !\n");
/* wait for keypress to unlock pause */
do {
Sleep(55);
} while (!(ReadConsoleInputA(GetStdHandle(STD_INPUT_HANDLE),&msg,1,&res) && (msg.EventType == KEY_EVENT)));
data->KbdFlags2 &= ~(1 << bit2); /* release "Pause" flag */
}
else
data->KbdFlags2 |= 1 << bit2;
}
if (bit1 != 255)
{
if (bit1 < 4) /* key "pressed" flag */
data->KbdFlags1 |= 1 << bit1;
else /* key "active" flag */
data->KbdFlags1 ^= 1 << bit1;
}
}
else /* "break" / release */
{
if (bit2 != 255)
data->KbdFlags2 &= ~(1 << bit2);
if (bit1 < 4) /* is it a key "pressed" bit ? */
data->KbdFlags1 &= ~(1 << bit1);
}
TRACE("ext. %d, bits %d/%d, KbdFlags %02x/%02x\n", extended, bit1, bit2, data->KbdFlags1, data->KbdFlags2);
}
/**********************************************************************
* DOSVM_Int09Handler
*
* Handler for int 09h.
* See http://www.execpc.com/~geezer/osd/kbd/ for a very good description
* of keyboard mapping modes.
*/
void WINAPI DOSVM_Int09Handler( CONTEXT *context )
{
BIOSDATA *data = DOSVM_BiosData();
BYTE ascii, scan = DOSVM_Int09ReadScan(&ascii);
BYTE realscan = scan & 0x7f; /* remove 0x80 make/break flag */
BOOL modifier = FALSE;
static BOOL extended = FALSE; /* indicates start of extended key sequence */
BYTE ch[2];
int cnt, c2;
TRACE("scan=%02x, ascii=%02x[%c]\n",scan, ascii, ascii ? ascii : ' ');
if (scan == 0xe0) /* extended keycode */
extended = TRUE;
/* check for keys concerning keyboard status flags */
if ((realscan == 0x52 /* insert */)
|| (realscan == 0x3a /* caps lock */)
|| (realscan == 0x45 /* num lock (extended) or pause/break */)
|| (realscan == 0x46 /* scroll lock */)
|| (realscan == 0x2a /* l shift */)
|| (realscan == 0x36 /* r shift */)
|| (realscan == 0x37 /* SysRq */)
|| (realscan == 0x38 /* l/r menu/alt, SysRq */)
|| (realscan == 0x1d /* l/r control */))
DOSVM_Int09UpdateKbdStatusFlags(scan, extended, data, &modifier);
if (scan != 0xe0)
extended = FALSE; /* reset extended flag now */
/* only interested in "make" (press) codes, not "break" (release),
* and also not in "modifier key only" (w/o ascii) notifications */
if (!(scan & 0x80) && !(modifier && !ascii))
{
if (ascii) {
/* we already have an ASCII code, no translation necessary */
if (data->KbdFlags1 & 8) /* Alt key ? */
ch[0] = 0; /* ASCII code needs to be 0 if Alt also pressed */
else
ch[0] = ascii;
/* FIXME: need to handle things such as Shift-F1 etc. */
cnt = 1;
} else {
/* translate */
UINT vkey = MapVirtualKeyA(scan&0x7f, 1);
BYTE keystate[256];
GetKeyboardState(keystate);
cnt = ToAscii(vkey, scan, keystate, (LPWORD)ch, 0);
}
if (cnt>0) {
for (c2=0; c2<cnt; c2++)
DOSVM_Int16AddChar(ch[c2], scan);
} else
if (cnt==0) {
/* FIXME: need to handle things like shift-F-keys,
* 0xE0 extended keys, etc */
DOSVM_Int16AddChar(0, scan);
}
}
DOSVM_AcknowledgeIRQ( context );
}
static void KbdRelay( CONTEXT *context, void *data )
{
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 (--kbdinfo.queuelen) {
memmove(kbdinfo.queue,kbdinfo.queue+1,kbdinfo.queuelen);
memmove(kbdinfo.ascii,kbdinfo.ascii+1,kbdinfo.queuelen);
}
}
}
void DOSVM_Int09SendScan( BYTE scan, BYTE ascii )
{
if (kbdinfo.queuelen == QUEUELEN) {
ERR("keyboard queue overflow\n");
return;
}
/* add scancode to queue */
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 DOSVM_Int09ReadScan( BYTE*ascii )
{
if (ascii) *ascii = kbdinfo.ascii[0];
return kbdinfo.queue[0];
}
/*
* DOS interrupt 16h handler
*
* Copyright 1998 Joseph Pranevich
* Copyright 1999 Ove Kåven
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "dosexe.h"
#include "wincon.h"
#include "wine/debug.h"
#include "windef.h"
#include "wingdi.h"
#include "winuser.h"
WINE_DEFAULT_DEBUG_CHANNEL(int);
/**********************************************************************
* DOSVM_Int16Handler
*
* Handler for int 16h (keyboard)
*
* NOTE:
*
* KEYB.COM (DOS >3.2) adds functions to this interrupt, they are
* not currently listed here.
*/
void WINAPI DOSVM_Int16Handler( CONTEXT *context )
{
BIOSDATA *data = NULL;
BYTE ascii, scan;
switch (AH_reg(context)) {
case 0x00: /* Get Keystroke */
/* Returns: AH = Scan code
AL = ASCII character */
TRACE("Get Keystroke\n");
DOSVM_Int16ReadChar(&ascii, &scan, context);
SET_AL( context, ascii );
SET_AH( context, scan );
break;
case 0x01: /* Check for Keystroke */
/* Returns: ZF set if no keystroke */
/* AH = Scan code */
/* AL = ASCII character */
TRACE("Check for Keystroke\n");
if (!DOSVM_Int16ReadChar(&ascii, &scan, NULL))
{
SET_ZFLAG(context);
}
else
{
SET_AL( context, ascii );
SET_AH( context, scan );
RESET_ZFLAG(context);
}
/* don't miss the opportunity to break some tight timing loop in DOS
* programs causing 100% CPU usage (by doing a Sleep here) */
Sleep(5);
break;
case 0x02: /* Get Shift Flags */
/* read value from BIOS data segment's keyboard status flags field */
data = DOSVM_BiosData();
SET_AL( context, data->KbdFlags1 );
TRACE("Get Shift Flags: returning 0x%02x\n", AL_reg(context));
break;
case 0x03: /* Set Typematic Rate and Delay */
FIXME("Set Typematic Rate and Delay - Not Supported\n");
break;
case 0x05:/*simulate Keystroke*/
FIXME("Simulating a keystroke is not supported yet\n");
break;
case 0x09: /* Get Keyboard Functionality */
FIXME("Get Keyboard Functionality - Not Supported\n");
/* As a temporary measure, say that "nothing" is supported... */
SET_AL( context, 0 );
break;
case 0x0a: /* Get Keyboard ID */
FIXME("Get Keyboard ID - Not Supported\n");
break;
case 0x10: /* Get Enhanced Keystroke */
TRACE("Get Enhanced Keystroke - Partially supported\n");
/* Returns: AH = Scan code
AL = ASCII character */
DOSVM_Int16ReadChar(&ascii, &scan, context);
SET_AL( context, ascii );
SET_AH( context, scan );
break;
case 0x11: /* Check for Enhanced Keystroke */
/* Returns: ZF set if no keystroke */
/* AH = Scan code */
/* AL = ASCII character */
TRACE("Check for Enhanced Keystroke - Partially supported\n");
if (!DOSVM_Int16ReadChar(&ascii, &scan, NULL))
{
SET_ZFLAG(context);
}
else
{
SET_AL( context, ascii );
SET_AH( context, scan );
RESET_ZFLAG(context);
}
break;
case 0x12: /* Get Extended Shift States */
FIXME("Get Extended Shift States - Not Supported\n");
break;
default:
FIXME("Unknown INT 16 function - 0x%x\n", AH_reg(context));
break;
}
}
/**********************************************************************
* DOSVM_Int16ReadChar
*
* Either peek into keyboard buffer or wait for next keystroke.
*
* If waitctx is NULL, return TRUE if buffer had keystrokes and
* FALSE if buffer is empty. Returned keystroke will be left into buffer.
*
* If waitctx is non-NULL, wait until keystrokes are available.
* Return value will always be TRUE and returned keystroke will be
* removed from buffer.
*/
BOOL DOSVM_Int16ReadChar(BYTE *ascii, BYTE *scan, CONTEXT *waitctx)
{
BIOSDATA *data = DOSVM_BiosData();
WORD CurOfs = data->NextKbdCharPtr;
/* check if there's data in buffer */
if (waitctx)
{
/* wait until input is available... */
while (CurOfs == data->FirstKbdCharPtr)
DOSVM_Wait( waitctx );
}
else
{
if (CurOfs == data->FirstKbdCharPtr)
return FALSE;
}
/* read from keyboard queue */
TRACE( "(%p,%p,%p) -> %02x %02x\n", ascii, scan, waitctx,
((BYTE*)data)[CurOfs], ((BYTE*)data)[CurOfs+1] );
if (ascii) *ascii = ((BYTE*)data)[CurOfs];
if (scan) *scan = ((BYTE*)data)[CurOfs+1];
if (waitctx)
{
CurOfs += 2;
if (CurOfs >= data->KbdBufferEnd) CurOfs = data->KbdBufferStart;
data->NextKbdCharPtr = CurOfs;
}
return TRUE;
}
BOOL DOSVM_Int16AddChar(BYTE ascii,BYTE scan)
{
BIOSDATA *data = DOSVM_BiosData();
WORD CurOfs = data->FirstKbdCharPtr;
WORD NextOfs = CurOfs + 2;
TRACE("(%02x,%02x)\n",ascii,scan);
if (NextOfs >= data->KbdBufferEnd) NextOfs = data->KbdBufferStart;
/* check if buffer is full */
if (NextOfs == data->NextKbdCharPtr) return FALSE;
/* okay, insert character in ring buffer */
((BYTE*)data)[CurOfs] = ascii;
((BYTE*)data)[CurOfs+1] = scan;
data->FirstKbdCharPtr = NextOfs;
return TRUE;
}
......@@ -369,40 +369,6 @@ static void INT21_SetCurrentDrive( BYTE drive )
/***********************************************************************
* INT21_ReadChar
*
* Reads a character from the standard input.
* Extended keycodes will be returned as two separate characters.
*/
static BOOL INT21_ReadChar( BYTE *input, CONTEXT *waitctx )
{
static BYTE pending_scan = 0;
if (pending_scan)
{
if (input)
*input = pending_scan;
if (waitctx)
pending_scan = 0;
return TRUE;
}
else
{
BYTE ascii;
BYTE scan;
if (!DOSVM_Int16ReadChar( &ascii, &scan, waitctx ))
return FALSE;
if (input)
*input = ascii;
if (waitctx && !ascii)
pending_scan = scan;
return TRUE;
}
}
/***********************************************************************
* INT21_GetSystemCountryCode
*
* Return DOS country code for default system locale.
......@@ -1143,67 +1109,6 @@ static BOOL INT21_CreateFile( CONTEXT *context,
/***********************************************************************
* INT21_BufferedInput
*
* Handler for function 0x0a and reading from console using
* function 0x3f.
*
* Reads a string of characters from standard input until
* enter key is pressed. Returns either number of characters
* read from console including terminating CR or
* zero if capacity was zero.
*/
static WORD INT21_BufferedInput( CONTEXT *context, BYTE *ptr, WORD capacity )
{
BYTE length = 0;
/*
* Return immediately if capacity is zero.
*/
if (capacity == 0)
return 0;
while(TRUE)
{
BYTE ascii;
BYTE scan;
DOSVM_Int16ReadChar( &ascii, &scan, context );
if (ascii == '\r' || ascii == '\n')
{
ptr[length] = '\r';
return length + 1;
}
/*
* DOS handles only backspace and KEY_LEFT
* perhaps we should do more
*/
if (ascii == '\b' || scan == KEY_LEFT)
{
if (length==0) continue;
DOSVM_PutChar( '\b' );
length--;
continue;
}
/*
* If the buffer becomes filled to within one byte of
* capacity, DOS rejects all further characters up to,
* but not including, the terminating carriage return.
*/
if (ascii != 0 && length < capacity-1)
{
DOSVM_PutChar( ascii );
ptr[length] = ascii;
length++;
}
}
}
/***********************************************************************
* INT21_GetCurrentDTA
*/
static BYTE *INT21_GetCurrentDTA( CONTEXT *context )
......@@ -2882,7 +2787,6 @@ static void INT21_Ioctl( CONTEXT *context )
}
else
{
DOSDEV_SetSharingRetry( CX_reg(context), DX_reg(context) );
RESET_CFLAG( context );
}
break;
......@@ -4174,16 +4078,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
break;
case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
{
BYTE ascii;
TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
INT21_ReadChar( &ascii, context );
SET_AL( context, ascii );
/*
* FIXME: What to echo when extended keycodes are read?
*/
DOSVM_PutChar(AL_reg(context));
}
TRACE("DIRECT CHARACTER INPUT WITH ECHO - not supported\n");
break;
case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
......@@ -4202,19 +4097,9 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
{
TRACE("Direct Console Input\n");
if (INT21_ReadChar( NULL, NULL ))
{
BYTE ascii;
INT21_ReadChar( &ascii, context );
SET_AL( context, ascii );
RESET_ZFLAG( context );
}
else
{
/* no character available */
SET_AL( context, 0 );
SET_ZFLAG( context );
}
/* no character available */
SET_AL( context, 0 );
SET_ZFLAG( context );
}
else
{
......@@ -4229,21 +4114,13 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
break;
case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
{
BYTE ascii;
TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
INT21_ReadChar( &ascii, context );
SET_AL( context, ascii );
}
TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO - not supported\n");
SET_AL( context, 0 );
break;
case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
{
BYTE ascii;
TRACE("CHARACTER INPUT WITHOUT ECHO\n");
INT21_ReadChar( &ascii, context );
SET_AL( context, ascii );
}
TRACE("CHARACTER INPUT WITHOUT ECHO - not supported\n");
SET_AL( context, 0 );
break;
case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
......@@ -4267,43 +4144,12 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
break;
case 0x0a: /* BUFFERED INPUT */
{
BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
context->SegDs,
context->Edx);
WORD result;
TRACE( "BUFFERED INPUT (size=%d)\n", ptr[0] );
/*
* FIXME: Some documents state that
* ptr[1] holds number of chars from last input which
* may be recalled on entry, other documents do not mention
* this at all.
*/
if (ptr[1])
TRACE( "Handle old chars in buffer!\n" );
/*
* ptr[0] - capacity (includes terminating CR)
* ptr[1] - characters read (excludes terminating CR)
*/
result = INT21_BufferedInput( context, ptr + 2, ptr[0] );
if (result > 0)
ptr[1] = (BYTE)result - 1;
else
ptr[1] = 0;
}
TRACE( "BUFFERED INPUT - not supported\n" );
break;
case 0x0b: /* GET STDIN STATUS */
TRACE( "GET STDIN STATUS\n" );
{
if (INT21_ReadChar( NULL, NULL ))
SET_AL( context, 0xff ); /* character available */
else
SET_AL( context, 0 ); /* no character available */
}
TRACE( "GET STDIN STATUS - not supported\n" );
SET_AL( context, 0 ); /* no character available */
break;
case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
......@@ -5037,11 +4883,9 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
break;
case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
{
SEGPTR ptr = DOSDEV_GetLOL( ISV86(context) );
context->SegEs = SELECTOROF(ptr);
SET_BX( context, OFFSETOF(ptr) );
}
TRACE("Get List of Lists - not supported\n");
context->SegEs = 0;
SET_BX( context, 0 );
break;
case 0x54: /* Get Verify Flag */
......
......@@ -53,8 +53,6 @@ typedef struct
typedef struct
{
CDROM_DEVICE_HEADER hdr;
WINEDEV_THUNK thunk;
WORD cdrom_segment; /* Real mode segment for CDROM_HEAP */
WORD cdrom_selector; /* Protected mode selector for CDROM_HEAP */
} CDROM_HEAP;
......@@ -1041,58 +1039,3 @@ static void MSCDEX_Handler(CONTEXT* context)
break;
}
}
/* prototypes */
static void WINAPI cdrom_strategy(CONTEXT*ctx);
static void WINAPI cdrom_interrupt(CONTEXT*ctx);
/* device info */
static const WINEDEV cdromdev =
{
"WINE_CD_",
ATTR_CHAR|ATTR_REMOVABLE|ATTR_IOCTL,
cdrom_strategy, cdrom_interrupt
};
static REQUEST_HEADER *cdrom_driver_request;
/* Return to caller */
static void do_lret(CONTEXT*ctx)
{
WORD *stack = CTX_SEG_OFF_TO_LIN(ctx, ctx->SegSs, ctx->Esp);
ctx->Eip = *(stack++);
ctx->SegCs = *(stack++);
ctx->Esp += 2*sizeof(WORD);
}
static void WINAPI cdrom_strategy(CONTEXT*ctx)
{
cdrom_driver_request = CTX_SEG_OFF_TO_LIN(ctx, ctx->SegEs, ctx->Ebx);
do_lret( ctx );
}
static void WINAPI cdrom_interrupt(CONTEXT*ctx)
{
if (cdrom_driver_request->unit > CDROM_GetHeap()->hdr.units)
cdrom_driver_request->status = STAT_ERROR | 1; /* unknown unit */
else
MSCDEX_Request((BYTE*)cdrom_driver_request, ISV86(ctx));
do_lret( ctx );
}
/**********************************************************************
* MSCDEX_InstallCDROM [internal]
*
* Install the CDROM driver into the DOS device driver chain.
*/
void MSCDEX_InstallCDROM(void)
{
CDROM_HEAP *cdrom_heap = CDROM_GetHeap();
DOSDEV_SetupDevice( &cdromdev,
cdrom_heap->cdrom_segment,
FIELD_OFFSET(CDROM_HEAP, hdr),
FIELD_OFFSET(CDROM_HEAP, thunk) );
}
......@@ -119,36 +119,6 @@ static WORD alloc_pm_selector( WORD seg, unsigned char flags )
/**********************************************************************
* dpmi_exception_handler
*
* Handle EXCEPTION_VM86_STI exceptions generated
* when there are pending asynchronous events.
*/
static LONG WINAPI dpmi_exception_handler(EXCEPTION_POINTERS *eptr)
{
EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
CONTEXT *context = eptr->ContextRecord;
if (rec->ExceptionCode == EXCEPTION_VM86_STI)
{
if (ISV86(context))
ERR( "Real mode STI caught by protected mode handler!\n" );
DOSVM_SendQueuedEvents(context);
return EXCEPTION_CONTINUE_EXECUTION;
}
else if (rec->ExceptionCode == EXCEPTION_VM86_INTx)
{
if (ISV86(context))
ERR( "Real mode INTx caught by protected mode handler!\n" );
DPMI_retval = (BYTE)rec->ExceptionInformation[0];
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
/**********************************************************************
* INT_GetRealModeContext
*/
static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT *context )
......@@ -386,7 +356,7 @@ static void DPMI_CallRMCBProc( CONTEXT *context, RMCB *rmcb, WORD flag )
if (wine_ldt_is_system( rmcb->proc_sel )) {
/* Wine-internal RMCB, call directly */
((RMCBPROC)rmcb->proc_ofs)(context);
} else __TRY {
} else {
UINT16 ss,es;
DWORD esp,edi;
......@@ -422,7 +392,7 @@ static void DPMI_CallRMCBProc( CONTEXT *context, RMCB *rmcb, WORD flag )
}
wine_ldt_free_entries( ss, 1 );
INT_GetRealModeContext( MapSL( MAKESEGPTR( es, edi )), context);
} __EXCEPT(dpmi_exception_handler) { } __ENDTRY
}
/* Restore virtual interrupt flag. */
get_vm86_teb_info()->dpmi_vif = old_vif;
......@@ -516,20 +486,14 @@ callrmproc_again:
already = TRUE;
}
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");
/* 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;
}
if (alloc) DOSMEM_FreeBlock( addr );
return 0;
......@@ -634,14 +598,7 @@ static void StartPM( CONTEXT *context )
TRACE("DOS program is now entering %d-bit protected mode\n",
DOSVM_IsDos32() ? 32 : 16);
__TRY
{
WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&pm_ctx );
}
__EXCEPT(dpmi_exception_handler)
{
}
__ENDTRY
WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&pm_ctx );
TRACE( "Protected mode DOS program is terminating\n" );
......@@ -732,59 +689,7 @@ static BOOL DPMI_FreeRMCB( DWORD address )
*/
void WINAPI DOSVM_RawModeSwitchHandler( CONTEXT *context )
{
CONTEXT 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 (get_vm86_teb_info()->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 %04x:%04x\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)
get_vm86_teb_info()->dpmi_vif = 1;
else
get_vm86_teb_info()->dpmi_vif = 0;
/* Return to new address and hope that we didn't mess up */
TRACE("re-entering protected mode at %04x:%08x\n",
context->SegCs, context->Eip);
FIXME( "no longer supported\n" );
}
......
/*
* DOS interrupt 33h handler
*
* Copyright 1999 Ove Kåven
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "dosexe.h"
#include "vga.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(int);
static struct
{
WORD x, y, but;
WORD lbcount, rbcount, rlastx, rlasty, llastx, llasty;
FARPROC16 callback;
WORD callmask;
WORD VMPratio, HMPratio, oldx, oldy;
WORD hide_count;
} mouse_info;
/**********************************************************************
* INT33_ResetMouse
*
* Handler for:
* - subfunction 0x00 (reset mouse)
* - subfunction 0x21 (software reset)
*/
static void INT33_ResetMouse( CONTEXT *context )
{
memset( &mouse_info, 0, sizeof(mouse_info) );
/* Set the default mickey/pixel ratio */
mouse_info.HMPratio = 8;
mouse_info.VMPratio = 16;
/* Hide the mouse cursor */
mouse_info.hide_count = 1;
VGA_ShowMouse( FALSE );
if (context)
{
SET_AX( context, 0xFFFF ); /* driver installed */
SET_BX( context, 3 ); /* number of buttons */
}
}
/**********************************************************************
* DOSVM_Int33Handler
*
* Handler for int 33h (MS MOUSE).
*/
void WINAPI DOSVM_Int33Handler( CONTEXT *context )
{
switch (AX_reg(context))
{
case 0x0000:
TRACE("Reset mouse driver and request status\n");
INT33_ResetMouse( context );
break;
case 0x0001:
TRACE("Show mouse cursor, old hide count: %d\n",
mouse_info.hide_count);
if (mouse_info.hide_count >= 1)
mouse_info.hide_count--;
if (!mouse_info.hide_count)
VGA_ShowMouse( TRUE );
break;
case 0x0002:
TRACE("Hide mouse cursor, old hide count: %d\n",
mouse_info.hide_count);
if(!mouse_info.hide_count)
VGA_ShowMouse( FALSE );
mouse_info.hide_count++;
break;
case 0x0003:
TRACE("Return mouse position and button status: (%d,%d) and %d\n",
mouse_info.x, mouse_info.y, mouse_info.but);
SET_BX( context, mouse_info.but );
SET_CX( context, mouse_info.x );
SET_DX( context, mouse_info.y );
break;
case 0x0004:
FIXME("Position mouse cursor\n");
break;
case 0x0005:
TRACE("Return Mouse button press Information for %s mouse button\n",
BX_reg(context) ? "right" : "left");
if (BX_reg(context))
{
SET_BX( context, mouse_info.rbcount );
mouse_info.rbcount = 0;
SET_CX( context, mouse_info.rlastx );
SET_DX( context, mouse_info.rlasty );
}
else
{
SET_BX( context, mouse_info.lbcount );
mouse_info.lbcount = 0;
SET_CX( context, mouse_info.llastx );
SET_DX( context, mouse_info.llasty );
}
SET_AX( context, mouse_info.but );
break;
case 0x0007:
FIXME("Define horizontal mouse cursor range %d..%d\n",
CX_reg(context), DX_reg(context));
break;
case 0x0008:
FIXME("Define vertical mouse cursor range %d..%d\n",
CX_reg(context), DX_reg(context));
break;
case 0x0009:
FIXME("Define graphics mouse cursor\n");
break;
case 0x000A:
FIXME("Define text mouse cursor\n");
break;
case 0x000B:
TRACE("Read Mouse motion counters\n");
{
int dx = ((int)mouse_info.x - (int)mouse_info.oldx)
* (mouse_info.HMPratio / 8);
int dy = ((int)mouse_info.y - (int)mouse_info.oldy)
* (mouse_info.VMPratio / 8);
SET_CX( context, (WORD)dx );
SET_DX( context, (WORD)dy );
mouse_info.oldx = mouse_info.x;
mouse_info.oldy = mouse_info.y;
}
break;
case 0x000C:
TRACE("Define mouse interrupt subroutine\n");
mouse_info.callmask = CX_reg(context);
mouse_info.callback = (FARPROC16)MAKESEGPTR(context->SegEs,
DX_reg(context));
break;
case 0x000F:
TRACE("Set mickey/pixel ratio\n");
mouse_info.HMPratio = CX_reg(context);
mouse_info.VMPratio = DX_reg(context);
break;
case 0x0010:
FIXME("Define screen region for update\n");
break;
case 0x0015:
TRACE("Get mouse driver state and memory requirements\n");
SET_BX(context, sizeof(mouse_info));
break;
case 0x0021:
TRACE("Software reset\n");
INT33_ResetMouse( context );
break;
default:
INT_BARF(context,0x33);
}
}
typedef struct {
FARPROC16 proc;
WORD mask,but,x,y,mx,my;
} MCALLDATA;
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);
}
static void QueueMouseRelay(DWORD mx, DWORD my, WORD mask)
{
mouse_info.x = mx;
mouse_info.y = my;
/* Left button down */
if(mask & 0x02) {
mouse_info.but |= 0x01;
mouse_info.llastx = mx;
mouse_info.llasty = my;
mouse_info.lbcount++;
}
/* Left button up */
if(mask & 0x04) {
mouse_info.but &= ~0x01;
}
/* Right button down */
if(mask & 0x08) {
mouse_info.but |= 0x02;
mouse_info.rlastx = mx;
mouse_info.rlasty = my;
mouse_info.rbcount++;
}
/* Right button up */
if(mask & 0x10) {
mouse_info.but &= ~0x02;
}
/* Middle button down */
if(mask & 0x20) {
mouse_info.but |= 0x04;
}
/* Middle button up */
if(mask & 0x40) {
mouse_info.but &= ~0x04;
}
if ((mask & mouse_info.callmask) && mouse_info.callback) {
MCALLDATA *data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MCALLDATA));
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;
/*
* Fake mickeys.
*
* FIXME: This is not entirely correct. If mouse if moved to the edge
* of the screen, mouse will stop moving and mickeys won't
* be updated even though they should be.
*/
data->mx = mouse_info.x * (mouse_info.HMPratio / 8);
data->my = mouse_info.y * (mouse_info.VMPratio / 8);
DOSVM_QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data);
}
}
void DOSVM_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
{
WORD mask = 0;
unsigned Height, Width, SX=1, SY=1;
if (VGA_GetMode(&Height, &Width, NULL)) {
/* may need to do some coordinate scaling */
if (Width)
SX = 640/Width;
if (!SX) SX=1;
}
switch (message) {
case WM_MOUSEMOVE:
mask |= 0x01;
break;
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
mask |= 0x02;
break;
case WM_LBUTTONUP:
mask |= 0x04;
break;
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
mask |= 0x08;
break;
case WM_RBUTTONUP:
mask |= 0x10;
break;
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
mask |= 0x20;
break;
case WM_MBUTTONUP:
mask |= 0x40;
break;
}
QueueMouseRelay(LOWORD(lParam) * SX,
HIWORD(lParam) * SY,
mask);
}
void DOSVM_Int33Console(MOUSE_EVENT_RECORD *record)
{
unsigned Height, Width;
WORD mask = 0;
BOOL newLeftButton = record->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED;
BOOL oldLeftButton = mouse_info.but & 0x01;
BOOL newRightButton = record->dwButtonState & RIGHTMOST_BUTTON_PRESSED;
BOOL oldRightButton = mouse_info.but & 0x02;
BOOL newMiddleButton = record->dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED;
BOOL oldMiddleButton = mouse_info.but & 0x04;
if(newLeftButton && !oldLeftButton)
mask |= 0x02;
else if(!newLeftButton && oldLeftButton)
mask |= 0x04;
if(newRightButton && !oldRightButton)
mask |= 0x08;
else if(!newRightButton && oldRightButton)
mask |= 0x10;
if(newMiddleButton && !oldMiddleButton)
mask |= 0x20;
else if(!newMiddleButton && oldMiddleButton)
mask |= 0x40;
if (VGA_GetAlphaMode(&Width, &Height))
QueueMouseRelay( 640 / Width * record->dwMousePosition.X,
200 / Height * record->dwMousePosition.Y,
mask );
}
......@@ -53,17 +53,17 @@ static const INTPROC DOSVM_VectorsBuiltin[] =
{
/* 00 */ 0, 0, 0, 0,
/* 04 */ 0, 0, 0, 0,
/* 08 */ DOSVM_Int08Handler, DOSVM_Int09Handler, 0, 0,
/* 08 */ 0, 0, 0, 0,
/* 0C */ 0, 0, 0, 0,
/* 10 */ DOSVM_Int10Handler, DOSVM_Int11Handler, DOSVM_Int12Handler, DOSVM_Int13Handler,
/* 14 */ 0, DOSVM_Int15Handler, DOSVM_Int16Handler, DOSVM_Int17Handler,
/* 14 */ 0, DOSVM_Int15Handler, 0, DOSVM_Int17Handler,
/* 18 */ 0, DOSVM_Int19Handler, DOSVM_Int1aHandler, 0,
/* 1C */ 0, 0, 0, 0,
/* 20 */ DOSVM_Int20Handler, DOSVM_Int21Handler, 0, 0,
/* 24 */ 0, DOSVM_Int25Handler, DOSVM_Int26Handler, 0,
/* 28 */ 0, DOSVM_Int29Handler, DOSVM_Int2aHandler, 0,
/* 2C */ 0, 0, 0, DOSVM_Int2fHandler,
/* 30 */ 0, DOSVM_Int31Handler, 0, DOSVM_Int33Handler,
/* 30 */ 0, DOSVM_Int31Handler, 0, 0,
/* 34 */ DOSVM_Int34Handler, DOSVM_Int35Handler, DOSVM_Int36Handler, DOSVM_Int37Handler,
/* 38 */ DOSVM_Int38Handler, DOSVM_Int39Handler, DOSVM_Int3aHandler, DOSVM_Int3bHandler,
/* 3C */ DOSVM_Int3cHandler, DOSVM_Int3dHandler, DOSVM_Int3eHandler, 0,
......@@ -111,23 +111,6 @@ static FARPROC16* DOSVM_GetRMVector( BYTE intnum )
/**********************************************************************
* DOSVM_IsIRQ
*
* Return TRUE if interrupt is an IRQ.
*/
static BOOL DOSVM_IsIRQ( BYTE intnum )
{
if (intnum >= 0x08 && intnum <= 0x0f)
return TRUE;
if (intnum >= 0x70 && intnum <= 0x77)
return TRUE;
return FALSE;
}
/**********************************************************************
* DOSVM_DefaultHandler
*
* Default interrupt handler. This will be used to emulate all
......@@ -152,10 +135,6 @@ static INTPROC DOSVM_GetBuiltinHandler( BYTE intnum )
}
WARN("int%x not implemented, returning dummy handler\n", intnum );
if (DOSVM_IsIRQ(intnum))
return DOSVM_AcknowledgeIRQ;
return DOSVM_DefaultHandler;
}
......@@ -173,33 +152,6 @@ static void DOSVM_IntProcRelay( CONTEXT *context, LPVOID data )
/**********************************************************************
* DOSVM_PrepareIRQ
*
*/
static void DOSVM_PrepareIRQ( CONTEXT *context, BOOL isbuiltin )
{
/* Disable virtual interrupts. */
get_vm86_teb_info()->dpmi_vif = 0;
if (!isbuiltin)
{
DWORD *stack = CTX_SEG_OFF_TO_LIN(context,
context->SegSs,
context->Esp);
/* Push return address to stack. */
*(--stack) = context->SegCs;
*(--stack) = context->Eip;
context->Esp += -8;
/* Jump to enable interrupts stub. */
context->SegCs = DOSVM_dpmi_segments->relay_code_sel;
context->Eip = 5;
}
}
/**********************************************************************
* DOSVM_PushFlags
*
* This routine is used to make default int25 and int26 handlers leave the
......@@ -365,8 +317,6 @@ void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum )
if (intnum == 0x25 || intnum == 0x26)
DOSVM_PushFlags( context, TRUE, FALSE );
else if (DOSVM_IsIRQ(intnum))
DOSVM_PrepareIRQ( context, TRUE );
DOSVM_BuildCallFrame( context,
DOSVM_IntProcRelay,
......@@ -379,9 +329,6 @@ void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum )
TRACE( "invoking hooked interrupt %02x at %04x:%08x\n",
intnum, addr.selector, addr.offset );
if (DOSVM_IsIRQ(intnum))
DOSVM_PrepareIRQ( context, FALSE );
/* Push the flags and return address on the stack */
stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
......@@ -407,8 +354,6 @@ void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum )
if (intnum == 0x25 || intnum == 0x26)
DOSVM_PushFlags( context, FALSE, FALSE );
else if (DOSVM_IsIRQ(intnum))
DOSVM_PrepareIRQ( context, TRUE );
DOSVM_BuildCallFrame( context,
DOSVM_IntProcRelay,
......@@ -420,9 +365,6 @@ void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum )
TRACE( "invoking hooked interrupt %02x at %04x:%04x\n",
intnum, SELECTOROF(addr), OFFSETOF(addr) );
if (DOSVM_IsIRQ(intnum))
DOSVM_PrepareIRQ( context, FALSE );
/* Push the flags and return address on the stack */
PUSH_WORD16( context, LOWORD(context->EFlags) );
PUSH_WORD16( context, context->SegCs );
......@@ -437,54 +379,6 @@ void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum )
/**********************************************************************
* DOSVM_HardwareInterruptRM
*
* Emulate call to interrupt handler in real mode.
*
* Either calls directly builtin handler or pushes interrupt frame to
* stack and changes instruction pointer to interrupt handler.
*/
void DOSVM_HardwareInterruptRM( CONTEXT *context, BYTE intnum )
{
FARPROC16 handler = DOSVM_GetRMHandler( intnum );
/* check if the call goes to an unhooked interrupt */
if (SELECTOROF(handler) == 0xf000)
{
/* if so, call it directly */
TRACE( "builtin interrupt %02x has been invoked "
"(through vector %02x)\n",
OFFSETOF(handler)/DOSVM_STUB_RM, intnum );
DOSVM_CallBuiltinHandler( context, OFFSETOF(handler)/DOSVM_STUB_RM );
}
else
{
/* the interrupt is hooked, simulate interrupt in DOS space */
WORD flag = LOWORD( context->EFlags );
TRACE( "invoking hooked interrupt %02x at %04x:%04x\n",
intnum, SELECTOROF(handler), OFFSETOF(handler) );
/* Copy virtual interrupt flag to pushed interrupt flag. */
if (context->EFlags & VIF_MASK)
flag |= IF_MASK;
else
flag &= ~IF_MASK;
PUSH_WORD16( context, flag );
PUSH_WORD16( context, context->SegCs );
PUSH_WORD16( context, LOWORD( context->Eip ));
context->SegCs = SELECTOROF( handler );
context->Eip = OFFSETOF( handler );
/* Clear virtual interrupt flag and trap flag. */
context->EFlags &= ~(VIF_MASK | TF_MASK);
}
}
/**********************************************************************
* DOSVM_GetRMHandler
*
* Return the real mode interrupt vector for a given interrupt.
......
......@@ -210,7 +210,6 @@ static void set_timer(unsigned timer)
switch (timer) {
case 0: /* System timer counter divisor */
DOSVM_SetTimer(val);
break;
case 1: /* RAM refresh */
FIXME("RAM refresh counter handling not implemented !\n");
......@@ -817,7 +816,6 @@ DWORD DOSVM_inport( int port, int size )
}
break;
case 0x60:
res = DOSVM_Int09ReadScan(NULL);
break;
case 0x61:
res = (DWORD)parport_8255[1];
......@@ -968,7 +966,6 @@ void DOSVM_outport( int port, int size, DWORD value )
switch (port)
{
case 0x20:
DOSVM_PIC_ioport_out( port, (BYTE)value );
break;
case 0x40:
case 0x41:
......
......@@ -110,10 +110,7 @@ static DWORD CALLBACK SB_Poll( void *dummy )
ERR("Unable to unlock sound buffer !\n");
SamplesCount -= size;
if (!SamplesCount) {
DOSVM_QueueEvent(SB_IRQ,SB_IRQ_PRI,NULL,NULL);
dma_enable = FALSE;
}
if (!SamplesCount) dma_enable = FALSE;
}
return 0;
}
......@@ -300,7 +297,6 @@ void SB_ioport_out( WORD port, BYTE val )
break;
case 0xF2: /* SB */
TRACE("IRQ Request (8-bit)\n");
DOSVM_QueueEvent(SB_IRQ,SB_IRQ_PRI,NULL,NULL);
break;
default:
if (((command&0xF0)==0xB0)||((DSP_InBuffer[0]&0xF0)==0xC0)) {
......
/*
* 8253/8254 Programmable Interval Timer (PIT) emulation
*
* Copyright 2003 Jukka Heinonen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "dosexe.h"
#include "wingdi.h"
#include "winuser.h"
/***********************************************************************
* DOSVM_SetTimer
*/
void DOSVM_SetTimer( UINT ticks )
{
}
/***********************************************************************
* DOSVM_Int08Handler
*
* DOS interrupt 08h handler (IRQ0 - TIMER).
*/
void WINAPI DOSVM_Int08Handler( CONTEXT *context )
{
BIOSDATA *bios_data = DOSVM_BiosData();
CONTEXT nested_context = *context;
FARPROC16 int1c_proc = DOSVM_GetRMHandler( 0x1c );
nested_context.SegCs = SELECTOROF(int1c_proc);
nested_context.Eip = OFFSETOF(int1c_proc);
/*
* Update BIOS ticks since midnight.
*
* FIXME: What to do when number of ticks exceeds ticks per day?
*/
bios_data->Ticks++;
/*
* If IRQ is called from protected mode, convert
* context into VM86 context. Stack is invalidated so
* that DPMI_CallRMProc allocates a new stack.
*/
if (!ISV86(&nested_context))
{
nested_context.EFlags |= V86_FLAG;
nested_context.SegSs = 0;
}
/*
* Call interrupt 0x1c.
*/
DPMI_CallRMProc( &nested_context, NULL, 0, TRUE );
DOSVM_AcknowledgeIRQ( context );
}
......@@ -46,19 +46,11 @@ extern void WINAPI wine_call_to_16_regs( CONTEXT *context, DWORD cbArgs, PEXCEPT
extern void __wine_call_to_16_ret(void);
extern void CALL32_CBClient_Ret(void);
extern void CALL32_CBClientEx_Ret(void);
extern void DPMI_PendingEventCheck(void);
extern void DPMI_PendingEventCheck_Cleanup(void);
extern void DPMI_PendingEventCheck_Return(void);
extern BYTE __wine_call16_start[];
extern BYTE __wine_call16_end[];
static SEGPTR call16_ret_addr; /* segptr to __wine_call_to_16_ret routine */
static WORD dpmi_checker_selector;
static DWORD dpmi_checker_offset_call;
static DWORD dpmi_checker_offset_cleanup;
static DWORD dpmi_checker_offset_return;
/***********************************************************************
* WOWTHUNK_Init
*/
......@@ -83,12 +75,6 @@ BOOL WOWTHUNK_Init(void)
CALL32_CBClientEx_RetAddr =
MAKESEGPTR( codesel, (BYTE *)CALL32_CBClientEx_Ret - __wine_call16_start );
/* Prepare selector and offsets for DPMI event checking. */
dpmi_checker_selector = codesel;
dpmi_checker_offset_call = (BYTE *)DPMI_PendingEventCheck - __wine_call16_start;
dpmi_checker_offset_cleanup = (BYTE *)DPMI_PendingEventCheck_Cleanup - __wine_call16_start;
dpmi_checker_offset_return = (BYTE *)DPMI_PendingEventCheck_Return - __wine_call16_start;
if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY16_InitDebugLists();
return TRUE;
......@@ -138,79 +124,6 @@ static BOOL fix_selector( CONTEXT *context )
/*************************************************************
* insert_event_check
*
* Make resuming the context check for pending DPMI events
* before the original context is restored. This is required
* because DPMI events are asynchronous, they are blocked while
* Wine 32-bit code is being executed and we want to prevent
* a race when returning back to 16-bit or 32-bit DPMI context.
*/
static void insert_event_check( CONTEXT *context )
{
char *stack = wine_ldt_get_ptr( context->SegSs, context->Esp );
/* don't do event check while in system code */
if (wine_ldt_is_system(context->SegCs))
return;
if(context->SegCs == dpmi_checker_selector &&
context->Eip >= dpmi_checker_offset_call &&
context->Eip <= dpmi_checker_offset_cleanup)
{
/*
* Nested call. Stack will be preserved.
*/
}
else if(context->SegCs == dpmi_checker_selector &&
context->Eip == dpmi_checker_offset_return)
{
/*
* Nested call. We have just finished popping the fs
* register, lets put it back into stack.
*/
stack -= sizeof(WORD);
*(WORD*)stack = context->SegFs;
context->Esp -= 2;
}
else
{
/*
* Call is not nested.
* Push modified registers into stack.
* These will be popped by the assembler stub.
*/
stack -= sizeof(DWORD);
*(DWORD*)stack = context->EFlags;
stack -= sizeof(DWORD);
*(DWORD*)stack = context->SegCs;
stack -= sizeof(DWORD);
*(DWORD*)stack = context->Eip;
stack -= sizeof(WORD);
*(WORD*)stack = context->SegFs;
context->Esp -= 14;
}
/*
* Modify the context so that we jump into assembler stub.
* TEB access is made easier by providing the stub
* with the correct fs register value.
*/
context->SegCs = dpmi_checker_selector;
context->Eip = dpmi_checker_offset_call;
context->SegFs = wine_get_fs();
}
/*************************************************************
* call16_handler
*
* Handler for exceptions occurring in 16-bit code.
......@@ -237,15 +150,6 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RE
SEGPTR gpHandler;
DWORD ret = __wine_emulate_instruction( record, context );
/*
* Insert check for pending DPMI events. Note that this
* check must be inserted after instructions have been
* emulated because the instruction emulation requires
* original CS:IP and the emulation may change TEB.dpmi_vif.
*/
if(get_vm86_teb_info()->dpmi_vif)
insert_event_check( context );
if (ret != ExceptionContinueSearch) return ret;
/* check for Win16 __GP handler */
......@@ -267,10 +171,6 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RE
}
}
}
else if (record->ExceptionCode == EXCEPTION_VM86_STI)
{
insert_event_check( context );
}
return ExceptionContinueSearch;
}
......@@ -546,19 +446,6 @@ BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
cbArgs += sizeof(SEGPTR);
}
/*
* Start call by checking for pending events.
* Note that wine_call_to_16_regs overwrites context stack
* pointer so we may modify it here without a problem.
*/
if (get_vm86_teb_info()->dpmi_vif)
{
context->SegSs = wine_get_ds();
context->Esp = (DWORD)stack;
insert_event_check( context );
cbArgs += (DWORD)stack - context->Esp;
}
_EnterWin16Lock();
wine_call_to_16_regs( context, cbArgs, call16_handler );
_LeaveWin16Lock();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment