diff --git a/dlls/kernel/kernel_main.c b/dlls/kernel/kernel_main.c index 09d3aafb9bd..11f3529a81f 100644 --- a/dlls/kernel/kernel_main.c +++ b/dlls/kernel/kernel_main.c @@ -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 */ diff --git a/dlls/kernel/thunk.c b/dlls/kernel/thunk.c index c61fbe3ac4b..8a25b0da54f 100644 --- a/dlls/kernel/thunk.c +++ b/dlls/kernel/thunk.c @@ -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; } diff --git a/dlls/winmm/mmsystem.c b/dlls/winmm/mmsystem.c index 6f62da3ff24..21ae14b77ad 100644 --- a/dlls/winmm/mmsystem.c +++ b/dlls/winmm/mmsystem.c @@ -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; diff --git a/graphics/x11drv/dib.c b/graphics/x11drv/dib.c index 0dee54399a5..645795b3a68 100644 --- a/graphics/x11drv/dib.c +++ b/graphics/x11drv/dib.c @@ -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 ); } diff --git a/if1632/builtin.c b/if1632/builtin.c index 2a62061c966..e125bccb192 100644 --- a/if1632/builtin.c +++ b/if1632/builtin.c @@ -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); diff --git a/if1632/relay.c b/if1632/relay.c index a314c4f6786..da947f5bdcd 100644 --- a/if1632/relay.c +++ b/if1632/relay.c @@ -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 */ diff --git a/if1632/snoop.c b/if1632/snoop.c index 1f5b69a2b08..57107a8b8c4 100644 --- a/if1632/snoop.c +++ b/if1632/snoop.c @@ -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 */ } diff --git a/include/builtin16.h b/include/builtin16.h index 4e0c02a02a3..f939fe821b8 100644 --- a/include/builtin16.h +++ b/include/builtin16.h @@ -9,7 +9,6 @@ #include "windef.h" #include "wine/windef16.h" -#include "ldt.h" struct _CONTEXT86; struct _STACK16FRAME; diff --git a/include/global.h b/include/global.h index 9314782358b..987e0c6dd90 100644 --- a/include/global.h +++ b/include/global.h @@ -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); diff --git a/include/ldt.h b/include/ldt.h index d600042da7e..4b35b70e68b 100644 --- a/include/ldt.h +++ b/include/ldt.h @@ -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 */ diff --git a/include/selectors.h b/include/selectors.h index ff8a4cc9367..7949126fddf 100644 --- a/include/selectors.h +++ b/include/selectors.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__ diff --git a/include/server.h b/include/server.h index c069f4371c3..c543e85912a 100644 --- a/include/server.h +++ b/include/server.h @@ -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 */ diff --git a/include/wine/library.h b/include/wine/library.h index f656ae91233..53fe0d26077 100644 --- a/include/wine/library.h +++ b/include/wine/library.h @@ -8,6 +8,7 @@ #define __WINE_WINE_LIBRARY_H #include +#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 */ diff --git a/library/Makefile.in b/library/Makefile.in index ab3271598d4..c75bb5cfd7a 100644 --- a/library/Makefile.in +++ b/library/Makefile.in @@ -10,6 +10,7 @@ SONAME = libwine.so C_SRCS = \ debug.c \ + ldt.c \ loader.c \ port.c diff --git a/library/ldt.c b/library/ldt.c new file mode 100644 index 00000000000..ca4e062f634 --- /dev/null +++ b/library/ldt.c @@ -0,0 +1,169 @@ +/* + * LDT manipulation functions + * + * Copyright 1993 Robert J. Amstadt + * Copyright 1995 Alexandre Julliard + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "winbase.h" +#include "wine/library.h" + +#ifdef __i386__ + +#ifdef linux + +#ifdef HAVE_SYS_SYSCALL_H +# include +#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 +extern int sysi86(int,void*); +#ifndef __sun__ +#include +#endif +#endif + +#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#include + +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; +} diff --git a/loader/ne/module.c b/loader/ne/module.c index 96ea71eeb74..fa2cd39bcca 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -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 ); diff --git a/loader/ne/resource.c b/loader/ne/resource.c index 7bc1d25778b..91d247e4a43 100644 --- a/loader/ne/resource.c +++ b/loader/ne/resource.c @@ -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 ); } diff --git a/loader/ne/segment.c b/loader/ne/segment.c index 9459ef5a85b..c2b0201fc5d 100644 --- a/loader/ne/segment.c +++ b/loader/ne/segment.c @@ -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; diff --git a/loader/task.c b/loader/task.c index 3924fad334b..4d3bf8dca8d 100644 --- a/loader/task.c +++ b/loader/task.c @@ -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 */ diff --git a/memory/Makefile.in b/memory/Makefile.in index fc7e36a8568..3139d1b8628 100644 --- a/memory/Makefile.in +++ b/memory/Makefile.in @@ -12,7 +12,6 @@ C_SRCS = \ global.c \ heap.c \ instr.c \ - ldt.c \ local.c \ registry.c \ selector.c \ diff --git a/memory/environ.c b/memory/environ.c index 380c8d839b8..e6864e00976 100644 --- a/memory/environ.c +++ b/memory/environ.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) ); diff --git a/memory/global.c b/memory/global.c index 3d9dce24074..0b00ee23c3d 100644 --- a/memory/global.c +++ b/memory/global.c @@ -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); diff --git a/memory/heap.c b/memory/heap.c index a9bf81d5f05..a3e03956de0 100644 --- a/memory/heap.c +++ b/memory/heap.c @@ -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; diff --git a/memory/instr.c b/memory/instr.c index d222a6fa6d2..d74c20e22d8 100644 --- a/memory/instr.c +++ b/memory/instr.c @@ -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 } diff --git a/memory/ldt.c b/memory/ldt.c deleted file mode 100644 index 0607f3b38ab..00000000000 --- a/memory/ldt.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * LDT manipulation functions - * - * Copyright 1993 Robert J. Amstadt - * Copyright 1995 Alexandre Julliard - */ - -#include "config.h" - -#include -#include -#include -#include -#include "ldt.h" -#include "debugtools.h" - -DEFAULT_DEBUG_CHANNEL(ldt); - -#ifdef __i386__ - -#ifdef linux - -#ifdef HAVE_SYS_SYSCALL_H -# include -#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 -extern int sysi86(int,void*); -#ifndef __sun__ -#include -#endif -#endif - -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) -#include - -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] ); - } -} diff --git a/memory/selector.c b/memory/selector.c index 2f3a90fd57f..331bdef3e39 100644 --- a/memory/selector.c +++ b/memory/selector.c @@ -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 ); } } } diff --git a/msdos/dosmem.c b/msdos/dosmem.c index cd2a9a2a40e..fd144960c28 100644 --- a/msdos/dosmem.c +++ b/msdos/dosmem.c @@ -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; } diff --git a/msdos/dpmi.c b/msdos/dpmi.c index 5ec241c0903..4d20f386f17 100644 --- a/msdos/dpmi.c +++ b/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; diff --git a/msdos/vxd.c b/msdos/vxd.c index adb00de9363..69c791e19b9 100644 --- a/msdos/vxd.c +++ b/msdos/vxd.c @@ -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 ); } diff --git a/objects/metafile.c b/objects/metafile.c index 5ff888d5a03..a02d307682a 100644 --- a/objects/metafile.c +++ b/objects/metafile.c @@ -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; } diff --git a/scheduler/process.c b/scheduler/process.c index 6db56a78aa6..c01c46b647d 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -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 ))) { diff --git a/scheduler/thread.c b/scheduler/thread.c index f0024c7ef0f..bdd94432579 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -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) ); diff --git a/server/process.c b/server/process.c index 917785edfb1..bdf4be68e5e 100644 --- a/server/process.c +++ b/server/process.c @@ -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 ); } diff --git a/server/thread.c b/server/thread.c index d6e9bef4cde..d21cdd7a228 100644 --- a/server/thread.c +++ b/server/thread.c @@ -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: diff --git a/server/trace.c b/server/trace.c index c5ff2eae84d..58762c7ad39 100644 --- a/server/trace.c +++ b/server/trace.c @@ -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 ); } diff --git a/tools/winebuild/relay.c b/tools/winebuild/relay.c index a58c0a793bf..72efee3cac9 100644 --- a/tools/winebuild/relay.c +++ b/tools/winebuild/relay.c @@ -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" ); diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c index 31edeeed13d..df03d92d2dc 100644 --- a/tools/winebuild/spec16.c +++ b/tools/winebuild/spec16.c @@ -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 );