Implemented GetThreadSelectorEntry through the server.

This commit is contained in:
Alexandre Julliard 2000-01-27 02:54:17 +00:00
parent 3d678afc4c
commit 0a7c1f6c5b
9 changed files with 152 additions and 19 deletions

View File

@ -148,6 +148,8 @@ struct boot_done_request
/* Initialize a process; called from the new process context */
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 hstdin; /* handle for stdin */
OUT int hstdout; /* handle for stdout */
@ -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 */
/* ### make_requests begin ### */
@ -1128,6 +1141,7 @@ enum request
REQ_CANCEL_TIMER,
REQ_GET_THREAD_CONTEXT,
REQ_SET_THREAD_CONTEXT,
REQ_GET_SELECTOR_ENTRY,
REQ_NB_REQUESTS
};

View File

@ -5,16 +5,18 @@
*/
#include <string.h>
#include "winerror.h"
#include "wine/winbase16.h"
#include "ldt.h"
#include "miscemu.h"
#include "selectors.h"
#include "stackframe.h"
#include "process.h"
#include "server.h"
#include "debugtools.h"
#include "toolhelp.h"
DEFAULT_DEBUG_CHANNEL(selector)
DEFAULT_DEBUG_CHANNEL(selector);
/***********************************************************************
@ -604,28 +606,74 @@ void WINAPI UnMapLS( SEGPTR sptr )
/***********************************************************************
* 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)
{
ldt_entry ldtentry;
#ifdef __i386__
struct get_selector_entry_request *req = get_req_buffer();
LDT_GetEntry(SELECTOR_TO_ENTRY(sel),&ldtentry);
ldtent->BaseLow = ldtentry.base & 0x0000ffff;
ldtent->HighWord.Bits.BaseMid = (ldtentry.base & 0x00ff0000) >> 16;
ldtent->HighWord.Bits.BaseHi = (ldtentry.base & 0xff000000) >> 24;
ldtent->LimitLow = ldtentry.limit & 0x0000ffff;
ldtent->HighWord.Bits.LimitHi = (ldtentry.limit & 0x00ff0000) >> 16;
ldtent->HighWord.Bits.Dpl = 3;
ldtent->HighWord.Bits.Sys = 0;
ldtent->HighWord.Bits.Pres = 1;
ldtent->HighWord.Bits.Type = 0x10|(ldtentry.type << 2);
if (!ldtentry.read_only)
ldtent->HighWord.Bits.Type|=0x2;
ldtent->HighWord.Bits.Granularity = ldtentry.limit_in_pages;
ldtent->HighWord.Bits.Default_Big = ldtentry.seg_32bit;
if (!(sel & 4)) /* GDT selector */
{
WORD seg;
sel &= ~3; /* ignore RPL */
if (!sel) /* null selector */
{
memset( ldtent, 0, sizeof(*ldtent) );
return TRUE;
}
ldtent->BaseLow = 0;
ldtent->HighWord.Bits.BaseMid = 0;
ldtent->HighWord.Bits.BaseHi = 0;
ldtent->LimitLow = 0xffff;
ldtent->HighWord.Bits.LimitHi = 0xf;
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;
#else
SetLastError( ERROR_NOT_IMPLEMENTED );
return FALSE;
#endif
}

View File

@ -254,6 +254,8 @@ static BOOL PROCESS_CreateEnvDB(void)
/* 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;
startup->dwFlags = req->start_flags;
startup->wShowWindow = req->cmd_show;

View File

@ -149,6 +149,8 @@ struct thread *create_process( int fd, struct process *parent,
process->console_out = NULL;
process->init_event = NULL;
process->info = NULL;
process->ldt_copy = NULL;
process->ldt_flags = NULL;
gettimeofday( &process->start_time, NULL );
if ((process->next = first_process) != NULL) process->next->prev = process;
first_process = process;
@ -539,6 +541,8 @@ DECL_HANDLER(init_process)
fatal_protocol_error( current, "init_process: called twice\n" );
return;
}
current->process->ldt_copy = req->ldt_copy;
current->process->ldt_flags = req->ldt_flags;
current->process->info = NULL;
req->start_flags = info->start_flags;
req->hstdin = info->hstdin;

View File

@ -34,6 +34,8 @@ struct process
struct object *console_in; /* console input */
struct object *console_out; /* console output */
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) */
};

View File

@ -162,6 +162,7 @@ DECL_HANDLER(set_timer);
DECL_HANDLER(cancel_timer);
DECL_HANDLER(get_thread_context);
DECL_HANDLER(set_thread_context);
DECL_HANDLER(get_selector_entry);
#ifdef WANT_REQUEST_HANDLERS
@ -261,6 +262,7 @@ static const struct handler {
{ (void(*)())req_cancel_timer, sizeof(struct cancel_timer_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_get_selector_entry, sizeof(struct get_selector_entry_request) },
};
#endif /* WANT_REQUEST_HANDLERS */

View File

@ -520,6 +520,37 @@ static int thread_queue_apc( struct thread *thread, void *func, void *param )
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 */
void kill_thread( struct thread *thread, int exit_code )
{
@ -689,3 +720,14 @@ DECL_HANDLER(get_apcs)
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 );
}
}

View File

@ -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 )
{
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 )
@ -1167,6 +1169,19 @@ static void dump_set_thread_context_request( const struct set_thread_context_req
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] = {
(dump_func)dump_new_process_request,
(dump_func)dump_new_thread_request,
@ -1260,6 +1275,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_cancel_timer_request,
(dump_func)dump_get_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] = {
@ -1355,6 +1371,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0,
(dump_func)dump_get_thread_context_reply,
(dump_func)0,
(dump_func)dump_get_selector_entry_reply,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@ -1450,6 +1467,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"cancel_timer",
"get_thread_context",
"set_thread_context",
"get_selector_entry",
};
/* ### make_requests end ### */

View File

@ -11,6 +11,7 @@
"int" => "%d",
"long" => "%ld",
"char" => "%c",
"unsigned char" => "%02x",
"unsigned int" => "%08x",
"void*" => "%p",
"time_t" => "%ld",