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