From ab898de498f1094e411e7812d61b7cc513242433 Mon Sep 17 00:00:00 2001 From: Dylan Smith Date: Sun, 26 Oct 2008 00:17:10 -0400 Subject: richedit: Initial testing of ITextServices methods. To: wine-patches Reply-To: wine-devel@winehq.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------1.5.4.3" This is a multi-part message in MIME format. --------------1.5.4.3 Content-Type: text/plain; charset=UTF-8; format=fixed Content-Transfer-Encoding: 8bit Mostly this patch defines the wrappers and macros that allow the ITextServices methods to be called, since they use the c++ thiscall calling convention. Assembly is used to make the conversion itself, and macros are used to abstract away these details from the tests. The code was only tested on an x86 machine with gcc and mingw, but it works on Windows and Wine. The public header files should not have these macros, since the native headers omit them, and they will cause code to crash on x86 platforms. --- dlls/riched20/tests/txtsrv.c | 281 ++++++++++++++++++++++++++++++++++++++++++ include/textserv.h | 19 --- 2 files changed, 281 insertions(+), 19 deletions(-) --------------1.5.4.3 Content-Type: text/x-patch; name="ab898de498f1094e411e7812d61b7cc513242433.diff" Content-Transfer-Encoding: 8bit Content-Disposition: attachment; filename="ab898de498f1094e411e7812d61b7cc513242433.diff" diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c index 5be953a..22ed157 100644 --- a/dlls/riched20/tests/txtsrv.c +++ b/dlls/riched20/tests/txtsrv.c @@ -73,6 +73,270 @@ static HMODULE hmoduleRichEdit; } #endif /* __GNUC__ */ +/* The ITextServices methods are defined as having the thiscall calling + * convention (the default calling convention for c++ methods). This is + * not compatible with the stdcall calling convention because the "This" + * pointer is stored in the ecx register on x86 machines. + * + * The following code manipulates the stack after a call to change + * the calling convention, then jumps right to the actual method. + */ +#ifdef __i386__ +#define STDCALL_TO_THISCALL \ + "movl 0x8(%esp), %ecx\n\t" \ + "popl %eax\n\t" \ + "movl %eax, 0x4(%esp)\n\t" \ + "popl %eax\n\t" \ + "jmp *%eax" + +#define THISCALL_NEEDED +#endif + +/* ITextServices functions used are now wrapped with this construct. */ + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_TxSendMessage(LPVOID function, + ITextServices *iface, + UINT msg, + WPARAM wparam, + LPARAM lparam, + LRESULT* plresult); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxSendMessage, STDCALL_TO_THISCALL); +#define ITextServices_TxSendMessage(This,a,b,c,d) fnTextSrv_TxSendMessage((This)->lpVtbl->TxSendMessage,This,a,b,c,d) +#else +#define ITextServices_TxSendMessage(This,a,b,c,d) (This)->lpVtbl->TxSendMessage(This,a,b,c,d) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_TxDraw(LPVOID function, + ITextServices *iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DVTARGETDEVICE* ptd, + HDC hdcDraw, + HDC hdcTargetDev, + LPCRECTL lprcBounds, + LPCRECTL lprcWBounds, + LPRECT lprcUpdate, + BOOL (CALLBACK * pfnContinue)(DWORD), + DWORD dwContinue, + LONG lViewId); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxDraw, STDCALL_TO_THISCALL) +#define ITextServices_TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l) fnTextSrv_TxDraw((This)->lpVtbl->TxDraw,This,a,b,c,d,e,f,g,h,i,j,k,l) +#else +#define ITextServices_TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l) (This)->lpVtbl->TxDraw(This,a,b,c,d,e,f,g,h,i,j,k,l) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_TxGetHScroll(LPVOID function, + ITextServices *iface, + LONG* plMin, + LONG* plMax, + LONG* plPos, + LONG* plPage, + BOOL* pfEnabled); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxGetHScroll, STDCALL_TO_THISCALL) +#define ITextServices_TxGetHScroll(This,a,b,c,d,e) fnTextSrv_TxGetHScroll((This)->lpVtbl->TxGetHScroll,This,a,b,c,d,e) +#else +#define ITextServices_TxGetHScroll(This,a,b,c,d,e) (This)->lpVtbl->TxGetHScroll(This,a,b,c,d,e) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_TxGetVScroll(LPVOID function, + ITextServices *iface, + LONG* plMin, + LONG* plMax, + LONG* plPos, + LONG* plPage, + BOOL* pfEnabled); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxGetVScroll, STDCALL_TO_THISCALL) +#define ITextServices_TxGetVScroll(This,a,b,c,d,e) fnTextSrv_TxGetVScroll((This)->lpVtbl->TxGetVScroll,This,a,b,c,d,e) +#else +#define ITextServices_TxGetVScroll(This,a,b,c,d,e) (This)->lpVtbl->TxGetVScroll(This,a,b,c,d,e) +#endif + +#ifdef THISCALL_NEEDED +HRESULT WINAPI fnTextSrv_OnTxSetCursor(LPVOID function, + ITextServices *iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DVTARGETDEVICE* ptd, + HDC hdcDraw, + HDC hicTargetDev, + LPCRECT lprcClient, + INT x, INT y); + +__ASM_GLOBAL_FUNC(fnTextSrv_OnTxSetCursor, STDCALL_TO_THISCALL) +#define ITextServices_OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) fnTextSrv_OnTxSetCursor((This)->lpVtbl->OnTxSetCursor,This,a,b,c,d,e,f,g,h,i) +#else +#define ITextServices_OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) (This)->lpVtbl->OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_TxQueryHitPoint(LPVOID function, + ITextServices *iface, + DWORD dwDrawAspect, + LONG lindex, + void* pvAspect, + DVTARGETDEVICE* ptd, + HDC hdcDraw, + HDC hicTargetDev, + LPCRECT lprcClient, + INT x, INT y, + DWORD* pHitResult); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxQueryHitPoint, STDCALL_TO_THISCALL) +#define ITextServices_TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) fnTextSrv_TxQueryHitPoint((This)->lpVtbl->TxQueryHitPoint,This,a,b,c,d,e,f,g,h,i,j) +#else +#define ITextServices_TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) (This)->lpVtbl->TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_OnTxInplaceActivate(LPVOID function, + ITextServices *iface, + LPCRECT prcClient); + +__ASM_GLOBAL_FUNC(fnTextSrv_OnTxInplaceActivate, STDCALL_TO_THISCALL) +#define ITextServices_OnTxInplaceActivate(This,a) fnTextSrv_OnTxInplaceActivate((This)->lpVtbl->OnTxInplaceActivate,This,a) +#else +#define ITextServices_OnTxInplaceActivate(This,a) (This)->lpVtbl->OnTxInplaceActivate(This,a) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_OnTxInplaceDeactivate(LPVOID function, + ITextServices *iface); + +__ASM_GLOBAL_FUNC(fnTextSrv_OnTxInplaceDeactivate, STDCALL_TO_THISCALL) +#define ITextServices_OnTxInplaceDeactivate(This) fnTextSrv_OnTxInplaceDeactivate((This)->lpVtbl->OnTxInplaceDeactivate,This) +#else +#define ITextServices_OnTxInplaceDeactivate(This) (This)->lpVtbl->OnTxInplaceDeactivate(This) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_OnTxUIActivate(LPVOID function, + ITextServices *iface); + +__ASM_GLOBAL_FUNC(fnTextSrv_OnTxUIActivate, STDCALL_TO_THISCALL) +#define ITextServices_OnTxUIActivate(This) fnTextSrv_OnTxUIActivate((This)->lpVtbl->OnTxUIActivate,This) +#else +#define ITextServices_OnTxUIActivate(This) (This)->lpVtbl->OnTxUIActivate(This) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_OnTxUIDeactivate(LPVOID function, + ITextServices *iface); + +__ASM_GLOBAL_FUNC(fnTextSrv_OnTxUIDeactivate, STDCALL_TO_THISCALL) +#define ITextServices_OnTxUIDeactivate(This) fnTextSrv_OnTxUIDeactivate((This)->lpVtbl->OnTxUIDeactivate,This) +#else +#define ITextServices_OnTxUIDeactivate(This) (This)->lpVtbl->OnTxUIDeactivate(This) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_TxGetText(LPVOID function, + ITextServices *iface, + BSTR* pbstrText); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxGetText, STDCALL_TO_THISCALL); +#define ITextServices_TxGetText(This,a) fnTextSrv_TxGetText((This)->lpVtbl->TxGetText,This,a) +#else +#define ITextServices_TxGetText(This,a) (This)->lpVtbl->TxGetText(This,a) +#endif + +#ifdef THISCALL_NEEDED +extern HRESULT WINAPI fnTextSrv_TxSetText(LPVOID function, + ITextServices *iface, + LPCTSTR pszText); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxSetText, STDCALL_TO_THISCALL); +#define ITextServices_TxSetText(This,a) fnTextSrv_TxSetText((This)->lpVtbl->TxSetText,This,a) +#else +#define ITextServices_TxSetText(This,a) (This)->lpVtbl->TxSetText(This,a) +#endif + +#ifdef THISCALL_NEEDED +HRESULT WINAPI fnTextSrv_TxGetCurrentTargetX(LPVOID function, + ITextServices *iface, + LONG* x); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxGetCurrentTargetX, STDCALL_TO_THISCALL); +#define ITextServices_TxGetCurrentTargetX(This,a) fnTextSrv_TxGetCurrentTargetX((This)->lpVtbl->TxGetCurrentTargetX,This,a) +#else +#define ITextServices_TxGetCurrentTargetX(This,a) (This)->lpVtbl->TxGetCurrentTargetX(This,a) +#endif + +#ifdef THISCALL_NEEDED +HRESULT WINAPI fnTextSrv_TxGetBaseLinePos(LPVOID function, + ITextServices *iface, + LONG* x); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxGetBaseLinePos, STDCALL_TO_THISCALL); +#define ITextServices_TxGetBaseLinePos(This,a) fnTextSrv_TxGetBaseLinePos((This)->lpVtbl->TxGetBaseLinePos,This,a) +#else +#define ITextServices_TxGetBaseLinePos(This,a) (This)->lpVtbl->TxGetBaseLinePos(This,a) +#endif + +#ifdef THISCALL_NEEDED +HRESULT WINAPI fnTextSrv_TxGetNaturalSize(LPVOID function, + ITextServices *iface, + DWORD dwAspect, + HDC hdcDraw, + HDC hicTargetDev, + DVTARGETDEVICE* ptd, + DWORD dwMode, + const SIZEL* psizelExtent, + LONG* pwidth, + LONG* pheight); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxGetNaturalSize, STDCALL_TO_THISCALL); +#define ITextServices_TxGetNaturalSize(This,a,b,c,d,e,f,g,h) fnTextSrv_TxGetNaturalSize((This)->lpVtbl->TxGetNaturalSize,This,a,b,c,d,e,f,g,h) +#else +#define ITextServices_TxGetNaturalSize(This,a,b,c,d,e,f,g,h) (This)->lpVtbl->TxGetNaturalSize(This,a,b,c,d,e,f,g,h) +#endif + +#ifdef THISCALL_NEEDED +HRESULT WINAPI fnTextSrv_TxGetDropTarget(LPVOID function, + ITextServices *iface, + IDropTarget** ppDropTarget); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxGetDropTarget, STDCALL_TO_THISCALL); +#define ITextServices_TxGetDropTarget(This,a) fnTextSrv_TxGetDropTarget((This)->lpVtbl->TxGetDropTarget,This,a) +#else +#define ITextServices_TxGetDropTarget(This,a) (This)->lpVtbl->TxGetDropTarget(This,a) +#endif + +#ifdef THISCALL_NEEDED +HRESULT WINAPI fnTextSrv_OnTxPropertyBitsChange(LPVOID function, + ITextServices *iface, + DWORD dwMask, + DWORD dwBits); + +__ASM_GLOBAL_FUNC(fnTextSrv_OnTxPropertyBitsChange, STDCALL_TO_THISCALL); +#define ITextServices_OnTxPropertyBitsChange(This,a,b) fnTextSrv_OnTxPropertyBitsChange((This)->lpVtbl->OnTxPropertyBitsChange,This,a,b) +#else +#define ITextServices_OnTxPropertyBitsChange(This,a,b) (This)->lpVtbl->OnTxPropertyBitsChange(This,a,b) +#endif + +#ifdef THISCALL_NEEDED +HRESULT WINAPI fnTextSrv_TxGetCachedSize(LPVOID function, + ITextServices *iface, + DWORD* pdwWidth, + DWORD* pdwHeight); + +__ASM_GLOBAL_FUNC(fnTextSrv_TxGetCachedSize, STDCALL_TO_THISCALL); +#define ITextServices_TxGetCachedSize(This,a,b) fnTextSrv_TxGetCachedSize((This)->lpVtbl->TxGetCachedSize,This,a,b) +#else +#define ITextServices_TxGetCachedSize(This,a,b) (This)->lpVtbl->TxGetCachedSize(This,a,b) +#endif + + + /* 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 @@ -649,6 +913,21 @@ BOOL init_texthost() return TRUE; } +static void test_TxGetText() +{ + 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 ) { /* Must explicitly LoadLibrary(). The test has no references to functions in @@ -661,4 +940,6 @@ START_TEST( txtsrv ) IUnknown_Release(txtserv); CoTaskMemFree(dummyTextHost); + + test_TxGetText(); } 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 --------------1.5.4.3--