Commit 0a7c1f6c authored by Alexandre Julliard's avatar Alexandre Julliard

Implemented GetThreadSelectorEntry through the server.

parent 3d678afc
...@@ -148,6 +148,8 @@ struct boot_done_request ...@@ -148,6 +148,8 @@ struct boot_done_request
/* Initialize a process; called from the new process context */ /* Initialize a process; called from the new process context */
struct init_process_request struct init_process_request
{ {
IN void* ldt_copy; /* addr of LDT copy */
IN void* ldt_flags; /* addr of LDT flags */
OUT int start_flags; /* flags from startup info */ OUT int start_flags; /* flags from startup info */
OUT int hstdin; /* handle for stdin */ OUT int hstdin; /* handle for stdin */
OUT int hstdout; /* handle for stdout */ OUT int hstdout; /* handle for stdout */
...@@ -1031,6 +1033,17 @@ struct set_thread_context_request ...@@ -1031,6 +1033,17 @@ struct set_thread_context_request
}; };
/* Fetch a selector entry for a thread */
struct get_selector_entry_request
{
IN int handle; /* thread handle */
IN int entry; /* LDT entry */
OUT unsigned int base; /* selector base */
OUT unsigned int limit; /* selector limit */
OUT unsigned char flags; /* selector flags */
};
/* Everything below this line is generated automatically by tools/make_requests */ /* Everything below this line is generated automatically by tools/make_requests */
/* ### make_requests begin ### */ /* ### make_requests begin ### */
...@@ -1128,6 +1141,7 @@ enum request ...@@ -1128,6 +1141,7 @@ enum request
REQ_CANCEL_TIMER, REQ_CANCEL_TIMER,
REQ_GET_THREAD_CONTEXT, REQ_GET_THREAD_CONTEXT,
REQ_SET_THREAD_CONTEXT, REQ_SET_THREAD_CONTEXT,
REQ_GET_SELECTOR_ENTRY,
REQ_NB_REQUESTS REQ_NB_REQUESTS
}; };
......
...@@ -5,16 +5,18 @@ ...@@ -5,16 +5,18 @@
*/ */
#include <string.h> #include <string.h>
#include "winerror.h"
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "ldt.h" #include "ldt.h"
#include "miscemu.h" #include "miscemu.h"
#include "selectors.h" #include "selectors.h"
#include "stackframe.h" #include "stackframe.h"
#include "process.h" #include "process.h"
#include "server.h"
#include "debugtools.h" #include "debugtools.h"
#include "toolhelp.h" #include "toolhelp.h"
DEFAULT_DEBUG_CHANNEL(selector) DEFAULT_DEBUG_CHANNEL(selector);
/*********************************************************************** /***********************************************************************
...@@ -604,28 +606,74 @@ void WINAPI UnMapLS( SEGPTR sptr ) ...@@ -604,28 +606,74 @@ void WINAPI UnMapLS( SEGPTR sptr )
/*********************************************************************** /***********************************************************************
* GetThreadSelectorEntry (KERNEL32) * GetThreadSelectorEntry (KERNEL32)
* FIXME: add #ifdef i386 for non x86 */
*/ BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldtent)
BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, {
LPLDT_ENTRY ldtent) #ifdef __i386__
{ struct get_selector_entry_request *req = get_req_buffer();
ldt_entry ldtentry;
if (!(sel & 4)) /* GDT selector */
LDT_GetEntry(SELECTOR_TO_ENTRY(sel),&ldtentry); {
ldtent->BaseLow = ldtentry.base & 0x0000ffff; WORD seg;
ldtent->HighWord.Bits.BaseMid = (ldtentry.base & 0x00ff0000) >> 16; sel &= ~3; /* ignore RPL */
ldtent->HighWord.Bits.BaseHi = (ldtentry.base & 0xff000000) >> 24; if (!sel) /* null selector */
ldtent->LimitLow = ldtentry.limit & 0x0000ffff; {
ldtent->HighWord.Bits.LimitHi = (ldtentry.limit & 0x00ff0000) >> 16; memset( ldtent, 0, sizeof(*ldtent) );
ldtent->HighWord.Bits.Dpl = 3; return TRUE;
ldtent->HighWord.Bits.Sys = 0; }
ldtent->HighWord.Bits.Pres = 1; ldtent->BaseLow = 0;
ldtent->HighWord.Bits.Type = 0x10|(ldtentry.type << 2); ldtent->HighWord.Bits.BaseMid = 0;
if (!ldtentry.read_only) ldtent->HighWord.Bits.BaseHi = 0;
ldtent->HighWord.Bits.Type|=0x2; ldtent->LimitLow = 0xffff;
ldtent->HighWord.Bits.Granularity = ldtentry.limit_in_pages; ldtent->HighWord.Bits.LimitHi = 0xf;
ldtent->HighWord.Bits.Default_Big = ldtentry.seg_32bit; ldtent->HighWord.Bits.Dpl = 3;
ldtent->HighWord.Bits.Sys = 0;
ldtent->HighWord.Bits.Pres = 1;
ldtent->HighWord.Bits.Granularity = 1;
ldtent->HighWord.Bits.Default_Big = 1;
ldtent->HighWord.Bits.Type = 0x12;
/* it has to be one of the system GDT selectors */
GET_DS(seg);
if (sel == (seg & ~3)) return TRUE;
GET_SS(seg);
if (sel == (seg & ~3)) return TRUE;
GET_CS(seg);
if (sel == (seg & ~3))
{
ldtent->HighWord.Bits.Type |= 8; /* code segment */
return TRUE;
}
SetLastError( ERROR_NOACCESS );
return FALSE;
}
req->handle = hthread;
req->entry = sel >> __AHSHIFT;
if (server_call( REQ_GET_SELECTOR_ENTRY )) return FALSE;
if (!(req->flags & LDT_FLAGS_ALLOCATED))
{
SetLastError( ERROR_MR_MID_NOT_FOUND ); /* sic */
return FALSE;
}
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;
return TRUE; return TRUE;
#else
SetLastError( ERROR_NOT_IMPLEMENTED );
return FALSE;
#endif
} }
......
...@@ -254,6 +254,8 @@ static BOOL PROCESS_CreateEnvDB(void) ...@@ -254,6 +254,8 @@ static BOOL PROCESS_CreateEnvDB(void)
/* Retrieve startup info from the server */ /* Retrieve startup info from the server */
req->ldt_copy = ldt_copy;
req->ldt_flags = ldt_flags_copy;
if (server_call( REQ_INIT_PROCESS )) return FALSE; if (server_call( REQ_INIT_PROCESS )) return FALSE;
startup->dwFlags = req->start_flags; startup->dwFlags = req->start_flags;
startup->wShowWindow = req->cmd_show; startup->wShowWindow = req->cmd_show;
......
...@@ -149,6 +149,8 @@ struct thread *create_process( int fd, struct process *parent, ...@@ -149,6 +149,8 @@ struct thread *create_process( int fd, struct process *parent,
process->console_out = NULL; process->console_out = NULL;
process->init_event = NULL; process->init_event = NULL;
process->info = NULL; process->info = NULL;
process->ldt_copy = NULL;
process->ldt_flags = NULL;
gettimeofday( &process->start_time, NULL ); gettimeofday( &process->start_time, NULL );
if ((process->next = first_process) != NULL) process->next->prev = process; if ((process->next = first_process) != NULL) process->next->prev = process;
first_process = process; first_process = process;
...@@ -539,6 +541,8 @@ DECL_HANDLER(init_process) ...@@ -539,6 +541,8 @@ DECL_HANDLER(init_process)
fatal_protocol_error( current, "init_process: called twice\n" ); fatal_protocol_error( current, "init_process: called twice\n" );
return; return;
} }
current->process->ldt_copy = req->ldt_copy;
current->process->ldt_flags = req->ldt_flags;
current->process->info = NULL; current->process->info = NULL;
req->start_flags = info->start_flags; req->start_flags = info->start_flags;
req->hstdin = info->hstdin; req->hstdin = info->hstdin;
......
...@@ -34,6 +34,8 @@ struct process ...@@ -34,6 +34,8 @@ struct process
struct object *console_in; /* console input */ struct object *console_in; /* console input */
struct object *console_out; /* console output */ struct object *console_out; /* console output */
struct event *init_event; /* event for init done */ struct event *init_event; /* event for init done */
void *ldt_copy; /* pointer to LDT copy in client addr space */
void *ldt_flags; /* pointer to LDT flags in client addr space */
struct new_process_request *info; /* startup info (freed after startup) */ struct new_process_request *info; /* startup info (freed after startup) */
}; };
......
...@@ -162,6 +162,7 @@ DECL_HANDLER(set_timer); ...@@ -162,6 +162,7 @@ DECL_HANDLER(set_timer);
DECL_HANDLER(cancel_timer); DECL_HANDLER(cancel_timer);
DECL_HANDLER(get_thread_context); DECL_HANDLER(get_thread_context);
DECL_HANDLER(set_thread_context); DECL_HANDLER(set_thread_context);
DECL_HANDLER(get_selector_entry);
#ifdef WANT_REQUEST_HANDLERS #ifdef WANT_REQUEST_HANDLERS
...@@ -261,6 +262,7 @@ static const struct handler { ...@@ -261,6 +262,7 @@ static const struct handler {
{ (void(*)())req_cancel_timer, sizeof(struct cancel_timer_request) }, { (void(*)())req_cancel_timer, sizeof(struct cancel_timer_request) },
{ (void(*)())req_get_thread_context, sizeof(struct get_thread_context_request) }, { (void(*)())req_get_thread_context, sizeof(struct get_thread_context_request) },
{ (void(*)())req_set_thread_context, sizeof(struct set_thread_context_request) }, { (void(*)())req_set_thread_context, sizeof(struct set_thread_context_request) },
{ (void(*)())req_get_selector_entry, sizeof(struct get_selector_entry_request) },
}; };
#endif /* WANT_REQUEST_HANDLERS */ #endif /* WANT_REQUEST_HANDLERS */
......
...@@ -520,6 +520,37 @@ static int thread_queue_apc( struct thread *thread, void *func, void *param ) ...@@ -520,6 +520,37 @@ static int thread_queue_apc( struct thread *thread, void *func, void *param )
return 1; return 1;
} }
/* retrieve an LDT selector entry */
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)
{
set_error( STATUS_ACCESS_DENIED );
return;
}
if (entry >= 8192)
{
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
return;
}
suspend_thread( thread, 0 );
if (thread->attached)
{
unsigned char flags_buf[4];
int *addr = (int *)thread->process->ldt_copy + 2 * 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, (int *)flags_buf ) == -1) goto done;
*flags = flags_buf[entry & 3];
}
else set_error( STATUS_ACCESS_DENIED );
done:
resume_thread( thread );
}
/* kill a thread on the spot */ /* kill a thread on the spot */
void kill_thread( struct thread *thread, int exit_code ) void kill_thread( struct thread *thread, int exit_code )
{ {
...@@ -689,3 +720,14 @@ DECL_HANDLER(get_apcs) ...@@ -689,3 +720,14 @@ DECL_HANDLER(get_apcs)
current->apc_count = 0; current->apc_count = 0;
} }
} }
/* fetch a selector entry for a thread */
DECL_HANDLER(get_selector_entry)
{
struct thread *thread;
if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
{
get_selector_entry( thread, req->entry, &req->base, &req->limit, &req->flags );
release_object( thread );
}
}
...@@ -239,6 +239,8 @@ static void dump_boot_done_request( const struct boot_done_request *req ) ...@@ -239,6 +239,8 @@ static void dump_boot_done_request( const struct boot_done_request *req )
static void dump_init_process_request( const struct init_process_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 );
} }
static void dump_init_process_reply( const struct init_process_request *req ) static void dump_init_process_reply( const struct init_process_request *req )
...@@ -1167,6 +1169,19 @@ static void dump_set_thread_context_request( const struct set_thread_context_req ...@@ -1167,6 +1169,19 @@ static void dump_set_thread_context_request( const struct set_thread_context_req
dump_context( &req->context ); dump_context( &req->context );
} }
static void dump_get_selector_entry_request( const struct get_selector_entry_request *req )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " entry=%d", req->entry );
}
static void dump_get_selector_entry_reply( const struct get_selector_entry_request *req )
{
fprintf( stderr, " base=%08x,", req->base );
fprintf( stderr, " limit=%08x,", req->limit );
fprintf( stderr, " flags=%02x", req->flags );
}
static const dump_func req_dumpers[REQ_NB_REQUESTS] = { static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request, (dump_func)dump_new_process_request,
(dump_func)dump_new_thread_request, (dump_func)dump_new_thread_request,
...@@ -1260,6 +1275,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -1260,6 +1275,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_cancel_timer_request, (dump_func)dump_cancel_timer_request,
(dump_func)dump_get_thread_context_request, (dump_func)dump_get_thread_context_request,
(dump_func)dump_set_thread_context_request, (dump_func)dump_set_thread_context_request,
(dump_func)dump_get_selector_entry_request,
}; };
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
...@@ -1355,6 +1371,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -1355,6 +1371,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0, (dump_func)0,
(dump_func)dump_get_thread_context_reply, (dump_func)dump_get_thread_context_reply,
(dump_func)0, (dump_func)0,
(dump_func)dump_get_selector_entry_reply,
}; };
static const char * const req_names[REQ_NB_REQUESTS] = { static const char * const req_names[REQ_NB_REQUESTS] = {
...@@ -1450,6 +1467,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -1450,6 +1467,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"cancel_timer", "cancel_timer",
"get_thread_context", "get_thread_context",
"set_thread_context", "set_thread_context",
"get_selector_entry",
}; };
/* ### make_requests end ### */ /* ### make_requests end ### */
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
"int" => "%d", "int" => "%d",
"long" => "%ld", "long" => "%ld",
"char" => "%c", "char" => "%c",
"unsigned char" => "%02x",
"unsigned int" => "%08x", "unsigned int" => "%08x",
"void*" => "%p", "void*" => "%p",
"time_t" => "%ld", "time_t" => "%ld",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment