Module: wine Branch: master Commit: 8fc1a4cd863aad02761f015bf5a5f67f94934aac URL: http://source.winehq.org/git/wine.git/?a=commit;h=8fc1a4cd863aad02761f015bf5...
Author: Huw Davies huw@codeweavers.com Date: Tue May 23 09:33:02 2017 +0100
ole32: OleUninitialize() does not release the reference to the clipboard's source dataobject.
Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ole32/clipboard.c | 64 ++++++++++++++++++++++++-------------------- dlls/ole32/tests/clipboard.c | 14 +++++++++- 2 files changed, 48 insertions(+), 30 deletions(-)
diff --git a/dlls/ole32/clipboard.c b/dlls/ole32/clipboard.c index b3c7665..919d9e3 100644 --- a/dlls/ole32/clipboard.c +++ b/dlls/ole32/clipboard.c @@ -1786,35 +1786,6 @@ void OLEClipbrd_Initialize(void) } }
-/*********************************************************************** - * OLEClipbrd_UnInitialize() - * Un-Initializes the OLE clipboard - */ -void OLEClipbrd_UnInitialize(void) -{ - ole_clipbrd *clipbrd = theOleClipboard; - - TRACE("()\n"); - - if ( clipbrd ) - { - static const WCHAR ole32W[] = {'o','l','e','3','2',0}; - HINSTANCE hinst = GetModuleHandleW(ole32W); - - if ( clipbrd->window ) - { - DestroyWindow(clipbrd->window); - UnregisterClassW( clipbrd_wndclass, hinst ); - } - - IStream_Release(clipbrd->marshal_data); - if (clipbrd->src_data) IDataObject_Release(clipbrd->src_data); - HeapFree(GetProcessHeap(), 0, clipbrd->cached_enum); - HeapFree(GetProcessHeap(), 0, clipbrd); - theOleClipboard = NULL; - } -} - /********************************************************************* * set_clipboard_formats * @@ -2015,6 +1986,41 @@ static HRESULT set_src_dataobject(ole_clipbrd *clipbrd, IDataObject *data) }
/*********************************************************************** + * OLEClipbrd_UnInitialize() + * Un-Initializes the OLE clipboard + */ +void OLEClipbrd_UnInitialize(void) +{ + ole_clipbrd *clipbrd = theOleClipboard; + + TRACE("()\n"); + + if ( clipbrd ) + { + static const WCHAR ole32W[] = {'o','l','e','3','2',0}; + HINSTANCE hinst = GetModuleHandleW(ole32W); + + /* OleUninitialize() does not release the reference to the dataobject, so + take an additional reference here. This reference is then leaked. */ + if (clipbrd->src_data) + { + IDataObject_AddRef(clipbrd->src_data); + set_src_dataobject(clipbrd, NULL); + } + + if ( clipbrd->window ) + { + DestroyWindow(clipbrd->window); + UnregisterClassW( clipbrd_wndclass, hinst ); + } + + IStream_Release(clipbrd->marshal_data); + HeapFree(GetProcessHeap(), 0, clipbrd); + theOleClipboard = NULL; + } +} + +/*********************************************************************** * clipbrd_wndproc */ static LRESULT CALLBACK clipbrd_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) diff --git a/dlls/ole32/tests/clipboard.c b/dlls/ole32/tests/clipboard.c index 1c8923e..4890782 100644 --- a/dlls/ole32/tests/clipboard.c +++ b/dlls/ole32/tests/clipboard.c @@ -1187,9 +1187,21 @@ static void test_consumer_refs(void) IDataObject_Release(get1);
IDataObject_Release(src2); - IDataObject_Release(src); + + /* Show that OleUninitialize() doesn't release the + dataobject's ref, and thus the object is leaked. */ + old_refs = count_refs(src); + ok(old_refs == 1, "%d\n", old_refs); + + OleSetClipboard(src); + refs = count_refs(src); + ok(refs > old_refs, "%d %d\n", refs, old_refs);
OleUninitialize(); + refs = count_refs(src); + ok(refs == 2, "%d\n", refs); + + IDataObject_Release(src); }
static void test_flushed_getdata(void)