msctf: Clear the corresponding DocumentMgr pointers for Associated Focus Windows on destruction.

Fixes a regression introduced by d541087079.

AssociateFocus does not grab ownership of the Document Manager, but it does
return it in the "prev" output parameter with an increased refcount. So,
if the docmgr gets destroyed and AssociateFocus is called again, its "prev"
parameter will refer to freed memory. Windows sets it to NULL in such case.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48469
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2020-01-15 18:02:03 +02:00 committed by Alexandre Julliard
parent 4e2da207d7
commit 6393edb714
2 changed files with 25 additions and 4 deletions

View File

@ -2287,6 +2287,7 @@ static void test_AssociateFocus(void)
ITfDocumentMgr *dm1, *dm2, *olddm, *dmcheck, *dmorig; ITfDocumentMgr *dm1, *dm2, *olddm, *dmcheck, *dmorig;
HWND wnd1, wnd2, wnd3; HWND wnd1, wnd2, wnd3;
HRESULT hr; HRESULT hr;
ULONG ref;
ITfThreadMgr_GetFocus(g_tm, &dmorig); ITfThreadMgr_GetFocus(g_tm, &dmorig);
test_CurrentFocus = NULL; test_CurrentFocus = NULL;
@ -2428,10 +2429,20 @@ static void test_AssociateFocus(void)
processPendingMessages(); processPendingMessages();
SetFocus(wnd1); SetFocus(wnd1);
processPendingMessages(); processPendingMessages();
test_OnSetFocus = SINK_UNEXPECTED;
hr = ITfThreadMgr_AssociateFocus(g_tm,wnd2,dm2,&olddm);
ok(SUCCEEDED(hr),"AssociateFocus failed\n");
/* Vista doesn't return NULL */
if (olddm) ITfDocumentMgr_Release(olddm);
ref = ITfDocumentMgr_Release(dm2);
ok(ref == 0, "incorrect DocumentMgr ref %d\n", ref);
hr = ITfThreadMgr_AssociateFocus(g_tm,wnd2,NULL,&olddm);
ok(SUCCEEDED(hr),"AssociateFocus failed\n");
ok(olddm == NULL, "incorrect old DocumentMgr returned\n");
ITfDocumentMgr_Release(dm1); ITfDocumentMgr_Release(dm1);
ITfDocumentMgr_Release(dm2);
test_CurrentFocus = dmorig; test_CurrentFocus = dmorig;
test_PrevFocus = FOCUS_IGNORE; test_PrevFocus = FOCUS_IGNORE;

View File

@ -1530,6 +1530,8 @@ void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr
{ {
ThreadMgr *This = impl_from_ITfThreadMgrEx((ITfThreadMgrEx *)iface); ThreadMgr *This = impl_from_ITfThreadMgrEx((ITfThreadMgrEx *)iface);
struct list *cursor; struct list *cursor;
BOOL found = FALSE;
LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs) LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
{ {
DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry); DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
@ -1537,8 +1539,16 @@ void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr
{ {
list_remove(cursor); list_remove(cursor);
HeapFree(GetProcessHeap(),0,mgrentry); HeapFree(GetProcessHeap(),0,mgrentry);
return; found = TRUE;
break;
} }
} }
FIXME("ITfDocumentMgr %p not found in this thread\n",mgr); if (!found) FIXME("ITfDocumentMgr %p not found in this thread\n",mgr);
LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
{
AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
if (wnd->docmgr == mgr)
wnd->docmgr = NULL;
}
} }