Commit a02d2773 authored by Alexandre Julliard's avatar Alexandre Julliard

krnl386: Reimplement LDT support using NtSetLdtEntries().

parent 12c3177e
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "wine/windef16.h" #include "wine/windef16.h"
#include "winbase.h" #include "winbase.h"
#include "winnt.h" /* for PCONTEXT */ #include "winnt.h" /* for PCONTEXT */
#include "kernel16_private.h"
#define MAX_DOS_DRIVES 26 #define MAX_DOS_DRIVES 26
...@@ -64,7 +65,7 @@ extern WORD relay_data_sel DECLSPEC_HIDDEN; ...@@ -64,7 +65,7 @@ extern WORD relay_data_sel DECLSPEC_HIDDEN;
* segmented mode is recognized by checking whether 'seg' is 32-bit * segmented mode is recognized by checking whether 'seg' is 32-bit
* selector which is neither system selector nor zero. * selector which is neither system selector nor zero.
*/ */
#define CTX_SEG_OFF_TO_LIN(context,seg,off) (wine_ldt_get_ptr((seg),(off))) #define CTX_SEG_OFF_TO_LIN(context,seg,off) (ldt_get_ptr((seg),(off)))
#define INT_BARF(context,num) \ #define INT_BARF(context,num) \
ERR( "int%x: unknown/not implemented parameters:\n" \ ERR( "int%x: unknown/not implemented parameters:\n" \
......
...@@ -53,14 +53,14 @@ static inline void add_stack( CONTEXT *context, int offset ) ...@@ -53,14 +53,14 @@ static inline void add_stack( CONTEXT *context, int offset )
static inline void *make_ptr( CONTEXT *context, DWORD seg, DWORD off, int long_addr ) static inline void *make_ptr( CONTEXT *context, DWORD seg, DWORD off, int long_addr )
{ {
if (wine_ldt_is_system(seg)) return (void *)off; if (ldt_is_system(seg)) return (void *)off;
if (!long_addr) off = LOWORD(off); if (!long_addr) off = LOWORD(off);
return (char *) MapSL( MAKESEGPTR( seg, 0 ) ) + off; return (char *) MapSL( MAKESEGPTR( seg, 0 ) ) + off;
} }
static inline void *get_stack( CONTEXT *context ) static inline void *get_stack( CONTEXT *context )
{ {
return wine_ldt_get_ptr( context->SegSs, context->Esp ); return ldt_get_ptr( context->SegSs, context->Esp );
} }
#include "pshpack1.h" #include "pshpack1.h"
...@@ -315,9 +315,9 @@ static BYTE *INSTR_GetOperandAddr( CONTEXT *context, BYTE *instr, ...@@ -315,9 +315,9 @@ static BYTE *INSTR_GetOperandAddr( CONTEXT *context, BYTE *instr,
if (segprefix != -1) seg = segprefix; if (segprefix != -1) seg = segprefix;
/* Make sure the segment and offset are valid */ /* Make sure the segment and offset are valid */
if (wine_ldt_is_system(seg)) return (BYTE *)(base + (index << ss)); if (ldt_is_system(seg)) return (BYTE *)(base + (index << ss));
if ((seg & 7) != 7) return NULL; if ((seg & 7) != 7) return NULL;
wine_ldt_get_entry( seg, &entry ); if (!ldt_get_entry( seg, &entry )) return NULL;
if (wine_ldt_is_empty( &entry )) return NULL; if (wine_ldt_is_empty( &entry )) return NULL;
if (wine_ldt_get_limit(&entry) < (base + (index << ss))) return NULL; if (wine_ldt_get_limit(&entry) < (base + (index << ss))) return NULL;
return (BYTE *)wine_ldt_get_base(&entry) + base + (index << ss); return (BYTE *)wine_ldt_get_base(&entry) + base + (index << ss);
...@@ -790,7 +790,7 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) ...@@ -790,7 +790,7 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
break; /* Unable to emulate it */ break; /* Unable to emulate it */
case 0xcf: /* iret */ case 0xcf: /* iret */
if (wine_ldt_is_system(context->SegCs)) break; /* don't emulate it in 32-bit code */ if (ldt_is_system(context->SegCs)) break; /* don't emulate it in 32-bit code */
if (long_op) if (long_op)
{ {
DWORD *stack = get_stack( context ); DWORD *stack = get_stack( context );
...@@ -884,7 +884,7 @@ LONG CALLBACK INSTR_vectored_handler( EXCEPTION_POINTERS *ptrs ) ...@@ -884,7 +884,7 @@ LONG CALLBACK INSTR_vectored_handler( EXCEPTION_POINTERS *ptrs )
EXCEPTION_RECORD *record = ptrs->ExceptionRecord; EXCEPTION_RECORD *record = ptrs->ExceptionRecord;
CONTEXT *context = ptrs->ContextRecord; CONTEXT *context = ptrs->ContextRecord;
if (wine_ldt_is_system(context->SegCs) && if (ldt_is_system(context->SegCs) &&
(record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION || (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
record->ExceptionCode == EXCEPTION_PRIV_INSTRUCTION)) record->ExceptionCode == EXCEPTION_PRIV_INSTRUCTION))
{ {
......
...@@ -242,9 +242,8 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context ) ...@@ -242,9 +242,8 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
TRACE( "get selector base address (0x%04x)\n", BX_reg(context) ); TRACE( "get selector base address (0x%04x)\n", BX_reg(context) );
{ {
LDT_ENTRY entry; LDT_ENTRY entry;
WORD sel = BX_reg(context);
wine_ldt_get_entry( sel, &entry ); if (!ldt_get_entry( BX_reg(context), &entry ) || wine_ldt_is_empty(&entry))
if (wine_ldt_is_empty(&entry))
{ {
context->Eax = 0x8022; /* invalid selector */ context->Eax = 0x8022; /* invalid selector */
SET_CFLAG(context); SET_CFLAG(context);
...@@ -301,7 +300,7 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context ) ...@@ -301,7 +300,7 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
{ {
LDT_ENTRY *entry = CTX_SEG_OFF_TO_LIN( context, context->SegEs, LDT_ENTRY *entry = CTX_SEG_OFF_TO_LIN( context, context->SegEs,
context->Edi ); context->Edi );
wine_ldt_get_entry( BX_reg(context), entry ); ldt_get_entry( BX_reg(context), entry );
} }
break; break;
...@@ -310,7 +309,7 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context ) ...@@ -310,7 +309,7 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
{ {
LDT_ENTRY *entry = CTX_SEG_OFF_TO_LIN( context, context->SegEs, LDT_ENTRY *entry = CTX_SEG_OFF_TO_LIN( context, context->SegEs,
context->Edi ); context->Edi );
wine_ldt_set_entry( BX_reg(context), entry ); if (!ldt_is_system( BX_reg(context) )) ldt_set_entry( BX_reg(context), *entry );
} }
break; break;
......
...@@ -280,7 +280,7 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum ) ...@@ -280,7 +280,7 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum )
DOSVM_IntProcRelay, DOSVM_IntProcRelay,
DOSVM_GetBuiltinHandler(intnum) ); DOSVM_GetBuiltinHandler(intnum) );
} }
else if (wine_ldt_is_system(context->SegCs)) else if (ldt_is_system(context->SegCs))
{ {
INTPROC proc; INTPROC proc;
if (intnum >= ARRAY_SIZE(DOSVM_VectorsBuiltin)) return FALSE; if (intnum >= ARRAY_SIZE(DOSVM_VectorsBuiltin)) return FALSE;
......
...@@ -71,6 +71,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) ...@@ -71,6 +71,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
switch(reason) switch(reason)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
init_selectors();
if (LoadLibrary16( "krnl386.exe" ) < 32) return FALSE; if (LoadLibrary16( "krnl386.exe" ) < 32) return FALSE;
/* fall through */ /* fall through */
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
......
...@@ -232,11 +232,16 @@ extern void NE_DllProcessAttach( HMODULE16 hModule ) DECLSPEC_HIDDEN; ...@@ -232,11 +232,16 @@ extern void NE_DllProcessAttach( HMODULE16 hModule ) DECLSPEC_HIDDEN;
extern void NE_CallUserSignalProc( HMODULE16 hModule, UINT16 code ) DECLSPEC_HIDDEN; extern void NE_CallUserSignalProc( HMODULE16 hModule, UINT16 code ) DECLSPEC_HIDDEN;
/* selector.c */ /* selector.c */
extern void init_selectors(void) DECLSPEC_HIDDEN;
extern BOOL ldt_is_system( WORD sel ) DECLSPEC_HIDDEN;
extern void *ldt_get_ptr( WORD sel, DWORD offset ) DECLSPEC_HIDDEN;
extern BOOL ldt_get_entry( WORD sel, LDT_ENTRY *entry ) DECLSPEC_HIDDEN;
extern void ldt_set_entry( WORD sel, LDT_ENTRY entry ) DECLSPEC_HIDDEN;
extern WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags ) DECLSPEC_HIDDEN; extern WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags ) DECLSPEC_HIDDEN;
extern WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size ) DECLSPEC_HIDDEN; extern WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size ) DECLSPEC_HIDDEN;
extern void SELECTOR_FreeBlock( WORD sel ) DECLSPEC_HIDDEN; extern void SELECTOR_FreeBlock( WORD sel ) DECLSPEC_HIDDEN;
#define IS_SELECTOR_32BIT(sel) \ #define IS_SELECTOR_32BIT(sel) \
(wine_ldt_is_system(sel) || (wine_ldt_copy.flags[LOWORD(sel) >> 3] & WINE_LDT_FLAGS_32BIT)) (ldt_is_system(sel) || (wine_ldt_copy.flags[LOWORD(sel) >> 3] & WINE_LDT_FLAGS_32BIT))
/* relay16.c */ /* relay16.c */
extern int relay_call_from_16( void *entry_point, unsigned char *args16, CONTEXT *context ) DECLSPEC_HIDDEN; extern int relay_call_from_16( void *entry_point, unsigned char *args16, CONTEXT *context ) DECLSPEC_HIDDEN;
......
...@@ -57,14 +57,10 @@ static SEGPTR call16_ret_addr; /* segptr to __wine_call_to_16_ret routine */ ...@@ -57,14 +57,10 @@ static SEGPTR call16_ret_addr; /* segptr to __wine_call_to_16_ret routine */
BOOL WOWTHUNK_Init(void) BOOL WOWTHUNK_Init(void)
{ {
/* allocate the code selector for CallTo16 routines */ /* allocate the code selector for CallTo16 routines */
LDT_ENTRY entry; WORD codesel = SELECTOR_AllocBlock( __wine_call16_start,
WORD codesel = wine_ldt_alloc_entries(1); (BYTE *)(&CallTo16_TebSelector + 1) - __wine_call16_start,
WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
if (!codesel) return FALSE; if (!codesel) return FALSE;
wine_ldt_set_base( &entry, __wine_call16_start );
wine_ldt_set_limit( &entry, (BYTE *)(&CallTo16_TebSelector + 1) - __wine_call16_start - 1 );
wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
wine_ldt_set_entry( codesel, &entry );
/* Patch the return addresses for CallTo16 routines */ /* Patch the return addresses for CallTo16 routines */
...@@ -116,7 +112,7 @@ static BOOL fix_selector( CONTEXT *context ) ...@@ -116,7 +112,7 @@ static BOOL fix_selector( CONTEXT *context )
default: default:
return FALSE; return FALSE;
} }
stack = wine_ldt_get_ptr( context->SegSs, context->Esp ); stack = ldt_get_ptr( context->SegSs, context->Esp );
TRACE( "fixing up selector %x for pop instruction\n", *stack ); TRACE( "fixing up selector %x for pop instruction\n", *stack );
*stack = 0; *stack = 0;
return TRUE; return TRUE;
...@@ -141,7 +137,7 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RE ...@@ -141,7 +137,7 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RE
else if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION || else if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
record->ExceptionCode == EXCEPTION_PRIV_INSTRUCTION) record->ExceptionCode == EXCEPTION_PRIV_INSTRUCTION)
{ {
if (wine_ldt_is_system(context->SegCs)) if (ldt_is_system(context->SegCs))
{ {
if (fix_selector( context )) return ExceptionContinueExecution; if (fix_selector( context )) return ExceptionContinueExecution;
} }
...@@ -155,7 +151,7 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RE ...@@ -155,7 +151,7 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RE
/* check for Win16 __GP handler */ /* check for Win16 __GP handler */
if ((gpHandler = HasGPHandler16( MAKESEGPTR( context->SegCs, context->Eip ) ))) if ((gpHandler = HasGPHandler16( MAKESEGPTR( context->SegCs, context->Eip ) )))
{ {
WORD *stack = wine_ldt_get_ptr( context->SegSs, context->Esp ); WORD *stack = ldt_get_ptr( context->SegSs, context->Esp );
*--stack = context->SegCs; *--stack = context->SegCs;
*--stack = context->Eip; *--stack = context->Eip;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment