Commit 914406f8 authored by Alexandre Julliard's avatar Alexandre Julliard

Moved LDT handling to libwine.so. Changed the interface to use the

exported LDT_ENTRY structure.
parent 41d6e2fe
......@@ -56,7 +56,7 @@ static BOOL process_attach(void)
#define SET_ENTRY_POINT( num, addr ) \
NE_SetEntryPoint( hModule, (num), GLOBAL_CreateBlock( GMEM_FIXED, \
DOSMEM_MapDosToLinear(addr), 0x10000, hModule, \
FALSE, FALSE, FALSE ))
WINE_LDT_FLAGS_DATA ))
SET_ENTRY_POINT( 174, 0xa0000 ); /* KERNEL.174: __A000H */
SET_ENTRY_POINT( 181, 0xb0000 ); /* KERNEL.181: __B000H */
......
......@@ -1012,7 +1012,7 @@ AllocSLCallback(
*(DWORD*)(thunk+18) = GetCurrentProcessId();
sel = SELECTOR_AllocBlock( thunk , 32, SEGMENT_CODE, FALSE, FALSE );
sel = SELECTOR_AllocBlock( thunk, 32, WINE_LDT_FLAGS_CODE );
return (sel<<16)|0;
}
......
......@@ -4925,9 +4925,8 @@ LRESULT WINAPI DefDriverProc(DWORD dwDriverIdentifier, HDRVR hDrv,
*/
HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
{
DWORD showCmd = 0x40002;
DWORD *pShowCmd;
LPSTR cmdline;
WORD sel1, sel2;
LOADPARAMS16* lp;
HINSTANCE16 ret;
HINSTANCE16 handle;
......@@ -4942,20 +4941,19 @@ HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD d
*/
FIXME("This is currently broken. It will fail\n");
cmdline = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 0x0d);
cmdline = SEGPTR_ALLOC(0x0d);
cmdline[0] = 0x0d;
*(LPDWORD)(cmdline + 1) = (DWORD)spProc;
*(LPDWORD)(cmdline + 5) = dwPmt;
*(LPDWORD)(cmdline + 9) = 0;
sel1 = SELECTOR_AllocBlock(cmdline, 0x0d, SEGMENT_DATA, FALSE, FALSE);
sel2 = SELECTOR_AllocBlock(&showCmd, sizeof(showCmd),
SEGMENT_DATA, FALSE, FALSE);
pShowCmd = SEGPTR_ALLOC(sizeof(DWORD));
*pShowCmd = 0x40002;
lp = (LOADPARAMS16*)HeapAlloc(GetProcessHeap(), 0, sizeof(LOADPARAMS16));
lp->hEnvironment = 0;
lp->cmdLine = PTR_SEG_OFF_TO_SEGPTR(sel1, 0);
lp->showCmd = PTR_SEG_OFF_TO_SEGPTR(sel2, 0);
lp->cmdLine = SEGPTR_GET(cmdline);
lp->showCmd = SEGPTR_GET(pShowCmd);
lp->reserved = 0;
#ifndef USE_MM_TSK_WINE
......@@ -4971,12 +4969,10 @@ HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD d
}
if (lphMmTask)
*lphMmTask = handle;
UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel2, 0));
UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel1, 0));
HeapFree(GetProcessHeap(), 0, lp);
HeapFree(GetProcessHeap(), 0, cmdline);
SEGPTR_FREE(pShowCmd);
SEGPTR_FREE(cmdline);
TRACE("=> 0x%04x/%d\n", handle, ret);
return ret;
......
......@@ -3324,8 +3324,7 @@ HBITMAP16 X11DRV_DIB_CreateDIBSection16(
if ( dib->dsBm.bmBits )
{
((X11DRV_DIBSECTION *) bmp->dib)->selector =
SELECTOR_AllocBlock( dib->dsBm.bmBits, size,
SEGMENT_DATA, FALSE, FALSE );
SELECTOR_AllocBlock( dib->dsBm.bmBits, size, WINE_LDT_FLAGS_DATA );
}
TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
......@@ -3600,12 +3599,8 @@ void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
if (dib->colorMap)
HeapFree(GetProcessHeap(), 0, dib->colorMap);
if (dib->selector)
{
WORD count = (GetSelectorLimit16( dib->selector ) >> 16) + 1;
SELECTOR_FreeBlock( dib->selector, count );
}
if (dib->selector) SELECTOR_FreeBlock( dib->selector );
}
......
......@@ -60,8 +60,7 @@ static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
HMODULE16 hModule;
hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
descr->module_size, 0,
FALSE, FALSE, FALSE );
descr->module_size, 0, WINE_LDT_FLAGS_DATA );
if (!hModule) return 0;
FarSetOwner16( hModule, hModule );
......@@ -76,7 +75,8 @@ static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
pSegTable = NE_SEG_TABLE( pModule );
pSegTable->hSeg = GLOBAL_CreateBlock( GMEM_FIXED, descr->code_start,
pSegTable->minsize, hModule, TRUE, TRUE, FALSE );
pSegTable->minsize, hModule,
WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT );
if (!pSegTable->hSeg) return 0;
patch_code_segment( descr->code_start );
pSegTable++;
......@@ -86,8 +86,7 @@ static HMODULE16 BUILTIN_DoLoadModule16( const BUILTIN16_DESCRIPTOR *descr )
minsize = pSegTable->minsize ? pSegTable->minsize : 0x10000;
minsize += pModule->heap_size;
if (minsize > 0x10000) minsize = 0x10000;
pSegTable->hSeg = GLOBAL_Alloc( GMEM_FIXED, minsize,
hModule, FALSE, FALSE, FALSE );
pSegTable->hSeg = GLOBAL_Alloc( GMEM_FIXED, minsize, hModule, WINE_LDT_FLAGS_DATA );
if (!pSegTable->hSeg) return 0;
if (pSegTable->minsize) memcpy( GlobalLock16( pSegTable->hSeg ),
descr->data_start, pSegTable->minsize);
......
......@@ -42,7 +42,7 @@ BOOL RELAY_Init(void)
codesel = SELECTOR_AllocBlock( (void *)Call16_Ret_Start,
(char *)Call16_Ret_End - (char *)Call16_Ret_Start,
SEGMENT_CODE, TRUE, FALSE );
WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
if (!codesel) return FALSE;
/* Patch the return addresses for CallTo16 routines */
......
......@@ -91,7 +91,7 @@ SNOOP16_RegisterDLL(NE_MODULE *pModule,LPCSTR name) {
if (!TRACE_ON(snoop)) return;
if (!snr) {
xsnr=GLOBAL_Alloc(GMEM_ZEROINIT,2*sizeof(*snr),0,TRUE,TRUE,FALSE);
xsnr=GLOBAL_Alloc(GMEM_ZEROINIT,2*sizeof(*snr),0,WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT);
snr = GlobalLock16(xsnr);
snr[0].pushbp = 0x5566;
snr[0].pusheax = 0x50;
......@@ -126,14 +126,13 @@ SNOOP16_RegisterDLL(NE_MODULE *pModule,LPCSTR name) {
(*dll)->name = HEAP_strdupA(GetProcessHeap(),0,name);
if ((s=strrchr((*dll)->name,'.')))
*s='\0';
(*dll)->funhandle = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT,65535,0,TRUE,FALSE,FALSE));
(*dll)->funhandle = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT,65535,0,WINE_LDT_FLAGS_CODE));
(*dll)->funs = GlobalLock16((*dll)->funhandle);
if (!(*dll)->funs) {
HeapFree(GetProcessHeap(),0,*dll);
FIXME("out of memory\n");
return;
}
memset((*dll)->funs,0,65535);
}
FARPROC16
......@@ -240,9 +239,8 @@ void WINAPI SNOOP16_Entry(FARPROC proc, LPBYTE args, CONTEXT86 *context) {
rets = &((*rets)->next);
}
if (!*rets) {
HANDLE16 hand = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT,65535,0,TRUE,FALSE,FALSE));
HANDLE16 hand = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT,65535,0,WINE_LDT_FLAGS_CODE));
*rets = GlobalLock16(hand);
memset(*rets,0,65535);
(*rets)->rethandle = hand;
i = 0; /* entry 0 is free */
}
......
......@@ -9,7 +9,6 @@
#include "windef.h"
#include "wine/windef16.h"
#include "ldt.h"
struct _CONTEXT86;
struct _STACK16FRAME;
......
......@@ -12,13 +12,10 @@
/* memory/global.c */
extern HGLOBAL16 GLOBAL_CreateBlock( UINT16 flags, const void *ptr, DWORD size,
HGLOBAL16 hOwner, BOOL16 isCode,
BOOL16 is32Bit, BOOL16 isReadOnly);
HGLOBAL16 hOwner, unsigned char selflags );
extern BOOL16 GLOBAL_FreeBlock( HGLOBAL16 handle );
extern BOOL16 GLOBAL_MoveBlock( HGLOBAL16 handle, const void *ptr, DWORD size );
extern HGLOBAL16 GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL16 hOwner,
BOOL16 isCode, BOOL16 is32Bit,
BOOL16 isReadOnly );
extern HGLOBAL16 GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL16 hOwner, unsigned char selflags );
/* memory/virtual.c */
extern DWORD VIRTUAL_GetPageSize(void);
......
......@@ -8,58 +8,15 @@
#define __WINE_LDT_H
#include "windef.h"
enum seg_type
{
SEGMENT_DATA = 0,
SEGMENT_STACK = 1,
SEGMENT_CODE = 2
};
/* This structure represents a real LDT entry. */
/* It is used by get_ldt_entry() and set_ldt_entry(). */
typedef struct
{
unsigned long base; /* base address */
unsigned long limit; /* segment limit (in pages or bytes) */
int seg_32bit; /* is segment 32-bit? */
int read_only; /* is segment read-only? */
int limit_in_pages; /* is the limit in pages or bytes? */
enum seg_type type; /* segment type */
} ldt_entry;
extern void LDT_BytesToEntry( const unsigned long *buffer, ldt_entry *content);
extern void LDT_EntryToBytes( unsigned long *buffer, const ldt_entry *content);
extern int LDT_GetEntry( int entry, ldt_entry *content );
extern int LDT_SetEntry( int entry, const ldt_entry *content );
extern void LDT_Print( int start, int length );
/* This structure is used to build the local copy of the LDT. */
typedef struct
{
unsigned long base; /* base address or 0 if entry is free */
unsigned long limit; /* limit in bytes or 0 if entry is free */
} ldt_copy_entry;
#define LDT_SIZE 8192
extern ldt_copy_entry ldt_copy[LDT_SIZE];
#include "wine/library.h"
#define __AHSHIFT 3 /* don't change! */
#define __AHINCR (1 << __AHSHIFT)
#define SELECTOR_TO_ENTRY(sel) (((int)(sel) & 0xffff) >> __AHSHIFT)
#define ENTRY_TO_SELECTOR(i) ((i) ? (((int)(i) << __AHSHIFT) | 7) : 0)
#define IS_LDT_ENTRY_FREE(i) (!(ldt_flags_copy[(i)] & LDT_FLAGS_ALLOCATED))
#define IS_SELECTOR_FREE(sel) (IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)))
#define GET_SEL_BASE(sel) (ldt_copy[SELECTOR_TO_ENTRY(sel)].base)
#define GET_SEL_LIMIT(sel) (ldt_copy[SELECTOR_TO_ENTRY(sel)].limit)
/* Convert a segmented ptr (16:16) to a linear (32) pointer */
#define PTR_SEG_OFF_TO_LIN(seg,off) \
((void*)(GET_SEL_BASE(seg) + (unsigned int)(off)))
((void*)((char*)wine_ldt_copy.base[LOWORD(seg) >> __AHSHIFT] + (unsigned int)(off)))
#define PTR_REAL_TO_LIN(seg,off) \
((void*)(((unsigned int)(seg) << 4) + LOWORD(off)))
#define PTR_SEG_TO_LIN(ptr) \
......@@ -74,23 +31,14 @@ extern ldt_copy_entry ldt_copy[LDT_SIZE];
#define W32S_APP2WINE(addr, offset) ((addr)? (DWORD)(addr) + (DWORD)(offset) : 0)
#define W32S_WINE2APP(addr, offset) ((addr)? (DWORD)(addr) - (DWORD)(offset) : 0)
extern unsigned char ldt_flags_copy[LDT_SIZE];
#define LDT_FLAGS_TYPE 0x03 /* Mask for segment type */
#define LDT_FLAGS_READONLY 0x04 /* Segment is read-only (data) */
#define LDT_FLAGS_EXECONLY 0x04 /* Segment is execute-only (code) */
#define LDT_FLAGS_32BIT 0x08 /* Segment is 32-bit (code or stack) */
#define LDT_FLAGS_BIG 0x10 /* Segment is big (limit is in pages) */
#define LDT_FLAGS_ALLOCATED 0x80 /* Segment is allocated (no longer free) */
#define GET_SEL_FLAGS(sel) (ldt_flags_copy[SELECTOR_TO_ENTRY(sel)])
#define FIRST_LDT_ENTRY_TO_ALLOC 17
#define IS_SELECTOR_FREE(sel) (!(wine_ldt_copy.flags[LOWORD(sel) >> __AHSHIFT] & WINE_LDT_FLAGS_ALLOCATED))
/* Determine if sel is a system selector (i.e. not managed by Wine) */
#define IS_SELECTOR_SYSTEM(sel) \
(!((sel) & 4) || (SELECTOR_TO_ENTRY(sel) < FIRST_LDT_ENTRY_TO_ALLOC))
(!((sel) & 4) || ((LOWORD(sel) >> __AHSHIFT) < FIRST_LDT_ENTRY_TO_ALLOC))
#define IS_SELECTOR_32BIT(sel) \
(IS_SELECTOR_SYSTEM(sel) || (GET_SEL_FLAGS(sel) & LDT_FLAGS_32BIT))
(IS_SELECTOR_SYSTEM(sel) || (wine_ldt_copy.flags[LOWORD(sel) >> __AHSHIFT] & WINE_LDT_FLAGS_32BIT))
#endif /* __WINE_LDT_H */
......@@ -10,12 +10,9 @@
#include "windef.h"
#include "ldt.h"
extern WORD SELECTOR_AllocBlock( const void *base, DWORD size,
enum seg_type type, BOOL is32bit,
BOOL readonly );
extern WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags );
extern WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size );
extern void SELECTOR_MoveBlock( WORD sel, const void *new_base );
extern void SELECTOR_FreeBlock( WORD sel, WORD count );
extern void SELECTOR_FreeBlock( WORD sel );
#ifdef __i386__
# ifdef __GNUC__
......
......@@ -178,7 +178,6 @@ struct init_process_request
{
REQUEST_HEADER; /* request header */
IN void* ldt_copy; /* addr of LDT copy */
IN void* ldt_flags; /* addr of LDT flags */
IN int ppid; /* parent Unix pid */
OUT int start_flags; /* flags from startup info */
OUT unsigned int server_start; /* server start time (GetTickCount) */
......@@ -1592,7 +1591,7 @@ union generic_request
struct async_result_request async_result;
};
#define SERVER_PROTOCOL_VERSION 27
#define SERVER_PROTOCOL_VERSION 28
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
......
......@@ -8,6 +8,7 @@
#define __WINE_WINE_LIBRARY_H
#include <sys/types.h>
#include "winbase.h"
/* dll loading */
......@@ -26,4 +27,65 @@ extern void wine_dbg_add_option( const char *name, unsigned char set, unsigned c
extern void *wine_anon_mmap( void *start, size_t size, int prot, int flags );
/* LDT management */
extern void wine_ldt_get_entry( unsigned short sel, LDT_ENTRY *entry );
extern int wine_ldt_set_entry( unsigned short sel, const LDT_ENTRY *entry );
/* the local copy of the LDT */
extern struct __wine_ldt_copy
{
void *base[8192]; /* base address or 0 if entry is free */
unsigned long limit[8192]; /* limit in bytes or 0 if entry is free */
unsigned char flags[8192]; /* flags (defined below) */
} wine_ldt_copy;
#define WINE_LDT_FLAGS_DATA 0x13 /* Data segment */
#define WINE_LDT_FLAGS_STACK 0x17 /* Stack segment */
#define WINE_LDT_FLAGS_CODE 0x1b /* Code segment */
#define WINE_LDT_FLAGS_TYPE_MASK 0x1f /* Mask for segment type */
#define WINE_LDT_FLAGS_32BIT 0x40 /* Segment is 32-bit (code or stack) */
#define WINE_LDT_FLAGS_ALLOCATED 0x80 /* Segment is allocated (no longer free) */
/* helper functions to manipulate the LDT_ENTRY structure */
inline static void wine_ldt_set_base( LDT_ENTRY *ent, const void *base )
{
ent->BaseLow = (WORD)(unsigned long)base;
ent->HighWord.Bits.BaseMid = (BYTE)((unsigned long)base >> 16);
ent->HighWord.Bits.BaseHi = (BYTE)((unsigned long)base >> 24);
}
inline static void wine_ldt_set_limit( LDT_ENTRY *ent, unsigned int limit )
{
if ((ent->HighWord.Bits.Granularity = (limit >= 0x100000))) limit >>= 12;
ent->LimitLow = (WORD)limit;
ent->HighWord.Bits.LimitHi = (limit >> 16);
}
inline static void *wine_ldt_get_base( const LDT_ENTRY *ent )
{
return (void *)(ent->BaseLow |
(unsigned long)ent->HighWord.Bits.BaseMid << 16 |
(unsigned long)ent->HighWord.Bits.BaseHi << 24);
}
inline static unsigned int wine_ldt_get_limit( const LDT_ENTRY *ent )
{
unsigned int limit = ent->LimitLow | (ent->HighWord.Bits.LimitHi << 16);
if (ent->HighWord.Bits.Granularity) limit = (limit << 12) | 0xfff;
return limit;
}
inline static void wine_ldt_set_flags( LDT_ENTRY *ent, unsigned char flags )
{
ent->HighWord.Bits.Dpl = 3;
ent->HighWord.Bits.Pres = 1;
ent->HighWord.Bits.Type = flags;
ent->HighWord.Bits.Sys = 0;
ent->HighWord.Bits.Reserved_0 = 0;
ent->HighWord.Bits.Default_Big = (flags & WINE_LDT_FLAGS_32BIT) != 0;
}
inline static unsigned char wine_ldt_get_flags( const LDT_ENTRY *ent )
{
unsigned char ret = ent->HighWord.Bits.Type;
if (ent->HighWord.Bits.Default_Big) ret |= WINE_LDT_FLAGS_32BIT;
return ret;
}
#endif /* __WINE_WINE_LIBRARY_H */
......@@ -10,6 +10,7 @@ SONAME = libwine.so
C_SRCS = \
debug.c \
ldt.c \
loader.c \
port.c
......
/*
* LDT manipulation functions
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Alexandre Julliard
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "winbase.h"
#include "wine/library.h"
#ifdef __i386__
#ifdef linux
#ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
struct modify_ldt_s
{
unsigned int entry_number;
unsigned long base_addr;
unsigned int limit;
unsigned int seg_32bit : 1;
unsigned int contents : 2;
unsigned int read_exec_only : 1;
unsigned int limit_in_pages : 1;
unsigned int seg_not_present : 1;
};
static inline int modify_ldt( int func, struct modify_ldt_s *ptr,
unsigned long count )
{
int res;
#ifdef __PIC__
__asm__ __volatile__( "pushl %%ebx\n\t"
"movl %2,%%ebx\n\t"
"int $0x80\n\t"
"popl %%ebx"
: "=a" (res)
: "0" (SYS_modify_ldt),
"r" (func),
"c" (ptr),
"d" (count) );
#else
__asm__ __volatile__("int $0x80"
: "=a" (res)
: "0" (SYS_modify_ldt),
"b" (func),
"c" (ptr),
"d" (count) );
#endif /* __PIC__ */
if (res >= 0) return res;
errno = -res;
return -1;
}
#endif /* linux */
#if defined(__svr4__) || defined(_SCO_DS)
#include <sys/sysi86.h>
extern int sysi86(int,void*);
#ifndef __sun__
#include <sys/seg.h>
#endif
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <machine/segments.h>
extern int i386_get_ldt(int, union descriptor *, int);
extern int i386_set_ldt(int, union descriptor *, int);
#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
#endif /* __i386__ */
/* local copy of the LDT */
struct __wine_ldt_copy wine_ldt_copy;
/***********************************************************************
* ldt_get_entry
*
* Retrieve an LDT entry.
*/
void wine_ldt_get_entry( unsigned short sel, LDT_ENTRY *entry )
{
int index = sel >> 3;
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] );
}
/***********************************************************************
* ldt_set_entry
*
* Set an LDT entry.
*/
int wine_ldt_set_entry( unsigned short sel, const LDT_ENTRY *entry )
{
int ret = 0, index = sel >> 3;
/* Entry 0 must not be modified; its base and limit are always 0 */
if (!index) return 0;
#ifdef __i386__
#ifdef linux
{
struct modify_ldt_s ldt_info;
ldt_info.entry_number = index;
ldt_info.base_addr = (unsigned long)wine_ldt_get_base(entry);
ldt_info.limit = entry->LimitLow | (entry->HighWord.Bits.LimitHi << 16);
ldt_info.seg_32bit = entry->HighWord.Bits.Default_Big;
ldt_info.contents = (entry->HighWord.Bits.Type >> 2) & 3;
ldt_info.read_exec_only = !(entry->HighWord.Bits.Type & 2);
ldt_info.limit_in_pages = entry->HighWord.Bits.Granularity;
ldt_info.seg_not_present = !entry->HighWord.Bits.Pres;
if ((ret = modify_ldt(1, &ldt_info, sizeof(ldt_info))) < 0)
perror( "modify_ldt" );
}
#endif /* linux */
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
{
ret = i386_set_ldt(index, (union descriptor *)entry, 1);
if (ret < 0)
{
perror("i386_set_ldt");
fprintf( stderr, "Did you reconfigure the kernel with \"options USER_LDT\"?\n" );
exit(1);
}
}
#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
#if defined(__svr4__) || defined(_SCO_DS)
{
struct ssd ldt_mod;
ldt_mod.sel = sel;
ldt_mod.bo = (unsigned long)wine_ldt_get_base(entry);
ldt_mod.ls = entry->LimitLow | (entry->HighWord.Bits.LimitHi << 16);
ldt_mod.acc1 = entry->HighWord.Bytes.Flags1;
ldt_mod.acc2 = entry->HighWord.Bytes.Flags2 >> 4;
if ((ret = sysi86(SI86DSCR, &ldt_mod)) == -1) perror("sysi86");
}
#endif
#endif /* __i386__ */
if (ret >= 0)
{
wine_ldt_copy.base[index] = wine_ldt_get_base(entry);
wine_ldt_copy.limit[index] = wine_ldt_get_limit(entry);
wine_ldt_copy.flags[index] = (entry->HighWord.Bits.Type |
(entry->HighWord.Bits.Default_Big ? WINE_LDT_FLAGS_32BIT : 0) |
(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED));
}
return ret;
}
......@@ -737,7 +737,7 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (ne_header.ne_cbnrestab)
{
pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.ne_cbnrestab,
hModule, FALSE, FALSE, FALSE );
hModule, WINE_LDT_FLAGS_DATA );
if (!pModule->nrname_handle)
{
GlobalFree16( hModule );
......@@ -763,7 +763,7 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
{
pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
(pModule->modref_count+1)*sizeof(HMODULE16),
hModule, FALSE, FALSE, FALSE );
hModule, WINE_LDT_FLAGS_DATA );
if (!pModule->dlls_to_init)
{
if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
......
......@@ -380,7 +380,7 @@ HGLOBAL16 WINAPI AllocResource16( HMODULE16 hModule, HRSRC16 hRsrc, DWORD size)
pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
if (size < (DWORD)pNameInfo->length << sizeShift)
size = (DWORD)pNameInfo->length << sizeShift;
return GLOBAL_Alloc( GMEM_FIXED, size, hModule, FALSE, FALSE, FALSE );
return GLOBAL_Alloc( GMEM_FIXED, size, hModule, WINE_LDT_FLAGS_DATA );
}
......@@ -398,7 +398,7 @@ HGLOBAL16 WINAPI DirectResAlloc16( HINSTANCE16 hInstance, WORD wType,
if(wType != 0x10) /* 0x10 is the only observed value, passed from
CreateCursorIndirect. */
TRACE("(wType=%x)\n", wType);
return GLOBAL_Alloc(GMEM_MOVEABLE, wSize, hInstance, FALSE, FALSE, FALSE);
return GLOBAL_Alloc(GMEM_MOVEABLE, wSize, hInstance, WINE_LDT_FLAGS_DATA );
}
......
......@@ -410,7 +410,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28);
selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
pModule->self_loading_sel = SEL(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
pModule->self_loading_sel = SEL(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, WINE_LDT_FLAGS_DATA));
oldstack = NtCurrentTeb()->cur_stack;
NtCurrentTeb()->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
0xff00 - sizeof(STACK16FRAME) );
......@@ -845,6 +845,7 @@ BOOL NE_CreateSegment( NE_MODULE *pModule, int segnum )
{
SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule ) + segnum - 1;
int minsize;
unsigned char selflags;
assert( !(pModule->flags & NE_FFLAGS_WIN32) );
......@@ -861,11 +862,9 @@ BOOL NE_CreateSegment( NE_MODULE *pModule, int segnum )
if ( segnum == pModule->ss ) minsize += pModule->stack_size;
if ( segnum == pModule->dgroup ) minsize += pModule->heap_size;
pSeg->hSeg = GLOBAL_Alloc( NE_Ne2MemFlags(pSeg->flags),
minsize, pModule->self,
!(pSeg->flags & NE_SEGFLAGS_DATA),
(pSeg->flags & NE_SEGFLAGS_32BIT) != 0,
FALSE /*pSeg->flags & NE_SEGFLAGS_READONLY*/ );
selflags = (pSeg->flags & NE_SEGFLAGS_DATA) ? WINE_LDT_FLAGS_DATA : WINE_LDT_FLAGS_CODE;
if (pSeg->flags & NE_SEGFLAGS_32BIT) selflags |= WINE_LDT_FLAGS_32BIT;
pSeg->hSeg = GLOBAL_Alloc( NE_Ne2MemFlags(pSeg->flags), minsize, pModule->self, selflags );
if (!pSeg->hSeg) return FALSE;
pSeg->flags |= NE_SEGFLAGS_ALLOCATED;
......
......@@ -169,7 +169,7 @@ static SEGPTR TASK_AllocThunk( HTASK16 hTask )
if (!sel) /* Allocate a new segment */
{
sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(THUNKS) + (MIN_THUNKS-1)*8,
pTask->hPDB, TRUE, FALSE, FALSE );
pTask->hPDB, WINE_LDT_FLAGS_CODE );
if (!sel) return (SEGPTR)0;
TASK_CreateThunks( sel, 0, MIN_THUNKS );
pThunk->next = sel;
......@@ -228,7 +228,7 @@ BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline,
/* Allocate the task structure */
hTask = GLOBAL_Alloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB),
pModule->self, FALSE, FALSE, FALSE );
pModule->self, WINE_LDT_FLAGS_DATA );
if (!hTask) return FALSE;
pTask = (TDB *)GlobalLock16( hTask );
......@@ -268,7 +268,7 @@ BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline,
/* Allocate a selector for the PDB */
pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB16),
pModule->self, FALSE, FALSE, FALSE );
pModule->self, WINE_LDT_FLAGS_DATA );
/* Fill the PDB */
......@@ -313,8 +313,7 @@ BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline,
/* Allocate a code segment alias for the TDB */
pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask,
sizeof(TDB), pTask->hPDB, TRUE,
FALSE, FALSE );
sizeof(TDB), pTask->hPDB, WINE_LDT_FLAGS_CODE );
/* Set the owner of the environment block */
......
......@@ -12,7 +12,6 @@ C_SRCS = \
global.c \
heap.c \
instr.c \
ldt.c \
local.c \
registry.c \
selector.c \
......
......@@ -123,7 +123,7 @@ BOOL ENV_BuildEnvironment(void)
if (!(p = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
current_envdb.environ = p;
current_envdb.env_sel = SELECTOR_AllocBlock( p, 0x10000, SEGMENT_DATA, FALSE, FALSE );
current_envdb.env_sel = SELECTOR_AllocBlock( p, 0x10000, WINE_LDT_FLAGS_DATA );
/* And fill it with the Unix environment */
......@@ -302,7 +302,8 @@ BOOL WINAPI SetEnvironmentVariableA( LPCSTR name, LPCSTR value )
if (!(new_env = HeapReAlloc( GetProcessHeap(), 0, env, old_size + len )))
goto done;
if (current_envdb.env_sel)
SELECTOR_MoveBlock( current_envdb.env_sel, new_env );
current_envdb.env_sel = SELECTOR_ReallocBlock( current_envdb.env_sel,
new_env, old_size + len );
p = new_env + (p - env);
if (len > 0) memmove( p + len, p, old_size - (p - new_env) );
......
......@@ -112,24 +112,20 @@ void debug_handles(void)
* Create a global heap block for a fixed range of linear memory.
*/
HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
HGLOBAL16 hOwner, BOOL16 isCode,
BOOL16 is32Bit, BOOL16 isReadOnly )
HGLOBAL16 hOwner, unsigned char selflags )
{
WORD sel, selcount;
GLOBALARENA *pArena;
/* Allocate the selector(s) */
sel = SELECTOR_AllocBlock( ptr, size,
isCode ? SEGMENT_CODE : SEGMENT_DATA,
is32Bit, isReadOnly );
sel = SELECTOR_AllocBlock( ptr, size, selflags );
if (!sel) return 0;
selcount = (size + 0xffff) / 0x10000;
if (!(pArena = GLOBAL_GetArena( sel, selcount )))
{
SELECTOR_FreeBlock( sel, selcount );
SELECTOR_FreeBlock( sel );
return 0;
}
......@@ -144,7 +140,7 @@ HGLOBAL16 GLOBAL_CreateBlock( WORD flags, const void *ptr, DWORD size,
pArena->flags = flags & GA_MOVEABLE;
if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
if (flags & GMEM_DDESHARE) pArena->flags |= GA_IPCSHARE;
if (!isCode) pArena->flags |= GA_DGROUP;
if (!(selflags & (WINE_LDT_FLAGS_CODE^WINE_LDT_FLAGS_DATA))) pArena->flags |= GA_DGROUP;
pArena->selCount = selcount;
if (selcount > 1) /* clear the next arena blocks */
memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
......@@ -169,7 +165,7 @@ BOOL16 GLOBAL_FreeBlock( HGLOBAL16 handle )
if (!VALID_HANDLE(sel))
return FALSE;
pArena = GET_ARENA_PTR(sel);
SELECTOR_FreeBlock( sel, (pArena->size + 0xffff) / 0x10000 );
SELECTOR_FreeBlock( sel );
memset( pArena, 0, sizeof(GLOBALARENA) );
return TRUE;
}
......@@ -192,10 +188,7 @@ BOOL16 GLOBAL_MoveBlock( HGLOBAL16 handle, const void *ptr, DWORD size )
pArena->base = (DWORD)ptr;
pArena->size = size;
SELECTOR_MoveBlock( sel, ptr );
SetSelectorLimit16( sel, size-1 );
SELECTOR_ReallocBlock( sel, ptr, size );
return TRUE;
}
......@@ -204,8 +197,7 @@ BOOL16 GLOBAL_MoveBlock( HGLOBAL16 handle, const void *ptr, DWORD size )
*
* Implementation of GlobalAlloc16()
*/
HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
BOOL16 isCode, BOOL16 is32Bit, BOOL16 isReadOnly )
HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner, unsigned char selflags )
{
void *ptr;
HGLOBAL16 handle;
......@@ -214,8 +206,7 @@ HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
/* If size is 0, create a discarded block */
if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, isCode,
is32Bit, isReadOnly );
if (size == 0) return GLOBAL_CreateBlock( flags, NULL, 1, hOwner, selflags );
/* Fixup the size */
......@@ -229,8 +220,7 @@ HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
/* Allocate the selector(s) */
handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
isCode, is32Bit, isReadOnly );
handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner, selflags );
if (!handle)
{
HeapFree( GetProcessHeap(), 0, ptr );
......@@ -255,7 +245,7 @@ HGLOBAL16 WINAPI GlobalAlloc16(
if (flags & GMEM_DDESHARE)
owner = GetExePtr(owner); /* Make it a module handle */
return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
return GLOBAL_Alloc( flags, size, owner, WINE_LDT_FLAGS_DATA );
}
......@@ -333,7 +323,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
ptr = HeapReAlloc( GetProcessHeap(), 0, ptr, size );
if (!ptr)
{
SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
SELECTOR_FreeBlock( sel );
memset( pArena, 0, sizeof(GLOBALARENA) );
return 0;
}
......@@ -352,7 +342,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
{
HeapFree( GetProcessHeap(), 0, ptr );
SELECTOR_FreeBlock( sel, selcount );
SELECTOR_FreeBlock( sel );
return 0;
}
......@@ -699,8 +689,7 @@ DWORD WINAPI GlobalDOSAlloc16(
WORD wSelector;
GLOBALARENA *pArena;
wSelector = GLOBAL_CreateBlock(GMEM_FIXED, lpBlock, size,
hModule, 0, 0, 0 );
wSelector = GLOBAL_CreateBlock(GMEM_FIXED, lpBlock, size, hModule, WINE_LDT_FLAGS_DATA );
pArena = GET_ARENA_PTR(wSelector);
pArena->flags |= GA_DOSMEM;
return MAKELONG(wSelector,uParagraph);
......
......@@ -484,10 +484,13 @@ static BOOL HEAP_InitSubHeap( HEAP *heap, LPVOID address, DWORD flags,
if (flags & HEAP_WINE_SEGPTR)
{
selector = SELECTOR_AllocBlock( address, totalSize,
(flags & (HEAP_WINE_CODESEG|HEAP_WINE_CODE16SEG))
? SEGMENT_CODE : SEGMENT_DATA,
(flags & HEAP_WINE_CODESEG) != 0, FALSE );
unsigned char selflags = WINE_LDT_FLAGS_DATA;
if (flags & (HEAP_WINE_CODESEG | HEAP_WINE_CODE16SEG))
selflags = WINE_LDT_FLAGS_CODE;
if (flags & HEAP_WINE_CODESEG)
selflags |= WINE_LDT_FLAGS_32BIT;
selector = SELECTOR_AllocBlock( address, totalSize, selflags );
if (!selector)
{
ERR("Could not allocate selector\n" );
......@@ -1835,16 +1838,13 @@ HANDLE WINAPI Local32Init16( WORD segment, DWORD tableSize,
nrBlocks = (totSize + 0x7fff) >> 15;
selectorTable = (LPWORD) HeapAlloc( header->heap, 0, nrBlocks * 2 );
selectorEven = SELECTOR_AllocBlock( base, totSize,
SEGMENT_DATA, FALSE, FALSE );
selectorOdd = SELECTOR_AllocBlock( base + 0x8000, totSize - 0x8000,
SEGMENT_DATA, FALSE, FALSE );
selectorEven = SELECTOR_AllocBlock( base, totSize, WINE_LDT_FLAGS_DATA );
selectorOdd = SELECTOR_AllocBlock( base + 0x8000, totSize - 0x8000, WINE_LDT_FLAGS_DATA );
if ( !selectorTable || !selectorEven || !selectorOdd )
{
if ( selectorTable ) HeapFree( header->heap, 0, selectorTable );
if ( selectorEven ) SELECTOR_FreeBlock( selectorEven, totSize >> 16 );
if ( selectorOdd ) SELECTOR_FreeBlock( selectorOdd, (totSize-0x8000) >> 16 );
if ( selectorEven ) SELECTOR_FreeBlock( selectorEven );
if ( selectorOdd ) SELECTOR_FreeBlock( selectorOdd );
HeapDestroy( header->heap );
VirtualFree( base, 0, MEM_RELEASE );
return 0;
......
......@@ -236,7 +236,7 @@ static BYTE *INSTR_GetOperandAddr( CONTEXT86 *context, BYTE *instr,
/* Make sure the segment and offset are valid */
if (IS_SELECTOR_SYSTEM(seg)) return (BYTE *)(base + (index << ss));
if (((seg & 7) != 7) || IS_SELECTOR_FREE(seg)) return NULL;
if (GET_SEL_LIMIT(seg) < (base + (index << ss))) return NULL;
if (wine_ldt_copy.limit[seg >> 3] < (base + (index << ss))) return NULL;
return (BYTE *)PTR_SEG_OFF_TO_LIN( seg, (base + (index << ss)) );
#undef GET_VAL
}
......
/*
* LDT manipulation functions
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Alexandre Julliard
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "ldt.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ldt);
#ifdef __i386__
#ifdef linux
#ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
struct modify_ldt_s
{
unsigned int entry_number;
unsigned long base_addr;
unsigned int limit;
unsigned int seg_32bit : 1;
unsigned int contents : 2;
unsigned int read_exec_only : 1;
unsigned int limit_in_pages : 1;
unsigned int seg_not_present : 1;
};
static inline int modify_ldt( int func, struct modify_ldt_s *ptr,
unsigned long count )
{
int res;
#ifdef __PIC__
__asm__ __volatile__( "pushl %%ebx\n\t"
"movl %2,%%ebx\n\t"
"int $0x80\n\t"
"popl %%ebx"
: "=a" (res)
: "0" (SYS_modify_ldt),
"r" (func),
"c" (ptr),
"d" (count) );
#else
__asm__ __volatile__("int $0x80"
: "=a" (res)
: "0" (SYS_modify_ldt),
"b" (func),
"c" (ptr),
"d" (count) );
#endif /* __PIC__ */
if (res >= 0) return res;
errno = -res;
return -1;
}
#endif /* linux */
#if defined(__svr4__) || defined(_SCO_DS)
#include <sys/sysi86.h>
extern int sysi86(int,void*);
#ifndef __sun__
#include <sys/seg.h>
#endif
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <machine/segments.h>
extern int i386_get_ldt(int, union descriptor *, int);
extern int i386_set_ldt(int, union descriptor *, int);
#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
#endif /* __i386__ */
ldt_copy_entry ldt_copy[LDT_SIZE];
unsigned char ldt_flags_copy[LDT_SIZE];
/***********************************************************************
* LDT_BytesToEntry
*
* Convert the raw bytes of the descriptor to an ldt_entry structure.
*/
void LDT_BytesToEntry( const unsigned long *buffer, ldt_entry *content )
{
content->base = (*buffer >> 16) & 0x0000ffff;
content->limit = *buffer & 0x0000ffff;
buffer++;
content->base |= (*buffer & 0xff000000) | ((*buffer << 16) & 0x00ff0000);
content->limit |= (*buffer & 0x000f0000);
content->type = (*buffer >> 10) & 3;
content->seg_32bit = (*buffer & 0x00400000) != 0;
content->read_only = (*buffer & 0x00000200) == 0;
content->limit_in_pages = (*buffer & 0x00800000) != 0;
}
/***********************************************************************
* LDT_EntryToBytes
*
* Convert an ldt_entry structure to the raw bytes of the descriptor.
*/
void LDT_EntryToBytes( unsigned long *buffer, const ldt_entry *content )
{
*buffer++ = ((content->base & 0x0000ffff) << 16) |
(content->limit & 0x0ffff);
*buffer = (content->base & 0xff000000) |
((content->base & 0x00ff0000)>>16) |
(content->limit & 0xf0000) |
(content->type << 10) |
((content->read_only == 0) << 9) |
((content->seg_32bit != 0) << 22) |
((content->limit_in_pages != 0) << 23) |
0xf000;
}
/***********************************************************************
* LDT_GetEntry
*
* Retrieve an LDT entry.
*/
int LDT_GetEntry( int entry, ldt_entry *content )
{
int ret = 0;
content->base = ldt_copy[entry].base;
content->limit = ldt_copy[entry].limit;
content->type = (ldt_flags_copy[entry] & LDT_FLAGS_TYPE);
content->seg_32bit = (ldt_flags_copy[entry] & LDT_FLAGS_32BIT) != 0;
content->read_only = (ldt_flags_copy[entry] & LDT_FLAGS_READONLY) !=0;
content->limit_in_pages = (ldt_flags_copy[entry] & LDT_FLAGS_BIG) !=0;
if (content->limit_in_pages) content->limit >>= 12;
return ret;
}
/***********************************************************************
* LDT_SetEntry
*
* Set an LDT entry.
*/
int LDT_SetEntry( int entry, const ldt_entry *content )
{
int ret = 0;
TRACE("entry=%04x base=%08lx limit=%05lx %s %d-bit "
"flags=%c%c%c\n", entry, content->base, content->limit,
content->limit_in_pages ? "pages" : "bytes",
content->seg_32bit ? 32 : 16,
content->read_only && (content->type & SEGMENT_CODE) ? '-' : 'r',
content->read_only || (content->type & SEGMENT_CODE) ? '-' : 'w',
(content->type & SEGMENT_CODE) ? 'x' : '-' );
/* Entry 0 must not be modified; its base and limit are always 0 */
if (!entry) return 0;
#ifdef __i386__
#ifdef linux
{
struct modify_ldt_s ldt_info;
ldt_info.entry_number = entry;
ldt_info.base_addr = content->base;
ldt_info.limit = content->limit;
ldt_info.seg_32bit = content->seg_32bit != 0;
ldt_info.contents = content->type;
ldt_info.read_exec_only = content->read_only != 0;
ldt_info.limit_in_pages = content->limit_in_pages != 0;
ldt_info.seg_not_present = 0;
/* Make sure the info will be accepted by the kernel */
/* This is ugly, but what can I do? */
if (content->type == SEGMENT_STACK)
{
/* FIXME */
}
else
{
if (ldt_info.base_addr >= 0xc0000000)
{
WARN("Invalid base addr %08lx\n",
ldt_info.base_addr );
return -1;
}
if (content->limit_in_pages)
{
if ((ldt_info.limit << 12) + 0xfff >
0xc0000000 - ldt_info.base_addr)
ldt_info.limit = (0xc0000000 - 0xfff - ldt_info.base_addr) >> 12;
}
else
{
if (ldt_info.limit > 0xc0000000 - ldt_info.base_addr)
ldt_info.limit = 0xc0000000 - ldt_info.base_addr;
}
}
if ((ret = modify_ldt(1, &ldt_info, sizeof(ldt_info))) < 0)
perror( "modify_ldt" );
}
#endif /* linux */
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
{
long d[2];
LDT_EntryToBytes( d, content );
ret = i386_set_ldt(entry, (union descriptor *)d, 1);
if (ret < 0)
{
perror("i386_set_ldt");
MESSAGE("Did you reconfigure the kernel with \"options USER_LDT\"?\n");
exit(1);
}
}
#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
#if defined(__svr4__) || defined(_SCO_DS)
{
struct ssd ldt_mod;
int i;
ldt_mod.sel = ENTRY_TO_SELECTOR(entry) | 4;
ldt_mod.bo = content->base;
ldt_mod.ls = content->limit;
i = ((content->limit & 0xf0000) |
(content->type << 10) |
(((content->read_only != 0) ^ 1) << 9) |
((content->seg_32bit != 0) << 22) |
((content->limit_in_pages != 0)<< 23) |
(1<<15) |
0x7000);
ldt_mod.acc1 = (i & 0xff00) >> 8;
ldt_mod.acc2 = (i & 0xf00000) >> 20;
if (content->base == 0)
{
ldt_mod.acc1 = 0;
ldt_mod.acc2 = 0;
}
if ((ret = sysi86(SI86DSCR, &ldt_mod)) == -1) perror("sysi86");
}
#endif
#endif /* __i386__ */
if (ret < 0) return ret;
ldt_copy[entry].base = content->base;
if (!content->limit_in_pages) ldt_copy[entry].limit = content->limit;
else ldt_copy[entry].limit = (content->limit << 12) | 0x0fff;
ldt_flags_copy[entry] = (content->type & LDT_FLAGS_TYPE) |
(content->read_only ? LDT_FLAGS_READONLY : 0) |
(content->seg_32bit ? LDT_FLAGS_32BIT : 0) |
(content->limit_in_pages ? LDT_FLAGS_BIG : 0) |
(ldt_flags_copy[entry] & LDT_FLAGS_ALLOCATED);
return ret;
}
/***********************************************************************
* LDT_Print
*
* Print the content of the LDT on stdout.
*/
void LDT_Print( int start, int length )
{
int i;
char flags[3];
if (length == -1) length = LDT_SIZE - start;
for (i = start; i < start + length; i++)
{
if (!ldt_copy[i].base && !ldt_copy[i].limit) continue; /* Free entry */
if ((ldt_flags_copy[i] & LDT_FLAGS_TYPE) == SEGMENT_CODE)
{
flags[0] = (ldt_flags_copy[i] & LDT_FLAGS_EXECONLY) ? '-' : 'r';
flags[1] = '-';
flags[2] = 'x';
}
else
{
flags[0] = 'r';
flags[1] = (ldt_flags_copy[i] & LDT_FLAGS_READONLY) ? '-' : 'w';
flags[2] = '-';
}
MESSAGE("%04x: sel=%04x base=%08lx limit=%08lx %d-bit %c%c%c\n",
i, ENTRY_TO_SELECTOR(i), ldt_copy[i].base, ldt_copy[i].limit,
ldt_flags_copy[i] & LDT_FLAGS_32BIT ? 32 : 16,
flags[0], flags[1], flags[2] );
}
}
......@@ -18,38 +18,55 @@
DEFAULT_DEBUG_CHANNEL(selector);
#define LDT_SIZE 8192
/* get the number of selectors needed to cover up to the selector limit */
inline static WORD get_sel_count( WORD sel )
{
return (wine_ldt_copy.limit[sel >> __AHSHIFT] >> 16) + 1;
}
/***********************************************************************
* AllocSelectorArray (KERNEL.206)
* SELECTOR_AllocArray
*
* Allocate a selector array without setting the LDT entries
*/
WORD WINAPI AllocSelectorArray16( WORD count )
static WORD SELECTOR_AllocArray( WORD count )
{
WORD i, sel, size = 0;
ldt_entry entry;
if (!count) return 0;
for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
{
if (!IS_LDT_ENTRY_FREE(i)) size = 0;
if (wine_ldt_copy.flags[i] & WINE_LDT_FLAGS_ALLOCATED) size = 0;
else if (++size >= count) break;
}
if (i == LDT_SIZE) return 0;
sel = i - size + 1;
entry.base = 0;
entry.type = SEGMENT_DATA;
entry.seg_32bit = FALSE;
entry.read_only = FALSE;
entry.limit_in_pages = FALSE;
entry.limit = 1; /* avoid 0 base and limit */
/* mark selectors as allocated */
for (i = 0; i < count; i++) wine_ldt_copy.flags[sel + i] |= WINE_LDT_FLAGS_ALLOCATED;
for (i = 0; i < count; i++)
return (sel << __AHSHIFT) | 7;
}
/***********************************************************************
* AllocSelectorArray (KERNEL.206)
*/
WORD WINAPI AllocSelectorArray16( WORD count )
{
WORD i, sel = SELECTOR_AllocArray( count );
if (sel)
{
/* Mark selector as allocated */
ldt_flags_copy[sel + i] |= LDT_FLAGS_ALLOCATED;
LDT_SetEntry( sel + i, &entry );
LDT_ENTRY entry;
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++) wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
}
return ENTRY_TO_SELECTOR( sel );
return sel;
}
......@@ -60,17 +77,16 @@ WORD WINAPI AllocSelector16( WORD sel )
{
WORD newsel, count, i;
count = sel ? ((GET_SEL_LIMIT(sel) >> 16) + 1) : 1;
newsel = AllocSelectorArray16( count );
TRACE("(%04x): returning %04x\n",
sel, newsel );
count = sel ? get_sel_count(sel) : 1;
newsel = SELECTOR_AllocArray( 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;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
LDT_SetEntry( SELECTOR_TO_ENTRY(newsel) + i, &entry );
LDT_ENTRY entry;
wine_ldt_get_entry( sel + (i << __AHSHIFT), &entry );
wine_ldt_set_entry( newsel + (i << __AHSHIFT), &entry );
}
return newsel;
}
......@@ -81,8 +97,23 @@ WORD WINAPI AllocSelector16( WORD sel )
*/
WORD WINAPI FreeSelector16( WORD sel )
{
LDT_ENTRY entry;
if (IS_SELECTOR_FREE(sel)) return sel; /* error */
SELECTOR_FreeBlock( sel, 1 );
#ifdef __i386__
/* Check if we are freeing current %fs or %gs selector */
if (!((__get_fs() ^ sel) & ~7))
{
WARN("Freeing %%fs selector (%04x), not good.\n", __get_fs() );
__set_fs( 0 );
}
if (!((__get_gs() ^ sel) & ~7)) __set_gs( 0 );
#endif /* __i386__ */
memset( &entry, 0, sizeof(entry) ); /* clear the LDT entries */
wine_ldt_set_entry( sel, &entry );
wine_ldt_copy.flags[sel >> __AHSHIFT] &= ~WINE_LDT_FLAGS_ALLOCATED;
return 0;
}
......@@ -92,32 +123,22 @@ WORD WINAPI FreeSelector16( WORD sel )
*
* Set the LDT entries for an array of selectors.
*/
static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size,
enum seg_type type, BOOL is32bit,
BOOL readonly )
static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size, unsigned char flags )
{
ldt_entry entry;
LDT_ENTRY entry;
WORD i, count;
/* The limit for the first selector is the whole */
/* block. The next selectors get a 64k limit. */
entry.base = (unsigned long)base;
entry.type = type;
entry.seg_32bit = is32bit;
entry.read_only = readonly;
entry.limit_in_pages = (size > 0x100000);
if (entry.limit_in_pages) entry.limit = ((size + 0xfff) >> 12) - 1;
else entry.limit = size - 1;
wine_ldt_set_base( &entry, base );
wine_ldt_set_limit( &entry, size - 1 );
wine_ldt_set_flags( &entry, flags );
/* Make sure base and limit are not 0 together if the size is not 0 */
if (!base && !entry.limit && size) entry.limit = 1;
if (!base && size == 1) wine_ldt_set_limit( &entry, 1 );
count = (size + 0xffff) / 0x10000;
for (i = 0; i < count; i++)
{
LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
entry.base += 0x10000;
/* Apparently the next selectors should *not* get a 64k limit. */
/* Can't remember where I read they should... --AJ */
entry.limit -= entry.limit_in_pages ? 0x10 : 0x10000;
wine_ldt_set_entry( sel + (i << __AHSHIFT), &entry );
wine_ldt_set_base( &entry, wine_ldt_get_base(&entry) + 0x10000 );
wine_ldt_set_limit( &entry, wine_ldt_get_limit(&entry) - 0x10000 );
}
}
......@@ -127,70 +148,29 @@ static void SELECTOR_SetEntries( WORD sel, const void *base, DWORD size,
*
* Allocate selectors for a block of linear memory.
*/
WORD SELECTOR_AllocBlock( const void *base, DWORD size, enum seg_type type,
BOOL is32bit, BOOL readonly )
WORD SELECTOR_AllocBlock( const void *base, DWORD size, unsigned char flags )
{
WORD sel, count;
if (!size) return 0;
count = (size + 0xffff) / 0x10000;
sel = AllocSelectorArray16( count );
if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
sel = SELECTOR_AllocArray( count );
if (sel) SELECTOR_SetEntries( sel, base, size, flags );
return sel;
}
/***********************************************************************
* SELECTOR_MoveBlock
*
* Move a block of selectors in linear memory.
*/
void SELECTOR_MoveBlock( WORD sel, const void *new_base )
{
WORD i, count = (GET_SEL_LIMIT(sel) >> 16) + 1;
for (i = 0; i < count; i++)
{
ldt_entry entry;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
entry.base = (unsigned long)new_base;
LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
}
}
/***********************************************************************
* SELECTOR_FreeBlock
*
* Free a block of selectors.
*/
void SELECTOR_FreeBlock( WORD sel, WORD count )
void SELECTOR_FreeBlock( WORD sel )
{
WORD i, nextsel;
ldt_entry entry;
WORD i, count = get_sel_count( sel );
TRACE("(%04x,%d)\n", sel, count );
sel &= ~(__AHINCR - 1); /* clear bottom bits of selector */
nextsel = sel + (count << __AHSHIFT);
#ifdef __i386__
{
/* Check if we are freeing current %fs or %gs selector */
if ((__get_fs() >= sel) && (__get_fs() < nextsel))
{
WARN("Freeing %%fs selector (%04x), not good.\n", __get_fs() );
__set_fs( 0 );
}
if ((__get_gs() >= sel) && (__get_gs() < nextsel)) __set_gs( 0 );
}
#endif /* __i386__ */
memset( &entry, 0, sizeof(entry) ); /* clear the LDT entries */
for (i = SELECTOR_TO_ENTRY(sel); count; i++, count--)
{
LDT_SetEntry( i, &entry );
ldt_flags_copy[i] &= ~LDT_FLAGS_ALLOCATED;
}
for (i = 0; i < count; i++) FreeSelector16( sel + (i << __AHSHIFT) );
}
......@@ -201,40 +181,39 @@ void SELECTOR_FreeBlock( WORD sel, WORD count )
*/
WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
{
ldt_entry entry;
LDT_ENTRY entry;
WORD i, oldcount, newcount;
if (!size) size = 1;
oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
oldcount = get_sel_count( sel );
newcount = (size + 0xffff) >> 16;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
wine_ldt_get_entry( sel, &entry );
if (oldcount < newcount) /* We need to add selectors */
{
WORD index = sel >> __AHSHIFT;
/* Check if the next selectors are free */
if (SELECTOR_TO_ENTRY(sel) + newcount > LDT_SIZE) i = oldcount;
if (index + newcount > LDT_SIZE) i = oldcount;
else
for (i = oldcount; i < newcount; i++)
if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)+i)) break;
if (wine_ldt_copy.flags[index+i] & WINE_LDT_FLAGS_ALLOCATED) break;
if (i < newcount) /* they are not free */
{
SELECTOR_FreeBlock( sel, oldcount );
sel = AllocSelectorArray16( newcount );
SELECTOR_FreeBlock( sel );
sel = SELECTOR_AllocArray( newcount );
}
else /* mark the selectors as allocated */
{
for (i = oldcount; i < newcount; i++)
ldt_flags_copy[SELECTOR_TO_ENTRY(sel)+i] |=LDT_FLAGS_ALLOCATED;
wine_ldt_copy.flags[index+i] |= WINE_LDT_FLAGS_ALLOCATED;
}
}
else if (oldcount > newcount) /* We need to remove selectors */
{
SELECTOR_FreeBlock( ENTRY_TO_SELECTOR(SELECTOR_TO_ENTRY(sel)+newcount),
oldcount - newcount );
SELECTOR_FreeBlock( sel + (newcount << __AHSHIFT) );
}
if (sel) SELECTOR_SetEntries( sel, base, size, entry.type,
entry.seg_32bit, entry.read_only );
if (sel) SELECTOR_SetEntries( sel, base, size, wine_ldt_get_flags(&entry) );
return sel;
}
......@@ -244,10 +223,11 @@ WORD SELECTOR_ReallocBlock( WORD sel, const void *base, DWORD size )
*/
WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
{
ldt_entry entry;
LDT_GetEntry( SELECTOR_TO_ENTRY( selSrc ), &entry );
entry.type ^= SEGMENT_CODE; /* toggle the executable bit */
LDT_SetEntry( SELECTOR_TO_ENTRY( selDst ), &entry );
LDT_ENTRY entry;
wine_ldt_get_entry( selSrc, &entry );
/* toggle the executable bit */
entry.HighWord.Bits.Type ^= (WINE_LDT_FLAGS_CODE ^ WINE_LDT_FLAGS_DATA);
wine_ldt_set_entry( selDst, &entry );
return selDst;
}
......@@ -258,15 +238,15 @@ WORD WINAPI PrestoChangoSelector16( WORD selSrc, WORD selDst )
WORD WINAPI AllocCStoDSAlias16( WORD sel )
{
WORD newsel;
ldt_entry entry;
LDT_ENTRY entry;
newsel = AllocSelectorArray16( 1 );
newsel = SELECTOR_AllocArray( 1 );
TRACE("(%04x): returning %04x\n",
sel, newsel );
if (!newsel) return 0;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
entry.type = SEGMENT_DATA;
LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
wine_ldt_get_entry( sel, &entry );
entry.HighWord.Bits.Type = WINE_LDT_FLAGS_DATA;
wine_ldt_set_entry( newsel, &entry );
return newsel;
}
......@@ -277,15 +257,15 @@ WORD WINAPI AllocCStoDSAlias16( WORD sel )
WORD WINAPI AllocDStoCSAlias16( WORD sel )
{
WORD newsel;
ldt_entry entry;
LDT_ENTRY entry;
newsel = AllocSelectorArray16( 1 );
newsel = SELECTOR_AllocArray( 1 );
TRACE("(%04x): returning %04x\n",
sel, newsel );
if (!newsel) return 0;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
entry.type = SEGMENT_CODE;
LDT_SetEntry( SELECTOR_TO_ENTRY(newsel), &entry );
wine_ldt_get_entry( sel, &entry );
entry.HighWord.Bits.Type = WINE_LDT_FLAGS_CODE;
wine_ldt_set_entry( newsel, &entry );
return newsel;
}
......@@ -295,10 +275,10 @@ WORD WINAPI AllocDStoCSAlias16( WORD sel )
*/
void WINAPI LongPtrAdd16( DWORD ptr, DWORD add )
{
ldt_entry entry;
LDT_GetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
entry.base += add;
LDT_SetEntry( SELECTOR_TO_ENTRY(SELECTOROF(ptr)), &entry );
LDT_ENTRY entry;
wine_ldt_get_entry( SELECTOROF(ptr), &entry );
wine_ldt_set_base( &entry, (char *)wine_ldt_get_base(&entry) + add );
wine_ldt_set_entry( SELECTOROF(ptr), &entry );
}
......@@ -318,12 +298,12 @@ DWORD WINAPI WIN16_GetSelectorBase( WORD sel )
}
DWORD WINAPI GetSelectorBase( WORD sel )
{
DWORD base = GET_SEL_BASE(sel);
void *base = wine_ldt_copy.base[sel >> __AHSHIFT];
/* if base points into DOSMEM, assume we have to
* return pointer into physical lower 1MB */
return DOSMEM_MapLinearToDos( (LPVOID)base );
return DOSMEM_MapLinearToDos( base );
}
......@@ -344,13 +324,10 @@ DWORD WINAPI WIN16_SetSelectorBase( WORD sel, DWORD base )
}
WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
{
ldt_entry entry;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
entry.base = (DWORD)DOSMEM_MapDosToLinear(base);
LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
LDT_ENTRY entry;
wine_ldt_get_entry( sel, &entry );
wine_ldt_set_base( &entry, DOSMEM_MapDosToLinear(base) );
wine_ldt_set_entry( sel, &entry );
return sel;
}
......@@ -360,7 +337,7 @@ WORD WINAPI SetSelectorBase( WORD sel, DWORD base )
*/
DWORD WINAPI GetSelectorLimit16( WORD sel )
{
return GET_SEL_LIMIT(sel);
return wine_ldt_copy.limit[sel >> __AHSHIFT];
}
......@@ -369,12 +346,10 @@ DWORD WINAPI GetSelectorLimit16( WORD sel )
*/
WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
{
ldt_entry entry;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
entry.limit_in_pages = (limit >= 0x100000);
if (entry.limit_in_pages) entry.limit = limit >> 12;
else entry.limit = limit;
LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
LDT_ENTRY entry;
wine_ldt_get_entry( sel, &entry );
wine_ldt_set_limit( &entry, limit );
wine_ldt_set_entry( sel, &entry );
return sel;
}
......@@ -384,26 +359,18 @@ WORD WINAPI SetSelectorLimit16( WORD sel, DWORD limit )
*/
WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
{
ldt_entry entry;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
LDT_ENTRY entry;
wine_ldt_get_entry( sel, &entry );
if (op == 0) /* get */
{
return 0x01 | /* accessed */
0x10 | /* not system */
0x60 | /* DPL 3 */
0x80 | /* present */
((entry.read_only == 0) << 1) |
(entry.type << 2) |
(entry.seg_32bit << 14) |
(entry.limit_in_pages << 15);
return entry.HighWord.Bytes.Flags1 | ((entry.HighWord.Bytes.Flags2 << 8) & 0xf0);
}
else /* set */
{
entry.read_only = ((val & 2) == 0);
entry.type = (val >> 2) & 3;
entry.seg_32bit = val & 0x4000;
entry.limit_in_pages = val & 0x8000;
LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
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 );
return 0;
}
}
......@@ -415,14 +382,15 @@ WORD WINAPI SelectorAccessRights16( WORD sel, WORD op, WORD val )
BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
{
WORD sel;
ldt_entry entry;
LDT_ENTRY entry;
sel = SELECTOROF(lpfn);
if (!sel) return TRUE;
if (IS_SELECTOR_FREE(sel)) return TRUE;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
if (entry.type != SEGMENT_CODE) return TRUE;
if (OFFSETOF(lpfn) > GET_SEL_LIMIT(sel)) return TRUE;
wine_ldt_get_entry( sel, &entry );
/* 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;
return FALSE;
}
......@@ -433,15 +401,17 @@ BOOL16 WINAPI IsBadCodePtr16( SEGPTR lpfn )
BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
{
WORD sel;
ldt_entry entry;
LDT_ENTRY entry;
sel = SELECTOROF(ptr);
if (!sel) return TRUE;
if (IS_SELECTOR_FREE(sel)) return TRUE;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
wine_ldt_get_entry( sel, &entry );
/* check for data or readable code segment */
if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE; /* non-readable code segment */
if (strlen(PTR_SEG_TO_LIN(ptr)) < size) size = strlen(PTR_SEG_TO_LIN(ptr)) + 1;
if (size && (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel))) return TRUE;
if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit(&entry))) return TRUE;
return FALSE;
}
......@@ -452,14 +422,16 @@ BOOL16 WINAPI IsBadStringPtr16( SEGPTR ptr, UINT16 size )
BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
{
WORD sel;
ldt_entry entry;
LDT_ENTRY entry;
sel = SELECTOROF(ptr);
if (!sel) return TRUE;
if (IS_SELECTOR_FREE(sel)) return TRUE;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
if (size && (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel))) return TRUE;
wine_ldt_get_entry( sel, &entry );
/* check for data or readable code segment */
if (!(entry.HighWord.Bits.Type & 0x10)) return TRUE; /* system descriptor */
if ((entry.HighWord.Bits.Type & 0x0a) == 0x08) return TRUE; /* non-readable code segment */
if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
return FALSE;
}
......@@ -470,14 +442,15 @@ BOOL16 WINAPI IsBadHugeReadPtr16( SEGPTR ptr, DWORD size )
BOOL16 WINAPI IsBadHugeWritePtr16( SEGPTR ptr, DWORD size )
{
WORD sel;
ldt_entry entry;
LDT_ENTRY entry;
sel = SELECTOROF(ptr);
if (!sel) return TRUE;
if (IS_SELECTOR_FREE(sel)) return TRUE;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
if ((entry.type == SEGMENT_CODE) || entry.read_only) return TRUE;
if (size && (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel))) return TRUE;
wine_ldt_get_entry( sel, &entry );
/* check for writeable data segment, ignoring expand-down and accessed flags */
if ((entry.HighWord.Bits.Type ^ WINE_LDT_FLAGS_DATA) & ~5) return TRUE;
if (size && (OFFSETOF(ptr) + size - 1 > wine_ldt_get_limit( &entry ))) return TRUE;
return FALSE;
}
......@@ -514,11 +487,13 @@ BOOL16 WINAPI IsBadFlatReadWritePtr16( SEGPTR ptr, DWORD size, BOOL16 bWrite )
*/
DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
{
if (IS_SELECTOR_FREE(sel)) return 0;
if (offset > GET_SEL_LIMIT(sel)) return 0;
if (offset + count > GET_SEL_LIMIT(sel) + 1)
count = GET_SEL_LIMIT(sel) + 1 - offset;
memcpy( buffer, ((char *)GET_SEL_BASE(sel)) + offset, count );
WORD index = sel >> __AHSHIFT;
if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)) return 0;
if (offset > wine_ldt_copy.limit[index]) return 0;
if (offset + count > wine_ldt_copy.limit[index] + 1)
count = wine_ldt_copy.limit[index] + 1 - offset;
memcpy( buffer, (char *)wine_ldt_copy.base[index] + offset, count );
return count;
}
......@@ -528,11 +503,13 @@ DWORD WINAPI MemoryRead16( WORD sel, DWORD offset, void *buffer, DWORD count )
*/
DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
{
if (IS_SELECTOR_FREE(sel)) return 0;
if (offset > GET_SEL_LIMIT(sel)) return 0;
if (offset + count > GET_SEL_LIMIT(sel) + 1)
count = GET_SEL_LIMIT(sel) + 1 - offset;
memcpy( ((char *)GET_SEL_BASE(sel)) + offset, buffer, count );
WORD index = sel >> __AHSHIFT;
if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)) return 0;
if (offset > wine_ldt_copy.limit[index]) return 0;
if (offset + count > wine_ldt_copy.limit[index] + 1)
count = wine_ldt_copy.limit[index] + 1 - offset;
memcpy( (char *)wine_ldt_copy.base[index] + offset, buffer, count );
return count;
}
......@@ -547,7 +524,7 @@ DWORD WINAPI MemoryWrite16( WORD sel, DWORD offset, void *buffer, DWORD count )
*/
LPVOID WINAPI MapSL( SEGPTR sptr )
{
return (LPVOID)PTR_SEG_TO_LIN(sptr);
return (char *)wine_ldt_copy.base[SELECTOROF(sptr) >> __AHSHIFT] + OFFSETOF(sptr);
}
/***********************************************************************
......@@ -583,7 +560,7 @@ SEGPTR WINAPI MapLS( LPVOID ptr )
return (SEGPTR)ptr;
else
{
WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, SEGMENT_DATA, FALSE, FALSE );
WORD sel = SELECTOR_AllocBlock( ptr, 0x10000, WINE_LDT_FLAGS_DATA );
return PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
}
}
......@@ -596,8 +573,7 @@ SEGPTR WINAPI MapLS( LPVOID ptr )
*/
void WINAPI UnMapLS( SEGPTR sptr )
{
if (SELECTOROF(sptr))
SELECTOR_FreeBlock( SELECTOROF(sptr), 1 );
if (SELECTOROF(sptr)) FreeSelector16( SELECTOROF(sptr) );
}
/***********************************************************************
......@@ -647,26 +623,16 @@ BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldten
req->entry = sel >> __AHSHIFT;
if ((ret = !server_call( REQ_GET_SELECTOR_ENTRY )))
{
if (!(req->flags & LDT_FLAGS_ALLOCATED))
if (!(req->flags & WINE_LDT_FLAGS_ALLOCATED))
{
SetLastError( ERROR_MR_MID_NOT_FOUND ); /* sic */
ret = FALSE;
}
else
{
if (req->flags & LDT_FLAGS_BIG) req->limit >>= 12;
ldtent->BaseLow = req->base & 0x0000ffff;
ldtent->HighWord.Bits.BaseMid = (req->base & 0x00ff0000) >> 16;
ldtent->HighWord.Bits.BaseHi = (req->base & 0xff000000) >> 24;
ldtent->LimitLow = req->limit & 0x0000ffff;
ldtent->HighWord.Bits.LimitHi = (req->limit & 0x000f0000) >> 16;
ldtent->HighWord.Bits.Dpl = 3;
ldtent->HighWord.Bits.Sys = 0;
ldtent->HighWord.Bits.Pres = 1;
ldtent->HighWord.Bits.Granularity = (req->flags & LDT_FLAGS_BIG) !=0;
ldtent->HighWord.Bits.Default_Big = (req->flags & LDT_FLAGS_32BIT) != 0;
ldtent->HighWord.Bits.Type = ((req->flags & LDT_FLAGS_TYPE) << 2) | 0x10;
if (!(req->flags & LDT_FLAGS_READONLY)) ldtent->HighWord.Bits.Type |= 0x2;
wine_ldt_set_base( ldtent, (void *)req->base );
wine_ldt_set_limit( ldtent, req->limit );
wine_ldt_set_flags( ldtent, req->flags );
}
}
}
......
......@@ -212,7 +212,7 @@ static void DOSMEM_InitDPMI(void)
memcpy( ptr, enter_xms, sizeof(enter_xms) );
ptr = DOSMEM_GetBlock( sizeof(enter_pm), &DOSMEM_dpmi_seg );
memcpy( ptr, enter_pm, sizeof(enter_pm) );
DOSMEM_dpmi_sel = SELECTOR_AllocBlock( ptr, sizeof(enter_pm), SEGMENT_CODE, FALSE, FALSE );
DOSMEM_dpmi_sel = SELECTOR_AllocBlock( ptr, sizeof(enter_pm), WINE_LDT_FLAGS_CODE );
}
BIOSDATA * DOSMEM_BiosData()
......@@ -506,11 +506,11 @@ BOOL DOSMEM_Init(BOOL dos_init)
setup_dos_mem( dos_init );
DOSMEM_0000H = GLOBAL_CreateBlock( GMEM_FIXED, DOSMEM_sysmem,
0x10000, 0, FALSE, FALSE, FALSE );
0x10000, 0, WINE_LDT_FLAGS_DATA );
DOSMEM_BiosDataSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_sysmem + 0x400,
0x100, 0, FALSE, FALSE, FALSE );
0x100, 0, WINE_LDT_FLAGS_DATA );
DOSMEM_BiosSysSeg = GLOBAL_CreateBlock(GMEM_FIXED,DOSMEM_dosmem+0xf0000,
0x10000, 0, FALSE, FALSE, FALSE );
0x10000, 0, WINE_LDT_FLAGS_DATA );
DOSMEM_FillBiosSegments();
DOSMEM_FillIsrTable();
DOSMEM_InitMemory();
......@@ -836,9 +836,8 @@ WORD DOSMEM_AllocSelector(WORD realsel)
HMODULE16 hModule = GetModuleHandle16("KERNEL");
WORD sel;
sel=GLOBAL_CreateBlock(
GMEM_FIXED,DOSMEM_dosmem+realsel*16,0x10000,
hModule,FALSE,FALSE,FALSE );
sel=GLOBAL_CreateBlock( GMEM_FIXED, DOSMEM_dosmem+realsel*16, 0x10000,
hModule, WINE_LDT_FLAGS_DATA );
TRACE_(selector)("(0x%04x) returns 0x%04x.\n", realsel,sel);
return sel;
}
......
......@@ -260,7 +260,7 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
DWORD esp,edi;
INT_SetRealModeContext((REALMODECALL *)PTR_SEG_OFF_TO_LIN( rmcb->regs_sel, rmcb->regs_ofs ), context);
ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, SEGMENT_DATA, FALSE, FALSE );
ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, WINE_LDT_FLAGS_DATA );
esp = context->Esp;
FIXME("untested!\n");
......@@ -583,25 +583,24 @@ static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask )
DWORD psp_ofs = (DWORD)(lpDosTask->psp_seg<<4);
PDB16 *psp = (PDB16 *)psp_ofs;
HANDLE16 env_seg = psp->environment;
int is32;
unsigned char selflags = WINE_LDT_FLAGS_DATA;
RESET_CFLAG(context);
lpDosTask->dpmi_flag = AX_reg(context);
is32 = lpDosTask->dpmi_flag & 1;
/* our mode switch wrapper have placed the desired CS into DX */
cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, SEGMENT_CODE, FALSE, FALSE );
cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, WINE_LDT_FLAGS_CODE );
/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
32-bit code using this stack. */
ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, SEGMENT_DATA, is32, FALSE );
if (lpDosTask->dpmi_flag & 1) selflags |= WINE_LDT_FLAGS_32BIT;
ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, selflags );
/* do the same for the data segments, just in case */
if (context->SegDs == context->SegSs) ds = ss;
else ds = SELECTOR_AllocBlock( (void *)(context->SegDs<<4), 0x10000, SEGMENT_DATA, is32, FALSE );
es = SELECTOR_AllocBlock( psp, 0x100, SEGMENT_DATA, is32, FALSE );
else ds = SELECTOR_AllocBlock( (void *)(context->SegDs<<4), 0x10000, selflags );
es = SELECTOR_AllocBlock( psp, 0x100, selflags );
/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4),
0x10000, SEGMENT_DATA, FALSE, FALSE );
psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4), 0x10000, WINE_LDT_FLAGS_DATA );
pm_ctx = *context;
pm_ctx.SegCs = DOSMEM_dpmi_sel;
......@@ -852,24 +851,20 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
case 0x000b: /* Get descriptor */
TRACE("get descriptor (0x%04x)\n",BX_reg(context));
{
ldt_entry entry;
LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
entry.base = W32S_WINE2APP(entry.base, offset);
LDT_ENTRY entry;
wine_ldt_set_base( &entry, (void*)W32S_WINE2APP(wine_ldt_get_base(&entry), offset) );
/* FIXME: should use ES:EDI for 32-bit clients */
LDT_EntryToBytes( PTR_SEG_OFF_TO_LIN( context->SegEs,
DI_reg(context) ), &entry );
*(LDT_ENTRY *)PTR_SEG_OFF_TO_LIN( context->SegEs, LOWORD(context->Edi) ) = entry;
}
break;
case 0x000c: /* Set descriptor */
TRACE("set descriptor (0x%04x)\n",BX_reg(context));
{
ldt_entry entry;
LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( context->SegEs,
DI_reg(context) ), &entry );
entry.base = W32S_APP2WINE(entry.base, offset);
LDT_SetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
LDT_ENTRY entry = *(LDT_ENTRY *)PTR_SEG_OFF_TO_LIN( context->SegEs,
LOWORD(context->Edi) );
wine_ldt_set_base( &entry, (void*)W32S_APP2WINE(wine_ldt_get_base(&entry), offset) );
wine_ldt_set_entry( LOWORD(context->Ebx), &entry );
}
break;
......
......@@ -392,8 +392,7 @@ void WINAPI VXD_TimerAPI ( CONTEXT86 *context )
case 0x0009: /* get system time selector */
if ( !System_Time_Selector )
{
System_Time_Selector = SELECTOR_AllocBlock( &System_Time, sizeof(DWORD),
SEGMENT_DATA, FALSE, TRUE );
System_Time_Selector = SELECTOR_AllocBlock( &System_Time, sizeof(DWORD), WINE_LDT_FLAGS_DATA );
CreateSystemTimer( 55, System_Time_Tick );
}
......
......@@ -101,7 +101,7 @@ HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
size = sizeof(METAHEADER) + sizeof(METAHEADERDISK);
hmf = GLOBAL_CreateBlock( GMEM_MOVEABLE, mh, mh->mtSize * sizeof(WORD),
GetCurrentPDB16(), FALSE, FALSE, FALSE );
GetCurrentPDB16(), WINE_LDT_FLAGS_DATA );
return hmf;
}
......
......@@ -192,8 +192,7 @@ static BOOL process_init( char *argv[] )
struct init_process_request *req = server_alloc_req( sizeof(*req),
sizeof(main_exe_name)-1 );
req->ldt_copy = ldt_copy;
req->ldt_flags = ldt_flags_copy;
req->ldt_copy = &wine_ldt_copy;
req->ppid = getppid();
if ((ret = !server_call( REQ_INIT_PROCESS )))
{
......
......@@ -93,7 +93,7 @@ static BOOL THREAD_InitTEB( TEB *teb )
teb->stack_top = (void *)~0UL;
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, WINE_LDT_FLAGS_DATA|WINE_LDT_FLAGS_32BIT );
return (teb->teb_sel != 0);
}
......@@ -196,8 +196,7 @@ TEB *THREAD_InitStack( TEB *teb, DWORD stack_size, BOOL alloc_stack16 )
if (alloc_stack16)
{
teb->stack_sel = SELECTOR_AllocBlock( teb->stack_top, 0x10000, SEGMENT_DATA,
FALSE, FALSE );
teb->stack_sel = SELECTOR_AllocBlock( teb->stack_top, 0x10000, WINE_LDT_FLAGS_DATA );
if (!teb->stack_sel) goto error;
teb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( teb->stack_sel,
0x10000 - sizeof(STACK16FRAME) );
......
......@@ -171,7 +171,6 @@ struct thread *create_process( int fd )
process->queue = NULL;
process->atom_table = NULL;
process->ldt_copy = NULL;
process->ldt_flags = NULL;
process->exe.next = NULL;
process->exe.prev = NULL;
process->exe.file = NULL;
......@@ -808,7 +807,6 @@ DECL_HANDLER(init_process)
return;
}
current->process->ldt_copy = req->ldt_copy;
current->process->ldt_flags = req->ldt_flags;
init_process( req->ppid, req );
}
......
......@@ -574,7 +574,7 @@ static void get_selector_entry( struct thread *thread, int entry,
unsigned int *base, unsigned int *limit,
unsigned char *flags )
{
if (!thread->process->ldt_copy || !thread->process->ldt_flags)
if (!thread->process->ldt_copy)
{
set_error( STATUS_ACCESS_DENIED );
return;
......@@ -587,10 +587,10 @@ static void get_selector_entry( struct thread *thread, int entry,
if (suspend_for_ptrace( thread ))
{
unsigned char flags_buf[4];
int *addr = (int *)thread->process->ldt_copy + 2 * entry;
int *addr = (int *)thread->process->ldt_copy + entry;
if (read_thread_int( thread, addr, base ) == -1) goto done;
if (read_thread_int( thread, addr + 1, limit ) == -1) goto done;
addr = (int *)thread->process->ldt_flags + (entry >> 2);
if (read_thread_int( thread, addr + 8192, limit ) == -1) goto done;
addr = (int *)thread->process->ldt_copy + 2*8192 + (entry >> 2);
if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done;
*flags = flags_buf[entry & 3];
done:
......
......@@ -324,7 +324,6 @@ static void dump_boot_done_request( const struct boot_done_request *req )
static void dump_init_process_request( const struct init_process_request *req )
{
fprintf( stderr, " ldt_copy=%p,", req->ldt_copy );
fprintf( stderr, " ldt_flags=%p,", req->ldt_flags );
fprintf( stderr, " ppid=%d", req->ppid );
}
......
......@@ -145,18 +145,19 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho
else
fprintf( outfile, "\tmovw " PREFIX "SYSLEVEL_Win16CurrentTeb, %%fs\n" );
/* Get address of ldt_copy array into %ecx */
/* Get address of wine_ldt_copy array into %ecx */
if ( UsePIC )
fprintf( outfile, "\tmovl " PREFIX "ldt_copy@GOT(%%ecx), %%ecx\n" );
fprintf( outfile, "\tmovl " PREFIX "wine_ldt_copy@GOT(%%ecx), %%ecx\n" );
else
fprintf( outfile, "\tmovl $" PREFIX "ldt_copy, %%ecx\n" );
fprintf( outfile, "\tmovl $" PREFIX "wine_ldt_copy, %%ecx\n" );
/* Translate STACK16FRAME base to flat offset in %edx */
fprintf( outfile, "\tmovw %%ss, %%dx\n" );
fprintf( outfile, "\tandl $0xfff8, %%edx\n" );
fprintf( outfile, "\tshrl $1, %%edx\n" );
fprintf( outfile, "\tmovl (%%ecx,%%edx), %%edx\n" );
fprintf( outfile, "\tmovzwl %%sp, %%ebp\n" );
fprintf( outfile, "\tleal (%%ebp,%%edx), %%edx\n" );
fprintf( outfile, "\tleal (%%ebp,%%edx), %%edx\n" );
/* Get saved flags into %ecx */
fprintf( outfile, "\tpopl %%ecx\n" );
......@@ -852,7 +853,8 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
fprintf( outfile, "\tshldl $16,%%ebx,%%eax\n" );
fprintf( outfile, "\tandl $0xfff8,%%eax\n" );
fprintf( outfile, "\tmovl " PREFIX "ldt_copy(%%eax),%%esi\n" );
fprintf( outfile, "\tshrl $1,%%eax\n" );
fprintf( outfile, "\tmovl " PREFIX "wine_ldt_copy(%%eax),%%esi\n" );
fprintf( outfile, "\tmovw %%bx,%%ax\n" );
fprintf( outfile, "\taddl %%eax,%%esi\n" );
......
......@@ -388,7 +388,8 @@ static void BuildCallFrom16Func( FILE *outfile, char *profile, char *prefix, int
case 'p': /* linear pointer */
case 't': /* linear pointer to null-terminated string */
if ( !usecdecl ) pos -= 4;
fprintf( outfile, "PTR_SEG_TO_LIN( *(SEGPTR *)(args+%d) )", pos );
fprintf( outfile, "((char*)wine_ldt_copy.base[*(WORD*)(args+%d) >> 3] + *(WORD*)(args+%d))",
pos + 2, pos );
if ( usecdecl ) pos += 4;
break;
......@@ -565,7 +566,11 @@ void BuildSpec16File( FILE *outfile )
input_file_name );
fprintf( outfile, "#include \"builtin16.h\"\n\n" );
fprintf( outfile, "extern void RELAY_Unimplemented16(void);\n\n" );
fprintf( outfile, "extern struct\n{\n" );
fprintf( outfile, " void *base[8192];\n" );
fprintf( outfile, " unsigned long limit[8192];\n" );
fprintf( outfile, " unsigned char flags[8192];\n" );
fprintf( outfile, "} wine_ldt_copy;\n\n" );
data = (unsigned char *)xmalloc( 0x10000 );
memset( data, 0, 16 );
......
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