[PATCH] server: Add support for 64-bits client/server
mlankhorst
mlankhorst at dhcp-172-29-61-127.smo.corp.google.com
Wed Dec 3 08:36:11 CST 2008
---
dlls/ntdll/server.c | 21 +++++++++++++++++----
server/protocol.def | 27 +++++++++++++++++++--------
server/request.c | 24 ++++++++++++++++++++++--
server/thread.c | 37 +++++++++++++++++++++++++++++++------
4 files changed, 89 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index 64d9a8b..7d265c8 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -1008,6 +1008,7 @@ size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point )
int reply_pipe[2];
struct sigaction sig_act;
size_t info_size;
+ int pointer_bytes;
sig_act.sa_handler = SIG_IGN;
sig_act.sa_flags = 0;
@@ -1038,19 +1039,27 @@ size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point )
{
req->unix_pid = unix_pid;
req->unix_tid = unix_tid;
- req->teb = NtCurrentTeb();
- req->peb = NtCurrentTeb()->Peb;
- req->entry = entry_point;
- req->ldt_copy = &wine_ldt_copy;
+ req->teb = (int)(long)NtCurrentTeb();
+ req->peb = (int)(long)NtCurrentTeb()->Peb;
+ req->entry = (int)(long)entry_point;
+ req->ldt_copy = (int)(long)&wine_ldt_copy;
+#ifdef _WIN64
+ req->teb_high = (int)(((long)NtCurrentTeb()) >> 32L);
+ req->peb_high = (int)(((long)NtCurrentTeb()->Peb) >> 32L);
+ req->entry_high = (int)(((long)entry_point) >> 32L);
+ req->ldt_copy_high= (int)(((long)&wine_ldt_copy) >> 32L);
+#endif
req->reply_fd = reply_pipe[1];
req->wait_fd = ntdll_get_thread_data()->wait_fd[1];
req->debug_level = (TRACE_ON(server) != 0);
+ req->pointer_bytes= sizeof(void *);
ret = wine_server_call( req );
NtCurrentTeb()->ClientId.UniqueProcess = ULongToHandle(reply->pid);
NtCurrentTeb()->ClientId.UniqueThread = ULongToHandle(reply->tid);
info_size = reply->info_size;
version = reply->version;
server_start_time = reply->server_start;
+ pointer_bytes = reply->pointer_bytes;
}
SERVER_END_REQ;
@@ -1062,5 +1071,9 @@ size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point )
"Or maybe the wrong wineserver is still running?\n",
version, SERVER_PROTOCOL_VERSION,
(version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
+ if (sizeof(void*) != pointer_bytes)
+ server_protocol_error( "Wineserver doesn't support %d bits binaries,\n"
+ "instead it was built for %d bits binaries\n",
+ (int)sizeof(void*)*8, pointer_bytes*8 );
return info_size;
}
diff --git a/server/protocol.def b/server/protocol.def
index e0537bf..0a7026d 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -57,9 +57,13 @@ struct reply_header
/* this is used to construct the generic_request union */
struct request_max_size
{
- int pad[16]; /* the max request size is 16 ints */
+ long pad1[6]; /* request is 6 handles, and 10 ints */
+ int pad2[10];
};
+#define REQ_SIZE_64 (sizeof(__int64) * 6 + sizeof(int) * 10)
+#define REQ_SIZE_32 (sizeof(int) * 16)
+
#define FIRST_USER_HANDLE 0x0020 /* first possible value for low word of user handle */
#define LAST_USER_HANDLE 0xffef /* last possible value for low word of user handle */
@@ -522,19 +526,25 @@ typedef union
@REQ(init_thread)
int unix_pid; /* Unix pid of new thread */
int unix_tid; /* Unix tid of new thread */
- int debug_level; /* new debug level */
- void* teb; /* TEB of new thread (in thread address space) */
- void* peb; /* address of PEB (in thread address space) */
- void* entry; /* thread entry point (in thread address space) */
- void* ldt_copy; /* address of LDT copy (in thread address space) */
+ short int debug_level; /* new debug level */
+ short int pointer_bytes;/* Amount of bytes in a pointer (for the client) */
+ int teb; /* TEB of new thread (in thread address space) */
+ int peb; /* address of PEB (in thread address space) */
+ int entry; /* thread entry point (in thread address space) */
+ int ldt_copy; /* address of LDT copy (in thread address space) */
int reply_fd; /* fd for reply pipe */
int wait_fd; /* fd for blocking calls pipe */
+ int teb_high; /* upper 32-bits of TEB */
+ int peb_high; /* upper 32-bits op PEB */
+ int entry_high; /* upper 32-bits of entry point */
+ int ldt_copy_high;/* upper 32-bits of ldt copy high */
@REPLY
process_id_t pid; /* process id of the new thread's process */
thread_id_t tid; /* thread id of the new thread */
- data_size_t info_size; /* total size of startup info */
- timeout_t server_start; /* server start time */
+ timeout_t server_start; /* swapped with info size for 64-bits alignment*/
+ data_size_t info_size; /* swapped with server_start for alignment */
int version; /* protocol version */
+ int pointer_bytes;/* Amount of bytes in a pointer (for the server) */
@END
@@ -3108,3 +3118,4 @@ enum message_type
unsigned int alpha; /* alpha (0..255) */
unsigned int flags; /* LWA_* flags */
@END
+
diff --git a/server/request.c b/server/request.c
index 8726e1c..41b5c0d 100644
--- a/server/request.c
+++ b/server/request.c
@@ -314,8 +314,20 @@ void read_request( struct thread *thread )
if (!thread->req_toread) /* no pending request */
{
- if ((ret = read( get_unix_fd( thread->request_fd ), &thread->req,
- sizeof(thread->req) )) != sizeof(thread->req)) goto error;
+ ret = read( get_unix_fd( thread->request_fd ), &thread->req, sizeof(thread->req) );
+ if (sizeof(thread->req) == REQ_SIZE_64 && ret == REQ_SIZE_32)
+ {
+ /* Uh oh, we received a partial read, not an error per se, if
+ * we were connecting a 32-bit client to a 64-bit server
+ */
+ if (thread->req.request_header.req == REQ_init_thread &&
+ thread->req.init_thread_request.pointer_bytes != sizeof(void *))
+ {
+ /* Do nothing, this is a 32-bits client */
+ }
+ else
+ goto error;
+ }
if (!(thread->req_toread = thread->req.request_header.request_size))
{
/* no data, handle request at once */
@@ -744,6 +756,14 @@ void open_master_socket(void)
assert( sizeof(union generic_request) == sizeof(struct request_max_size) );
assert( sizeof(union generic_reply) == sizeof(struct request_max_size) );
+ /* Make sure REQ_SIZE_32 and REQ_SIZE_64 are of correct size */
+ if (sizeof(void *) == sizeof(int))
+ assert(sizeof(struct request_max_size) == REQ_SIZE_32);
+ else if (sizeof(void *) == sizeof(__int64))
+ assert(sizeof(struct request_max_size) == REQ_SIZE_64);
+ else
+ assert(0);
+
if (!server_dir) fatal_error( "directory %s cannot be accessed\n", config_dir );
if (chdir( config_dir ) == -1) fatal_perror( "chdir to %s", config_dir );
if ((config_dir_fd = open( ".", O_RDONLY )) == -1) fatal_perror( "open %s", config_dir );
diff --git a/server/thread.c b/server/thread.c
index 0c496db..848a54f 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1011,7 +1011,8 @@ DECL_HANDLER(init_thread)
{
struct process *process = current->process;
int reply_fd = thread_get_inflight_fd( current, req->reply_fd );
- int wait_fd = thread_get_inflight_fd( current, req->wait_fd );
+ int wait_fd = -1;
+ void *teb, *peb, *ldt_copy, *entry;
if (current->reply_fd) /* already initialised */
{
@@ -1025,6 +1026,29 @@ DECL_HANDLER(init_thread)
reply_fd = -1;
if (!current->reply_fd) goto error;
+ /* The version of wine is too old, or a different-sized binary was trying
+ * to connect
+ */
+ if (req->pointer_bytes != sizeof(void *))
+ {
+ reply->version = SERVER_PROTOCOL_VERSION;
+ reply->pointer_bytes = sizeof(void *);
+ return;
+ }
+
+#ifndef _WIN64
+ teb = (void *)(long)req->teb;
+ peb = (void *)(long)req->peb;
+ ldt_copy = (void *)(long)req->ldt_copy;
+ entry = (void *)(long)req->entry;
+#else
+ teb = (void *)(((long)req->teb) + (((long)req->teb_high) << 32L));
+ peb = (void *)(((long)req->teb) + (((long)req->peb_high) << 32L));
+ ldt_copy = (void *)(((long)req->ldt_copy) + (((long)req->ldt_copy_high) << 32L));
+ entry = (void *)(((long)req->entry) + (((long)req->entry_high) << 32L));
+#endif
+
+ wait_fd = thread_get_inflight_fd( current, req->wait_fd );
if (wait_fd == -1)
{
set_error( STATUS_TOO_MANY_OPENED_FILES ); /* most likely reason */
@@ -1033,7 +1057,7 @@ DECL_HANDLER(init_thread)
if (!(current->wait_fd = create_anonymous_fd( &thread_fd_ops, wait_fd, ¤t->obj, 0 )))
return;
- if (!is_valid_address(req->teb) || !is_valid_address(req->peb) || !is_valid_address(req->ldt_copy))
+ if (!is_valid_address(teb) || !is_valid_address(peb) || !is_valid_address(ldt_copy))
{
set_error( STATUS_INVALID_PARAMETER );
return;
@@ -1041,13 +1065,13 @@ DECL_HANDLER(init_thread)
current->unix_pid = req->unix_pid;
current->unix_tid = req->unix_tid;
- current->teb = req->teb;
+ current->teb = teb;
if (!process->peb) /* first thread, initialize the process too */
{
process->unix_pid = current->unix_pid;
- process->peb = req->peb;
- process->ldt_copy = req->ldt_copy;
+ process->peb = peb;
+ process->ldt_copy = ldt_copy;
reply->info_size = init_process( current );
}
else
@@ -1055,7 +1079,7 @@ DECL_HANDLER(init_thread)
if (process->unix_pid != current->unix_pid)
process->unix_pid = -1; /* can happen with linuxthreads */
if (current->suspend + process->suspend > 0) stop_thread( current );
- generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
+ generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, entry );
}
debug_level = max( debug_level, req->debug_level );
@@ -1063,6 +1087,7 @@ DECL_HANDLER(init_thread)
reply->tid = get_thread_id( current );
reply->version = SERVER_PROTOCOL_VERSION;
reply->server_start = server_start_time;
+ reply->pointer_bytes = sizeof(void *);
return;
error:
--
1.5.6.5
--------------080302040609030601000308--
More information about the wine-patches
mailing list