jscript: Added support for VT_UI4 variants.
[wine.git] / dlls / scrrun / tests / filesystem.c
blobb3f3beed2c87b41e935e3cdd7cb7b8d5be63150b
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>
23 #include <limits.h>
25 #include "windows.h"
26 #include "ole2.h"
27 #include "olectl.h"
28 #include "oleauto.h"
29 #include "dispex.h"
31 #include "wine/test.h"
33 #include "initguid.h"
34 #include "scrrun.h"
36 static IFileSystem3 *fs3;
38 static inline ULONG get_refcount(IUnknown *iface)
40 IUnknown_AddRef(iface);
41 return IUnknown_Release(iface);
44 static const WCHAR crlfW[] = {'\r','\n',0};
45 static const char utf16bom[] = {0xff,0xfe,0};
47 #define GET_REFCOUNT(iface) \
48 get_refcount((IUnknown*)iface)
50 static inline void get_temp_path(const WCHAR *prefix, WCHAR *path)
52 WCHAR buffW[MAX_PATH];
54 GetTempPathW(MAX_PATH, buffW);
55 GetTempFileNameW(buffW, prefix, 0, path);
56 DeleteFileW(path);
59 static void test_interfaces(void)
61 static const WCHAR nonexistent_dirW[] = {
62 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', 0};
63 static const WCHAR pathW[] = {'p','a','t','h',0};
64 static const WCHAR file_kernel32W[] = {
65 '\\', 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
66 HRESULT hr;
67 IDispatch *disp;
68 IDispatchEx *dispex;
69 IObjectWithSite *site;
70 VARIANT_BOOL b;
71 BSTR path;
72 WCHAR windows_path[MAX_PATH];
73 WCHAR file_path[MAX_PATH];
75 IFileSystem3_QueryInterface(fs3, &IID_IDispatch, (void**)&disp);
77 GetSystemDirectoryW(windows_path, MAX_PATH);
78 lstrcpyW(file_path, windows_path);
79 lstrcatW(file_path, file_kernel32W);
81 hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site);
82 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
84 hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
85 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
87 b = VARIANT_TRUE;
88 hr = IFileSystem3_FileExists(fs3, NULL, &b);
89 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
90 ok(b == VARIANT_FALSE, "got %x\n", b);
92 hr = IFileSystem3_FileExists(fs3, NULL, NULL);
93 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
95 path = SysAllocString(pathW);
96 b = VARIANT_TRUE;
97 hr = IFileSystem3_FileExists(fs3, path, &b);
98 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
99 ok(b == VARIANT_FALSE, "got %x\n", b);
100 SysFreeString(path);
102 path = SysAllocString(file_path);
103 b = VARIANT_FALSE;
104 hr = IFileSystem3_FileExists(fs3, path, &b);
105 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
106 ok(b == VARIANT_TRUE, "got %x\n", b);
107 SysFreeString(path);
109 path = SysAllocString(windows_path);
110 b = VARIANT_TRUE;
111 hr = IFileSystem3_FileExists(fs3, path, &b);
112 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
113 ok(b == VARIANT_FALSE, "got %x\n", b);
114 SysFreeString(path);
116 /* Folder Exists */
117 hr = IFileSystem3_FolderExists(fs3, NULL, NULL);
118 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
120 path = SysAllocString(windows_path);
121 hr = IFileSystem3_FolderExists(fs3, path, &b);
122 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
123 ok(b == VARIANT_TRUE, "Folder doesn't exists\n");
124 SysFreeString(path);
126 path = SysAllocString(nonexistent_dirW);
127 hr = IFileSystem3_FolderExists(fs3, path, &b);
128 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
129 ok(b == VARIANT_FALSE, "Folder exists\n");
130 SysFreeString(path);
132 path = SysAllocString(file_path);
133 hr = IFileSystem3_FolderExists(fs3, path, &b);
134 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
135 ok(b == VARIANT_FALSE, "Folder exists\n");
136 SysFreeString(path);
138 IDispatch_Release(disp);
141 static void test_createfolder(void)
143 WCHAR buffW[MAX_PATH];
144 HRESULT hr;
145 BSTR path;
146 IFolder *folder;
147 BOOL ret;
149 get_temp_path(NULL, buffW);
150 ret = CreateDirectoryW(buffW, NULL);
151 ok(ret, "got %d, %d\n", ret, GetLastError());
153 /* create existing directory */
154 path = SysAllocString(buffW);
155 folder = (void*)0xdeabeef;
156 hr = IFileSystem3_CreateFolder(fs3, path, &folder);
157 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
158 ok(folder == NULL, "got %p\n", folder);
159 SysFreeString(path);
160 RemoveDirectoryW(buffW);
163 static void test_textstream(void)
165 static const WCHAR testfileW[] = {'t','e','s','t','f','i','l','e','.','t','x','t',0};
166 ITextStream *stream;
167 VARIANT_BOOL b;
168 DWORD written;
169 HANDLE file;
170 HRESULT hr;
171 BSTR name, data;
172 BOOL ret;
174 file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
175 CloseHandle(file);
177 name = SysAllocString(testfileW);
178 b = VARIANT_FALSE;
179 hr = IFileSystem3_FileExists(fs3, name, &b);
180 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
181 ok(b == VARIANT_TRUE, "got %x\n", b);
183 /* different mode combinations */
184 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
185 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
187 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
188 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
190 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForReading, VARIANT_FALSE, TristateFalse, &stream);
191 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
193 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
194 ok(hr == S_OK, "got 0x%08x\n", hr);
195 hr = ITextStream_Read(stream, 1, &data);
196 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
197 ITextStream_Release(stream);
199 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
200 ok(hr == S_OK, "got 0x%08x\n", hr);
201 hr = ITextStream_Read(stream, 1, &data);
202 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
203 ITextStream_Release(stream);
205 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
206 ok(hr == S_OK, "got 0x%08x\n", hr);
208 /* try to write when open for reading */
209 hr = ITextStream_WriteLine(stream, name);
210 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
212 hr = ITextStream_Write(stream, name);
213 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
215 hr = ITextStream_get_AtEndOfStream(stream, NULL);
216 ok(hr == E_POINTER, "got 0x%08x\n", hr);
218 b = 10;
219 hr = ITextStream_get_AtEndOfStream(stream, &b);
220 ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr);
221 ok(b == VARIANT_TRUE, "got 0x%x\n", b);
223 ITextStream_Release(stream);
225 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
226 ok(hr == S_OK, "got 0x%08x\n", hr);
228 b = 10;
229 hr = ITextStream_get_AtEndOfStream(stream, &b);
230 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
231 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
233 b = 10;
234 hr = ITextStream_get_AtEndOfLine(stream, &b);
235 todo_wine {
236 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
237 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
239 hr = ITextStream_Read(stream, 1, &data);
240 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
242 hr = ITextStream_ReadLine(stream, &data);
243 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
245 hr = ITextStream_ReadAll(stream, &data);
246 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
248 ITextStream_Release(stream);
250 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
251 ok(hr == S_OK, "got 0x%08x\n", hr);
253 b = 10;
254 hr = ITextStream_get_AtEndOfStream(stream, &b);
255 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
256 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
258 b = 10;
259 hr = ITextStream_get_AtEndOfLine(stream, &b);
260 todo_wine {
261 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
262 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
264 hr = ITextStream_Read(stream, 1, &data);
265 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
267 hr = ITextStream_ReadLine(stream, &data);
268 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
270 hr = ITextStream_ReadAll(stream, &data);
271 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
273 ITextStream_Release(stream);
275 /* now with non-empty file */
276 file = CreateFileW(testfileW, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
277 ret = WriteFile(file, testfileW, sizeof(testfileW), &written, NULL);
278 ok(ret && written == sizeof(testfileW), "got %d\n", ret);
279 CloseHandle(file);
281 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
282 ok(hr == S_OK, "got 0x%08x\n", hr);
283 b = 10;
284 hr = ITextStream_get_AtEndOfStream(stream, &b);
285 ok(hr == S_OK, "got 0x%08x\n", hr);
286 ok(b == VARIANT_FALSE, "got 0x%x\n", b);
287 ITextStream_Release(stream);
289 SysFreeString(name);
290 DeleteFileW(testfileW);
293 static void test_GetFileVersion(void)
295 static const WCHAR k32W[] = {'\\','k','e','r','n','e','l','3','2','.','d','l','l',0};
296 static const WCHAR k33W[] = {'\\','k','e','r','n','e','l','3','3','.','d','l','l',0};
297 WCHAR pathW[MAX_PATH], filenameW[MAX_PATH];
298 BSTR path, version;
299 HRESULT hr;
301 GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
303 lstrcpyW(filenameW, pathW);
304 lstrcatW(filenameW, k32W);
306 path = SysAllocString(filenameW);
307 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
308 ok(hr == S_OK, "got 0x%08x\n", hr);
309 ok(*version != 0, "got %s\n", wine_dbgstr_w(version));
310 SysFreeString(version);
311 SysFreeString(path);
313 lstrcpyW(filenameW, pathW);
314 lstrcatW(filenameW, k33W);
316 path = SysAllocString(filenameW);
317 version = (void*)0xdeadbeef;
318 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
319 ok(broken(hr == S_OK) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
320 if (hr == S_OK)
322 ok(*version == 0, "got %s\n", wine_dbgstr_w(version));
323 SysFreeString(version);
325 else
326 ok(version == (void*)0xdeadbeef, "got %p\n", version);
327 SysFreeString(path);
330 static void test_GetParentFolderName(void)
332 static const WCHAR path1[] = {'a',0};
333 static const WCHAR path2[] = {'a','/','a','/','a',0};
334 static const WCHAR path3[] = {'a','\\','a','\\','a',0};
335 static const WCHAR path4[] = {'a','/','a','/','/','\\','\\',0};
336 static const WCHAR path5[] = {'c',':','\\','\\','a',0};
337 static const WCHAR path6[] = {'a','c',':','\\','a',0};
338 static const WCHAR result2[] = {'a','/','a',0};
339 static const WCHAR result3[] = {'a','\\','a',0};
340 static const WCHAR result4[] = {'a',0};
341 static const WCHAR result5[] = {'c',':','\\',0};
342 static const WCHAR result6[] = {'a','c',':',0};
344 static const struct {
345 const WCHAR *path;
346 const WCHAR *result;
347 } tests[] = {
348 {NULL, NULL},
349 {path1, NULL},
350 {path2, result2},
351 {path3, result3},
352 {path4, result4},
353 {path5, result5},
354 {path6, result6}
357 BSTR path, result;
358 HRESULT hr;
359 int i;
361 hr = IFileSystem3_GetParentFolderName(fs3, NULL, NULL);
362 ok(hr == E_POINTER, "GetParentFolderName returned %x, expected E_POINTER\n", hr);
364 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
365 result = (BSTR)0xdeadbeef;
366 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
367 hr = IFileSystem3_GetParentFolderName(fs3, path, &result);
368 ok(hr == S_OK, "%d) GetParentFolderName returned %x, expected S_OK\n", i, hr);
369 if(!tests[i].result)
370 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
371 else
372 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
373 SysFreeString(path);
374 SysFreeString(result);
378 static void test_GetFileName(void)
380 static const WCHAR path1[] = {'a',0};
381 static const WCHAR path2[] = {'a','/','a','.','b',0};
382 static const WCHAR path3[] = {'a','\\',0};
383 static const WCHAR path4[] = {'c',':',0};
384 static const WCHAR path5[] = {'/','\\',0};
385 static const WCHAR result2[] = {'a','.','b',0};
386 static const WCHAR result3[] = {'a',0};
388 static const struct {
389 const WCHAR *path;
390 const WCHAR *result;
391 } tests[] = {
392 {NULL, NULL},
393 {path1, path1},
394 {path2, result2},
395 {path3, result3},
396 {path4, NULL},
397 {path5, NULL}
400 BSTR path, result;
401 HRESULT hr;
402 int i;
404 hr = IFileSystem3_GetFileName(fs3, NULL, NULL);
405 ok(hr == E_POINTER, "GetFileName returned %x, expected E_POINTER\n", hr);
407 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
408 result = (BSTR)0xdeadbeef;
409 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
410 hr = IFileSystem3_GetFileName(fs3, path, &result);
411 ok(hr == S_OK, "%d) GetFileName returned %x, expected S_OK\n", i, hr);
412 if(!tests[i].result)
413 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
414 else
415 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
416 SysFreeString(path);
417 SysFreeString(result);
421 static void test_GetBaseName(void)
423 static const WCHAR path1[] = {'a',0};
424 static const WCHAR path2[] = {'a','/','a','.','b','.','c',0};
425 static const WCHAR path3[] = {'a','.','b','\\',0};
426 static const WCHAR path4[] = {'c',':',0};
427 static const WCHAR path5[] = {'/','\\',0};
428 static const WCHAR path6[] = {'.','a',0};
429 static const WCHAR result1[] = {'a',0};
430 static const WCHAR result2[] = {'a','.','b',0};
431 static const WCHAR result6[] = {0};
433 static const struct {
434 const WCHAR *path;
435 const WCHAR *result;
436 } tests[] = {
437 {NULL, NULL},
438 {path1, result1},
439 {path2, result2},
440 {path3, result1},
441 {path4, NULL},
442 {path5, NULL},
443 {path6, result6}
446 BSTR path, result;
447 HRESULT hr;
448 int i;
450 hr = IFileSystem3_GetBaseName(fs3, NULL, NULL);
451 ok(hr == E_POINTER, "GetBaseName returned %x, expected E_POINTER\n", hr);
453 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
454 result = (BSTR)0xdeadbeef;
455 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
456 hr = IFileSystem3_GetBaseName(fs3, path, &result);
457 ok(hr == S_OK, "%d) GetBaseName returned %x, expected S_OK\n", i, hr);
458 if(!tests[i].result)
459 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
460 else
461 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
462 SysFreeString(path);
463 SysFreeString(result);
467 static void test_GetAbsolutePathName(void)
469 static const WCHAR dir1[] = {'t','e','s','t','_','d','i','r','1',0};
470 static const WCHAR dir2[] = {'t','e','s','t','_','d','i','r','2',0};
471 static const WCHAR dir_match1[] = {'t','e','s','t','_','d','i','r','*',0};
472 static const WCHAR dir_match2[] = {'t','e','s','t','_','d','i','*',0};
473 static const WCHAR cur_dir[] = {'.',0};
475 WIN32_FIND_DATAW fdata;
476 HANDLE find;
477 WCHAR buf[MAX_PATH], buf2[MAX_PATH];
478 BSTR path, result;
479 HRESULT hr;
481 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, NULL);
482 ok(hr == E_POINTER, "GetAbsolutePathName returned %x, expected E_POINTER\n", hr);
484 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result);
485 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
486 GetFullPathNameW(cur_dir, MAX_PATH, buf, NULL);
487 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
488 SysFreeString(result);
490 find = FindFirstFileW(dir_match2, &fdata);
491 if(find != INVALID_HANDLE_VALUE) {
492 skip("GetAbsolutePathName tests\n");
493 FindClose(find);
494 return;
497 path = SysAllocString(dir_match1);
498 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
499 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
500 GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL);
501 ok(!lstrcmpiW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2));
502 SysFreeString(result);
504 ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1));
505 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
506 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
507 GetFullPathNameW(dir1, MAX_PATH, buf, NULL);
508 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
509 wine_dbgstr_w(result), wine_dbgstr_w(buf));
510 SysFreeString(result);
512 ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2));
513 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
514 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
515 if(!lstrcmpiW(buf, result) || !lstrcmpiW(buf2, result)) {
516 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
517 wine_dbgstr_w(result), wine_dbgstr_w(buf));
518 }else {
519 GetFullPathNameW(dir2, MAX_PATH, buf, NULL);
520 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n",
521 wine_dbgstr_w(result), wine_dbgstr_w(buf));
523 SysFreeString(result);
525 SysFreeString(path);
526 path = SysAllocString(dir_match2);
527 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
528 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
529 GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL);
530 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
531 SysFreeString(result);
532 SysFreeString(path);
534 RemoveDirectoryW(dir1);
535 RemoveDirectoryW(dir2);
538 static void test_GetFile(void)
540 static const WCHAR slW[] = {'\\',0};
541 BSTR path;
542 WCHAR pathW[MAX_PATH];
543 FileAttribute fa;
544 VARIANT size;
545 DWORD gfa;
546 IFile *file;
547 HRESULT hr;
548 HANDLE hf;
549 BOOL ret;
551 get_temp_path(NULL, pathW);
553 path = SysAllocString(pathW);
554 hr = IFileSystem3_GetFile(fs3, path, NULL);
555 ok(hr == E_POINTER, "GetFile returned %x, expected E_POINTER\n", hr);
556 hr = IFileSystem3_GetFile(fs3, NULL, &file);
557 ok(hr == E_INVALIDARG, "GetFile returned %x, expected E_INVALIDARG\n", hr);
559 file = (IFile*)0xdeadbeef;
560 hr = IFileSystem3_GetFile(fs3, path, &file);
561 ok(!file, "file != NULL\n");
562 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
564 hf = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
565 if(hf == INVALID_HANDLE_VALUE) {
566 skip("Can't create temporary file\n");
567 SysFreeString(path);
568 return;
570 CloseHandle(hf);
572 hr = IFileSystem3_GetFile(fs3, path, &file);
573 ok(hr == S_OK, "GetFile returned %x, expected S_OK\n", hr);
575 hr = IFile_get_Attributes(file, &fa);
576 gfa = GetFileAttributesW(pathW) & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
577 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE |
578 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED);
579 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
580 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa);
582 hr = IFile_get_Size(file, &size);
583 ok(hr == S_OK, "get_Size returned %x, expected S_OK\n", hr);
584 ok(V_VT(&size) == VT_I4, "V_VT(&size) = %d, expected VT_I4\n", V_VT(&size));
585 ok(V_I4(&size) == 0, "V_I4(&size) = %d, expected 0\n", V_I4(&size));
586 IFile_Release(file);
588 hr = IFileSystem3_DeleteFile(fs3, path, FALSE);
589 ok(hr==CTL_E_PERMISSIONDENIED || broken(hr==S_OK),
590 "DeleteFile returned %x, expected CTL_E_PERMISSIONDENIED\n", hr);
591 if(hr != S_OK) {
592 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
593 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
595 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
596 ok(hr == CTL_E_FILENOTFOUND, "DeleteFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
598 SysFreeString(path);
600 /* try with directory */
601 lstrcatW(pathW, slW);
602 ret = CreateDirectoryW(pathW, NULL);
603 ok(ret, "got %d, error %d\n", ret, GetLastError());
605 path = SysAllocString(pathW);
606 hr = IFileSystem3_GetFile(fs3, path, &file);
607 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected S_OK\n", hr);
608 SysFreeString(path);
610 RemoveDirectoryW(pathW);
613 static inline BOOL create_file(const WCHAR *name)
615 HANDLE f = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
616 CloseHandle(f);
617 return f != INVALID_HANDLE_VALUE;
620 static inline void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret)
622 DWORD len = lstrlenW(folder);
623 memmove(ret, folder, len*sizeof(WCHAR));
624 ret[len] = '\\';
625 memmove(ret+len+1, name, (lstrlenW(name)+1)*sizeof(WCHAR));
628 static void test_CopyFolder(void)
630 static const WCHAR filesystem3_dir[] = {'f','i','l','e','s','y','s','t','e','m','3','_','t','e','s','t',0};
631 static const WCHAR s1[] = {'s','r','c','1',0};
632 static const WCHAR s[] = {'s','r','c','*',0};
633 static const WCHAR d[] = {'d','s','t',0};
634 static const WCHAR empty[] = {0};
636 WCHAR tmp[MAX_PATH];
637 BSTR bsrc, bdst;
638 HRESULT hr;
640 if(!CreateDirectoryW(filesystem3_dir, NULL)) {
641 skip("can't create temporary directory\n");
642 return;
645 create_path(filesystem3_dir, s1, tmp);
646 bsrc = SysAllocString(tmp);
647 create_path(filesystem3_dir, d, tmp);
648 bdst = SysAllocString(tmp);
649 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
650 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
652 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
653 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
655 ok(create_file(bsrc), "can't create %s file\n", wine_dbgstr_w(bsrc));
656 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
657 ok(hr == S_OK, "CopyFile returned %x, expected S_OK\n", hr);
659 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
660 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
662 hr = IFileSystem3_DeleteFile(fs3, bsrc, VARIANT_FALSE);
663 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
665 ok(CreateDirectoryW(bsrc, NULL), "can't create %s\n", wine_dbgstr_w(bsrc));
666 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
667 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
669 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
670 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
672 hr = IFileSystem3_DeleteFile(fs3, bdst, VARIANT_TRUE);
673 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
675 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
676 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
678 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
679 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
680 create_path(tmp, s1, tmp);
681 ok(GetFileAttributesW(tmp) == INVALID_FILE_ATTRIBUTES,
682 "%s file exists\n", wine_dbgstr_w(tmp));
684 create_path(filesystem3_dir, d, tmp);
685 create_path(tmp, empty, tmp);
686 SysFreeString(bdst);
687 bdst = SysAllocString(tmp);
688 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
689 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
690 create_path(tmp, s1, tmp);
691 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
692 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
693 ok(RemoveDirectoryW(tmp), "can't remove %s directory\n", wine_dbgstr_w(tmp));
694 create_path(filesystem3_dir, d, tmp);
695 SysFreeString(bdst);
696 bdst = SysAllocString(tmp);
699 create_path(filesystem3_dir, s, tmp);
700 SysFreeString(bsrc);
701 bsrc = SysAllocString(tmp);
702 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
703 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
704 create_path(filesystem3_dir, d, tmp);
705 create_path(tmp, s1, tmp);
706 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
707 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
709 hr = IFileSystem3_DeleteFolder(fs3, bdst, VARIANT_FALSE);
710 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
712 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
713 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
715 create_path(filesystem3_dir, s1, tmp);
716 SysFreeString(bsrc);
717 bsrc = SysAllocString(tmp);
718 create_path(tmp, s1, tmp);
719 ok(create_file(tmp), "can't create %s file\n", wine_dbgstr_w(tmp));
720 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
721 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
723 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
724 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
726 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
727 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
728 SysFreeString(bsrc);
729 SysFreeString(bdst);
731 bsrc = SysAllocString(filesystem3_dir);
732 hr = IFileSystem3_DeleteFolder(fs3, bsrc, VARIANT_FALSE);
733 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
734 SysFreeString(bsrc);
737 static BSTR bstr_from_str(const char *str)
739 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
740 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */
741 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
742 return ret;
745 struct buildpath_test
747 const char *path;
748 const char *name;
749 const char *result;
752 static struct buildpath_test buildpath_data[] =
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:\\path\\\\", "\\\\name.tmp", "C:\\path\\\\\\name.tmp" },
762 { "C:\\\\", "\\name.tmp", "C:\\\\name.tmp" },
763 { "C:", "name.tmp", "C:name.tmp" },
764 { "C:", "\\\\name.tmp", "C:\\\\name.tmp" },
765 { NULL }
768 static void test_BuildPath(void)
770 struct buildpath_test *ptr = buildpath_data;
771 BSTR ret, path;
772 HRESULT hr;
773 int i = 0;
775 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, NULL);
776 ok(hr == E_POINTER, "got 0x%08x\n", hr);
778 ret = (BSTR)0xdeadbeef;
779 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, &ret);
780 ok(hr == S_OK, "got 0x%08x\n", hr);
781 ok(*ret == 0, "got %p\n", ret);
782 SysFreeString(ret);
784 ret = (BSTR)0xdeadbeef;
785 path = bstr_from_str("path");
786 hr = IFileSystem3_BuildPath(fs3, path, NULL, &ret);
787 ok(hr == S_OK, "got 0x%08x\n", hr);
788 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
789 SysFreeString(ret);
790 SysFreeString(path);
792 ret = (BSTR)0xdeadbeef;
793 path = bstr_from_str("path");
794 hr = IFileSystem3_BuildPath(fs3, NULL, path, &ret);
795 ok(hr == S_OK, "got 0x%08x\n", hr);
796 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
797 SysFreeString(ret);
798 SysFreeString(path);
800 while (ptr->path)
802 BSTR name, result;
804 ret = NULL;
805 path = bstr_from_str(ptr->path);
806 name = bstr_from_str(ptr->name);
807 result = bstr_from_str(ptr->result);
808 hr = IFileSystem3_BuildPath(fs3, path, name, &ret);
809 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
810 if (hr == S_OK)
812 ok(!lstrcmpW(ret, result), "%d: got wrong path %s, expected %s\n", i, wine_dbgstr_w(ret),
813 wine_dbgstr_w(result));
814 SysFreeString(ret);
816 SysFreeString(path);
817 SysFreeString(name);
818 SysFreeString(result);
820 i++;
821 ptr++;
825 static void test_GetFolder(void)
827 static const WCHAR dummyW[] = {'d','u','m','m','y',0};
828 WCHAR buffW[MAX_PATH];
829 IFolder *folder;
830 HRESULT hr;
831 BSTR str;
833 folder = (void*)0xdeadbeef;
834 hr = IFileSystem3_GetFolder(fs3, NULL, &folder);
835 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
836 ok(folder == NULL, "got %p\n", folder);
838 hr = IFileSystem3_GetFolder(fs3, NULL, NULL);
839 ok(hr == E_POINTER, "got 0x%08x\n", hr);
841 /* something that doesn't exist */
842 str = SysAllocString(dummyW);
844 hr = IFileSystem3_GetFolder(fs3, str, NULL);
845 ok(hr == E_POINTER, "got 0x%08x\n", hr);
847 folder = (void*)0xdeadbeef;
848 hr = IFileSystem3_GetFolder(fs3, str, &folder);
849 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
850 ok(folder == NULL, "got %p\n", folder);
851 SysFreeString(str);
853 GetWindowsDirectoryW(buffW, MAX_PATH);
854 str = SysAllocString(buffW);
855 hr = IFileSystem3_GetFolder(fs3, str, &folder);
856 ok(hr == S_OK, "got 0x%08x\n", hr);
857 SysFreeString(str);
858 IFolder_Release(folder);
861 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
862 static void test_FolderCollection(void)
864 static const WCHAR fooW[] = {'f','o','o',0};
865 static const WCHAR aW[] = {'\\','a',0};
866 static const WCHAR bW[] = {'\\','b',0};
867 static const WCHAR cW[] = {'\\','c',0};
868 IFolderCollection *folders;
869 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
870 IEnumVARIANT *enumvar, *clone;
871 LONG count, ref, ref2, i;
872 IUnknown *unk, *unk2;
873 IFolder *folder;
874 ULONG fetched;
875 VARIANT var, var2[2];
876 HRESULT hr;
877 BSTR str;
878 int found_a = 0, found_b = 0, found_c = 0;
880 get_temp_path(fooW, buffW);
881 CreateDirectoryW(buffW, NULL);
883 str = SysAllocString(buffW);
884 hr = IFileSystem3_GetFolder(fs3, str, &folder);
885 ok(hr == S_OK, "got 0x%08x\n", hr);
886 SysFreeString(str);
888 hr = IFolder_get_SubFolders(folder, NULL);
889 ok(hr == E_POINTER, "got 0x%08x\n", hr);
891 hr = IFolder_get_Path(folder, NULL);
892 ok(hr == E_POINTER, "got 0x%08x\n", hr);
894 hr = IFolder_get_Path(folder, &str);
895 ok(hr == S_OK, "got 0x%08x\n", hr);
896 ok(!lstrcmpiW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
897 SysFreeString(str);
899 lstrcpyW(pathW, buffW);
900 lstrcatW(pathW, aW);
901 CreateDirectoryW(pathW, NULL);
903 lstrcpyW(pathW, buffW);
904 lstrcatW(pathW, bW);
905 CreateDirectoryW(pathW, NULL);
907 hr = IFolder_get_SubFolders(folder, &folders);
908 ok(hr == S_OK, "got 0x%08x\n", hr);
909 IFolder_Release(folder);
911 count = 0;
912 hr = IFolderCollection_get_Count(folders, &count);
913 ok(hr == S_OK, "got 0x%08x\n", hr);
914 ok(count == 2, "got %d\n", count);
916 lstrcpyW(pathW, buffW);
917 lstrcatW(pathW, cW);
918 CreateDirectoryW(pathW, NULL);
920 /* every time property is requested it scans directory */
921 count = 0;
922 hr = IFolderCollection_get_Count(folders, &count);
923 ok(hr == S_OK, "got 0x%08x\n", hr);
924 ok(count == 3, "got %d\n", count);
926 hr = IFolderCollection_get__NewEnum(folders, NULL);
927 ok(hr == E_POINTER, "got 0x%08x\n", hr);
929 hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk);
930 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
932 /* NewEnum creates new instance each time it's called */
933 ref = GET_REFCOUNT(folders);
935 unk = NULL;
936 hr = IFolderCollection_get__NewEnum(folders, &unk);
937 ok(hr == S_OK, "got 0x%08x\n", hr);
939 ref2 = GET_REFCOUNT(folders);
940 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
942 unk2 = NULL;
943 hr = IFolderCollection_get__NewEnum(folders, &unk2);
944 ok(hr == S_OK, "got 0x%08x\n", hr);
945 ok(unk != unk2, "got %p, %p\n", unk2, unk);
946 IUnknown_Release(unk2);
948 /* now get IEnumVARIANT */
949 ref = GET_REFCOUNT(folders);
950 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
951 ok(hr == S_OK, "got 0x%08x\n", hr);
952 ref2 = GET_REFCOUNT(folders);
953 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
955 /* clone enumerator */
956 hr = IEnumVARIANT_Clone(enumvar, &clone);
957 ok(hr == S_OK, "got 0x%08x\n", hr);
958 ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
959 IEnumVARIANT_Release(clone);
961 hr = IEnumVARIANT_Reset(enumvar);
962 ok(hr == S_OK, "got 0x%08x\n", hr);
964 for (i = 0; i < 3; i++)
966 VariantInit(&var);
967 fetched = 0;
968 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
969 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
970 ok(fetched == 1, "%d: got %d\n", i, fetched);
971 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
973 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder);
974 ok(hr == S_OK, "got 0x%08x\n", hr);
976 str = NULL;
977 hr = IFolder_get_Name(folder, &str);
978 ok(hr == S_OK, "got 0x%08x\n", hr);
979 if (!lstrcmpW(str, aW + 1))
980 found_a++;
981 else if (!lstrcmpW(str, bW + 1))
982 found_b++;
983 else if (!lstrcmpW(str, cW + 1))
984 found_c++;
985 else
986 ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str));
987 SysFreeString(str);
989 IFolder_Release(folder);
990 VariantClear(&var);
993 ok(found_a == 1 && found_b == 1 && found_c == 1,
994 "each folder should be found 1 time instead of %d/%d/%d\n",
995 found_a, found_b, found_c);
997 VariantInit(&var);
998 fetched = -1;
999 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1000 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1001 ok(fetched == 0, "got %d\n", fetched);
1003 hr = IEnumVARIANT_Reset(enumvar);
1004 ok(hr == S_OK, "got 0x%08x\n", hr);
1005 hr = IEnumVARIANT_Skip(enumvar, 2);
1006 ok(hr == S_OK, "got 0x%08x\n", hr);
1007 hr = IEnumVARIANT_Skip(enumvar, 0);
1008 ok(hr == S_OK, "got 0x%08x\n", hr);
1010 VariantInit(&var2[0]);
1011 VariantInit(&var2[1]);
1012 fetched = -1;
1013 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1014 ok(hr == S_OK, "got 0x%08x\n", hr);
1015 ok(fetched == 0, "got %d\n", fetched);
1016 fetched = -1;
1017 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1018 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1019 ok(fetched == 1, "got %d\n", fetched);
1020 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1021 VariantClear(&var2[0]);
1022 VariantClear(&var2[1]);
1024 IEnumVARIANT_Release(enumvar);
1025 IUnknown_Release(unk);
1027 lstrcpyW(pathW, buffW);
1028 lstrcatW(pathW, aW);
1029 RemoveDirectoryW(pathW);
1030 lstrcpyW(pathW, buffW);
1031 lstrcatW(pathW, bW);
1032 RemoveDirectoryW(pathW);
1033 lstrcpyW(pathW, buffW);
1034 lstrcatW(pathW, cW);
1035 RemoveDirectoryW(pathW);
1036 RemoveDirectoryW(buffW);
1038 IFolderCollection_Release(folders);
1041 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
1042 static void test_FileCollection(void)
1044 static const WCHAR fooW[] = {'\\','f','o','o',0};
1045 static const WCHAR aW[] = {'\\','a',0};
1046 static const WCHAR bW[] = {'\\','b',0};
1047 static const WCHAR cW[] = {'\\','c',0};
1048 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
1049 IFolder *folder;
1050 IFileCollection *files;
1051 IFile *file;
1052 IEnumVARIANT *enumvar, *clone;
1053 LONG count, ref, ref2, i;
1054 IUnknown *unk, *unk2;
1055 ULONG fetched;
1056 VARIANT var, var2[2];
1057 HRESULT hr;
1058 BSTR str;
1059 HANDLE file_a, file_b, file_c;
1060 int found_a = 0, found_b = 0, found_c = 0;
1062 get_temp_path(fooW, buffW);
1063 CreateDirectoryW(buffW, NULL);
1065 str = SysAllocString(buffW);
1066 hr = IFileSystem3_GetFolder(fs3, str, &folder);
1067 ok(hr == S_OK, "got 0x%08x\n", hr);
1068 SysFreeString(str);
1070 hr = IFolder_get_Files(folder, NULL);
1071 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1073 lstrcpyW(pathW, buffW);
1074 lstrcatW(pathW, aW);
1075 file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1076 FILE_FLAG_DELETE_ON_CLOSE, 0);
1077 lstrcpyW(pathW, buffW);
1078 lstrcatW(pathW, bW);
1079 file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1080 FILE_FLAG_DELETE_ON_CLOSE, 0);
1082 hr = IFolder_get_Files(folder, &files);
1083 ok(hr == S_OK, "got 0x%08x\n", hr);
1084 IFolder_Release(folder);
1086 count = 0;
1087 hr = IFileCollection_get_Count(files, &count);
1088 ok(hr == S_OK, "got 0x%08x\n", hr);
1089 ok(count == 2, "got %d\n", count);
1091 lstrcpyW(pathW, buffW);
1092 lstrcatW(pathW, cW);
1093 file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1094 FILE_FLAG_DELETE_ON_CLOSE, 0);
1096 /* every time property is requested it scans directory */
1097 count = 0;
1098 hr = IFileCollection_get_Count(files, &count);
1099 ok(hr == S_OK, "got 0x%08x\n", hr);
1100 ok(count == 3, "got %d\n", count);
1102 hr = IFileCollection_get__NewEnum(files, NULL);
1103 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1105 hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk);
1106 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1108 /* NewEnum creates new instance each time it's called */
1109 ref = GET_REFCOUNT(files);
1111 unk = NULL;
1112 hr = IFileCollection_get__NewEnum(files, &unk);
1113 ok(hr == S_OK, "got 0x%08x\n", hr);
1115 ref2 = GET_REFCOUNT(files);
1116 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1118 unk2 = NULL;
1119 hr = IFileCollection_get__NewEnum(files, &unk2);
1120 ok(hr == S_OK, "got 0x%08x\n", hr);
1121 ok(unk != unk2, "got %p, %p\n", unk2, unk);
1122 IUnknown_Release(unk2);
1124 /* now get IEnumVARIANT */
1125 ref = GET_REFCOUNT(files);
1126 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1127 ok(hr == S_OK, "got 0x%08x\n", hr);
1128 ref2 = GET_REFCOUNT(files);
1129 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1131 /* clone enumerator */
1132 hr = IEnumVARIANT_Clone(enumvar, &clone);
1133 ok(hr == S_OK, "got 0x%08x\n", hr);
1134 ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
1135 IEnumVARIANT_Release(clone);
1137 hr = IEnumVARIANT_Reset(enumvar);
1138 ok(hr == S_OK, "got 0x%08x\n", hr);
1140 for (i = 0; i < 3; i++)
1142 VariantInit(&var);
1143 fetched = 0;
1144 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1145 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1146 ok(fetched == 1, "%d: got %d\n", i, fetched);
1147 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1149 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file);
1150 ok(hr == S_OK, "got 0x%08x\n", hr);
1152 str = NULL;
1153 hr = IFile_get_Name(file, &str);
1154 ok(hr == S_OK, "got 0x%08x\n", hr);
1155 if (!lstrcmpW(str, aW + 1))
1156 found_a++;
1157 else if (!lstrcmpW(str, bW + 1))
1158 found_b++;
1159 else if (!lstrcmpW(str, cW + 1))
1160 found_c++;
1161 else
1162 ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str));
1163 SysFreeString(str);
1165 IFile_Release(file);
1166 VariantClear(&var);
1169 ok(found_a == 1 && found_b == 1 && found_c == 1,
1170 "each file should be found 1 time instead of %d/%d/%d\n",
1171 found_a, found_b, found_c);
1173 VariantInit(&var);
1174 fetched = -1;
1175 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1176 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1177 ok(fetched == 0, "got %d\n", fetched);
1179 hr = IEnumVARIANT_Reset(enumvar);
1180 ok(hr == S_OK, "got 0x%08x\n", hr);
1181 hr = IEnumVARIANT_Skip(enumvar, 2);
1182 ok(hr == S_OK, "got 0x%08x\n", hr);
1183 hr = IEnumVARIANT_Skip(enumvar, 0);
1184 ok(hr == S_OK, "got 0x%08x\n", hr);
1186 VariantInit(&var2[0]);
1187 VariantInit(&var2[1]);
1188 fetched = -1;
1189 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1190 ok(hr == S_OK, "got 0x%08x\n", hr);
1191 ok(fetched == 0, "got %d\n", fetched);
1192 fetched = -1;
1193 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1194 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1195 ok(fetched == 1, "got %d\n", fetched);
1196 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1197 VariantClear(&var2[0]);
1198 VariantClear(&var2[1]);
1200 IEnumVARIANT_Release(enumvar);
1201 IUnknown_Release(unk);
1203 CloseHandle(file_a);
1204 CloseHandle(file_b);
1205 CloseHandle(file_c);
1206 RemoveDirectoryW(buffW);
1208 IFileCollection_Release(files);
1211 static void test_DriveCollection(void)
1213 IDriveCollection *drives;
1214 IEnumVARIANT *enumvar;
1215 ULONG fetched;
1216 VARIANT var;
1217 HRESULT hr;
1218 LONG count;
1220 hr = IFileSystem3_get_Drives(fs3, &drives);
1221 ok(hr == S_OK, "got 0x%08x\n", hr);
1223 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar);
1224 ok(hr == S_OK, "got 0x%08x\n", hr);
1226 hr = IDriveCollection_get_Count(drives, NULL);
1227 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1229 count = 0;
1230 hr = IDriveCollection_get_Count(drives, &count);
1231 ok(hr == S_OK, "got 0x%08x\n", hr);
1232 ok(count > 0, "got %d\n", count);
1234 V_VT(&var) = VT_EMPTY;
1235 fetched = -1;
1236 hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched);
1237 ok(hr == S_OK, "got 0x%08x\n", hr);
1238 ok(fetched == 0, "got %d\n", fetched);
1240 hr = IEnumVARIANT_Skip(enumvar, 0);
1241 ok(hr == S_OK, "got 0x%08x\n", hr);
1243 hr = IEnumVARIANT_Skip(enumvar, count);
1244 ok(hr == S_OK, "got 0x%08x\n", hr);
1246 hr = IEnumVARIANT_Skip(enumvar, 1);
1247 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1249 /* reset and iterate again */
1250 hr = IEnumVARIANT_Reset(enumvar);
1251 ok(hr == S_OK, "got 0x%08x\n", hr);
1253 while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) {
1254 IDrive *drive = (IDrive*)V_DISPATCH(&var);
1255 DriveTypeConst type;
1256 BSTR str;
1258 hr = IDrive_get_DriveType(drive, &type);
1259 ok(hr == S_OK, "got 0x%08x\n", hr);
1261 hr = IDrive_get_DriveLetter(drive, NULL);
1262 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1264 hr = IDrive_get_DriveLetter(drive, &str);
1265 ok(hr == S_OK, "got 0x%08x\n", hr);
1266 ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str));
1267 SysFreeString(str);
1269 hr = IDrive_get_IsReady(drive, NULL);
1270 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1272 hr = IDrive_get_TotalSize(drive, NULL);
1273 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1275 hr = IDrive_get_AvailableSpace(drive, NULL);
1276 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1278 hr = IDrive_get_FreeSpace(drive, NULL);
1279 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1281 if (type == Fixed) {
1282 VARIANT_BOOL ready = VARIANT_FALSE;
1283 VARIANT size;
1285 hr = IDrive_get_IsReady(drive, &ready);
1286 ok(hr == S_OK, "got 0x%08x\n", hr);
1287 ok(ready == VARIANT_TRUE, "got %x\n", ready);
1289 V_VT(&size) = VT_EMPTY;
1290 hr = IDrive_get_TotalSize(drive, &size);
1291 ok(hr == S_OK, "got 0x%08x\n", hr);
1292 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1293 if (V_VT(&size) == VT_R8)
1294 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1295 else
1296 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1298 V_VT(&size) = VT_EMPTY;
1299 hr = IDrive_get_AvailableSpace(drive, &size);
1300 ok(hr == S_OK, "got 0x%08x\n", hr);
1301 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1302 if (V_VT(&size) == VT_R8)
1303 ok(V_R8(&size) > (double)INT_MAX, "got %f\n", V_R8(&size));
1304 else
1305 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1307 V_VT(&size) = VT_EMPTY;
1308 hr = IDrive_get_FreeSpace(drive, &size);
1309 ok(hr == S_OK, "got 0x%08x\n", hr);
1310 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1311 if (V_VT(&size) == VT_R8)
1312 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1313 else
1314 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1316 VariantClear(&var);
1319 IEnumVARIANT_Release(enumvar);
1320 IDriveCollection_Release(drives);
1323 static void test_CreateTextFile(void)
1325 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1326 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1327 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[10];
1328 ITextStream *stream;
1329 BSTR nameW, str;
1330 HANDLE file;
1331 HRESULT hr;
1332 BOOL ret;
1334 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1335 lstrcatW(pathW, scrrunW);
1336 lstrcpyW(dirW, pathW);
1337 lstrcatW(pathW, testfileW);
1339 /* dir doesn't exist */
1340 nameW = SysAllocString(pathW);
1341 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1342 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
1344 ret = CreateDirectoryW(dirW, NULL);
1345 ok(ret, "got %d, %d\n", ret, GetLastError());
1347 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1348 ok(hr == S_OK, "got 0x%08x\n", hr);
1350 hr = ITextStream_Read(stream, 1, &str);
1351 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1353 ITextStream_Release(stream);
1355 /* check it's created */
1356 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1357 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1358 CloseHandle(file);
1360 /* try to create again with no-overwrite mode */
1361 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1362 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
1364 /* now overwrite */
1365 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1366 ok(hr == S_OK, "got 0x%08x\n", hr);
1367 ITextStream_Release(stream);
1369 /* overwrite in Unicode mode, check for BOM */
1370 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
1371 ok(hr == S_OK, "got 0x%08x\n", hr);
1372 ITextStream_Release(stream);
1374 /* File was created in Unicode mode, it contains 0xfffe BOM. Opening it in non-Unicode mode
1375 treats BOM like a valuable data with appropriate CP_ACP -> WCHAR conversion. */
1376 buffW[0] = 0;
1377 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR));
1379 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1380 ok(hr == S_OK, "got 0x%08x\n", hr);
1381 hr = ITextStream_ReadAll(stream, &str);
1382 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1383 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1384 SysFreeString(str);
1385 ITextStream_Release(stream);
1387 DeleteFileW(nameW);
1388 RemoveDirectoryW(dirW);
1389 SysFreeString(nameW);
1392 static void test_WriteLine(void)
1394 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1395 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1396 WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
1397 WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
1398 char buffA[MAX_PATH];
1399 ITextStream *stream;
1400 DWORD r, len;
1401 HANDLE file;
1402 BSTR nameW;
1403 HRESULT hr;
1404 BOOL ret;
1406 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1407 lstrcatW(pathW, scrrunW);
1408 lstrcpyW(dirW, pathW);
1409 lstrcatW(pathW, testfileW);
1411 ret = CreateDirectoryW(dirW, NULL);
1412 ok(ret, "got %d, %d\n", ret, GetLastError());
1414 /* create as ASCII file first */
1415 nameW = SysAllocString(pathW);
1416 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1417 ok(hr == S_OK, "got 0x%08x\n", hr);
1419 hr = ITextStream_WriteLine(stream, nameW);
1420 ok(hr == S_OK, "got 0x%08x\n", hr);
1421 ITextStream_Release(stream);
1423 /* check contents */
1424 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1425 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1426 r = 0;
1427 ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL);
1428 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1430 len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, sizeof(buffW)/sizeof(WCHAR));
1431 buffW[len] = 0;
1432 lstrcpyW(buff2W, nameW);
1433 lstrcatW(buff2W, crlfW);
1434 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1435 CloseHandle(file);
1436 DeleteFileW(nameW);
1438 /* same for unicode file */
1439 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1440 ok(hr == S_OK, "got 0x%08x\n", hr);
1442 hr = ITextStream_WriteLine(stream, nameW);
1443 ok(hr == S_OK, "got 0x%08x\n", hr);
1444 ITextStream_Release(stream);
1446 /* check contents */
1447 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1448 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1449 r = 0;
1450 ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL);
1451 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1452 buffW[r/sizeof(WCHAR)] = 0;
1454 buff2W[0] = 0xfeff;
1455 buff2W[1] = 0;
1456 lstrcatW(buff2W, nameW);
1457 lstrcatW(buff2W, crlfW);
1458 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1459 CloseHandle(file);
1460 DeleteFileW(nameW);
1462 RemoveDirectoryW(dirW);
1463 SysFreeString(nameW);
1466 static void test_ReadAll(void)
1468 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1469 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1470 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1471 static const WCHAR aW[] = {'A',0};
1472 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1473 ITextStream *stream;
1474 BSTR nameW;
1475 HRESULT hr;
1476 BOOL ret;
1477 BSTR str;
1479 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1480 lstrcatW(pathW, scrrunW);
1481 lstrcpyW(dirW, pathW);
1482 lstrcatW(pathW, testfileW);
1484 ret = CreateDirectoryW(dirW, NULL);
1485 ok(ret, "got %d, %d\n", ret, GetLastError());
1487 /* Unicode file -> read with ascii stream */
1488 nameW = SysAllocString(pathW);
1489 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1490 ok(hr == S_OK, "got 0x%08x\n", hr);
1492 hr = ITextStream_WriteLine(stream, nameW);
1493 ok(hr == S_OK, "got 0x%08x\n", hr);
1495 str = SysAllocString(secondlineW);
1496 hr = ITextStream_WriteLine(stream, str);
1497 ok(hr == S_OK, "got 0x%08x\n", hr);
1498 SysFreeString(str);
1500 hr = ITextStream_ReadAll(stream, NULL);
1501 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1503 str = (void*)0xdeadbeef;
1504 hr = ITextStream_ReadAll(stream, &str);
1505 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1506 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1508 ITextStream_Release(stream);
1510 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1511 ok(hr == S_OK, "got 0x%08x\n", hr);
1513 hr = ITextStream_ReadAll(stream, NULL);
1514 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1516 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1517 str = NULL;
1518 hr = ITextStream_ReadAll(stream, &str);
1519 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1520 buffW[0] = 0;
1521 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR));
1522 ok(str[0] == buffW[0] && str[1] == buffW[1], "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
1523 SysFreeString(str);
1524 ITextStream_Release(stream);
1526 /* Unicode file -> read with unicode stream */
1527 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1528 ok(hr == S_OK, "got 0x%08x\n", hr);
1530 lstrcpyW(buffW, nameW);
1531 lstrcatW(buffW, crlfW);
1532 lstrcatW(buffW, secondlineW);
1533 lstrcatW(buffW, crlfW);
1534 str = NULL;
1535 hr = ITextStream_ReadAll(stream, &str);
1536 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1537 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1538 SysFreeString(str);
1540 /* ReadAll one more time */
1541 str = (void*)0xdeadbeef;
1542 hr = ITextStream_ReadAll(stream, &str);
1543 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1544 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1546 /* ReadLine fails the same way */
1547 str = (void*)0xdeadbeef;
1548 hr = ITextStream_ReadLine(stream, &str);
1549 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1550 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1551 ITextStream_Release(stream);
1553 /* Open again and skip first line before ReadAll */
1554 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1555 ok(hr == S_OK, "got 0x%08x\n", hr);
1557 str = NULL;
1558 hr = ITextStream_ReadLine(stream, &str);
1559 todo_wine {
1560 ok(hr == S_OK, "got 0x%08x\n", hr);
1561 ok(str != NULL, "got %p\n", str);
1563 SysFreeString(str);
1565 lstrcpyW(buffW, secondlineW);
1566 lstrcatW(buffW, crlfW);
1567 str = NULL;
1568 hr = ITextStream_ReadAll(stream, &str);
1569 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1570 todo_wine
1571 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1572 SysFreeString(str);
1573 ITextStream_Release(stream);
1575 /* ASCII file, read with Unicode stream */
1576 /* 1. one byte content, not enough for Unicode read */
1577 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1578 ok(hr == S_OK, "got 0x%08x\n", hr);
1579 str = SysAllocString(aW);
1580 hr = ITextStream_Write(stream, str);
1581 ok(hr == S_OK, "got 0x%08x\n", hr);
1582 SysFreeString(str);
1583 ITextStream_Release(stream);
1585 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1586 ok(hr == S_OK, "got 0x%08x\n", hr);
1588 str = (void*)0xdeadbeef;
1589 hr = ITextStream_ReadAll(stream, &str);
1590 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1591 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1593 ITextStream_Release(stream);
1595 DeleteFileW(nameW);
1596 RemoveDirectoryW(dirW);
1597 SysFreeString(nameW);
1600 static void test_Read(void)
1602 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1603 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1604 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1605 static const WCHAR aW[] = {'A',0};
1606 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1607 ITextStream *stream;
1608 BSTR nameW;
1609 HRESULT hr;
1610 BOOL ret;
1611 BSTR str;
1613 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1614 lstrcatW(pathW, scrrunW);
1615 lstrcpyW(dirW, pathW);
1616 lstrcatW(pathW, testfileW);
1618 ret = CreateDirectoryW(dirW, NULL);
1619 ok(ret, "got %d, %d\n", ret, GetLastError());
1621 /* Unicode file -> read with ascii stream */
1622 nameW = SysAllocString(pathW);
1623 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1624 ok(hr == S_OK, "got 0x%08x\n", hr);
1626 hr = ITextStream_WriteLine(stream, nameW);
1627 ok(hr == S_OK, "got 0x%08x\n", hr);
1629 str = SysAllocString(secondlineW);
1630 hr = ITextStream_WriteLine(stream, str);
1631 ok(hr == S_OK, "got 0x%08x\n", hr);
1632 SysFreeString(str);
1634 hr = ITextStream_Read(stream, 0, NULL);
1635 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1637 hr = ITextStream_Read(stream, 1, NULL);
1638 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1640 hr = ITextStream_Read(stream, -1, NULL);
1641 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1643 str = (void*)0xdeadbeef;
1644 hr = ITextStream_Read(stream, 1, &str);
1645 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1646 ok(str == NULL, "got %p\n", str);
1648 ITextStream_Release(stream);
1650 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1651 ok(hr == S_OK, "got 0x%08x\n", hr);
1653 hr = ITextStream_Read(stream, 1, NULL);
1654 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1656 str = (void*)0xdeadbeef;
1657 hr = ITextStream_Read(stream, -1, &str);
1658 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1659 ok(str == NULL, "got %p\n", str);
1661 str = (void*)0xdeadbeef;
1662 hr = ITextStream_Read(stream, 0, &str);
1663 ok(hr == S_OK, "got 0x%08x\n", hr);
1664 ok(str == NULL, "got %p\n", str);
1666 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1667 str = NULL;
1668 hr = ITextStream_Read(stream, 2, &str);
1669 ok(hr == S_OK, "got 0x%08x\n", hr);
1671 buffW[0] = 0;
1672 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, sizeof(buffW)/sizeof(WCHAR));
1674 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1675 ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str));
1676 SysFreeString(str);
1677 ITextStream_Release(stream);
1679 /* Unicode file -> read with unicode stream */
1680 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1681 ok(hr == S_OK, "got 0x%08x\n", hr);
1683 lstrcpyW(buffW, nameW);
1684 lstrcatW(buffW, crlfW);
1685 lstrcatW(buffW, secondlineW);
1686 lstrcatW(buffW, crlfW);
1687 str = NULL;
1688 hr = ITextStream_Read(stream, 500, &str);
1689 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1690 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1691 SysFreeString(str);
1693 /* ReadAll one more time */
1694 str = (void*)0xdeadbeef;
1695 hr = ITextStream_Read(stream, 10, &str);
1696 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1697 ok(str == NULL, "got %p\n", str);
1699 /* ReadLine fails the same way */
1700 str = (void*)0xdeadbeef;
1701 hr = ITextStream_ReadLine(stream, &str);
1702 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1703 ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str);
1704 ITextStream_Release(stream);
1706 /* Open again and skip first line before ReadAll */
1707 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1708 ok(hr == S_OK, "got 0x%08x\n", hr);
1710 str = NULL;
1711 hr = ITextStream_ReadLine(stream, &str);
1712 todo_wine {
1713 ok(hr == S_OK, "got 0x%08x\n", hr);
1714 ok(str != NULL, "got %p\n", str);
1716 SysFreeString(str);
1718 lstrcpyW(buffW, secondlineW);
1719 lstrcatW(buffW, crlfW);
1720 str = NULL;
1721 hr = ITextStream_Read(stream, 100, &str);
1722 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1723 todo_wine
1724 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1725 SysFreeString(str);
1726 ITextStream_Release(stream);
1728 /* ASCII file, read with Unicode stream */
1729 /* 1. one byte content, not enough for Unicode read */
1730 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1731 ok(hr == S_OK, "got 0x%08x\n", hr);
1732 str = SysAllocString(aW);
1733 hr = ITextStream_Write(stream, str);
1734 ok(hr == S_OK, "got 0x%08x\n", hr);
1735 SysFreeString(str);
1736 ITextStream_Release(stream);
1738 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1739 ok(hr == S_OK, "got 0x%08x\n", hr);
1741 str = (void*)0xdeadbeef;
1742 hr = ITextStream_Read(stream, 500, &str);
1743 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1744 ok(str == NULL, "got %p\n", str);
1746 ITextStream_Release(stream);
1748 DeleteFileW(nameW);
1749 RemoveDirectoryW(dirW);
1750 SysFreeString(nameW);
1753 struct getdrivename_test {
1754 const WCHAR path[10];
1755 const WCHAR drive[5];
1758 static const struct getdrivename_test getdrivenametestdata[] = {
1759 { {'C',':','\\','1','.','t','s','t',0}, {'C',':',0} },
1760 { {'O',':','\\','1','.','t','s','t',0}, {'O',':',0} },
1761 { {'O',':',0}, {'O',':',0} },
1762 { {'o',':',0}, {'o',':',0} },
1763 { {'O','O',':',0} },
1764 { {':',0} },
1765 { {'O',0} },
1766 { { 0 } }
1769 static void test_GetDriveName(void)
1771 const struct getdrivename_test *ptr = getdrivenametestdata;
1772 HRESULT hr;
1773 BSTR name;
1775 hr = IFileSystem3_GetDriveName(fs3, NULL, NULL);
1776 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1778 name = (void*)0xdeadbeef;
1779 hr = IFileSystem3_GetDriveName(fs3, NULL, &name);
1780 ok(hr == S_OK, "got 0x%08x\n", hr);
1781 ok(name == NULL, "got %p\n", name);
1783 while (*ptr->path) {
1784 BSTR path = SysAllocString(ptr->path);
1785 name = (void*)0xdeadbeef;
1786 hr = IFileSystem3_GetDriveName(fs3, path, &name);
1787 ok(hr == S_OK, "got 0x%08x\n", hr);
1788 if (name)
1789 ok(!lstrcmpW(ptr->drive, name), "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive));
1790 else
1791 ok(!*ptr->drive, "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive));
1792 SysFreeString(path);
1793 SysFreeString(name);
1794 ptr++;
1798 static void test_SerialNumber(void)
1800 IDriveCollection *drives;
1801 IEnumVARIANT *iter;
1802 IDrive *drive;
1803 LONG serial;
1804 HRESULT hr;
1805 BSTR name;
1807 hr = IFileSystem3_get_Drives(fs3, &drives);
1808 ok(hr == S_OK, "got 0x%08x\n", hr);
1810 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&iter);
1811 ok(hr == S_OK, "got 0x%08x\n", hr);
1812 IDriveCollection_Release(drives);
1814 while (1) {
1815 DriveTypeConst type;
1816 VARIANT var;
1818 hr = IEnumVARIANT_Next(iter, 1, &var, NULL);
1819 if (hr == S_FALSE) {
1820 skip("No fixed drive found, skipping test.\n");
1821 IEnumVARIANT_Release(iter);
1822 return;
1824 ok(hr == S_OK, "got 0x%08x\n", hr);
1826 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDrive, (void**)&drive);
1827 ok(hr == S_OK, "got 0x%08x\n", hr);
1828 VariantClear(&var);
1830 hr = IDrive_get_DriveType(drive, &type);
1831 ok(hr == S_OK, "got 0x%08x\n", hr);
1832 if (type == Fixed)
1833 break;
1835 IDrive_Release(drive);
1838 hr = IDrive_get_SerialNumber(drive, NULL);
1839 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1841 serial = 0xdeadbeef;
1842 hr = IDrive_get_SerialNumber(drive, &serial);
1843 ok(hr == S_OK, "got 0x%08x\n", hr);
1844 ok(serial != 0xdeadbeef, "got %x\n", serial);
1846 hr = IDrive_get_FileSystem(drive, NULL);
1847 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1849 name = NULL;
1850 hr = IDrive_get_FileSystem(drive, &name);
1851 ok(hr == S_OK, "got 0x%08x\n", hr);
1852 ok(name != NULL, "got %p\n", name);
1853 SysFreeString(name);
1855 hr = IDrive_get_VolumeName(drive, NULL);
1856 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1858 name = NULL;
1859 hr = IDrive_get_VolumeName(drive, &name);
1860 ok(hr == S_OK, "got 0x%08x\n", hr);
1861 ok(name != NULL, "got %p\n", name);
1862 SysFreeString(name);
1864 IDrive_Release(drive);
1865 IEnumVARIANT_Release(iter);
1868 START_TEST(filesystem)
1870 HRESULT hr;
1872 CoInitialize(NULL);
1874 hr = CoCreateInstance(&CLSID_FileSystemObject, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1875 &IID_IFileSystem3, (void**)&fs3);
1876 if(FAILED(hr)) {
1877 win_skip("Could not create FileSystem object: %08x\n", hr);
1878 return;
1881 test_interfaces();
1882 test_createfolder();
1883 test_textstream();
1884 test_GetFileVersion();
1885 test_GetParentFolderName();
1886 test_GetFileName();
1887 test_GetBaseName();
1888 test_GetAbsolutePathName();
1889 test_GetFile();
1890 test_CopyFolder();
1891 test_BuildPath();
1892 test_GetFolder();
1893 test_FolderCollection();
1894 test_FileCollection();
1895 test_DriveCollection();
1896 test_CreateTextFile();
1897 test_WriteLine();
1898 test_ReadAll();
1899 test_Read();
1900 test_GetDriveName();
1901 test_SerialNumber();
1903 IFileSystem3_Release(fs3);
1905 CoUninitialize();