diff --git a/dlls/krnl386.exe16/Makefile.in b/dlls/krnl386.exe16/Makefile.in index dae89e277c2..1848bbec5cd 100644 --- a/dlls/krnl386.exe16/Makefile.in +++ b/dlls/krnl386.exe16/Makefile.in @@ -8,7 +8,6 @@ C_SRCS = \ atom.c \ dma.c \ dosmem.c \ - dosvm.c \ error.c \ file.c \ fpu.c \ diff --git a/dlls/krnl386.exe16/dosexe.h b/dlls/krnl386.exe16/dosexe.h index dfeae8a78ec..74416d53b36 100644 --- a/dlls/krnl386.exe16/dosexe.h +++ b/dlls/krnl386.exe16/dosexe.h @@ -35,21 +35,14 @@ /* amount of space reserved for relay stack */ #define DOSVM_RELAY_DATA_SIZE 4096 -/* various real-mode code stubs */ -struct DPMI_segments -{ - WORD int16_sel; - WORD relay_code_sel; - WORD relay_data_sel; -}; - typedef void (*DOSRELAY)(CONTEXT*,void*); typedef void (WINAPI *RMCBPROC)(CONTEXT*); typedef void (WINAPI *INTPROC)(CONTEXT*); extern WORD DOSVM_psp DECLSPEC_HIDDEN; /* psp of current DOS task */ -extern WORD DOSVM_retval DECLSPEC_HIDDEN; /* return value of previous DOS task */ -extern struct DPMI_segments *DOSVM_dpmi_segments DECLSPEC_HIDDEN; +extern WORD int16_sel DECLSPEC_HIDDEN; +extern WORD relay_code_sel DECLSPEC_HIDDEN; +extern WORD relay_data_sel DECLSPEC_HIDDEN; /* * Declare some CONTEXT.EFlags bits. @@ -218,8 +211,6 @@ typedef struct /* dosvm.c */ extern void DOSVM_Exit( WORD retval ) DECLSPEC_HIDDEN; -extern LPVOID DOSVM_AllocDataUMB(DWORD, WORD *) DECLSPEC_HIDDEN; -extern void DOSVM_InitSegments(void) DECLSPEC_HIDDEN; /* dma.c */ extern int DMA_Transfer(int channel,int reqlength,void* buffer) DECLSPEC_HIDDEN; diff --git a/dlls/krnl386.exe16/dosmem.c b/dlls/krnl386.exe16/dosmem.c index b899f7b9380..1910105bbe8 100644 --- a/dlls/krnl386.exe16/dosmem.c +++ b/dlls/krnl386.exe16/dosmem.c @@ -48,6 +48,11 @@ WORD DOSMEM_0000H; /* segment at 0:0 */ WORD DOSMEM_BiosDataSeg; /* BIOS data segment at 0x40:0 */ WORD DOSMEM_BiosSysSeg; /* BIOS ROM segment at 0xf000:0 */ +WORD DOSVM_psp = 0; +WORD int16_sel = 0; +WORD relay_code_sel = 0; +WORD relay_data_sel = 0; + /* DOS memory highest address (including HMA) */ #define DOSMEM_SIZE 0x110000 #define DOSMEM_64KB 0x10000 @@ -295,6 +300,57 @@ static void DOSMEM_Collapse( MCB* mcb ) } } + +/*********************************************************************** + * DOSMEM_InitSegments + */ +static void DOSMEM_InitSegments(void) +{ + LPSTR ptr; + int i; + + static const char relay[]= + { + 0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */ + 0xcd, 0x31, /* int 31 */ + 0xfb, 0x66, 0xcb /* sti and 32-bit far return */ + }; + + /* + * PM / offset N*5: Interrupt N in 16-bit protected mode. + */ + int16_sel = GLOBAL_Alloc( GMEM_FIXED, 5 * 256, 0, WINE_LDT_FLAGS_CODE ); + ptr = GlobalLock16( int16_sel ); + for(i=0; i<256; i++) { + /* + * Each 16-bit interrupt handler is 5 bytes: + * 0xCD, = int (interrupt) + * 0xCA,0x02,0x00 = ret 2 (16-bit far return and pop 2 bytes / eflags) + */ + ptr[i * 5 + 0] = 0xCD; + ptr[i * 5 + 1] = i; + ptr[i * 5 + 2] = 0xCA; + ptr[i * 5 + 3] = 0x02; + ptr[i * 5 + 4] = 0x00; + } + GlobalUnlock16( int16_sel ); + + /* + * PM / offset 0: Stub where __wine_call_from_16_regs returns. + * PM / offset 3: Stub which swaps back to 32-bit application code/stack. + * PM / offset 5: Stub which enables interrupts + */ + relay_code_sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(relay), 0, WINE_LDT_FLAGS_CODE ); + ptr = GlobalLock16( relay_code_sel ); + memcpy( ptr, relay, sizeof(relay) ); + GlobalUnlock16( relay_code_sel ); + + /* + * Space for 16-bit stack used by relay code. + */ + relay_data_sel = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, DOSVM_RELAY_DATA_SIZE ); +} + /****************************************************************** * DOSMEM_InitDosMemory */ @@ -349,7 +405,7 @@ BOOL DOSMEM_InitDosMemory(void) TRACE("DOS conventional memory initialized, %d bytes free.\n", DOSMEM_Available()); - DOSVM_InitSegments(); + DOSMEM_InitSegments(); SetEvent( hRunOnce ); done = TRUE; diff --git a/dlls/krnl386.exe16/dosvm.c b/dlls/krnl386.exe16/dosvm.c deleted file mode 100644 index a33b37a8a54..00000000000 --- a/dlls/krnl386.exe16/dosvm.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * DOS Virtual Machine - * - * Copyright 1998 Ove Kåven - * Copyright 2002 Jukka Heinonen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * Note: This code hasn't been completely cleaned up yet. - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif -#include - -#include "wine/winbase16.h" -#include "wine/exception.h" -#include "windef.h" -#include "winbase.h" -#include "winternl.h" -#include "wingdi.h" -#include "winuser.h" -#include "wownt32.h" -#include "winnt.h" -#include "wincon.h" - -#include "dosexe.h" -#include "wine/debug.h" -#include "excpt.h" - -WINE_DEFAULT_DEBUG_CHANNEL(int); - -WORD DOSVM_psp = 0; -WORD DOSVM_retval = 0; - -/* - * Wine DOS memory layout above 640k: - * - * a0000 - affff : VGA graphics (vga.c) - * b0000 - bffff : Monochrome text (unused) - * b8000 - bffff : VGA text (vga.c) - * c0000 - cffff : EMS frame (int67.c) - * d0000 - effff : Free memory for UMBs (himem.c) - * f0000 - fffff : BIOS stuff (msdos/dosmem.c) - * 100000 -10ffff : High memory area (unused) - */ - -/* - * Table of real mode segments and protected mode selectors - * for code stubs and other miscellaneous storage. - */ -struct DPMI_segments *DOSVM_dpmi_segments = NULL; - -/* - * First and last address available for upper memory blocks. - */ -#define DOSVM_UMB_BOTTOM 0xd0000 -#define DOSVM_UMB_TOP 0xeffff - -/* - * First free address for upper memory blocks. - */ -static DWORD DOSVM_umb_free = DOSVM_UMB_BOTTOM; - - -/********************************************************************** - * DOSVM_Exit - */ -void DOSVM_Exit( WORD retval ) -{ - DWORD count; - - ReleaseThunkLock( &count ); - ExitThread( retval ); -} - -/*********************************************************************** - * DOSVM_AllocUMB - * - * Allocate upper memory block (UMB) from upper memory. - * Returned pointer is aligned to 16-byte (paragraph) boundary. - * - * This routine is only for allocating static storage for - * Wine internal uses. Allocated memory can be accessed from - * real mode, memory is taken from area already mapped and reserved - * by Wine and the allocation has very little memory and speed - * overhead. Use of this routine also preserves precious DOS - * conventional memory. - */ -static LPVOID DOSVM_AllocUMB( DWORD size ) -{ - LPVOID ptr = (LPVOID)DOSVM_umb_free; - - size = ((size + 15) >> 4) << 4; - - if(DOSVM_umb_free + size - 1 > DOSVM_UMB_TOP) { - ERR("Out of upper memory area.\n"); - return 0; - } - - DOSVM_umb_free += size; - return ptr; -} - - -/********************************************************************** - * alloc_selector - * - * Allocate a selector corresponding to a real mode address. - * size must be < 64k. - */ -static WORD alloc_selector( void *base, DWORD size, unsigned char flags ) -{ - WORD sel = wine_ldt_alloc_entries( 1 ); - - if (sel) - { - LDT_ENTRY entry; - wine_ldt_set_base( &entry, base ); - wine_ldt_set_limit( &entry, size - 1 ); - wine_ldt_set_flags( &entry, flags ); - wine_ldt_set_entry( sel, &entry ); - } - return sel; -} - - -/*********************************************************************** - * DOSVM_AllocCodeUMB - * - * Allocate upper memory block for storing code stubs. - * Initializes real mode segment and 16-bit protected mode selector - * for the allocated code block. - * - * FIXME: should allocate a single PM selector for the whole UMB range. - */ -static LPVOID DOSVM_AllocCodeUMB( DWORD size, WORD *selector ) -{ - LPVOID ptr = DOSVM_AllocUMB( size ); - *selector = alloc_selector( ptr, size, WINE_LDT_FLAGS_CODE ); - return ptr; -} - - -/*********************************************************************** - * DOSVM_AllocDataUMB - * - * Allocate upper memory block for storing data. - * Initializes real mode segment and 16-bit protected mode selector - * for the allocated data block. - */ -LPVOID DOSVM_AllocDataUMB( DWORD size, WORD *selector ) -{ - LPVOID ptr = DOSVM_AllocUMB( size ); - *selector = alloc_selector( ptr, size, WINE_LDT_FLAGS_DATA ); - return ptr; -} - - -/*********************************************************************** - * DOSVM_InitSegments - * - * Initializes DOSVM_dpmi_segments. Allocates required memory and - * sets up segments and selectors for accessing the memory. - */ -void DOSVM_InitSegments(void) -{ - DWORD old_prot; - LPSTR ptr; - int i; - - static const char relay[]= - { - 0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */ - 0xcd, 0x31, /* int 31 */ - 0xfb, 0x66, 0xcb /* sti and 32-bit far return */ - }; - - /* - * Allocate pointer array. - */ - DOSVM_dpmi_segments = DOSVM_AllocUMB( sizeof(struct DPMI_segments) ); - - /* - * PM / offset N*5: Interrupt N in 16-bit protected mode. - */ - ptr = DOSVM_AllocCodeUMB( 5 * 256, &DOSVM_dpmi_segments->int16_sel ); - for(i=0; i<256; i++) { - /* - * Each 16-bit interrupt handler is 5 bytes: - * 0xCD, = int (interrupt) - * 0xCA,0x02,0x00 = ret 2 (16-bit far return and pop 2 bytes / eflags) - */ - ptr[i * 5 + 0] = 0xCD; - ptr[i * 5 + 1] = i; - ptr[i * 5 + 2] = 0xCA; - ptr[i * 5 + 3] = 0x02; - ptr[i * 5 + 4] = 0x00; - } - - /* - * PM / offset 0: Stub where __wine_call_from_16_regs returns. - * PM / offset 3: Stub which swaps back to 32-bit application code/stack. - * PM / offset 5: Stub which enables interrupts - */ - ptr = DOSVM_AllocCodeUMB( sizeof(relay), &DOSVM_dpmi_segments->relay_code_sel); - memcpy( ptr, relay, sizeof(relay) ); - - /* - * Space for 16-bit stack used by relay code. - */ - ptr = DOSVM_AllocDataUMB( DOSVM_RELAY_DATA_SIZE, &DOSVM_dpmi_segments->relay_data_sel); - memset( ptr, 0, DOSVM_RELAY_DATA_SIZE ); - - /* - * As we store code in UMB we should make sure it is executable - */ - VirtualProtect((void *)DOSVM_UMB_BOTTOM, DOSVM_UMB_TOP - DOSVM_UMB_BOTTOM, PAGE_EXECUTE_READWRITE, &old_prot); -} diff --git a/dlls/krnl386.exe16/int21.c b/dlls/krnl386.exe16/int21.c index f5b257b6d7a..f4244563420 100644 --- a/dlls/krnl386.exe16/int21.c +++ b/dlls/krnl386.exe16/int21.c @@ -520,9 +520,8 @@ static INT21_HEAP *INT21_GetHeapPointer( void ) if (!heap_pointer) { - WORD heap_selector; - - heap_pointer = DOSVM_AllocDataUMB( sizeof(INT21_HEAP), &heap_selector ); + WORD heap_selector = GlobalAlloc16( GMEM_FIXED, sizeof(INT21_HEAP) ); + heap_pointer = GlobalLock16( heap_selector ); heap_pointer->misc_selector = heap_selector; INT21_FillHeap( heap_pointer ); } @@ -4782,8 +4781,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context ) case 0x4d: /* GET RETURN CODE */ TRACE("GET RETURN CODE (ERRORLEVEL)\n"); - SET_AX( context, DOSVM_retval ); - DOSVM_retval = 0; + SET_AX( context, 0 ); break; case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */ diff --git a/dlls/krnl386.exe16/int2f.c b/dlls/krnl386.exe16/int2f.c index 92055b06f42..b0a36e3c059 100644 --- a/dlls/krnl386.exe16/int2f.c +++ b/dlls/krnl386.exe16/int2f.c @@ -459,10 +459,8 @@ static CDROM_HEAP *CDROM_GetHeap( void ) if ( !heap_pointer ) { - WORD heap_selector; - - /* allocate a new DOS data segment */ - heap_pointer = DOSVM_AllocDataUMB( sizeof(CDROM_HEAP), &heap_selector ); + WORD heap_selector = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(CDROM_HEAP) ); + heap_pointer = GlobalLock16( heap_selector ); heap_pointer->cdrom_selector = heap_selector; CDROM_FillHeap( heap_pointer ); } diff --git a/dlls/krnl386.exe16/interrupts.c b/dlls/krnl386.exe16/interrupts.c index c4448c6d002..aa71b01c100 100644 --- a/dlls/krnl386.exe16/interrupts.c +++ b/dlls/krnl386.exe16/interrupts.c @@ -96,6 +96,18 @@ static void WINAPI DOSVM_DefaultHandler( CONTEXT *context ) } +/********************************************************************** + * DOSVM_Exit + */ +void DOSVM_Exit( WORD retval ) +{ + DWORD count; + + ReleaseThunkLock( &count ); + ExitThread( retval ); +} + + /********************************************************************** * DOSVM_GetBuiltinHandler * @@ -189,7 +201,7 @@ static void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum ) { FARPROC16 addr = DOSVM_GetPMHandler16( intnum ); - if (SELECTOROF(addr) == DOSVM_dpmi_segments->int16_sel) + if (SELECTOROF(addr) == int16_sel) { TRACE( "builtin interrupt %02x has been invoked " "(through vector %02x)\n", @@ -243,14 +255,14 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum ) DOSMEM_InitDosMemory(); - if (context->SegCs == DOSVM_dpmi_segments->relay_code_sel) + if (context->SegCs == relay_code_sel) { /* * This must not be called using DOSVM_BuildCallFrame. */ DOSVM_RelayHandler( context ); } - else if (context->SegCs == DOSVM_dpmi_segments->int16_sel) + else if (context->SegCs == int16_sel) { /* Restore original flags stored into the stack by the caller. */ WORD *stack = CTX_SEG_OFF_TO_LIN(context, @@ -328,8 +340,7 @@ FARPROC16 DOSVM_GetPMHandler16( BYTE intnum ) } if (!DOSVM_Vectors16[intnum]) { - proc = (FARPROC16)MAKESEGPTR( DOSVM_dpmi_segments->int16_sel, - DOSVM_STUB_PM16 * intnum ); + proc = (FARPROC16)MAKESEGPTR( int16_sel, DOSVM_STUB_PM16 * intnum ); DOSVM_Vectors16[intnum] = proc; } return DOSVM_Vectors16[intnum]; diff --git a/dlls/krnl386.exe16/relay.c b/dlls/krnl386.exe16/relay.c index 264ba2c589b..a47e85126ea 100644 --- a/dlls/krnl386.exe16/relay.c +++ b/dlls/krnl386.exe16/relay.c @@ -601,7 +601,7 @@ int relay_call_from_16( void *entry_point, unsigned char *args16, CONTEXT *conte static RELAY_Stack16 *RELAY_GetPointer( DWORD offset ) { offset = offset / sizeof(RELAY_Stack16) * sizeof(RELAY_Stack16); - return MapSL(MAKESEGPTR(DOSVM_dpmi_segments->relay_data_sel, offset)); + return MapSL(MAKESEGPTR(relay_data_sel, offset)); } @@ -637,9 +637,9 @@ static void RELAY_MakeShortContext( CONTEXT *context ) stack->stack_bottom = RELAY_MAGIC; stack->stack_top = RELAY_MAGIC; - context->SegSs = DOSVM_dpmi_segments->relay_data_sel; + context->SegSs = relay_data_sel; context->Esp = offset; - context->SegCs = DOSVM_dpmi_segments->relay_code_sel; + context->SegCs = relay_code_sel; context->Eip = 3; } @@ -712,7 +712,7 @@ void DOSVM_RelayHandler( CONTEXT *context ) */ void DOSVM_BuildCallFrame( CONTEXT *context, DOSRELAY relay, LPVOID data ) { - WORD code_sel = DOSVM_dpmi_segments->relay_code_sel; + WORD code_sel = relay_code_sel; /* * Allocate separate stack for relay call.