Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
e7715126
Commit
e7715126
authored
Dec 29, 2009
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winedos: Move 16-bit VxD support back into kernel.
parent
475b7d22
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1698 additions
and
1695 deletions
+1698
-1695
.gitignore
.gitignore
+0
-1
Makefile.in
dlls/Makefile.in
+1
-4
kernel16_private.h
dlls/krnl386.exe16/kernel16_private.h
+39
-0
krnl386.exe16.spec
dlls/krnl386.exe16/krnl386.exe16.spec
+19
-1
vxd.c
dlls/krnl386.exe16/vxd.c
+1636
-0
Makefile.in
dlls/winedos/Makefile.in
+0
-3
int2f.c
dlls/winedos/int2f.c
+3
-4
vxd.c
dlls/winedos/vxd.c
+0
-1682
No files found.
.gitignore
View file @
e7715126
...
...
@@ -118,7 +118,6 @@ dlls/sti/sti_wia.h
dlls/sti/sti_wia_p.c
dlls/urlmon/urlmon_urlmon.h
dlls/urlmon/urlmon_urlmon_p.c
dlls/wprocs.dll16
include/activaut.h
include/activdbg.h
include/activscp.h
...
...
dlls/Makefile.in
View file @
e7715126
...
...
@@ -18,7 +18,7 @@ DOCSUBDIRS = $(DLLSUBDIRS)
# 16-bit dlls
WIN16_FILES
=
\
wprocs.dll16
@MAKE_RULES@
...
...
@@ -28,9 +28,6 @@ all: $(BUILDSUBDIRS) @WIN16_FILES@
# Placeholders for 16-bit libraries
wprocs.dll16
:
echo
"winedos.dll"
>
$@
# Import libraries
STATIC_IMPLIBEXT
=
$
(
IMPLIBEXT:def
=
def.a
)
...
...
dlls/krnl386.exe16/kernel16_private.h
View file @
e7715126
...
...
@@ -298,4 +298,43 @@ static inline struct kernel_thread_data *kernel_get_thread_data(void)
"call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" \
"ret $(4*" #args ")" )
/* fake ret to make copy protections happy */
#define AX_reg(context) ((WORD)(context)->Eax)
#define BX_reg(context) ((WORD)(context)->Ebx)
#define CX_reg(context) ((WORD)(context)->Ecx)
#define DX_reg(context) ((WORD)(context)->Edx)
#define SI_reg(context) ((WORD)(context)->Esi)
#define DI_reg(context) ((WORD)(context)->Edi)
#define AL_reg(context) ((BYTE)(context)->Eax)
#define AH_reg(context) ((BYTE)((context)->Eax >> 8))
#define BL_reg(context) ((BYTE)(context)->Ebx)
#define BH_reg(context) ((BYTE)((context)->Ebx >> 8))
#define CL_reg(context) ((BYTE)(context)->Ecx)
#define CH_reg(context) ((BYTE)((context)->Ecx >> 8))
#define DL_reg(context) ((BYTE)(context)->Edx)
#define DH_reg(context) ((BYTE)((context)->Edx >> 8))
#define SET_CFLAG(context) ((context)->EFlags |= 0x0001)
#define RESET_CFLAG(context) ((context)->EFlags &= ~0x0001)
#define SET_ZFLAG(context) ((context)->EFlags |= 0x0040)
#define RESET_ZFLAG(context) ((context)->EFlags &= ~0x0040)
#define ISV86(context) ((context)->EFlags & 0x00020000)
#define SET_AX(context,val) ((void)((context)->Eax = ((context)->Eax & ~0xffff) | (WORD)(val)))
#define SET_BX(context,val) ((void)((context)->Ebx = ((context)->Ebx & ~0xffff) | (WORD)(val)))
#define SET_CX(context,val) ((void)((context)->Ecx = ((context)->Ecx & ~0xffff) | (WORD)(val)))
#define SET_DX(context,val) ((void)((context)->Edx = ((context)->Edx & ~0xffff) | (WORD)(val)))
#define SET_SI(context,val) ((void)((context)->Esi = ((context)->Esi & ~0xffff) | (WORD)(val)))
#define SET_DI(context,val) ((void)((context)->Edi = ((context)->Edi & ~0xffff) | (WORD)(val)))
#define SET_AL(context,val) ((void)((context)->Eax = ((context)->Eax & ~0xff) | (BYTE)(val)))
#define SET_BL(context,val) ((void)((context)->Ebx = ((context)->Ebx & ~0xff) | (BYTE)(val)))
#define SET_CL(context,val) ((void)((context)->Ecx = ((context)->Ecx & ~0xff) | (BYTE)(val)))
#define SET_DL(context,val) ((void)((context)->Edx = ((context)->Edx & ~0xff) | (BYTE)(val)))
#define SET_AH(context,val) ((void)((context)->Eax = ((context)->Eax & ~0xff00) | (((BYTE)(val)) << 8)))
#define SET_BH(context,val) ((void)((context)->Ebx = ((context)->Ebx & ~0xff00) | (((BYTE)(val)) << 8)))
#define SET_CH(context,val) ((void)((context)->Ecx = ((context)->Ecx & ~0xff00) | (((BYTE)(val)) << 8)))
#define SET_DH(context,val) ((void)((context)->Edx = ((context)->Edx & ~0xff00) | (((BYTE)(val)) << 8)))
#endif
/* __WINE_KERNEL16_PRIVATE_H */
dlls/krnl386.exe16/krnl386.exe16.spec
View file @
e7715126
...
...
@@ -523,12 +523,30 @@
703 stub CallProc32WFix
704 pascal -register SSConfirmSmallStack() SSConfirmSmallStack
# Win95 krnl386.exe also exports ordinals 802-864,
# however, those seem to be only callback stubs that are
# never called directly by other modules ...
################################################################
# VxD entry points
#
901 pascal -register __wine_vxd_vmm() __wine_vxd_vmm
905 pascal -register __wine_vxd_timer() __wine_vxd_timer
909 pascal -register __wine_vxd_reboot() __wine_vxd_reboot
910 pascal -register __wine_vxd_vdd() __wine_vxd_vdd
912 pascal -register __wine_vxd_vmd() __wine_vxd_vmd
914 pascal -register __wine_vxd_comm() __wine_vxd_comm
#915 pascal -register __wine_vxd_printer() __wine_vxd_printer
923 pascal -register __wine_vxd_shell() __wine_vxd_shell
933 pascal -register __wine_vxd_pagefile() __wine_vxd_pagefile
938 pascal -register __wine_vxd_apm() __wine_vxd_apm
939 pascal -register __wine_vxd_vxdloader() __wine_vxd_vxdloader
945 pascal -register __wine_vxd_win32s() __wine_vxd_win32s
951 pascal -register __wine_vxd_configmg() __wine_vxd_configmg
955 pascal -register __wine_vxd_enable() __wine_vxd_enable
1990 pascal -register __wine_vxd_timerapi() __wine_vxd_timerapi
################################################################
# 32-bit version of the various 16-bit functions exported by kernel32
#
@ stdcall -arch=win32 -register VxDCall0(long) VxDCall
...
...
dlls/krnl386.exe16/vxd.c
View file @
e7715126
...
...
@@ -34,6 +34,10 @@
#include <string.h>
#include <stdarg.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
...
...
@@ -78,6 +82,17 @@ static struct vxdcall_service vxd_services[] =
#define NB_VXD_SERVICES (sizeof(vxd_services)/sizeof(vxd_services[0]))
#define W32S_APP2WINE(addr) ((addr)? (DWORD)(addr) + W32S_offset : 0)
#define W32S_WINE2APP(addr) ((addr)? (DWORD)(addr) - W32S_offset : 0)
#define VXD_BARF(context,name) \
TRACE( "vxd %s: unknown/not implemented parameters:\n" \
"vxd %s: AX %04x, BX %04x, CX %04x, DX %04x, " \
"SI %04x, DI %04x, DS %04x, ES %04x\n", \
(name), (name), AX_reg(context), BX_reg(context), \
CX_reg(context), DX_reg(context), SI_reg(context), \
DI_reg(context), (WORD)context->SegDs, (WORD)context->SegEs )
static
CRITICAL_SECTION
vxd_section
;
static
CRITICAL_SECTION_DEBUG
critsect_debug
=
{
...
...
@@ -87,6 +102,13 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
};
static
CRITICAL_SECTION
vxd_section
=
{
&
critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
static
UINT
W32S_offset
;
static
WORD
VXD_WinVersion
(
void
)
{
WORD
version
=
LOWORD
(
GetVersion16
());
return
(
version
>>
8
)
|
(
version
<<
8
);
}
/* create a file handle to represent a VxD, by opening a dummy file in the wineserver directory */
static
HANDLE
open_vxd_handle
(
LPCWSTR
name
)
...
...
@@ -293,3 +315,1617 @@ void WINAPI __regs_VxDCall( DWORD service, CONTEXT86 *context )
#ifdef DEFINE_REGS_ENTRYPOINT
DEFINE_REGS_ENTRYPOINT
(
VxDCall
,
1
)
#endif
/***********************************************************************
* __wine_vxd_vmm (WPROCS.401)
*/
void
WINAPI
__wine_vxd_vmm
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] VMM
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x026d
:
/* Get_Debug_Flag '/m' */
case
0x026e
:
/* Get_Debug_Flag '/n' */
SET_AL
(
context
,
0
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"VMM"
);
}
}
/***********************************************************************
* __wine_vxd_pagefile (WPROCS.433)
*/
void
WINAPI
__wine_vxd_pagefile
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
/* taken from Ralf Brown's Interrupt List */
TRACE
(
"[%04x] PageFile
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x00
:
/* get version, is this windows version? */
TRACE
(
"returning version
\n
"
);
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x01
:
/* get swap file info */
TRACE
(
"VxD PageFile: returning swap file info
\n
"
);
SET_AX
(
context
,
0x00
);
/* paging disabled */
context
->
Ecx
=
0
;
/* maximum size of paging file */
/* FIXME: do I touch DS:SI or DS:DI? */
RESET_CFLAG
(
context
);
break
;
case
0x02
:
/* delete permanent swap on exit */
TRACE
(
"VxD PageFile: supposed to delete swap
\n
"
);
RESET_CFLAG
(
context
);
break
;
case
0x03
:
/* current temporary swap file size */
TRACE
(
"VxD PageFile: what is current temp. swap size
\n
"
);
RESET_CFLAG
(
context
);
break
;
case
0x04
:
/* read or write?? INTERRUP.D */
case
0x05
:
/* cancel?? INTERRUP.D */
case
0x06
:
/* test I/O valid INTERRUP.D */
default
:
VXD_BARF
(
context
,
"pagefile"
);
break
;
}
}
/***********************************************************************
* __wine_vxd_reboot (WPROCS.409)
*/
void
WINAPI
__wine_vxd_reboot
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] Reboot
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"REBOOT"
);
}
}
/***********************************************************************
* __wine_vxd_vdd (WPROCS.410)
*/
void
WINAPI
__wine_vxd_vdd
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] VDD
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"VDD"
);
}
}
/***********************************************************************
* __wine_vxd_vmd (WPROCS.412)
*/
void
WINAPI
__wine_vxd_vmd
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] VMD
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"VMD"
);
}
}
/***********************************************************************
* __wine_vxd_vxdloader (WPROCS.439)
*/
void
WINAPI
__wine_vxd_vxdloader
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] VXDLoader
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* get version */
TRACE
(
"returning version
\n
"
);
SET_AX
(
context
,
0x0000
);
SET_DX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x0001
:
/* load device */
FIXME
(
"load device %04x:%04x (%s)
\n
"
,
context
->
SegDs
,
DX_reg
(
context
),
debugstr_a
(
MapSL
(
MAKESEGPTR
(
context
->
SegDs
,
DX_reg
(
context
)))));
SET_AX
(
context
,
0x0000
);
context
->
SegEs
=
0x0000
;
SET_DI
(
context
,
0x0000
);
RESET_CFLAG
(
context
);
break
;
case
0x0002
:
/* unload device */
FIXME
(
"unload device (%08x)
\n
"
,
context
->
Ebx
);
SET_AX
(
context
,
0x0000
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"VXDLDR"
);
SET_AX
(
context
,
0x000B
);
/* invalid function number */
SET_CFLAG
(
context
);
break
;
}
}
/***********************************************************************
* __wine_vxd_shell (WPROCS.423)
*/
void
WINAPI
__wine_vxd_shell
(
CONTEXT86
*
context
)
{
unsigned
service
=
DX_reg
(
context
);
TRACE
(
"[%04x] Shell
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
/* Ralf Brown says EDX, but I use DX instead */
{
case
0x0000
:
TRACE
(
"returning version
\n
"
);
SET_AX
(
context
,
VXD_WinVersion
()
);
context
->
Ebx
=
1
;
/* system VM Handle */
break
;
case
0x0001
:
case
0x0002
:
case
0x0003
:
/* SHELL_SYSMODAL_Message
ebx virtual machine handle
eax message box flags
ecx address of message
edi address of caption
return response in eax
*/
case
0x0004
:
/* SHELL_Message
ebx virtual machine handle
eax message box flags
ecx address of message
edi address of caption
esi address callback
edx reference data for callback
return response in eax
*/
case
0x0005
:
VXD_BARF
(
context
,
"shell"
);
break
;
case
0x0006
:
/* SHELL_Get_VM_State */
TRACE
(
"VxD Shell: returning VM state
\n
"
);
/* Actually we don't, not yet. We have to return a structure
* and I am not to sure how to set it up and return it yet,
* so for now let's do nothing. I can (hopefully) get this
* by the next release
*/
/* RESET_CFLAG(context); */
break
;
case
0x0007
:
case
0x0008
:
case
0x0009
:
case
0x000A
:
case
0x000B
:
case
0x000C
:
case
0x000D
:
case
0x000E
:
case
0x000F
:
case
0x0010
:
case
0x0011
:
case
0x0012
:
case
0x0013
:
case
0x0014
:
case
0x0015
:
case
0x0016
:
VXD_BARF
(
context
,
"SHELL"
);
break
;
/* the new Win95 shell API */
case
0x0100
:
/* get version */
SET_AX
(
context
,
VXD_WinVersion
()
);
break
;
case
0x0104
:
/* retrieve Hook_Properties list */
case
0x0105
:
/* call Hook_Properties callbacks */
VXD_BARF
(
context
,
"SHELL"
);
break
;
case
0x0106
:
/* install timeout callback */
TRACE
(
"VxD Shell: ignoring shell callback (%d sec.)
\n
"
,
context
->
Ebx
);
SET_CFLAG
(
context
);
break
;
case
0x0107
:
/* get version of any VxD */
default
:
VXD_BARF
(
context
,
"SHELL"
);
break
;
}
}
/***********************************************************************
* __wine_vxd_comm (WPROCS.414)
*/
void
WINAPI
__wine_vxd_comm
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] Comm
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* get version */
TRACE
(
"returning version
\n
"
);
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x0001
:
/* set port global */
case
0x0002
:
/* get focus */
case
0x0003
:
/* virtualise port */
default
:
VXD_BARF
(
context
,
"comm"
);
}
}
/***********************************************************************
* __wine_vxd_timer (WPROCS.405)
*/
void
WINAPI
__wine_vxd_timer
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] Virtual Timer
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x0100
:
/* clock tick time, in 840nsecs */
context
->
Eax
=
GetTickCount
();
context
->
Edx
=
context
->
Eax
>>
22
;
context
->
Eax
<<=
10
;
/* not very precise */
break
;
case
0x0101
:
/* current Windows time, msecs */
case
0x0102
:
/* current VM time, msecs */
context
->
Eax
=
GetTickCount
();
break
;
default
:
VXD_BARF
(
context
,
"VTD"
);
}
}
/***********************************************************************
* timer_thread
*/
static
DWORD
CALLBACK
timer_thread
(
void
*
arg
)
{
DWORD
*
system_time
=
arg
;
for
(;;)
{
*
system_time
=
GetTickCount
();
Sleep
(
55
);
}
return
0
;
}
/***********************************************************************
* __wine_vxd_timerapi (WPROCS.1490)
*/
void
WINAPI
__wine_vxd_timerapi
(
CONTEXT86
*
context
)
{
static
WORD
System_Time_Selector
;
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] TimerAPI
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x0009
:
/* get system time selector */
if
(
!
System_Time_Selector
)
{
HANDLE16
handle
=
GlobalAlloc16
(
GMEM_FIXED
,
sizeof
(
DWORD
)
);
System_Time_Selector
=
handle
|
7
;
CloseHandle
(
CreateThread
(
NULL
,
0
,
timer_thread
,
GlobalLock16
(
handle
),
0
,
NULL
)
);
}
SET_AX
(
context
,
System_Time_Selector
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"VTDAPI"
);
}
}
/***********************************************************************
* __wine_vxd_configmg (WPROCS.451)
*/
void
WINAPI
__wine_vxd_configmg
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] ConfigMG
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"CONFIGMG"
);
}
}
/***********************************************************************
* __wine_vxd_enable (WPROCS.455)
*/
void
WINAPI
__wine_vxd_enable
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] Enable
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"ENABLE"
);
}
}
/***********************************************************************
* __wine_vxd_apm (WPROCS.438)
*/
void
WINAPI
__wine_vxd_apm
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] APM
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default
:
VXD_BARF
(
context
,
"APM"
);
}
}
/***********************************************************************
* __wine_vxd_win32s (WPROCS.445)
*
* This is an implementation of the services of the Win32s VxD.
* Since official documentation of these does not seem to be available,
* certain arguments of some of the services remain unclear.
*
* FIXME: The following services are currently unimplemented:
* Exception handling (0x01, 0x1C)
* Debugger support (0x0C, 0x14, 0x17)
* Low-level memory access (0x02, 0x03, 0x0A, 0x0B)
* Memory Statistics (0x1B)
*
*
* We have a specific problem running Win32s on Linux (and probably also
* the other x86 unixes), since Win32s tries to allocate its main 'flat
* code/data segment' selectors with a base of 0xffff0000 (and limit 4GB).
* The rationale for this seems to be that they want one the one hand to
* be able to leave the Win 3.1 memory (starting with the main DOS memory)
* at linear address 0, but want at other hand to have offset 0 of the
* flat data/code segment point to an unmapped page (to catch NULL pointer
* accesses). Hence they allocate the flat segments with a base of 0xffff0000
* so that the Win 3.1 memory area at linear address zero shows up in the
* flat segments at offset 0x10000 (since linear addresses wrap around at
* 4GB). To compensate for that discrepancy between flat segment offsets
* and plain linear addresses, all flat pointers passed between the 32-bit
* and the 16-bit parts of Win32s are shifted by 0x10000 in the appropriate
* direction by the glue code (mainly) in W32SKRNL and WIN32S16.
*
* The problem for us is now that Linux does not allow a LDT selector with
* base 0xffff0000 to be created, since it would 'see' a part of the kernel
* address space. To address this problem we introduce *another* offset:
* We add 0x10000 to every linear address we get as an argument from Win32s.
* This means especially that the flat code/data selectors get actually
* allocated with base 0x0, so that flat offsets and (real) linear addresses
* do again agree! In fact, every call e.g. of a Win32s VxD service now
* has all pointer arguments (which are offsets in the flat data segment)
* first reduced by 0x10000 by the W32SKRNL glue code, and then again
* increased by 0x10000 by *our* code.
*
* Note that to keep everything consistent, this offset has to be applied by
* every Wine function that operates on 'linear addresses' passed to it by
* Win32s. Fortunately, since Win32s does not directly call any Wine 32-bit
* API routines, this affects only two locations: this VxD and the DPMI
* handler. (NOTE: Should any Win32s application pass a linear address to
* any routine apart from those, e.g. some other VxD handler, that code
* would have to take the offset into account as well!)
*
* The offset is set the first time any application calls the GetVersion()
* service of the Win32s VxD. (Note that the offset is never reset.)
*
*/
void
WINAPI
__wine_vxd_win32s
(
CONTEXT86
*
context
)
{
switch
(
AX_reg
(
context
))
{
case
0x0000
:
/* Get Version */
/*
* Input: None
*
* Output: EAX: LoWord: Win32s Version (1.30)
* HiWord: VxD Version (200)
*
* EBX: Build (172)
*
* ECX: ??? (1)
*
* EDX: Debugging Flags
*
* EDI: Error Flag
* 0 if OK,
* 1 if VMCPD VxD not found
*/
TRACE
(
"GetVersion()
\n
"
);
context
->
Eax
=
VXD_WinVersion
()
|
(
200
<<
16
);
context
->
Ebx
=
0
;
context
->
Ecx
=
0
;
context
->
Edx
=
0
;
context
->
Edi
=
0
;
/*
* If this is the first time we are called for this process,
* hack the memory image of WIN32S16 so that it doesn't try
* to access the GDT directly ...
*
* The first code segment of WIN32S16 (version 1.30) contains
* an unexported function somewhere between the exported functions
* SetFS and StackLinearToSegmented that tries to find a selector
* in the LDT that maps to the memory image of the LDT itself.
* If it succeeds, it stores this selector into a global variable
* which will be used to speed up execution by using this selector
* to modify the LDT directly instead of using the DPMI calls.
*
* To perform this search of the LDT, this function uses the
* sgdt and sldt instructions to find the linear address of
* the (GDT and then) LDT. While those instructions themselves
* execute without problem, the linear address that sgdt returns
* points (at least under Linux) to the kernel address space, so
* that any subsequent access leads to a segfault.
*
* Fortunately, WIN32S16 still contains as a fallback option the
* mechanism of using DPMI calls to modify LDT selectors instead
* of direct writes to the LDT. Thus we can circumvent the problem
* by simply replacing the first byte of the offending function
* with an 'retf' instruction. This means that the global variable
* supposed to contain the LDT alias selector will remain zero,
* and hence WIN32S16 will fall back to using DPMI calls.
*
* The heuristic we employ to _find_ that function is as follows:
* We search between the addresses of the exported symbols SetFS
* and StackLinearToSegmented for the byte sequence '0F 01 04'
* (this is the opcode of 'sgdt [si]'). We then search backwards
* from this address for the last occurrence of 'CB' (retf) that marks
* the end of the preceding function. The following byte (which
* should now be the first byte of the function we are looking for)
* will be replaced by 'CB' (retf).
*
* This heuristic works for the retail as well as the debug version
* of Win32s version 1.30. For versions earlier than that this
* hack should not be necessary at all, since the whole mechanism
* ('PERF130') was introduced only in 1.30 to improve the overall
* performance of Win32s.
*/
if
(
!
W32S_offset
)
{
HMODULE16
hModule
=
GetModuleHandle16
(
"win32s16"
);
SEGPTR
func1
=
(
SEGPTR
)
GetProcAddress16
(
hModule
,
"SetFS"
);
SEGPTR
func2
=
(
SEGPTR
)
GetProcAddress16
(
hModule
,
"StackLinearToSegmented"
);
if
(
hModule
&&
func1
&&
func2
&&
SELECTOROF
(
func1
)
==
SELECTOROF
(
func2
))
{
BYTE
*
start
=
MapSL
(
func1
);
BYTE
*
end
=
MapSL
(
func2
);
BYTE
*
p
,
*
retv
=
NULL
;
int
found
=
0
;
for
(
p
=
start
;
p
<
end
;
p
++
)
if
(
*
p
==
0xCB
)
found
=
0
,
retv
=
p
;
else
if
(
*
p
==
0x0F
)
found
=
1
;
else
if
(
*
p
==
0x01
&&
found
==
1
)
found
=
2
;
else
if
(
*
p
==
0x04
&&
found
==
2
)
{
found
=
3
;
break
;
}
else
found
=
0
;
if
(
found
==
3
&&
retv
)
{
TRACE
(
"PERF130 hack: "
"Replacing byte %02X at offset %04X:%04X
\n
"
,
*
(
retv
+
1
),
SELECTOROF
(
func1
),
OFFSETOF
(
func1
)
+
retv
+
1
-
start
);
*
(
retv
+
1
)
=
(
BYTE
)
0xCB
;
}
}
}
/*
* Mark process as Win32s, so that subsequent DPMI calls
* will perform the W32S_APP2WINE/W32S_WINE2APP address shift.
*/
W32S_offset
=
0x10000
;
break
;
case
0x0001
:
/* Install Exception Handling */
/*
* Input: EBX: Flat address of W32SKRNL Exception Data
*
* ECX: LoWord: Flat Code Selector
* HiWord: Flat Data Selector
*
* EDX: Flat address of W32SKRNL Exception Handler
* (this is equal to W32S_BackTo32 + 0x40)
*
* ESI: SEGPTR KERNEL.HASGPHANDLER
*
* EDI: SEGPTR phCurrentTask (KERNEL.THHOOK + 0x10)
*
* Output: EAX: 0 if OK
*/
TRACE
(
"[0001] EBX=%x ECX=%x EDX=%x ESI=%x EDI=%x
\n
"
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
,
context
->
Esi
,
context
->
Edi
);
/* FIXME */
context
->
Eax
=
0
;
break
;
case
0x0002
:
/* Set Page Access Flags */
/*
* Input: EBX: New access flags
* Bit 2: User Page if set, Supervisor Page if clear
* Bit 1: Read-Write if set, Read-Only if clear
*
* ECX: Size of memory area to change
*
* EDX: Flat start address of memory area
*
* Output: EAX: Size of area changed
*/
TRACE
(
"[0002] EBX=%x ECX=%x EDX=%x
\n
"
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
);
/* FIXME */
context
->
Eax
=
context
->
Ecx
;
break
;
case
0x0003
:
/* Get Page Access Flags */
/*
* Input: EDX: Flat address of page to query
*
* Output: EAX: Page access flags
* Bit 2: User Page if set, Supervisor Page if clear
* Bit 1: Read-Write if set, Read-Only if clear
*/
TRACE
(
"[0003] EDX=%x
\n
"
,
context
->
Edx
);
/* FIXME */
context
->
Eax
=
6
;
break
;
case
0x0004
:
/* Map Module */
/*
* Input: ECX: IMTE (offset in Module Table) of new module
*
* EDX: Flat address of Win32s Module Table
*
* Output: EAX: 0 if OK
*/
if
(
!
context
->
Edx
||
CX_reg
(
context
)
==
0xFFFF
)
{
TRACE
(
"MapModule: Initialization call
\n
"
);
context
->
Eax
=
0
;
}
else
{
/*
* Structure of a Win32s Module Table Entry:
*/
struct
Win32sModule
{
DWORD
flags
;
DWORD
flatBaseAddr
;
LPCSTR
moduleName
;
LPCSTR
pathName
;
LPCSTR
unknown
;
LPBYTE
baseAddr
;
DWORD
hModule
;
DWORD
relocDelta
;
};
/*
* Note: This function should set up a demand-paged memory image
* of the given module. Since mmap does not allow file offsets
* not aligned at 1024 bytes, we simply load the image fully
* into memory.
*/
struct
Win32sModule
*
moduleTable
=
(
struct
Win32sModule
*
)
W32S_APP2WINE
(
context
->
Edx
);
struct
Win32sModule
*
module
=
moduleTable
+
context
->
Ecx
;
IMAGE_NT_HEADERS
*
nt_header
=
RtlImageNtHeader
(
(
HMODULE
)
module
->
baseAddr
);
IMAGE_SECTION_HEADER
*
pe_seg
=
(
IMAGE_SECTION_HEADER
*
)((
char
*
)
&
nt_header
->
OptionalHeader
+
nt_header
->
FileHeader
.
SizeOfOptionalHeader
);
HFILE
image
=
_lopen
(
module
->
pathName
,
OF_READ
);
BOOL
error
=
(
image
==
HFILE_ERROR
);
UINT
i
;
TRACE
(
"MapModule: Loading %s
\n
"
,
module
->
pathName
);
for
(
i
=
0
;
!
error
&&
i
<
nt_header
->
FileHeader
.
NumberOfSections
;
i
++
,
pe_seg
++
)
if
(
!
(
pe_seg
->
Characteristics
&
IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
{
DWORD
off
=
pe_seg
->
PointerToRawData
;
DWORD
len
=
pe_seg
->
SizeOfRawData
;
LPBYTE
addr
=
module
->
baseAddr
+
pe_seg
->
VirtualAddress
;
TRACE
(
"MapModule: "
"Section %d at %08x from %08x len %08x
\n
"
,
i
,
(
DWORD
)
addr
,
off
,
len
);
if
(
_llseek
(
image
,
off
,
SEEK_SET
)
!=
off
||
_lread
(
image
,
addr
,
len
)
!=
len
)
error
=
TRUE
;
}
_lclose
(
image
);
if
(
error
)
ERR
(
"MapModule: Unable to load %s
\n
"
,
module
->
pathName
);
else
if
(
module
->
relocDelta
!=
0
)
{
IMAGE_DATA_DIRECTORY
*
dir
=
nt_header
->
OptionalHeader
.
DataDirectory
+
IMAGE_DIRECTORY_ENTRY_BASERELOC
;
IMAGE_BASE_RELOCATION
*
r
=
(
IMAGE_BASE_RELOCATION
*
)
(
dir
->
Size
?
module
->
baseAddr
+
dir
->
VirtualAddress
:
0
);
TRACE
(
"MapModule: Reloc delta %08x
\n
"
,
module
->
relocDelta
);
while
(
r
&&
r
->
VirtualAddress
)
{
LPBYTE
page
=
module
->
baseAddr
+
r
->
VirtualAddress
;
WORD
*
TypeOffset
=
(
WORD
*
)(
r
+
1
);
unsigned
int
count
=
(
r
->
SizeOfBlock
-
sizeof
(
*
r
))
/
sizeof
(
*
TypeOffset
);
TRACE
(
"MapModule: %d relocations for page %08x
\n
"
,
count
,
(
DWORD
)
page
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
int
offset
=
TypeOffset
[
i
]
&
0xFFF
;
int
type
=
TypeOffset
[
i
]
>>
12
;
switch
(
type
)
{
case
IMAGE_REL_BASED_ABSOLUTE
:
break
;
case
IMAGE_REL_BASED_HIGH
:
*
(
WORD
*
)(
page
+
offset
)
+=
HIWORD
(
module
->
relocDelta
);
break
;
case
IMAGE_REL_BASED_LOW
:
*
(
WORD
*
)(
page
+
offset
)
+=
LOWORD
(
module
->
relocDelta
);
break
;
case
IMAGE_REL_BASED_HIGHLOW
:
*
(
DWORD
*
)(
page
+
offset
)
+=
module
->
relocDelta
;
break
;
default:
WARN
(
"MapModule: Unsupported fixup type
\n
"
);
break
;
}
}
r
=
(
IMAGE_BASE_RELOCATION
*
)((
LPBYTE
)
r
+
r
->
SizeOfBlock
);
}
}
context
->
Eax
=
0
;
RESET_CFLAG
(
context
);
}
break
;
case
0x0005
:
/* UnMap Module */
/*
* Input: EDX: Flat address of module image
*
* Output: EAX: 1 if OK
*/
TRACE
(
"UnMapModule: %x
\n
"
,
W32S_APP2WINE
(
context
->
Edx
));
/* As we didn't map anything, there's nothing to unmap ... */
context
->
Eax
=
1
;
break
;
case
0x0006
:
/* VirtualAlloc */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] Flat base address of allocated region
* LPVOID base [in] Flat address of region to reserve/commit
* DWORD size [in] Size of region
* DWORD type [in] Type of allocation
* DWORD prot [in] Type of access protection
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
type
=
stack
[
3
];
DWORD
prot
=
stack
[
4
];
DWORD
result
;
TRACE
(
"VirtualAlloc(%x, %x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
,
type
,
prot
);
if
(
type
&
0x80000000
)
{
WARN
(
"VirtualAlloc: strange type %x
\n
"
,
type
);
type
&=
0x7fffffff
;
}
if
(
!
base
&&
(
type
&
MEM_COMMIT
)
&&
prot
==
PAGE_READONLY
)
{
WARN
(
"VirtualAlloc: NLS hack, allowing write access!
\n
"
);
prot
=
PAGE_READWRITE
;
}
result
=
(
DWORD
)
VirtualAlloc
(
base
,
size
,
type
,
prot
);
if
(
W32S_WINE2APP
(
result
))
*
retv
=
W32S_WINE2APP
(
result
),
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
0
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0007
:
/* VirtualFree */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] TRUE if success, FALSE if failure
* LPVOID base [in] Flat address of region
* DWORD size [in] Size of region
* DWORD type [in] Type of operation
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
type
=
stack
[
3
];
DWORD
result
;
TRACE
(
"VirtualFree(%x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
,
type
);
result
=
VirtualFree
(
base
,
size
,
type
);
if
(
result
)
*
retv
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0008
:
/* VirtualProtect */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] TRUE if success, FALSE if failure
* LPVOID base [in] Flat address of region
* DWORD size [in] Size of region
* DWORD new_prot [in] Desired access protection
* DWORD *old_prot [out] Previous access protection
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
new_prot
=
stack
[
3
];
DWORD
*
old_prot
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
4
]);
DWORD
result
;
TRACE
(
"VirtualProtect(%x, %x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
,
new_prot
,
(
DWORD
)
old_prot
);
result
=
VirtualProtect
(
base
,
size
,
new_prot
,
old_prot
);
if
(
result
)
*
retv
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0009
:
/* VirtualQuery */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] Nr. bytes returned
* LPVOID base [in] Flat address of region
* LPMEMORY_BASIC_INFORMATION info [out] Info buffer
* DWORD len [in] Size of buffer
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
PMEMORY_BASIC_INFORMATION
info
=
(
PMEMORY_BASIC_INFORMATION
)
W32S_APP2WINE
(
stack
[
2
]);
DWORD
len
=
stack
[
3
];
DWORD
result
;
TRACE
(
"VirtualQuery(%x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
(
DWORD
)
info
,
len
);
result
=
VirtualQuery
(
base
,
info
,
len
);
*
retv
=
result
;
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x000A
:
/* SetVirtMemProcess */
/*
* Input: ECX: Process Handle
*
* EDX: Flat address of region
*
* Output: EAX: NtStatus
*/
TRACE
(
"[000a] ECX=%x EDX=%x
\n
"
,
context
->
Ecx
,
context
->
Edx
);
/* FIXME */
context
->
Eax
=
STATUS_SUCCESS
;
break
;
case
0x000B
:
/* ??? some kind of cleanup */
/*
* Input: ECX: Process Handle
*
* Output: EAX: NtStatus
*/
TRACE
(
"[000b] ECX=%x
\n
"
,
context
->
Ecx
);
/* FIXME */
context
->
Eax
=
STATUS_SUCCESS
;
break
;
case
0x000C
:
/* Set Debug Flags */
/*
* Input: EDX: Debug Flags
*
* Output: EDX: Previous Debug Flags
*/
FIXME
(
"[000c] EDX=%x
\n
"
,
context
->
Edx
);
/* FIXME */
context
->
Edx
=
0
;
break
;
case
0x000D
:
/* NtCreateSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 *retv [out] Handle of Section created
* DWORD flags1 [in] (?? unknown ??)
* DWORD atom [in] Name of Section to create
* LARGE_INTEGER *size [in] Size of Section
* DWORD protect [in] Access protection
* DWORD flags2 [in] (?? unknown ??)
* HFILE32 hFile [in] Handle of file to map
* DWORD psp [in] (Win32s: PSP that hFile belongs to)
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
*
retv
=
(
HANDLE
*
)
W32S_APP2WINE
(
stack
[
0
]);
DWORD
flags1
=
stack
[
1
];
DWORD
atom
=
stack
[
2
];
LARGE_INTEGER
*
size
=
(
LARGE_INTEGER
*
)
W32S_APP2WINE
(
stack
[
3
]);
DWORD
protect
=
stack
[
4
];
DWORD
flags2
=
stack
[
5
];
HANDLE
hFile
=
DosFileHandleToWin32Handle
(
stack
[
6
]);
DWORD
psp
=
stack
[
7
];
HANDLE
result
=
INVALID_HANDLE_VALUE
;
char
name
[
128
];
TRACE
(
"NtCreateSection(%x, %x, %x, %x, %x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
flags1
,
atom
,
(
DWORD
)
size
,
protect
,
flags2
,
(
DWORD
)
hFile
,
psp
);
if
(
!
atom
||
GlobalGetAtomNameA
(
atom
,
name
,
sizeof
(
name
)))
{
TRACE
(
"NtCreateSection: name=%s
\n
"
,
atom
?
name
:
NULL
);
result
=
CreateFileMappingA
(
hFile
,
NULL
,
protect
,
size
?
size
->
u
.
HighPart
:
0
,
size
?
size
->
u
.
LowPart
:
0
,
atom
?
name
:
NULL
);
}
if
(
result
==
INVALID_HANDLE_VALUE
)
WARN
(
"NtCreateSection: failed!
\n
"
);
else
TRACE
(
"NtCreateSection: returned %x
\n
"
,
(
DWORD
)
result
);
if
(
result
!=
INVALID_HANDLE_VALUE
)
*
retv
=
result
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
result
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x000E
:
/* NtOpenSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 *retv [out] Handle of Section opened
* DWORD protect [in] Access protection
* DWORD atom [in] Name of Section to create
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
*
retv
=
(
HANDLE
*
)
W32S_APP2WINE
(
stack
[
0
]);
DWORD
protect
=
stack
[
1
];
DWORD
atom
=
stack
[
2
];
HANDLE
result
=
INVALID_HANDLE_VALUE
;
char
name
[
128
];
TRACE
(
"NtOpenSection(%x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
protect
,
atom
);
if
(
atom
&&
GlobalGetAtomNameA
(
atom
,
name
,
sizeof
(
name
)))
{
TRACE
(
"NtOpenSection: name=%s
\n
"
,
name
);
result
=
OpenFileMappingA
(
protect
,
FALSE
,
name
);
}
if
(
result
==
INVALID_HANDLE_VALUE
)
WARN
(
"NtOpenSection: failed!
\n
"
);
else
TRACE
(
"NtOpenSection: returned %x
\n
"
,
(
DWORD
)
result
);
if
(
result
!=
INVALID_HANDLE_VALUE
)
*
retv
=
result
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
result
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x000F
:
/* NtCloseSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 handle [in] Handle of Section to close
* DWORD *id [out] Unique ID (?? unclear ??)
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
handle
=
(
HANDLE
)
stack
[
0
];
DWORD
*
id
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
1
]);
TRACE
(
"NtCloseSection(%x, %x)
\n
"
,
(
DWORD
)
handle
,
(
DWORD
)
id
);
CloseHandle
(
handle
);
if
(
id
)
*
id
=
0
;
/* FIXME */
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x0010
:
/* NtDupSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 handle [in] Handle of Section to duplicate
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
handle
=
(
HANDLE
)
stack
[
0
];
HANDLE
new_handle
;
TRACE
(
"NtDupSection(%x)
\n
"
,
(
DWORD
)
handle
);
DuplicateHandle
(
GetCurrentProcess
(),
handle
,
GetCurrentProcess
(),
&
new_handle
,
0
,
FALSE
,
DUPLICATE_SAME_ACCESS
);
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x0011
:
/* NtMapViewOfSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 SectionHandle [in] Section to be mapped
* DWORD ProcessHandle [in] Process to be mapped into
* DWORD * BaseAddress [in/out] Address to be mapped at
* DWORD ZeroBits [in] (?? unclear ??)
* DWORD CommitSize [in] (?? unclear ??)
* LARGE_INTEGER *SectionOffset [in] Offset within section
* DWORD * ViewSize [in] Size of view
* DWORD InheritDisposition [in] (?? unclear ??)
* DWORD AllocationType [in] (?? unclear ??)
* DWORD Protect [in] Access protection
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
SectionHandle
=
(
HANDLE
)
stack
[
0
];
DWORD
ProcessHandle
=
stack
[
1
];
/* ignored */
DWORD
*
BaseAddress
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
2
]);
DWORD
ZeroBits
=
stack
[
3
];
DWORD
CommitSize
=
stack
[
4
];
LARGE_INTEGER
*
SectionOffset
=
(
LARGE_INTEGER
*
)
W32S_APP2WINE
(
stack
[
5
]);
DWORD
*
ViewSize
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
6
]);
DWORD
InheritDisposition
=
stack
[
7
];
DWORD
AllocationType
=
stack
[
8
];
DWORD
Protect
=
stack
[
9
];
LPBYTE
address
=
(
LPBYTE
)(
BaseAddress
?
W32S_APP2WINE
(
*
BaseAddress
)
:
0
);
DWORD
access
=
0
,
result
;
switch
(
Protect
&
~
(
PAGE_GUARD
|
PAGE_NOCACHE
))
{
case
PAGE_READONLY
:
access
=
FILE_MAP_READ
;
break
;
case
PAGE_READWRITE
:
access
=
FILE_MAP_WRITE
;
break
;
case
PAGE_WRITECOPY
:
access
=
FILE_MAP_COPY
;
break
;
case
PAGE_EXECUTE_READ
:
access
=
FILE_MAP_READ
;
break
;
case
PAGE_EXECUTE_READWRITE
:
access
=
FILE_MAP_WRITE
;
break
;
case
PAGE_EXECUTE_WRITECOPY
:
access
=
FILE_MAP_COPY
;
break
;
}
TRACE
(
"NtMapViewOfSection"
"(%x, %x, %x, %x, %x, %x, %x, %x, %x, %x)
\n
"
,
(
DWORD
)
SectionHandle
,
ProcessHandle
,
(
DWORD
)
BaseAddress
,
ZeroBits
,
CommitSize
,
(
DWORD
)
SectionOffset
,
(
DWORD
)
ViewSize
,
InheritDisposition
,
AllocationType
,
Protect
);
TRACE
(
"NtMapViewOfSection: "
"base=%x, offset=%x, size=%x, access=%x
\n
"
,
(
DWORD
)
address
,
SectionOffset
?
SectionOffset
->
u
.
LowPart
:
0
,
ViewSize
?
*
ViewSize
:
0
,
access
);
result
=
(
DWORD
)
MapViewOfFileEx
(
SectionHandle
,
access
,
SectionOffset
?
SectionOffset
->
u
.
HighPart
:
0
,
SectionOffset
?
SectionOffset
->
u
.
LowPart
:
0
,
ViewSize
?
*
ViewSize
:
0
,
address
);
TRACE
(
"NtMapViewOfSection: result=%x
\n
"
,
result
);
if
(
W32S_WINE2APP
(
result
))
{
if
(
BaseAddress
)
*
BaseAddress
=
W32S_WINE2APP
(
result
);
context
->
Eax
=
STATUS_SUCCESS
;
}
else
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0012
:
/* NtUnmapViewOfSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* DWORD ProcessHandle [in] Process (defining address space)
* LPBYTE BaseAddress [in] Base address of view to be unmapped
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
ProcessHandle
=
stack
[
0
];
/* ignored */
LPBYTE
BaseAddress
=
(
LPBYTE
)
W32S_APP2WINE
(
stack
[
1
]);
TRACE
(
"NtUnmapViewOfSection(%x, %x)
\n
"
,
ProcessHandle
,
(
DWORD
)
BaseAddress
);
UnmapViewOfFile
(
BaseAddress
);
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x0013
:
/* NtFlushVirtualMemory */
/*
* Input: EDX: Flat address of arguments on stack
*
* DWORD ProcessHandle [in] Process (defining address space)
* LPBYTE *BaseAddress [in?] Base address of range to be flushed
* DWORD *ViewSize [in?] Number of bytes to be flushed
* DWORD *unknown [???] (?? unknown ??)
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
ProcessHandle
=
stack
[
0
];
/* ignored */
DWORD
*
BaseAddress
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
*
ViewSize
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
2
]);
DWORD
*
unknown
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
3
]);
LPBYTE
address
=
(
LPBYTE
)(
BaseAddress
?
W32S_APP2WINE
(
*
BaseAddress
)
:
0
);
DWORD
size
=
ViewSize
?
*
ViewSize
:
0
;
TRACE
(
"NtFlushVirtualMemory(%x, %x, %x, %x)
\n
"
,
ProcessHandle
,
(
DWORD
)
BaseAddress
,
(
DWORD
)
ViewSize
,
(
DWORD
)
unknown
);
TRACE
(
"NtFlushVirtualMemory: base=%x, size=%x
\n
"
,
(
DWORD
)
address
,
size
);
FlushViewOfFile
(
address
,
size
);
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x0014
:
/* Get/Set Debug Registers */
/*
* Input: ECX: 0 if Get, 1 if Set
*
* EDX: Get: Flat address of buffer to receive values of
* debug registers DR0 .. DR7
* Set: Flat address of buffer containing values of
* debug registers DR0 .. DR7 to be set
* Output: None
*/
FIXME
(
"[0014] ECX=%x EDX=%x
\n
"
,
context
->
Ecx
,
context
->
Edx
);
/* FIXME */
break
;
case
0x0015
:
/* Set Coprocessor Emulation Flag */
/*
* Input: EDX: 0 to deactivate, 1 to activate coprocessor emulation
*
* Output: None
*/
TRACE
(
"[0015] EDX=%x
\n
"
,
context
->
Edx
);
/* We don't care, as we always have a coprocessor anyway */
break
;
case
0x0016
:
/* Init Win32S VxD PSP */
/*
* If called to query required PSP size:
*
* Input: EBX: 0
* Output: EDX: Required size of Win32s VxD PSP
*
* If called to initialize allocated PSP:
*
* Input: EBX: LoWord: Selector of Win32s VxD PSP
* HiWord: Paragraph of Win32s VxD PSP (DOSMEM)
* Output: None
*/
if
(
context
->
Ebx
==
0
)
context
->
Edx
=
0x80
;
else
{
PDB16
*
psp
=
MapSL
(
MAKESEGPTR
(
BX_reg
(
context
),
0
));
psp
->
nbFiles
=
32
;
psp
->
fileHandlesPtr
=
MAKELONG
(
HIWORD
(
context
->
Ebx
),
0x5c
);
memset
((
LPBYTE
)
psp
+
0x5c
,
'\xFF'
,
32
);
}
break
;
case
0x0017
:
/* Set Break Point */
/*
* Input: EBX: Offset of Break Point
* CX: Selector of Break Point
*
* Output: None
*/
FIXME
(
"[0017] EBX=%x CX=%x
\n
"
,
context
->
Ebx
,
CX_reg
(
context
));
/* FIXME */
break
;
case
0x0018
:
/* VirtualLock */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] TRUE if success, FALSE if failure
* LPVOID base [in] Flat address of range to lock
* DWORD size [in] Size of range
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
result
;
TRACE
(
"VirtualLock(%x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
);
result
=
VirtualLock
(
base
,
size
);
if
(
result
)
*
retv
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0019
:
/* VirtualUnlock */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] TRUE if success, FALSE if failure
* LPVOID base [in] Flat address of range to unlock
* DWORD size [in] Size of range
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
result
;
TRACE
(
"VirtualUnlock(%x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
);
result
=
VirtualUnlock
(
base
,
size
);
if
(
result
)
*
retv
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x001A
:
/* KGetSystemInfo */
/*
* Input: None
*
* Output: ECX: Start of sparse memory arena
* EDX: End of sparse memory arena
*/
TRACE
(
"KGetSystemInfo()
\n
"
);
/*
* Note: Win32s reserves 0GB - 2GB for Win 3.1 and uses 2GB - 4GB as
* sparse memory arena. We do it the other way around, since
* we have to reserve 3GB - 4GB for Linux, and thus use
* 0GB - 3GB as sparse memory arena.
*
* FIXME: What about other OSes ?
*/
context
->
Ecx
=
W32S_WINE2APP
(
0x00000000
);
context
->
Edx
=
W32S_WINE2APP
(
0xbfffffff
);
break
;
case
0x001B
:
/* KGlobalMemStat */
/*
* Input: ESI: Flat address of buffer to receive memory info
*
* Output: None
*/
{
struct
Win32sMemoryInfo
{
DWORD
DIPhys_Count
;
/* Total physical pages */
DWORD
DIFree_Count
;
/* Free physical pages */
DWORD
DILin_Total_Count
;
/* Total virtual pages (private arena) */
DWORD
DILin_Total_Free
;
/* Free virtual pages (private arena) */
DWORD
SparseTotal
;
/* Total size of sparse arena (bytes ?) */
DWORD
SparseFree
;
/* Free size of sparse arena (bytes ?) */
};
struct
Win32sMemoryInfo
*
info
=
(
struct
Win32sMemoryInfo
*
)
W32S_APP2WINE
(
context
->
Esi
);
FIXME
(
"KGlobalMemStat(%x)
\n
"
,
(
DWORD
)
info
);
/* FIXME */
}
break
;
case
0x001C
:
/* Enable/Disable Exceptions */
/*
* Input: ECX: 0 to disable, 1 to enable exception handling
*
* Output: None
*/
TRACE
(
"[001c] ECX=%x
\n
"
,
context
->
Ecx
);
/* FIXME */
break
;
case
0x001D
:
/* VirtualAlloc called from 16-bit code */
/*
* Input: EDX: Segmented address of arguments on stack
*
* LPVOID base [in] Flat address of region to reserve/commit
* DWORD size [in] Size of region
* DWORD type [in] Type of allocation
* DWORD prot [in] Type of access protection
*
* Output: EAX: NtStatus
* EDX: Flat base address of allocated region
*/
{
DWORD
*
stack
=
MapSL
(
MAKESEGPTR
(
LOWORD
(
context
->
Edx
),
HIWORD
(
context
->
Edx
)
));
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
0
]);
DWORD
size
=
stack
[
1
];
DWORD
type
=
stack
[
2
];
DWORD
prot
=
stack
[
3
];
DWORD
result
;
TRACE
(
"VirtualAlloc16(%x, %x, %x, %x)
\n
"
,
(
DWORD
)
base
,
size
,
type
,
prot
);
if
(
type
&
0x80000000
)
{
WARN
(
"VirtualAlloc16: strange type %x
\n
"
,
type
);
type
&=
0x7fffffff
;
}
result
=
(
DWORD
)
VirtualAlloc
(
base
,
size
,
type
,
prot
);
if
(
W32S_WINE2APP
(
result
))
context
->
Edx
=
W32S_WINE2APP
(
result
),
context
->
Eax
=
STATUS_SUCCESS
;
else
context
->
Edx
=
0
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
TRACE
(
"VirtualAlloc16: returning base %x
\n
"
,
context
->
Edx
);
}
break
;
case
0x001E
:
/* VirtualFree called from 16-bit code */
/*
* Input: EDX: Segmented address of arguments on stack
*
* LPVOID base [in] Flat address of region
* DWORD size [in] Size of region
* DWORD type [in] Type of operation
*
* Output: EAX: NtStatus
* EDX: TRUE if success, FALSE if failure
*/
{
DWORD
*
stack
=
MapSL
(
MAKESEGPTR
(
LOWORD
(
context
->
Edx
),
HIWORD
(
context
->
Edx
)
));
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
0
]);
DWORD
size
=
stack
[
1
];
DWORD
type
=
stack
[
2
];
DWORD
result
;
TRACE
(
"VirtualFree16(%x, %x, %x)
\n
"
,
(
DWORD
)
base
,
size
,
type
);
result
=
VirtualFree
(
base
,
size
,
type
);
if
(
result
)
context
->
Edx
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
context
->
Edx
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x001F
:
/* FWorkingSetSize */
/*
* Input: EDX: 0 if Get, 1 if Set
*
* ECX: Get: Buffer to receive Working Set Size
* Set: Buffer containing Working Set Size
*
* Output: NtStatus
*/
{
DWORD
*
ptr
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Ecx
);
BOOL
set
=
context
->
Edx
;
TRACE
(
"FWorkingSetSize(%x, %x)
\n
"
,
(
DWORD
)
ptr
,
(
DWORD
)
set
);
if
(
set
)
/* We do it differently ... */
;
else
*
ptr
=
0x100
;
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
default
:
VXD_BARF
(
context
,
"W32S"
);
}
}
dlls/winedos/Makefile.in
View file @
e7715126
...
...
@@ -5,8 +5,6 @@ VPATH = @srcdir@
MODULE
=
winedos.dll
IMPORTS
=
user32 kernel32 ntdll
SPEC_SRCS16
=
wprocs.spec
C_SRCS
=
\
devices.c
\
dma.c
\
...
...
@@ -36,7 +34,6 @@ C_SRCS = \
soundblaster.c
\
timer.c
\
vga.c
\
vxd.c
\
xms.c
@MAKE_DLL_RULES@
...
...
dlls/winedos/int2f.c
View file @
e7715126
...
...
@@ -39,8 +39,8 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
int
);
/* base
WPROCS.DL
L ordinal number for VxDs */
#define VXD_BASE
4
00
/* base
KERNE
L ordinal number for VxDs */
#define VXD_BASE
9
00
typedef
struct
{
...
...
@@ -432,8 +432,7 @@ static void do_int2f_16( CONTEXT86 *context )
case
0x84
:
/* Get device API entry point */
{
HMODULE16
mod
=
GetModuleHandle16
(
"wprocs"
);
if
(
mod
<
32
)
mod
=
LoadLibrary16
(
"wprocs"
);
HMODULE16
mod
=
GetModuleHandle16
(
"kernel"
);
addr
=
(
DWORD
)
GetProcAddress16
(
mod
,
(
LPCSTR
)(
VXD_BASE
+
BX_reg
(
context
))
);
if
(
!
addr
)
/* not supported */
ERR
(
"Accessing unknown VxD %04x - Expect a failure now.
\n
"
,
BX_reg
(
context
)
);
...
...
dlls/winedos/vxd.c
deleted
100644 → 0
View file @
475b7d22
/*
* VxD emulation
*
* Copyright 1995 Anand Kumria
*
* 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 "wine/port.h"
#include <fcntl.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winternl.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/winbase16.h"
#include "dosexe.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
vxd
);
#define W32S_APP2WINE(addr) ((addr)? (DWORD)(addr) + W32S_offset : 0)
#define W32S_WINE2APP(addr) ((addr)? (DWORD)(addr) - W32S_offset : 0)
#define VXD_BARF(context,name) \
TRACE( "vxd %s: unknown/not implemented parameters:\n" \
"vxd %s: AX %04x, BX %04x, CX %04x, DX %04x, " \
"SI %04x, DI %04x, DS %04x, ES %04x\n", \
(name), (name), AX_reg(context), BX_reg(context), \
CX_reg(context), DX_reg(context), SI_reg(context), \
DI_reg(context), (WORD)context->SegDs, (WORD)context->SegEs )
static
UINT
W32S_offset
;
static
WORD
VXD_WinVersion
(
void
)
{
WORD
version
=
LOWORD
(
GetVersion16
());
return
(
version
>>
8
)
|
(
version
<<
8
);
}
/***********************************************************************
* VXD_VMM (WPROCS.401)
*/
void
WINAPI
VXD_VMM
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] VMM
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x026d
:
/* Get_Debug_Flag '/m' */
case
0x026e
:
/* Get_Debug_Flag '/n' */
SET_AL
(
context
,
0
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"VMM"
);
}
}
/***********************************************************************
* VXD_PageFile (WPROCS.433)
*/
void
WINAPI
VXD_PageFile
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
/* taken from Ralf Brown's Interrupt List */
TRACE
(
"[%04x] PageFile
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x00
:
/* get version, is this windows version? */
TRACE
(
"returning version
\n
"
);
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x01
:
/* get swap file info */
TRACE
(
"VxD PageFile: returning swap file info
\n
"
);
SET_AX
(
context
,
0x00
);
/* paging disabled */
context
->
Ecx
=
0
;
/* maximum size of paging file */
/* FIXME: do I touch DS:SI or DS:DI? */
RESET_CFLAG
(
context
);
break
;
case
0x02
:
/* delete permanent swap on exit */
TRACE
(
"VxD PageFile: supposed to delete swap
\n
"
);
RESET_CFLAG
(
context
);
break
;
case
0x03
:
/* current temporary swap file size */
TRACE
(
"VxD PageFile: what is current temp. swap size
\n
"
);
RESET_CFLAG
(
context
);
break
;
case
0x04
:
/* read or write?? INTERRUP.D */
case
0x05
:
/* cancel?? INTERRUP.D */
case
0x06
:
/* test I/O valid INTERRUP.D */
default:
VXD_BARF
(
context
,
"pagefile"
);
break
;
}
}
/***********************************************************************
* VXD_Reboot (WPROCS.409)
*/
void
WINAPI
VXD_Reboot
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] Reboot
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"REBOOT"
);
}
}
/***********************************************************************
* VXD_VDD (WPROCS.410)
*/
void
WINAPI
VXD_VDD
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] VDD
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"VDD"
);
}
}
/***********************************************************************
* VXD_VMD (WPROCS.412)
*/
void
WINAPI
VXD_VMD
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] VMD
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"VMD"
);
}
}
/***********************************************************************
* VXD_VXDLoader (WPROCS.439)
*/
void
WINAPI
VXD_VXDLoader
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] VXDLoader
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* get version */
TRACE
(
"returning version
\n
"
);
SET_AX
(
context
,
0x0000
);
SET_DX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x0001
:
/* load device */
FIXME
(
"load device %04x:%04x (%s)
\n
"
,
context
->
SegDs
,
DX_reg
(
context
),
debugstr_a
(
MapSL
(
MAKESEGPTR
(
context
->
SegDs
,
DX_reg
(
context
)))));
SET_AX
(
context
,
0x0000
);
context
->
SegEs
=
0x0000
;
SET_DI
(
context
,
0x0000
);
RESET_CFLAG
(
context
);
break
;
case
0x0002
:
/* unload device */
FIXME
(
"unload device (%08x)
\n
"
,
context
->
Ebx
);
SET_AX
(
context
,
0x0000
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"VXDLDR"
);
SET_AX
(
context
,
0x000B
);
/* invalid function number */
SET_CFLAG
(
context
);
break
;
}
}
/***********************************************************************
* VXD_Shell (WPROCS.423)
*/
void
WINAPI
VXD_Shell
(
CONTEXT86
*
context
)
{
unsigned
service
=
DX_reg
(
context
);
TRACE
(
"[%04x] Shell
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
/* Ralf Brown says EDX, but I use DX instead */
{
case
0x0000
:
TRACE
(
"returning version
\n
"
);
SET_AX
(
context
,
VXD_WinVersion
()
);
context
->
Ebx
=
1
;
/* system VM Handle */
break
;
case
0x0001
:
case
0x0002
:
case
0x0003
:
/* SHELL_SYSMODAL_Message
ebx virtual machine handle
eax message box flags
ecx address of message
edi address of caption
return response in eax
*/
case
0x0004
:
/* SHELL_Message
ebx virtual machine handle
eax message box flags
ecx address of message
edi address of caption
esi address callback
edx reference data for callback
return response in eax
*/
case
0x0005
:
VXD_BARF
(
context
,
"shell"
);
break
;
case
0x0006
:
/* SHELL_Get_VM_State */
TRACE
(
"VxD Shell: returning VM state
\n
"
);
/* Actually we don't, not yet. We have to return a structure
* and I am not to sure how to set it up and return it yet,
* so for now let's do nothing. I can (hopefully) get this
* by the next release
*/
/* RESET_CFLAG(context); */
break
;
case
0x0007
:
case
0x0008
:
case
0x0009
:
case
0x000A
:
case
0x000B
:
case
0x000C
:
case
0x000D
:
case
0x000E
:
case
0x000F
:
case
0x0010
:
case
0x0011
:
case
0x0012
:
case
0x0013
:
case
0x0014
:
case
0x0015
:
case
0x0016
:
VXD_BARF
(
context
,
"SHELL"
);
break
;
/* the new Win95 shell API */
case
0x0100
:
/* get version */
SET_AX
(
context
,
VXD_WinVersion
()
);
break
;
case
0x0104
:
/* retrieve Hook_Properties list */
case
0x0105
:
/* call Hook_Properties callbacks */
VXD_BARF
(
context
,
"SHELL"
);
break
;
case
0x0106
:
/* install timeout callback */
TRACE
(
"VxD Shell: ignoring shell callback (%d sec.)
\n
"
,
context
->
Ebx
);
SET_CFLAG
(
context
);
break
;
case
0x0107
:
/* get version of any VxD */
default:
VXD_BARF
(
context
,
"SHELL"
);
break
;
}
}
/***********************************************************************
* VXD_Comm (WPROCS.414)
*/
void
WINAPI
VXD_Comm
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] Comm
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* get version */
TRACE
(
"returning version
\n
"
);
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x0001
:
/* set port global */
case
0x0002
:
/* get focus */
case
0x0003
:
/* virtualise port */
default:
VXD_BARF
(
context
,
"comm"
);
}
}
/***********************************************************************
* VXD_Timer (WPROCS.405)
*/
void
WINAPI
VXD_Timer
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] Virtual Timer
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x0100
:
/* clock tick time, in 840nsecs */
context
->
Eax
=
GetTickCount
();
context
->
Edx
=
context
->
Eax
>>
22
;
context
->
Eax
<<=
10
;
/* not very precise */
break
;
case
0x0101
:
/* current Windows time, msecs */
case
0x0102
:
/* current VM time, msecs */
context
->
Eax
=
GetTickCount
();
break
;
default:
VXD_BARF
(
context
,
"VTD"
);
}
}
/***********************************************************************
* timer_thread
*/
static
DWORD
CALLBACK
timer_thread
(
void
*
arg
)
{
DWORD
*
system_time
=
arg
;
for
(;;)
{
*
system_time
=
GetTickCount
();
Sleep
(
55
);
}
return
0
;
}
/***********************************************************************
* VXD_TimerAPI (WPROCS.1490)
*/
void
WINAPI
VXD_TimerAPI
(
CONTEXT86
*
context
)
{
static
WORD
System_Time_Selector
;
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] TimerAPI
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
case
0x0009
:
/* get system time selector */
if
(
!
System_Time_Selector
)
{
HANDLE16
handle
=
GlobalAlloc16
(
GMEM_FIXED
,
sizeof
(
DWORD
)
);
System_Time_Selector
=
handle
|
7
;
CloseHandle
(
CreateThread
(
NULL
,
0
,
timer_thread
,
GlobalLock16
(
handle
),
0
,
NULL
)
);
}
SET_AX
(
context
,
System_Time_Selector
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"VTDAPI"
);
}
}
/***********************************************************************
* VXD_ConfigMG (WPROCS.451)
*/
void
WINAPI
VXD_ConfigMG
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] ConfigMG
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"CONFIGMG"
);
}
}
/***********************************************************************
* VXD_Enable (WPROCS.455)
*/
void
WINAPI
VXD_Enable
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] Enable
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"ENABLE"
);
}
}
/***********************************************************************
* VXD_APM (WPROCS.438)
*/
void
WINAPI
VXD_APM
(
CONTEXT86
*
context
)
{
unsigned
service
=
AX_reg
(
context
);
TRACE
(
"[%04x] APM
\n
"
,
(
UINT16
)
service
);
switch
(
service
)
{
case
0x0000
:
/* version */
SET_AX
(
context
,
VXD_WinVersion
()
);
RESET_CFLAG
(
context
);
break
;
default:
VXD_BARF
(
context
,
"APM"
);
}
}
/***********************************************************************
* VXD_Win32s (WPROCS.445)
*
* This is an implementation of the services of the Win32s VxD.
* Since official documentation of these does not seem to be available,
* certain arguments of some of the services remain unclear.
*
* FIXME: The following services are currently unimplemented:
* Exception handling (0x01, 0x1C)
* Debugger support (0x0C, 0x14, 0x17)
* Low-level memory access (0x02, 0x03, 0x0A, 0x0B)
* Memory Statistics (0x1B)
*
*
* We have a specific problem running Win32s on Linux (and probably also
* the other x86 unixes), since Win32s tries to allocate its main 'flat
* code/data segment' selectors with a base of 0xffff0000 (and limit 4GB).
* The rationale for this seems to be that they want one the one hand to
* be able to leave the Win 3.1 memory (starting with the main DOS memory)
* at linear address 0, but want at other hand to have offset 0 of the
* flat data/code segment point to an unmapped page (to catch NULL pointer
* accesses). Hence they allocate the flat segments with a base of 0xffff0000
* so that the Win 3.1 memory area at linear address zero shows up in the
* flat segments at offset 0x10000 (since linear addresses wrap around at
* 4GB). To compensate for that discrepancy between flat segment offsets
* and plain linear addresses, all flat pointers passed between the 32-bit
* and the 16-bit parts of Win32s are shifted by 0x10000 in the appropriate
* direction by the glue code (mainly) in W32SKRNL and WIN32S16.
*
* The problem for us is now that Linux does not allow a LDT selector with
* base 0xffff0000 to be created, since it would 'see' a part of the kernel
* address space. To address this problem we introduce *another* offset:
* We add 0x10000 to every linear address we get as an argument from Win32s.
* This means especially that the flat code/data selectors get actually
* allocated with base 0x0, so that flat offsets and (real) linear addresses
* do again agree! In fact, every call e.g. of a Win32s VxD service now
* has all pointer arguments (which are offsets in the flat data segment)
* first reduced by 0x10000 by the W32SKRNL glue code, and then again
* increased by 0x10000 by *our* code.
*
* Note that to keep everything consistent, this offset has to be applied by
* every Wine function that operates on 'linear addresses' passed to it by
* Win32s. Fortunately, since Win32s does not directly call any Wine 32-bit
* API routines, this affects only two locations: this VxD and the DPMI
* handler. (NOTE: Should any Win32s application pass a linear address to
* any routine apart from those, e.g. some other VxD handler, that code
* would have to take the offset into account as well!)
*
* The offset is set the first time any application calls the GetVersion()
* service of the Win32s VxD. (Note that the offset is never reset.)
*
*/
void
WINAPI
VXD_Win32s
(
CONTEXT86
*
context
)
{
switch
(
AX_reg
(
context
))
{
case
0x0000
:
/* Get Version */
/*
* Input: None
*
* Output: EAX: LoWord: Win32s Version (1.30)
* HiWord: VxD Version (200)
*
* EBX: Build (172)
*
* ECX: ??? (1)
*
* EDX: Debugging Flags
*
* EDI: Error Flag
* 0 if OK,
* 1 if VMCPD VxD not found
*/
TRACE
(
"GetVersion()
\n
"
);
context
->
Eax
=
VXD_WinVersion
()
|
(
200
<<
16
);
context
->
Ebx
=
0
;
context
->
Ecx
=
0
;
context
->
Edx
=
0
;
context
->
Edi
=
0
;
/*
* If this is the first time we are called for this process,
* hack the memory image of WIN32S16 so that it doesn't try
* to access the GDT directly ...
*
* The first code segment of WIN32S16 (version 1.30) contains
* an unexported function somewhere between the exported functions
* SetFS and StackLinearToSegmented that tries to find a selector
* in the LDT that maps to the memory image of the LDT itself.
* If it succeeds, it stores this selector into a global variable
* which will be used to speed up execution by using this selector
* to modify the LDT directly instead of using the DPMI calls.
*
* To perform this search of the LDT, this function uses the
* sgdt and sldt instructions to find the linear address of
* the (GDT and then) LDT. While those instructions themselves
* execute without problem, the linear address that sgdt returns
* points (at least under Linux) to the kernel address space, so
* that any subsequent access leads to a segfault.
*
* Fortunately, WIN32S16 still contains as a fallback option the
* mechanism of using DPMI calls to modify LDT selectors instead
* of direct writes to the LDT. Thus we can circumvent the problem
* by simply replacing the first byte of the offending function
* with an 'retf' instruction. This means that the global variable
* supposed to contain the LDT alias selector will remain zero,
* and hence WIN32S16 will fall back to using DPMI calls.
*
* The heuristic we employ to _find_ that function is as follows:
* We search between the addresses of the exported symbols SetFS
* and StackLinearToSegmented for the byte sequence '0F 01 04'
* (this is the opcode of 'sgdt [si]'). We then search backwards
* from this address for the last occurrence of 'CB' (retf) that marks
* the end of the preceding function. The following byte (which
* should now be the first byte of the function we are looking for)
* will be replaced by 'CB' (retf).
*
* This heuristic works for the retail as well as the debug version
* of Win32s version 1.30. For versions earlier than that this
* hack should not be necessary at all, since the whole mechanism
* ('PERF130') was introduced only in 1.30 to improve the overall
* performance of Win32s.
*/
if
(
!
W32S_offset
)
{
HMODULE16
hModule
=
GetModuleHandle16
(
"win32s16"
);
SEGPTR
func1
=
(
SEGPTR
)
GetProcAddress16
(
hModule
,
"SetFS"
);
SEGPTR
func2
=
(
SEGPTR
)
GetProcAddress16
(
hModule
,
"StackLinearToSegmented"
);
if
(
hModule
&&
func1
&&
func2
&&
SELECTOROF
(
func1
)
==
SELECTOROF
(
func2
))
{
BYTE
*
start
=
MapSL
(
func1
);
BYTE
*
end
=
MapSL
(
func2
);
BYTE
*
p
,
*
retv
=
NULL
;
int
found
=
0
;
for
(
p
=
start
;
p
<
end
;
p
++
)
if
(
*
p
==
0xCB
)
found
=
0
,
retv
=
p
;
else
if
(
*
p
==
0x0F
)
found
=
1
;
else
if
(
*
p
==
0x01
&&
found
==
1
)
found
=
2
;
else
if
(
*
p
==
0x04
&&
found
==
2
)
{
found
=
3
;
break
;
}
else
found
=
0
;
if
(
found
==
3
&&
retv
)
{
TRACE
(
"PERF130 hack: "
"Replacing byte %02X at offset %04X:%04X
\n
"
,
*
(
retv
+
1
),
SELECTOROF
(
func1
),
OFFSETOF
(
func1
)
+
retv
+
1
-
start
);
*
(
retv
+
1
)
=
(
BYTE
)
0xCB
;
}
}
}
/*
* Mark process as Win32s, so that subsequent DPMI calls
* will perform the W32S_APP2WINE/W32S_WINE2APP address shift.
*/
W32S_offset
=
0x10000
;
break
;
case
0x0001
:
/* Install Exception Handling */
/*
* Input: EBX: Flat address of W32SKRNL Exception Data
*
* ECX: LoWord: Flat Code Selector
* HiWord: Flat Data Selector
*
* EDX: Flat address of W32SKRNL Exception Handler
* (this is equal to W32S_BackTo32 + 0x40)
*
* ESI: SEGPTR KERNEL.HASGPHANDLER
*
* EDI: SEGPTR phCurrentTask (KERNEL.THHOOK + 0x10)
*
* Output: EAX: 0 if OK
*/
TRACE
(
"[0001] EBX=%x ECX=%x EDX=%x ESI=%x EDI=%x
\n
"
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
,
context
->
Esi
,
context
->
Edi
);
/* FIXME */
context
->
Eax
=
0
;
break
;
case
0x0002
:
/* Set Page Access Flags */
/*
* Input: EBX: New access flags
* Bit 2: User Page if set, Supervisor Page if clear
* Bit 1: Read-Write if set, Read-Only if clear
*
* ECX: Size of memory area to change
*
* EDX: Flat start address of memory area
*
* Output: EAX: Size of area changed
*/
TRACE
(
"[0002] EBX=%x ECX=%x EDX=%x
\n
"
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
);
/* FIXME */
context
->
Eax
=
context
->
Ecx
;
break
;
case
0x0003
:
/* Get Page Access Flags */
/*
* Input: EDX: Flat address of page to query
*
* Output: EAX: Page access flags
* Bit 2: User Page if set, Supervisor Page if clear
* Bit 1: Read-Write if set, Read-Only if clear
*/
TRACE
(
"[0003] EDX=%x
\n
"
,
context
->
Edx
);
/* FIXME */
context
->
Eax
=
6
;
break
;
case
0x0004
:
/* Map Module */
/*
* Input: ECX: IMTE (offset in Module Table) of new module
*
* EDX: Flat address of Win32s Module Table
*
* Output: EAX: 0 if OK
*/
if
(
!
context
->
Edx
||
CX_reg
(
context
)
==
0xFFFF
)
{
TRACE
(
"MapModule: Initialization call
\n
"
);
context
->
Eax
=
0
;
}
else
{
/*
* Structure of a Win32s Module Table Entry:
*/
struct
Win32sModule
{
DWORD
flags
;
DWORD
flatBaseAddr
;
LPCSTR
moduleName
;
LPCSTR
pathName
;
LPCSTR
unknown
;
LPBYTE
baseAddr
;
DWORD
hModule
;
DWORD
relocDelta
;
};
/*
* Note: This function should set up a demand-paged memory image
* of the given module. Since mmap does not allow file offsets
* not aligned at 1024 bytes, we simply load the image fully
* into memory.
*/
struct
Win32sModule
*
moduleTable
=
(
struct
Win32sModule
*
)
W32S_APP2WINE
(
context
->
Edx
);
struct
Win32sModule
*
module
=
moduleTable
+
context
->
Ecx
;
IMAGE_NT_HEADERS
*
nt_header
=
RtlImageNtHeader
(
(
HMODULE
)
module
->
baseAddr
);
IMAGE_SECTION_HEADER
*
pe_seg
=
(
IMAGE_SECTION_HEADER
*
)((
char
*
)
&
nt_header
->
OptionalHeader
+
nt_header
->
FileHeader
.
SizeOfOptionalHeader
);
HFILE
image
=
_lopen
(
module
->
pathName
,
OF_READ
);
BOOL
error
=
(
image
==
HFILE_ERROR
);
UINT
i
;
TRACE
(
"MapModule: Loading %s
\n
"
,
module
->
pathName
);
for
(
i
=
0
;
!
error
&&
i
<
nt_header
->
FileHeader
.
NumberOfSections
;
i
++
,
pe_seg
++
)
if
(
!
(
pe_seg
->
Characteristics
&
IMAGE_SCN_CNT_UNINITIALIZED_DATA
))
{
DWORD
off
=
pe_seg
->
PointerToRawData
;
DWORD
len
=
pe_seg
->
SizeOfRawData
;
LPBYTE
addr
=
module
->
baseAddr
+
pe_seg
->
VirtualAddress
;
TRACE
(
"MapModule: "
"Section %d at %08x from %08x len %08x
\n
"
,
i
,
(
DWORD
)
addr
,
off
,
len
);
if
(
_llseek
(
image
,
off
,
SEEK_SET
)
!=
off
||
_lread
(
image
,
addr
,
len
)
!=
len
)
error
=
TRUE
;
}
_lclose
(
image
);
if
(
error
)
ERR
(
"MapModule: Unable to load %s
\n
"
,
module
->
pathName
);
else
if
(
module
->
relocDelta
!=
0
)
{
IMAGE_DATA_DIRECTORY
*
dir
=
nt_header
->
OptionalHeader
.
DataDirectory
+
IMAGE_DIRECTORY_ENTRY_BASERELOC
;
IMAGE_BASE_RELOCATION
*
r
=
(
IMAGE_BASE_RELOCATION
*
)
(
dir
->
Size
?
module
->
baseAddr
+
dir
->
VirtualAddress
:
0
);
TRACE
(
"MapModule: Reloc delta %08x
\n
"
,
module
->
relocDelta
);
while
(
r
&&
r
->
VirtualAddress
)
{
LPBYTE
page
=
module
->
baseAddr
+
r
->
VirtualAddress
;
WORD
*
TypeOffset
=
(
WORD
*
)(
r
+
1
);
unsigned
int
count
=
(
r
->
SizeOfBlock
-
sizeof
(
*
r
))
/
sizeof
(
*
TypeOffset
);
TRACE
(
"MapModule: %d relocations for page %08x
\n
"
,
count
,
(
DWORD
)
page
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
int
offset
=
TypeOffset
[
i
]
&
0xFFF
;
int
type
=
TypeOffset
[
i
]
>>
12
;
switch
(
type
)
{
case
IMAGE_REL_BASED_ABSOLUTE
:
break
;
case
IMAGE_REL_BASED_HIGH
:
*
(
WORD
*
)(
page
+
offset
)
+=
HIWORD
(
module
->
relocDelta
);
break
;
case
IMAGE_REL_BASED_LOW
:
*
(
WORD
*
)(
page
+
offset
)
+=
LOWORD
(
module
->
relocDelta
);
break
;
case
IMAGE_REL_BASED_HIGHLOW
:
*
(
DWORD
*
)(
page
+
offset
)
+=
module
->
relocDelta
;
break
;
default:
WARN
(
"MapModule: Unsupported fixup type
\n
"
);
break
;
}
}
r
=
(
IMAGE_BASE_RELOCATION
*
)((
LPBYTE
)
r
+
r
->
SizeOfBlock
);
}
}
context
->
Eax
=
0
;
RESET_CFLAG
(
context
);
}
break
;
case
0x0005
:
/* UnMap Module */
/*
* Input: EDX: Flat address of module image
*
* Output: EAX: 1 if OK
*/
TRACE
(
"UnMapModule: %x
\n
"
,
W32S_APP2WINE
(
context
->
Edx
));
/* As we didn't map anything, there's nothing to unmap ... */
context
->
Eax
=
1
;
break
;
case
0x0006
:
/* VirtualAlloc */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] Flat base address of allocated region
* LPVOID base [in] Flat address of region to reserve/commit
* DWORD size [in] Size of region
* DWORD type [in] Type of allocation
* DWORD prot [in] Type of access protection
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
type
=
stack
[
3
];
DWORD
prot
=
stack
[
4
];
DWORD
result
;
TRACE
(
"VirtualAlloc(%x, %x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
,
type
,
prot
);
if
(
type
&
0x80000000
)
{
WARN
(
"VirtualAlloc: strange type %x
\n
"
,
type
);
type
&=
0x7fffffff
;
}
if
(
!
base
&&
(
type
&
MEM_COMMIT
)
&&
prot
==
PAGE_READONLY
)
{
WARN
(
"VirtualAlloc: NLS hack, allowing write access!
\n
"
);
prot
=
PAGE_READWRITE
;
}
result
=
(
DWORD
)
VirtualAlloc
(
base
,
size
,
type
,
prot
);
if
(
W32S_WINE2APP
(
result
))
*
retv
=
W32S_WINE2APP
(
result
),
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
0
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0007
:
/* VirtualFree */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] TRUE if success, FALSE if failure
* LPVOID base [in] Flat address of region
* DWORD size [in] Size of region
* DWORD type [in] Type of operation
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
type
=
stack
[
3
];
DWORD
result
;
TRACE
(
"VirtualFree(%x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
,
type
);
result
=
VirtualFree
(
base
,
size
,
type
);
if
(
result
)
*
retv
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0008
:
/* VirtualProtect */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] TRUE if success, FALSE if failure
* LPVOID base [in] Flat address of region
* DWORD size [in] Size of region
* DWORD new_prot [in] Desired access protection
* DWORD *old_prot [out] Previous access protection
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
new_prot
=
stack
[
3
];
DWORD
*
old_prot
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
4
]);
DWORD
result
;
TRACE
(
"VirtualProtect(%x, %x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
,
new_prot
,
(
DWORD
)
old_prot
);
result
=
VirtualProtect
(
base
,
size
,
new_prot
,
old_prot
);
if
(
result
)
*
retv
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0009
:
/* VirtualQuery */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] Nr. bytes returned
* LPVOID base [in] Flat address of region
* LPMEMORY_BASIC_INFORMATION info [out] Info buffer
* DWORD len [in] Size of buffer
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
PMEMORY_BASIC_INFORMATION
info
=
(
PMEMORY_BASIC_INFORMATION
)
W32S_APP2WINE
(
stack
[
2
]);
DWORD
len
=
stack
[
3
];
DWORD
result
;
TRACE
(
"VirtualQuery(%x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
(
DWORD
)
info
,
len
);
result
=
VirtualQuery
(
base
,
info
,
len
);
*
retv
=
result
;
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x000A
:
/* SetVirtMemProcess */
/*
* Input: ECX: Process Handle
*
* EDX: Flat address of region
*
* Output: EAX: NtStatus
*/
TRACE
(
"[000a] ECX=%x EDX=%x
\n
"
,
context
->
Ecx
,
context
->
Edx
);
/* FIXME */
context
->
Eax
=
STATUS_SUCCESS
;
break
;
case
0x000B
:
/* ??? some kind of cleanup */
/*
* Input: ECX: Process Handle
*
* Output: EAX: NtStatus
*/
TRACE
(
"[000b] ECX=%x
\n
"
,
context
->
Ecx
);
/* FIXME */
context
->
Eax
=
STATUS_SUCCESS
;
break
;
case
0x000C
:
/* Set Debug Flags */
/*
* Input: EDX: Debug Flags
*
* Output: EDX: Previous Debug Flags
*/
FIXME
(
"[000c] EDX=%x
\n
"
,
context
->
Edx
);
/* FIXME */
context
->
Edx
=
0
;
break
;
case
0x000D
:
/* NtCreateSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 *retv [out] Handle of Section created
* DWORD flags1 [in] (?? unknown ??)
* DWORD atom [in] Name of Section to create
* LARGE_INTEGER *size [in] Size of Section
* DWORD protect [in] Access protection
* DWORD flags2 [in] (?? unknown ??)
* HFILE32 hFile [in] Handle of file to map
* DWORD psp [in] (Win32s: PSP that hFile belongs to)
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
*
retv
=
(
HANDLE
*
)
W32S_APP2WINE
(
stack
[
0
]);
DWORD
flags1
=
stack
[
1
];
DWORD
atom
=
stack
[
2
];
LARGE_INTEGER
*
size
=
(
LARGE_INTEGER
*
)
W32S_APP2WINE
(
stack
[
3
]);
DWORD
protect
=
stack
[
4
];
DWORD
flags2
=
stack
[
5
];
HANDLE
hFile
=
DosFileHandleToWin32Handle
(
stack
[
6
]);
DWORD
psp
=
stack
[
7
];
HANDLE
result
=
INVALID_HANDLE_VALUE
;
char
name
[
128
];
TRACE
(
"NtCreateSection(%x, %x, %x, %x, %x, %x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
flags1
,
atom
,
(
DWORD
)
size
,
protect
,
flags2
,
(
DWORD
)
hFile
,
psp
);
if
(
!
atom
||
GlobalGetAtomNameA
(
atom
,
name
,
sizeof
(
name
)))
{
TRACE
(
"NtCreateSection: name=%s
\n
"
,
atom
?
name
:
NULL
);
result
=
CreateFileMappingA
(
hFile
,
NULL
,
protect
,
size
?
size
->
u
.
HighPart
:
0
,
size
?
size
->
u
.
LowPart
:
0
,
atom
?
name
:
NULL
);
}
if
(
result
==
INVALID_HANDLE_VALUE
)
WARN
(
"NtCreateSection: failed!
\n
"
);
else
TRACE
(
"NtCreateSection: returned %x
\n
"
,
(
DWORD
)
result
);
if
(
result
!=
INVALID_HANDLE_VALUE
)
*
retv
=
result
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
result
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x000E
:
/* NtOpenSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 *retv [out] Handle of Section opened
* DWORD protect [in] Access protection
* DWORD atom [in] Name of Section to create
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
*
retv
=
(
HANDLE
*
)
W32S_APP2WINE
(
stack
[
0
]);
DWORD
protect
=
stack
[
1
];
DWORD
atom
=
stack
[
2
];
HANDLE
result
=
INVALID_HANDLE_VALUE
;
char
name
[
128
];
TRACE
(
"NtOpenSection(%x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
protect
,
atom
);
if
(
atom
&&
GlobalGetAtomNameA
(
atom
,
name
,
sizeof
(
name
)))
{
TRACE
(
"NtOpenSection: name=%s
\n
"
,
name
);
result
=
OpenFileMappingA
(
protect
,
FALSE
,
name
);
}
if
(
result
==
INVALID_HANDLE_VALUE
)
WARN
(
"NtOpenSection: failed!
\n
"
);
else
TRACE
(
"NtOpenSection: returned %x
\n
"
,
(
DWORD
)
result
);
if
(
result
!=
INVALID_HANDLE_VALUE
)
*
retv
=
result
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
result
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x000F
:
/* NtCloseSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 handle [in] Handle of Section to close
* DWORD *id [out] Unique ID (?? unclear ??)
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
handle
=
(
HANDLE
)
stack
[
0
];
DWORD
*
id
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
1
]);
TRACE
(
"NtCloseSection(%x, %x)
\n
"
,
(
DWORD
)
handle
,
(
DWORD
)
id
);
CloseHandle
(
handle
);
if
(
id
)
*
id
=
0
;
/* FIXME */
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x0010
:
/* NtDupSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 handle [in] Handle of Section to duplicate
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
handle
=
(
HANDLE
)
stack
[
0
];
HANDLE
new_handle
;
TRACE
(
"NtDupSection(%x)
\n
"
,
(
DWORD
)
handle
);
DuplicateHandle
(
GetCurrentProcess
(),
handle
,
GetCurrentProcess
(),
&
new_handle
,
0
,
FALSE
,
DUPLICATE_SAME_ACCESS
);
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x0011
:
/* NtMapViewOfSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* HANDLE32 SectionHandle [in] Section to be mapped
* DWORD ProcessHandle [in] Process to be mapped into
* DWORD * BaseAddress [in/out] Address to be mapped at
* DWORD ZeroBits [in] (?? unclear ??)
* DWORD CommitSize [in] (?? unclear ??)
* LARGE_INTEGER *SectionOffset [in] Offset within section
* DWORD * ViewSize [in] Size of view
* DWORD InheritDisposition [in] (?? unclear ??)
* DWORD AllocationType [in] (?? unclear ??)
* DWORD Protect [in] Access protection
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
HANDLE
SectionHandle
=
(
HANDLE
)
stack
[
0
];
DWORD
ProcessHandle
=
stack
[
1
];
/* ignored */
DWORD
*
BaseAddress
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
2
]);
DWORD
ZeroBits
=
stack
[
3
];
DWORD
CommitSize
=
stack
[
4
];
LARGE_INTEGER
*
SectionOffset
=
(
LARGE_INTEGER
*
)
W32S_APP2WINE
(
stack
[
5
]);
DWORD
*
ViewSize
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
6
]);
DWORD
InheritDisposition
=
stack
[
7
];
DWORD
AllocationType
=
stack
[
8
];
DWORD
Protect
=
stack
[
9
];
LPBYTE
address
=
(
LPBYTE
)(
BaseAddress
?
W32S_APP2WINE
(
*
BaseAddress
)
:
0
);
DWORD
access
=
0
,
result
;
switch
(
Protect
&
~
(
PAGE_GUARD
|
PAGE_NOCACHE
))
{
case
PAGE_READONLY
:
access
=
FILE_MAP_READ
;
break
;
case
PAGE_READWRITE
:
access
=
FILE_MAP_WRITE
;
break
;
case
PAGE_WRITECOPY
:
access
=
FILE_MAP_COPY
;
break
;
case
PAGE_EXECUTE_READ
:
access
=
FILE_MAP_READ
;
break
;
case
PAGE_EXECUTE_READWRITE
:
access
=
FILE_MAP_WRITE
;
break
;
case
PAGE_EXECUTE_WRITECOPY
:
access
=
FILE_MAP_COPY
;
break
;
}
TRACE
(
"NtMapViewOfSection"
"(%x, %x, %x, %x, %x, %x, %x, %x, %x, %x)
\n
"
,
(
DWORD
)
SectionHandle
,
ProcessHandle
,
(
DWORD
)
BaseAddress
,
ZeroBits
,
CommitSize
,
(
DWORD
)
SectionOffset
,
(
DWORD
)
ViewSize
,
InheritDisposition
,
AllocationType
,
Protect
);
TRACE
(
"NtMapViewOfSection: "
"base=%x, offset=%x, size=%x, access=%x
\n
"
,
(
DWORD
)
address
,
SectionOffset
?
SectionOffset
->
u
.
LowPart
:
0
,
ViewSize
?
*
ViewSize
:
0
,
access
);
result
=
(
DWORD
)
MapViewOfFileEx
(
SectionHandle
,
access
,
SectionOffset
?
SectionOffset
->
u
.
HighPart
:
0
,
SectionOffset
?
SectionOffset
->
u
.
LowPart
:
0
,
ViewSize
?
*
ViewSize
:
0
,
address
);
TRACE
(
"NtMapViewOfSection: result=%x
\n
"
,
result
);
if
(
W32S_WINE2APP
(
result
))
{
if
(
BaseAddress
)
*
BaseAddress
=
W32S_WINE2APP
(
result
);
context
->
Eax
=
STATUS_SUCCESS
;
}
else
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0012
:
/* NtUnmapViewOfSection */
/*
* Input: EDX: Flat address of arguments on stack
*
* DWORD ProcessHandle [in] Process (defining address space)
* LPBYTE BaseAddress [in] Base address of view to be unmapped
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
ProcessHandle
=
stack
[
0
];
/* ignored */
LPBYTE
BaseAddress
=
(
LPBYTE
)
W32S_APP2WINE
(
stack
[
1
]);
TRACE
(
"NtUnmapViewOfSection(%x, %x)
\n
"
,
ProcessHandle
,
(
DWORD
)
BaseAddress
);
UnmapViewOfFile
(
BaseAddress
);
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x0013
:
/* NtFlushVirtualMemory */
/*
* Input: EDX: Flat address of arguments on stack
*
* DWORD ProcessHandle [in] Process (defining address space)
* LPBYTE *BaseAddress [in?] Base address of range to be flushed
* DWORD *ViewSize [in?] Number of bytes to be flushed
* DWORD *unknown [???] (?? unknown ??)
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
ProcessHandle
=
stack
[
0
];
/* ignored */
DWORD
*
BaseAddress
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
*
ViewSize
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
2
]);
DWORD
*
unknown
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
3
]);
LPBYTE
address
=
(
LPBYTE
)(
BaseAddress
?
W32S_APP2WINE
(
*
BaseAddress
)
:
0
);
DWORD
size
=
ViewSize
?
*
ViewSize
:
0
;
TRACE
(
"NtFlushVirtualMemory(%x, %x, %x, %x)
\n
"
,
ProcessHandle
,
(
DWORD
)
BaseAddress
,
(
DWORD
)
ViewSize
,
(
DWORD
)
unknown
);
TRACE
(
"NtFlushVirtualMemory: base=%x, size=%x
\n
"
,
(
DWORD
)
address
,
size
);
FlushViewOfFile
(
address
,
size
);
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
case
0x0014
:
/* Get/Set Debug Registers */
/*
* Input: ECX: 0 if Get, 1 if Set
*
* EDX: Get: Flat address of buffer to receive values of
* debug registers DR0 .. DR7
* Set: Flat address of buffer containing values of
* debug registers DR0 .. DR7 to be set
* Output: None
*/
FIXME
(
"[0014] ECX=%x EDX=%x
\n
"
,
context
->
Ecx
,
context
->
Edx
);
/* FIXME */
break
;
case
0x0015
:
/* Set Coprocessor Emulation Flag */
/*
* Input: EDX: 0 to deactivate, 1 to activate coprocessor emulation
*
* Output: None
*/
TRACE
(
"[0015] EDX=%x
\n
"
,
context
->
Edx
);
/* We don't care, as we always have a coprocessor anyway */
break
;
case
0x0016
:
/* Init Win32S VxD PSP */
/*
* If called to query required PSP size:
*
* Input: EBX: 0
* Output: EDX: Required size of Win32s VxD PSP
*
* If called to initialize allocated PSP:
*
* Input: EBX: LoWord: Selector of Win32s VxD PSP
* HiWord: Paragraph of Win32s VxD PSP (DOSMEM)
* Output: None
*/
if
(
context
->
Ebx
==
0
)
context
->
Edx
=
0x80
;
else
{
PDB16
*
psp
=
MapSL
(
MAKESEGPTR
(
BX_reg
(
context
),
0
));
psp
->
nbFiles
=
32
;
psp
->
fileHandlesPtr
=
MAKELONG
(
HIWORD
(
context
->
Ebx
),
0x5c
);
memset
((
LPBYTE
)
psp
+
0x5c
,
'\xFF'
,
32
);
}
break
;
case
0x0017
:
/* Set Break Point */
/*
* Input: EBX: Offset of Break Point
* CX: Selector of Break Point
*
* Output: None
*/
FIXME
(
"[0017] EBX=%x CX=%x
\n
"
,
context
->
Ebx
,
CX_reg
(
context
));
/* FIXME */
break
;
case
0x0018
:
/* VirtualLock */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] TRUE if success, FALSE if failure
* LPVOID base [in] Flat address of range to lock
* DWORD size [in] Size of range
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
result
;
TRACE
(
"VirtualLock(%x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
);
result
=
VirtualLock
(
base
,
size
);
if
(
result
)
*
retv
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x0019
:
/* VirtualUnlock */
/*
* Input: ECX: Current Process
*
* EDX: Flat address of arguments on stack
*
* DWORD *retv [out] TRUE if success, FALSE if failure
* LPVOID base [in] Flat address of range to unlock
* DWORD size [in] Size of range
*
* Output: EAX: NtStatus
*/
{
DWORD
*
stack
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Edx
);
DWORD
*
retv
=
(
DWORD
*
)
W32S_APP2WINE
(
stack
[
0
]);
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
1
]);
DWORD
size
=
stack
[
2
];
DWORD
result
;
TRACE
(
"VirtualUnlock(%x, %x, %x)
\n
"
,
(
DWORD
)
retv
,
(
DWORD
)
base
,
size
);
result
=
VirtualUnlock
(
base
,
size
);
if
(
result
)
*
retv
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
*
retv
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x001A
:
/* KGetSystemInfo */
/*
* Input: None
*
* Output: ECX: Start of sparse memory arena
* EDX: End of sparse memory arena
*/
TRACE
(
"KGetSystemInfo()
\n
"
);
/*
* Note: Win32s reserves 0GB - 2GB for Win 3.1 and uses 2GB - 4GB as
* sparse memory arena. We do it the other way around, since
* we have to reserve 3GB - 4GB for Linux, and thus use
* 0GB - 3GB as sparse memory arena.
*
* FIXME: What about other OSes ?
*/
context
->
Ecx
=
W32S_WINE2APP
(
0x00000000
);
context
->
Edx
=
W32S_WINE2APP
(
0xbfffffff
);
break
;
case
0x001B
:
/* KGlobalMemStat */
/*
* Input: ESI: Flat address of buffer to receive memory info
*
* Output: None
*/
{
struct
Win32sMemoryInfo
{
DWORD
DIPhys_Count
;
/* Total physical pages */
DWORD
DIFree_Count
;
/* Free physical pages */
DWORD
DILin_Total_Count
;
/* Total virtual pages (private arena) */
DWORD
DILin_Total_Free
;
/* Free virtual pages (private arena) */
DWORD
SparseTotal
;
/* Total size of sparse arena (bytes ?) */
DWORD
SparseFree
;
/* Free size of sparse arena (bytes ?) */
};
struct
Win32sMemoryInfo
*
info
=
(
struct
Win32sMemoryInfo
*
)
W32S_APP2WINE
(
context
->
Esi
);
FIXME
(
"KGlobalMemStat(%x)
\n
"
,
(
DWORD
)
info
);
/* FIXME */
}
break
;
case
0x001C
:
/* Enable/Disable Exceptions */
/*
* Input: ECX: 0 to disable, 1 to enable exception handling
*
* Output: None
*/
TRACE
(
"[001c] ECX=%x
\n
"
,
context
->
Ecx
);
/* FIXME */
break
;
case
0x001D
:
/* VirtualAlloc called from 16-bit code */
/*
* Input: EDX: Segmented address of arguments on stack
*
* LPVOID base [in] Flat address of region to reserve/commit
* DWORD size [in] Size of region
* DWORD type [in] Type of allocation
* DWORD prot [in] Type of access protection
*
* Output: EAX: NtStatus
* EDX: Flat base address of allocated region
*/
{
DWORD
*
stack
=
MapSL
(
MAKESEGPTR
(
LOWORD
(
context
->
Edx
),
HIWORD
(
context
->
Edx
)
));
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
0
]);
DWORD
size
=
stack
[
1
];
DWORD
type
=
stack
[
2
];
DWORD
prot
=
stack
[
3
];
DWORD
result
;
TRACE
(
"VirtualAlloc16(%x, %x, %x, %x)
\n
"
,
(
DWORD
)
base
,
size
,
type
,
prot
);
if
(
type
&
0x80000000
)
{
WARN
(
"VirtualAlloc16: strange type %x
\n
"
,
type
);
type
&=
0x7fffffff
;
}
result
=
(
DWORD
)
VirtualAlloc
(
base
,
size
,
type
,
prot
);
if
(
W32S_WINE2APP
(
result
))
context
->
Edx
=
W32S_WINE2APP
(
result
),
context
->
Eax
=
STATUS_SUCCESS
;
else
context
->
Edx
=
0
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
TRACE
(
"VirtualAlloc16: returning base %x
\n
"
,
context
->
Edx
);
}
break
;
case
0x001E
:
/* VirtualFree called from 16-bit code */
/*
* Input: EDX: Segmented address of arguments on stack
*
* LPVOID base [in] Flat address of region
* DWORD size [in] Size of region
* DWORD type [in] Type of operation
*
* Output: EAX: NtStatus
* EDX: TRUE if success, FALSE if failure
*/
{
DWORD
*
stack
=
MapSL
(
MAKESEGPTR
(
LOWORD
(
context
->
Edx
),
HIWORD
(
context
->
Edx
)
));
LPVOID
base
=
(
LPVOID
)
W32S_APP2WINE
(
stack
[
0
]);
DWORD
size
=
stack
[
1
];
DWORD
type
=
stack
[
2
];
DWORD
result
;
TRACE
(
"VirtualFree16(%x, %x, %x)
\n
"
,
(
DWORD
)
base
,
size
,
type
);
result
=
VirtualFree
(
base
,
size
,
type
);
if
(
result
)
context
->
Edx
=
TRUE
,
context
->
Eax
=
STATUS_SUCCESS
;
else
context
->
Edx
=
FALSE
,
context
->
Eax
=
STATUS_NO_MEMORY
;
/* FIXME */
}
break
;
case
0x001F
:
/* FWorkingSetSize */
/*
* Input: EDX: 0 if Get, 1 if Set
*
* ECX: Get: Buffer to receive Working Set Size
* Set: Buffer containing Working Set Size
*
* Output: NtStatus
*/
{
DWORD
*
ptr
=
(
DWORD
*
)
W32S_APP2WINE
(
context
->
Ecx
);
BOOL
set
=
context
->
Edx
;
TRACE
(
"FWorkingSetSize(%x, %x)
\n
"
,
(
DWORD
)
ptr
,
(
DWORD
)
set
);
if
(
set
)
/* We do it differently ... */
;
else
*
ptr
=
0x100
;
context
->
Eax
=
STATUS_SUCCESS
;
}
break
;
default:
VXD_BARF
(
context
,
"W32S"
);
}
}
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