2 * Tests for IRichEditOle and friends.
4 * Copyright 2008 Google (Dan Hipschman)
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.
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.
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
34 #include <wine/test.h>
36 static HMODULE hmoduleRichEdit
;
38 static HWND
new_window(LPCSTR lpClassName
, DWORD dwStyle
, HWND parent
)
40 HWND hwnd
= CreateWindowA(lpClassName
, NULL
,
41 dwStyle
| WS_POPUP
| WS_HSCROLL
| WS_VSCROLL
| WS_VISIBLE
,
42 0, 0, 200, 60, parent
, NULL
, hmoduleRichEdit
, NULL
);
46 static HWND
new_richedit(HWND parent
)
48 return new_window(RICHEDIT_CLASS20A
, ES_MULTILINE
, parent
);
51 static BOOL
touch_file(LPCWSTR filename
)
55 file
= CreateFileW(filename
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
56 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
58 if(file
== INVALID_HANDLE_VALUE
)
64 static BOOL
is_existing_file(LPCWSTR filename
)
68 file
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
,
69 OPEN_EXISTING
, 0, NULL
);
70 if(file
== INVALID_HANDLE_VALUE
)
76 static void create_interfaces(HWND
*w
, IRichEditOle
**reOle
, ITextDocument
**txtDoc
,
77 ITextSelection
**txtSel
)
79 *w
= new_richedit(NULL
);
80 SendMessageA(*w
, EM_GETOLEINTERFACE
, 0, (LPARAM
)reOle
);
81 IRichEditOle_QueryInterface(*reOle
, &IID_ITextDocument
,
83 ITextDocument_GetSelection(*txtDoc
, txtSel
);
86 static void release_interfaces(HWND
*w
, IRichEditOle
**reOle
, ITextDocument
**txtDoc
,
87 ITextSelection
**txtSel
)
89 ITextDocument_Release(*txtDoc
);
90 IRichEditOle_Release(*reOle
);
92 ITextSelection_Release(*txtSel
);
95 static void test_Interfaces(void)
97 IRichEditOle
*reOle
= NULL
;
98 ITextDocument
*txtDoc
= NULL
;
99 ITextSelection
*txtSel
= NULL
;
105 w
= new_richedit(NULL
);
107 skip("Couldn't create window\n");
111 res
= SendMessageA(w
, EM_GETOLEINTERFACE
, 0, (LPARAM
)&reOle
);
112 ok(res
, "SendMessage\n");
113 ok(reOle
!= NULL
, "EM_GETOLEINTERFACE\n");
115 hres
= IRichEditOle_QueryInterface(reOle
, &IID_ITextDocument
,
117 ok(hres
== S_OK
, "IRichEditOle_QueryInterface\n");
118 ok(txtDoc
!= NULL
, "IRichEditOle_QueryInterface\n");
120 ITextDocument_GetSelection(txtDoc
, &txtSel
);
123 hres
= ITextSelection_QueryInterface(txtSel
, &IID_ITextSelection
, (void **) &punk
);
124 ok(hres
== S_OK
, "ITextSelection_QueryInterface\n");
125 ok(punk
!= NULL
, "ITextSelection_QueryInterface\n");
126 IUnknown_Release(punk
);
129 hres
= ITextSelection_QueryInterface(txtSel
, &IID_ITextRange
, (void **) &punk
);
130 ok(hres
== S_OK
, "ITextSelection_QueryInterface\n");
131 ok(punk
!= NULL
, "ITextSelection_QueryInterface\n");
132 IUnknown_Release(punk
);
135 hres
= ITextSelection_QueryInterface(txtSel
, &IID_IDispatch
, (void **) &punk
);
136 ok(hres
== S_OK
, "ITextSelection_QueryInterface\n");
137 ok(punk
!= NULL
, "ITextSelection_QueryInterface\n");
138 IUnknown_Release(punk
);
140 ITextDocument_Release(txtDoc
);
141 IRichEditOle_Release(reOle
);
144 /* Methods should return CO_E_RELEASED if the backing document has
145 been released. One test should suffice. */
146 hres
= ITextSelection_CanEdit(txtSel
, NULL
);
147 ok(hres
== CO_E_RELEASED
, "ITextSelection after ITextDocument destroyed\n");
149 ITextSelection_Release(txtSel
);
152 static void test_ITextDocument_Open(void)
154 IRichEditOle
*reOle
= NULL
;
155 ITextDocument
*txtDoc
= NULL
;
156 ITextSelection
*txtSel
= NULL
;
161 WCHAR filename
[] = {'t', 'e', 's', 't','.','t','x','t', 0};
164 static const CHAR chACP
[] = "TestSomeText";
165 static const CHAR chUTF8
[] = "\xef\xbb\xbfTextWithUTF8BOM";
166 static const WCHAR chUTF16
[] = {0xfeff, 'T', 'e', 's', 't', 'S', 'o', 'm',
167 'e', 'T', 'e', 'x', 't', 0};
169 #define MAX_BUF_LEN 1024
170 CHAR bufACP
[MAX_BUF_LEN
];
171 WCHAR bufUnicode
[MAX_BUF_LEN
];
173 static const int tomConstantsSingle
[] =
175 tomReadOnly
, tomShareDenyRead
, tomShareDenyWrite
,
176 tomCreateAlways
, tomOpenExisting
, tomOpenAlways
,
177 tomTruncateExisting
, tomRTF
, tomText
180 static const int tomConstantsMulti
[] =
182 tomReadOnly
|tomShareDenyRead
|tomPasteFile
, tomReadOnly
|tomPasteFile
,
183 tomReadOnly
|tomShareDenyWrite
|tomPasteFile
,
184 tomReadOnly
|tomShareDenyRead
|tomShareDenyWrite
|tomPasteFile
, tomShareDenyWrite
|tomPasteFile
,
185 tomShareDenyRead
|tomShareDenyWrite
|tomPasteFile
, tomShareDenyRead
|tomPasteFile
,
186 tomShareDenyRead
|tomShareDenyWrite
, tomReadOnly
|tomShareDenyRead
|tomShareDenyWrite
,
187 tomReadOnly
|tomShareDenyWrite
, tomReadOnly
|tomShareDenyRead
190 int tomNumSingle
= sizeof(tomConstantsSingle
)/sizeof(tomConstantsSingle
[0]);
191 int tomNumMulti
= sizeof(tomConstantsMulti
)/sizeof(tomConstantsMulti
[0]);
194 V_VT(&testfile
) = VT_BSTR
;
195 V_BSTR(&testfile
) = SysAllocString(filename
);
197 for(i
=0; i
< tomNumSingle
; i
++)
199 touch_file(filename
);
200 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
201 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomConstantsSingle
[i
], CP_ACP
);
202 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
203 tomConstantsSingle
[i
], hres
);
204 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
205 DeleteFileW(filename
);
207 touch_file(filename
);
208 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
209 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomConstantsSingle
[i
], CP_UTF8
);
210 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
211 tomConstantsSingle
[i
], hres
);
212 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
213 DeleteFileW(filename
);
216 for(i
=0; i
< tomNumMulti
; i
++)
218 touch_file(filename
);
219 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
220 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomConstantsMulti
[i
], CP_ACP
);
221 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_ACP hres:0x%x\n",
222 tomConstantsMulti
[i
], hres
);
223 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
224 DeleteFileW(filename
);
226 touch_file(filename
);
227 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
228 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomConstantsMulti
[i
], CP_UTF8
);
229 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open: Filename:test.txt Flags:0x%x Codepage:CP_UTF8 hres:0x%x\n",
230 tomConstantsMulti
[i
], hres
);
231 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
232 DeleteFileW(filename
);
235 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
236 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateAlways
, CP_ACP
);
237 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_ACP\n");
238 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
239 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
240 DeleteFileW(filename
);
242 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
243 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateAlways
, CP_UTF8
);
244 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_UTF8\n");
245 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
246 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
247 DeleteFileW(filename
);
249 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
250 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomOpenAlways
, CP_ACP
);
251 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_ACP\n");
252 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
253 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
254 DeleteFileW(filename
);
256 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
257 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomOpenAlways
, CP_UTF8
);
258 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_UTF8\n");
259 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
260 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
261 DeleteFileW(filename
);
263 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
264 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateNew
, CP_ACP
);
265 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_ACP\n");
266 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
267 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
268 DeleteFileW(filename
);
270 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
271 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateNew
, CP_UTF8
);
272 todo_wine
ok(hres
== S_OK
, "ITextDocument_Open should success Codepage:CP_UTF8\n");
273 todo_wine
ok(is_existing_file(filename
), "ITextDocument_Open should create a file\n");
274 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
275 DeleteFileW(filename
);
277 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
278 touch_file(filename
);
279 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateNew
, CP_ACP
);
280 todo_wine
ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "ITextDocument_Open should fail Codepage:CP_ACP\n");
281 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
282 DeleteFileW(filename
);
284 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
285 touch_file(filename
);
286 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomCreateNew
, CP_UTF8
);
287 todo_wine
ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
288 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
289 DeleteFileW(filename
);
291 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
292 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomOpenExisting
, CP_ACP
);
293 todo_wine
ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "ITextDocument_Open should fail Codepage:CP_ACP\n");
294 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
296 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
297 hres
= ITextDocument_Open(txtDoc
, &testfile
, tomOpenExisting
, CP_UTF8
);
298 todo_wine
ok(hres
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "ITextDocument_Open should fail Codepage:CP_UTF8\n");
299 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
301 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
302 DeleteFileW(filename
);
303 ITextDocument_Open(txtDoc
, &testfile
, tomText
, CP_ACP
);
304 todo_wine
ok(is_existing_file(filename
) == TRUE
, "a file should be created default\n");
305 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
306 DeleteFileW(filename
);
308 /* test of share mode */
309 touch_file(filename
);
310 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
311 ITextDocument_Open(txtDoc
, &testfile
, tomShareDenyRead
, CP_ACP
);
312 SetLastError(0xdeadbeef);
313 hFile
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
,
314 FILE_ATTRIBUTE_NORMAL
, NULL
);
315 todo_wine
ok(GetLastError() == ERROR_SHARING_VIOLATION
, "ITextDocument_Open should fail\n");
317 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
318 DeleteFileW(filename
);
320 touch_file(filename
);
321 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
322 ITextDocument_Open(txtDoc
, &testfile
, tomShareDenyWrite
, CP_ACP
);
323 SetLastError(0xdeadbeef);
324 hFile
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
,
325 FILE_ATTRIBUTE_NORMAL
, NULL
);
326 todo_wine
ok(GetLastError() == ERROR_SHARING_VIOLATION
, "ITextDocument_Open should fail\n");
328 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
329 DeleteFileW(filename
);
331 touch_file(filename
);
332 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
333 SetLastError(0xdeadbeef);
334 ITextDocument_Open(txtDoc
, &testfile
, tomShareDenyWrite
|tomShareDenyRead
, CP_ACP
);
335 hFile
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
,
336 FILE_ATTRIBUTE_NORMAL
, NULL
);
337 todo_wine
ok(GetLastError() == ERROR_SHARING_VIOLATION
, "ITextDocument_Open should fail\n");
339 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
340 DeleteFileW(filename
);
342 /* tests to check the content */
343 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
,
344 FILE_ATTRIBUTE_NORMAL
, NULL
);
345 WriteFile(hFile
, chACP
, sizeof(chACP
)-sizeof(CHAR
), &dw
, NULL
);
347 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
348 ITextDocument_Open(txtDoc
, &testfile
, tomReadOnly
, CP_ACP
);
349 result
= SendMessageA(w
, WM_GETTEXT
, 1024, (LPARAM
)bufACP
);
350 todo_wine
ok(result
== 12, "ITextDocument_Open: Test ASCII returned %d, expected 12\n", result
);
351 result
= strcmp(bufACP
, chACP
);
352 todo_wine
ok(result
== 0, "ITextDocument_Open: Test ASCII set wrong text: Result: %s\n", bufACP
);
353 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
354 DeleteFileW(filename
);
356 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
,
357 FILE_ATTRIBUTE_NORMAL
, NULL
);
358 WriteFile(hFile
, chUTF8
, sizeof(chUTF8
)-sizeof(CHAR
), &dw
, NULL
);
360 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
361 ITextDocument_Open(txtDoc
, &testfile
, tomReadOnly
, CP_UTF8
);
362 result
= SendMessageA(w
, WM_GETTEXT
, 1024, (LPARAM
)bufACP
);
363 todo_wine
ok(result
== 15, "ITextDocument_Open: Test UTF-8 returned %d, expected 15\n", result
);
364 result
= strcmp(bufACP
, &chUTF8
[3]);
365 todo_wine
ok(result
== 0, "ITextDocument_Open: Test UTF-8 set wrong text: Result: %s\n", bufACP
);
366 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
367 DeleteFileW(filename
);
369 hFile
= CreateFileW(filename
, GENERIC_WRITE
, FILE_SHARE_READ
, NULL
, CREATE_ALWAYS
,
370 FILE_ATTRIBUTE_NORMAL
, NULL
);
371 WriteFile(hFile
, chUTF16
, sizeof(chUTF16
)-sizeof(WCHAR
), &dw
, NULL
);
373 create_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
374 ITextDocument_Open(txtDoc
, &testfile
, tomReadOnly
, 1200);
375 result
= SendMessageW(w
, WM_GETTEXT
, 1024, (LPARAM
)bufUnicode
);
376 todo_wine
ok(result
== 12, "ITextDocument_Open: Test UTF-16 returned %d, expected 12\n", result
);
377 result
= lstrcmpW(bufUnicode
, &chUTF16
[1]);
378 todo_wine
ok(result
== 0, "ITextDocument_Open: Test UTF-16 set wrong text: Result: %s\n", wine_dbgstr_w(bufUnicode
));
379 release_interfaces(&w
, &reOle
, &txtDoc
, &txtSel
);
380 DeleteFileW(filename
);
382 VariantClear(&testfile
);
387 /* Must explicitly LoadLibrary(). The test has no references to functions in
388 * RICHED20.DLL, so the linker doesn't actually link to it. */
389 hmoduleRichEdit
= LoadLibraryA("riched20.dll");
390 ok(hmoduleRichEdit
!= NULL
, "error: %d\n", (int) GetLastError());
393 test_ITextDocument_Open();