mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-06 18:50:07 +00:00
krnl386: Remove support for DOS devices and event handling.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0741d193ff
commit
5ec5449596
|
@ -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 \
|
||||
|
|
|
@ -1,489 +0,0 @@
|
|||
/*
|
||||
* DOS devices
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "wine/winbase16.h"
|
||||
#include "dosexe.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "pshpack1.h"
|
||||
|
||||
/* Warning: need to return LOL ptr w/ offset 0 (&ptr_first_DPB) to programs ! */
|
||||
typedef struct _DOS_LISTOFLISTS
|
||||
{
|
||||
WORD CX_Int21_5e01; /* -24d contents of CX from INT 21/AX=5E01h */
|
||||
WORD LRU_count_FCB_cache; /* -22d */
|
||||
WORD LRU_count_FCB_open; /* -20d */
|
||||
DWORD OEM_func_handler; /* -18d OEM function of INT 21/AH=F8h */
|
||||
WORD INT21_offset; /* -14d offset in DOS CS of code to return from INT 21 call */
|
||||
WORD sharing_retry_count; /* -12d */
|
||||
WORD sharing_retry_delay; /* -10d */
|
||||
DWORD ptr_disk_buf; /* -8d ptr to current disk buf */
|
||||
WORD offs_unread_CON; /* -4d pointer in DOS data segment of unread CON input */
|
||||
WORD seg_first_MCB; /* -2d */
|
||||
DWORD ptr_first_DPB; /* 00 */
|
||||
DWORD ptr_first_SysFileTable; /* 04 */
|
||||
DWORD ptr_clock_dev_hdr; /* 08 */
|
||||
DWORD ptr_CON_dev_hdr; /* 0C */
|
||||
WORD max_byte_per_sec; /* 10 maximum bytes per sector of any block device */
|
||||
DWORD ptr_disk_buf_info; /* 12 */
|
||||
DWORD ptr_array_CDS; /* 16 current directory structure */
|
||||
DWORD ptr_sys_FCB; /* 1A */
|
||||
WORD nr_protect_FCB; /* 1E */
|
||||
BYTE nr_block_dev; /* 20 */
|
||||
BYTE nr_avail_drive_letters; /* 21 */
|
||||
DOS_DEVICE_HEADER NUL_dev; /* 22 */
|
||||
BYTE nr_drives_JOINed; /* 34 */
|
||||
WORD ptr_spec_prg_names; /* 35 */
|
||||
DWORD ptr_SETVER_prg_list; /* 37 */
|
||||
WORD DOS_HIGH_A20_func_offs;/* 3B */
|
||||
WORD PSP_last_exec; /* 3D if DOS in HMA: PSP of program executed last; if DOS low: 0000h */
|
||||
WORD BUFFERS_val; /* 3F */
|
||||
WORD BUFFERS_nr_lookahead; /* 41 */
|
||||
BYTE boot_drive; /* 43 */
|
||||
BYTE flag_DWORD_moves; /* 44 01h for 386+, 00h otherwise */
|
||||
WORD size_extended_mem; /* 45 size of extended mem in KB */
|
||||
SEGPTR wine_rm_lol; /* -- wine: Real mode pointer to LOL */
|
||||
SEGPTR wine_pm_lol; /* -- wine: Protected mode pointer to LOL */
|
||||
} DOS_LISTOFLISTS;
|
||||
|
||||
#include "poppack.h"
|
||||
|
||||
#define CON_BUFFER 128
|
||||
|
||||
enum strategy { SYSTEM_STRATEGY_NUL, SYSTEM_STRATEGY_CON, NB_SYSTEM_STRATEGIES };
|
||||
|
||||
static void *strategy_data[NB_SYSTEM_STRATEGIES];
|
||||
|
||||
#define LJMP 0xea
|
||||
|
||||
|
||||
/* prototypes */
|
||||
static void WINAPI nul_strategy(CONTEXT*ctx);
|
||||
static void WINAPI nul_interrupt(CONTEXT*ctx);
|
||||
static void WINAPI con_strategy(CONTEXT*ctx);
|
||||
static void WINAPI con_interrupt(CONTEXT*ctx);
|
||||
|
||||
/* devices */
|
||||
static const WINEDEV devs[] =
|
||||
{
|
||||
{ "NUL ",
|
||||
ATTR_CHAR|ATTR_NUL|ATTR_DEVICE,
|
||||
nul_strategy, nul_interrupt },
|
||||
|
||||
{ "CON ",
|
||||
ATTR_CHAR|ATTR_STDIN|ATTR_STDOUT|ATTR_FASTCON|ATTR_NOTEOF|ATTR_DEVICE,
|
||||
con_strategy, con_interrupt }
|
||||
};
|
||||
|
||||
#define NR_DEVS (sizeof(devs)/sizeof(WINEDEV))
|
||||
|
||||
/* DOS data segment */
|
||||
typedef struct
|
||||
{
|
||||
DOS_LISTOFLISTS lol;
|
||||
DOS_DEVICE_HEADER dev[NR_DEVS-1];
|
||||
DOS_DEVICE_HEADER *last_dev; /* ptr to last registered device driver */
|
||||
WINEDEV_THUNK thunk[NR_DEVS];
|
||||
REQ_IO req;
|
||||
BYTE buffer[CON_BUFFER];
|
||||
|
||||
} DOS_DATASEG;
|
||||
|
||||
#define DOS_DATASEG_OFF(xxx) FIELD_OFFSET(DOS_DATASEG, xxx)
|
||||
|
||||
static DWORD DOS_LOLSeg;
|
||||
|
||||
static struct _DOS_LISTOFLISTS * DOSMEM_LOL(void)
|
||||
{
|
||||
return PTR_REAL_TO_LIN(HIWORD(DOS_LOLSeg),0);
|
||||
}
|
||||
|
||||
|
||||
/* the device implementations */
|
||||
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 do_strategy(CONTEXT*ctx, int id, int extra)
|
||||
{
|
||||
REQUEST_HEADER *hdr = CTX_SEG_OFF_TO_LIN(ctx, ctx->SegEs, ctx->Ebx);
|
||||
void **hdr_ptr = strategy_data[id];
|
||||
|
||||
if (!hdr_ptr) {
|
||||
hdr_ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(void *)+extra);
|
||||
strategy_data[id] = hdr_ptr;
|
||||
}
|
||||
*hdr_ptr = hdr;
|
||||
do_lret(ctx);
|
||||
}
|
||||
|
||||
static REQUEST_HEADER * get_hdr(int id, void**extra)
|
||||
{
|
||||
void **hdr_ptr = strategy_data[id];
|
||||
if (extra)
|
||||
*extra = hdr_ptr ? (void*)(hdr_ptr+1) : NULL;
|
||||
return hdr_ptr ? *hdr_ptr : NULL;
|
||||
}
|
||||
|
||||
static void WINAPI nul_strategy(CONTEXT*ctx)
|
||||
{
|
||||
do_strategy(ctx, SYSTEM_STRATEGY_NUL, 0);
|
||||
}
|
||||
|
||||
static void WINAPI nul_interrupt(CONTEXT*ctx)
|
||||
{
|
||||
REQUEST_HEADER *hdr = get_hdr(SYSTEM_STRATEGY_NUL, NULL);
|
||||
/* eat everything and recycle nothing */
|
||||
switch (hdr->command) {
|
||||
case CMD_INPUT:
|
||||
((REQ_IO*)hdr)->count = 0;
|
||||
hdr->status = STAT_DONE;
|
||||
break;
|
||||
case CMD_SAFEINPUT:
|
||||
hdr->status = STAT_DONE|STAT_BUSY;
|
||||
break;
|
||||
default:
|
||||
hdr->status = STAT_DONE;
|
||||
}
|
||||
do_lret(ctx);
|
||||
}
|
||||
|
||||
static void WINAPI con_strategy(CONTEXT*ctx)
|
||||
{
|
||||
do_strategy(ctx, SYSTEM_STRATEGY_CON, sizeof(int));
|
||||
}
|
||||
|
||||
static void WINAPI con_interrupt(CONTEXT*ctx)
|
||||
{
|
||||
int *scan;
|
||||
REQUEST_HEADER *hdr = get_hdr(SYSTEM_STRATEGY_CON,(void **)&scan);
|
||||
BIOSDATA *bios = DOSVM_BiosData();
|
||||
WORD CurOfs = bios->NextKbdCharPtr;
|
||||
DOS_LISTOFLISTS *lol = DOSMEM_LOL();
|
||||
DOS_DATASEG *dataseg = (DOS_DATASEG *)lol;
|
||||
BYTE *linebuffer = dataseg->buffer;
|
||||
BYTE *curbuffer = (lol->offs_unread_CON) ?
|
||||
(((BYTE*)dataseg) + lol->offs_unread_CON) : NULL;
|
||||
DOS_DEVICE_HEADER *con = dataseg->dev;
|
||||
DWORD w;
|
||||
|
||||
switch (hdr->command) {
|
||||
case CMD_INPUT:
|
||||
{
|
||||
REQ_IO *io = (REQ_IO *)hdr;
|
||||
WORD count = io->count, len = 0;
|
||||
BYTE *buffer = CTX_SEG_OFF_TO_LIN(ctx,
|
||||
SELECTOROF(io->buffer),
|
||||
(DWORD)OFFSETOF(io->buffer));
|
||||
|
||||
hdr->status = STAT_BUSY;
|
||||
/* first, check whether we already have data in line buffer */
|
||||
if (curbuffer) {
|
||||
/* yep, copy as much as we can */
|
||||
BYTE data = 0;
|
||||
while ((len<count) && (data != '\r')) {
|
||||
data = *curbuffer++;
|
||||
buffer[len++] = data;
|
||||
}
|
||||
if (data == '\r') {
|
||||
/* line buffer emptied */
|
||||
lol->offs_unread_CON = 0;
|
||||
curbuffer = NULL;
|
||||
/* if we're not in raw mode, call it a day */
|
||||
if (!(con->attr & ATTR_RAW)) {
|
||||
hdr->status = STAT_DONE;
|
||||
io->count = len;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* still some data left */
|
||||
lol->offs_unread_CON = curbuffer - (BYTE*)lol;
|
||||
/* but buffer was filled, we're done */
|
||||
hdr->status = STAT_DONE;
|
||||
io->count = len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we're in raw mode, we just need to fill the buffer */
|
||||
if (con->attr & ATTR_RAW) {
|
||||
while (len<count) {
|
||||
WORD data;
|
||||
|
||||
/* do we have a waiting scancode? */
|
||||
if (*scan) {
|
||||
/* yes, store scancode in buffer */
|
||||
buffer[len++] = *scan;
|
||||
*scan = 0;
|
||||
if (len==count) break;
|
||||
}
|
||||
|
||||
/* check for new keyboard input */
|
||||
while (CurOfs == bios->FirstKbdCharPtr) {
|
||||
/* no input available yet, so wait... */
|
||||
DOSVM_Wait( ctx );
|
||||
}
|
||||
/* read from keyboard queue (call int16?) */
|
||||
data = ((WORD*)bios)[CurOfs];
|
||||
CurOfs += 2;
|
||||
if (CurOfs >= bios->KbdBufferEnd) CurOfs = bios->KbdBufferStart;
|
||||
bios->NextKbdCharPtr = CurOfs;
|
||||
/* if it's an extended key, save scancode */
|
||||
if (LOBYTE(data) == 0) *scan = HIBYTE(data);
|
||||
/* store ASCII char in buffer */
|
||||
buffer[len++] = LOBYTE(data);
|
||||
}
|
||||
} else {
|
||||
/* we're not in raw mode, so we need to do line input... */
|
||||
while (TRUE) {
|
||||
WORD data;
|
||||
/* check for new keyboard input */
|
||||
while (CurOfs == bios->FirstKbdCharPtr) {
|
||||
/* no input available yet, so wait... */
|
||||
DOSVM_Wait( ctx );
|
||||
}
|
||||
/* read from keyboard queue (call int16?) */
|
||||
data = ((WORD*)bios)[CurOfs];
|
||||
CurOfs += 2;
|
||||
if (CurOfs >= bios->KbdBufferEnd) CurOfs = bios->KbdBufferStart;
|
||||
bios->NextKbdCharPtr = CurOfs;
|
||||
|
||||
if (LOBYTE(data) == '\r') {
|
||||
/* it's the return key, we're done */
|
||||
linebuffer[len++] = LOBYTE(data);
|
||||
break;
|
||||
}
|
||||
else if (LOBYTE(data) >= ' ') {
|
||||
/* a character */
|
||||
if ((len+1)<CON_BUFFER) {
|
||||
linebuffer[len] = LOBYTE(data);
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &linebuffer[len++], 1, &w, NULL);
|
||||
}
|
||||
/* else beep, but I don't like noise */
|
||||
}
|
||||
else switch (LOBYTE(data)) {
|
||||
case '\b':
|
||||
if (len>0) {
|
||||
len--;
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\b \b", 3, &w, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (len > count) {
|
||||
/* save rest of line for later */
|
||||
lol->offs_unread_CON = linebuffer - (BYTE*)lol + count;
|
||||
len = count;
|
||||
}
|
||||
memcpy(buffer, linebuffer, len);
|
||||
}
|
||||
hdr->status = STAT_DONE;
|
||||
io->count = len;
|
||||
}
|
||||
break;
|
||||
case CMD_SAFEINPUT:
|
||||
if (curbuffer) {
|
||||
/* some line input waiting */
|
||||
hdr->status = STAT_DONE;
|
||||
((REQ_SAFEINPUT*)hdr)->data = *curbuffer;
|
||||
}
|
||||
else if (con->attr & ATTR_RAW) {
|
||||
if (CurOfs == bios->FirstKbdCharPtr) {
|
||||
/* no input */
|
||||
hdr->status = STAT_DONE|STAT_BUSY;
|
||||
} else {
|
||||
/* some keyboard input waiting */
|
||||
hdr->status = STAT_DONE;
|
||||
((REQ_SAFEINPUT*)hdr)->data = ((BYTE*)bios)[CurOfs];
|
||||
}
|
||||
} else {
|
||||
/* no line input */
|
||||
hdr->status = STAT_DONE|STAT_BUSY;
|
||||
}
|
||||
break;
|
||||
case CMD_INSTATUS:
|
||||
if (curbuffer) {
|
||||
/* we have data */
|
||||
hdr->status = STAT_DONE;
|
||||
}
|
||||
else if (con->attr & ATTR_RAW) {
|
||||
if (CurOfs == bios->FirstKbdCharPtr) {
|
||||
/* no input */
|
||||
hdr->status = STAT_DONE|STAT_BUSY;
|
||||
} else {
|
||||
/* some keyboard input waiting */
|
||||
hdr->status = STAT_DONE;
|
||||
}
|
||||
} else {
|
||||
/* no line input */
|
||||
hdr->status = STAT_DONE|STAT_BUSY;
|
||||
}
|
||||
|
||||
break;
|
||||
case CMD_INFLUSH:
|
||||
/* flush line and keyboard queue */
|
||||
lol->offs_unread_CON = 0;
|
||||
bios->NextKbdCharPtr = bios->FirstKbdCharPtr;
|
||||
break;
|
||||
case CMD_OUTPUT:
|
||||
case CMD_SAFEOUTPUT:
|
||||
{
|
||||
REQ_IO *io = (REQ_IO *)hdr;
|
||||
BYTE *buffer = CTX_SEG_OFF_TO_LIN(ctx,
|
||||
SELECTOROF(io->buffer),
|
||||
(DWORD)OFFSETOF(io->buffer));
|
||||
DWORD result = 0;
|
||||
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buffer, io->count, &result, NULL);
|
||||
io->count = result;
|
||||
hdr->status = STAT_DONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
hdr->status = STAT_DONE;
|
||||
}
|
||||
do_lret(ctx);
|
||||
}
|
||||
|
||||
static void InitListOfLists(DOS_LISTOFLISTS *DOS_LOL)
|
||||
{
|
||||
/*
|
||||
Output of DOS 6.22:
|
||||
|
||||
0133:0020 6A 13-33 01 CC 00 33 01 59 00 j.3...3.Y.
|
||||
0133:0030 70 00 00 00 72 02 00 02-6D 00 33 01 00 00 2E 05 p...r...m.3.....
|
||||
0133:0040 00 00 FC 04 00 00 03 08-92 21 11 E0 04 80 C6 0D .........!......
|
||||
0133:0050 CC 0D 4E 55 4C 20 20 20-20 20 00 00 00 00 00 00 ..NUL ......
|
||||
0133:0060 00 4B BA C1 06 14 00 00-00 03 01 00 04 70 CE FF .K...........p..
|
||||
0133:0070 FF 00 00 00 00 00 00 00-00 01 00 00 0D 05 00 00 ................
|
||||
0133:0080 00 FF FF 00 00 00 00 FE-00 00 F8 03 FF 9F 70 02 ..............p.
|
||||
0133:0090 D0 44 C8 FD D4 44 C8 FD-D4 44 C8 FD D0 44 C8 FD .D...D...D...D..
|
||||
0133:00A0 D0 44 C8 FD D0 44 .D...D
|
||||
*/
|
||||
DOS_LOL->CX_Int21_5e01 = 0x0;
|
||||
DOS_LOL->LRU_count_FCB_cache = 0x0;
|
||||
DOS_LOL->LRU_count_FCB_open = 0x0;
|
||||
DOS_LOL->OEM_func_handler = -1; /* not available */
|
||||
DOS_LOL->INT21_offset = 0x0;
|
||||
DOS_LOL->sharing_retry_count = 3;
|
||||
DOS_LOL->sharing_retry_delay = 1;
|
||||
DOS_LOL->ptr_disk_buf = 0x0;
|
||||
DOS_LOL->offs_unread_CON = 0x0;
|
||||
DOS_LOL->seg_first_MCB = 0x0;
|
||||
DOS_LOL->ptr_first_DPB = 0x0;
|
||||
DOS_LOL->ptr_first_SysFileTable = 0x0;
|
||||
DOS_LOL->ptr_clock_dev_hdr = 0x0;
|
||||
DOS_LOL->ptr_CON_dev_hdr = 0x0;
|
||||
DOS_LOL->max_byte_per_sec = 512;
|
||||
DOS_LOL->ptr_disk_buf_info = 0x0;
|
||||
DOS_LOL->ptr_array_CDS = 0x0;
|
||||
DOS_LOL->ptr_sys_FCB = 0x0;
|
||||
DOS_LOL->nr_protect_FCB = 0x0;
|
||||
DOS_LOL->nr_block_dev = 0x0;
|
||||
DOS_LOL->nr_avail_drive_letters = 26; /* A - Z */
|
||||
DOS_LOL->nr_drives_JOINed = 0x0;
|
||||
DOS_LOL->ptr_spec_prg_names = 0x0;
|
||||
DOS_LOL->ptr_SETVER_prg_list = 0x0; /* no SETVER list */
|
||||
DOS_LOL->DOS_HIGH_A20_func_offs = 0x0;
|
||||
DOS_LOL->PSP_last_exec = 0x0;
|
||||
DOS_LOL->BUFFERS_val = 99; /* maximum: 99 */
|
||||
DOS_LOL->BUFFERS_nr_lookahead = 8; /* maximum: 8 */
|
||||
DOS_LOL->boot_drive = 3; /* C: */
|
||||
DOS_LOL->flag_DWORD_moves = 0x01; /* i386+ */
|
||||
DOS_LOL->size_extended_mem = 0xf000; /* very high value */
|
||||
}
|
||||
|
||||
void DOSDEV_SetupDevice(const WINEDEV * devinfo,
|
||||
WORD seg, WORD off_dev, WORD off_thunk)
|
||||
{
|
||||
DOS_DEVICE_HEADER *dev = PTR_REAL_TO_LIN(seg, off_dev);
|
||||
WINEDEV_THUNK *thunk = PTR_REAL_TO_LIN(seg, off_thunk);
|
||||
DOS_DATASEG *dataseg = (DOS_DATASEG*)DOSMEM_LOL();
|
||||
|
||||
dev->attr = devinfo->attr;
|
||||
dev->strategy = off_thunk + FIELD_OFFSET(WINEDEV_THUNK, ljmp1);
|
||||
dev->interrupt = off_thunk + FIELD_OFFSET(WINEDEV_THUNK, ljmp2);
|
||||
memcpy(dev->name, devinfo->name, 8);
|
||||
|
||||
thunk->ljmp1 = LJMP;
|
||||
thunk->strategy = DPMI_AllocInternalRMCB(devinfo->strategy);
|
||||
thunk->ljmp2 = LJMP;
|
||||
thunk->interrupt = DPMI_AllocInternalRMCB(devinfo->interrupt);
|
||||
|
||||
dev->next_dev = NONEXT;
|
||||
if (dataseg->last_dev)
|
||||
dataseg->last_dev->next_dev = MAKESEGPTR(seg, off_dev);
|
||||
dataseg->last_dev = dev;
|
||||
}
|
||||
|
||||
void DOSDEV_InstallDOSDevices(void)
|
||||
{
|
||||
DOS_DATASEG *dataseg;
|
||||
WORD seg;
|
||||
WORD selector;
|
||||
unsigned int n;
|
||||
|
||||
/* allocate DOS data segment or something */
|
||||
dataseg = DOSVM_AllocDataUMB( sizeof(DOS_DATASEG), &seg, &selector );
|
||||
|
||||
DOS_LOLSeg = MAKESEGPTR( seg, 0 );
|
||||
DOSMEM_LOL()->wine_rm_lol =
|
||||
MAKESEGPTR( seg, FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB) );
|
||||
DOSMEM_LOL()->wine_pm_lol =
|
||||
MAKESEGPTR( selector, FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB) );
|
||||
|
||||
/* initialize the magnificent List Of Lists */
|
||||
InitListOfLists(&dataseg->lol);
|
||||
|
||||
/* Set up first device (NUL) */
|
||||
dataseg->last_dev = NULL;
|
||||
DOSDEV_SetupDevice( &devs[0],
|
||||
seg,
|
||||
DOS_DATASEG_OFF(lol.NUL_dev),
|
||||
DOS_DATASEG_OFF(thunk[0]) );
|
||||
|
||||
/* Set up the remaining devices */
|
||||
for (n = 1; n < NR_DEVS; n++)
|
||||
DOSDEV_SetupDevice( &devs[n],
|
||||
seg,
|
||||
DOS_DATASEG_OFF(dev[n-1]),
|
||||
DOS_DATASEG_OFF(thunk[n]) );
|
||||
|
||||
/* CON is device 1 */
|
||||
dataseg->lol.ptr_CON_dev_hdr = MAKESEGPTR(seg, DOS_DATASEG_OFF(dev[0]));
|
||||
}
|
||||
|
||||
void DOSDEV_SetSharingRetry(WORD delay, WORD count)
|
||||
{
|
||||
DOSMEM_LOL()->sharing_retry_delay = delay;
|
||||
if (count) DOSMEM_LOL()->sharing_retry_count = count;
|
||||
}
|
||||
|
||||
SEGPTR DOSDEV_GetLOL(BOOL v86)
|
||||
{
|
||||
if (v86) return DOSMEM_LOL()->wine_rm_lol;
|
||||
else return DOSMEM_LOL()->wine_pm_lol;
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
|
@ -272,53 +100,6 @@ void DOSVM_Exit( WORD retval )
|
|||
ExitThread( 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
|
||||
*
|
||||
|
@ -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 */
|
||||
|
|
|
@ -1,244 +0,0 @@
|
|||
/*
|
||||
* 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];
|
||||
}
|
|
@ -1,215 +0,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;
|
||||
}
|
|
@ -368,40 +368,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
|
||||
*
|
||||
|
@ -1142,67 +1108,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
|
||||
*/
|
||||
|
@ -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) );
|
||||
}
|
||||
|
|
|
@ -118,36 +118,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
|
||||
*/
|
||||
|
@ -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" );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,367 +0,0 @@
|
|||
/*
|
||||
* 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,
|
||||
|
@ -110,23 +110,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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -172,33 +151,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
|
||||
*
|
||||
|
@ -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 );
|
||||
|
@ -436,54 +378,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
|
||||
*
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
|
@ -137,79 +123,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
|
||||
*
|
||||
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue