[PATCH 2/2] ole32: Do not link OLE clipboard object lifecycle to OLE initialization state.

Paul Gofman pgofman at codeweavers.com
Fri Jul 23 12:18:43 CDT 2021


Fixes text paste in Origin launcher and overlay.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ole32/clipboard.c       | 105 +++++++++++++++++++++--------------
 dlls/ole32/compobj.c         |   1 +
 dlls/ole32/compobj_private.h |   2 +
 dlls/ole32/ole2.c            |   8 +--
 dlls/ole32/tests/clipboard.c |  31 +++++++++--
 5 files changed, 94 insertions(+), 53 deletions(-)

diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index a1e68c64845..1735b457d25 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.c
@@ -202,9 +202,6 @@ UINT ole_private_data_clipboard_format = 0;
 
 static UINT wine_marshal_clipboard_format;
 
-/*********************************************************
- *               register_clipboard_formats
- */
 static void register_clipboard_formats(void)
 {
     ownerlink_clipboard_format = RegisterClipboardFormatW(L"OwnerLink");
@@ -222,56 +219,58 @@ static void register_clipboard_formats(void)
     wine_marshal_clipboard_format = RegisterClipboardFormatW(L"Wine Marshalled DataObject");
 }
 
-/***********************************************************************
- * OLEClipbrd_Initialize()
- * Initializes the OLE clipboard.
- */
-void OLEClipbrd_Initialize(void)
+static BOOL WINAPI oleclipboard_create(INIT_ONCE *init_once, void *parameter, void **context)
 {
-    register_clipboard_formats();
-
-    if ( !theOleClipboard )
-    {
-        ole_clipbrd* clipbrd;
-        HGLOBAL h;
+    ole_clipbrd* clipbrd;
+    HGLOBAL h;
 
-        TRACE("()\n");
+    TRACE("()\n");
 
-        clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
-        if (!clipbrd) return;
+    register_clipboard_formats();
 
-        clipbrd->latest_snapshot = NULL;
-        clipbrd->window = NULL;
-        clipbrd->src_data = NULL;
-        clipbrd->cached_enum = NULL;
+    clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
+    if (!clipbrd)
+    {
+        ERR("No memory.\n");
+        return FALSE;
+    }
 
-        h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
-        if(!h)
-        {
-            HeapFree(GetProcessHeap(), 0, clipbrd);
-            return;
-        }
+    clipbrd->latest_snapshot = NULL;
+    clipbrd->window = NULL;
+    clipbrd->src_data = NULL;
+    clipbrd->cached_enum = NULL;
 
-        if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
-        {
-            GlobalFree(h);
-            HeapFree(GetProcessHeap(), 0, clipbrd);
-            return;
-        }
+    h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
+    if(!h)
+    {
+        ERR("No memory.\n");
+        HeapFree(GetProcessHeap(), 0, clipbrd);
+        return FALSE;
+    }
 
-        theOleClipboard = clipbrd;
+    if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
+    {
+        ERR("CreateStreamOnHGlobal failed.\n");
+        GlobalFree(h);
+        HeapFree(GetProcessHeap(), 0, clipbrd);
+        return FALSE;
     }
+
+    theOleClipboard = clipbrd;
+    return TRUE;
 }
 
 static inline HRESULT get_ole_clipbrd(ole_clipbrd **clipbrd)
 {
-    struct oletls *info = COM_CurrentInfo();
-    *clipbrd = NULL;
+    static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
 
-    if(!info->ole_inits)
+    if (!InitOnceExecuteOnce(&init_once, oleclipboard_create, NULL, NULL))
+    {
+        *clipbrd = NULL;
         return CO_E_NOTINITIALIZED;
-    *clipbrd = theOleClipboard;
+    }
 
+    *clipbrd = theOleClipboard;
     return S_OK;
 }
 
@@ -2023,14 +2022,28 @@ void OLEClipbrd_UnInitialize(void)
         {
             DestroyWindow(clipbrd->window);
             UnregisterClassW( clipbrd_wndclass, GetModuleHandleW(L"ole32") );
+            clipbrd->window = NULL;
         }
-
-        IStream_Release(clipbrd->marshal_data);
-        HeapFree(GetProcessHeap(), 0, clipbrd);
-        theOleClipboard = NULL;
     }
 }
 
+/***********************************************************************
+ * OLEClipbrd_Destroy()
+ * Destroy the OLE clipboard
+ */
+void OLEClipbrd_Destroy(void)
+{
+    ole_clipbrd *clipbrd = theOleClipboard;
+
+    if (!clipbrd) return;
+
+    OLEClipbrd_UnInitialize();
+
+    IStream_Release(clipbrd->marshal_data);
+    HeapFree(GetProcessHeap(), 0, clipbrd);
+    theOleClipboard = NULL;
+}
+
 /***********************************************************************
  *                   clipbrd_wndproc
  */
@@ -2164,12 +2177,16 @@ static HRESULT set_dataobject_format(HWND hwnd)
 
 HRESULT WINAPI OleSetClipboard(IDataObject* data)
 {
+  struct oletls *info = COM_CurrentInfo();
   HRESULT hr;
   ole_clipbrd *clipbrd;
   HWND wnd;
 
   TRACE("(%p)\n", data);
 
+  if(!info->ole_inits)
+    return CO_E_NOTINITIALIZED;
+
   if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
 
   if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
@@ -2258,6 +2275,7 @@ HRESULT WINAPI OleGetClipboard(IDataObject **obj)
  */
 HRESULT WINAPI OleFlushClipboard(void)
 {
+  struct oletls *info = COM_CurrentInfo();
   HRESULT hr;
   ole_clipbrd *clipbrd;
   HWND wnd;
@@ -2266,6 +2284,9 @@ HRESULT WINAPI OleFlushClipboard(void)
 
   if(FAILED(hr = get_ole_clipbrd(&clipbrd))) return hr;
 
+  if(!info->ole_inits)
+    return E_FAIL;
+
   if(FAILED(hr = get_clipbrd_window(clipbrd, &wnd))) return hr;
 
   /*
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index c40d8d03b2d..8538a64cae5 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -937,6 +937,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID reserved)
 	break;
 
     case DLL_PROCESS_DETACH:
+        OLEClipbrd_Destroy();
         if (reserved) break;
         release_std_git();
         break;
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index 3c0e338127c..992d67a69fa 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -132,6 +132,8 @@ extern UINT object_descriptor_clipboard_format DECLSPEC_HIDDEN;
 extern UINT link_source_descriptor_clipboard_format DECLSPEC_HIDDEN;
 extern UINT ole_private_data_clipboard_format DECLSPEC_HIDDEN;
 
+void OLEClipbrd_Destroy(void) DECLSPEC_HIDDEN;
+
 extern LSTATUS create_classes_key(HKEY, const WCHAR *, REGSAM, HKEY *) DECLSPEC_HIDDEN;
 extern LSTATUS open_classes_key(HKEY, const WCHAR *, REGSAM, HKEY *) DECLSPEC_HIDDEN;
 
diff --git a/dlls/ole32/ole2.c b/dlls/ole32/ole2.c
index f2224ad5b6a..7acbc7b64b8 100644
--- a/dlls/ole32/ole2.c
+++ b/dlls/ole32/ole2.c
@@ -133,10 +133,9 @@ static LRESULT CALLBACK OLEMenu_CallWndProc(INT code, WPARAM wParam, LPARAM lPar
 static LRESULT CALLBACK OLEMenu_GetMsgProc(INT code, WPARAM wParam, LPARAM lParam);
 
 /******************************************************************************
- * These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)
+ * This is a prototypes of the OLE Clipboard uninitialization method (in clipboard.c)
  */
 extern void OLEClipbrd_UnInitialize(void);
-extern void OLEClipbrd_Initialize(void);
 
 /******************************************************************************
  * These are the prototypes of the utility methods used for OLE Drag n Drop
@@ -197,11 +196,6 @@ HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
      */
     TRACE("() - Initializing the OLE libraries\n");
 
-    /*
-     * OLE Clipboard
-     */
-    OLEClipbrd_Initialize();
-
     /*
      * Drag and Drop
      */
diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c
index fd8f287680b..501a48e8555 100644
--- a/dlls/ole32/tests/clipboard.c
+++ b/dlls/ole32/tests/clipboard.c
@@ -503,13 +503,27 @@ static HRESULT DataObjectImpl_CreateComplex(LPDATAOBJECT *lplpdataobj)
 
 static void test_get_clipboard_uninitialized(void)
 {
-    HRESULT hr;
+    REFCLSID rclsid = &CLSID_InternetZoneManager;
     IDataObject *pDObj;
+    IUnknown *pUnk;
+    HRESULT hr;
 
     pDObj = (IDataObject *)0xdeadbeef;
     hr = OleGetClipboard(&pDObj);
-    todo_wine ok(hr == S_OK, "OleGetClipboard() got 0x%08x instead of 0x%08x\n", hr, S_OK);
-    if (pDObj && pDObj != (IDataObject *)0xdeadbeef) IDataObject_Release(pDObj);
+    ok(hr == S_OK, "OleGetClipboard() got 0x%08x instead of 0x%08x\n", hr, S_OK);
+    ok(!!pDObj && pDObj != (IDataObject *)0xdeadbeef, "Got unexpected pDObj %p.\n", pDObj);
+
+    /* COM is still not initialized. */
+    hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
+    ok(hr == CO_E_NOTINITIALIZED, "Got unexpected hr %#x.\n", hr);
+
+    hr = OleFlushClipboard();
+    ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+
+    hr = OleIsCurrentClipboard(pDObj);
+    ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
+
+    IDataObject_Release(pDObj);
 }
 
 static void test_get_clipboard(void)
@@ -1275,7 +1289,7 @@ static void test_consumer_refs(void)
     IDataObject_Release(src2);
 
     /* Show that OleUninitialize() doesn't release the
-       dataobject's ref, and thus the object is leaked. */
+       dataobject's ref and the object is leaked. */
     old_refs = count_refs(src);
     ok(old_refs == 1, "%d\n", old_refs);
 
@@ -1288,6 +1302,15 @@ static void test_consumer_refs(void)
     refs = count_refs(src);
     ok(refs == 2, "%d\n", refs);
 
+    OleInitialize(NULL);
+    hr = OleSetClipboard(NULL);
+    ok(hr == S_OK, "Failed to clear clipboard, hr %#x.\n", hr);
+
+    OleUninitialize();
+
+    refs = count_refs(src);
+    ok(refs == 2, "%d\n", refs);
+
     IDataObject_Release(src);
 }
 
-- 
2.31.1




More information about the wine-devel mailing list