diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 8e54c9942771..734aebb53907 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -2465,6 +2465,20 @@ static void dlopen_32on64_opengl32(void) } #endif +BOOL simulate_writecopy; + +static void hacks_init(void) +{ + const char *env_str; + + env_str = getenv("WINE_SIMULATE_WRITECOPY"); + if (env_str) simulate_writecopy = atoi(env_str); + else simulate_writecopy = main_argc > 1 && ( + strstr(main_argv[1], "UplayWebCore.exe") + || strstr(main_argv[1], "Battle.net.exe") /* CW HACK 23072 */ + ); +} + /*********************************************************************** * start_main_thread */ @@ -2479,6 +2493,7 @@ static void start_main_thread(void) signal_init_thread( teb ); dbg_init(); startup_info_size = server_init_process(); + hacks_init(); msync_init(); esync_init(); virtual_map_user_shared_data(); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index f5f410ae8701..fcad50f232af 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -163,6 +163,7 @@ extern USHORT ds32_sel DECLSPEC_HIDDEN; extern USHORT cs64_sel DECLSPEC_HIDDEN; #endif +extern BOOL simulate_writecopy; extern void init_environment( int argc, char *argv[], char *envp[] ) DECLSPEC_HIDDEN; extern void init_startup_info(void) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 8ead2cc99d7f..a8345548d801 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -120,6 +120,7 @@ struct file_view #define VPROT_GUARD 0x10 #define VPROT_COMMITTED 0x20 #define VPROT_WRITEWATCH 0x40 +#define VPROT_COPIED 0x80 /* per-mapping protection flags */ #define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */ @@ -4134,6 +4135,16 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T { old = get_win32_prot( vprot, view->protect ); status = set_protection( view, base, size, new_prot ); + + if (simulate_writecopy && status == STATUS_SUCCESS + && ((old == PAGE_WRITECOPY || old == PAGE_EXECUTE_WRITECOPY))) + { + TRACE("Setting VPROT_COPIED.\n"); + + set_page_vprot_bits(base, size, VPROT_COPIED, 0); + vprot |= VPROT_COPIED; + old = get_win32_prot( vprot, view->protect ); + } } else status = STATUS_NOT_COMMITTED; }