From 5e3b4d8dda41a79679a3f76afe242eefc4a17d23 Mon Sep 17 00:00:00 2001 From: Jactry Zeng Date: Wed, 24 Sep 2014 10:01:54 +0800 Subject: [PATCH 1/2] riched20: Add IID_IRichEditOle support for ITextServices::QueryInterface. To: wine-patches Reply-To: wine-devel --- dlls/riched20/editor.c | 4 ++-- dlls/riched20/editor.h | 2 +- dlls/riched20/richole.c | 11 ++++++++- dlls/riched20/tests/txtsrv.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ dlls/riched20/txtsrv.c | 7 +++++- 5 files changed, 72 insertions(+), 5 deletions(-) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 3c0d970..d19fb05 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -1194,7 +1194,7 @@ static BOOL ME_RTFInsertOleObject(RTF_Info *info, HENHMETAFILE hemf, HBITMAP hbm if (!info->lpRichEditOle) { - CreateIRichEditOle(info->editor, (VOID**)&info->lpRichEditOle); + CreateIRichEditOle(info->editor, (VOID**)&info->lpRichEditOle, NULL); } if (OleCreateDefaultHandler(&CLSID_NULL, NULL, &IID_IOleObject, (void**)&lpObject) == S_OK && @@ -4474,7 +4474,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_GETOLEINTERFACE: { if (!editor->reOle) - if (!CreateIRichEditOle(editor, (LPVOID *)&editor->reOle)) + if (!CreateIRichEditOle(editor, (LPVOID *)&editor->reOle, NULL)) return 0; *(LPVOID *)lParam = editor->reOle; IRichEditOle_AddRef(editor->reOle); diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index edbac8e..111d318 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -240,7 +240,7 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) DECLSPEC_HIDDEN; int ME_GetParaBorderWidth(const ME_Context *c, int flags) DECLSPEC_HIDDEN; /* richole.c */ -LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *) DECLSPEC_HIDDEN; +LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj, IUnknown *parent) 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; diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index f7e7870..26142fb 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -60,6 +60,7 @@ typedef struct IRichEditOleImpl { ITextSelectionImpl *txtSel; IOleClientSiteImpl *clientSite; struct list rangelist; + IUnknown *parent; } IRichEditOleImpl; struct ITextRangeImpl { @@ -126,6 +127,9 @@ IRichEditOle_fnAddRef(IRichEditOle *me) TRACE("%p ref = %u\n", This, ref); + if (This->parent) + IUnknown_AddRef(This->parent); + return ref; } @@ -137,6 +141,8 @@ IRichEditOle_fnRelease(IRichEditOle *me) TRACE ("%p ref=%u\n", This, ref); + if (This->parent) + IUnknown_Release(This->parent); if (!ref) { ITextRangeImpl *txtRge; @@ -146,6 +152,8 @@ IRichEditOle_fnRelease(IRichEditOle *me) IOleClientSite_Release(&This->clientSite->IOleClientSite_iface); LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, entry) txtRge->reOle = NULL; + This->editor->reOle = NULL; + This->parent = NULL; heap_free(This); } return ref; @@ -2304,7 +2312,7 @@ CreateTextSelection(IRichEditOleImpl *reOle) return txtSel; } -LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) +LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj, IUnknown *parent) { IRichEditOleImpl *reo; @@ -2316,6 +2324,7 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) reo->ITextDocument_iface.lpVtbl = &tdvt; reo->ref = 1; reo->editor = editor; + reo->parent = parent; reo->txtSel = CreateTextSelection(reo); if (!reo->txtSel) { diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c index 3401f8b..003a274 100644 --- a/dlls/riched20/tests/txtsrv.c +++ b/dlls/riched20/tests/txtsrv.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -862,6 +864,56 @@ 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 *txtsrv_reOle; + ITextDocument *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\n"); + + refcount = get_refcount((IUnknown *)txtserv); + ok(refcount == 2, "got wrong ref count: %d\n", refcount); + + if (SUCCEEDED(hres)) { + 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); + } else { + win_skip("IRichEditOle not available\n"); + } + + free_texthost(); +} + START_TEST( txtsrv ) { setup_thiscall_wrappers(); @@ -887,6 +939,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 636efff..15fcdd8 100644 --- a/dlls/riched20/txtsrv.c +++ b/dlls/riched20/txtsrv.c @@ -79,7 +79,12 @@ 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)) { + if (!This->editor->reOle) + CreateIRichEditOle(This->editor, (LPVOID *)&(This->editor->reOle), iface); + IRichEditOle_QueryInterface(This->editor->reOle, &IID_IRichEditOle, (void **)ppv); + return S_OK; + } else { *ppv = NULL; FIXME("Unknown interface: %s\n", debugstr_guid(riid)); return E_NOINTERFACE; -- 2.0.2