[Bug 44931] Macromedia Director Player 5.0/6.0 based games fail to run: " This program requires at least 3MB of free virtual memory to run" (Nine: The last Resort)

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Apr 7 11:40:57 CDT 2018


https://bugs.winehq.org/show_bug.cgi?id=44931

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|-unknown                    |kernel32

--- Comment #2 from Anastasius Focht <focht at 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/fe09e2dba66095f1494946226c911a2acc65c9c6:/dlls/kernel32/heap.c#l1373

--- 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/2130f613102c46aaa643336ff4f5595a104c7151
("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

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list