[PATCH] server: Add support for 64-bits
mlankhorst
mlankhorst at dhcp-172-29-61-127.smo.corp.google.com
Tue Dec 2 07:06:49 CST 2008
---
dlls/ntdll/server.c | 7 +++
server/protocol.def | 12 +++-
server/request.c | 14 +++++-
server/thread.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 156 insertions(+), 14 deletions(-)
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index 64d9a8b..012d5e7 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;
@@ -1045,12 +1046,14 @@ size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point )
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 +1065,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",
+ (int)sizeof(void*)*8, pointer_bytes*8 );
return info_size;
}
diff --git a/server/protocol.def b/server/protocol.def
index e0537bf..4a98832 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 */
@@ -152,6 +156,7 @@ struct wake_up_reply
/* NT-style timeout, in 100ns units, negative means relative timeout */
typedef __int64 timeout_t;
+
#define TIMEOUT_INFINITE (((timeout_t)0x7fffffff) << 32 | 0xffffffff)
/* structure returned in the list of window properties */
@@ -523,6 +528,7 @@ typedef union
int unix_pid; /* Unix pid of new thread */
int unix_tid; /* Unix tid of new thread */
int debug_level; /* new debug level */
+ int pointer_bytes;/* Amount of bytes in a pointer (of the client) */
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) */
@@ -532,12 +538,12 @@ typedef union
@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 */
+ data_size_t info_size; /* total size of startup info */
int version; /* protocol version */
+ int pointer_bytes;/* Amount of bytes in a pointer (of the server) */
@END
-
/* Terminate a process */
@REQ(terminate_process)
obj_handle_t handle; /* process handle to terminate */
diff --git a/server/request.c b/server/request.c
index 8726e1c..cb08e35 100644
--- a/server/request.c
+++ b/server/request.c
@@ -314,8 +314,10 @@ 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 (ret != REQ_SIZE_64 && ret != REQ_SIZE_32)
+ goto error;
+
if (!(thread->req_toread = thread->req.request_header.request_size))
{
/* no data, handle request at once */
@@ -744,6 +746,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..9ee2eb3 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1006,12 +1006,123 @@ DECL_HANDLER(new_thread)
}
}
+/* Wineserver protocol <= 346 type init_thread request structure */
+struct init_thread_request_legacy32
+{
+ struct request_header __header;
+ int unix_pid;
+ int unix_tid;
+ int debug_level;
+ int teb;
+ int peb;
+ int entry;
+ int ldt_copy;
+ int reply_fd;
+ int wait_fd;
+};
+
+/* Current type init_thread request structure, pointer size = 32 */
+struct init_thread_request32
+{
+ struct request_header __header;
+ int unix_pid;
+ int unix_tid;
+ int debug_level;
+ int pointer_bytes;
+ int teb;
+ int peb;
+ int entry;
+ int ldt_copy;
+ int reply_fd;
+ int wait_fd;
+};
+
+/* Current type init_thread request structure, pointer size = 64 */
+struct init_thread_request64
+{
+ struct request_header __header;
+ int unix_pid;
+ int unix_tid;
+ int debug_level;
+ int pointer_bytes;
+ __int64 teb;
+ __int64 peb;
+ __int64 entry;
+ __int64 ldt_copy;
+ int reply_fd;
+ int wait_fd;
+};
+
/* initialize a new thread */
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 reply_fd, wait_fd;
+ void *ldt_copy, *entry, *peb, *teb;
+
+ /* 64-bits wineserver with 32-bits interaction is not yet supported
+ * "fake" success, but return the version and pointer bytes
+ * The client will terminate itself after reading the wrong
+ * protocol version or because of the pointer size mismatch
+ */
+
+ /* First upconvert 'old' wineserver requests from pure 32-bits wine
+ */
+ if (req->pointer_bytes != sizeof(void *) && req->pointer_bytes > 8)
+ {
+ struct init_thread_request_legacy32 *reql =
+ (struct init_thread_request_legacy32 *)req;
+
+ wait_fd = reql->wait_fd;
+ reply_fd = reql->reply_fd;
+ ldt_copy = (void *)(long)reql->ldt_copy;
+ entry = (void *)(long)reql->entry;
+ peb = (void *)(long)reql->peb;
+ teb = (void *)(long)reql->teb;
+ }
+ /* Case where a 64-bits client tries to connect to 32-bits wineserver
+ * The pointer types will be invalid, but we continue anyway to make
+ * it possible for the 64-bits client to realize that the pointer type
+ * is wrong
+ */
+ else if (req->pointer_bytes > sizeof(void *))
+ {
+ struct init_thread_request64 *req64 =
+ (struct init_thread_request64 *)req;
+
+ wait_fd = req64->wait_fd;
+ reply_fd = req64->reply_fd;
+ ldt_copy = (void *)(long)req64->ldt_copy;
+ entry = (void *)(long)req64->entry;
+ peb = (void *)(long)req64->peb;
+ teb = (void *)(long)req64->teb;
+ }
+ /* Case where a 32-bits client tries to connect to a 64-bits wineserver */
+ else if (req->pointer_bytes < sizeof(void *))
+ {
+ struct init_thread_request32 *req32 =
+ (struct init_thread_request32 *)req;
+
+ wait_fd = req32->wait_fd;
+ reply_fd = req32->reply_fd;
+ ldt_copy = (void *)(long)req32->ldt_copy;
+ entry = (void *)(long)req32->entry;
+ peb = (void *)(long)req32->peb;
+ teb = (void *)(long)req32->teb;
+ }
+ /* XX-bits client converts to XX-bits server */
+ else
+ {
+ wait_fd = req->wait_fd;
+ reply_fd = req->reply_fd;
+ ldt_copy = req->ldt_copy;
+ entry = req->entry;
+ peb = req->peb;
+ teb = req->teb;
+ }
+
+ reply_fd = thread_get_inflight_fd( current, reply_fd );
+ wait_fd = thread_get_inflight_fd( current, wait_fd );
if (current->reply_fd) /* already initialised */
{
@@ -1033,21 +1144,28 @@ 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))
+ /* Skip the validity checks if connecting a 64-bits client to 32-bits wineserver
+ * The client will realize its mistake, print an error about incompatibility
+ * and exit
+ */
+ if (req->pointer_bytes != 8 || sizeof(void *) != sizeof(int))
{
- set_error( STATUS_INVALID_PARAMETER );
- return;
+ if (!is_valid_address(teb) || !is_valid_address(peb) || !is_valid_address(ldt_copy))
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
}
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,13 +1173,14 @@ 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 );
reply->pid = get_process_id( process );
reply->tid = get_thread_id( current );
reply->version = SERVER_PROTOCOL_VERSION;
+ reply->pointer_bytes = sizeof(void *);
reply->server_start = server_start_time;
return;
--
1.5.6.5
--------------030701000408010007050700--
More information about the wine-patches
mailing list