https://bugs.winehq.org/show_bug.cgi?id=44931
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|-unknown |kernel32
--- Comment #2 from Anastasius Focht focht@gmx.net --- Hello again,
I found a "backup" of 'Macromedia Director 5' on Internet to play with. Even the installer has the same problem.
--- quote --- Macromedia Director 5 Released in 1996 by Macromedia For Windows 3.1 with Win32s and Windows 95
Director is a multimedia authoring tool, and is used to create Macromedia Shockwave content.
This archive contains an ISO image with both a 16-bit Windows 3.1 version and a 32-bit Windows 95 version. --- quote ---
On my system:
--- snip --- $ WINEDEBUG=+seh,+relay,+globalmem wine ./d5acce32.exe >>log.txt 2>&1 ... 0009:Call KERNEL32.GlobalMemoryStatus(0032f81c) ret=00469cfb 0009:trace:globalmem:GlobalMemoryStatusEx <-- LPMEMORYSTATUSEX: dwLength 64, dwMemoryLoad 13, ullTotalPhys 3e32a9000, ullAvailPhys 35c7a0000, ullTotalPageFile 5d92a8000, ullAvailPageFile 55279f000, ullTotalVirtual 7ffdffff, ullAvailVirtual 7ffcffff 0009:trace:globalmem:GlobalMemoryStatus Length 32, MemoryLoad 13, TotalPhys 7fffffff, AvailPhys 7fffffff, TotalPageFile 7fffffff, AvailPageFile 7fffffff, TotalVirtual 7ffdffff, AvailVirtual 7ffcffff 0009:Ret KERNEL32.GlobalMemoryStatus() retval=000000c7 ret=00469cfb 0009:Call user32.LoadStringA(00400000,00000880,0032f88c,00000080) ret=00469d2b 0009:Ret user32.LoadStringA() retval=00000013 ret=00469d2b 0009:Call user32.LoadStringA(00400000,0000000f,0032f90c,00000080) ret=00469d42 0009:Ret user32.LoadStringA() retval=00000042 ret=00469d42 0009:Call user32.MessageBoxA(00000000,0032f98c "This program requires at least 3MB of free virtual memory to run.",0032f88c "Director Player 5.0",00000000) ret=00469d7b ... --- snip ---
Disassembly of installer show the same brain damaged sequence as from the link I posted earlier:
--- snip --- 00469CE0 SUB ESP,29C 00469CE6 LEA EAX,[LOCAL.156] 00469CEA PUSH ESI 00469CEB MOV DWORD PTR SS:[LOCAL.156],20 00469CF3 PUSH EDI 00469CF4 PUSH EAX ; pMemorystatus => OFFSET LOCAL.156 00469CF5 CALL DWORD PTR DS:[<&KERNEL32.GlobalMemoryStatus>] 00469CFB MOV EAX,DWORD PTR SS:[LOCAL.151] ; AvailPageFile = 0x7FFFFFFF 00469CFF ADD EAX,DWORD PTR SS:[LOCAL.153] ; AvailPhys = 0x7FFFFFFF ; 2GB AvailPageFile + 2GB AvailPhys = overflow 00469D03 CMP EAX,387520 ; >= 3700000 Bytes? 00469D08 JGE SHORT 00469D88 00469D0A LEA EAX,[LOCAL.128] 00469D11 PUSH 80 00469D16 PUSH EAX 00469D17 MOV ECX,DWORD PTR DS:[514350] 00469D1D PUSH 880 ; StringID = 2176. => 'Director Player 5.01' 00469D22 MOV ESI,DWORD PTR DS:[<&USER32.LoadStringA>] 00469D28 PUSH ECX 00469D29 CALL ESI ; USER32.LoadStringA 00469D2B LEA ECX,[LOCAL.96] 00469D32 PUSH 80 00469D37 PUSH ECX 00469D38 MOV EAX,DWORD PTR DS:[514350] 00469D3D PUSH 0F ; StringID = 15. => 'This program requires at least %dMB of free virtual memory to run.' 00469D3F PUSH EAX 00469D40 CALL ESI ; USER32.LoadStringA 00469D42 LEA ECX,[LOCAL.96] 00469D49 PUSH 3 00469D4B LEA EDX,[LOCAL.64] 00469D52 PUSH ECX 00469D53 PUSH 100 00469D58 PUSH EDX 00469D59 CALL 004FFA7F 00469D5E LEA ECX,[LOCAL.128] 00469D65 LEA EDX,[LOCAL.64] 00469D6C ADD ESP,10 00469D6F PUSH 0 ; Type = MB_OK|MB_DEFBUTTON1|MB_APPLMODAL 00469D71 PUSH ECX ; Caption => OFFSET LOCAL.128 00469D72 PUSH EDX ; Text => OFFSET LOCAL.64 00469D73 PUSH 0 ; hOwner = NULL 00469D75 CALL DWORD PTR DS:[<&USER32.MessageBoxA>] 00469D7B XOR EAX,EAX 00469D7D POP EDI 00469D7E POP ESI 00469D7F ADD ESP,29C 00469D85 RETN 8 00469D88 CALL 004676C0 00469D8D TEST EAX,EAX 00469D8F JZ SHORT 00469D9E 00469D91 XOR EAX,EAX 00469D93 POP EDI 00469D94 POP ESI 00469D95 ADD ESP,29C 00469D9B RETN 8 --- snip ---
You basically need to ensure dwAvailPageFile+dwAvailPhys <= 0x7FFFFFFF (2GB)
Wine source:
https://source.winehq.org/git/wine.git/blob/fe09e2dba66095f1494946226c911a2a...
--- snip --- 1373 VOID WINAPI GlobalMemoryStatus( LPMEMORYSTATUS lpBuffer ) 1374 { 1375 MEMORYSTATUSEX memstatus; 1376 OSVERSIONINFOW osver; 1377 IMAGE_NT_HEADERS *nt = RtlImageNtHeader( GetModuleHandleW(0) ); 1378 1379 /* Because GlobalMemoryStatus is identical to GlobalMemoryStatusEX save 1380 for one extra field in the struct, and the lack of a bug, we simply 1381 call GlobalMemoryStatusEx and copy the values across. */ 1382 memstatus.dwLength = sizeof(memstatus); 1383 GlobalMemoryStatusEx(&memstatus); 1384 1385 lpBuffer->dwLength = sizeof(*lpBuffer); 1386 lpBuffer->dwMemoryLoad = memstatus.dwMemoryLoad; ... 1416 /* values are limited to 2Gb unless the app has the IMAGE_FILE_LARGE_ADDRESS_AWARE flag */ 1417 /* page file sizes are not limited (Adobe Illustrator 8 depends on this) */ 1418 if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) 1419 { 1420 if (lpBuffer->dwTotalPhys > MAXLONG) lpBuffer->dwTotalPhys = MAXLONG; 1421 if (lpBuffer->dwAvailPhys > MAXLONG) lpBuffer->dwAvailPhys = MAXLONG; 1422 if (lpBuffer->dwTotalVirtual > MAXLONG) lpBuffer->dwTotalVirtual = MAXLONG; 1423 if (lpBuffer->dwAvailVirtual > MAXLONG) lpBuffer->dwAvailVirtual = MAXLONG; 1424 } 1425 1426 /* work around for broken photoshop 4 installer */ 1427 if ( lpBuffer->dwAvailPhys + lpBuffer->dwAvailPageFile >= 2U*1024*1024*1024) 1428 lpBuffer->dwAvailPageFile = 2U*1024*1024*1024 - lpBuffer->dwAvailPhys - 1; 1429 1430 /* limit page file size for really old binaries */ 1431 if (nt->OptionalHeader.MajorSubsystemVersion < 4 || 1432 nt->OptionalHeader.MajorOperatingSystemVersion < 4) 1433 { 1434 if (lpBuffer->dwTotalPageFile > MAXLONG) lpBuffer->dwTotalPageFile = MAXLONG; 1435 if (lpBuffer->dwAvailPageFile > MAXLONG) lpBuffer->dwAvailPageFile = MAXLONG; 1436 } ... 1443 } --- snip ---
"work around for broken photoshop 4 installer" -> Line 1427 looks pretty much what we want. The change was introduced by Alexandre himself in year 2004:
https://source.winehq.org/git/wine.git/commitdiff/2130f613102c46aaa643336ff4... ("In GlobalMemoryStatus, also cap the sum of dwAvailPhys and")
The problem with that code is the test for < 2 GB range (MAXLONG). GCC emits this code:
--- snip --- ... addl %edx,%eax testl %eax,%eax jns no_need_to_cap_2gb ... --- snip ---
'test' will set the sign flag based on the most significant bit of %eax.
Consider two cases:
dwAvailPageFile(0x7fffffff) + dwAvailPhys(0x7fffffff) = 0xfffffffe, causes a signed overflow, but not an unsigned overflow (or carry) -> 'S' flag set, 'C' flag not set.
dwAvailPageFile(0xffffffff) + dwAvailPhys(0x7fffffff) = 0x7ffffffe, causes an unsigned overflow (with carry) -> 'C' flag set, 'S' flag not set.
The latter case is actually the default for non-IMAGE_FILE_LARGE_ADDRESS_AWARE apps. The unsigned overflow is not detected hence no 2GB cap handling. I've modified the expression to take potential unsigned integer overflow into account and the app works correctly. This will likely fix a lot of old Adobe installers/apps from Win9X era.
Regards