http://bugs.winehq.org/show_bug.cgi?id=17902
Summary: ole32.CoGetClassObject: threads without apartment should use existing MTA Product: Wine Version: 1.1.18 Platform: Other URL: http://www.microsoft.com/downloads/details.aspx?FamilyID =fe6f2099-b7b4-4f47-a244-c96d69c35dec OS/Version: other Status: UNCONFIRMED Severity: normal Priority: P2 Component: ole32 AssignedTo: wine-bugs@winehq.org ReportedBy: focht@gmx.net
Hello,
there are apps which use free threaded COM (inproc) servers and call CoGetClassObject() from (new) threads that do not explicitly initialize COM. This is valid behaviour when one of the existing threads already created the MTA by calling CoInitializeEx(NULL, COINIT_MULTITHREADED).
See: http://support.microsoft.com/kb/150777
--- quote --- Current implementations of COM allow a thread that does not explicitly initialize COM to be a part of the MTA. A thread that does not initialize COM is part of the MTA only if it starts using COM after at least one other thread in the process has previously called CoInitializeEx(NULL, COINIT_MULTITHREADED). (It is even possible that COM itself may have initialized the MTA when no client thread has explicitly done so; for example, a thread associated with an STA calls CoGetClassObject/CoCreateInstance[Ex] on a CLSID that is marked "ThreadingModel=Free" and COM implicitly creates an MTA into which the class object is loaded.) See the information on threading model interoperability below.
However, this is a configuration that might cause problems, such as access violations, under certain circumstances. Therefore, it is strongly recommended that each thread that needs to do COM work initialize COM by calling CoInitializeEx and then, on completion of COM work, call CoUninitialize. The cost of "unnecessarily" initializing an MTA is minimal. --- quote ---
An example app suffering from this is the managed console debugger from .NET 2.0 SDK "cordbg.exe":
When trying to debug a simple console C# app created with symbols (.pdb format):
--- snip --- wine "C:\windows\Microsoft.NET\Framework\v2.0.50727\csc.exe" /debug+ foo.cs --- snip ---
Start debugger:
--- snip --- wine "C:\Program Files\Microsoft.NET\SDK\v2.0\Bin\cordbg.exe foo.exe" --- snip ---
The debugger will immediately begin to execute the app - not halting in Main() method (source). This is because symbol information can't be loaded using COR symbol binder which lives in a free threaded COM inproc server. 0A29FF9E-7F9C-4437-8B11-F424491E3931 -> CLSID_CorSymBinder
Threads 0x38 (main) and 0x36 call "CoInitializeEx" with COINIT_MULTITHREADED, creating the MTA. Thread 0x3b is created later as pooled thread - part of MTA - to serve CLR debugger requests (work items). That thread never makes any init calls to COM (verified).
--- snip --- ... 0038:Call KERNEL32.GetProcAddress(60970000,7a37e2ae "CoInitializeEx") ret=79e9d311 0038:Ret KERNEL32.GetProcAddress() retval=609750c8 ret=79e9d311 0038:Call ole32.CoInitializeEx(00000000,00000000) ret=79ebfba8 0038:Call ntdll.RtlAllocateHeap(00110000,00000008,000000fc) ret=60986499 0038:Ret ntdll.RtlAllocateHeap() retval=0014f9c0 ret=60986499 0038:Call ntdll.RtlAllocateHeap(00110000,00000000,00000028) ret=609a750c 0038:Ret ntdll.RtlAllocateHeap() retval=001500e8 ret=609a750c 0038:Call KERNEL32.InitializeCriticalSection(001500f8) ret=609a7543 0038:Ret KERNEL32.InitializeCriticalSection() retval=00000001 ret=609a7543 0038:Call ntdll.RtlAllocateHeap(00110000,00000008,0000007c) ret=60983f54 0038:Ret ntdll.RtlAllocateHeap() retval=00151df0 ret=60983f54 0038:Call KERNEL32.InitializeCriticalSection(00151e10) ret=60983fb4 0038:Ret KERNEL32.InitializeCriticalSection() retval=00000001 ret=60983fb4 0038:Ret ole32.CoInitializeEx() retval=00000000 ret=79ebfba8 ... 0036:Call ole32.CoInitializeEx(00000000,00000000) ret=79ebfba8 0036:Call ntdll.RtlAllocateHeap(00110000,00000008,000000fc) ret=60986499 0036:Ret ntdll.RtlAllocateHeap() retval=00151e78 ret=60986499 0036:Ret ole32.CoInitializeEx() retval=00000000 ret=79ebfba8 ... 003b:Call advapi32.RegOpenKeyExW(80000000,0310d170 L"CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931}\InprocServer32",00000000,00020019,0310d0dc) ret=79ea5b8a 003b:Ret advapi32.RegOpenKeyExW() retval=00000000 ret=79ea5b8a 003b:Call ... 003b:Call advapi32.RegOpenKeyExW(00000238,0310d270 L"2.0.50727",00000000,00020019,0310d0ec) ret=79ea5b8a 003b:Ret advapi32.RegOpenKeyExW() retval=00000000 ret=79ea5b8a 003b:Call advapi32.RegQueryValueExW(0000023c,7a136a40 L"ImplementedInThisVersion",00000000,0310d0e4,00000000,0310d0e8) ret=79ea5bd0 003b:Ret advapi32.RegQueryValueExW() retval=00000000 ret=79ea5bd0 003b:Call advapi32.RegCloseKey(0000023c) ret=7a1369f2 003b:Ret advapi32.RegCloseKey() retval=00000000 ret=7a1369f2 ... 003b:Call advapi32.RegOpenKeyExW(80000000,0310d318 L"CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931}\InprocServer32\2.0.50727",00000000,00020019,0310d314) ret=79ea5b8a 003b:Ret advapi32.RegOpenKeyExW() retval=00000000 ret=79ea5b8a 003b:Call advapi32.RegQueryValueExW(00000238,79f873d0 L"Class",00000000,0310d2f8,00000000,0310d310) ret=79ea5bd0 003b:Ret advapi32.RegQueryValueExW() retval=00000002 ret=79ea5bd0 003b:Call advapi32.RegCloseKey(00000238) ret=79f88946 003b:Ret advapi32.RegCloseKey() retval=00000000 ret=79f88946 ... 003b:Call KERNEL32.GetProcAddress(60970000,7a37e222 "CoGetClassObject") ret=79e9d311 003b:Ret KERNEL32.GetProcAddress() retval=60974f78 ret=79e9d311 003b:Call ole32.CoGetClassObject(00175d3c,00000015,00000000,79f83a7c,0310d5e8) ret=7a041335 003b:err:ole:CoGetClassObject apartment not initialised 003b:Ret ole32.CoGetClassObject() retval=800401f0 ret=7a041335 003b:Call KERNEL32.GetLastError() ret=79e74ab4 003b:Ret KERNEL32.GetLastError() retval=0000007f ret=79e74ab4 000007f ret=78132d14 ... 003b:Call KERNEL32.FormatMessageW(000031ff,00000000,800401f0,00000400,0310d4f4,00000000,0310d4a0) ret=7a127c38 003b:Ret KERNEL32.FormatMessageW() retval=00000000 ret=7a127c38 --- quote ---
The failure is due to Wine's CoGetClassObject() rejecting requests when no apartment in current thread (oletls) exists.
--- snip dlls/ole32/compobj.c --- HRESULT WINAPI CoGetClassObject( REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo, REFIID iid, LPVOID *ppv) { LPUNKNOWN regClassObject; HRESULT hres = E_UNEXPECTED; APARTMENT *apt;
TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid));
if (!ppv) return E_INVALIDARG;
*ppv = NULL;
apt = COM_CurrentApt(); if (!apt) { ERR("apartment not initialised\n"); return CO_E_NOTINITIALIZED; } ... --- snip dlls/ole32/compobj.c ---
Rather than failing CoGetClassObject() without apartment, it should look for an existing MTA and let the current thread use it.
With the MTA being used, the inproc server is created and the app works as intended, e.g. symbols get loaded, source can be stepped ...
Regards
http://bugs.winehq.org/show_bug.cgi?id=17902
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download
http://bugs.winehq.org/show_bug.cgi?id=17902
--- Comment #1 from Anastasius Focht focht@gmx.net 2009-04-28 05:38:42 --- Hello,
Adobe cs3, cs4 installer custom action threads also rely on reuse of MTA to have CoCreateInstance()/CoGetClassObject() succeed. Bug 1807 , bug 18228 and possibly others.
Regards
http://bugs.winehq.org/show_bug.cgi?id=17902
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution| |FIXED
--- Comment #2 from Anastasius Focht focht@gmx.net 2009-05-05 13:40:10 --- Hello,
thanks, fixed by commit bd4975acb0b682bbf2b4934d12f942ea629f5bbb See my comment in bug 18070 for the CA issue which might be still present.
Regards
http://bugs.winehq.org/show_bug.cgi?id=17902
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #3 from Alexandre Julliard julliard@winehq.org 2009-05-08 12:50:57 --- Closing bugs fixed in 1.1.21.
http://bugs.winehq.org/show_bug.cgi?id=17902
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |bd4975acb0b682bbf2b4934d12f | |942ea629f5bbb
--- Comment #4 from Anastasius Focht focht@gmx.net 2011-10-11 15:35:07 CDT --- Hello,
filling/correcting fields ...
Regards
http://bugs.winehq.org/show_bug.cgi?id=17902
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Hardware|Other |x86 OS|other |Linux
https://bugs.winehq.org/show_bug.cgi?id=17902
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|ole32.CoGetClassObject: |ole32.CoGetClassObject: |threads without apartment |threads without apartment |should use existing MTA |should use existing MTA | |(.NET Framework 2.0 SDK | |cordbg) Keywords| |dotnet URL|http://www.microsoft.com/do |https://web.archive.org/web |wnloads/details.aspx?Family |/20111026224703/http://down |ID=fe6f2099-b7b4-4f47-a244- |load.microsoft.com/download |c96d69c35dec |/c/4/b/c4b15d7d-6f37-4d5a-b | |9c6-8f07e7d46635/setup.exe