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>
This commit is contained in:
Paul Gofman 2021-07-26 11:28:13 +01:00 committed by Alexandre Julliard
parent 949a48498c
commit 71aeb64c73
5 changed files with 101 additions and 60 deletions

View File

@ -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)
{
ole_clipbrd* clipbrd;
HGLOBAL h;
TRACE("()\n");
register_clipboard_formats();
if ( !theOleClipboard )
clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
if (!clipbrd)
{
ole_clipbrd* clipbrd;
HGLOBAL h;
TRACE("()\n");
clipbrd = HeapAlloc( GetProcessHeap(), 0, sizeof(*clipbrd) );
if (!clipbrd) return;
clipbrd->latest_snapshot = NULL;
clipbrd->window = NULL;
clipbrd->src_data = NULL;
clipbrd->cached_enum = NULL;
h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
if(!h)
{
HeapFree(GetProcessHeap(), 0, clipbrd);
return;
}
if(FAILED(CreateStreamOnHGlobal(h, TRUE, &clipbrd->marshal_data)))
{
GlobalFree(h);
HeapFree(GetProcessHeap(), 0, clipbrd);
return;
}
theOleClipboard = clipbrd;
ERR("No memory.\n");
return FALSE;
}
clipbrd->latest_snapshot = NULL;
clipbrd->window = NULL;
clipbrd->src_data = NULL;
clipbrd->cached_enum = NULL;
h = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
if(!h)
{
ERR("No memory.\n");
HeapFree(GetProcessHeap(), 0, clipbrd);
return FALSE;
}
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;
/*

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);
}