[Bug 46949] New: DDraw games using older windowed mode wrappers such as DirectX Windower Embedded v2.3 /D3D Windower v1.x crash (ddraw_palette_vtbl and ddraw_surface{1,2,3,4, 7}_vtbl need to be writable)

wine-bugs at winehq.org wine-bugs at winehq.org
Tue Apr 2 17:48:35 CDT 2019


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

            Bug ID: 46949
           Summary: DDraw games using older windowed mode wrappers such as
                    DirectX Windower Embedded v2.3/D3D Windower v1.x crash
                    (ddraw_palette_vtbl and ddraw_surface{1,2,3,4,7}_vtbl
                    need to be writable)
           Product: Wine
           Version: 4.5
          Hardware: x86-64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: directx-d3d
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net
      Distribution: ---

Hello folks,

encountered while investigating bug 44803 ("Age of Empires II Forgotten Empires
crashes "Unhandled privileged instruction").

There are various community installers that claim to add windowed mode support
for old DDraw-based games. The presence of older windowed mode wrappers causes
the games to crash. These old wrappers (over)write function pointers directly
to vtables without changing the page protection.

--- snip ---
-=[ ProtectionID v0.6.9.0 DECEMBER]=-
(c) 2003-2017 CDKiLLER & TippeX
Build 24/12/17-21:05:42
Ready...
Scanning -> C:\Program Files (x86)\Microsoft Games\Age of Empires
II\age2_x1\wndmode.dll
File Type : 32-Bit Dll (Subsystem : Win GUI / 2), Size : 778752 (0BE200h)
Byte(s) | Machine: 0x14C (I386)
Compilation TimeStamp : 0x413D41E7 -> Tue 07th Sep 2004 05:06:47 (GMT)
[TimeStamp] 0x413D41E7 -> Tue 07th Sep 2004 05:06:47 (GMT) | PE Header | - |
Offset: 0x00000208 | VA: 0x00400208 | -
[File Heuristics] -> Flag #1 : 00000000000000001000000000100000 (0x00008020)
[Entrypoint Section Entropy] : 6.54 (section #0) ".text   " | Size : 0x98400
(623616) byte(s)
[DllCharacteristics] -> Flag : (0x0000) -> NONE
[SectionCount] 7 (0x7) | ImageSize 0xC8000 (819200) byte(s)
[VersionInfo] Product Name : DirectX Windower Embedded v2.3 (based on D3D
Windower v1.88)
[VersionInfo] File Description : DirectX Windower Embedded
[VersionInfo] File Version : 2.3.0.12
[VersionInfo] Original FileName : wndmode.dll
[VersionInfo] Legal Copyrights : (C) 2008 VEG <veg at tut.by>. (C) 2004 menopem
<menopem at yahoo.co.jp>
[ModuleReport] [IAT] Modules -> KERNEL32.DLL | ADVAPI32.DLL | COMCTL32.DLL |
GDI32.DLL | OLE32.DLL | OLEAUT32.DLL | USER32.DLL | VERSION.DLL | WINMM.DLL
[CdKeySerial] found "Invalid code" @ VA: 0x00096E24 / Offset: 0x00096424
[CompilerDetect] -> Borland C/C++
[!] File appears to have no protection or is using an unknown protection
- Scan Took : 0.410 Second(s) [00000019Ah (410) tick(s)] [246 of 580 scan(s)
done]
--- snip ---

--- snip ---
$ winedbg --gdb ./age2_x2.exe 

Wine-gdb> bt

#0  ddraw1_CreatePalette (iface=0x192a7c, flags=68, entries=0x32c048,
palette=0x9261fc, outer_unknown=0x0) at
/home/focht/projects/wine/mainline-src/dlls/ddraw/ddraw.c:3521
#1  0x00b21274 in ?? ()
#2  0x005a1019 in ?? ()
#3  0x00000000 in ?? ()

...

Wine-gdb> x/10i $eip

=> 0xb21291:    movl   $0xb212a0,0x18(%edx)
   0xb21298:    pop    %ebx
   0xb21299:    pop    %ebp
   0xb2129a:    ret    $0x14

Wine-gdb> x/10x $edx

0x1c0588:    0x7e0e21c8    0x00000001    0x001c0748    0x00192a70
0x1c0598:    0x00000000    0x00000044    0x00000000    0x001c0580
0x1c05a8:    0x00000080    0x00455355

Wine-gdb> x/10x 0x7e0e21c8

0x7e0e21c8 <ddraw_palette_vtbl>:    0x7e09f667    0x7e09f74d    0x7e09f7fc   
0x7e09f9a7
0x7e0e21d8 <ddraw_palette_vtbl+16>:    0x7e09fb32    0x7e09f92c    0x7e09fa42  
 0x00000000
0x7e0e21e8:    0x00000000    0x00000000
--- snip ---

Obviously can't work because the vtable is const data:

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ddraw/palette.c#l221

--- snip ---
 221 static const struct IDirectDrawPaletteVtbl ddraw_palette_vtbl =
 222 {
 223     /*** IUnknown ***/
 224     ddraw_palette_QueryInterface,
 225     ddraw_palette_AddRef,
 226     ddraw_palette_Release,
 227     /*** IDirectDrawPalette ***/
 228     ddraw_palette_GetCaps,
 229     ddraw_palette_GetEntries,
 230     ddraw_palette_Initialize,
 231     ddraw_palette_SetEntries
 232 };
--- snip ---

--- snip ---
Thread 1 received signal SIGSEGV, Segmentation fault.
0x00b2b130 in ?? ()

Wine-gdb> bt

#0  0x00b2b130 in ?? ()
#1  0x00b2163c in ?? ()
#2  0x005a14c4 in ?? ()
#3  0x001c0fc8 in ?? ()
#4  0x00192a7c in ?? ()

Wine-gdb> x/10i 0x00b2b130

=> 0xb2b130:    rep movsl %ds:(%esi),%es:(%edi)
   0xb2b132:    pop    %edi
   0xb2b133:    pop    %esi
   0xb2b134:    mov    -0x44(%ebp),%ecx
   0xb2b137:    push   %ecx
   0xb2b138:    mov    -0x44(%ebp),%edx
   0xb2b13b:    test   %edx,%edx
   0xb2b13d:    jne    0xb2b143
   0xb2b13f:    xor    %ecx,%ecx

Wine-gdb> info reg

eax            0x7e070500    2114389248
ecx            0x24    36
edx            0x7e070500    2114389248
ebx            0x1c03c8    1835976
esp            0x32ba7c    0x32ba7c
ebp            0x32bb14    0x32bb14
esi            0xbbeae4    12315364
edi            0x7e070500    2114389248
eip            0xb2b130    0xb2b130
eflags         0x210246    [ PF ZF IF RF ID ]
cs             0x23    35
ss             0x2b    43
ds             0x2b    43
es             0x2b    43
fs             0x63    99
gs             0x6b    107

Wine-gdb> x/10x 0x7e070500

0x7e070500 <ddraw_surface1_vtbl>:    0x7e02f169    0x7e02f7fb    0x7e03030f   
0x7e0341b1
0x7e070510 <ddraw_surface1_vtbl+16>:    0x7e034a8f    0x7e033a73    0x7e03648a 
  0x7e03aa33
0x7e070520 <ddraw_surface1_vtbl+32>:    0x7e034784    0x7e036a03
--- snip ---

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ddraw/surface.c#l5600

--- snip ---
5600 static const struct IDirectDrawSurfaceVtbl ddraw_surface1_vtbl =
5601 {
5602     /* IUnknown */
5603     ddraw_surface1_QueryInterface,
5604     ddraw_surface1_AddRef,
5605     ddraw_surface1_Release,
...
--- snip ---

--- snip ---
Wine-gdb> bt

#0  0x00b2b1d6 in ?? ()
#1  0x00b2163c in ?? ()
#2  0x005a14c4 in ?? ()
#3  0x001c0fc8 in ?? ()
#4  0x00192a7c in ?? ()

Wine-gdb> x/10i 0x00b2b1d6

=> 0xb2b1d6:    rep movsl %ds:(%esi),%es:(%edi)
   0xb2b1d8:    pop    %edi
   0xb2b1d9:    pop    %esi
   0xb2b1da:    mov    -0x48(%ebp),%ecx
   0xb2b1dd:    push   %ecx
   0xb2b1de:    mov    -0x48(%ebp),%edx
   0xb2b1e1:    test   %edx,%edx
   0xb2b1e3:    jne    0xb2b1e9
   0xb2b1e5:    xor    %ecx,%ecx
   0xb2b1e7:    jmp    0xb2b238

ine-gdb> info reg
eax            0x7e0704e0    2114389216
ecx            0x27    39
edx            0x7e0704e0    2114389216
ebx            0x1c03c8    1835976
esp            0x32ba7c    0x32ba7c
ebp            0x32bb14    0x32bb14
esi            0xbbeb74    12315508
edi            0x7e0704e0    2114389216
eip            0xb2b1d6    0xb2b1d6
eflags         0x210246    [ PF ZF IF RF ID ]
cs             0x23    35
ss             0x2b    43
ds             0x2b    43
es             0x2b    43
fs             0x63    99
gs             0x6b    107

Wine-gdb> x/10x 0x7e0704e0

0x7e0704e0 <ddraw_surface2_vtbl>:    0x7e02f0c4    0x7e02f737    0x7e03024b   
0x7e0340b3
0x7e0704f0 <ddraw_surface2_vtbl+16>:    0x7e0349f0    0x7e033977    0x7e0363de 
  0x7e03a947
0x7e070500 <ddraw_surface2_vtbl+32>:    0x7e0346db    0x7e036959
--- snip ---

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ddraw/surface.c#l5554

--- snip ---
5554 static const struct IDirectDrawSurface2Vtbl ddraw_surface2_vtbl =
5555 {
5556     /* IUnknown */
5557     ddraw_surface2_QueryInterface,
5558     ddraw_surface2_AddRef,
5559     ddraw_surface2_Release,
5560     /* IDirectDrawSurface */
...
--- snip ---

--- snip ---
Wine-gdb> bt

#0  0x00b2b27c in ?? ()
#1  0x00b2163c in ?? ()
#2  0x005a14c4 in ?? ()
#3  0x001c0fc8 in ?? ()
#4  0x00192a7c in ?? ()

Wine-gdb> x/10i 0x00b2b27c

=> 0xb2b27c:    rep movsl %ds:(%esi),%es:(%edi)
   0xb2b27e:    pop    %edi
   0xb2b27f:    pop    %esi
   0xb2b280:    mov    -0x4c(%ebp),%ecx
   0xb2b283:    push   %ecx
   0xb2b284:    mov    -0x4c(%ebp),%edx
   0xb2b287:    test   %edx,%edx
   0xb2b289:    jne    0xb2b28f
   0xb2b28b:    xor    %ecx,%ecx
   0xb2b28d:    jmp    0xb2b2de

Wine-gdb> info reg

eax            0x7e0704e0    2114389216
ecx            0x28    40
edx            0x7e0704e0    2114389216
ebx            0x1c03c8    1835976
esp            0x32ba7c    0x32ba7c
ebp            0x32bb14    0x32bb14
esi            0xbbec10    12315664
edi            0x7e0704e0    2114389216
eip            0xb2b27c    0xb2b27c
eflags         0x210246    [ PF ZF IF RF ID ]
cs             0x23    35
ss             0x2b    43
ds             0x2b    43
es             0x2b    43
fs             0x63    99
gs             0x6b    107

Wine-gdb> x/10x 0x7e0704e0

0x7e0704e0 <ddraw_surface3_vtbl>:    0x7e02f01f    0x7e02f673    0x7e030187   
0x7e033fb5
0x7e0704f0 <ddraw_surface3_vtbl+16>:    0x7e034951    0x7e03387b    0x7e036332 
  0x7e03a85b
0x7e070500 <ddraw_surface3_vtbl+32>:    0x7e034632    0x7e0368af
--- snip ---

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ddraw/surface.c#l5506

--- snip ---
5506 static const struct IDirectDrawSurface3Vtbl ddraw_surface3_vtbl =
5507 {
5508     /* IUnknown */
5509     ddraw_surface3_QueryInterface,
5510     ddraw_surface3_AddRef,
5511     ddraw_surface3_Release,
5512     /* IDirectDrawSurface */
...
--- snip ---

--- snip ---
Wine-gdb> bt

#0  0x00b2b322 in ?? ()
#1  0x00b2163c in ?? ()
#2  0x005a14c4 in ?? ()
#3  0x001c0fc8 in ?? ()
#4  0x00192a7c in ?? ()

Wine-gdb> x/10i 0x00b2b322

=> 0xb2b322:    rep movsl %ds:(%esi),%es:(%edi)
   0xb2b324:    pop    %edi
   0xb2b325:    pop    %esi
   0xb2b326:    mov    -0x50(%ebp),%ecx
   0xb2b329:    push   %ecx
   0xb2b32a:    mov    -0x50(%ebp),%edx
   0xb2b32d:    test   %edx,%edx
   0xb2b32f:    jne    0xb2b335
   0xb2b331:    xor    %ecx,%ecx
   0xb2b333:    jmp    0xb2b384

Wine-gdb> info reg

eax            0x7e0704e0    2114389216
ecx            0x2d    45
edx            0x7e0704e0    2114389216
ebx            0x1c03c8    1835976
esp            0x32ba7c    0x32ba7c
ebp            0x32bb14    0x32bb14
esi            0xbbecb0    12315824
edi            0x7e0704e0    2114389216
eip            0xb2b322    0xb2b322
eflags         0x210246    [ PF ZF IF RF ID ]
cs             0x23    35
ss             0x2b    43
ds             0x2b    43
es             0x2b    43
fs             0x63    99
gs             0x6b    107

Wine-gdb> x/10x 0x7e0704e0

0x7e0704e0 <ddraw_surface4_vtbl>:    0x7e02ef7a    0x7e02f5af    0x7e0300c3   
0x7e033dd2
0x7e0704f0 <ddraw_surface4_vtbl+16>:    0x7e0348b2    0x7e03377f    0x7e036286 
  0x7e03a76f
0x7e070500 <ddraw_surface4_vtbl+32>:    0x7e034589    0x7e036805
--- snip ---

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ddraw/surface.c#l5452

--- snip ---
5452 static const struct IDirectDrawSurface4Vtbl ddraw_surface4_vtbl =
5453 {
5454     /* IUnknown */
5455     ddraw_surface4_QueryInterface,
5456     ddraw_surface4_AddRef,
5457     ddraw_surface4_Release,
5458     /* IDirectDrawSurface */
...
--- snip ---

--- snip ---
Wine-gdb> bt

#0  0x00b2b3c8 in ?? ()
#1  0x00b2163c in ?? ()
#2  0x005a14c4 in ?? ()
#3  0x001c0fc8 in ?? ()
#4  0x00192a7c in ?? ()

Wine-gdb> x/10i 0x00b2b3c8

=> 0xb2b3c8:    rep movsl %ds:(%esi),%es:(%edi)
   0xb2b3ca:    pop    %edi
   0xb2b3cb:    pop    %esi
   0xb2b3cc:    mov    -0x54(%ebp),%ecx
   0xb2b3cf:    push   %ecx
   0xb2b3d0:    mov    -0x54(%ebp),%edx
   0xb2b3d3:    test   %edx,%edx
   0xb2b3d5:    jne    0xb2b3db
   0xb2b3d7:    xor    %ecx,%ecx
   0xb2b3d9:    jmp    0xb2b42a

Wine-gdb> info reg

eax            0x7e0704c0    2114389184
ecx            0x31    49
edx            0x7e0704c0    2114389184
ebx            0x1c03c8    1835976
esp            0x32ba7c    0x32ba7c
ebp            0x32bb14    0x32bb14
esi            0xbbed64    12316004
edi            0x7e0704c0    2114389184
eip            0xb2b3c8    0xb2b3c8
eflags         0x210246    [ PF ZF IF RF ID ]
cs             0x23    35
ss             0x2b    43
ds             0x2b    43
es             0x2b    43
fs             0x63    99
gs             0x6b    107

Wine-gdb> x/10x 0x7e0704c0

0x7e0704c0 <ddraw_surface7_vtbl>:    0x7e02e8a8    0x7e02f4eb    0x7e02ffff   
0x7e033c96
0x7e0704d0 <ddraw_surface7_vtbl+16>:    0x7e03482d    0x7e032e03    0x7e0361f5 
  0x7e03a442
0x7e0704e0 <ddraw_surface7_vtbl+32>:    0x7e0344e0    0x7e036526
--- snip ---

https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/ddraw/surface.c#l5393

--- snip ---
5393 static const struct IDirectDrawSurface7Vtbl ddraw_surface7_vtbl =
5394 {
5395     /* IUnknown */
5396     ddraw_surface7_QueryInterface,
5397     ddraw_surface7_AddRef,
5398     ddraw_surface7_Release,
5399     /* IDirectDrawSurface */
--- snip ---

If you remove the 'const' the old games start successfully in windowed mode.

Tested with AoE2 + expansions. NOTE: I'm not talking about the newer AoE2HD
which supports windowed mode out of the box, it's the older versions that
didn't support windowed mode at all.

Newer windowed mode wrapper projects such as 'DxWnd'
(https://github.com/DxWnd/DxWnd.reloaded) use more safe mechanisms
(VirtualProtect) to make sure the vtables are actually writable.

But again, it seems native DDraw has writable vtables.

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