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
;
39 /* Define C Macros for ITextServices calls. */
41 /* Use a special table for x86 machines to convert the thiscall
42 * calling convention. This isn't needed on other platforms. */
44 static ITextServicesVtbl itextServicesStdcallVtbl
;
45 #define TXTSERV_VTABLE(This) (&itextServicesStdcallVtbl)
47 #define TXTSERV_VTABLE(This) (This)->lpVtbl
50 #define ITextServices_TxSendMessage(This,a,b,c,d) TXTSERV_VTABLE(This)->TxSendMessage(This,a,b,c,d)
51 #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)
52 #define ITextServices_TxGetHScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetHScroll(This,a,b,c,d,e)
53 #define ITextServices_TxGetVScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetVScroll(This,a,b,c,d,e)
54 #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)
55 #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)
56 #define ITextServices_OnTxInplaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInplaceActivate(This,a)
57 #define ITextServices_OnTxInplaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInplaceDeactivate(This)
58 #define ITextServices_OnTxUIActivate(This) TXTSERV_VTABLE(This)->OnTxUIActivate(This)
59 #define ITextServices_OnTxUIDeactivate(This) TXTSERV_VTABLE(This)->OnTxUIDeactivate(This)
60 #define ITextServices_TxGetText(This,a) TXTSERV_VTABLE(This)->TxGetText(This,a)
61 #define ITextServices_TxSetText(This,a) TXTSERV_VTABLE(This)->TxSetText(This,a)
62 #define ITextServices_TxGetCurrentTargetX(This,a) TXTSERV_VTABLE(This)->TxGetCurrentTargetX(This,a)
63 #define ITextServices_TxGetBaseLinePos(This,a) TXTSERV_VTABLE(This)->TxGetBaseLinePos(This,a)
64 #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)
65 #define ITextServices_TxGetDropTarget(This,a) TXTSERV_VTABLE(This)->TxGetDropTarget(This,a)
66 #define ITextServices_OnTxPropertyBitsChange(This,a,b) TXTSERV_VTABLE(This)->OnTxPropertyBitsChange(This,a,b)
67 #define ITextServices_TxGetCachedSize(This,a,b) TXTSERV_VTABLE(This)->TxGetCachedSize(This,a,b)
69 /* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose
70 * function call traces of ITextHost. */
71 #define TRACECALL if(winetest_debug > 1) trace
73 /************************************************************************/
74 /* ITextHost implementation for conformance testing. */
76 typedef struct ITextHostTestImpl
78 ITextHostVtbl
*lpVtbl
;
82 static HRESULT WINAPI
ITextHostImpl_QueryInterface(ITextHost
*iface
,
86 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
88 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_ITextHost
)) {
90 ITextHost_AddRef((ITextHost
*)*ppvObject
);
97 static ULONG WINAPI
ITextHostImpl_AddRef(ITextHost
*iface
)
99 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
100 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
104 static ULONG WINAPI
ITextHostImpl_Release(ITextHost
*iface
)
106 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
107 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
118 static HDC WINAPI
ITextHostImpl_TxGetDC(ITextHost
*iface
)
120 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
121 TRACECALL("Call to TxGetDC(%p)\n", This
);
125 static INT WINAPI
ITextHostImpl_TxReleaseDC(ITextHost
*iface
,
128 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
129 TRACECALL("Call to TxReleaseDC(%p)\n", This
);
133 static BOOL WINAPI
ITextHostImpl_TxShowScrollBar(ITextHost
*iface
,
137 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
138 TRACECALL("Call to TxShowScrollBar(%p, fnBar=%d, fShow=%d)\n",
143 static BOOL WINAPI
ITextHostImpl_TxEnableScrollBar(ITextHost
*iface
,
147 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
148 TRACECALL("Call to TxEnableScrollBar(%p, fuSBFlags=%d, fuArrowflags=%d)\n",
149 This
, fuSBFlags
, fuArrowflags
);
153 static BOOL WINAPI
ITextHostImpl_TxSetScrollRange(ITextHost
*iface
,
159 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
160 TRACECALL("Call to TxSetScrollRange(%p, fnBar=%d, nMinPos=%d, nMaxPos=%d, fRedraw=%d)\n",
161 This
, fnBar
, nMinPos
, nMaxPos
, fRedraw
);
165 static BOOL WINAPI
ITextHostImpl_TxSetScrollPos(ITextHost
*iface
,
170 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
171 TRACECALL("Call to TxSetScrollPos(%p, fnBar=%d, nPos=%d, fRedraw=%d)\n",
172 This
, fnBar
, nPos
, fRedraw
);
176 static void WINAPI
ITextHostImpl_TxInvalidateRect(ITextHost
*iface
,
180 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
181 TRACECALL("Call to TxInvalidateRect(%p, prc=%p, fMode=%d)\n",
185 static void WINAPI
ITextHostImpl_TxViewChange(ITextHost
*iface
, BOOL fUpdate
)
187 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
188 TRACECALL("Call to TxViewChange(%p, fUpdate=%d)\n",
192 static BOOL WINAPI
ITextHostImpl_TxCreateCaret(ITextHost
*iface
,
194 INT xWidth
, INT yHeight
)
196 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
197 TRACECALL("Call to TxCreateCaret(%p, nbmp=%p, xWidth=%d, yHeight=%d)\n",
198 This
, hbmp
, xWidth
, yHeight
);
202 static BOOL WINAPI
ITextHostImpl_TxShowCaret(ITextHost
*iface
, BOOL fShow
)
204 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
205 TRACECALL("Call to TxShowCaret(%p, fShow=%d)\n",
210 static BOOL WINAPI
ITextHostImpl_TxSetCaretPos(ITextHost
*iface
,
213 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
214 TRACECALL("Call to TxSetCaretPos(%p, x=%d, y=%d)\n", This
, x
, y
);
218 static BOOL WINAPI
ITextHostImpl_TxSetTimer(ITextHost
*iface
,
219 UINT idTimer
, UINT uTimeout
)
221 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
222 TRACECALL("Call to TxSetTimer(%p, idTimer=%u, uTimeout=%u)\n",
223 This
, idTimer
, uTimeout
);
227 static void WINAPI
ITextHostImpl_TxKillTimer(ITextHost
*iface
, UINT idTimer
)
229 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
230 TRACECALL("Call to TxKillTimer(%p, idTimer=%u)\n", This
, idTimer
);
233 static void WINAPI
ITextHostImpl_TxScrollWindowEx(ITextHost
*iface
,
241 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
242 TRACECALL("Call to TxScrollWindowEx(%p, %d, %d, %p, %p, %p, %p, %d)\n",
243 This
, dx
, dy
, lprcScroll
, lprcClip
, hRgnUpdate
, lprcUpdate
, fuScroll
);
246 static void WINAPI
ITextHostImpl_TxSetCapture(ITextHost
*iface
, BOOL fCapture
)
248 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
249 TRACECALL("Call to TxSetCapture(%p, fCapture=%d)\n", This
, fCapture
);
252 static void WINAPI
ITextHostImpl_TxSetFocus(ITextHost
*iface
)
254 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
255 TRACECALL("Call to TxSetFocus(%p)\n", This
);
258 static void WINAPI
ITextHostImpl_TxSetCursor(ITextHost
*iface
,
262 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
263 TRACECALL("Call to TxSetCursor(%p, hcur=%p, fText=%d)\n",
267 static BOOL WINAPI
ITextHostImpl_TxScreenToClient(ITextHost
*iface
,
270 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
271 TRACECALL("Call to TxScreenToClient(%p, lppt=%p)\n", This
, lppt
);
275 static BOOL WINAPI
ITextHostImpl_TxClientToScreen(ITextHost
*iface
,
278 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
279 TRACECALL("Call to TxClientToScreen(%p, lppt=%p)\n", This
, lppt
);
283 static HRESULT WINAPI
ITextHostImpl_TxActivate(ITextHost
*iface
,
286 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
287 TRACECALL("Call to TxActivate(%p, plOldState=%p)\n", This
, plOldState
);
291 static HRESULT WINAPI
ITextHostImpl_TxDeactivate(ITextHost
*iface
,
294 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
295 TRACECALL("Call to TxDeactivate(%p, lNewState=%d)\n", This
, lNewState
);
299 static HRESULT WINAPI
ITextHostImpl_TxGetClientRect(ITextHost
*iface
,
302 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
303 TRACECALL("Call to TxGetClientRect(%p, prc=%p)\n", This
, prc
);
307 static HRESULT WINAPI
ITextHostImpl_TxGetViewInset(ITextHost
*iface
,
310 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
311 TRACECALL("Call to TxGetViewInset(%p, prc=%p)\n", This
, prc
);
315 static HRESULT WINAPI
ITextHostImpl_TxGetCharFormat(ITextHost
*iface
,
316 const CHARFORMATW
**ppCF
)
318 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
319 TRACECALL("Call to TxGetCharFormat(%p, ppCF=%p)\n", This
, ppCF
);
323 static HRESULT WINAPI
ITextHostImpl_TxGetParaFormat(ITextHost
*iface
,
324 const PARAFORMAT
**ppPF
)
326 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
327 TRACECALL("Call to TxGetParaFormat(%p, ppPF=%p)\n", This
, ppPF
);
331 static COLORREF WINAPI
ITextHostImpl_TxGetSysColor(ITextHost
*iface
,
334 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
335 TRACECALL("Call to TxGetSysColor(%p, nIndex=%d)\n", This
, nIndex
);
339 static HRESULT WINAPI
ITextHostImpl_TxGetBackStyle(ITextHost
*iface
,
340 TXTBACKSTYLE
*pStyle
)
342 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
343 TRACECALL("Call to TxGetBackStyle(%p, pStyle=%p)\n", This
, pStyle
);
347 static HRESULT WINAPI
ITextHostImpl_TxGetMaxLength(ITextHost
*iface
,
350 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
351 TRACECALL("Call to TxGetMaxLength(%p, pLength=%p)\n", This
, pLength
);
355 static HRESULT WINAPI
ITextHostImpl_TxGetScrollBars(ITextHost
*iface
,
358 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
359 TRACECALL("Call to TxGetScrollBars(%p, pdwScrollBar=%p)\n",
364 static HRESULT WINAPI
ITextHostImpl_TxGetPasswordChar(ITextHost
*iface
,
367 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
368 TRACECALL("Call to TxGetPasswordChar(%p, pch=%p)\n", This
, pch
);
372 static HRESULT WINAPI
ITextHostImpl_TxGetAcceleratorPos(ITextHost
*iface
,
375 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
376 TRACECALL("Call to TxGetAcceleratorPos(%p, pch=%p)\n", This
, pch
);
380 static HRESULT WINAPI
ITextHostImpl_TxGetExtent(ITextHost
*iface
,
383 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
384 TRACECALL("Call to TxGetExtent(%p, lpExtent=%p)\n", This
, lpExtent
);
388 static HRESULT WINAPI
ITextHostImpl_OnTxCharFormatChange(ITextHost
*iface
,
389 const CHARFORMATW
*pcf
)
391 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
392 TRACECALL("Call to OnTxCharFormatChange(%p, pcf=%p)\n", This
, pcf
);
396 static HRESULT WINAPI
ITextHostImpl_OnTxParaFormatChange(ITextHost
*iface
,
397 const PARAFORMAT
*ppf
)
399 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
400 TRACECALL("Call to OnTxParaFormatChange(%p, ppf=%p)\n", This
, ppf
);
404 /* This must return S_OK for the native ITextServices object to
406 static HRESULT WINAPI
ITextHostImpl_TxGetPropertyBits(ITextHost
*iface
,
410 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
411 TRACECALL("Call to TxGetPropertyBits(%p, dwMask=0x%08x, pdwBits=%p)\n",
412 This
, dwMask
, pdwBits
);
417 static HRESULT WINAPI
ITextHostImpl_TxNotify(ITextHost
*iface
, DWORD iNotify
,
420 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
421 TRACECALL("Call to TxNotify(%p, iNotify=%d, pv=%p)\n", This
, iNotify
, pv
);
425 static HIMC WINAPI
ITextHostImpl_TxImmGetContext(ITextHost
*iface
)
427 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
428 TRACECALL("Call to TxImmGetContext(%p)\n", This
);
432 static void WINAPI
ITextHostImpl_TxImmReleaseContext(ITextHost
*iface
, HIMC himc
)
434 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
435 TRACECALL("Call to TxImmReleaseContext(%p, himc=%p)\n", This
, himc
);
438 /* This function must set the variable pointed to by *lSelBarWidth.
439 Otherwise an uninitalized value will be used to calculate
440 positions and sizes even if E_NOTIMPL is returned. */
441 static HRESULT WINAPI
ITextHostImpl_TxGetSelectionBarWidth(ITextHost
*iface
,
444 ITextHostTestImpl
*This
= (ITextHostTestImpl
*)iface
;
445 TRACECALL("Call to TxGetSelectionBarWidth(%p, lSelBarWidth=%p)\n",
451 static ITextHostVtbl itextHostVtbl
= {
452 ITextHostImpl_QueryInterface
,
453 ITextHostImpl_AddRef
,
454 ITextHostImpl_Release
,
455 ITextHostImpl_TxGetDC
,
456 ITextHostImpl_TxReleaseDC
,
457 ITextHostImpl_TxShowScrollBar
,
458 ITextHostImpl_TxEnableScrollBar
,
459 ITextHostImpl_TxSetScrollRange
,
460 ITextHostImpl_TxSetScrollPos
,
461 ITextHostImpl_TxInvalidateRect
,
462 ITextHostImpl_TxViewChange
,
463 ITextHostImpl_TxCreateCaret
,
464 ITextHostImpl_TxShowCaret
,
465 ITextHostImpl_TxSetCaretPos
,
466 ITextHostImpl_TxSetTimer
,
467 ITextHostImpl_TxKillTimer
,
468 ITextHostImpl_TxScrollWindowEx
,
469 ITextHostImpl_TxSetCapture
,
470 ITextHostImpl_TxSetFocus
,
471 ITextHostImpl_TxSetCursor
,
472 ITextHostImpl_TxScreenToClient
,
473 ITextHostImpl_TxClientToScreen
,
474 ITextHostImpl_TxActivate
,
475 ITextHostImpl_TxDeactivate
,
476 ITextHostImpl_TxGetClientRect
,
477 ITextHostImpl_TxGetViewInset
,
478 ITextHostImpl_TxGetCharFormat
,
479 ITextHostImpl_TxGetParaFormat
,
480 ITextHostImpl_TxGetSysColor
,
481 ITextHostImpl_TxGetBackStyle
,
482 ITextHostImpl_TxGetMaxLength
,
483 ITextHostImpl_TxGetScrollBars
,
484 ITextHostImpl_TxGetPasswordChar
,
485 ITextHostImpl_TxGetAcceleratorPos
,
486 ITextHostImpl_TxGetExtent
,
487 ITextHostImpl_OnTxCharFormatChange
,
488 ITextHostImpl_OnTxParaFormatChange
,
489 ITextHostImpl_TxGetPropertyBits
,
490 ITextHostImpl_TxNotify
,
491 ITextHostImpl_TxImmGetContext
,
492 ITextHostImpl_TxImmReleaseContext
,
493 ITextHostImpl_TxGetSelectionBarWidth
496 static ITextServices
*txtserv
= NULL
;
497 static ITextHostTestImpl
*dummyTextHost
;
498 static void *wrapperCodeMem
= NULL
;
500 #include "pshpack1.h"
502 /* Code structure for x86 byte code */
505 BYTE pop_eax
; /* popl %eax */
506 BYTE push_ecx
; /* pushl %ecx */
507 BYTE push_eax
; /* pushl %eax */
508 BYTE jmp_func
; /* jmp $func */
510 } THISCALL_TO_STDCALL_THUNK
;
514 BYTE pop_eax
; /* popl %eax */
515 BYTE pop_ecx
; /* popl %ecx */
516 BYTE push_eax
; /* pushl %eax */
517 BYTE mov_vtable_eax
[2]; /* movl (%ecx), %eax */
518 BYTE jmp_eax
[2]; /* jmp *$vtablefunc_offset(%eax) */
519 int vtablefunc_offset
;
520 } STDCALL_TO_THISCALL_THUNK
;
524 static void setup_thiscall_wrappers(void)
529 THISCALL_TO_STDCALL_THUNK
*thunk
;
530 STDCALL_TO_THISCALL_THUNK
*thunk2
;
532 wrapperCodeMem
= VirtualAlloc(NULL
,
533 (sizeof(ITextHostVtbl
)/sizeof(void*) - 3)
534 * sizeof(THISCALL_TO_STDCALL_THUNK
)
535 +(sizeof(ITextServicesVtbl
)/sizeof(void*) - 3)
536 * sizeof(STDCALL_TO_THISCALL_THUNK
),
537 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
538 thunk
= wrapperCodeMem
;
540 /* Wrap all ITextHostImpl methods with code to perform a thiscall to
541 * stdcall conversion. The thiscall calling convention places the This
542 * pointer in ecx on the x86 platform, and the stdcall calling convention
543 * pushes the This pointer on the stack as the first argument.
545 * The byte code does the conversion then jumps to the real function.
547 * Each wrapper needs to be modified so that the function to jump to is
548 * modified in the byte code. */
550 /* Skip QueryInterface, AddRef, and Release native actually
551 * defined them with the stdcall calling convention. */
552 pVtable
= (void**)&itextHostVtbl
+ 3;
553 pVtableEnd
= (void**)(&itextHostVtbl
+ 1);
554 while (pVtable
!= pVtableEnd
) {
555 /* write byte code to executable memory */
556 thunk
->pop_eax
= 0x58; /* popl %eax */
557 thunk
->push_ecx
= 0x51; /* pushl %ecx */
558 thunk
->push_eax
= 0x50; /* pushl %eax */
559 thunk
->jmp_func
= 0xe9; /* jmp $func */
560 /* The address needs to be relative to the end of the jump instructions. */
561 thunk
->func
= (char*)*pVtable
- (char*)(&thunk
->func
+ 1);
567 /* Setup an ITextServices standard call vtable that will call the
568 * native thiscall vtable when the methods are called. */
570 /* QueryInterface, AddRef, and Release should be called directly on the
571 * real vtable since they use the stdcall calling convention. */
572 thunk2
= (STDCALL_TO_THISCALL_THUNK
*)thunk
;
573 pVtable
= (void**)&itextServicesStdcallVtbl
+ 3;
574 pVtableEnd
= (void**)(&itextServicesStdcallVtbl
+ 1);
575 while (pVtable
!= pVtableEnd
) {
576 /* write byte code to executable memory */
577 thunk2
->pop_eax
= 0x58; /* popl %eax */
578 thunk2
->pop_ecx
= 0x59; /* popl %ecx */
579 thunk2
->push_eax
= 0x50; /* pushl %eax */
580 thunk2
->mov_vtable_eax
[0] = 0x8b; /* movl (%ecx), %eax */
581 thunk2
->mov_vtable_eax
[1] = 0x01;
582 thunk2
->jmp_eax
[0] = 0xff; /* jmp *$vtablefunc_offset(%eax) */
583 thunk2
->jmp_eax
[1] = 0xa0;
584 thunk2
->vtablefunc_offset
= (char*)pVtable
- (char*)&itextServicesStdcallVtbl
;
589 #endif /* __i386__ */
592 /*************************************************************************/
593 /* Conformance test functions. */
595 /* Initialize the test texthost structure */
596 static BOOL
init_texthost(void)
600 PCreateTextServices pCreateTextServices
;
602 dummyTextHost
= CoTaskMemAlloc(sizeof(*dummyTextHost
));
603 if (dummyTextHost
== NULL
) {
604 skip("Insufficient memory to create ITextHost interface\n");
607 dummyTextHost
->lpVtbl
= &itextHostVtbl
;
608 dummyTextHost
->refCount
= 1;
610 /* MSDN states that an IUnknown object is returned by
611 CreateTextServices which is then queried to obtain a
612 ITextServices object. */
613 pCreateTextServices
= (void*)GetProcAddress(hmoduleRichEdit
, "CreateTextServices");
614 result
= (*pCreateTextServices
)(NULL
,(ITextHost
*)dummyTextHost
, &init
);
615 ok(result
== S_OK
, "Did not return OK when created. Returned %x\n", result
);
616 if (result
!= S_OK
) {
617 CoTaskMemFree(dummyTextHost
);
618 skip("CreateTextServices failed.\n");
622 result
= IUnknown_QueryInterface(init
, &IID_ITextServices
,
624 ok((result
== S_OK
) && (txtserv
!= NULL
), "Querying interface failed\n");
625 IUnknown_Release(init
);
626 if (!((result
== S_OK
) && (txtserv
!= NULL
))) {
627 CoTaskMemFree(dummyTextHost
);
628 skip("Could not retrieve ITextServices interface\n");
635 static void test_TxGetText(void)
640 if (!init_texthost())
643 hres
= ITextServices_TxGetText(txtserv
, &rettext
);
644 ok(hres
== S_OK
, "ITextServices_TxGetText failed\n");
646 IUnknown_Release(txtserv
);
647 CoTaskMemFree(dummyTextHost
);
650 static void test_TxSetText(void)
654 WCHAR settext
[] = {'T','e','s','t',0};
656 if (!init_texthost())
659 hres
= ITextServices_TxSetText(txtserv
, settext
);
660 ok(hres
== S_OK
, "ITextServices_TxSetText failed\n");
662 hres
= ITextServices_TxGetText(txtserv
, &rettext
);
663 ok(hres
== S_OK
, "ITextServices_TxGetText failed\n");
665 ok(SysStringLen(rettext
) == 4,
666 "String returned of wrong length\n");
667 ok(memcmp(rettext
,settext
,SysStringByteLen(rettext
)) == 0,
668 "String returned differs\n");
670 IUnknown_Release(txtserv
);
671 CoTaskMemFree(dummyTextHost
);
674 static void test_TxGetNaturalSize(void) {
678 /* This value is used when calling TxGetNaturalSize. MSDN says
679 that this is not supported however a null pointer cannot be
680 used as it will cause a segmentation violation. The values in
681 the structure being pointed to are required to be INT_MAX
682 otherwise calculations can give wrong values. */
683 const SIZEL psizelExtent
= {INT_MAX
,INT_MAX
};
685 static const WCHAR oneA
[] = {'A',0};
687 /* Results of measurements */
690 /* The device context to do the tests in */
693 /* Variables with the text metric information */
694 INT charwidth_caps_text
[26];
695 TEXTMETRIC tmInfo_text
;
697 if (!init_texthost())
700 hdcDraw
= GetDC(NULL
);
703 /* Populate the metric strucs */
704 SetMapMode(hdcDraw
,MM_TEXT
);
705 GetTextMetrics(hdcDraw
, &tmInfo_text
);
706 SetLastError(0xdeadbeef);
707 ret
= GetCharWidth32(hdcDraw
,'A','Z',charwidth_caps_text
);
708 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
709 win_skip("GetCharWidth32 is not available\n");
710 RestoreDC(hdcDraw
,1);
711 ReleaseDC(NULL
,hdcDraw
);
715 /* Make measurements in MM_TEXT */
716 SetMapMode(hdcDraw
,MM_TEXT
);
719 result
= ITextServices_TxSetText(txtserv
, oneA
);
720 ok(result
== S_OK
, "ITextServices_TxSetText failed\n");
722 result
= ITextServices_TxGetNaturalSize(txtserv
, DVASPECT_CONTENT
,
724 TXTNS_FITTOCONTENT
, &psizelExtent
,
726 todo_wine
ok(result
== S_OK
, "TxGetNaturalSize failed\n");
727 todo_wine
ok(ydim
== tmInfo_text
.tmHeight
,
728 "Height calculated incorrectly (expected %d, got %d)\n",
729 tmInfo_text
.tmHeight
, ydim
);
730 /* The native DLL adds one pixel extra when calculating widths. */
731 todo_wine
ok(xdim
>= charwidth_caps_text
[0] && xdim
<= charwidth_caps_text
[0] + 1,
732 "Width calculated incorrectly (expected %d {+1}, got %d)\n",
733 charwidth_caps_text
[0], xdim
);
735 RestoreDC(hdcDraw
,1);
736 ReleaseDC(NULL
,hdcDraw
);
738 IUnknown_Release(txtserv
);
739 CoTaskMemFree(dummyTextHost
);
744 setup_thiscall_wrappers();
746 /* Must explicitly LoadLibrary(). The test has no references to functions in
747 * RICHED20.DLL, so the linker doesn't actually link to it. */
748 hmoduleRichEdit
= LoadLibrary("RICHED20.DLL");
749 ok(hmoduleRichEdit
!= NULL
, "error: %d\n", (int) GetLastError());
753 IUnknown_Release(txtserv
);
754 CoTaskMemFree(dummyTextHost
);
758 test_TxGetNaturalSize();
760 if (wrapperCodeMem
) VirtualFree(wrapperCodeMem
, 0, MEM_RELEASE
);