Implemented GetThreadSelectorEntry through the server.
This commit is contained in:
parent
3d678afc4c
commit
0a7c1f6c5b
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ### */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"int" => "%d",
|
||||
"long" => "%ld",
|
||||
"char" => "%c",
|
||||
"unsigned char" => "%02x",
|
||||
"unsigned int" => "%08x",
|
||||
"void*" => "%p",
|
||||
"time_t" => "%ld",
|
||||
|
|
Loading…
Reference in New Issue