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 #include <limits.h>
24
25 #include "windows.h"
26 #include "ole2.h"
27 #include "olectl.h"
28 #include "oleauto.h"
29 #include "dispex.h"
30
31 #include "wine/test.h"
32
33 #include "initguid.h"
34 #include "scrrun.h"
35
36 static IFileSystem3 *fs3;
37
38 /* w2k and 2k3 error code. */
39 #define E_VAR_NOT_SET 0x800a005b
40
get_refcount(IUnknown * iface)41 static inline ULONG get_refcount(IUnknown *iface)
42 {
43 IUnknown_AddRef(iface);
44 return IUnknown_Release(iface);
45 }
46
47 static const WCHAR crlfW[] = {'\r','\n',0};
48 static const char utf16bom[] = {0xff,0xfe,0};
49 static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
50
51 #define GET_REFCOUNT(iface) \
52 get_refcount((IUnknown*)iface)
53
get_temp_path(const WCHAR * prefix,WCHAR * path)54 static inline void get_temp_path(const WCHAR *prefix, WCHAR *path)
55 {
56 WCHAR buffW[MAX_PATH];
57
58 GetTempPathW(MAX_PATH, buffW);
59 GetTempFileNameW(buffW, prefix, 0, path);
60 DeleteFileW(path);
61 }
62
get_fixed_drive(void)63 static IDrive *get_fixed_drive(void)
64 {
65 IDriveCollection *drives;
66 IEnumVARIANT *iter;
67 IDrive *drive;
68 HRESULT hr;
69
70 hr = IFileSystem3_get_Drives(fs3, &drives);
71 ok(hr == S_OK, "got 0x%08x\n", hr);
72
73 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&iter);
74 ok(hr == S_OK, "got 0x%08x\n", hr);
75 IDriveCollection_Release(drives);
76
77 while (1) {
78 DriveTypeConst type;
79 VARIANT var;
80
81 hr = IEnumVARIANT_Next(iter, 1, &var, NULL);
82 if (hr == S_FALSE) {
83 drive = NULL;
84 break;
85 }
86 ok(hr == S_OK, "got 0x%08x\n", hr);
87
88 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDrive, (void**)&drive);
89 ok(hr == S_OK, "got 0x%08x\n", hr);
90 VariantClear(&var);
91
92 hr = IDrive_get_DriveType(drive, &type);
93 ok(hr == S_OK, "got 0x%08x\n", hr);
94 if (type == Fixed)
95 break;
96
97 IDrive_Release(drive);
98 }
99
100 IEnumVARIANT_Release(iter);
101 return drive;
102 }
103
104 #define test_provideclassinfo(a, b) _test_provideclassinfo((IDispatch*)a, b, __LINE__)
_test_provideclassinfo(IDispatch * disp,const GUID * guid,int line)105 static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line)
106 {
107 IProvideClassInfo *classinfo;
108 TYPEATTR *attr;
109 ITypeInfo *ti;
110 IUnknown *unk;
111 HRESULT hr;
112
113 hr = IDispatch_QueryInterface(disp, &IID_IProvideClassInfo, (void **)&classinfo);
114 ok_(__FILE__,line) (hr == S_OK, "Failed to get IProvideClassInfo, %#x.\n", hr);
115
116 hr = IProvideClassInfo_GetClassInfo(classinfo, &ti);
117 ok_(__FILE__,line) (hr == S_OK, "GetClassInfo() failed, %#x.\n", hr);
118
119 hr = ITypeInfo_GetTypeAttr(ti, &attr);
120 ok_(__FILE__,line) (hr == S_OK, "GetTypeAttr() failed, %#x.\n", hr);
121
122 ok_(__FILE__,line) (IsEqualGUID(&attr->guid, guid), "Unexpected typeinfo %s, expected %s\n", wine_dbgstr_guid(&attr->guid),
123 wine_dbgstr_guid(guid));
124
125 hr = IProvideClassInfo_QueryInterface(classinfo, &IID_IUnknown, (void **)&unk);
126 ok(hr == S_OK, "Failed to QI for IUnknown.\n");
127 ok(unk == (IUnknown *)disp, "Got unk %p, original %p.\n", unk, disp);
128 IUnknown_Release(unk);
129
130 IProvideClassInfo_Release(classinfo);
131 ITypeInfo_ReleaseTypeAttr(ti, attr);
132 ITypeInfo_Release(ti);
133 }
134
test_interfaces(void)135 static void test_interfaces(void)
136 {
137 static const WCHAR nonexistent_dirW[] = {
138 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', 0};
139 static const WCHAR pathW[] = {'p','a','t','h',0};
140 static const WCHAR file_kernel32W[] = {
141 '\\', 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
142 HRESULT hr;
143 IDispatch *disp;
144 IDispatchEx *dispex;
145 IObjectWithSite *site;
146 VARIANT_BOOL b;
147 BSTR path;
148 WCHAR windows_path[MAX_PATH];
149 WCHAR file_path[MAX_PATH];
150
151 IFileSystem3_QueryInterface(fs3, &IID_IDispatch, (void**)&disp);
152
153 GetSystemDirectoryW(windows_path, MAX_PATH);
154 lstrcpyW(file_path, windows_path);
155 lstrcatW(file_path, file_kernel32W);
156
157 test_provideclassinfo(disp, &CLSID_FileSystemObject);
158
159 hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site);
160 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
161
162 hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
163 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
164
165 b = VARIANT_TRUE;
166 hr = IFileSystem3_FileExists(fs3, NULL, &b);
167 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
168 ok(b == VARIANT_FALSE, "got %x\n", b);
169
170 hr = IFileSystem3_FileExists(fs3, NULL, NULL);
171 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
172
173 path = SysAllocString(pathW);
174 b = VARIANT_TRUE;
175 hr = IFileSystem3_FileExists(fs3, path, &b);
176 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
177 ok(b == VARIANT_FALSE, "got %x\n", b);
178 SysFreeString(path);
179
180 path = SysAllocString(file_path);
181 b = VARIANT_FALSE;
182 hr = IFileSystem3_FileExists(fs3, path, &b);
183 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
184 ok(b == VARIANT_TRUE, "got %x\n", b);
185 SysFreeString(path);
186
187 path = SysAllocString(windows_path);
188 b = VARIANT_TRUE;
189 hr = IFileSystem3_FileExists(fs3, path, &b);
190 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
191 ok(b == VARIANT_FALSE, "got %x\n", b);
192 SysFreeString(path);
193
194 /* Folder Exists */
195 hr = IFileSystem3_FolderExists(fs3, NULL, NULL);
196 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
197
198 path = SysAllocString(windows_path);
199 hr = IFileSystem3_FolderExists(fs3, path, &b);
200 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
201 ok(b == VARIANT_TRUE, "Folder doesn't exists\n");
202 SysFreeString(path);
203
204 path = SysAllocString(nonexistent_dirW);
205 hr = IFileSystem3_FolderExists(fs3, path, &b);
206 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
207 ok(b == VARIANT_FALSE, "Folder exists\n");
208 SysFreeString(path);
209
210 path = SysAllocString(file_path);
211 hr = IFileSystem3_FolderExists(fs3, path, &b);
212 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
213 ok(b == VARIANT_FALSE, "Folder exists\n");
214 SysFreeString(path);
215
216 IDispatch_Release(disp);
217 }
218
test_createfolder(void)219 static void test_createfolder(void)
220 {
221 WCHAR buffW[MAX_PATH];
222 HRESULT hr;
223 BSTR path;
224 IFolder *folder;
225 BOOL ret;
226
227 get_temp_path(NULL, buffW);
228 ret = CreateDirectoryW(buffW, NULL);
229 ok(ret, "got %d, %d\n", ret, GetLastError());
230
231 /* create existing directory */
232 path = SysAllocString(buffW);
233 folder = (void*)0xdeabeef;
234 hr = IFileSystem3_CreateFolder(fs3, path, &folder);
235 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
236 ok(folder == NULL, "got %p\n", folder);
237 SysFreeString(path);
238 RemoveDirectoryW(buffW);
239 }
240
test_textstream(void)241 static void test_textstream(void)
242 {
243 ITextStream *stream;
244 VARIANT_BOOL b;
245 DWORD written;
246 HANDLE file;
247 HRESULT hr;
248 BSTR name, data;
249 BOOL ret;
250
251 file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
252 CloseHandle(file);
253
254 name = SysAllocString(testfileW);
255 b = VARIANT_FALSE;
256 hr = IFileSystem3_FileExists(fs3, name, &b);
257 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
258 ok(b == VARIANT_TRUE, "got %x\n", b);
259
260 /* different mode combinations */
261 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
262 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
263
264 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
265 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
266
267 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForReading, VARIANT_FALSE, TristateFalse, &stream);
268 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
269
270 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
271 ok(hr == S_OK, "got 0x%08x\n", hr);
272 hr = ITextStream_Read(stream, 1, &data);
273 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
274 ITextStream_Release(stream);
275
276 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
277 ok(hr == S_OK, "got 0x%08x\n", hr);
278 hr = ITextStream_Read(stream, 1, &data);
279 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
280 ITextStream_Release(stream);
281
282 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
283 ok(hr == S_OK, "got 0x%08x\n", hr);
284
285 /* try to write when open for reading */
286 hr = ITextStream_WriteLine(stream, name);
287 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
288
289 hr = ITextStream_Write(stream, name);
290 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
291
292 hr = ITextStream_get_AtEndOfStream(stream, NULL);
293 ok(hr == E_POINTER, "got 0x%08x\n", hr);
294
295 b = 10;
296 hr = ITextStream_get_AtEndOfStream(stream, &b);
297 ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr);
298 ok(b == VARIANT_TRUE, "got 0x%x\n", b);
299
300 ITextStream_Release(stream);
301
302 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
303 ok(hr == S_OK, "got 0x%08x\n", hr);
304
305 b = 10;
306 hr = ITextStream_get_AtEndOfStream(stream, &b);
307 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
308 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
309
310 b = 10;
311 hr = ITextStream_get_AtEndOfLine(stream, &b);
312 todo_wine {
313 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
314 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
315 }
316 hr = ITextStream_Read(stream, 1, &data);
317 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
318
319 hr = ITextStream_ReadLine(stream, &data);
320 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
321
322 hr = ITextStream_ReadAll(stream, &data);
323 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
324
325 ITextStream_Release(stream);
326
327 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
328 ok(hr == S_OK, "got 0x%08x\n", hr);
329
330 b = 10;
331 hr = ITextStream_get_AtEndOfStream(stream, &b);
332 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
333 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
334
335 b = 10;
336 hr = ITextStream_get_AtEndOfLine(stream, &b);
337 todo_wine {
338 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
339 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
340 }
341 hr = ITextStream_Read(stream, 1, &data);
342 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
343
344 hr = ITextStream_ReadLine(stream, &data);
345 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
346
347 hr = ITextStream_ReadAll(stream, &data);
348 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
349
350 ITextStream_Release(stream);
351
352 /* now with non-empty file */
353 file = CreateFileW(testfileW, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
354 ret = WriteFile(file, testfileW, sizeof(testfileW), &written, NULL);
355 ok(ret && written == sizeof(testfileW), "got %d\n", ret);
356 CloseHandle(file);
357
358 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
359 ok(hr == S_OK, "got 0x%08x\n", hr);
360 b = 10;
361 hr = ITextStream_get_AtEndOfStream(stream, &b);
362 ok(hr == S_OK, "got 0x%08x\n", hr);
363 ok(b == VARIANT_FALSE, "got 0x%x\n", b);
364 ITextStream_Release(stream);
365
366 SysFreeString(name);
367 DeleteFileW(testfileW);
368 }
369
test_GetFileVersion(void)370 static void test_GetFileVersion(void)
371 {
372 static const WCHAR k32W[] = {'\\','k','e','r','n','e','l','3','2','.','d','l','l',0};
373 static const WCHAR k33W[] = {'\\','k','e','r','n','e','l','3','3','.','d','l','l',0};
374 WCHAR pathW[MAX_PATH], filenameW[MAX_PATH];
375 BSTR path, version;
376 HRESULT hr;
377
378 GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW));
379
380 lstrcpyW(filenameW, pathW);
381 lstrcatW(filenameW, k32W);
382
383 path = SysAllocString(filenameW);
384 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
385 ok(hr == S_OK, "got 0x%08x\n", hr);
386 ok(*version != 0, "got %s\n", wine_dbgstr_w(version));
387 SysFreeString(version);
388 SysFreeString(path);
389
390 lstrcpyW(filenameW, pathW);
391 lstrcatW(filenameW, k33W);
392
393 path = SysAllocString(filenameW);
394 version = (void*)0xdeadbeef;
395 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
396 ok(broken(hr == S_OK) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
397 if (hr == S_OK)
398 {
399 ok(*version == 0, "got %s\n", wine_dbgstr_w(version));
400 SysFreeString(version);
401 }
402 else
403 ok(version == (void*)0xdeadbeef, "got %p\n", version);
404 SysFreeString(path);
405 }
406
test_GetParentFolderName(void)407 static void test_GetParentFolderName(void)
408 {
409 static const WCHAR path1[] = {'a',0};
410 static const WCHAR path2[] = {'a','/','a','/','a',0};
411 static const WCHAR path3[] = {'a','\\','a','\\','a',0};
412 static const WCHAR path4[] = {'a','/','a','/','/','\\','\\',0};
413 static const WCHAR path5[] = {'c',':','\\','\\','a',0};
414 static const WCHAR path6[] = {'a','c',':','\\','a',0};
415 static const WCHAR result2[] = {'a','/','a',0};
416 static const WCHAR result3[] = {'a','\\','a',0};
417 static const WCHAR result4[] = {'a',0};
418 static const WCHAR result5[] = {'c',':','\\',0};
419 static const WCHAR result6[] = {'a','c',':',0};
420
421 static const struct {
422 const WCHAR *path;
423 const WCHAR *result;
424 } tests[] = {
425 {NULL, NULL},
426 {path1, NULL},
427 {path2, result2},
428 {path3, result3},
429 {path4, result4},
430 {path5, result5},
431 {path6, result6}
432 };
433
434 BSTR path, result;
435 HRESULT hr;
436 int i;
437
438 hr = IFileSystem3_GetParentFolderName(fs3, NULL, NULL);
439 ok(hr == E_POINTER, "GetParentFolderName returned %x, expected E_POINTER\n", hr);
440
441 for(i=0; i < ARRAY_SIZE(tests); i++) {
442 result = (BSTR)0xdeadbeef;
443 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
444 hr = IFileSystem3_GetParentFolderName(fs3, path, &result);
445 ok(hr == S_OK, "%d) GetParentFolderName returned %x, expected S_OK\n", i, hr);
446 if(!tests[i].result)
447 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
448 else
449 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
450 SysFreeString(path);
451 SysFreeString(result);
452 }
453 }
454
test_GetFileName(void)455 static void test_GetFileName(void)
456 {
457 static const WCHAR path1[] = {'a',0};
458 static const WCHAR path2[] = {'a','/','a','.','b',0};
459 static const WCHAR path3[] = {'a','\\',0};
460 static const WCHAR path4[] = {'c',':',0};
461 static const WCHAR path5[] = {'/','\\',0};
462 static const WCHAR result2[] = {'a','.','b',0};
463 static const WCHAR result3[] = {'a',0};
464
465 static const struct {
466 const WCHAR *path;
467 const WCHAR *result;
468 } tests[] = {
469 {NULL, NULL},
470 {path1, path1},
471 {path2, result2},
472 {path3, result3},
473 {path4, NULL},
474 {path5, NULL}
475 };
476
477 BSTR path, result;
478 HRESULT hr;
479 int i;
480
481 hr = IFileSystem3_GetFileName(fs3, NULL, NULL);
482 ok(hr == E_POINTER, "GetFileName returned %x, expected E_POINTER\n", hr);
483
484 for(i=0; i < ARRAY_SIZE(tests); i++) {
485 result = (BSTR)0xdeadbeef;
486 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
487 hr = IFileSystem3_GetFileName(fs3, path, &result);
488 ok(hr == S_OK, "%d) GetFileName returned %x, expected S_OK\n", i, hr);
489 if(!tests[i].result)
490 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
491 else
492 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
493 SysFreeString(path);
494 SysFreeString(result);
495 }
496 }
497
test_GetBaseName(void)498 static void test_GetBaseName(void)
499 {
500 static const WCHAR path1[] = {'a',0};
501 static const WCHAR path2[] = {'a','/','a','.','b','.','c',0};
502 static const WCHAR path3[] = {'a','.','b','\\',0};
503 static const WCHAR path4[] = {'c',':',0};
504 static const WCHAR path5[] = {'/','\\',0};
505 static const WCHAR path6[] = {'.','a',0};
506 static const WCHAR result1[] = {'a',0};
507 static const WCHAR result2[] = {'a','.','b',0};
508 static const WCHAR result6[] = {0};
509
510 static const struct {
511 const WCHAR *path;
512 const WCHAR *result;
513 } tests[] = {
514 {NULL, NULL},
515 {path1, result1},
516 {path2, result2},
517 {path3, result1},
518 {path4, NULL},
519 {path5, NULL},
520 {path6, result6}
521 };
522
523 BSTR path, result;
524 HRESULT hr;
525 int i;
526
527 hr = IFileSystem3_GetBaseName(fs3, NULL, NULL);
528 ok(hr == E_POINTER, "GetBaseName returned %x, expected E_POINTER\n", hr);
529
530 for(i=0; i < ARRAY_SIZE(tests); i++) {
531 result = (BSTR)0xdeadbeef;
532 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
533 hr = IFileSystem3_GetBaseName(fs3, path, &result);
534 ok(hr == S_OK, "%d) GetBaseName returned %x, expected S_OK\n", i, hr);
535 if(!tests[i].result)
536 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
537 else
538 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
539 SysFreeString(path);
540 SysFreeString(result);
541 }
542 }
543
test_GetAbsolutePathName(void)544 static void test_GetAbsolutePathName(void)
545 {
546 static const WCHAR dir1[] = {'t','e','s','t','_','d','i','r','1',0};
547 static const WCHAR dir2[] = {'t','e','s','t','_','d','i','r','2',0};
548 static const WCHAR dir_match1[] = {'t','e','s','t','_','d','i','r','*',0};
549 static const WCHAR dir_match2[] = {'t','e','s','t','_','d','i','*',0};
550 static const WCHAR cur_dir[] = {'.',0};
551
552 WIN32_FIND_DATAW fdata;
553 HANDLE find;
554 WCHAR buf[MAX_PATH], buf2[MAX_PATH];
555 BSTR path, result;
556 HRESULT hr;
557
558 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, NULL);
559 ok(hr == E_POINTER, "GetAbsolutePathName returned %x, expected E_POINTER\n", hr);
560
561 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result);
562 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
563 GetFullPathNameW(cur_dir, MAX_PATH, buf, NULL);
564 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
565 SysFreeString(result);
566
567 find = FindFirstFileW(dir_match2, &fdata);
568 if(find != INVALID_HANDLE_VALUE) {
569 skip("GetAbsolutePathName tests\n");
570 FindClose(find);
571 return;
572 }
573
574 path = SysAllocString(dir_match1);
575 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
576 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
577 GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL);
578 ok(!lstrcmpiW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2));
579 SysFreeString(result);
580
581 ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1));
582 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
583 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
584 GetFullPathNameW(dir1, MAX_PATH, buf, NULL);
585 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
586 wine_dbgstr_w(result), wine_dbgstr_w(buf));
587 SysFreeString(result);
588
589 ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2));
590 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
591 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
592 if(!lstrcmpiW(buf, result) || !lstrcmpiW(buf2, result)) {
593 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
594 wine_dbgstr_w(result), wine_dbgstr_w(buf));
595 }else {
596 GetFullPathNameW(dir2, MAX_PATH, buf, NULL);
597 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n",
598 wine_dbgstr_w(result), wine_dbgstr_w(buf));
599 }
600 SysFreeString(result);
601
602 SysFreeString(path);
603 path = SysAllocString(dir_match2);
604 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
605 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
606 GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL);
607 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
608 SysFreeString(result);
609 SysFreeString(path);
610
611 RemoveDirectoryW(dir1);
612 RemoveDirectoryW(dir2);
613 }
614
test_GetFile(void)615 static void test_GetFile(void)
616 {
617 static const WCHAR slW[] = {'\\',0};
618 BSTR path, str;
619 WCHAR pathW[MAX_PATH];
620 FileAttribute fa;
621 VARIANT size;
622 DWORD gfa, new_gfa;
623 IFile *file;
624 HRESULT hr;
625 HANDLE hf;
626 BOOL ret;
627 DATE date;
628
629 get_temp_path(NULL, pathW);
630
631 path = SysAllocString(pathW);
632 hr = IFileSystem3_GetFile(fs3, path, NULL);
633 ok(hr == E_POINTER, "GetFile returned %x, expected E_POINTER\n", hr);
634 hr = IFileSystem3_GetFile(fs3, NULL, &file);
635 ok(hr == E_INVALIDARG, "GetFile returned %x, expected E_INVALIDARG\n", hr);
636
637 file = (IFile*)0xdeadbeef;
638 hr = IFileSystem3_GetFile(fs3, path, &file);
639 ok(!file, "file != NULL\n");
640 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
641
642 hf = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
643 if(hf == INVALID_HANDLE_VALUE) {
644 skip("Can't create temporary file\n");
645 SysFreeString(path);
646 return;
647 }
648 CloseHandle(hf);
649
650 hr = IFileSystem3_GetFile(fs3, path, &file);
651 ok(hr == S_OK, "GetFile returned %x, expected S_OK\n", hr);
652
653 hr = IFile_get_DateLastModified(file, NULL);
654 ok(hr == E_POINTER, "got 0x%08x\n", hr);
655
656 date = 0.0;
657 hr = IFile_get_DateLastModified(file, &date);
658 ok(hr == S_OK, "got 0x%08x\n", hr);
659 ok(date > 0.0, "got %f\n", date);
660
661 hr = IFile_get_Path(file, NULL);
662 ok(hr == E_POINTER, "got 0x%08x\n", hr);
663
664 hr = IFile_get_Path(file, &str);
665 ok(hr == S_OK, "got 0x%08x\n", hr);
666 ok(!lstrcmpiW(str, pathW), "got %s\n", wine_dbgstr_w(str));
667 SysFreeString(str);
668
669 #define FILE_ATTR_MASK (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
670 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | \
671 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED)
672
673 hr = IFile_get_Attributes(file, &fa);
674 gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK;
675 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
676 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa);
677
678 hr = IFile_put_Attributes(file, gfa | FILE_ATTRIBUTE_READONLY);
679 ok(hr == S_OK, "put_Attributes failed: %08x\n", hr);
680 new_gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK;
681 ok(new_gfa == (gfa|FILE_ATTRIBUTE_READONLY), "new_gfa = %x, expected %x\n", new_gfa, gfa|FILE_ATTRIBUTE_READONLY);
682
683 hr = IFile_get_Attributes(file, &fa);
684 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
685 ok(fa == new_gfa, "fa = %x, expected %x\n", fa, new_gfa);
686
687 hr = IFile_put_Attributes(file, gfa);
688 ok(hr == S_OK, "put_Attributes failed: %08x\n", hr);
689 new_gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK;
690 ok(new_gfa == gfa, "new_gfa = %x, expected %x\n", new_gfa, gfa);
691
692 hr = IFile_get_Attributes(file, &fa);
693 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
694 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa);
695
696 hr = IFile_get_Size(file, &size);
697 ok(hr == S_OK, "get_Size returned %x, expected S_OK\n", hr);
698 ok(V_VT(&size) == VT_I4, "V_VT(&size) = %d, expected VT_I4\n", V_VT(&size));
699 ok(V_I4(&size) == 0, "V_I4(&size) = %d, expected 0\n", V_I4(&size));
700 IFile_Release(file);
701
702 hr = IFileSystem3_DeleteFile(fs3, path, FALSE);
703 ok(hr==CTL_E_PERMISSIONDENIED || broken(hr==S_OK),
704 "DeleteFile returned %x, expected CTL_E_PERMISSIONDENIED\n", hr);
705 if(hr != S_OK) {
706 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
707 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
708 }
709 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
710 ok(hr == CTL_E_FILENOTFOUND, "DeleteFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
711
712 SysFreeString(path);
713
714 /* try with directory */
715 lstrcatW(pathW, slW);
716 ret = CreateDirectoryW(pathW, NULL);
717 ok(ret, "got %d, error %d\n", ret, GetLastError());
718
719 path = SysAllocString(pathW);
720 hr = IFileSystem3_GetFile(fs3, path, &file);
721 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected S_OK\n", hr);
722 SysFreeString(path);
723
724 RemoveDirectoryW(pathW);
725 }
726
create_file(const WCHAR * name)727 static inline BOOL create_file(const WCHAR *name)
728 {
729 HANDLE f = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
730 CloseHandle(f);
731 return f != INVALID_HANDLE_VALUE;
732 }
733
create_path(const WCHAR * folder,const WCHAR * name,WCHAR * ret)734 static inline void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret)
735 {
736 DWORD len = lstrlenW(folder);
737 memmove(ret, folder, len*sizeof(WCHAR));
738 ret[len] = '\\';
739 memmove(ret+len+1, name, (lstrlenW(name)+1)*sizeof(WCHAR));
740 }
741
test_CopyFolder(void)742 static void test_CopyFolder(void)
743 {
744 static const WCHAR filesystem3_dir[] = {'f','i','l','e','s','y','s','t','e','m','3','_','t','e','s','t',0};
745 static const WCHAR s1[] = {'s','r','c','1',0};
746 static const WCHAR s[] = {'s','r','c','*',0};
747 static const WCHAR d[] = {'d','s','t',0};
748 static const WCHAR empty[] = {0};
749
750 WCHAR tmp[MAX_PATH];
751 BSTR bsrc, bdst;
752 HRESULT hr;
753
754 if(!CreateDirectoryW(filesystem3_dir, NULL)) {
755 skip("can't create temporary directory\n");
756 return;
757 }
758
759 create_path(filesystem3_dir, s1, tmp);
760 bsrc = SysAllocString(tmp);
761 create_path(filesystem3_dir, d, tmp);
762 bdst = SysAllocString(tmp);
763 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
764 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
765
766 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
767 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
768
769 ok(create_file(bsrc), "can't create %s file\n", wine_dbgstr_w(bsrc));
770 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
771 ok(hr == S_OK, "CopyFile returned %x, expected S_OK\n", hr);
772
773 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
774 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
775
776 hr = IFileSystem3_DeleteFile(fs3, bsrc, VARIANT_FALSE);
777 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
778
779 ok(CreateDirectoryW(bsrc, NULL), "can't create %s\n", wine_dbgstr_w(bsrc));
780 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
781 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
782
783 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
784 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
785
786 hr = IFileSystem3_DeleteFile(fs3, bdst, VARIANT_TRUE);
787 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
788
789 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
790 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
791
792 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
793 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
794 create_path(tmp, s1, tmp);
795 ok(GetFileAttributesW(tmp) == INVALID_FILE_ATTRIBUTES,
796 "%s file exists\n", wine_dbgstr_w(tmp));
797
798 create_path(filesystem3_dir, d, tmp);
799 create_path(tmp, empty, tmp);
800 SysFreeString(bdst);
801 bdst = SysAllocString(tmp);
802 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
803 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
804 create_path(tmp, s1, tmp);
805 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
806 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
807 ok(RemoveDirectoryW(tmp), "can't remove %s directory\n", wine_dbgstr_w(tmp));
808 create_path(filesystem3_dir, d, tmp);
809 SysFreeString(bdst);
810 bdst = SysAllocString(tmp);
811
812
813 create_path(filesystem3_dir, s, tmp);
814 SysFreeString(bsrc);
815 bsrc = SysAllocString(tmp);
816 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
817 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
818 create_path(filesystem3_dir, d, tmp);
819 create_path(tmp, s1, tmp);
820 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
821 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
822
823 hr = IFileSystem3_DeleteFolder(fs3, bdst, VARIANT_FALSE);
824 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
825
826 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
827 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
828
829 create_path(filesystem3_dir, s1, tmp);
830 SysFreeString(bsrc);
831 bsrc = SysAllocString(tmp);
832 create_path(tmp, s1, tmp);
833 ok(create_file(tmp), "can't create %s file\n", wine_dbgstr_w(tmp));
834 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
835 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
836
837 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
838 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
839
840 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
841 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
842 SysFreeString(bsrc);
843 SysFreeString(bdst);
844
845 bsrc = SysAllocString(filesystem3_dir);
846 hr = IFileSystem3_DeleteFolder(fs3, bsrc, VARIANT_FALSE);
847 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
848 SysFreeString(bsrc);
849 }
850
bstr_from_str(const char * str)851 static BSTR bstr_from_str(const char *str)
852 {
853 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
854 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */
855 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
856 return ret;
857 }
858
859 struct buildpath_test
860 {
861 const char *path;
862 const char *name;
863 const char *result;
864 };
865
866 static struct buildpath_test buildpath_data[] =
867 {
868 { "C:\\path", "..\\name.tmp", "C:\\path\\..\\name.tmp" },
869 { "C:\\path", "\\name.tmp", "C:\\path\\name.tmp" },
870 { "C:\\path", "name.tmp", "C:\\path\\name.tmp" },
871 { "C:\\path\\", "name.tmp", "C:\\path\\name.tmp" },
872 { "C:\\path", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
873 { "C:\\path\\", "\\name.tmp", "C:\\path\\name.tmp" },
874 { "C:\\path\\", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
875 { "C:\\path\\\\", "\\\\name.tmp", "C:\\path\\\\\\name.tmp" },
876 { "C:\\\\", "\\name.tmp", "C:\\\\name.tmp" },
877 { "C:", "name.tmp", "C:name.tmp" },
878 { "C:", "\\\\name.tmp", "C:\\\\name.tmp" },
879 { NULL }
880 };
881
test_BuildPath(void)882 static void test_BuildPath(void)
883 {
884 struct buildpath_test *ptr = buildpath_data;
885 BSTR ret, path;
886 HRESULT hr;
887 int i = 0;
888
889 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, NULL);
890 ok(hr == E_POINTER, "got 0x%08x\n", hr);
891
892 ret = (BSTR)0xdeadbeef;
893 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, &ret);
894 ok(hr == S_OK, "got 0x%08x\n", hr);
895 ok(*ret == 0, "got %p\n", ret);
896 SysFreeString(ret);
897
898 ret = (BSTR)0xdeadbeef;
899 path = bstr_from_str("path");
900 hr = IFileSystem3_BuildPath(fs3, path, NULL, &ret);
901 ok(hr == S_OK, "got 0x%08x\n", hr);
902 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
903 SysFreeString(ret);
904 SysFreeString(path);
905
906 ret = (BSTR)0xdeadbeef;
907 path = bstr_from_str("path");
908 hr = IFileSystem3_BuildPath(fs3, NULL, path, &ret);
909 ok(hr == S_OK, "got 0x%08x\n", hr);
910 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
911 SysFreeString(ret);
912 SysFreeString(path);
913
914 while (ptr->path)
915 {
916 BSTR name, result;
917
918 ret = NULL;
919 path = bstr_from_str(ptr->path);
920 name = bstr_from_str(ptr->name);
921 result = bstr_from_str(ptr->result);
922 hr = IFileSystem3_BuildPath(fs3, path, name, &ret);
923 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
924 if (hr == S_OK)
925 {
926 ok(!lstrcmpW(ret, result), "%d: got wrong path %s, expected %s\n", i, wine_dbgstr_w(ret),
927 wine_dbgstr_w(result));
928 SysFreeString(ret);
929 }
930 SysFreeString(path);
931 SysFreeString(name);
932 SysFreeString(result);
933
934 i++;
935 ptr++;
936 }
937 }
938
test_GetFolder(void)939 static void test_GetFolder(void)
940 {
941 static const WCHAR dummyW[] = {'d','u','m','m','y',0};
942 WCHAR buffW[MAX_PATH];
943 IFolder *folder;
944 HRESULT hr;
945 BSTR str;
946
947 folder = (void*)0xdeadbeef;
948 hr = IFileSystem3_GetFolder(fs3, NULL, &folder);
949 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
950 ok(folder == NULL, "got %p\n", folder);
951
952 hr = IFileSystem3_GetFolder(fs3, NULL, NULL);
953 ok(hr == E_POINTER, "got 0x%08x\n", hr);
954
955 /* something that doesn't exist */
956 str = SysAllocString(dummyW);
957
958 hr = IFileSystem3_GetFolder(fs3, str, NULL);
959 ok(hr == E_POINTER, "got 0x%08x\n", hr);
960
961 folder = (void*)0xdeadbeef;
962 hr = IFileSystem3_GetFolder(fs3, str, &folder);
963 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
964 ok(folder == NULL, "got %p\n", folder);
965 SysFreeString(str);
966
967 GetWindowsDirectoryW(buffW, MAX_PATH);
968 str = SysAllocString(buffW);
969 hr = IFileSystem3_GetFolder(fs3, str, &folder);
970 ok(hr == S_OK, "got 0x%08x\n", hr);
971 SysFreeString(str);
972 test_provideclassinfo(folder, &CLSID_Folder);
973 IFolder_Release(folder);
974 }
975
_test_clone(IEnumVARIANT * enumvar,BOOL position_inherited,LONG count,int line)976 static void _test_clone(IEnumVARIANT *enumvar, BOOL position_inherited, LONG count, int line)
977 {
978 HRESULT hr;
979 IEnumVARIANT *clone;
980 ULONG fetched;
981 VARIANT var, var2;
982
983 hr = IEnumVARIANT_Reset(enumvar);
984 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
985
986 VariantInit(&var);
987 fetched = -1;
988 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
989 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
990 ok(fetched == 1, "%d: got %d\n", line, fetched);
991
992 /* clone enumerator */
993 hr = IEnumVARIANT_Clone(enumvar, &clone);
994 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
995 ok(clone != enumvar, "%d: got %p, %p\n", line, enumvar, clone);
996
997 /* check if clone inherits position */
998 VariantInit(&var2);
999 fetched = -1;
1000 hr = IEnumVARIANT_Next(clone, 1, &var2, &fetched);
1001 if (position_inherited && count == 1)
1002 {
1003 ok(hr == S_FALSE, "%d: got 0x%08x\n", line, hr);
1004 ok(fetched == 0, "%d: got %d\n", line, fetched);
1005 }
1006 else
1007 {
1008 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
1009 ok(fetched == 1, "%d: got %d\n", line, fetched);
1010 if (!position_inherited)
1011 todo_wine ok(V_DISPATCH(&var) == V_DISPATCH(&var2), "%d: values don't match\n", line);
1012 else
1013 {
1014 fetched = -1;
1015 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1016 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
1017 ok(fetched == 1, "%d: got %d\n", line, fetched);
1018 todo_wine ok(V_DISPATCH(&var) == V_DISPATCH(&var2), "%d: values don't match\n", line);
1019 }
1020 }
1021
1022 VariantClear(&var2);
1023 VariantClear(&var);
1024 IEnumVARIANT_Release(clone);
1025
1026 hr = IEnumVARIANT_Reset(enumvar);
1027 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
1028 }
1029 #define test_clone(a, b, c) _test_clone(a, b, c, __LINE__)
1030
1031 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
test_FolderCollection(void)1032 static void test_FolderCollection(void)
1033 {
1034 static const WCHAR fooW[] = {'f','o','o',0};
1035 static const WCHAR aW[] = {'\\','a',0};
1036 static const WCHAR bW[] = {'\\','b',0};
1037 static const WCHAR cW[] = {'\\','c',0};
1038 IFolderCollection *folders;
1039 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
1040 IEnumVARIANT *enumvar;
1041 LONG count, ref, ref2, i;
1042 IUnknown *unk, *unk2;
1043 IFolder *folder;
1044 ULONG fetched;
1045 VARIANT var, var2[2];
1046 HRESULT hr;
1047 BSTR str;
1048 int found_a = 0, found_b = 0, found_c = 0;
1049
1050 get_temp_path(fooW, buffW);
1051 CreateDirectoryW(buffW, NULL);
1052
1053 str = SysAllocString(buffW);
1054 hr = IFileSystem3_GetFolder(fs3, str, &folder);
1055 ok(hr == S_OK, "got 0x%08x\n", hr);
1056 SysFreeString(str);
1057
1058 hr = IFolder_get_SubFolders(folder, NULL);
1059 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1060
1061 hr = IFolder_get_Path(folder, NULL);
1062 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1063
1064 hr = IFolder_get_Path(folder, &str);
1065 ok(hr == S_OK, "got 0x%08x\n", hr);
1066 ok(!lstrcmpiW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1067 SysFreeString(str);
1068
1069 lstrcpyW(pathW, buffW);
1070 lstrcatW(pathW, aW);
1071 CreateDirectoryW(pathW, NULL);
1072
1073 lstrcpyW(pathW, buffW);
1074 lstrcatW(pathW, bW);
1075 CreateDirectoryW(pathW, NULL);
1076
1077 hr = IFolder_get_SubFolders(folder, &folders);
1078 ok(hr == S_OK, "got 0x%08x\n", hr);
1079 test_provideclassinfo(folders, &CLSID_Folders);
1080 IFolder_Release(folder);
1081
1082 count = 0;
1083 hr = IFolderCollection_get_Count(folders, &count);
1084 ok(hr == S_OK, "got 0x%08x\n", hr);
1085 ok(count == 2, "got %d\n", count);
1086
1087 lstrcpyW(pathW, buffW);
1088 lstrcatW(pathW, cW);
1089 CreateDirectoryW(pathW, NULL);
1090
1091 /* every time property is requested it scans directory */
1092 count = 0;
1093 hr = IFolderCollection_get_Count(folders, &count);
1094 ok(hr == S_OK, "got 0x%08x\n", hr);
1095 ok(count == 3, "got %d\n", count);
1096
1097 hr = IFolderCollection_get__NewEnum(folders, NULL);
1098 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1099
1100 hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk);
1101 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1102
1103 /* NewEnum creates new instance each time it's called */
1104 ref = GET_REFCOUNT(folders);
1105
1106 unk = NULL;
1107 hr = IFolderCollection_get__NewEnum(folders, &unk);
1108 ok(hr == S_OK, "got 0x%08x\n", hr);
1109
1110 ref2 = GET_REFCOUNT(folders);
1111 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1112
1113 unk2 = NULL;
1114 hr = IFolderCollection_get__NewEnum(folders, &unk2);
1115 ok(hr == S_OK, "got 0x%08x\n", hr);
1116 ok(unk != unk2, "got %p, %p\n", unk2, unk);
1117 IUnknown_Release(unk2);
1118
1119 /* now get IEnumVARIANT */
1120 ref = GET_REFCOUNT(folders);
1121 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1122 ok(hr == S_OK, "got 0x%08x\n", hr);
1123 ref2 = GET_REFCOUNT(folders);
1124 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1125
1126 test_clone(enumvar, FALSE, count);
1127
1128 for (i = 0; i < 3; i++)
1129 {
1130 VariantInit(&var);
1131 fetched = 0;
1132 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1133 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1134 ok(fetched == 1, "%d: got %d\n", i, fetched);
1135 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1136
1137 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder);
1138 ok(hr == S_OK, "got 0x%08x\n", hr);
1139
1140 str = NULL;
1141 hr = IFolder_get_Name(folder, &str);
1142 ok(hr == S_OK, "got 0x%08x\n", hr);
1143 if (!lstrcmpW(str, aW + 1))
1144 found_a++;
1145 else if (!lstrcmpW(str, bW + 1))
1146 found_b++;
1147 else if (!lstrcmpW(str, cW + 1))
1148 found_c++;
1149 else
1150 ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str));
1151 SysFreeString(str);
1152
1153 IFolder_Release(folder);
1154 VariantClear(&var);
1155 }
1156
1157 ok(found_a == 1 && found_b == 1 && found_c == 1,
1158 "each folder should be found 1 time instead of %d/%d/%d\n",
1159 found_a, found_b, found_c);
1160
1161 VariantInit(&var);
1162 fetched = -1;
1163 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1164 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1165 ok(fetched == 0, "got %d\n", fetched);
1166
1167 hr = IEnumVARIANT_Reset(enumvar);
1168 ok(hr == S_OK, "got 0x%08x\n", hr);
1169 hr = IEnumVARIANT_Skip(enumvar, 2);
1170 ok(hr == S_OK, "got 0x%08x\n", hr);
1171 hr = IEnumVARIANT_Skip(enumvar, 0);
1172 ok(hr == S_OK, "got 0x%08x\n", hr);
1173
1174 VariantInit(&var2[0]);
1175 VariantInit(&var2[1]);
1176 fetched = -1;
1177 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1178 ok(hr == S_OK, "got 0x%08x\n", hr);
1179 ok(fetched == 0, "got %d\n", fetched);
1180 fetched = -1;
1181 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1182 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1183 ok(fetched == 1, "got %d\n", fetched);
1184 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1185 VariantClear(&var2[0]);
1186 VariantClear(&var2[1]);
1187
1188 IEnumVARIANT_Release(enumvar);
1189 IUnknown_Release(unk);
1190
1191 lstrcpyW(pathW, buffW);
1192 lstrcatW(pathW, aW);
1193 RemoveDirectoryW(pathW);
1194 lstrcpyW(pathW, buffW);
1195 lstrcatW(pathW, bW);
1196 RemoveDirectoryW(pathW);
1197 lstrcpyW(pathW, buffW);
1198 lstrcatW(pathW, cW);
1199 RemoveDirectoryW(pathW);
1200 RemoveDirectoryW(buffW);
1201
1202 IFolderCollection_Release(folders);
1203 }
1204
1205 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
test_FileCollection(void)1206 static void test_FileCollection(void)
1207 {
1208 static const WCHAR fooW[] = {'\\','f','o','o',0};
1209 static const WCHAR aW[] = {'\\','a',0};
1210 static const WCHAR bW[] = {'\\','b',0};
1211 static const WCHAR cW[] = {'\\','c',0};
1212 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
1213 IFolder *folder;
1214 IFileCollection *files;
1215 IFile *file;
1216 IEnumVARIANT *enumvar;
1217 LONG count, ref, ref2, i;
1218 IUnknown *unk, *unk2;
1219 ULONG fetched;
1220 VARIANT var, var2[2];
1221 HRESULT hr;
1222 BSTR str;
1223 HANDLE file_a, file_b, file_c;
1224 int found_a = 0, found_b = 0, found_c = 0;
1225
1226 get_temp_path(fooW, buffW);
1227 CreateDirectoryW(buffW, NULL);
1228
1229 str = SysAllocString(buffW);
1230 hr = IFileSystem3_GetFolder(fs3, str, &folder);
1231 ok(hr == S_OK, "got 0x%08x\n", hr);
1232 SysFreeString(str);
1233
1234 hr = IFolder_get_Files(folder, NULL);
1235 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1236
1237 lstrcpyW(pathW, buffW);
1238 lstrcatW(pathW, aW);
1239 file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1240 FILE_FLAG_DELETE_ON_CLOSE, 0);
1241 lstrcpyW(pathW, buffW);
1242 lstrcatW(pathW, bW);
1243 file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1244 FILE_FLAG_DELETE_ON_CLOSE, 0);
1245
1246 hr = IFolder_get_Files(folder, &files);
1247 ok(hr == S_OK, "got 0x%08x\n", hr);
1248 test_provideclassinfo(files, &CLSID_Files);
1249 IFolder_Release(folder);
1250
1251 count = 0;
1252 hr = IFileCollection_get_Count(files, &count);
1253 ok(hr == S_OK, "got 0x%08x\n", hr);
1254 ok(count == 2, "got %d\n", count);
1255
1256 lstrcpyW(pathW, buffW);
1257 lstrcatW(pathW, cW);
1258 file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1259 FILE_FLAG_DELETE_ON_CLOSE, 0);
1260
1261 /* every time property is requested it scans directory */
1262 count = 0;
1263 hr = IFileCollection_get_Count(files, &count);
1264 ok(hr == S_OK, "got 0x%08x\n", hr);
1265 ok(count == 3, "got %d\n", count);
1266
1267 hr = IFileCollection_get__NewEnum(files, NULL);
1268 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1269
1270 hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk);
1271 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1272
1273 /* NewEnum creates new instance each time it's called */
1274 ref = GET_REFCOUNT(files);
1275
1276 unk = NULL;
1277 hr = IFileCollection_get__NewEnum(files, &unk);
1278 ok(hr == S_OK, "got 0x%08x\n", hr);
1279
1280 ref2 = GET_REFCOUNT(files);
1281 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1282
1283 unk2 = NULL;
1284 hr = IFileCollection_get__NewEnum(files, &unk2);
1285 ok(hr == S_OK, "got 0x%08x\n", hr);
1286 ok(unk != unk2, "got %p, %p\n", unk2, unk);
1287 IUnknown_Release(unk2);
1288
1289 /* now get IEnumVARIANT */
1290 ref = GET_REFCOUNT(files);
1291 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1292 ok(hr == S_OK, "got 0x%08x\n", hr);
1293 ref2 = GET_REFCOUNT(files);
1294 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1295
1296 test_clone(enumvar, FALSE, count);
1297
1298 for (i = 0; i < 3; i++)
1299 {
1300 VariantInit(&var);
1301 fetched = 0;
1302 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1303 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1304 ok(fetched == 1, "%d: got %d\n", i, fetched);
1305 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1306
1307 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file);
1308 ok(hr == S_OK, "got 0x%08x\n", hr);
1309 test_provideclassinfo(file, &CLSID_File);
1310
1311 str = NULL;
1312 hr = IFile_get_Name(file, &str);
1313 ok(hr == S_OK, "got 0x%08x\n", hr);
1314 if (!lstrcmpW(str, aW + 1))
1315 found_a++;
1316 else if (!lstrcmpW(str, bW + 1))
1317 found_b++;
1318 else if (!lstrcmpW(str, cW + 1))
1319 found_c++;
1320 else
1321 ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str));
1322 SysFreeString(str);
1323
1324 IFile_Release(file);
1325 VariantClear(&var);
1326 }
1327
1328 ok(found_a == 1 && found_b == 1 && found_c == 1,
1329 "each file should be found 1 time instead of %d/%d/%d\n",
1330 found_a, found_b, found_c);
1331
1332 VariantInit(&var);
1333 fetched = -1;
1334 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1335 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1336 ok(fetched == 0, "got %d\n", fetched);
1337
1338 hr = IEnumVARIANT_Reset(enumvar);
1339 ok(hr == S_OK, "got 0x%08x\n", hr);
1340 hr = IEnumVARIANT_Skip(enumvar, 2);
1341 ok(hr == S_OK, "got 0x%08x\n", hr);
1342 hr = IEnumVARIANT_Skip(enumvar, 0);
1343 ok(hr == S_OK, "got 0x%08x\n", hr);
1344
1345 VariantInit(&var2[0]);
1346 VariantInit(&var2[1]);
1347 fetched = -1;
1348 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1349 ok(hr == S_OK, "got 0x%08x\n", hr);
1350 ok(fetched == 0, "got %d\n", fetched);
1351 fetched = -1;
1352 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1353 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1354 ok(fetched == 1, "got %d\n", fetched);
1355 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1356 VariantClear(&var2[0]);
1357 VariantClear(&var2[1]);
1358
1359 IEnumVARIANT_Release(enumvar);
1360 IUnknown_Release(unk);
1361
1362 CloseHandle(file_a);
1363 CloseHandle(file_b);
1364 CloseHandle(file_c);
1365 RemoveDirectoryW(buffW);
1366
1367 IFileCollection_Release(files);
1368 }
1369
test_DriveCollection(void)1370 static void test_DriveCollection(void)
1371 {
1372 IDriveCollection *drives;
1373 IEnumVARIANT *enumvar;
1374 ULONG fetched;
1375 VARIANT var;
1376 HRESULT hr;
1377 LONG count;
1378
1379 hr = IFileSystem3_get_Drives(fs3, &drives);
1380 ok(hr == S_OK, "got 0x%08x\n", hr);
1381
1382 test_provideclassinfo(drives, &CLSID_Drives);
1383
1384 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar);
1385 ok(hr == S_OK, "got 0x%08x\n", hr);
1386
1387 hr = IDriveCollection_get_Count(drives, NULL);
1388 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1389
1390 count = 0;
1391 hr = IDriveCollection_get_Count(drives, &count);
1392 ok(hr == S_OK, "got 0x%08x\n", hr);
1393 ok(count > 0, "got %d\n", count);
1394
1395 V_VT(&var) = VT_EMPTY;
1396 fetched = -1;
1397 hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched);
1398 ok(hr == S_OK, "got 0x%08x\n", hr);
1399 ok(fetched == 0, "got %d\n", fetched);
1400
1401 hr = IEnumVARIANT_Skip(enumvar, 0);
1402 ok(hr == S_OK, "got 0x%08x\n", hr);
1403
1404 hr = IEnumVARIANT_Skip(enumvar, count);
1405 ok(hr == S_OK, "got 0x%08x\n", hr);
1406
1407 hr = IEnumVARIANT_Skip(enumvar, 1);
1408 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1409
1410 test_clone(enumvar, TRUE, count);
1411
1412 while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) {
1413 IDrive *drive = (IDrive*)V_DISPATCH(&var);
1414 DriveTypeConst type;
1415 BSTR str;
1416
1417 hr = IDrive_get_DriveType(drive, &type);
1418 ok(hr == S_OK, "got 0x%08x\n", hr);
1419
1420 hr = IDrive_get_DriveLetter(drive, NULL);
1421 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1422
1423 hr = IDrive_get_DriveLetter(drive, &str);
1424 ok(hr == S_OK, "got 0x%08x\n", hr);
1425 ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str));
1426 SysFreeString(str);
1427
1428 hr = IDrive_get_IsReady(drive, NULL);
1429 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1430
1431 hr = IDrive_get_TotalSize(drive, NULL);
1432 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1433
1434 hr = IDrive_get_AvailableSpace(drive, NULL);
1435 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1436
1437 hr = IDrive_get_FreeSpace(drive, NULL);
1438 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1439
1440 if (type == Fixed) {
1441 VARIANT_BOOL ready = VARIANT_FALSE;
1442 VARIANT size;
1443
1444 hr = IDrive_get_IsReady(drive, &ready);
1445 ok(hr == S_OK, "got 0x%08x\n", hr);
1446 ok(ready == VARIANT_TRUE, "got %x\n", ready);
1447
1448 if (ready != VARIANT_TRUE) {
1449 hr = IDrive_get_DriveLetter(drive, &str);
1450 ok(hr == S_OK, "got 0x%08x\n", hr);
1451
1452 skip("Drive %s is not ready, skipping some tests\n", wine_dbgstr_w(str));
1453
1454 VariantClear(&var);
1455 SysFreeString(str);
1456 continue;
1457 }
1458
1459 V_VT(&size) = VT_EMPTY;
1460 hr = IDrive_get_TotalSize(drive, &size);
1461 ok(hr == S_OK, "got 0x%08x\n", hr);
1462 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1463 if (V_VT(&size) == VT_R8)
1464 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1465 else
1466 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1467
1468 V_VT(&size) = VT_EMPTY;
1469 hr = IDrive_get_AvailableSpace(drive, &size);
1470 ok(hr == S_OK, "got 0x%08x\n", hr);
1471 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1472 if (V_VT(&size) == VT_R8)
1473 ok(V_R8(&size) > (double)INT_MAX, "got %f\n", V_R8(&size));
1474 else
1475 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1476
1477 V_VT(&size) = VT_EMPTY;
1478 hr = IDrive_get_FreeSpace(drive, &size);
1479 ok(hr == S_OK, "got 0x%08x\n", hr);
1480 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1481 if (V_VT(&size) == VT_R8)
1482 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1483 else
1484 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1485 }
1486 VariantClear(&var);
1487 }
1488
1489 IEnumVARIANT_Release(enumvar);
1490 IDriveCollection_Release(drives);
1491 }
1492
get_temp_filepath(const WCHAR * filename,WCHAR * path,WCHAR * dir)1493 static void get_temp_filepath(const WCHAR *filename, WCHAR *path, WCHAR *dir)
1494 {
1495 static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1496
1497 GetTempPathW(MAX_PATH, path);
1498 lstrcatW(path, scrrunW);
1499 lstrcpyW(dir, path);
1500 lstrcatW(path, filename);
1501 }
1502
test_CreateTextFile(void)1503 static void test_CreateTextFile(void)
1504 {
1505 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[10];
1506 ITextStream *stream;
1507 BSTR nameW, str;
1508 HANDLE file;
1509 HRESULT hr;
1510 BOOL ret;
1511
1512 get_temp_filepath(testfileW, pathW, dirW);
1513
1514 /* dir doesn't exist */
1515 nameW = SysAllocString(pathW);
1516 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1517 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
1518
1519 ret = CreateDirectoryW(dirW, NULL);
1520 ok(ret, "got %d, %d\n", ret, GetLastError());
1521
1522 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1523 ok(hr == S_OK, "got 0x%08x\n", hr);
1524
1525 test_provideclassinfo(stream, &CLSID_TextStream);
1526
1527 hr = ITextStream_Read(stream, 1, &str);
1528 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1529
1530 hr = ITextStream_Close(stream);
1531 ok(hr == S_OK, "got 0x%08x\n", hr);
1532
1533 hr = ITextStream_Read(stream, 1, &str);
1534 ok(hr == CTL_E_BADFILEMODE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr);
1535
1536 hr = ITextStream_Close(stream);
1537 ok(hr == S_FALSE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr);
1538
1539 ITextStream_Release(stream);
1540
1541 /* check it's created */
1542 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1543 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1544 CloseHandle(file);
1545
1546 /* try to create again with no-overwrite mode */
1547 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1548 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
1549
1550 /* now overwrite */
1551 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1552 ok(hr == S_OK, "got 0x%08x\n", hr);
1553 ITextStream_Release(stream);
1554
1555 /* overwrite in Unicode mode, check for BOM */
1556 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
1557 ok(hr == S_OK, "got 0x%08x\n", hr);
1558 ITextStream_Release(stream);
1559
1560 /* File was created in Unicode mode, it contains 0xfffe BOM. Opening it in non-Unicode mode
1561 treats BOM like a valuable data with appropriate CP_ACP -> WCHAR conversion. */
1562 buffW[0] = 0;
1563 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1564
1565 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1566 ok(hr == S_OK, "got 0x%08x\n", hr);
1567 hr = ITextStream_ReadAll(stream, &str);
1568 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1569 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1570 SysFreeString(str);
1571 ITextStream_Release(stream);
1572
1573 DeleteFileW(nameW);
1574 RemoveDirectoryW(dirW);
1575 SysFreeString(nameW);
1576 }
1577
test_WriteLine(void)1578 static void test_WriteLine(void)
1579 {
1580 WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
1581 WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
1582 char buffA[MAX_PATH];
1583 ITextStream *stream;
1584 DWORD r, len;
1585 HANDLE file;
1586 BSTR nameW;
1587 HRESULT hr;
1588 BOOL ret;
1589
1590 get_temp_filepath(testfileW, pathW, dirW);
1591
1592 ret = CreateDirectoryW(dirW, NULL);
1593 ok(ret, "got %d, %d\n", ret, GetLastError());
1594
1595 /* create as ASCII file first */
1596 nameW = SysAllocString(pathW);
1597 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1598 ok(hr == S_OK, "got 0x%08x\n", hr);
1599
1600 hr = ITextStream_WriteLine(stream, nameW);
1601 ok(hr == S_OK, "got 0x%08x\n", hr);
1602 ITextStream_Release(stream);
1603
1604 /* check contents */
1605 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1606 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1607 r = 0;
1608 ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL);
1609 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1610
1611 len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, ARRAY_SIZE(buffW));
1612 buffW[len] = 0;
1613 lstrcpyW(buff2W, nameW);
1614 lstrcatW(buff2W, crlfW);
1615 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1616 CloseHandle(file);
1617 DeleteFileW(nameW);
1618
1619 /* same for unicode file */
1620 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1621 ok(hr == S_OK, "got 0x%08x\n", hr);
1622
1623 hr = ITextStream_WriteLine(stream, nameW);
1624 ok(hr == S_OK, "got 0x%08x\n", hr);
1625 ITextStream_Release(stream);
1626
1627 /* check contents */
1628 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1629 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1630 r = 0;
1631 ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL);
1632 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1633 buffW[r/sizeof(WCHAR)] = 0;
1634
1635 buff2W[0] = 0xfeff;
1636 buff2W[1] = 0;
1637 lstrcatW(buff2W, nameW);
1638 lstrcatW(buff2W, crlfW);
1639 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1640 CloseHandle(file);
1641 DeleteFileW(nameW);
1642
1643 RemoveDirectoryW(dirW);
1644 SysFreeString(nameW);
1645 }
1646
test_ReadAll(void)1647 static void test_ReadAll(void)
1648 {
1649 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1650 static const WCHAR aW[] = {'A',0};
1651 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1652 ITextStream *stream;
1653 BSTR nameW;
1654 HRESULT hr;
1655 BOOL ret;
1656 BSTR str;
1657
1658 get_temp_filepath(testfileW, pathW, dirW);
1659
1660 ret = CreateDirectoryW(dirW, NULL);
1661 ok(ret, "got %d, %d\n", ret, GetLastError());
1662
1663 /* Unicode file -> read with ascii stream */
1664 nameW = SysAllocString(pathW);
1665 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1666 ok(hr == S_OK, "got 0x%08x\n", hr);
1667
1668 hr = ITextStream_WriteLine(stream, nameW);
1669 ok(hr == S_OK, "got 0x%08x\n", hr);
1670
1671 str = SysAllocString(secondlineW);
1672 hr = ITextStream_WriteLine(stream, str);
1673 ok(hr == S_OK, "got 0x%08x\n", hr);
1674 SysFreeString(str);
1675
1676 hr = ITextStream_ReadAll(stream, NULL);
1677 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1678
1679 str = (void*)0xdeadbeef;
1680 hr = ITextStream_ReadAll(stream, &str);
1681 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1682 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1683
1684 ITextStream_Release(stream);
1685
1686 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1687 ok(hr == S_OK, "got 0x%08x\n", hr);
1688
1689 hr = ITextStream_ReadAll(stream, NULL);
1690 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1691
1692 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1693 str = NULL;
1694 hr = ITextStream_ReadAll(stream, &str);
1695 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1696 buffW[0] = 0;
1697 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1698 ok(str[0] == buffW[0] && str[1] == buffW[1], "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
1699 SysFreeString(str);
1700 ITextStream_Release(stream);
1701
1702 /* Unicode file -> read with unicode stream */
1703 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1704 ok(hr == S_OK, "got 0x%08x\n", hr);
1705
1706 lstrcpyW(buffW, nameW);
1707 lstrcatW(buffW, crlfW);
1708 lstrcatW(buffW, secondlineW);
1709 lstrcatW(buffW, crlfW);
1710 str = NULL;
1711 hr = ITextStream_ReadAll(stream, &str);
1712 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1713 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1714 SysFreeString(str);
1715
1716 /* ReadAll one more time */
1717 str = (void*)0xdeadbeef;
1718 hr = ITextStream_ReadAll(stream, &str);
1719 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1720 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1721
1722 /* ReadLine fails the same way */
1723 str = (void*)0xdeadbeef;
1724 hr = ITextStream_ReadLine(stream, &str);
1725 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1726 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1727 ITextStream_Release(stream);
1728
1729 /* Open again and skip first line before ReadAll */
1730 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1731 ok(hr == S_OK, "got 0x%08x\n", hr);
1732
1733 str = NULL;
1734 hr = ITextStream_ReadLine(stream, &str);
1735 todo_wine {
1736 ok(hr == S_OK, "got 0x%08x\n", hr);
1737 ok(str != NULL, "got %p\n", str);
1738 }
1739 SysFreeString(str);
1740
1741 lstrcpyW(buffW, secondlineW);
1742 lstrcatW(buffW, crlfW);
1743 str = NULL;
1744 hr = ITextStream_ReadAll(stream, &str);
1745 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1746 todo_wine
1747 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1748 SysFreeString(str);
1749 ITextStream_Release(stream);
1750
1751 /* ASCII file, read with Unicode stream */
1752 /* 1. one byte content, not enough for Unicode read */
1753 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1754 ok(hr == S_OK, "got 0x%08x\n", hr);
1755 str = SysAllocString(aW);
1756 hr = ITextStream_Write(stream, str);
1757 ok(hr == S_OK, "got 0x%08x\n", hr);
1758 SysFreeString(str);
1759 ITextStream_Release(stream);
1760
1761 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1762 ok(hr == S_OK, "got 0x%08x\n", hr);
1763
1764 str = (void*)0xdeadbeef;
1765 hr = ITextStream_ReadAll(stream, &str);
1766 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1767 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1768
1769 ITextStream_Release(stream);
1770
1771 DeleteFileW(nameW);
1772 RemoveDirectoryW(dirW);
1773 SysFreeString(nameW);
1774 }
1775
test_Read(void)1776 static void test_Read(void)
1777 {
1778 static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1779 static const WCHAR aW[] = {'A',0};
1780 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1781 ITextStream *stream;
1782 BSTR nameW;
1783 HRESULT hr;
1784 BOOL ret;
1785 BSTR str;
1786
1787 get_temp_filepath(testfileW, pathW, dirW);
1788
1789 ret = CreateDirectoryW(dirW, NULL);
1790 ok(ret, "got %d, %d\n", ret, GetLastError());
1791
1792 /* Unicode file -> read with ascii stream */
1793 nameW = SysAllocString(pathW);
1794 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1795 ok(hr == S_OK, "got 0x%08x\n", hr);
1796
1797 hr = ITextStream_WriteLine(stream, nameW);
1798 ok(hr == S_OK, "got 0x%08x\n", hr);
1799
1800 str = SysAllocString(secondlineW);
1801 hr = ITextStream_WriteLine(stream, str);
1802 ok(hr == S_OK, "got 0x%08x\n", hr);
1803 SysFreeString(str);
1804
1805 hr = ITextStream_Read(stream, 0, NULL);
1806 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1807
1808 hr = ITextStream_Read(stream, 1, NULL);
1809 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1810
1811 hr = ITextStream_Read(stream, -1, NULL);
1812 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1813
1814 str = (void*)0xdeadbeef;
1815 hr = ITextStream_Read(stream, 1, &str);
1816 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1817 ok(str == NULL, "got %p\n", str);
1818
1819 ITextStream_Release(stream);
1820
1821 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1822 ok(hr == S_OK, "got 0x%08x\n", hr);
1823
1824 hr = ITextStream_Read(stream, 1, NULL);
1825 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1826
1827 str = (void*)0xdeadbeef;
1828 hr = ITextStream_Read(stream, -1, &str);
1829 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1830 ok(str == NULL, "got %p\n", str);
1831
1832 str = (void*)0xdeadbeef;
1833 hr = ITextStream_Read(stream, 0, &str);
1834 ok(hr == S_OK, "got 0x%08x\n", hr);
1835 ok(str == NULL, "got %p\n", str);
1836
1837 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1838 str = NULL;
1839 hr = ITextStream_Read(stream, 2, &str);
1840 ok(hr == S_OK, "got 0x%08x\n", hr);
1841
1842 buffW[0] = 0;
1843 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1844
1845 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1846 ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str));
1847 SysFreeString(str);
1848 ITextStream_Release(stream);
1849
1850 /* Unicode file -> read with unicode stream */
1851 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1852 ok(hr == S_OK, "got 0x%08x\n", hr);
1853
1854 lstrcpyW(buffW, nameW);
1855 lstrcatW(buffW, crlfW);
1856 lstrcatW(buffW, secondlineW);
1857 lstrcatW(buffW, crlfW);
1858 str = NULL;
1859 hr = ITextStream_Read(stream, 500, &str);
1860 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1861 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1862 SysFreeString(str);
1863
1864 /* ReadAll one more time */
1865 str = (void*)0xdeadbeef;
1866 hr = ITextStream_Read(stream, 10, &str);
1867 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1868 ok(str == NULL, "got %p\n", str);
1869
1870 /* ReadLine fails the same way */
1871 str = (void*)0xdeadbeef;
1872 hr = ITextStream_ReadLine(stream, &str);
1873 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1874 ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str);
1875 ITextStream_Release(stream);
1876
1877 /* Open again and skip first line before ReadAll */
1878 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1879 ok(hr == S_OK, "got 0x%08x\n", hr);
1880
1881 str = NULL;
1882 hr = ITextStream_ReadLine(stream, &str);
1883 todo_wine {
1884 ok(hr == S_OK, "got 0x%08x\n", hr);
1885 ok(str != NULL, "got %p\n", str);
1886 }
1887 SysFreeString(str);
1888
1889 lstrcpyW(buffW, secondlineW);
1890 lstrcatW(buffW, crlfW);
1891 str = NULL;
1892 hr = ITextStream_Read(stream, 100, &str);
1893 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1894 todo_wine
1895 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1896 SysFreeString(str);
1897 ITextStream_Release(stream);
1898
1899 /* default read will use Unicode */
1900 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateUseDefault, &stream);
1901 ok(hr == S_OK, "got 0x%08x\n", hr);
1902
1903 lstrcpyW(buffW, nameW);
1904 lstrcatW(buffW, crlfW);
1905 lstrcatW(buffW, secondlineW);
1906 lstrcatW(buffW, crlfW);
1907 str = NULL;
1908 hr = ITextStream_Read(stream, 500, &str);
1909 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1910 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1911 SysFreeString(str);
1912
1913 ITextStream_Release(stream);
1914
1915 /* default append will use Unicode */
1916 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForAppending, VARIANT_FALSE, TristateUseDefault, &stream);
1917 ok(hr == S_OK, "got 0x%08x\n", hr);
1918
1919 str = SysAllocString(L"123");
1920 hr = ITextStream_Write(stream, str);
1921 ok(hr == S_OK, "got %08x\n", hr);
1922 SysFreeString(str);
1923
1924 ITextStream_Release(stream);
1925
1926 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1927 ok(hr == S_OK, "got 0x%08x\n", hr);
1928
1929 lstrcatW(buffW, L"123");
1930 str = NULL;
1931 hr = ITextStream_Read(stream, 500, &str);
1932 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1933 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1934 SysFreeString(str);
1935
1936 ITextStream_Release(stream);
1937
1938 /* default write will use ASCII */
1939 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForWriting, VARIANT_FALSE, TristateUseDefault, &stream);
1940 ok(hr == S_OK, "got 0x%08x\n", hr);
1941
1942 str = SysAllocString(L"123");
1943 hr = ITextStream_Write(stream, str);
1944 ok(hr == S_OK, "got %08x\n", hr);
1945 SysFreeString(str);
1946
1947 ITextStream_Release(stream);
1948
1949 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1950 ok(hr == S_OK, "got 0x%08x\n", hr);
1951
1952 str = (void*)0xdeadbeef;
1953 hr = ITextStream_Read(stream, 500, &str);
1954 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1955 ok(!wcscmp(str, L"123"), "got %s\n", wine_dbgstr_w(str));
1956
1957 ITextStream_Release(stream);
1958 /* ASCII file, read with default stream */
1959 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1960 ok(hr == S_OK, "got 0x%08x\n", hr);
1961 str = SysAllocString(L"test");
1962 hr = ITextStream_Write(stream, str);
1963 ok(hr == S_OK, "got 0x%08x\n", hr);
1964 SysFreeString(str);
1965 ITextStream_Release(stream);
1966
1967 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateUseDefault, &stream);
1968 ok(hr == S_OK, "got 0x%08x\n", hr);
1969
1970 str = (void*)0xdeadbeef;
1971 hr = ITextStream_Read(stream, 500, &str);
1972 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1973 ok(!wcscmp(str, L"test"), "got %s\n", wine_dbgstr_w(str));
1974
1975 ITextStream_Release(stream);
1976
1977 /* default append will use Unicode */
1978 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForAppending, VARIANT_FALSE, TristateUseDefault, &stream);
1979 ok(hr == S_OK, "got 0x%08x\n", hr);
1980
1981 str = SysAllocString(L"123");
1982 hr = ITextStream_Write(stream, str);
1983 ok(hr == S_OK, "got %08x\n", hr);
1984 SysFreeString(str);
1985
1986 ITextStream_Release(stream);
1987
1988 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1989 ok(hr == S_OK, "got 0x%08x\n", hr);
1990
1991 str = NULL;
1992 hr = ITextStream_Read(stream, 500, &str);
1993 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1994 ok(!lstrcmpW(L"test123", str), "got %s\n", wine_dbgstr_w(str));
1995 SysFreeString(str);
1996
1997 ITextStream_Release(stream);
1998
1999 /* default write will use ASCII as well */
2000 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForWriting, VARIANT_FALSE, TristateUseDefault, &stream);
2001 ok(hr == S_OK, "got 0x%08x\n", hr);
2002
2003 str = SysAllocString(L"test string");
2004 hr = ITextStream_Write(stream, str);
2005 ok(hr == S_OK, "got %08x\n", hr);
2006 SysFreeString(str);
2007
2008 ITextStream_Release(stream);
2009
2010 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
2011 ok(hr == S_OK, "got 0x%08x\n", hr);
2012
2013 str = (void*)0xdeadbeef;
2014 hr = ITextStream_Read(stream, 500, &str);
2015 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
2016 ok(!wcscmp(str, L"test string"), "got %s\n", wine_dbgstr_w(str));
2017
2018 ITextStream_Release(stream);
2019
2020 /* ASCII file, read with Unicode stream */
2021 /* 1. one byte content, not enough for Unicode read */
2022 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
2023 ok(hr == S_OK, "got 0x%08x\n", hr);
2024 str = SysAllocString(aW);
2025 hr = ITextStream_Write(stream, str);
2026 ok(hr == S_OK, "got 0x%08x\n", hr);
2027 SysFreeString(str);
2028 ITextStream_Release(stream);
2029
2030 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
2031 ok(hr == S_OK, "got 0x%08x\n", hr);
2032
2033 str = (void*)0xdeadbeef;
2034 hr = ITextStream_Read(stream, 500, &str);
2035 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
2036 ok(str == NULL, "got %p\n", str);
2037
2038 ITextStream_Release(stream);
2039
2040 DeleteFileW(nameW);
2041 RemoveDirectoryW(dirW);
2042 SysFreeString(nameW);
2043 }
2044
2045 struct driveexists_test {
2046 const WCHAR drivespec[10];
2047 const INT drivetype;
2048 const VARIANT_BOOL expected_ret;
2049 };
2050
2051 /* If 'drivetype' != -1, the first character of 'drivespec' will be replaced
2052 * with the drive letter of a drive of this type. If such a drive does not exist,
2053 * the test will be skipped. */
2054 static const struct driveexists_test driveexiststestdata[] = {
2055 { {'N',':','\\',0}, DRIVE_NO_ROOT_DIR, VARIANT_FALSE },
2056 { {'R',':','\\',0}, DRIVE_REMOVABLE, VARIANT_TRUE },
2057 { {'F',':','\\',0}, DRIVE_FIXED, VARIANT_TRUE },
2058 { {'F',':',0}, DRIVE_FIXED, VARIANT_TRUE },
2059 { {'F','?',0}, DRIVE_FIXED, VARIANT_FALSE },
2060 { {'F',0}, DRIVE_FIXED, VARIANT_TRUE },
2061 { {'?',0}, -1, VARIANT_FALSE },
2062 { { 0 } }
2063 };
2064
test_DriveExists(void)2065 static void test_DriveExists(void)
2066 {
2067 const struct driveexists_test *ptr = driveexiststestdata;
2068 HRESULT hr;
2069 VARIANT_BOOL ret;
2070 BSTR drivespec;
2071 WCHAR root[] = {'?',':','\\',0};
2072
2073 hr = IFileSystem3_DriveExists(fs3, NULL, NULL);
2074 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2075
2076 ret = VARIANT_TRUE;
2077 hr = IFileSystem3_DriveExists(fs3, NULL, &ret);
2078 ok(hr == S_OK, "got 0x%08x\n", hr);
2079 ok(ret == VARIANT_FALSE, "got %x\n", ret);
2080
2081 drivespec = SysAllocString(root);
2082 hr = IFileSystem3_DriveExists(fs3, drivespec, NULL);
2083 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2084 SysFreeString(drivespec);
2085
2086 for (; *ptr->drivespec; ptr++) {
2087 drivespec = SysAllocString(ptr->drivespec);
2088 if (ptr->drivetype != -1) {
2089 for (root[0] = 'A'; root[0] <= 'Z'; root[0]++)
2090 if (GetDriveTypeW(root) == ptr->drivetype)
2091 break;
2092 if (root[0] > 'Z') {
2093 skip("No drive with type 0x%x found, skipping test %s.\n",
2094 ptr->drivetype, wine_dbgstr_w(ptr->drivespec));
2095 SysFreeString(drivespec);
2096 continue;
2097 }
2098
2099 /* Test both upper and lower case drive letters. */
2100 drivespec[0] = root[0];
2101 ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE;
2102 hr = IFileSystem3_DriveExists(fs3, drivespec, &ret);
2103 ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n",
2104 hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
2105 ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n",
2106 ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
2107
2108 drivespec[0] = tolower(root[0]);
2109 }
2110
2111 ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE;
2112 hr = IFileSystem3_DriveExists(fs3, drivespec, &ret);
2113 ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n",
2114 hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
2115 ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n",
2116 ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
2117
2118 SysFreeString(drivespec);
2119 }
2120 }
2121
2122 struct getdrivename_test {
2123 const WCHAR path[10];
2124 const WCHAR drive[5];
2125 };
2126
2127 static const struct getdrivename_test getdrivenametestdata[] = {
2128 { {'C',':','\\','1','.','t','s','t',0}, {'C',':',0} },
2129 { {'O',':','\\','1','.','t','s','t',0}, {'O',':',0} },
2130 { {'O',':',0}, {'O',':',0} },
2131 { {'o',':',0}, {'o',':',0} },
2132 { {'O','O',':',0} },
2133 { {':',0} },
2134 { {'O',0} },
2135 { { 0 } }
2136 };
2137
test_GetDriveName(void)2138 static void test_GetDriveName(void)
2139 {
2140 const struct getdrivename_test *ptr = getdrivenametestdata;
2141 HRESULT hr;
2142 BSTR name;
2143
2144 hr = IFileSystem3_GetDriveName(fs3, NULL, NULL);
2145 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2146
2147 name = (void*)0xdeadbeef;
2148 hr = IFileSystem3_GetDriveName(fs3, NULL, &name);
2149 ok(hr == S_OK, "got 0x%08x\n", hr);
2150 ok(name == NULL, "got %p\n", name);
2151
2152 while (*ptr->path) {
2153 BSTR path = SysAllocString(ptr->path);
2154 name = (void*)0xdeadbeef;
2155 hr = IFileSystem3_GetDriveName(fs3, path, &name);
2156 ok(hr == S_OK, "got 0x%08x\n", hr);
2157 if (name)
2158 ok(!lstrcmpW(ptr->drive, name), "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive));
2159 else
2160 ok(!*ptr->drive, "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive));
2161 SysFreeString(path);
2162 SysFreeString(name);
2163 ptr++;
2164 }
2165 }
2166
2167 struct getdrive_test {
2168 const WCHAR drivespec[12];
2169 HRESULT res;
2170 const WCHAR driveletter[2];
2171 };
2172
test_GetDrive(void)2173 static void test_GetDrive(void)
2174 {
2175 HRESULT hr;
2176 IDrive *drive_fixed, *drive;
2177 BSTR dl_fixed, drivespec;
2178 WCHAR root[] = {'?',':','\\',0};
2179
2180 drive = (void*)0xdeadbeef;
2181 hr = IFileSystem3_GetDrive(fs3, NULL, NULL);
2182 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2183 ok(drive == (void*)0xdeadbeef, "got %p\n", drive);
2184
2185 for (root[0] = 'A'; root[0] <= 'Z'; root[0]++)
2186 if (GetDriveTypeW(root) == DRIVE_NO_ROOT_DIR)
2187 break;
2188
2189 if (root[0] > 'Z')
2190 skip("All drive letters are occupied, skipping test for nonexisting drive.\n");
2191 else {
2192 drivespec = SysAllocString(root);
2193 drive = (void*)0xdeadbeef;
2194 hr = IFileSystem3_GetDrive(fs3, drivespec, &drive);
2195 ok(hr == CTL_E_DEVICEUNAVAILABLE, "got 0x%08x\n", hr);
2196 ok(drive == NULL, "got %p\n", drive);
2197 SysFreeString(drivespec);
2198 }
2199
2200 drive_fixed = get_fixed_drive();
2201 if (!drive_fixed) {
2202 skip("No fixed drive found, skipping test.\n");
2203 return;
2204 }
2205
2206 hr = IDrive_get_DriveLetter(drive_fixed, &dl_fixed);
2207 ok(hr == S_OK, "got 0x%08x\n", hr);
2208
2209 if (FAILED(hr))
2210 skip("Could not retrieve drive letter of fixed drive, skipping test.\n");
2211 else {
2212 WCHAR dl_upper = toupper(dl_fixed[0]);
2213 WCHAR dl_lower = tolower(dl_fixed[0]);
2214 struct getdrive_test testdata[] = {
2215 { {dl_upper,0}, S_OK, {dl_upper,0} },
2216 { {dl_upper,':',0}, S_OK, {dl_upper,0} },
2217 { {dl_upper,':','\\',0}, S_OK, {dl_upper,0} },
2218 { {dl_lower,':','\\',0}, S_OK, {dl_upper,0} },
2219 { {dl_upper,'\\',0}, E_INVALIDARG, { 0 } },
2220 { {dl_lower,'\\',0}, E_INVALIDARG, { 0 } },
2221 { {'$',':','\\',0}, E_INVALIDARG, { 0 } },
2222 { {'\\','h','o','s','t','\\','s','h','a','r','e',0}, E_INVALIDARG, { 0 } },
2223 { {'h','o','s','t','\\','s','h','a','r','e',0}, E_INVALIDARG, { 0 } },
2224 { { 0 } },
2225 };
2226 struct getdrive_test *ptr = &testdata[0];
2227
2228 for (; *ptr->drivespec; ptr++) {
2229 drivespec = SysAllocString(ptr->drivespec);
2230 drive = (void*)0xdeadbeef;
2231 hr = IFileSystem3_GetDrive(fs3, drivespec, &drive);
2232 ok(hr == ptr->res, "got 0x%08x, expected 0x%08x for drive spec %s\n",
2233 hr, ptr->res, wine_dbgstr_w(ptr->drivespec));
2234 ok(!lstrcmpW(ptr->drivespec, drivespec), "GetDrive modified its DriveSpec argument\n");
2235 SysFreeString(drivespec);
2236
2237 if (*ptr->driveletter) {
2238 BSTR driveletter;
2239 hr = IDrive_get_DriveLetter(drive, &driveletter);
2240 ok(hr == S_OK, "got 0x%08x for drive spec %s\n", hr, wine_dbgstr_w(ptr->drivespec));
2241 if (SUCCEEDED(hr)) {
2242 ok(!lstrcmpW(ptr->driveletter, driveletter), "got %s, expected %s for drive spec %s\n",
2243 wine_dbgstr_w(driveletter), wine_dbgstr_w(ptr->driveletter),
2244 wine_dbgstr_w(ptr->drivespec));
2245 SysFreeString(driveletter);
2246 }
2247 test_provideclassinfo(drive, &CLSID_Drive);
2248 IDrive_Release(drive);
2249 } else
2250 ok(drive == NULL, "got %p for drive spec %s\n", drive, wine_dbgstr_w(ptr->drivespec));
2251 }
2252 SysFreeString(dl_fixed);
2253 }
2254 }
2255
test_SerialNumber(void)2256 static void test_SerialNumber(void)
2257 {
2258 IDrive *drive;
2259 LONG serial;
2260 HRESULT hr;
2261 BSTR name;
2262
2263 drive = get_fixed_drive();
2264 if (!drive) {
2265 skip("No fixed drive found, skipping test.\n");
2266 return;
2267 }
2268
2269 hr = IDrive_get_SerialNumber(drive, NULL);
2270 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2271
2272 serial = 0xdeadbeef;
2273 hr = IDrive_get_SerialNumber(drive, &serial);
2274 ok(hr == S_OK, "got 0x%08x\n", hr);
2275 ok(serial != 0xdeadbeef, "got %x\n", serial);
2276
2277 hr = IDrive_get_FileSystem(drive, NULL);
2278 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2279
2280 name = NULL;
2281 hr = IDrive_get_FileSystem(drive, &name);
2282 ok(hr == S_OK, "got 0x%08x\n", hr);
2283 ok(name != NULL, "got %p\n", name);
2284 SysFreeString(name);
2285
2286 hr = IDrive_get_VolumeName(drive, NULL);
2287 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2288
2289 name = NULL;
2290 hr = IDrive_get_VolumeName(drive, &name);
2291 ok(hr == S_OK, "got 0x%08x\n", hr);
2292 ok(name != NULL, "got %p\n", name);
2293 SysFreeString(name);
2294
2295 IDrive_Release(drive);
2296 }
2297
2298 static const struct extension_test {
2299 WCHAR path[20];
2300 WCHAR ext[10];
2301 } extension_tests[] = {
2302 { {'n','o','e','x','t',0}, {0} },
2303 { {'n','.','o','.','e','x','t',0}, {'e','x','t',0} },
2304 { {'n','.','o','.','e','X','t',0}, {'e','X','t',0} },
2305 { { 0 } }
2306 };
2307
test_GetExtensionName(void)2308 static void test_GetExtensionName(void)
2309 {
2310 BSTR path, ext;
2311 HRESULT hr;
2312 int i;
2313
2314 for (i = 0; i < ARRAY_SIZE(extension_tests); i++) {
2315
2316 path = SysAllocString(extension_tests[i].path);
2317 ext = NULL;
2318 hr = IFileSystem3_GetExtensionName(fs3, path, &ext);
2319 ok(hr == S_OK, "got 0x%08x\n", hr);
2320 if (*extension_tests[i].ext)
2321 ok(!lstrcmpW(ext, extension_tests[i].ext), "%d: path %s, got %s, expected %s\n", i,
2322 wine_dbgstr_w(path), wine_dbgstr_w(ext), wine_dbgstr_w(extension_tests[i].ext));
2323 else
2324 ok(ext == NULL, "%d: path %s, got %s, expected %s\n", i,
2325 wine_dbgstr_w(path), wine_dbgstr_w(ext), wine_dbgstr_w(extension_tests[i].ext));
2326
2327 SysFreeString(path);
2328 SysFreeString(ext);
2329 }
2330 }
2331
test_GetSpecialFolder(void)2332 static void test_GetSpecialFolder(void)
2333 {
2334 WCHAR pathW[MAX_PATH];
2335 IFolder *folder;
2336 HRESULT hr;
2337 DWORD ret;
2338 BSTR path;
2339
2340 hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, NULL);
2341 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2342
2343 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, NULL);
2344 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2345
2346 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, &folder);
2347 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2348
2349 hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, &folder);
2350 ok(hr == S_OK, "got 0x%08x\n", hr);
2351 hr = IFolder_get_Path(folder, &path);
2352 ok(hr == S_OK, "got 0x%08x\n", hr);
2353 GetWindowsDirectoryW(pathW, ARRAY_SIZE(pathW));
2354 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2355 SysFreeString(path);
2356 IFolder_Release(folder);
2357
2358 hr = IFileSystem3_GetSpecialFolder(fs3, SystemFolder, &folder);
2359 ok(hr == S_OK, "got 0x%08x\n", hr);
2360 hr = IFolder_get_Path(folder, &path);
2361 ok(hr == S_OK, "got 0x%08x\n", hr);
2362 GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW));
2363 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2364 SysFreeString(path);
2365 IFolder_Release(folder);
2366
2367 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder, &folder);
2368 ok(hr == S_OK, "got 0x%08x\n", hr);
2369 hr = IFolder_get_Path(folder, &path);
2370 ok(hr == S_OK, "got 0x%08x\n", hr);
2371 ret = GetTempPathW(ARRAY_SIZE(pathW), pathW);
2372 if (ret && pathW[ret-1] == '\\')
2373 pathW[ret-1] = 0;
2374
2375 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2376 SysFreeString(path);
2377 IFolder_Release(folder);
2378 }
2379
START_TEST(filesystem)2380 START_TEST(filesystem)
2381 {
2382 HRESULT hr;
2383
2384 CoInitialize(NULL);
2385
2386 hr = CoCreateInstance(&CLSID_FileSystemObject, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2387 &IID_IFileSystem3, (void**)&fs3);
2388 if(FAILED(hr)) {
2389 win_skip("Could not create FileSystem object: %08x\n", hr);
2390 return;
2391 }
2392
2393 test_interfaces();
2394 test_createfolder();
2395 test_textstream();
2396 test_GetFileVersion();
2397 test_GetParentFolderName();
2398 test_GetFileName();
2399 test_GetBaseName();
2400 test_GetAbsolutePathName();
2401 test_GetFile();
2402 test_CopyFolder();
2403 test_BuildPath();
2404 test_GetFolder();
2405 test_FolderCollection();
2406 test_FileCollection();
2407 test_DriveCollection();
2408 test_CreateTextFile();
2409 test_WriteLine();
2410 test_ReadAll();
2411 test_Read();
2412 test_DriveExists();
2413 test_GetDriveName();
2414 test_GetDrive();
2415 test_SerialNumber();
2416 test_GetExtensionName();
2417 test_GetSpecialFolder();
2418
2419 IFileSystem3_Release(fs3);
2420
2421 CoUninitialize();
2422 }
2423