Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Li Wenzhe
wine
Commits
e78e1af4
Commit
e78e1af4
authored
25 years ago
by
Ove Kåven
Committed by
Alexandre Julliard
25 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Various DPMI fixes and preliminary DPMI raw mode switch handler.
parent
fe0a5e88
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
loader/dos/dosvm.c
+2
-0
2 additions, 0 deletions
loader/dos/dosvm.c
loader/dos/module.c
+3
-3
3 additions, 3 deletions
loader/dos/module.c
msdos/dpmi.c
+171
-27
171 additions, 27 deletions
msdos/dpmi.c
with
176 additions
and
30 deletions
loader/dos/dosvm.c
+
2
−
0
View file @
e78e1af4
...
...
@@ -389,6 +389,8 @@ int DOSVM_Enter( PCONTEXT context )
#define CP(x,y) VM86.regs.x = y##_reg(context)
CV
;
#undef CP
if
(
VM86
.
regs
.
eflags
&
IF_MASK
)
VM86
.
regs
.
eflags
|=
VIF_MASK
;
}
else
{
/* initial setup */
/* allocate standard DOS handles */
...
...
This diff is collapsed.
Click to expand it.
loader/dos/module.c
+
3
−
3
View file @
e78e1af4
...
...
@@ -537,9 +537,9 @@ void MZ_KillModule( LPDOSTASK lpDosTask )
#undef DFREE
#if 0
/* FIXME: this seems to crash */
if (lpDosTask->dpmi_sel)
UnMapLS(PTR_SEG_OFF_TO_SEGPTR
(lpDosTask->dpmi_sel,
0)
);
/* FIXME: this seems to crash */
if (lpDosTask->dpmi_sel)
SELECTOR_FreeBlock
(lpDosTask->dpmi_sel,
1
);
#endif
}
...
...
This diff is collapsed.
Click to expand it.
msdos/dpmi.c
+
171
−
27
View file @
e78e1af4
...
...
@@ -243,7 +243,7 @@ static void DPMI_CallRMCBProc( CONTEXT *context, RMCB *rmcb, WORD flag )
es
=
ES_reg
(
&
ctx
);
edi
=
EDI_reg
(
&
ctx
);
}
UnMapLS
(
PTR_SEG_OFF_TO_SEGPTR
(
ss
,
0
)
);
SELECTOR_FreeBlock
(
ss
,
1
);
INT_GetRealModeContext
((
REALMODECALL
*
)
PTR_SEG_OFF_TO_LIN
(
es
,
edi
),
context
);
#else
ERR
(
int31
,
"RMCBs only implemented for i386
\n
"
);
...
...
@@ -391,7 +391,7 @@ callrmproc_again:
EBP_reg
(
context
)
=
OFFSETOF
(
thdb
->
cur_stack
)
+
(
WORD
)
&
((
STACK16FRAME
*
)
0
)
->
bp
;
Callbacks
->
CallRegisterShortProc
(
context
,
args
*
sizeof
(
WORD
));
UnMapLS
(
seg_addr
);
SELECTOR_FreeBlock
(
sel
,
1
);
#endif
}
if
(
alloc
)
DOSMEM_FreeBlock
(
pModule
->
self
,
addr
);
...
...
@@ -596,14 +596,28 @@ static void StartPM( CONTEXT *context, LPDOSTASK lpDosTask )
char
*
base
=
DOSMEM_MemoryBase
(
0
);
UINT16
cs
,
ss
,
ds
,
es
;
CONTEXT
pm_ctx
;
DWORD
psp_ofs
=
(
DWORD
)(
lpDosTask
->
psp_seg
<<
4
);
PDB16
*
psp
=
(
PDB16
*
)(
base
+
psp_ofs
);
HANDLE16
env_seg
=
psp
->
environment
;
int
is32
;
RESET_CFLAG
(
context
);
lpDosTask
->
dpmi_flag
=
AX_reg
(
context
);
is32
=
lpDosTask
->
dpmi_flag
&
1
;
/* our mode switch wrapper have placed the desired CS into DX */
cs
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
DX_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_CODE
,
FALSE
,
FALSE
);
ss
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
SS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
FALSE
,
FALSE
);
ds
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
DS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
FALSE
,
FALSE
);
es
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
lpDosTask
->
psp_seg
<<
4
),
0x100
,
SEGMENT_DATA
,
FALSE
,
FALSE
);
/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
32-bit code using this stack. */
ss
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
SS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
is32
,
FALSE
);
/* do the same for the data segments, just in case */
if
(
DS_reg
(
context
)
==
SS_reg
(
context
))
ds
=
ss
;
else
ds
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
DS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
is32
,
FALSE
);
es
=
SELECTOR_AllocBlock
(
base
+
psp_ofs
,
0x100
,
SEGMENT_DATA
,
is32
,
FALSE
);
/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
psp
->
environment
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
env_seg
<<
4
),
0x10000
,
SEGMENT_DATA
,
FALSE
,
FALSE
);
pm_ctx
=
*
context
;
CS_reg
(
&
pm_ctx
)
=
lpDosTask
->
dpmi_sel
;
...
...
@@ -619,14 +633,90 @@ static void StartPM( CONTEXT *context, LPDOSTASK lpDosTask )
Callbacks
->
CallRegisterShortProc
(
&
pm_ctx
,
0
);
/* in the current state of affairs, we won't ever actually return here... */
/* we should have int21/ah=4c do it someday, though... */
SELECTOR_FreeBlock
(
psp
->
environment
,
1
);
psp
->
environment
=
env_seg
;
SELECTOR_FreeBlock
(
es
,
1
);
if
(
ds
!=
ss
)
SELECTOR_FreeBlock
(
ds
,
1
);
SELECTOR_FreeBlock
(
ss
,
1
);
SELECTOR_FreeBlock
(
cs
,
1
);
}
/* DPMI Raw Mode Switch handler */
void
WINAPI
DPMI_RawModeSwitch
(
SIGCONTEXT
*
context
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
CONTEXT
rm_ctx
;
int
ret
;
if
(
!
lpDosTask
)
{
/* we could probably start a DPMI-only dosmod task here, but I doubt
anything other than real DOS apps want to call raw mode switch */
ERR
(
int31
,
"attempting raw mode switch without DOS task!
\n
"
);
ExitProcess
(
1
);
}
/* initialize real-mode context as per spec */
memset
(
&
rm_ctx
,
0
,
sizeof
(
rm_ctx
));
DS_reg
(
&
rm_ctx
)
=
AX_sig
(
context
);
ES_reg
(
&
rm_ctx
)
=
CX_sig
(
context
);
SS_reg
(
&
rm_ctx
)
=
DX_sig
(
context
);
ESP_reg
(
&
rm_ctx
)
=
EBX_sig
(
context
);
CS_reg
(
&
rm_ctx
)
=
SI_sig
(
context
);
EIP_reg
(
&
rm_ctx
)
=
EDI_sig
(
context
);
EBP_reg
(
&
rm_ctx
)
=
EBP_sig
(
context
);
FS_reg
(
&
rm_ctx
)
=
0
;
GS_reg
(
&
rm_ctx
)
=
0
;
EFL_reg
(
&
rm_ctx
)
=
EFL_sig
(
context
);
/* at least we need the IF flag */
/* enter real mode again */
TRACE
(
int31
,
"re-entering real mode at %04lx:%04lx
\n
"
,
CS_reg
(
&
rm_ctx
),
EIP_reg
(
&
rm_ctx
));
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
)
{
/* if the sync was lost, there's no way to recover */
ExitProcess
(
1
);
}
/* alter protected-mode context as per spec */
DS_sig
(
context
)
=
AX_reg
(
&
rm_ctx
);
ES_sig
(
context
)
=
CX_reg
(
&
rm_ctx
);
SS_sig
(
context
)
=
DX_reg
(
&
rm_ctx
);
ESP_sig
(
context
)
=
EBX_reg
(
&
rm_ctx
);
CS_sig
(
context
)
=
SI_reg
(
&
rm_ctx
);
EIP_sig
(
context
)
=
EDI_reg
(
&
rm_ctx
);
EBP_sig
(
context
)
=
EBP_reg
(
&
rm_ctx
);
FS_sig
(
context
)
=
0
;
GS_sig
(
context
)
=
0
;
/* Return to new address and hope that we didn't mess up */
TRACE
(
int31
,
"re-entering protected mode at %04x:%08lx
\n
"
,
CS_sig
(
context
),
EIP_sig
(
context
));
}
UnMapLS
(
PTR_SEG_OFF_TO_SEGPTR
(
es
,
0
));
UnMapLS
(
PTR_SEG_OFF_TO_SEGPTR
(
ds
,
0
));
UnMapLS
(
PTR_SEG_OFF_TO_SEGPTR
(
ss
,
0
));
UnMapLS
(
PTR_SEG_OFF_TO_SEGPTR
(
cs
,
0
));
#else
void
WINAPI
DPMI_RawModeSwitch
(
SIGCONTEXT
*
context
)
{
ERR
(
int31
,
"don't even think about DPMI raw mode switch without DOS support!
\n
"
);
ExitProcess
(
1
);
}
#endif
#define DOS_APP_ISDOS(addr,base) ((addr) < 0x110000)
#define DOS_WINE_ISDOS(addr,base) (((addr) >= (base)) && ((addr) < (base) + 0x110000))
#define DOS_UC_APPTOWINE(addr,base) ((addr) + (base))
#define DOS_UC_WINETOAPP(addr,base) ((addr) - (base))
#define DOS_APPTOWINE(addr,base) (DOS_APP_ISDOS(addr,base) ? DOS_UC_APPTOWINE(addr,base) : (addr))
#define DOS_WINETOAPP(addr,base) (DOS_WINE_ISDOS(addr,base) ? DOS_UC_WINETOAPP(addr,base) : (addr))
#define DOS_BADLIMIT(addr,base,limit) \
((limit == 0xffffffff) ||
/* disallow "fat DS" for now */
\
(DOS_WINE_ISDOS(addr,base) && \
((addr) + (limit) > (base) + 0x110000)))
/**********************************************************************
* INT_Int31Handler
*
...
...
@@ -645,21 +735,18 @@ void WINAPI INT_Int31Handler( CONTEXT *context )
DWORD
dw
;
BYTE
*
ptr
;
TDB
*
pTask
=
(
TDB
*
)
GlobalLock16
(
GetCurrentTask
()
);
NE_MODULE
*
pModule
=
pTask
?
NE_GetPtr
(
pTask
->
hModule
)
:
NULL
;
GlobalUnlock16
(
GetCurrentTask
()
);
LPDOSTASK
lpDosTask
=
MZ_Current
();
#ifdef MZ_SUPPORTED
if
(
ISV86
(
context
)
&&
pModule
&&
pModule
->
lpDosTask
)
{
if
(
ISV86
(
context
)
&&
lpDosTask
)
{
/* Called from real mode, check if it's our wrapper */
TRACE
(
int31
,
"called from real mode
\n
"
);
if
(
CS_reg
(
context
)
==
pModule
->
lpDosTask
->
dpmi_seg
)
{
if
(
CS_reg
(
context
)
==
lpDosTask
->
dpmi_seg
)
{
/* This is the protected mode switch */
StartPM
(
context
,
pModule
->
lpDosTask
);
StartPM
(
context
,
lpDosTask
);
return
;
}
else
if
(
CS_reg
(
context
)
==
pModule
->
lpDosTask
->
xms_seg
)
{
if
(
CS_reg
(
context
)
==
lpDosTask
->
xms_seg
)
{
/* This is the XMS driver entry point */
XMS_Handler
(
context
);
return
;
...
...
@@ -673,7 +760,7 @@ void WINAPI INT_Int31Handler( CONTEXT *context )
if
(
CurrRMCB
)
{
/* RMCB call, propagate to protected-mode handler */
DPMI_CallRMCBProc
(
context
,
CurrRMCB
,
pModule
->
lpDosTask
->
dpmi_flag
);
DPMI_CallRMCBProc
(
context
,
CurrRMCB
,
lpDosTask
->
dpmi_flag
);
return
;
}
}
...
...
@@ -763,9 +850,9 @@ void WINAPI INT_Int31Handler( CONTEXT *context )
else
{
#ifdef MZ_SUPPORTED
if
(
pModule
&&
pModule
->
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
(
pModule
->
self
);
if
((
dw
>
=
base
)
&&
(
dw
<
base
+
0x110000
))
dw
-=
base
;
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
(
lpDosTask
->
hModule
);
dw
=
DOS_WINETOAPP
(
dw
,
base
)
;
}
#endif
CX_reg
(
context
)
=
HIWORD
(
W32S_WINE2APP
(
dw
,
offset
));
...
...
@@ -779,9 +866,9 @@ void WINAPI INT_Int31Handler( CONTEXT *context )
W32S_APP2WINE
(
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
)),
offset
));
dw
=
W32S_APP2WINE
(
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
)),
offset
);
#ifdef MZ_SUPPORTED
/* well, what else could we possibly do? */
if
(
pModule
&&
pModule
->
lpDosTask
)
{
if
(
dw
<
0x110000
)
dw
+=
(
DWORD
)
DOSMEM_MemoryBase
(
pModule
->
self
);
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
(
lpDosTask
->
hModule
);
dw
=
DOS_APPTOWINE
(
dw
,
base
);
}
#endif
SetSelectorBase
(
BX_reg
(
context
),
dw
);
...
...
@@ -791,9 +878,21 @@ void WINAPI INT_Int31Handler( CONTEXT *context )
TRACE
(
int31
,
"set selector limit (0x%04x,0x%08lx)
\n
"
,
BX_reg
(
context
),
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
)));
dw
=
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
)
);
#ifdef MZ_SUPPORTED
if
(
pModule
&&
pModule
->
lpDosTask
)
{
DWORD
base
=
GetSelectorBase
(
BX_reg
(
context
)
);
if
((
dw
==
0xffffffff
)
||
((
base
<
0x110000
)
&&
(
base
+
dw
>
0x110000
)))
{
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
(
lpDosTask
->
hModule
);
DWORD
sbase
=
GetSelectorBase
(
BX_reg
(
context
)
);
if
(
!
sbase
)
{
/* the app has set the limit without setting the base,
* it must be relying on that the default should be DOS space;
* so set the base address now */
SetSelectorBase
(
BX_reg
(
context
),
sbase
=
base
);
if
(
dw
==
0xffffffff
)
{
/* djgpp does this without checking (in _dos_ds setup, crt1.c),
* so we have to override the limit here */
dw
=
0x110000
;
}
}
if
(
DOS_BADLIMIT
(
sbase
,
base
,
dw
))
{
AX_reg
(
context
)
=
0x8021
;
/* invalid value */
SET_CFLAG
(
context
);
break
;
...
...
@@ -822,6 +921,12 @@ void WINAPI INT_Int31Handler( CONTEXT *context )
{
ldt_entry
entry
;
LDT_GetEntry
(
SELECTOR_TO_ENTRY
(
BX_reg
(
context
)
),
&
entry
);
#ifdef MZ_SUPPORTED
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
(
lpDosTask
->
hModule
);
entry
.
base
=
DOS_WINETOAPP
(
entry
.
base
,
base
);
}
#endif
entry
.
base
=
W32S_WINE2APP
(
entry
.
base
,
offset
);
/* FIXME: should use ES:EDI for 32-bit clients */
...
...
@@ -837,6 +942,17 @@ void WINAPI INT_Int31Handler( CONTEXT *context )
LDT_BytesToEntry
(
PTR_SEG_OFF_TO_LIN
(
ES_reg
(
context
),
DI_reg
(
context
)
),
&
entry
);
entry
.
base
=
W32S_APP2WINE
(
entry
.
base
,
offset
);
#ifdef MZ_SUPPORTED
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
(
lpDosTask
->
hModule
);
entry
.
base
=
DOS_APPTOWINE
(
entry
.
base
,
base
);
if
(
DOS_BADLIMIT
(
entry
.
base
,
base
,
entry
.
limit
))
{
AX_reg
(
context
)
=
0x8021
;
/* invalid value */
SET_CFLAG
(
context
);
break
;
}
}
#endif
LDT_SetEntry
(
SELECTOR_TO_ENTRY
(
BX_reg
(
context
)
),
&
entry
);
}
...
...
@@ -911,6 +1027,34 @@ void WINAPI INT_Int31Handler( CONTEXT *context )
FreeRMCB
(
context
);
break
;
case
0x0305
:
/* Get State Save/Restore Addresses */
TRACE
(
int31
,
"get state save/restore addresses
\n
"
);
/* we probably won't need this kind of state saving */
AX_reg
(
context
)
=
0
;
/* real mode: just point to the lret */
BX_reg
(
context
)
=
DPMI_wrap_seg
;
ECX_reg
(
context
)
=
2
;
/* protected mode: don't have any handler yet... */
FIXME
(
int31
,
"no protected-mode dummy state save/restore handler yet
\n
"
);
SI_reg
(
context
)
=
0
;
EDI_reg
(
context
)
=
0
;
break
;
case
0x0306
:
/* Get Raw Mode Switch Addresses */
TRACE
(
int31
,
"get raw mode switch addresses
\n
"
);
if
(
lpDosTask
)
{
/* real mode, point to standard DPMI return wrapper */
BX_reg
(
context
)
=
DPMI_wrap_seg
;
ECX_reg
(
context
)
=
0
;
/* protected mode, point to DPMI call wrapper */
SI_reg
(
context
)
=
lpDosTask
->
dpmi_sel
;
EDI_reg
(
context
)
=
8
;
/* offset of the INT 0x31 call */
}
else
{
ERR
(
int31
,
"win app attempting to get raw mode switch!
\n
"
);
AX_reg
(
context
)
=
0x8001
;
/* unsupported function */
SET_CFLAG
(
context
);
}
break
;
case
0x0400
:
/* Get DPMI version */
TRACE
(
int31
,
"get DPMI version
\n
"
);
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment