out-of-process COM design

Robert Shearman rob at codeweavers.com
Sat Dec 18 07:13:23 CST 2004


Mike Hearn wrote:

>On Fri, 17 Dec 2004 10:49:45 -0800, Bill Medland wrote:
>  
>
>>Does anyone know anything about this?  e.g. when starting a new thread where 
>>does the apartment get initialized?
>>    
>>
>
>It's supposed to get initialized in the call to CoInitialize[Ex] however
>the _LocalServerThread never calls this as it's an internal implementation
>detail of out of process DCOM.
>
>This looks like we haven't got the design quite right here, the
>LocalServerThread doesn't exist in native DCOM as far as I can tell
>so it may need to be replaced by something else.
>  
>

Rewriting this stuff is next on my todo list. The correct fix is to 
marshal it in the context of the calling thread, rather than in the new 
thread. This part is implemented in the native version as kind of a mix 
between the rpcrt4 thread pooling and undocumented local activator 
interfaces registered for each apartment.

>The code in StdMarshalImpl is correct, the problem is that the local
>server thread is violating the COM laws by using CoMarshalInterface before
>entering an apartment. 
>
>For now, does this patch help?
>
>
>
>Index: dlls/ole32/compobj.c
>===================================================================
>RCS file: /home/wine/wine/dlls/ole32/compobj.c,v
>retrieving revision 1.113
>diff -u -p -r1.113 compobj.c
>--- dlls/ole32/compobj.c	14 Dec 2004 15:28:58 -0000	1.113
>+++ dlls/ole32/compobj.c	17 Dec 2004 19:13:22 -0000
>@@ -102,6 +102,7 @@ typedef struct tagRegisteredClass
>   DWORD     connectFlags;
>   DWORD     dwCookie;
>   HANDLE    hThread; /* only for localserver */
>+  APARTMENT *apt;    /* owning apartment */
>   struct tagRegisteredClass* nextClass;
> } RegisteredClass;
> 
>@@ -1107,6 +1108,13 @@ _LocalServerThread(LPVOID param) {
> 
>     TRACE("Starting threader for %s.\n",debugstr_guid(&newClass->classIdentifier));
> 
>+    /* we need to enter the apartment of the thread which registered
>+     * the class object to perform the next stage
>+     */
>+
>+    assert( newClass->apt );
>+    NtCurrentTeb()->ReservedForOle = newClass->apt;
>+
>     strcpy(pipefn,PIPEPREF);
>     WINE_StringFromCLSID(&newClass->classIdentifier,pipefn+strlen(PIPEPREF));
> 
>@@ -1219,6 +1227,12 @@ HRESULT WINAPI CoRegisterClassObject(
>   if ( (lpdwRegister==0) || (pUnk==0) )
>     return E_INVALIDARG;
> 
>+  if (!COM_CurrentApt())
>+  {
>+      ERR("COM was not initialized\n");
>+      return CO_E_NOTINITIALIZED;
>+  }
>+
>   *lpdwRegister = 0;
> 
>   /*
>@@ -1240,6 +1254,7 @@ HRESULT WINAPI CoRegisterClassObject(
>   newClass->classIdentifier = *rclsid;
>   newClass->runContext      = dwClsContext;
>   newClass->connectFlags    = flags;
>+  newClass->apt             = COM_CurrentApt();
>   /*
>    * Use the address of the chain node as the cookie since we are sure it's
>    * unique.
>
>  
>

That patch is very hackish and needlessly complicated. This patch 
accomplishes the same task in fewer lines (note that this is not the 
best solution for the problem, I am working on that):

Index: compobj.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/compobj.c,v
retrieving revision 1.113
diff -u -p -r1.113 compobj.c
--- compobj.c   14 Dec 2004 15:28:58 -0000      1.113
+++ compobj.c   18 Dec 2004 13:58:03 -0000
@@ -1107,6 +1107,8 @@ _LocalServerThread(LPVOID param) {

     TRACE("Starting threader for 
%s.\n",debugstr_guid(&newClass->classIdentifier));

+    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+
     strcpy(pipefn,PIPEPREF);
     
WINE_StringFromCLSID(&newClass->classIdentifier,pipefn+strlen(PIPEPREF));


Rob



More information about the wine-devel mailing list