Wine-20050111 vendor drop
Added: vendor/wine/dlls/ole32/Wine-20050111/
Modified: vendor/wine/dlls/ole32/Wine-20050111/Makefile.in
Modified: vendor/wine/dlls/ole32/Wine-20050111/bindctx.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/clipboard.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/compobj.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/compobj_private.h
Modified: vendor/wine/dlls/ole32/Wine-20050111/compositemoniker.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/datacache.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/defaulthandler.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/errorinfo.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/filemoniker.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/ftmarshal.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/hglobalstream.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/ifs.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/ifs.h
Modified: vendor/wine/dlls/ole32/Wine-20050111/itemmoniker.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/marshal.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/memlockbytes.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/moniker.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/ole2.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/oleobj.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/oleproxy.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/rpc.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/stg_bigblockfile.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/stg_stream.c
Modified: vendor/wine/dlls/ole32/Wine-20050111/storage32.c
Added: vendor/wine/dlls/ole32/Wine-20050111/stubmanager.c
Modified: vendor/wine/dlls/ole32/current/Makefile.in
Modified: vendor/wine/dlls/ole32/current/bindctx.c
Modified: vendor/wine/dlls/ole32/current/clipboard.c
Modified: vendor/wine/dlls/ole32/current/compobj.c
Modified: vendor/wine/dlls/ole32/current/compobj_private.h
Modified: vendor/wine/dlls/ole32/current/compositemoniker.c
Modified: vendor/wine/dlls/ole32/current/datacache.c
Modified: vendor/wine/dlls/ole32/current/defaulthandler.c
Modified: vendor/wine/dlls/ole32/current/errorinfo.c
Modified: vendor/wine/dlls/ole32/current/filemoniker.c
Modified: vendor/wine/dlls/ole32/current/ftmarshal.c
Modified: vendor/wine/dlls/ole32/current/hglobalstream.c
Modified: vendor/wine/dlls/ole32/current/ifs.c
Modified: vendor/wine/dlls/ole32/current/ifs.h
Modified: vendor/wine/dlls/ole32/current/itemmoniker.c
Modified: vendor/wine/dlls/ole32/current/marshal.c
Modified: vendor/wine/dlls/ole32/current/memlockbytes.c
Modified: vendor/wine/dlls/ole32/current/moniker.c
Modified: vendor/wine/dlls/ole32/current/ole2.c
Modified: vendor/wine/dlls/ole32/current/oleobj.c
Modified: vendor/wine/dlls/ole32/current/oleproxy.c
Modified: vendor/wine/dlls/ole32/current/rpc.c
Modified: vendor/wine/dlls/ole32/current/stg_bigblockfile.c
Modified: vendor/wine/dlls/ole32/current/stg_stream.c
Modified: vendor/wine/dlls/ole32/current/storage32.c
Added: vendor/wine/dlls/ole32/current/stubmanager.c

Copied: vendor/wine/dlls/ole32/Wine-20050111 (from rev 12927, vendor/wine/dlls/ole32/current)

Modified: vendor/wine/dlls/ole32/Wine-20050111/Makefile.in
--- vendor/wine/dlls/ole32/current/Makefile.in	2005-01-11 20:23:48 UTC (rev 12927)
+++ vendor/wine/dlls/ole32/Wine-20050111/Makefile.in	2005-01-12 09:03:31 UTC (rev 12947)
@@ -35,7 +35,8 @@
 	rpc.c \
 	stg_bigblockfile.c \
 	stg_stream.c \
-	storage32.c
+	storage32.c \
+	stubmanager.c
 
 C_SRCS16 = \
 	memlockbytes16.c \

Modified: vendor/wine/dlls/ole32/Wine-20050111/bindctx.c
--- vendor/wine/dlls/ole32/current/bindctx.c	2005-01-11 20:23:48 UTC (rev 12927)
+++ vendor/wine/dlls/ole32/Wine-20050111/bindctx.c	2005-01-12 09:03:31 UTC (rev 12947)
@@ -275,8 +275,7 @@
 
     if(This->bindCtxTable[index].pObj)
         IUnknown_Release(This->bindCtxTable[index].pObj);
-    if(This->bindCtxTable[index].pkeyObj)
-        HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
+    HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
     
     /* left-shift all elements in the right side of the current revoked object */
     for(j=index; j<This->bindCtxTableLastIndex-1; j++)
@@ -302,8 +301,7 @@
     {
         if(This->bindCtxTable[i].pObj)
             IUnknown_Release(This->bindCtxTable[i].pObj);
-        if(This->bindCtxTable[i].pkeyObj)
-            HeapFree(GetProcessHeap(),0,This->bindCtxTable[i].pkeyObj);
+        HeapFree(GetProcessHeap(),0,This->bindCtxTable[i].pkeyObj);
     }
     
     This->bindCtxTableLastIndex = 0;
@@ -472,8 +470,7 @@
     /* release the object if it's found */
     if(This->bindCtxTable[index].pObj)
         IUnknown_Release(This->bindCtxTable[index].pObj);
-    if(This->bindCtxTable[index].pkeyObj)
-        HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
+    HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
     
     /* remove the object from the table with a left-shifting of all objects in the right side */
     for(j=index; j<This->bindCtxTableLastIndex-1; j++)

Modified: vendor/wine/dlls/ole32/Wine-20050111/clipboard.c
--- vendor/wine/dlls/ole32/current/clipboard.c	2005-01-11 20:23:48 UTC (rev 12927)
+++ vendor/wine/dlls/ole32/Wine-20050111/clipboard.c	2005-01-12 09:03:31 UTC (rev 12947)
@@ -736,7 +736,7 @@
      * We don't bother doing this since the FindClassByAtom code
      * would have to be changed to deal with this idiosyncrasy. */
     wcex.style          = CS_GLOBALCLASS;
-    wcex.lpfnWndProc    = (WNDPROC)OLEClipbrd_WndProc;
+    wcex.lpfnWndProc    = OLEClipbrd_WndProc;
     wcex.hInstance      = 0;
     wcex.lpszClassName  = OLEClipbrd_WNDCLASS;
 
@@ -1489,8 +1489,7 @@
   /*
    * Free the array of FORMATETC's
    */
-  if (afmt)
-    HeapFree(GetProcessHeap(), 0, afmt);
+  HeapFree(GetProcessHeap(), 0, afmt);
 
   /*
    * Close Windows clipboard

Modified: vendor/wine/dlls/ole32/Wine-20050111/compobj.c
--- vendor/wine/dlls/ole32/current/compobj.c	2005-01-11 20:23:48 UTC (rev 12927)
+++ vendor/wine/dlls/ole32/Wine-20050111/compobj.c	2005-01-12 09:03:31 UTC (rev 12947)
@@ -21,6 +21,44 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Note
+ * 1. COINIT_MULTITHREADED is 0; it is the lack of COINIT_APARTMENTTHREADED
+ *    Therefore do not test against COINIT_MULTITHREADED
+ *
+ * TODO list:           (items bunched together depend on each other)
+ *
+ *   - Switch wine_marshal_id to use IPIDs not IIDs
+ *   - Once that's done, replace wine_marshal_id with STDOBJREF
+ *
+ *   - Rewrite the CoLockObjectExternal code, it does totally the wrong
+ *     thing currently (should be controlling the stub manager)
+ *
+ *   - Make the MTA dynamically allocated and refcounted
+ *   - Free the ReservedForOle data in DllMain(THREAD_DETACH)
+ *
+ *   - Implement the service control manager (in rpcss) to keep track
+ *     of registered class objects: ISCM::ServerRegisterClsid et al
+ *   - Implement the OXID resolver so we don't need magic pipe names for
+ *     clients and servers to meet up
+ *   - Flip our marshalling on top of the RPC runtime transport API,
+ *     so we no longer use named pipes to communicate
+ *   - Rework threading so re-entrant calls don't need to be sent on
+ *     the incoming pipe
+ *   - Implement RPC thread affinity (should fix InstallShield painting
+ *     problems)
+ *
+ *   - Implement IRemUnknown and marshalling for it, then use that for
+ *     reffing/unreffing the stub manager from a proxy instead of our
+ *     current hack of simply reffing the stub manager once when it's
+ *     registered.
+ *   - Implement table marshalling, then use it to let us do the final
+ *     rework of the threading
+ *
+ *   - Make our custom marshalling use NDR to be wire compatible with
+ *     native DCOM
+ *     
+ *        
  */
 
 #include "config.h"
@@ -61,15 +99,15 @@
  *
  * TODO: Most of these things will have to be made thread-safe.
  */
-HINSTANCE       COMPOBJ_hInstance32 = 0;
 
 static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN*  ppUnk);
-static void COM_RevokeAllClasses();
-static void COM_ExternalLockFreeList();
+static void COM_RevokeAllClasses(void);
+static void COM_ExternalLockFreeList(void);
 
 const CLSID CLSID_StdGlobalInterfaceTable = { 0x00000323, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
 
-APARTMENT MTA, *apts;
+APARTMENT MTA;
+static struct list apts = LIST_INIT( apts );
 
 static CRITICAL_SECTION csApartment;
 static CRITICAL_SECTION_DEBUG critsect_debug =
@@ -102,7 +140,7 @@
   DWORD     runContext;
   DWORD     connectFlags;
   DWORD     dwCookie;
-  HANDLE    hThread; /* only for localserver */
+  LPSTREAM  pMarshaledData; /* FIXME: only really need to store OXID and IPID */
   struct tagRegisteredClass* nextClass;
 } RegisteredClass;
 
@@ -206,6 +244,7 @@
     MTA.oxid = 0;
 }
 
+
 /* creates an apartment structure which stores OLE thread-local
  * information. Call with COINIT_UNINITIALIZED to create an apartment
  * that will be initialized with a model later. Note: do not call
@@ -213,81 +252,138 @@
  * with a different COINIT value */
 APARTMENT* COM_CreateApartment(DWORD model)
 {
-    APARTMENT *apt;
-    BOOL create = (NtCurrentTeb()->ReservedForOle == NULL);
+    APARTMENT *apt = COM_CurrentApt();
 
-    if (create)
+    if (!apt)
     {
+        if (!(model & COINIT_APARTMENTTHREADED)) /* See note 1 above */
+        {
+            TRACE("thread 0x%lx is entering the multithreaded apartment\n", GetCurrentThreadId());
+            COM_CurrentInfo()->apt = &MTA;
+            return COM_CurrentInfo()->apt;
+        }
+
+        TRACE("creating new apartment, model=%ld\n", model);
+
         apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APARTMENT));
         apt->tid = GetCurrentThreadId();
         DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
                         GetCurrentProcess(), &apt->thread,
                         THREAD_ALL_ACCESS, FALSE, 0);
+
+        list_init(&apt->proxies);
+        list_init(&apt->stubmgrs);
+        apt->oidc = 1;
+        apt->refs = 1;
+        InitializeCriticalSection(&apt->cs);
+
+        apt->model = model;
+
+        /* we don't ref the apartment as CoInitializeEx will do it for us */
+
+        if (model & COINIT_APARTMENTTHREADED)
+        {
+            /* FIXME: how does windoze create OXIDs? */
+            apt->oxid = MTA.oxid | GetCurrentThreadId();
+            TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid));
+            apt->win = CreateWindowA(aptWinClass, NULL, 0,
+                                     0, 0, 0, 0,
+                                     0, 0, OLE32_hInstance, NULL);
+        }
+
+        EnterCriticalSection(&csApartment);
+        list_add_head(&apts, &apt->entry);
+        LeaveCriticalSection(&csApartment);
+
+        COM_CurrentInfo()->apt = apt;
     }
-    else
-        apt = NtCurrentTeb()->ReservedForOle;
 
-    apt->model = model;
-    if (model & COINIT_APARTMENTTHREADED) {
-      /* FIXME: how does windoze create OXIDs? */
-      apt->oxid = MTA.oxid | GetCurrentThreadId();
-      apt->win = CreateWindowA(aptWinClass, NULL, 0,
-			       0, 0, 0, 0,
-			       0, 0, OLE32_hInstance, NULL);
-      InitializeCriticalSection(&apt->cs);
-    }
-    else if (!(model & COINIT_UNINITIALIZED)) {
-      apt->parent = &MTA;
-      apt->oxid = MTA.oxid;
-    }
-    EnterCriticalSection(&csApartment);
-    if (create)
+    return apt;
+}
+
+DWORD COM_ApartmentAddRef(struct apartment *apt)
+{
+    return InterlockedIncrement(&apt->refs);
+}
+
+DWORD COM_ApartmentRelease(struct apartment *apt)
+{
+    DWORD ret;
+
+    ret = InterlockedDecrement(&apt->refs);
+    if (ret == 0)
     {
-        if (apts) apts->prev = apt;
-        apt->next = apts;
-        apts = apt;
+        TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid));
+
+        EnterCriticalSection(&csApartment);
+        list_remove(&apt->entry);
+        LeaveCriticalSection(&csApartment);
+
+        MARSHAL_Disconnect_Proxies(apt);
+
+        if (apt->win) DestroyWindow(apt->win);
+
+        if (!list_empty(&apt->stubmgrs))
+        {
+            FIXME("Destroy outstanding stubs\n");
+        }
+
+        if (apt->filter) IUnknown_Release(apt->filter);
+
+
+        DeleteCriticalSection(&apt->cs);
+        CloseHandle(apt->thread);
+        HeapFree(GetProcessHeap(), 0, apt);
+
+        apt = NULL;
     }
-    LeaveCriticalSection(&csApartment);
-    NtCurrentTeb()->ReservedForOle = apt;
-    return apt;
+
+    return ret;
 }
 
-static void COM_DestroyApartment(APARTMENT *apt)
+/* The given OXID must be local to this process: you cannot use
+ * apartment windows to send RPCs to other processes. This all needs
+ * to move to rpcrt4.
+ *
+ * The ref parameter is here mostly to ensure people remember that
+ * they get one, you should normally take a ref for thread safety.
+ */
+APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref)
 {
+    APARTMENT *result = NULL;
+    struct list *cursor;
+
     EnterCriticalSection(&csApartment);
-    if (apt->prev) apt->prev->next = apt->next;
-    if (apt->next) apt->next->prev = apt->prev;
-    if (apts == apt) apts = apt->next;
-    apt->prev = NULL; apt->next = NULL;
+    LIST_FOR_EACH( cursor, &apts )
+    {
+        struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry );
+        if (apt->oxid == oxid)
+        {
+            result = apt;
+            if (ref) COM_ApartmentAddRef(result);
+            break;
+        }
+    }
     LeaveCriticalSection(&csApartment);
-    if (apt->model & COINIT_APARTMENTTHREADED) {
-      if (apt->win) DestroyWindow(apt->win);
-      DeleteCriticalSection(&apt->cs);
-    }
-    CloseHandle(apt->thread);
-    HeapFree(GetProcessHeap(), 0, apt);
+
+    return result;
 }
 
-/* The given OXID must be local to this process: you cannot use apartment
-   windows to send RPCs to other processes. This all needs to move to rpcrt4 */
-HWND COM_GetApartmentWin(OXID oxid)
+HWND COM_GetApartmentWin(OXID oxid, BOOL ref)
 {
     APARTMENT *apt;
-    HWND win = 0;
 
-    EnterCriticalSection(&csApartment);
-    apt = apts;
-    while (apt && apt->oxid != oxid) apt = apt->next;
-    if (apt) win = apt->win;
-    LeaveCriticalSection(&csApartment);
-    return win;
+    apt = COM_ApartmentFromOXID(oxid, ref);
+    if (!apt) return NULL;
+
+    return apt->win;
 }
 
 /* Currently inter-thread marshalling is not fully implemented, so this does nothing */
 static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
   return DefWindowProcA(hWnd, msg, wParam, lParam);
-} 
+}
 
 /*****************************************************************************
  * This section contains OpenDllList implemantation
@@ -418,8 +514,7 @@
  *   CoUninitialize
  */
 HRESULT WINAPI CoInitializeEx(
-	LPVOID lpReserved,	/* [in] pointer to win32 malloc interface
-                                   (obsolete, should be NULL) */
+	LPVOID lpReserved,	/* [in] pointer to win32 malloc interface (obsolete, should be NULL) */
 	DWORD dwCoInit		/* [in] A value from COINIT specifies the threading model */
 )
 {
@@ -433,21 +528,6 @@
     ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved);
   }
 
-  apt = NtCurrentTeb()->ReservedForOle;
-  if (apt && !(apt->model == COINIT_UNINITIALIZED))
-  {
-    if (dwCoInit != apt->model)
-    {
-      /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine
-         code then we are probably using the wrong threading model to implement that API. */
-      ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit);
-      return RPC_E_CHANGED_MODE;
-    }
-    hr = S_FALSE;
-  }
-  else
-    hr = S_OK;
-
   /*
    * Check the lock count. If this is the first time going through the initialize
    * process, we have to initialize the libraries.
@@ -463,13 +543,25 @@
 
     COM_InitMTA();
 
+    /* we may need to defer this until after apartment initialisation */
     RunningObjectTableImpl_Initialize();
   }
 
-  if (!apt || apt->model == COINIT_UNINITIALIZED) apt = COM_CreateApartment(dwCoInit);
+  if (!(apt = COM_CurrentInfo()->apt))
+  {
+    apt = COM_CreateApartment(dwCoInit);
+    if (!apt) return E_OUTOFMEMORY;
+  }
+  else if (dwCoInit != apt->model)
+  {
+    /* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine
+       code then we are probably using the wrong threading model to implement that API. */
+    ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit);
+    COM_ApartmentRelease(apt);
+    return RPC_E_CHANGED_MODE;
+  }
 
-  InterlockedIncrement(&apt->inits);
-  if (hr == S_OK) NtCurrentTeb()->ReservedForOle = apt;
+  COM_CurrentInfo()->inits++;
 
   return hr;
 }
@@ -480,14 +572,20 @@
 void COM_FlushMessageQueue(void)
 {
     MSG message;
-    APARTMENT *apt = NtCurrentTeb()->ReservedForOle;
+    APARTMENT *apt = COM_CurrentApt();
 
     if (!apt || !apt->win) return;
 
     TRACE("Flushing STA message queue\n");
 
-    while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE)) {
-        if (message.hwnd != apt->win) continue;
+    while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE))
+    {
+        if (message.hwnd != apt->win)
+        {
+            WARN("discarding message 0x%x for window %p\n", message.message, message.hwnd);
+            continue;
+        }
+
         TranslateMessage(&message);
         DispatchMessageA(&message);
     }
@@ -511,19 +609,27 @@
  */
 void WINAPI CoUninitialize(void)
 {
+  struct oletls * info = COM_CurrentInfo();
   LONG lCOMRefCnt;
-  APARTMENT *apt;
 
   TRACE("()\n");
 
-  apt = NtCurrentTeb()->ReservedForOle;
-  if (!apt) return;
-  if (InterlockedDecrement(&apt->inits)==0) {
-    NtCurrentTeb()->ReservedForOle = NULL;
-    COM_DestroyApartment(apt);
-    apt = NULL;
+  /* will only happen on OOM */
+  if (!info) return;
+
+  /* sanity check */
+  if (!info->inits)
+  {
+    ERR("Mismatched CoUninitialize\n");
+    return;
   }
 
+  if (!--info->inits)
+  {
+    COM_ApartmentRelease(info->apt);
+    info->apt = NULL;
+  }
+
   /*
    * Decrease the reference count.
    * If we are back to 0 locks on the COM library, make sure we free
@@ -536,14 +642,6 @@
 
     RunningObjectTableImpl_UnInitialize();
 
-    /* disconnect proxies to release the corresponding stubs.
-     * It is confirmed in "Essential COM" in the sub-chapter on
-     * "Lifecycle Management and Marshalling" that the native version also
-     * does some kind of proxy cleanup in this function.
-     * FIXME: does it just disconnect or completely destroy the proxies?
-     * FIXME: should this be in the apartment destructor? */
-    MARSHAL_Disconnect_Proxies();
-
     /* Release the references to the registered class objects */
     COM_RevokeAllClasses();
 
@@ -1091,117 +1189,24 @@
   return hr;
 }
 
-static DWORD WINAPI
-_LocalServerThread(LPVOID param) {
-    HANDLE		hPipe;
-    char 		pipefn[200];
-    RegisteredClass *newClass = (RegisteredClass*)param;
-    HRESULT		hres;
-    IStream		*pStm;
-    STATSTG		ststg;
-    unsigned char	*buffer;
-    int 		buflen;
-    IClassFactory	*classfac;
-    LARGE_INTEGER	seekto;
-    ULARGE_INTEGER	newpos;
-    ULONG		res;
-
-    TRACE("Starting threader for %s.\n",debugstr_guid(&newClass->classIdentifier));
-
-    strcpy(pipefn,PIPEPREF);
-    WINE_StringFromCLSID(&newClass->classIdentifier,pipefn+strlen(PIPEPREF));
-
-    hPipe = CreateNamedPipeA( pipefn, PIPE_ACCESS_DUPLEX,
-               PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
-               4096, 4096, NMPWAIT_USE_DEFAULT_WAIT, NULL );
-    if (hPipe == INVALID_HANDLE_VALUE) {
-        FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError());
-        return 1;
-    }
-    while (1) {
-        if (!ConnectNamedPipe(hPipe,NULL)) {
-            ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError());
-            break;
-        }
-
-        TRACE("marshalling IClassFactory to client\n");
-        
-        hres = IUnknown_QueryInterface(newClass->classObject,&IID_IClassFactory,(LPVOID*)&classfac);
-        if (hres) return hres;
-
-        hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
-        if (hres) {
-            FIXME("Failed to create stream on hglobal.\n");
-            return hres;
-        }
-        hres = CoMarshalInterface(pStm,&IID_IClassFactory,(LPVOID)classfac,0,NULL,0);
-        if (hres) {
-            FIXME("CoMarshalInterface failed, %lx!\n",hres);
-            return hres;
-        }
-
-        IUnknown_Release(classfac); /* is this right? */
-
-        hres = IStream_Stat(pStm,&ststg,0);
-        if (hres) return hres;
-
-        buflen = ststg.cbSize.u.LowPart;
-        buffer = HeapAlloc(GetProcessHeap(),0,buflen);
-        seekto.u.LowPart = 0;
-        seekto.u.HighPart = 0;
-        hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
-        if (hres) {
-            FIXME("IStream_Seek failed, %lx\n",hres);
-            return hres;
-        }
-        
-        hres = IStream_Read(pStm,buffer,buflen,&res);
-        if (hres) {
-            FIXME("Stream Read failed, %lx\n",hres);
-            return hres;
-        }
-        
-        IStream_Release(pStm);
-
-        WriteFile(hPipe,buffer,buflen,&res,NULL);
-        FlushFileBuffers(hPipe);
-        DisconnectNamedPipe(hPipe);
-
-        TRACE("done marshalling IClassFactory\n");
-    }
-    CloseHandle(hPipe);
-    return 0;
-}
-
 /******************************************************************************
  *		CoRegisterClassObject	[OLE32.@]
- * 
- * This method will register the class object for a given class
- * ID. Servers housed in EXE files use this method instead of
- * exporting DllGetClassObject to allow other code to connect to their
- * objects.
  *
- * When a class object (an object which implements IClassFactory) is
- * registered in this way, a new thread is started which listens for
- * connections on a named pipe specific to the registered CLSID. When
- * something else connects to it, it writes out the marshalled
- * IClassFactory interface to the pipe. The code on the other end uses
- * this buffer to unmarshal the class factory, and can then call
- * methods on it.
+ * Registers the class object for a given class ID. Servers housed in EXE
+ * files use this method instead of exporting DllGetClassObject to allow
+ * other code to connect to their objects.
  *
- * In Windows, such objects are registered with the RPC endpoint
- * mapper, not with a unique named pipe.
- *
- * MSDN claims that multiple interface registrations are legal, but we
- * can't do that with our current implementation.
- *
  * RETURNS
- *   S_OK on success, 
- *   E_INVALIDARG if lpdwRegister or pUnk are NULL, 
+ *   S_OK on success,
+ *   E_INVALIDARG if lpdwRegister or pUnk are NULL,
  *   CO_E_OBJISREG if the object is already registered. We should not return this.
  *
  * SEE ALSO
  *   CoRevokeClassObject, CoGetClassObject
+ *
+ * BUGS
+ *  MSDN claims that multiple interface registrations are legal, but we
+ *  can't do that with our current implementation.
  */
 HRESULT WINAPI CoRegisterClassObject(
         REFCLSID rclsid,       /* [in] CLSID of the object to register */
@@ -1220,6 +1225,12 @@
   if ( (lpdwRegister==0) || (pUnk==0) )
     return E_INVALIDARG;
 
+  if (!COM_CurrentApt())
+  {
+      ERR("COM was not initialized\n");
+      return CO_E_NOTINITIALIZED;
+  }
+
   *lpdwRegister = 0;
 
   /*
@@ -1243,7 +1254,7 @@
   newClass->connectFlags    = flags;
   /*
    * Use the address of the chain node as the cookie since we are sure it's
-   * unique.
+   * unique. FIXME: not on 64-bit platforms.
    */
   newClass->dwCookie        = (DWORD)newClass;
   newClass->nextClass       = firstRegisteredClass;
@@ -1261,10 +1272,30 @@
   *lpdwRegister = newClass->dwCookie;
 
   if (dwClsContext & CLSCTX_LOCAL_SERVER) {
-      DWORD tid;
+      IClassFactory *classfac;
 
-      STUBMGR_Start();
-      newClass->hThread=CreateThread(NULL,0,_LocalServerThread,newClass,0,&tid);
+      hr = IUnknown_QueryInterface(newClass->classObject, &IID_IClassFactory,
+                                   (LPVOID*)&classfac);
+      if (hr) return hr;
+
+      hr = CreateStreamOnHGlobal(0, TRUE, &newClass->pMarshaledData);
+      if (hr) {
+          FIXME("Failed to create stream on hglobal, %lx\n", hr);
+          IUnknown_Release(classfac);
+          return hr;
+      }
+      hr = CoMarshalInterface(newClass->pMarshaledData, &IID_IClassFactory,
+                              (LPVOID)classfac, MSHCTX_LOCAL, NULL,
+                              MSHLFLAGS_TABLESTRONG);
+      if (hr) {
+          FIXME("CoMarshalInterface failed, %lx!\n",hr);
+          IUnknown_Release(classfac);
+          return hr;
+      }
+
+      IUnknown_Release(classfac);
+
+      RPC_StartLocalServer(&newClass->classIdentifier, newClass->pMarshaledData);
   }
   return S_OK;
 }
@@ -1310,6 +1341,15 @@
        */
       IUnknown_Release(curClass->classObject);
 
+      if (curClass->pMarshaledData)
+      {
+        LARGE_INTEGER zero;
+        memset(&zero, 0, sizeof(zero));
+        /* FIXME: stop local server thread */
+        IStream_Seek(curClass->pMarshaledData, zero, SEEK_SET, NULL);
+        CoReleaseMarshalData(curClass->pMarshaledData);
+      }
+
       /*
        * Free the memory used by the chain node.
        */
@@ -1509,7 +1549,7 @@
             pat=ReadPatternFromRegistry(i,j);
             hFile=CreateFileW(filePathName,,,,,,hFile);
             SetFilePosition(hFile,pat.offset);
-            ReadFile(hFile,buf,pat.size,NULL,NULL);
+            ReadFile(hFile,buf,pat.size,&r,NULL);
             if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
 
                 *pclsid=ReadCLSIDFromRegistry(i);
@@ -1573,7 +1613,7 @@
   LPCLASSFACTORY lpclf = 0;
 
   if (!COM_CurrentApt()) return CO_E_NOTINITIALIZED;
-        
+
   /*
    * Sanity check
    */
@@ -1590,15 +1630,15 @@
    * Rather than create a class factory, we can just check for it here
    */
   if (IsEqualIID(rclsid, &CLSID_StdGlobalInterfaceTable)) {
-    if (StdGlobalInterfaceTableInstance == NULL) 
+    if (StdGlobalInterfaceTableInstance == NULL)
       StdGlobalInterfaceTableInstance = StdGlobalInterfaceTable_Construct();
     hres = IGlobalInterfaceTable_QueryInterface( (IGlobalInterfaceTable*) StdGlobalInterfaceTableInstance, iid, ppv);
     if (hres) return hres;
-    
+
     TRACE("Retrieved GIT (%p)\n", *ppv);
     return S_OK;
   }
-  
+
   /*
    * Get a class factory to construct the object we want.
    */
@@ -1982,6 +2022,8 @@
     BOOL fLock,		/* [in] do lock */
     BOOL fLastUnlockReleases) /* [in] unlock all */
 {
+    TRACE("pUnk=%p, fLock=%s, fLastUnlockReleases=%s\n",
+          pUnk, fLock ? "TRUE" : "FALSE", fLastUnlockReleases ? "TRUE" : "FALSE");
 
 	if (fLock) {
             /*
@@ -2015,19 +2057,19 @@
  */
 HRESULT WINAPI CoGetState(IUnknown ** ppv)
 {
-	APARTMENT * apt = COM_CurrentInfo();
+    HRESULT    hr  = E_FAIL;
 
-	FIXME("\n");
+    *ppv = NULL;
 
-	if(apt && apt->state) {
-	    IUnknown_AddRef(apt->state);
-	    *ppv = apt->state;
-	    FIXME("-- %p\n", *ppv);
-	    return S_OK;
-	}
-	*ppv = NULL;
-	return E_FAIL;
+    if (COM_CurrentInfo()->state)
+    {
+        IUnknown_AddRef(COM_CurrentInfo()->state);
+        *ppv = COM_CurrentInfo()->state;
+        TRACE("apt->state=%p\n", COM_CurrentInfo()->state);
+        hr = S_OK;
+    }
 
+    return hr;
 }
 
 /***********************************************************************
@@ -2036,22 +2078,17 @@
  */
 HRESULT WINAPI CoSetState(IUnknown * pv)
 {
-    APARTMENT * apt = COM_CurrentInfo();
+    if (pv) IUnknown_AddRef(pv);
 
-    if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED);
+    if (COM_CurrentInfo()->state)
+    {
+        TRACE("-- release %p now\n", COM_CurrentInfo()->state);
+        IUnknown_Release(COM_CurrentInfo()->state);
+    }
 
-	FIXME("(%p),stub!\n", pv);
+    COM_CurrentInfo()->state = pv;
 
-	if (pv) {
-	    IUnknown_AddRef(pv);
-	}
-
-	if (apt->state) {
-	    TRACE("-- release %p now\n", apt->state);
-	    IUnknown_Release(apt->state);
-	}
-	apt->state = pv;
-	return S_OK;
+    return S_OK;
 }
 
 
@@ -2206,7 +2243,7 @@
 done:
     if (hkey) RegCloseKey(hkey);
     return res;
-    
+
 }
 
 /***********************************************************************

Modified: vendor/wine/dlls/ole32/Wine-20050111/compobj_private.h
--- vendor/wine/dlls/ole32/current/compobj_private.h	2005-01-11 20:23:48 UTC (rev 12927)
+++ vendor/wine/dlls/ole32/Wine-20050111/compobj_private.h	2005-01-12 09:03:31 UTC (rev 12947)
@@ -5,6 +5,7 @@
  * Copyright 1999 Sylvain St-Germain
  * Copyright 2002 Marcus Meissner
  * Copyright 2003 Ove Kåven, TransGaming Technologies
+ * Copyright 2004 Mike Hearn, CodeWeavers Inc
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -28,6 +29,8 @@
 
 #include <stdarg.h>
 
+#include "wine/list.h"
+
 #include "windef.h"
 #include "winbase.h"
 #include "wtypes.h"
@@ -35,13 +38,9 @@
 #include "winreg.h"
 #include "winternl.h"
 
-/* Windows maps COINIT values to 0x80 for apartment threaded, 0x140
- * for free threaded, and 0 for uninitialized apartments. There is
- * no real advantage in us doing this and certainly no release version
- * of an app should be poking around with these flags. So we need a
- * special value for uninitialized */
-#define COINIT_UNINITIALIZED 0x100
+struct apartment;
 
+
 /* exported interface */
 typedef struct tagXIF {
   struct tagXIF *next;
@@ -56,7 +55,7 @@
 /* exported object */
 typedef struct tagXOBJECT {
   IRpcStubBufferVtbl *lpVtbl;
-  struct tagAPARTMENT *parent;
+  struct apartment *parent;
   struct tagXOBJECT *next;
   LPUNKNOWN obj;           /* object identity (IUnknown) */
   OID oid;                 /* object ID */
@@ -65,51 +64,54 @@
   DWORD refs;              /* external reference count */
 } XOBJECT;
 
-/* imported interface */
-typedef struct tagIIF {
-  struct tagIIF *next;
+/* imported interface proxy */
+struct ifproxy
+{
+  struct list entry;
   LPVOID iface;            /* interface pointer */
   IID iid;                 /* interface ID */
   IPID ipid;               /* imported interface ID */
   LPRPCPROXYBUFFER proxy;  /* interface proxy */
   DWORD refs;              /* imported (public) references */
-  HRESULT hres;            /* result of proxy creation attempt */
-} IIF;
+};
 
-/* imported object */
-typedef struct tagIOBJECT {
-  IRemUnknownVtbl *lpVtbl;
-  struct tagAPARTMENT *parent;
-  struct tagIOBJECT *next;
+/* imported object / proxy manager */
+struct proxy_manager
+{
+  const IInternalUnknownVtbl *lpVtbl;
+  struct apartment *parent;
+  struct list entry;
   LPRPCCHANNELBUFFER chan; /* channel to object */
   OXID oxid;               /* object exported ID */
   OID oid;                 /* object ID */
-  IPID ipid;               /* first imported interface ID */
-  IIF *ifaces;             /* imported interfaces */
+  struct list interfaces;  /* imported interfaces */
   DWORD refs;              /* proxy reference count */
-} IOBJECT;
+  CRITICAL_SECTION cs;     /* thread safety for this object and children */
+};
 
-/* apartment */
-typedef struct tagAPARTMENT {
-  struct tagAPARTMENT *next, *prev, *parent;
+/* this needs to become a COM object that implements IRemUnknown */
+struct apartment
+{
+  struct list entry;       
+
+  DWORD refs;              /* refcount of the apartment */
   DWORD model;             /* threading model */
-  DWORD inits;             /* CoInitialize count */
   DWORD tid;               /* thread id */
   HANDLE thread;           /* thread handle */
   OXID oxid;               /* object exporter ID */
-  OID oidc;                /* object ID counter */
+  OID oidc;                /* object ID counter, starts at 1, zero is invalid OID */
   HWND win;                /* message window */
   CRITICAL_SECTION cs;     /* thread safety */
   LPMESSAGEFILTER filter;  /* message filter */
   XOBJECT *objs;           /* exported objects */
-  IOBJECT *proxies;        /* imported objects */
-  LPUNKNOWN state;         /* state object (see Co[Get,Set]State) */
-  LPVOID ErrorInfo;        /* thread error info */
-} APARTMENT;
+  struct list proxies;     /* imported objects */
+  DWORD listenertid;       /* id of apartment_listener_thread */
+  struct list stubmgrs;    /* stub managers for exported objects */
+};
 
-extern APARTMENT MTA, *apts;
+typedef struct apartment APARTMENT;
 
-extern void* StdGlobalInterfaceTable_Construct();
+extern void* StdGlobalInterfaceTable_Construct(void);
 extern void  StdGlobalInterfaceTable_Destroy(void* self);
 extern HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv);
 
@@ -118,75 +120,124 @@
 
 extern void* StdGlobalInterfaceTableInstance;
 
-#define PIPEPREF "\\\\.\\pipe\\"
-#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr"
-
 /* Standard Marshalling definitions */
 typedef struct _wine_marshal_id {
-    DWORD	processid;
-    DWORD	objectid;	/* unique value corresp. IUnknown of object */
-    IID		iid;
+    OXID    oxid;       /* id of apartment */
+    OID     oid;        /* id of stub manager */
+    IPID    ipid;       /* id of interface pointer */
 } wine_marshal_id;
 
 inline static BOOL
 MARSHAL_Compare_Mids(wine_marshal_id *mid1,wine_marshal_id *mid2) {
     return
-	(mid1->processid == mid2->processid)	&&
-	(mid1->objectid == mid2->objectid)	&&
-	IsEqualIID(&(mid1->iid),&(mid2->iid))
+	(mid1->oxid == mid2->oxid)	&&
+	(mid1->oid == mid2->oid)	&&
+	IsEqualGUID(&(mid1->ipid),&(mid2->ipid))
     ;
 }
 
-/* compare without interface compare */
-inline static BOOL
-MARSHAL_Compare_Mids_NoInterface(wine_marshal_id *mid1, wine_marshal_id *mid2) {
-    return
-	(mid1->processid == mid2->processid)	&&
-	(mid1->objectid == mid2->objectid)
-    ;
-}
+HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt);
+HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
 
-HRESULT MARSHAL_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub);
-void    MARSHAL_Invalidate_Stub_From_MID(wine_marshal_id *mid);
-HRESULT MARSHAL_Disconnect_Proxies();
+/* Thread-safety Annotation Legend:
+ *
+ * RO   - The value is read only. It never changes after creation, so no
+ *        locking is required.
+ * LOCK - The value is written to only using Interlocked* functions.
+ * CS   - The value is read or written to with a critical section held.
+ *        The identifier following "CS" is the specific critical section that
+ *        must be used.
+ */
 
-HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
+/* an interface stub */
+struct ifstub   
+{
+    struct list       entry;      /* entry in stub_manager->ifstubs list (CS stub_manager->lock) */
+    IRpcStubBuffer   *stubbuffer; /* RO */
+    IID               iid;        /* RO */
+    IPID              ipid;       /* RO */
+    IUnknown         *iface;      /* RO */
+    BOOL              table;      /* CS stub_manager->lock */
+};
 
-void STUBMGR_Start();
 
+/* stub managers hold refs on the object and each interface stub */
+struct stub_manager
+{
+    struct list       entry;      /* entry in apartment stubmgr list (CS apt->cs) */
+    struct list       ifstubs;    /* list of active ifstubs for the object (CS lock) */
+    CRITICAL_SECTION  lock;
+    APARTMENT        *apt;        /* owning apt (RO) */
+
+    ULONG             extrefs;    /* number of 'external' references (LOCK) */
+    ULONG             refs;       /* internal reference count (CS apt->cs) */
+    OID               oid;        /* apartment-scoped unique identifier (RO) */
+    IUnknown         *object;     /* the object we are managing the stub for (RO) */
+    ULONG             next_ipid;  /* currently unused (LOCK) */
[truncated at 1000 lines; 7593 more skipped]