Implemented GetThreadSelectorEntry through the server.
diff --git a/server/process.c b/server/process.c
index b2743e1..915ecf6 100644
--- a/server/process.c
+++ b/server/process.c
@@ -149,6 +149,8 @@
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 @@
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;
diff --git a/server/process.h b/server/process.h
index 737de56..6e84a32 100644
--- a/server/process.h
+++ b/server/process.h
@@ -34,6 +34,8 @@
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) */
};
diff --git a/server/request.h b/server/request.h
index c9fcd10..9957e4e 100644
--- a/server/request.h
+++ b/server/request.h
@@ -162,6 +162,7 @@
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 @@
{ (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 */
diff --git a/server/thread.c b/server/thread.c
index d2c5a56..962a7bf 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -520,6 +520,37 @@
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 @@
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 );
+ }
+}
diff --git a/server/trace.c b/server/trace.c
index 89547b5..391125d 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -239,6 +239,8 @@
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 @@
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 @@
(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 @@
(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 @@
"cancel_timer",
"get_thread_context",
"set_thread_context",
+ "get_selector_entry",
};
/* ### make_requests end ### */