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