[SCRRUN_WINETEST]
[reactos.git] / rostests / winetests / scrrun / filesystem.c
1 /*
2 *
3 * Copyright 2012 Alistair Leslie-Hughes
4 * Copyright 2014 Dmitry Timoshkov
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define COBJMACROS
22 #include <stdio.h>
23
24 #include "windows.h"
25 #include "ole2.h"
26 #include "olectl.h"
27 #include "oleauto.h"
28 #include "dispex.h"
29
30 #include "wine/test.h"
31
32 #include "initguid.h"
33 #include "scrrun.h"
34
35 static IFileSystem3 *fs3;
36
37 static inline ULONG get_refcount(IUnknown *iface)
38 {
39 IUnknown_AddRef(iface);
40 return IUnknown_Release(iface);
41 }
42
43 static const WCHAR crlfW[] = {'\r','\n',0};
44
45 #define GET_REFCOUNT(iface) \
46 get_refcount((IUnknown*)iface)
47
48 static void test_interfaces(void)
49 {
50 static const WCHAR nonexistent_dirW[] = {
51 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', 0};
52 static const WCHAR pathW[] = {'p','a','t','h',0};
53 static const WCHAR file_kernel32W[] = {
54 '\\', 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
55 HRESULT hr;
56 IDispatch *disp;
57 IDispatchEx *dispex;
58 IObjectWithSite *site;
59 VARIANT_BOOL b;
60 BSTR path;
61 WCHAR windows_path[MAX_PATH];
62 WCHAR file_path[MAX_PATH];
63
64 IFileSystem3_QueryInterface(fs3, &IID_IDispatch, (void**)&disp);
65
66 GetSystemDirectoryW(windows_path, MAX_PATH);
67 lstrcpyW(file_path, windows_path);
68 lstrcatW(file_path, file_kernel32W);
69
70 hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site);
71 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
72
73 hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
74 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
75
76 b = VARIANT_TRUE;
77 hr = IFileSystem3_FileExists(fs3, NULL, &b);
78 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
79 ok(b == VARIANT_FALSE, "got %x\n", b);
80
81 hr = IFileSystem3_FileExists(fs3, NULL, NULL);
82 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
83
84 path = SysAllocString(pathW);
85 b = VARIANT_TRUE;
86 hr = IFileSystem3_FileExists(fs3, path, &b);
87 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
88 ok(b == VARIANT_FALSE, "got %x\n", b);
89 SysFreeString(path);
90
91 path = SysAllocString(file_path);
92 b = VARIANT_FALSE;
93 hr = IFileSystem3_FileExists(fs3, path, &b);
94 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
95 ok(b == VARIANT_TRUE, "got %x\n", b);
96 SysFreeString(path);
97
98 path = SysAllocString(windows_path);
99 b = VARIANT_TRUE;
100 hr = IFileSystem3_FileExists(fs3, path, &b);
101 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
102 ok(b == VARIANT_FALSE, "got %x\n", b);
103 SysFreeString(path);
104
105 /* Folder Exists */
106 hr = IFileSystem3_FolderExists(fs3, NULL, NULL);
107 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
108
109 path = SysAllocString(windows_path);
110 hr = IFileSystem3_FolderExists(fs3, path, &b);
111 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
112 ok(b == VARIANT_TRUE, "Folder doesn't exists\n");
113 SysFreeString(path);
114
115 path = SysAllocString(nonexistent_dirW);
116 hr = IFileSystem3_FolderExists(fs3, path, &b);
117 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
118 ok(b == VARIANT_FALSE, "Folder exists\n");
119 SysFreeString(path);
120
121 path = SysAllocString(file_path);
122 hr = IFileSystem3_FolderExists(fs3, path, &b);
123 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
124 ok(b == VARIANT_FALSE, "Folder exists\n");
125 SysFreeString(path);
126
127 IDispatch_Release(disp);
128 }
129
130 static void test_createfolder(void)
131 {
132 WCHAR pathW[MAX_PATH], buffW[MAX_PATH];
133 HRESULT hr;
134 BSTR path;
135 IFolder *folder;
136 BOOL ret;
137
138 GetTempPathW(MAX_PATH, pathW);
139 GetTempFileNameW(pathW, NULL, 0, buffW);
140 DeleteFileW(buffW);
141 ret = CreateDirectoryW(buffW, NULL);
142 ok(ret, "got %d, %d\n", ret, GetLastError());
143
144 /* create existing directory */
145 path = SysAllocString(buffW);
146 folder = (void*)0xdeabeef;
147 hr = IFileSystem3_CreateFolder(fs3, path, &folder);
148 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
149 ok(folder == NULL, "got %p\n", folder);
150 SysFreeString(path);
151 RemoveDirectoryW(buffW);
152 }
153
154 static void test_textstream(void)
155 {
156 static const WCHAR testfileW[] = {'t','e','s','t','f','i','l','e','.','t','x','t',0};
157 ITextStream *stream;
158 VARIANT_BOOL b;
159 DWORD written;
160 HANDLE file;
161 HRESULT hr;
162 BSTR name, data;
163 BOOL ret;
164
165 file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
166 CloseHandle(file);
167
168 name = SysAllocString(testfileW);
169 b = VARIANT_FALSE;
170 hr = IFileSystem3_FileExists(fs3, name, &b);
171 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
172 ok(b == VARIANT_TRUE, "got %x\n", b);
173
174 /* different mode combinations */
175 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
176 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
177
178 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
179 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
180
181 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForReading, VARIANT_FALSE, TristateFalse, &stream);
182 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
183
184 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
185 ok(hr == S_OK, "got 0x%08x\n", hr);
186 hr = ITextStream_Read(stream, 1, &data);
187 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
188 ITextStream_Release(stream);
189
190 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
191 ok(hr == S_OK, "got 0x%08x\n", hr);
192 hr = ITextStream_Read(stream, 1, &data);
193 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
194 ITextStream_Release(stream);
195
196 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
197 ok(hr == S_OK, "got 0x%08x\n", hr);
198
199 /* try to write when open for reading */
200 hr = ITextStream_WriteLine(stream, name);
201 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
202
203 hr = ITextStream_Write(stream, name);
204 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
205
206 hr = ITextStream_get_AtEndOfStream(stream, NULL);
207 ok(hr == E_POINTER, "got 0x%08x\n", hr);
208
209 b = 10;
210 hr = ITextStream_get_AtEndOfStream(stream, &b);
211 ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr);
212 ok(b == VARIANT_TRUE, "got 0x%x\n", b);
213
214 ITextStream_Release(stream);
215
216 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
217 ok(hr == S_OK, "got 0x%08x\n", hr);
218
219 b = 10;
220 hr = ITextStream_get_AtEndOfStream(stream, &b);
221 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
222 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
223
224 b = 10;
225 hr = ITextStream_get_AtEndOfLine(stream, &b);
226 todo_wine {
227 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
228 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
229 }
230 hr = ITextStream_Read(stream, 1, &data);
231 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
232
233 hr = ITextStream_ReadLine(stream, &data);
234 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
235
236 hr = ITextStream_ReadAll(stream, &data);
237 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
238
239 ITextStream_Release(stream);
240
241 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
242 ok(hr == S_OK, "got 0x%08x\n", hr);
243
244 b = 10;
245 hr = ITextStream_get_AtEndOfStream(stream, &b);
246 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
247 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
248
249 b = 10;
250 hr = ITextStream_get_AtEndOfLine(stream, &b);
251 todo_wine {
252 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
253 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
254 }
255 hr = ITextStream_Read(stream, 1, &data);
256 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
257
258 hr = ITextStream_ReadLine(stream, &data);
259 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
260
261 hr = ITextStream_ReadAll(stream, &data);
262 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
263
264 ITextStream_Release(stream);
265
266 /* now with non-empty file */
267 file = CreateFileW(testfileW, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
268 ret = WriteFile(file, testfileW, sizeof(testfileW), &written, NULL);
269 ok(ret && written == sizeof(testfileW), "got %d\n", ret);
270 CloseHandle(file);
271
272 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
273 ok(hr == S_OK, "got 0x%08x\n", hr);
274 b = 10;
275 hr = ITextStream_get_AtEndOfStream(stream, &b);
276 ok(hr == S_OK, "got 0x%08x\n", hr);
277 ok(b == VARIANT_FALSE, "got 0x%x\n", b);
278 ITextStream_Release(stream);
279
280 SysFreeString(name);
281 DeleteFileW(testfileW);
282 }
283
284 static void test_GetFileVersion(void)
285 {
286 static const WCHAR k32W[] = {'\\','k','e','r','n','e','l','3','2','.','d','l','l',0};
287 static const WCHAR k33W[] = {'\\','k','e','r','n','e','l','3','3','.','d','l','l',0};
288 WCHAR pathW[MAX_PATH], filenameW[MAX_PATH];
289 BSTR path, version;
290 HRESULT hr;
291
292 GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
293
294 lstrcpyW(filenameW, pathW);
295 lstrcatW(filenameW, k32W);
296
297 path = SysAllocString(filenameW);
298 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
299 ok(hr == S_OK, "got 0x%08x\n", hr);
300 ok(*version != 0, "got %s\n", wine_dbgstr_w(version));
301 SysFreeString(version);
302 SysFreeString(path);
303
304 lstrcpyW(filenameW, pathW);
305 lstrcatW(filenameW, k33W);
306
307 path = SysAllocString(filenameW);
308 version = (void*)0xdeadbeef;
309 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
310 ok(broken(hr == S_OK) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
311 if (hr == S_OK)
312 {
313 ok(*version == 0, "got %s\n", wine_dbgstr_w(version));
314 SysFreeString(version);
315 }
316 else
317 ok(version == (void*)0xdeadbeef, "got %p\n", version);
318 SysFreeString(path);
319 }
320
321 static void test_GetParentFolderName(void)
322 {
323 static const WCHAR path1[] = {'a',0};
324 static const WCHAR path2[] = {'a','/','a','/','a',0};
325 static const WCHAR path3[] = {'a','\\','a','\\','a',0};
326 static const WCHAR path4[] = {'a','/','a','/','/','\\','\\',0};
327 static const WCHAR path5[] = {'c',':','\\','\\','a',0};
328 static const WCHAR path6[] = {'a','c',':','\\','a',0};
329 static const WCHAR result2[] = {'a','/','a',0};
330 static const WCHAR result3[] = {'a','\\','a',0};
331 static const WCHAR result4[] = {'a',0};
332 static const WCHAR result5[] = {'c',':','\\',0};
333 static const WCHAR result6[] = {'a','c',':',0};
334
335 static const struct {
336 const WCHAR *path;
337 const WCHAR *result;
338 } tests[] = {
339 {NULL, NULL},
340 {path1, NULL},
341 {path2, result2},
342 {path3, result3},
343 {path4, result4},
344 {path5, result5},
345 {path6, result6}
346 };
347
348 BSTR path, result;
349 HRESULT hr;
350 int i;
351
352 hr = IFileSystem3_GetParentFolderName(fs3, NULL, NULL);
353 ok(hr == E_POINTER, "GetParentFolderName returned %x, expected E_POINTER\n", hr);
354
355 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
356 result = (BSTR)0xdeadbeef;
357 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
358 hr = IFileSystem3_GetParentFolderName(fs3, path, &result);
359 ok(hr == S_OK, "%d) GetParentFolderName returned %x, expected S_OK\n", i, hr);
360 if(!tests[i].result)
361 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
362 else
363 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
364 SysFreeString(path);
365 SysFreeString(result);
366 }
367 }
368
369 static void test_GetFileName(void)
370 {
371 static const WCHAR path1[] = {'a',0};
372 static const WCHAR path2[] = {'a','/','a','.','b',0};
373 static const WCHAR path3[] = {'a','\\',0};
374 static const WCHAR path4[] = {'c',':',0};
375 static const WCHAR path5[] = {'/','\\',0};
376 static const WCHAR result2[] = {'a','.','b',0};
377 static const WCHAR result3[] = {'a',0};
378
379 static const struct {
380 const WCHAR *path;
381 const WCHAR *result;
382 } tests[] = {
383 {NULL, NULL},
384 {path1, path1},
385 {path2, result2},
386 {path3, result3},
387 {path4, NULL},
388 {path5, NULL}
389 };
390
391 BSTR path, result;
392 HRESULT hr;
393 int i;
394
395 hr = IFileSystem3_GetFileName(fs3, NULL, NULL);
396 ok(hr == E_POINTER, "GetFileName returned %x, expected E_POINTER\n", hr);
397
398 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
399 result = (BSTR)0xdeadbeef;
400 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
401 hr = IFileSystem3_GetFileName(fs3, path, &result);
402 ok(hr == S_OK, "%d) GetFileName returned %x, expected S_OK\n", i, hr);
403 if(!tests[i].result)
404 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
405 else
406 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
407 SysFreeString(path);
408 SysFreeString(result);
409 }
410 }
411
412 static void test_GetBaseName(void)
413 {
414 static const WCHAR path1[] = {'a',0};
415 static const WCHAR path2[] = {'a','/','a','.','b','.','c',0};
416 static const WCHAR path3[] = {'a','.','b','\\',0};
417 static const WCHAR path4[] = {'c',':',0};
418 static const WCHAR path5[] = {'/','\\',0};
419 static const WCHAR path6[] = {'.','a',0};
420 static const WCHAR result1[] = {'a',0};
421 static const WCHAR result2[] = {'a','.','b',0};
422 static const WCHAR result6[] = {0};
423
424 static const struct {
425 const WCHAR *path;
426 const WCHAR *result;
427 } tests[] = {
428 {NULL, NULL},
429 {path1, result1},
430 {path2, result2},
431 {path3, result1},
432 {path4, NULL},
433 {path5, NULL},
434 {path6, result6}
435 };
436
437 BSTR path, result;
438 HRESULT hr;
439 int i;
440
441 hr = IFileSystem3_GetBaseName(fs3, NULL, NULL);
442 ok(hr == E_POINTER, "GetBaseName returned %x, expected E_POINTER\n", hr);
443
444 for(i=0; i<sizeof(tests)/sizeof(tests[0]); i++) {
445 result = (BSTR)0xdeadbeef;
446 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
447 hr = IFileSystem3_GetBaseName(fs3, path, &result);
448 ok(hr == S_OK, "%d) GetBaseName returned %x, expected S_OK\n", i, hr);
449 if(!tests[i].result)
450 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
451 else
452 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
453 SysFreeString(path);
454 SysFreeString(result);
455 }
456 }
457
458 static void test_GetAbsolutePathName(void)
459 {
460 static const WCHAR dir1[] = {'t','e','s','t','_','d','i','r','1',0};
461 static const WCHAR dir2[] = {'t','e','s','t','_','d','i','r','2',0};
462 static const WCHAR dir_match1[] = {'t','e','s','t','_','d','i','r','*',0};
463 static const WCHAR dir_match2[] = {'t','e','s','t','_','d','i','*',0};
464 static const WCHAR cur_dir[] = {'.',0};
465
466 WIN32_FIND_DATAW fdata;
467 HANDLE find;
468 WCHAR buf[MAX_PATH], buf2[MAX_PATH];
469 BSTR path, result;
470 HRESULT hr;
471
472 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, NULL);
473 ok(hr == E_POINTER, "GetAbsolutePathName returned %x, expected E_POINTER\n", hr);
474
475 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result);
476 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
477 GetFullPathNameW(cur_dir, MAX_PATH, buf, NULL);
478 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
479 SysFreeString(result);
480
481 find = FindFirstFileW(dir_match2, &fdata);
482 if(find != INVALID_HANDLE_VALUE) {
483 skip("GetAbsolutePathName tests\n");
484 FindClose(find);
485 return;
486 }
487
488 path = SysAllocString(dir_match1);
489 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
490 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
491 GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL);
492 ok(!lstrcmpiW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2));
493 SysFreeString(result);
494
495 ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1));
496 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
497 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
498 GetFullPathNameW(dir1, MAX_PATH, buf, NULL);
499 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
500 wine_dbgstr_w(result), wine_dbgstr_w(buf));
501 SysFreeString(result);
502
503 ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2));
504 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
505 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
506 if(!lstrcmpiW(buf, result) || !lstrcmpiW(buf2, result)) {
507 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
508 wine_dbgstr_w(result), wine_dbgstr_w(buf));
509 }else {
510 GetFullPathNameW(dir2, MAX_PATH, buf, NULL);
511 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n",
512 wine_dbgstr_w(result), wine_dbgstr_w(buf));
513 }
514 SysFreeString(result);
515
516 SysFreeString(path);
517 path = SysAllocString(dir_match2);
518 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
519 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
520 GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL);
521 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
522 SysFreeString(result);
523 SysFreeString(path);
524
525 RemoveDirectoryW(dir1);
526 RemoveDirectoryW(dir2);
527 }
528
529 static void test_GetFile(void)
530 {
531 static const WCHAR get_file[] = {'g','e','t','_','f','i','l','e','.','t','s','t',0};
532
533 BSTR path = SysAllocString(get_file);
534 FileAttribute fa;
535 VARIANT size;
536 DWORD gfa;
537 IFile *file;
538 HRESULT hr;
539 HANDLE hf;
540
541 hr = IFileSystem3_GetFile(fs3, path, NULL);
542 ok(hr == E_POINTER, "GetFile returned %x, expected E_POINTER\n", hr);
543 hr = IFileSystem3_GetFile(fs3, NULL, &file);
544 ok(hr == E_INVALIDARG, "GetFile returned %x, expected E_INVALIDARG\n", hr);
545
546 if(GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES) {
547 skip("File already exists, skipping GetFile tests\n");
548 SysFreeString(path);
549 return;
550 }
551
552 file = (IFile*)0xdeadbeef;
553 hr = IFileSystem3_GetFile(fs3, path, &file);
554 ok(!file, "file != NULL\n");
555 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
556
557 hf = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
558 if(hf == INVALID_HANDLE_VALUE) {
559 skip("Can't create temporary file\n");
560 SysFreeString(path);
561 return;
562 }
563 CloseHandle(hf);
564
565 hr = IFileSystem3_GetFile(fs3, path, &file);
566 ok(hr == S_OK, "GetFile returned %x, expected S_OK\n", hr);
567
568 hr = IFile_get_Attributes(file, &fa);
569 gfa = GetFileAttributesW(get_file) & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
570 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE |
571 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED);
572 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
573 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa);
574
575 hr = IFile_get_Size(file, &size);
576 ok(hr == S_OK, "get_Size returned %x, expected S_OK\n", hr);
577 ok(V_VT(&size) == VT_I4, "V_VT(&size) = %d, expected VT_I4\n", V_VT(&size));
578 ok(V_I4(&size) == 0, "V_I4(&size) = %d, expected 0\n", V_I4(&size));
579 IFile_Release(file);
580
581 hr = IFileSystem3_DeleteFile(fs3, path, FALSE);
582 ok(hr==CTL_E_PERMISSIONDENIED || broken(hr==S_OK),
583 "DeleteFile returned %x, expected CTL_E_PERMISSIONDENIED\n", hr);
584 if(hr != S_OK) {
585 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
586 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
587 }
588 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
589 ok(hr == CTL_E_FILENOTFOUND, "DeleteFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
590
591 SysFreeString(path);
592 }
593
594 static inline BOOL create_file(const WCHAR *name)
595 {
596 HANDLE f = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
597 CloseHandle(f);
598 return f != INVALID_HANDLE_VALUE;
599 }
600
601 static inline void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret)
602 {
603 DWORD len = lstrlenW(folder);
604 memmove(ret, folder, len*sizeof(WCHAR));
605 ret[len] = '\\';
606 memmove(ret+len+1, name, (lstrlenW(name)+1)*sizeof(WCHAR));
607 }
608
609 static void test_CopyFolder(void)
610 {
611 static const WCHAR filesystem3_dir[] = {'f','i','l','e','s','y','s','t','e','m','3','_','t','e','s','t',0};
612 static const WCHAR s1[] = {'s','r','c','1',0};
613 static const WCHAR s[] = {'s','r','c','*',0};
614 static const WCHAR d[] = {'d','s','t',0};
615 static const WCHAR empty[] = {0};
616
617 WCHAR tmp[MAX_PATH];
618 BSTR bsrc, bdst;
619 HRESULT hr;
620
621 if(!CreateDirectoryW(filesystem3_dir, NULL)) {
622 skip("can't create temporary directory\n");
623 return;
624 }
625
626 create_path(filesystem3_dir, s1, tmp);
627 bsrc = SysAllocString(tmp);
628 create_path(filesystem3_dir, d, tmp);
629 bdst = SysAllocString(tmp);
630 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
631 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
632
633 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
634 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
635
636 ok(create_file(bsrc), "can't create %s file\n", wine_dbgstr_w(bsrc));
637 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
638 ok(hr == S_OK, "CopyFile returned %x, expected S_OK\n", hr);
639
640 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
641 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
642
643 hr = IFileSystem3_DeleteFile(fs3, bsrc, VARIANT_FALSE);
644 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
645
646 ok(CreateDirectoryW(bsrc, NULL), "can't create %s\n", wine_dbgstr_w(bsrc));
647 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
648 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
649
650 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
651 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
652
653 hr = IFileSystem3_DeleteFile(fs3, bdst, VARIANT_TRUE);
654 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
655
656 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
657 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
658
659 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
660 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
661 create_path(tmp, s1, tmp);
662 ok(GetFileAttributesW(tmp) == INVALID_FILE_ATTRIBUTES,
663 "%s file exists\n", wine_dbgstr_w(tmp));
664
665 create_path(filesystem3_dir, d, tmp);
666 create_path(tmp, empty, tmp);
667 SysFreeString(bdst);
668 bdst = SysAllocString(tmp);
669 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
670 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
671 create_path(tmp, s1, tmp);
672 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
673 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
674 ok(RemoveDirectoryW(tmp), "can't remove %s directory\n", wine_dbgstr_w(tmp));
675 create_path(filesystem3_dir, d, tmp);
676 SysFreeString(bdst);
677 bdst = SysAllocString(tmp);
678
679
680 create_path(filesystem3_dir, s, tmp);
681 SysFreeString(bsrc);
682 bsrc = SysAllocString(tmp);
683 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
684 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
685 create_path(filesystem3_dir, d, tmp);
686 create_path(tmp, s1, tmp);
687 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
688 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
689
690 hr = IFileSystem3_DeleteFolder(fs3, bdst, VARIANT_FALSE);
691 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
692
693 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
694 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
695
696 create_path(filesystem3_dir, s1, tmp);
697 SysFreeString(bsrc);
698 bsrc = SysAllocString(tmp);
699 create_path(tmp, s1, tmp);
700 ok(create_file(tmp), "can't create %s file\n", wine_dbgstr_w(tmp));
701 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
702 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
703
704 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
705 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
706
707 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
708 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
709 SysFreeString(bsrc);
710 SysFreeString(bdst);
711
712 bsrc = SysAllocString(filesystem3_dir);
713 hr = IFileSystem3_DeleteFolder(fs3, bsrc, VARIANT_FALSE);
714 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
715 SysFreeString(bsrc);
716 }
717
718 static BSTR bstr_from_str(const char *str)
719 {
720 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
721 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */
722 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
723 return ret;
724 }
725
726 struct buildpath_test
727 {
728 const char *path;
729 const char *name;
730 const char *result;
731 };
732
733 static struct buildpath_test buildpath_data[] =
734 {
735 { "C:\\path", "..\\name.tmp", "C:\\path\\..\\name.tmp" },
736 { "C:\\path", "\\name.tmp", "C:\\path\\name.tmp" },
737 { "C:\\path", "name.tmp", "C:\\path\\name.tmp" },
738 { "C:\\path\\", "name.tmp", "C:\\path\\name.tmp" },
739 { "C:\\path", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
740 { "C:\\path\\", "\\name.tmp", "C:\\path\\name.tmp" },
741 { "C:\\path\\", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
742 { "C:\\path\\\\", "\\\\name.tmp", "C:\\path\\\\\\name.tmp" },
743 { "C:\\\\", "\\name.tmp", "C:\\\\name.tmp" },
744 { "C:", "name.tmp", "C:name.tmp" },
745 { "C:", "\\\\name.tmp", "C:\\\\name.tmp" },
746 { NULL }
747 };
748
749 static void test_BuildPath(void)
750 {
751 struct buildpath_test *ptr = buildpath_data;
752 BSTR ret, path;
753 HRESULT hr;
754 int i = 0;
755
756 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, NULL);
757 ok(hr == E_POINTER, "got 0x%08x\n", hr);
758
759 ret = (BSTR)0xdeadbeef;
760 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, &ret);
761 ok(hr == S_OK, "got 0x%08x\n", hr);
762 ok(*ret == 0, "got %p\n", ret);
763 SysFreeString(ret);
764
765 ret = (BSTR)0xdeadbeef;
766 path = bstr_from_str("path");
767 hr = IFileSystem3_BuildPath(fs3, path, NULL, &ret);
768 ok(hr == S_OK, "got 0x%08x\n", hr);
769 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
770 SysFreeString(ret);
771 SysFreeString(path);
772
773 ret = (BSTR)0xdeadbeef;
774 path = bstr_from_str("path");
775 hr = IFileSystem3_BuildPath(fs3, NULL, path, &ret);
776 ok(hr == S_OK, "got 0x%08x\n", hr);
777 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
778 SysFreeString(ret);
779 SysFreeString(path);
780
781 while (ptr->path)
782 {
783 BSTR name, result;
784
785 ret = NULL;
786 path = bstr_from_str(ptr->path);
787 name = bstr_from_str(ptr->name);
788 result = bstr_from_str(ptr->result);
789 hr = IFileSystem3_BuildPath(fs3, path, name, &ret);
790 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
791 if (hr == S_OK)
792 {
793 ok(!lstrcmpW(ret, result), "%d: got wrong path %s, expected %s\n", i, wine_dbgstr_w(ret),
794 wine_dbgstr_w(result));
795 SysFreeString(ret);
796 }
797 SysFreeString(path);
798 SysFreeString(name);
799 SysFreeString(result);
800
801 i++;
802 ptr++;
803 }
804 }
805
806 static void test_GetFolder(void)
807 {
808 static const WCHAR dummyW[] = {'d','u','m','m','y',0};
809 WCHAR buffW[MAX_PATH];
810 IFolder *folder;
811 HRESULT hr;
812 BSTR str;
813
814 folder = (void*)0xdeadbeef;
815 hr = IFileSystem3_GetFolder(fs3, NULL, &folder);
816 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
817 ok(folder == NULL, "got %p\n", folder);
818
819 hr = IFileSystem3_GetFolder(fs3, NULL, NULL);
820 ok(hr == E_POINTER, "got 0x%08x\n", hr);
821
822 /* something that doesn't exist */
823 str = SysAllocString(dummyW);
824
825 hr = IFileSystem3_GetFolder(fs3, str, NULL);
826 ok(hr == E_POINTER, "got 0x%08x\n", hr);
827
828 folder = (void*)0xdeadbeef;
829 hr = IFileSystem3_GetFolder(fs3, str, &folder);
830 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
831 ok(folder == NULL, "got %p\n", folder);
832 SysFreeString(str);
833
834 GetWindowsDirectoryW(buffW, MAX_PATH);
835 str = SysAllocString(buffW);
836 hr = IFileSystem3_GetFolder(fs3, str, &folder);
837 ok(hr == S_OK, "got 0x%08x\n", hr);
838 SysFreeString(str);
839 IFolder_Release(folder);
840 }
841
842 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
843 static void test_FolderCollection(void)
844 {
845 static const WCHAR fooW[] = {'f','o','o',0};
846 static const WCHAR aW[] = {'\\','a',0};
847 static const WCHAR bW[] = {'\\','b',0};
848 static const WCHAR cW[] = {'\\','c',0};
849 IFolderCollection *folders;
850 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
851 IEnumVARIANT *enumvar, *clone;
852 LONG count, ref, ref2, i;
853 IUnknown *unk, *unk2;
854 IFolder *folder;
855 ULONG fetched;
856 VARIANT var, var2[2];
857 HRESULT hr;
858 BSTR str;
859 int found_a = 0, found_b = 0, found_c = 0;
860
861 GetTempPathW(MAX_PATH, pathW);
862 GetTempFileNameW(pathW, fooW, 0, buffW);
863 DeleteFileW(buffW);
864 CreateDirectoryW(buffW, NULL);
865
866 str = SysAllocString(buffW);
867 hr = IFileSystem3_GetFolder(fs3, str, &folder);
868 ok(hr == S_OK, "got 0x%08x\n", hr);
869 SysFreeString(str);
870
871 hr = IFolder_get_SubFolders(folder, NULL);
872 ok(hr == E_POINTER, "got 0x%08x\n", hr);
873
874 hr = IFolder_get_Path(folder, NULL);
875 ok(hr == E_POINTER, "got 0x%08x\n", hr);
876
877 hr = IFolder_get_Path(folder, &str);
878 ok(hr == S_OK, "got 0x%08x\n", hr);
879 ok(!lstrcmpW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
880 SysFreeString(str);
881
882 lstrcpyW(pathW, buffW);
883 lstrcatW(pathW, aW);
884 CreateDirectoryW(pathW, NULL);
885
886 lstrcpyW(pathW, buffW);
887 lstrcatW(pathW, bW);
888 CreateDirectoryW(pathW, NULL);
889
890 hr = IFolder_get_SubFolders(folder, &folders);
891 ok(hr == S_OK, "got 0x%08x\n", hr);
892 IFolder_Release(folder);
893
894 count = 0;
895 hr = IFolderCollection_get_Count(folders, &count);
896 ok(hr == S_OK, "got 0x%08x\n", hr);
897 ok(count == 2, "got %d\n", count);
898
899 lstrcpyW(pathW, buffW);
900 lstrcatW(pathW, cW);
901 CreateDirectoryW(pathW, NULL);
902
903 /* every time property is requested it scans directory */
904 count = 0;
905 hr = IFolderCollection_get_Count(folders, &count);
906 ok(hr == S_OK, "got 0x%08x\n", hr);
907 ok(count == 3, "got %d\n", count);
908
909 hr = IFolderCollection_get__NewEnum(folders, NULL);
910 ok(hr == E_POINTER, "got 0x%08x\n", hr);
911
912 hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk);
913 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
914
915 /* NewEnum creates new instance each time it's called */
916 ref = GET_REFCOUNT(folders);
917
918 unk = NULL;
919 hr = IFolderCollection_get__NewEnum(folders, &unk);
920 ok(hr == S_OK, "got 0x%08x\n", hr);
921
922 ref2 = GET_REFCOUNT(folders);
923 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
924
925 unk2 = NULL;
926 hr = IFolderCollection_get__NewEnum(folders, &unk2);
927 ok(hr == S_OK, "got 0x%08x\n", hr);
928 ok(unk != unk2, "got %p, %p\n", unk2, unk);
929 IUnknown_Release(unk2);
930
931 /* now get IEnumVARIANT */
932 ref = GET_REFCOUNT(folders);
933 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
934 ok(hr == S_OK, "got 0x%08x\n", hr);
935 ref2 = GET_REFCOUNT(folders);
936 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
937
938 /* clone enumerator */
939 hr = IEnumVARIANT_Clone(enumvar, &clone);
940 ok(hr == S_OK, "got 0x%08x\n", hr);
941 ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
942 IEnumVARIANT_Release(clone);
943
944 hr = IEnumVARIANT_Reset(enumvar);
945 ok(hr == S_OK, "got 0x%08x\n", hr);
946
947 for (i = 0; i < 3; i++)
948 {
949 VariantInit(&var);
950 fetched = 0;
951 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
952 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
953 ok(fetched == 1, "%d: got %d\n", i, fetched);
954 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
955
956 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder);
957 ok(hr == S_OK, "got 0x%08x\n", hr);
958
959 str = NULL;
960 hr = IFolder_get_Name(folder, &str);
961 ok(hr == S_OK, "got 0x%08x\n", hr);
962 if (!lstrcmpW(str, aW + 1))
963 found_a++;
964 else if (!lstrcmpW(str, bW + 1))
965 found_b++;
966 else if (!lstrcmpW(str, cW + 1))
967 found_c++;
968 else
969 ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str));
970 SysFreeString(str);
971
972 IFolder_Release(folder);
973 VariantClear(&var);
974 }
975
976 ok(found_a == 1 && found_b == 1 && found_c == 1,
977 "each folder should be found 1 time instead of %d/%d/%d\n",
978 found_a, found_b, found_c);
979
980 VariantInit(&var);
981 fetched = -1;
982 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
983 ok(hr == S_FALSE, "got 0x%08x\n", hr);
984 ok(fetched == 0, "got %d\n", fetched);
985
986 hr = IEnumVARIANT_Reset(enumvar);
987 ok(hr == S_OK, "got 0x%08x\n", hr);
988 hr = IEnumVARIANT_Skip(enumvar, 2);
989 ok(hr == S_OK, "got 0x%08x\n", hr);
990 hr = IEnumVARIANT_Skip(enumvar, 0);
991 ok(hr == S_OK, "got 0x%08x\n", hr);
992
993 VariantInit(&var2[0]);
994 VariantInit(&var2[1]);
995 fetched = -1;
996 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
997 ok(hr == S_OK, "got 0x%08x\n", hr);
998 ok(fetched == 0, "got %d\n", fetched);
999 fetched = -1;
1000 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1001 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1002 ok(fetched == 1, "got %d\n", fetched);
1003 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1004 VariantClear(&var2[0]);
1005 VariantClear(&var2[1]);
1006
1007 IEnumVARIANT_Release(enumvar);
1008 IUnknown_Release(unk);
1009
1010 lstrcpyW(pathW, buffW);
1011 lstrcatW(pathW, aW);
1012 RemoveDirectoryW(pathW);
1013 lstrcpyW(pathW, buffW);
1014 lstrcatW(pathW, bW);
1015 RemoveDirectoryW(pathW);
1016 lstrcpyW(pathW, buffW);
1017 lstrcatW(pathW, cW);
1018 RemoveDirectoryW(pathW);
1019 RemoveDirectoryW(buffW);
1020
1021 IFolderCollection_Release(folders);
1022 }
1023
1024 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
1025 static void test_FileCollection(void)
1026 {
1027 static const WCHAR fooW[] = {'\\','f','o','o',0};
1028 static const WCHAR aW[] = {'\\','a',0};
1029 static const WCHAR bW[] = {'\\','b',0};
1030 static const WCHAR cW[] = {'\\','c',0};
1031 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
1032 IFolder *folder;
1033 IFileCollection *files;
1034 IFile *file;
1035 IEnumVARIANT *enumvar, *clone;
1036 LONG count, ref, ref2, i;
1037 IUnknown *unk, *unk2;
1038 ULONG fetched;
1039 VARIANT var, var2[2];
1040 HRESULT hr;
1041 BSTR str;
1042 HANDLE file_a, file_b, file_c;
1043 int found_a = 0, found_b = 0, found_c = 0;
1044
1045 GetTempPathW(MAX_PATH, pathW);
1046 GetTempFileNameW(pathW, fooW, 0, buffW);
1047 DeleteFileW(buffW);
1048 CreateDirectoryW(buffW, NULL);
1049
1050 str = SysAllocString(buffW);
1051 hr = IFileSystem3_GetFolder(fs3, str, &folder);
1052 ok(hr == S_OK, "got 0x%08x\n", hr);
1053 SysFreeString(str);
1054
1055 hr = IFolder_get_Files(folder, NULL);
1056 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1057
1058 lstrcpyW(pathW, buffW);
1059 lstrcatW(pathW, aW);
1060 file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1061 FILE_FLAG_DELETE_ON_CLOSE, 0);
1062 lstrcpyW(pathW, buffW);
1063 lstrcatW(pathW, bW);
1064 file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1065 FILE_FLAG_DELETE_ON_CLOSE, 0);
1066
1067 hr = IFolder_get_Files(folder, &files);
1068 ok(hr == S_OK, "got 0x%08x\n", hr);
1069 IFolder_Release(folder);
1070
1071 count = 0;
1072 hr = IFileCollection_get_Count(files, &count);
1073 todo_wine
1074 ok(hr == S_OK, "got 0x%08x\n", hr);
1075 todo_wine
1076 ok(count == 2, "got %d\n", count);
1077
1078 lstrcpyW(pathW, buffW);
1079 lstrcatW(pathW, cW);
1080 file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1081 FILE_FLAG_DELETE_ON_CLOSE, 0);
1082
1083 /* every time property is requested it scans directory */
1084 count = 0;
1085 hr = IFileCollection_get_Count(files, &count);
1086 todo_wine
1087 ok(hr == S_OK, "got 0x%08x\n", hr);
1088 todo_wine
1089 ok(count == 3, "got %d\n", count);
1090
1091 hr = IFileCollection_get__NewEnum(files, NULL);
1092 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1093
1094 hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk);
1095 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1096
1097 /* NewEnum creates new instance each time it's called */
1098 ref = GET_REFCOUNT(files);
1099
1100 unk = NULL;
1101 hr = IFileCollection_get__NewEnum(files, &unk);
1102 ok(hr == S_OK, "got 0x%08x\n", hr);
1103
1104 ref2 = GET_REFCOUNT(files);
1105 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1106
1107 unk2 = NULL;
1108 hr = IFileCollection_get__NewEnum(files, &unk2);
1109 ok(hr == S_OK, "got 0x%08x\n", hr);
1110 ok(unk != unk2, "got %p, %p\n", unk2, unk);
1111 IUnknown_Release(unk2);
1112
1113 /* now get IEnumVARIANT */
1114 ref = GET_REFCOUNT(files);
1115 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1116 ok(hr == S_OK, "got 0x%08x\n", hr);
1117 ref2 = GET_REFCOUNT(files);
1118 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1119
1120 /* clone enumerator */
1121 hr = IEnumVARIANT_Clone(enumvar, &clone);
1122 ok(hr == S_OK, "got 0x%08x\n", hr);
1123 ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
1124 IEnumVARIANT_Release(clone);
1125
1126 hr = IEnumVARIANT_Reset(enumvar);
1127 ok(hr == S_OK, "got 0x%08x\n", hr);
1128
1129 for (i = 0; i < 3; i++)
1130 {
1131 VariantInit(&var);
1132 fetched = 0;
1133 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1134 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1135 ok(fetched == 1, "%d: got %d\n", i, fetched);
1136 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1137
1138 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file);
1139 ok(hr == S_OK, "got 0x%08x\n", hr);
1140
1141 str = NULL;
1142 hr = IFile_get_Name(file, &str);
1143 ok(hr == S_OK, "got 0x%08x\n", hr);
1144 if (!lstrcmpW(str, aW + 1))
1145 found_a++;
1146 else if (!lstrcmpW(str, bW + 1))
1147 found_b++;
1148 else if (!lstrcmpW(str, cW + 1))
1149 found_c++;
1150 else
1151 ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str));
1152 SysFreeString(str);
1153
1154 IFile_Release(file);
1155 VariantClear(&var);
1156 }
1157
1158 ok(found_a == 1 && found_b == 1 && found_c == 1,
1159 "each file should be found 1 time instead of %d/%d/%d\n",
1160 found_a, found_b, found_c);
1161
1162 VariantInit(&var);
1163 fetched = -1;
1164 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1165 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1166 ok(fetched == 0, "got %d\n", fetched);
1167
1168 hr = IEnumVARIANT_Reset(enumvar);
1169 ok(hr == S_OK, "got 0x%08x\n", hr);
1170 hr = IEnumVARIANT_Skip(enumvar, 2);
1171 ok(hr == S_OK, "got 0x%08x\n", hr);
1172 hr = IEnumVARIANT_Skip(enumvar, 0);
1173 ok(hr == S_OK, "got 0x%08x\n", hr);
1174
1175 VariantInit(&var2[0]);
1176 VariantInit(&var2[1]);
1177 fetched = -1;
1178 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1179 ok(hr == S_OK, "got 0x%08x\n", hr);
1180 ok(fetched == 0, "got %d\n", fetched);
1181 fetched = -1;
1182 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1183 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1184 ok(fetched == 1, "got %d\n", fetched);
1185 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1186 VariantClear(&var2[0]);
1187 VariantClear(&var2[1]);
1188
1189 IEnumVARIANT_Release(enumvar);
1190 IUnknown_Release(unk);
1191
1192 CloseHandle(file_a);
1193 CloseHandle(file_b);
1194 CloseHandle(file_c);
1195 RemoveDirectoryW(buffW);
1196
1197 IFileCollection_Release(files);
1198 }
1199
1200 static void test_DriveCollection(void)
1201 {
1202 IDriveCollection *drives;
1203 IEnumVARIANT *enumvar;
1204 ULONG fetched;
1205 VARIANT var;
1206 HRESULT hr;
1207 LONG count;
1208
1209 hr = IFileSystem3_get_Drives(fs3, &drives);
1210 ok(hr == S_OK, "got 0x%08x\n", hr);
1211
1212 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar);
1213 ok(hr == S_OK, "got 0x%08x\n", hr);
1214
1215 hr = IDriveCollection_get_Count(drives, NULL);
1216 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1217
1218 count = 0;
1219 hr = IDriveCollection_get_Count(drives, &count);
1220 ok(hr == S_OK, "got 0x%08x\n", hr);
1221 ok(count > 0, "got %d\n", count);
1222
1223 V_VT(&var) = VT_EMPTY;
1224 fetched = -1;
1225 hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched);
1226 ok(hr == S_OK, "got 0x%08x\n", hr);
1227 ok(fetched == 0, "got %d\n", fetched);
1228
1229 hr = IEnumVARIANT_Skip(enumvar, 0);
1230 ok(hr == S_OK, "got 0x%08x\n", hr);
1231
1232 hr = IEnumVARIANT_Skip(enumvar, count);
1233 ok(hr == S_OK, "got 0x%08x\n", hr);
1234
1235 hr = IEnumVARIANT_Skip(enumvar, 1);
1236 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1237
1238 /* reset and iterate again */
1239 hr = IEnumVARIANT_Reset(enumvar);
1240 ok(hr == S_OK, "got 0x%08x\n", hr);
1241
1242 while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) {
1243 IDrive *drive = (IDrive*)V_DISPATCH(&var);
1244 DriveTypeConst type;
1245 BSTR str;
1246
1247 hr = IDrive_get_DriveType(drive, &type);
1248 ok(hr == S_OK, "got 0x%08x\n", hr);
1249
1250 hr = IDrive_get_DriveLetter(drive, NULL);
1251 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1252
1253 hr = IDrive_get_DriveLetter(drive, &str);
1254 ok(hr == S_OK, "got 0x%08x\n", hr);
1255 ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str));
1256 SysFreeString(str);
1257
1258 hr = IDrive_get_IsReady(drive, NULL);
1259 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1260
1261 hr = IDrive_get_TotalSize(drive, NULL);
1262 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1263
1264 hr = IDrive_get_AvailableSpace(drive, NULL);
1265 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1266
1267 hr = IDrive_get_FreeSpace(drive, NULL);
1268 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1269
1270 if (type == Fixed) {
1271 VARIANT_BOOL ready = VARIANT_FALSE;
1272 VARIANT size;
1273
1274 hr = IDrive_get_IsReady(drive, &ready);
1275 ok(hr == S_OK, "got 0x%08x\n", hr);
1276 ok(ready == VARIANT_TRUE, "got %x\n", ready);
1277
1278 V_VT(&size) = VT_EMPTY;
1279 hr = IDrive_get_TotalSize(drive, &size);
1280 ok(hr == S_OK, "got 0x%08x\n", hr);
1281 ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
1282 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1283
1284 V_VT(&size) = VT_EMPTY;
1285 hr = IDrive_get_AvailableSpace(drive, &size);
1286 ok(hr == S_OK, "got 0x%08x\n", hr);
1287 ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
1288 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1289
1290 V_VT(&size) = VT_EMPTY;
1291 hr = IDrive_get_FreeSpace(drive, &size);
1292 ok(hr == S_OK, "got 0x%08x\n", hr);
1293 ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
1294 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1295 }
1296 VariantClear(&var);
1297 }
1298
1299 IEnumVARIANT_Release(enumvar);
1300 IDriveCollection_Release(drives);
1301 }
1302
1303 static void test_CreateTextFile(void)
1304 {
1305 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1306 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1307 static const WCHAR bomAW[] = {0xff,0xfe,0};
1308 WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
1309 ITextStream *stream;
1310 BSTR nameW, str;
1311 HANDLE file;
1312 HRESULT hr;
1313 BOOL ret;
1314
1315 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1316 lstrcatW(pathW, scrrunW);
1317 lstrcpyW(dirW, pathW);
1318 lstrcatW(pathW, testfileW);
1319
1320 /* dir doesn't exist */
1321 nameW = SysAllocString(pathW);
1322 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1323 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
1324
1325 ret = CreateDirectoryW(dirW, NULL);
1326 ok(ret, "got %d, %d\n", ret, GetLastError());
1327
1328 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1329 ok(hr == S_OK, "got 0x%08x\n", hr);
1330
1331 hr = ITextStream_Read(stream, 1, &str);
1332 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1333
1334 ITextStream_Release(stream);
1335
1336 /* check it's created */
1337 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1338 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1339 CloseHandle(file);
1340
1341 /* try to create again with no-overwrite mode */
1342 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1343 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
1344
1345 /* now overwrite */
1346 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1347 ok(hr == S_OK, "got 0x%08x\n", hr);
1348 ITextStream_Release(stream);
1349
1350 /* overwrite in Unicode mode, check for BOM */
1351 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
1352 ok(hr == S_OK, "got 0x%08x\n", hr);
1353 ITextStream_Release(stream);
1354
1355 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1356 ok(hr == S_OK, "got 0x%08x\n", hr);
1357 hr = ITextStream_ReadAll(stream, &str);
1358 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1359 ok(!lstrcmpW(str, bomAW), "got %s\n", wine_dbgstr_w(str));
1360 SysFreeString(str);
1361 ITextStream_Release(stream);
1362
1363 DeleteFileW(nameW);
1364 RemoveDirectoryW(dirW);
1365 SysFreeString(nameW);
1366 }
1367
1368 static void test_WriteLine(void)
1369 {
1370 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1371 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1372 WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
1373 WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
1374 char buffA[MAX_PATH];
1375 ITextStream *stream;
1376 DWORD r, len;
1377 HANDLE file;
1378 BSTR nameW;
1379 HRESULT hr;
1380 BOOL ret;
1381
1382 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1383 lstrcatW(pathW, scrrunW);
1384 lstrcpyW(dirW, pathW);
1385 lstrcatW(pathW, testfileW);
1386
1387 ret = CreateDirectoryW(dirW, NULL);
1388 ok(ret, "got %d, %d\n", ret, GetLastError());
1389
1390 /* create as ASCII file first */
1391 nameW = SysAllocString(pathW);
1392 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1393 ok(hr == S_OK, "got 0x%08x\n", hr);
1394
1395 hr = ITextStream_WriteLine(stream, nameW);
1396 ok(hr == S_OK, "got 0x%08x\n", hr);
1397 ITextStream_Release(stream);
1398
1399 /* check contents */
1400 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1401 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1402 r = 0;
1403 ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL);
1404 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1405
1406 len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, sizeof(buffW)/sizeof(WCHAR));
1407 buffW[len] = 0;
1408 lstrcpyW(buff2W, nameW);
1409 lstrcatW(buff2W, crlfW);
1410 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1411 CloseHandle(file);
1412 DeleteFileW(nameW);
1413
1414 /* same for unicode file */
1415 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1416 ok(hr == S_OK, "got 0x%08x\n", hr);
1417
1418 hr = ITextStream_WriteLine(stream, nameW);
1419 ok(hr == S_OK, "got 0x%08x\n", hr);
1420 ITextStream_Release(stream);
1421
1422 /* check contents */
1423 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1424 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1425 r = 0;
1426 ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL);
1427 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1428 buffW[r/sizeof(WCHAR)] = 0;
1429
1430 buff2W[0] = 0xfeff;
1431 buff2W[1] = 0;
1432 lstrcatW(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);
1437
1438 RemoveDirectoryW(dirW);
1439 SysFreeString(nameW);
1440 }
1441
1442 static void test_ReadAll(void)
1443 {
1444 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1445 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1446 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1447 static const WCHAR aW[] = {'A',0};
1448 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1449 ITextStream *stream;
1450 BSTR nameW;
1451 HRESULT hr;
1452 BOOL ret;
1453 BSTR str;
1454
1455 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1456 lstrcatW(pathW, scrrunW);
1457 lstrcpyW(dirW, pathW);
1458 lstrcatW(pathW, testfileW);
1459
1460 ret = CreateDirectoryW(dirW, NULL);
1461 ok(ret, "got %d, %d\n", ret, GetLastError());
1462
1463 /* Unicode file -> read with ascii stream */
1464 nameW = SysAllocString(pathW);
1465 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1466 ok(hr == S_OK, "got 0x%08x\n", hr);
1467
1468 hr = ITextStream_WriteLine(stream, nameW);
1469 ok(hr == S_OK, "got 0x%08x\n", hr);
1470
1471 str = SysAllocString(secondlineW);
1472 hr = ITextStream_WriteLine(stream, str);
1473 ok(hr == S_OK, "got 0x%08x\n", hr);
1474 SysFreeString(str);
1475
1476 hr = ITextStream_ReadAll(stream, NULL);
1477 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1478
1479 str = (void*)0xdeadbeef;
1480 hr = ITextStream_ReadAll(stream, &str);
1481 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1482 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1483
1484 ITextStream_Release(stream);
1485
1486 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1487 ok(hr == S_OK, "got 0x%08x\n", hr);
1488
1489 hr = ITextStream_ReadAll(stream, NULL);
1490 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1491
1492 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1493 str = NULL;
1494 hr = ITextStream_ReadAll(stream, &str);
1495 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1496 ok(str[0] == 0x00ff && str[1] == 0x00fe, "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
1497 SysFreeString(str);
1498 ITextStream_Release(stream);
1499
1500 /* Unicode file -> read with unicode stream */
1501 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1502 ok(hr == S_OK, "got 0x%08x\n", hr);
1503
1504 lstrcpyW(buffW, nameW);
1505 lstrcatW(buffW, crlfW);
1506 lstrcatW(buffW, secondlineW);
1507 lstrcatW(buffW, crlfW);
1508 str = NULL;
1509 hr = ITextStream_ReadAll(stream, &str);
1510 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1511 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1512 SysFreeString(str);
1513
1514 /* ReadAll one more time */
1515 str = (void*)0xdeadbeef;
1516 hr = ITextStream_ReadAll(stream, &str);
1517 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1518 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1519
1520 /* ReadLine fails the same way */
1521 str = (void*)0xdeadbeef;
1522 hr = ITextStream_ReadLine(stream, &str);
1523 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1524 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1525 ITextStream_Release(stream);
1526
1527 /* Open again and skip first line before ReadAll */
1528 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1529 ok(hr == S_OK, "got 0x%08x\n", hr);
1530
1531 str = NULL;
1532 hr = ITextStream_ReadLine(stream, &str);
1533 todo_wine {
1534 ok(hr == S_OK, "got 0x%08x\n", hr);
1535 ok(str != NULL, "got %p\n", str);
1536 }
1537 SysFreeString(str);
1538
1539 lstrcpyW(buffW, secondlineW);
1540 lstrcatW(buffW, crlfW);
1541 str = NULL;
1542 hr = ITextStream_ReadAll(stream, &str);
1543 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1544 todo_wine
1545 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1546 SysFreeString(str);
1547 ITextStream_Release(stream);
1548
1549 /* ASCII file, read with Unicode stream */
1550 /* 1. one byte content, not enough for Unicode read */
1551 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1552 ok(hr == S_OK, "got 0x%08x\n", hr);
1553 str = SysAllocString(aW);
1554 hr = ITextStream_Write(stream, str);
1555 SysFreeString(str);
1556 ITextStream_Release(stream);
1557
1558 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1559 ok(hr == S_OK, "got 0x%08x\n", hr);
1560
1561 str = (void*)0xdeadbeef;
1562 hr = ITextStream_ReadAll(stream, &str);
1563 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1564 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1565
1566 ITextStream_Release(stream);
1567
1568 DeleteFileW(nameW);
1569 RemoveDirectoryW(dirW);
1570 SysFreeString(nameW);
1571 }
1572
1573 static void test_Read(void)
1574 {
1575 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1576 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
1577 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1578 static const WCHAR aW[] = {'A',0};
1579 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1580 ITextStream *stream;
1581 BSTR nameW;
1582 HRESULT hr;
1583 BOOL ret;
1584 BSTR str;
1585
1586 GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
1587 lstrcatW(pathW, scrrunW);
1588 lstrcpyW(dirW, pathW);
1589 lstrcatW(pathW, testfileW);
1590
1591 ret = CreateDirectoryW(dirW, NULL);
1592 ok(ret, "got %d, %d\n", ret, GetLastError());
1593
1594 /* Unicode file -> read with ascii stream */
1595 nameW = SysAllocString(pathW);
1596 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1597 ok(hr == S_OK, "got 0x%08x\n", hr);
1598
1599 hr = ITextStream_WriteLine(stream, nameW);
1600 ok(hr == S_OK, "got 0x%08x\n", hr);
1601
1602 str = SysAllocString(secondlineW);
1603 hr = ITextStream_WriteLine(stream, str);
1604 ok(hr == S_OK, "got 0x%08x\n", hr);
1605 SysFreeString(str);
1606
1607 hr = ITextStream_Read(stream, 0, NULL);
1608 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1609
1610 hr = ITextStream_Read(stream, 1, NULL);
1611 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1612
1613 hr = ITextStream_Read(stream, -1, NULL);
1614 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1615
1616 str = (void*)0xdeadbeef;
1617 hr = ITextStream_Read(stream, 1, &str);
1618 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1619 ok(str == NULL, "got %p\n", str);
1620
1621 ITextStream_Release(stream);
1622
1623 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1624 ok(hr == S_OK, "got 0x%08x\n", hr);
1625
1626 hr = ITextStream_Read(stream, 1, NULL);
1627 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1628
1629 str = (void*)0xdeadbeef;
1630 hr = ITextStream_Read(stream, -1, &str);
1631 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1632 ok(str == NULL, "got %p\n", str);
1633
1634 str = (void*)0xdeadbeef;
1635 hr = ITextStream_Read(stream, 0, &str);
1636 ok(hr == S_OK, "got 0x%08x\n", hr);
1637 ok(str == NULL, "got %p\n", str);
1638
1639 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1640 str = NULL;
1641 hr = ITextStream_Read(stream, 2, &str);
1642 ok(hr == S_OK, "got 0x%08x\n", hr);
1643 ok(str[0] == 0x00ff && str[1] == 0x00fe, "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
1644 ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str));
1645 SysFreeString(str);
1646 ITextStream_Release(stream);
1647
1648 /* Unicode file -> read with unicode stream */
1649 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1650 ok(hr == S_OK, "got 0x%08x\n", hr);
1651
1652 lstrcpyW(buffW, nameW);
1653 lstrcatW(buffW, crlfW);
1654 lstrcatW(buffW, secondlineW);
1655 lstrcatW(buffW, crlfW);
1656 str = NULL;
1657 hr = ITextStream_Read(stream, 500, &str);
1658 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1659 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1660 SysFreeString(str);
1661
1662 /* ReadAll one more time */
1663 str = (void*)0xdeadbeef;
1664 hr = ITextStream_Read(stream, 10, &str);
1665 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1666 ok(str == NULL, "got %p\n", str);
1667
1668 /* ReadLine fails the same way */
1669 str = (void*)0xdeadbeef;
1670 hr = ITextStream_ReadLine(stream, &str);
1671 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1672 ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str);
1673 ITextStream_Release(stream);
1674
1675 /* Open again and skip first line before ReadAll */
1676 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1677 ok(hr == S_OK, "got 0x%08x\n", hr);
1678
1679 str = NULL;
1680 hr = ITextStream_ReadLine(stream, &str);
1681 todo_wine {
1682 ok(hr == S_OK, "got 0x%08x\n", hr);
1683 ok(str != NULL, "got %p\n", str);
1684 }
1685 SysFreeString(str);
1686
1687 lstrcpyW(buffW, secondlineW);
1688 lstrcatW(buffW, crlfW);
1689 str = NULL;
1690 hr = ITextStream_Read(stream, 100, &str);
1691 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1692 todo_wine
1693 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1694 SysFreeString(str);
1695 ITextStream_Release(stream);
1696
1697 /* ASCII file, read with Unicode stream */
1698 /* 1. one byte content, not enough for Unicode read */
1699 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1700 ok(hr == S_OK, "got 0x%08x\n", hr);
1701 str = SysAllocString(aW);
1702 hr = ITextStream_Write(stream, str);
1703 SysFreeString(str);
1704 ITextStream_Release(stream);
1705
1706 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1707 ok(hr == S_OK, "got 0x%08x\n", hr);
1708
1709 str = (void*)0xdeadbeef;
1710 hr = ITextStream_Read(stream, 500, &str);
1711 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1712 ok(str == NULL, "got %p\n", str);
1713
1714 ITextStream_Release(stream);
1715
1716 DeleteFileW(nameW);
1717 RemoveDirectoryW(dirW);
1718 SysFreeString(nameW);
1719 }
1720
1721 START_TEST(filesystem)
1722 {
1723 HRESULT hr;
1724
1725 CoInitialize(NULL);
1726
1727 hr = CoCreateInstance(&CLSID_FileSystemObject, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1728 &IID_IFileSystem3, (void**)&fs3);
1729 if(FAILED(hr)) {
1730 win_skip("Could not create FileSystem object: %08x\n", hr);
1731 return;
1732 }
1733
1734 test_interfaces();
1735 test_createfolder();
1736 test_textstream();
1737 test_GetFileVersion();
1738 test_GetParentFolderName();
1739 test_GetFileName();
1740 test_GetBaseName();
1741 test_GetAbsolutePathName();
1742 test_GetFile();
1743 test_CopyFolder();
1744 test_BuildPath();
1745 test_GetFolder();
1746 test_FolderCollection();
1747 test_FileCollection();
1748 test_DriveCollection();
1749 test_CreateTextFile();
1750 test_WriteLine();
1751 test_ReadAll();
1752 test_Read();
1753
1754 IFileSystem3_Release(fs3);
1755
1756 CoUninitialize();
1757 }