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

Huw Davies huw at codeweavers.com
Mon Jul 26 05:28:13 CDT 2021


From: Paul Gofman <pgofman at codeweavers.com>

Fixes text paste in Origin launcher and overlay.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/ole32/clipboard.c       | 111 +++++++++++++++++++++--------------
 dlls/ole32/compobj.c         |   1 +
 dlls/ole32/compobj_private.h |   2 +
 dlls/ole32/ole2.c            |  12 +---
 dlls/ole32/tests/clipboard.c |  29 ++++++++-
 5 files changed, 98 insertions(+), 57 deletions(-)

diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c
index a1e68c64845..1cad47a6a47 100644
--- a/dlls/ole32/clipboard.c
+++ b/dlls/ole32/clipboard.c
@@ -170,7 +170,7 @@ typedef struct PresentationDataHeader
 } PresentationDataHeader;
 
 /*
- * The one and only ole_clipbrd object which is created by OLEClipbrd_Initialize()
+ * The one and only ole_clipbrd object which is created by clipbrd_create()
  */
 static ole_clipbrd* theOleClipboard;
 
@@ -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 clipbrd_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, clipbrd_create, NULL, NULL))
+    {
+        *clipbrd = NULL;
         return CO_E_NOTINITIALIZED;
-    *clipbrd = theOleClipboard;
+    }
 
+    *clipbrd = theOleClipboard;
     return S_OK;
 }
 
@@ -2000,10 +1999,10 @@ static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data)
 }
 
 /***********************************************************************
- * OLEClipbrd_UnInitialize()
+ * clipbrd_uninitialize()
  * Un-Initializes the OLE clipboard
  */
-void OLEClipbrd_UnInitialize(void)
+void clipbrd_uninitialize(void)
 {
     ole_clipbrd *clipbrd = theOleClipboard;
 
@@ -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;
     }
 }
 
+/***********************************************************************
+ * clipbrd_destroy()
+ * Destroy the OLE clipboard
+ */
+void clipbrd_destroy(void)
+{
+    ole_clipbrd *clipbrd = theOleClipboard;
+
+    if (!clipbrd) return;
+
+    clipbrd_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..815fdcb11d0 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:
+        clipbrd_destroy();
         if (reserved) break;
         release_std_git();
         break;
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index 3c0e338127c..34f5a8ec485 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 clipbrd_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..3f8f9b3232b 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 prototype of the OLE Clipboard uninitialization method (in clipboard.c)
  */
-extern void OLEClipbrd_UnInitialize(void);
-extern void OLEClipbrd_Initialize(void);
+extern void clipbrd_uninitialize(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
      */
@@ -241,7 +235,7 @@ void WINAPI DECLSPEC_HOTPATCH OleUninitialize(void)
     /*
      * OLE Clipboard
      */
-    OLEClipbrd_UnInitialize();
+    clipbrd_uninitialize();
 
     /*
      * OLE shared menu
diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c
index fd8f287680b..97575371edc 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)
@@ -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.25.1




More information about the wine-devel mailing list