2 * Unit test suite for windowless rich edit controls
4 * Copyright 2008 Maarten Lankhorst
5 * Copyright 2008 Austin Lund
6 * Copyright 2008 Dylan Smith
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include <wine/test.h>
37 static HMODULE hmoduleRichEdit
;
38 static IID
*pIID_ITextServices
;
39 static IID
*pIID_ITextHost
;
40 static IID
*pIID_ITextHost2
;
42 static const char *debugstr_guid(REFIID riid
)
49 sprintf(buf
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
50 riid
->Data1
, riid
->Data2
, riid
->Data3
, riid
->Data4
[0],
51 riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3], riid
->Data4
[4],
52 riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]);
57 /* Define C Macros for ITextServices calls. */
59 /* Use a special table for x86 machines to convert the thiscall
60 * calling convention. This isn't needed on other platforms. */
62 static ITextServicesVtbl itextServicesStdcallVtbl
;
63 #define TXTSERV_VTABLE(This) (&itextServicesStdcallVtbl)
65 #define TXTSERV_VTABLE(This) (This)->lpVtbl
68 #define ITextServices_TxSendMessage(This,a,b,c,d) TXTSERV_VTABLE(This)->TxSendMessage(This,a,b,c,d)
69 #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)
70 #define ITextServices_TxGetHScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetHScroll(This,a,b,c,d,e)
71 #define ITextServices_TxGetVScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetVScroll(This,a,b,c,d,e)
72 #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)
73 #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)
74 #define ITextServices_OnTxInplaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInplaceActivate(This,a)
75 #define ITextServices_OnTxInplaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInplaceDeactivate(This)
76 #define ITextServices_OnTxUIActivate(This) TXTSERV_VTABLE(This)->OnTxUIActivate(This)
77 #define ITextServices_OnTxUIDeactivate(This) TXTSERV_VTABLE(This)->OnTxUIDeactivate(This)
78 #define ITextServices_TxGetText(This,a) TXTSERV_VTABLE(This)->TxGetText(This,a)
79 #define ITextServices_TxSetText(This,a) TXTSERV_VTABLE(This)->TxSetText(This,a)
80 #define ITextServices_TxGetCurrentTargetX(This,a) TXTSERV_VTABLE(This)->TxGetCurrentTargetX(This,a)
81 #define ITextServices_TxGetBaseLinePos(This,a) TXTSERV_VTABLE(This)->TxGetBaseLinePos(This,a)
82 #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)
83 #define ITextServices_TxGetDropTarget(This,a) TXTSERV_VTABLE(This)->TxGetDropTarget(This,a)
84 #define ITextServices_OnTxPropertyBitsChange(This,a,b) TXTSERV_VTABLE(This)->OnTxPropertyBitsChange(This,a,b)
85 #define ITextServices_TxGetCachedSize(This,a,b) TXTSERV_VTABLE(This)->TxGetCachedSize(This,a,b)
87 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
88 * function call traces of ITextHost. */
89 #define TRACECALL if(winetest_debug > 1) trace
91 /************************************************************************/
92 /* ITextHost implementation for conformance testing. */
94 typedef struct ITextHostTestImpl
96 ITextHost ITextHost_iface
;
100 static inline ITextHostTestImpl
*impl_from_ITextHost(ITextHost
*iface
)
102 return CONTAINING_RECORD(iface
, ITextHostTestImpl
, ITextHost_iface
);
105 static HRESULT WINAPI
ITextHostImpl_QueryInterface(ITextHost
*iface
,
109 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
111 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, pIID_ITextHost
)) {
113 ITextHost_AddRef((ITextHost
*)*ppvObject
);
117 return E_NOINTERFACE
;
120 static ULONG WINAPI
ITextHostImpl_AddRef(ITextHost
*iface
)
122 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
123 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
127 static ULONG WINAPI
ITextHostImpl_Release(ITextHost
*iface
)
129 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
130 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
141 static HDC WINAPI
ITextHostImpl_TxGetDC(ITextHost
*iface
)
143 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
144 TRACECALL("Call to TxGetDC(%p)\n", This
);
148 static INT WINAPI
ITextHostImpl_TxReleaseDC(ITextHost
*iface
,
151 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
152 TRACECALL("Call to TxReleaseDC(%p)\n", This
);
156 static BOOL WINAPI
ITextHostImpl_TxShowScrollBar(ITextHost
*iface
,
160 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
161 TRACECALL("Call to TxShowScrollBar(%p, fnBar=%d, fShow=%d)\n",
166 static BOOL WINAPI
ITextHostImpl_TxEnableScrollBar(ITextHost
*iface
,
170 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
171 TRACECALL("Call to TxEnableScrollBar(%p, fuSBFlags=%d, fuArrowflags=%d)\n",
172 This
, fuSBFlags
, fuArrowflags
);
176 static BOOL WINAPI
ITextHostImpl_TxSetScrollRange(ITextHost
*iface
,
182 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
183 TRACECALL("Call to TxSetScrollRange(%p, fnBar=%d, nMinPos=%d, nMaxPos=%d, fRedraw=%d)\n",
184 This
, fnBar
, nMinPos
, nMaxPos
, fRedraw
);
188 static BOOL WINAPI
ITextHostImpl_TxSetScrollPos(ITextHost
*iface
,
193 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
194 TRACECALL("Call to TxSetScrollPos(%p, fnBar=%d, nPos=%d, fRedraw=%d)\n",
195 This
, fnBar
, nPos
, fRedraw
);
199 static void WINAPI
ITextHostImpl_TxInvalidateRect(ITextHost
*iface
,
203 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
204 TRACECALL("Call to TxInvalidateRect(%p, prc=%p, fMode=%d)\n",
208 static void WINAPI
ITextHostImpl_TxViewChange(ITextHost
*iface
, BOOL fUpdate
)
210 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
211 TRACECALL("Call to TxViewChange(%p, fUpdate=%d)\n",
215 static BOOL WINAPI
ITextHostImpl_TxCreateCaret(ITextHost
*iface
,
217 INT xWidth
, INT yHeight
)
219 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
220 TRACECALL("Call to TxCreateCaret(%p, nbmp=%p, xWidth=%d, yHeight=%d)\n",
221 This
, hbmp
, xWidth
, yHeight
);
225 static BOOL WINAPI
ITextHostImpl_TxShowCaret(ITextHost
*iface
, BOOL fShow
)
227 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
228 TRACECALL("Call to TxShowCaret(%p, fShow=%d)\n",
233 static BOOL WINAPI
ITextHostImpl_TxSetCaretPos(ITextHost
*iface
,
236 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
237 TRACECALL("Call to TxSetCaretPos(%p, x=%d, y=%d)\n", This
, x
, y
);
241 static BOOL WINAPI
ITextHostImpl_TxSetTimer(ITextHost
*iface
,
242 UINT idTimer
, UINT uTimeout
)
244 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
245 TRACECALL("Call to TxSetTimer(%p, idTimer=%u, uTimeout=%u)\n",
246 This
, idTimer
, uTimeout
);
250 static void WINAPI
ITextHostImpl_TxKillTimer(ITextHost
*iface
, UINT idTimer
)
252 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
253 TRACECALL("Call to TxKillTimer(%p, idTimer=%u)\n", This
, idTimer
);
256 static void WINAPI
ITextHostImpl_TxScrollWindowEx(ITextHost
*iface
,
264 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
265 TRACECALL("Call to TxScrollWindowEx(%p, %d, %d, %p, %p, %p, %p, %d)\n",
266 This
, dx
, dy
, lprcScroll
, lprcClip
, hRgnUpdate
, lprcUpdate
, fuScroll
);
269 static void WINAPI
ITextHostImpl_TxSetCapture(ITextHost
*iface
, BOOL fCapture
)
271 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
272 TRACECALL("Call to TxSetCapture(%p, fCapture=%d)\n", This
, fCapture
);
275 static void WINAPI
ITextHostImpl_TxSetFocus(ITextHost
*iface
)
277 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
278 TRACECALL("Call to TxSetFocus(%p)\n", This
);
281 static void WINAPI
ITextHostImpl_TxSetCursor(ITextHost
*iface
,
285 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
286 TRACECALL("Call to TxSetCursor(%p, hcur=%p, fText=%d)\n",
290 static BOOL WINAPI
ITextHostImpl_TxScreenToClient(ITextHost
*iface
,
293 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
294 TRACECALL("Call to TxScreenToClient(%p, lppt=%p)\n", This
, lppt
);
298 static BOOL WINAPI
ITextHostImpl_TxClientToScreen(ITextHost
*iface
,
301 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
302 TRACECALL("Call to TxClientToScreen(%p, lppt=%p)\n", This
, lppt
);
306 static HRESULT WINAPI
ITextHostImpl_TxActivate(ITextHost
*iface
,
309 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
310 TRACECALL("Call to TxActivate(%p, plOldState=%p)\n", This
, plOldState
);
314 static HRESULT WINAPI
ITextHostImpl_TxDeactivate(ITextHost
*iface
,
317 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
318 TRACECALL("Call to TxDeactivate(%p, lNewState=%d)\n", This
, lNewState
);
322 static HRESULT WINAPI
ITextHostImpl_TxGetClientRect(ITextHost
*iface
,
325 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
326 TRACECALL("Call to TxGetClientRect(%p, prc=%p)\n", This
, prc
);
330 static HRESULT WINAPI
ITextHostImpl_TxGetViewInset(ITextHost
*iface
,
333 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
334 TRACECALL("Call to TxGetViewInset(%p, prc=%p)\n", This
, prc
);
338 static HRESULT WINAPI
ITextHostImpl_TxGetCharFormat(ITextHost
*iface
,
339 const CHARFORMATW
**ppCF
)
341 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
342 TRACECALL("Call to TxGetCharFormat(%p, ppCF=%p)\n", This
, ppCF
);
346 static HRESULT WINAPI
ITextHostImpl_TxGetParaFormat(ITextHost
*iface
,
347 const PARAFORMAT
**ppPF
)
349 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
350 TRACECALL("Call to TxGetParaFormat(%p, ppPF=%p)\n", This
, ppPF
);
354 static COLORREF WINAPI
ITextHostImpl_TxGetSysColor(ITextHost
*iface
,
357 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
358 TRACECALL("Call to TxGetSysColor(%p, nIndex=%d)\n", This
, nIndex
);
362 static HRESULT WINAPI
ITextHostImpl_TxGetBackStyle(ITextHost
*iface
,
363 TXTBACKSTYLE
*pStyle
)
365 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
366 TRACECALL("Call to TxGetBackStyle(%p, pStyle=%p)\n", This
, pStyle
);
370 static HRESULT WINAPI
ITextHostImpl_TxGetMaxLength(ITextHost
*iface
,
373 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
374 TRACECALL("Call to TxGetMaxLength(%p, pLength=%p)\n", This
, pLength
);
378 static HRESULT WINAPI
ITextHostImpl_TxGetScrollBars(ITextHost
*iface
,
381 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
382 TRACECALL("Call to TxGetScrollBars(%p, pdwScrollBar=%p)\n",
387 static HRESULT WINAPI
ITextHostImpl_TxGetPasswordChar(ITextHost
*iface
,
390 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
391 TRACECALL("Call to TxGetPasswordChar(%p, pch=%p)\n", This
, pch
);
395 static HRESULT WINAPI
ITextHostImpl_TxGetAcceleratorPos(ITextHost
*iface
,
398 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
399 TRACECALL("Call to TxGetAcceleratorPos(%p, pch=%p)\n", This
, pch
);
403 static HRESULT WINAPI
ITextHostImpl_TxGetExtent(ITextHost
*iface
,
406 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
407 TRACECALL("Call to TxGetExtent(%p, lpExtent=%p)\n", This
, lpExtent
);
411 static HRESULT WINAPI
ITextHostImpl_OnTxCharFormatChange(ITextHost
*iface
,
412 const CHARFORMATW
*pcf
)
414 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
415 TRACECALL("Call to OnTxCharFormatChange(%p, pcf=%p)\n", This
, pcf
);
419 static HRESULT WINAPI
ITextHostImpl_OnTxParaFormatChange(ITextHost
*iface
,
420 const PARAFORMAT
*ppf
)
422 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
423 TRACECALL("Call to OnTxParaFormatChange(%p, ppf=%p)\n", This
, ppf
);
427 /* This must return S_OK for the native ITextServices object to
429 static HRESULT WINAPI
ITextHostImpl_TxGetPropertyBits(ITextHost
*iface
,
433 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
434 TRACECALL("Call to TxGetPropertyBits(%p, dwMask=0x%08x, pdwBits=%p)\n",
435 This
, dwMask
, pdwBits
);
440 static HRESULT WINAPI
ITextHostImpl_TxNotify(ITextHost
*iface
, DWORD iNotify
,
443 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
444 TRACECALL("Call to TxNotify(%p, iNotify=%d, pv=%p)\n", This
, iNotify
, pv
);
448 static HIMC WINAPI
ITextHostImpl_TxImmGetContext(ITextHost
*iface
)
450 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
451 TRACECALL("Call to TxImmGetContext(%p)\n", This
);
455 static void WINAPI
ITextHostImpl_TxImmReleaseContext(ITextHost
*iface
, HIMC himc
)
457 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
458 TRACECALL("Call to TxImmReleaseContext(%p, himc=%p)\n", This
, himc
);
461 /* This function must set the variable pointed to by *lSelBarWidth.
462 Otherwise an uninitialized value will be used to calculate
463 positions and sizes even if E_NOTIMPL is returned. */
464 static HRESULT WINAPI
ITextHostImpl_TxGetSelectionBarWidth(ITextHost
*iface
,
467 ITextHostTestImpl
*This
= impl_from_ITextHost(iface
);
468 TRACECALL("Call to TxGetSelectionBarWidth(%p, lSelBarWidth=%p)\n",
474 static ITextHostVtbl itextHostVtbl
= {
475 ITextHostImpl_QueryInterface
,
476 ITextHostImpl_AddRef
,
477 ITextHostImpl_Release
,
478 ITextHostImpl_TxGetDC
,
479 ITextHostImpl_TxReleaseDC
,
480 ITextHostImpl_TxShowScrollBar
,
481 ITextHostImpl_TxEnableScrollBar
,
482 ITextHostImpl_TxSetScrollRange
,
483 ITextHostImpl_TxSetScrollPos
,
484 ITextHostImpl_TxInvalidateRect
,
485 ITextHostImpl_TxViewChange
,
486 ITextHostImpl_TxCreateCaret
,
487 ITextHostImpl_TxShowCaret
,
488 ITextHostImpl_TxSetCaretPos
,
489 ITextHostImpl_TxSetTimer
,
490 ITextHostImpl_TxKillTimer
,
491 ITextHostImpl_TxScrollWindowEx
,
492 ITextHostImpl_TxSetCapture
,
493 ITextHostImpl_TxSetFocus
,
494 ITextHostImpl_TxSetCursor
,
495 ITextHostImpl_TxScreenToClient
,
496 ITextHostImpl_TxClientToScreen
,
497 ITextHostImpl_TxActivate
,
498 ITextHostImpl_TxDeactivate
,
499 ITextHostImpl_TxGetClientRect
,
500 ITextHostImpl_TxGetViewInset
,
501 ITextHostImpl_TxGetCharFormat
,
502 ITextHostImpl_TxGetParaFormat
,
503 ITextHostImpl_TxGetSysColor
,
504 ITextHostImpl_TxGetBackStyle
,
505 ITextHostImpl_TxGetMaxLength
,
506 ITextHostImpl_TxGetScrollBars
,
507 ITextHostImpl_TxGetPasswordChar
,
508 ITextHostImpl_TxGetAcceleratorPos
,
509 ITextHostImpl_TxGetExtent
,
510 ITextHostImpl_OnTxCharFormatChange
,
511 ITextHostImpl_OnTxParaFormatChange
,
512 ITextHostImpl_TxGetPropertyBits
,
513 ITextHostImpl_TxNotify
,
514 ITextHostImpl_TxImmGetContext
,
515 ITextHostImpl_TxImmReleaseContext
,
516 ITextHostImpl_TxGetSelectionBarWidth
519 static ITextServices
*txtserv
= NULL
;
520 static ITextHostTestImpl
*dummyTextHost
;
521 static void *wrapperCodeMem
= NULL
;
523 #include "pshpack1.h"
525 /* Code structure for x86 byte code */
528 BYTE pop_eax
; /* popl %eax */
529 BYTE push_ecx
; /* pushl %ecx */
530 BYTE push_eax
; /* pushl %eax */
531 BYTE jmp_func
; /* jmp $func */
533 } THISCALL_TO_STDCALL_THUNK
;
537 BYTE pop_eax
; /* popl %eax */
538 BYTE pop_ecx
; /* popl %ecx */
539 BYTE push_eax
; /* pushl %eax */
540 BYTE mov_vtable_eax
[2]; /* movl (%ecx), %eax */
541 BYTE jmp_eax
[2]; /* jmp *$vtablefunc_offset(%eax) */
542 int vtablefunc_offset
;
543 } STDCALL_TO_THISCALL_THUNK
;
547 static void setup_thiscall_wrappers(void)
552 THISCALL_TO_STDCALL_THUNK
*thunk
;
553 STDCALL_TO_THISCALL_THUNK
*thunk2
;
555 wrapperCodeMem
= VirtualAlloc(NULL
,
556 (sizeof(ITextHostVtbl
)/sizeof(void*) - 3)
557 * sizeof(THISCALL_TO_STDCALL_THUNK
)
558 +(sizeof(ITextServicesVtbl
)/sizeof(void*) - 3)
559 * sizeof(STDCALL_TO_THISCALL_THUNK
),
560 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
561 thunk
= wrapperCodeMem
;
563 /* Wrap all ITextHostImpl methods with code to perform a thiscall to
564 * stdcall conversion. The thiscall calling convention places the This
565 * pointer in ecx on the x86 platform, and the stdcall calling convention
566 * pushes the This pointer on the stack as the first argument.
568 * The byte code does the conversion then jumps to the real function.
570 * Each wrapper needs to be modified so that the function to jump to is
571 * modified in the byte code. */
573 /* Skip QueryInterface, AddRef, and Release native actually
574 * defined them with the stdcall calling convention. */
575 pVtable
= (void**)&itextHostVtbl
+ 3;
576 pVtableEnd
= (void**)(&itextHostVtbl
+ 1);
577 while (pVtable
!= pVtableEnd
) {
578 /* write byte code to executable memory */
579 thunk
->pop_eax
= 0x58; /* popl %eax */
580 thunk
->push_ecx
= 0x51; /* pushl %ecx */
581 thunk
->push_eax
= 0x50; /* pushl %eax */
582 thunk
->jmp_func
= 0xe9; /* jmp $func */
583 /* The address needs to be relative to the end of the jump instructions. */
584 thunk
->func
= (char*)*pVtable
- (char*)(&thunk
->func
+ 1);
590 /* Setup an ITextServices standard call vtable that will call the
591 * native thiscall vtable when the methods are called. */
593 /* QueryInterface, AddRef, and Release should be called directly on the
594 * real vtable since they use the stdcall calling convention. */
595 thunk2
= (STDCALL_TO_THISCALL_THUNK
*)thunk
;
596 pVtable
= (void**)&itextServicesStdcallVtbl
+ 3;
597 pVtableEnd
= (void**)(&itextServicesStdcallVtbl
+ 1);
598 while (pVtable
!= pVtableEnd
) {
599 /* write byte code to executable memory */
600 thunk2
->pop_eax
= 0x58; /* popl %eax */
601 thunk2
->pop_ecx
= 0x59; /* popl %ecx */
602 thunk2
->push_eax
= 0x50; /* pushl %eax */
603 thunk2
->mov_vtable_eax
[0] = 0x8b; /* movl (%ecx), %eax */
604 thunk2
->mov_vtable_eax
[1] = 0x01;
605 thunk2
->jmp_eax
[0] = 0xff; /* jmp *$vtablefunc_offset(%eax) */
606 thunk2
->jmp_eax
[1] = 0xa0;
607 thunk2
->vtablefunc_offset
= (char*)pVtable
- (char*)&itextServicesStdcallVtbl
;
612 #endif /* __i386__ */
615 /*************************************************************************/
616 /* Conformance test functions. */
618 /* Initialize the test texthost structure */
619 static BOOL
init_texthost(void)
623 PCreateTextServices pCreateTextServices
;
625 dummyTextHost
= CoTaskMemAlloc(sizeof(*dummyTextHost
));
626 if (dummyTextHost
== NULL
) {
627 skip("Insufficient memory to create ITextHost interface\n");
630 dummyTextHost
->ITextHost_iface
.lpVtbl
= &itextHostVtbl
;
631 dummyTextHost
->refCount
= 1;
633 /* MSDN states that an IUnknown object is returned by
634 CreateTextServices which is then queried to obtain a
635 ITextServices object. */
636 pCreateTextServices
= (void*)GetProcAddress(hmoduleRichEdit
, "CreateTextServices");
637 result
= (*pCreateTextServices
)(NULL
, &dummyTextHost
->ITextHost_iface
, &init
);
638 ok(result
== S_OK
, "Did not return S_OK when created (result = %x)\n", result
);
639 if (result
!= S_OK
) {
640 CoTaskMemFree(dummyTextHost
);
641 skip("CreateTextServices failed.\n");
645 result
= IUnknown_QueryInterface(init
, pIID_ITextServices
,
647 ok((result
== S_OK
) && (txtserv
!= NULL
), "Querying interface failed (result = %x, txtserv = %p)\n", result
, txtserv
);
648 IUnknown_Release(init
);
649 if (!((result
== S_OK
) && (txtserv
!= NULL
))) {
650 CoTaskMemFree(dummyTextHost
);
651 skip("Could not retrieve ITextServices interface\n");
658 static void free_texthost(void)
660 IUnknown_Release(txtserv
);
661 CoTaskMemFree(dummyTextHost
);
664 static void test_TxGetText(void)
669 if (!init_texthost())
672 hres
= ITextServices_TxGetText(txtserv
, &rettext
);
673 ok(hres
== S_OK
, "ITextServices_TxGetText failed (result = %x)\n", hres
);
678 static void test_TxSetText(void)
682 WCHAR settext
[] = {'T','e','s','t',0};
684 if (!init_texthost())
687 hres
= ITextServices_TxSetText(txtserv
, settext
);
688 ok(hres
== S_OK
, "ITextServices_TxSetText failed (result = %x)\n", hres
);
690 hres
= ITextServices_TxGetText(txtserv
, &rettext
);
691 ok(hres
== S_OK
, "ITextServices_TxGetText failed (result = %x)\n", hres
);
693 ok(SysStringLen(rettext
) == 4,
694 "String returned of wrong length (expected 4, got %d)\n", SysStringLen(rettext
));
695 ok(memcmp(rettext
,settext
,SysStringByteLen(rettext
)) == 0,
696 "String returned differs\n");
698 SysFreeString(rettext
);
702 static void test_TxGetNaturalSize(void) {
706 /* This value is used when calling TxGetNaturalSize. MSDN says
707 that this is not supported however a null pointer cannot be
708 used as it will cause a segmentation violation. The values in
709 the structure being pointed to are required to be INT_MAX
710 otherwise calculations can give wrong values. */
711 const SIZEL psizelExtent
= {INT_MAX
,INT_MAX
};
713 static const WCHAR oneA
[] = {'A',0};
715 /* Results of measurements */
718 /* The device context to do the tests in */
721 /* Variables with the text metric information */
722 INT charwidth_caps_text
[26];
723 TEXTMETRIC tmInfo_text
;
725 if (!init_texthost())
728 hdcDraw
= GetDC(NULL
);
731 /* Populate the metric strucs */
732 SetMapMode(hdcDraw
,MM_TEXT
);
733 GetTextMetrics(hdcDraw
, &tmInfo_text
);
734 SetLastError(0xdeadbeef);
735 ret
= GetCharWidth32(hdcDraw
,'A','Z',charwidth_caps_text
);
736 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
737 win_skip("GetCharWidth32 is not available\n");
741 /* Make measurements in MM_TEXT */
742 SetMapMode(hdcDraw
,MM_TEXT
);
745 result
= ITextServices_TxSetText(txtserv
, oneA
);
746 ok(result
== S_OK
, "ITextServices_TxSetText failed (result = %x)\n", result
);
747 if (result
!= S_OK
) {
748 skip("Could not set text\n");
752 SetLastError(0xdeadbeef);
753 result
= ITextServices_TxGetNaturalSize(txtserv
, DVASPECT_CONTENT
,
755 TXTNS_FITTOCONTENT
, &psizelExtent
,
757 todo_wine
ok(result
== S_OK
|| broken(result
== E_FAIL
), /* WINXP Arabic Language */
758 "TxGetNaturalSize gave unexpected return value (result = %x)\n", result
);
759 if (result
== S_OK
) {
760 todo_wine
ok(ydim
== tmInfo_text
.tmHeight
,
761 "Height calculated incorrectly (expected %d, got %d)\n",
762 tmInfo_text
.tmHeight
, ydim
);
763 /* The native DLL adds one pixel extra when calculating widths. */
764 todo_wine
ok(xdim
>= charwidth_caps_text
[0] && xdim
<= charwidth_caps_text
[0] + 1,
765 "Width calculated incorrectly (expected %d {+1}, got %d)\n",
766 charwidth_caps_text
[0], xdim
);
768 skip("TxGetNaturalSize measurements not performed (xdim = %d, ydim = %d, result = %x, error = %x)\n",
769 xdim
, ydim
, result
, GetLastError());
772 RestoreDC(hdcDraw
,1);
773 ReleaseDC(NULL
,hdcDraw
);
777 static void test_TxDraw(void)
779 HDC tmphdc
= GetDC(NULL
);
780 DWORD dwAspect
= DVASPECT_CONTENT
;
781 HDC hicTargetDev
= NULL
; /* Means "default" device */
782 DVTARGETDEVICE
*ptd
= NULL
;
783 void *pvAspect
= NULL
;
785 RECTL client
= {0,0,100,100};
787 if (!init_texthost())
791 result
= ITextServices_TxDraw(txtserv
, dwAspect
, 0, pvAspect
, ptd
,
792 tmphdc
, hicTargetDev
, &client
, NULL
,
794 ok(result
== S_OK
, "TxDraw failed (result = %x)\n", result
);
801 DEFINE_GUID(expected_iid_itextservices
, 0x8d33f740, 0xcf58, 0x11ce, 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5);
802 DEFINE_GUID(expected_iid_itexthost
, 0x13e670f4,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1);
803 DEFINE_GUID(expected_iid_itexthost2
, 0x13e670f5,0x1a5a,0x11cf,0xab,0xeb,0x00,0xaa,0x00,0xb6,0x5e,0xa1);
805 static void test_IIDs(void)
807 ok(IsEqualIID(pIID_ITextServices
, &expected_iid_itextservices
),
808 "unexpected value for IID_ITextServices: %s\n", debugstr_guid(pIID_ITextServices
));
809 ok(IsEqualIID(pIID_ITextHost
, &expected_iid_itexthost
),
810 "unexpected value for IID_ITextHost: %s\n", debugstr_guid(pIID_ITextHost
));
811 ok(IsEqualIID(pIID_ITextHost2
, &expected_iid_itexthost2
),
812 "unexpected value for IID_ITextHost2: %s\n", debugstr_guid(pIID_ITextHost2
));
818 setup_thiscall_wrappers();
820 /* Must explicitly LoadLibrary(). The test has no references to functions in
821 * RICHED20.DLL, so the linker doesn't actually link to it. */
822 hmoduleRichEdit
= LoadLibrary("RICHED20.DLL");
823 ok(hmoduleRichEdit
!= NULL
, "error: %d\n", (int) GetLastError());
825 pIID_ITextServices
= (IID
*)GetProcAddress(hmoduleRichEdit
, "IID_ITextServices");
826 pIID_ITextHost
= (IID
*)GetProcAddress(hmoduleRichEdit
, "IID_ITextHost");
827 pIID_ITextHost2
= (IID
*)GetProcAddress(hmoduleRichEdit
, "IID_ITextHost2");
836 test_TxGetNaturalSize();
839 if (wrapperCodeMem
) VirtualFree(wrapperCodeMem
, 0, MEM_RELEASE
);