Dylan Smith : richedit: Initial testing of ITextServices methods.
Alexandre Julliard
julliard at winehq.org
Thu Nov 13 08:51:45 CST 2008
Module: wine
Branch: master
Commit: e4ef9c5c15c99f03c81d508a0a1ebe169460e7de
URL: http://source.winehq.org/git/wine.git/?a=commit;h=e4ef9c5c15c99f03c81d508a0a1ebe169460e7de
Author: Dylan Smith <dylan.ah.smith at gmail.com>
Date: Wed Nov 12 14:47:24 2008 -0500
richedit: Initial testing of ITextServices methods.
---
dlls/riched20/tests/txtsrv.c | 91 +++++++++++++++++++++++++++++++++++++++++-
include/textserv.h | 19 ---------
2 files changed, 89 insertions(+), 21 deletions(-)
diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c
index ffc52fd..3d47490 100644
--- a/dlls/riched20/tests/txtsrv.c
+++ b/dlls/riched20/tests/txtsrv.c
@@ -34,6 +34,35 @@
static HMODULE hmoduleRichEdit;
+/* Define C Macros for ITextServices calls. */
+
+/* Use a special table for x86 machines to convert the thiscall
+ * calling convention. This isn't needed on other platforms. */
+#ifdef __i386__
+#define TXTSERV_VTABLE(This) (&itextServicesStdcallVtbl)
+#else /* __i386__ */
+#define TXTSERV_VTABLE(This) (This)->lpVtbl
+#endif /* __i386__ */
+
+#define ITextServices_TxSendMessage(This,a,b,c,d) TXTSERV_VTABLE(This)->TxSendMessage(This,a,b,c,d)
+#define ITextServices_TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l) TXTSERV_VTABLE(This)->TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l)
+#define ITextServices_TxGetHScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetHScroll(This,a,b,c,d,e)
+#define ITextServices_TxGetVScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetVScroll(This,a,b,c,d,e)
+#define ITextServices_OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) TXTSERV_VTABLE(This)->OnTxSetCursor(This,a,b,c,d,e,f,g,h,i)
+#define ITextServices_TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) TXTSERV_VTABLE(This)->TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j)
+#define ITextServices_OnTxInplaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInplaceActivate(This,a)
+#define ITextServices_OnTxInplaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInplaceDeactivate(This)
+#define ITextServices_OnTxUIActivate(This) TXTSERV_VTABLE(This)->OnTxUIActivate(This)
+#define ITextServices_OnTxUIDeactivate(This) TXTSERV_VTABLE(This)->OnTxUIDeactivate(This)
+#define ITextServices_TxGetText(This,a) TXTSERV_VTABLE(This)->TxGetText(This,a)
+#define ITextServices_TxSetText(This,a) TXTSERV_VTABLE(This)->TxSetText(This,a)
+#define ITextServices_TxGetCurrentTargetX(This,a) TXTSERV_VTABLE(This)->TxGetCurrentTargetX(This,a)
+#define ITextServices_TxGetBaseLinePos(This,a) TXTSERV_VTABLE(This)->TxGetBaseLinePos(This,a)
+#define ITextServices_TxGetNaturalSize(This,a,b,c,d,e,f,g,h) TXTSERV_VTABLE(This)->TxGetNaturalSize(This,a,b,c,d,e,f,g,h)
+#define ITextServices_TxGetDropTarget(This,a) TXTSERV_VTABLE(This)->TxGetDropTarget(This,a)
+#define ITextServices_OnTxPropertyBitsChange(This,a,b) TXTSERV_VTABLE(This)->OnTxPropertyBitsChange(This,a,b)
+#define ITextServices_TxGetCachedSize(This,a,b) TXTSERV_VTABLE(This)->TxGetCachedSize(This,a,b)
+
/* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
* function call traces of ITextHost. */
#define TRACECALL if(winetest_debug > 1) trace
@@ -412,6 +441,8 @@ static HRESULT WINAPI ITextHostImpl_TxGetSelectionBarWidth(ITextHost *iface,
return E_NOTIMPL;
}
+static ITextServicesVtbl itextServicesStdcallVtbl;
+
static ITextHostVtbl itextHostVtbl = {
ITextHostImpl_QueryInterface,
ITextHostImpl_AddRef,
@@ -461,6 +492,8 @@ static ITextServices *txtserv = NULL;
static ITextHostTestImpl *dummyTextHost;
static void *wrapperCodeMem = NULL;
+#include "pshpack1.h"
+
/* Code structure for x86 byte code */
typedef struct
{
@@ -471,6 +504,17 @@ typedef struct
DWORD func;
} THISCALL_TO_STDCALL_THUNK;
+typedef struct
+{
+ BYTE pop_eax; /* popl %eax */
+ BYTE pop_ecx; /* popl %ecx */
+ BYTE push_eax; /* pushl %eax */
+ BYTE mov_vtable_eax[2]; /* movl (%ecx), %eax */
+ BYTE jmp_eax[2]; /* jmp *$vtablefunc_offset(%eax) */
+ int vtablefunc_offset;
+} STDCALL_TO_THISCALL_THUNK;
+
+#include "poppack.h"
static void setup_thiscall_wrappers(void)
{
@@ -478,10 +522,13 @@ static void setup_thiscall_wrappers(void)
void** pVtable;
void** pVtableEnd;
THISCALL_TO_STDCALL_THUNK *thunk;
+ STDCALL_TO_THISCALL_THUNK *thunk2;
wrapperCodeMem = VirtualAlloc(NULL,
(sizeof(ITextHostVtbl)/sizeof(void*) - 3)
- * sizeof(THISCALL_TO_STDCALL_THUNK),
+ * sizeof(THISCALL_TO_STDCALL_THUNK)
+ +(sizeof(ITextServicesVtbl)/sizeof(void*) - 3)
+ * sizeof(STDCALL_TO_THISCALL_THUNK),
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
thunk = wrapperCodeMem;
@@ -498,7 +545,7 @@ static void setup_thiscall_wrappers(void)
/* Skip QueryInterface, AddRef, and Release native actually
* defined them with the stdcall calling convention. */
pVtable = (void**)&itextHostVtbl + 3;
- pVtableEnd = (void**)((char*)&itextHostVtbl + sizeof(ITextHostVtbl));
+ pVtableEnd = (void**)(&itextHostVtbl + 1);
while (pVtable != pVtableEnd) {
/* write byte code to executable memory */
thunk->pop_eax = 0x58; /* popl %eax */
@@ -511,6 +558,29 @@ static void setup_thiscall_wrappers(void)
pVtable++;
thunk++;
}
+
+ /* Setup an ITextServices standard call vtable that will call the
+ * native thiscall vtable when the methods are called. */
+
+ /* QueryInterface, AddRef, and Release should be called directly on the
+ * real vtable since they use the stdcall calling convention. */
+ thunk2 = (STDCALL_TO_THISCALL_THUNK *)thunk;
+ pVtable = (void**)&itextServicesStdcallVtbl + 3;
+ pVtableEnd = (void**)(&itextServicesStdcallVtbl + 1);
+ while (pVtable != pVtableEnd) {
+ /* write byte code to executable memory */
+ thunk2->pop_eax = 0x58; /* popl %eax */
+ thunk2->pop_ecx = 0x59; /* popl %ecx */
+ thunk2->push_eax = 0x50; /* pushl %eax */
+ thunk2->mov_vtable_eax[0] = 0x8b; /* movl (%ecx), %eax */
+ thunk2->mov_vtable_eax[1] = 0x01;
+ thunk2->jmp_eax[0] = 0xff; /* jmp *$vtablefunc_offset(%eax) */
+ thunk2->jmp_eax[1] = 0xa0;
+ thunk2->vtablefunc_offset = (char*)pVtable - (char*)&itextServicesStdcallVtbl;
+ *pVtable = thunk2;
+ pVtable++;
+ thunk2++;
+ }
#endif /* __i386__ */
}
@@ -557,6 +627,21 @@ static BOOL init_texthost(void)
return TRUE;
}
+static void test_TxGetText(void)
+{
+ HRESULT hres;
+ BSTR rettext;
+
+ if (!init_texthost())
+ return;
+
+ hres = ITextServices_TxGetText(txtserv, &rettext);
+ todo_wine ok(hres == S_OK, "ITextServices_TxGetText failed\n");
+
+ IUnknown_Release(txtserv);
+ CoTaskMemFree(dummyTextHost);
+}
+
START_TEST( txtsrv )
{
setup_thiscall_wrappers();
@@ -570,6 +655,8 @@ START_TEST( txtsrv )
{
IUnknown_Release(txtserv);
CoTaskMemFree(dummyTextHost);
+
+ test_TxGetText();
}
if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE);
}
diff --git a/include/textserv.h b/include/textserv.h
index 9b3cbf9..1c262ac 100644
--- a/include/textserv.h
+++ b/include/textserv.h
@@ -147,25 +147,6 @@ DECLARE_INTERFACE_(ITextServices,IUnknown)
#define ITextServices_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
#define ITextServices_AddRef(p) (p)->lpVtbl->AddRef(p)
#define ITextServices_Release(p) (p)->lpVtbl->Release(p)
-/*** ITextServices methods ***/
-#define ITextServices_TxSendMessage(p,a,b,c,d) (p)->lpVtbl->TxSendMessage(p,a,b,c,d)
-#define ITextServices_TxDraw(p,a,b,c,d,e,f,g,h,i,j,k,l) (p)->lpVtbl->TxDraw(p,a,b,c,d,e,f,g,h,i,j,k,l)
-#define ITextServices_TxGetHScroll(p,a,b,c,d,e) (p)->lpVtbl->TxGetHScroll(p,a,b,c,d,e)
-#define ITextServices_TxGetVScroll(p,a,b,c,d,e) (p)->lpVtbl->TxGetVScroll(p,a,b,c,d,e)
-#define ITextServices_OnTxSetCursor(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->OnTxSetCursor(p,a,b,c,d,e,f,g,h,i)
-#define ITextServices_TxQueryHitPoint(p,a,b,c,d,e,f,g,h,i,j) (p)->lpVtbl->TxQueryHitPoint(p,a,b,c,d,e,f,g,h,i,j)
-#define ITextServices_OnTxInplaceActivate(p,a) (p)->lpVtbl->OnTxInplaceActivate(p,a)
-#define ITextServices_OnTxInplaceDeactivate(p) (p)->lpVtbl->OnTxInplaceDeactivate(p)
-#define ITextServices_OnTxUIActivate(p) (p)->lpVtbl->OnTxUIActivate(p)
-#define ITextServices_OnTxUIDeactivate(p) (p)->lpVtbl->OnTxUIDeactivate(p)
-#define ITextServices_TxGetText(p,a) (p)->lpVtbl->TxGetText(p,a)
-#define ITextServices_TxSetText(p,a) (p)->lpVtbl->TxSetText(p,a)
-#define ITextServices_TxGetCurrentTargetX(p,a) (p)->lpVtbl->TxGetCurrentTargetX(p,a)
-#define ITextServices_TxGetBaseLinePos(p,a) (p)->lpVtbl->TxGetBaseLinePos(p,a)
-#define ITextServices_TxGetNaturalSize(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->TxGetNaturalSize(p,a,b,c,d,e,f,g,h)
-#define ITextServices_TxGetDropTarget(p,a) (p)->lpVtbl->TxGetDropTarget(p,a)
-#define ITextServices_OnTxPropertyBitsChange(p,a,b) (p)->lpVtbl->OnTxPropertyBitsChange(p,a,b)
-#define ITextServices_TxGetCachedSize(p,a,b) (p)->lpVtbl->TxGetCachedSize(p,a,b)
#endif
#undef INTERFACE
More information about the wine-cvs
mailing list