Paul Gofman : ole32: Do not link OLE clipboard object lifecycle to OLE initialization state.
Alexandre Julliard
julliard at winehq.org
Mon Jul 26 15:30:28 CDT 2021
Module: wine
Branch: master
Commit: 71aeb64c7350fc38b08ba797690a42ff618ce149
URL: https://source.winehq.org/git/wine.git/?a=commit;h=71aeb64c7350fc38b08ba797690a42ff618ce149
Author: Paul Gofman <pgofman at codeweavers.com>
Date: Mon Jul 26 11:28:13 2021 +0100
ole32: Do not link OLE clipboard object lifecycle to OLE initialization state.
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>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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);
}
More information about the wine-cvs
mailing list