[PATCH 2/6] combase: Move initialisation functions.

Nikolay Sivov nsivov at codeweavers.com
Thu Aug 27 03:37:45 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/combase/combase.c         | 136 ++++++++++++++++++++++++-
 dlls/combase/combase.spec      |   5 +-
 dlls/combase/combase_private.h |   3 +
 dlls/ole32/compobj.c           | 179 ---------------------------------
 dlls/ole32/ole32.spec          |   4 +-
 5 files changed, 142 insertions(+), 185 deletions(-)

diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c
index 4ce43717fb4..cddc9e23067 100644
--- a/dlls/combase/combase.c
+++ b/dlls/combase/combase.c
@@ -40,6 +40,13 @@ HINSTANCE hProxyDll;
 
 #define CHARS_IN_GUID 39
 
+extern void WINAPI DestroyRunningObjectTable(void);
+
+/*
+ * Number of times CoInitialize is called. It is decreased every time CoUninitialize is called. When it hits 0, the COM libraries are freed
+ */
+static LONG com_lockcount;
+
 struct comclassredirect_data
 {
     ULONG size;
@@ -1757,7 +1764,7 @@ HRESULT WINAPI CoRegisterMessageFilter(IMessageFilter *filter, IMessageFilter **
     return S_OK;
 }
 
-void WINAPI InternalRevokeAllPSClsids(void)
+static void com_revoke_all_ps_clsids(void)
 {
     struct registered_ps *cur, *cur2;
 
@@ -2267,6 +2274,133 @@ void WINAPI DECLSPEC_HOTPATCH CoFreeUnusedLibrariesEx(DWORD unload_delay, DWORD
     apartment_freeunusedlibraries(apt, unload_delay);
 }
 
+/*
+ * When locked, don't modify list (unless we add a new head), so that it's
+ * safe to iterate it. Freeing of list entries is delayed and done on unlock.
+ */
+static inline void lock_init_spies(struct tlsdata *tlsdata)
+{
+    tlsdata->spies_lock++;
+}
+
+static void unlock_init_spies(struct tlsdata *tlsdata)
+{
+    struct init_spy *spy, *next;
+
+    if (--tlsdata->spies_lock) return;
+
+    LIST_FOR_EACH_ENTRY_SAFE(spy, next, &tlsdata->spies, struct init_spy, entry)
+    {
+        if (spy->spy) continue;
+        list_remove(&spy->entry);
+        heap_free(spy);
+    }
+}
+
+/******************************************************************************
+ *                    CoInitializeEx    (combase.@)
+ */
+HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(void *reserved, DWORD model)
+{
+    struct tlsdata *tlsdata;
+    struct init_spy *cursor;
+    HRESULT hr;
+
+    TRACE("%p, %#x\n", reserved, model);
+
+    if (reserved)
+        WARN("Unexpected reserved argument %p\n", reserved);
+
+    if (FAILED(hr = com_get_tlsdata(&tlsdata)))
+        return hr;
+
+    if (InterlockedExchangeAdd(&com_lockcount, 1) == 0)
+        TRACE("Initializing the COM libraries\n");
+
+    lock_init_spies(tlsdata);
+    LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry)
+    {
+        if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, model, tlsdata->inits);
+    }
+    unlock_init_spies(tlsdata);
+
+    hr = enter_apartment(tlsdata, model);
+
+    lock_init_spies(tlsdata);
+    LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry)
+    {
+        if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, model, tlsdata->inits);
+    }
+    unlock_init_spies(tlsdata);
+
+    return hr;
+}
+
+/***********************************************************************
+ *           CoUninitialize    (combase.@)
+ */
+void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
+{
+    struct tlsdata *tlsdata;
+    struct init_spy *cursor, *next;
+    LONG lockcount;
+
+    TRACE("\n");
+
+    if (FAILED(com_get_tlsdata(&tlsdata)))
+        return;
+
+    lock_init_spies(tlsdata);
+    LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &tlsdata->spies, struct init_spy, entry)
+    {
+        if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, tlsdata->inits);
+    }
+    unlock_init_spies(tlsdata);
+
+    /* sanity check */
+    if (!tlsdata->inits)
+    {
+        ERR("Mismatched CoUninitialize\n");
+
+        lock_init_spies(tlsdata);
+        LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &tlsdata->spies, struct init_spy, entry)
+        {
+            if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, tlsdata->inits);
+        }
+        unlock_init_spies(tlsdata);
+
+        return;
+    }
+
+    leave_apartment(tlsdata);
+
+    /*
+     * Decrease the reference count.
+     * If we are back to 0 locks on the COM library, make sure we free
+     * all the associated data structures.
+     */
+    lockcount = InterlockedExchangeAdd(&com_lockcount, -1);
+    if (lockcount == 1)
+    {
+        TRACE("Releasing the COM libraries\n");
+
+        com_revoke_all_ps_clsids();
+        DestroyRunningObjectTable();
+    }
+    else if (lockcount < 1)
+    {
+        ERR("Unbalanced lock count %d\n", lockcount);
+        InterlockedExchangeAdd(&com_lockcount, 1);
+    }
+
+    lock_init_spies(tlsdata);
+    LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry)
+    {
+        if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, tlsdata->inits);
+    }
+    unlock_init_spies(tlsdata);
+}
+
 /***********************************************************************
  *            DllMain     (combase.@)
  */
diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec
index 00aea556d94..01377c8045e 100644
--- a/dlls/combase/combase.spec
+++ b/dlls/combase/combase.spec
@@ -123,7 +123,7 @@
 @ stdcall CoGetTreatAsClass(ptr ptr)
 @ stdcall CoImpersonateClient()
 @ stdcall CoIncrementMTAUsage(ptr) ole32.CoIncrementMTAUsage
-@ stdcall CoInitializeEx(ptr long) ole32.CoInitializeEx
+@ stdcall CoInitializeEx(ptr long)
 @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr)
 @ stdcall CoInitializeWOW(long long) ole32.CoInitializeWOW
 @ stub CoInvalidateRemoteMachineBindings
@@ -163,7 +163,7 @@
 @ stdcall CoTaskMemFree(ptr)
 @ stdcall CoTaskMemRealloc(ptr long)
 @ stub CoTestCancel
-@ stdcall CoUninitialize() ole32.CoUninitialize
+@ stdcall CoUninitialize()
 @ stub CoUnloadingWOW
 @ stdcall CoUnmarshalHresult(ptr ptr)
 @ stdcall CoUnmarshalInterface(ptr ptr ptr) ole32.CoUnmarshalInterface
@@ -268,7 +268,6 @@
 @ stub InternalNotifyDDStartOrStop
 @ stub InternalOleModalLoopBlockFn
 @ stub InternalRegisterWindowPropInterface
-@ stdcall InternalRevokeAllPSClsids()
 @ stub InternalReleaseMarshalObjRef
 @ stub InternalSTAInvoke
 @ stub InternalServerExceptionFilter
diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h
index 7fe548af593..122522baad5 100644
--- a/dlls/combase/combase_private.h
+++ b/dlls/combase/combase_private.h
@@ -131,6 +131,9 @@ struct stub_manager
     BOOL              disconnected; /* CoDisconnectObject has been called (CS lock) */
 };
 
+HRESULT WINAPI enter_apartment(struct tlsdata *data, DWORD model);
+void WINAPI leave_apartment(struct tlsdata *data);
+
 /* Stub Manager */
 
 ULONG stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN;
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 88482392d5e..5afacf3ee3f 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -142,12 +142,6 @@ struct class_reg_data
     } u;
 };
 
-/*
- * This lock count counts the number of times CoInitialize is called. It is
- * decreased every time CoUninitialize is called. When it hits 0, the COM
- * libraries are freed
- */
-static LONG s_COMLockCount = 0;
 /* Reference count used by CoAddRefServerProcess/CoReleaseServerProcess */
 static LONG s_COMServerProcessReferences = 0;
 
@@ -182,8 +176,6 @@ static CRITICAL_SECTION_DEBUG class_cs_debug =
 };
 static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0, 0 };
 
-extern void WINAPI InternalRevokeAllPSClsids(void);
-
 static inline enum comclass_miscfields dvaspect_to_miscfields(DWORD aspect)
 {
     switch (aspect)
@@ -661,29 +653,6 @@ DWORD WINAPI CoBuildVersion(void)
     return (rmm<<16)+rup;
 }
 
-/*
- * When locked, don't modify list (unless we add a new head), so that it's
- * safe to iterate it. Freeing of list entries is delayed and done on unlock.
- */
-static inline void lock_init_spies(struct oletls *info)
-{
-    info->spies_lock++;
-}
-
-static void unlock_init_spies(struct oletls *info)
-{
-    struct init_spy *spy, *next;
-
-    if (--info->spies_lock) return;
-
-    LIST_FOR_EACH_ENTRY_SAFE(spy, next, &info->spies, struct init_spy, entry)
-    {
-        if (spy->spy) continue;
-        list_remove(&spy->entry);
-        heap_free(spy);
-    }
-}
-
 /******************************************************************************
  *		CoInitialize	[OLE32.@]
  *
@@ -708,154 +677,6 @@ HRESULT WINAPI CoInitialize(LPVOID lpReserved)
   return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
 }
 
-/******************************************************************************
- *		CoInitializeEx	[OLE32.@]
- *
- * Initializes the COM libraries.
- *
- * PARAMS
- *  lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
- *  dwCoInit   [I] One or more flags from the COINIT enumeration. See notes.
- *
- * RETURNS
- *  S_OK               if successful,
- *  S_FALSE            if this function was called already.
- *  RPC_E_CHANGED_MODE if a previous call to CoInitializeEx specified another
- *                     threading model.
- *
- * NOTES
- *
- * The behavior used to set the IMalloc used for memory management is
- * obsolete.
- * The dwCoInit parameter must specify one of the following apartment
- * threading models:
- *| COINIT_APARTMENTTHREADED - A single-threaded apartment (STA).
- *| COINIT_MULTITHREADED - A multi-threaded apartment (MTA).
- * The parameter may also specify zero or more of the following flags:
- *| COINIT_DISABLE_OLE1DDE - Don't use DDE for OLE1 support.
- *| COINIT_SPEED_OVER_MEMORY - Trade memory for speed.
- *
- * SEE ALSO
- *   CoUninitialize
- */
-HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
-{
-  struct oletls *info = COM_CurrentInfo();
-  struct init_spy *cursor;
-  HRESULT hr;
-
-  TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit);
-
-  if (lpReserved!=NULL)
-  {
-    ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved);
-  }
-
-  /*
-   * Check the lock count. If this is the first time going through the initialize
-   * process, we have to initialize the libraries.
-   *
-   * And crank-up that lock count.
-   */
-  if (InterlockedExchangeAdd(&s_COMLockCount,1)==0)
-    TRACE("() - Initializing the COM libraries\n");
-
-  lock_init_spies(info);
-  LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
-  {
-      if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, dwCoInit, info->inits);
-  }
-  unlock_init_spies(info);
-
-  hr = enter_apartment( info, dwCoInit );
-
-  lock_init_spies(info);
-  LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
-  {
-      if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, dwCoInit, info->inits);
-  }
-  unlock_init_spies(info);
-
-  return hr;
-}
-
-/***********************************************************************
- *           CoUninitialize   [OLE32.@]
- *
- * This method will decrement the refcount on the current apartment, freeing
- * the resources associated with it if it is the last thread in the apartment.
- * If the last apartment is freed, the function will additionally release
- * any COM resources associated with the process.
- *
- * PARAMS
- *
- * RETURNS
- *  Nothing.
- *
- * SEE ALSO
- *   CoInitializeEx
- */
-void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
-{
-  struct oletls * info = COM_CurrentInfo();
-  struct init_spy *cursor, *next;
-  LONG lCOMRefCnt;
-
-  TRACE("()\n");
-
-  /* will only happen on OOM */
-  if (!info) return;
-
-  lock_init_spies(info);
-  LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &info->spies, struct init_spy, entry)
-  {
-      if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, info->inits);
-  }
-  unlock_init_spies(info);
-
-  /* sanity check */
-  if (!info->inits)
-  {
-      ERR("Mismatched CoUninitialize\n");
-
-      lock_init_spies(info);
-      LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &info->spies, struct init_spy, entry)
-      {
-          if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits);
-      }
-      unlock_init_spies(info);
-
-      return;
-  }
-
-  leave_apartment( info );
-
-  /*
-   * Decrease the reference count.
-   * If we are back to 0 locks on the COM library, make sure we free
-   * all the associated data structures.
-   */
-  lCOMRefCnt = InterlockedExchangeAdd(&s_COMLockCount,-1);
-  if (lCOMRefCnt==1)
-  {
-    TRACE("() - Releasing the COM libraries\n");
-
-    InternalRevokeAllPSClsids();
-    DestroyRunningObjectTable();
-  }
-  else if (lCOMRefCnt<1) {
-    ERR( "CoUninitialize() - not CoInitialized.\n" );
-    InterlockedExchangeAdd(&s_COMLockCount,1); /* restore the lock count. */
-  }
-
-  lock_init_spies(info);
-  LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
-  {
-      if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits);
-  }
-  unlock_init_spies(info);
-}
-
 /******************************************************************************
  *		CoDisconnectObject	[OLE32.@]
  *
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec
index c102bce1776..e80cafd3663 100644
--- a/dlls/ole32/ole32.spec
+++ b/dlls/ole32/ole32.spec
@@ -50,7 +50,7 @@
 @ stdcall CoImpersonateClient() combase.CoImpersonateClient
 @ stdcall CoIncrementMTAUsage(ptr)
 @ stdcall CoInitialize(ptr)
-@ stdcall CoInitializeEx(ptr long)
+@ stdcall CoInitializeEx(ptr long) combase.CoInitializeEx
 @ stdcall CoInitializeSecurity(ptr long ptr ptr long long ptr long ptr) combase.CoInitializeSecurity
 @ stdcall CoInitializeWOW(long long)
 @ stdcall CoIsHandlerConnected(ptr)
@@ -87,7 +87,7 @@
 @ stdcall CoTaskMemFree(ptr) combase.CoTaskMemFree
 @ stdcall CoTaskMemRealloc(ptr long) combase.CoTaskMemRealloc
 @ stdcall CoTreatAsClass(ptr ptr)
-@ stdcall CoUninitialize()
+@ stdcall CoUninitialize() combase.CoUninitialize
 @ stub CoUnloadingWOW
 @ stdcall CoUnmarshalHresult(ptr ptr) combase.CoUnmarshalHresult
 @ stdcall CoUnmarshalInterface(ptr ptr ptr)
-- 
2.28.0




More information about the wine-devel mailing list