From ac69fcb14feb4afb9ea78d349749f2c573cbdda8 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 4 May 2010 18:23:29 +0200 Subject: [PATCH] server: Check that the prefix type can support the client architecture. --- dlls/kernel32/process.c | 14 -------------- dlls/ntdll/server.c | 28 ++++++++++++++++------------ server/object.h | 1 + server/registry.c | 28 ++++++++++++++++++++++++++++ server/thread.c | 10 +++++++--- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 1062aa6036c..9a1f2f52426 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -908,11 +908,8 @@ static void start_wineboot( HANDLE handles[2] ) { static const WCHAR wineboot[] = {'\\','w','i','n','e','b','o','o','t','.','e','x','e',0}; static const WCHAR args[] = {' ','-','-','i','n','i','t',0}; - const DWORD expected_type = (sizeof(void*) > sizeof(int) || is_wow64) ? - SCS_64BIT_BINARY : SCS_32BIT_BINARY; STARTUPINFOW si; PROCESS_INFORMATION pi; - DWORD type; void *redir; WCHAR app[MAX_PATH]; WCHAR cmdline[MAX_PATH + (sizeof(wineboot) + sizeof(args)) / sizeof(WCHAR)]; @@ -928,17 +925,6 @@ static void start_wineboot( HANDLE handles[2] ) lstrcatW( app, wineboot ); Wow64DisableWow64FsRedirection( &redir ); - if (GetBinaryTypeW( app, &type ) && type != expected_type) - { - if (type == SCS_64BIT_BINARY) - MESSAGE( "wine: '%s' is a 64-bit prefix, it cannot be used with 32-bit Wine.\n", - wine_get_config_dir() ); - else - MESSAGE( "wine: '%s' is a 32-bit prefix, it cannot be used with %s Wine.\n", - wine_get_config_dir(), is_wow64 ? "wow64" : "64-bit" ); - ExitProcess( 1 ); - } - strcpyW( cmdline, app ); strcatW( cmdline, args ); if (CreateProcessW( app, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi )) diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 568f0c5df87..08ee7843ddc 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -1039,6 +1039,7 @@ NTSTATUS server_init_process_done(void) */ size_t server_init_thread( void *entry_point ) { + static const int is_win64 = (sizeof(void *) > sizeof(int)); int ret; int reply_pipe[2]; struct sigaction sig_act; @@ -1083,20 +1084,23 @@ size_t server_init_thread( void *entry_point ) } SERVER_END_REQ; -#ifndef _WIN64 - is_wow64 = (server_cpus & (1 << CPU_x86_64)) != 0; -#endif + is_wow64 = !is_win64 && (server_cpus & (1 << CPU_x86_64)) != 0; ntdll_get_thread_data()->wow64_redir = is_wow64; - if (ret) + switch (ret) { - if (ret == STATUS_NOT_SUPPORTED) - { - static const char * const cpu_arch[] = { "x86", "x86_64", "Alpha", "PowerPC", "Sparc" }; - server_protocol_error( "the running wineserver doesn't support the %s architecture.\n", - cpu_arch[client_cpu] ); - } - else server_protocol_error( "init_thread failed with status %x\n", ret ); + case STATUS_SUCCESS: + return info_size; + case STATUS_NOT_REGISTRY_FILE: + fatal_error( "'%s' is a 32-bit installation, it cannot support 64-bit applications.\n", + wine_get_config_dir() ); + case STATUS_NOT_SUPPORTED: + if (is_win64) + fatal_error( "wineserver is 32-bit, it cannot support 64-bit applications.\n" ); + else + fatal_error( "'%s' is a 64-bit installation, it cannot be used with a 32-bit wineserver.\n", + wine_get_config_dir() ); + default: + server_protocol_error( "init_thread failed with status %x\n", ret ); } - return info_size; } diff --git a/server/object.h b/server/object.h index 01dc00ea93a..172c3f763a0 100644 --- a/server/object.h +++ b/server/object.h @@ -186,6 +186,7 @@ extern int get_page_size(void); /* registry functions */ +extern unsigned int get_prefix_cpu_mask(void); extern void init_registry(void); extern void flush_registry(void); diff --git a/server/registry.c b/server/registry.c index 7f782096449..483b064325a 100644 --- a/server/registry.c +++ b/server/registry.c @@ -1641,6 +1641,34 @@ static WCHAR *format_user_registry_path( const SID *sid, struct unicode_str *pat return p; } +/* get the cpu architectures that can be supported in the current prefix */ +unsigned int get_prefix_cpu_mask(void) +{ + /* Allowed server/client/prefix combinations: + * + * prefix + * 32 64 + * server +------+------+ client + * | ok | fail | 32 + * 32 +------+------+--- + * | fail | fail | 64 + * ---+------+------+--- + * | ok | ok | 32 + * 64 +------+------+--- + * | fail | ok | 64 + * ---+------+------+--- + */ + switch (prefix_type) + { + case PREFIX_64BIT: + /* 64-bit prefix requires 64-bit server */ + return sizeof(void *) > sizeof(int) ? ~0 : 0; + case PREFIX_32BIT: + default: + return ~CPU_64BIT_MASK; /* only 32-bit cpus supported on 32-bit prefix */ + } +} + /* registry initialisation */ void init_registry(void) { diff --git a/server/thread.c b/server/thread.c index 1c3e5bb6eed..c4deb68df62 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1098,6 +1098,7 @@ DECL_HANDLER(new_thread) /* initialize a new thread */ DECL_HANDLER(init_thread) { + unsigned int prefix_cpu_mask = get_prefix_cpu_mask(); 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 ); @@ -1134,9 +1135,12 @@ DECL_HANDLER(init_thread) if (!process->peb) /* first thread, initialize the process too */ { - if (!CPU_FLAG(req->cpu) || !(supported_cpus & CPU_FLAG(req->cpu))) + if (!CPU_FLAG(req->cpu) || !(supported_cpus & prefix_cpu_mask & CPU_FLAG(req->cpu))) { - set_error( STATUS_NOT_SUPPORTED ); + if (!(supported_cpus & CPU_64BIT_MASK)) + set_error( STATUS_NOT_SUPPORTED ); + else + set_error( STATUS_NOT_REGISTRY_FILE ); /* server supports it but not the prefix */ return; } process->unix_pid = current->unix_pid; @@ -1163,7 +1167,7 @@ DECL_HANDLER(init_thread) reply->tid = get_thread_id( current ); reply->version = SERVER_PROTOCOL_VERSION; reply->server_start = server_start_time; - reply->all_cpus = supported_cpus; + reply->all_cpus = supported_cpus & prefix_cpu_mask; return; error: