1 /*
2  * Tests for IRichEditOle and friends.
3  *
4  * Copyright 2008 Google (Dan Hipschman)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define COBJMACROS
22 
23 #include <stdarg.h>
24 
25 #include <windef.h>
26 #include <winbase.h>
27 #include <wingdi.h>
28 #include <winuser.h>
29 #include <initguid.h>
30 #include <ole2.h>
31 #include <richedit.h>
32 #include <richole.h>
33 #include <tom.h>
34 #include <wine/test.h>
35 
36 static HMODULE hmoduleRichEdit;
37 
38 DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
39 
40 static const WCHAR sysW[] = {'S','y','s','t','e','m',0};
41 
42 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
43 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
44 {
45     ULONG rc;
46     IUnknown_AddRef(obj);
47     rc = IUnknown_Release(obj);
48     ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
49 }
50 
51 static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent)
52 {
53   HWND hwnd = CreateWindowA(lpClassName, NULL,
54                             dwStyle | WS_POPUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE,
55                             0, 0, 200, 60, parent, NULL, hmoduleRichEdit, NULL);
56   ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
57   return hwnd;
58 }
59 
60 static HWND new_richedit(HWND parent)
61 {
62   return new_window(RICHEDIT_CLASS20A, ES_MULTILINE, parent);
63 }
64 
65 static BOOL touch_file(LPCWSTR filename)
66 {
67   HANDLE file;
68 
69   file = CreateFileW(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
70 		     CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
71 
72   if(file == INVALID_HANDLE_VALUE)
73     return FALSE;
74   CloseHandle(file);
75   return TRUE;
76 }
77 
78 static BOOL is_existing_file(LPCWSTR filename)
79 {
80   HANDLE file;
81 
82   file = CreateFileW(filename, GENERIC_READ, 0, NULL,
83 		     OPEN_EXISTING, 0, NULL);
84   if(file == INVALID_HANDLE_VALUE)
85     return FALSE;
86   CloseHandle(file);
87   return TRUE;
88 }
89 
90 static void create_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txtDoc,
91                               ITextSelection **txtSel)
92 {
93   *w = new_richedit(NULL);
94   SendMessageA(*w, EM_GETOLEINTERFACE, 0, (LPARAM)reOle);
95   IRichEditOle_QueryInterface(*reOle, &IID_ITextDocument,
96                                  (void **) txtDoc);
97   ITextDocument_GetSelection(*txtDoc, txtSel);
98 }
99 
100 static void release_interfaces(HWND *w, IRichEditOle **reOle, ITextDocument **txtDoc,
101                                ITextSelection **txtSel)
102 {
103   if(txtSel)
104     ITextSelection_Release(*txtSel);
105   ITextDocument_Release(*txtDoc);
106   IRichEditOle_Release(*reOle);
107   DestroyWindow(*w);
108 }
109 
110 static ULONG get_refcount(IUnknown *iface)
111 {
112   IUnknown_AddRef(iface);
113   return IUnknown_Release(iface);
114 }
115 
116 static void test_Interfaces(void)
117 {
118   IRichEditOle *reOle = NULL, *reOle1 = NULL;
119   ITextDocument *txtDoc = NULL;
120   ITextSelection *txtSel = NULL, *txtSel2;
121   IUnknown *punk;
122   HRESULT hres;
123   LRESULT res;
124   HWND w;
125   ULONG refcount;
126 
127   w = new_richedit(NULL);
128   if (!w) {
129     skip("Couldn't create window\n");
130     return;
131   }
132 
133   res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle);
134   ok(res, "SendMessage\n");
135   ok(reOle != NULL, "EM_GETOLEINTERFACE\n");
136   EXPECT_REF(reOle, 2);
137 
138   res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle1);
139   ok(res == 1, "SendMessage\n");
140   ok(reOle1 == reOle, "Should not return a new IRichEditOle interface\n");
141   EXPECT_REF(reOle, 3);
142 
143   hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument,
144                                  (void **) &txtDoc);
145   ok(hres == S_OK, "IRichEditOle_QueryInterface\n");
146   ok(txtDoc != NULL, "IRichEditOle_QueryInterface\n");
147 
148   hres = ITextDocument_GetSelection(txtDoc, NULL);
149   ok(hres == E_INVALIDARG, "ITextDocument_GetSelection: 0x%x\n", hres);
150 
151   EXPECT_REF(txtDoc, 4);
152 
153   hres = ITextDocument_GetSelection(txtDoc, &txtSel);
154   ok(hres == S_OK, "got 0x%08x\n", hres);
155 
156   EXPECT_REF(txtDoc, 4);
157   EXPECT_REF(txtSel, 2);
158 
159   hres = ITextDocument_GetSelection(txtDoc, &txtSel2);
160   ok(hres == S_OK, "got 0x%08x\n", hres);
161   ok(txtSel2 == txtSel, "got %p, %p\n", txtSel, txtSel2);
162 
163   EXPECT_REF(txtDoc, 4);
164   EXPECT_REF(txtSel, 3);
165 
166   ITextSelection_Release(txtSel2);
167 
168   punk = NULL;
169   hres = ITextSelection_QueryInterface(txtSel, &IID_ITextSelection, (void **) &punk);
170   ok(hres == S_OK, "ITextSelection_QueryInterface\n");
171   ok(punk != NULL, "ITextSelection_QueryInterface\n");
172   IUnknown_Release(punk);
173 
174   punk = NULL;
175   hres = ITextSelection_QueryInterface(txtSel, &IID_ITextRange, (void **) &punk);
176   ok(hres == S_OK, "ITextSelection_QueryInterface\n");
177   ok(punk != NULL, "ITextSelection_QueryInterface\n");
178   IUnknown_Release(punk);
179 
180   punk = NULL;
181   hres = ITextSelection_QueryInterface(txtSel, &IID_IDispatch, (void **) &punk);
182   ok(hres == S_OK, "ITextSelection_QueryInterface\n");
183   ok(punk != NULL, "ITextSelection_QueryInterface\n");
184   IUnknown_Release(punk);
185 
186   punk = NULL;
187   hres = IRichEditOle_QueryInterface(reOle, &IID_IOleClientSite, (void **) &punk);
188   ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
189 
190   punk = NULL;
191   hres = IRichEditOle_QueryInterface(reOle, &IID_IOleWindow, (void **) &punk);
192   ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
193 
194   punk = NULL;
195   hres = IRichEditOle_QueryInterface(reOle, &IID_IOleInPlaceSite, (void **) &punk);
196   ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
197 
198   ITextDocument_Release(txtDoc);
199   IRichEditOle_Release(reOle);
200   refcount = IRichEditOle_Release(reOle);
201   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
202   DestroyWindow(w);
203 
204   /* Methods should return CO_E_RELEASED if the backing document has
205      been released.  One test should suffice.  */
206   hres = ITextSelection_CanEdit(txtSel, NULL);
207   ok(hres == CO_E_RELEASED, "ITextSelection after ITextDocument destroyed\n");
208 
209   ITextSelection_Release(txtSel);
210 }
211 
212 static void test_ITextDocument_Open(void)
213 {
214   IRichEditOle *reOle = NULL;
215   ITextDocument *txtDoc = NULL;
216   ITextSelection *txtSel = NULL;
217   HRESULT hres;
218   HWND w;
219   HANDLE hFile;
220   VARIANT testfile;
221   WCHAR filename[] = {'t', 'e', 's', 't','.','t','x','t', 0};
222   int result;
223   DWORD dw;
224   static const CHAR chACP[] = "TestSomeText";
225   static const CHAR chUTF8[] = "\xef\xbb\xbfTextWithUTF8BOM";
226   static const WCHAR chUTF16[] = {0xfeff, 'T', 'e', 's', 't', 'S', 'o', 'm',
227                                   'e', 'T', 'e', 'x', 't', 0};
228 
229 #define MAX_BUF_LEN 1024
230   CHAR bufACP[MAX_BUF_LEN];
231   WCHAR bufUnicode[MAX_BUF_LEN];
232 
233   static const int tomConstantsSingle[] =
234     {
235       tomReadOnly, tomShareDenyRead, tomShareDenyWrite,
236       tomCreateAlways, tomOpenExisting, tomOpenAlways,
237       tomTruncateExisting, tomRTF, tomText
238     };
239 
240   static const int tomConstantsMulti[] =
241     {
242       tomReadOnly|tomShareDenyRead|tomPasteFile, tomReadOnly|tomPasteFile,
243       tomReadOnly|tomShareDenyWrite|tomPasteFile,
244       tomReadOnly|tomShareDenyRead|tomShareDenyWrite|tomPasteFile, tomShareDenyWrite|tomPasteFile,
245       tomShareDenyRead|tomShareDenyWrite|tomPasteFile, tomShareDenyRead|tomPasteFile,
246       tomShareDenyRead|tomShareDenyWrite, tomReadOnly|tomShareDenyRead|tomShareDenyWrite,
247       tomReadOnly|tomShareDenyWrite, tomReadOnly|tomShareDenyRead
248     };
249 
250   int tomNumSingle =  sizeof(tomConstantsSingle)/sizeof(tomConstantsSingle[0]);
251   int tomNumMulti = sizeof(tomConstantsMulti)/sizeof(tomConstantsMulti[0]);
252   int i;
253 
254   V_VT(&testfile) = VT_BSTR;
255   V_BSTR(&testfile) = SysAllocString(filename);
256 
257   for(i=0; i < tomNumSingle; i++)
258     {
259       touch_file(filename);
260       create_interfaces(&w, &reOle, &txtDoc, &txtSel);
261       hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsSingle[i], CP_ACP);
262       todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
263          tomConstantsSingle[i], hres);
264       release_interfaces(&w, &reOle, &txtDoc, &txtSel);
265       DeleteFileW(filename);
266 
267       touch_file(filename);
268       create_interfaces(&w, &reOle, &txtDoc, &txtSel);
269       hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsSingle[i], CP_UTF8);
270       todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
271          tomConstantsSingle[i], hres);
272       release_interfaces(&w, &reOle, &txtDoc, &txtSel);
273       DeleteFileW(filename);
274     }
275 
276   for(i=0; i < tomNumMulti; i++)
277     {
278       touch_file(filename);
279       create_interfaces(&w, &reOle, &txtDoc, &txtSel);
280       hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsMulti[i], CP_ACP);
281       todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
282          tomConstantsMulti[i], hres);
283       release_interfaces(&w, &reOle, &txtDoc, &txtSel);
284       DeleteFileW(filename);
285 
286       touch_file(filename);
287       create_interfaces(&w, &reOle, &txtDoc, &txtSel);
288       hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsMulti[i], CP_UTF8);
289       todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
290          tomConstantsMulti[i], hres);
291       release_interfaces(&w, &reOle, &txtDoc, &txtSel);
292       DeleteFileW(filename);
293     }
294 
295   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
296   hres = ITextDocument_Open(txtDoc, &testfile, tomCreateAlways, CP_ACP);
297   todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
298   todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
299   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
300   DeleteFileW(filename);
301 
302   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
303   hres = ITextDocument_Open(txtDoc, &testfile, tomCreateAlways, CP_UTF8);
304   todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
305   todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
306   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
307   DeleteFileW(filename);
308 
309   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
310   hres = ITextDocument_Open(txtDoc, &testfile, tomOpenAlways, CP_ACP);
311   todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
312   todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
313   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
314   DeleteFileW(filename);
315 
316   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
317   hres = ITextDocument_Open(txtDoc, &testfile, tomOpenAlways, CP_UTF8);
318   todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
319   todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
320   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
321   DeleteFileW(filename);
322 
323   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
324   hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_ACP);
325   todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
326   todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
327   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
328   DeleteFileW(filename);
329 
330   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
331   hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_UTF8);
332   todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
333   todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
334   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
335   DeleteFileW(filename);
336 
337   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
338   touch_file(filename);
339   hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_ACP);
340   todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "ITextDocument_Open should fail Codepage:CP_ACP\n");
341   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
342   DeleteFileW(filename);
343 
344   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
345   touch_file(filename);
346   hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_UTF8);
347   todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
348   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
349   DeleteFileW(filename);
350 
351   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
352   hres = ITextDocument_Open(txtDoc, &testfile, tomOpenExisting, CP_ACP);
353   todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ITextDocument_Open should fail Codepage:CP_ACP\n");
354   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
355 
356   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
357   hres = ITextDocument_Open(txtDoc, &testfile, tomOpenExisting, CP_UTF8);
358   todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
359   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
360 
361   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
362   DeleteFileW(filename);
363   hres = ITextDocument_Open(txtDoc, &testfile, tomText, CP_ACP);
364 todo_wine {
365   ok(hres == S_OK, "got 0x%08x\n", hres);
366   ok(is_existing_file(filename) == TRUE, "a file should be created default\n");
367 }
368   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
369   DeleteFileW(filename);
370 
371   /* test of share mode */
372   touch_file(filename);
373   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
374   hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyRead, CP_ACP);
375 todo_wine
376   ok(hres == S_OK, "got 0x%08x\n", hres);
377   SetLastError(0xdeadbeef);
378   hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
379                           FILE_ATTRIBUTE_NORMAL, NULL);
380   todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
381   CloseHandle(hFile);
382   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
383   DeleteFileW(filename);
384 
385   touch_file(filename);
386   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
387   hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyWrite, CP_ACP);
388 todo_wine
389   ok(hres == S_OK, "got 0x%08x\n", hres);
390   SetLastError(0xdeadbeef);
391   hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
392                           FILE_ATTRIBUTE_NORMAL, NULL);
393   todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
394   CloseHandle(hFile);
395   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
396   DeleteFileW(filename);
397 
398   touch_file(filename);
399   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
400   SetLastError(0xdeadbeef);
401   hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyWrite|tomShareDenyRead, CP_ACP);
402 todo_wine
403   ok(hres == S_OK, "got 0x%08x\n", hres);
404   hFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
405                           FILE_ATTRIBUTE_NORMAL, NULL);
406   todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
407   CloseHandle(hFile);
408   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
409   DeleteFileW(filename);
410 
411   /* tests to check the content */
412   hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
413                       FILE_ATTRIBUTE_NORMAL, NULL);
414   WriteFile(hFile, chACP, sizeof(chACP)-sizeof(CHAR), &dw, NULL);
415   CloseHandle(hFile);
416   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
417   hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, CP_ACP);
418 todo_wine
419   ok(hres == S_OK, "got 0x%08x\n", hres);
420   result = SendMessageA(w, WM_GETTEXT, 1024, (LPARAM)bufACP);
421   todo_wine ok(result == 12, "ITextDocument_Open: Test ASCII returned %d, expected 12\n", result);
422   result = strcmp(bufACP, chACP);
423   todo_wine ok(result == 0, "ITextDocument_Open: Test ASCII set wrong text: Result: %s\n", bufACP);
424   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
425   DeleteFileW(filename);
426 
427   hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
428                       FILE_ATTRIBUTE_NORMAL, NULL);
429   WriteFile(hFile, chUTF8, sizeof(chUTF8)-sizeof(CHAR), &dw, NULL);
430   CloseHandle(hFile);
431   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
432   hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, CP_UTF8);
433 todo_wine
434   ok(hres == S_OK, "got 0x%08x\n", hres);
435   result = SendMessageA(w, WM_GETTEXT, 1024, (LPARAM)bufACP);
436   todo_wine ok(result == 15, "ITextDocument_Open: Test UTF-8 returned %d, expected 15\n", result);
437   result = strcmp(bufACP, &chUTF8[3]);
438   todo_wine ok(result == 0, "ITextDocument_Open: Test UTF-8 set wrong text: Result: %s\n", bufACP);
439   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
440   DeleteFileW(filename);
441 
442   hFile = CreateFileW(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
443                       FILE_ATTRIBUTE_NORMAL, NULL);
444   WriteFile(hFile, chUTF16, sizeof(chUTF16)-sizeof(WCHAR), &dw, NULL);
445   CloseHandle(hFile);
446   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
447   hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, 1200);
448 todo_wine
449   ok(hres == S_OK, "got 0x%08x\n", hres);
450   result = SendMessageW(w, WM_GETTEXT, 1024, (LPARAM)bufUnicode);
451   todo_wine ok(result == 12, "ITextDocument_Open: Test UTF-16 returned %d, expected 12\n", result);
452   result = lstrcmpW(bufUnicode, &chUTF16[1]);
453   todo_wine ok(result == 0, "ITextDocument_Open: Test UTF-16 set wrong text: Result: %s\n", wine_dbgstr_w(bufUnicode));
454   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
455   DeleteFileW(filename);
456 
457   VariantClear(&testfile);
458 }
459 
460 static void test_GetText(void)
461 {
462   HWND w;
463   IRichEditOle *reOle = NULL;
464   ITextDocument *txtDoc = NULL;
465   ITextSelection *txtSel = NULL;
466   HRESULT hres;
467   BSTR bstr = NULL;
468   int first, lim;
469   static const CHAR test_text1[] = "TestSomeText";
470   static const WCHAR bufW1[] = {'T', 'e', 's', 't', 0};
471   static const WCHAR bufW2[] = {'T', 'e', 'x', 't', '\r', 0};
472   static const WCHAR bufW3[] = {'T', 'e', 'x', 't', 0};
473   static const WCHAR bufW4[] = {'T', 'e', 's', 't', 'S', 'o', 'm',
474                                 'e', 'T', 'e', 'x', 't', '\r', 0};
475   static const WCHAR bufW5[] = {'\r', 0};
476   static const WCHAR bufW6[] = {'T','e','s','t','S','o','m','e','T',0};
477   BOOL is64bit = sizeof(void *) > sizeof(int);
478   ITextRange *range;
479 
480   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
481   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
482 
483   /* ITextSelection */
484   first = 0, lim = 4;
485   SendMessageA(w, EM_SETSEL, first, lim);
486   hres = ITextSelection_GetText(txtSel, &bstr);
487   ok(hres == S_OK, "ITextSelection_GetText\n");
488   ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
489   SysFreeString(bstr);
490 
491   first = 4, lim = 0;
492   SendMessageA(w, EM_SETSEL, first, lim);
493   hres = ITextSelection_GetText(txtSel, &bstr);
494   ok(hres == S_OK, "ITextSelection_GetText\n");
495   ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
496   SysFreeString(bstr);
497 
498   first = 1, lim = 1;
499   SendMessageA(w, EM_SETSEL, first, lim);
500   hres = ITextSelection_GetText(txtSel, &bstr);
501   ok(hres == S_OK, "ITextSelection_GetText\n");
502   ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
503 
504   if (!is64bit)
505     {
506       hres = ITextSelection_GetText(txtSel, NULL);
507       ok(hres == E_INVALIDARG, "ITextSelection_GetText\n");
508     }
509 
510   first = 8, lim = 12;
511   SendMessageA(w, EM_SETSEL, first, lim);
512   hres = ITextSelection_GetText(txtSel, &bstr);
513   ok(hres == S_OK, "ITextSelection_GetText\n");
514   ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr));
515   SysFreeString(bstr);
516 
517   first = 8, lim = 13;
518   SendMessageA(w, EM_SETSEL, first, lim);
519   hres = ITextSelection_GetText(txtSel, &bstr);
520   ok(hres == S_OK, "ITextSelection_GetText\n");
521   ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr));
522   SysFreeString(bstr);
523 
524   first = 12, lim = 13;
525   SendMessageA(w, EM_SETSEL, first, lim);
526   hres = ITextSelection_GetText(txtSel, &bstr);
527   ok(hres == S_OK, "ITextSelection_GetText\n");
528   ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr));
529   SysFreeString(bstr);
530 
531   first = 0, lim = -1;
532   SendMessageA(w, EM_SETSEL, first, lim);
533   hres = ITextSelection_GetText(txtSel, &bstr);
534   ok(hres == S_OK, "ITextSelection_GetText\n");
535   ok(!lstrcmpW(bstr, bufW4), "got wrong text: %s\n", wine_dbgstr_w(bstr));
536   SysFreeString(bstr);
537 
538   first = -1, lim = 9;
539   SendMessageA(w, EM_SETSEL, first, lim);
540   hres = ITextSelection_GetText(txtSel, &bstr);
541   ok(hres == S_OK, "ITextSelection_GetText\n");
542   ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
543 
544   /* ITextRange */
545   hres = ITextDocument_Range(txtDoc, 0, 4, &range);
546   ok(hres == S_OK, "got 0x%08x\n", hres);
547   hres = ITextRange_GetText(range, &bstr);
548   ok(hres == S_OK, "got 0x%08x\n", hres);
549   ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
550 
551   SysFreeString(bstr);
552   ITextRange_Release(range);
553 
554   hres = ITextDocument_Range(txtDoc, 4, 0, &range);
555   ok(hres == S_OK, "got 0x%08x\n", hres);
556   hres = ITextRange_GetText(range, &bstr);
557   ok(hres == S_OK, "got 0x%08x\n", hres);
558   ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
559 
560   SysFreeString(bstr);
561   ITextRange_Release(range);
562 
563   hres = ITextDocument_Range(txtDoc, 1, 1, &range);
564   ok(hres == S_OK, "got 0x%08x\n", hres);
565   hres = ITextRange_GetText(range, &bstr);
566   ok(hres == S_OK, "got 0x%08x\n", hres);
567   ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
568   if (!is64bit)
569   {
570     hres = ITextRange_GetText(range, NULL);
571     ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
572   }
573   ITextRange_Release(range);
574 
575   hres = ITextDocument_Range(txtDoc, 8, 12, &range);
576   ok(hres == S_OK, "got 0x%08x\n", hres);
577   hres = ITextRange_GetText(range, &bstr);
578   ok(hres == S_OK, "got 0x%08x\n", hres);
579   ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr));
580 
581   SysFreeString(bstr);
582   ITextRange_Release(range);
583 
584   hres = ITextDocument_Range(txtDoc, 8, 13, &range);
585   ok(hres == S_OK, "got 0x%08x\n", hres);
586   hres = ITextRange_GetText(range, &bstr);
587   ok(hres == S_OK, "got 0x%08x\n", hres);
588   ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr));
589 
590   SysFreeString(bstr);
591   ITextRange_Release(range);
592 
593   hres = ITextDocument_Range(txtDoc, 12, 13, &range);
594   ok(hres == S_OK, "got 0x%08x\n", hres);
595   hres = ITextRange_GetText(range, &bstr);
596   ok(hres == S_OK, "got 0x%08x\n", hres);
597   ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr));
598 
599   SysFreeString(bstr);
600   ITextRange_Release(range);
601 
602   hres = ITextDocument_Range(txtDoc, 0, -1, &range);
603   ok(hres == S_OK, "got 0x%08x\n", hres);
604   hres = ITextRange_GetText(range, &bstr);
605   ok(hres == S_OK, "got 0x%08x\n", hres);
606   ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
607   ITextRange_Release(range);
608 
609   hres = ITextDocument_Range(txtDoc, -1, 9, &range);
610   ok(hres == S_OK, "got 0x%08x\n", hres);
611   hres = ITextRange_GetText(range, &bstr);
612   ok(hres == S_OK, "got 0x%08x\n", hres);
613   ok(!lstrcmpW(bstr, bufW6), "got wrong text: %s\n", wine_dbgstr_w(bstr));
614 
615   SysFreeString(bstr);
616 
617   release_interfaces(&w, &reOle, &txtDoc, NULL);
618 
619   /* detached selection/range */
620   if (is64bit) {
621     bstr = (void*)0xdeadbeef;
622     hres = ITextSelection_GetText(txtSel, &bstr);
623     ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
624 todo_wine
625     ok(bstr == NULL, "got %p\n", bstr);
626 
627     bstr = (void*)0xdeadbeef;
628     hres = ITextRange_GetText(range, &bstr);
629     ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
630 todo_wine
631     ok(bstr == NULL, "got %p\n", bstr);
632   }
633   else {
634     hres = ITextSelection_GetText(txtSel, NULL);
635     ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
636 
637     hres = ITextRange_GetText(range, NULL);
638     ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
639   }
640 
641   ITextRange_Release(range);
642   ITextSelection_Release(txtSel);
643 }
644 
645 static void test_ITextDocument_Range(void)
646 {
647   static const CHAR test_text1[] = "TestSomeText";
648   HWND w;
649   IRichEditOle *reOle = NULL;
650   ITextDocument *txtDoc = NULL;
651   ITextRange *txtRge, *range2;
652   HRESULT hres;
653   LONG value;
654 
655   create_interfaces(&w, &reOle, &txtDoc, NULL);
656   hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge);
657   ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
658   EXPECT_REF(txtRge, 1);
659 
660   hres = ITextDocument_Range(txtDoc, 0, 0, &range2);
661   ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
662   ok(range2 != txtRge, "A new pointer should be returned\n");
663   ITextRange_Release(range2);
664 
665   hres = ITextDocument_Range(txtDoc, 0, 0, NULL);
666   ok(hres == E_INVALIDARG, "ITextDocument_Range should fail 0x%x.\n", hres);
667 
668   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
669 
670   hres = ITextDocument_Range(txtDoc, 8, 30, &range2);
671   ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
672   hres = ITextRange_GetStart(range2, &value);
673   ok(hres == S_OK, "got 0x%08x\n", hres);
674   ok(value == 8, "got %d\n", value);
675 
676   hres = ITextRange_GetEnd(range2, &value);
677   ok(hres == S_OK, "got 0x%08x\n", hres);
678   ok(value == 13, "got %d\n", value);
679   ITextRange_Release(range2);
680 
681   release_interfaces(&w, &reOle, &txtDoc, NULL);
682   hres = ITextRange_CanEdit(txtRge, NULL);
683   ok(hres == CO_E_RELEASED, "ITextRange after ITextDocument destroyed\n");
684   ITextRange_Release(txtRge);
685 }
686 
687 static void test_ITextRange_GetChar(void)
688 {
689   HWND w;
690   IRichEditOle *reOle = NULL;
691   ITextDocument *txtDoc = NULL;
692   ITextRange *txtRge = NULL;
693   HRESULT hres;
694   LONG pch;
695   int first, lim;
696   static const CHAR test_text1[] = "TestSomeText";
697 
698   first = 0, lim = 4;
699   create_interfaces(&w, &reOle, &txtDoc, NULL);
700   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
701   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
702   ok(hres == S_OK, "got 0x%08x\n", hres);
703   pch = 0xdeadbeef;
704   hres = ITextRange_GetChar(txtRge, &pch);
705   ok(hres == S_OK, "ITextRange_GetChar\n");
706   ok(pch == 'T', "got wrong char: %c\n", pch);
707   ITextRange_Release(txtRge);
708   release_interfaces(&w, &reOle, &txtDoc, NULL);
709 
710   first = 0, lim = 0;
711   create_interfaces(&w, &reOle, &txtDoc, NULL);
712   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
713   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
714   ok(hres == S_OK, "got 0x%08x\n", hres);
715   pch = 0xdeadbeef;
716   hres = ITextRange_GetChar(txtRge, &pch);
717   ok(hres == S_OK, "ITextRange_GetChar\n");
718   ok(pch == 'T', "got wrong char: %c\n", pch);
719   ITextRange_Release(txtRge);
720   release_interfaces(&w, &reOle, &txtDoc, NULL);
721 
722   first = 12, lim = 12;
723   create_interfaces(&w, &reOle, &txtDoc, NULL);
724   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
725   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
726   ok(hres == S_OK, "got 0x%08x\n", hres);
727   pch = 0xdeadbeef;
728   hres = ITextRange_GetChar(txtRge, &pch);
729   ok(hres == S_OK, "ITextRange_GetChar\n");
730   ok(pch == '\r', "got wrong char: %c\n", pch);
731   ITextRange_Release(txtRge);
732   release_interfaces(&w, &reOle, &txtDoc, NULL);
733 
734   first = 13, lim = 13;
735   create_interfaces(&w, &reOle, &txtDoc, NULL);
736   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
737   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
738   ok(hres == S_OK, "got 0x%08x\n", hres);
739   pch = 0xdeadbeef;
740   hres = ITextRange_GetChar(txtRge, &pch);
741   ok(hres == S_OK, "ITextRange_GetChar\n");
742   ok(pch == '\r', "got wrong char: %c\n", pch);
743   ITextRange_Release(txtRge);
744   release_interfaces(&w, &reOle, &txtDoc, NULL);
745 
746   create_interfaces(&w, &reOle, &txtDoc, NULL);
747   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
748   first = 12, lim = 12;
749   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
750   ok(hres == S_OK, "got 0x%08x\n", hres);
751   hres = ITextRange_GetChar(txtRge, NULL);
752   ok(hres == E_INVALIDARG, "ITextRange_GetChar\n");
753 
754   release_interfaces(&w, &reOle, &txtDoc, NULL);
755 
756   hres = ITextRange_GetChar(txtRge, NULL);
757   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
758 
759   hres = ITextRange_GetChar(txtRge, &pch);
760   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
761 
762   ITextRange_Release(txtRge);
763 }
764 
765 /* Helper function for testing ITextRange_ScrollIntoView */
766 static void check_range(HWND w, ITextDocument* doc, int first, int lim,
767                         LONG bStart, int expected_nonzero)
768 {
769   SCROLLINFO si;
770   ITextRange *txtRge = NULL;
771   HRESULT hres;
772 
773   si.cbSize = sizeof(SCROLLINFO);
774   si.fMask = SIF_POS | SIF_RANGE;
775 
776   hres = ITextDocument_Range(doc, first, lim, &txtRge);
777   ok(hres == S_OK, "got 0x%08x\n", hres);
778   hres = ITextRange_ScrollIntoView(txtRge, bStart);
779   ok(hres == S_OK, "got 0x%08x\n", hres);
780   GetScrollInfo(w, SB_VERT, &si);
781   if (expected_nonzero) {
782     ok(si.nPos != 0,
783        "Scrollbar at 0, should be >0. (TextRange %d-%d, scroll range %d-%d.)\n",
784        first, lim, si.nMin, si.nMax);
785   } else {
786     ok(si.nPos == 0,
787        "Scrollbar at %d, should be 0. (TextRange %d-%d, scroll range %d-%d.)\n",
788        si.nPos, first, lim, si.nMin, si.nMax);
789   }
790 }
791 
792 static void test_ITextRange_ScrollIntoView(void)
793 {
794   HWND w;
795   IRichEditOle *reOle = NULL;
796   ITextDocument *txtDoc = NULL;
797   ITextRange *txtRge = NULL;
798   HRESULT hres;
799   static const CHAR test_text1[] = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10";
800 
801   create_interfaces(&w, &reOle, &txtDoc, NULL);
802   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
803 
804   /* Scroll to the top. */
805   check_range(w, txtDoc, 0, 1, tomStart, 0);
806 
807   /* Scroll to the bottom. */
808   check_range(w, txtDoc, 19, 20, tomStart, 1);
809 
810   /* Back up to the top. */
811   check_range(w, txtDoc, 0, 1, tomStart, 0);
812 
813   /* Large range */
814   check_range(w, txtDoc, 0, 20, tomStart, 0);
815 
816   hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge);
817   ok(hres == S_OK, "got 0x%08x\n", hres);
818   release_interfaces(&w, &reOle, &txtDoc, NULL);
819   hres = ITextRange_ScrollIntoView(txtRge, tomStart);
820   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
821   ITextRange_Release(txtRge);
822 }
823 
824 static void test_ITextSelection_GetChar(void)
825 {
826   HWND w;
827   IRichEditOle *reOle = NULL;
828   ITextDocument *txtDoc = NULL;
829   ITextSelection *txtSel = NULL;
830   HRESULT hres;
831   LONG pch;
832   int first, lim;
833   static const CHAR test_text1[] = "TestSomeText";
834 
835   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
836   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
837 
838   first = 0, lim = 4;
839   SendMessageA(w, EM_SETSEL, first, lim);
840   pch = 0xdeadbeef;
841   hres = ITextSelection_GetChar(txtSel, &pch);
842   ok(hres == S_OK, "ITextSelection_GetChar\n");
843   ok(pch == 'T', "got wrong char: %c\n", pch);
844 
845   first = 0, lim = 0;
846   SendMessageA(w, EM_SETSEL, first, lim);
847   pch = 0xdeadbeef;
848   hres = ITextSelection_GetChar(txtSel, &pch);
849   ok(hres == S_OK, "ITextSelection_GetChar\n");
850   ok(pch == 'T', "got wrong char: %c\n", pch);
851 
852   first = 12, lim = 12;
853   SendMessageA(w, EM_SETSEL, first, lim);
854   pch = 0xdeadbeef;
855   hres = ITextSelection_GetChar(txtSel, &pch);
856   ok(hres == S_OK, "ITextSelection_GetChar\n");
857   ok(pch == '\r', "got wrong char: %c\n", pch);
858 
859   first = 13, lim = 13;
860   SendMessageA(w, EM_SETSEL, first, lim);
861   pch = 0xdeadbeef;
862   hres = ITextSelection_GetChar(txtSel, &pch);
863   ok(hres == S_OK, "ITextSelection_GetChar\n");
864   ok(pch == '\r', "got wrong char: %c\n", pch);
865 
866   hres = ITextSelection_GetChar(txtSel, NULL);
867   ok(hres == E_INVALIDARG, "ITextSelection_GetChar\n");
868 
869   release_interfaces(&w, &reOle, &txtDoc, NULL);
870 
871   hres = ITextSelection_GetChar(txtSel, NULL);
872   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
873 
874   hres = ITextSelection_GetChar(txtSel, &pch);
875   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
876 
877   ITextSelection_Release(txtSel);
878 }
879 
880 static void test_ITextRange_GetStart_GetEnd(void)
881 {
882   HWND w;
883   IRichEditOle *reOle = NULL;
884   ITextDocument *txtDoc = NULL;
885   ITextRange *txtRge = NULL;
886   HRESULT hres;
887   int first, lim, start, end;
888   static const CHAR test_text1[] = "TestSomeText";
889 
890   create_interfaces(&w, &reOle, &txtDoc, NULL);
891   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
892 
893   first = 1, lim = 6;
894   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
895   ok(hres == S_OK, "got 0x%08x\n", hres);
896   start = 0xdeadbeef;
897   hres = ITextRange_GetStart(txtRge, &start);
898   ok(hres == S_OK, "ITextRange_GetStart\n");
899   ok(start == 1, "got wrong start value: %d\n", start);
900   end = 0xdeadbeef;
901   hres = ITextRange_GetEnd(txtRge, &end);
902   ok(hres == S_OK, "ITextRange_GetEnd\n");
903   ok(end == 6, "got wrong end value: %d\n", end);
904   ITextRange_Release(txtRge);
905 
906   first = 6, lim = 1;
907   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
908   ok(hres == S_OK, "got 0x%08x\n", hres);
909   start = 0xdeadbeef;
910   hres = ITextRange_GetStart(txtRge, &start);
911   ok(hres == S_OK, "ITextRange_GetStart\n");
912   ok(start == 1, "got wrong start value: %d\n", start);
913   end = 0xdeadbeef;
914   hres = ITextRange_GetEnd(txtRge, &end);
915   ok(hres == S_OK, "ITextRange_GetEnd\n");
916   ok(end == 6, "got wrong end value: %d\n", end);
917   ITextRange_Release(txtRge);
918 
919   first = -1, lim = 13;
920   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
921   ok(hres == S_OK, "got 0x%08x\n", hres);
922   start = 0xdeadbeef;
923   hres = ITextRange_GetStart(txtRge, &start);
924   ok(hres == S_OK, "ITextRange_GetStart\n");
925   ok(start == 0, "got wrong start value: %d\n", start);
926   end = 0xdeadbeef;
927   hres = ITextRange_GetEnd(txtRge, &end);
928   ok(hres == S_OK, "ITextRange_GetEnd\n");
929   ok(end == 13, "got wrong end value: %d\n", end);
930   ITextRange_Release(txtRge);
931 
932   first = 13, lim = 13;
933   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
934   ok(hres == S_OK, "got 0x%08x\n", hres);
935   start = 0xdeadbeef;
936   hres = ITextRange_GetStart(txtRge, &start);
937   ok(hres == S_OK, "ITextRange_GetStart\n");
938   ok(start == 12, "got wrong start value: %d\n", start);
939   end = 0xdeadbeef;
940   hres = ITextRange_GetEnd(txtRge, &end);
941   ok(hres == S_OK, "ITextRange_GetEnd\n");
942   ok(end == 12, "got wrong end value: %d\n", end);
943 
944   /* SetStart */
945   hres = ITextRange_SetStart(txtRge, 0);
946   ok(hres == S_OK, "got 0x%08x\n", hres);
947 
948   /* same value */
949   hres = ITextRange_SetStart(txtRge, 0);
950   ok(hres == S_FALSE, "got 0x%08x\n", hres);
951 
952   hres = ITextRange_SetStart(txtRge, 1);
953   ok(hres == S_OK, "got 0x%08x\n", hres);
954 
955   /* negative resets to 0, return value is S_FALSE when
956      position wasn't changed */
957   hres = ITextRange_SetStart(txtRge, -1);
958   ok(hres == S_OK, "got 0x%08x\n", hres);
959 
960   hres = ITextRange_SetStart(txtRge, -1);
961   ok(hres == S_FALSE, "got 0x%08x\n", hres);
962 
963   hres = ITextRange_SetStart(txtRge, 0);
964   ok(hres == S_FALSE, "got 0x%08x\n", hres);
965 
966   start = -1;
967   hres = ITextRange_GetStart(txtRge, &start);
968   ok(hres == S_OK, "got 0x%08x\n", hres);
969   ok(start == 0, "got %d\n", start);
970 
971   /* greater than initial end, but less than total char count */
972   hres = ITextRange_SetStart(txtRge, 1);
973   ok(hres == S_OK, "got 0x%08x\n", hres);
974 
975   hres = ITextRange_SetEnd(txtRge, 3);
976   ok(hres == S_OK, "got 0x%08x\n", hres);
977 
978   hres = ITextRange_SetStart(txtRge, 10);
979   ok(hres == S_OK, "got 0x%08x\n", hres);
980 
981   start = 0;
982   hres = ITextRange_GetStart(txtRge, &start);
983   ok(hres == S_OK, "got 0x%08x\n", hres);
984   ok(start == 10, "got %d\n", start);
985 
986   end = 0;
987   hres = ITextRange_GetEnd(txtRge, &end);
988   ok(hres == S_OK, "got 0x%08x\n", hres);
989   ok(end == 10, "got %d\n", end);
990 
991   /* more that total text length */
992   hres = ITextRange_SetStart(txtRge, 50);
993   ok(hres == S_OK, "got 0x%08x\n", hres);
994 
995   start = 0;
996   hres = ITextRange_GetStart(txtRge, &start);
997   ok(hres == S_OK, "got 0x%08x\n", hres);
998   ok(start == 12, "got %d\n", start);
999 
1000   end = 0;
1001   hres = ITextRange_GetEnd(txtRge, &end);
1002   ok(hres == S_OK, "got 0x%08x\n", hres);
1003   ok(end == 12, "got %d\n", end);
1004 
1005   /* SetEnd */
1006   hres = ITextRange_SetStart(txtRge, 0);
1007   ok(hres == S_OK, "got 0x%08x\n", hres);
1008 
1009   /* same value */
1010   hres = ITextRange_SetEnd(txtRge, 5);
1011   ok(hres == S_OK, "got 0x%08x\n", hres);
1012 
1013   hres = ITextRange_SetEnd(txtRge, 5);
1014   ok(hres == S_FALSE, "got 0x%08x\n", hres);
1015 
1016   /* negative resets to 0 */
1017   hres = ITextRange_SetEnd(txtRge, -1);
1018   ok(hres == S_OK, "got 0x%08x\n", hres);
1019 
1020   end = -1;
1021   hres = ITextRange_GetEnd(txtRge, &end);
1022   ok(hres == S_OK, "got 0x%08x\n", hres);
1023   ok(end == 0, "got %d\n", end);
1024 
1025   start = -1;
1026   hres = ITextRange_GetStart(txtRge, &start);
1027   ok(hres == S_OK, "got 0x%08x\n", hres);
1028   ok(start == 0, "got %d\n", start);
1029 
1030   /* greater than initial end, but less than total char count */
1031   hres = ITextRange_SetStart(txtRge, 3);
1032   ok(hres == S_OK, "got 0x%08x\n", hres);
1033 
1034   hres = ITextRange_SetEnd(txtRge, 1);
1035   ok(hres == S_OK, "got 0x%08x\n", hres);
1036 
1037   start = 0;
1038   hres = ITextRange_GetStart(txtRge, &start);
1039   ok(hres == S_OK, "got 0x%08x\n", hres);
1040   ok(start == 1, "got %d\n", start);
1041 
1042   end = 0;
1043   hres = ITextRange_GetEnd(txtRge, &end);
1044   ok(hres == S_OK, "got 0x%08x\n", hres);
1045   ok(end == 1, "got %d\n", end);
1046 
1047   /* more than total count */
1048   hres = ITextRange_SetEnd(txtRge, 50);
1049   ok(hres == S_OK, "got 0x%08x\n", hres);
1050 
1051   start = 0;
1052   hres = ITextRange_GetStart(txtRge, &start);
1053   ok(hres == S_OK, "got 0x%08x\n", hres);
1054   ok(start == 1, "got %d\n", start);
1055 
1056   end = 0;
1057   hres = ITextRange_GetEnd(txtRge, &end);
1058   ok(hres == S_OK, "got 0x%08x\n", hres);
1059   ok(end == 13, "got %d\n", end);
1060 
1061   /* zero */
1062   hres = ITextRange_SetEnd(txtRge, 0);
1063   ok(hres == S_OK, "got 0x%08x\n", hres);
1064 
1065   start = 0;
1066   hres = ITextRange_GetStart(txtRge, &start);
1067   ok(hres == S_OK, "got 0x%08x\n", hres);
1068   ok(start == 0, "got %d\n", start);
1069 
1070   end = 0;
1071   hres = ITextRange_GetEnd(txtRge, &end);
1072   ok(hres == S_OK, "got 0x%08x\n", hres);
1073   ok(end == 0, "got %d\n", end);
1074 
1075   release_interfaces(&w, &reOle, &txtDoc, NULL);
1076 
1077   /* detached range */
1078   hres = ITextRange_SetStart(txtRge, 0);
1079   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1080 
1081   hres = ITextRange_SetEnd(txtRge, 3);
1082   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1083 
1084   hres = ITextRange_GetStart(txtRge, &start);
1085   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1086 
1087   hres = ITextRange_GetStart(txtRge, NULL);
1088   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1089 
1090   hres = ITextRange_GetEnd(txtRge, &end);
1091   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1092 
1093   hres = ITextRange_GetEnd(txtRge, NULL);
1094   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1095 
1096   ITextRange_Release(txtRge);
1097 }
1098 
1099 static void test_ITextSelection_GetStart_GetEnd(void)
1100 {
1101   HWND w;
1102   IRichEditOle *reOle = NULL;
1103   ITextDocument *txtDoc = NULL;
1104   ITextSelection *txtSel = NULL;
1105   HRESULT hres;
1106   int first, lim, start, end;
1107   static const CHAR test_text1[] = "TestSomeText";
1108 
1109   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
1110   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1111 
1112   first = 2, lim = 5;
1113   SendMessageA(w, EM_SETSEL, first, lim);
1114   start = 0xdeadbeef;
1115   hres = ITextSelection_GetStart(txtSel, &start);
1116   ok(hres == S_OK, "ITextSelection_GetStart\n");
1117   ok(start == 2, "got wrong start value: %d\n", start);
1118   end = 0xdeadbeef;
1119   hres = ITextSelection_GetEnd(txtSel, &end);
1120   ok(hres == S_OK, "ITextSelection_GetEnd\n");
1121   ok(end == 5, "got wrong end value: %d\n", end);
1122 
1123   first = 5, lim = 2;
1124   SendMessageA(w, EM_SETSEL, first, lim);
1125   start = 0xdeadbeef;
1126   hres = ITextSelection_GetStart(txtSel, &start);
1127   ok(hres == S_OK, "ITextSelection_GetStart\n");
1128   ok(start == 2, "got wrong start value: %d\n", start);
1129   end = 0xdeadbeef;
1130   hres = ITextSelection_GetEnd(txtSel, &end);
1131   ok(hres == S_OK, "ITextSelection_GetEnd\n");
1132   ok(end == 5, "got wrong end value: %d\n", end);
1133 
1134   first = 0, lim = -1;
1135   SendMessageA(w, EM_SETSEL, first, lim);
1136   start = 0xdeadbeef;
1137   hres = ITextSelection_GetStart(txtSel, &start);
1138   ok(hres == S_OK, "ITextSelection_GetStart\n");
1139   ok(start == 0, "got wrong start value: %d\n", start);
1140   end = 0xdeadbeef;
1141   hres = ITextSelection_GetEnd(txtSel, &end);
1142   ok(hres == S_OK, "ITextSelection_GetEnd\n");
1143   ok(end == 13, "got wrong end value: %d\n", end);
1144 
1145   first = 13, lim = 13;
1146   SendMessageA(w, EM_SETSEL, first, lim);
1147   start = 0xdeadbeef;
1148   hres = ITextSelection_GetStart(txtSel, &start);
1149   ok(hres == S_OK, "ITextSelection_GetStart\n");
1150   ok(start == 12, "got wrong start value: %d\n", start);
1151   end = 0xdeadbeef;
1152   hres = ITextSelection_GetEnd(txtSel, &end);
1153   ok(hres == S_OK, "ITextSelection_GetEnd\n");
1154   ok(end == 12, "got wrong end value: %d\n", end);
1155 
1156   /* SetStart/SetEnd */
1157   hres = ITextSelection_SetStart(txtSel, 0);
1158   ok(hres == S_OK, "got 0x%08x\n", hres);
1159 
1160   /* same value */
1161   hres = ITextSelection_SetStart(txtSel, 0);
1162   ok(hres == S_FALSE, "got 0x%08x\n", hres);
1163 
1164   hres = ITextSelection_SetStart(txtSel, 1);
1165   ok(hres == S_OK, "got 0x%08x\n", hres);
1166 
1167   /* negative resets to 0, return value is S_FALSE when
1168      position wasn't changed */
1169   hres = ITextSelection_SetStart(txtSel, -1);
1170   ok(hres == S_OK, "got 0x%08x\n", hres);
1171 
1172   hres = ITextSelection_SetStart(txtSel, -1);
1173   ok(hres == S_FALSE, "got 0x%08x\n", hres);
1174 
1175   hres = ITextSelection_SetStart(txtSel, 0);
1176   ok(hres == S_FALSE, "got 0x%08x\n", hres);
1177 
1178   start = -1;
1179   hres = ITextSelection_GetStart(txtSel, &start);
1180   ok(hres == S_OK, "got 0x%08x\n", hres);
1181   ok(start == 0, "got %d\n", start);
1182 
1183   /* greater than initial end, but less than total char count */
1184   hres = ITextSelection_SetStart(txtSel, 1);
1185   ok(hres == S_OK, "got 0x%08x\n", hres);
1186 
1187   hres = ITextSelection_SetEnd(txtSel, 3);
1188   ok(hres == S_OK, "got 0x%08x\n", hres);
1189 
1190   hres = ITextSelection_SetStart(txtSel, 10);
1191   ok(hres == S_OK, "got 0x%08x\n", hres);
1192 
1193   start = 0;
1194   hres = ITextSelection_GetStart(txtSel, &start);
1195   ok(hres == S_OK, "got 0x%08x\n", hres);
1196   ok(start == 10, "got %d\n", start);
1197 
1198   end = 0;
1199   hres = ITextSelection_GetEnd(txtSel, &end);
1200   ok(hres == S_OK, "got 0x%08x\n", hres);
1201   ok(end == 10, "got %d\n", end);
1202 
1203   /* more that total text length */
1204   hres = ITextSelection_SetStart(txtSel, 50);
1205   ok(hres == S_OK, "got 0x%08x\n", hres);
1206 
1207   start = 0;
1208   hres = ITextSelection_GetStart(txtSel, &start);
1209   ok(hres == S_OK, "got 0x%08x\n", hres);
1210   ok(start == 12, "got %d\n", start);
1211 
1212   end = 0;
1213   hres = ITextSelection_GetEnd(txtSel, &end);
1214   ok(hres == S_OK, "got 0x%08x\n", hres);
1215   ok(end == 12, "got %d\n", end);
1216 
1217   /* SetEnd */
1218   hres = ITextSelection_SetStart(txtSel, 0);
1219   ok(hres == S_OK, "got 0x%08x\n", hres);
1220 
1221   /* same value */
1222   hres = ITextSelection_SetEnd(txtSel, 5);
1223   ok(hres == S_OK, "got 0x%08x\n", hres);
1224 
1225   hres = ITextSelection_SetEnd(txtSel, 5);
1226   ok(hres == S_FALSE, "got 0x%08x\n", hres);
1227 
1228   /* negative resets to 0 */
1229   hres = ITextSelection_SetEnd(txtSel, -1);
1230   ok(hres == S_OK, "got 0x%08x\n", hres);
1231 
1232   end = -1;
1233   hres = ITextSelection_GetEnd(txtSel, &end);
1234   ok(hres == S_OK, "got 0x%08x\n", hres);
1235   ok(end == 0, "got %d\n", end);
1236 
1237   start = -1;
1238   hres = ITextSelection_GetStart(txtSel, &start);
1239   ok(hres == S_OK, "got 0x%08x\n", hres);
1240   ok(start == 0, "got %d\n", start);
1241 
1242   /* greater than initial end, but less than total char count */
1243   hres = ITextSelection_SetStart(txtSel, 3);
1244   ok(hres == S_OK, "got 0x%08x\n", hres);
1245 
1246   hres = ITextSelection_SetEnd(txtSel, 1);
1247   ok(hres == S_OK, "got 0x%08x\n", hres);
1248 
1249   start = 0;
1250   hres = ITextSelection_GetStart(txtSel, &start);
1251   ok(hres == S_OK, "got 0x%08x\n", hres);
1252   ok(start == 1, "got %d\n", start);
1253 
1254   end = 0;
1255   hres = ITextSelection_GetEnd(txtSel, &end);
1256   ok(hres == S_OK, "got 0x%08x\n", hres);
1257   ok(end == 1, "got %d\n", end);
1258 
1259   /* more than total count */
1260   hres = ITextSelection_SetEnd(txtSel, 50);
1261   ok(hres == S_OK, "got 0x%08x\n", hres);
1262 
1263   start = 0;
1264   hres = ITextSelection_GetStart(txtSel, &start);
1265   ok(hres == S_OK, "got 0x%08x\n", hres);
1266   ok(start == 1, "got %d\n", start);
1267 
1268   end = 0;
1269   hres = ITextSelection_GetEnd(txtSel, &end);
1270   ok(hres == S_OK, "got 0x%08x\n", hres);
1271   ok(end == 13, "got %d\n", end);
1272 
1273   /* zero */
1274   hres = ITextSelection_SetEnd(txtSel, 0);
1275   ok(hres == S_OK, "got 0x%08x\n", hres);
1276 
1277   start = 0;
1278   hres = ITextSelection_GetStart(txtSel, &start);
1279   ok(hres == S_OK, "got 0x%08x\n", hres);
1280   ok(start == 0, "got %d\n", start);
1281 
1282   end = 0;
1283   hres = ITextSelection_GetEnd(txtSel, &end);
1284   ok(hres == S_OK, "got 0x%08x\n", hres);
1285   ok(end == 0, "got %d\n", end);
1286 
1287   release_interfaces(&w, &reOle, &txtDoc, NULL);
1288 
1289   /* detached selection */
1290   hres = ITextSelection_GetStart(txtSel, NULL);
1291   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1292 
1293   hres = ITextSelection_GetStart(txtSel, &start);
1294   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1295 
1296   hres = ITextSelection_GetEnd(txtSel, NULL);
1297   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1298 
1299   hres = ITextSelection_GetEnd(txtSel, &end);
1300   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1301 
1302   ITextSelection_Release(txtSel);
1303 }
1304 
1305 static void test_ITextRange_GetDuplicate(void)
1306 {
1307   HWND w;
1308   IRichEditOle *reOle = NULL;
1309   ITextDocument *txtDoc = NULL;
1310   ITextRange *txtRge = NULL;
1311   ITextRange *txtRgeDup = NULL;
1312   HRESULT hres;
1313   LONG first, lim, start, end;
1314   static const CHAR test_text1[] = "TestSomeText";
1315 
1316   create_interfaces(&w, &reOle, &txtDoc, NULL);
1317   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1318   first = 0, lim = 4;
1319   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1320   ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
1321 
1322   hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup);
1323   ok(hres == S_OK, "ITextRange_GetDuplicate\n");
1324   ok(txtRgeDup != txtRge, "A new pointer should be returned\n");
1325   hres = ITextRange_GetStart(txtRgeDup, &start);
1326   ok(hres == S_OK, "got 0x%08x\n", hres);
1327   ok(start == first, "got wrong value: %d\n", start);
1328   hres = ITextRange_GetEnd(txtRgeDup, &end);
1329   ok(hres == S_OK, "got 0x%08x\n", hres);
1330   ok(end == lim, "got wrong value: %d\n", end);
1331 
1332   ITextRange_Release(txtRgeDup);
1333 
1334   hres = ITextRange_GetDuplicate(txtRge, NULL);
1335   ok(hres == E_INVALIDARG, "ITextRange_GetDuplicate\n");
1336 
1337   release_interfaces(&w, &reOle, &txtDoc, NULL);
1338 
1339   hres = ITextRange_GetDuplicate(txtRge, NULL);
1340   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1341 
1342   hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup);
1343   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1344 
1345   ITextRange_Release(txtRge);
1346 }
1347 
1348 static void test_ITextRange_Collapse(void)
1349 {
1350   HWND w;
1351   IRichEditOle *reOle = NULL;
1352   ITextDocument *txtDoc = NULL;
1353   ITextRange *txtRge = NULL;
1354   HRESULT hres;
1355   LONG first, lim, start, end;
1356   static const CHAR test_text1[] = "TestSomeText";
1357 
1358   create_interfaces(&w, &reOle, &txtDoc, NULL);
1359   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1360 
1361   first = 4, lim = 8;
1362   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1363   ok(hres == S_OK, "got 0x%08x\n", hres);
1364   hres = ITextRange_Collapse(txtRge, tomTrue);
1365   ok(hres == S_OK, "ITextRange_Collapse\n");
1366   hres = ITextRange_GetStart(txtRge, &start);
1367   ok(hres == S_OK, "got 0x%08x\n", hres);
1368   ok(start == 4, "got wrong start value: %d\n", start);
1369   hres = ITextRange_GetEnd(txtRge, &end);
1370   ok(hres == S_OK, "got 0x%08x\n", hres);
1371   ok(end == 4, "got wrong end value: %d\n", end);
1372   ITextRange_Release(txtRge);
1373 
1374   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1375   ok(hres == S_OK, "got 0x%08x\n", hres);
1376   hres = ITextRange_Collapse(txtRge, tomStart);
1377   ok(hres == S_OK, "ITextRange_Collapse\n");
1378   hres = ITextRange_GetStart(txtRge, &start);
1379   ok(hres == S_OK, "got 0x%08x\n", hres);
1380   ok(start == 4, "got wrong start value: %d\n", start);
1381   hres = ITextRange_GetEnd(txtRge, &end);
1382   ok(hres == S_OK, "got 0x%08x\n", hres);
1383   ok(end == 4, "got wrong end value: %d\n", end);
1384   ITextRange_Release(txtRge);
1385 
1386   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1387   ok(hres == S_OK, "got 0x%08x\n", hres);
1388   hres = ITextRange_Collapse(txtRge, tomFalse);
1389   ok(hres == S_OK, "ITextRange_Collapse\n");
1390   hres = ITextRange_GetStart(txtRge, &start);
1391   ok(hres == S_OK, "got 0x%08x\n", hres);
1392   ok(start == 8, "got wrong start value: %d\n", start);
1393   hres = ITextRange_GetEnd(txtRge, &end);
1394   ok(hres == S_OK, "got 0x%08x\n", hres);
1395   ok(end == 8, "got wrong end value: %d\n", end);
1396   ITextRange_Release(txtRge);
1397 
1398   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1399   ok(hres == S_OK, "got 0x%08x\n", hres);
1400   hres = ITextRange_Collapse(txtRge, tomEnd);
1401   ok(hres == S_OK, "ITextRange_Collapse\n");
1402   hres = ITextRange_GetStart(txtRge, &start);
1403   ok(hres == S_OK, "got 0x%08x\n", hres);
1404   ok(start == 8, "got wrong start value: %d\n", start);
1405   hres = ITextRange_GetEnd(txtRge, &end);
1406   ok(hres == S_OK, "got 0x%08x\n", hres);
1407   ok(end == 8, "got wrong end value: %d\n", end);
1408   ITextRange_Release(txtRge);
1409 
1410   /* tomStart is the default */
1411   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1412   ok(hres == S_OK, "got 0x%08x\n", hres);
1413   hres = ITextRange_Collapse(txtRge, 256);
1414   ok(hres == S_OK, "ITextRange_Collapse\n");
1415   hres = ITextRange_GetStart(txtRge, &start);
1416   ok(hres == S_OK, "got 0x%08x\n", hres);
1417   ok(start == 4, "got wrong start value: %d\n", start);
1418   hres = ITextRange_GetEnd(txtRge, &end);
1419   ok(hres == S_OK, "got 0x%08x\n", hres);
1420   ok(end == 4, "got wrong end value: %d\n", end);
1421   ITextRange_Release(txtRge);
1422 
1423   first = 6, lim = 6;
1424   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1425   ok(hres == S_OK, "got 0x%08x\n", hres);
1426   hres = ITextRange_Collapse(txtRge, tomEnd);
1427   ok(hres == S_FALSE, "ITextRange_Collapse\n");
1428   hres = ITextRange_GetStart(txtRge, &start);
1429   ok(hres == S_OK, "got 0x%08x\n", hres);
1430   ok(start == 6, "got wrong start value: %d\n", start);
1431   hres = ITextRange_GetEnd(txtRge, &end);
1432   ok(hres == S_OK, "got 0x%08x\n", hres);
1433   ok(end == 6, "got wrong end value: %d\n", end);
1434   ITextRange_Release(txtRge);
1435 
1436   first = 8, lim = 8;
1437   hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1438   ok(hres == S_OK, "got 0x%08x\n", hres);
1439   hres = ITextRange_Collapse(txtRge, tomStart);
1440   ok(hres == S_FALSE, "ITextRange_Collapse\n");
1441   hres = ITextRange_GetStart(txtRge, &start);
1442   ok(hres == S_OK, "got 0x%08x\n", hres);
1443   ok(start == 8, "got wrong start value: %d\n", start);
1444   hres = ITextRange_GetEnd(txtRge, &end);
1445   ok(hres == S_OK, "got 0x%08x\n", hres);
1446   ok(end == 8, "got wrong end value: %d\n", end);
1447 
1448   release_interfaces(&w, &reOle, &txtDoc, NULL);
1449 
1450   hres = ITextRange_Collapse(txtRge, tomStart);
1451   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1452 
1453   hres = ITextRange_Collapse(txtRge, tomUndefined);
1454   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1455 
1456   ITextRange_Release(txtRge);
1457 }
1458 
1459 static void test_ITextSelection_Collapse(void)
1460 {
1461   HWND w;
1462   IRichEditOle *reOle = NULL;
1463   ITextDocument *txtDoc = NULL;
1464   ITextSelection *txtSel = NULL;
1465   HRESULT hres;
1466   LONG first, lim, start, end;
1467   static const CHAR test_text1[] = "TestSomeText";
1468 
1469   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
1470   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1471 
1472   first = 4, lim = 8;
1473   SendMessageA(w, EM_SETSEL, first, lim);
1474   hres = ITextSelection_Collapse(txtSel, tomTrue);
1475   ok(hres == S_OK, "ITextSelection_Collapse\n");
1476   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1477   ok(start == 4, "got wrong start value: %d\n", start);
1478   ok(end == 4, "got wrong end value: %d\n", end);
1479 
1480   SendMessageA(w, EM_SETSEL, first, lim);
1481   hres = ITextSelection_Collapse(txtSel, tomStart);
1482   ok(hres == S_OK, "ITextSelection_Collapse\n");
1483   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1484   ok(start == 4, "got wrong start value: %d\n", start);
1485   ok(end == 4, "got wrong end value: %d\n", end);
1486 
1487   SendMessageA(w, EM_SETSEL, first, lim);
1488   hres = ITextSelection_Collapse(txtSel, tomFalse);
1489   ok(hres == S_OK, "ITextSelection_Collapse\n");
1490   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1491   ok(start == 8, "got wrong start value: %d\n", start);
1492   ok(end == 8, "got wrong end value: %d\n", end);
1493 
1494   SendMessageA(w, EM_SETSEL, first, lim);
1495   hres = ITextSelection_Collapse(txtSel, tomEnd);
1496   ok(hres == S_OK, "ITextSelection_Collapse\n");
1497   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1498   ok(start == 8, "got wrong start value: %d\n", start);
1499   ok(end == 8, "got wrong end value: %d\n", end);
1500 
1501   /* tomStart is the default */
1502   SendMessageA(w, EM_SETSEL, first, lim);
1503   hres = ITextSelection_Collapse(txtSel, 256);
1504   ok(hres == S_OK, "ITextSelection_Collapse\n");
1505   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1506   ok(start == 4, "got wrong start value: %d\n", start);
1507   ok(end == 4, "got wrong end value: %d\n", end);
1508 
1509   first = 6, lim = 6;
1510   SendMessageA(w, EM_SETSEL, first, lim);
1511   hres = ITextSelection_Collapse(txtSel, tomEnd);
1512   ok(hres == S_FALSE, "ITextSelection_Collapse\n");
1513   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1514   ok(start == 6, "got wrong start value: %d\n", start);
1515   ok(end == 6, "got wrong end value: %d\n", end);
1516 
1517   first = 8, lim = 8;
1518   SendMessageA(w, EM_SETSEL, first, lim);
1519   hres = ITextSelection_Collapse(txtSel, tomStart);
1520   ok(hres == S_FALSE, "ITextSelection_Collapse\n");
1521   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);
1522   ok(start == 8, "got wrong start value: %d\n", start);
1523   ok(end == 8, "got wrong end value: %d\n", end);
1524 
1525   release_interfaces(&w, &reOle, &txtDoc, NULL);
1526 
1527   hres = ITextSelection_Collapse(txtSel, tomStart);
1528   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1529 
1530   hres = ITextSelection_Collapse(txtSel, tomUndefined);
1531   ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1532 
1533   ITextSelection_Release(txtSel);
1534 }
1535 
1536 static void test_GetClientSite(void)
1537 {
1538   HWND w;
1539   IRichEditOle *reOle = NULL, *reOle1 = NULL;
1540   ITextDocument *txtDoc = NULL;
1541   IOleClientSite *clientSite = NULL, *clientSite1 = NULL, *clientSite2 = NULL;
1542   IOleWindow *oleWin = NULL, *oleWin1 = NULL;
1543   IOleInPlaceSite *olePlace = NULL, *olePlace1 = NULL;
1544   HRESULT hres;
1545   LONG refcount1, refcount2;
1546 
1547   create_interfaces(&w, &reOle, &txtDoc, NULL);
1548   hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1549   ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1550   EXPECT_REF(clientSite, 1);
1551 
1552   hres = IOleClientSite_QueryInterface(clientSite, &IID_IRichEditOle, (void **)&reOle1);
1553   ok(hres == E_NOINTERFACE, "IOleClientSite_QueryInterface: %x\n", hres);
1554 
1555   hres = IRichEditOle_GetClientSite(reOle, &clientSite1);
1556   ok(hres == S_OK, "got 0x%08x\n", hres);
1557   ok(clientSite != clientSite1, "got %p, %p\n", clientSite, clientSite1);
1558   IOleClientSite_Release(clientSite1);
1559 
1560   hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleClientSite, (void **)&clientSite1);
1561   ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1562   ok(clientSite == clientSite1, "Should not return a new pointer.\n");
1563   EXPECT_REF(clientSite, 2);
1564 
1565   /* IOleWindow interface */
1566   hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin);
1567   ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1568   refcount1 = get_refcount((IUnknown *)clientSite);
1569   refcount2 = get_refcount((IUnknown *)oleWin);
1570   ok(refcount1 == refcount2, "got wrong ref count.\n");
1571 
1572   hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin1);
1573   ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1574   ok(oleWin == oleWin1, "Should not return a new pointer.\n");
1575   refcount1 = get_refcount((IUnknown *)clientSite);
1576   refcount2 = get_refcount((IUnknown *)oleWin);
1577   ok(refcount1 == refcount2, "got wrong ref count.\n");
1578 
1579   hres = IOleWindow_QueryInterface(oleWin, &IID_IOleClientSite, (void **)&clientSite2);
1580   ok(hres == S_OK, "IOleWindow_QueryInterface: 0x%08x\n", hres);
1581   ok(clientSite2 == clientSite1, "got wrong pointer\n");
1582 
1583   /* IOleInPlaceSite interface */
1584   hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace);
1585   ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1586   refcount1 = get_refcount((IUnknown *)olePlace);
1587   refcount2 = get_refcount((IUnknown *)clientSite);
1588   ok(refcount1 == refcount2, "got wrong ref count.\n");
1589 
1590   hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace1);
1591   ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1592   ok(olePlace == olePlace1, "Should not return a new pointer.\n");
1593   IOleInPlaceSite_Release(olePlace1);
1594 
1595   hres = IOleWindow_QueryInterface(oleWin, &IID_IOleInPlaceSite, (void **)&olePlace1);
1596   ok(hres == S_OK, "IOleWindow_QueryInterface: 0x%08x\n", hres);
1597   refcount1 = get_refcount((IUnknown *)olePlace1);
1598   refcount2 = get_refcount((IUnknown *)oleWin);
1599   ok(refcount1 == refcount2, "got wrong ref count.\n");
1600 
1601   IOleInPlaceSite_Release(olePlace1);
1602   IOleInPlaceSite_Release(olePlace);
1603   IOleWindow_Release(oleWin1);
1604   IOleWindow_Release(oleWin);
1605   IOleClientSite_Release(clientSite2);
1606   IOleClientSite_Release(clientSite1);
1607   IOleClientSite_Release(clientSite);
1608   release_interfaces(&w, &reOle, &txtDoc, NULL);
1609 }
1610 
1611 static void test_IOleWindow_GetWindow(void)
1612 {
1613   HWND w;
1614   IRichEditOle *reOle = NULL;
1615   ITextDocument *txtDoc = NULL;
1616   IOleClientSite *clientSite = NULL;
1617   IOleWindow *oleWin = NULL;
1618   HRESULT hres;
1619   HWND hwnd;
1620 
1621   create_interfaces(&w, &reOle, &txtDoc, NULL);
1622   hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1623   ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1624 
1625   hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin);
1626   ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1627   hres = IOleWindow_GetWindow(oleWin, &hwnd);
1628   ok(hres == S_OK, "IOleClientSite_GetWindow: 0x%08x\n", hres);
1629   ok(w == hwnd, "got wrong pointer\n");
1630 
1631   hres = IOleWindow_GetWindow(oleWin, NULL);
1632   ok(hres == E_INVALIDARG, "IOleClientSite_GetWindow: 0x%08x\n", hres);
1633 
1634   IOleWindow_Release(oleWin);
1635   IOleClientSite_Release(clientSite);
1636   release_interfaces(&w, &reOle, &txtDoc, NULL);
1637 }
1638 
1639 static void test_IOleInPlaceSite_GetWindow(void)
1640 {
1641   HWND w;
1642   IRichEditOle *reOle = NULL;
1643   ITextDocument *txtDoc = NULL;
1644   IOleClientSite *clientSite = NULL;
1645   IOleInPlaceSite *olePlace = NULL;
1646   HRESULT hres;
1647   HWND hwnd;
1648 
1649   create_interfaces(&w, &reOle, &txtDoc, NULL);
1650   hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1651   ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1652 
1653   hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace);
1654   ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1655   hres = IOleInPlaceSite_GetWindow(olePlace, &hwnd);
1656   ok(hres == S_OK, "IOleInPlaceSite_GetWindow: 0x%08x\n", hres);
1657   ok(w == hwnd, "got wrong pointer.\n");
1658 
1659   hres = IOleInPlaceSite_GetWindow(olePlace, NULL);
1660   ok(hres == E_INVALIDARG, "IOleInPlaceSite_GetWindow: 0x%08x\n", hres);
1661 
1662   IOleInPlaceSite_Release(olePlace);
1663   IOleClientSite_Release(clientSite);
1664   release_interfaces(&w, &reOle, &txtDoc, NULL);
1665 }
1666 
1667 static void test_GetFont(void)
1668 {
1669   static const CHAR test_text1[] = "TestSomeText";
1670   IRichEditOle *reOle = NULL;
1671   ITextDocument *doc = NULL;
1672   ITextRange *range = NULL;
1673   ITextSelection *selection;
1674   ITextFont *font, *font2;
1675   CHARFORMAT2A cf;
1676   LONG value;
1677   float size;
1678   HRESULT hr;
1679   HWND hwnd;
1680   BOOL ret;
1681 
1682   create_interfaces(&hwnd, &reOle, &doc, NULL);
1683   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
1684 
1685   hr = ITextDocument_GetSelection(doc, &selection);
1686   ok(hr == S_OK, "got 0x%08x\n", hr);
1687   hr = ITextSelection_GetFont(selection, &font);
1688   ok(hr == S_OK, "got 0x%08x\n", hr);
1689   hr = ITextSelection_GetFont(selection, &font2);
1690   ok(hr == S_OK, "got 0x%08x\n", hr);
1691   ok(font != font2, "got %p, %p\n", font, font2);
1692   ITextFont_Release(font2);
1693   ITextFont_Release(font);
1694   ITextSelection_Release(selection);
1695 
1696   EXPECT_REF(reOle, 3);
1697   EXPECT_REF(doc, 3);
1698 
1699   hr = ITextDocument_Range(doc, 0, 4, &range);
1700   ok(hr == S_OK, "got 0x%08x\n", hr);
1701 
1702   EXPECT_REF(reOle, 3);
1703   EXPECT_REF(doc, 3);
1704   EXPECT_REF(range, 1);
1705 
1706   hr = ITextRange_GetFont(range, NULL);
1707   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1708 
1709   hr = ITextRange_GetFont(range, &font);
1710   ok(hr == S_OK, "got 0x%08x\n", hr);
1711 
1712   EXPECT_REF(reOle, 3);
1713   EXPECT_REF(doc, 3);
1714   EXPECT_REF(range, 2);
1715   EXPECT_REF(font, 1);
1716 
1717   hr = ITextRange_GetFont(range, &font2);
1718   ok(hr == S_OK, "got 0x%08x\n", hr);
1719   ok(font != font2, "got %p, %p\n", font, font2);
1720 
1721   EXPECT_REF(reOle, 3);
1722   EXPECT_REF(doc, 3);
1723   EXPECT_REF(range, 3);
1724   EXPECT_REF(font, 1);
1725   EXPECT_REF(font2, 1);
1726 
1727   ITextFont_Release(font2);
1728 
1729   /* set different font style within a range */
1730   hr = ITextFont_GetItalic(font, NULL);
1731   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1732 
1733   hr = ITextFont_GetSize(font, NULL);
1734   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1735 
1736   size = 0.0;
1737   hr = ITextFont_GetSize(font, &size);
1738   ok(hr == S_OK, "got 0x%08x\n", hr);
1739   ok(size > 0.0, "size %.2f\n", size);
1740 
1741   value = 0;
1742   hr = ITextFont_GetLanguageID(font, &value);
1743   ok(hr == S_OK, "got 0x%08x\n", hr);
1744   ok(value == GetSystemDefaultLCID(), "got lcid %x, user lcid %x\n", value,
1745       GetSystemDefaultLCID());
1746 
1747   /* range is non-italic */
1748   value = tomTrue;
1749   hr = ITextFont_GetItalic(font, &value);
1750   ok(hr == S_OK, "got 0x%08x\n", hr);
1751   ok(value == tomFalse, "got %d\n", value);
1752 
1753   cf.cbSize = sizeof(CHARFORMAT2A);
1754   cf.dwMask = CFM_ITALIC|CFM_SIZE;
1755   cf.dwEffects = CFE_ITALIC;
1756   cf.yHeight = 24.0;
1757 
1758   SendMessageA(hwnd, EM_SETSEL, 2, 3);
1759   ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
1760   ok(ret, "got %d\n", ret);
1761 
1762   /* now range is partially italicized */
1763   value = tomFalse;
1764   hr = ITextFont_GetItalic(font, &value);
1765   ok(hr == S_OK, "got 0x%08x\n", hr);
1766   ok(value == tomUndefined, "got %d\n", value);
1767 
1768   size = 0.0;
1769   hr = ITextFont_GetSize(font, &size);
1770   ok(hr == S_OK, "got 0x%08x\n", hr);
1771   ok(size == tomUndefined, "size %.2f\n", size);
1772 
1773   ITextFont_Release(font);
1774   release_interfaces(&hwnd, &reOle, &doc, NULL);
1775 
1776   hr = ITextRange_GetFont(range, NULL);
1777   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1778 
1779   hr = ITextRange_GetFont(range, &font2);
1780   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1781 
1782   ITextRange_Release(range);
1783 }
1784 
1785 static void test_GetPara(void)
1786 {
1787   static const CHAR test_text1[] = "TestSomeText";
1788   IRichEditOle *reOle = NULL;
1789   ITextDocument *doc = NULL;
1790   ITextSelection *selection;
1791   ITextRange *range = NULL;
1792   ITextPara *para, *para2;
1793   HRESULT hr;
1794   HWND hwnd;
1795 
1796   create_interfaces(&hwnd, &reOle, &doc, &selection);
1797   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
1798 
1799   EXPECT_REF(reOle, 3);
1800   EXPECT_REF(doc, 3);
1801 
1802   hr = ITextDocument_Range(doc, 0, 4, &range);
1803   ok(hr == S_OK, "got 0x%08x\n", hr);
1804 
1805   EXPECT_REF(reOle, 3);
1806   EXPECT_REF(doc, 3);
1807   EXPECT_REF(range, 1);
1808 
1809   hr = ITextRange_GetPara(range, NULL);
1810   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1811 
1812   hr = ITextRange_GetPara(range, &para);
1813   ok(hr == S_OK, "got 0x%08x\n", hr);
1814 
1815   EXPECT_REF(reOle, 3);
1816   EXPECT_REF(doc, 3);
1817   EXPECT_REF(range, 2);
1818   EXPECT_REF(para, 1);
1819 
1820   hr = ITextRange_GetPara(range, &para2);
1821   ok(hr == S_OK, "got 0x%08x\n", hr);
1822   ok(para != para2, "got %p, %p\n", para, para2);
1823 
1824   EXPECT_REF(reOle, 3);
1825   EXPECT_REF(doc, 3);
1826   EXPECT_REF(range, 3);
1827   EXPECT_REF(para, 1);
1828   EXPECT_REF(para2, 1);
1829 
1830   ITextPara_Release(para);
1831   ITextPara_Release(para2);
1832 
1833   EXPECT_REF(reOle, 3);
1834   EXPECT_REF(doc, 3);
1835   EXPECT_REF(selection, 2);
1836 
1837   hr = ITextSelection_GetPara(selection, &para);
1838   ok(hr == S_OK, "got 0x%08x\n", hr);
1839 
1840   EXPECT_REF(reOle, 3);
1841   EXPECT_REF(doc, 3);
1842   EXPECT_REF(selection, 3);
1843   EXPECT_REF(para, 1);
1844 
1845   hr = ITextSelection_GetPara(selection, &para2);
1846   ok(hr == S_OK, "got 0x%08x\n", hr);
1847   ok(para != para2, "got %p, %p\n", para, para2);
1848 
1849   ITextPara_Release(para);
1850   ITextPara_Release(para2);
1851   release_interfaces(&hwnd, &reOle, &doc, NULL);
1852 
1853   hr = ITextRange_GetPara(range, NULL);
1854   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1855 
1856   hr = ITextRange_GetPara(range, &para);
1857   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1858 
1859   hr = ITextSelection_GetPara(selection, NULL);
1860   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1861 
1862   hr = ITextSelection_GetPara(selection, &para);
1863   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1864 
1865   ITextSelection_Release(selection);
1866   ITextRange_Release(range);
1867 }
1868 
1869 static void test_dispatch(void)
1870 {
1871   static const WCHAR testnameW[] = {'G','e','t','T','e','x','t',0};
1872   static const WCHAR testname2W[] = {'T','e','x','t',0};
1873   IRichEditOle *reOle = NULL;
1874   ITextDocument *doc = NULL;
1875   ITextRange *range = NULL;
1876   WCHAR *nameW;
1877   DISPID dispid;
1878   HRESULT hr;
1879   UINT count;
1880   HWND hwnd;
1881 
1882   create_interfaces(&hwnd, &reOle, &doc, NULL);
1883 
1884   range = NULL;
1885   hr = ITextDocument_Range(doc, 0, 0, &range);
1886   ok(hr == S_OK, "got 0x%08x\n", hr);
1887   ok(range != NULL, "got %p\n", range);
1888 
1889   dispid = 123;
1890   nameW = (WCHAR*)testnameW;
1891   hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1892   ok(hr == DISP_E_UNKNOWNNAME, "got 0x%08x\n", hr);
1893   ok(dispid == DISPID_UNKNOWN, "got %d\n", dispid);
1894 
1895   dispid = 123;
1896   nameW = (WCHAR*)testname2W;
1897   hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1898   ok(hr == S_OK, "got 0x%08x\n", hr);
1899   ok(dispid == DISPID_VALUE, "got %d\n", dispid);
1900 
1901   release_interfaces(&hwnd, &reOle, &doc, NULL);
1902 
1903   /* try dispatch methods on detached range */
1904   hr = ITextRange_GetTypeInfoCount(range, &count);
1905   ok(hr == S_OK, "got 0x%08x\n", hr);
1906 
1907   dispid = 123;
1908   nameW = (WCHAR*)testname2W;
1909   hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1910   ok(hr == S_OK, "got 0x%08x\n", hr);
1911   ok(dispid == DISPID_VALUE, "got %d\n", dispid);
1912 
1913   ITextRange_Release(range);
1914 }
1915 
1916 static void test_detached_font_getters(ITextFont *font, BOOL duplicate)
1917 {
1918   HRESULT hr, hrexp = duplicate ? S_OK : CO_E_RELEASED;
1919   LONG value;
1920   float size;
1921   BSTR str;
1922 
1923   hr = ITextFont_GetBold(font, NULL);
1924   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1925 
1926   hr = ITextFont_GetBold(font, &value);
1927   ok(hr == hrexp, "got 0x%08x\n", hr);
1928 
1929   hr = ITextFont_GetForeColor(font, NULL);
1930   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1931 
1932   hr = ITextFont_GetForeColor(font, &value);
1933   ok(hr == hrexp, "got 0x%08x\n", hr);
1934 
1935   hr = ITextFont_GetItalic(font, NULL);
1936   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1937 
1938   hr = ITextFont_GetItalic(font, &value);
1939   ok(hr == hrexp, "got 0x%08x\n", hr);
1940 
1941   hr = ITextFont_GetLanguageID(font, NULL);
1942   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1943 
1944   hr = ITextFont_GetLanguageID(font, &value);
1945   ok(hr == hrexp, "got 0x%08x\n", hr);
1946 
1947   hr = ITextFont_GetName(font, NULL);
1948   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1949 
1950   hr = ITextFont_GetName(font, &str);
1951   ok(hr == hrexp, "got 0x%08x\n", hr);
1952 
1953   hr = ITextFont_GetSize(font, NULL);
1954   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1955 
1956   hr = ITextFont_GetSize(font, &size);
1957   ok(hr == hrexp, "got 0x%08x\n", hr);
1958 
1959   hr = ITextFont_GetStrikeThrough(font, NULL);
1960   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1961 
1962   hr = ITextFont_GetStrikeThrough(font, &value);
1963   ok(hr == hrexp, "got 0x%08x\n", hr);
1964 
1965   hr = ITextFont_GetSubscript(font, NULL);
1966   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1967 
1968   hr = ITextFont_GetSubscript(font, &value);
1969   ok(hr == hrexp, "got 0x%08x\n", hr);
1970 
1971   hr = ITextFont_GetSuperscript(font, NULL);
1972   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1973 
1974   hr = ITextFont_GetSuperscript(font, &value);
1975   ok(hr == hrexp, "got 0x%08x\n", hr);
1976 
1977   hr = ITextFont_GetUnderline(font, NULL);
1978   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1979 
1980   hr = ITextFont_GetUnderline(font, &value);
1981   ok(hr == hrexp, "got 0x%08x\n", hr);
1982 }
1983 
1984 static void test_textfont_global_defaults(ITextFont *font)
1985 {
1986   float valuef;
1987   LONG value;
1988   HRESULT hr;
1989   BSTR str;
1990 
1991   value = tomUndefined;
1992   hr = ITextFont_GetAllCaps(font, &value);
1993   ok(hr == S_OK, "got 0x%08x\n", hr);
1994   ok(value == tomFalse, "got %d\n", value);
1995 
1996   value = tomUndefined;
1997   hr = ITextFont_GetAnimation(font, &value);
1998   ok(hr == S_OK, "got 0x%08x\n", hr);
1999   ok(value == tomFalse, "got %d\n", value);
2000 
2001   value = tomUndefined;
2002   hr = ITextFont_GetBackColor(font, &value);
2003   ok(hr == S_OK, "got 0x%08x\n", hr);
2004   ok(value == tomAutoColor, "got %d\n", value);
2005 
2006   value = tomUndefined;
2007   hr = ITextFont_GetBold(font, &value);
2008   ok(hr == S_OK, "got 0x%08x\n", hr);
2009   ok(value == tomFalse || value == tomTrue, "got %d\n", value);
2010 
2011   value = tomUndefined;
2012   hr = ITextFont_GetEmboss(font, &value);
2013   ok(hr == S_OK, "got 0x%08x\n", hr);
2014   ok(value == tomFalse, "got %d\n", value);
2015 
2016   value = tomUndefined;
2017   hr = ITextFont_GetForeColor(font, &value);
2018   ok(hr == S_OK, "got 0x%08x\n", hr);
2019   ok(value == tomAutoColor, "got %d\n", value);
2020 
2021   value = tomUndefined;
2022   hr = ITextFont_GetHidden(font, &value);
2023   ok(hr == S_OK, "got 0x%08x\n", hr);
2024   ok(value == tomFalse, "got %d\n", value);
2025 
2026   value = tomUndefined;
2027   hr = ITextFont_GetEngrave(font, &value);
2028   ok(hr == S_OK, "got 0x%08x\n", hr);
2029   ok(value == tomFalse, "got %d\n", value);
2030 
2031   value = tomUndefined;
2032   hr = ITextFont_GetItalic(font, &value);
2033   ok(hr == S_OK, "got 0x%08x\n", hr);
2034   ok(value == tomFalse, "got %d\n", value);
2035 
2036   valuef = 1.0;
2037   hr = ITextFont_GetKerning(font, &valuef);
2038   ok(hr == S_OK, "got 0x%08x\n", hr);
2039   ok(valuef == 0.0, "got %.2f\n", valuef);
2040 
2041   value = tomUndefined;
2042   hr = ITextFont_GetLanguageID(font, &value);
2043   ok(hr == S_OK, "got 0x%08x\n", hr);
2044   ok(value == GetSystemDefaultLCID(), "got %d\n", value);
2045 
2046   str = NULL;
2047   hr = ITextFont_GetName(font, &str);
2048   ok(hr == S_OK, "got 0x%08x\n", hr);
2049   ok(!lstrcmpW(sysW, str), "%s\n", wine_dbgstr_w(str));
2050   SysFreeString(str);
2051 
2052   value = tomUndefined;
2053   hr = ITextFont_GetOutline(font, &value);
2054   ok(hr == S_OK, "got 0x%08x\n", hr);
2055   ok(value == tomFalse, "got %d\n", value);
2056 
2057   valuef = 1.0;
2058   hr = ITextFont_GetPosition(font, &valuef);
2059   ok(hr == S_OK, "got 0x%08x\n", hr);
2060   ok(valuef == 0.0, "got %.2f\n", valuef);
2061 
2062   value = tomUndefined;
2063   hr = ITextFont_GetProtected(font, &value);
2064   ok(hr == S_OK, "got 0x%08x\n", hr);
2065   ok(value == tomFalse, "got %d\n", value);
2066 
2067   value = tomUndefined;
2068   hr = ITextFont_GetShadow(font, &value);
2069   ok(hr == S_OK, "got 0x%08x\n", hr);
2070   ok(value == tomFalse, "got %d\n", value);
2071 
2072   valuef = 0.0;
2073   hr = ITextFont_GetSize(font, &valuef);
2074   ok(hr == S_OK, "got 0x%08x\n", hr);
2075   ok(valuef >= 0.0, "got %.2f\n", valuef);
2076 
2077   value = tomUndefined;
2078   hr = ITextFont_GetSmallCaps(font, &value);
2079   ok(hr == S_OK, "got 0x%08x\n", hr);
2080   ok(value == tomFalse, "got %d\n", value);
2081 
2082   valuef = 1.0;
2083   hr = ITextFont_GetSpacing(font, &valuef);
2084   ok(hr == S_OK, "got 0x%08x\n", hr);
2085   ok(valuef == 0.0, "got %.2f\n", valuef);
2086 
2087   value = tomUndefined;
2088   hr = ITextFont_GetStrikeThrough(font, &value);
2089   ok(hr == S_OK, "got 0x%08x\n", hr);
2090   ok(value == tomFalse, "got %d\n", value);
2091 
2092   value = tomUndefined;
2093   hr = ITextFont_GetSubscript(font, &value);
2094   ok(hr == S_OK, "got 0x%08x\n", hr);
2095   ok(value == tomFalse, "got %d\n", value);
2096 
2097   value = tomUndefined;
2098   hr = ITextFont_GetSuperscript(font, &value);
2099   ok(hr == S_OK, "got 0x%08x\n", hr);
2100   ok(value == tomFalse, "got %d\n", value);
2101 
2102   value = tomUndefined;
2103   hr = ITextFont_GetUnderline(font, &value);
2104   ok(hr == S_OK, "got 0x%08x\n", hr);
2105   ok(value == tomFalse, "got %d\n", value);
2106 
2107   value = tomUndefined;
2108   hr = ITextFont_GetWeight(font, &value);
2109   ok(hr == S_OK, "got 0x%08x\n", hr);
2110   ok(value == FW_NORMAL || value == FW_BOLD, "got %d\n", value);
2111 }
2112 
2113 static void test_textfont_undefined(ITextFont *font)
2114 {
2115   float valuef;
2116   LONG value;
2117   HRESULT hr;
2118 
2119   value = tomFalse;
2120   hr = ITextFont_GetAllCaps(font, &value);
2121   ok(hr == S_OK, "got 0x%08x\n", hr);
2122   ok(value == tomUndefined, "got %d\n", value);
2123 
2124   value = tomFalse;
2125   hr = ITextFont_GetAnimation(font, &value);
2126   ok(hr == S_OK, "got 0x%08x\n", hr);
2127   ok(value == tomUndefined, "got %d\n", value);
2128 
2129   value = tomFalse;
2130   hr = ITextFont_GetBackColor(font, &value);
2131   ok(hr == S_OK, "got 0x%08x\n", hr);
2132   ok(value == tomUndefined, "got %d\n", value);
2133 
2134   value = tomFalse;
2135   hr = ITextFont_GetBold(font, &value);
2136   ok(hr == S_OK, "got 0x%08x\n", hr);
2137   ok(value == tomUndefined, "got %d\n", value);
2138 
2139   value = tomFalse;
2140   hr = ITextFont_GetEmboss(font, &value);
2141   ok(hr == S_OK, "got 0x%08x\n", hr);
2142   ok(value == tomUndefined, "got %d\n", value);
2143 
2144   value = tomFalse;
2145   hr = ITextFont_GetForeColor(font, &value);
2146   ok(hr == S_OK, "got 0x%08x\n", hr);
2147   ok(value == tomUndefined, "got %d\n", value);
2148 
2149   value = tomFalse;
2150   hr = ITextFont_GetHidden(font, &value);
2151   ok(hr == S_OK, "got 0x%08x\n", hr);
2152   ok(value == tomUndefined, "got %d\n", value);
2153 
2154   value = tomFalse;
2155   hr = ITextFont_GetEngrave(font, &value);
2156   ok(hr == S_OK, "got 0x%08x\n", hr);
2157   ok(value == tomUndefined, "got %d\n", value);
2158 
2159   value = tomFalse;
2160   hr = ITextFont_GetItalic(font, &value);
2161   ok(hr == S_OK, "got 0x%08x\n", hr);
2162   ok(value == tomUndefined, "got %d\n", value);
2163 
2164   valuef = 0.0;
2165   hr = ITextFont_GetKerning(font, &valuef);
2166   ok(hr == S_OK, "got 0x%08x\n", hr);
2167   ok(valuef == tomUndefined, "got %.2f\n", valuef);
2168 
2169   value = tomFalse;
2170   hr = ITextFont_GetLanguageID(font, &value);
2171   ok(hr == S_OK, "got 0x%08x\n", hr);
2172   ok(value == tomUndefined, "got %d\n", value);
2173 
2174   value = tomFalse;
2175   hr = ITextFont_GetOutline(font, &value);
2176   ok(hr == S_OK, "got 0x%08x\n", hr);
2177   ok(value == tomUndefined, "got %d\n", value);
2178 
2179   valuef = 0.0;
2180   hr = ITextFont_GetPosition(font, &valuef);
2181   ok(hr == S_OK, "got 0x%08x\n", hr);
2182   ok(valuef == tomUndefined, "got %.2f\n", valuef);
2183 
2184   value = tomFalse;
2185   hr = ITextFont_GetProtected(font, &value);
2186   ok(hr == S_OK, "got 0x%08x\n", hr);
2187   ok(value == tomUndefined, "got %d\n", value);
2188 
2189   value = tomFalse;
2190   hr = ITextFont_GetShadow(font, &value);
2191   ok(hr == S_OK, "got 0x%08x\n", hr);
2192   ok(value == tomUndefined, "got %d\n", value);
2193 
2194   valuef = 0.0;
2195   hr = ITextFont_GetSize(font, &valuef);
2196   ok(hr == S_OK, "got 0x%08x\n", hr);
2197   ok(valuef == tomUndefined, "got %.2f\n", valuef);
2198 
2199   value = tomFalse;
2200   hr = ITextFont_GetSmallCaps(font, &value);
2201   ok(hr == S_OK, "got 0x%08x\n", hr);
2202   ok(value == tomUndefined, "got %d\n", value);
2203 
2204   valuef = 0.0;
2205   hr = ITextFont_GetSpacing(font, &valuef);
2206   ok(hr == S_OK, "got 0x%08x\n", hr);
2207   ok(valuef == tomUndefined, "got %.2f\n", valuef);
2208 
2209   value = tomFalse;
2210   hr = ITextFont_GetStrikeThrough(font, &value);
2211   ok(hr == S_OK, "got 0x%08x\n", hr);
2212   ok(value == tomUndefined, "got %d\n", value);
2213 
2214   value = tomFalse;
2215   hr = ITextFont_GetSubscript(font, &value);
2216   ok(hr == S_OK, "got 0x%08x\n", hr);
2217   ok(value == tomUndefined, "got %d\n", value);
2218 
2219   value = tomFalse;
2220   hr = ITextFont_GetSuperscript(font, &value);
2221   ok(hr == S_OK, "got 0x%08x\n", hr);
2222   ok(value == tomUndefined, "got %d\n", value);
2223 
2224   value = tomFalse;
2225   hr = ITextFont_GetUnderline(font, &value);
2226   ok(hr == S_OK, "got 0x%08x\n", hr);
2227   ok(value == tomUndefined, "got %d\n", value);
2228 
2229   value = tomFalse;
2230   hr = ITextFont_GetWeight(font, &value);
2231   ok(hr == S_OK, "got 0x%08x\n", hr);
2232   ok(value == tomUndefined, "got %d\n", value);
2233 }
2234 
2235 static inline FLOAT twips_to_points(LONG value)
2236 {
2237   return value * 72.0 / 1440;
2238 }
2239 
2240 static void test_ITextFont(void)
2241 {
2242   static const WCHAR arialW[] = {'A','r','i','a','l',0};
2243   static const CHAR test_text1[] = "TestSomeText";
2244   ITextFont *font, *font2, *font3;
2245   FLOAT size, position, kerning;
2246   IRichEditOle *reOle = NULL;
2247   ITextDocument *doc = NULL;
2248   ITextRange *range = NULL;
2249   CHARFORMAT2A cf;
2250   LONG value;
2251   HRESULT hr;
2252   HWND hwnd;
2253   BOOL ret;
2254   BSTR str;
2255 
2256   create_interfaces(&hwnd, &reOle, &doc, NULL);
2257   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2258 
2259   hr = ITextDocument_Range(doc, 0, 10, &range);
2260   ok(hr == S_OK, "got 0x%08x\n", hr);
2261 
2262   hr = ITextRange_GetFont(range, &font);
2263   ok(hr == S_OK, "got 0x%08x\n", hr);
2264 
2265   hr = ITextFont_Reset(font, tomUseTwips);
2266   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2267 
2268   hr = ITextFont_Reset(font, tomUsePoints);
2269   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2270 
2271   hr = ITextFont_GetName(font, NULL);
2272   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2273 
2274   /* default font size unit is point */
2275   size = 0.0;
2276   hr = ITextFont_GetSize(font, &size);
2277   ok(hr == S_OK, "got 0x%08x\n", hr);
2278 
2279   /* set to some non-zero values */
2280   hr = ITextFont_SetPosition(font, 20.0);
2281   ok(hr == S_OK, "got 0x%08x\n", hr);
2282 
2283   hr = ITextFont_SetKerning(font, 10.0);
2284   ok(hr == S_OK, "got 0x%08x\n", hr);
2285 
2286   position = 0.0;
2287   hr = ITextFont_GetPosition(font, &position);
2288   ok(hr == S_OK, "got 0x%08x\n", hr);
2289 
2290   kerning = 0.0;
2291   hr = ITextFont_GetKerning(font, &kerning);
2292   ok(hr == S_OK, "got 0x%08x\n", hr);
2293 
2294   memset(&cf, 0, sizeof(cf));
2295   cf.cbSize = sizeof(cf);
2296   cf.dwMask = CFM_SIZE|CFM_OFFSET|CFM_KERNING;
2297 
2298   /* CHARFORMAT members are in twips */
2299   SendMessageA(hwnd, EM_SETSEL, 0, 10);
2300   ret = SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2301   ok(ret, "got %d\n", ret);
2302   ok(size == twips_to_points(cf.yHeight), "got yHeight %d, size %.2f\n", cf.yHeight, size);
2303   ok(position == twips_to_points(cf.yOffset), "got yOffset %d, position %.2f\n", cf.yOffset, position);
2304   ok(kerning == twips_to_points(cf.wKerning), "got wKerning %d, kerning %.2f\n", cf.wKerning, kerning);
2305 
2306   hr = ITextFont_Reset(font, tomUseTwips);
2307   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2308 
2309   hr = ITextFont_Reset(font, tomUsePoints);
2310   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2311 
2312   hr = ITextFont_GetDuplicate(font, &font2);
2313   ok(hr == S_OK, "got 0x%08x\n", hr);
2314 
2315   hr = ITextFont_Reset(font2, tomUseTwips);
2316   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2317 
2318   hr = ITextFont_Reset(font2, tomUsePoints);
2319   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2320 
2321   ITextFont_Release(font2);
2322 
2323   /* default font name */
2324   str = NULL;
2325   hr = ITextFont_GetName(font, &str);
2326   ok(hr == S_OK, "got 0x%08x\n", hr);
2327   ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2328   SysFreeString(str);
2329 
2330   /* change font name for an inner subrange */
2331   memset(&cf, 0, sizeof(cf));
2332   cf.cbSize = sizeof(cf);
2333   cf.dwMask = CFM_FACE;
2334   strcpy(cf.szFaceName, "Arial");
2335 
2336   SendMessageA(hwnd, EM_SETSEL, 3, 4);
2337   ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2338   ok(ret, "got %d\n", ret);
2339 
2340   /* still original name */
2341   str = NULL;
2342   hr = ITextFont_GetName(font, &str);
2343   ok(hr == S_OK, "got 0x%08x\n", hr);
2344   ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2345   SysFreeString(str);
2346 
2347   SendMessageA(hwnd, EM_SETSEL, 1, 2);
2348   ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2349   ok(ret, "got %d\n", ret);
2350 
2351   str = NULL;
2352   hr = ITextFont_GetName(font, &str);
2353   ok(hr == S_OK, "got 0x%08x\n", hr);
2354   ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2355   SysFreeString(str);
2356 
2357   /* name is returned for first position within a range */
2358   SendMessageA(hwnd, EM_SETSEL, 0, 1);
2359   ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2360   ok(ret, "got %d\n", ret);
2361 
2362   str = NULL;
2363   hr = ITextFont_GetName(font, &str);
2364   ok(hr == S_OK, "got 0x%08x\n", hr);
2365   ok(!lstrcmpW(str, arialW), "got %s\n", wine_dbgstr_w(str));
2366   SysFreeString(str);
2367 
2368   /* GetDuplicate() */
2369   hr = ITextFont_GetDuplicate(font, NULL);
2370   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2371 
2372   EXPECT_REF(range, 2);
2373   font2 = NULL;
2374   hr = ITextFont_GetDuplicate(font, &font2);
2375   ok(hr == S_OK, "got 0x%08x\n", hr);
2376   EXPECT_REF(range, 2);
2377 
2378   /* set whole range to italic */
2379   cf.cbSize = sizeof(CHARFORMAT2A);
2380   cf.dwMask = CFM_ITALIC;
2381   cf.dwEffects = CFE_ITALIC;
2382 
2383   SendMessageA(hwnd, EM_SETSEL, 0, 10);
2384   ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2385   ok(ret, "got %d\n", ret);
2386 
2387   value = tomFalse;
2388   hr = ITextFont_GetItalic(font, &value);
2389   ok(hr == S_OK, "got 0x%08x\n", hr);
2390   ok(value == tomTrue, "got %d\n", value);
2391 
2392   /* duplicate retains original value */
2393   value = tomTrue;
2394   hr = ITextFont_GetItalic(font2, &value);
2395   ok(hr == S_OK, "got 0x%08x\n", hr);
2396   ok(value == tomFalse, "got %d\n", value);
2397 
2398   /* get a duplicate from a cloned font */
2399   hr = ITextFont_GetDuplicate(font2, &font3);
2400   ok(hr == S_OK, "got 0x%08x\n", hr);
2401   ITextFont_Release(font3);
2402 
2403   ITextRange_Release(range);
2404   release_interfaces(&hwnd, &reOle, &doc, NULL);
2405 
2406   hr = ITextFont_GetDuplicate(font, NULL);
2407   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2408 
2409   test_detached_font_getters(font, FALSE);
2410   test_detached_font_getters(font2, TRUE);
2411 
2412   /* get a duplicate of detached font */
2413   hr = ITextFont_GetDuplicate(font2, &font3);
2414   ok(hr == S_OK, "got 0x%08x\n", hr);
2415   ITextFont_Release(font3);
2416 
2417   /* reset detached font to undefined */
2418   value = tomUndefined;
2419   hr = ITextFont_GetBold(font2, &value);
2420   ok(hr == S_OK, "got 0x%08x\n", hr);
2421   ok(value != tomUndefined, "got %d\n", value);
2422 
2423   /* reset to undefined for detached font */
2424   hr = ITextFont_Reset(font2, tomUndefined);
2425   ok(hr == S_OK, "got 0x%08x\n", hr);
2426   test_textfont_undefined(font2);
2427 
2428   /* font is detached, default means global TOM defaults */
2429   hr = ITextFont_Reset(font2, tomDefault);
2430   ok(hr == S_OK, "got 0x%08x\n", hr);
2431   test_textfont_global_defaults(font2);
2432 
2433   hr = ITextFont_GetDuplicate(font2, &font3);
2434   ok(hr == S_OK, "got 0x%08x\n", hr);
2435   test_textfont_global_defaults(font2);
2436 
2437   hr = ITextFont_Reset(font2, tomApplyNow);
2438   ok(hr == S_OK, "got 0x%08x\n", hr);
2439   test_textfont_global_defaults(font2);
2440 
2441   hr = ITextFont_Reset(font2, tomApplyLater);
2442   ok(hr == S_OK, "got 0x%08x\n", hr);
2443   test_textfont_global_defaults(font2);
2444 
2445   hr = ITextFont_Reset(font2, tomTrackParms);
2446   ok(hr == S_OK, "got 0x%08x\n", hr);
2447   test_textfont_global_defaults(font2);
2448 
2449   hr = ITextFont_SetItalic(font2, tomUndefined);
2450   ok(hr == S_OK, "got 0x%08x\n", hr);
2451 
2452   hr = ITextFont_GetItalic(font2, &value);
2453   ok(hr == S_OK, "got 0x%08x\n", hr);
2454   ok(value == tomFalse, "got %d\n", value);
2455 
2456   hr = ITextFont_Reset(font2, tomCacheParms);
2457   ok(hr == S_OK, "got 0x%08x\n", hr);
2458   test_textfont_global_defaults(font2);
2459 
2460   ITextFont_Release(font3);
2461   ITextFont_Release(font2);
2462 
2463   font2 = (void*)0xdeadbeef;
2464   hr = ITextFont_GetDuplicate(font, &font2);
2465   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2466   ok(font2 == NULL, "got %p\n", font2);
2467 
2468   hr = ITextFont_Reset(font, tomDefault);
2469   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2470 
2471   ITextFont_Release(font);
2472 
2473   /* Reset() */
2474   create_interfaces(&hwnd, &reOle, &doc, NULL);
2475   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2476 
2477   hr = ITextDocument_Range(doc, 0, 10, &range);
2478   ok(hr == S_OK, "got 0x%08x\n", hr);
2479 
2480   hr = ITextRange_GetFont(range, &font);
2481   ok(hr == S_OK, "got 0x%08x\n", hr);
2482 
2483   value = tomUndefined;
2484   hr = ITextFont_GetBold(font, &value);
2485   ok(hr == S_OK, "got 0x%08x\n", hr);
2486   ok(value != tomUndefined, "got %d\n", value);
2487 
2488   /* reset to undefined for attached font */
2489   hr = ITextFont_Reset(font, tomUndefined);
2490   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2491 
2492   value = tomUndefined;
2493   hr = ITextFont_GetBold(font, &value);
2494   ok(hr == S_OK, "got 0x%08x\n", hr);
2495   ok(value != tomUndefined, "got %d\n", value);
2496 
2497   /* tomCacheParms/tomTrackParms */
2498   hr = ITextFont_Reset(font, tomCacheParms);
2499   ok(hr == S_OK, "got 0x%08x\n", hr);
2500 
2501   hr = ITextFont_GetItalic(font, &value);
2502   ok(hr == S_OK, "got 0x%08x\n", hr);
2503   ok(value == tomFalse, "got %d\n", value);
2504 
2505   memset(&cf, 0, sizeof(cf));
2506   cf.cbSize = sizeof(CHARFORMAT2A);
2507   cf.dwMask = CFM_ITALIC;
2508 
2509   cf.dwEffects = CFE_ITALIC;
2510   SendMessageA(hwnd, EM_SETSEL, 0, 10);
2511   ret = SendMessageA(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2512   ok(ret, "got %d\n", ret);
2513 
2514   /* still cached value */
2515   hr = ITextFont_GetItalic(font, &value);
2516   ok(hr == S_OK, "got 0x%08x\n", hr);
2517   ok(value == tomFalse, "got %d\n", value);
2518 
2519   hr = ITextFont_Reset(font, tomTrackParms);
2520   ok(hr == S_OK, "got 0x%08x\n", hr);
2521 
2522   hr = ITextFont_GetItalic(font, &value);
2523   ok(hr == S_OK, "got 0x%08x\n", hr);
2524   ok(value == tomTrue, "got %d\n", value);
2525 
2526   /* switch back to cache - value retained */
2527   hr = ITextFont_Reset(font, tomCacheParms);
2528   ok(hr == S_OK, "got 0x%08x\n", hr);
2529 
2530   hr = ITextFont_GetItalic(font, &value);
2531   ok(hr == S_OK, "got 0x%08x\n", hr);
2532   ok(value == tomTrue, "got %d\n", value);
2533 
2534   /* tomApplyLater */
2535   hr = ITextFont_Reset(font, tomApplyLater);
2536   ok(hr == S_OK, "got 0x%08x\n", hr);
2537 
2538   hr = ITextFont_SetItalic(font, tomFalse);
2539   ok(hr == S_OK, "got 0x%08x\n", hr);
2540 
2541   hr = ITextFont_GetItalic(font, &value);
2542   ok(hr == S_OK, "got 0x%08x\n", hr);
2543   ok(value == tomFalse, "got %d\n", value);
2544 
2545   cf.dwEffects = 0;
2546   SendMessageA(hwnd, EM_SETSEL, 0, 10);
2547   ret = SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2548   ok(ret, "got %d\n", ret);
2549   ok((cf.dwEffects & CFE_ITALIC) == CFE_ITALIC, "got 0x%08x\n", cf.dwEffects);
2550 
2551   hr = ITextFont_Reset(font, tomApplyNow);
2552   ok(hr == S_OK, "got 0x%08x\n", hr);
2553 
2554   cf.dwEffects = 0;
2555   SendMessageA(hwnd, EM_SETSEL, 0, 10);
2556   ret = SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2557   ok(ret, "got %d\n", ret);
2558   ok((cf.dwEffects & CFE_ITALIC) == 0, "got 0x%08x\n", cf.dwEffects);
2559 
2560   hr = ITextFont_SetItalic(font, tomUndefined);
2561   ok(hr == S_OK, "got 0x%08x\n", hr);
2562 
2563   hr = ITextFont_GetItalic(font, &value);
2564   ok(hr == S_OK, "got 0x%08x\n", hr);
2565   ok(value == tomFalse, "got %d\n", value);
2566 
2567   hr = ITextFont_SetItalic(font, tomAutoColor);
2568   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2569 
2570   cf.dwEffects = 0;
2571   SendMessageA(hwnd, EM_SETSEL, 0, 10);
2572   ret = SendMessageA(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
2573   ok(ret, "got %d\n", ret);
2574   ok((cf.dwEffects & CFE_ITALIC) == 0, "got 0x%08x\n", cf.dwEffects);
2575 
2576   ITextRange_Release(range);
2577   ITextFont_Release(font);
2578   release_interfaces(&hwnd, &reOle, &doc, NULL);
2579 }
2580 
2581 static void test_Delete(void)
2582 {
2583   static const CHAR test_text1[] = "TestSomeText";
2584   IRichEditOle *reOle = NULL;
2585   ITextDocument *doc = NULL;
2586   ITextRange *range, *range2;
2587   LONG value;
2588   HRESULT hr;
2589   HWND hwnd;
2590 
2591   create_interfaces(&hwnd, &reOle, &doc, NULL);
2592   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2593 
2594   hr = ITextDocument_Range(doc, 0, 4, &range);
2595   ok(hr == S_OK, "got 0x%08x\n", hr);
2596 
2597   hr = ITextDocument_Range(doc, 1, 2, &range2);
2598   ok(hr == S_OK, "got 0x%08x\n", hr);
2599 
2600   hr = ITextRange_GetEnd(range, &value);
2601   ok(hr == S_OK, "got 0x%08x\n", hr);
2602   ok(value == 4, "got %d\n", value);
2603 
2604   /* unit type doesn't matter is count is 0 */
2605   value = 0;
2606   hr = ITextRange_Delete(range2, tomSentence, 0, &value);
2607 todo_wine {
2608   ok(hr == S_OK, "got 0x%08x\n", hr);
2609   ok(value == 1, "got %d\n", value);
2610 }
2611   value = 1;
2612   hr = ITextRange_Delete(range2, tomCharacter, 0, &value);
2613 todo_wine {
2614   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2615   ok(value == 0, "got %d\n", value);
2616 }
2617   hr = ITextRange_GetEnd(range, &value);
2618   ok(hr == S_OK, "got 0x%08x\n", hr);
2619 todo_wine
2620   ok(value == 3, "got %d\n", value);
2621 
2622   hr = ITextRange_GetStart(range2, &value);
2623   ok(hr == S_OK, "got 0x%08x\n", hr);
2624   ok(value == 1, "got %d\n", value);
2625 
2626   hr = ITextRange_GetEnd(range2, &value);
2627   ok(hr == S_OK, "got 0x%08x\n", hr);
2628 todo_wine
2629   ok(value == 1, "got %d\n", value);
2630 
2631   ITextRange_Release(range);
2632   ITextRange_Release(range2);
2633   release_interfaces(&hwnd, &reOle, &doc, NULL);
2634 }
2635 
2636 static void test_SetText(void)
2637 {
2638   static const CHAR test_text1[] = "TestSomeText";
2639   static const WCHAR textW[] = {'a','b','c','d','e','f','g','h','i',0};
2640   IRichEditOle *reOle = NULL;
2641   ITextDocument *doc = NULL;
2642   ITextRange *range, *range2;
2643   LONG value;
2644   HRESULT hr;
2645   HWND hwnd;
2646   BSTR str;
2647 
2648   create_interfaces(&hwnd, &reOle, &doc, NULL);
2649   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2650 
2651   hr = ITextDocument_Range(doc, 0, 4, &range);
2652   ok(hr == S_OK, "got 0x%08x\n", hr);
2653 
2654   hr = ITextDocument_Range(doc, 0, 4, &range2);
2655   ok(hr == S_OK, "got 0x%08x\n", hr);
2656 
2657   value = 1;
2658   hr = ITextRange_GetStart(range2, &value);
2659   ok(hr == S_OK, "got 0x%08x\n", hr);
2660   ok(value == 0, "got %d\n", value);
2661 
2662   value = 0;
2663   hr = ITextRange_GetEnd(range2, &value);
2664   ok(hr == S_OK, "got 0x%08x\n", hr);
2665   ok(value == 4, "got %d\n", value);
2666 
2667   hr = ITextRange_SetText(range, NULL);
2668   ok(hr == S_OK, "got 0x%08x\n", hr);
2669 
2670   value = 1;
2671   hr = ITextRange_GetEnd(range2, &value);
2672   ok(hr == S_OK, "got 0x%08x\n", hr);
2673   ok(value == 0, "got %d\n", value);
2674 
2675   str = SysAllocString(textW);
2676   hr = ITextRange_SetText(range, str);
2677   ok(hr == S_OK, "got 0x%08x\n", hr);
2678   SysFreeString(str);
2679 
2680   value = 1;
2681   hr = ITextRange_GetStart(range, &value);
2682   ok(hr == S_OK, "got 0x%08x\n", hr);
2683   ok(value == 0, "got %d\n", value);
2684 
2685   value = 0;
2686   hr = ITextRange_GetEnd(range, &value);
2687   ok(hr == S_OK, "got 0x%08x\n", hr);
2688   ok(value == 9, "got %d\n", value);
2689 
2690   value = 1;
2691   hr = ITextRange_GetStart(range2, &value);
2692   ok(hr == S_OK, "got 0x%08x\n", hr);
2693   ok(value == 0, "got %d\n", value);
2694 
2695   value = 0;
2696   hr = ITextRange_GetEnd(range2, &value);
2697   ok(hr == S_OK, "got 0x%08x\n", hr);
2698   ok(value == 0, "got %d\n", value);
2699 
2700   str = SysAllocStringLen(NULL, 0);
2701   hr = ITextRange_SetText(range, str);
2702   ok(hr == S_OK, "got 0x%08x\n", hr);
2703   value = 1;
2704   hr = ITextRange_GetEnd(range, &value);
2705   ok(hr == S_OK, "got 0x%08x\n", hr);
2706   ok(value == 0, "got %d\n", value);
2707   SysFreeString(str);
2708 
2709   ITextRange_Release(range2);
2710   release_interfaces(&hwnd, &reOle, &doc, NULL);
2711 
2712   hr = ITextRange_SetText(range, NULL);
2713   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2714 
2715   str = SysAllocStringLen(NULL, 0);
2716   hr = ITextRange_SetText(range, str);
2717   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2718   SysFreeString(str);
2719 
2720   ITextRange_Release(range);
2721 }
2722 
2723 static void test_InRange(void)
2724 {
2725   static const CHAR test_text1[] = "TestSomeText";
2726   ITextRange *range, *range2, *range3;
2727   IRichEditOle *reOle = NULL;
2728   ITextDocument *doc = NULL;
2729   ITextSelection *selection;
2730   LONG value;
2731   HRESULT hr;
2732   HWND hwnd;
2733 
2734   create_interfaces(&hwnd, &reOle, &doc, &selection);
2735   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2736   SendMessageA(hwnd, EM_SETSEL, 1, 2);
2737 
2738   hr = ITextDocument_Range(doc, 0, 4, &range);
2739   ok(hr == S_OK, "got 0x%08x\n", hr);
2740 
2741   hr = ITextDocument_Range(doc, 0, 4, &range2);
2742   ok(hr == S_OK, "got 0x%08x\n", hr);
2743 
2744   /* matches selection */
2745   hr = ITextDocument_Range(doc, 1, 2, &range3);
2746   ok(hr == S_OK, "got 0x%08x\n", hr);
2747 
2748   hr = ITextRange_InRange(range, NULL, NULL);
2749   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2750 
2751   value = tomTrue;
2752   hr = ITextRange_InRange(range, NULL, &value);
2753   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2754   ok(value == tomFalse, "got %d\n", value);
2755 
2756   hr = ITextRange_InRange(range, range2, NULL);
2757   ok(hr == S_OK, "got 0x%08x\n", hr);
2758 
2759   value = tomFalse;
2760   hr = ITextRange_InRange(range, range2, &value);
2761   ok(hr == S_OK, "got 0x%08x\n", hr);
2762   ok(value == tomTrue, "got %d\n", value);
2763 
2764   /* selection */
2765   hr = ITextSelection_InRange(selection, NULL, NULL);
2766   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2767 
2768   value = tomTrue;
2769   hr = ITextSelection_InRange(selection, NULL, &value);
2770   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2771   ok(value == tomFalse, "got %d\n", value);
2772 
2773   hr = ITextSelection_InRange(selection, range2, NULL);
2774   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2775 
2776   value = tomTrue;
2777   hr = ITextSelection_InRange(selection, range2, &value);
2778   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2779   ok(value == tomFalse, "got %d\n", value);
2780 
2781   value = tomTrue;
2782   hr = ITextSelection_InRange(selection, range3, &value);
2783   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2784   ok(value == tomFalse, "got %d\n", value);
2785 
2786   /* seems to work on ITextSelection ranges only */
2787   value = tomFalse;
2788   hr = ITextSelection_InRange(selection, (ITextRange*)selection, &value);
2789   ok(hr == S_OK, "got 0x%08x\n", hr);
2790   ok(value == tomTrue, "got %d\n", value);
2791 
2792   release_interfaces(&hwnd, &reOle, &doc, NULL);
2793 
2794   hr = ITextRange_InRange(range, NULL, NULL);
2795   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2796 
2797   value = tomTrue;
2798   hr = ITextRange_InRange(range, NULL, &value);
2799   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2800   ok(value == tomFalse, "got %d\n", value);
2801 
2802   hr = ITextRange_InRange(range, range2, NULL);
2803   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2804 
2805   value = tomTrue;
2806   hr = ITextRange_InRange(range, range2, &value);
2807   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2808   ok(value == tomFalse, "got %d\n", value);
2809 
2810   /* selection */
2811   hr = ITextSelection_InRange(selection, NULL, NULL);
2812   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2813 
2814   value = tomTrue;
2815   hr = ITextSelection_InRange(selection, NULL, &value);
2816   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2817   ok(value == tomFalse, "got %d\n", value);
2818 
2819   hr = ITextSelection_InRange(selection, range2, NULL);
2820   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2821 
2822   value = tomTrue;
2823   hr = ITextSelection_InRange(selection, range2, &value);
2824   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2825   ok(value == tomFalse, "got %d\n", value);
2826 
2827   ITextRange_Release(range);
2828   ITextRange_Release(range2);
2829   ITextRange_Release(range3);
2830   ITextSelection_Release(selection);
2831 }
2832 
2833 static void test_ITextRange_IsEqual(void)
2834 {
2835   static const CHAR test_text1[] = "TestSomeText";
2836   ITextRange *range, *range2, *range3;
2837   IRichEditOle *reOle = NULL;
2838   ITextDocument *doc = NULL;
2839   ITextSelection *selection;
2840   LONG value;
2841   HRESULT hr;
2842   HWND hwnd;
2843 
2844   create_interfaces(&hwnd, &reOle, &doc, &selection);
2845   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2846   SendMessageA(hwnd, EM_SETSEL, 1, 2);
2847 
2848   hr = ITextDocument_Range(doc, 0, 4, &range);
2849   ok(hr == S_OK, "got 0x%08x\n", hr);
2850 
2851   hr = ITextDocument_Range(doc, 0, 4, &range2);
2852   ok(hr == S_OK, "got 0x%08x\n", hr);
2853 
2854   /* matches selection */
2855   hr = ITextDocument_Range(doc, 1, 2, &range3);
2856   ok(hr == S_OK, "got 0x%08x\n", hr);
2857 
2858   hr = ITextRange_IsEqual(range, NULL, NULL);
2859   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2860 
2861   value = tomTrue;
2862   hr = ITextRange_IsEqual(range, NULL, &value);
2863   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2864   ok(value == tomFalse, "got %d\n", value);
2865 
2866   hr = ITextRange_IsEqual(range, range2, NULL);
2867   ok(hr == S_OK, "got 0x%08x\n", hr);
2868 
2869   value = tomFalse;
2870   hr = ITextRange_IsEqual(range, range2, &value);
2871   ok(hr == S_OK, "got 0x%08x\n", hr);
2872   ok(value == tomTrue, "got %d\n", value);
2873 
2874   value = tomTrue;
2875   hr = ITextRange_IsEqual(range, range3, &value);
2876   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2877   ok(value == tomFalse, "got %d\n", value);
2878 
2879   /* selection */
2880   hr = ITextSelection_IsEqual(selection, NULL, NULL);
2881   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2882 
2883   value = tomTrue;
2884   hr = ITextSelection_IsEqual(selection, NULL, &value);
2885   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2886   ok(value == tomFalse, "got %d\n", value);
2887 
2888   hr = ITextSelection_IsEqual(selection, range2, NULL);
2889   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2890 
2891   value = tomTrue;
2892   hr = ITextSelection_IsEqual(selection, range2, &value);
2893   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2894   ok(value == tomFalse, "got %d\n", value);
2895 
2896   value = tomTrue;
2897   hr = ITextSelection_IsEqual(selection, range3, &value);
2898   ok(hr == S_FALSE, "got 0x%08x\n", hr);
2899   ok(value == tomFalse, "got %d\n", value);
2900 
2901   /* seems to work on ITextSelection ranges only */
2902   value = tomFalse;
2903   hr = ITextSelection_IsEqual(selection, (ITextRange*)selection, &value);
2904   ok(hr == S_OK, "got 0x%08x\n", hr);
2905   ok(value == tomTrue, "got %d\n", value);
2906 
2907   release_interfaces(&hwnd, &reOle, &doc, NULL);
2908 
2909   hr = ITextRange_IsEqual(range, NULL, NULL);
2910   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2911 
2912   value = tomTrue;
2913   hr = ITextRange_IsEqual(range, NULL, &value);
2914   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2915   ok(value == tomFalse, "got %d\n", value);
2916 
2917   hr = ITextRange_IsEqual(range, range2, NULL);
2918   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2919 
2920   value = tomTrue;
2921   hr = ITextRange_IsEqual(range, range2, &value);
2922   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2923   ok(value == tomFalse, "got %d\n", value);
2924 
2925   /* selection */
2926   hr = ITextSelection_IsEqual(selection, NULL, NULL);
2927   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2928 
2929   value = tomTrue;
2930   hr = ITextSelection_IsEqual(selection, NULL, &value);
2931   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2932   ok(value == tomFalse, "got %d\n", value);
2933 
2934   hr = ITextSelection_IsEqual(selection, range2, NULL);
2935   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2936 
2937   value = tomTrue;
2938   hr = ITextSelection_IsEqual(selection, range2, &value);
2939   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2940   ok(value == tomFalse, "got %d\n", value);
2941 
2942   ITextRange_Release(range);
2943   ITextRange_Release(range2);
2944   ITextRange_Release(range3);
2945   ITextSelection_Release(selection);
2946 }
2947 
2948 static void test_Select(void)
2949 {
2950   static const CHAR test_text1[] = "TestSomeText";
2951   IRichEditOle *reOle = NULL;
2952   ITextDocument *doc = NULL;
2953   ITextSelection *selection;
2954   ITextRange *range;
2955   LONG value;
2956   HRESULT hr;
2957   HWND hwnd;
2958 
2959   create_interfaces(&hwnd, &reOle, &doc, &selection);
2960   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2961   SendMessageA(hwnd, EM_SETSEL, 1, 2);
2962 
2963   hr = ITextDocument_Range(doc, 0, 4, &range);
2964   ok(hr == S_OK, "got 0x%08x\n", hr);
2965 
2966   hr = ITextRange_Select(range);
2967   ok(hr == S_OK, "got 0x%08x\n", hr);
2968 
2969   value = 1;
2970   hr = ITextSelection_GetStart(selection, &value);
2971   ok(hr == S_OK, "got 0x%08x\n", hr);
2972   ok(value == 0, "got %d\n", value);
2973 
2974   hr = ITextRange_Select(range);
2975   ok(hr == S_OK, "got 0x%08x\n", hr);
2976 
2977   hr = ITextSelection_Select(selection);
2978   ok(hr == S_OK, "got 0x%08x\n", hr);
2979 
2980   release_interfaces(&hwnd, &reOle, &doc, NULL);
2981 
2982   hr = ITextRange_Select(range);
2983   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2984 
2985   hr = ITextSelection_Select(selection);
2986   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2987 
2988   ITextRange_Release(range);
2989   ITextSelection_Release(selection);
2990 }
2991 
2992 static void test_GetStoryType(void)
2993 {
2994   static const CHAR test_text1[] = "TestSomeText";
2995   IRichEditOle *reOle = NULL;
2996   ITextDocument *doc = NULL;
2997   ITextSelection *selection;
2998   ITextRange *range;
2999   LONG value;
3000   HRESULT hr;
3001   HWND hwnd;
3002 
3003   create_interfaces(&hwnd, &reOle, &doc, &selection);
3004   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3005   SendMessageA(hwnd, EM_SETSEL, 1, 2);
3006 
3007   hr = ITextDocument_Range(doc, 0, 4, &range);
3008   ok(hr == S_OK, "got 0x%08x\n", hr);
3009 
3010   hr = ITextRange_GetStoryType(range, NULL);
3011   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3012 
3013   value = tomTextFrameStory;
3014   hr = ITextRange_GetStoryType(range, &value);
3015   ok(hr == S_OK, "got 0x%08x\n", hr);
3016   ok(value == tomUnknownStory, "got %d\n", value);
3017 
3018   hr = ITextSelection_GetStoryType(selection, NULL);
3019   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3020 
3021   value = tomTextFrameStory;
3022   hr = ITextSelection_GetStoryType(selection, &value);
3023   ok(hr == S_OK, "got 0x%08x\n", hr);
3024   ok(value == tomUnknownStory, "got %d\n", value);
3025 
3026   release_interfaces(&hwnd, &reOle, &doc, NULL);
3027 
3028   hr = ITextRange_GetStoryType(range, NULL);
3029   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3030 
3031   value = 123;
3032   hr = ITextRange_GetStoryType(range, &value);
3033   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3034   ok(value == 123, "got %d\n", value);
3035 
3036   hr = ITextSelection_GetStoryType(selection, NULL);
3037   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3038 
3039   value = 123;
3040   hr = ITextSelection_GetStoryType(selection, &value);
3041   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3042   ok(value == 123, "got %d\n", value);
3043 
3044   ITextRange_Release(range);
3045   ITextSelection_Release(selection);
3046 }
3047 
3048 static void test_SetFont(void)
3049 {
3050   static const CHAR test_text1[] = "TestSomeText";
3051   IRichEditOle *reOle = NULL;
3052   ITextDocument *doc = NULL;
3053   ITextSelection *selection;
3054   ITextRange *range, *range2;
3055   ITextFont *font, *font2;
3056   LONG value;
3057   HRESULT hr;
3058   HWND hwnd;
3059 
3060   create_interfaces(&hwnd, &reOle, &doc, &selection);
3061   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3062   SendMessageA(hwnd, EM_SETSEL, 1, 2);
3063 
3064   hr = ITextDocument_Range(doc, 0, 4, &range);
3065   ok(hr == S_OK, "got 0x%08x\n", hr);
3066 
3067   hr = ITextDocument_Range(doc, 5, 2, &range2);
3068   ok(hr == S_OK, "got 0x%08x\n", hr);
3069 
3070   EXPECT_REF(range, 1);
3071   hr = ITextRange_GetFont(range, &font);
3072   ok(hr == S_OK, "got 0x%08x\n", hr);
3073   EXPECT_REF(range, 2);
3074 
3075   EXPECT_REF(range2, 1);
3076   hr = ITextRange_GetFont(range2, &font2);
3077   ok(hr == S_OK, "got 0x%08x\n", hr);
3078   EXPECT_REF(range2, 2);
3079 
3080   hr = ITextRange_SetFont(range, NULL);
3081   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3082 
3083   /* setting same font, no-op */
3084   EXPECT_REF(range, 2);
3085   hr = ITextRange_SetFont(range, font);
3086   ok(hr == S_OK, "got 0x%08x\n", hr);
3087   EXPECT_REF(range, 2);
3088 
3089   EXPECT_REF(range2, 2);
3090   EXPECT_REF(range, 2);
3091   hr = ITextRange_SetFont(range, font2);
3092   ok(hr == S_OK, "got 0x%08x\n", hr);
3093   EXPECT_REF(range2, 2);
3094   EXPECT_REF(range, 2);
3095 
3096   /* originally range 0-4 is non-italic */
3097   value = tomTrue;
3098   hr = ITextFont_GetItalic(font, &value);
3099   ok(hr == S_OK, "got 0x%08x\n", hr);
3100   ok(value == tomFalse, "got %d\n", value);
3101 
3102   /* set range 5-2 to italic, then set this font to range 0-4 */
3103   hr = ITextFont_SetItalic(font2, tomTrue);
3104   ok(hr == S_OK, "got 0x%08x\n", hr);
3105 
3106   hr = ITextRange_SetFont(range, font2);
3107   ok(hr == S_OK, "got 0x%08x\n", hr);
3108 
3109   value = tomFalse;
3110   hr = ITextFont_GetItalic(font, &value);
3111   ok(hr == S_OK, "got 0x%08x\n", hr);
3112   ok(value == tomTrue, "got %d\n", value);
3113 
3114   release_interfaces(&hwnd, &reOle, &doc, NULL);
3115 
3116   hr = ITextRange_SetFont(range, NULL);
3117   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3118 
3119   hr = ITextRange_SetFont(range, font);
3120   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3121 
3122   hr = ITextSelection_SetFont(selection, NULL);
3123   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3124 
3125   hr = ITextSelection_SetFont(selection, font);
3126   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3127 
3128   ITextFont_Release(font);
3129   ITextFont_Release(font2);
3130   ITextRange_Release(range);
3131   ITextRange_Release(range2);
3132   ITextSelection_Release(selection);
3133 }
3134 
3135 static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj,
3136                                  LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx,
3137                                  LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user)
3138 {
3139   reobj->cbStruct = sizeof(*reobj);
3140   reobj->clsid = CLSID_NULL;
3141   reobj->cp = cp;
3142   reobj->poleobj = poleobj;
3143   reobj->pstg = pstg;
3144   reobj->polesite = polesite;
3145   reobj->sizel.cx = sizel_cx;
3146   reobj->sizel.cy = sizel_cy;
3147   reobj->dvaspect = aspect;
3148   reobj->dwFlags = flags;
3149   reobj->dwUser = user;
3150 }
3151 
3152 #define CHECK_REOBJECT_STRUCT(reobj,poleobj,pstg,polesite,user) \
3153   _check_reobject_struct(reobj, poleobj, pstg, polesite, user, __LINE__)
3154 static void _check_reobject_struct(REOBJECT reobj, LPOLEOBJECT poleobj, LPSTORAGE pstg,
3155                                   LPOLECLIENTSITE polesite, DWORD user, int line)
3156 {
3157   ok_(__FILE__,line)(reobj.poleobj == poleobj, "got wrong object interface.\n");
3158   ok_(__FILE__,line)(reobj.pstg == pstg, "got wrong storage interface.\n");
3159   ok_(__FILE__,line)(reobj.polesite == polesite, "got wrong site interface.\n");
3160   ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n");
3161 }
3162 
3163 static void test_InsertObject(void)
3164 {
3165   static CHAR test_text1[] = "abcdefg";
3166   IRichEditOle *reole = NULL;
3167   ITextDocument *doc = NULL;
3168   IOleClientSite *clientsite;
3169   REOBJECT reo1, reo2, reo3, received_reo1, received_reo2, received_reo3, received_reo4;
3170   HRESULT hr;
3171   HWND hwnd;
3172   LONG count;
3173 
3174   create_interfaces(&hwnd, &reole, &doc, NULL);
3175   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3176 
3177   hr = IRichEditOle_InsertObject(reole, NULL);
3178   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3179 
3180   /* insert object1 in (0, 1)*/
3181   SendMessageA(hwnd, EM_SETSEL, 0, 1);
3182   hr = IRichEditOle_GetClientSite(reole, &clientsite);
3183   ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3184   fill_reobject_struct(&reo1, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 1);
3185   hr = IRichEditOle_InsertObject(reole, &reo1);
3186   ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3187   count = IRichEditOle_GetObjectCount(reole);
3188   ok(count == 1, "got wrong object count: %d\n", count);
3189   IOleClientSite_Release(clientsite);
3190 
3191   /* insert object2 in (2, 3)*/
3192   SendMessageA(hwnd, EM_SETSEL, 2, 3);
3193   hr = IRichEditOle_GetClientSite(reole, &clientsite);
3194   ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3195   fill_reobject_struct(&reo2, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 2);
3196   hr = IRichEditOle_InsertObject(reole, &reo2);
3197   ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3198   count = IRichEditOle_GetObjectCount(reole);
3199   ok(count == 2, "got wrong object count: %d\n", count);
3200   IOleClientSite_Release(clientsite);
3201 
3202   /* insert object3 in (1, 2)*/
3203   SendMessageA(hwnd, EM_SETSEL, 1, 2);
3204   hr = IRichEditOle_GetClientSite(reole, &clientsite);
3205   ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3206   fill_reobject_struct(&reo3, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 3);
3207   hr = IRichEditOle_InsertObject(reole, &reo3);
3208   ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3209   count = IRichEditOle_GetObjectCount(reole);
3210   ok(count == 3, "got wrong object count: %d\n", count);
3211   IOleClientSite_Release(clientsite);
3212 
3213   /* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */
3214   received_reo1.cbStruct = sizeof(received_reo1);
3215   hr = IRichEditOle_GetObject(reole, 0, &received_reo1, REO_GETOBJ_ALL_INTERFACES);
3216   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3217   CHECK_REOBJECT_STRUCT(received_reo1, NULL, NULL, reo1.polesite, 1);
3218 
3219   received_reo2.cbStruct = sizeof(received_reo2);
3220   hr = IRichEditOle_GetObject(reole, 1, &received_reo2, REO_GETOBJ_ALL_INTERFACES);
3221   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3222   CHECK_REOBJECT_STRUCT(received_reo2, NULL, NULL, reo3.polesite, 3);
3223 
3224   received_reo3.cbStruct = sizeof(received_reo3);
3225   hr = IRichEditOle_GetObject(reole, 2, &received_reo3, REO_GETOBJ_ALL_INTERFACES);
3226   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3227   CHECK_REOBJECT_STRUCT(received_reo3, NULL, NULL, reo2.polesite, 2);
3228 
3229   hr = IRichEditOle_GetObject(reole, 2, NULL, REO_GETOBJ_ALL_INTERFACES);
3230   ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3231 
3232   received_reo4.cbStruct = 0;
3233   hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3234   ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3235 
3236   received_reo4.cbStruct = sizeof(received_reo4);
3237   hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_PSTG);
3238   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3239   CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2);
3240 
3241   hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_POLESITE);
3242   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3243   CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
3244 
3245   hr = IRichEditOle_GetObject(reole, 4, &received_reo4, REO_GETOBJ_POLESITE);
3246   ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3247 
3248   hr = IRichEditOle_GetObject(reole, 1024, &received_reo4, REO_GETOBJ_POLESITE);
3249   ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3250 
3251   /* received_reo4 will be zeroed before be used */
3252   hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_NO_INTERFACES);
3253   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3254   CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2);
3255 
3256   received_reo4.cbStruct = sizeof(received_reo4);
3257   received_reo4.cp = 0;
3258   hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3259   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3260   CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1);
3261 
3262   received_reo4.cbStruct = sizeof(received_reo4);
3263   received_reo4.cp = 1;
3264   hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3265   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3266   CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3);
3267 
3268   received_reo4.cbStruct = sizeof(received_reo4);
3269   received_reo4.cp = 2;
3270   hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3271   ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3272   CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
3273 
3274   received_reo4.cbStruct = sizeof(received_reo4);
3275   received_reo4.cp = 4;
3276   hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3277   ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3278   /* received_reo4 didn't be zeroed in E_INVALIDARG case */
3279   CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
3280 
3281   release_interfaces(&hwnd, &reole, &doc, NULL);
3282 }
3283 
3284 static void test_GetStoryLength(void)
3285 {
3286   static const CHAR test_text1[] = "TestSomeText";
3287   IRichEditOle *reOle = NULL;
3288   ITextDocument *doc = NULL;
3289   ITextSelection *selection;
3290   ITextRange *range;
3291   LONG value;
3292   HRESULT hr;
3293   HWND hwnd;
3294 
3295   create_interfaces(&hwnd, &reOle, &doc, &selection);
3296   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3297   SendMessageA(hwnd, EM_SETSEL, 1, 2);
3298 
3299   hr = ITextDocument_Range(doc, 0, 4, &range);
3300   ok(hr == S_OK, "got 0x%08x\n", hr);
3301 
3302   hr = ITextRange_GetStoryLength(range, NULL);
3303   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3304 
3305   value = 0;
3306   hr = ITextRange_GetStoryLength(range, &value);
3307   ok(hr == S_OK, "got 0x%08x\n", hr);
3308   ok(value == 13, "got %d\n", value);
3309 
3310   hr = ITextSelection_GetStoryLength(selection, NULL);
3311   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3312 
3313   value = 0;
3314   hr = ITextSelection_GetStoryLength(selection, &value);
3315   ok(hr == S_OK, "got 0x%08x\n", hr);
3316   ok(value == 13, "got %d\n", value);
3317 
3318   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
3319 
3320   value = 0;
3321   hr = ITextRange_GetStoryLength(range, &value);
3322   ok(hr == S_OK, "got 0x%08x\n", hr);
3323   ok(value == 1, "got %d\n", value);
3324 
3325   value = 0;
3326   hr = ITextSelection_GetStoryLength(selection, &value);
3327   ok(hr == S_OK, "got 0x%08x\n", hr);
3328   ok(value == 1, "got %d\n", value);
3329 
3330   release_interfaces(&hwnd, &reOle, &doc, NULL);
3331 
3332   hr = ITextRange_GetStoryLength(range, NULL);
3333   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3334 
3335   value = 100;
3336   hr = ITextRange_GetStoryLength(range, &value);
3337   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3338   ok(value == 100, "got %d\n", value);
3339 
3340   hr = ITextSelection_GetStoryLength(selection, NULL);
3341   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3342 
3343   value = 100;
3344   hr = ITextSelection_GetStoryLength(selection, &value);
3345   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3346   ok(value == 100, "got %d\n", value);
3347 
3348   ITextSelection_Release(selection);
3349   ITextRange_Release(range);
3350 }
3351 
3352 static void test_ITextSelection_GetDuplicate(void)
3353 {
3354   static const CHAR test_text1[] = "TestSomeText";
3355   IRichEditOle *reOle = NULL;
3356   ITextDocument *doc = NULL;
3357   ITextSelection *selection, *sel2;
3358   ITextRange *range, *range2;
3359   ITextFont *font;
3360   LONG value;
3361   HRESULT hr;
3362   HWND hwnd;
3363 
3364   create_interfaces(&hwnd, &reOle, &doc, &selection);
3365   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3366   SendMessageA(hwnd, EM_SETSEL, 1, 2);
3367 
3368   hr = ITextSelection_GetDuplicate(selection, NULL);
3369   ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3370 
3371   EXPECT_REF(selection, 2);
3372 
3373   hr = ITextSelection_GetDuplicate(selection, &range);
3374   ok(hr == S_OK, "got 0x%08x\n", hr);
3375 
3376   hr = ITextSelection_GetDuplicate(selection, &range2);
3377   ok(hr == S_OK, "got 0x%08x\n", hr);
3378   ok(range != range2, "got %p, %p\n", range, range2);
3379 
3380   EXPECT_REF(selection, 2);
3381   EXPECT_REF(range, 1);
3382   EXPECT_REF(range2, 1);
3383 
3384   ITextRange_Release(range2);
3385 
3386   value = 0;
3387   hr = ITextRange_GetStart(range, &value);
3388   ok(hr == S_OK, "got 0x%08x\n", hr);
3389   ok(value == 1, "got %d\n", value);
3390 
3391   value = 0;
3392   hr = ITextRange_GetEnd(range, &value);
3393   ok(hr == S_OK, "got 0x%08x\n", hr);
3394   ok(value == 2, "got %d\n", value);
3395 
3396   SendMessageA(hwnd, EM_SETSEL, 2, 3);
3397 
3398   value = 0;
3399   hr = ITextRange_GetStart(range, &value);
3400   ok(hr == S_OK, "got 0x%08x\n", hr);
3401   ok(value == 1, "got %d\n", value);
3402 
3403   value = 0;
3404   hr = ITextRange_GetEnd(range, &value);
3405   ok(hr == S_OK, "got 0x%08x\n", hr);
3406   ok(value == 2, "got %d\n", value);
3407 
3408   hr = ITextRange_QueryInterface(range, &IID_ITextSelection, (void**)&sel2);
3409   ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
3410 
3411   release_interfaces(&hwnd, &reOle, &doc, NULL);
3412 
3413   hr = ITextSelection_GetDuplicate(selection, NULL);
3414   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3415 
3416   hr = ITextSelection_GetDuplicate(selection, &range);
3417   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3418 
3419   hr = ITextRange_GetFont(range, &font);
3420   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3421 
3422   ITextSelection_Release(selection);
3423   ITextRange_Release(range);
3424 }
3425 
3426 #define RESET_RANGE(range,start,end) \
3427   _reset_range(range, start, end, __LINE__)
3428 static void _reset_range(ITextRange *range, LONG start, LONG end, int line)
3429 {
3430   HRESULT hr;
3431 
3432   hr = ITextRange_SetStart(range, start);
3433   ok_(__FILE__,line)(hr == S_OK, "SetStart failed: 0x%08x\n", hr);
3434   hr = ITextRange_SetEnd(range, end);
3435   ok_(__FILE__,line)(hr == S_OK, "SetEnd failed: 0x%08x\n", hr);
3436 }
3437 
3438 #define CHECK_RANGE(range,expected_start,expected_end) \
3439   _check_range(range, expected_start, expected_end, __LINE__)
3440 static void _check_range(ITextRange* range, LONG expected_start, LONG expected_end, int line)
3441 {
3442   HRESULT hr;
3443   LONG value;
3444 
3445   hr = ITextRange_GetStart(range, &value);
3446   ok_(__FILE__,line)(hr == S_OK, "GetStart failed: 0x%08x\n", hr);
3447   ok_(__FILE__,line)(value == expected_start, "Expected start %d got %d\n",
3448                      expected_start, value);
3449   hr = ITextRange_GetEnd(range, &value);
3450   ok_(__FILE__,line)(hr == S_OK, "GetEnd failed: 0x%08x\n", hr);
3451   ok_(__FILE__,line)(value == expected_end, "Expected end %d got %d\n",
3452                      expected_end, value);
3453 }
3454 
3455 #define RESET_SELECTION(selection,start,end) \
3456   _reset_selection(selection, start, end, __LINE__)
3457 static void _reset_selection(ITextSelection *selection, LONG start, LONG end, int line)
3458 {
3459   HRESULT hr;
3460 
3461   hr = ITextSelection_SetStart(selection, start);
3462   ok_(__FILE__,line)(hr == S_OK, "SetStart failed: 0x%08x\n", hr);
3463   hr = ITextSelection_SetEnd(selection, end);
3464   ok_(__FILE__,line)(hr == S_OK, "SetEnd failed: 0x%08x\n", hr);
3465 }
3466 
3467 #define CHECK_SELECTION(selection,expected_start,expected_end) \
3468   _check_selection(selection, expected_start, expected_end, __LINE__)
3469 static void _check_selection(ITextSelection *selection, LONG expected_start, LONG expected_end, int line)
3470 {
3471   HRESULT hr;
3472   LONG value;
3473 
3474   hr = ITextSelection_GetStart(selection, &value);
3475   ok_(__FILE__,line)(hr == S_OK, "GetStart failed: 0x%08x\n", hr);
3476   ok_(__FILE__,line)(value == expected_start, "Expected start %d got %d\n",
3477                      expected_start, value);
3478   hr = ITextSelection_GetEnd(selection, &value);
3479   ok_(__FILE__,line)(hr == S_OK, "GetEnd failed: 0x%08x\n", hr);
3480   ok_(__FILE__,line)(value == expected_end, "Expected end %d got %d\n",
3481                      expected_end, value);
3482 }
3483 
3484 static void test_Expand(void)
3485 {
3486   static const char test_text1[] = "TestSomeText";
3487   IRichEditOle *reole = NULL;
3488   ITextDocument *doc = NULL;
3489   ITextSelection *selection;
3490   ITextRange *range;
3491   LONG value;
3492   HRESULT hr;
3493   HWND hwnd;
3494 
3495   create_interfaces(&hwnd, &reole, &doc, &selection);
3496   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3497   SendMessageA(hwnd, EM_SETSEL, 1, 2);
3498 
3499   hr = ITextDocument_Range(doc, 0, 4, &range);
3500   ok(hr == S_OK, "got 0x%08x\n", hr);
3501 
3502   hr = ITextRange_Expand(range, tomStory, NULL);
3503   ok(hr == S_OK, "got 0x%08x\n", hr);
3504   CHECK_RANGE(range, 0, 13);
3505 
3506   hr = ITextSelection_Expand(selection, tomStory, NULL);
3507   ok(hr == S_OK, "got 0x%08x\n", hr);
3508   CHECK_SELECTION(selection, 0, 13);
3509 
3510   RESET_RANGE(range, 1, 2);
3511   RESET_SELECTION(selection, 1, 2);
3512 
3513   value = 0;
3514   hr = ITextRange_Expand(range, tomStory, &value);
3515   ok(hr == S_OK, "got 0x%08x\n", hr);
3516   ok(value == 12, "got %d\n", value);
3517   CHECK_RANGE(range, 0, 13);
3518 
3519   value = 0;
3520   hr = ITextSelection_Expand(selection, tomStory, &value);
3521   ok(hr == S_OK, "got 0x%08x\n", hr);
3522   ok(value == 12, "got %d\n", value);
3523   CHECK_SELECTION(selection, 0, 13);
3524 
3525   release_interfaces(&hwnd, &reole, &doc, NULL);
3526 
3527   hr = ITextRange_Expand(range, tomStory, NULL);
3528   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3529 
3530   hr = ITextRange_Expand(range, tomStory, &value);
3531   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3532 
3533   hr = ITextSelection_Expand(selection, tomStory, NULL);
3534   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3535 
3536   hr = ITextSelection_Expand(selection, tomStory, &value);
3537   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3538 
3539   ITextSelection_Release(selection);
3540   ITextRange_Release(range);
3541 }
3542 
3543 static void test_MoveEnd(void)
3544 {
3545   static const char test_text1[] = "Word1 Word2";
3546   IRichEditOle *reole = NULL;
3547   ITextDocument *doc = NULL;
3548   ITextSelection *selection;
3549   ITextRange *range;
3550   LONG delta;
3551   HRESULT hr;
3552   HWND hwnd;
3553 
3554   create_interfaces(&hwnd, &reole, &doc, &selection);
3555   SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3556   SendMessageA(hwnd, EM_SETSEL, 1, 2);
3557 
3558   hr = ITextDocument_Range(doc, 1, 2, &range);
3559   ok(hr == S_OK, "got 0x%08x\n", hr);
3560 
3561   hr = ITextRange_MoveEnd(range, tomStory, 0, &delta);
3562   ok(hr == S_FALSE, "got 0x%08x\n", hr);
3563   ok(delta == 0, "got %d\n", delta);
3564   CHECK_RANGE(range, 1, 2);
3565 
3566   hr = ITextRange_MoveEnd(range, tomStory, -1, &delta);
3567   ok(hr == S_OK, "got 0x%08x\n", hr);
3568   ok(delta == -1, "got %d\n", delta);
3569   CHECK_RANGE(range, 0, 0);
3570 
3571   hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
3572   ok(hr == S_OK, "got 0x%08x\n", hr);
3573   ok(delta == 1, "got %d\n", delta);
3574   CHECK_RANGE(range, 0, 12);
3575 
3576   hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
3577   ok(hr == S_FALSE, "got 0x%08x\n", hr);
3578   ok(delta == 0, "got %d\n", delta);
3579   CHECK_RANGE(range, 0, 12);
3580 
3581   RESET_RANGE(range, 1, 2);
3582 
3583   hr = ITextRange_MoveEnd(range, tomStory, 3, &delta);
3584   ok(hr == S_OK, "got 0x%08x\n", hr);
3585   ok(delta == 1, "got %d\n", delta);
3586   CHECK_RANGE(range, 1, 12);
3587 
3588   RESET_RANGE(range, 2, 3);
3589 
3590   hr = ITextRange_MoveEnd(range, tomStory, -3, &delta);
3591   ok(hr == S_OK, "got 0x%08x\n", hr);
3592   ok(delta == -1, "got %d\n", delta);
3593   CHECK_RANGE(range, 0, 0);
3594 
3595   hr = ITextRange_MoveEnd(range, tomStory, -1, &delta);
3596   ok(hr == S_FALSE, "got 0x%08x\n", hr);
3597   ok(delta == 0, "got %d\n", delta);
3598   CHECK_RANGE(range, 0, 0);
3599 
3600   hr = ITextSelection_MoveEnd(selection, tomStory, 0, &delta);
3601   ok(hr == S_FALSE, "got 0x%08x\n", hr);
3602   ok(delta == 0, "got %d\n", delta);
3603   CHECK_SELECTION(selection, 1, 2);
3604 
3605   hr = ITextSelection_MoveEnd(selection, tomStory, -1, &delta);
3606   ok(hr == S_OK, "got 0x%08x\n", hr);
3607   ok(delta == -1, "got %d\n", delta);
3608   CHECK_SELECTION(selection, 0, 0);
3609 
3610   hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
3611   ok(hr == S_OK, "got 0x%08x\n", hr);
3612   ok(delta == 1, "got %d\n", delta);
3613   CHECK_SELECTION(selection, 0, 12);
3614 
3615   hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
3616   ok(hr == S_FALSE, "got 0x%08x\n", hr);
3617   ok(delta == 0, "got %d\n", delta);
3618   CHECK_SELECTION(selection, 0, 12);
3619 
3620   RESET_SELECTION(selection, 1, 2);
3621 
3622   hr = ITextSelection_MoveEnd(selection, tomStory, 3, &delta);
3623   ok(hr == S_OK, "got 0x%08x\n", hr);
3624   ok(delta == 1, "got %d\n", delta);
3625   CHECK_SELECTION(selection, 1, 12);
3626 
3627   RESET_SELECTION(selection, 2, 3);
3628 
3629   hr = ITextSelection_MoveEnd(selection, tomStory, -3, &delta);
3630   ok(hr == S_OK, "got 0x%08x\n", hr);
3631   ok(delta == -1, "got %d\n", delta);
3632   CHECK_SELECTION(selection, 0, 0);
3633 
3634   hr = ITextSelection_MoveEnd(selection, tomStory, -1, &delta);
3635   ok(hr == S_FALSE, "got 0x%08x\n", hr);
3636   ok(delta == 0, "got %d\n", delta);
3637   CHECK_SELECTION(selection, 0, 0);
3638 
3639   release_interfaces(&hwnd, &reole, &doc, NULL);
3640 
3641   hr = ITextRange_MoveEnd(range, tomStory, 1, NULL);
3642   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3643 
3644   hr = ITextRange_MoveEnd(range, tomStory, 1, &delta);
3645   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3646 
3647   hr = ITextSelection_MoveEnd(selection, tomStory, 1, NULL);
3648   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3649 
3650   hr = ITextSelection_MoveEnd(selection, tomStory, 1, &delta);
3651   ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3652 
3653   ITextSelection_Release(selection);
3654   ITextRange_Release(range);
3655 }
3656 
3657 static void test_ITextRange_SetStart(void)
3658 {
3659   HWND w;
3660   IRichEditOle *reOle = NULL;
3661   ITextDocument *txtDoc = NULL;
3662   ITextRange *txtRge = NULL;
3663   HRESULT hres;
3664   LONG first, lim, start, end;
3665   static const CHAR test_text1[] = "TestSomeText";
3666 
3667   create_interfaces(&w, &reOle, &txtDoc, NULL);
3668   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3669 
3670   first = 4, lim = 8;
3671   ITextDocument_Range(txtDoc, first, lim, &txtRge);
3672   hres = ITextRange_SetStart(txtRge, first);
3673   ok(hres == S_FALSE, "ITextRange_SetStart\n");
3674 
3675 #define TEST_TXTRGE_SETSTART(cp, expected_start, expected_end)  \
3676   hres = ITextRange_SetStart(txtRge, cp);                       \
3677   ok(hres == S_OK, "ITextRange_SetStart\n");                    \
3678   ITextRange_GetStart(txtRge, &start);                          \
3679   ITextRange_GetEnd(txtRge, &end);                              \
3680   ok(start == expected_start, "got wrong start value: %d\n", start);  \
3681   ok(end == expected_end, "got wrong end value: %d\n", end);
3682 
3683   TEST_TXTRGE_SETSTART(2, 2, 8)
3684   TEST_TXTRGE_SETSTART(-1, 0, 8)
3685   TEST_TXTRGE_SETSTART(13, 12, 12)
3686 
3687   release_interfaces(&w, &reOle, &txtDoc, NULL);
3688 }
3689 
3690 static void test_ITextRange_SetEnd(void)
3691 {
3692   HWND w;
3693   IRichEditOle *reOle = NULL;
3694   ITextDocument *txtDoc = NULL;
3695   ITextRange *txtRge = NULL;
3696   HRESULT hres;
3697   LONG first, lim, start, end;
3698   static const CHAR test_text1[] = "TestSomeText";
3699 
3700   create_interfaces(&w, &reOle, &txtDoc, NULL);
3701   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3702 
3703   first = 4, lim = 8;
3704   ITextDocument_Range(txtDoc, first, lim, &txtRge);
3705   hres = ITextRange_SetEnd(txtRge, lim);
3706   ok(hres == S_FALSE, "ITextRange_SetEnd\n");
3707 
3708 #define TEST_TXTRGE_SETEND(cp, expected_start, expected_end)    \
3709   hres = ITextRange_SetEnd(txtRge, cp);                         \
3710   ok(hres == S_OK, "ITextRange_SetEnd\n");                      \
3711   ITextRange_GetStart(txtRge, &start);                          \
3712   ITextRange_GetEnd(txtRge, &end);                              \
3713   ok(start == expected_start, "got wrong start value: %d\n", start);  \
3714   ok(end == expected_end, "got wrong end value: %d\n", end);
3715 
3716   TEST_TXTRGE_SETEND(6, 4, 6)
3717   TEST_TXTRGE_SETEND(14, 4, 13)
3718   TEST_TXTRGE_SETEND(-1, 0, 0)
3719 
3720   ITextRange_Release(txtRge);
3721   release_interfaces(&w, &reOle, &txtDoc, NULL);
3722 }
3723 
3724 static void test_ITextSelection_SetStart(void)
3725 {
3726   HWND w;
3727   IRichEditOle *reOle = NULL;
3728   ITextDocument *txtDoc = NULL;
3729   ITextSelection *txtSel = NULL;
3730   HRESULT hres;
3731   LONG first, lim, start, end;
3732   static const CHAR test_text1[] = "TestSomeText";
3733 
3734   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
3735   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3736 
3737   first = 4, lim = 8;
3738   SendMessageA(w, EM_SETSEL, first, lim);
3739   hres = ITextSelection_SetStart(txtSel, first);
3740   ok(hres == S_FALSE, "ITextSelection_SetStart\n");
3741 
3742 #define TEST_TXTSEL_SETSTART(cp, expected_start, expected_end)        \
3743   hres = ITextSelection_SetStart(txtSel, cp);                         \
3744   ok(hres == S_OK, "ITextSelection_SetStart\n");                      \
3745   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);           \
3746   ok(start == expected_start, "got wrong start value: %d\n", start);  \
3747   ok(end == expected_end, "got wrong end value: %d\n", end);
3748 
3749   TEST_TXTSEL_SETSTART(2, 2, 8)
3750   TEST_TXTSEL_SETSTART(-1, 0, 8)
3751   TEST_TXTSEL_SETSTART(13, 12, 12)
3752 
3753   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
3754 }
3755 
3756 static void test_ITextSelection_SetEnd(void)
3757 {
3758   HWND w;
3759   IRichEditOle *reOle = NULL;
3760   ITextDocument *txtDoc = NULL;
3761   ITextSelection *txtSel = NULL;
3762   HRESULT hres;
3763   LONG first, lim, start, end;
3764   static const CHAR test_text1[] = "TestSomeText";
3765 
3766   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
3767   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3768 
3769   first = 4, lim = 8;
3770   SendMessageA(w, EM_SETSEL, first, lim);
3771   hres = ITextSelection_SetEnd(txtSel, lim);
3772   ok(hres == S_FALSE, "ITextSelection_SetEnd\n");
3773 
3774 #define TEST_TXTSEL_SETEND(cp, expected_start, expected_end)          \
3775   hres = ITextSelection_SetEnd(txtSel, cp);                           \
3776   ok(hres == S_OK, "ITextSelection_SetEnd\n");                        \
3777   SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end);           \
3778   ok(start == expected_start, "got wrong start value: %d\n", start);  \
3779   ok(end == expected_end, "got wrong end value: %d\n", end);
3780 
3781   TEST_TXTSEL_SETEND(6, 4, 6)
3782   TEST_TXTSEL_SETEND(14, 4, 13)
3783   TEST_TXTSEL_SETEND(-1, 0, 0)
3784 
3785   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
3786 }
3787 
3788 static void test_ITextRange_GetFont(void)
3789 {
3790   HWND w;
3791   IRichEditOle *reOle = NULL;
3792   ITextDocument *txtDoc = NULL;
3793   ITextRange *txtRge = NULL;
3794   ITextFont *txtFont = NULL, *txtFont1 = NULL;
3795   HRESULT hres;
3796   int first, lim;
3797   int refcount;
3798   static const CHAR test_text1[] = "TestSomeText";
3799   LONG value;
3800 
3801   create_interfaces(&w, &reOle, &txtDoc, NULL);
3802   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3803 
3804   first = 4, lim = 4;
3805   ITextDocument_Range(txtDoc, first, lim, &txtRge);
3806   refcount = get_refcount((IUnknown *)txtRge);
3807   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
3808 
3809   hres = ITextRange_GetFont(txtRge, &txtFont);
3810   ok(hres == S_OK, "ITextRange_GetFont\n");
3811   refcount = get_refcount((IUnknown *)txtFont);
3812   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
3813   refcount = get_refcount((IUnknown *)txtRge);
3814   ok(refcount == 2, "got wrong ref count: %d\n", refcount);
3815 
3816   hres = ITextRange_GetFont(txtRge, &txtFont1);
3817   ok(hres == S_OK, "ITextRange_GetFont\n");
3818   ok(txtFont1 != txtFont, "A new pointer should be return\n");
3819   refcount = get_refcount((IUnknown *)txtFont1);
3820   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
3821   ITextFont_Release(txtFont1);
3822   refcount = get_refcount((IUnknown *)txtRge);
3823   ok(refcount == 2, "got wrong ref count: %d\n", refcount);
3824 
3825   ITextRange_Release(txtRge);
3826   release_interfaces(&w, &reOle, &txtDoc, NULL);
3827 
3828   hres = ITextFont_GetOutline(txtFont, &value);
3829   ok(hres == CO_E_RELEASED, "ITextFont after ITextDocument destroyed\n");
3830 
3831   ITextFont_Release(txtFont);
3832 }
3833 
3834 static void test_ITextSelection_GetFont(void)
3835 {
3836   HWND w;
3837   IRichEditOle *reOle = NULL;
3838   ITextDocument *txtDoc = NULL;
3839   ITextSelection *txtSel = NULL;
3840   ITextFont *txtFont = NULL, *txtFont1 = NULL;
3841   HRESULT hres;
3842   int first, lim;
3843   int refcount;
3844   static const CHAR test_text1[] = "TestSomeText";
3845   LONG value;
3846 
3847   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
3848   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3849 
3850   first = 4, lim = 4;
3851   SendMessageA(w, EM_SETSEL, first, lim);
3852   refcount = get_refcount((IUnknown *)txtSel);
3853   ok(refcount == 2, "got wrong ref count: %d\n", refcount);
3854 
3855   hres = ITextSelection_GetFont(txtSel, &txtFont);
3856   ok(hres == S_OK, "ITextSelection_GetFont\n");
3857   refcount = get_refcount((IUnknown *)txtFont);
3858   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
3859   refcount = get_refcount((IUnknown *)txtSel);
3860   ok(refcount == 3, "got wrong ref count: %d\n", refcount);
3861 
3862   hres = ITextSelection_GetFont(txtSel, &txtFont1);
3863   ok(hres == S_OK, "ITextSelection_GetFont\n");
3864   ok(txtFont1 != txtFont, "A new pointer should be return\n");
3865   refcount = get_refcount((IUnknown *)txtFont1);
3866   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
3867   ITextFont_Release(txtFont1);
3868   refcount = get_refcount((IUnknown *)txtSel);
3869   ok(refcount == 3, "got wrong ref count: %d\n", refcount);
3870 
3871   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
3872 
3873   hres = ITextFont_GetOutline(txtFont, &value);
3874   ok(hres == CO_E_RELEASED, "ITextFont after ITextDocument destroyed\n");
3875 
3876   ITextFont_Release(txtFont);
3877 }
3878 
3879 static void test_ITextRange_GetPara(void)
3880 {
3881   HWND w;
3882   IRichEditOle *reOle = NULL;
3883   ITextDocument *txtDoc = NULL;
3884   ITextRange *txtRge = NULL;
3885   ITextPara *txtPara = NULL, *txtPara1 = NULL;
3886   HRESULT hres;
3887   int first, lim;
3888   int refcount;
3889   static const CHAR test_text1[] = "TestSomeText";
3890   LONG value;
3891 
3892   create_interfaces(&w, &reOle, &txtDoc, NULL);
3893   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3894 
3895   first = 4, lim = 4;
3896   ITextDocument_Range(txtDoc, first, lim, &txtRge);
3897   refcount = get_refcount((IUnknown *)txtRge);
3898   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
3899 
3900   hres = ITextRange_GetPara(txtRge, &txtPara);
3901   ok(hres == S_OK, "ITextRange_GetPara\n");
3902   refcount = get_refcount((IUnknown *)txtPara);
3903   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
3904   refcount = get_refcount((IUnknown *)txtRge);
3905   ok(refcount == 2, "got wrong ref count: %d\n", refcount);
3906 
3907   hres = ITextRange_GetPara(txtRge, &txtPara1);
3908   ok(hres == S_OK, "ITextRange_GetPara\n");
3909   ok(txtPara1 != txtPara, "A new pointer should be return\n");
3910   refcount = get_refcount((IUnknown *)txtPara1);
3911   ok(refcount == 1, "got wrong ref count: %d\n", refcount);
3912   ITextPara_Release(txtPara1);
3913   refcount = get_refcount((IUnknown *)txtRge);
3914   ok(refcount == 2, "got wrong ref count: %d\n", refcount);
3915 
3916   ITextRange_Release(txtRge);
3917   release_interfaces(&w, &reOle, &txtDoc, NULL);
3918 
3919   hres = ITextPara_GetStyle(txtPara, &value);
3920   ok(hres == CO_E_RELEASED, "ITextPara after ITextDocument destroyed\n");
3921 
3922   ITextPara_Release(txtPara);
3923 }
3924 
3925 static void test_ITextRange_GetText(void)
3926 {
3927   HWND w;
3928   IRichEditOle *reOle = NULL;
3929   ITextDocument *txtDoc = NULL;
3930   ITextRange *txtRge = NULL;
3931   HRESULT hres;
3932   BSTR bstr = NULL;
3933   static const CHAR test_text1[] = "TestSomeText";
3934   static const WCHAR bufW1[] = {'T', 'e', 's', 't', 0};
3935   static const WCHAR bufW2[] = {'T', 'e', 'x', 't', '\r', 0};
3936   static const WCHAR bufW3[] = {'T', 'e', 'x', 't', 0};
3937   static const WCHAR bufW4[] = {'T', 'e', 's', 't', 'S', 'o', 'm',
3938                                 'e', 'T', 'e', 'x', 't', '\r', 0};
3939   static const WCHAR bufW5[] = {'\r', 0};
3940 
3941 
3942 #define TEST_TXTRGE_GETTEXT(first, lim, expected_string)                \
3943   create_interfaces(&w, &reOle, &txtDoc, NULL);                         \
3944   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);                   \
3945   ITextDocument_Range(txtDoc, first, lim, &txtRge);                     \
3946   hres = ITextRange_GetText(txtRge, &bstr);                             \
3947   ok(hres == S_OK, "ITextRange_GetText\n");                             \
3948   ok(!lstrcmpW(bstr, expected_string), "got wrong text: %s\n", wine_dbgstr_w(bstr)); \
3949   SysFreeString(bstr);                                                  \
3950   ITextRange_Release(txtRge);                                           \
3951   release_interfaces(&w, &reOle, &txtDoc, NULL);
3952 
3953   TEST_TXTRGE_GETTEXT(0, 4, bufW1)
3954   TEST_TXTRGE_GETTEXT(4, 0, bufW1)
3955   TEST_TXTRGE_GETTEXT(8, 12, bufW3)
3956   TEST_TXTRGE_GETTEXT(8, 13, bufW2)
3957   TEST_TXTRGE_GETTEXT(12, 13, bufW5)
3958   TEST_TXTRGE_GETTEXT(0, 13, bufW4)
3959   TEST_TXTRGE_GETTEXT(1, 1, NULL)
3960 }
3961 
3962 static void test_ITextRange_SetRange(void)
3963 {
3964   HWND w;
3965   IRichEditOle *reOle = NULL;
3966   ITextDocument *txtDoc = NULL;
3967   ITextRange *txtRge = NULL;
3968   HRESULT hres;
3969   int start, end;
3970   static const CHAR test_text1[] = "TestSomeText";
3971 
3972   create_interfaces(&w, &reOle, &txtDoc, NULL);
3973   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
3974   ITextDocument_Range(txtDoc, 0, 0, &txtRge);
3975 
3976 #define TEST_TXTRGE_SETRANGE(first, lim, expected_start, expected_end, expected_return) \
3977   hres = ITextRange_SetRange(txtRge, first, lim);                       \
3978   ok(hres == expected_return, "ITextRange_SetRange\n");                 \
3979   ITextRange_GetStart(txtRge, &start);                                  \
3980   ITextRange_GetEnd(txtRge, &end);                                      \
3981   ok(start == expected_start, "got wrong start value: %d\n", start);    \
3982   ok(end == expected_end, "got wrong end value: %d\n", end);
3983 
3984   TEST_TXTRGE_SETRANGE(2, 4, 2, 4, S_OK)
3985   TEST_TXTRGE_SETRANGE(2, 4, 2, 4, S_FALSE)
3986   TEST_TXTRGE_SETRANGE(4, 2, 2, 4, S_FALSE)
3987   TEST_TXTRGE_SETRANGE(14, 14, 12, 12, S_OK)
3988   TEST_TXTRGE_SETRANGE(15, 15, 12, 12, S_FALSE)
3989   TEST_TXTRGE_SETRANGE(14, 1, 1, 13, S_OK)
3990   TEST_TXTRGE_SETRANGE(-1, 4, 0, 4, S_OK)
3991 
3992   ITextRange_Release(txtRge);
3993   release_interfaces(&w, &reOle, &txtDoc, NULL);
3994 }
3995 
3996 static void test_ITextRange_IsEqual2(void)
3997 {
3998   HWND w;
3999   IRichEditOle *reOle = NULL;
4000   ITextDocument *txtDoc = NULL;
4001   ITextRange *txtRge1 = NULL, *txtRge2 = NULL;
4002   HRESULT hres;
4003   static const CHAR test_text1[] = "TestSomeText";
4004   LONG res;
4005 
4006   create_interfaces(&w, &reOle, &txtDoc, NULL);
4007   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
4008   ITextDocument_Range(txtDoc, 2, 4, &txtRge1);
4009   ITextDocument_Range(txtDoc, 2, 4, &txtRge2);
4010 
4011 #define TEST_TXTRGE_ISEQUAL(expected_hres, expected_res)                \
4012   hres = ITextRange_IsEqual(txtRge1, txtRge2, &res);                    \
4013   ok(hres == expected_hres, "ITextRange_IsEqual\n");                    \
4014   ok(res == expected_res, "got wrong return value: %d\n", res);
4015 
4016   TEST_TXTRGE_ISEQUAL(S_OK, tomTrue)
4017   ITextRange_SetRange(txtRge2, 1, 2);
4018   TEST_TXTRGE_ISEQUAL(S_FALSE, tomFalse)
4019 
4020   ITextRange_SetRange(txtRge1, 1, 1);
4021   ITextRange_SetRange(txtRge2, 2, 2);
4022   TEST_TXTRGE_ISEQUAL(S_FALSE, tomFalse)
4023 
4024   ITextRange_SetRange(txtRge2, 1, 1);
4025   TEST_TXTRGE_ISEQUAL(S_OK, tomTrue)
4026 
4027   hres = ITextRange_IsEqual(txtRge1, txtRge1, &res);
4028   ok(hres == S_OK, "ITextRange_IsEqual\n");
4029   ok(res == tomTrue, "got wrong return value: %d\n", res);
4030 
4031   hres = ITextRange_IsEqual(txtRge1, txtRge2, NULL);
4032   ok(hres == S_OK, "ITextRange_IsEqual\n");
4033 
4034   hres = ITextRange_IsEqual(txtRge1, NULL, NULL);
4035   ok(hres == S_FALSE, "ITextRange_IsEqual\n");
4036 
4037   ITextRange_Release(txtRge1);
4038   ITextRange_Release(txtRge2);
4039   release_interfaces(&w, &reOle, &txtDoc, NULL);
4040 }
4041 
4042 static void test_ITextRange_GetStoryLength(void)
4043 {
4044   HWND w;
4045   IRichEditOle *reOle = NULL;
4046   ITextDocument *txtDoc = NULL;
4047   ITextRange *txtRge = NULL;
4048   HRESULT hres;
4049   LONG count;
4050   static const CHAR test_text1[] = "TestSomeText";
4051   int len = strlen(test_text1) + 1;
4052 
4053   create_interfaces(&w, &reOle, &txtDoc, NULL);
4054   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
4055   ITextDocument_Range(txtDoc, 0, 0, &txtRge);
4056 
4057   hres = ITextRange_GetStoryLength(txtRge, &count);
4058   ok(hres == S_OK, "ITextRange_GetStoryLength\n");
4059   ok(count == len, "got wrong length: %d\n", count);
4060 
4061   ITextRange_SetRange(txtRge, 1, 2);
4062   hres = ITextRange_GetStoryLength(txtRge, &count);
4063   ok(hres == S_OK, "ITextRange_GetStoryLength\n");
4064   ok(count == len, "got wrong length: %d\n", count);
4065 
4066   hres = ITextRange_GetStoryLength(txtRge, NULL);
4067   ok(hres == E_INVALIDARG, "ITextRange_GetStoryLength\n");
4068 
4069   ITextRange_Release(txtRge);
4070   release_interfaces(&w, &reOle, &txtDoc, NULL);
4071 }
4072 
4073 static void test_ITextSelection_GetStoryLength(void)
4074 {
4075   HWND w;
4076   IRichEditOle *reOle = NULL;
4077   ITextDocument *txtDoc = NULL;
4078   ITextSelection *txtSel = NULL;
4079   HRESULT hres;
4080   LONG count;
4081   static const CHAR test_text1[] = "TestSomeText";
4082   int len = strlen(test_text1) + 1;
4083 
4084   create_interfaces(&w, &reOle, &txtDoc, &txtSel);
4085   SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
4086 
4087   hres = ITextSelection_GetStoryLength(txtSel, &count);
4088   ok(hres == S_OK, "ITextSelection_GetStoryLength\n");
4089   ok(count == len, "got wrong length: %d\n", count);
4090 
4091   SendMessageA(w, EM_SETSEL, 1, 2);
4092   hres = ITextSelection_GetStoryLength(txtSel, &count);
4093   ok(hres == S_OK, "ITextSelection_GetStoryLength\n");
4094   ok(count == len, "got wrong length: %d\n", count);
4095 
4096   hres = ITextSelection_GetStoryLength(txtSel, NULL);
4097   ok(hres == E_INVALIDARG, "ITextSelection_GetStoryLength\n");
4098 
4099   release_interfaces(&w, &reOle, &txtDoc, &txtSel);
4100 }
4101 
4102 START_TEST(richole)
4103 {
4104   /* Must explicitly LoadLibrary(). The test has no references to functions in
4105    * RICHED20.DLL, so the linker doesn't actually link to it. */
4106   hmoduleRichEdit = LoadLibraryA("riched20.dll");
4107   ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
4108 
4109   test_Interfaces();
4110   test_ITextDocument_Open();
4111   test_GetText();
4112   test_ITextSelection_GetChar();
4113   test_ITextSelection_GetStart_GetEnd();
4114   test_ITextSelection_SetStart();
4115   test_ITextSelection_SetEnd();
4116   test_ITextSelection_Collapse();
4117   test_ITextSelection_GetFont();
4118   test_ITextSelection_GetStoryLength();
4119   test_ITextDocument_Range();
4120   test_ITextRange_GetChar();
4121   test_ITextRange_ScrollIntoView();
4122   test_ITextRange_GetStart_GetEnd();
4123   test_ITextRange_GetDuplicate();
4124   test_ITextRange_SetStart();
4125   test_ITextRange_SetEnd();
4126   test_ITextRange_Collapse();
4127   test_ITextRange_GetFont();
4128   test_ITextRange_GetPara();
4129   test_ITextRange_GetText();
4130   test_ITextRange_SetRange();
4131   test_ITextRange_IsEqual2();
4132   test_ITextRange_GetStoryLength();
4133   test_GetClientSite();
4134   test_IOleWindow_GetWindow();
4135   test_IOleInPlaceSite_GetWindow();
4136   test_GetFont();
4137   test_GetPara();
4138   test_dispatch();
4139   test_ITextFont();
4140   test_Delete();
4141   test_SetText();
4142   test_InRange();
4143   test_ITextRange_IsEqual();
4144   test_Select();
4145   test_GetStoryType();
4146   test_SetFont();
4147   test_InsertObject();
4148   test_GetStoryLength();
4149   test_ITextSelection_GetDuplicate();
4150   test_Expand();
4151   test_MoveEnd();
4152 }
4153