ReactOS  0.4.14-dev-342-gdc047f9
richole.c
Go to the documentation of this file.
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 
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 
61 {
63 }
64 
66 {
67  HANDLE file;
68 
71 
73  return FALSE;
75  return TRUE;
76 }
77 
79 {
80  HANDLE file;
81 
83  OPEN_EXISTING, 0, NULL);
85  return FALSE;
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);
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 
111 {
112  IUnknown_AddRef(iface);
113  return IUnknown_Release(iface);
114 }
115 
116 static void test_Interfaces(void)
117 {
118  IRichEditOle *reOle = NULL, *reOle1 = NULL;
119  ITextDocument *txtDoc = NULL;
120  ITextSelection *txtSel = NULL, *txtSel2;
121  IUnknown *punk;
122  HRESULT hres;
123  LRESULT res;
124  HWND w;
125  ULONG refcount;
126 
127  w = new_richedit(NULL);
128  if (!w) {
129  skip("Couldn't create window\n");
130  return;
131  }
132 
133  res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle);
134  ok(res, "SendMessage\n");
135  ok(reOle != NULL, "EM_GETOLEINTERFACE\n");
136  EXPECT_REF(reOle, 2);
137 
138  res = SendMessageA(w, EM_GETOLEINTERFACE, 0, (LPARAM)&reOle1);
139  ok(res == 1, "SendMessage\n");
140  ok(reOle1 == reOle, "Should not return a new IRichEditOle interface\n");
141  EXPECT_REF(reOle, 3);
142 
143  hres = IRichEditOle_QueryInterface(reOle, &IID_ITextDocument,
144  (void **) &txtDoc);
145  ok(hres == S_OK, "IRichEditOle_QueryInterface\n");
146  ok(txtDoc != NULL, "IRichEditOle_QueryInterface\n");
147 
148  hres = ITextDocument_GetSelection(txtDoc, NULL);
149  ok(hres == E_INVALIDARG, "ITextDocument_GetSelection: 0x%x\n", hres);
150 
151  EXPECT_REF(txtDoc, 4);
152 
153  hres = ITextDocument_GetSelection(txtDoc, &txtSel);
154  ok(hres == S_OK, "got 0x%08x\n", hres);
155 
156  EXPECT_REF(txtDoc, 4);
157  EXPECT_REF(txtSel, 2);
158 
159  hres = ITextDocument_GetSelection(txtDoc, &txtSel2);
160  ok(hres == S_OK, "got 0x%08x\n", hres);
161  ok(txtSel2 == txtSel, "got %p, %p\n", txtSel, txtSel2);
162 
163  EXPECT_REF(txtDoc, 4);
164  EXPECT_REF(txtSel, 3);
165 
166  ITextSelection_Release(txtSel2);
167 
168  punk = NULL;
169  hres = ITextSelection_QueryInterface(txtSel, &IID_ITextSelection, (void **) &punk);
170  ok(hres == S_OK, "ITextSelection_QueryInterface\n");
171  ok(punk != NULL, "ITextSelection_QueryInterface\n");
172  IUnknown_Release(punk);
173 
174  punk = NULL;
175  hres = ITextSelection_QueryInterface(txtSel, &IID_ITextRange, (void **) &punk);
176  ok(hres == S_OK, "ITextSelection_QueryInterface\n");
177  ok(punk != NULL, "ITextSelection_QueryInterface\n");
178  IUnknown_Release(punk);
179 
180  punk = NULL;
181  hres = ITextSelection_QueryInterface(txtSel, &IID_IDispatch, (void **) &punk);
182  ok(hres == S_OK, "ITextSelection_QueryInterface\n");
183  ok(punk != NULL, "ITextSelection_QueryInterface\n");
184  IUnknown_Release(punk);
185 
186  punk = NULL;
187  hres = IRichEditOle_QueryInterface(reOle, &IID_IOleClientSite, (void **) &punk);
188  ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
189 
190  punk = NULL;
191  hres = IRichEditOle_QueryInterface(reOle, &IID_IOleWindow, (void **) &punk);
192  ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
193 
194  punk = NULL;
195  hres = IRichEditOle_QueryInterface(reOle, &IID_IOleInPlaceSite, (void **) &punk);
196  ok(hres == E_NOINTERFACE, "IRichEditOle_QueryInterface\n");
197 
198  ITextDocument_Release(txtDoc);
199  IRichEditOle_Release(reOle);
200  refcount = IRichEditOle_Release(reOle);
201  ok(refcount == 1, "got wrong ref count: %d\n", refcount);
202  DestroyWindow(w);
203 
204  /* Methods should return CO_E_RELEASED if the backing document has
205  been released. One test should suffice. */
206  hres = ITextSelection_CanEdit(txtSel, NULL);
207  ok(hres == CO_E_RELEASED, "ITextSelection after ITextDocument destroyed\n");
208 
209  ITextSelection_Release(txtSel);
210 }
211 
212 static void test_ITextDocument_Open(void)
213 {
214  IRichEditOle *reOle = NULL;
215  ITextDocument *txtDoc = NULL;
216  ITextSelection *txtSel = NULL;
217  HRESULT hres;
218  HWND w;
219  HANDLE hFile;
220  VARIANT testfile;
221  WCHAR filename[] = {'t', 'e', 's', 't','.','t','x','t', 0};
222  int result;
223  DWORD dw;
224  static const CHAR chACP[] = "TestSomeText";
225  static const CHAR chUTF8[] = "\xef\xbb\xbfTextWithUTF8BOM";
226  static const WCHAR chUTF16[] = {0xfeff, 'T', 'e', 's', 't', 'S', 'o', 'm',
227  'e', 'T', 'e', 'x', 't', 0};
228 
229 #define MAX_BUF_LEN 1024
230  CHAR bufACP[MAX_BUF_LEN];
231  WCHAR bufUnicode[MAX_BUF_LEN];
232 
233  static const int tomConstantsSingle[] =
234  {
238  };
239 
240  static const int tomConstantsMulti[] =
241  {
248  };
249 
250  int tomNumSingle = sizeof(tomConstantsSingle)/sizeof(tomConstantsSingle[0]);
251  int tomNumMulti = sizeof(tomConstantsMulti)/sizeof(tomConstantsMulti[0]);
252  int i;
253 
254  V_VT(&testfile) = VT_BSTR;
255  V_BSTR(&testfile) = SysAllocString(filename);
256 
257  for(i=0; i < tomNumSingle; i++)
258  {
260  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
261  hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsSingle[i], CP_ACP);
262  todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
263  tomConstantsSingle[i], hres);
264  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
266 
268  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
269  hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsSingle[i], CP_UTF8);
270  todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
271  tomConstantsSingle[i], hres);
272  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
274  }
275 
276  for(i=0; i < tomNumMulti; i++)
277  {
279  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
280  hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsMulti[i], CP_ACP);
281  todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
282  tomConstantsMulti[i], hres);
283  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
285 
287  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
288  hres = ITextDocument_Open(txtDoc, &testfile, tomConstantsMulti[i], CP_UTF8);
289  todo_wine ok(hres == S_OK, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
290  tomConstantsMulti[i], hres);
291  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
293  }
294 
295  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
296  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateAlways, CP_ACP);
297  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
298  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
299  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
301 
302  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
303  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateAlways, CP_UTF8);
304  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
305  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
306  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
308 
309  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
310  hres = ITextDocument_Open(txtDoc, &testfile, tomOpenAlways, CP_ACP);
311  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
312  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
313  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
315 
316  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
317  hres = ITextDocument_Open(txtDoc, &testfile, tomOpenAlways, CP_UTF8);
318  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
319  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
320  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
322 
323  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
324  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_ACP);
325  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_ACP\n");
326  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
327  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
329 
330  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
331  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_UTF8);
332  todo_wine ok(hres == S_OK, "ITextDocument_Open should success Codepage:CP_UTF8\n");
333  todo_wine ok(is_existing_file(filename), "ITextDocument_Open should create a file\n");
334  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
336 
337  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
339  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_ACP);
340  todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "ITextDocument_Open should fail Codepage:CP_ACP\n");
341  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
343 
344  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
346  hres = ITextDocument_Open(txtDoc, &testfile, tomCreateNew, CP_UTF8);
347  todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
348  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
350 
351  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
352  hres = ITextDocument_Open(txtDoc, &testfile, tomOpenExisting, CP_ACP);
353  todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ITextDocument_Open should fail Codepage:CP_ACP\n");
354  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
355 
356  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
357  hres = ITextDocument_Open(txtDoc, &testfile, tomOpenExisting, CP_UTF8);
358  todo_wine ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
359  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
360 
361  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
363  hres = ITextDocument_Open(txtDoc, &testfile, tomText, CP_ACP);
364 todo_wine {
365  ok(hres == S_OK, "got 0x%08x\n", hres);
366  ok(is_existing_file(filename) == TRUE, "a file should be created default\n");
367 }
368  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
370 
371  /* test of share mode */
373  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
374  hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyRead, CP_ACP);
375 todo_wine
376  ok(hres == S_OK, "got 0x%08x\n", hres);
377  SetLastError(0xdeadbeef);
380  todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
382  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
384 
386  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
387  hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyWrite, CP_ACP);
388 todo_wine
389  ok(hres == S_OK, "got 0x%08x\n", hres);
390  SetLastError(0xdeadbeef);
393  todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
395  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
397 
399  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
400  SetLastError(0xdeadbeef);
401  hres = ITextDocument_Open(txtDoc, &testfile, tomShareDenyWrite|tomShareDenyRead, CP_ACP);
402 todo_wine
403  ok(hres == S_OK, "got 0x%08x\n", hres);
406  todo_wine ok(GetLastError() == ERROR_SHARING_VIOLATION, "ITextDocument_Open should fail\n");
408  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
410 
411  /* tests to check the content */
414  WriteFile(hFile, chACP, sizeof(chACP)-sizeof(CHAR), &dw, NULL);
416  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
417  hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, CP_ACP);
418 todo_wine
419  ok(hres == S_OK, "got 0x%08x\n", hres);
420  result = SendMessageA(w, WM_GETTEXT, 1024, (LPARAM)bufACP);
421  todo_wine ok(result == 12, "ITextDocument_Open: Test ASCII returned %d, expected 12\n", result);
422  result = strcmp(bufACP, chACP);
423  todo_wine ok(result == 0, "ITextDocument_Open: Test ASCII set wrong text: Result: %s\n", bufACP);
424  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
426 
429  WriteFile(hFile, chUTF8, sizeof(chUTF8)-sizeof(CHAR), &dw, NULL);
431  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
432  hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, CP_UTF8);
433 todo_wine
434  ok(hres == S_OK, "got 0x%08x\n", hres);
435  result = SendMessageA(w, WM_GETTEXT, 1024, (LPARAM)bufACP);
436  todo_wine ok(result == 15, "ITextDocument_Open: Test UTF-8 returned %d, expected 15\n", result);
437  result = strcmp(bufACP, &chUTF8[3]);
438  todo_wine ok(result == 0, "ITextDocument_Open: Test UTF-8 set wrong text: Result: %s\n", bufACP);
439  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
441 
444  WriteFile(hFile, chUTF16, sizeof(chUTF16)-sizeof(WCHAR), &dw, NULL);
446  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
447  hres = ITextDocument_Open(txtDoc, &testfile, tomReadOnly, 1200);
448 todo_wine
449  ok(hres == S_OK, "got 0x%08x\n", hres);
450  result = SendMessageW(w, WM_GETTEXT, 1024, (LPARAM)bufUnicode);
451  todo_wine ok(result == 12, "ITextDocument_Open: Test UTF-16 returned %d, expected 12\n", result);
452  result = lstrcmpW(bufUnicode, &chUTF16[1]);
453  todo_wine ok(result == 0, "ITextDocument_Open: Test UTF-16 set wrong text: Result: %s\n", wine_dbgstr_w(bufUnicode));
454  release_interfaces(&w, &reOle, &txtDoc, &txtSel);
456 
457  VariantClear(&testfile);
458 }
459 
460 static void test_GetText(void)
461 {
462  HWND w;
463  IRichEditOle *reOle = NULL;
464  ITextDocument *txtDoc = NULL;
465  ITextSelection *txtSel = NULL;
466  HRESULT hres;
467  BSTR bstr = NULL;
468  int first, lim;
469  static const CHAR test_text1[] = "TestSomeText";
470  static const WCHAR bufW1[] = {'T', 'e', 's', 't', 0};
471  static const WCHAR bufW2[] = {'T', 'e', 'x', 't', '\r', 0};
472  static const WCHAR bufW3[] = {'T', 'e', 'x', 't', 0};
473  static const WCHAR bufW4[] = {'T', 'e', 's', 't', 'S', 'o', 'm',
474  'e', 'T', 'e', 'x', 't', '\r', 0};
475  static const WCHAR bufW5[] = {'\r', 0};
476  static const WCHAR bufW6[] = {'T','e','s','t','S','o','m','e','T',0};
477  BOOL is64bit = sizeof(void *) > sizeof(int);
478  ITextRange *range;
479 
480  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
481  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
482 
483  /* ITextSelection */
484  first = 0, lim = 4;
485  SendMessageA(w, EM_SETSEL, first, lim);
486  hres = ITextSelection_GetText(txtSel, &bstr);
487  ok(hres == S_OK, "ITextSelection_GetText\n");
488  ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
489  SysFreeString(bstr);
490 
491  first = 4, lim = 0;
492  SendMessageA(w, EM_SETSEL, first, lim);
493  hres = ITextSelection_GetText(txtSel, &bstr);
494  ok(hres == S_OK, "ITextSelection_GetText\n");
495  ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
496  SysFreeString(bstr);
497 
498  first = 1, lim = 1;
499  SendMessageA(w, EM_SETSEL, first, lim);
500  hres = ITextSelection_GetText(txtSel, &bstr);
501  ok(hres == S_OK, "ITextSelection_GetText\n");
502  ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
503 
504  if (!is64bit)
505  {
506  hres = ITextSelection_GetText(txtSel, NULL);
507  ok(hres == E_INVALIDARG, "ITextSelection_GetText\n");
508  }
509 
510  first = 8, lim = 12;
511  SendMessageA(w, EM_SETSEL, first, lim);
512  hres = ITextSelection_GetText(txtSel, &bstr);
513  ok(hres == S_OK, "ITextSelection_GetText\n");
514  ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr));
515  SysFreeString(bstr);
516 
517  first = 8, lim = 13;
518  SendMessageA(w, EM_SETSEL, first, lim);
519  hres = ITextSelection_GetText(txtSel, &bstr);
520  ok(hres == S_OK, "ITextSelection_GetText\n");
521  ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr));
522  SysFreeString(bstr);
523 
524  first = 12, lim = 13;
525  SendMessageA(w, EM_SETSEL, first, lim);
526  hres = ITextSelection_GetText(txtSel, &bstr);
527  ok(hres == S_OK, "ITextSelection_GetText\n");
528  ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr));
529  SysFreeString(bstr);
530 
531  first = 0, lim = -1;
532  SendMessageA(w, EM_SETSEL, first, lim);
533  hres = ITextSelection_GetText(txtSel, &bstr);
534  ok(hres == S_OK, "ITextSelection_GetText\n");
535  ok(!lstrcmpW(bstr, bufW4), "got wrong text: %s\n", wine_dbgstr_w(bstr));
536  SysFreeString(bstr);
537 
538  first = -1, lim = 9;
539  SendMessageA(w, EM_SETSEL, first, lim);
540  hres = ITextSelection_GetText(txtSel, &bstr);
541  ok(hres == S_OK, "ITextSelection_GetText\n");
542  ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
543 
544  /* ITextRange */
545  hres = ITextDocument_Range(txtDoc, 0, 4, &range);
546  ok(hres == S_OK, "got 0x%08x\n", hres);
547  hres = ITextRange_GetText(range, &bstr);
548  ok(hres == S_OK, "got 0x%08x\n", hres);
549  ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
550 
551  SysFreeString(bstr);
552  ITextRange_Release(range);
553 
554  hres = ITextDocument_Range(txtDoc, 4, 0, &range);
555  ok(hres == S_OK, "got 0x%08x\n", hres);
556  hres = ITextRange_GetText(range, &bstr);
557  ok(hres == S_OK, "got 0x%08x\n", hres);
558  ok(!lstrcmpW(bstr, bufW1), "got wrong text: %s\n", wine_dbgstr_w(bstr));
559 
560  SysFreeString(bstr);
561  ITextRange_Release(range);
562 
563  hres = ITextDocument_Range(txtDoc, 1, 1, &range);
564  ok(hres == S_OK, "got 0x%08x\n", hres);
565  hres = ITextRange_GetText(range, &bstr);
566  ok(hres == S_OK, "got 0x%08x\n", hres);
567  ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
568  if (!is64bit)
569  {
570  hres = ITextRange_GetText(range, NULL);
571  ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
572  }
573  ITextRange_Release(range);
574 
575  hres = ITextDocument_Range(txtDoc, 8, 12, &range);
576  ok(hres == S_OK, "got 0x%08x\n", hres);
577  hres = ITextRange_GetText(range, &bstr);
578  ok(hres == S_OK, "got 0x%08x\n", hres);
579  ok(!lstrcmpW(bstr, bufW3), "got wrong text: %s\n", wine_dbgstr_w(bstr));
580 
581  SysFreeString(bstr);
582  ITextRange_Release(range);
583 
584  hres = ITextDocument_Range(txtDoc, 8, 13, &range);
585  ok(hres == S_OK, "got 0x%08x\n", hres);
586  hres = ITextRange_GetText(range, &bstr);
587  ok(hres == S_OK, "got 0x%08x\n", hres);
588  ok(!lstrcmpW(bstr, bufW2), "got wrong text: %s\n", wine_dbgstr_w(bstr));
589 
590  SysFreeString(bstr);
591  ITextRange_Release(range);
592 
593  hres = ITextDocument_Range(txtDoc, 12, 13, &range);
594  ok(hres == S_OK, "got 0x%08x\n", hres);
595  hres = ITextRange_GetText(range, &bstr);
596  ok(hres == S_OK, "got 0x%08x\n", hres);
597  ok(!lstrcmpW(bstr, bufW5), "got wrong text: %s\n", wine_dbgstr_w(bstr));
598 
599  SysFreeString(bstr);
600  ITextRange_Release(range);
601 
602  hres = ITextDocument_Range(txtDoc, 0, -1, &range);
603  ok(hres == S_OK, "got 0x%08x\n", hres);
604  hres = ITextRange_GetText(range, &bstr);
605  ok(hres == S_OK, "got 0x%08x\n", hres);
606  ok(!bstr, "got wrong text: %s\n", wine_dbgstr_w(bstr));
607  ITextRange_Release(range);
608 
609  hres = ITextDocument_Range(txtDoc, -1, 9, &range);
610  ok(hres == S_OK, "got 0x%08x\n", hres);
611  hres = ITextRange_GetText(range, &bstr);
612  ok(hres == S_OK, "got 0x%08x\n", hres);
613  ok(!lstrcmpW(bstr, bufW6), "got wrong text: %s\n", wine_dbgstr_w(bstr));
614 
615  SysFreeString(bstr);
616 
617  release_interfaces(&w, &reOle, &txtDoc, NULL);
618 
619  /* detached selection/range */
620  if (is64bit) {
621  bstr = (void*)0xdeadbeef;
622  hres = ITextSelection_GetText(txtSel, &bstr);
623  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
624 todo_wine
625  ok(bstr == NULL, "got %p\n", bstr);
626 
627  bstr = (void*)0xdeadbeef;
628  hres = ITextRange_GetText(range, &bstr);
629  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
630 todo_wine
631  ok(bstr == NULL, "got %p\n", bstr);
632  }
633  else {
634  hres = ITextSelection_GetText(txtSel, NULL);
635  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
636 
637  hres = ITextRange_GetText(range, NULL);
638  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
639  }
640 
641  ITextRange_Release(range);
642  ITextSelection_Release(txtSel);
643 }
644 
645 static void test_ITextDocument_Range(void)
646 {
647  static const CHAR test_text1[] = "TestSomeText";
648  HWND w;
649  IRichEditOle *reOle = NULL;
650  ITextDocument *txtDoc = NULL;
651  ITextRange *txtRge, *range2;
652  HRESULT hres;
653  LONG value;
654 
655  create_interfaces(&w, &reOle, &txtDoc, NULL);
656  hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge);
657  ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
658  EXPECT_REF(txtRge, 1);
659 
660  hres = ITextDocument_Range(txtDoc, 0, 0, &range2);
661  ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
662  ok(range2 != txtRge, "A new pointer should be returned\n");
663  ITextRange_Release(range2);
664 
665  hres = ITextDocument_Range(txtDoc, 0, 0, NULL);
666  ok(hres == E_INVALIDARG, "ITextDocument_Range should fail 0x%x.\n", hres);
667 
668  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
669 
670  hres = ITextDocument_Range(txtDoc, 8, 30, &range2);
671  ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
672  hres = ITextRange_GetStart(range2, &value);
673  ok(hres == S_OK, "got 0x%08x\n", hres);
674  ok(value == 8, "got %d\n", value);
675 
676  hres = ITextRange_GetEnd(range2, &value);
677  ok(hres == S_OK, "got 0x%08x\n", hres);
678  ok(value == 13, "got %d\n", value);
679  ITextRange_Release(range2);
680 
681  release_interfaces(&w, &reOle, &txtDoc, NULL);
682  hres = ITextRange_CanEdit(txtRge, NULL);
683  ok(hres == CO_E_RELEASED, "ITextRange after ITextDocument destroyed\n");
684  ITextRange_Release(txtRge);
685 }
686 
687 static void test_ITextRange_GetChar(void)
688 {
689  HWND w;
690  IRichEditOle *reOle = NULL;
691  ITextDocument *txtDoc = NULL;
692  ITextRange *txtRge = NULL;
693  HRESULT hres;
694  LONG pch;
695  int first, lim;
696  static const CHAR test_text1[] = "TestSomeText";
697 
698  first = 0, lim = 4;
699  create_interfaces(&w, &reOle, &txtDoc, NULL);
700  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
701  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
702  ok(hres == S_OK, "got 0x%08x\n", hres);
703  pch = 0xdeadbeef;
704  hres = ITextRange_GetChar(txtRge, &pch);
705  ok(hres == S_OK, "ITextRange_GetChar\n");
706  ok(pch == 'T', "got wrong char: %c\n", pch);
707  ITextRange_Release(txtRge);
708  release_interfaces(&w, &reOle, &txtDoc, NULL);
709 
710  first = 0, lim = 0;
711  create_interfaces(&w, &reOle, &txtDoc, NULL);
712  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
713  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
714  ok(hres == S_OK, "got 0x%08x\n", hres);
715  pch = 0xdeadbeef;
716  hres = ITextRange_GetChar(txtRge, &pch);
717  ok(hres == S_OK, "ITextRange_GetChar\n");
718  ok(pch == 'T', "got wrong char: %c\n", pch);
719  ITextRange_Release(txtRge);
720  release_interfaces(&w, &reOle, &txtDoc, NULL);
721 
722  first = 12, lim = 12;
723  create_interfaces(&w, &reOle, &txtDoc, NULL);
724  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
725  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
726  ok(hres == S_OK, "got 0x%08x\n", hres);
727  pch = 0xdeadbeef;
728  hres = ITextRange_GetChar(txtRge, &pch);
729  ok(hres == S_OK, "ITextRange_GetChar\n");
730  ok(pch == '\r', "got wrong char: %c\n", pch);
731  ITextRange_Release(txtRge);
732  release_interfaces(&w, &reOle, &txtDoc, NULL);
733 
734  first = 13, lim = 13;
735  create_interfaces(&w, &reOle, &txtDoc, NULL);
736  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
737  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
738  ok(hres == S_OK, "got 0x%08x\n", hres);
739  pch = 0xdeadbeef;
740  hres = ITextRange_GetChar(txtRge, &pch);
741  ok(hres == S_OK, "ITextRange_GetChar\n");
742  ok(pch == '\r', "got wrong char: %c\n", pch);
743  ITextRange_Release(txtRge);
744  release_interfaces(&w, &reOle, &txtDoc, NULL);
745 
746  create_interfaces(&w, &reOle, &txtDoc, NULL);
747  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
748  first = 12, lim = 12;
749  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
750  ok(hres == S_OK, "got 0x%08x\n", hres);
751  hres = ITextRange_GetChar(txtRge, NULL);
752  ok(hres == E_INVALIDARG, "ITextRange_GetChar\n");
753 
754  release_interfaces(&w, &reOle, &txtDoc, NULL);
755 
756  hres = ITextRange_GetChar(txtRge, NULL);
757  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
758 
759  hres = ITextRange_GetChar(txtRge, &pch);
760  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
761 
762  ITextRange_Release(txtRge);
763 }
764 
765 /* Helper function for testing ITextRange_ScrollIntoView */
766 static void check_range(HWND w, ITextDocument* doc, int first, int lim,
767  LONG bStart, int expected_nonzero)
768 {
769  SCROLLINFO si;
770  ITextRange *txtRge = NULL;
771  HRESULT hres;
772 
773  si.cbSize = sizeof(SCROLLINFO);
774  si.fMask = SIF_POS | SIF_RANGE;
775 
776  hres = ITextDocument_Range(doc, first, lim, &txtRge);
777  ok(hres == S_OK, "got 0x%08x\n", hres);
778  hres = ITextRange_ScrollIntoView(txtRge, bStart);
779  ok(hres == S_OK, "got 0x%08x\n", hres);
780  GetScrollInfo(w, SB_VERT, &si);
781  if (expected_nonzero) {
782  ok(si.nPos != 0,
783  "Scrollbar at 0, should be >0. (TextRange %d-%d, scroll range %d-%d.)\n",
784  first, lim, si.nMin, si.nMax);
785  } else {
786  ok(si.nPos == 0,
787  "Scrollbar at %d, should be 0. (TextRange %d-%d, scroll range %d-%d.)\n",
788  si.nPos, first, lim, si.nMin, si.nMax);
789  }
790 }
791 
793 {
794  HWND w;
795  IRichEditOle *reOle = NULL;
796  ITextDocument *txtDoc = NULL;
797  ITextRange *txtRge = NULL;
798  HRESULT hres;
799  static const CHAR test_text1[] = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10";
800 
801  create_interfaces(&w, &reOle, &txtDoc, NULL);
802  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
803 
804  /* Scroll to the top. */
805  check_range(w, txtDoc, 0, 1, tomStart, 0);
806 
807  /* Scroll to the bottom. */
808  check_range(w, txtDoc, 19, 20, tomStart, 1);
809 
810  /* Back up to the top. */
811  check_range(w, txtDoc, 0, 1, tomStart, 0);
812 
813  /* Large range */
814  check_range(w, txtDoc, 0, 20, tomStart, 0);
815 
816  hres = ITextDocument_Range(txtDoc, 0, 0, &txtRge);
817  ok(hres == S_OK, "got 0x%08x\n", hres);
818  release_interfaces(&w, &reOle, &txtDoc, NULL);
819  hres = ITextRange_ScrollIntoView(txtRge, tomStart);
820  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
821  ITextRange_Release(txtRge);
822 }
823 
825 {
826  HWND w;
827  IRichEditOle *reOle = NULL;
828  ITextDocument *txtDoc = NULL;
829  ITextSelection *txtSel = NULL;
830  HRESULT hres;
831  LONG pch;
832  int first, lim;
833  static const CHAR test_text1[] = "TestSomeText";
834 
835  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
836  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
837 
838  first = 0, lim = 4;
839  SendMessageA(w, EM_SETSEL, first, lim);
840  pch = 0xdeadbeef;
841  hres = ITextSelection_GetChar(txtSel, &pch);
842  ok(hres == S_OK, "ITextSelection_GetChar\n");
843  ok(pch == 'T', "got wrong char: %c\n", pch);
844 
845  first = 0, lim = 0;
846  SendMessageA(w, EM_SETSEL, first, lim);
847  pch = 0xdeadbeef;
848  hres = ITextSelection_GetChar(txtSel, &pch);
849  ok(hres == S_OK, "ITextSelection_GetChar\n");
850  ok(pch == 'T', "got wrong char: %c\n", pch);
851 
852  first = 12, lim = 12;
853  SendMessageA(w, EM_SETSEL, first, lim);
854  pch = 0xdeadbeef;
855  hres = ITextSelection_GetChar(txtSel, &pch);
856  ok(hres == S_OK, "ITextSelection_GetChar\n");
857  ok(pch == '\r', "got wrong char: %c\n", pch);
858 
859  first = 13, lim = 13;
860  SendMessageA(w, EM_SETSEL, first, lim);
861  pch = 0xdeadbeef;
862  hres = ITextSelection_GetChar(txtSel, &pch);
863  ok(hres == S_OK, "ITextSelection_GetChar\n");
864  ok(pch == '\r', "got wrong char: %c\n", pch);
865 
866  hres = ITextSelection_GetChar(txtSel, NULL);
867  ok(hres == E_INVALIDARG, "ITextSelection_GetChar\n");
868 
869  release_interfaces(&w, &reOle, &txtDoc, NULL);
870 
871  hres = ITextSelection_GetChar(txtSel, NULL);
872  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
873 
874  hres = ITextSelection_GetChar(txtSel, &pch);
875  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
876 
877  ITextSelection_Release(txtSel);
878 }
879 
881 {
882  HWND w;
883  IRichEditOle *reOle = NULL;
884  ITextDocument *txtDoc = NULL;
885  ITextRange *txtRge = NULL;
886  HRESULT hres;
887  int first, lim, start, end;
888  static const CHAR test_text1[] = "TestSomeText";
889 
890  create_interfaces(&w, &reOle, &txtDoc, NULL);
891  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
892 
893  first = 1, lim = 6;
894  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
895  ok(hres == S_OK, "got 0x%08x\n", hres);
896  start = 0xdeadbeef;
897  hres = ITextRange_GetStart(txtRge, &start);
898  ok(hres == S_OK, "ITextRange_GetStart\n");
899  ok(start == 1, "got wrong start value: %d\n", start);
900  end = 0xdeadbeef;
901  hres = ITextRange_GetEnd(txtRge, &end);
902  ok(hres == S_OK, "ITextRange_GetEnd\n");
903  ok(end == 6, "got wrong end value: %d\n", end);
904  ITextRange_Release(txtRge);
905 
906  first = 6, lim = 1;
907  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
908  ok(hres == S_OK, "got 0x%08x\n", hres);
909  start = 0xdeadbeef;
910  hres = ITextRange_GetStart(txtRge, &start);
911  ok(hres == S_OK, "ITextRange_GetStart\n");
912  ok(start == 1, "got wrong start value: %d\n", start);
913  end = 0xdeadbeef;
914  hres = ITextRange_GetEnd(txtRge, &end);
915  ok(hres == S_OK, "ITextRange_GetEnd\n");
916  ok(end == 6, "got wrong end value: %d\n", end);
917  ITextRange_Release(txtRge);
918 
919  first = -1, lim = 13;
920  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
921  ok(hres == S_OK, "got 0x%08x\n", hres);
922  start = 0xdeadbeef;
923  hres = ITextRange_GetStart(txtRge, &start);
924  ok(hres == S_OK, "ITextRange_GetStart\n");
925  ok(start == 0, "got wrong start value: %d\n", start);
926  end = 0xdeadbeef;
927  hres = ITextRange_GetEnd(txtRge, &end);
928  ok(hres == S_OK, "ITextRange_GetEnd\n");
929  ok(end == 13, "got wrong end value: %d\n", end);
930  ITextRange_Release(txtRge);
931 
932  first = 13, lim = 13;
933  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
934  ok(hres == S_OK, "got 0x%08x\n", hres);
935  start = 0xdeadbeef;
936  hres = ITextRange_GetStart(txtRge, &start);
937  ok(hres == S_OK, "ITextRange_GetStart\n");
938  ok(start == 12, "got wrong start value: %d\n", start);
939  end = 0xdeadbeef;
940  hres = ITextRange_GetEnd(txtRge, &end);
941  ok(hres == S_OK, "ITextRange_GetEnd\n");
942  ok(end == 12, "got wrong end value: %d\n", end);
943 
944  /* SetStart */
945  hres = ITextRange_SetStart(txtRge, 0);
946  ok(hres == S_OK, "got 0x%08x\n", hres);
947 
948  /* same value */
949  hres = ITextRange_SetStart(txtRge, 0);
950  ok(hres == S_FALSE, "got 0x%08x\n", hres);
951 
952  hres = ITextRange_SetStart(txtRge, 1);
953  ok(hres == S_OK, "got 0x%08x\n", hres);
954 
955  /* negative resets to 0, return value is S_FALSE when
956  position wasn't changed */
957  hres = ITextRange_SetStart(txtRge, -1);
958  ok(hres == S_OK, "got 0x%08x\n", hres);
959 
960  hres = ITextRange_SetStart(txtRge, -1);
961  ok(hres == S_FALSE, "got 0x%08x\n", hres);
962 
963  hres = ITextRange_SetStart(txtRge, 0);
964  ok(hres == S_FALSE, "got 0x%08x\n", hres);
965 
966  start = -1;
967  hres = ITextRange_GetStart(txtRge, &start);
968  ok(hres == S_OK, "got 0x%08x\n", hres);
969  ok(start == 0, "got %d\n", start);
970 
971  /* greater than initial end, but less than total char count */
972  hres = ITextRange_SetStart(txtRge, 1);
973  ok(hres == S_OK, "got 0x%08x\n", hres);
974 
975  hres = ITextRange_SetEnd(txtRge, 3);
976  ok(hres == S_OK, "got 0x%08x\n", hres);
977 
978  hres = ITextRange_SetStart(txtRge, 10);
979  ok(hres == S_OK, "got 0x%08x\n", hres);
980 
981  start = 0;
982  hres = ITextRange_GetStart(txtRge, &start);
983  ok(hres == S_OK, "got 0x%08x\n", hres);
984  ok(start == 10, "got %d\n", start);
985 
986  end = 0;
987  hres = ITextRange_GetEnd(txtRge, &end);
988  ok(hres == S_OK, "got 0x%08x\n", hres);
989  ok(end == 10, "got %d\n", end);
990 
991  /* more that total text length */
992  hres = ITextRange_SetStart(txtRge, 50);
993  ok(hres == S_OK, "got 0x%08x\n", hres);
994 
995  start = 0;
996  hres = ITextRange_GetStart(txtRge, &start);
997  ok(hres == S_OK, "got 0x%08x\n", hres);
998  ok(start == 12, "got %d\n", start);
999 
1000  end = 0;
1001  hres = ITextRange_GetEnd(txtRge, &end);
1002  ok(hres == S_OK, "got 0x%08x\n", hres);
1003  ok(end == 12, "got %d\n", end);
1004 
1005  /* SetEnd */
1006  hres = ITextRange_SetStart(txtRge, 0);
1007  ok(hres == S_OK, "got 0x%08x\n", hres);
1008 
1009  /* same value */
1010  hres = ITextRange_SetEnd(txtRge, 5);
1011  ok(hres == S_OK, "got 0x%08x\n", hres);
1012 
1013  hres = ITextRange_SetEnd(txtRge, 5);
1014  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1015 
1016  /* negative resets to 0 */
1017  hres = ITextRange_SetEnd(txtRge, -1);
1018  ok(hres == S_OK, "got 0x%08x\n", hres);
1019 
1020  end = -1;
1021  hres = ITextRange_GetEnd(txtRge, &end);
1022  ok(hres == S_OK, "got 0x%08x\n", hres);
1023  ok(end == 0, "got %d\n", end);
1024 
1025  start = -1;
1026  hres = ITextRange_GetStart(txtRge, &start);
1027  ok(hres == S_OK, "got 0x%08x\n", hres);
1028  ok(start == 0, "got %d\n", start);
1029 
1030  /* greater than initial end, but less than total char count */
1031  hres = ITextRange_SetStart(txtRge, 3);
1032  ok(hres == S_OK, "got 0x%08x\n", hres);
1033 
1034  hres = ITextRange_SetEnd(txtRge, 1);
1035  ok(hres == S_OK, "got 0x%08x\n", hres);
1036 
1037  start = 0;
1038  hres = ITextRange_GetStart(txtRge, &start);
1039  ok(hres == S_OK, "got 0x%08x\n", hres);
1040  ok(start == 1, "got %d\n", start);
1041 
1042  end = 0;
1043  hres = ITextRange_GetEnd(txtRge, &end);
1044  ok(hres == S_OK, "got 0x%08x\n", hres);
1045  ok(end == 1, "got %d\n", end);
1046 
1047  /* more than total count */
1048  hres = ITextRange_SetEnd(txtRge, 50);
1049  ok(hres == S_OK, "got 0x%08x\n", hres);
1050 
1051  start = 0;
1052  hres = ITextRange_GetStart(txtRge, &start);
1053  ok(hres == S_OK, "got 0x%08x\n", hres);
1054  ok(start == 1, "got %d\n", start);
1055 
1056  end = 0;
1057  hres = ITextRange_GetEnd(txtRge, &end);
1058  ok(hres == S_OK, "got 0x%08x\n", hres);
1059  ok(end == 13, "got %d\n", end);
1060 
1061  /* zero */
1062  hres = ITextRange_SetEnd(txtRge, 0);
1063  ok(hres == S_OK, "got 0x%08x\n", hres);
1064 
1065  start = 0;
1066  hres = ITextRange_GetStart(txtRge, &start);
1067  ok(hres == S_OK, "got 0x%08x\n", hres);
1068  ok(start == 0, "got %d\n", start);
1069 
1070  end = 0;
1071  hres = ITextRange_GetEnd(txtRge, &end);
1072  ok(hres == S_OK, "got 0x%08x\n", hres);
1073  ok(end == 0, "got %d\n", end);
1074 
1075  release_interfaces(&w, &reOle, &txtDoc, NULL);
1076 
1077  /* detached range */
1078  hres = ITextRange_SetStart(txtRge, 0);
1079  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1080 
1081  hres = ITextRange_SetEnd(txtRge, 3);
1082  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1083 
1084  hres = ITextRange_GetStart(txtRge, &start);
1085  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1086 
1087  hres = ITextRange_GetStart(txtRge, NULL);
1088  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1089 
1090  hres = ITextRange_GetEnd(txtRge, &end);
1091  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1092 
1093  hres = ITextRange_GetEnd(txtRge, NULL);
1094  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1095 
1096  ITextRange_Release(txtRge);
1097 }
1098 
1100 {
1101  HWND w;
1102  IRichEditOle *reOle = NULL;
1103  ITextDocument *txtDoc = NULL;
1104  ITextSelection *txtSel = NULL;
1105  HRESULT hres;
1106  int first, lim, start, end;
1107  static const CHAR test_text1[] = "TestSomeText";
1108 
1109  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
1110  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1111 
1112  first = 2, lim = 5;
1113  SendMessageA(w, EM_SETSEL, first, lim);
1114  start = 0xdeadbeef;
1115  hres = ITextSelection_GetStart(txtSel, &start);
1116  ok(hres == S_OK, "ITextSelection_GetStart\n");
1117  ok(start == 2, "got wrong start value: %d\n", start);
1118  end = 0xdeadbeef;
1119  hres = ITextSelection_GetEnd(txtSel, &end);
1120  ok(hres == S_OK, "ITextSelection_GetEnd\n");
1121  ok(end == 5, "got wrong end value: %d\n", end);
1122 
1123  first = 5, lim = 2;
1124  SendMessageA(w, EM_SETSEL, first, lim);
1125  start = 0xdeadbeef;
1126  hres = ITextSelection_GetStart(txtSel, &start);
1127  ok(hres == S_OK, "ITextSelection_GetStart\n");
1128  ok(start == 2, "got wrong start value: %d\n", start);
1129  end = 0xdeadbeef;
1130  hres = ITextSelection_GetEnd(txtSel, &end);
1131  ok(hres == S_OK, "ITextSelection_GetEnd\n");
1132  ok(end == 5, "got wrong end value: %d\n", end);
1133 
1134  first = 0, lim = -1;
1135  SendMessageA(w, EM_SETSEL, first, lim);
1136  start = 0xdeadbeef;
1137  hres = ITextSelection_GetStart(txtSel, &start);
1138  ok(hres == S_OK, "ITextSelection_GetStart\n");
1139  ok(start == 0, "got wrong start value: %d\n", start);
1140  end = 0xdeadbeef;
1141  hres = ITextSelection_GetEnd(txtSel, &end);
1142  ok(hres == S_OK, "ITextSelection_GetEnd\n");
1143  ok(end == 13, "got wrong end value: %d\n", end);
1144 
1145  first = 13, lim = 13;
1146  SendMessageA(w, EM_SETSEL, first, lim);
1147  start = 0xdeadbeef;
1148  hres = ITextSelection_GetStart(txtSel, &start);
1149  ok(hres == S_OK, "ITextSelection_GetStart\n");
1150  ok(start == 12, "got wrong start value: %d\n", start);
1151  end = 0xdeadbeef;
1152  hres = ITextSelection_GetEnd(txtSel, &end);
1153  ok(hres == S_OK, "ITextSelection_GetEnd\n");
1154  ok(end == 12, "got wrong end value: %d\n", end);
1155 
1156  /* SetStart/SetEnd */
1157  hres = ITextSelection_SetStart(txtSel, 0);
1158  ok(hres == S_OK, "got 0x%08x\n", hres);
1159 
1160  /* same value */
1161  hres = ITextSelection_SetStart(txtSel, 0);
1162  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1163 
1164  hres = ITextSelection_SetStart(txtSel, 1);
1165  ok(hres == S_OK, "got 0x%08x\n", hres);
1166 
1167  /* negative resets to 0, return value is S_FALSE when
1168  position wasn't changed */
1169  hres = ITextSelection_SetStart(txtSel, -1);
1170  ok(hres == S_OK, "got 0x%08x\n", hres);
1171 
1172  hres = ITextSelection_SetStart(txtSel, -1);
1173  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1174 
1175  hres = ITextSelection_SetStart(txtSel, 0);
1176  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1177 
1178  start = -1;
1179  hres = ITextSelection_GetStart(txtSel, &start);
1180  ok(hres == S_OK, "got 0x%08x\n", hres);
1181  ok(start == 0, "got %d\n", start);
1182 
1183  /* greater than initial end, but less than total char count */
1184  hres = ITextSelection_SetStart(txtSel, 1);
1185  ok(hres == S_OK, "got 0x%08x\n", hres);
1186 
1187  hres = ITextSelection_SetEnd(txtSel, 3);
1188  ok(hres == S_OK, "got 0x%08x\n", hres);
1189 
1190  hres = ITextSelection_SetStart(txtSel, 10);
1191  ok(hres == S_OK, "got 0x%08x\n", hres);
1192 
1193  start = 0;
1194  hres = ITextSelection_GetStart(txtSel, &start);
1195  ok(hres == S_OK, "got 0x%08x\n", hres);
1196  ok(start == 10, "got %d\n", start);
1197 
1198  end = 0;
1199  hres = ITextSelection_GetEnd(txtSel, &end);
1200  ok(hres == S_OK, "got 0x%08x\n", hres);
1201  ok(end == 10, "got %d\n", end);
1202 
1203  /* more that total text length */
1204  hres = ITextSelection_SetStart(txtSel, 50);
1205  ok(hres == S_OK, "got 0x%08x\n", hres);
1206 
1207  start = 0;
1208  hres = ITextSelection_GetStart(txtSel, &start);
1209  ok(hres == S_OK, "got 0x%08x\n", hres);
1210  ok(start == 12, "got %d\n", start);
1211 
1212  end = 0;
1213  hres = ITextSelection_GetEnd(txtSel, &end);
1214  ok(hres == S_OK, "got 0x%08x\n", hres);
1215  ok(end == 12, "got %d\n", end);
1216 
1217  /* SetEnd */
1218  hres = ITextSelection_SetStart(txtSel, 0);
1219  ok(hres == S_OK, "got 0x%08x\n", hres);
1220 
1221  /* same value */
1222  hres = ITextSelection_SetEnd(txtSel, 5);
1223  ok(hres == S_OK, "got 0x%08x\n", hres);
1224 
1225  hres = ITextSelection_SetEnd(txtSel, 5);
1226  ok(hres == S_FALSE, "got 0x%08x\n", hres);
1227 
1228  /* negative resets to 0 */
1229  hres = ITextSelection_SetEnd(txtSel, -1);
1230  ok(hres == S_OK, "got 0x%08x\n", hres);
1231 
1232  end = -1;
1233  hres = ITextSelection_GetEnd(txtSel, &end);
1234  ok(hres == S_OK, "got 0x%08x\n", hres);
1235  ok(end == 0, "got %d\n", end);
1236 
1237  start = -1;
1238  hres = ITextSelection_GetStart(txtSel, &start);
1239  ok(hres == S_OK, "got 0x%08x\n", hres);
1240  ok(start == 0, "got %d\n", start);
1241 
1242  /* greater than initial end, but less than total char count */
1243  hres = ITextSelection_SetStart(txtSel, 3);
1244  ok(hres == S_OK, "got 0x%08x\n", hres);
1245 
1246  hres = ITextSelection_SetEnd(txtSel, 1);
1247  ok(hres == S_OK, "got 0x%08x\n", hres);
1248 
1249  start = 0;
1250  hres = ITextSelection_GetStart(txtSel, &start);
1251  ok(hres == S_OK, "got 0x%08x\n", hres);
1252  ok(start == 1, "got %d\n", start);
1253 
1254  end = 0;
1255  hres = ITextSelection_GetEnd(txtSel, &end);
1256  ok(hres == S_OK, "got 0x%08x\n", hres);
1257  ok(end == 1, "got %d\n", end);
1258 
1259  /* more than total count */
1260  hres = ITextSelection_SetEnd(txtSel, 50);
1261  ok(hres == S_OK, "got 0x%08x\n", hres);
1262 
1263  start = 0;
1264  hres = ITextSelection_GetStart(txtSel, &start);
1265  ok(hres == S_OK, "got 0x%08x\n", hres);
1266  ok(start == 1, "got %d\n", start);
1267 
1268  end = 0;
1269  hres = ITextSelection_GetEnd(txtSel, &end);
1270  ok(hres == S_OK, "got 0x%08x\n", hres);
1271  ok(end == 13, "got %d\n", end);
1272 
1273  /* zero */
1274  hres = ITextSelection_SetEnd(txtSel, 0);
1275  ok(hres == S_OK, "got 0x%08x\n", hres);
1276 
1277  start = 0;
1278  hres = ITextSelection_GetStart(txtSel, &start);
1279  ok(hres == S_OK, "got 0x%08x\n", hres);
1280  ok(start == 0, "got %d\n", start);
1281 
1282  end = 0;
1283  hres = ITextSelection_GetEnd(txtSel, &end);
1284  ok(hres == S_OK, "got 0x%08x\n", hres);
1285  ok(end == 0, "got %d\n", end);
1286 
1287  release_interfaces(&w, &reOle, &txtDoc, NULL);
1288 
1289  /* detached selection */
1290  hres = ITextSelection_GetStart(txtSel, NULL);
1291  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1292 
1293  hres = ITextSelection_GetStart(txtSel, &start);
1294  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1295 
1296  hres = ITextSelection_GetEnd(txtSel, NULL);
1297  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1298 
1299  hres = ITextSelection_GetEnd(txtSel, &end);
1300  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1301 
1302  ITextSelection_Release(txtSel);
1303 }
1304 
1306 {
1307  HWND w;
1308  IRichEditOle *reOle = NULL;
1309  ITextDocument *txtDoc = NULL;
1310  ITextRange *txtRge = NULL;
1311  ITextRange *txtRgeDup = NULL;
1312  HRESULT hres;
1313  LONG first, lim, start, end;
1314  static const CHAR test_text1[] = "TestSomeText";
1315 
1316  create_interfaces(&w, &reOle, &txtDoc, NULL);
1317  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1318  first = 0, lim = 4;
1319  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1320  ok(hres == S_OK, "ITextDocument_Range fails 0x%x.\n", hres);
1321 
1322  hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup);
1323  ok(hres == S_OK, "ITextRange_GetDuplicate\n");
1324  ok(txtRgeDup != txtRge, "A new pointer should be returned\n");
1325  hres = ITextRange_GetStart(txtRgeDup, &start);
1326  ok(hres == S_OK, "got 0x%08x\n", hres);
1327  ok(start == first, "got wrong value: %d\n", start);
1328  hres = ITextRange_GetEnd(txtRgeDup, &end);
1329  ok(hres == S_OK, "got 0x%08x\n", hres);
1330  ok(end == lim, "got wrong value: %d\n", end);
1331 
1332  ITextRange_Release(txtRgeDup);
1333 
1334  hres = ITextRange_GetDuplicate(txtRge, NULL);
1335  ok(hres == E_INVALIDARG, "ITextRange_GetDuplicate\n");
1336 
1337  release_interfaces(&w, &reOle, &txtDoc, NULL);
1338 
1339  hres = ITextRange_GetDuplicate(txtRge, NULL);
1340  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1341 
1342  hres = ITextRange_GetDuplicate(txtRge, &txtRgeDup);
1343  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1344 
1345  ITextRange_Release(txtRge);
1346 }
1347 
1348 static void test_ITextRange_Collapse(void)
1349 {
1350  HWND w;
1351  IRichEditOle *reOle = NULL;
1352  ITextDocument *txtDoc = NULL;
1353  ITextRange *txtRge = NULL;
1354  HRESULT hres;
1355  LONG first, lim, start, end;
1356  static const CHAR test_text1[] = "TestSomeText";
1357 
1358  create_interfaces(&w, &reOle, &txtDoc, NULL);
1359  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1360 
1361  first = 4, lim = 8;
1362  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1363  ok(hres == S_OK, "got 0x%08x\n", hres);
1364  hres = ITextRange_Collapse(txtRge, tomTrue);
1365  ok(hres == S_OK, "ITextRange_Collapse\n");
1366  hres = ITextRange_GetStart(txtRge, &start);
1367  ok(hres == S_OK, "got 0x%08x\n", hres);
1368  ok(start == 4, "got wrong start value: %d\n", start);
1369  hres = ITextRange_GetEnd(txtRge, &end);
1370  ok(hres == S_OK, "got 0x%08x\n", hres);
1371  ok(end == 4, "got wrong end value: %d\n", end);
1372  ITextRange_Release(txtRge);
1373 
1374  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1375  ok(hres == S_OK, "got 0x%08x\n", hres);
1376  hres = ITextRange_Collapse(txtRge, tomStart);
1377  ok(hres == S_OK, "ITextRange_Collapse\n");
1378  hres = ITextRange_GetStart(txtRge, &start);
1379  ok(hres == S_OK, "got 0x%08x\n", hres);
1380  ok(start == 4, "got wrong start value: %d\n", start);
1381  hres = ITextRange_GetEnd(txtRge, &end);
1382  ok(hres == S_OK, "got 0x%08x\n", hres);
1383  ok(end == 4, "got wrong end value: %d\n", end);
1384  ITextRange_Release(txtRge);
1385 
1386  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1387  ok(hres == S_OK, "got 0x%08x\n", hres);
1388  hres = ITextRange_Collapse(txtRge, tomFalse);
1389  ok(hres == S_OK, "ITextRange_Collapse\n");
1390  hres = ITextRange_GetStart(txtRge, &start);
1391  ok(hres == S_OK, "got 0x%08x\n", hres);
1392  ok(start == 8, "got wrong start value: %d\n", start);
1393  hres = ITextRange_GetEnd(txtRge, &end);
1394  ok(hres == S_OK, "got 0x%08x\n", hres);
1395  ok(end == 8, "got wrong end value: %d\n", end);
1396  ITextRange_Release(txtRge);
1397 
1398  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1399  ok(hres == S_OK, "got 0x%08x\n", hres);
1400  hres = ITextRange_Collapse(txtRge, tomEnd);
1401  ok(hres == S_OK, "ITextRange_Collapse\n");
1402  hres = ITextRange_GetStart(txtRge, &start);
1403  ok(hres == S_OK, "got 0x%08x\n", hres);
1404  ok(start == 8, "got wrong start value: %d\n", start);
1405  hres = ITextRange_GetEnd(txtRge, &end);
1406  ok(hres == S_OK, "got 0x%08x\n", hres);
1407  ok(end == 8, "got wrong end value: %d\n", end);
1408  ITextRange_Release(txtRge);
1409 
1410  /* tomStart is the default */
1411  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1412  ok(hres == S_OK, "got 0x%08x\n", hres);
1413  hres = ITextRange_Collapse(txtRge, 256);
1414  ok(hres == S_OK, "ITextRange_Collapse\n");
1415  hres = ITextRange_GetStart(txtRge, &start);
1416  ok(hres == S_OK, "got 0x%08x\n", hres);
1417  ok(start == 4, "got wrong start value: %d\n", start);
1418  hres = ITextRange_GetEnd(txtRge, &end);
1419  ok(hres == S_OK, "got 0x%08x\n", hres);
1420  ok(end == 4, "got wrong end value: %d\n", end);
1421  ITextRange_Release(txtRge);
1422 
1423  first = 6, lim = 6;
1424  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1425  ok(hres == S_OK, "got 0x%08x\n", hres);
1426  hres = ITextRange_Collapse(txtRge, tomEnd);
1427  ok(hres == S_FALSE, "ITextRange_Collapse\n");
1428  hres = ITextRange_GetStart(txtRge, &start);
1429  ok(hres == S_OK, "got 0x%08x\n", hres);
1430  ok(start == 6, "got wrong start value: %d\n", start);
1431  hres = ITextRange_GetEnd(txtRge, &end);
1432  ok(hres == S_OK, "got 0x%08x\n", hres);
1433  ok(end == 6, "got wrong end value: %d\n", end);
1434  ITextRange_Release(txtRge);
1435 
1436  first = 8, lim = 8;
1437  hres = ITextDocument_Range(txtDoc, first, lim, &txtRge);
1438  ok(hres == S_OK, "got 0x%08x\n", hres);
1439  hres = ITextRange_Collapse(txtRge, tomStart);
1440  ok(hres == S_FALSE, "ITextRange_Collapse\n");
1441  hres = ITextRange_GetStart(txtRge, &start);
1442  ok(hres == S_OK, "got 0x%08x\n", hres);
1443  ok(start == 8, "got wrong start value: %d\n", start);
1444  hres = ITextRange_GetEnd(txtRge, &end);
1445  ok(hres == S_OK, "got 0x%08x\n", hres);
1446  ok(end == 8, "got wrong end value: %d\n", end);
1447 
1448  release_interfaces(&w, &reOle, &txtDoc, NULL);
1449 
1450  hres = ITextRange_Collapse(txtRge, tomStart);
1451  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1452 
1453  hres = ITextRange_Collapse(txtRge, tomUndefined);
1454  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1455 
1456  ITextRange_Release(txtRge);
1457 }
1458 
1460 {
1461  HWND w;
1462  IRichEditOle *reOle = NULL;
1463  ITextDocument *txtDoc = NULL;
1464  ITextSelection *txtSel = NULL;
1465  HRESULT hres;
1466  LONG first, lim, start, end;
1467  static const CHAR test_text1[] = "TestSomeText";
1468 
1469  create_interfaces(&w, &reOle, &txtDoc, &txtSel);
1470  SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1);
1471 
1472  first = 4, lim = 8;
1473  SendMessageA(w, EM_SETSEL, first, lim);
1474  hres = ITextSelection_Collapse(txtSel, tomTrue);
1475  ok(hres == S_OK, "ITextSelection_Collapse\n");
1477  ok(start == 4, "got wrong start value: %d\n", start);
1478  ok(end == 4, "got wrong end value: %d\n", end);
1479 
1480  SendMessageA(w, EM_SETSEL, first, lim);
1481  hres = ITextSelection_Collapse(txtSel, tomStart);
1482  ok(hres == S_OK, "ITextSelection_Collapse\n");
1484  ok(start == 4, "got wrong start value: %d\n", start);
1485  ok(end == 4, "got wrong end value: %d\n", end);
1486 
1487  SendMessageA(w, EM_SETSEL, first, lim);
1488  hres = ITextSelection_Collapse(txtSel, tomFalse);
1489  ok(hres == S_OK, "ITextSelection_Collapse\n");
1491  ok(start == 8, "got wrong start value: %d\n", start);
1492  ok(end == 8, "got wrong end value: %d\n", end);
1493 
1494  SendMessageA(w, EM_SETSEL, first, lim);
1495  hres = ITextSelection_Collapse(txtSel, tomEnd);
1496  ok(hres == S_OK, "ITextSelection_Collapse\n");
1498  ok(start == 8, "got wrong start value: %d\n", start);
1499  ok(end == 8, "got wrong end value: %d\n", end);
1500 
1501  /* tomStart is the default */
1502  SendMessageA(w, EM_SETSEL, first, lim);
1503  hres = ITextSelection_Collapse(txtSel, 256);
1504  ok(hres == S_OK, "ITextSelection_Collapse\n");
1506  ok(start == 4, "got wrong start value: %d\n", start);
1507  ok(end == 4, "got wrong end value: %d\n", end);
1508 
1509  first = 6, lim = 6;
1510  SendMessageA(w, EM_SETSEL, first, lim);
1511  hres = ITextSelection_Collapse(txtSel, tomEnd);
1512  ok(hres == S_FALSE, "ITextSelection_Collapse\n");
1514  ok(start == 6, "got wrong start value: %d\n", start);
1515  ok(end == 6, "got wrong end value: %d\n", end);
1516 
1517  first = 8, lim = 8;
1518  SendMessageA(w, EM_SETSEL, first, lim);
1519  hres = ITextSelection_Collapse(txtSel, tomStart);
1520  ok(hres == S_FALSE, "ITextSelection_Collapse\n");
1522  ok(start == 8, "got wrong start value: %d\n", start);
1523  ok(end == 8, "got wrong end value: %d\n", end);
1524 
1525  release_interfaces(&w, &reOle, &txtDoc, NULL);
1526 
1527  hres = ITextSelection_Collapse(txtSel, tomStart);
1528  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1529 
1530  hres = ITextSelection_Collapse(txtSel, tomUndefined);
1531  ok(hres == CO_E_RELEASED, "got 0x%08x\n", hres);
1532 
1533  ITextSelection_Release(txtSel);
1534 }
1535 
1536 static void test_GetClientSite(void)
1537 {
1538  HWND w;
1539  IRichEditOle *reOle = NULL, *reOle1 = NULL;
1540  ITextDocument *txtDoc = NULL;
1541  IOleClientSite *clientSite = NULL, *clientSite1 = NULL, *clientSite2 = NULL;
1542  IOleWindow *oleWin = NULL, *oleWin1 = NULL;
1543  IOleInPlaceSite *olePlace = NULL, *olePlace1 = NULL;
1544  HRESULT hres;
1545  LONG refcount1, refcount2;
1546 
1547  create_interfaces(&w, &reOle, &txtDoc, NULL);
1548  hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1549  ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1550  EXPECT_REF(clientSite, 1);
1551 
1552  hres = IOleClientSite_QueryInterface(clientSite, &IID_IRichEditOle, (void **)&reOle1);
1553  ok(hres == E_NOINTERFACE, "IOleClientSite_QueryInterface: %x\n", hres);
1554 
1555  hres = IRichEditOle_GetClientSite(reOle, &clientSite1);
1556  ok(hres == S_OK, "got 0x%08x\n", hres);
1557  ok(clientSite != clientSite1, "got %p, %p\n", clientSite, clientSite1);
1558  IOleClientSite_Release(clientSite1);
1559 
1560  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleClientSite, (void **)&clientSite1);
1561  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1562  ok(clientSite == clientSite1, "Should not return a new pointer.\n");
1563  EXPECT_REF(clientSite, 2);
1564 
1565  /* IOleWindow interface */
1566  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin);
1567  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1568  refcount1 = get_refcount((IUnknown *)clientSite);
1569  refcount2 = get_refcount((IUnknown *)oleWin);
1570  ok(refcount1 == refcount2, "got wrong ref count.\n");
1571 
1572  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin1);
1573  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1574  ok(oleWin == oleWin1, "Should not return a new pointer.\n");
1575  refcount1 = get_refcount((IUnknown *)clientSite);
1576  refcount2 = get_refcount((IUnknown *)oleWin);
1577  ok(refcount1 == refcount2, "got wrong ref count.\n");
1578 
1579  hres = IOleWindow_QueryInterface(oleWin, &IID_IOleClientSite, (void **)&clientSite2);
1580  ok(hres == S_OK, "IOleWindow_QueryInterface: 0x%08x\n", hres);
1581  ok(clientSite2 == clientSite1, "got wrong pointer\n");
1582 
1583  /* IOleInPlaceSite interface */
1584  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace);
1585  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1586  refcount1 = get_refcount((IUnknown *)olePlace);
1587  refcount2 = get_refcount((IUnknown *)clientSite);
1588  ok(refcount1 == refcount2, "got wrong ref count.\n");
1589 
1590  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace1);
1591  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1592  ok(olePlace == olePlace1, "Should not return a new pointer.\n");
1593  IOleInPlaceSite_Release(olePlace1);
1594 
1595  hres = IOleWindow_QueryInterface(oleWin, &IID_IOleInPlaceSite, (void **)&olePlace1);
1596  ok(hres == S_OK, "IOleWindow_QueryInterface: 0x%08x\n", hres);
1597  refcount1 = get_refcount((IUnknown *)olePlace1);
1598  refcount2 = get_refcount((IUnknown *)oleWin);
1599  ok(refcount1 == refcount2, "got wrong ref count.\n");
1600 
1601  IOleInPlaceSite_Release(olePlace1);
1602  IOleInPlaceSite_Release(olePlace);
1603  IOleWindow_Release(oleWin1);
1604  IOleWindow_Release(oleWin);
1605  IOleClientSite_Release(clientSite2);
1606  IOleClientSite_Release(clientSite1);
1607  IOleClientSite_Release(clientSite);
1608  release_interfaces(&w, &reOle, &txtDoc, NULL);
1609 }
1610 
1611 static void test_IOleWindow_GetWindow(void)
1612 {
1613  HWND w;
1614  IRichEditOle *reOle = NULL;
1615  ITextDocument *txtDoc = NULL;
1616  IOleClientSite *clientSite = NULL;
1617  IOleWindow *oleWin = NULL;
1618  HRESULT hres;
1619  HWND hwnd;
1620 
1621  create_interfaces(&w, &reOle, &txtDoc, NULL);
1622  hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1623  ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1624 
1625  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleWindow, (void **)&oleWin);
1626  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1627  hres = IOleWindow_GetWindow(oleWin, &hwnd);
1628  ok(hres == S_OK, "IOleClientSite_GetWindow: 0x%08x\n", hres);
1629  ok(w == hwnd, "got wrong pointer\n");
1630 
1631  hres = IOleWindow_GetWindow(oleWin, NULL);
1632  ok(hres == E_INVALIDARG, "IOleClientSite_GetWindow: 0x%08x\n", hres);
1633 
1634  IOleWindow_Release(oleWin);
1635  IOleClientSite_Release(clientSite);
1636  release_interfaces(&w, &reOle, &txtDoc, NULL);
1637 }
1638 
1640 {
1641  HWND w;
1642  IRichEditOle *reOle = NULL;
1643  ITextDocument *txtDoc = NULL;
1644  IOleClientSite *clientSite = NULL;
1645  IOleInPlaceSite *olePlace = NULL;
1646  HRESULT hres;
1647  HWND hwnd;
1648 
1649  create_interfaces(&w, &reOle, &txtDoc, NULL);
1650  hres = IRichEditOle_GetClientSite(reOle, &clientSite);
1651  ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres);
1652 
1653  hres = IOleClientSite_QueryInterface(clientSite, &IID_IOleInPlaceSite, (void **)&olePlace);
1654  ok(hres == S_OK, "IOleClientSite_QueryInterface: 0x%08x\n", hres);
1655  hres = IOleInPlaceSite_GetWindow(olePlace, &hwnd);
1656  ok(hres == S_OK, "IOleInPlaceSite_GetWindow: 0x%08x\n", hres);
1657  ok(w == hwnd, "got wrong pointer.\n");
1658 
1659  hres = IOleInPlaceSite_GetWindow(olePlace, NULL);
1660  ok(hres == E_INVALIDARG, "IOleInPlaceSite_GetWindow: 0x%08x\n", hres);
1661 
1662  IOleInPlaceSite_Release(olePlace);
1663  IOleClientSite_Release(clientSite);
1664  release_interfaces(&w, &reOle, &txtDoc, NULL);
1665 }
1666 
1667 static void test_GetFont(void)
1668 {
1669  static const CHAR test_text1[] = "TestSomeText";
1670  IRichEditOle *reOle = NULL;
1671  ITextDocument *doc = NULL;
1672  ITextRange *range = NULL;
1674  ITextFont *font, *font2;
1675  CHARFORMAT2A cf;
1676  LONG value;
1677  float size;
1678  HRESULT hr;
1679  HWND hwnd;
1680  BOOL ret;
1681 
1682  create_interfaces(&hwnd, &reOle, &doc, NULL);
1683  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
1684 
1685  hr = ITextDocument_GetSelection(doc, &selection);
1686  ok(hr == S_OK, "got 0x%08x\n", hr);
1687  hr = ITextSelection_GetFont(selection, &font);
1688  ok(hr == S_OK, "got 0x%08x\n", hr);
1689  hr = ITextSelection_GetFont(selection, &font2);
1690  ok(hr == S_OK, "got 0x%08x\n", hr);
1691  ok(font != font2, "got %p, %p\n", font, font2);
1692  ITextFont_Release(font2);
1693  ITextFont_Release(font);
1694  ITextSelection_Release(selection);
1695 
1696  EXPECT_REF(reOle, 3);
1697  EXPECT_REF(doc, 3);
1698 
1699  hr = ITextDocument_Range(doc, 0, 4, &range);
1700  ok(hr == S_OK, "got 0x%08x\n", hr);
1701 
1702  EXPECT_REF(reOle, 3);
1703  EXPECT_REF(doc, 3);
1704  EXPECT_REF(range, 1);
1705 
1706  hr = ITextRange_GetFont(range, NULL);
1707  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1708 
1709  hr = ITextRange_GetFont(range, &font);
1710  ok(hr == S_OK, "got 0x%08x\n", hr);
1711 
1712  EXPECT_REF(reOle, 3);
1713  EXPECT_REF(doc, 3);
1714  EXPECT_REF(range, 2);
1715  EXPECT_REF(font, 1);
1716 
1717  hr = ITextRange_GetFont(range, &font2);
1718  ok(hr == S_OK, "got 0x%08x\n", hr);
1719  ok(font != font2, "got %p, %p\n", font, font2);
1720 
1721  EXPECT_REF(reOle, 3);
1722  EXPECT_REF(doc, 3);
1723  EXPECT_REF(range, 3);
1724  EXPECT_REF(font, 1);
1725  EXPECT_REF(font2, 1);
1726 
1727  ITextFont_Release(font2);
1728 
1729  /* set different font style within a range */
1730  hr = ITextFont_GetItalic(font, NULL);
1731  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1732 
1733  hr = ITextFont_GetSize(font, NULL);
1734  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1735 
1736  size = 0.0;
1737  hr = ITextFont_GetSize(font, &size);
1738  ok(hr == S_OK, "got 0x%08x\n", hr);
1739  ok(size > 0.0, "size %.2f\n", size);
1740 
1741  value = 0;
1742  hr = ITextFont_GetLanguageID(font, &value);
1743  ok(hr == S_OK, "got 0x%08x\n", hr);
1744  ok(value == GetSystemDefaultLCID(), "got lcid %x, user lcid %x\n", value,
1746 
1747  /* range is non-italic */
1748  value = tomTrue;
1749  hr = ITextFont_GetItalic(font, &value);
1750  ok(hr == S_OK, "got 0x%08x\n", hr);
1751  ok(value == tomFalse, "got %d\n", value);
1752 
1753  cf.cbSize = sizeof(CHARFORMAT2A);
1754  cf.dwMask = CFM_ITALIC|CFM_SIZE;
1755  cf.dwEffects = CFE_ITALIC;
1756  cf.yHeight = 24.0;
1757 
1758  SendMessageA(hwnd, EM_SETSEL, 2, 3);
1760  ok(ret, "got %d\n", ret);
1761 
1762  /* now range is partially italicized */
1763  value = tomFalse;
1764  hr = ITextFont_GetItalic(font, &value);
1765  ok(hr == S_OK, "got 0x%08x\n", hr);
1766  ok(value == tomUndefined, "got %d\n", value);
1767 
1768  size = 0.0;
1769  hr = ITextFont_GetSize(font, &size);
1770  ok(hr == S_OK, "got 0x%08x\n", hr);
1771  ok(size == tomUndefined, "size %.2f\n", size);
1772 
1773  ITextFont_Release(font);
1774  release_interfaces(&hwnd, &reOle, &doc, NULL);
1775 
1776  hr = ITextRange_GetFont(range, NULL);
1777  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1778 
1779  hr = ITextRange_GetFont(range, &font2);
1780  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1781 
1782  ITextRange_Release(range);
1783 }
1784 
1785 static void test_GetPara(void)
1786 {
1787  static const CHAR test_text1[] = "TestSomeText";
1788  IRichEditOle *reOle = NULL;
1789  ITextDocument *doc = NULL;
1791  ITextRange *range = NULL;
1792  ITextPara *para, *para2;
1793  HRESULT hr;
1794  HWND hwnd;
1795 
1796  create_interfaces(&hwnd, &reOle, &doc, &selection);
1797  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
1798 
1799  EXPECT_REF(reOle, 3);
1800  EXPECT_REF(doc, 3);
1801 
1802  hr = ITextDocument_Range(doc, 0, 4, &range);
1803  ok(hr == S_OK, "got 0x%08x\n", hr);
1804 
1805  EXPECT_REF(reOle, 3);
1806  EXPECT_REF(doc, 3);
1807  EXPECT_REF(range, 1);
1808 
1809  hr = ITextRange_GetPara(range, NULL);
1810  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1811 
1812  hr = ITextRange_GetPara(range, &para);
1813  ok(hr == S_OK, "got 0x%08x\n", hr);
1814 
1815  EXPECT_REF(reOle, 3);
1816  EXPECT_REF(doc, 3);
1817  EXPECT_REF(range, 2);
1818  EXPECT_REF(para, 1);
1819 
1820  hr = ITextRange_GetPara(range, &para2);
1821  ok(hr == S_OK, "got 0x%08x\n", hr);
1822  ok(para != para2, "got %p, %p\n", para, para2);
1823 
1824  EXPECT_REF(reOle, 3);
1825  EXPECT_REF(doc, 3);
1826  EXPECT_REF(range, 3);
1827  EXPECT_REF(para, 1);
1828  EXPECT_REF(para2, 1);
1829 
1830  ITextPara_Release(para);
1831  ITextPara_Release(para2);
1832 
1833  EXPECT_REF(reOle, 3);
1834  EXPECT_REF(doc, 3);
1835  EXPECT_REF(selection, 2);
1836 
1837  hr = ITextSelection_GetPara(selection, &para);
1838  ok(hr == S_OK, "got 0x%08x\n", hr);
1839 
1840  EXPECT_REF(reOle, 3);
1841  EXPECT_REF(doc, 3);
1842  EXPECT_REF(selection, 3);
1843  EXPECT_REF(para, 1);
1844 
1845  hr = ITextSelection_GetPara(selection, &para2);
1846  ok(hr == S_OK, "got 0x%08x\n", hr);
1847  ok(para != para2, "got %p, %p\n", para, para2);
1848 
1849  ITextPara_Release(para);
1850  ITextPara_Release(para2);
1851  release_interfaces(&hwnd, &reOle, &doc, NULL);
1852 
1853  hr = ITextRange_GetPara(range, NULL);
1854  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1855 
1856  hr = ITextRange_GetPara(range, &para);
1857  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1858 
1859  hr = ITextSelection_GetPara(selection, NULL);
1860  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1861 
1862  hr = ITextSelection_GetPara(selection, &para);
1863  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
1864 
1865  ITextSelection_Release(selection);
1866  ITextRange_Release(range);
1867 }
1868 
1869 static void test_dispatch(void)
1870 {
1871  static const WCHAR testnameW[] = {'G','e','t','T','e','x','t',0};
1872  static const WCHAR testname2W[] = {'T','e','x','t',0};
1873  IRichEditOle *reOle = NULL;
1874  ITextDocument *doc = NULL;
1875  ITextRange *range = NULL;
1876  WCHAR *nameW;
1877  DISPID dispid;
1878  HRESULT hr;
1879  UINT count;
1880  HWND hwnd;
1881 
1882  create_interfaces(&hwnd, &reOle, &doc, NULL);
1883 
1884  range = NULL;
1885  hr = ITextDocument_Range(doc, 0, 0, &range);
1886  ok(hr == S_OK, "got 0x%08x\n", hr);
1887  ok(range != NULL, "got %p\n", range);
1888 
1889  dispid = 123;
1890  nameW = (WCHAR*)testnameW;
1891  hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1892  ok(hr == DISP_E_UNKNOWNNAME, "got 0x%08x\n", hr);
1893  ok(dispid == DISPID_UNKNOWN, "got %d\n", dispid);
1894 
1895  dispid = 123;
1896  nameW = (WCHAR*)testname2W;
1897  hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1898  ok(hr == S_OK, "got 0x%08x\n", hr);
1899  ok(dispid == DISPID_VALUE, "got %d\n", dispid);
1900 
1901  release_interfaces(&hwnd, &reOle, &doc, NULL);
1902 
1903  /* try dispatch methods on detached range */
1904  hr = ITextRange_GetTypeInfoCount(range, &count);
1905  ok(hr == S_OK, "got 0x%08x\n", hr);
1906 
1907  dispid = 123;
1908  nameW = (WCHAR*)testname2W;
1909  hr = ITextRange_GetIDsOfNames(range, &IID_NULL, &nameW, 1, LOCALE_USER_DEFAULT, &dispid);
1910  ok(hr == S_OK, "got 0x%08x\n", hr);
1911  ok(dispid == DISPID_VALUE, "got %d\n", dispid);
1912 
1913  ITextRange_Release(range);
1914 }
1915 
1917 {
1918  HRESULT hr, hrexp = duplicate ? S_OK : CO_E_RELEASED;
1919  LONG value;
1920  float size;
1921  BSTR str;
1922 
1923  hr = ITextFont_GetBold(font, NULL);
1924  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1925 
1926  hr = ITextFont_GetBold(font, &value);
1927  ok(hr == hrexp, "got 0x%08x\n", hr);
1928 
1929  hr = ITextFont_GetForeColor(font, NULL);
1930  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1931 
1932  hr = ITextFont_GetForeColor(font, &value);
1933  ok(hr == hrexp, "got 0x%08x\n", hr);
1934 
1935  hr = ITextFont_GetItalic(font, NULL);
1936  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1937 
1938  hr = ITextFont_GetItalic(font, &value);
1939  ok(hr == hrexp, "got 0x%08x\n", hr);
1940 
1941  hr = ITextFont_GetLanguageID(font, NULL);
1942  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1943 
1944  hr = ITextFont_GetLanguageID(font, &value);
1945  ok(hr == hrexp, "got 0x%08x\n", hr);
1946 
1947  hr = ITextFont_GetName(font, NULL);
1948  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1949 
1950  hr = ITextFont_GetName(font, &str);
1951  ok(hr == hrexp, "got 0x%08x\n", hr);
1952 
1953  hr = ITextFont_GetSize(font, NULL);
1954  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1955 
1956  hr = ITextFont_GetSize(font, &size);
1957  ok(hr == hrexp, "got 0x%08x\n", hr);
1958 
1959  hr = ITextFont_GetStrikeThrough(font, NULL);
1960  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1961 
1962  hr = ITextFont_GetStrikeThrough(font, &value);
1963  ok(hr == hrexp, "got 0x%08x\n", hr);
1964 
1965  hr = ITextFont_GetSubscript(font, NULL);
1966  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1967 
1968  hr = ITextFont_GetSubscript(font, &value);
1969  ok(hr == hrexp, "got 0x%08x\n", hr);
1970 
1971  hr = ITextFont_GetSuperscript(font, NULL);
1972  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1973 
1974  hr = ITextFont_GetSuperscript(font, &value);
1975  ok(hr == hrexp, "got 0x%08x\n", hr);
1976 
1977  hr = ITextFont_GetUnderline(font, NULL);
1978  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1979 
1980  hr = ITextFont_GetUnderline(font, &value);
1981  ok(hr == hrexp, "got 0x%08x\n", hr);
1982 }
1983 
1985 {
1986  float valuef;
1987  LONG value;
1988  HRESULT hr;
1989  BSTR str;
1990 
1991  value = tomUndefined;
1992  hr = ITextFont_GetAllCaps(font, &value);
1993  ok(hr == S_OK, "got 0x%08x\n", hr);
1994  ok(value == tomFalse, "got %d\n", value);
1995 
1996  value = tomUndefined;
1997  hr = ITextFont_GetAnimation(font, &value);
1998  ok(hr == S_OK, "got 0x%08x\n", hr);
1999  ok(value == tomFalse, "got %d\n", value);
2000 
2001  value = tomUndefined;
2002  hr = ITextFont_GetBackColor(font, &value);
2003  ok(hr == S_OK, "got 0x%08x\n", hr);
2004  ok(value == tomAutoColor, "got %d\n", value);
2005 
2006  value = tomUndefined;
2007  hr = ITextFont_GetBold(font, &value);
2008  ok(hr == S_OK, "got 0x%08x\n", hr);
2009  ok(value == tomFalse || value == tomTrue, "got %d\n", value);
2010 
2011  value = tomUndefined;
2012  hr = ITextFont_GetEmboss(font, &value);
2013  ok(hr == S_OK, "got 0x%08x\n", hr);
2014  ok(value == tomFalse, "got %d\n", value);
2015 
2016  value = tomUndefined;
2017  hr = ITextFont_GetForeColor(font, &value);
2018  ok(hr == S_OK, "got 0x%08x\n", hr);
2019  ok(value == tomAutoColor, "got %d\n", value);
2020 
2021  value = tomUndefined;
2022  hr = ITextFont_GetHidden(font, &value);
2023  ok(hr == S_OK, "got 0x%08x\n", hr);
2024  ok(value == tomFalse, "got %d\n", value);
2025 
2026  value = tomUndefined;
2027  hr = ITextFont_GetEngrave(font, &value);
2028  ok(hr == S_OK, "got 0x%08x\n", hr);
2029  ok(value == tomFalse, "got %d\n", value);
2030 
2031  value = tomUndefined;
2032  hr = ITextFont_GetItalic(font, &value);
2033  ok(hr == S_OK, "got 0x%08x\n", hr);
2034  ok(value == tomFalse, "got %d\n", value);
2035 
2036  valuef = 1.0;
2037  hr = ITextFont_GetKerning(font, &valuef);
2038  ok(hr == S_OK, "got 0x%08x\n", hr);
2039  ok(valuef == 0.0, "got %.2f\n", valuef);
2040 
2041  value = tomUndefined;
2042  hr = ITextFont_GetLanguageID(font, &value);
2043  ok(hr == S_OK, "got 0x%08x\n", hr);
2044  ok(value == GetSystemDefaultLCID(), "got %d\n", value);
2045 
2046  str = NULL;
2047  hr = ITextFont_GetName(font, &str);
2048  ok(hr == S_OK, "got 0x%08x\n", hr);
2049  ok(!lstrcmpW(sysW, str), "%s\n", wine_dbgstr_w(str));
2050  SysFreeString(str);
2051 
2052  value = tomUndefined;
2053  hr = ITextFont_GetOutline(font, &value);
2054  ok(hr == S_OK, "got 0x%08x\n", hr);
2055  ok(value == tomFalse, "got %d\n", value);
2056 
2057  valuef = 1.0;
2058  hr = ITextFont_GetPosition(font, &valuef);
2059  ok(hr == S_OK, "got 0x%08x\n", hr);
2060  ok(valuef == 0.0, "got %.2f\n", valuef);
2061 
2062  value = tomUndefined;
2063  hr = ITextFont_GetProtected(font, &value);
2064  ok(hr == S_OK, "got 0x%08x\n", hr);
2065  ok(value == tomFalse, "got %d\n", value);
2066 
2067  value = tomUndefined;
2068  hr = ITextFont_GetShadow(font, &value);
2069  ok(hr == S_OK, "got 0x%08x\n", hr);
2070  ok(value == tomFalse, "got %d\n", value);
2071 
2072  valuef = 0.0;
2073  hr = ITextFont_GetSize(font, &valuef);
2074  ok(hr == S_OK, "got 0x%08x\n", hr);
2075  ok(valuef >= 0.0, "got %.2f\n", valuef);
2076 
2077  value = tomUndefined;
2078  hr = ITextFont_GetSmallCaps(font, &value);
2079  ok(hr == S_OK, "got 0x%08x\n", hr);
2080  ok(value == tomFalse, "got %d\n", value);
2081 
2082  valuef = 1.0;
2083  hr = ITextFont_GetSpacing(font, &valuef);
2084  ok(hr == S_OK, "got 0x%08x\n", hr);
2085  ok(valuef == 0.0, "got %.2f\n", valuef);
2086 
2087  value = tomUndefined;
2088  hr = ITextFont_GetStrikeThrough(font, &value);
2089  ok(hr == S_OK, "got 0x%08x\n", hr);
2090  ok(value == tomFalse, "got %d\n", value);
2091 
2092  value = tomUndefined;
2093  hr = ITextFont_GetSubscript(font, &value);
2094  ok(hr == S_OK, "got 0x%08x\n", hr);
2095  ok(value == tomFalse, "got %d\n", value);
2096 
2097  value = tomUndefined;
2098  hr = ITextFont_GetSuperscript(font, &value);
2099  ok(hr == S_OK, "got 0x%08x\n", hr);
2100  ok(value == tomFalse, "got %d\n", value);
2101 
2102  value = tomUndefined;
2103  hr = ITextFont_GetUnderline(font, &value);
2104  ok(hr == S_OK, "got 0x%08x\n", hr);
2105  ok(value == tomFalse, "got %d\n", value);
2106 
2107  value = tomUndefined;
2108  hr = ITextFont_GetWeight(font, &value);
2109  ok(hr == S_OK, "got 0x%08x\n", hr);
2110  ok(value == FW_NORMAL || value == FW_BOLD, "got %d\n", value);
2111 }
2112 
2114 {
2115  float valuef;
2116  LONG value;
2117  HRESULT hr;
2118 
2119  value = tomFalse;
2120  hr = ITextFont_GetAllCaps(font, &value);
2121  ok(hr == S_OK, "got 0x%08x\n", hr);
2122  ok(value == tomUndefined, "got %d\n", value);
2123 
2124  value = tomFalse;
2125  hr = ITextFont_GetAnimation(font, &value);
2126  ok(hr == S_OK, "got 0x%08x\n", hr);
2127  ok(value == tomUndefined, "got %d\n", value);
2128 
2129  value = tomFalse;
2130  hr = ITextFont_GetBackColor(font, &value);
2131  ok(hr == S_OK, "got 0x%08x\n", hr);
2132  ok(value == tomUndefined, "got %d\n", value);
2133 
2134  value = tomFalse;
2135  hr = ITextFont_GetBold(font, &value);
2136  ok(hr == S_OK, "got 0x%08x\n", hr);
2137  ok(value == tomUndefined, "got %d\n", value);
2138 
2139  value = tomFalse;
2140  hr = ITextFont_GetEmboss(font, &value);
2141  ok(hr == S_OK, "got 0x%08x\n", hr);
2142  ok(value == tomUndefined, "got %d\n", value);
2143 
2144  value = tomFalse;
2145  hr = ITextFont_GetForeColor(font, &value);
2146  ok(hr == S_OK, "got 0x%08x\n", hr);
2147  ok(value == tomUndefined, "got %d\n", value);
2148 
2149  value = tomFalse;
2150  hr = ITextFont_GetHidden(font, &value);
2151  ok(hr == S_OK, "got 0x%08x\n", hr);
2152  ok(value == tomUndefined, "got %d\n", value);
2153 
2154  value = tomFalse;
2155  hr = ITextFont_GetEngrave(font, &value);
2156  ok(hr == S_OK, "got 0x%08x\n", hr);
2157  ok(value == tomUndefined, "got %d\n", value);
2158 
2159  value = tomFalse;
2160  hr = ITextFont_GetItalic(font, &value);
2161  ok(hr == S_OK, "got 0x%08x\n", hr);
2162  ok(value == tomUndefined, "got %d\n", value);
2163 
2164  valuef = 0.0;
2165  hr = ITextFont_GetKerning(font, &valuef);
2166  ok(hr == S_OK, "got 0x%08x\n", hr);
2167  ok(valuef == tomUndefined, "got %.2f\n", valuef);
2168 
2169  value = tomFalse;
2170  hr = ITextFont_GetLanguageID(font, &value);
2171  ok(hr == S_OK, "got 0x%08x\n", hr);
2172  ok(value == tomUndefined, "got %d\n", value);
2173 
2174  value = tomFalse;
2175  hr = ITextFont_GetOutline(font, &value);
2176  ok(hr == S_OK, "got 0x%08x\n", hr);
2177  ok(value == tomUndefined, "got %d\n", value);
2178 
2179  valuef = 0.0;
2180  hr = ITextFont_GetPosition(font, &valuef);
2181  ok(hr == S_OK, "got 0x%08x\n", hr);
2182  ok(valuef == tomUndefined, "got %.2f\n", valuef);
2183 
2184  value = tomFalse;
2185  hr = ITextFont_GetProtected(font, &value);
2186  ok(hr == S_OK, "got 0x%08x\n", hr);
2187  ok(value == tomUndefined, "got %d\n", value);
2188 
2189  value = tomFalse;
2190  hr = ITextFont_GetShadow(font, &value);
2191  ok(hr == S_OK, "got 0x%08x\n", hr);
2192  ok(value == tomUndefined, "got %d\n", value);
2193 
2194  valuef = 0.0;
2195  hr = ITextFont_GetSize(font, &valuef);
2196  ok(hr == S_OK, "got 0x%08x\n", hr);
2197  ok(valuef == tomUndefined, "got %.2f\n", valuef);
2198 
2199  value = tomFalse;
2200  hr = ITextFont_GetSmallCaps(font, &value);
2201  ok(hr == S_OK, "got 0x%08x\n", hr);
2202  ok(value == tomUndefined, "got %d\n", value);
2203 
2204  valuef = 0.0;
2205  hr = ITextFont_GetSpacing(font, &valuef);
2206  ok(hr == S_OK, "got 0x%08x\n", hr);
2207  ok(valuef == tomUndefined, "got %.2f\n", valuef);
2208 
2209  value = tomFalse;
2210  hr = ITextFont_GetStrikeThrough(font, &value);
2211  ok(hr == S_OK, "got 0x%08x\n", hr);
2212  ok(value == tomUndefined, "got %d\n", value);
2213 
2214  value = tomFalse;
2215  hr = ITextFont_GetSubscript(font, &value);
2216  ok(hr == S_OK, "got 0x%08x\n", hr);
2217  ok(value == tomUndefined, "got %d\n", value);
2218 
2219  value = tomFalse;
2220  hr = ITextFont_GetSuperscript(font, &value);
2221  ok(hr == S_OK, "got 0x%08x\n", hr);
2222  ok(value == tomUndefined, "got %d\n", value);
2223 
2224  value = tomFalse;
2225  hr = ITextFont_GetUnderline(font, &value);
2226  ok(hr == S_OK, "got 0x%08x\n", hr);
2227  ok(value == tomUndefined, "got %d\n", value);
2228 
2229  value = tomFalse;
2230  hr = ITextFont_GetWeight(font, &value);
2231  ok(hr == S_OK, "got 0x%08x\n", hr);
2232  ok(value == tomUndefined, "got %d\n", value);
2233 }
2234 
2236 {
2237  return value * 72.0 / 1440;
2238 }
2239 
2240 static void test_ITextFont(void)
2241 {
2242  static const WCHAR arialW[] = {'A','r','i','a','l',0};
2243  static const CHAR test_text1[] = "TestSomeText";
2244  ITextFont *font, *font2, *font3;
2245  FLOAT size, position, kerning;
2246  IRichEditOle *reOle = NULL;
2247  ITextDocument *doc = NULL;
2248  ITextRange *range = NULL;
2249  CHARFORMAT2A cf;
2250  LONG value;
2251  HRESULT hr;
2252  HWND hwnd;
2253  BOOL ret;
2254  BSTR str;
2255 
2256  create_interfaces(&hwnd, &reOle, &doc, NULL);
2257  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2258 
2259  hr = ITextDocument_Range(doc, 0, 10, &range);
2260  ok(hr == S_OK, "got 0x%08x\n", hr);
2261 
2262  hr = ITextRange_GetFont(range, &font);
2263  ok(hr == S_OK, "got 0x%08x\n", hr);
2264 
2265  hr = ITextFont_Reset(font, tomUseTwips);
2266  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2267 
2268  hr = ITextFont_Reset(font, tomUsePoints);
2269  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2270 
2271  hr = ITextFont_GetName(font, NULL);
2272  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2273 
2274  /* default font size unit is point */
2275  size = 0.0;
2276  hr = ITextFont_GetSize(font, &size);
2277  ok(hr == S_OK, "got 0x%08x\n", hr);
2278 
2279  /* set to some non-zero values */
2280  hr = ITextFont_SetPosition(font, 20.0);
2281  ok(hr == S_OK, "got 0x%08x\n", hr);
2282 
2283  hr = ITextFont_SetKerning(font, 10.0);
2284  ok(hr == S_OK, "got 0x%08x\n", hr);
2285 
2286  position = 0.0;
2287  hr = ITextFont_GetPosition(font, &position);
2288  ok(hr == S_OK, "got 0x%08x\n", hr);
2289 
2290  kerning = 0.0;
2291  hr = ITextFont_GetKerning(font, &kerning);
2292  ok(hr == S_OK, "got 0x%08x\n", hr);
2293 
2294  memset(&cf, 0, sizeof(cf));
2295  cf.cbSize = sizeof(cf);
2296  cf.dwMask = CFM_SIZE|CFM_OFFSET|CFM_KERNING;
2297 
2298  /* CHARFORMAT members are in twips */
2299  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2301  ok(ret, "got %d\n", ret);
2302  ok(size == twips_to_points(cf.yHeight), "got yHeight %d, size %.2f\n", cf.yHeight, size);
2303  ok(position == twips_to_points(cf.yOffset), "got yOffset %d, position %.2f\n", cf.yOffset, position);
2304  ok(kerning == twips_to_points(cf.wKerning), "got wKerning %d, kerning %.2f\n", cf.wKerning, kerning);
2305 
2306  hr = ITextFont_Reset(font, tomUseTwips);
2307  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2308 
2309  hr = ITextFont_Reset(font, tomUsePoints);
2310  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2311 
2312  hr = ITextFont_GetDuplicate(font, &font2);
2313  ok(hr == S_OK, "got 0x%08x\n", hr);
2314 
2315  hr = ITextFont_Reset(font2, tomUseTwips);
2316  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2317 
2318  hr = ITextFont_Reset(font2, tomUsePoints);
2319  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2320 
2321  ITextFont_Release(font2);
2322 
2323  /* default font name */
2324  str = NULL;
2325  hr = ITextFont_GetName(font, &str);
2326  ok(hr == S_OK, "got 0x%08x\n", hr);
2327  ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2328  SysFreeString(str);
2329 
2330  /* change font name for an inner subrange */
2331  memset(&cf, 0, sizeof(cf));
2332  cf.cbSize = sizeof(cf);
2333  cf.dwMask = CFM_FACE;
2334  strcpy(cf.szFaceName, "Arial");
2335 
2336  SendMessageA(hwnd, EM_SETSEL, 3, 4);
2338  ok(ret, "got %d\n", ret);
2339 
2340  /* still original name */
2341  str = NULL;
2342  hr = ITextFont_GetName(font, &str);
2343  ok(hr == S_OK, "got 0x%08x\n", hr);
2344  ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2345  SysFreeString(str);
2346 
2347  SendMessageA(hwnd, EM_SETSEL, 1, 2);
2349  ok(ret, "got %d\n", ret);
2350 
2351  str = NULL;
2352  hr = ITextFont_GetName(font, &str);
2353  ok(hr == S_OK, "got 0x%08x\n", hr);
2354  ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
2355  SysFreeString(str);
2356 
2357  /* name is returned for first position within a range */
2358  SendMessageA(hwnd, EM_SETSEL, 0, 1);
2360  ok(ret, "got %d\n", ret);
2361 
2362  str = NULL;
2363  hr = ITextFont_GetName(font, &str);
2364  ok(hr == S_OK, "got 0x%08x\n", hr);
2365  ok(!lstrcmpW(str, arialW), "got %s\n", wine_dbgstr_w(str));
2366  SysFreeString(str);
2367 
2368  /* GetDuplicate() */
2369  hr = ITextFont_GetDuplicate(font, NULL);
2370  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2371 
2372  EXPECT_REF(range, 2);
2373  font2 = NULL;
2374  hr = ITextFont_GetDuplicate(font, &font2);
2375  ok(hr == S_OK, "got 0x%08x\n", hr);
2376  EXPECT_REF(range, 2);
2377 
2378  /* set whole range to italic */
2379  cf.cbSize = sizeof(CHARFORMAT2A);
2380  cf.dwMask = CFM_ITALIC;
2381  cf.dwEffects = CFE_ITALIC;
2382 
2383  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2385  ok(ret, "got %d\n", ret);
2386 
2387  value = tomFalse;
2388  hr = ITextFont_GetItalic(font, &value);
2389  ok(hr == S_OK, "got 0x%08x\n", hr);
2390  ok(value == tomTrue, "got %d\n", value);
2391 
2392  /* duplicate retains original value */
2393  value = tomTrue;
2394  hr = ITextFont_GetItalic(font2, &value);
2395  ok(hr == S_OK, "got 0x%08x\n", hr);
2396  ok(value == tomFalse, "got %d\n", value);
2397 
2398  /* get a duplicate from a cloned font */
2399  hr = ITextFont_GetDuplicate(font2, &font3);
2400  ok(hr == S_OK, "got 0x%08x\n", hr);
2401  ITextFont_Release(font3);
2402 
2403  ITextRange_Release(range);
2404  release_interfaces(&hwnd, &reOle, &doc, NULL);
2405 
2406  hr = ITextFont_GetDuplicate(font, NULL);
2407  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2408 
2411 
2412  /* get a duplicate of detached font */
2413  hr = ITextFont_GetDuplicate(font2, &font3);
2414  ok(hr == S_OK, "got 0x%08x\n", hr);
2415  ITextFont_Release(font3);
2416 
2417  /* reset detached font to undefined */
2418  value = tomUndefined;
2419  hr = ITextFont_GetBold(font2, &value);
2420  ok(hr == S_OK, "got 0x%08x\n", hr);
2421  ok(value != tomUndefined, "got %d\n", value);
2422 
2423  /* reset to undefined for detached font */
2424  hr = ITextFont_Reset(font2, tomUndefined);
2425  ok(hr == S_OK, "got 0x%08x\n", hr);
2426  test_textfont_undefined(font2);
2427 
2428  /* font is detached, default means global TOM defaults */
2429  hr = ITextFont_Reset(font2, tomDefault);
2430  ok(hr == S_OK, "got 0x%08x\n", hr);
2432 
2433  hr = ITextFont_GetDuplicate(font2, &font3);
2434  ok(hr == S_OK, "got 0x%08x\n", hr);
2436 
2437  hr = ITextFont_Reset(font2, tomApplyNow);
2438  ok(hr == S_OK, "got 0x%08x\n", hr);
2440 
2441  hr = ITextFont_Reset(font2, tomApplyLater);
2442  ok(hr == S_OK, "got 0x%08x\n", hr);
2444 
2445  hr = ITextFont_Reset(font2, tomTrackParms);
2446  ok(hr == S_OK, "got 0x%08x\n", hr);
2448 
2449  hr = ITextFont_SetItalic(font2, tomUndefined);
2450  ok(hr == S_OK, "got 0x%08x\n", hr);
2451 
2452  hr = ITextFont_GetItalic(font2, &value);
2453  ok(hr == S_OK, "got 0x%08x\n", hr);
2454  ok(value == tomFalse, "got %d\n", value);
2455 
2456  hr = ITextFont_Reset(font2, tomCacheParms);
2457  ok(hr == S_OK, "got 0x%08x\n", hr);
2459 
2460  ITextFont_Release(font3);
2461  ITextFont_Release(font2);
2462 
2463  font2 = (void*)0xdeadbeef;
2464  hr = ITextFont_GetDuplicate(font, &font2);
2465  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2466  ok(font2 == NULL, "got %p\n", font2);
2467 
2468  hr = ITextFont_Reset(font, tomDefault);
2469  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2470 
2471  ITextFont_Release(font);
2472 
2473  /* Reset() */
2474  create_interfaces(&hwnd, &reOle, &doc, NULL);
2475  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2476 
2477  hr = ITextDocument_Range(doc, 0, 10, &range);
2478  ok(hr == S_OK, "got 0x%08x\n", hr);
2479 
2480  hr = ITextRange_GetFont(range, &font);
2481  ok(hr == S_OK, "got 0x%08x\n", hr);
2482 
2483  value = tomUndefined;
2484  hr = ITextFont_GetBold(font, &value);
2485  ok(hr == S_OK, "got 0x%08x\n", hr);
2486  ok(value != tomUndefined, "got %d\n", value);
2487 
2488  /* reset to undefined for attached font */
2489  hr = ITextFont_Reset(font, tomUndefined);
2490  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2491 
2492  value = tomUndefined;
2493  hr = ITextFont_GetBold(font, &value);
2494  ok(hr == S_OK, "got 0x%08x\n", hr);
2495  ok(value != tomUndefined, "got %d\n", value);
2496 
2497  /* tomCacheParms/tomTrackParms */
2498  hr = ITextFont_Reset(font, tomCacheParms);
2499  ok(hr == S_OK, "got 0x%08x\n", hr);
2500 
2501  hr = ITextFont_GetItalic(font, &value);
2502  ok(hr == S_OK, "got 0x%08x\n", hr);
2503  ok(value == tomFalse, "got %d\n", value);
2504 
2505  memset(&cf, 0, sizeof(cf));
2506  cf.cbSize = sizeof(CHARFORMAT2A);
2507  cf.dwMask = CFM_ITALIC;
2508 
2509  cf.dwEffects = CFE_ITALIC;
2510  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2512  ok(ret, "got %d\n", ret);
2513 
2514  /* still cached value */
2515  hr = ITextFont_GetItalic(font, &value);
2516  ok(hr == S_OK, "got 0x%08x\n", hr);
2517  ok(value == tomFalse, "got %d\n", value);
2518 
2519  hr = ITextFont_Reset(font, tomTrackParms);
2520  ok(hr == S_OK, "got 0x%08x\n", hr);
2521 
2522  hr = ITextFont_GetItalic(font, &value);
2523  ok(hr == S_OK, "got 0x%08x\n", hr);
2524  ok(value == tomTrue, "got %d\n", value);
2525 
2526  /* switch back to cache - value retained */
2527  hr = ITextFont_Reset(font, tomCacheParms);
2528  ok(hr == S_OK, "got 0x%08x\n", hr);
2529 
2530  hr = ITextFont_GetItalic(font, &value);
2531  ok(hr == S_OK, "got 0x%08x\n", hr);
2532  ok(value == tomTrue, "got %d\n", value);
2533 
2534  /* tomApplyLater */
2535  hr = ITextFont_Reset(font, tomApplyLater);
2536  ok(hr == S_OK, "got 0x%08x\n", hr);
2537 
2538  hr = ITextFont_SetItalic(font, tomFalse);
2539  ok(hr == S_OK, "got 0x%08x\n", hr);
2540 
2541  hr = ITextFont_GetItalic(font, &value);
2542  ok(hr == S_OK, "got 0x%08x\n", hr);
2543  ok(value == tomFalse, "got %d\n", value);
2544 
2545  cf.dwEffects = 0;
2546  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2548  ok(ret, "got %d\n", ret);
2549  ok((cf.dwEffects & CFE_ITALIC) == CFE_ITALIC, "got 0x%08x\n", cf.dwEffects);
2550 
2551  hr = ITextFont_Reset(font, tomApplyNow);
2552  ok(hr == S_OK, "got 0x%08x\n", hr);
2553 
2554  cf.dwEffects = 0;
2555  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2557  ok(ret, "got %d\n", ret);
2558  ok((cf.dwEffects & CFE_ITALIC) == 0, "got 0x%08x\n", cf.dwEffects);
2559 
2560  hr = ITextFont_SetItalic(font, tomUndefined);
2561  ok(hr == S_OK, "got 0x%08x\n", hr);
2562 
2563  hr = ITextFont_GetItalic(font, &value);
2564  ok(hr == S_OK, "got 0x%08x\n", hr);
2565  ok(value == tomFalse, "got %d\n", value);
2566 
2567  hr = ITextFont_SetItalic(font, tomAutoColor);
2568  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2569 
2570  cf.dwEffects = 0;
2571  SendMessageA(hwnd, EM_SETSEL, 0, 10);
2573  ok(ret, "got %d\n", ret);
2574  ok((cf.dwEffects & CFE_ITALIC) == 0, "got 0x%08x\n", cf.dwEffects);
2575 
2576  ITextRange_Release(range);
2577  ITextFont_Release(font);
2578  release_interfaces(&hwnd, &reOle, &doc, NULL);
2579 }
2580 
2581 static void test_Delete(void)
2582 {
2583  static const CHAR test_text1[] = "TestSomeText";
2584  IRichEditOle *reOle = NULL;
2585  ITextDocument *doc = NULL;
2586  ITextRange *range, *range2;
2587  LONG value;
2588  HRESULT hr;
2589  HWND hwnd;
2590 
2591  create_interfaces(&hwnd, &reOle, &doc, NULL);
2592  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2593 
2594  hr = ITextDocument_Range(doc, 0, 4, &range);
2595  ok(hr == S_OK, "got 0x%08x\n", hr);
2596 
2597  hr = ITextDocument_Range(doc, 1, 2, &range2);
2598  ok(hr == S_OK, "got 0x%08x\n", hr);
2599 
2600  hr = ITextRange_GetEnd(range, &value);
2601  ok(hr == S_OK, "got 0x%08x\n", hr);
2602  ok(value == 4, "got %d\n", value);
2603 
2604  /* unit type doesn't matter is count is 0 */
2605  value = 0;
2606  hr = ITextRange_Delete(range2, tomSentence, 0, &value);
2607 todo_wine {
2608  ok(hr == S_OK, "got 0x%08x\n", hr);
2609  ok(value == 1, "got %d\n", value);
2610 }
2611  value = 1;
2612  hr = ITextRange_Delete(range2, tomCharacter, 0, &value);
2613 todo_wine {
2614  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2615  ok(value == 0, "got %d\n", value);
2616 }
2617  hr = ITextRange_GetEnd(range, &value);
2618  ok(hr == S_OK, "got 0x%08x\n", hr);
2619 todo_wine
2620  ok(value == 3, "got %d\n", value);
2621 
2622  hr = ITextRange_GetStart(range2, &value);
2623  ok(hr == S_OK, "got 0x%08x\n", hr);
2624  ok(value == 1, "got %d\n", value);
2625 
2626  hr = ITextRange_GetEnd(range2, &value);
2627  ok(hr == S_OK, "got 0x%08x\n", hr);
2628 todo_wine
2629  ok(value == 1, "got %d\n", value);
2630 
2631  ITextRange_Release(range);
2632  ITextRange_Release(range2);
2633  release_interfaces(&hwnd, &reOle, &doc, NULL);
2634 }
2635 
2636 static void test_SetText(void)
2637 {
2638  static const CHAR test_text1[] = "TestSomeText";
2639  static const WCHAR textW[] = {'a','b','c','d','e','f','g','h','i',0};
2640  IRichEditOle *reOle = NULL;
2641  ITextDocument *doc = NULL;
2642  ITextRange *range, *range2;
2643  LONG value;
2644  HRESULT hr;
2645  HWND hwnd;
2646  BSTR str;
2647 
2648  create_interfaces(&hwnd, &reOle, &doc, NULL);
2649  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2650 
2651  hr = ITextDocument_Range(doc, 0, 4, &range);
2652  ok(hr == S_OK, "got 0x%08x\n", hr);
2653 
2654  hr = ITextDocument_Range(doc, 0, 4, &range2);
2655  ok(hr == S_OK, "got 0x%08x\n", hr);
2656 
2657  value = 1;
2658  hr = ITextRange_GetStart(range2, &value);
2659  ok(hr == S_OK, "got 0x%08x\n", hr);
2660  ok(value == 0, "got %d\n", value);
2661 
2662  value = 0;
2663  hr = ITextRange_GetEnd(range2, &value);
2664  ok(hr == S_OK, "got 0x%08x\n", hr);
2665  ok(value == 4, "got %d\n", value);
2666 
2667  hr = ITextRange_SetText(range, NULL);
2668  ok(hr == S_OK, "got 0x%08x\n", hr);
2669 
2670  value = 1;
2671  hr = ITextRange_GetEnd(range2, &value);
2672  ok(hr == S_OK, "got 0x%08x\n", hr);
2673  ok(value == 0, "got %d\n", value);
2674 
2676  hr = ITextRange_SetText(range, str);
2677  ok(hr == S_OK, "got 0x%08x\n", hr);
2678  SysFreeString(str);
2679 
2680  value = 1;
2681  hr = ITextRange_GetStart(range, &value);
2682  ok(hr == S_OK, "got 0x%08x\n", hr);
2683  ok(value == 0, "got %d\n", value);
2684 
2685  value = 0;
2686  hr = ITextRange_GetEnd(range, &value);
2687  ok(hr == S_OK, "got 0x%08x\n", hr);
2688  ok(value == 9, "got %d\n", value);
2689 
2690  value = 1;
2691  hr = ITextRange_GetStart(range2, &value);
2692  ok(hr == S_OK, "got 0x%08x\n", hr);
2693  ok(value == 0, "got %d\n", value);
2694 
2695  value = 0;
2696  hr = ITextRange_GetEnd(range2, &value);
2697  ok(hr == S_OK, "got 0x%08x\n", hr);
2698  ok(value == 0, "got %d\n", value);
2699 
2700  str = SysAllocStringLen(NULL, 0);
2701  hr = ITextRange_SetText(range, str);
2702  ok(hr == S_OK, "got 0x%08x\n", hr);
2703  value = 1;
2704  hr = ITextRange_GetEnd(range, &value);
2705  ok(hr == S_OK, "got 0x%08x\n", hr);
2706  ok(value == 0, "got %d\n", value);
2707  SysFreeString(str);
2708 
2709  ITextRange_Release(range2);
2710  release_interfaces(&hwnd, &reOle, &doc, NULL);
2711 
2712  hr = ITextRange_SetText(range, NULL);
2713  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2714 
2715  str = SysAllocStringLen(NULL, 0);
2716  hr = ITextRange_SetText(range, str);
2717  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2718  SysFreeString(str);
2719 
2720  ITextRange_Release(range);
2721 }
2722 
2723 static void test_InRange(void)
2724 {
2725  static const CHAR test_text1[] = "TestSomeText";
2726  ITextRange *range, *range2, *range3;
2727  IRichEditOle *reOle = NULL;
2728  ITextDocument *doc = NULL;
2730  LONG value;
2731  HRESULT hr;
2732  HWND hwnd;
2733 
2734  create_interfaces(&hwnd, &reOle, &doc, &selection);
2735  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2736  SendMessageA(hwnd, EM_SETSEL, 1, 2);
2737 
2738  hr = ITextDocument_Range(doc, 0, 4, &range);
2739  ok(hr == S_OK, "got 0x%08x\n", hr);
2740 
2741  hr = ITextDocument_Range(doc, 0, 4, &range2);
2742  ok(hr == S_OK, "got 0x%08x\n", hr);
2743 
2744  /* matches selection */
2745  hr = ITextDocument_Range(doc, 1, 2, &range3);
2746  ok(hr == S_OK, "got 0x%08x\n", hr);
2747 
2748  hr = ITextRange_InRange(range, NULL, NULL);
2749  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2750 
2751  value = tomTrue;
2752  hr = ITextRange_InRange(range, NULL, &value);
2753  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2754  ok(value == tomFalse, "got %d\n", value);
2755 
2756  hr = ITextRange_InRange(range, range2, NULL);
2757  ok(hr == S_OK, "got 0x%08x\n", hr);
2758 
2759  value = tomFalse;
2760  hr = ITextRange_InRange(range, range2, &value);
2761  ok(hr == S_OK, "got 0x%08x\n", hr);
2762  ok(value == tomTrue, "got %d\n", value);
2763 
2764  /* selection */
2765  hr = ITextSelection_InRange(selection, NULL, NULL);
2766  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2767 
2768  value = tomTrue;
2769  hr = ITextSelection_InRange(selection, NULL, &value);
2770  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2771  ok(value == tomFalse, "got %d\n", value);
2772 
2773  hr = ITextSelection_InRange(selection, range2, NULL);
2774  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2775 
2776  value = tomTrue;
2777  hr = ITextSelection_InRange(selection, range2, &value);
2778  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2779  ok(value == tomFalse, "got %d\n", value);
2780 
2781  value = tomTrue;
2782  hr = ITextSelection_InRange(selection, range3, &value);
2783  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2784  ok(value == tomFalse, "got %d\n", value);
2785 
2786  /* seems to work on ITextSelection ranges only */
2787  value = tomFalse;
2788  hr = ITextSelection_InRange(selection, (ITextRange*)selection, &value);
2789  ok(hr == S_OK, "got 0x%08x\n", hr);
2790  ok(value == tomTrue, "got %d\n", value);
2791 
2792  release_interfaces(&hwnd, &reOle, &doc, NULL);
2793 
2794  hr = ITextRange_InRange(range, NULL, NULL);
2795  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2796 
2797  value = tomTrue;
2798  hr = ITextRange_InRange(range, NULL, &value);
2799  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2800  ok(value == tomFalse, "got %d\n", value);
2801 
2802  hr = ITextRange_InRange(range, range2, NULL);
2803  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2804 
2805  value = tomTrue;
2806  hr = ITextRange_InRange(range, range2, &value);
2807  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2808  ok(value == tomFalse, "got %d\n", value);
2809 
2810  /* selection */
2811  hr = ITextSelection_InRange(selection, NULL, NULL);
2812  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2813 
2814  value = tomTrue;
2815  hr = ITextSelection_InRange(selection, NULL, &value);
2816  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2817  ok(value == tomFalse, "got %d\n", value);
2818 
2819  hr = ITextSelection_InRange(selection, range2, NULL);
2820  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2821 
2822  value = tomTrue;
2823  hr = ITextSelection_InRange(selection, range2, &value);
2824  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2825  ok(value == tomFalse, "got %d\n", value);
2826 
2827  ITextRange_Release(range);
2828  ITextRange_Release(range2);
2829  ITextRange_Release(range3);
2830  ITextSelection_Release(selection);
2831 }
2832 
2833 static void test_ITextRange_IsEqual(void)
2834 {
2835  static const CHAR test_text1[] = "TestSomeText";
2836  ITextRange *range, *range2, *range3;
2837  IRichEditOle *reOle = NULL;
2838  ITextDocument *doc = NULL;
2840  LONG value;
2841  HRESULT hr;
2842  HWND hwnd;
2843 
2844  create_interfaces(&hwnd, &reOle, &doc, &selection);
2845  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2846  SendMessageA(hwnd, EM_SETSEL, 1, 2);
2847 
2848  hr = ITextDocument_Range(doc, 0, 4, &range);
2849  ok(hr == S_OK, "got 0x%08x\n", hr);
2850 
2851  hr = ITextDocument_Range(doc, 0, 4, &range2);
2852  ok(hr == S_OK, "got 0x%08x\n", hr);
2853 
2854  /* matches selection */
2855  hr = ITextDocument_Range(doc, 1, 2, &range3);
2856  ok(hr == S_OK, "got 0x%08x\n", hr);
2857 
2858  hr = ITextRange_IsEqual(range, NULL, NULL);
2859  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2860 
2861  value = tomTrue;
2862  hr = ITextRange_IsEqual(range, NULL, &value);
2863  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2864  ok(value == tomFalse, "got %d\n", value);
2865 
2866  hr = ITextRange_IsEqual(range, range2, NULL);
2867  ok(hr == S_OK, "got 0x%08x\n", hr);
2868 
2869  value = tomFalse;
2870  hr = ITextRange_IsEqual(range, range2, &value);
2871  ok(hr == S_OK, "got 0x%08x\n", hr);
2872  ok(value == tomTrue, "got %d\n", value);
2873 
2874  value = tomTrue;
2875  hr = ITextRange_IsEqual(range, range3, &value);
2876  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2877  ok(value == tomFalse, "got %d\n", value);
2878 
2879  /* selection */
2880  hr = ITextSelection_IsEqual(selection, NULL, NULL);
2881  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2882 
2883  value = tomTrue;
2884  hr = ITextSelection_IsEqual(selection, NULL, &value);
2885  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2886  ok(value == tomFalse, "got %d\n", value);
2887 
2888  hr = ITextSelection_IsEqual(selection, range2, NULL);
2889  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2890 
2891  value = tomTrue;
2892  hr = ITextSelection_IsEqual(selection, range2, &value);
2893  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2894  ok(value == tomFalse, "got %d\n", value);
2895 
2896  value = tomTrue;
2897  hr = ITextSelection_IsEqual(selection, range3, &value);
2898  ok(hr == S_FALSE, "got 0x%08x\n", hr);
2899  ok(value == tomFalse, "got %d\n", value);
2900 
2901  /* seems to work on ITextSelection ranges only */
2902  value = tomFalse;
2903  hr = ITextSelection_IsEqual(selection, (ITextRange*)selection, &value);
2904  ok(hr == S_OK, "got 0x%08x\n", hr);
2905  ok(value == tomTrue, "got %d\n", value);
2906 
2907  release_interfaces(&hwnd, &reOle, &doc, NULL);
2908 
2909  hr = ITextRange_IsEqual(range, NULL, NULL);
2910  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2911 
2912  value = tomTrue;
2913  hr = ITextRange_IsEqual(range, NULL, &value);
2914  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2915  ok(value == tomFalse, "got %d\n", value);
2916 
2917  hr = ITextRange_IsEqual(range, range2, NULL);
2918  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2919 
2920  value = tomTrue;
2921  hr = ITextRange_IsEqual(range, range2, &value);
2922  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2923  ok(value == tomFalse, "got %d\n", value);
2924 
2925  /* selection */
2926  hr = ITextSelection_IsEqual(selection, NULL, NULL);
2927  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2928 
2929  value = tomTrue;
2930  hr = ITextSelection_IsEqual(selection, NULL, &value);
2931  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2932  ok(value == tomFalse, "got %d\n", value);
2933 
2934  hr = ITextSelection_IsEqual(selection, range2, NULL);
2935  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2936 
2937  value = tomTrue;
2938  hr = ITextSelection_IsEqual(selection, range2, &value);
2939  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2940  ok(value == tomFalse, "got %d\n", value);
2941 
2942  ITextRange_Release(range);
2943  ITextRange_Release(range2);
2944  ITextRange_Release(range3);
2945  ITextSelection_Release(selection);
2946 }
2947 
2948 static void test_Select(void)
2949 {
2950  static const CHAR test_text1[] = "TestSomeText";
2951  IRichEditOle *reOle = NULL;
2952  ITextDocument *doc = NULL;
2954  ITextRange *range;
2955  LONG value;
2956  HRESULT hr;
2957  HWND hwnd;
2958 
2959  create_interfaces(&hwnd, &reOle, &doc, &selection);
2960  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
2961  SendMessageA(hwnd, EM_SETSEL, 1, 2);
2962 
2963  hr = ITextDocument_Range(doc, 0, 4, &range);
2964  ok(hr == S_OK, "got 0x%08x\n", hr);
2965 
2966  hr = ITextRange_Select(range);
2967  ok(hr == S_OK, "got 0x%08x\n", hr);
2968 
2969  value = 1;
2970  hr = ITextSelection_GetStart(selection, &value);
2971  ok(hr == S_OK, "got 0x%08x\n", hr);
2972  ok(value == 0, "got %d\n", value);
2973 
2974  hr = ITextRange_Select(range);
2975  ok(hr == S_OK, "got 0x%08x\n", hr);
2976 
2977  hr = ITextSelection_Select(selection);
2978  ok(hr == S_OK, "got 0x%08x\n", hr);
2979 
2980  release_interfaces(&hwnd, &reOle, &doc, NULL);
2981 
2982  hr = ITextRange_Select(range);
2983  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2984 
2985  hr = ITextSelection_Select(selection);
2986  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
2987 
2988  ITextRange_Release(range);
2989  ITextSelection_Release(selection);
2990 }
2991 
2992 static void test_GetStoryType(void)
2993 {
2994  static const CHAR test_text1[] = "TestSomeText";
2995  IRichEditOle *reOle = NULL;
2996  ITextDocument *doc = NULL;
2998  ITextRange *range;
2999  LONG value;
3000  HRESULT hr;
3001  HWND hwnd;
3002 
3003  create_interfaces(&hwnd, &reOle, &doc, &selection);
3004  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3005  SendMessageA(hwnd, EM_SETSEL, 1, 2);
3006 
3007  hr = ITextDocument_Range(doc, 0, 4, &range);
3008  ok(hr == S_OK, "got 0x%08x\n", hr);
3009 
3010  hr = ITextRange_GetStoryType(range, NULL);
3011  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3012 
3014  hr = ITextRange_GetStoryType(range, &value);
3015  ok(hr == S_OK, "got 0x%08x\n", hr);
3016  ok(value == tomUnknownStory, "got %d\n", value);
3017 
3018  hr = ITextSelection_GetStoryType(selection, NULL);
3019  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3020 
3022  hr = ITextSelection_GetStoryType(selection, &value);
3023  ok(hr == S_OK, "got 0x%08x\n", hr);
3024  ok(value == tomUnknownStory, "got %d\n", value);
3025 
3026  release_interfaces(&hwnd, &reOle, &doc, NULL);
3027 
3028  hr = ITextRange_GetStoryType(range, NULL);
3029  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3030 
3031  value = 123;
3032  hr = ITextRange_GetStoryType(range, &value);
3033  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3034  ok(value == 123, "got %d\n", value);
3035 
3036  hr = ITextSelection_GetStoryType(selection, NULL);
3037  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3038 
3039  value = 123;
3040  hr = ITextSelection_GetStoryType(selection, &value);
3041  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3042  ok(value == 123, "got %d\n", value);
3043 
3044  ITextRange_Release(range);
3045  ITextSelection_Release(selection);
3046 }
3047 
3048 static void test_SetFont(void)
3049 {
3050  static const CHAR test_text1[] = "TestSomeText";
3051  IRichEditOle *reOle = NULL;
3052  ITextDocument *doc = NULL;
3054  ITextRange *range, *range2;
3055  ITextFont *font, *font2;
3056  LONG value;
3057  HRESULT hr;
3058  HWND hwnd;
3059 
3060  create_interfaces(&hwnd, &reOle, &doc, &selection);
3061  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3062  SendMessageA(hwnd, EM_SETSEL, 1, 2);
3063 
3064  hr = ITextDocument_Range(doc, 0, 4, &range);
3065  ok(hr == S_OK, "got 0x%08x\n", hr);
3066 
3067  hr = ITextDocument_Range(doc, 5, 2, &range2);
3068  ok(hr == S_OK, "got 0x%08x\n", hr);
3069 
3070  EXPECT_REF(range, 1);
3071  hr = ITextRange_GetFont(range, &font);
3072  ok(hr == S_OK, "got 0x%08x\n", hr);
3073  EXPECT_REF(range, 2);
3074 
3075  EXPECT_REF(range2, 1);
3076  hr = ITextRange_GetFont(range2, &font2);
3077  ok(hr == S_OK, "got 0x%08x\n", hr);
3078  EXPECT_REF(range2, 2);
3079 
3080  hr = ITextRange_SetFont(range, NULL);
3081  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3082 
3083  /* setting same font, no-op */
3084  EXPECT_REF(range, 2);
3085  hr = ITextRange_SetFont(range, font);
3086  ok(hr == S_OK, "got 0x%08x\n", hr);
3087  EXPECT_REF(range, 2);
3088 
3089  EXPECT_REF(range2, 2);
3090  EXPECT_REF(range, 2);
3091  hr = ITextRange_SetFont(range, font2);
3092  ok(hr == S_OK, "got 0x%08x\n", hr);
3093  EXPECT_REF(range2, 2);
3094  EXPECT_REF(range, 2);
3095 
3096  /* originally range 0-4 is non-italic */
3097  value = tomTrue;
3098  hr = ITextFont_GetItalic(font, &value);
3099  ok(hr == S_OK, "got 0x%08x\n", hr);
3100  ok(value == tomFalse, "got %d\n", value);
3101 
3102  /* set range 5-2 to italic, then set this font to range 0-4 */
3103  hr = ITextFont_SetItalic(font2, tomTrue);
3104  ok(hr == S_OK, "got 0x%08x\n", hr);
3105 
3106  hr = ITextRange_SetFont(range, font2);
3107  ok(hr == S_OK, "got 0x%08x\n", hr);
3108 
3109  value = tomFalse;
3110  hr = ITextFont_GetItalic(font, &value);
3111  ok(hr == S_OK, "got 0x%08x\n", hr);
3112  ok(value == tomTrue, "got %d\n", value);
3113 
3114  release_interfaces(&hwnd, &reOle, &doc, NULL);
3115 
3116  hr = ITextRange_SetFont(range, NULL);
3117  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3118 
3119  hr = ITextRange_SetFont(range, font);
3120  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3121 
3122  hr = ITextSelection_SetFont(selection, NULL);
3123  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3124 
3125  hr = ITextSelection_SetFont(selection, font);
3126  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3127 
3128  ITextFont_Release(font);
3129  ITextFont_Release(font2);
3130  ITextRange_Release(range);
3131  ITextRange_Release(range2);
3132  ITextSelection_Release(selection);
3133 }
3134 
3135 static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj,
3136  LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx,
3137  LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user)
3138 {
3139  reobj->cbStruct = sizeof(*reobj);
3140  reobj->clsid = CLSID_NULL;
3141  reobj->cp = cp;
3142  reobj->poleobj = poleobj;
3143  reobj->pstg = pstg;
3144  reobj->polesite = polesite;
3145  reobj->sizel.cx = sizel_cx;
3146  reobj->sizel.cy = sizel_cy;
3147  reobj->dvaspect = aspect;
3148  reobj->dwFlags = flags;
3149  reobj->dwUser = user;
3150 }
3151 
3152 #define CHECK_REOBJECT_STRUCT(reobj,poleobj,pstg,polesite,user) \
3153  _check_reobject_struct(reobj, poleobj, pstg, polesite, user, __LINE__)
3154 static void _check_reobject_struct(REOBJECT reobj, LPOLEOBJECT poleobj, LPSTORAGE pstg,
3155  LPOLECLIENTSITE polesite, DWORD user, int line)
3156 {
3157  ok_(__FILE__,line)(reobj.poleobj == poleobj, "got wrong object interface.\n");
3158  ok_(__FILE__,line)(reobj.pstg == pstg, "got wrong storage interface.\n");
3159  ok_(__FILE__,line)(reobj.polesite == polesite, "got wrong site interface.\n");
3160  ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n");
3161 }
3162 
3163 static void test_InsertObject(void)
3164 {
3165  static CHAR test_text1[] = "abcdefg";
3166  IRichEditOle *reole = NULL;
3167  ITextDocument *doc = NULL;
3168  IOleClientSite *clientsite;
3169  REOBJECT reo1, reo2, reo3, received_reo1, received_reo2, received_reo3, received_reo4;
3170  HRESULT hr;
3171  HWND hwnd;
3172  LONG count;
3173 
3174  create_interfaces(&hwnd, &reole, &doc, NULL);
3175  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3176 
3177  hr = IRichEditOle_InsertObject(reole, NULL);
3178  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3179 
3180  /* insert object1 in (0, 1)*/
3181  SendMessageA(hwnd, EM_SETSEL, 0, 1);
3182  hr = IRichEditOle_GetClientSite(reole, &clientsite);
3183  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3184  fill_reobject_struct(&reo1, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 1);
3185  hr = IRichEditOle_InsertObject(reole, &reo1);
3186  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3187  count = IRichEditOle_GetObjectCount(reole);
3188  ok(count == 1, "got wrong object count: %d\n", count);
3189  IOleClientSite_Release(clientsite);
3190 
3191  /* insert object2 in (2, 3)*/
3192  SendMessageA(hwnd, EM_SETSEL, 2, 3);
3193  hr = IRichEditOle_GetClientSite(reole, &clientsite);
3194  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3195  fill_reobject_struct(&reo2, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 2);
3196  hr = IRichEditOle_InsertObject(reole, &reo2);
3197  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3198  count = IRichEditOle_GetObjectCount(reole);
3199  ok(count == 2, "got wrong object count: %d\n", count);
3200  IOleClientSite_Release(clientsite);
3201 
3202  /* insert object3 in (1, 2)*/
3203  SendMessageA(hwnd, EM_SETSEL, 1, 2);
3204  hr = IRichEditOle_GetClientSite(reole, &clientsite);
3205  ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr);
3206  fill_reobject_struct(&reo3, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 3);
3207  hr = IRichEditOle_InsertObject(reole, &reo3);
3208  ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr);
3209  count = IRichEditOle_GetObjectCount(reole);
3210  ok(count == 3, "got wrong object count: %d\n", count);
3211  IOleClientSite_Release(clientsite);
3212 
3213  /* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */
3214  received_reo1.cbStruct = sizeof(received_reo1);
3215  hr = IRichEditOle_GetObject(reole, 0, &received_reo1, REO_GETOBJ_ALL_INTERFACES);
3216  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3217  CHECK_REOBJECT_STRUCT(received_reo1, NULL, NULL, reo1.polesite, 1);
3218 
3219  received_reo2.cbStruct = sizeof(received_reo2);
3220  hr = IRichEditOle_GetObject(reole, 1, &received_reo2, REO_GETOBJ_ALL_INTERFACES);
3221  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3222  CHECK_REOBJECT_STRUCT(received_reo2, NULL, NULL, reo3.polesite, 3);
3223 
3224  received_reo3.cbStruct = sizeof(received_reo3);
3225  hr = IRichEditOle_GetObject(reole, 2, &received_reo3, REO_GETOBJ_ALL_INTERFACES);
3226  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3227  CHECK_REOBJECT_STRUCT(received_reo3, NULL, NULL, reo2.polesite, 2);
3228 
3229  hr = IRichEditOle_GetObject(reole, 2, NULL, REO_GETOBJ_ALL_INTERFACES);
3230  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3231 
3232  received_reo4.cbStruct = 0;
3233  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3234  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3235 
3236  received_reo4.cbStruct = sizeof(received_reo4);
3237  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_PSTG);
3238  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3239  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2);
3240 
3241  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_POLESITE);
3242  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3243  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
3244 
3245  hr = IRichEditOle_GetObject(reole, 4, &received_reo4, REO_GETOBJ_POLESITE);
3246  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3247 
3248  hr = IRichEditOle_GetObject(reole, 1024, &received_reo4, REO_GETOBJ_POLESITE);
3249  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3250 
3251  /* received_reo4 will be zeroed before be used */
3252  hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_NO_INTERFACES);
3253  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3254  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2);
3255 
3256  received_reo4.cbStruct = sizeof(received_reo4);
3257  received_reo4.cp = 0;
3258  hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3259  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3260  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1);
3261 
3262  received_reo4.cbStruct = sizeof(received_reo4);
3263  received_reo4.cp = 1;
3264  hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3265  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3266  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3);
3267 
3268  received_reo4.cbStruct = sizeof(received_reo4);
3269  received_reo4.cp = 2;
3270  hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3271  ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr);
3272  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
3273 
3274  received_reo4.cbStruct = sizeof(received_reo4);
3275  received_reo4.cp = 4;
3276  hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES);
3277  ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr);
3278  /* received_reo4 didn't be zeroed in E_INVALIDARG case */
3279  CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2);
3280 
3281  release_interfaces(&hwnd, &reole, &doc, NULL);
3282 }
3283 
3284 static void test_GetStoryLength(void)
3285 {
3286  static const CHAR test_text1[] = "TestSomeText";
3287  IRichEditOle *reOle = NULL;
3288  ITextDocument *doc = NULL;
3290  ITextRange *range;
3291  LONG value;
3292  HRESULT hr;
3293  HWND hwnd;
3294 
3295  create_interfaces(&hwnd, &reOle, &doc, &selection);
3296  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
3297  SendMessageA(hwnd, EM_SETSEL, 1, 2);
3298 
3299  hr = ITextDocument_Range(doc, 0, 4, &range);
3300  ok(hr == S_OK, "got 0x%08x\n", hr);
3301 
3302  hr = ITextRange_GetStoryLength(range, NULL);
3303  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3304 
3305  value = 0;
3306  hr = ITextRange_GetStoryLength(range, &value);
3307  ok(hr == S_OK, "got 0x%08x\n", hr);
3308  ok(value == 13, "got %d\n", value);
3309 
3310  hr = ITextSelection_GetStoryLength(selection, NULL);
3311  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3312 
3313  value = 0;
3314  hr = ITextSelection_GetStoryLength(selection, &value);
3315  ok(hr == S_OK, "got 0x%08x\n", hr);
3316  ok(value == 13, "got %d\n", value);
3317 
3318  SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
3319 
3320  value = 0;
3321  hr = ITextRange_GetStoryLength(range, &value);
3322  ok(hr == S_OK, "got 0x%08x\n", hr);
3323  ok(value == 1, "got %d\n", value);
3324 
3325  value = 0;
3326  hr = ITextSelection_GetStoryLength(selection, &value);
3327  ok(hr == S_OK, "got 0x%08x\n", hr);
3328  ok(value == 1, "got %d\n", value);
3329 
3330  release_interfaces(&hwnd, &reOle, &doc, NULL);
3331 
3332  hr = ITextRange_GetStoryLength(range, NULL);
3333  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3334 
3335  value = 100;
3336  hr = ITextRange_GetStoryLength(range, &value);
3337  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3338  ok(value == 100, "got %d\n", value);
3339 
3340  hr = ITextSelection_GetStoryLength(selection, NULL);
3341  ok(hr == CO_E_RELEASED, "got 0x%08x\n", hr);
3342 
3343  value = 100;
3344  hr = ITextSelection_GetStoryLength(selection, &value);
3345  ok(