diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 375b16292c9..1e62fc110d9 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -2889,7 +2889,7 @@ void ME_DestroyEditor(ME_TextEditor *editor) ITextHost_Release(editor->texthost); if (editor->reOle) { - IRichEditOle_Release(editor->reOle); + DestroyIRichEditOle(editor->reOle); editor->reOle = NULL; } OleUninitialize(); diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 255945e95ee..d8abe4eb37f 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -241,10 +241,12 @@ int ME_GetParaBorderWidth(const ME_Context *c, int flags) DECLSPEC_HIDDEN; /* richole.c */ LRESULT CreateIRichEditOle(IUnknown *outer_unk, ME_TextEditor *editor, LPVOID *ppvObj) DECLSPEC_HIDDEN; +void DestroyIRichEditOle(IRichEditOle *iface) DECLSPEC_HIDDEN; void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run* run, ME_Paragraph *para, BOOL selected) DECLSPEC_HIDDEN; void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize) DECLSPEC_HIDDEN; void ME_CopyReObject(REOBJECT* dst, const REOBJECT* src) DECLSPEC_HIDDEN; void ME_DeleteReObject(REOBJECT* reo) DECLSPEC_HIDDEN; +void ME_GetITextDocumentInterface(IRichEditOle *iface, LPVOID *ppvObj) DECLSPEC_HIDDEN; /* editor.c */ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) DECLSPEC_HIDDEN; diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index 07ba2793b47..0788125c1b7 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -143,17 +143,7 @@ static ULONG WINAPI IRichEditOleImpl_inner_fnRelease(IUnknown *iface) TRACE ("%p ref=%u\n", This, ref); if (!ref) - { - ITextRangeImpl *txtRge; - TRACE ("Destroying %p\n", This); - This->txtSel->reOle = NULL; - This->editor->reOle = NULL; - ITextSelection_Release(&This->txtSel->ITextSelection_iface); - IOleClientSite_Release(&This->clientSite->IOleClientSite_iface); - LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, entry) - txtRge->reOle = NULL; - heap_free(This); - } + DestroyIRichEditOle(&This->IRichEditOle_iface); return ref; } @@ -2375,6 +2365,21 @@ LRESULT CreateIRichEditOle(IUnknown *outer_unk, ME_TextEditor *editor, LPVOID *p return 1; } +void DestroyIRichEditOle(IRichEditOle *iface) +{ + IRichEditOleImpl *This = impl_from_IRichEditOle(iface); + ITextRangeImpl *txtRge; + + TRACE("Destroying %p\n", This); + This->txtSel->reOle = NULL; + This->editor->reOle = NULL; + ITextSelection_Release(&This->txtSel->ITextSelection_iface); + IOleClientSite_Release(&This->clientSite->IOleClientSite_iface); + LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, entry) + txtRge->reOle = NULL; + heap_free(This); +} + static void convert_sizel(const ME_Context *c, const SIZEL* szl, SIZE* sz) { /* sizel is in .01 millimeters, sz in pixels */ @@ -2578,3 +2583,9 @@ void ME_CopyReObject(REOBJECT* dst, const REOBJECT* src) if (dst->pstg) IStorage_AddRef(dst->pstg); if (dst->polesite) IOleClientSite_AddRef(dst->polesite); } + +void ME_GetITextDocumentInterface(IRichEditOle *iface, LPVOID *ppvObj) +{ + IRichEditOleImpl *This = impl_from_IRichEditOle(iface); + *ppvObj = &This->ITextDocument_iface; +} diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c index 3401f8b477c..c154e2dee4a 100644 --- a/dlls/riched20/tests/txtsrv.c +++ b/dlls/riched20/tests/txtsrv.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -862,6 +864,72 @@ static void test_COM(void) IUnknown_Release(unk_obj.inner_unk); } +static ULONG get_refcount(IUnknown *iface) +{ + IUnknown_AddRef(iface); + return IUnknown_Release(iface); +} + +static void test_QueryInterface(void) +{ + HRESULT hres; + IRichEditOle *reole, *txtsrv_reole; + ITextDocument *txtdoc, *txtsrv_txtdoc; + ULONG refcount; + + if(!init_texthost()) + return; + + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 1, "got wrong ref count: %d\n", refcount); + + /* IID_IRichEditOle */ + hres = ITextServices_QueryInterface(txtserv, &IID_IRichEditOle, (void **)&txtsrv_reole); + ok(hres == S_OK, "ITextServices_QueryInterface: 0x%08x\n", hres); + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 2, "got wrong ref count: %d\n", refcount); + refcount = get_refcount((IUnknown *)txtsrv_reole); + ok(refcount == 2, "got wrong ref count: %d\n", refcount); + + hres = IRichEditOle_QueryInterface(txtsrv_reole, &IID_ITextDocument, (void **)&txtdoc); + ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres); + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 3, "got wrong ref count: %d\n", refcount); + refcount = get_refcount((IUnknown *)txtsrv_reole); + ok(refcount == 3, "got wrong ref count: %d\n", refcount); + + ITextDocument_Release(txtdoc); + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 2, "got wrong ref count: %d\n", refcount); + IRichEditOle_Release(txtsrv_reole); + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 1, "got wrong ref count: %d\n", refcount); + + /* IID_ITextDocument */ + hres = ITextServices_QueryInterface(txtserv, &IID_ITextDocument, (void **)&txtsrv_txtdoc); + ok(hres == S_OK, "ITextServices_QueryInterface: 0x%08x\n", hres); + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 2, "got wrong ref count: %d\n", refcount); + refcount = get_refcount((IUnknown *)txtsrv_txtdoc); + ok(refcount == 2, "got wrong ref count: %d\n", refcount); + + hres = ITextDocument_QueryInterface(txtsrv_txtdoc, &IID_IRichEditOle, (void **)&reole); + ok(hres == S_OK, "ITextDocument_QueryInterface: 0x%08x\n", hres); + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 3, "got wrong ref count: %d\n", refcount); + refcount = get_refcount((IUnknown *)txtsrv_txtdoc); + ok(refcount == 3, "got wrong ref count: %d\n", refcount); + + IRichEditOle_Release(reole); + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 2, "got wrong ref count: %d\n", refcount); + ITextDocument_Release(txtsrv_txtdoc); + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 1, "got wrong ref count: %d\n", refcount); + + free_texthost(); +} + START_TEST( txtsrv ) { setup_thiscall_wrappers(); @@ -887,6 +955,7 @@ START_TEST( txtsrv ) test_TxSetText(); test_TxGetNaturalSize(); test_TxDraw(); + test_QueryInterface(); } if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE); } diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c index 0ca1e1b5b4d..75bee6d99fd 100644 --- a/dlls/riched20/txtsrv.c +++ b/dlls/riched20/txtsrv.c @@ -29,6 +29,7 @@ #include "ole2.h" #include "oleauto.h" #include "richole.h" +#include "tom.h" #include "imm.h" #include "textserv.h" #include "wine/debug.h" @@ -79,7 +80,15 @@ static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID r *ppv = &This->IUnknown_inner; else if (IsEqualIID(riid, &IID_ITextServices)) *ppv = &This->ITextServices_iface; - else { + else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid, &IID_ITextDocument)) { + if (!This->editor->reOle) + if (!CreateIRichEditOle(This->outer_unk, This->editor, (void **)(&This->editor->reOle))) + return E_OUTOFMEMORY; + if (IsEqualIID(riid, &IID_ITextDocument)) + ME_GetITextDocumentInterface(This->editor->reOle, ppv); + else + *ppv = This->editor->reOle; + } else { *ppv = NULL; FIXME("Unknown interface: %s\n", debugstr_guid(riid)); return E_NOINTERFACE;