Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
ed6bdb3c
Commit
ed6bdb3c
authored
Feb 05, 2018
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
krnl386: Remove support for DPMI real-mode calls.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
4a589081
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
30 additions
and
1316 deletions
+30
-1316
Makefile.in
dlls/krnl386.exe16/Makefile.in
+0
-1
dosaspi.c
dlls/krnl386.exe16/dosaspi.c
+0
-234
dosexe.h
dlls/krnl386.exe16/dosexe.h
+0
-23
dosvm.c
dlls/krnl386.exe16/dosvm.c
+3
-98
instr.c
dlls/krnl386.exe16/instr.c
+0
-2
int21.c
dlls/krnl386.exe16/int21.c
+2
-12
int2f.c
dlls/krnl386.exe16/int2f.c
+1
-19
int31.c
dlls/krnl386.exe16/int31.c
+23
-780
interrupts.c
dlls/krnl386.exe16/interrupts.c
+1
-147
No files found.
dlls/krnl386.exe16/Makefile.in
View file @
ed6bdb3c
...
...
@@ -7,7 +7,6 @@ EXTRADLLFLAGS = -m16 -nodefaultlibs -Wb,--dll-name,kernel
C_SRCS
=
\
atom.c
\
dma.c
\
dosaspi.c
\
dosmem.c
\
dosvm.c
\
error.c
\
...
...
dlls/krnl386.exe16/dosaspi.c
deleted
100644 → 0
View file @
4a589081
/*
* Copyright 2000 David Elliott
*
* 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 <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wine/windef16.h"
#include "wine/winaspi.h"
#include "wine/debug.h"
#include "dosexe.h"
#include "winerror.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
aspi
);
static
HINSTANCE
hWNASPI32
=
INVALID_HANDLE_VALUE
;
static
DWORD
(
__cdecl
*
pSendASPI32Command
)
(
LPSRB
)
=
NULL
;
static
void
DOSASPI_PostProc
(
SRB_ExecSCSICmd
*
lpPRB
)
{
DWORD
ptrSRB
;
LPSRB16
lpSRB16
;
memcpy
(
&
ptrSRB
,
lpPRB
->
SenseArea
+
lpPRB
->
SRB_SenseLen
,
sizeof
(
DWORD
));
TRACE
(
"Copying data back to DOS client at 0x%8x
\n
"
,
ptrSRB
);
lpSRB16
=
PTR_REAL_TO_LIN
(
SELECTOROF
(
ptrSRB
),
OFFSETOF
(
ptrSRB
));
lpSRB16
->
cmd
.
SRB_TargStat
=
lpPRB
->
SRB_TargStat
;
lpSRB16
->
cmd
.
SRB_HaStat
=
lpPRB
->
SRB_HaStat
;
memcpy
(
lpSRB16
->
cmd
.
CDBByte
+
lpSRB16
->
cmd
.
SRB_CDBLen
,
lpPRB
->
SenseArea
,
lpSRB16
->
cmd
.
SRB_SenseLen
);
/* Now do posting */
if
(
lpPRB
->
SRB_Status
==
SS_SECURITY_VIOLATION
)
{
/* SS_SECURITY_VIOLATION isn't defined in DOS ASPI */
TRACE
(
"Returning SS_NO_DEVICE for SS_SECURITY_VIOLATION
\n
"
);
lpPRB
->
SRB_Status
=
SS_NO_DEVICE
;
}
lpSRB16
->
cmd
.
SRB_Status
=
lpPRB
->
SRB_Status
;
TRACE
(
"SRB_Status = 0x%x
\n
"
,
lpPRB
->
SRB_Status
);
HeapFree
(
GetProcessHeap
(),
0
,
lpPRB
);
if
(
(
lpSRB16
->
cmd
.
SRB_Flags
&
SRB_POSTING
)
&&
lpSRB16
->
cmd
.
SRB_PostProc
)
{
CONTEXT
ctx
;
/* The stack should look like this on entry to proc
* NOTE: the SDK draws the following diagram bass awkwardly, use this one
* to avoid being confused. Remember, the act of pushing something on
* an intel stack involves decreasing the stack pointer by the size of
* the data, and then copying the data at the new SP.
*/
/***************************
* ... Other crap that is already on the stack ...
* Segment of SRB Pointer <- SP+6
* Offset of SRB Pointer <- SP+4
* Segment of return address <- SP+2
* Offset of return address <- SP+0
*/
/* FIXME: I am about 99% sure what is here is correct,
* but this code has never been tested (and probably
* won't be either until someone finds a DOS program
* that actually uses a Post Routine) */
/* Zero everything */
memset
(
&
ctx
,
0
,
sizeof
(
ctx
));
ctx
.
EFlags
|=
V86_FLAG
;
/* CS:IP is routine to call */
ctx
.
SegCs
=
SELECTOROF
(
lpSRB16
->
cmd
.
SRB_PostProc
);
ctx
.
Eip
=
OFFSETOF
(
lpSRB16
->
cmd
.
SRB_PostProc
);
/* DPMI_CallRMProc will push the pointer to the stack
* it is given (in this case &ptrSRB) with length
* 2*sizeof(WORD), that is, it copies the contents
* of ptrSRB onto the stack, and decs sp by 2*sizeof(WORD).
* After doing that, it pushes the return address
* onto the stack (so we don't need to worry about that)
* So the stack should be okay for the PostProc
*/
if
(
DPMI_CallRMProc
(
&
ctx
,
(
LPWORD
)
&
ptrSRB
,
2
,
FALSE
))
{
TRACE
(
"DPMI_CallRMProc returned nonzero (error) status
\n
"
);
}
}
/* if ((SRB_Flags&SRB_POSTING) && SRB_PostProc) */
}
static
DWORD
ASPI_SendASPIDOSCommand
(
DWORD
ptrSRB
)
{
PSRB_ExecSCSICmd
lpPRB
;
DWORD
retval
;
union
tagSRB16
*
lpSRB16
;
lpSRB16
=
PTR_REAL_TO_LIN
(
SELECTOROF
(
ptrSRB
),
OFFSETOF
(
ptrSRB
));
retval
=
SS_ERR
;
switch
(
lpSRB16
->
common
.
SRB_Cmd
)
{
case
SC_HA_INQUIRY
:
TRACE
(
"SC_HA_INQUIRY
\n
"
);
/* Format is identical in this case */
retval
=
(
*
pSendASPI32Command
)((
LPSRB
)
lpSRB16
);
break
;
case
SC_GET_DEV_TYPE
:
TRACE
(
"SC_GET_DEV_TYPE
\n
"
);
/* Format is identical in this case */
retval
=
(
*
pSendASPI32Command
)((
LPSRB
)
lpSRB16
);
break
;
case
SC_EXEC_SCSI_CMD
:
TRACE
(
"SC_EXEC_SCSI_CMD
\n
"
);
TRACE
(
"Copying data from DOS client at 0x%8x
\n
"
,
ptrSRB
);
lpPRB
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
SRB
)
+
lpSRB16
->
cmd
.
SRB_SenseLen
+
sizeof
(
DWORD
));
#define srb_dos_to_w32(name) \
lpPRB->SRB_##name = lpSRB16->cmd.SRB_##name
srb_dos_to_w32
(
Cmd
);
srb_dos_to_w32
(
Status
);
srb_dos_to_w32
(
HaId
);
srb_dos_to_w32
(
BufLen
);
srb_dos_to_w32
(
SenseLen
);
srb_dos_to_w32
(
CDBLen
);
srb_dos_to_w32
(
Target
);
srb_dos_to_w32
(
Lun
);
#undef srb_dos_to_w32
/* Allow certain flags to go on to WNASPI32, we also need
* to make sure SRB_POSTING is enabled */
lpPRB
->
SRB_Flags
=
SRB_POSTING
|
(
lpSRB16
->
cmd
.
SRB_Flags
&
(
SRB_DIR_IN
|
SRB_DIR_OUT
|
SRB_ENABLE_RESIDUAL_COUNT
));
/* Pointer to data buffer */
lpPRB
->
SRB_BufPointer
=
PTR_REAL_TO_LIN
(
SELECTOROF
(
lpSRB16
->
cmd
.
SRB_BufPointer
),
OFFSETOF
(
lpSRB16
->
cmd
.
SRB_BufPointer
));
/* Copy CDB in */
memcpy
(
&
lpPRB
->
CDBByte
[
0
],
&
lpSRB16
->
cmd
.
CDBByte
[
0
],
lpSRB16
->
cmd
.
SRB_CDBLen
);
/* Set post proc to our post proc */
lpPRB
->
SRB_PostProc
=
DOSASPI_PostProc
;
/* Stick the DWORD after all the sense info */
memcpy
(
lpPRB
->
SenseArea
+
lpPRB
->
SRB_SenseLen
,
&
ptrSRB
,
sizeof
(
DWORD
));
retval
=
(
*
pSendASPI32Command
)((
LPSRB
)
lpPRB
);
break
;
case
SC_ABORT_SRB
:
TRACE
(
"SC_ABORT_SRB
\n
"
);
/* Would need some sort of table of active shit */
break
;
case
SC_RESET_DEV
:
TRACE
(
"SC_RESET_DEV
\n
"
);
break
;
default:
TRACE
(
"Unknown command code
\n
"
);
break
;
}
TRACE
(
"Returning %x
\n
"
,
retval
);
return
retval
;
}
static
void
WINAPI
ASPI_DOS_func
(
CONTEXT
*
context
)
{
WORD
*
stack
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegSs
,
context
->
Esp
);
DWORD
ptrSRB
=
*
(
DWORD
*
)
&
stack
[
2
];
ASPI_SendASPIDOSCommand
(
ptrSRB
);
/* simulate a normal RETF sequence as required by DPMI CallRMProcFar */
context
->
Eip
=
*
(
stack
++
);
context
->
SegCs
=
*
(
stack
++
);
context
->
Esp
+=
2
*
sizeof
(
WORD
);
}
/**********************************************************************
* ASPIHandler
*
* returns the address of a real mode callback to ASPI_DOS_func()
*/
void
DOSVM_ASPIHandler
(
CONTEXT
*
context
)
{
FARPROC16
*
p
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegDs
,
context
->
Edx
);
TRACE
(
"DOS ASPI opening
\n
"
);
if
((
CX_reg
(
context
)
==
4
)
||
(
CX_reg
(
context
)
==
5
))
{
if
(
hWNASPI32
==
INVALID_HANDLE_VALUE
)
{
TRACE
(
"Loading WNASPI32
\n
"
);
hWNASPI32
=
LoadLibraryExA
(
"WNASPI32"
,
0
,
0
);
}
if
(
hWNASPI32
==
INVALID_HANDLE_VALUE
)
{
ERR
(
"Error loading WNASPI32
\n
"
);
goto
error_exit
;
}
/* Get SendASPI32Command by Ordinal 2 */
/* Cast to correct argument/return types */
pSendASPI32Command
=
(
DWORD
(
*
)(
LPSRB
))
GetProcAddress
(
hWNASPI32
,
(
LPCSTR
)
2
);
if
(
!
pSendASPI32Command
)
{
ERR
(
"Error getting ordinal 2 from WNASPI32
\n
"
);
goto
error_exit
;
}
*
p
=
DPMI_AllocInternalRMCB
(
ASPI_DOS_func
);
TRACE
(
"allocated real mode proc %p
\n
"
,
*
p
);
SET_AX
(
context
,
CX_reg
(
context
)
);
return
;
}
error_exit:
/* Return some error... General Failure sounds okay */
SET_AX
(
context
,
ERROR_GEN_FAILURE
);
SET_CFLAG
(
context
);
}
dlls/krnl386.exe16/dosexe.h
View file @
ed6bdb3c
...
...
@@ -38,22 +38,11 @@
/* various real-mode code stubs */
struct
DPMI_segments
{
WORD
wrap_seg
;
WORD
xms_seg
;
WORD
dpmi_seg
;
WORD
dpmi_sel
;
WORD
int48_sel
;
WORD
int16_sel
;
WORD
relay_code_sel
;
WORD
relay_data_sel
;
};
/* 48-bit segmented pointers for DOS DPMI32 */
typedef
struct
{
WORD
selector
;
DWORD
offset
;
}
SEGPTR48
,
FARPROC48
;
typedef
void
(
*
DOSRELAY
)(
CONTEXT
*
,
void
*
);
typedef
void
(
WINAPI
*
RMCBPROC
)(
CONTEXT
*
);
typedef
void
(
WINAPI
*
INTPROC
)(
CONTEXT
*
);
...
...
@@ -239,9 +228,6 @@ extern int DMA_Transfer(int channel,int reqlength,void* buffer) DECLSPEC_HIDDEN;
extern
void
DMA_ioport_out
(
WORD
port
,
BYTE
val
)
DECLSPEC_HIDDEN
;
extern
BYTE
DMA_ioport_in
(
WORD
port
)
DECLSPEC_HIDDEN
;
/* dosaspi.c */
extern
void
DOSVM_ASPIHandler
(
CONTEXT
*
)
DECLSPEC_HIDDEN
;
/* dosmem.c */
extern
BIOSDATA
*
DOSVM_BiosData
(
void
)
DECLSPEC_HIDDEN
;
extern
void
DOSVM_start_bios_timer
(
void
)
DECLSPEC_HIDDEN
;
...
...
@@ -281,11 +267,6 @@ extern void WINAPI DOSVM_Int2fHandler(CONTEXT*) DECLSPEC_HIDDEN;
/* int31.c */
extern
void
WINAPI
DOSVM_Int31Handler
(
CONTEXT
*
)
DECLSPEC_HIDDEN
;
extern
void
WINAPI
DOSVM_RawModeSwitchHandler
(
CONTEXT
*
)
DECLSPEC_HIDDEN
;
extern
BOOL
DOSVM_IsDos32
(
void
)
DECLSPEC_HIDDEN
;
extern
FARPROC16
DPMI_AllocInternalRMCB
(
RMCBPROC
)
DECLSPEC_HIDDEN
;
extern
int
DPMI_CallRMProc
(
CONTEXT
*
,
LPWORD
,
int
,
int
)
DECLSPEC_HIDDEN
;
extern
BOOL
DOSVM_CheckWrappers
(
CONTEXT
*
)
DECLSPEC_HIDDEN
;
/* int67.c */
extern
void
WINAPI
DOSVM_Int67Handler
(
CONTEXT
*
)
DECLSPEC_HIDDEN
;
...
...
@@ -296,12 +277,8 @@ extern void __wine_call_int_handler( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
extern
void
DOSVM_CallBuiltinHandler
(
CONTEXT
*
,
BYTE
)
DECLSPEC_HIDDEN
;
extern
BOOL
DOSVM_EmulateInterruptPM
(
CONTEXT
*
,
BYTE
)
DECLSPEC_HIDDEN
;
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_SetPMHandler16
(
BYTE
,
FARPROC16
)
DECLSPEC_HIDDEN
;
extern
void
DOSVM_SetPMHandler48
(
BYTE
,
FARPROC48
)
DECLSPEC_HIDDEN
;
extern
void
DOSVM_SetRMHandler
(
BYTE
,
FARPROC16
)
DECLSPEC_HIDDEN
;
/* ioports.c */
extern
DWORD
DOSVM_inport
(
int
port
,
int
size
)
DECLSPEC_HIDDEN
;
...
...
dlls/krnl386.exe16/dosvm.c
View file @
ed6bdb3c
...
...
@@ -160,16 +160,10 @@ static WORD alloc_selector( void *base, DWORD size, unsigned char flags )
*
* FIXME: should allocate a single PM selector for the whole UMB range.
*/
static
LPVOID
DOSVM_AllocCodeUMB
(
DWORD
size
,
WORD
*
se
gment
,
WORD
*
se
lector
)
static
LPVOID
DOSVM_AllocCodeUMB
(
DWORD
size
,
WORD
*
selector
)
{
LPVOID
ptr
=
DOSVM_AllocUMB
(
size
);
if
(
segment
)
*
segment
=
(
DWORD
)
ptr
>>
4
;
if
(
selector
)
*
selector
=
alloc_selector
(
ptr
,
size
,
WINE_LDT_FLAGS_CODE
);
return
ptr
;
}
...
...
@@ -207,50 +201,6 @@ void DOSVM_InitSegments(void)
LPSTR
ptr
;
int
i
;
static
const
char
wrap_code
[]
=
{
0xCD
,
0x31
,
/* int $0x31 */
0xCB
/* lret */
};
static
const
char
enter_xms
[]
=
{
/* XMS hookable entry point */
0xEB
,
0x03
,
/* jmp entry */
0x90
,
0x90
,
0x90
,
/* nop;nop;nop */
/* entry: */
/* real entry point */
/* for simplicity, we'll just use the same hook as DPMI below */
0xCD
,
0x31
,
/* int $0x31 */
0xCB
/* lret */
};
static
const
char
enter_pm
[]
=
{
0x50
,
/* pushw %ax */
0x52
,
/* pushw %dx */
0x55
,
/* pushw %bp */
0x89
,
0xE5
,
/* movw %sp,%bp */
/* get return CS */
0x8B
,
0x56
,
0x08
,
/* movw 8(%bp),%dx */
/* just call int 31 here to get into protected mode... */
/* it'll check whether it was called from dpmi_seg... */
0xCD
,
0x31
,
/* int $0x31 */
/* we are now in the context of a 16-bit relay call */
/* need to fixup our stack;
* 16-bit relay return address will be lost,
* but we won't worry quite yet
*/
0x8E
,
0xD0
,
/* movw %ax,%ss */
0x66
,
0x0F
,
0xB7
,
0xE5
,
/* movzwl %bp,%esp */
/* set return CS */
0x89
,
0x56
,
0x08
,
/* movw %dx,8(%bp) */
0x5D
,
/* popw %bp */
0x5A
,
/* popw %dx */
0x58
,
/* popw %ax */
0xfb
,
/* sti, enable and check virtual interrupts */
0xCB
/* lret */
};
static
const
char
relay
[]
=
{
0xca
,
0x04
,
0x00
,
/* 16-bit far return and pop 4 bytes (relay void* arg) */
...
...
@@ -264,53 +214,9 @@ void DOSVM_InitSegments(void)
DOSVM_dpmi_segments
=
DOSVM_AllocUMB
(
sizeof
(
struct
DPMI_segments
)
);
/*
* RM / offset 0: Exit from real mode.
* RM / offset 2: Points to lret opcode.
*/
ptr
=
DOSVM_AllocCodeUMB
(
sizeof
(
wrap_code
),
&
DOSVM_dpmi_segments
->
wrap_seg
,
0
);
memcpy
(
ptr
,
wrap_code
,
sizeof
(
wrap_code
)
);
/*
* RM / offset 0: XMS driver entry.
*/
ptr
=
DOSVM_AllocCodeUMB
(
sizeof
(
enter_xms
),
&
DOSVM_dpmi_segments
->
xms_seg
,
0
);
memcpy
(
ptr
,
enter_xms
,
sizeof
(
enter_xms
)
);
/*
* RM / offset 0: Switch to DPMI.
* PM / offset 8: DPMI raw mode switch.
*/
ptr
=
DOSVM_AllocCodeUMB
(
sizeof
(
enter_pm
),
&
DOSVM_dpmi_segments
->
dpmi_seg
,
&
DOSVM_dpmi_segments
->
dpmi_sel
);
memcpy
(
ptr
,
enter_pm
,
sizeof
(
enter_pm
)
);
/*
* PM / offset N*6: Interrupt N in DPMI32.
*/
ptr
=
DOSVM_AllocCodeUMB
(
6
*
256
,
0
,
&
DOSVM_dpmi_segments
->
int48_sel
);
for
(
i
=
0
;
i
<
256
;
i
++
)
{
/*
* Each 32-bit interrupt handler is 6 bytes:
* 0xCD,<i> = int <i> (nested 16-bit interrupt)
* 0x66,0xCA,0x04,0x00 = ret 4 (32-bit far return and pop 4 bytes / eflags)
*/
ptr
[
i
*
6
+
0
]
=
0xCD
;
ptr
[
i
*
6
+
1
]
=
i
;
ptr
[
i
*
6
+
2
]
=
0x66
;
ptr
[
i
*
6
+
3
]
=
0xCA
;
ptr
[
i
*
6
+
4
]
=
0x04
;
ptr
[
i
*
6
+
5
]
=
0x00
;
}
/*
* PM / offset N*5: Interrupt N in 16-bit protected mode.
*/
ptr
=
DOSVM_AllocCodeUMB
(
5
*
256
,
0
,
&
DOSVM_dpmi_segments
->
int16_sel
);
ptr
=
DOSVM_AllocCodeUMB
(
5
*
256
,
&
DOSVM_dpmi_segments
->
int16_sel
);
for
(
i
=
0
;
i
<
256
;
i
++
)
{
/*
* Each 16-bit interrupt handler is 5 bytes:
...
...
@@ -329,8 +235,7 @@ void DOSVM_InitSegments(void)
* PM / offset 3: Stub which swaps back to 32-bit application code/stack.
* PM / offset 5: Stub which enables interrupts
*/
ptr
=
DOSVM_AllocCodeUMB
(
sizeof
(
relay
),
0
,
&
DOSVM_dpmi_segments
->
relay_code_sel
);
ptr
=
DOSVM_AllocCodeUMB
(
sizeof
(
relay
),
&
DOSVM_dpmi_segments
->
relay_code_sel
);
memcpy
(
ptr
,
relay
,
sizeof
(
relay
)
);
/*
...
...
dlls/krnl386.exe16/instr.c
View file @
ed6bdb3c
...
...
@@ -865,12 +865,10 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
return
ExceptionContinueExecution
;
case
0xfa
:
/* cli */
get_vm86_teb_info
()
->
dpmi_vif
=
0
;
context
->
Eip
+=
prefixlen
+
1
;
return
ExceptionContinueExecution
;
case
0xfb
:
/* sti */
get_vm86_teb_info
()
->
dpmi_vif
=
1
;
context
->
Eip
+=
prefixlen
+
1
;
return
ExceptionContinueExecution
;
}
...
...
dlls/krnl386.exe16/int21.c
View file @
ed6bdb3c
...
...
@@ -2582,15 +2582,12 @@ static void INT21_IoctlScsiMgrHandler( CONTEXT *context )
SET_DX
(
context
,
0xc0c0
);
break
;
case
0x02
:
/* READ FROM CHARACTER DEVICE CONTROL CHANNEL */
DOSVM_ASPIHandler
(
context
);
break
;
case
0x0a
:
/* CHECK IF HANDLE IS REMOTE */
SET_DX
(
context
,
0
);
break
;
case
0x01
:
/* SET DEVICE INFORMATION */
case
0x02
:
/* READ FROM CHARACTER DEVICE CONTROL CHANNEL */
case
0x03
:
/* WRITE TO CHARACTER DEVICE CONTROL CHANNEL */
case
0x06
:
/* GET INPUT STATUS */
case
0x07
:
/* GET OUTPUT STATUS */
...
...
@@ -4291,10 +4288,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
TRACE
(
"SET INTERRUPT VECTOR 0x%02x
\n
"
,
AL_reg
(
context
));
{
FARPROC16
ptr
=
(
FARPROC16
)
MAKESEGPTR
(
context
->
SegDs
,
DX_reg
(
context
)
);
if
(
!
ISV86
(
context
))
DOSVM_SetPMHandler16
(
AL_reg
(
context
),
ptr
);
else
DOSVM_SetRMHandler
(
AL_reg
(
context
),
ptr
);
}
break
;
...
...
@@ -4487,11 +4481,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
case
0x35
:
/* GET INTERRUPT VECTOR */
TRACE
(
"GET INTERRUPT VECTOR 0x%02x
\n
"
,
AL_reg
(
context
));
{
FARPROC16
addr
;
if
(
!
ISV86
(
context
))
addr
=
DOSVM_GetPMHandler16
(
AL_reg
(
context
)
);
else
addr
=
DOSVM_GetRMHandler
(
AL_reg
(
context
)
);
FARPROC16
addr
=
DOSVM_GetPMHandler16
(
AL_reg
(
context
)
);
context
->
SegEs
=
SELECTOROF
(
addr
);
SET_BX
(
context
,
OFFSETOF
(
addr
)
);
}
...
...
dlls/krnl386.exe16/int2f.c
View file @
ed6bdb3c
...
...
@@ -139,26 +139,8 @@ void WINAPI DOSVM_Int2fHandler( CONTEXT *context )
break
;
case
0x43
:
#if 1
switch
(
LOBYTE
(
context
->
Eax
))
{
case
0x00
:
/* XMS v2+ installation check */
WARN
(
"XMS is not fully implemented
\n
"
);
SET_AL
(
context
,
0x80
);
break
;
case
0x10
:
/* XMS v2+ get driver address */
{
context
->
SegEs
=
DOSVM_dpmi_segments
->
xms_seg
;
SET_BX
(
context
,
0
);
break
;
}
default:
INT_BARF
(
context
,
0x2f
);
}
#else
FIXME
(
"check for XMS (not supported)
\n
"
);
SET_AL
(
context
,
0x42
);
/* != 0x80 */
#endif
break
;
case
0x45
:
...
...
@@ -399,7 +381,7 @@ static void do_int2f_16( CONTEXT *context )
SET_CL
(
context
,
si
.
wProcessorLevel
);
SET_DX
(
context
,
0x005a
);
/* DPMI major/minor 0.90 */
SET_SI
(
context
,
0
);
/* # of para. of DOS extended private data */
context
->
SegEs
=
DOSVM_dpmi_segments
->
dpmi_seg
;
context
->
SegEs
=
0
;
/* no DPMI switch */
SET_DI
(
context
,
0
);
/* ES:DI is DPMI switch entry point */
break
;
}
...
...
dlls/krnl386.exe16/int31.c
View file @
ed6bdb3c
...
...
@@ -37,133 +37,7 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
int31
);
/* Structure for real-mode callbacks */
typedef
struct
{
DWORD
edi
;
DWORD
esi
;
DWORD
ebp
;
DWORD
reserved
;
DWORD
ebx
;
DWORD
edx
;
DWORD
ecx
;
DWORD
eax
;
WORD
fl
;
WORD
es
;
WORD
ds
;
WORD
fs
;
WORD
gs
;
WORD
ip
;
WORD
cs
;
WORD
sp
;
WORD
ss
;
}
REALMODECALL
;
typedef
struct
tagRMCB
{
DWORD
address
;
DWORD
proc_ofs
,
proc_sel
;
DWORD
regs_ofs
,
regs_sel
;
struct
tagRMCB
*
next
;
}
RMCB
;
static
RMCB
*
FirstRMCB
=
NULL
;
static
WORD
dpmi_flag
;
static
void
*
lastvalloced
=
NULL
;
static
BYTE
DPMI_retval
;
#include "pshpack1.h"
typedef
struct
{
WORD
Handle
;
DWORD
Offset
;
}
MOVEOFS
;
typedef
struct
{
DWORD
Length
;
MOVEOFS
Source
;
MOVEOFS
Dest
;
}
MOVESTRUCT
;
#include "poppack.h"
/**********************************************************************
* DOSVM_IsDos32
*
* Return TRUE if we are in 32-bit protected mode DOS process.
*/
BOOL
DOSVM_IsDos32
(
void
)
{
return
(
dpmi_flag
&
1
)
!=
0
;
}
/**********************************************************************
* alloc_pm_selector
*
* Allocate a 64k sized selector corresponding to a real mode segment.
*/
static
WORD
alloc_pm_selector
(
WORD
seg
,
unsigned
char
flags
)
{
WORD
sel
=
wine_ldt_alloc_entries
(
1
);
if
(
sel
)
{
LDT_ENTRY
entry
;
wine_ldt_set_base
(
&
entry
,
(
void
*
)(
seg
<<
4
)
);
wine_ldt_set_limit
(
&
entry
,
0xffff
);
wine_ldt_set_flags
(
&
entry
,
flags
);
wine_ldt_set_entry
(
sel
,
&
entry
);
}
return
sel
;
}
/**********************************************************************
* INT_GetRealModeContext
*/
static
void
INT_GetRealModeContext
(
REALMODECALL
*
call
,
CONTEXT
*
context
)
{
context
->
Eax
=
call
->
eax
;
context
->
Ebx
=
call
->
ebx
;
context
->
Ecx
=
call
->
ecx
;
context
->
Edx
=
call
->
edx
;
context
->
Esi
=
call
->
esi
;
context
->
Edi
=
call
->
edi
;
context
->
Ebp
=
call
->
ebp
;
context
->
EFlags
=
call
->
fl
|
V86_FLAG
;
context
->
Eip
=
call
->
ip
;
context
->
Esp
=
call
->
sp
;
context
->
SegCs
=
call
->
cs
;
context
->
SegDs
=
call
->
ds
;
context
->
SegEs
=
call
->
es
;
context
->
SegFs
=
call
->
fs
;
context
->
SegGs
=
call
->
gs
;
context
->
SegSs
=
call
->
ss
;
}
/**********************************************************************
* INT_SetRealModeContext
*/
static
void
INT_SetRealModeContext
(
REALMODECALL
*
call
,
CONTEXT
*
context
)
{
call
->
eax
=
context
->
Eax
;
call
->
ebx
=
context
->
Ebx
;
call
->
ecx
=
context
->
Ecx
;
call
->
edx
=
context
->
Edx
;
call
->
esi
=
context
->
Esi
;
call
->
edi
=
context
->
Edi
;
call
->
ebp
=
context
->
Ebp
;
call
->
fl
=
LOWORD
(
context
->
EFlags
);
call
->
ip
=
LOWORD
(
context
->
Eip
);
call
->
sp
=
LOWORD
(
context
->
Esp
);
call
->
cs
=
context
->
SegCs
;
call
->
ds
=
context
->
SegDs
;
call
->
es
=
context
->
SegEs
;
call
->
fs
=
context
->
SegFs
;
call
->
gs
=
context
->
SegGs
;
call
->
ss
=
context
->
SegSs
;
}
/**********************************************************************
* DPMI_xalloc
...
...
@@ -273,588 +147,6 @@ static LPVOID DPMI_xrealloc( LPVOID ptr, DWORD newsize )
}
void
DPMI_CallRMCB32
(
RMCB
*
rmcb
,
UINT16
ss
,
DWORD
esp
,
UINT16
*
es
,
DWORD
*
edi
)
#if 0 /* original code, which early gccs puke on */
{
int _clobber;
__asm__ __volatile__(
"pushl %%ebp\n"
"pushl %%ebx\n"
"pushl %%es\n"
"pushl %%ds\n"
"pushfl\n"
"mov %7,%%es\n"
"mov %5,%%ds\n"
".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */
"popl %%ds\n"
"mov %%es,%0\n"
"popl %%es\n"
"popl %%ebx\n"
"popl %%ebp\n"
: "=d" (*es), "=D" (*edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber)
: "0" (ss), "2" (esp),
"4" (rmcb->regs_sel), "1" (rmcb->regs_ofs),
"3" (&rmcb->proc_ofs) );
}
#else
/* code generated by a gcc new enough */
;
__ASM_GLOBAL_FUNC
(
DPMI_CallRMCB32
,
"pushl %ebp
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
__ASM_CFI
(
".cfi_rel_offset %ebp,0
\n\t
"
)
"movl %esp,%ebp
\n\t
"
__ASM_CFI
(
".cfi_def_cfa_register %ebp
\n\t
"
)
"pushl %edi
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %edi,-4
\n\t
"
)
"pushl %esi
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %esi,-8
\n\t
"
)
"movl 0x8(%ebp),%eax
\n\t
"
"movl 0x10(%ebp),%esi
\n\t
"
"movl 0xc(%ebp),%edx
\n\t
"
"movl 0x10(%eax),%ecx
\n\t
"
"movl 0xc(%eax),%edi
\n\t
"
"addl $0x4,%eax
\n\t
"
"pushl %ebp
\n\t
"
"pushl %ebx
\n\t
"
"pushl %es
\n\t
"
"pushl %ds
\n\t
"
"pushfl
\n\t
"
"mov %cx,%es
\n\t
"
"mov %dx,%ds
\n\t
"
".byte 0x36, 0xff, 0x18
\n\t
"
/* lcall *%ss:(%eax) */
"popl %ds
\n\t
"
"mov %es,%dx
\n\t
"
"popl %es
\n\t
"
"popl %ebx
\n\t
"
"popl %ebp
\n\t
"
"movl 0x14(%ebp),%eax
\n\t
"
"movw %dx,(%eax)
\n\t
"
"movl 0x18(%ebp),%edx
\n\t
"
"movl %edi,(%edx)
\n\t
"
"popl %esi
\n\t
"
__ASM_CFI
(
".cfi_same_value %esi
\n\t
"
)
"popl %edi
\n\t
"
__ASM_CFI
(
".cfi_same_value %edi
\n\t
"
)
"leave
\n\t
"
__ASM_CFI
(
".cfi_def_cfa %esp,4
\n\t
"
)
__ASM_CFI
(
".cfi_same_value %ebp
\n\t
"
)
"ret"
)
#endif
/**********************************************************************
* DPMI_CallRMCBProc
*
* This routine does the hard work of calling a callback procedure.
*/
static
void
DPMI_CallRMCBProc
(
CONTEXT
*
context
,
RMCB
*
rmcb
,
WORD
flag
)
{
DWORD
old_vif
=
get_vm86_teb_info
()
->
dpmi_vif
;
/* Disable virtual interrupts. */
get_vm86_teb_info
()
->
dpmi_vif
=
0
;
if
(
wine_ldt_is_system
(
rmcb
->
proc_sel
))
{
/* Wine-internal RMCB, call directly */
((
RMCBPROC
)
rmcb
->
proc_ofs
)(
context
);
}
else
{
UINT16
ss
,
es
;
DWORD
esp
,
edi
;
INT_SetRealModeContext
(
MapSL
(
MAKESEGPTR
(
rmcb
->
regs_sel
,
rmcb
->
regs_ofs
)),
context
);
ss
=
alloc_pm_selector
(
context
->
SegSs
,
WINE_LDT_FLAGS_DATA
);
esp
=
context
->
Esp
;
FIXME
(
"untested!
\n
"
);
/* The called proc ends with an IRET, and takes these parameters:
* DS:ESI = pointer to real-mode SS:SP
* ES:EDI = pointer to real-mode call structure
* It returns:
* ES:EDI = pointer to real-mode call structure (may be a copy)
* It is the proc's responsibility to change the return CS:IP in the
* real-mode call structure. */
if
(
flag
&
1
)
{
/* 32-bit DPMI client */
DPMI_CallRMCB32
(
rmcb
,
ss
,
esp
,
&
es
,
&
edi
);
}
else
{
/* 16-bit DPMI client */
CONTEXT
ctx
=
*
context
;
ctx
.
SegCs
=
rmcb
->
proc_sel
;
ctx
.
Eip
=
rmcb
->
proc_ofs
;
ctx
.
SegDs
=
ss
;
ctx
.
Esi
=
esp
;
ctx
.
SegEs
=
rmcb
->
regs_sel
;
ctx
.
Edi
=
rmcb
->
regs_ofs
;
/* FIXME: I'm pretty sure this isn't right - should push flags first */
WOWCallback16Ex
(
0
,
WCB16_REGS
,
0
,
NULL
,
(
DWORD
*
)
&
ctx
);
es
=
ctx
.
SegEs
;
edi
=
ctx
.
Edi
;
}
wine_ldt_free_entries
(
ss
,
1
);
INT_GetRealModeContext
(
MapSL
(
MAKESEGPTR
(
es
,
edi
)),
context
);
}
/* Restore virtual interrupt flag. */
get_vm86_teb_info
()
->
dpmi_vif
=
old_vif
;
}
/**********************************************************************
* DPMI_CallRMProc
*
* This routine does the hard work of calling a real mode procedure.
*/
int
DPMI_CallRMProc
(
CONTEXT
*
context
,
LPWORD
stack
,
int
args
,
int
iret
)
{
LPWORD
stack16
;
LPVOID
addr
=
NULL
;
/* avoid gcc warning */
RMCB
*
CurrRMCB
;
BOOL
alloc
=
FALSE
,
already
=
FALSE
;
BYTE
*
code
;
TRACE
(
"EAX=%08x EBX=%08x ECX=%08x EDX=%08x
\n
"
,
context
->
Eax
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
);
TRACE
(
"ESI=%08x EDI=%08x ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s
\n
"
,
context
->
Esi
,
context
->
Edi
,
context
->
SegEs
,
context
->
SegDs
,
context
->
SegCs
,
LOWORD
(
context
->
Eip
),
args
,
iret
?
"IRET"
:
"FAR"
);
callrmproc_again
:
/* there might be some code that just jumps to RMCBs or the like,
in which case following the jumps here might get us to a shortcut */
code
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegCs
,
context
->
Eip
);
switch
(
*
code
)
{
case
0xe9
:
/* JMP NEAR */
context
->
Eip
+=
3
+
*
(
WORD
*
)(
code
+
1
);
/* yeah, I know these gotos don't look good... */
goto
callrmproc_again
;
case
0xea
:
/* JMP FAR */
context
->
Eip
=
*
(
WORD
*
)(
code
+
1
);
context
->
SegCs
=
*
(
WORD
*
)(
code
+
3
);
/* ...but since the label is there anyway... */
goto
callrmproc_again
;
case
0xeb
:
/* JMP SHORT */
context
->
Eip
+=
2
+
*
(
signed
char
*
)(
code
+
1
);
/* ...because of other gotos below, so... */
goto
callrmproc_again
;
}
/* shortcut for chaining to internal interrupt handlers */
if
((
context
->
SegCs
==
0xF000
)
&&
iret
)
{
DOSVM_CallBuiltinHandler
(
context
,
LOWORD
(
context
->
Eip
)
/
4
);
return
0
;
}
/* shortcut for RMCBs */
CurrRMCB
=
FirstRMCB
;
while
(
CurrRMCB
&&
(
HIWORD
(
CurrRMCB
->
address
)
!=
context
->
SegCs
))
CurrRMCB
=
CurrRMCB
->
next
;
if
(
!
CurrRMCB
)
{
FIXME
(
"DPMI real-mode call using DOS VM task system, not fully tested!
\n
"
);
return
0
;
}
if
(
!
already
)
{
if
(
!
context
->
SegSs
)
{
alloc
=
TRUE
;
/* allocate default stack */
stack16
=
addr
=
DOSMEM_AllocBlock
(
64
,
(
UINT16
*
)
&
(
context
->
SegSs
)
);
context
->
Esp
=
64
-
2
;
stack16
+=
32
-
1
;
if
(
!
addr
)
{
ERR
(
"could not allocate default stack
\n
"
);
return
1
;
}
}
else
{
stack16
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegSs
,
context
->
Esp
);
}
context
->
Esp
-=
(
args
+
(
iret
?
1
:
0
))
*
sizeof
(
WORD
);
stack16
-=
args
;
if
(
args
)
memcpy
(
stack16
,
stack
,
args
*
sizeof
(
WORD
)
);
/* push flags if iret */
if
(
iret
)
{
stack16
--
;
args
++
;
*
stack16
=
LOWORD
(
context
->
EFlags
);
}
/* push return address (return to interrupt wrapper) */
*
(
--
stack16
)
=
DOSVM_dpmi_segments
->
wrap_seg
;
*
(
--
stack16
)
=
0
;
/* adjust stack */
context
->
Esp
-=
2
*
sizeof
(
WORD
);
already
=
TRUE
;
}
/* 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
;
}
/**********************************************************************
* CallRMInt
*/
static
void
DOSVM_CallRMInt
(
CONTEXT
*
context
)
{
CONTEXT
realmode_ctx
;
FARPROC16
rm_int
=
DOSVM_GetRMHandler
(
BL_reg
(
context
)
);
REALMODECALL
*
call
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegEs
,
context
->
Edi
);
INT_GetRealModeContext
(
call
,
&
realmode_ctx
);
/* we need to check if a real-mode program has hooked the interrupt */
if
(
HIWORD
(
rm_int
)
!=
0xF000
)
{
/* yup, which means we need to switch to real mode... */
realmode_ctx
.
SegCs
=
HIWORD
(
rm_int
);
realmode_ctx
.
Eip
=
LOWORD
(
rm_int
);
if
(
DPMI_CallRMProc
(
&
realmode_ctx
,
NULL
,
0
,
TRUE
))
SET_CFLAG
(
context
);
}
else
{
RESET_CFLAG
(
context
);
/* use the IP we have instead of BL_reg, in case some apps
decide to move interrupts around for whatever reason... */
DOSVM_CallBuiltinHandler
(
&
realmode_ctx
,
LOWORD
(
rm_int
)
/
4
);
}
INT_SetRealModeContext
(
call
,
&
realmode_ctx
);
}
/**********************************************************************
* CallRMProc
*/
static
void
DOSVM_CallRMProc
(
CONTEXT
*
context
,
int
iret
)
{
REALMODECALL
*
p
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegEs
,
context
->
Edi
);
CONTEXT
context16
;
TRACE
(
"RealModeCall: EAX=%08x EBX=%08x ECX=%08x EDX=%08x
\n
"
,
p
->
eax
,
p
->
ebx
,
p
->
ecx
,
p
->
edx
);
TRACE
(
" ESI=%08x EDI=%08x ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s
\n
"
,
p
->
esi
,
p
->
edi
,
p
->
es
,
p
->
ds
,
p
->
cs
,
p
->
ip
,
CX_reg
(
context
),
iret
?
"IRET"
:
"FAR"
);
if
(
!
(
p
->
cs
)
&&
!
(
p
->
ip
))
{
/* remove this check
if Int21/6501 case map function
has been implemented */
SET_CFLAG
(
context
);
return
;
}
INT_GetRealModeContext
(
p
,
&
context16
);
DPMI_CallRMProc
(
&
context16
,
((
LPWORD
)
MapSL
(
MAKESEGPTR
(
context
->
SegSs
,
LOWORD
(
context
->
Esp
))))
+
3
,
CX_reg
(
context
),
iret
);
INT_SetRealModeContext
(
p
,
&
context16
);
}
/* (see dosmem.c, function DOSMEM_InitDPMI) */
static
void
StartPM
(
CONTEXT
*
context
)
{
UINT16
cs
,
ss
,
ds
,
es
;
CONTEXT
pm_ctx
;
DWORD
psp_ofs
=
(
DWORD
)(
DOSVM_psp
<<
4
);
PDB16
*
psp
=
(
PDB16
*
)
psp_ofs
;
HANDLE16
env_seg
=
psp
->
environment
;
unsigned
char
selflags
=
WINE_LDT_FLAGS_DATA
;
RESET_CFLAG
(
context
);
dpmi_flag
=
AX_reg
(
context
);
/* our mode switch wrapper have placed the desired CS into DX */
cs
=
alloc_pm_selector
(
context
->
Edx
,
WINE_LDT_FLAGS_CODE
);
/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
32-bit code using this stack. */
if
(
dpmi_flag
&
1
)
selflags
|=
WINE_LDT_FLAGS_32BIT
;
ss
=
alloc_pm_selector
(
context
->
SegSs
,
selflags
);
/* do the same for the data segments, just in case */
if
(
context
->
SegDs
==
context
->
SegSs
)
ds
=
ss
;
else
ds
=
alloc_pm_selector
(
context
->
SegDs
,
selflags
);
es
=
alloc_pm_selector
(
DOSVM_psp
,
selflags
);
/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
psp
->
environment
=
alloc_pm_selector
(
env_seg
,
WINE_LDT_FLAGS_DATA
);
pm_ctx
=
*
context
;
pm_ctx
.
SegCs
=
DOSVM_dpmi_segments
->
dpmi_sel
;
/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */
pm_ctx
.
Eax
=
ss
;
pm_ctx
.
Edx
=
cs
;
pm_ctx
.
SegDs
=
ds
;
pm_ctx
.
SegEs
=
es
;
pm_ctx
.
SegFs
=
wine_get_fs
();
pm_ctx
.
SegGs
=
wine_get_gs
();
pm_ctx
.
EFlags
&=
~
V86_FLAG
;
TRACE
(
"DOS program is now entering %d-bit protected mode
\n
"
,
DOSVM_IsDos32
()
?
32
:
16
);
WOWCallback16Ex
(
0
,
WCB16_REGS
,
0
,
NULL
,
(
DWORD
*
)
&
pm_ctx
);
TRACE
(
"Protected mode DOS program is terminating
\n
"
);
/*
* FIXME: Instead of calling DOSVM_Exit, we should release all
* allocated protected mode resources and call MZ_Exit
* using real mode context. See DPMI specification.
*/
DOSVM_Exit
(
DPMI_retval
);
#if 0
wine_ldt_free_entries( psp->environment, 1 );
psp->environment = env_seg;
wine_ldt_free_entries(es,1);
if (ds != ss) wine_ldt_free_entries(ds,1);
wine_ldt_free_entries(ss,1);
wine_ldt_free_entries(cs,1);
#endif
}
static
RMCB
*
DPMI_AllocRMCB
(
void
)
{
RMCB
*
NewRMCB
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
RMCB
));
UINT16
uParagraph
;
if
(
NewRMCB
)
{
LPVOID
RMCBmem
=
DOSMEM_AllocBlock
(
4
,
&
uParagraph
);
LPBYTE
p
=
RMCBmem
;
*
p
++
=
0xcd
;
/* RMCB: */
*
p
++
=
0x31
;
/* int $0x31 */
/* it is the called procedure's task to change the return CS:EIP
the DPMI 0.9 spec states that if it doesn't, it will be called again */
*
p
++
=
0xeb
;
*
p
++
=
0xfc
;
/* jmp RMCB */
NewRMCB
->
address
=
MAKELONG
(
0
,
uParagraph
);
NewRMCB
->
next
=
FirstRMCB
;
FirstRMCB
=
NewRMCB
;
}
return
NewRMCB
;
}
FARPROC16
DPMI_AllocInternalRMCB
(
RMCBPROC
proc
)
{
RMCB
*
NewRMCB
=
DPMI_AllocRMCB
();
if
(
NewRMCB
)
{
NewRMCB
->
proc_ofs
=
(
DWORD
)
proc
;
NewRMCB
->
proc_sel
=
0
;
NewRMCB
->
regs_ofs
=
0
;
NewRMCB
->
regs_sel
=
0
;
return
(
FARPROC16
)(
NewRMCB
->
address
);
}
return
NULL
;
}
static
BOOL
DPMI_FreeRMCB
(
DWORD
address
)
{
RMCB
*
CurrRMCB
=
FirstRMCB
;
RMCB
*
PrevRMCB
=
NULL
;
while
(
CurrRMCB
&&
(
CurrRMCB
->
address
!=
address
))
{
PrevRMCB
=
CurrRMCB
;
CurrRMCB
=
CurrRMCB
->
next
;
}
if
(
CurrRMCB
)
{
if
(
PrevRMCB
)
PrevRMCB
->
next
=
CurrRMCB
->
next
;
else
FirstRMCB
=
CurrRMCB
->
next
;
DOSMEM_FreeBlock
(
PTR_REAL_TO_LIN
(
SELECTOROF
(
CurrRMCB
->
address
),
OFFSETOF
(
CurrRMCB
->
address
)));
HeapFree
(
GetProcessHeap
(),
0
,
CurrRMCB
);
return
TRUE
;
}
return
FALSE
;
}
/**********************************************************************
* DOSVM_RawModeSwitchHandler
*
* DPMI Raw Mode Switch handler
*/
void
WINAPI
DOSVM_RawModeSwitchHandler
(
CONTEXT
*
context
)
{
FIXME
(
"no longer supported
\n
"
);
}
/**********************************************************************
* AllocRMCB
*/
static
void
DOSVM_AllocRMCB
(
CONTEXT
*
context
)
{
RMCB
*
NewRMCB
=
DPMI_AllocRMCB
();
TRACE
(
"Function to call: %04x:%04x
\n
"
,
(
WORD
)
context
->
SegDs
,
SI_reg
(
context
)
);
if
(
NewRMCB
)
{
NewRMCB
->
proc_ofs
=
DOSVM_IsDos32
()
?
context
->
Esi
:
LOWORD
(
context
->
Esi
);
NewRMCB
->
proc_sel
=
context
->
SegDs
;
NewRMCB
->
regs_ofs
=
DOSVM_IsDos32
()
?
context
->
Edi
:
LOWORD
(
context
->
Edi
);
NewRMCB
->
regs_sel
=
context
->
SegEs
;
SET_CX
(
context
,
HIWORD
(
NewRMCB
->
address
)
);
SET_DX
(
context
,
LOWORD
(
NewRMCB
->
address
)
);
}
else
{
SET_AX
(
context
,
0x8015
);
/* callback unavailable */
SET_CFLAG
(
context
);
}
}
/**********************************************************************
* FreeRMCB
*/
static
void
DOSVM_FreeRMCB
(
CONTEXT
*
context
)
{
FIXME
(
"callback address: %04x:%04x
\n
"
,
CX_reg
(
context
),
DX_reg
(
context
));
if
(
!
DPMI_FreeRMCB
(
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
))))
{
SET_AX
(
context
,
0x8024
);
/* invalid callback address */
SET_CFLAG
(
context
);
}
}
static
BYTE
*
XMS_Offset
(
MOVEOFS
*
ofs
)
{
if
(
ofs
->
Handle
)
return
(
BYTE
*
)
GlobalLock16
(
ofs
->
Handle
)
+
ofs
->
Offset
;
else
return
PTR_REAL_TO_LIN
(
SELECTOROF
(
ofs
->
Offset
),
OFFSETOF
(
ofs
->
Offset
));
}
/**********************************************************************
* XMS_Handler
*/
static
void
XMS_Handler
(
CONTEXT
*
context
)
{
switch
(
AH_reg
(
context
))
{
case
0x00
:
/* Get XMS version number */
TRACE
(
"get XMS version number
\n
"
);
SET_AX
(
context
,
0x0200
);
/* 2.0 */
SET_BX
(
context
,
0x0000
);
/* internal revision */
SET_DX
(
context
,
0x0001
);
/* HMA exists */
break
;
case
0x08
:
/* Query Free Extended Memory */
{
MEMORYSTATUS
status
;
TRACE
(
"query free extended memory
\n
"
);
GlobalMemoryStatus
(
&
status
);
SET_DX
(
context
,
status
.
dwAvailVirtual
>>
10
);
SET_AX
(
context
,
status
.
dwAvailVirtual
>>
10
);
TRACE
(
"returning largest %dK, total %dK
\n
"
,
AX_reg
(
context
),
DX_reg
(
context
));
}
break
;
case
0x09
:
/* Allocate Extended Memory Block */
TRACE
(
"allocate extended memory block (%dK)
\n
"
,
DX_reg
(
context
));
SET_DX
(
context
,
GlobalAlloc16
(
GMEM_MOVEABLE
,
(
DWORD
)
DX_reg
(
context
)
<<
10
)
);
SET_AX
(
context
,
DX_reg
(
context
)
?
1
:
0
);
if
(
!
DX_reg
(
context
))
SET_BL
(
context
,
0xA0
);
/* out of memory */
break
;
case
0x0a
:
/* Free Extended Memory Block */
TRACE
(
"free extended memory block %04x
\n
"
,
DX_reg
(
context
));
if
(
!
DX_reg
(
context
)
||
GlobalFree16
(
DX_reg
(
context
)))
{
SET_AX
(
context
,
0
);
/* failure */
SET_BL
(
context
,
0xa2
);
/* invalid handle */
}
else
SET_AX
(
context
,
1
);
/* success */
break
;
case
0x0b
:
/* Move Extended Memory Block */
{
MOVESTRUCT
*
move
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegDs
,
context
->
Esi
);
BYTE
*
src
,
*
dst
;
TRACE
(
"move extended memory block
\n
"
);
src
=
XMS_Offset
(
&
move
->
Source
);
dst
=
XMS_Offset
(
&
move
->
Dest
);
memcpy
(
dst
,
src
,
move
->
Length
);
if
(
move
->
Source
.
Handle
)
GlobalUnlock16
(
move
->
Source
.
Handle
);
if
(
move
->
Dest
.
Handle
)
GlobalUnlock16
(
move
->
Dest
.
Handle
);
break
;
}
case
0x88
:
/* Query Any Free Extended Memory */
{
MEMORYSTATUS
status
;
SYSTEM_INFO
info
;
TRACE
(
"query any free extended memory
\n
"
);
GlobalMemoryStatus
(
&
status
);
GetSystemInfo
(
&
info
);
context
->
Eax
=
status
.
dwAvailVirtual
>>
10
;
context
->
Edx
=
status
.
dwAvailVirtual
>>
10
;
context
->
Ecx
=
(
DWORD
)
info
.
lpMaximumApplicationAddress
;
SET_BL
(
context
,
0
);
/* No errors. */
TRACE
(
"returning largest %dK, total %dK, highest 0x%x
\n
"
,
context
->
Eax
,
context
->
Edx
,
context
->
Ecx
);
}
break
;
default
:
INT_BARF
(
context
,
0x31
);
SET_AX
(
context
,
0x0000
);
/* failure */
SET_BL
(
context
,
0x80
);
/* function not implemented */
break
;
}
}
/**********************************************************************
* DOSVM_CheckWrappers
*
* Check if this was really a wrapper call instead of an interrupt.
*/
BOOL
DOSVM_CheckWrappers
(
CONTEXT
*
context
)
{
if
(
context
->
SegCs
==
DOSVM_dpmi_segments
->
dpmi_seg
)
{
/* This is the protected mode switch */
StartPM
(
context
);
return
TRUE
;
}
else
if
(
context
->
SegCs
==
DOSVM_dpmi_segments
->
xms_seg
)
{
/* This is the XMS driver entry point */
XMS_Handler
(
context
);
return
TRUE
;
}
else
{
/* Check for RMCB */
RMCB
*
CurrRMCB
=
FirstRMCB
;
while
(
CurrRMCB
&&
(
HIWORD
(
CurrRMCB
->
address
)
!=
context
->
SegCs
))
CurrRMCB
=
CurrRMCB
->
next
;
if
(
CurrRMCB
)
{
/* RMCB call, propagate to protected-mode handler */
DPMI_CallRMCBProc
(
context
,
CurrRMCB
,
dpmi_flag
);
return
TRUE
;
}
}
return
FALSE
;
}
/**********************************************************************
* DOSVM_Int31Handler
*
...
...
@@ -1068,35 +360,22 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
break
;
case
0x0200
:
/* get real mode interrupt vector */
TRACE
(
"get realmode interrupt vector (0x%02x)
\n
"
,
TRACE
(
"get realmode interrupt vector (0x%02x)
- not supported
\n
"
,
BL_reg
(
context
)
);
{
FARPROC16
proc
=
DOSVM_GetRMHandler
(
BL_reg
(
context
)
);
SET_CX
(
context
,
SELECTOROF
(
proc
)
);
SET_DX
(
context
,
OFFSETOF
(
proc
)
);
}
SET_CX
(
context
,
0
);
SET_DX
(
context
,
0
);
break
;
case
0x0201
:
/* set real mode interrupt vector */
TRACE
(
"set realmode interrupt vector (0x%02x, 0x%04x:0x%04x)
\n
"
,
TRACE
(
"set realmode interrupt vector (0x%02x, 0x%04x:0x%04x)
- not supported
\n
"
,
BL_reg
(
context
),
CX_reg
(
context
),
DX_reg
(
context
)
);
DOSVM_SetRMHandler
(
BL_reg
(
context
),
(
FARPROC16
)
MAKESEGPTR
(
CX_reg
(
context
),
DX_reg
(
context
))
);
break
;
case
0x0202
:
/* Get Processor Exception Handler Vector */
FIXME
(
"Get Processor Exception Handler Vector (0x%02x)
\n
"
,
BL_reg
(
context
)
);
if
(
DOSVM_IsDos32
())
{
SET_CX
(
context
,
0
);
context
->
Edx
=
0
;
}
else
{
SET_CX
(
context
,
0
);
SET_DX
(
context
,
0
);
}
break
;
case
0x0203
:
/* Set Processor Exception Handler Vector */
...
...
@@ -1107,13 +386,6 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
case
0x0204
:
/* Get protected mode interrupt vector */
TRACE
(
"get protected mode interrupt handler (0x%02x)
\n
"
,
BL_reg
(
context
));
if
(
DOSVM_IsDos32
())
{
FARPROC48
handler
=
DOSVM_GetPMHandler48
(
BL_reg
(
context
)
);
SET_CX
(
context
,
handler
.
selector
);
context
->
Edx
=
handler
.
offset
;
}
else
{
FARPROC16
handler
=
DOSVM_GetPMHandler16
(
BL_reg
(
context
)
);
SET_CX
(
context
,
SELECTOROF
(
handler
)
);
...
...
@@ -1124,14 +396,6 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
case
0x0205
:
/* Set protected mode interrupt vector */
TRACE
(
"set protected mode interrupt handler (0x%02x,0x%04x:0x%08x)
\n
"
,
BL_reg
(
context
),
CX_reg
(
context
),
context
->
Edx
);
if
(
DOSVM_IsDos32
())
{
FARPROC48
handler
;
handler
.
selector
=
CX_reg
(
context
);
handler
.
offset
=
context
->
Edx
;
DOSVM_SetPMHandler48
(
BL_reg
(
context
),
handler
);
}
else
{
FARPROC16
handler
;
handler
=
(
FARPROC16
)
MAKESEGPTR
(
CX_reg
(
context
),
DX_reg
(
context
));
...
...
@@ -1140,58 +404,45 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
break
;
case
0x0300
:
/* Simulate real mode interrupt */
TRACE
(
"Simulate real mode interrupt %02x.
\n
"
,
BL_reg
(
context
));
DOSVM_CallRMInt
(
context
);
TRACE
(
"Simulate real mode interrupt %02x - not supported
\n
"
,
BL_reg
(
context
));
break
;
case
0x0301
:
/* Call real mode procedure with far return */
TRACE
(
"Call real mode procedure with far return.
\n
"
);
DOSVM_CallRMProc
(
context
,
FALSE
);
TRACE
(
"Call real mode procedure with far return - not supported
\n
"
);
break
;
case
0x0302
:
/* Call real mode procedure with interrupt return */
TRACE
(
"Call real mode procedure with interrupt return.
\n
"
);
DOSVM_CallRMProc
(
context
,
TRUE
);
TRACE
(
"Call real mode procedure with interrupt return - not supported
\n
"
);
break
;
case
0x0303
:
/* Allocate Real Mode Callback Address */
TRACE
(
"Allocate real mode callback address.
\n
"
);
DOSVM_AllocRMCB
(
context
);
TRACE
(
"Allocate real mode callback address - not supported
\n
"
);
break
;
case
0x0304
:
/* Free Real Mode Callback Address */
TRACE
(
"Free real mode callback address.
\n
"
);
DOSVM_FreeRMCB
(
context
);
TRACE
(
"Free real mode callback address - not supported
\n
"
);
break
;
case
0x0305
:
/* Get State Save/Restore Addresses */
TRACE
(
"get state save/restore addresses
\n
"
);
TRACE
(
"get state save/restore addresses
- no longer supported
\n
"
);
/* we probably won't need this kind of state saving */
SET_AX
(
context
,
0
);
/* real mode: just point to the lret */
SET_BX
(
context
,
DOSVM_dpmi_segments
->
wrap_seg
);
SET_CX
(
context
,
2
);
/* protected mode: don't have any handler yet... */
/* FIXME: Use DI in 16-bit DPMI and EDI in 32-bit DPMI */
FIXME
(
"no protected-mode dummy state save/restore handler yet
\n
"
);
/* real mode */
SET_BX
(
context
,
0
);
SET_CX
(
context
,
0
);
/* protected mode */
SET_SI
(
context
,
0
);
context
->
Edi
=
0
;
break
;
case
0x0306
:
/* Get Raw Mode Switch Addresses */
TRACE
(
"get raw mode switch addresses
\n
"
);
/* real mode, point to standard DPMI return wrapper */
SET_BX
(
context
,
DOSVM_dpmi_segments
->
wrap_seg
);
TRACE
(
"get raw mode switch addresses - no longer supported
\n
"
);
/* real mode */
SET_BX
(
context
,
0
);
SET_CX
(
context
,
0
);
/* protected mode, point to DPMI call wrapper */
/* FIXME: Use DI in 16-bit DPMI and EDI in 32-bit DPMI */
/* FIXME: Doesn't work in DPMI32... */
SET_SI
(
context
,
DOSVM_dpmi_segments
->
dpmi_sel
);
context
->
Edi
=
8
;
/* offset of the INT 0x31 call */
/* protected mode */
SET_SI
(
context
,
0
);
context
->
Edi
=
0
;
break
;
case
0x0400
:
/* Get DPMI version */
...
...
@@ -1354,23 +605,15 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
break
;
case
0x0900
:
/* Get and Disable Virtual Interrupt State */
TRACE
(
"Get and Disable Virtual Interrupt State: %d
\n
"
,
get_vm86_teb_info
()
->
dpmi_vif
);
SET_AL
(
context
,
get_vm86_teb_info
()
->
dpmi_vif
?
1
:
0
);
get_vm86_teb_info
()
->
dpmi_vif
=
0
;
TRACE
(
"Get and Disable Virtual Interrupt State - not supported
\n
"
);
break
;
case
0x0901
:
/* Get and Enable Virtual Interrupt State */
TRACE
(
"Get and Enable Virtual Interrupt State: %d
\n
"
,
get_vm86_teb_info
()
->
dpmi_vif
);
SET_AL
(
context
,
get_vm86_teb_info
()
->
dpmi_vif
?
1
:
0
);
get_vm86_teb_info
()
->
dpmi_vif
=
1
;
TRACE
(
"Get and Enable Virtual Interrupt State - not supported
\n
"
);
break
;
case
0x0902
:
/* Get Virtual Interrupt State */
TRACE
(
"Get Virtual Interrupt State: %d
\n
"
,
get_vm86_teb_info
()
->
dpmi_vif
);
SET_AL
(
context
,
get_vm86_teb_info
()
->
dpmi_vif
?
1
:
0
);
TRACE
(
"Get Virtual Interrupt State - not supported
\n
"
);
break
;
case
0x0e00
:
/* Get Coprocessor Status (1.0) */
...
...
dlls/krnl386.exe16/interrupts.c
View file @
ed6bdb3c
...
...
@@ -47,7 +47,6 @@ static void WINAPI DOSVM_Int5cHandler(CONTEXT*);
static
void
WINAPI
DOSVM_DefaultHandler
(
CONTEXT
*
);
static
FARPROC16
DOSVM_Vectors16
[
256
];
static
FARPROC48
DOSVM_Vectors48
[
256
];
static
const
INTPROC
DOSVM_VectorsBuiltin
[]
=
{
/* 00 */
0
,
0
,
0
,
0
,
...
...
@@ -83,30 +82,7 @@ static const INTPROC DOSVM_VectorsBuiltin[] =
/*
* Sizes of real mode and protected mode interrupt stubs.
*/
#define DOSVM_STUB_RM 4
#define DOSVM_STUB_PM16 5
#define DOSVM_STUB_PM48 6
/**********************************************************************
* DOSVM_GetRMVector
*
* Return pointer to real mode interrupt vector. These are not at fixed
* location because those Win16 programs that do not use any real mode
* code have protected NULL pointer catching block at low linear memory
* and interrupt vectors have been moved to another location.
*/
static
FARPROC16
*
DOSVM_GetRMVector
(
BYTE
intnum
)
{
LDT_ENTRY
entry
;
FARPROC16
proc
;
proc
=
GetProcAddress16
(
GetModuleHandle16
(
"KERNEL"
),
(
LPCSTR
)(
ULONG_PTR
)
183
);
wine_ldt_get_entry
(
LOWORD
(
proc
),
&
entry
);
return
(
FARPROC16
*
)
wine_ldt_get_base
(
&
entry
)
+
intnum
;
}
/**********************************************************************
...
...
@@ -224,40 +200,13 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum )
DOSMEM_InitDosMemory
();
if
(
context
->
SegCs
==
DOSVM_dpmi_segments
->
dpmi_sel
)
{
DOSVM_BuildCallFrame
(
context
,
DOSVM_IntProcRelay
,
DOSVM_RawModeSwitchHandler
);
}
else
if
(
context
->
SegCs
==
DOSVM_dpmi_segments
->
relay_code_sel
)
if
(
context
->
SegCs
==
DOSVM_dpmi_segments
->
relay_code_sel
)
{
/*
* This must not be called using DOSVM_BuildCallFrame.
*/
DOSVM_RelayHandler
(
context
);
}
else
if
(
context
->
SegCs
==
DOSVM_dpmi_segments
->
int48_sel
)
{
/* Restore original flags stored into the stack by the caller. */
DWORD
*
stack
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegSs
,
context
->
Esp
);
context
->
EFlags
=
stack
[
2
];
if
(
intnum
!=
context
->
Eip
/
DOSVM_STUB_PM48
)
WARN
(
"interrupt stub has been modified "
"(interrupt is %02x, interrupt stub is %02x)
\n
"
,
intnum
,
context
->
Eip
/
DOSVM_STUB_PM48
);
TRACE
(
"builtin interrupt %02x has been branched to
\n
"
,
intnum
);
if
(
intnum
==
0x25
||
intnum
==
0x26
)
DOSVM_PushFlags
(
context
,
TRUE
,
TRUE
);
DOSVM_BuildCallFrame
(
context
,
DOSVM_IntProcRelay
,
DOSVM_GetBuiltinHandler
(
intnum
)
);
}
else
if
(
context
->
SegCs
==
DOSVM_dpmi_segments
->
int16_sel
)
{
/* Restore original flags stored into the stack by the caller. */
...
...
@@ -304,45 +253,6 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum )
*/
void
DOSVM_HardwareInterruptPM
(
CONTEXT
*
context
,
BYTE
intnum
)
{
if
(
DOSVM_IsDos32
())
{
FARPROC48
addr
=
DOSVM_GetPMHandler48
(
intnum
);
if
(
addr
.
selector
==
DOSVM_dpmi_segments
->
int48_sel
)
{
TRACE
(
"builtin interrupt %02x has been invoked "
"(through vector %02x)
\n
"
,
addr
.
offset
/
DOSVM_STUB_PM48
,
intnum
);
if
(
intnum
==
0x25
||
intnum
==
0x26
)
DOSVM_PushFlags
(
context
,
TRUE
,
FALSE
);
DOSVM_BuildCallFrame
(
context
,
DOSVM_IntProcRelay
,
DOSVM_GetBuiltinHandler
(
addr
.
offset
/
DOSVM_STUB_PM48
)
);
}
else
{
DWORD
*
stack
;
TRACE
(
"invoking hooked interrupt %02x at %04x:%08x
\n
"
,
intnum
,
addr
.
selector
,
addr
.
offset
);
/* Push the flags and return address on the stack */
stack
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegSs
,
context
->
Esp
);
*
(
--
stack
)
=
context
->
EFlags
;
*
(
--
stack
)
=
context
->
SegCs
;
*
(
--
stack
)
=
context
->
Eip
;
context
->
Esp
+=
-
12
;
/* Jump to the interrupt handler */
context
->
SegCs
=
addr
.
selector
;
context
->
Eip
=
addr
.
offset
;
}
}
else
{
FARPROC16
addr
=
DOSVM_GetPMHandler16
(
intnum
);
if
(
SELECTOROF
(
addr
)
==
DOSVM_dpmi_segments
->
int16_sel
)
...
...
@@ -373,31 +283,6 @@ void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum )
context
->
SegCs
=
HIWORD
(
addr
);
context
->
Eip
=
LOWORD
(
addr
);
}
}
}
/**********************************************************************
* DOSVM_GetRMHandler
*
* Return the real mode interrupt vector for a given interrupt.
*/
FARPROC16
DOSVM_GetRMHandler
(
BYTE
intnum
)
{
return
*
DOSVM_GetRMVector
(
intnum
);
}
/**********************************************************************
* DOSVM_SetRMHandler
*
* Set the real mode interrupt handler for a given interrupt.
*/
void
DOSVM_SetRMHandler
(
BYTE
intnum
,
FARPROC16
handler
)
{
TRACE
(
"Set real mode interrupt vector %02x <- %04x:%04x
\n
"
,
intnum
,
HIWORD
(
handler
),
LOWORD
(
handler
)
);
*
DOSVM_GetRMVector
(
intnum
)
=
handler
;
}
...
...
@@ -497,37 +382,6 @@ void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler )
/**********************************************************************
* DOSVM_GetPMHandler48
*
* Return the protected mode interrupt vector for a given interrupt.
* Used to get 48-bit pointer for 32-bit interrupt handlers in DPMI32.
*/
FARPROC48
DOSVM_GetPMHandler48
(
BYTE
intnum
)
{
if
(
!
DOSVM_Vectors48
[
intnum
].
selector
)
{
DOSVM_Vectors48
[
intnum
].
selector
=
DOSVM_dpmi_segments
->
int48_sel
;
DOSVM_Vectors48
[
intnum
].
offset
=
DOSVM_STUB_PM48
*
intnum
;
}
return
DOSVM_Vectors48
[
intnum
];
}
/**********************************************************************
* DOSVM_SetPMHandler48
*
* Set the protected mode interrupt handler for a given interrupt.
* Used to set 48-bit pointer for 32-bit interrupt handlers in DPMI32.
*/
void
DOSVM_SetPMHandler48
(
BYTE
intnum
,
FARPROC48
handler
)
{
TRACE
(
"Set 32-bit protected mode interrupt vector %02x <- %04x:%08x
\n
"
,
intnum
,
handler
.
selector
,
handler
.
offset
);
DOSVM_Vectors48
[
intnum
]
=
handler
;
}
/**********************************************************************
* DOSVM_CallBuiltinHandler
*
* Execute Wine interrupt handler procedure.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment