[PATCH 2/2] Moving wprocs.dll16 out of winedos
Eric Pouech
eric.pouech at orange.fr
Sun Oct 18 06:23:07 CDT 2009
A+
---
.gitignore | 1
configure | 15
configure.ac | 1
dlls/Makefile.in | 6
dlls/winedos/Makefile.in | 3
dlls/winedos/vxd.c | 1718 -----------------------------------
dlls/winedos/wprocs.spec | 19
dlls/wprocs.dll16/Makefile.in | 15
dlls/wprocs.dll16/vxd.c | 1718 +++++++++++++++++++++++++++++++++++
dlls/wprocs.dll16/wprocs.dll16.spec | 19
10 files changed, 1766 insertions(+), 1749 deletions(-)
delete mode 100644 dlls/winedos/vxd.c
delete mode 100644 dlls/winedos/wprocs.spec
create mode 100644 dlls/wprocs.dll16/Makefile.in
create mode 100644 dlls/wprocs.dll16/vxd.c
create mode 100644 dlls/wprocs.dll16/wprocs.dll16.spec
diff --git a/.gitignore b/.gitignore
index 5d498c8..2569443 100644
--- a/.gitignore
+++ b/.gitignore
@@ -119,7 +119,6 @@ dlls/shdocvw/shdocvw_v1.tlb
dlls/stdole2.tlb/std_ole_v2.tlb
dlls/stdole32.tlb/std_ole_v1.tlb
dlls/user.exe16
-dlls/wprocs.dll16
include/activaut.h
include/activdbg.h
include/activscp.h
diff --git a/configure b/configure
index dae14db..8f9e4f8 100755
--- a/configure
+++ b/configure
@@ -17327,6 +17327,14 @@ dlls/wow32/Makefile: dlls/wow32/Makefile.in dlls/Makedll.rules"
ac_config_files="$ac_config_files dlls/wow32/Makefile"
ALL_MAKEFILES="$ALL_MAKEFILES \\
+ dlls/wprocs.dll16/Makefile"
+test "x$enable_win16" != xno && ALL_DLL_DIRS="$ALL_DLL_DIRS \\
+ wprocs.dll16"
+ALL_MAKEFILE_DEPENDS="$ALL_MAKEFILE_DEPENDS
+dlls/wprocs.dll16/Makefile: dlls/wprocs.dll16/Makefile.in dlls/Makedll.rules"
+ac_config_files="$ac_config_files dlls/wprocs.dll16/Makefile"
+
+ALL_MAKEFILES="$ALL_MAKEFILES \\
dlls/ws2_32/Makefile"
test "x$enable_ws2_32" != xno && ALL_DLL_DIRS="$ALL_DLL_DIRS \\
ws2_32"
@@ -18568,9 +18576,9 @@ esac
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
-config_files="$ac_config_files"
-config_headers="$ac_config_headers"
-config_commands="$ac_config_commands"
+config_files="`echo $ac_config_files`"
+config_headers="`echo $ac_config_headers`"
+config_commands="`echo $ac_config_commands`"
_ACEOF
@@ -19175,6 +19183,7 @@ do
"dlls/wmiutils/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/wmiutils/Makefile" ;;
"dlls/wnaspi32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/wnaspi32/Makefile" ;;
"dlls/wow32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/wow32/Makefile" ;;
+ "dlls/wprocs.dll16/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/wprocs.dll16/Makefile" ;;
"dlls/ws2_32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/ws2_32/Makefile" ;;
"dlls/ws2_32/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/ws2_32/tests/Makefile" ;;
"dlls/wsock32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/wsock32/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index 5210c35..cef4935 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2552,6 +2552,7 @@ WINE_CONFIG_MAKEFILE([dlls/wmi/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DI
WINE_CONFIG_MAKEFILE([dlls/wmiutils/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
WINE_CONFIG_MAKEFILE([dlls/wnaspi32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
WINE_CONFIG_MAKEFILE([dlls/wow32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
+WINE_CONFIG_MAKEFILE([dlls/wprocs.dll16/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS],[enable_win16])
WINE_CONFIG_MAKEFILE([dlls/ws2_32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
WINE_CONFIG_MAKEFILE([dlls/ws2_32/tests/Makefile],[dlls/Maketest.rules],[dlls],[ALL_TEST_DIRS],[enable_tests])
WINE_CONFIG_MAKEFILE([dlls/wsock32/Makefile],[dlls/Makedll.rules],[dlls],[ALL_DLL_DIRS])
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index 8dcfdab..1f0dcc1 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -22,8 +22,7 @@ WIN16_FILES = \
gdi.exe16 \
krnl386.exe16 \
mmsystem.dll16 \
- user.exe16 \
- wprocs.dll16
+ user.exe16
@MAKE_RULES@
@@ -45,9 +44,6 @@ krnl386.exe16:
user.exe16:
echo "user32.dll" >$@
-wprocs.dll16:
- echo "winedos.dll" >$@
-
mmsystem.dll16:
echo "winmm.dll" >$@
diff --git a/dlls/winedos/Makefile.in b/dlls/winedos/Makefile.in
index ede4c7c..58a50c9 100644
--- a/dlls/winedos/Makefile.in
+++ b/dlls/winedos/Makefile.in
@@ -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@
diff --git a/dlls/winedos/vxd.c b/dlls/winedos/vxd.c
deleted file mode 100644
index fa66691..0000000
--- a/dlls/winedos/vxd.c
+++ /dev/null
@@ -1,1718 +0,0 @@
-/*
- * 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 "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(vxd);
-
-#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 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)))
-
-#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 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)
-{
- RTL_OSVERSIONINFOEXW info;
- WORD version;
-
- info.dwOSVersionInfoSize = sizeof(info);
- if (!RtlGetVersion(&info) && info.dwMajorVersion <= 3)
- version = MAKEWORD(info.dwMajorVersion, info.dwMinorVersion);
- else
- version = MAKEWORD(3, 95);
-
- 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" );
- }
-
-}
diff --git a/dlls/winedos/wprocs.spec b/dlls/winedos/wprocs.spec
deleted file mode 100644
index 1691590..0000000
--- a/dlls/winedos/wprocs.spec
+++ /dev/null
@@ -1,19 +0,0 @@
-# VxDs. The first Vxd is at 400
-#
-#400+VXD_ID pascal -register <VxD handler>() <VxD handler>
-#
-401 pascal -register VXD_VMM() VXD_VMM
-405 pascal -register VXD_Timer() VXD_Timer
-409 pascal -register VXD_Reboot() VXD_Reboot
-410 pascal -register VXD_VDD() VXD_VDD
-412 pascal -register VXD_VMD() VXD_VMD
-414 pascal -register VXD_Comm() VXD_Comm
-#415 pascal -register VXD_Printer() VXD_Printer
-423 pascal -register VXD_Shell() VXD_Shell
-433 pascal -register VXD_PageFile() VXD_PageFile
-438 pascal -register VXD_APM() VXD_APM
-439 pascal -register VXD_VXDLoader() VXD_VXDLoader
-445 pascal -register VXD_Win32s() VXD_Win32s
-451 pascal -register VXD_ConfigMG() VXD_ConfigMG
-455 pascal -register VXD_Enable() VXD_Enable
-1490 pascal -register VXD_TimerAPI() VXD_TimerAPI
diff --git a/dlls/wprocs.dll16/Makefile.in b/dlls/wprocs.dll16/Makefile.in
new file mode 100644
index 0000000..7112d1a
--- /dev/null
+++ b/dlls/wprocs.dll16/Makefile.in
@@ -0,0 +1,15 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR = @srcdir@
+VPATH = @srcdir@
+MODULE = wprocs.dll16
+IMPORTS = kernel32 ntdll
+
+EXTRADLLFLAGS = -Wb,--subsystem,win16,--main-module,winedos.dll
+
+C_SRCS = \
+ vxd.c
+
+ at MAKE_DLL_RULES@
+
+ at DEPENDENCIES@ # everything below this line is overwritten by make depend
diff --git a/dlls/wprocs.dll16/vxd.c b/dlls/wprocs.dll16/vxd.c
new file mode 100644
index 0000000..fa66691
--- /dev/null
+++ b/dlls/wprocs.dll16/vxd.c
@@ -0,0 +1,1718 @@
+/*
+ * 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 "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(vxd);
+
+#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 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)))
+
+#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 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)
+{
+ RTL_OSVERSIONINFOEXW info;
+ WORD version;
+
+ info.dwOSVersionInfoSize = sizeof(info);
+ if (!RtlGetVersion(&info) && info.dwMajorVersion <= 3)
+ version = MAKEWORD(info.dwMajorVersion, info.dwMinorVersion);
+ else
+ version = MAKEWORD(3, 95);
+
+ 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" );
+ }
+
+}
diff --git a/dlls/wprocs.dll16/wprocs.dll16.spec b/dlls/wprocs.dll16/wprocs.dll16.spec
new file mode 100644
index 0000000..1691590
--- /dev/null
+++ b/dlls/wprocs.dll16/wprocs.dll16.spec
@@ -0,0 +1,19 @@
+# VxDs. The first Vxd is at 400
+#
+#400+VXD_ID pascal -register <VxD handler>() <VxD handler>
+#
+401 pascal -register VXD_VMM() VXD_VMM
+405 pascal -register VXD_Timer() VXD_Timer
+409 pascal -register VXD_Reboot() VXD_Reboot
+410 pascal -register VXD_VDD() VXD_VDD
+412 pascal -register VXD_VMD() VXD_VMD
+414 pascal -register VXD_Comm() VXD_Comm
+#415 pascal -register VXD_Printer() VXD_Printer
+423 pascal -register VXD_Shell() VXD_Shell
+433 pascal -register VXD_PageFile() VXD_PageFile
+438 pascal -register VXD_APM() VXD_APM
+439 pascal -register VXD_VXDLoader() VXD_VXDLoader
+445 pascal -register VXD_Win32s() VXD_Win32s
+451 pascal -register VXD_ConfigMG() VXD_ConfigMG
+455 pascal -register VXD_Enable() VXD_Enable
+1490 pascal -register VXD_TimerAPI() VXD_TimerAPI
More information about the wine-patches
mailing list