Module: wine Branch: master Commit: 71aeb64c7350fc38b08ba797690a42ff618ce149 URL: https://source.winehq.org/git/wine.git/?a=commit;h=71aeb64c7350fc38b08ba7976...
Author: Paul Gofman pgofman@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@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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); }