[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    Patches for adding IRichEditOle/ITextDocument support for ITextServices::QueryInterface ask for revi
From:       Jactry Zeng <jactry92 () gmail ! com>
Date:       2014-09-24 7:44:43
Message-ID: CAManwExWvMuuObGGfeXgk8oadfb5DS7Bp5K-==+7XeJyBTXjdA () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


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

[Attachment #5 (text/html)]

<div dir="ltr">Hi folks,<div><br></div><div>I wrote two patches for adding \
IRichEditOle/ITextDocument support for ITextServices::QueryInterface(for bug \
17042[1]), but I&#39;m</div><div>no sure is it the correct way. I need your review \
and comment!  I will really appreciate it!</div><div><br></div><div>There are some \
tests for ITextServices::QueryInterface in dlls/riched20/txtsrv.c: \
test_QueryInterfaces():</div><div>1.  </div><div><div>      refcount = \
get_refcount((IUnknown *)txtserv);</div><div>      ok(refcount == 1, &quot;got wrong \
ref count: %d\n&quot;, refcount);</div><div><br></div><div>      /* IID_IRichEditOle \
*/</div><div>      hres = ITextServices_QueryInterface(txtserv, \
&amp;IID_IRichEditOle, (void **)&amp;txtsrv_reOle);</div><div>      ok(hres == S_OK, \
&quot;ITextServices_QueryInterface\n&quot;);</div><div><br></div><div>      refcount \
= get_refcount((IUnknown *)txtserv);</div><div>      ok(refcount == 2, &quot;got \
wrong ref count: %d\n&quot;, refcount);</div></div><div><br></div><div>From this case \
we know ref count of ITextServices will increase after get a IRichEditOle interface \
from</div><div>ITextServices::QueryInterface.   \
ITextServices::QueryInterface(&amp;IID_ITextDocument) is also \
similar.</div><div><br></div><div>2.  </div><div>      refcount = \
get_refcount((IUnknown *)txtserv);</div><div>      ok(refcount == 2, &quot;got wrong \
ref count: %d\n&quot;, refcount);</div><div><br></div><div>      if (SUCCEEDED(hres)) \
{</div><div>            refcount = get_refcount((IUnknown *)txtsrv_reOle);</div><div> \
ok(refcount == 2, &quot;got wrong ref count: %d\n&quot;, \
refcount);</div><div><br></div><div>            hres = \
IRichEditOle_QueryInterface(txtsrv_reOle, &amp;IID_ITextDocument, (void \
**)&amp;txtDoc);</div><div>            ok(hres == S_OK, \
&quot;IRichEditOle_QueryInterface: 0x%08x\n&quot;, hres);</div><div>            \
refcount = get_refcount((IUnknown *)txtserv);</div><div>            ok(refcount == 3, \
&quot;got wrong ref count: %d\n&quot;, refcount);</div><div>            refcount = \
get_refcount((IUnknown *)txtsrv_reOle);</div><div>            ok(refcount == 3, \
&quot;got wrong ref count: %d\n&quot;, refcount);</div><div><br></div><div><div>From \
this case we know when a IRichEditOle was got by \
ITextServices::QueryInterface(&amp;IID_IRichEditOle) then</div><div>we used \
IRichEditOle::QueryInterface to get another interface, the ref count of ITextServices \
will increase too.</div><div>For implementing this feature I added IUnknown *parent \
in IRichEditOleImpl and passed ITextServices interface into  \
</div><div>CreateIRichEditOle when we call it in \
ITextServices::QueryInterface:</div><div>dlls/riched20/richole.c</div><div>---snip---</div><div><div>typedef \
struct IRichEditOleImpl {</div><div>      IRichEditOle IRichEditOle_iface;</div><div> \
ITextDocument ITextDocument_iface;</div><div>      LONG \
ref;</div><div><br></div><div>      ME_TextEditor *editor;</div><div>      \
ITextSelectionImpl *txtSel;</div><div>      IOleClientSiteImpl \
*clientSite;</div><div>      struct list rangelist;</div><div>      IUnknown \
*parent;</div><div>} \
IRichEditOleImpl;</div></div><div>---snip---</div><div>dlls/riched20/txtsrv.c</div><div>---snip---</div><div><div> \
else if (IsEqualIID(riid, &amp;IID_IRichEditOle) || IsEqualIID(riid, \
&amp;IID_ITextDocument)) {</div><div>           if \
(!This-&gt;editor-&gt;reOle)</div><div>                 \
CreateIRichEditOle(This-&gt;editor, (LPVOID *)&amp;(This-&gt;editor-&gt;reOle), \
iface);</div><div>           IRichEditOle_QueryInterface(This-&gt;editor-&gt;reOle, \
riid, (void **)ppv);</div><div>           return S_OK;</div><div>     } else \
{</div></div><div>---snip---</div><div><br></div><div>3. By some other tests, I found \
when a ITextServices was got by IRichEditOle::QueryInterface, then</div><div>we use \
ITextServices::QueryInterface to got another interface, the ref count of IRichEditOle \
will increase</div><div>too.</div><div><br></div><div>Thanks!</div><div><br></div><div>[1] \
<a href="https://bugs.winehq.org/show_bug.cgi?id=17042" \
target="_blank">https://bugs.winehq.org/show_bug.cgi?id=17042</a></div><div><br></div>-- \
<br><div dir="ltr"><div>Regards,<br></div><div>Jactry Zeng</div><div><br></div></div> \
</div></div>

--047d7bdc0c6ce29a070503caddd6--


["0001-riched20-Add-IID_IRichEditOle-support-for-ITextService.txt" (text/plain)]

From 5e3b4d8dda41a79679a3f76afe242eefc4a17d23 Mon Sep 17 00:00:00 2001
From: Jactry Zeng <jzeng@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@winehq.org>
Reply-To: wine-devel <wine-devel@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


["0002-riched20-Add-IID_ITextDocument-support-for-ITextServic.txt" (text/plain)]

From 73e01cce0760454777401a9dd5c9a1f4f3dee14c Mon Sep 17 00:00:00 2001
From: Jactry Zeng <jzeng@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@winehq.org>
Reply-To: wine-devel <wine-devel@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





[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic