@ -0,0 +1,41 @@ | |||||
Original patch code by Valve Corporation | |||||
Original commits: | |||||
https://github.com/ValveSoftware/wine/commit/62c9478e4768e94e841da2ef75eb778ed346e3ab | |||||
LICENSE: See https://github.com/ValveSoftware/wine | |||||
Target Wine version of this patch file: | |||||
Wine 4.9 (Vanilla/Non-staging) | |||||
--- a/dlls/kernel32/heap.c | |||||
+++ b/dlls/kernel32/heap.c | |||||
@@ -75,6 +75,7 @@ WINE_DECLARE_DEBUG_CHANNEL(globalmem); | |||||
static HANDLE systemHeap; /* globally shared heap */ | |||||
+extern BOOL CDECL __wine_needs_override_large_address_aware(void); | |||||
/*********************************************************************** | |||||
* HEAP_CreateSystemHeap | |||||
@@ -1375,6 +1376,10 @@ VOID WINAPI GlobalMemoryStatus( LPMEMORY | |||||
MEMORYSTATUSEX memstatus; | |||||
OSVERSIONINFOW osver; | |||||
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( GetModuleHandleW(0) ); | |||||
+ static int force_large_address_aware = -1; | |||||
+ | |||||
+ if (force_large_address_aware == -1) | |||||
+ force_large_address_aware = __wine_needs_override_large_address_aware(); | |||||
/* Because GlobalMemoryStatus is identical to GlobalMemoryStatusEX save | |||||
for one extra field in the struct, and the lack of a bug, we simply | |||||
@@ -1415,7 +1420,8 @@ VOID WINAPI GlobalMemoryStatus( LPMEMORY | |||||
/* values are limited to 2Gb unless the app has the IMAGE_FILE_LARGE_ADDRESS_AWARE flag */ | |||||
/* page file sizes are not limited (Adobe Illustrator 8 depends on this) */ | |||||
- if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) | |||||
+ if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) && | |||||
+ !force_large_address_aware) | |||||
{ | |||||
if (lpBuffer->dwTotalPhys > MAXLONG) lpBuffer->dwTotalPhys = MAXLONG; | |||||
if (lpBuffer->dwAvailPhys > MAXLONG) lpBuffer->dwAvailPhys = MAXLONG; |
@ -0,0 +1,31 @@ | |||||
--- a/dlls/kernel32/heap.c | |||||
+++ b/dlls/kernel32/heap.c | |||||
@@ -75,6 +75,7 @@ WINE_DECLARE_DEBUG_CHANNEL(globalmem); | |||||
static HANDLE systemHeap; /* globally shared heap */ | |||||
+extern BOOL CDECL __wine_needs_override_large_address_aware(void); | |||||
/*********************************************************************** | |||||
* HEAP_CreateSystemHeap | |||||
@@ -1375,6 +1376,10 @@ VOID WINAPI GlobalMemoryStatus( LPMEMORY | |||||
MEMORYSTATUSEX memstatus; | |||||
OSVERSIONINFOW osver; | |||||
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( GetModuleHandleW(0) ); | |||||
+ static int force_large_address_aware = -1; | |||||
+ | |||||
+ if (force_large_address_aware == -1) | |||||
+ force_large_address_aware = __wine_needs_override_large_address_aware(); | |||||
/* Because GlobalMemoryStatus is identical to GlobalMemoryStatusEX save | |||||
for one extra field in the struct, and the lack of a bug, we simply | |||||
@@ -1415,7 +1420,8 @@ VOID WINAPI GlobalMemoryStatus( LPMEMORY | |||||
/* values are limited to 2Gb unless the app has the IMAGE_FILE_LARGE_ADDRESS_AWARE flag */ | |||||
/* page file sizes are not limited (Adobe Illustrator 8 depends on this) */ | |||||
- if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) | |||||
+ if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) && | |||||
+ !force_large_address_aware) | |||||
{ | |||||
if (lpBuffer->dwTotalPhys > MAXLONG) lpBuffer->dwTotalPhys = MAXLONG; | |||||
if (lpBuffer->dwAvailPhys > MAXLONG) lpBuffer->dwAvailPhys = MAXLONG; |
@ -0,0 +1,188 @@ | |||||
Original patch code by Valve Corporation | |||||
Original commits: | |||||
https://github.com/ValveSoftware/wine/commit/62c9478e4768e94e841da2ef75eb778ed346e3ab | |||||
LICENSE: See https://github.com/ValveSoftware/wine | |||||
Target Wine version of this patch file: | |||||
Wine 4.9 (Vanilla/Non-staging) | |||||
--- a/dlls/ntdll/virtual.c | |||||
+++ b/dlls/ntdll/virtual.c | |||||
@@ -2442,11 +2442,11 @@ void virtual_release_address_space(void) | |||||
* | |||||
* Enable use of a large address space when allowed by the application. | |||||
*/ | |||||
-void virtual_set_large_address_space(void) | |||||
+void virtual_set_large_address_space(BOOL force_large_address) | |||||
{ | |||||
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); | |||||
- if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) return; | |||||
+ if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) && !force_large_address) return; | |||||
/* no large address space on win9x */ | |||||
if (NtCurrentTeb()->Peb->OSPlatformId != VER_PLATFORM_WIN32_NT) return; | |||||
--- a/dlls/ntdll/loader.c | |||||
+++ b/dlls/ntdll/loader.c | |||||
@@ -2038,6 +2038,126 @@ static BOOL is_valid_binary( HMODULE mod | |||||
#endif | |||||
} | |||||
+/*************************************************************************** | |||||
+ * get_basename | |||||
+ * | |||||
+ * Return the base name of a file name (i.e. remove the path components). | |||||
+ */ | |||||
+static const WCHAR *get_basename( const WCHAR *name ) | |||||
+{ | |||||
+ const WCHAR *ptr; | |||||
+ | |||||
+ if (name[0] && name[1] == ':') name += 2; /* strip drive specification */ | |||||
+ if ((ptr = strrchrW( name, '\\' ))) name = ptr + 1; | |||||
+ if ((ptr = strrchrW( name, '/' ))) name = ptr + 1; | |||||
+ return name; | |||||
+} | |||||
+ | |||||
+ | |||||
+/*************************************************************************** | |||||
+ * large_address_aware_env | |||||
+ * | |||||
+ * Checks for override for LARGE_ADDRESS_AWARE bit in environment. Takes | |||||
+ * precedence over any AppDefaults registry entry. | |||||
+ * | |||||
+ * Returns: | |||||
+ * -1 if not defined in environment (prefer registry entries) | |||||
+ * 0 if disabled | |||||
+ * 1 if enabled | |||||
+ */ | |||||
+static int large_address_aware_env( void ) | |||||
+{ | |||||
+ static int large_address_aware_cached = -2; | |||||
+ | |||||
+ if (large_address_aware_cached == -2) { | |||||
+ const char *envvar = getenv("WINE_LARGE_ADDRESS_AWARE"); | |||||
+ if (envvar) | |||||
+ large_address_aware_cached = atoi(envvar); | |||||
+ else | |||||
+ large_address_aware_cached = -1; | |||||
+ } | |||||
+ | |||||
+ return large_address_aware_cached; | |||||
+} | |||||
+ | |||||
+/*************************************************************************** | |||||
+ * needs_override_large_address_aware | |||||
+ * | |||||
+ * Checks for AppDefaults override for LARGE_ADDRESS_AWARE bit. | |||||
+ * | |||||
+ * Returns: | |||||
+ * TRUE if override was found in the registry, or environment variable | |||||
+ * explicitly enabled this override | |||||
+ * FALSE if no override was found in the registry, or environment variable | |||||
+ * explicitly disabled this override | |||||
+ */ | |||||
+static BOOL needs_override_large_address_aware(const WCHAR *exename) | |||||
+{ | |||||
+ BOOL result; | |||||
+ OBJECT_ATTRIBUTES attr; | |||||
+ UNICODE_STRING nameW; | |||||
+ UNICODE_STRING valueNameW; | |||||
+ HANDLE root; | |||||
+ WCHAR *str; | |||||
+ static const WCHAR AppDefaultsW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\', | |||||
+ 'A','p','p','D','e','f','a','u','l','t','s','\\',0}; | |||||
+ static const WCHAR LargeAddressAwareW[] = {'L','a','r','g','e','A','d','d','r','e','s','s','A','w','a','r','e',0}; | |||||
+ char tmp[64]; | |||||
+ KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)tmp; | |||||
+ DWORD count; | |||||
+ int env_override; | |||||
+ HANDLE app_key = (HANDLE)-1; | |||||
+ | |||||
+ /* Environment variable takes precedence. */ | |||||
+ env_override = large_address_aware_env(); | |||||
+ if (large_address_aware_env() >= 0) | |||||
+ return env_override; | |||||
+ | |||||
+ exename = get_basename(exename); | |||||
+ | |||||
+ if (app_key != (HANDLE)-1) return FALSE; | |||||
+ | |||||
+ str = RtlAllocateHeap( GetProcessHeap(), 0, | |||||
+ sizeof(AppDefaultsW) + strlenW(exename) * sizeof(WCHAR) ); | |||||
+ if (!str) return FALSE; | |||||
+ strcpyW( str, AppDefaultsW ); | |||||
+ strcatW( str, exename ); | |||||
+ | |||||
+ RtlOpenCurrentUser( KEY_ALL_ACCESS, &root ); | |||||
+ attr.Length = sizeof(attr); | |||||
+ attr.RootDirectory = root; | |||||
+ attr.ObjectName = &nameW; | |||||
+ attr.Attributes = 0; | |||||
+ attr.SecurityDescriptor = NULL; | |||||
+ attr.SecurityQualityOfService = NULL; | |||||
+ RtlInitUnicodeString( &nameW, str ); | |||||
+ RtlInitUnicodeString( &valueNameW, LargeAddressAwareW ); | |||||
+ | |||||
+ result = FALSE; | |||||
+ | |||||
+ /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe */ | |||||
+ if (!NtOpenKey( &app_key, KEY_ALL_ACCESS, &attr )) | |||||
+ { | |||||
+ if (!NtQueryValueKey( app_key, &valueNameW, KeyValuePartialInformation, tmp, sizeof(tmp)-1, &count)) | |||||
+ { | |||||
+ if (info->DataLength >= sizeof(DWORD)) | |||||
+ { | |||||
+ if ((*(DWORD *)info->Data) != 0) | |||||
+ result = TRUE; | |||||
+ } | |||||
+ } | |||||
+ NtClose( app_key ); | |||||
+ } | |||||
+ NtClose( root ); | |||||
+ RtlFreeHeap( GetProcessHeap(), 0, str ); | |||||
+ return result; | |||||
+} | |||||
+ | |||||
+BOOL CDECL __wine_needs_override_large_address_aware(void) | |||||
+{ | |||||
+ PEB *peb = NtCurrentTeb()->Peb; | |||||
+ return needs_override_large_address_aware(peb->ProcessParameters->ImagePathName.Buffer); | |||||
+} | |||||
/*********************************************************************** | |||||
* open_dll_file | |||||
@@ -3800,7 +3920,7 @@ void __wine_process_init(void) | |||||
NtCurrentTeb()->Peb->LoaderLock = &loader_section; | |||||
update_user_process_params( &wm->ldr.FullDllName ); | |||||
version_init( wm->ldr.FullDllName.Buffer ); | |||||
- virtual_set_large_address_space(); | |||||
+ virtual_set_large_address_space(needs_override_large_address_aware(NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer)); | |||||
LdrQueryImageFileExecutionOptions( &wm->ldr.FullDllName, globalflagW, REG_DWORD, | |||||
&NtCurrentTeb()->Peb->NtGlobalFlag, sizeof(DWORD), NULL ); | |||||
--- a/dlls/ntdll/ntdll.spec | |||||
+++ b/dlls/ntdll/ntdll.spec | |||||
@@ -1514,6 +1514,7 @@ | |||||
# Virtual memory | |||||
@ cdecl __wine_locked_recvmsg(long ptr long) | |||||
+@ cdecl __wine_needs_override_large_address_aware() | |||||
# Version | |||||
@ cdecl wine_get_version() NTDLL_wine_get_version | |||||
--- b/dlls/ntdll/ntdll_misc.h | |||||
+++ b/dlls/ntdll/ntdll_misc.h | |||||
@@ -188,7 +188,7 @@ | |||||
extern NTSTATUS virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_T size ) DECLSPEC_HIDDEN; | |||||
extern void VIRTUAL_SetForceExec( BOOL enable ) DECLSPEC_HIDDEN; | |||||
extern void virtual_release_address_space(void) DECLSPEC_HIDDEN; | |||||
-extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN; | |||||
+extern void virtual_set_large_address_space( BOOL force ) DECLSPEC_HIDDEN; | |||||
extern void virtual_fill_image_information( const pe_image_info_t *pe_info, | |||||
SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; | |||||
extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; |
@ -0,0 +1,188 @@ | |||||
Original patch code by Valve Corporation | |||||
Original commits: | |||||
https://github.com/ValveSoftware/wine/commit/62c9478e4768e94e841da2ef75eb778ed346e3ab | |||||
LICENSE: See https://github.com/ValveSoftware/wine | |||||
Target Wine version of this patch file: | |||||
Wine 4.9 (Vanilla/Non-staging) | |||||
--- a/dlls/ntdll/virtual.c | |||||
+++ b/dlls/ntdll/virtual.c | |||||
@@ -2531,11 +2531,11 @@ void virtual_release_address_space(void) | |||||
* | |||||
* Enable use of a large address space when allowed by the application. | |||||
*/ | |||||
-void virtual_set_large_address_space(void) | |||||
+void virtual_set_large_address_space(BOOL force_large_address) | |||||
{ | |||||
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); | |||||
- if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) return; | |||||
+ if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) && !force_large_address) return; | |||||
/* no large address space on win9x */ | |||||
if (NtCurrentTeb()->Peb->OSPlatformId != VER_PLATFORM_WIN32_NT) return; | |||||
--- a/dlls/ntdll/loader.c | |||||
+++ b/dlls/ntdll/loader.c | |||||
@@ -2194,6 +2194,126 @@ static BOOL is_valid_binary( HMODULE mod | |||||
#endif | |||||
} | |||||
+/*************************************************************************** | |||||
+ * get_basename | |||||
+ * | |||||
+ * Return the base name of a file name (i.e. remove the path components). | |||||
+ */ | |||||
+static const WCHAR *get_basename( const WCHAR *name ) | |||||
+{ | |||||
+ const WCHAR *ptr; | |||||
+ | |||||
+ if (name[0] && name[1] == ':') name += 2; /* strip drive specification */ | |||||
+ if ((ptr = strrchrW( name, '\\' ))) name = ptr + 1; | |||||
+ if ((ptr = strrchrW( name, '/' ))) name = ptr + 1; | |||||
+ return name; | |||||
+} | |||||
+ | |||||
+ | |||||
+/*************************************************************************** | |||||
+ * large_address_aware_env | |||||
+ * | |||||
+ * Checks for override for LARGE_ADDRESS_AWARE bit in environment. Takes | |||||
+ * precedence over any AppDefaults registry entry. | |||||
+ * | |||||
+ * Returns: | |||||
+ * -1 if not defined in environment (prefer registry entries) | |||||
+ * 0 if disabled | |||||
+ * 1 if enabled | |||||
+ */ | |||||
+static int large_address_aware_env( void ) | |||||
+{ | |||||
+ static int large_address_aware_cached = -2; | |||||
+ | |||||
+ if (large_address_aware_cached == -2) { | |||||
+ const char *envvar = getenv("WINE_LARGE_ADDRESS_AWARE"); | |||||
+ if (envvar) | |||||
+ large_address_aware_cached = atoi(envvar); | |||||
+ else | |||||
+ large_address_aware_cached = -1; | |||||
+ } | |||||
+ | |||||
+ return large_address_aware_cached; | |||||
+} | |||||
+ | |||||
+/*************************************************************************** | |||||
+ * needs_override_large_address_aware | |||||
+ * | |||||
+ * Checks for AppDefaults override for LARGE_ADDRESS_AWARE bit. | |||||
+ * | |||||
+ * Returns: | |||||
+ * TRUE if override was found in the registry, or environment variable | |||||
+ * explicitly enabled this override | |||||
+ * FALSE if no override was found in the registry, or environment variable | |||||
+ * explicitly disabled this override | |||||
+ */ | |||||
+static BOOL needs_override_large_address_aware(const WCHAR *exename) | |||||
+{ | |||||
+ BOOL result; | |||||
+ OBJECT_ATTRIBUTES attr; | |||||
+ UNICODE_STRING nameW; | |||||
+ UNICODE_STRING valueNameW; | |||||
+ HANDLE root; | |||||
+ WCHAR *str; | |||||
+ static const WCHAR AppDefaultsW[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\', | |||||
+ 'A','p','p','D','e','f','a','u','l','t','s','\\',0}; | |||||
+ static const WCHAR LargeAddressAwareW[] = {'L','a','r','g','e','A','d','d','r','e','s','s','A','w','a','r','e',0}; | |||||
+ char tmp[64]; | |||||
+ KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)tmp; | |||||
+ DWORD count; | |||||
+ int env_override; | |||||
+ HANDLE app_key = (HANDLE)-1; | |||||
+ | |||||
+ /* Environment variable takes precedence. */ | |||||
+ env_override = large_address_aware_env(); | |||||
+ if (large_address_aware_env() >= 0) | |||||
+ return env_override; | |||||
+ | |||||
+ exename = get_basename(exename); | |||||
+ | |||||
+ if (app_key != (HANDLE)-1) return FALSE; | |||||
+ | |||||
+ str = RtlAllocateHeap( GetProcessHeap(), 0, | |||||
+ sizeof(AppDefaultsW) + strlenW(exename) * sizeof(WCHAR) ); | |||||
+ if (!str) return FALSE; | |||||
+ strcpyW( str, AppDefaultsW ); | |||||
+ strcatW( str, exename ); | |||||
+ | |||||
+ RtlOpenCurrentUser( KEY_ALL_ACCESS, &root ); | |||||
+ attr.Length = sizeof(attr); | |||||
+ attr.RootDirectory = root; | |||||
+ attr.ObjectName = &nameW; | |||||
+ attr.Attributes = 0; | |||||
+ attr.SecurityDescriptor = NULL; | |||||
+ attr.SecurityQualityOfService = NULL; | |||||
+ RtlInitUnicodeString( &nameW, str ); | |||||
+ RtlInitUnicodeString( &valueNameW, LargeAddressAwareW ); | |||||
+ | |||||
+ result = FALSE; | |||||
+ | |||||
+ /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe */ | |||||
+ if (!NtOpenKey( &app_key, KEY_ALL_ACCESS, &attr )) | |||||
+ { | |||||
+ if (!NtQueryValueKey( app_key, &valueNameW, KeyValuePartialInformation, tmp, sizeof(tmp)-1, &count)) | |||||
+ { | |||||
+ if (info->DataLength >= sizeof(DWORD)) | |||||
+ { | |||||
+ if ((*(DWORD *)info->Data) != 0) | |||||
+ result = TRUE; | |||||
+ } | |||||
+ } | |||||
+ NtClose( app_key ); | |||||
+ } | |||||
+ NtClose( root ); | |||||
+ RtlFreeHeap( GetProcessHeap(), 0, str ); | |||||
+ return result; | |||||
+} | |||||
+ | |||||
+BOOL CDECL __wine_needs_override_large_address_aware(void) | |||||
+{ | |||||
+ PEB *peb = NtCurrentTeb()->Peb; | |||||
+ return needs_override_large_address_aware(peb->ProcessParameters->ImagePathName.Buffer); | |||||
+} | |||||
/*********************************************************************** | |||||
* open_dll_file | |||||
@@ -4030,7 +4150,7 @@ void __wine_process_init(void) | |||||
version_init( wm->ldr.FullDllName.Buffer ); | |||||
user_shared_data_init(); | |||||
hidden_exports_init( wm->ldr.FullDllName.Buffer ); | |||||
- virtual_set_large_address_space(); | |||||
+ virtual_set_large_address_space(needs_override_large_address_aware(NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer)); | |||||
LdrQueryImageFileExecutionOptions( &wm->ldr.FullDllName, globalflagW, REG_DWORD, | |||||
&NtCurrentTeb()->Peb->NtGlobalFlag, sizeof(DWORD), NULL ); | |||||
--- a/dlls/ntdll/ntdll.spec | |||||
+++ b/dlls/ntdll/ntdll.spec | |||||
@@ -1518,6 +1518,7 @@ | |||||
# Virtual memory | |||||
@ cdecl __wine_locked_recvmsg(long ptr long) | |||||
+@ cdecl __wine_needs_override_large_address_aware() | |||||
# Token | |||||
@ cdecl __wine_create_default_token(long) | |||||
--- b/dlls/ntdll/ntdll_misc.h | |||||
+++ b/dlls/ntdll/ntdll_misc.h | |||||
@@ -197,7 +197,7 @@ extern SIZE_T virtual_uninterrupted_read | |||||
extern NTSTATUS virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_T size ) DECLSPEC_HIDDEN; | |||||
extern void VIRTUAL_SetForceExec( BOOL enable ) DECLSPEC_HIDDEN; | |||||
extern void virtual_release_address_space(void) DECLSPEC_HIDDEN; | |||||
-extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN; | |||||
+extern void virtual_set_large_address_space( BOOL force ) DECLSPEC_HIDDEN; | |||||
extern void virtual_fill_image_information( const pe_image_info_t *pe_info, | |||||
SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; | |||||
extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN; |