[Bug 12757] Europa Universalis Rome crashes on startup (D3DXLoadSurfaceFromFileInMemory must not unconditionally call CoUninitialize(), different COM threading model used)

wine-bugs at winehq.org wine-bugs at winehq.org
Sun Feb 23 13:26:13 CST 2014


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

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |NEW
                 CC|                            |focht at gmx.net
            Summary|Europa Universalis Rome:    |Europa Universalis Rome
                   |Crashes on start-up         |crashes on startup
                   |                            |(D3DXLoadSurfaceFromFileInM
                   |                            |emory must not
                   |                            |unconditionally call
                   |                            |CoUninitialize(), different
                   |                            |COM threading model used)

--- Comment #20 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

confirming - although this bug has been recycled at least once for different
issues.

The game uses a multi-threaded apartment on its main thread.
Multiple Wine components/API create apartment-threaded COM inproc servers on
the same thread (dsound, d3dx, ...).

The caller needs to be aware of this situation (RPC_E_CHANGED_MODE) in order to
avoid messing up the coinit refcount.
The visible part is the infamous 'Attempt to change threading model of this
apartment from multi-threaded to apartment threaded' message in terminal.

Relevant part of trace log:

The game creates multi-threaded apartment and quartz instance:

--- snip ---
0025:Call ole32.CoInitializeEx(00000000,0000000c) ret=00897417
...
0025:Ret  ole32.CoInitializeEx() retval=00000000 ret=00897417
...
0025:Call ole32.CoCreateInstance(00a37470,00000000,00000003,00a37420,00e454d8)
ret=008317a7
...
0025:Call KERNEL32.LoadLibraryExW(0033ee8e
L"C:\\windows\\system32\\quartz.dll",00000000,00000008) ret=7eb6a6cb 
...
0025:Ret  PE DLL (proc=0x7d2c1b70,module=0x7d210000
L"quartz.dll",reason=PROCESS_ATTACH,res=(nil)) retval=1
0025:Ret  KERNEL32.LoadLibraryExW() retval=7d210000 ret=7eb6a6cb
...
0025:Ret  ole32.CoCreateInstance() retval=00000000 ret=008317a7
--- snip ---

Wine uses multiple COM servers on the same thread with apartment threading
model:

--- snip ---
...
0025:Call dsound.DirectSoundCreate8(00000000,00de1880,00000000) ret=0082f977 
...
0025:Call ole32.CoInitialize(00000000) ret=7e2ce081
0025:err:ole:CoInitializeEx Attempt to change threading model of this apartment
from multi-threaded to apartment threaded
0025:Ret  ole32.CoInitialize() retval=80010106 ret=7e2ce081
0025:Call ole32.CoCreateInstance(7e2e27d8,00000000,00000001,7e2e27a8,0033efa8)
ret=7e2ce0b6 
...
--- snip ---

The problematic one:

--- snip ---
...
0025:trace:d3dx:D3DXLoadSurfaceFromFileInMemory dst_surface 0xb34afa8,
dst_palette (nil), dst_rect (null), src_data 0x1570000, src_data_size 65580,
src_rect (null), filter 0x1, color_key 0x00000000, src_info (nil).
0025:trace:d3dx:D3DXGetImageInfoFromFileInMemory (0x1570000, 65580, 0x33ea64)
0025:Call ole32.CoInitializeEx(00000000,00000002) ret=7ed82a47
0025:err:ole:CoInitializeEx Attempt to change threading model of this apartment
from multi-threaded to apartment threaded
0025:Ret  ole32.CoInitializeEx() retval=80010106 ret=7ed82a47
0025:Call ole32.CoCreateInstance(7ed9ed1c,00000000,00000001,7ed9ed2c,0033e8cc)
ret=7ed82a7f 
...
0025:trace:d3dx:D3DXLoadSurfaceFromMemory (0xb34afa8, (nil), (null), 0xb361c10,
0x16, 512, (nil), (0,0)-(128,128) 0x1, 0x00000000) 
...
0025:Call ole32.CoUninitialize() ret=7ed84242
0025:Call quartz.DllCanUnloadNow() ret=7eb6c1c3
0025:Call rpcrt4.NdrDllCanUnloadNow(7d30bab8) ret=7d2633fd
0025:Ret  rpcrt4.NdrDllCanUnloadNow() retval=00000000 ret=7d2633fd
0025:Ret  quartz.DllCanUnloadNow() retval=00000000 ret=7eb6c1c3
0025:Call KERNEL32.FreeLibrary(7d210000) ret=7eb6aa42
0025:Call PE DLL (proc=0x7d2c1b70,module=0x7d210000
L"quartz.dll",reason=PROCESS_DETACH,res=(nil))
0025:Ret  PE DLL (proc=0x7d2c1b70,module=0x7d210000
L"quartz.dll",reason=PROCESS_DETACH,res=(nil)) retval=1
0025:Call PE DLL (proc=0x7dcc9d1c,module=0x7dcb0000
L"msvfw32.dll",reason=PROCESS_DETACH,res=(nil))
0025:Ret  PE DLL (proc=0x7dcc9d1c,module=0x7dcb0000
L"msvfw32.dll",reason=PROCESS_DETACH,res=(nil)) retval=1
0025:Call PE DLL (proc=0x7cd1c3bc,module=0x7cc60000
L"comctl32.dll",reason=PROCESS_DETACH,res=(nil)) 
...
--- snip ---

At this point 'quartz.dll' is unloaded from memory but the game still holds COM
class/iface references!

The crash is a late manifestation, it tries to call
quartz.BasicAudio_put_Volume() with the PE image already gone.

Wine code like D3DXGetImageInfoFromFileInMemory() does it right, taking
CoInitializeEx() result into account.
The COM threading model used might be still questionable.

Source:
http://source.winehq.org/git/wine.git/blob/fa8a0dc7f61715a093a3b2e4453e843a4129476e:/dlls/d3dx9_36/surface.c#l1023

--- snip ---
1023 HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9
*pDestSurface,
1024        const PALETTEENTRY *pDestPalette, const RECT *pDestRect, const void
*pSrcData, UINT SrcDataSize,
1025        const RECT *pSrcRect, DWORD dwFilter, D3DCOLOR Colorkey,
D3DXIMAGE_INFO *pSrcInfo)
1026 {
...
1081     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1082
1083     if (FAILED(CoCreateInstance(&CLSID_WICImagingFactory, NULL,
CLSCTX_INPROC_SERVER, &IID_IWICImagingFactory, (void**)&factory)))
1084         goto cleanup_err;
...
1180 cleanup_err:
1181     if (factory)
1182         IWICImagingFactory_Release(factory);
1183
1184     CoUninitialize();
...
--- snip ---

With that bug fixed it runs farther - and crashes again due to another d3dx9_36
insufficiency.

$ sha1sum Rome_Demo.exe
57e1fc8f2a1b8eeb0a1ccff218010eb828b00159  Rome_Demo.exe

$ du -sh Rome_Demo.exe
308M    Rome_Demo.exe

$ wine --version
wine-1.7.13-27-ge610713

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