Patches for adding IRichEditOle/ITextDocument support for ITextServices::QueryInterface ask for review

Jactry Zeng jactry92 at gmail.com
Wed Sep 24 02:44:43 CDT 2014


Hi folks,

I wrote two patches for adding IRichEditOle/ITextDocument support for
ITextServices::QueryInterface(for bug 17042[1]), but I'm
no sure is it the correct way. I need your review and comment! I will
really appreciate it!

There are some tests for ITextServices::QueryInterface in
dlls/riched20/txtsrv.c: test_QueryInterfaces():
1.
    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);

>From this case we know ref count of ITextServices will increase after get a
IRichEditOle interface from
ITextServices::QueryInterface.
ITextServices::QueryInterface(&IID_ITextDocument) is also similar.

2.
    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);

>From this case we know when a IRichEditOle was got by
ITextServices::QueryInterface(&IID_IRichEditOle) then
we used IRichEditOle::QueryInterface to get another interface, the ref
count of ITextServices will increase too.
For implementing this feature I added IUnknown *parent in IRichEditOleImpl
and passed ITextServices interface into
CreateIRichEditOle when we call it in ITextServices::QueryInterface:
dlls/riched20/richole.c
---snip---
typedef struct IRichEditOleImpl {
    IRichEditOle IRichEditOle_iface;
    ITextDocument ITextDocument_iface;
    LONG ref;

    ME_TextEditor *editor;
    ITextSelectionImpl *txtSel;
    IOleClientSiteImpl *clientSite;
    struct list rangelist;
    IUnknown *parent;
} IRichEditOleImpl;
---snip---
dlls/riched20/txtsrv.c
---snip---
   else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid,
&IID_ITextDocument)) {
       if (!This->editor->reOle)
           CreateIRichEditOle(This->editor, (LPVOID
*)&(This->editor->reOle), iface);
       IRichEditOle_QueryInterface(This->editor->reOle, riid, (void **)ppv);
       return S_OK;
   } else {
---snip---

3. By some other tests, I found when a ITextServices was got by
IRichEditOle::QueryInterface, then
we use ITextServices::QueryInterface to got another interface, the ref
count of IRichEditOle will increase
too.

Thanks!

[1] https://bugs.winehq.org/show_bug.cgi?id=17042

-- 
Regards,
Jactry Zeng
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20140924/a92d4966/attachment-0001.html>
-------------- next part --------------
From 5e3b4d8dda41a79679a3f76afe242eefc4a17d23 Mon Sep 17 00:00:00 2001
From: Jactry Zeng <jzeng at codeweavers.com>
Date: Wed, 24 Sep 2014 10:01:54 +0800
Subject: [PATCH 1/2] riched20: Add IID_IRichEditOle support for
 ITextServices::QueryInterface.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>

---
 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 <windef.h>
 #include <winbase.h>
 #include <objbase.h>
+#include <tom.h>
+#include <richole.h>
 #include <richedit.h>
 #include <initguid.h>
 #include <imm.h>
@@ -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

-------------- next part --------------
From 73e01cce0760454777401a9dd5c9a1f4f3dee14c Mon Sep 17 00:00:00 2001
From: Jactry Zeng <jzeng at codeweavers.com>
Date: Tue, 23 Sep 2014 15:36:31 +0800
Subject: [PATCH 2/2] riched20: Add IID_ITextDocument support for
 ITextServices::QueryInterface.
To: wine-patches <wine-patches at winehq.org>
Reply-To: wine-devel <wine-devel at winehq.org>

---
 dlls/riched20/tests/txtsrv.c | 30 ++++++++++++++++++++++++++++--
 dlls/riched20/txtsrv.c       |  5 +++--
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c
index 003a274..7b7db20 100644
--- a/dlls/riched20/tests/txtsrv.c
+++ b/dlls/riched20/tests/txtsrv.c
@@ -873,8 +873,8 @@ static ULONG get_refcount(IUnknown *iface)
 static void test_QueryInterface(void)
 {
     HRESULT hres;
-    IRichEditOle *txtsrv_reOle;
-    ITextDocument *txtDoc;
+    IRichEditOle *txtsrv_reOle, *reOle;
+    ITextDocument *txtsrv_txtDoc, *txtDoc;
     ULONG refcount;
 
     if(!init_texthost())
@@ -911,6 +911,32 @@ static void test_QueryInterface(void)
         win_skip("IRichEditOle not available\n");
     }
 
+    /* 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);
+
+    if (SUCCEEDED(hres)) {
+        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();
 }
 
diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c
index 15fcdd8..ae38640 100644
--- a/dlls/riched20/txtsrv.c
+++ b/dlls/riched20/txtsrv.c
@@ -33,6 +33,7 @@
 #include "textserv.h"
 #include "wine/debug.h"
 #include "editstr.h"
+#include "tom.h"
 
 #ifdef __i386__  /* thiscall functions are i386-specific */
 
@@ -79,10 +80,10 @@ static HRESULT WINAPI ITextServicesImpl_QueryInterface(IUnknown *iface, REFIID r
       *ppv = &This->IUnknown_inner;
    else if (IsEqualIID(riid, &IID_ITextServices))
       *ppv = &This->ITextServices_iface;
-   else if (IsEqualIID(riid, &IID_IRichEditOle)) {
+   else if (IsEqualIID(riid, &IID_IRichEditOle) || IsEqualIID(riid, &IID_ITextDocument)) {
        if (!This->editor->reOle)
            CreateIRichEditOle(This->editor, (LPVOID *)&(This->editor->reOle), iface);
-       IRichEditOle_QueryInterface(This->editor->reOle, &IID_IRichEditOle, (void **)ppv);
+       IRichEditOle_QueryInterface(This->editor->reOle, riid, (void **)ppv);
        return S_OK;
    } else {
       *ppv = NULL;
-- 
2.0.2



More information about the wine-devel mailing list