krnl386: Reimplement LDT support using NtSetLdtEntries().
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
12c3177ed5
commit
a02d2773be
8 changed files with 186 additions and 105 deletions
|
@ -29,6 +29,7 @@
|
|||
#include "wine/windef16.h"
|
||||
#include "winbase.h"
|
||||
#include "winnt.h" /* for PCONTEXT */
|
||||
#include "kernel16_private.h"
|
||||
|
||||
#define MAX_DOS_DRIVES 26
|
||||
|
||||
|
@ -64,7 +65,7 @@ extern WORD relay_data_sel DECLSPEC_HIDDEN;
|
|||
* segmented mode is recognized by checking whether 'seg' is 32-bit
|
||||
* 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) \
|
||||
ERR( "int%x: unknown/not implemented parameters:\n" \
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
if (wine_ldt_is_system(seg)) return (void *)off;
|
||||
if (ldt_is_system(seg)) return (void *)off;
|
||||
if (!long_addr) off = LOWORD(off);
|
||||
return (char *) MapSL( MAKESEGPTR( seg, 0 ) ) + off;
|
||||
}
|
||||
|
||||
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"
|
||||
|
@ -315,9 +315,9 @@ static BYTE *INSTR_GetOperandAddr( CONTEXT *context, BYTE *instr,
|
|||
if (segprefix != -1) seg = segprefix;
|
||||
|
||||
/* 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;
|
||||
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_get_limit(&entry) < (base + (index << ss))) return NULL;
|
||||
return (BYTE *)wine_ldt_get_base(&entry) + base + (index << ss);
|
||||
|
@ -790,7 +790,7 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
|
|||
break; /* Unable to emulate it */
|
||||
|
||||
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)
|
||||
{
|
||||
DWORD *stack = get_stack( context );
|
||||
|
@ -884,7 +884,7 @@ LONG CALLBACK INSTR_vectored_handler( EXCEPTION_POINTERS *ptrs )
|
|||
EXCEPTION_RECORD *record = ptrs->ExceptionRecord;
|
||||
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_PRIV_INSTRUCTION))
|
||||
{
|
||||
|
|
|
@ -242,9 +242,8 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
|
|||
TRACE( "get selector base address (0x%04x)\n", BX_reg(context) );
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
WORD sel = BX_reg(context);
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
if (wine_ldt_is_empty(&entry))
|
||||
|
||||
if (!ldt_get_entry( BX_reg(context), &entry ) || wine_ldt_is_empty(&entry))
|
||||
{
|
||||
context->Eax = 0x8022; /* invalid selector */
|
||||
SET_CFLAG(context);
|
||||
|
@ -301,7 +300,7 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
|
|||
{
|
||||
LDT_ENTRY *entry = CTX_SEG_OFF_TO_LIN( context, context->SegEs,
|
||||
context->Edi );
|
||||
wine_ldt_get_entry( BX_reg(context), entry );
|
||||
ldt_get_entry( BX_reg(context), entry );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -310,7 +309,7 @@ void WINAPI DOSVM_Int31Handler( CONTEXT *context )
|
|||
{
|
||||
LDT_ENTRY *entry = CTX_SEG_OFF_TO_LIN( context, context->SegEs,
|
||||
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;
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum )
|
|||
DOSVM_IntProcRelay,
|
||||
DOSVM_GetBuiltinHandler(intnum) );
|
||||
}
|
||||
else if (wine_ldt_is_system(context->SegCs))
|
||||
else if (ldt_is_system(context->SegCs))
|
||||
{
|
||||
INTPROC proc;
|
||||
if (intnum >= ARRAY_SIZE(DOSVM_VectorsBuiltin)) return FALSE;
|
||||
|
|
|
@ -71,6 +71,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
|
|||
switch(reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
init_selectors();
|
||||
if (LoadLibrary16( "krnl386.exe" ) < 32) return FALSE;
|
||||
/* fall through */
|
||||
case DLL_THREAD_ATTACH:
|
||||
|
|
|
@ -232,11 +232,16 @@ extern void NE_DllProcessAttach( HMODULE16 hModule ) DECLSPEC_HIDDEN;
|
|||
extern void NE_CallUserSignalProc( HMODULE16 hModule, UINT16 code ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* 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_ReallocBlock( WORD sel, const void *base, DWORD size ) DECLSPEC_HIDDEN;
|
||||
extern void SELECTOR_FreeBlock( WORD sel ) DECLSPEC_HIDDEN;
|
||||
#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 */
|
||||
extern int relay_call_from_16( void *entry_point, unsigned char *args16, CONTEXT *context ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -32,19 +32,104 @@ WINE_DEFAULT_DEBUG_CHANNEL(selector);
|
|||
|
||||
#define LDT_SIZE 8192
|
||||
|
||||
static ULONG bitmap_data[LDT_SIZE / 32];
|
||||
static RTL_BITMAP ldt_bitmap = { LDT_SIZE, bitmap_data };
|
||||
static const LDT_ENTRY null_entry;
|
||||
static WORD first_ldt_entry = 32;
|
||||
|
||||
/* get the number of selectors needed to cover up to the selector limit */
|
||||
static inline WORD get_sel_count( WORD sel )
|
||||
{
|
||||
return (wine_ldt_copy.limit[sel >> __AHSHIFT] >> 16) + 1;
|
||||
}
|
||||
|
||||
static inline int is_gdt_sel( WORD sel )
|
||||
{
|
||||
return !(sel & 4);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* init_selectors
|
||||
*/
|
||||
void init_selectors(void)
|
||||
{
|
||||
if (!is_gdt_sel( wine_get_gs() )) first_ldt_entry += 512;
|
||||
if (!is_gdt_sel( wine_get_fs() )) first_ldt_entry += 512;
|
||||
RtlSetBits( &ldt_bitmap, 0, first_ldt_entry );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ldt_is_system
|
||||
*/
|
||||
BOOL ldt_is_system( WORD sel )
|
||||
{
|
||||
return is_gdt_sel( sel ) || ((sel >> 3) < first_ldt_entry);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ldt_get_ptr
|
||||
*/
|
||||
void *ldt_get_ptr( WORD sel, DWORD offset )
|
||||
{
|
||||
ULONG index = sel >> 3;
|
||||
|
||||
if (ldt_is_system( sel )) return (void *)offset;
|
||||
if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_32BIT)) offset &= 0xffff;
|
||||
return (char *)wine_ldt_copy.base[index] + offset;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ldt_get_entry
|
||||
*/
|
||||
BOOL ldt_get_entry( WORD sel, LDT_ENTRY *entry )
|
||||
{
|
||||
ULONG index = sel >> 3;
|
||||
|
||||
if (ldt_is_system( sel ) || !(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED))
|
||||
{
|
||||
*entry = null_entry;
|
||||
return FALSE;
|
||||
}
|
||||
wine_ldt_set_base( entry, wine_ldt_copy.base[index] );
|
||||
wine_ldt_set_limit( entry, wine_ldt_copy.limit[index] );
|
||||
wine_ldt_set_flags( entry, wine_ldt_copy.flags[index] );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ldt_set_entry
|
||||
*/
|
||||
void ldt_set_entry( WORD sel, LDT_ENTRY entry )
|
||||
{
|
||||
NtSetLdtEntries( sel, entry, 0, null_entry );
|
||||
}
|
||||
|
||||
|
||||
static ULONG alloc_entries( ULONG count )
|
||||
{
|
||||
ULONG idx = RtlFindClearBitsAndSet( &ldt_bitmap, count, first_ldt_entry );
|
||||
|
||||
if (idx == ~0u) return 0;
|
||||
return (idx << 3) | 7;
|
||||
}
|
||||
|
||||
static void free_entries( ULONG sel, ULONG count )
|
||||
{
|
||||
RtlClearBits( &ldt_bitmap, sel >> 3, count );
|
||||
while (count--)
|
||||
{
|
||||
ldt_set_entry( sel, null_entry );
|
||||
sel += 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* AllocSelectorArray (KERNEL.206)
|
||||
*/
|
||||
WORD WINAPI AllocSelectorArray16( WORD count )
|
||||
{
|
||||
WORD i, sel = wine_ldt_alloc_entries( count );
|
||||
WORD i, sel = alloc_entries( count );
|
||||
|
||||
if (sel)
|
||||
{
|
||||
|
@ -52,14 +137,7 @@ WORD WINAPI AllocSelectorArray16( WORD count )
|
|||
wine_ldt_set_base( &entry, 0 );
|
||||
wine_ldt_set_limit( &entry, 1 ); /* avoid 0 base and limit */
|
||||
wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_DATA );
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry ) < 0)
|
||||
{
|
||||
wine_ldt_free_entries( sel, count );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count; i++) ldt_set_entry( sel + (i << 3), entry );
|
||||
}
|
||||
return sel;
|
||||
}
|
||||
|
@ -73,15 +151,15 @@ WORD WINAPI AllocSelector16( WORD sel )
|
|||
WORD newsel, count, i;
|
||||
|
||||
count = sel ? get_sel_count(sel) : 1;
|
||||
newsel = wine_ldt_alloc_entries( count );
|
||||
newsel = alloc_entries( count );
|
||||
TRACE("(%04x): returning %04x\n", sel, newsel );
|
||||
if (!newsel) return 0;
|
||||
if (!sel) return newsel; /* nothing to copy */
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
wine_ldt_get_entry( sel + (i << __AHSHIFT), &entry );
|
||||
wine_ldt_set_entry( newsel + (i << __AHSHIFT), &entry );
|
||||
if (!ldt_get_entry( sel + (i << 3), &entry )) break;
|
||||
ldt_set_entry( newsel + (i << 3), entry );
|
||||
}
|
||||
return newsel;
|
||||
}
|
||||
|
@ -92,14 +170,11 @@ WORD WINAPI AllocSelector16( WORD sel )
|
|||
*/
|
||||
WORD WINAPI FreeSelector16( WORD sel )
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
WORD idx = sel >> 3;
|
||||
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
if (wine_ldt_is_empty( &entry )) return sel; /* error */
|
||||
/* Check if we are freeing current %fs selector */
|
||||
if (!((wine_get_fs() ^ sel) & ~3))
|
||||
WARN("Freeing %%fs selector (%04x), not good.\n", wine_get_fs() );
|
||||
wine_ldt_free_entries( sel, 1 );
|
||||
if (idx < first_ldt_entry) return sel; /* error */
|
||||
if (!RtlAreBitsSet( &ldt_bitmap, idx, 1 )) return sel; /* error */
|
||||
free_entries( sel, 1 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -109,23 +184,20 @@ WORD WINAPI FreeSelector16( WORD sel )
|
|||
*
|
||||
* Set the LDT entries for an array of selectors.
|
||||
*/
|
||||
static BOOL SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, unsigned char flags )
|
||||
static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, unsigned char flags )
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
WORD i, count;
|
||||
WORD i, count = (size + 0xffff) / 0x10000;
|
||||
|
||||
wine_ldt_set_base( &entry, base );
|
||||
wine_ldt_set_limit( &entry, size - 1 );
|
||||
wine_ldt_set_flags( &entry, flags );
|
||||
count = (size + 0xffff) / 0x10000;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry ) < 0) return FALSE;
|
||||
wine_ldt_set_base( &entry, (char*)wine_ldt_get_base(&entry) + 0x10000);
|
||||
/* yep, Windows sets limit like that, not 64K sel units */
|
||||
wine_ldt_set_limit( &entry, wine_ldt_get_limit(&entry) - 0x10000 );
|
||||
wine_ldt_set_base( &entry, base );
|
||||
wine_ldt_set_limit( &entry, size - 1 );
|
||||
ldt_set_entry( sel + (i << 3), entry );
|
||||
base = (const char *)base + 0x10000;
|
||||
size -= 0x10000; /* yep, Windows sets limit like that, not 64K sel units */
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -140,12 +212,7 @@ WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags )
|
|||
|
||||
if (!size) return 0;
|
||||
count = (size + 0xffff) / 0x10000;
|
||||
if ((sel = wine_ldt_alloc_entries( count )))
|
||||
{
|
||||
if (SELECTOR_SetEntries( sel, base, size, flags )) return sel;
|
||||
wine_ldt_free_entries( sel, count );
|
||||
sel = 0;
|
||||
}
|
||||
if ((sel = alloc_entries( count ))) SELECTOR_SetEntries( sel, base, size, flags );
|
||||
return sel;
|
||||
}
|
||||
|
||||
|
@ -157,10 +224,13 @@ WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags )
|
|||
*/
|
||||
void SELECTOR_FreeBlock( WORD sel )
|
||||
{
|
||||
WORD i, count = get_sel_count( sel );
|
||||
WORD idx = sel >> 3, count = get_sel_count( sel );
|
||||
|
||||
TRACE("(%04x,%d)\n", sel, count );
|
||||
for (i = 0; i < count; i++) FreeSelector16( sel + (i << __AHSHIFT) );
|
||||
|
||||
if (idx < first_ldt_entry) return; /* error */
|
||||
if (!RtlAreBitsSet( &ldt_bitmap, idx, count )) return; /* error */
|
||||
free_entries( sel, count );
|
||||
}
|
||||
|
||||
|
||||
|
@ -175,11 +245,28 @@ WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
|
|||
int oldcount, newcount;
|
||||
|
||||
if (!size) size = 1;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
if (!ldt_get_entry( sel, &entry )) return sel;
|
||||
oldcount = (wine_ldt_get_limit(&entry) >> 16) + 1;
|
||||
newcount = (size + 0xffff) >> 16;
|
||||
|
||||
sel = wine_ldt_realloc_entries( sel, oldcount, newcount );
|
||||
if (oldcount < newcount) /* we need to add selectors */
|
||||
{
|
||||
ULONG idx = sel >> 3;
|
||||
|
||||
if (RtlAreBitsClear( &ldt_bitmap, idx + oldcount, newcount - oldcount ))
|
||||
{
|
||||
RtlSetBits( &ldt_bitmap, idx + oldcount, newcount - oldcount );
|
||||
}
|
||||
else
|
||||
{
|
||||
free_entries( sel, oldcount );
|
||||
sel = alloc_entries( newcount );
|
||||
}
|
||||
}
|
||||
else if (oldcount > newcount)
|
||||
{
|
||||
free_entries( sel + (newcount << 3), oldcount - newcount );
|
||||
}
|
||||
if (sel) SELECTOR_SetEntries( sel, base, size, wine_ldt_get_flags(&entry) );
|
||||
return sel;
|
||||
}
|
||||
|
@ -191,10 +278,11 @@ WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
|
|||
WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
wine_ldt_get_entry( selSrc, &entry );
|
||||
|
||||
if (!ldt_get_entry( selSrc, &entry )) return selDst;
|
||||
/* toggle the executable bit */
|
||||
entry.HighWord.Bits.Type ^= (WINE_LDT_FLAGS_CODE ^ WINE_LDT_FLAGS_DATA);
|
||||
wine_ldt_set_entry( selDst, &entry );
|
||||
ldt_set_entry( selDst, entry );
|
||||
return selDst;
|
||||
}
|
||||
|
||||
|
@ -208,15 +296,13 @@ WORD WINAPI AllocCStoDSAlias16( WORD sel )
|
|||
WORD newsel;
|
||||
LDT_ENTRY entry;
|
||||
|
||||
newsel = wine_ldt_alloc_entries( 1 );
|
||||
TRACE("(%04x): returning %04x\n",
|
||||
sel, newsel );
|
||||
if (!ldt_get_entry( sel, &entry )) return 0;
|
||||
newsel = AllocSelector16( 0 );
|
||||
TRACE("(%04x): returning %04x\n", sel, newsel );
|
||||
if (!newsel) return 0;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
entry.HighWord.Bits.Type = WINE_LDT_FLAGS_DATA;
|
||||
if (wine_ldt_set_entry( newsel, &entry ) >= 0) return newsel;
|
||||
wine_ldt_free_entries( newsel, 1 );
|
||||
return 0;
|
||||
ldt_set_entry( newsel, entry );
|
||||
return newsel;
|
||||
}
|
||||
|
||||
|
||||
|
@ -228,15 +314,13 @@ WORD WINAPI AllocDStoCSAlias16( WORD sel )
|
|||
WORD newsel;
|
||||
LDT_ENTRY entry;
|
||||
|
||||
newsel = wine_ldt_alloc_entries( 1 );
|
||||
TRACE("(%04x): returning %04x\n",
|
||||
sel, newsel );
|
||||
if (!ldt_get_entry( sel, &entry )) return 0;
|
||||
newsel = AllocSelector16( 0 );
|
||||
TRACE("(%04x): returning %04x\n", sel, newsel );
|
||||
if (!newsel) return 0;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
entry.HighWord.Bits.Type = WINE_LDT_FLAGS_CODE;
|
||||
if (wine_ldt_set_entry( newsel, &entry ) >= 0) return newsel;
|
||||
wine_ldt_free_entries( newsel, 1 );
|
||||
return 0;
|
||||
ldt_set_entry( newsel, entry );
|
||||
return newsel;
|
||||
}
|
||||
|
||||
|
||||
|
@ -246,9 +330,10 @@ WORD WINAPI AllocDStoCSAlias16( WORD sel )
|
|||
void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
wine_ldt_get_entry( SELECTOROF(ptr), &entry );
|
||||
|
||||
if (!ldt_get_entry( SELECTOROF(ptr), &entry )) return;
|
||||
wine_ldt_set_base( &entry, (char *)wine_ldt_get_base(&entry) + add );
|
||||
wine_ldt_set_entry( SELECTOROF(ptr), &entry );
|
||||
ldt_set_entry( SELECTOROF(ptr), entry );
|
||||
}
|
||||
|
||||
|
||||
|
@ -272,9 +357,10 @@ DWORD WINAPI GetSelectorBase( WORD sel )
|
|||
WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
|
||||
if (!ldt_get_entry( sel, &entry )) return 0;
|
||||
wine_ldt_set_base( &entry, DOSMEM_MapDosToLinear(base) );
|
||||
if (wine_ldt_set_entry( sel, &entry ) < 0) sel = 0;
|
||||
ldt_set_entry( sel, entry );
|
||||
return sel;
|
||||
}
|
||||
|
||||
|
@ -294,9 +380,10 @@ DWORD WINAPI GetSelectorLimit16( WORD sel )
|
|||
WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
|
||||
if (!ldt_get_entry( sel, &entry )) return 0;
|
||||
wine_ldt_set_limit( &entry, limit );
|
||||
if (wine_ldt_set_entry( sel, &entry ) < 0) sel = 0;
|
||||
ldt_set_entry( sel, entry );
|
||||
return sel;
|
||||
}
|
||||
|
||||
|
@ -307,8 +394,8 @@ WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
|
|||
WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
|
||||
{
|
||||
LDT_ENTRY entry;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
|
||||
if (!ldt_get_entry( sel, &entry )) return 0;
|
||||
if (op == 0) /* get */
|
||||
{
|
||||
return entry.HighWord.Bytes.Flags1 | ((entry.HighWord.Bytes.Flags2 & 0xf0) << 8);
|
||||
|
@ -317,7 +404,7 @@ WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
|
|||
{
|
||||
entry.HighWord.Bytes.Flags1 = LOBYTE(val) | 0xf0;
|
||||
entry.HighWord.Bytes.Flags2 = (entry.HighWord.Bytes.Flags2 & 0x0f) | (HIBYTE(val) & 0xf0);
|
||||
wine_ldt_set_entry( sel, &entry );
|
||||
ldt_set_entry( sel, entry );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -326,18 +413,16 @@ WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
|
|||
/***********************************************************************
|
||||
* IsBadCodePtr (KERNEL.336)
|
||||
*/
|
||||
BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
|
||||
BOOL16 WINAPI IsBadCodePtr16( SEGPTR ptr )
|
||||
{
|
||||
WORD sel;
|
||||
WORD sel = SELECTOROF( ptr );
|
||||
LDT_ENTRY entry;
|
||||
|
||||
sel = SELECTOROF(lpfn);
|
||||
if (!sel) return TRUE;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
if (!ldt_get_entry( sel, &entry )) return TRUE;
|
||||
if (wine_ldt_is_empty( &entry )) return TRUE;
|
||||
/* check for code segment, ignoring conforming, read-only and accessed bits */
|
||||
if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_CODE) & 0x18) return TRUE;
|
||||
if (OFFSETOF(lpfn) > wine_ldt_get_limit(&entry)) return TRUE;
|
||||
if (OFFSETOF(ptr) > wine_ldt_get_limit(&entry)) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -347,12 +432,10 @@ BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
|
|||
*/
|
||||
BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
|
||||
{
|
||||
WORD sel;
|
||||
WORD sel = SELECTOROF( ptr );
|
||||
LDT_ENTRY entry;
|
||||
|
||||
sel = SELECTOROF(ptr);
|
||||
if (!sel) return TRUE;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
if (!ldt_get_entry( sel, &entry )) return TRUE;
|
||||
if (wine_ldt_is_empty( &entry )) return TRUE;
|
||||
/* check for data or readable code segment */
|
||||
if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
|
||||
|
@ -368,12 +451,10 @@ BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
|
|||
*/
|
||||
BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
|
||||
{
|
||||
WORD sel;
|
||||
WORD sel = SELECTOROF( ptr );
|
||||
LDT_ENTRY entry;
|
||||
|
||||
sel = SELECTOROF(ptr);
|
||||
if (!sel) return TRUE;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
if (!ldt_get_entry( sel, &entry )) return TRUE;
|
||||
if (wine_ldt_is_empty( &entry )) return TRUE;
|
||||
/* check for data or readable code segment */
|
||||
if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
|
||||
|
@ -388,12 +469,10 @@ BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
|
|||
*/
|
||||
BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
|
||||
{
|
||||
WORD sel;
|
||||
WORD sel = SELECTOROF( ptr );
|
||||
LDT_ENTRY entry;
|
||||
|
||||
sel = SELECTOROF(ptr);
|
||||
if (!sel) return TRUE;
|
||||
wine_ldt_get_entry( sel, &entry );
|
||||
if (!ldt_get_entry( sel, &entry )) return TRUE;
|
||||
if (wine_ldt_is_empty( &entry )) return TRUE;
|
||||
/* check for writable data segment, ignoring expand-down and accessed flags */
|
||||
if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_DATA) & ~5) return TRUE;
|
||||
|
|
|
@ -57,14 +57,10 @@ static SEGPTR call16_ret_addr; /* segptr to __wine_call_to_16_ret routine */
|
|||
BOOL WOWTHUNK_Init(void)
|
||||
{
|
||||
/* allocate the code selector for CallTo16 routines */
|
||||
LDT_ENTRY entry;
|
||||
WORD codesel = wine_ldt_alloc_entries(1);
|
||||
|
||||
WORD codesel = SELECTOR_AllocBlock( __wine_call16_start,
|
||||
(BYTE *)(&CallTo16_TebSelector + 1) - __wine_call16_start,
|
||||
WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
|
||||
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 */
|
||||
|
||||
|
@ -116,7 +112,7 @@ static BOOL fix_selector( CONTEXT *context )
|
|||
default:
|
||||
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 );
|
||||
*stack = 0;
|
||||
return TRUE;
|
||||
|
@ -141,7 +137,7 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RE
|
|||
else if (record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
|
||||
record->ExceptionCode == EXCEPTION_PRIV_INSTRUCTION)
|
||||
{
|
||||
if (wine_ldt_is_system(context->SegCs))
|
||||
if (ldt_is_system(context->SegCs))
|
||||
{
|
||||
if (fix_selector( context )) return ExceptionContinueExecution;
|
||||
}
|
||||
|
@ -155,7 +151,7 @@ static DWORD call16_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RE
|
|||
/* check for Win16 __GP handler */
|
||||
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->Eip;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue