Moved LDT handling to libwine.so. Changed the interface to use the
exported LDT_ENTRY structure.
This commit is contained in:
parent
41d6e2feba
commit
914406f854
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
||||
|
|
302
memory/ldt.c
302
memory/ldt.c
|
@ -1,302 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SELECTOR_AllocArray
|
||||
*
|
||||
* Allocate a selector array without setting the LDT entries
|
||||
*/
|
||||
static WORD SELECTOR_AllocArray( WORD count )
|
||||
{
|
||||
WORD i, sel, size = 0;
|
||||
|
||||
if (!count) return 0;
|
||||
for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
|
||||
{
|
||||
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;
|
||||
|
||||
/* mark selectors as allocated */
|
||||
for (i = 0; i < count; i++) wine_ldt_copy.flags[sel + i] |= WINE_LDT_FLAGS_ALLOCATED;
|
||||
|
||||
return (sel << __AHSHIFT) | 7;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* AllocSelectorArray (KERNEL.206)
|
||||
*/
|
||||
WORD WINAPI AllocSelectorArray16( WORD count )
|
||||
{
|
||||
WORD i, sel, size = 0;
|
||||
ldt_entry entry;
|
||||
WORD i, sel = SELECTOR_AllocArray( count );
|
||||
|
||||
if (!count) return 0;
|
||||
for (i = FIRST_LDT_ENTRY_TO_ALLOC; i < LDT_SIZE; i++)
|
||||
if (sel)
|
||||
{
|
||||
if (!IS_LDT_ENTRY_FREE(i)) size = 0;
|
||||
else if (++size >= count) break;
|
||||
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 );
|
||||
}
|
||||
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 */
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
/* Mark selector as allocated */
|
||||
ldt_flags_copy[sel + i] |= LDT_FLAGS_ALLOCATED;
|
||||
LDT_SetEntry( sel + i, &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;
|
||||
}
|
||||
|
|
35
msdos/dpmi.c
35
msdos/dpmi.c
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue