scrrun: Implement Count() property for file collection.
[wine/multimedia.git] / dlls / scrrun / tests / filesystem.c
blob531b73276d721467ad1e500b1ab1fb7cb0e49180
1 /*
3 * Copyright 2012 Alistair Leslie-Hughes
4 * Copyright 2014 Dmitry Timoshkov
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
21 #define COBJMACROS
22 #include <stdio.h>
24 #include "windows.h"
25 #include "ole2.h"
26 #include "olectl.h"
27 #include "oleauto.h"
28 #include "dispex.h"
30 #include "wine/test.h"
32 #include "initguid.h"
33 #include "scrrun.h"
35 static IFileSystem3 *fs3;
37 static inline ULONG get_refcount(IUnknown *iface)
39 IUnknown_AddRef(iface);
40 return IUnknown_Release(iface);
43 static const WCHAR crlfW[] = {'\r','\n',0};
44 static const char utf16bom[] = {0xff,0xfe,0};
46 #define GET_REFCOUNT(iface) \
47 get_refcount((IUnknown*)iface)
49 static inline void get_temp_path(const WCHAR *prefix, WCHAR *path)
51 WCHAR buffW[MAX_PATH];
53 GetTempPathW(MAX_PATH, buffW);
54 GetTempFileNameW(buffW, prefix, 0, path);
55 DeleteFileW(path);
58 static void test_interfaces(void)
60 static const WCHAR nonexistent_dirW[] = {
61 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', 0};
62 static const WCHAR pathW[] = {'p','a','t','h',0};
63 static const WCHAR file_kernel32W[] = {
64 '\\', 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
65 HRESULT hr;
66 IDispatch *disp;
67 IDispatchEx *dispex;
68 IObjectWithSite *site;
69 VARIANT_BOOL b;
70 BSTR path;
71 WCHAR windows_path[MAX_PATH];
72 WCHAR file_path[MAX_PATH];
74 IFileSystem3_QueryInterface(fs3, &IID_IDispatch, (void**)&disp);
76 GetSystemDirectoryW(windows_path, MAX_PATH);
77 lstrcpyW(file_path, windows_path);
78 lstrcatW(file_path, file_kernel32W);
80 hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site);
81 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
83 hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
84 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
86 b = VARIANT_TRUE;
87 hr = IFileSystem3_FileExists(fs3, NULL, &b);
88 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
89 ok(b == VARIANT_FALSE, "got %x\n", b);
91 hr = IFileSystem3_FileExists(fs3, NULL, NULL);
92 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
94 path = SysAllocString(pathW);
95 b = VARIANT_TRUE;
96 hr = IFileSystem3_FileExists(fs3, path, &b);
97 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
98 ok(b == VARIANT_FALSE, "got %x\n", b);
99 SysFreeString(path);
101 path = SysAllocString(file_path);
102 b = VARIANT_FALSE;
103 hr = IFileSystem3_FileExists(fs3, path, &b);
104 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
105 ok(b == VARIANT_TRUE, "got %x\n", b);
106 SysFreeString(path);
108 path = SysAllocString(windows_path);
109 b = VARIANT_TRUE;
110 hr = IFileSystem3_FileExists(fs3, path, &b);
111 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
112 ok(b == VARIANT_FALSE, "got %x\n", b);
113 SysFreeString(path);
115 /* Folder Exists */
116 hr = IFileSystem3_FolderExists(fs3, NULL, NULL);
117 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
119 path = SysAllocString(windows_path);
120 hr = IFileSystem3_FolderExists(fs3, path, &b);
121 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
122 ok(b == VARIANT_TRUE, "Folder doesn't exists\n");
123 SysFreeString(path);
125 path = SysAllocString(nonexistent_dirW);
126 hr = IFileSystem3_FolderExists(fs3, path, &b);
127 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
128 ok(b == VARIANT_FALSE, "Folder exists\n");
129 SysFreeString(path);
131 path = SysAllocString(file_path);
132 hr = IFileSystem3_FolderExists(fs3, path, &b);
133 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
134 ok(b == VARIANT_FALSE, "Folder exists\n");
135 SysFreeString(path);
137 IDispatch_Release(disp);
140 static void test_createfolder(void)
142 WCHAR buffW[MAX_PATH];
143 HRESULT hr;
144 BSTR path;
145 IFolder *folder;
146 BOOL ret;
148 get_temp_path(NULL, buffW);
149 ret = CreateDirectoryW(buffW, NULL);
150 ok(ret, "got %d, %d\n", ret, GetLastError());
152 /* create existing directory */
153 path = SysAllocString(buffW);
154 folder = (void*)0xdeabeef;
155 hr = IFileSystem3_CreateFolder(fs3, path, &folder);
156 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
157 ok(folder == NULL, "got %p\n", folder);
158 SysFreeString(path);
159 RemoveDirectoryW(buffW);
162 static void test_textstream(void)
164 static const WCHAR testfileW[] = {'t','e','s','t','f','i','l','e','.','t','x','t',0};
165 ITextStream *stream;
166 VARIANT_BOOL b;
167 DWORD written;
168 HANDLE file;
169 HRESULT hr;
170 BSTR name, data;
171 BOOL ret;
173 file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
174 CloseHandle(file);
176 name = SysAllocString(testfileW);
177 b = VARIANT_FALSE;
178 hr = IFileSystem3_FileExists(fs3, name, &b);
179 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
180 ok(b == VARIANT_TRUE, "got %x\n", b);
182 /* different mode combinations */
183 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
184 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
186 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
187 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
189 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForReading, VARIANT_FALSE, TristateFalse, &stream);
190 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
192 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
193 ok(hr == S_OK, "got 0x%08x\n", hr);
194 hr = ITextStream_Read(stream, 1, &data);
195 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
196 ITextStream_Release(stream);
198 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
199 ok(hr == S_OK, "got 0x%08x\n", hr);
200 hr = ITextStream_Read(stream, 1, &data);
201 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
202 ITextStream_Release(stream);
204 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
205 ok(hr == S_OK, "got 0x%08x\n", hr);
207 /* try to write when open for reading */
208 hr = ITextStream_WriteLine(stream, name);
209 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
211 hr = ITextStream_Write(stream, name);
212 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
214 hr = ITextStream_get_AtEndOfStream(stream, NULL);
215 ok(hr == E_POINTER, "got 0x%08x\n", hr);
217 b = 10;
218 hr = ITextStream_get_AtEndOfStream(stream, &b);
219 ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr);
220 ok(b == VARIANT_TRUE, "got 0x%x\n", b);
222 ITextStream_Release(stream);
224 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
225 ok(hr == S_OK, "got 0x%08x\n", hr);
227 b = 10;
228 hr = ITextStream_get_AtEndOfStream(stream, &b);
229 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
230 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
232 b = 10;
233 hr = ITextStream_get_AtEndOfLine(stream, &b);
234 todo_wine {
235 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
236 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
238 hr = ITextStream_Read(stream, 1, &data);
239 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
241 hr = ITextStream_ReadLine(stream, &data);
242 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
244 hr = ITextStream_ReadAll(stream, &data);
245 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
247 ITextStream_Release(stream);
249 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
250 ok(hr == S_OK, "got 0x%08x\n", hr);
252 b = 10;
253 hr = ITextStream_get_AtEndOfStream(stream, &b);
254 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
255 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
257 b = 10;
258 hr = ITextStream_get_AtEndOfLine(stream, &b);
259 todo_wine {
260 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
261 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
263 hr = ITextStream_Read(stream, 1, &data);
264 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
266 hr = ITextStream_ReadLine(stream, &data);
267 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
269 hr = ITextStream_ReadAll(stream, &data);
270 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
272 ITextStream_Release(stream);
274 /* now with non-empty file */
275 file = CreateFileW(testfileW, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
276 ret = WriteFile(file, testfileW, sizeof(testfileW), &written, NULL);
277 ok(ret && written == sizeof(testfileW), "got %d\n", ret);
278 CloseHandle(file);
280 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
281 ok(hr == S_OK, "got 0x%08x\n", hr);
282 b = 10;
283 hr = ITextStream_get_AtEndOfStream(stream, &b);
284 ok(hr == S_OK, "got 0x%08x\n", hr);
285 ok(b == VARIANT_FALSE, "got 0x%x\n", b);
286 ITextStream_Release(stream);
288 SysFreeString(name);
289 DeleteFileW(testfileW);
292 static void test_GetFileVersion(void)
294 static const WCHAR k32W[] = {'\\','k','e','r','n','e','l','3','2','.','d','l','l',0};
295 static const WCHAR k33W[] = {'\\','k','e','r','n','e','l','3','3','.','d','l','l',0};
296 WCHAR pathW[MAX_PATH], filenameW[MAX_PATH];
297 BSTR path, version;
298 HRESULT hr;
300 GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
302 lstrcpyW(filenameW, pathW);
303 lstrcatW(filenameW, k32W);
305 path = SysAllocString(filenameW);
306 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
307 ok(hr == S_OK, "got 0x%08x\n", hr);
308 ok(*version != 0, "got %s\n", wine_dbgstr_w(version));
309 SysFreeString(version);
310 SysFreeString(path);
312 lstrcpyW(filenameW, pathW);
313 lstrcatW(filenameW, k33W);
315 path = SysAllocString(filenameW);
316 version = (void*)0xdeadbeef;
317 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
318 ok(broken(hr == S_OK) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
319 if (hr == S_OK)
321 ok(*version == 0, "got %s\n", wine_dbgstr_w(version));
322 SysFreeString(version);
324 else
325 ok(version == (void*)0xdeadbeef, "got %p\n", version);
326 SysFreeString(path);
329 static void test_GetParentFolderName(void)
331 static const WCHAR path1[] = {'a',0};
332 static const WCHAR path2[] = {'a','/','a','/','a',0};
333 static const WCHAR path3[] = {'a','\\','a','\\','a',0};
334 static const WCHAR path4[] = {'a','/','a','/','/','\\','\\',0};
335 static const WCHAR path5[] = {'c',':','\\','\\','a',0};
336 static const WCHAR path6[] = {'a','c',':','\\','a',0};
337 static const WCHAR result2[] = {'a','/','a',0};
338 static const WCHAR result3[] = {'a','\\','a',0};
339 static const WCHAR result4[] = {'a',0};
340 static const WCHAR result5[] = {'c',':','\\',0};
341 static const WCHAR result6[] = {'a','c',':',0};
343 static const struct {
344 const WCHAR *path;
345 const WCHAR *result;
346 } tests[] = {
347 {NULL, NULL},
348 {path1, NULL},
349 {path2, result2},
350 {path3, result3},
351 {path4, result4},
352 {path5, result5},
353 {path6, result6}
356 BSTR path, result;
357 HRESULT hr;
358 int i;
360 hr = IFileSystem3_GetParentFolderName(fs3, NULL, NULL);
361 ok(hr == E_POINTER, "GetParentFolderName returned %x, expected E_POINTER\n", hr);
363 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
364 result = (BSTR)0xdeadbeef;
365 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
366 hr = IFileSystem3_GetParentFolderName(fs3, path, &result);
367 ok(hr == S_OK, "%d) GetParentFolderName returned %x, expected S_OK\n", i, hr);
368 if(!tests[i].result)
369 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
370 else
371 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
372 SysFreeString(path);
373 SysFreeString(result);
377 static void test_GetFileName(void)
379 static const WCHAR path1[] = {'a',0};
380 static const WCHAR path2[] = {'a','/','a','.','b',0};
381 static const WCHAR path3[] = {'a','\\',0};
382 static const WCHAR path4[] = {'c',':',0};
383 static const WCHAR path5[] = {'/','\\',0};
384 static const WCHAR result2[] = {'a','.','b',0};
385 static const WCHAR result3[] = {'a',0};
387 static const struct {
388 const WCHAR *path;
389 const WCHAR *result;
390 } tests[] = {
391 {NULL, NULL},
392 {path1, path1},
393 {path2, result2},
394 {path3, result3},
395 {path4, NULL},
396 {path5, NULL}
399 BSTR path, result;
400 HRESULT hr;
401 int i;
403 hr = IFileSystem3_GetFileName(fs3, NULL, NULL);
404 ok(hr == E_POINTER, "GetFileName returned %x, expected E_POINTER\n", hr);
406 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
407 result = (BSTR)0xdeadbeef;
408 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
409 hr = IFileSystem3_GetFileName(fs3, path, &result);
410 ok(hr == S_OK, "%d) GetFileName returned %x, expected S_OK\n", i, hr);
411 if(!tests[i].result)
412 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
413 else
414 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
415 SysFreeString(path);
416 SysFreeString(result);
420 static void test_GetBaseName(void)
422 static const WCHAR path1[] = {'a',0};
423 static const WCHAR path2[] = {'a','/','a','.','b','.','c',0};
424 static const WCHAR path3[] = {'a','.','b','\\',0};
425 static const WCHAR path4[] = {'c',':',0};
426 static const WCHAR path5[] = {'/','\\',0};
427 static const WCHAR path6[] = {'.','a',0};
428 static const WCHAR result1[] = {'a',0};
429 static const WCHAR result2[] = {'a','.','b',0};
430 static const WCHAR result6[] = {0};
432 static const struct {
433 const WCHAR *path;
434 const WCHAR *result;
435 } tests[] = {
436 {NULL, NULL},
437 {path1, result1},
438 {path2, result2},
439 {path3, result1},
440 {path4, NULL},
441 {path5, NULL},
442 {path6, result6}
445 BSTR path, result;
446 HRESULT hr;
447 int i;
449 hr = IFileSystem3_GetBaseName(fs3, NULL, NULL);
450 ok(hr == E_POINTER, "GetBaseName returned %x, expected E_POINTER\n", hr);
452 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
453 result = (BSTR)0xdeadbeef;
454 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
455 hr = IFileSystem3_GetBaseName(fs3, path, &result);
456 ok(hr == S_OK, "%d) GetBaseName returned %x, expected S_OK\n", i, hr);
457 if(!tests[i].result)
458 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
459 else
460 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
461 SysFreeString(path);
462 SysFreeString(result);
466 static void test_GetAbsolutePathName(void)
468 static const WCHAR dir1[] = {'t','e','s','t','_','d','i','r','1',0};
469 static const WCHAR dir2[] = {'t','e','s','t','_','d','i','r','2',0};
470 static const WCHAR dir_match1[] = {'t','e','s','t','_','d','i','r','*',0};
471 static const WCHAR dir_match2[] = {'t','e','s','t','_','d','i','*',0};
472 static const WCHAR cur_dir[] = {'.',0};
474 WIN32_FIND_DATAW fdata;
475 HANDLE find;
476 WCHAR buf[MAX_PATH], buf2[MAX_PATH];
477 BSTR path, result;
478 HRESULT hr;
480 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, NULL);
481 ok(hr == E_POINTER, "GetAbsolutePathName returned %x, expected E_POINTER\n", hr);
483 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result);
484 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
485 GetFullPathNameW(cur_dir, MAX_PATH, buf, NULL);
486 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
487 SysFreeString(result);
489 find = FindFirstFileW(dir_match2, &fdata);
490 if(find != INVALID_HANDLE_VALUE) {
491 skip("GetAbsolutePathName tests\n");
492 FindClose(find);
493 return;
496 path = SysAllocString(dir_match1);
497 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
498 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
499 GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL);
500 ok(!lstrcmpiW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2));
501 SysFreeString(result);
503 ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1));
504 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
505 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
506 GetFullPathNameW(dir1, MAX_PATH, buf, NULL);
507 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
508 wine_dbgstr_w(result), wine_dbgstr_w(buf));
509 SysFreeString(result);
511 ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2));
512 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
513 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
514 if(!lstrcmpiW(buf, result) || !lstrcmpiW(buf2, result)) {
515 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
516 wine_dbgstr_w(result), wine_dbgstr_w(buf));
517 }else {
518 GetFullPathNameW(dir2, MAX_PATH, buf, NULL);
519 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n",
520 wine_dbgstr_w(result), wine_dbgstr_w(buf));
522 SysFreeString(result);
524 SysFreeString(path);
525 path = SysAllocString(dir_match2);
526 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
527 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
528 GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL);
529 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
530 SysFreeString(result);
531 SysFreeString(path);
533 RemoveDirectoryW(dir1);
534 RemoveDirectoryW(dir2);
537 static void test_GetFile(void)
539 static const WCHAR slW[] = {'\\',0};
540 BSTR path;
541 WCHAR pathW[MAX_PATH];
542 FileAttribute fa;
543 VARIANT size;
544 DWORD gfa;
545 IFile *file;
546 HRESULT hr;
547 HANDLE hf;
548 BOOL ret;
550 get_temp_path(NULL, pathW);
552 path = SysAllocString(pathW);
553 hr = IFileSystem3_GetFile(fs3, path, NULL);
554 ok(hr == E_POINTER, "GetFile returned %x, expected E_POINTER\n", hr);
555 hr = IFileSystem3_GetFile(fs3, NULL, &file);
556 ok(hr == E_INVALIDARG, "GetFile returned %x, expected E_INVALIDARG\n", hr);
558 file = (IFile*)0xdeadbeef;
559 hr = IFileSystem3_GetFile(fs3, path, &file);
560 ok(!file, "file != NULL\n");
561 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
563 hf = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
564 if(hf == INVALID_HANDLE_VALUE) {
565 skip("Can't create temporary file\n");
566 SysFreeString(path);
567 return;
569 CloseHandle(hf);
571 hr = IFileSystem3_GetFile(fs3, path, &file);
572 ok(hr == S_OK, "GetFile returned %x, expected S_OK\n", hr);
574 hr = IFile_get_Attributes(file, &fa);
575 gfa = GetFileAttributesW(pathW) & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
576 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE |
577 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED);
578 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
579 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa);
581 hr = IFile_get_Size(file, &size);
582 ok(hr == S_OK, "get_Size returned %x, expected S_OK\n", hr);
583 ok(V_VT(&size) == VT_I4, "V_VT(&size) = %d, expected VT_I4\n", V_VT(&size));
584 ok(V_I4(&size) == 0, "V_I4(&size) = %d, expected 0\n", V_I4(&size));
585 IFile_Release(file);
587 hr = IFileSystem3_DeleteFile(fs3, path, FALSE);
588 ok(hr==CTL_E_PERMISSIONDENIED || broken(hr==S_OK),
589 "DeleteFile returned %x, expected CTL_E_PERMISSIONDENIED\n", hr);
590 if(hr != S_OK) {
591 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
592 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
594 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
595 ok(hr == CTL_E_FILENOTFOUND, "DeleteFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
597 SysFreeString(path);
599 /* try with directory */
600 lstrcatW(pathW, slW);
601 ret = CreateDirectoryW(pathW, NULL);
602 ok(ret, "got %d, error %d\n", ret, GetLastError());
604 path = SysAllocString(pathW);
605 hr = IFileSystem3_GetFile(fs3, path, &file);
606 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected S_OK\n", hr);
607 SysFreeString(path);
609 RemoveDirectoryW(pathW);
612 static inline BOOL create_file(const WCHAR *name)
614 HANDLE f = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
615 CloseHandle(f);
616 return f != INVALID_HANDLE_VALUE;
619 static inline void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret)
621 DWORD len = lstrlenW(folder);
622 memmove(ret, folder, len*sizeof(WCHAR));
623 ret[len] = '\\';
624 memmove(ret+len+1, name, (lstrlenW(name)+1)*sizeof(WCHAR));
627 static void test_CopyFolder(void)
629 static const WCHAR filesystem3_dir[] = {'f','i','l','e','s','y','s','t','e','m','3','_','t','e','s','t',0};
630 static const WCHAR s1[] = {'s','r','c','1',0};
631 static const WCHAR s[] = {'s','r','c','*',0};
632 static const WCHAR d[] = {'d','s','t',0};
633 static const WCHAR empty[] = {0};
635 WCHAR tmp[MAX_PATH];
636 BSTR bsrc, bdst;
637 HRESULT hr;
639 if(!CreateDirectoryW(filesystem3_dir, NULL)) {
640 skip("can't create temporary directory\n");
641 return;
644 create_path(filesystem3_dir, s1, tmp);
645 bsrc = SysAllocString(tmp);
646 create_path(filesystem3_dir, d, tmp);
647 bdst = SysAllocString(tmp);
648 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
649 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
651 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
652 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
654 ok(create_file(bsrc), "can't create %s file\n", wine_dbgstr_w(bsrc));
655 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
656 ok(hr == S_OK, "CopyFile returned %x, expected S_OK\n", hr);
658 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
659 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
661 hr = IFileSystem3_DeleteFile(fs3, bsrc, VARIANT_FALSE);
662 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
664 ok(CreateDirectoryW(bsrc, NULL), "can't create %s\n", wine_dbgstr_w(bsrc));
665 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
666 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
668 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
669 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
671 hr = IFileSystem3_DeleteFile(fs3, bdst, VARIANT_TRUE);
672 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
674 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
675 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
677 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
678 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
679 create_path(tmp, s1, tmp);
680 ok(GetFileAttributesW(tmp) == INVALID_FILE_ATTRIBUTES,
681 "%s file exists\n", wine_dbgstr_w(tmp));
683 create_path(filesystem3_dir, d, tmp);
684 create_path(tmp, empty, tmp);
685 SysFreeString(bdst);
686 bdst = SysAllocString(tmp);
687 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
688 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
689 create_path(tmp, s1, tmp);
690 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
691 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
692 ok(RemoveDirectoryW(tmp), "can't remove %s directory\n", wine_dbgstr_w(tmp));
693 create_path(filesystem3_dir, d, tmp);
694 SysFreeString(bdst);
695 bdst = SysAllocString(tmp);
698 create_path(filesystem3_dir, s, tmp);
699 SysFreeString(bsrc);
700 bsrc = SysAllocString(tmp);
701 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
702 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
703 create_path(filesystem3_dir, d, tmp);
704 create_path(tmp, s1, tmp);
705 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
706 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
708 hr = IFileSystem3_DeleteFolder(fs3, bdst, VARIANT_FALSE);
709 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
711 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
712 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
714 create_path(filesystem3_dir, s1, tmp);
715 SysFreeString(bsrc);
716 bsrc = SysAllocString(tmp);
717 create_path(tmp, s1, tmp);
718 ok(create_file(tmp), "can't create %s file\n", wine_dbgstr_w(tmp));
719 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
720 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
722 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
723 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
725 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
726 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
727 SysFreeString(bsrc);
728 SysFreeString(bdst);
730 bsrc = SysAllocString(filesystem3_dir);
731 hr = IFileSystem3_DeleteFolder(fs3, bsrc, VARIANT_FALSE);
732 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
733 SysFreeString(bsrc);
736 static BSTR bstr_from_str(const char *str)
738 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
739 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */
740 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
741 return ret;
744 struct buildpath_test
746 const char *path;
747 const char *name;
748 const char *result;
751 static struct buildpath_test buildpath_data[] =
753 { "C:\\path", "..\\name.tmp", "C:\\path\\..\\name.tmp" },
754 { "C:\\path", "\\name.tmp", "C:\\path\\name.tmp" },
755 { "C:\\path", "name.tmp", "C:\\path\\name.tmp" },
756 { "C:\\path\\", "name.tmp", "C:\\path\\name.tmp" },
757 { "C:\\path", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
758 { "C:\\path\\", "\\name.tmp", "C:\\path\\name.tmp" },
759 { "C:\\path\\", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
760 { "C:\\path\\\\", "\\\\name.tmp", "C:\\path\\\\\\name.tmp" },
761 { "C:\\\\", "\\name.tmp", "C:\\\\name.tmp" },
762 { "C:", "name.tmp", "C:name.tmp" },
763 { "C:", "\\\\name.tmp", "C:\\\\name.tmp" },
764 { NULL }
767 static void test_BuildPath(void)
769 struct buildpath_test *ptr = buildpath_data;
770 BSTR ret, path;
771 HRESULT hr;
772 int i = 0;
774 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, NULL);
775 ok(hr == E_POINTER, "got 0x%08x\n", hr);
777 ret = (BSTR)0xdeadbeef;
778 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, &ret);
779 ok(hr == S_OK, "got 0x%08x\n", hr);
780 ok(*ret == 0, "got %p\n", ret);
781 SysFreeString(ret);
783 ret = (BSTR)0xdeadbeef;
784 path = bstr_from_str("path");
785 hr = IFileSystem3_BuildPath(fs3, path, NULL, &ret);
786 ok(hr == S_OK, "got 0x%08x\n", hr);
787 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
788 SysFreeString(ret);
789 SysFreeString(path);
791 ret = (BSTR)0xdeadbeef;
792 path = bstr_from_str("path");
793 hr = IFileSystem3_BuildPath(fs3, NULL, path, &ret);
794 ok(hr == S_OK, "got 0x%08x\n", hr);
795 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
796 SysFreeString(ret);
797 SysFreeString(path);
799 while (ptr->path)
801 BSTR name, result;
803 ret = NULL;
804 path = bstr_from_str(ptr->path);
805 name = bstr_from_str(ptr->name);
806 result = bstr_from_str(ptr->result);
807 hr = IFileSystem3_BuildPath(fs3, path, name, &ret);
808 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
809 if (hr == S_OK)
811 ok(!lstrcmpW(ret, result), "%d: got wrong path %s, expected %s\n", i, wine_dbgstr_w(ret),
812 wine_dbgstr_w(result));
813 SysFreeString(ret);
815 SysFreeString(path);
816 SysFreeString(name);
817 SysFreeString(result);
819 i++;
820 ptr++;
824 static void test_GetFolder(void)
826 static const WCHAR dummyW[] = {'d','u','m','m','y',0};
827 WCHAR buffW[MAX_PATH];
828 IFolder *folder;
829 HRESULT hr;
830 BSTR str;
832 folder = (void*)0xdeadbeef;
833 hr = IFileSystem3_GetFolder(fs3, NULL, &folder);
834 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
835 ok(folder == NULL, "got %p\n", folder);
837 hr = IFileSystem3_GetFolder(fs3, NULL, NULL);
838 ok(hr == E_POINTER, "got 0x%08x\n", hr);
840 /* something that doesn't exist */
841 str = SysAllocString(dummyW);
843 hr = IFileSystem3_GetFolder(fs3, str, NULL);
844 ok(hr == E_POINTER, "got 0x%08x\n", hr);
846 folder = (void*)0xdeadbeef;
847 hr = IFileSystem3_GetFolder(fs3, str, &folder);
848 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
849 ok(folder == NULL, "got %p\n", folder);
850 SysFreeString(str);
852 GetWindowsDirectoryW(buffW, MAX_PATH);
853 str = SysAllocString(buffW);
854 hr = IFileSystem3_GetFolder(fs3, str, &folder);
855 ok(hr == S_OK, "got 0x%08x\n", hr);
856 SysFreeString(str);
857 IFolder_Release(folder);
860 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
861 static void test_FolderCollection(void)
863 static const WCHAR fooW[] = {'f','o','o',0};
864 static const WCHAR aW[] = {'\\','a',0};
865 static const WCHAR bW[] = {'\\','b',0};
866 static const WCHAR cW[] = {'\\','c',0};
867 IFolderCollection *folders;
868 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
869 IEnumVARIANT *enumvar, *clone;
870 LONG count, ref, ref2, i;
871 IUnknown *unk, *unk2;
872 IFolder *folder;
873 ULONG fetched;
874 VARIANT var, var2[2];
875 HRESULT hr;
876 BSTR str;
877 int found_a = 0, found_b = 0, found_c = 0;
879 get_temp_path(fooW, buffW);
880 CreateDirectoryW(buffW, NULL);
882 str = SysAllocString(buffW);
883 hr = IFileSystem3_GetFolder(fs3, str, &folder);
884 ok(hr == S_OK, "got 0x%08x\n", hr);
885 SysFreeString(str);
887 hr = IFolder_get_SubFolders(folder, NULL);
888 ok(hr == E_POINTER, "got 0x%08x\n", hr);
890 hr = IFolder_get_Path(folder, NULL);
891 ok(hr == E_POINTER, "got 0x%08x\n", hr);
893 hr = IFolder_get_Path(folder, &str);
894 ok(hr == S_OK, "got 0x%08x\n", hr);
895 ok(!lstrcmpW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
896 SysFreeString(str);
898 lstrcpyW(pathW, buffW);
899 lstrcatW(pathW, aW);
900 CreateDirectoryW(pathW, NULL);
902 lstrcpyW(pathW, buffW);
903 lstrcatW(pathW, bW);
904 CreateDirectoryW(pathW, NULL);
906 hr = IFolder_get_SubFolders(folder, &folders);
907 ok(hr == S_OK, "got 0x%08x\n", hr);
908 IFolder_Release(folder);
910 count = 0;
911 hr = IFolderCollection_get_Count(folders, &count);
912 ok(hr == S_OK, "got 0x%08x\n", hr);
913 ok(count == 2, "got %d\n", count);
915 lstrcpyW(pathW, buffW);
916 lstrcatW(pathW, cW);
917 CreateDirectoryW(pathW, NULL);
919 /* every time property is requested it scans directory */
920 count = 0;
921 hr = IFolderCollection_get_Count(folders, &count);
922 ok(hr == S_OK, "got 0x%08x\n", hr);
923 ok(count == 3, "got %d\n", count);
925 hr = IFolderCollection_get__NewEnum(folders, NULL);
926 ok(hr == E_POINTER, "got 0x%08x\n", hr);
928 hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk);
929 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
931 /* NewEnum creates new instance each time it's called */
932 ref = GET_REFCOUNT(folders);
934 unk = NULL;
935 hr = IFolderCollection_get__NewEnum(folders, &unk);
936 ok(hr == S_OK, "got 0x%08x\n", hr);
938 ref2 = GET_REFCOUNT(folders);
939 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
941 unk2 = NULL;
942 hr = IFolderCollection_get__NewEnum(folders, &unk2);
943 ok(hr == S_OK, "got 0x%08x\n", hr);
944 ok(unk != unk2, "got %p, %p\n", unk2, unk);
945 IUnknown_Release(unk2);
947 /* now get IEnumVARIANT */
948 ref = GET_REFCOUNT(folders);
949 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
950 ok(hr == S_OK, "got 0x%08x\n", hr);
951 ref2 = GET_REFCOUNT(folders);
952 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
954 /* clone enumerator */
955 hr = IEnumVARIANT_Clone(enumvar, &clone);
956 ok(hr == S_OK, "got 0x%08x\n", hr);
957 ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
958 IEnumVARIANT_Release(clone);
960 hr = IEnumVARIANT_Reset(enumvar);
961 ok(hr == S_OK, "got 0x%08x\n", hr);
963 for (i = 0; i < 3; i++)
965 VariantInit(&var);
966 fetched = 0;
967 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
968 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
969 ok(fetched == 1, "%d: got %d\n", i, fetched);
970 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
972 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder);
973 ok(hr == S_OK, "got 0x%08x\n", hr);
975 str = NULL;
976 hr = IFolder_get_Name(folder, &str);
977 ok(hr == S_OK, "got 0x%08x\n", hr);
978 if (!lstrcmpW(str, aW + 1))
979 found_a++;
980 else if (!lstrcmpW(str, bW + 1))
981 found_b++;
982 else if (!lstrcmpW(str, cW + 1))
983 found_c++;
984 else
985 ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str));
986 SysFreeString(str);
988 IFolder_Release(folder);
989 VariantClear(&var);
992 ok(found_a == 1 && found_b == 1 && found_c == 1,
993 "each folder should be found 1 time instead of %d/%d/%d\n",
994 found_a, found_b, found_c);
996 VariantInit(&var);
997 fetched = -1;
998 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
999 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1000 ok(fetched == 0, "got %d\n", fetched);
1002 hr = IEnumVARIANT_Reset(enumvar);
1003 ok(hr == S_OK, "got 0x%08x\n", hr);
1004 hr = IEnumVARIANT_Skip(enumvar, 2);
1005 ok(hr == S_OK, "got 0x%08x\n", hr);
1006 hr = IEnumVARIANT_Skip(enumvar, 0);
1007 ok(hr == S_OK, "got 0x%08x\n", hr);
1009 VariantInit(&var2[0]);
1010 VariantInit(&var2[1]);
1011 fetched = -1;
1012 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1013 ok(hr == S_OK, "got 0x%08x\n", hr);
1014 ok(fetched == 0, "got %d\n", fetched);
1015 fetched = -1;
1016 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1017 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1018 ok(fetched == 1, "got %d\n", fetched);
1019 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1020 VariantClear(&var2[0]);
1021 VariantClear(&var2[1]);
1023 IEnumVARIANT_Release(enumvar);
1024 IUnknown_Release(unk);
1026 lstrcpyW(pathW, buffW);
1027 lstrcatW(pathW, aW);
1028 RemoveDirectoryW(pathW);
1029 lstrcpyW(pathW, buffW);
1030 lstrcatW(pathW, bW);
1031 RemoveDirectoryW(pathW);
1032 lstrcpyW(pathW, buffW);
1033 lstrcatW(pathW, cW);
1034 RemoveDirectoryW(pathW);
1035 RemoveDirectoryW(buffW);
1037 IFolderCollection_Release(folders);
1040 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
1041 static void test_FileCollection(void)
1043 static const WCHAR fooW[] = {'\\','f','o','o',0};
1044 static const WCHAR aW[] = {'\\','a',0};
1045 static const WCHAR bW[] = {'\\','b',0};
1046 static const WCHAR cW[] = {'\\','c',0};
1047 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
1048 IFolder *folder;
1049 IFileCollection *files;
1050 IFile *file;
1051 IEnumVARIANT *enumvar, *clone;
1052 LONG count, ref, ref2, i;
1053 IUnknown *unk, *unk2;
1054 ULONG fetched;
1055 VARIANT var, var2[2];
1056 HRESULT hr;
1057 BSTR str;
1058 HANDLE file_a, file_b, file_c;
1059 int found_a = 0, found_b = 0, found_c = 0;
1061 get_temp_path(fooW, buffW);
1062 CreateDirectoryW(buffW, NULL);
1064 str = SysAllocString(buffW);
1065 hr = IFileSystem3_GetFolder(fs3, str, &folder);
1066 ok(hr == S_OK, "got 0x%08x\n", hr);
1067 SysFreeString(str);
1069 hr = IFolder_get_Files(folder, NULL);
1070 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1072 lstrcpyW(pathW, buffW);
1073 lstrcatW(pathW, aW);
1074 file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1075 FILE_FLAG_DELETE_ON_CLOSE, 0);
1076 lstrcpyW(pathW, buffW);
1077 lstrcatW(pathW, bW);
1078 file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1079 FILE_FLAG_DELETE_ON_CLOSE, 0);
1081 hr = IFolder_get_Files(folder, &files);
1082 ok(hr == S_OK, "got 0x%08x\n", hr);
1083 IFolder_Release(folder);
1085 count = 0;
1086 hr = IFileCollection_get_Count(files, &count);
1087 ok(hr == S_OK, "got 0x%08x\n", hr);
1088 ok(count == 2, "got %d\n", count);
1090 lstrcpyW(pathW, buffW);
1091 lstrcatW(pathW, cW);
1092 file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1093 FILE_FLAG_DELETE_ON_CLOSE, 0);
1095 /* every time property is requested it scans directory */
1096 count = 0;
1097 hr = IFileCollection_get_Count(files, &count);
1098 ok(hr == S_OK, "got 0x%08x\n", hr);
1099 ok(count == 3, "got %d\n", count);
1101 hr = IFileCollection_get__NewEnum(files, NULL);
1102 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1104 hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk);
1105 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1107 /* NewEnum creates new instance each time it's called */
1108 ref = GET_REFCOUNT(files);
1110 unk = NULL;
1111 hr = IFileCollection_get__NewEnum(files, &unk);
1112 ok(hr == S_OK, "got 0x%08x\n", hr);
1114 ref2 = GET_REFCOUNT(files);
1115 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1117 unk2 = NULL;
1118 hr = IFileCollection_get__NewEnum(files, &unk2);
1119 ok(hr == S_OK, "got 0x%08x\n", hr);
1120 ok(unk != unk2, "got %p, %p\n", unk2, unk);
1121 IUnknown_Release(unk2);
1123 /* now get IEnumVARIANT */
1124 ref = GET_REFCOUNT(files);
1125 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1126 ok(hr == S_OK, "got 0x%08x\n", hr);
1127 ref2 = GET_REFCOUNT(files);
1128 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1130 /* clone enumerator */
1131 hr = IEnumVARIANT_Clone(enumvar, &clone);
1132 ok(hr == S_OK, "got 0x%08x\n", hr);
1133 ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
1134 IEnumVARIANT_Release(clone);
1136 hr = IEnumVARIANT_Reset(enumvar);
1137 ok(hr == S_OK, "got 0x%08x\n", hr);
1139 for (i = 0; i < 3; i++)
1141 VariantInit(&var);
1142 fetched = 0;
1143 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1144 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1145 ok(fetched == 1, "%d: got %d\n", i, fetched);
1146 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1148 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file);
1149 ok(hr == S_OK, "got 0x%08x\n", hr);
1151 str = NULL;
1152 hr = IFile_get_Name(file, &str);
1153 ok(hr == S_OK, "got 0x%08x\n", hr);
1154 if (!lstrcmpW(str, aW + 1))
1155 found_a++;
1156 else if (!lstrcmpW(str, bW + 1))
1157 found_b++;
1158 else if (!lstrcmpW(str, cW + 1))
1159 found_c++;
1160 else
1161 ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str));
1162 SysFreeString(str);
1164 IFile_Release(file);
1165 VariantClear(&var);
1168 ok(found_a == 1 && found_b == 1 && found_c == 1,
1169 "each file should be found 1 time instead of %d/%d/%d\n",
1170 found_a, found_b, found_c);
1172 VariantInit(&var);
1173 fetched = -1;
1174 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1175 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1176 ok(fetched == 0, "got %d\n", fetched);
1178 hr = IEnumVARIANT_Reset(enumvar);
1179 ok(hr == S_OK, "got 0x%08x\n", hr);
1180 hr = IEnumVARIANT_Skip(enumvar, 2);
1181 ok(hr == S_OK, "got 0x%08x\n", hr);
1182 hr = IEnumVARIANT_Skip(enumvar, 0);
1183 ok(hr == S_OK, "got 0x%08x\n", hr);
1185 VariantInit(&var2[0]);
1186 VariantInit(&var2[1]);
1187 fetched = -1;
1188 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1189 ok(hr == S_OK, "got 0x%08x\n", hr);
1190 ok(fetched == 0, "got %d\n", fetched);
1191 fetched = -1;
1192 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1193 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1194 ok(fetched == 1, "got %d\n", fetched);
1195 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1196 VariantClear(&var2[0]);
1197 VariantClear(&var2[1]);
1199 IEnumVARIANT_Release(enumvar);
1200 IUnknown_Release(unk);
1202 CloseHandle(file_a);
1203 CloseHandle(file_b);
1204 CloseHandle(file_c);
1205 RemoveDirectoryW(buffW);
1207 IFileCollection_Release(files);
1210 static void test_DriveCollection(void)
1212 IDriveCollection *drives;
1213 IEnumVARIANT *enumvar;
1214 ULONG fetched;
1215 VARIANT var;
1216 HRESULT hr;
1217 LONG count;
1219 hr = IFileSystem3_get_Drives(fs3, &drives);
1220 ok(hr == S_OK, "got 0x%08x\n", hr);
1222 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar);
1223 ok(hr == S_OK, "got 0x%08x\n", hr);
1225 hr = IDriveCollection_get_Count(drives, NULL);
1226 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1228 count = 0;
1229 hr = IDriveCollection_get_Count(drives, &count);
1230 ok(hr == S_OK, "got 0x%08x\n", hr);
1231 ok(count > 0, "got %d\n", count);
1233 V_VT(&var) = VT_EMPTY;
1234 fetched = -1;
1235 hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched);
1236 ok(hr == S_OK, "got 0x%08x\n", hr);
1237 ok(fetched == 0, "got %d\n", fetched);
1239 hr = IEnumVARIANT_Skip(enumvar, 0);
1240 ok(hr == S_OK, "got 0x%08x\n", hr);
1242 hr = IEnumVARIANT_Skip(enumvar, count);
1243 ok(hr == S_OK, "got 0x%08x\n", hr);
1245 hr = IEnumVARIANT_Skip(enumvar, 1);
1246 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1248 /* reset and iterate again */
1249 hr = IEnumVARIANT_Reset(enumvar);
1250 ok(hr == S_OK, "got 0x%08x\n", hr);
1252 while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) {
1253 IDrive *drive = (IDrive*)V_DISPATCH(&var);
1254 DriveTypeConst type;
1255 BSTR str;
1257 hr = IDrive_get_DriveType(drive, &type);
1258 ok(hr == S_OK, "got 0x%08x\n", hr);
1260 hr = IDrive_get_DriveLetter(drive, NULL);
1261 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1263 hr = IDrive_get_DriveLetter(drive, &str);
1264 ok(hr == S_OK, "got 0x%08x\n", hr);
1265 ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str));
1266 SysFreeString(str);
1268 hr = IDrive_get_IsReady(drive, NULL);
1269 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1271 hr = IDrive_get_TotalSize(drive, NULL);
1272 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1274 hr = IDrive_get_AvailableSpace(drive, NULL);
1275 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1277 hr = IDrive_get_FreeSpace(drive, NULL);
1278 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1280 if (type == Fixed) {
1281 VARIANT_BOOL ready = VARIANT_FALSE;
1282 VARIANT size;
1284 hr = IDrive_get_IsReady(drive, &ready);
1285 ok(hr == S_OK, "got 0x%08x\n", hr);
1286 ok(ready == VARIANT_TRUE, "got %x\n", ready);
1288 V_VT(&size) = VT_EMPTY;
1289 hr = IDrive_get_TotalSize(drive, &size);
1290 ok(hr == S_OK, "got 0x%08x\n", hr);
1291 ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
1292 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1294 V_VT(&size) = VT_EMPTY;
1295 hr = IDrive_get_AvailableSpace(drive, &size);
1296 ok(hr == S_OK, "got 0x%08x\n", hr);
1297 ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
1298 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1300 V_VT(&size) = VT_EMPTY;
1301 hr = IDrive_get_FreeSpace(drive, &size);
1302 ok(hr == S_OK, "got 0x%08x\n", hr);
1303 ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
1304 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1306 VariantClear(&var);
1309 IEnumVARIANT_Release(enumvar);
1310 IDriveCollection_Release(drives);
1313 static void test_CreateTextFile(void)
1315 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1316 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1317 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[10];
1318 ITextStream *stream;
1319 BSTR nameW, str;
1320 HANDLE file;
1321 HRESULT hr;
1322 BOOL ret;
1324 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1325 lstrcatW(pathW, scrrunW);
1326 lstrcpyW(dirW, pathW);
1327 lstrcatW(pathW, testfileW);
1329 /* dir doesn't exist */
1330 nameW = SysAllocString(pathW);
1331 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1332 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
1334 ret = CreateDirectoryW(dirW, NULL);
1335 ok(ret, "got %d, %d\n", ret, GetLastError());
1337 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1338 ok(hr == S_OK, "got 0x%08x\n", hr);
1340 hr = ITextStream_Read(stream, 1, &str);
1341 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1343 ITextStream_Release(stream);
1345 /* check it's created */
1346 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1347 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1348 CloseHandle(file);
1350 /* try to create again with no-overwrite mode */
1351 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1352 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
1354 /* now overwrite */
1355 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1356 ok(hr == S_OK, "got 0x%08x\n", hr);
1357 ITextStream_Release(stream);
1359 /* overwrite in Unicode mode, check for BOM */
1360 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
1361 ok(hr == S_OK, "got 0x%08x\n", hr);
1362 ITextStream_Release(stream);
1364 /* File was created in Unicode mode, it contains 0xfffe BOM. Opening it in non-Unicode mode
1365 treats BOM like a valuable data with appropriate CP_ACP -> WCHAR conversion. */
1366 buffW[0] = 0;
1367 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR));
1369 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1370 ok(hr == S_OK, "got 0x%08x\n", hr);
1371 hr = ITextStream_ReadAll(stream, &str);
1372 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1373 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1374 SysFreeString(str);
1375 ITextStream_Release(stream);
1377 DeleteFileW(nameW);
1378 RemoveDirectoryW(dirW);
1379 SysFreeString(nameW);
1382 static void test_WriteLine(void)
1384 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1385 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1386 WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
1387 WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
1388 char buffA[MAX_PATH];
1389 ITextStream *stream;
1390 DWORD r, len;
1391 HANDLE file;
1392 BSTR nameW;
1393 HRESULT hr;
1394 BOOL ret;
1396 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1397 lstrcatW(pathW, scrrunW);
1398 lstrcpyW(dirW, pathW);
1399 lstrcatW(pathW, testfileW);
1401 ret = CreateDirectoryW(dirW, NULL);
1402 ok(ret, "got %d, %d\n", ret, GetLastError());
1404 /* create as ASCII file first */
1405 nameW = SysAllocString(pathW);
1406 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1407 ok(hr == S_OK, "got 0x%08x\n", hr);
1409 hr = ITextStream_WriteLine(stream, nameW);
1410 ok(hr == S_OK, "got 0x%08x\n", hr);
1411 ITextStream_Release(stream);
1413 /* check contents */
1414 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1415 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1416 r = 0;
1417 ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL);
1418 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1420 len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, sizeof(buffW)/sizeof(WCHAR));
1421 buffW[len] = 0;
1422 lstrcpyW(buff2W, nameW);
1423 lstrcatW(buff2W, crlfW);
1424 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1425 CloseHandle(file);
1426 DeleteFileW(nameW);
1428 /* same for unicode file */
1429 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1430 ok(hr == S_OK, "got 0x%08x\n", hr);
1432 hr = ITextStream_WriteLine(stream, nameW);
1433 ok(hr == S_OK, "got 0x%08x\n", hr);
1434 ITextStream_Release(stream);
1436 /* check contents */
1437 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1438 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1439 r = 0;
1440 ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL);
1441 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1442 buffW[r/sizeof(WCHAR)] = 0;
1444 buff2W[0] = 0xfeff;
1445 buff2W[1] = 0;
1446 lstrcatW(buff2W, nameW);
1447 lstrcatW(buff2W, crlfW);
1448 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1449 CloseHandle(file);
1450 DeleteFileW(nameW);
1452 RemoveDirectoryW(dirW);
1453 SysFreeString(nameW);
1456 static void test_ReadAll(void)
1458 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1459 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1460 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1461 static const WCHAR aW[] = {'A',0};
1462 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1463 ITextStream *stream;
1464 BSTR nameW;
1465 HRESULT hr;
1466 BOOL ret;
1467 BSTR str;
1469 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1470 lstrcatW(pathW, scrrunW);
1471 lstrcpyW(dirW, pathW);
1472 lstrcatW(pathW, testfileW);
1474 ret = CreateDirectoryW(dirW, NULL);
1475 ok(ret, "got %d, %d\n", ret, GetLastError());
1477 /* Unicode file -> read with ascii stream */
1478 nameW = SysAllocString(pathW);
1479 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1480 ok(hr == S_OK, "got 0x%08x\n", hr);
1482 hr = ITextStream_WriteLine(stream, nameW);
1483 ok(hr == S_OK, "got 0x%08x\n", hr);
1485 str = SysAllocString(secondlineW);
1486 hr = ITextStream_WriteLine(stream, str);
1487 ok(hr == S_OK, "got 0x%08x\n", hr);
1488 SysFreeString(str);
1490 hr = ITextStream_ReadAll(stream, NULL);
1491 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1493 str = (void*)0xdeadbeef;
1494 hr = ITextStream_ReadAll(stream, &str);
1495 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1496 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1498 ITextStream_Release(stream);
1500 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1501 ok(hr == S_OK, "got 0x%08x\n", hr);
1503 hr = ITextStream_ReadAll(stream, NULL);
1504 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1506 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1507 str = NULL;
1508 hr = ITextStream_ReadAll(stream, &str);
1509 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1510 buffW[0] = 0;
1511 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR));
1512 ok(str[0] == buffW[0] && str[1] == buffW[1], "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
1513 SysFreeString(str);
1514 ITextStream_Release(stream);
1516 /* Unicode file -> read with unicode stream */
1517 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1518 ok(hr == S_OK, "got 0x%08x\n", hr);
1520 lstrcpyW(buffW, nameW);
1521 lstrcatW(buffW, crlfW);
1522 lstrcatW(buffW, secondlineW);
1523 lstrcatW(buffW, crlfW);
1524 str = NULL;
1525 hr = ITextStream_ReadAll(stream, &str);
1526 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1527 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1528 SysFreeString(str);
1530 /* ReadAll one more time */
1531 str = (void*)0xdeadbeef;
1532 hr = ITextStream_ReadAll(stream, &str);
1533 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1534 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1536 /* ReadLine fails the same way */
1537 str = (void*)0xdeadbeef;
1538 hr = ITextStream_ReadLine(stream, &str);
1539 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1540 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1541 ITextStream_Release(stream);
1543 /* Open again and skip first line before ReadAll */
1544 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1545 ok(hr == S_OK, "got 0x%08x\n", hr);
1547 str = NULL;
1548 hr = ITextStream_ReadLine(stream, &str);
1549 todo_wine {
1550 ok(hr == S_OK, "got 0x%08x\n", hr);
1551 ok(str != NULL, "got %p\n", str);
1553 SysFreeString(str);
1555 lstrcpyW(buffW, secondlineW);
1556 lstrcatW(buffW, crlfW);
1557 str = NULL;
1558 hr = ITextStream_ReadAll(stream, &str);
1559 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1560 todo_wine
1561 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1562 SysFreeString(str);
1563 ITextStream_Release(stream);
1565 /* ASCII file, read with Unicode stream */
1566 /* 1. one byte content, not enough for Unicode read */
1567 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1568 ok(hr == S_OK, "got 0x%08x\n", hr);
1569 str = SysAllocString(aW);
1570 hr = ITextStream_Write(stream, str);
1571 SysFreeString(str);
1572 ITextStream_Release(stream);
1574 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1575 ok(hr == S_OK, "got 0x%08x\n", hr);
1577 str = (void*)0xdeadbeef;
1578 hr = ITextStream_ReadAll(stream, &str);
1579 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1580 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1582 ITextStream_Release(stream);
1584 DeleteFileW(nameW);
1585 RemoveDirectoryW(dirW);
1586 SysFreeString(nameW);
1589 static void test_Read(void)
1591 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1592 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1593 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1594 static const WCHAR aW[] = {'A',0};
1595 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1596 ITextStream *stream;
1597 BSTR nameW;
1598 HRESULT hr;
1599 BOOL ret;
1600 BSTR str;
1602 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1603 lstrcatW(pathW, scrrunW);
1604 lstrcpyW(dirW, pathW);
1605 lstrcatW(pathW, testfileW);
1607 ret = CreateDirectoryW(dirW, NULL);
1608 ok(ret, "got %d, %d\n", ret, GetLastError());
1610 /* Unicode file -> read with ascii stream */
1611 nameW = SysAllocString(pathW);
1612 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1613 ok(hr == S_OK, "got 0x%08x\n", hr);
1615 hr = ITextStream_WriteLine(stream, nameW);
1616 ok(hr == S_OK, "got 0x%08x\n", hr);
1618 str = SysAllocString(secondlineW);
1619 hr = ITextStream_WriteLine(stream, str);
1620 ok(hr == S_OK, "got 0x%08x\n", hr);
1621 SysFreeString(str);
1623 hr = ITextStream_Read(stream, 0, NULL);
1624 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1626 hr = ITextStream_Read(stream, 1, NULL);
1627 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1629 hr = ITextStream_Read(stream, -1, NULL);
1630 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1632 str = (void*)0xdeadbeef;
1633 hr = ITextStream_Read(stream, 1, &str);
1634 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1635 ok(str == NULL, "got %p\n", str);
1637 ITextStream_Release(stream);
1639 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1640 ok(hr == S_OK, "got 0x%08x\n", hr);
1642 hr = ITextStream_Read(stream, 1, NULL);
1643 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1645 str = (void*)0xdeadbeef;
1646 hr = ITextStream_Read(stream, -1, &str);
1647 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1648 ok(str == NULL, "got %p\n", str);
1650 str = (void*)0xdeadbeef;
1651 hr = ITextStream_Read(stream, 0, &str);
1652 ok(hr == S_OK, "got 0x%08x\n", hr);
1653 ok(str == NULL, "got %p\n", str);
1655 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1656 str = NULL;
1657 hr = ITextStream_Read(stream, 2, &str);
1658 ok(hr == S_OK, "got 0x%08x\n", hr);
1660 buffW[0] = 0;
1661 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR));
1663 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1664 ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str));
1665 SysFreeString(str);
1666 ITextStream_Release(stream);
1668 /* Unicode file -> read with unicode stream */
1669 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1670 ok(hr == S_OK, "got 0x%08x\n", hr);
1672 lstrcpyW(buffW, nameW);
1673 lstrcatW(buffW, crlfW);
1674 lstrcatW(buffW, secondlineW);
1675 lstrcatW(buffW, crlfW);
1676 str = NULL;
1677 hr = ITextStream_Read(stream, 500, &str);
1678 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1679 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1680 SysFreeString(str);
1682 /* ReadAll one more time */
1683 str = (void*)0xdeadbeef;
1684 hr = ITextStream_Read(stream, 10, &str);
1685 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1686 ok(str == NULL, "got %p\n", str);
1688 /* ReadLine fails the same way */
1689 str = (void*)0xdeadbeef;
1690 hr = ITextStream_ReadLine(stream, &str);
1691 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1692 ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str);
1693 ITextStream_Release(stream);
1695 /* Open again and skip first line before ReadAll */
1696 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1697 ok(hr == S_OK, "got 0x%08x\n", hr);
1699 str = NULL;
1700 hr = ITextStream_ReadLine(stream, &str);
1701 todo_wine {
1702 ok(hr == S_OK, "got 0x%08x\n", hr);
1703 ok(str != NULL, "got %p\n", str);
1705 SysFreeString(str);
1707 lstrcpyW(buffW, secondlineW);
1708 lstrcatW(buffW, crlfW);
1709 str = NULL;
1710 hr = ITextStream_Read(stream, 100, &str);
1711 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1712 todo_wine
1713 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1714 SysFreeString(str);
1715 ITextStream_Release(stream);
1717 /* ASCII file, read with Unicode stream */
1718 /* 1. one byte content, not enough for Unicode read */
1719 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1720 ok(hr == S_OK, "got 0x%08x\n", hr);
1721 str = SysAllocString(aW);
1722 hr = ITextStream_Write(stream, str);
1723 SysFreeString(str);
1724 ITextStream_Release(stream);
1726 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1727 ok(hr == S_OK, "got 0x%08x\n", hr);
1729 str = (void*)0xdeadbeef;
1730 hr = ITextStream_Read(stream, 500, &str);
1731 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1732 ok(str == NULL, "got %p\n", str);
1734 ITextStream_Release(stream);
1736 DeleteFileW(nameW);
1737 RemoveDirectoryW(dirW);
1738 SysFreeString(nameW);
1741 START_TEST(filesystem)
1743 HRESULT hr;
1745 CoInitialize(NULL);
1747 hr = CoCreateInstance(&CLSID_FileSystemObject, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1748 &IID_IFileSystem3, (void**)&fs3);
1749 if(FAILED(hr)) {
1750 win_skip("Could not create FileSystem object: %08x\n", hr);
1751 return;
1754 test_interfaces();
1755 test_createfolder();
1756 test_textstream();
1757 test_GetFileVersion();
1758 test_GetParentFolderName();
1759 test_GetFileName();
1760 test_GetBaseName();
1761 test_GetAbsolutePathName();
1762 test_GetFile();
1763 test_CopyFolder();
1764 test_BuildPath();
1765 test_GetFolder();
1766 test_FolderCollection();
1767 test_FileCollection();
1768 test_DriveCollection();
1769 test_CreateTextFile();
1770 test_WriteLine();
1771 test_ReadAll();
1772 test_Read();
1774 IFileSystem3_Release(fs3);
1776 CoUninitialize();