diff --git a/dlls/msctf/documentmgr.c b/dlls/msctf/documentmgr.c index 66f0f508b51..0a25b3d3b67 100644 --- a/dlls/msctf/documentmgr.c +++ b/dlls/msctf/documentmgr.c @@ -69,7 +69,12 @@ static inline DocumentMgr *impl_from_ITfSourceVtbl(ITfSource *iface) static void DocumentMgr_Destructor(DocumentMgr *This) { + ITfThreadMgr *tm; TRACE("destroying %p\n", This); + + TF_GetThreadMgr(&tm); + ThreadMgr_OnDocumentMgrDestruction(tm, (ITfDocumentMgr*)This); + if (This->contextStack[0]) ITfContext_Release(This->contextStack[0]); if (This->contextStack[1]) diff --git a/dlls/msctf/msctf_internal.h b/dlls/msctf/msctf_internal.h index 928b046d49a..3bb0baa6ee7 100644 --- a/dlls/msctf/msctf_internal.h +++ b/dlls/msctf/msctf_internal.h @@ -43,6 +43,7 @@ extern HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *This); extern HRESULT Context_Initialize(ITfContext *cxt, ITfDocumentMgr *manager); extern HRESULT Context_Uninitialize(ITfContext *cxt); +extern void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr); extern HRESULT TF_SELECTION_to_TS_SELECTION_ACP(const TF_SELECTION *tf, TS_SELECTION_ACP *tsAcp); /* cookie function */ diff --git a/dlls/msctf/threadmgr.c b/dlls/msctf/threadmgr.c index b10910709bc..da2c74a7ec3 100644 --- a/dlls/msctf/threadmgr.c +++ b/dlls/msctf/threadmgr.c @@ -65,6 +65,12 @@ typedef struct tagPreservedKey TfClientId tid; } PreservedKey; +typedef struct tagDocumentMgrs +{ + struct list entry; + ITfDocumentMgr *docmgr; +} DocumentMgrEntry; + typedef struct tagACLMulti { const ITfThreadMgrVtbl *ThreadMgrVtbl; const ITfSourceVtbl *SourceVtbl; @@ -90,6 +96,7 @@ typedef struct tagACLMulti { CLSID forgroundTextService; struct list CurrentPreservedKeys; + struct list CreatedDocumentMgrs; /* kept as separate lists to reduce unnecessary iterations */ struct list ActiveLanguageProfileNotifySink; @@ -186,6 +193,14 @@ static void ThreadMgr_Destructor(ThreadMgr *This) HeapFree(GetProcessHeap(),0,key); } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs) + { + DocumentMgrEntry *mgr = LIST_ENTRY(cursor,DocumentMgrEntry,entry); + list_remove(cursor); + FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n"); + HeapFree(GetProcessHeap(),0,mgr); + } + CompartmentMgr_Destructor(This->CompartmentMgr); HeapFree(GetProcessHeap(),0,This); @@ -303,8 +318,25 @@ static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocum **ppdim) { ThreadMgr *This = (ThreadMgr *)iface; + DocumentMgrEntry *mgrentry; + HRESULT hr; + TRACE("(%p)\n",iface); - return DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim); + mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry)); + if (mgrentry == NULL) + return E_OUTOFMEMORY; + + hr = DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim); + + if (SUCCEEDED(hr)) + { + mgrentry->docmgr = *ppdim; + list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry); + } + else + HeapFree(GetProcessHeap(),0,mgrentry); + + return hr; } static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs @@ -1083,6 +1115,7 @@ HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr); list_init(&This->CurrentPreservedKeys); + list_init(&This->CreatedDocumentMgrs); list_init(&This->ActiveLanguageProfileNotifySink); list_init(&This->DisplayAttributeNotifySink); @@ -1095,3 +1128,20 @@ HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) *ppOut = (IUnknown *)This; return S_OK; } + +void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr) +{ + ThreadMgr *This = (ThreadMgr *)tm; + struct list *cursor; + LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs) + { + DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry); + if (mgrentry->docmgr == mgr) + { + list_remove(cursor); + HeapFree(GetProcessHeap(),0,mgrentry); + return; + } + } + FIXME("ITfDocumenMgr %p not found in this thread\n",mgr); +}