diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index b4e2d15e983..e812f634ff9 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -2301,6 +2301,11 @@ int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh) #define LDT_SIZE 8192 +#define LDT_FLAGS_DATA 0x13 /* Data segment */ +#define LDT_FLAGS_CODE 0x1b /* Code segment */ +#define LDT_FLAGS_32BIT 0x40 /* Segment is 32-bit (code or stack) */ +#define LDT_FLAGS_ALLOCATED 0x80 /* Segment is allocated */ + static WORD gdt_fs_sel; static RTL_CRITICAL_SECTION ldt_section; @@ -2335,13 +2340,36 @@ static void ldt_unlock(void) else RtlLeaveCriticalSection( &ldt_section ); } +static inline void *ldt_get_base( LDT_ENTRY ent ) +{ + return (void *)(ent.BaseLow | + (ULONG_PTR)ent.HighWord.Bits.BaseMid << 16 | + (ULONG_PTR)ent.HighWord.Bits.BaseHi << 24); +} + +static inline unsigned int ldt_get_limit( LDT_ENTRY ent ) +{ + unsigned int limit = ent.LimitLow | (ent.HighWord.Bits.LimitHi << 16); + if (ent.HighWord.Bits.Granularity) limit = (limit << 12) | 0xfff; + return limit; +} + static LDT_ENTRY ldt_make_entry( void *base, unsigned int limit, unsigned char flags ) { LDT_ENTRY entry; - wine_ldt_set_base( &entry, base ); - wine_ldt_set_limit( &entry, limit ); - wine_ldt_set_flags( &entry, flags ); + entry.BaseLow = (WORD)(ULONG_PTR)base; + entry.HighWord.Bits.BaseMid = (BYTE)((ULONG_PTR)base >> 16); + entry.HighWord.Bits.BaseHi = (BYTE)((ULONG_PTR)base >> 24); + if ((entry.HighWord.Bits.Granularity = (limit >= 0x100000))) limit >>= 12; + entry.LimitLow = (WORD)limit; + entry.HighWord.Bits.LimitHi = limit >> 16; + entry.HighWord.Bits.Dpl = 3; + entry.HighWord.Bits.Pres = 1; + entry.HighWord.Bits.Type = flags; + entry.HighWord.Bits.Sys = 0; + entry.HighWord.Bits.Reserved_0 = 0; + entry.HighWord.Bits.Default_Big = (flags & LDT_FLAGS_32BIT) != 0; return entry; } @@ -2352,7 +2380,7 @@ static void ldt_set_entry( WORD sel, LDT_ENTRY entry ) #ifdef linux struct modify_ldt_s ldt_info = { index }; - ldt_info.base_addr = wine_ldt_get_base( &entry ); + ldt_info.base_addr = 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; @@ -2374,7 +2402,7 @@ static void ldt_set_entry( WORD sel, LDT_ENTRY entry ) struct ssd ldt_mod; ldt_mod.sel = sel; - ldt_mod.bo = (unsigned long)wine_ldt_get_base(&entry); + ldt_mod.bo = (unsigned long)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; @@ -2389,11 +2417,11 @@ static void ldt_set_entry( WORD sel, LDT_ENTRY entry ) exit(1); #endif - wine_ldt_copy.base[index] = wine_ldt_get_base( &entry ); - wine_ldt_copy.limit[index] = wine_ldt_get_limit( &entry ); + wine_ldt_copy.base[index] = ldt_get_base( entry ); + wine_ldt_copy.limit[index] = 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_FLAGS_ALLOCATED); + (entry.HighWord.Bits.Default_Big ? LDT_FLAGS_32BIT : 0) | + LDT_FLAGS_ALLOCATED); } static void ldt_init(void) @@ -2422,7 +2450,7 @@ WORD ldt_alloc_fs( TEB *teb, int first_thread ) if (gdt_fs_sel) return gdt_fs_sel; - entry = ldt_make_entry( teb, teb_size - 1, WINE_LDT_FLAGS_DATA | WINE_LDT_FLAGS_32BIT ); + entry = ldt_make_entry( teb, teb_size - 1, LDT_FLAGS_DATA | LDT_FLAGS_32BIT ); if (first_thread) /* no locking for first thread */ { @@ -2490,11 +2518,11 @@ NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_ if (!(info->Selector & ~3)) info->Entry = null_entry; else if ((info->Selector | 3) == wine_get_cs()) - info->Entry = ldt_make_entry( 0, ~0u, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT ); + info->Entry = ldt_make_entry( 0, ~0u, LDT_FLAGS_CODE | LDT_FLAGS_32BIT ); else if ((info->Selector | 3) == wine_get_ds()) - info->Entry = ldt_make_entry( 0, ~0u, WINE_LDT_FLAGS_DATA | WINE_LDT_FLAGS_32BIT ); + info->Entry = ldt_make_entry( 0, ~0u, LDT_FLAGS_DATA | LDT_FLAGS_32BIT ); else if ((info->Selector | 3) == wine_get_fs()) - info->Entry = ldt_make_entry( NtCurrentTeb(), 0xfff, WINE_LDT_FLAGS_DATA | WINE_LDT_FLAGS_32BIT ); + info->Entry = ldt_make_entry( NtCurrentTeb(), 0xfff, LDT_FLAGS_DATA | LDT_FLAGS_32BIT ); else return STATUS_UNSUCCESSFUL; }