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