richedit: Initial testing of ITextServices methods.
This commit is contained in:
parent
6cd908d420
commit
e4ef9c5c15
|
@ -34,6 +34,35 @@
|
||||||
|
|
||||||
static HMODULE hmoduleRichEdit;
|
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
|
/* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
|
||||||
* function call traces of ITextHost. */
|
* function call traces of ITextHost. */
|
||||||
#define TRACECALL if(winetest_debug > 1) trace
|
#define TRACECALL if(winetest_debug > 1) trace
|
||||||
|
@ -412,6 +441,8 @@ static HRESULT WINAPI ITextHostImpl_TxGetSelectionBarWidth(ITextHost *iface,
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ITextServicesVtbl itextServicesStdcallVtbl;
|
||||||
|
|
||||||
static ITextHostVtbl itextHostVtbl = {
|
static ITextHostVtbl itextHostVtbl = {
|
||||||
ITextHostImpl_QueryInterface,
|
ITextHostImpl_QueryInterface,
|
||||||
ITextHostImpl_AddRef,
|
ITextHostImpl_AddRef,
|
||||||
|
@ -461,6 +492,8 @@ static ITextServices *txtserv = NULL;
|
||||||
static ITextHostTestImpl *dummyTextHost;
|
static ITextHostTestImpl *dummyTextHost;
|
||||||
static void *wrapperCodeMem = NULL;
|
static void *wrapperCodeMem = NULL;
|
||||||
|
|
||||||
|
#include "pshpack1.h"
|
||||||
|
|
||||||
/* Code structure for x86 byte code */
|
/* Code structure for x86 byte code */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -471,6 +504,17 @@ typedef struct
|
||||||
DWORD func;
|
DWORD func;
|
||||||
} THISCALL_TO_STDCALL_THUNK;
|
} 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)
|
static void setup_thiscall_wrappers(void)
|
||||||
{
|
{
|
||||||
|
@ -478,10 +522,13 @@ static void setup_thiscall_wrappers(void)
|
||||||
void** pVtable;
|
void** pVtable;
|
||||||
void** pVtableEnd;
|
void** pVtableEnd;
|
||||||
THISCALL_TO_STDCALL_THUNK *thunk;
|
THISCALL_TO_STDCALL_THUNK *thunk;
|
||||||
|
STDCALL_TO_THISCALL_THUNK *thunk2;
|
||||||
|
|
||||||
wrapperCodeMem = VirtualAlloc(NULL,
|
wrapperCodeMem = VirtualAlloc(NULL,
|
||||||
(sizeof(ITextHostVtbl)/sizeof(void*) - 3)
|
(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);
|
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
thunk = wrapperCodeMem;
|
thunk = wrapperCodeMem;
|
||||||
|
|
||||||
|
@ -498,7 +545,7 @@ static void setup_thiscall_wrappers(void)
|
||||||
/* Skip QueryInterface, AddRef, and Release native actually
|
/* Skip QueryInterface, AddRef, and Release native actually
|
||||||
* defined them with the stdcall calling convention. */
|
* defined them with the stdcall calling convention. */
|
||||||
pVtable = (void**)&itextHostVtbl + 3;
|
pVtable = (void**)&itextHostVtbl + 3;
|
||||||
pVtableEnd = (void**)((char*)&itextHostVtbl + sizeof(ITextHostVtbl));
|
pVtableEnd = (void**)(&itextHostVtbl + 1);
|
||||||
while (pVtable != pVtableEnd) {
|
while (pVtable != pVtableEnd) {
|
||||||
/* write byte code to executable memory */
|
/* write byte code to executable memory */
|
||||||
thunk->pop_eax = 0x58; /* popl %eax */
|
thunk->pop_eax = 0x58; /* popl %eax */
|
||||||
|
@ -511,6 +558,29 @@ static void setup_thiscall_wrappers(void)
|
||||||
pVtable++;
|
pVtable++;
|
||||||
thunk++;
|
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__ */
|
#endif /* __i386__ */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,6 +627,21 @@ static BOOL init_texthost(void)
|
||||||
return TRUE;
|
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 )
|
START_TEST( txtsrv )
|
||||||
{
|
{
|
||||||
setup_thiscall_wrappers();
|
setup_thiscall_wrappers();
|
||||||
|
@ -570,6 +655,8 @@ START_TEST( txtsrv )
|
||||||
{
|
{
|
||||||
IUnknown_Release(txtserv);
|
IUnknown_Release(txtserv);
|
||||||
CoTaskMemFree(dummyTextHost);
|
CoTaskMemFree(dummyTextHost);
|
||||||
|
|
||||||
|
test_TxGetText();
|
||||||
}
|
}
|
||||||
if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE);
|
if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,25 +147,6 @@ DECLARE_INTERFACE_(ITextServices,IUnknown)
|
||||||
#define ITextServices_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
#define ITextServices_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||||
#define ITextServices_AddRef(p) (p)->lpVtbl->AddRef(p)
|
#define ITextServices_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||||
#define ITextServices_Release(p) (p)->lpVtbl->Release(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
|
#endif
|
||||||
|
|
||||||
#undef INTERFACE
|
#undef INTERFACE
|
||||||
|
|
Loading…
Reference in New Issue