reg: Stop parsing REG_SZ values containing NUL character sequences.
[wine/zf.git] / dlls / scrrun / tests / filesystem.c
blob5c55965ce888918706c07bdffef7a46471ea7273
1 /*
3 * Copyright 2012 Alistair Leslie-Hughes
4 * Copyright 2014 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #include <stdio.h>
23 #include <limits.h>
25 #include "windows.h"
26 #include "ole2.h"
27 #include "olectl.h"
28 #include "oleauto.h"
29 #include "dispex.h"
31 #include "wine/test.h"
33 #include "initguid.h"
34 #include "scrrun.h"
36 static IFileSystem3 *fs3;
38 /* w2k and 2k3 error code. */
39 #define E_VAR_NOT_SET 0x800a005b
41 static inline ULONG get_refcount(IUnknown *iface)
43 IUnknown_AddRef(iface);
44 return IUnknown_Release(iface);
47 static const char utf16bom[] = {0xff,0xfe,0};
48 static const WCHAR testfileW[] = L"test.txt";
50 #define GET_REFCOUNT(iface) \
51 get_refcount((IUnknown*)iface)
53 static inline void get_temp_path(const WCHAR *prefix, WCHAR *path)
55 WCHAR buffW[MAX_PATH];
57 GetTempPathW(MAX_PATH, buffW);
58 GetTempFileNameW(buffW, prefix, 0, path);
59 DeleteFileW(path);
62 static IDrive *get_fixed_drive(void)
64 IDriveCollection *drives;
65 IEnumVARIANT *iter;
66 IDrive *drive;
67 HRESULT hr;
69 hr = IFileSystem3_get_Drives(fs3, &drives);
70 ok(hr == S_OK, "got 0x%08x\n", hr);
72 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&iter);
73 ok(hr == S_OK, "got 0x%08x\n", hr);
74 IDriveCollection_Release(drives);
76 while (1) {
77 DriveTypeConst type;
78 VARIANT var;
80 hr = IEnumVARIANT_Next(iter, 1, &var, NULL);
81 if (hr == S_FALSE) {
82 drive = NULL;
83 break;
85 ok(hr == S_OK, "got 0x%08x\n", hr);
87 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IDrive, (void**)&drive);
88 ok(hr == S_OK, "got 0x%08x\n", hr);
89 VariantClear(&var);
91 hr = IDrive_get_DriveType(drive, &type);
92 ok(hr == S_OK, "got 0x%08x\n", hr);
93 if (type == Fixed)
94 break;
96 IDrive_Release(drive);
99 IEnumVARIANT_Release(iter);
100 return drive;
103 #define test_provideclassinfo(a, b) _test_provideclassinfo((IDispatch*)a, b, __LINE__)
104 static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line)
106 IProvideClassInfo *classinfo;
107 TYPEATTR *attr;
108 ITypeInfo *ti;
109 IUnknown *unk;
110 HRESULT hr;
112 hr = IDispatch_QueryInterface(disp, &IID_IProvideClassInfo, (void **)&classinfo);
113 ok_(__FILE__,line) (hr == S_OK, "Failed to get IProvideClassInfo, %#x.\n", hr);
115 hr = IProvideClassInfo_GetClassInfo(classinfo, &ti);
116 ok_(__FILE__,line) (hr == S_OK, "GetClassInfo() failed, %#x.\n", hr);
118 hr = ITypeInfo_GetTypeAttr(ti, &attr);
119 ok_(__FILE__,line) (hr == S_OK, "GetTypeAttr() failed, %#x.\n", hr);
121 ok_(__FILE__,line) (IsEqualGUID(&attr->guid, guid), "Unexpected typeinfo %s, expected %s\n", wine_dbgstr_guid(&attr->guid),
122 wine_dbgstr_guid(guid));
124 hr = IProvideClassInfo_QueryInterface(classinfo, &IID_IUnknown, (void **)&unk);
125 ok(hr == S_OK, "Failed to QI for IUnknown.\n");
126 ok(unk == (IUnknown *)disp, "Got unk %p, original %p.\n", unk, disp);
127 IUnknown_Release(unk);
129 IProvideClassInfo_Release(classinfo);
130 ITypeInfo_ReleaseTypeAttr(ti, attr);
131 ITypeInfo_Release(ti);
134 static void test_interfaces(void)
136 HRESULT hr;
137 IDispatch *disp;
138 IDispatchEx *dispex;
139 IObjectWithSite *site;
140 VARIANT_BOOL b;
141 BSTR path;
142 WCHAR windows_path[MAX_PATH];
143 WCHAR file_path[MAX_PATH];
145 IFileSystem3_QueryInterface(fs3, &IID_IDispatch, (void**)&disp);
147 GetSystemDirectoryW(windows_path, MAX_PATH);
148 lstrcpyW(file_path, windows_path);
149 lstrcatW(file_path, L"\\kernel32.dll");
151 test_provideclassinfo(disp, &CLSID_FileSystemObject);
153 hr = IDispatch_QueryInterface(disp, &IID_IObjectWithSite, (void**)&site);
154 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
156 hr = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
157 ok(hr == E_NOINTERFACE, "got 0x%08x, expected 0x%08x\n", hr, E_NOINTERFACE);
159 b = VARIANT_TRUE;
160 hr = IFileSystem3_FileExists(fs3, NULL, &b);
161 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
162 ok(b == VARIANT_FALSE, "got %x\n", b);
164 hr = IFileSystem3_FileExists(fs3, NULL, NULL);
165 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
167 path = SysAllocString(L"path");
168 b = VARIANT_TRUE;
169 hr = IFileSystem3_FileExists(fs3, path, &b);
170 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
171 ok(b == VARIANT_FALSE, "got %x\n", b);
172 SysFreeString(path);
174 path = SysAllocString(file_path);
175 b = VARIANT_FALSE;
176 hr = IFileSystem3_FileExists(fs3, path, &b);
177 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
178 ok(b == VARIANT_TRUE, "got %x\n", b);
179 SysFreeString(path);
181 path = SysAllocString(windows_path);
182 b = VARIANT_TRUE;
183 hr = IFileSystem3_FileExists(fs3, path, &b);
184 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
185 ok(b == VARIANT_FALSE, "got %x\n", b);
186 SysFreeString(path);
188 /* Folder Exists */
189 hr = IFileSystem3_FolderExists(fs3, NULL, NULL);
190 ok(hr == E_POINTER, "got 0x%08x, expected 0x%08x\n", hr, E_POINTER);
192 path = SysAllocString(windows_path);
193 hr = IFileSystem3_FolderExists(fs3, path, &b);
194 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
195 ok(b == VARIANT_TRUE, "Folder doesn't exists\n");
196 SysFreeString(path);
198 path = SysAllocString(L"c:\\Nonexistent");
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_FALSE, "Folder exists\n");
202 SysFreeString(path);
204 path = SysAllocString(file_path);
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);
210 IDispatch_Release(disp);
213 static void test_createfolder(void)
215 WCHAR buffW[MAX_PATH];
216 HRESULT hr;
217 BSTR path;
218 IFolder *folder;
219 BOOL ret;
221 get_temp_path(NULL, buffW);
222 ret = CreateDirectoryW(buffW, NULL);
223 ok(ret, "got %d, %d\n", ret, GetLastError());
225 /* create existing directory */
226 path = SysAllocString(buffW);
227 folder = (void*)0xdeabeef;
228 hr = IFileSystem3_CreateFolder(fs3, path, &folder);
229 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
230 ok(folder == NULL, "got %p\n", folder);
231 SysFreeString(path);
232 RemoveDirectoryW(buffW);
235 static void test_textstream(void)
237 ITextStream *stream;
238 VARIANT_BOOL b;
239 DWORD written;
240 HANDLE file;
241 HRESULT hr;
242 BSTR name, data;
243 BOOL ret;
245 file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
246 CloseHandle(file);
248 name = SysAllocString(testfileW);
249 b = VARIANT_FALSE;
250 hr = IFileSystem3_FileExists(fs3, name, &b);
251 ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
252 ok(b == VARIANT_TRUE, "got %x\n", b);
254 /* different mode combinations */
255 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
256 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
258 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
259 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
261 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForReading, VARIANT_FALSE, TristateFalse, &stream);
262 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
264 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
265 ok(hr == S_OK, "got 0x%08x\n", hr);
266 hr = ITextStream_Read(stream, 1, &data);
267 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
268 ITextStream_Release(stream);
270 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, 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);
276 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
277 ok(hr == S_OK, "got 0x%08x\n", hr);
279 /* try to write when open for reading */
280 hr = ITextStream_WriteLine(stream, name);
281 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
283 hr = ITextStream_Write(stream, name);
284 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
286 hr = ITextStream_get_AtEndOfStream(stream, NULL);
287 ok(hr == E_POINTER, "got 0x%08x\n", hr);
289 b = 10;
290 hr = ITextStream_get_AtEndOfStream(stream, &b);
291 ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr);
292 ok(b == VARIANT_TRUE, "got 0x%x\n", b);
294 ITextStream_Release(stream);
296 hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
297 ok(hr == S_OK, "got 0x%08x\n", hr);
299 b = 10;
300 hr = ITextStream_get_AtEndOfStream(stream, &b);
301 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
302 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
304 b = 10;
305 hr = ITextStream_get_AtEndOfLine(stream, &b);
306 todo_wine {
307 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
308 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
310 hr = ITextStream_Read(stream, 1, &data);
311 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
313 hr = ITextStream_ReadLine(stream, &data);
314 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
316 hr = ITextStream_ReadAll(stream, &data);
317 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
319 ITextStream_Release(stream);
321 hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
322 ok(hr == S_OK, "got 0x%08x\n", hr);
324 b = 10;
325 hr = ITextStream_get_AtEndOfStream(stream, &b);
326 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
327 ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
329 b = 10;
330 hr = ITextStream_get_AtEndOfLine(stream, &b);
331 todo_wine {
332 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
333 ok(b == VARIANT_FALSE || broken(b == 10), "got 0x%x\n", b);
335 hr = ITextStream_Read(stream, 1, &data);
336 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
338 hr = ITextStream_ReadLine(stream, &data);
339 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
341 hr = ITextStream_ReadAll(stream, &data);
342 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
344 ITextStream_Release(stream);
346 /* now with non-empty file */
347 file = CreateFileW(testfileW, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
348 ret = WriteFile(file, testfileW, sizeof(testfileW), &written, NULL);
349 ok(ret && written == sizeof(testfileW), "got %d\n", ret);
350 CloseHandle(file);
352 hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
353 ok(hr == S_OK, "got 0x%08x\n", hr);
354 b = 10;
355 hr = ITextStream_get_AtEndOfStream(stream, &b);
356 ok(hr == S_OK, "got 0x%08x\n", hr);
357 ok(b == VARIANT_FALSE, "got 0x%x\n", b);
358 ITextStream_Release(stream);
360 SysFreeString(name);
361 DeleteFileW(testfileW);
364 static void test_GetFileVersion(void)
366 WCHAR pathW[MAX_PATH], filenameW[MAX_PATH];
367 BSTR path, version;
368 HRESULT hr;
370 GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW));
372 lstrcpyW(filenameW, pathW);
373 lstrcatW(filenameW, L"\\kernel32.dll");
375 path = SysAllocString(filenameW);
376 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
377 ok(hr == S_OK, "got 0x%08x\n", hr);
378 ok(*version != 0, "got %s\n", wine_dbgstr_w(version));
379 SysFreeString(version);
380 SysFreeString(path);
382 lstrcpyW(filenameW, pathW);
383 lstrcatW(filenameW, L"\\kernel33.dll");
385 path = SysAllocString(filenameW);
386 version = (void*)0xdeadbeef;
387 hr = IFileSystem3_GetFileVersion(fs3, path, &version);
388 ok(broken(hr == S_OK) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
389 if (hr == S_OK)
391 ok(*version == 0, "got %s\n", wine_dbgstr_w(version));
392 SysFreeString(version);
394 else
395 ok(version == (void*)0xdeadbeef, "got %p\n", version);
396 SysFreeString(path);
399 static void test_GetParentFolderName(void)
401 static const struct
403 const WCHAR *path;
404 const WCHAR *result;
406 tests[] =
408 { NULL, NULL },
409 { L"a", NULL },
410 { L"a/a/a", L"a/a" },
411 { L"a\\a\\a", L"a\\a" },
412 { L"a/a//\\\\", L"a" },
413 { L"c:\\\\a", L"c:\\" },
414 { L"ac:\\a", L"ac:" }
417 BSTR path, result;
418 HRESULT hr;
419 int i;
421 hr = IFileSystem3_GetParentFolderName(fs3, NULL, NULL);
422 ok(hr == E_POINTER, "GetParentFolderName returned %x, expected E_POINTER\n", hr);
424 for(i=0; i < ARRAY_SIZE(tests); i++) {
425 result = (BSTR)0xdeadbeef;
426 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
427 hr = IFileSystem3_GetParentFolderName(fs3, path, &result);
428 ok(hr == S_OK, "%d) GetParentFolderName returned %x, expected S_OK\n", i, hr);
429 if(!tests[i].result)
430 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
431 else
432 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
433 SysFreeString(path);
434 SysFreeString(result);
438 static void test_GetFileName(void)
440 static const struct
442 const WCHAR *path;
443 const WCHAR *result;
444 } tests[] =
446 { NULL, NULL },
447 { L"a", L"a" },
448 { L"a/a.b", L"a.b" },
449 { L"a\\", L"a" },
450 { L"c:", NULL },
451 { L"/\\", NULL }
454 BSTR path, result;
455 HRESULT hr;
456 int i;
458 hr = IFileSystem3_GetFileName(fs3, NULL, NULL);
459 ok(hr == E_POINTER, "GetFileName returned %x, expected E_POINTER\n", hr);
461 for(i=0; i < ARRAY_SIZE(tests); i++) {
462 result = (BSTR)0xdeadbeef;
463 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
464 hr = IFileSystem3_GetFileName(fs3, path, &result);
465 ok(hr == S_OK, "%d) GetFileName returned %x, expected S_OK\n", i, hr);
466 if(!tests[i].result)
467 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
468 else
469 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
470 SysFreeString(path);
471 SysFreeString(result);
475 static void test_GetBaseName(void)
477 static const struct
479 const WCHAR *path;
480 const WCHAR *result;
482 tests[] =
484 { NULL, NULL},
485 { L"a", L"a" },
486 { L"a/a.b.c", L"a.b" },
487 { L"a.b\\", L"a" },
488 { L"c:", NULL },
489 { L"/\\", NULL },
490 { L".a", L"" }
493 BSTR path, result;
494 HRESULT hr;
495 int i;
497 hr = IFileSystem3_GetBaseName(fs3, NULL, NULL);
498 ok(hr == E_POINTER, "GetBaseName returned %x, expected E_POINTER\n", hr);
500 for(i=0; i < ARRAY_SIZE(tests); i++) {
501 result = (BSTR)0xdeadbeef;
502 path = tests[i].path ? SysAllocString(tests[i].path) : NULL;
503 hr = IFileSystem3_GetBaseName(fs3, path, &result);
504 ok(hr == S_OK, "%d) GetBaseName returned %x, expected S_OK\n", i, hr);
505 if(!tests[i].result)
506 ok(!result, "%d) result = %s\n", i, wine_dbgstr_w(result));
507 else
508 ok(!lstrcmpW(result, tests[i].result), "%d) result = %s\n", i, wine_dbgstr_w(result));
509 SysFreeString(path);
510 SysFreeString(result);
514 static void test_GetAbsolutePathName(void)
516 static const WCHAR dir1[] = L"test_dir1";
517 static const WCHAR dir2[] = L"test_dir2";
518 static const WCHAR dir_match1[] = L"test_dir*";
519 static const WCHAR dir_match2[] = L"test_di*";
521 WIN32_FIND_DATAW fdata;
522 HANDLE find;
523 WCHAR buf[MAX_PATH], buf2[MAX_PATH];
524 BSTR path, result;
525 HRESULT hr;
527 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, NULL);
528 ok(hr == E_POINTER, "GetAbsolutePathName returned %x, expected E_POINTER\n", hr);
530 hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result);
531 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
532 GetFullPathNameW(L".", MAX_PATH, buf, NULL);
533 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
534 SysFreeString(result);
536 find = FindFirstFileW(dir_match2, &fdata);
537 if(find != INVALID_HANDLE_VALUE) {
538 skip("GetAbsolutePathName tests\n");
539 FindClose(find);
540 return;
543 path = SysAllocString(dir_match1);
544 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
545 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
546 GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL);
547 ok(!lstrcmpiW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2));
548 SysFreeString(result);
550 ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1));
551 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
552 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
553 GetFullPathNameW(dir1, MAX_PATH, buf, NULL);
554 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
555 wine_dbgstr_w(result), wine_dbgstr_w(buf));
556 SysFreeString(result);
558 ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2));
559 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
560 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
561 if(!lstrcmpiW(buf, result) || !lstrcmpiW(buf2, result)) {
562 ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
563 wine_dbgstr_w(result), wine_dbgstr_w(buf));
564 }else {
565 GetFullPathNameW(dir2, MAX_PATH, buf, NULL);
566 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n",
567 wine_dbgstr_w(result), wine_dbgstr_w(buf));
569 SysFreeString(result);
571 SysFreeString(path);
572 path = SysAllocString(dir_match2);
573 hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
574 ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
575 GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL);
576 ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
577 SysFreeString(result);
578 SysFreeString(path);
580 RemoveDirectoryW(dir1);
581 RemoveDirectoryW(dir2);
584 static void test_GetFile(void)
586 BSTR path, str;
587 WCHAR pathW[MAX_PATH];
588 FileAttribute fa;
589 VARIANT size;
590 DWORD gfa, new_gfa;
591 IFile *file;
592 HRESULT hr;
593 HANDLE hf;
594 BOOL ret;
595 DATE date;
597 get_temp_path(NULL, pathW);
599 path = SysAllocString(pathW);
600 hr = IFileSystem3_GetFile(fs3, path, NULL);
601 ok(hr == E_POINTER, "GetFile returned %x, expected E_POINTER\n", hr);
602 hr = IFileSystem3_GetFile(fs3, NULL, &file);
603 ok(hr == E_INVALIDARG, "GetFile returned %x, expected E_INVALIDARG\n", hr);
605 file = (IFile*)0xdeadbeef;
606 hr = IFileSystem3_GetFile(fs3, path, &file);
607 ok(!file, "file != NULL\n");
608 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
610 hf = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
611 if(hf == INVALID_HANDLE_VALUE) {
612 skip("Can't create temporary file\n");
613 SysFreeString(path);
614 return;
616 CloseHandle(hf);
618 hr = IFileSystem3_GetFile(fs3, path, &file);
619 ok(hr == S_OK, "GetFile returned %x, expected S_OK\n", hr);
621 hr = IFile_get_DateLastModified(file, NULL);
622 ok(hr == E_POINTER, "got 0x%08x\n", hr);
624 date = 0.0;
625 hr = IFile_get_DateLastModified(file, &date);
626 ok(hr == S_OK, "got 0x%08x\n", hr);
627 ok(date > 0.0, "got %f\n", date);
629 hr = IFile_get_Path(file, NULL);
630 ok(hr == E_POINTER, "got 0x%08x\n", hr);
632 hr = IFile_get_Path(file, &str);
633 ok(hr == S_OK, "got 0x%08x\n", hr);
634 ok(!lstrcmpiW(str, pathW), "got %s\n", wine_dbgstr_w(str));
635 SysFreeString(str);
637 #define FILE_ATTR_MASK (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
638 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | \
639 FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_COMPRESSED)
641 hr = IFile_get_Attributes(file, &fa);
642 gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK;
643 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
644 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa);
646 hr = IFile_put_Attributes(file, gfa | FILE_ATTRIBUTE_READONLY);
647 ok(hr == S_OK, "put_Attributes failed: %08x\n", hr);
648 new_gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK;
649 ok(new_gfa == (gfa|FILE_ATTRIBUTE_READONLY), "new_gfa = %x, expected %x\n", new_gfa, gfa|FILE_ATTRIBUTE_READONLY);
651 hr = IFile_get_Attributes(file, &fa);
652 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
653 ok(fa == new_gfa, "fa = %x, expected %x\n", fa, new_gfa);
655 hr = IFile_put_Attributes(file, gfa);
656 ok(hr == S_OK, "put_Attributes failed: %08x\n", hr);
657 new_gfa = GetFileAttributesW(pathW) & FILE_ATTR_MASK;
658 ok(new_gfa == gfa, "new_gfa = %x, expected %x\n", new_gfa, gfa);
660 hr = IFile_get_Attributes(file, &fa);
661 ok(hr == S_OK, "get_Attributes returned %x, expected S_OK\n", hr);
662 ok(fa == gfa, "fa = %x, expected %x\n", fa, gfa);
664 hr = IFile_get_Size(file, &size);
665 ok(hr == S_OK, "get_Size returned %x, expected S_OK\n", hr);
666 ok(V_VT(&size) == VT_I4, "V_VT(&size) = %d, expected VT_I4\n", V_VT(&size));
667 ok(V_I4(&size) == 0, "V_I4(&size) = %d, expected 0\n", V_I4(&size));
668 IFile_Release(file);
670 hr = IFileSystem3_DeleteFile(fs3, path, FALSE);
671 ok(hr==CTL_E_PERMISSIONDENIED || broken(hr==S_OK),
672 "DeleteFile returned %x, expected CTL_E_PERMISSIONDENIED\n", hr);
673 if(hr != S_OK) {
674 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
675 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
677 hr = IFileSystem3_DeleteFile(fs3, path, TRUE);
678 ok(hr == CTL_E_FILENOTFOUND, "DeleteFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
680 SysFreeString(path);
682 /* try with directory */
683 lstrcatW(pathW, L"\\");
684 ret = CreateDirectoryW(pathW, NULL);
685 ok(ret, "got %d, error %d\n", ret, GetLastError());
687 path = SysAllocString(pathW);
688 hr = IFileSystem3_GetFile(fs3, path, &file);
689 ok(hr == CTL_E_FILENOTFOUND, "GetFile returned %x, expected S_OK\n", hr);
690 SysFreeString(path);
692 RemoveDirectoryW(pathW);
695 static inline BOOL create_file(const WCHAR *name)
697 HANDLE f = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
698 CloseHandle(f);
699 return f != INVALID_HANDLE_VALUE;
702 static inline void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret)
704 DWORD len = lstrlenW(folder);
705 memmove(ret, folder, len*sizeof(WCHAR));
706 ret[len] = '\\';
707 memmove(ret+len+1, name, (lstrlenW(name)+1)*sizeof(WCHAR));
710 static void test_CopyFolder(void)
712 static const WCHAR filesystem3_dir[] = L"filesystem3_test";
713 static const WCHAR src1W[] = L"src1";
714 static const WCHAR dstW[] = L"dst";
716 WCHAR tmp[MAX_PATH];
717 BSTR bsrc, bdst;
718 HRESULT hr;
720 if(!CreateDirectoryW(filesystem3_dir, NULL)) {
721 skip("can't create temporary directory\n");
722 return;
725 create_path(filesystem3_dir, src1W, tmp);
726 bsrc = SysAllocString(tmp);
727 create_path(filesystem3_dir, dstW, tmp);
728 bdst = SysAllocString(tmp);
729 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
730 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
732 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
733 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
735 ok(create_file(bsrc), "can't create %s file\n", wine_dbgstr_w(bsrc));
736 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
737 ok(hr == S_OK, "CopyFile returned %x, expected S_OK\n", hr);
739 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
740 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
742 hr = IFileSystem3_DeleteFile(fs3, bsrc, VARIANT_FALSE);
743 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
745 ok(CreateDirectoryW(bsrc, NULL), "can't create %s\n", wine_dbgstr_w(bsrc));
746 hr = IFileSystem3_CopyFile(fs3, bsrc, bdst, VARIANT_TRUE);
747 ok(hr == CTL_E_FILENOTFOUND, "CopyFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
749 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
750 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
752 hr = IFileSystem3_DeleteFile(fs3, bdst, VARIANT_TRUE);
753 ok(hr == S_OK, "DeleteFile returned %x, expected S_OK\n", hr);
755 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
756 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
758 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
759 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
760 create_path(tmp, src1W, tmp);
761 ok(GetFileAttributesW(tmp) == INVALID_FILE_ATTRIBUTES,
762 "%s file exists\n", wine_dbgstr_w(tmp));
764 create_path(filesystem3_dir, dstW, tmp);
765 create_path(tmp, L"", tmp);
766 SysFreeString(bdst);
767 bdst = SysAllocString(tmp);
768 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
769 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
770 create_path(tmp, src1W, tmp);
771 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
772 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
773 ok(RemoveDirectoryW(tmp), "can't remove %s directory\n", wine_dbgstr_w(tmp));
774 create_path(filesystem3_dir, dstW, tmp);
775 SysFreeString(bdst);
776 bdst = SysAllocString(tmp);
778 create_path(filesystem3_dir, L"src*", tmp);
779 SysFreeString(bsrc);
780 bsrc = SysAllocString(tmp);
781 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
782 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
783 create_path(filesystem3_dir, dstW, tmp);
784 create_path(tmp, src1W, tmp);
785 ok(GetFileAttributesW(tmp) != INVALID_FILE_ATTRIBUTES,
786 "%s directory doesn't exist\n", wine_dbgstr_w(tmp));
788 hr = IFileSystem3_DeleteFolder(fs3, bdst, VARIANT_FALSE);
789 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
791 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
792 ok(hr == CTL_E_PATHNOTFOUND, "CopyFolder returned %x, expected CTL_E_PATHNOTFOUND\n", hr);
794 create_path(filesystem3_dir, src1W, tmp);
795 SysFreeString(bsrc);
796 bsrc = SysAllocString(tmp);
797 create_path(tmp, src1W, tmp);
798 ok(create_file(tmp), "can't create %s file\n", wine_dbgstr_w(tmp));
799 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
800 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
802 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_FALSE);
803 ok(hr == CTL_E_FILEALREADYEXISTS, "CopyFolder returned %x, expected CTL_E_FILEALREADYEXISTS\n", hr);
805 hr = IFileSystem3_CopyFolder(fs3, bsrc, bdst, VARIANT_TRUE);
806 ok(hr == S_OK, "CopyFolder returned %x, expected S_OK\n", hr);
807 SysFreeString(bsrc);
808 SysFreeString(bdst);
810 bsrc = SysAllocString(filesystem3_dir);
811 hr = IFileSystem3_DeleteFolder(fs3, bsrc, VARIANT_FALSE);
812 ok(hr == S_OK, "DeleteFolder returned %x, expected S_OK\n", hr);
813 SysFreeString(bsrc);
816 static BSTR bstr_from_str(const char *str)
818 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
819 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */
820 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
821 return ret;
824 struct buildpath_test
826 const char *path;
827 const char *name;
828 const char *result;
831 static struct buildpath_test buildpath_data[] =
833 { "C:\\path", "..\\name.tmp", "C:\\path\\..\\name.tmp" },
834 { "C:\\path", "\\name.tmp", "C:\\path\\name.tmp" },
835 { "C:\\path", "name.tmp", "C:\\path\\name.tmp" },
836 { "C:\\path\\", "name.tmp", "C:\\path\\name.tmp" },
837 { "C:\\path", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
838 { "C:\\path\\", "\\name.tmp", "C:\\path\\name.tmp" },
839 { "C:\\path\\", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
840 { "C:\\path\\\\", "\\\\name.tmp", "C:\\path\\\\\\name.tmp" },
841 { "C:\\\\", "\\name.tmp", "C:\\\\name.tmp" },
842 { "C:", "name.tmp", "C:name.tmp" },
843 { "C:", "\\\\name.tmp", "C:\\\\name.tmp" },
844 { NULL }
847 static void test_BuildPath(void)
849 struct buildpath_test *ptr = buildpath_data;
850 BSTR ret, path;
851 HRESULT hr;
852 int i = 0;
854 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, NULL);
855 ok(hr == E_POINTER, "got 0x%08x\n", hr);
857 ret = (BSTR)0xdeadbeef;
858 hr = IFileSystem3_BuildPath(fs3, NULL, NULL, &ret);
859 ok(hr == S_OK, "got 0x%08x\n", hr);
860 ok(*ret == 0, "got %p\n", ret);
861 SysFreeString(ret);
863 ret = (BSTR)0xdeadbeef;
864 path = bstr_from_str("path");
865 hr = IFileSystem3_BuildPath(fs3, path, NULL, &ret);
866 ok(hr == S_OK, "got 0x%08x\n", hr);
867 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
868 SysFreeString(ret);
869 SysFreeString(path);
871 ret = (BSTR)0xdeadbeef;
872 path = bstr_from_str("path");
873 hr = IFileSystem3_BuildPath(fs3, NULL, path, &ret);
874 ok(hr == S_OK, "got 0x%08x\n", hr);
875 ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
876 SysFreeString(ret);
877 SysFreeString(path);
879 while (ptr->path)
881 BSTR name, result;
883 ret = NULL;
884 path = bstr_from_str(ptr->path);
885 name = bstr_from_str(ptr->name);
886 result = bstr_from_str(ptr->result);
887 hr = IFileSystem3_BuildPath(fs3, path, name, &ret);
888 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
889 if (hr == S_OK)
891 ok(!lstrcmpW(ret, result), "%d: got wrong path %s, expected %s\n", i, wine_dbgstr_w(ret),
892 wine_dbgstr_w(result));
893 SysFreeString(ret);
895 SysFreeString(path);
896 SysFreeString(name);
897 SysFreeString(result);
899 i++;
900 ptr++;
904 static void test_GetFolder(void)
906 WCHAR buffW[MAX_PATH];
907 IFolder *folder;
908 HRESULT hr;
909 BSTR str;
911 folder = (void*)0xdeadbeef;
912 hr = IFileSystem3_GetFolder(fs3, NULL, &folder);
913 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
914 ok(folder == NULL, "got %p\n", folder);
916 hr = IFileSystem3_GetFolder(fs3, NULL, NULL);
917 ok(hr == E_POINTER, "got 0x%08x\n", hr);
919 /* something that doesn't exist */
920 str = SysAllocString(L"dummy");
922 hr = IFileSystem3_GetFolder(fs3, str, NULL);
923 ok(hr == E_POINTER, "got 0x%08x\n", hr);
925 folder = (void*)0xdeadbeef;
926 hr = IFileSystem3_GetFolder(fs3, str, &folder);
927 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
928 ok(folder == NULL, "got %p\n", folder);
929 SysFreeString(str);
931 GetWindowsDirectoryW(buffW, MAX_PATH);
932 str = SysAllocString(buffW);
933 hr = IFileSystem3_GetFolder(fs3, str, &folder);
934 ok(hr == S_OK, "got 0x%08x\n", hr);
935 SysFreeString(str);
936 test_provideclassinfo(folder, &CLSID_Folder);
937 IFolder_Release(folder);
940 static void _test_clone(IEnumVARIANT *enumvar, BOOL position_inherited, LONG count, int line)
942 HRESULT hr;
943 IEnumVARIANT *clone;
944 ULONG fetched;
945 VARIANT var, var2;
947 hr = IEnumVARIANT_Reset(enumvar);
948 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
950 VariantInit(&var);
951 fetched = -1;
952 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
953 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
954 ok(fetched == 1, "%d: got %d\n", line, fetched);
956 /* clone enumerator */
957 hr = IEnumVARIANT_Clone(enumvar, &clone);
958 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
959 ok(clone != enumvar, "%d: got %p, %p\n", line, enumvar, clone);
961 /* check if clone inherits position */
962 VariantInit(&var2);
963 fetched = -1;
964 hr = IEnumVARIANT_Next(clone, 1, &var2, &fetched);
965 if (position_inherited && count == 1)
967 ok(hr == S_FALSE, "%d: got 0x%08x\n", line, hr);
968 ok(fetched == 0, "%d: got %d\n", line, fetched);
970 else
972 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
973 ok(fetched == 1, "%d: got %d\n", line, fetched);
974 if (!position_inherited)
975 todo_wine ok(V_DISPATCH(&var) == V_DISPATCH(&var2), "%d: values don't match\n", line);
976 else
978 fetched = -1;
979 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
980 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
981 ok(fetched == 1, "%d: got %d\n", line, fetched);
982 todo_wine ok(V_DISPATCH(&var) == V_DISPATCH(&var2), "%d: values don't match\n", line);
986 VariantClear(&var2);
987 VariantClear(&var);
988 IEnumVARIANT_Release(clone);
990 hr = IEnumVARIANT_Reset(enumvar);
991 ok(hr == S_OK, "%d: got 0x%08x\n", line, hr);
993 #define test_clone(a, b, c) _test_clone(a, b, c, __LINE__)
995 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
996 static void test_FolderCollection(void)
998 static const WCHAR aW[] = L"\\a";
999 static const WCHAR bW[] = L"\\b";
1000 static const WCHAR cW[] = L"\\c";
1001 IFolderCollection *folders;
1002 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
1003 IEnumVARIANT *enumvar;
1004 LONG count, ref, ref2, i;
1005 IUnknown *unk, *unk2;
1006 IFolder *folder;
1007 ULONG fetched;
1008 VARIANT var, var2[2];
1009 HRESULT hr;
1010 BSTR str;
1011 int found_a = 0, found_b = 0, found_c = 0;
1013 get_temp_path(L"foo", buffW);
1014 CreateDirectoryW(buffW, NULL);
1016 str = SysAllocString(buffW);
1017 hr = IFileSystem3_GetFolder(fs3, str, &folder);
1018 ok(hr == S_OK, "got 0x%08x\n", hr);
1019 SysFreeString(str);
1021 hr = IFolder_get_SubFolders(folder, NULL);
1022 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1024 hr = IFolder_get_Path(folder, NULL);
1025 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1027 hr = IFolder_get_Path(folder, &str);
1028 ok(hr == S_OK, "got 0x%08x\n", hr);
1029 ok(!lstrcmpiW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1030 SysFreeString(str);
1032 lstrcpyW(pathW, buffW);
1033 lstrcatW(pathW, aW);
1034 CreateDirectoryW(pathW, NULL);
1036 lstrcpyW(pathW, buffW);
1037 lstrcatW(pathW, bW);
1038 CreateDirectoryW(pathW, NULL);
1040 hr = IFolder_get_SubFolders(folder, &folders);
1041 ok(hr == S_OK, "got 0x%08x\n", hr);
1042 test_provideclassinfo(folders, &CLSID_Folders);
1043 IFolder_Release(folder);
1045 count = 0;
1046 hr = IFolderCollection_get_Count(folders, &count);
1047 ok(hr == S_OK, "got 0x%08x\n", hr);
1048 ok(count == 2, "got %d\n", count);
1050 lstrcpyW(pathW, buffW);
1051 lstrcatW(pathW, cW);
1052 CreateDirectoryW(pathW, NULL);
1054 /* every time property is requested it scans directory */
1055 count = 0;
1056 hr = IFolderCollection_get_Count(folders, &count);
1057 ok(hr == S_OK, "got 0x%08x\n", hr);
1058 ok(count == 3, "got %d\n", count);
1060 hr = IFolderCollection_get__NewEnum(folders, NULL);
1061 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1063 hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk);
1064 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1066 /* NewEnum creates new instance each time it's called */
1067 ref = GET_REFCOUNT(folders);
1069 unk = NULL;
1070 hr = IFolderCollection_get__NewEnum(folders, &unk);
1071 ok(hr == S_OK, "got 0x%08x\n", hr);
1073 ref2 = GET_REFCOUNT(folders);
1074 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1076 unk2 = NULL;
1077 hr = IFolderCollection_get__NewEnum(folders, &unk2);
1078 ok(hr == S_OK, "got 0x%08x\n", hr);
1079 ok(unk != unk2, "got %p, %p\n", unk2, unk);
1080 IUnknown_Release(unk2);
1082 /* now get IEnumVARIANT */
1083 ref = GET_REFCOUNT(folders);
1084 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1085 ok(hr == S_OK, "got 0x%08x\n", hr);
1086 ref2 = GET_REFCOUNT(folders);
1087 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1089 test_clone(enumvar, FALSE, count);
1091 for (i = 0; i < 3; i++)
1093 VariantInit(&var);
1094 fetched = 0;
1095 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1096 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1097 ok(fetched == 1, "%d: got %d\n", i, fetched);
1098 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1100 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder);
1101 ok(hr == S_OK, "got 0x%08x\n", hr);
1103 str = NULL;
1104 hr = IFolder_get_Name(folder, &str);
1105 ok(hr == S_OK, "got 0x%08x\n", hr);
1106 if (!lstrcmpW(str, aW + 1))
1107 found_a++;
1108 else if (!lstrcmpW(str, bW + 1))
1109 found_b++;
1110 else if (!lstrcmpW(str, cW + 1))
1111 found_c++;
1112 else
1113 ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str));
1114 SysFreeString(str);
1116 IFolder_Release(folder);
1117 VariantClear(&var);
1120 ok(found_a == 1 && found_b == 1 && found_c == 1,
1121 "each folder should be found 1 time instead of %d/%d/%d\n",
1122 found_a, found_b, found_c);
1124 VariantInit(&var);
1125 fetched = -1;
1126 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1127 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1128 ok(fetched == 0, "got %d\n", fetched);
1130 hr = IEnumVARIANT_Reset(enumvar);
1131 ok(hr == S_OK, "got 0x%08x\n", hr);
1132 hr = IEnumVARIANT_Skip(enumvar, 2);
1133 ok(hr == S_OK, "got 0x%08x\n", hr);
1134 hr = IEnumVARIANT_Skip(enumvar, 0);
1135 ok(hr == S_OK, "got 0x%08x\n", hr);
1137 VariantInit(&var2[0]);
1138 VariantInit(&var2[1]);
1139 fetched = -1;
1140 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1141 ok(hr == S_OK, "got 0x%08x\n", hr);
1142 ok(fetched == 0, "got %d\n", fetched);
1143 fetched = -1;
1144 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1145 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1146 ok(fetched == 1, "got %d\n", fetched);
1147 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1148 VariantClear(&var2[0]);
1149 VariantClear(&var2[1]);
1151 IEnumVARIANT_Release(enumvar);
1152 IUnknown_Release(unk);
1154 lstrcpyW(pathW, buffW);
1155 lstrcatW(pathW, aW);
1156 RemoveDirectoryW(pathW);
1157 lstrcpyW(pathW, buffW);
1158 lstrcatW(pathW, bW);
1159 RemoveDirectoryW(pathW);
1160 lstrcpyW(pathW, buffW);
1161 lstrcatW(pathW, cW);
1162 RemoveDirectoryW(pathW);
1163 RemoveDirectoryW(buffW);
1165 IFolderCollection_Release(folders);
1168 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
1169 static void test_FileCollection(void)
1171 static const WCHAR aW[] = L"\\a";
1172 static const WCHAR bW[] = L"\\b";
1173 static const WCHAR cW[] = L"\\c";
1174 WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
1175 IFolder *folder;
1176 IFileCollection *files;
1177 IFile *file;
1178 IEnumVARIANT *enumvar;
1179 LONG count, ref, ref2, i;
1180 IUnknown *unk, *unk2;
1181 ULONG fetched;
1182 VARIANT var, var2[2];
1183 HRESULT hr;
1184 BSTR str;
1185 HANDLE file_a, file_b, file_c;
1186 int found_a = 0, found_b = 0, found_c = 0;
1188 get_temp_path(L"\\foo", buffW);
1189 CreateDirectoryW(buffW, NULL);
1191 str = SysAllocString(buffW);
1192 hr = IFileSystem3_GetFolder(fs3, str, &folder);
1193 ok(hr == S_OK, "got 0x%08x\n", hr);
1194 SysFreeString(str);
1196 hr = IFolder_get_Files(folder, NULL);
1197 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1199 lstrcpyW(pathW, buffW);
1200 lstrcatW(pathW, aW);
1201 file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1202 FILE_FLAG_DELETE_ON_CLOSE, 0);
1203 lstrcpyW(pathW, buffW);
1204 lstrcatW(pathW, bW);
1205 file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1206 FILE_FLAG_DELETE_ON_CLOSE, 0);
1208 hr = IFolder_get_Files(folder, &files);
1209 ok(hr == S_OK, "got 0x%08x\n", hr);
1210 test_provideclassinfo(files, &CLSID_Files);
1211 IFolder_Release(folder);
1213 count = 0;
1214 hr = IFileCollection_get_Count(files, &count);
1215 ok(hr == S_OK, "got 0x%08x\n", hr);
1216 ok(count == 2, "got %d\n", count);
1218 lstrcpyW(pathW, buffW);
1219 lstrcatW(pathW, cW);
1220 file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1221 FILE_FLAG_DELETE_ON_CLOSE, 0);
1223 /* every time property is requested it scans directory */
1224 count = 0;
1225 hr = IFileCollection_get_Count(files, &count);
1226 ok(hr == S_OK, "got 0x%08x\n", hr);
1227 ok(count == 3, "got %d\n", count);
1229 hr = IFileCollection_get__NewEnum(files, NULL);
1230 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1232 hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk);
1233 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1235 /* NewEnum creates new instance each time it's called */
1236 ref = GET_REFCOUNT(files);
1238 unk = NULL;
1239 hr = IFileCollection_get__NewEnum(files, &unk);
1240 ok(hr == S_OK, "got 0x%08x\n", hr);
1242 ref2 = GET_REFCOUNT(files);
1243 ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1245 unk2 = NULL;
1246 hr = IFileCollection_get__NewEnum(files, &unk2);
1247 ok(hr == S_OK, "got 0x%08x\n", hr);
1248 ok(unk != unk2, "got %p, %p\n", unk2, unk);
1249 IUnknown_Release(unk2);
1251 /* now get IEnumVARIANT */
1252 ref = GET_REFCOUNT(files);
1253 hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1254 ok(hr == S_OK, "got 0x%08x\n", hr);
1255 ref2 = GET_REFCOUNT(files);
1256 ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1258 test_clone(enumvar, FALSE, count);
1260 for (i = 0; i < 3; i++)
1262 VariantInit(&var);
1263 fetched = 0;
1264 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1265 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1266 ok(fetched == 1, "%d: got %d\n", i, fetched);
1267 ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1269 hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file);
1270 ok(hr == S_OK, "got 0x%08x\n", hr);
1271 test_provideclassinfo(file, &CLSID_File);
1273 str = NULL;
1274 hr = IFile_get_Name(file, &str);
1275 ok(hr == S_OK, "got 0x%08x\n", hr);
1276 if (!lstrcmpW(str, aW + 1))
1277 found_a++;
1278 else if (!lstrcmpW(str, bW + 1))
1279 found_b++;
1280 else if (!lstrcmpW(str, cW + 1))
1281 found_c++;
1282 else
1283 ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str));
1284 SysFreeString(str);
1286 IFile_Release(file);
1287 VariantClear(&var);
1290 ok(found_a == 1 && found_b == 1 && found_c == 1,
1291 "each file should be found 1 time instead of %d/%d/%d\n",
1292 found_a, found_b, found_c);
1294 VariantInit(&var);
1295 fetched = -1;
1296 hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1297 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1298 ok(fetched == 0, "got %d\n", fetched);
1300 hr = IEnumVARIANT_Reset(enumvar);
1301 ok(hr == S_OK, "got 0x%08x\n", hr);
1302 hr = IEnumVARIANT_Skip(enumvar, 2);
1303 ok(hr == S_OK, "got 0x%08x\n", hr);
1304 hr = IEnumVARIANT_Skip(enumvar, 0);
1305 ok(hr == S_OK, "got 0x%08x\n", hr);
1307 VariantInit(&var2[0]);
1308 VariantInit(&var2[1]);
1309 fetched = -1;
1310 hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1311 ok(hr == S_OK, "got 0x%08x\n", hr);
1312 ok(fetched == 0, "got %d\n", fetched);
1313 fetched = -1;
1314 hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1315 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1316 ok(fetched == 1, "got %d\n", fetched);
1317 ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1318 VariantClear(&var2[0]);
1319 VariantClear(&var2[1]);
1321 IEnumVARIANT_Release(enumvar);
1322 IUnknown_Release(unk);
1324 CloseHandle(file_a);
1325 CloseHandle(file_b);
1326 CloseHandle(file_c);
1327 RemoveDirectoryW(buffW);
1329 IFileCollection_Release(files);
1332 static void test_DriveCollection(void)
1334 IDriveCollection *drives;
1335 IEnumVARIANT *enumvar;
1336 ULONG fetched;
1337 VARIANT var;
1338 HRESULT hr;
1339 LONG count;
1341 hr = IFileSystem3_get_Drives(fs3, &drives);
1342 ok(hr == S_OK, "got 0x%08x\n", hr);
1344 test_provideclassinfo(drives, &CLSID_Drives);
1346 hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar);
1347 ok(hr == S_OK, "got 0x%08x\n", hr);
1349 hr = IDriveCollection_get_Count(drives, NULL);
1350 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1352 count = 0;
1353 hr = IDriveCollection_get_Count(drives, &count);
1354 ok(hr == S_OK, "got 0x%08x\n", hr);
1355 ok(count > 0, "got %d\n", count);
1357 V_VT(&var) = VT_EMPTY;
1358 fetched = -1;
1359 hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched);
1360 ok(hr == S_OK, "got 0x%08x\n", hr);
1361 ok(fetched == 0, "got %d\n", fetched);
1363 hr = IEnumVARIANT_Skip(enumvar, 0);
1364 ok(hr == S_OK, "got 0x%08x\n", hr);
1366 hr = IEnumVARIANT_Skip(enumvar, count);
1367 ok(hr == S_OK, "got 0x%08x\n", hr);
1369 hr = IEnumVARIANT_Skip(enumvar, 1);
1370 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1372 test_clone(enumvar, TRUE, count);
1374 while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) {
1375 IDrive *drive = (IDrive*)V_DISPATCH(&var);
1376 DriveTypeConst type;
1377 BSTR str;
1379 hr = IDrive_get_DriveType(drive, &type);
1380 ok(hr == S_OK, "got 0x%08x\n", hr);
1382 hr = IDrive_get_DriveLetter(drive, NULL);
1383 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1385 hr = IDrive_get_DriveLetter(drive, &str);
1386 ok(hr == S_OK, "got 0x%08x\n", hr);
1387 ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str));
1388 SysFreeString(str);
1390 hr = IDrive_get_IsReady(drive, NULL);
1391 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1393 hr = IDrive_get_TotalSize(drive, NULL);
1394 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1396 hr = IDrive_get_AvailableSpace(drive, NULL);
1397 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1399 hr = IDrive_get_FreeSpace(drive, NULL);
1400 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1402 if (type == Fixed) {
1403 VARIANT_BOOL ready = VARIANT_FALSE;
1404 VARIANT size;
1406 hr = IDrive_get_IsReady(drive, &ready);
1407 ok(hr == S_OK, "got 0x%08x\n", hr);
1408 ok(ready == VARIANT_TRUE, "got %x\n", ready);
1410 if (ready != VARIANT_TRUE) {
1411 hr = IDrive_get_DriveLetter(drive, &str);
1412 ok(hr == S_OK, "got 0x%08x\n", hr);
1414 skip("Drive %s is not ready, skipping some tests\n", wine_dbgstr_w(str));
1416 VariantClear(&var);
1417 SysFreeString(str);
1418 continue;
1421 V_VT(&size) = VT_EMPTY;
1422 hr = IDrive_get_TotalSize(drive, &size);
1423 ok(hr == S_OK, "got 0x%08x\n", hr);
1424 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1425 if (V_VT(&size) == VT_R8)
1426 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1427 else
1428 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1430 V_VT(&size) = VT_EMPTY;
1431 hr = IDrive_get_AvailableSpace(drive, &size);
1432 ok(hr == S_OK, "got 0x%08x\n", hr);
1433 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1434 if (V_VT(&size) == VT_R8)
1435 ok(V_R8(&size) > (double)INT_MAX, "got %f\n", V_R8(&size));
1436 else
1437 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1439 V_VT(&size) = VT_EMPTY;
1440 hr = IDrive_get_FreeSpace(drive, &size);
1441 ok(hr == S_OK, "got 0x%08x\n", hr);
1442 ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1443 if (V_VT(&size) == VT_R8)
1444 ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1445 else
1446 ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1448 VariantClear(&var);
1451 IEnumVARIANT_Release(enumvar);
1452 IDriveCollection_Release(drives);
1455 static void get_temp_filepath(const WCHAR *filename, WCHAR *path, WCHAR *dir)
1457 GetTempPathW(MAX_PATH, path);
1458 lstrcatW(path, L"scrrun\\");
1459 lstrcpyW(dir, path);
1460 lstrcatW(path, filename);
1463 static void test_CreateTextFile(void)
1465 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[10];
1466 ITextStream *stream;
1467 BSTR nameW, str;
1468 HANDLE file;
1469 HRESULT hr;
1470 BOOL ret;
1472 get_temp_filepath(testfileW, pathW, dirW);
1474 /* dir doesn't exist */
1475 nameW = SysAllocString(pathW);
1476 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1477 ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
1479 ret = CreateDirectoryW(dirW, NULL);
1480 ok(ret, "got %d, %d\n", ret, GetLastError());
1482 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1483 ok(hr == S_OK, "got 0x%08x\n", hr);
1485 test_provideclassinfo(stream, &CLSID_TextStream);
1487 hr = ITextStream_Read(stream, 1, &str);
1488 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1490 hr = ITextStream_Close(stream);
1491 ok(hr == S_OK, "got 0x%08x\n", hr);
1493 hr = ITextStream_Read(stream, 1, &str);
1494 ok(hr == CTL_E_BADFILEMODE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr);
1496 hr = ITextStream_Close(stream);
1497 ok(hr == S_FALSE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr);
1499 ITextStream_Release(stream);
1501 /* check it's created */
1502 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1503 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1504 CloseHandle(file);
1506 /* try to create again with no-overwrite mode */
1507 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1508 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
1510 /* now overwrite */
1511 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1512 ok(hr == S_OK, "got 0x%08x\n", hr);
1513 ITextStream_Release(stream);
1515 /* overwrite in Unicode mode, check for BOM */
1516 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
1517 ok(hr == S_OK, "got 0x%08x\n", hr);
1518 ITextStream_Release(stream);
1520 /* File was created in Unicode mode, it contains 0xfffe BOM. Opening it in non-Unicode mode
1521 treats BOM like a valuable data with appropriate CP_ACP -> WCHAR conversion. */
1522 buffW[0] = 0;
1523 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1525 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1526 ok(hr == S_OK, "got 0x%08x\n", hr);
1527 hr = ITextStream_ReadAll(stream, &str);
1528 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1529 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1530 SysFreeString(str);
1531 ITextStream_Release(stream);
1533 DeleteFileW(nameW);
1534 RemoveDirectoryW(dirW);
1535 SysFreeString(nameW);
1538 static void test_WriteLine(void)
1540 WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
1541 WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
1542 char buffA[MAX_PATH];
1543 ITextStream *stream;
1544 DWORD r, len;
1545 HANDLE file;
1546 BSTR nameW;
1547 HRESULT hr;
1548 BOOL ret;
1550 get_temp_filepath(testfileW, pathW, dirW);
1552 ret = CreateDirectoryW(dirW, NULL);
1553 ok(ret, "got %d, %d\n", ret, GetLastError());
1555 /* create as ASCII file first */
1556 nameW = SysAllocString(pathW);
1557 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1558 ok(hr == S_OK, "got 0x%08x\n", hr);
1560 hr = ITextStream_WriteLine(stream, nameW);
1561 ok(hr == S_OK, "got 0x%08x\n", hr);
1562 ITextStream_Release(stream);
1564 /* check contents */
1565 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1566 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1567 r = 0;
1568 ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL);
1569 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1571 len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, ARRAY_SIZE(buffW));
1572 buffW[len] = 0;
1573 lstrcpyW(buff2W, nameW);
1574 lstrcatW(buff2W, L"\r\n");
1575 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1576 CloseHandle(file);
1577 DeleteFileW(nameW);
1579 /* same for unicode file */
1580 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1581 ok(hr == S_OK, "got 0x%08x\n", hr);
1583 hr = ITextStream_WriteLine(stream, nameW);
1584 ok(hr == S_OK, "got 0x%08x\n", hr);
1585 ITextStream_Release(stream);
1587 /* check contents */
1588 file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1589 ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1590 r = 0;
1591 ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL);
1592 ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1593 buffW[r/sizeof(WCHAR)] = 0;
1595 buff2W[0] = 0xfeff;
1596 buff2W[1] = 0;
1597 lstrcatW(buff2W, nameW);
1598 lstrcatW(buff2W, L"\r\n");
1599 ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1600 CloseHandle(file);
1601 DeleteFileW(nameW);
1603 RemoveDirectoryW(dirW);
1604 SysFreeString(nameW);
1607 static void test_ReadAll(void)
1609 static const WCHAR secondlineW[] = L"second";
1610 static const WCHAR aW[] = L"A";
1611 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1612 ITextStream *stream;
1613 BSTR nameW;
1614 HRESULT hr;
1615 BOOL ret;
1616 BSTR str;
1618 get_temp_filepath(testfileW, pathW, dirW);
1620 ret = CreateDirectoryW(dirW, NULL);
1621 ok(ret, "got %d, %d\n", ret, GetLastError());
1623 /* Unicode file -> read with ascii stream */
1624 nameW = SysAllocString(pathW);
1625 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1626 ok(hr == S_OK, "got 0x%08x\n", hr);
1628 hr = ITextStream_WriteLine(stream, nameW);
1629 ok(hr == S_OK, "got 0x%08x\n", hr);
1631 str = SysAllocString(secondlineW);
1632 hr = ITextStream_WriteLine(stream, str);
1633 ok(hr == S_OK, "got 0x%08x\n", hr);
1634 SysFreeString(str);
1636 hr = ITextStream_ReadAll(stream, NULL);
1637 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1639 str = (void*)0xdeadbeef;
1640 hr = ITextStream_ReadAll(stream, &str);
1641 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1642 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1644 ITextStream_Release(stream);
1646 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1647 ok(hr == S_OK, "got 0x%08x\n", hr);
1649 hr = ITextStream_ReadAll(stream, NULL);
1650 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1652 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1653 str = NULL;
1654 hr = ITextStream_ReadAll(stream, &str);
1655 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1656 buffW[0] = 0;
1657 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1658 ok(str[0] == buffW[0] && str[1] == buffW[1], "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
1659 SysFreeString(str);
1660 ITextStream_Release(stream);
1662 /* Unicode file -> read with unicode stream */
1663 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1664 ok(hr == S_OK, "got 0x%08x\n", hr);
1666 lstrcpyW(buffW, nameW);
1667 lstrcatW(buffW, L"\r\n");
1668 lstrcatW(buffW, secondlineW);
1669 lstrcatW(buffW, L"\r\n");
1670 str = NULL;
1671 hr = ITextStream_ReadAll(stream, &str);
1672 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1673 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1674 SysFreeString(str);
1676 /* ReadAll one more time */
1677 str = (void*)0xdeadbeef;
1678 hr = ITextStream_ReadAll(stream, &str);
1679 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1680 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1682 /* ReadLine fails the same way */
1683 str = (void*)0xdeadbeef;
1684 hr = ITextStream_ReadLine(stream, &str);
1685 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1686 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1687 ITextStream_Release(stream);
1689 /* Open again and skip first line before ReadAll */
1690 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1691 ok(hr == S_OK, "got 0x%08x\n", hr);
1693 str = NULL;
1694 hr = ITextStream_ReadLine(stream, &str);
1695 ok(hr == S_OK, "got 0x%08x\n", hr);
1696 ok(str != NULL, "got %p\n", str);
1697 ok(!wcscmp(str, nameW), "got %s\n", wine_dbgstr_w(str));
1698 SysFreeString(str);
1700 lstrcpyW(buffW, secondlineW);
1701 lstrcatW(buffW, L"\r\n");
1702 str = NULL;
1703 hr = ITextStream_ReadAll(stream, &str);
1704 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1705 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1706 SysFreeString(str);
1707 ITextStream_Release(stream);
1709 /* ASCII file, read with Unicode stream */
1710 /* 1. one byte content, not enough for Unicode read */
1711 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1712 ok(hr == S_OK, "got 0x%08x\n", hr);
1713 str = SysAllocString(aW);
1714 hr = ITextStream_Write(stream, str);
1715 ok(hr == S_OK, "got 0x%08x\n", hr);
1716 SysFreeString(str);
1717 ITextStream_Release(stream);
1719 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1720 ok(hr == S_OK, "got 0x%08x\n", hr);
1722 str = (void*)0xdeadbeef;
1723 hr = ITextStream_ReadAll(stream, &str);
1724 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1725 ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1727 ITextStream_Release(stream);
1729 DeleteFileW(nameW);
1730 RemoveDirectoryW(dirW);
1731 SysFreeString(nameW);
1734 static void test_Read(void)
1736 static const WCHAR secondlineW[] = L"second";
1737 WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1738 ITextStream *stream;
1739 BSTR nameW;
1740 HRESULT hr;
1741 BOOL ret;
1742 BSTR str;
1744 get_temp_filepath(testfileW, pathW, dirW);
1746 ret = CreateDirectoryW(dirW, NULL);
1747 ok(ret, "got %d, %d\n", ret, GetLastError());
1749 /* Unicode file -> read with ascii stream */
1750 nameW = SysAllocString(pathW);
1751 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1752 ok(hr == S_OK, "got 0x%08x\n", hr);
1754 hr = ITextStream_WriteLine(stream, nameW);
1755 ok(hr == S_OK, "got 0x%08x\n", hr);
1757 str = SysAllocString(secondlineW);
1758 hr = ITextStream_WriteLine(stream, str);
1759 ok(hr == S_OK, "got 0x%08x\n", hr);
1760 SysFreeString(str);
1762 hr = ITextStream_Read(stream, 0, NULL);
1763 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1765 hr = ITextStream_Read(stream, 1, NULL);
1766 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1768 hr = ITextStream_Read(stream, -1, NULL);
1769 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1771 str = (void*)0xdeadbeef;
1772 hr = ITextStream_Read(stream, 1, &str);
1773 ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1774 ok(str == NULL, "got %p\n", str);
1776 ITextStream_Release(stream);
1778 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1779 ok(hr == S_OK, "got 0x%08x\n", hr);
1781 hr = ITextStream_Read(stream, 1, NULL);
1782 ok(hr == E_POINTER, "got 0x%08x\n", hr);
1784 str = (void*)0xdeadbeef;
1785 hr = ITextStream_Read(stream, -1, &str);
1786 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1787 ok(str == NULL, "got %p\n", str);
1789 str = (void*)0xdeadbeef;
1790 hr = ITextStream_Read(stream, 0, &str);
1791 ok(hr == S_OK, "got 0x%08x\n", hr);
1792 ok(str == NULL, "got %p\n", str);
1794 /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1795 str = NULL;
1796 hr = ITextStream_Read(stream, 2, &str);
1797 ok(hr == S_OK, "got 0x%08x\n", hr);
1799 buffW[0] = 0;
1800 MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1802 ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1803 ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str));
1804 SysFreeString(str);
1805 ITextStream_Release(stream);
1807 /* Unicode file -> read with unicode stream */
1808 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1809 ok(hr == S_OK, "got 0x%08x\n", hr);
1811 lstrcpyW(buffW, nameW);
1812 lstrcatW(buffW, L"\r\n");
1813 lstrcatW(buffW, secondlineW);
1814 lstrcatW(buffW, L"\r\n");
1815 str = NULL;
1816 hr = ITextStream_Read(stream, 500, &str);
1817 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1818 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1819 SysFreeString(str);
1821 /* ReadAll one more time */
1822 str = (void*)0xdeadbeef;
1823 hr = ITextStream_Read(stream, 10, &str);
1824 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1825 ok(str == NULL, "got %p\n", str);
1827 /* ReadLine fails the same way */
1828 str = (void*)0xdeadbeef;
1829 hr = ITextStream_ReadLine(stream, &str);
1830 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1831 ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str);
1832 ITextStream_Release(stream);
1834 /* Open again and skip first line before ReadAll */
1835 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1836 ok(hr == S_OK, "got 0x%08x\n", hr);
1838 str = NULL;
1839 hr = ITextStream_ReadLine(stream, &str);
1840 ok(hr == S_OK, "got 0x%08x\n", hr);
1841 ok(str != NULL, "got %p\n", str);
1842 SysFreeString(str);
1844 lstrcpyW(buffW, secondlineW);
1845 lstrcatW(buffW, L"\r\n");
1846 str = NULL;
1847 hr = ITextStream_Read(stream, 100, &str);
1848 ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1849 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1850 SysFreeString(str);
1851 ITextStream_Release(stream);
1853 /* default read will use Unicode */
1854 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateUseDefault, &stream);
1855 ok(hr == S_OK, "got 0x%08x\n", hr);
1857 lstrcpyW(buffW, nameW);
1858 lstrcatW(buffW, L"\r\n");
1859 lstrcatW(buffW, secondlineW);
1860 lstrcatW(buffW, L"\r\n");
1861 str = NULL;
1862 hr = ITextStream_Read(stream, 500, &str);
1863 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1864 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1865 SysFreeString(str);
1867 ITextStream_Release(stream);
1869 /* default append will use Unicode */
1870 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForAppending, VARIANT_FALSE, TristateUseDefault, &stream);
1871 ok(hr == S_OK, "got 0x%08x\n", hr);
1873 str = SysAllocString(L"123");
1874 hr = ITextStream_Write(stream, str);
1875 ok(hr == S_OK, "got %08x\n", hr);
1876 SysFreeString(str);
1878 ITextStream_Release(stream);
1880 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1881 ok(hr == S_OK, "got 0x%08x\n", hr);
1883 lstrcatW(buffW, L"123");
1884 str = NULL;
1885 hr = ITextStream_Read(stream, 500, &str);
1886 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1887 ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1888 SysFreeString(str);
1890 ITextStream_Release(stream);
1892 /* default write will use ASCII */
1893 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForWriting, VARIANT_FALSE, TristateUseDefault, &stream);
1894 ok(hr == S_OK, "got 0x%08x\n", hr);
1896 str = SysAllocString(L"123");
1897 hr = ITextStream_Write(stream, str);
1898 ok(hr == S_OK, "got %08x\n", hr);
1899 SysFreeString(str);
1901 ITextStream_Release(stream);
1903 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1904 ok(hr == S_OK, "got 0x%08x\n", hr);
1906 str = (void*)0xdeadbeef;
1907 hr = ITextStream_Read(stream, 500, &str);
1908 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1909 ok(!wcscmp(str, L"123"), "got %s\n", wine_dbgstr_w(str));
1911 ITextStream_Release(stream);
1912 /* ASCII file, read with default stream */
1913 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1914 ok(hr == S_OK, "got 0x%08x\n", hr);
1915 str = SysAllocString(L"test");
1916 hr = ITextStream_Write(stream, str);
1917 ok(hr == S_OK, "got 0x%08x\n", hr);
1918 SysFreeString(str);
1919 ITextStream_Release(stream);
1921 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateUseDefault, &stream);
1922 ok(hr == S_OK, "got 0x%08x\n", hr);
1924 str = (void*)0xdeadbeef;
1925 hr = ITextStream_Read(stream, 500, &str);
1926 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1927 ok(!wcscmp(str, L"test"), "got %s\n", wine_dbgstr_w(str));
1929 ITextStream_Release(stream);
1931 /* default append will use Unicode */
1932 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForAppending, VARIANT_FALSE, TristateUseDefault, &stream);
1933 ok(hr == S_OK, "got 0x%08x\n", hr);
1935 str = SysAllocString(L"123");
1936 hr = ITextStream_Write(stream, str);
1937 ok(hr == S_OK, "got %08x\n", hr);
1938 SysFreeString(str);
1940 ITextStream_Release(stream);
1942 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1943 ok(hr == S_OK, "got 0x%08x\n", hr);
1945 str = NULL;
1946 hr = ITextStream_Read(stream, 500, &str);
1947 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1948 ok(!lstrcmpW(L"test123", str), "got %s\n", wine_dbgstr_w(str));
1949 SysFreeString(str);
1951 ITextStream_Release(stream);
1953 /* default write will use ASCII as well */
1954 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForWriting, VARIANT_FALSE, TristateUseDefault, &stream);
1955 ok(hr == S_OK, "got 0x%08x\n", hr);
1957 str = SysAllocString(L"test string");
1958 hr = ITextStream_Write(stream, str);
1959 ok(hr == S_OK, "got %08x\n", hr);
1960 SysFreeString(str);
1962 ITextStream_Release(stream);
1964 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1965 ok(hr == S_OK, "got 0x%08x\n", hr);
1967 str = (void*)0xdeadbeef;
1968 hr = ITextStream_Read(stream, 500, &str);
1969 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
1970 ok(!wcscmp(str, L"test string"), "got %s\n", wine_dbgstr_w(str));
1972 ITextStream_Release(stream);
1974 /* ASCII file, read with Unicode stream */
1975 /* 1. one byte content, not enough for Unicode read */
1976 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1977 ok(hr == S_OK, "got 0x%08x\n", hr);
1978 str = SysAllocString(L"A");
1979 hr = ITextStream_Write(stream, str);
1980 ok(hr == S_OK, "got 0x%08x\n", hr);
1981 SysFreeString(str);
1982 ITextStream_Release(stream);
1984 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1985 ok(hr == S_OK, "got 0x%08x\n", hr);
1987 str = (void*)0xdeadbeef;
1988 hr = ITextStream_Read(stream, 500, &str);
1989 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1990 ok(str == NULL, "got %p\n", str);
1992 ITextStream_Release(stream);
1994 /* ASCII file, read with Unicode stream */
1995 /* 3. one byte content, 2 are interpreted as a character, 3rd is lost */
1996 hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1997 ok(hr == S_OK, "got 0x%08x\n", hr);
1998 str = SysAllocString(L"abc");
1999 hr = ITextStream_Write(stream, str);
2000 ok(hr == S_OK, "got 0x%08x\n", hr);
2001 SysFreeString(str);
2002 ITextStream_Release(stream);
2004 hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
2005 ok(hr == S_OK, "got 0x%08x\n", hr);
2007 str = NULL;
2008 hr = ITextStream_Read(stream, 500, &str);
2009 ok(hr == S_FALSE || broken(hr == S_OK) /* win2003 */, "got 0x%08x\n", hr);
2010 ok(SysStringLen(str) == 1, "len = %u\n", SysStringLen(str));
2011 SysFreeString(str);
2013 str = (void*)0xdeadbeef;
2014 hr = ITextStream_Read(stream, 500, &str);
2015 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
2016 ok(str == NULL, "got %p\n", str);
2018 ITextStream_Release(stream);
2020 DeleteFileW(nameW);
2021 RemoveDirectoryW(dirW);
2022 SysFreeString(nameW);
2025 static void test_ReadLine(void)
2027 WCHAR path[MAX_PATH], dir[MAX_PATH];
2028 ITextStream *stream;
2029 unsigned int i;
2030 HANDLE file;
2031 DWORD size;
2032 HRESULT hr;
2033 BSTR str;
2034 BOOL ret;
2036 const char data[] = "first line\r\nsecond\n\n\rt\r\re \rst\n";
2038 get_temp_filepath(L"test.txt", path, dir);
2040 ret = CreateDirectoryW(dir, NULL);
2041 ok(ret, "got %d, %d\n", ret, GetLastError());
2043 file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
2044 FILE_ATTRIBUTE_NORMAL, NULL);
2045 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
2047 for (i = 0; i < 1000; i++)
2048 WriteFile(file, data, strlen(data), &size, NULL);
2049 CloseHandle(file);
2051 str = SysAllocString(path);
2052 hr = IFileSystem3_OpenTextFile(fs3, str, ForReading, VARIANT_FALSE, TristateFalse, &stream);
2053 ok(hr == S_OK, "got 0x%08x\n", hr);
2054 SysFreeString(str);
2056 for (i = 0; i < 1000; i++)
2058 hr = ITextStream_ReadLine(stream, &str);
2059 ok(hr == S_OK, "ReadLine failed: %08x\n", hr);
2060 ok(!wcscmp(str, L"first line"), "ReadLine returned %s\n", wine_dbgstr_w(str));
2061 SysFreeString(str);
2063 hr = ITextStream_ReadLine(stream, &str);
2064 ok(hr == S_OK, "ReadLine failed: %08x\n", hr);
2065 ok(!wcscmp(str, L"second"), "ReadLine returned %s\n", wine_dbgstr_w(str));
2066 SysFreeString(str);
2068 hr = ITextStream_ReadLine(stream, &str);
2069 ok(hr == S_OK, "ReadLine failed: %08x\n", hr);
2070 ok(!*str, "ReadLine returned %s\n", wine_dbgstr_w(str));
2071 SysFreeString(str);
2073 hr = ITextStream_ReadLine(stream, &str);
2074 ok(hr == S_OK, "ReadLine failed: %08x\n", hr);
2075 ok(!wcscmp(str, L"\rt\r\re \rst"), "ReadLine returned %s\n", wine_dbgstr_w(str));
2076 SysFreeString(str);
2079 str = NULL;
2080 hr = ITextStream_ReadLine(stream, &str);
2081 ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
2082 ok(!str, "ReadLine returned %s\n", wine_dbgstr_w(str));
2083 SysFreeString(str);
2085 ITextStream_Release(stream);
2087 ret = DeleteFileW(path);
2088 ok(ret, "DeleteFile failed: %u\n", GetLastError());
2090 ret = RemoveDirectoryW(dir);
2091 ok(ret, "RemoveDirectory failed: %u\n", GetLastError());
2094 struct driveexists_test {
2095 const WCHAR drivespec[10];
2096 const INT drivetype;
2097 const VARIANT_BOOL expected_ret;
2100 /* If 'drivetype' != -1, the first character of 'drivespec' will be replaced
2101 * with the drive letter of a drive of this type. If such a drive does not exist,
2102 * the test will be skipped. */
2103 static const struct driveexists_test driveexiststestdata[] = {
2104 { L"N:\\", DRIVE_NO_ROOT_DIR, VARIANT_FALSE },
2105 { L"R:\\", DRIVE_REMOVABLE, VARIANT_TRUE },
2106 { L"F:\\", DRIVE_FIXED, VARIANT_TRUE },
2107 { L"F:", DRIVE_FIXED, VARIANT_TRUE },
2108 { L"F?", DRIVE_FIXED, VARIANT_FALSE },
2109 { L"F", DRIVE_FIXED, VARIANT_TRUE },
2110 { L"?", -1, VARIANT_FALSE },
2111 { L"" }
2114 static void test_DriveExists(void)
2116 const struct driveexists_test *ptr = driveexiststestdata;
2117 HRESULT hr;
2118 VARIANT_BOOL ret;
2119 BSTR drivespec;
2120 WCHAR root[] = L"?:\\";
2122 hr = IFileSystem3_DriveExists(fs3, NULL, NULL);
2123 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2125 ret = VARIANT_TRUE;
2126 hr = IFileSystem3_DriveExists(fs3, NULL, &ret);
2127 ok(hr == S_OK, "got 0x%08x\n", hr);
2128 ok(ret == VARIANT_FALSE, "got %x\n", ret);
2130 drivespec = SysAllocString(root);
2131 hr = IFileSystem3_DriveExists(fs3, drivespec, NULL);
2132 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2133 SysFreeString(drivespec);
2135 for (; *ptr->drivespec; ptr++) {
2136 drivespec = SysAllocString(ptr->drivespec);
2137 if (ptr->drivetype != -1) {
2138 for (root[0] = 'A'; root[0] <= 'Z'; root[0]++)
2139 if (GetDriveTypeW(root) == ptr->drivetype)
2140 break;
2141 if (root[0] > 'Z') {
2142 skip("No drive with type 0x%x found, skipping test %s.\n",
2143 ptr->drivetype, wine_dbgstr_w(ptr->drivespec));
2144 SysFreeString(drivespec);
2145 continue;
2148 /* Test both upper and lower case drive letters. */
2149 drivespec[0] = root[0];
2150 ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE;
2151 hr = IFileSystem3_DriveExists(fs3, drivespec, &ret);
2152 ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n",
2153 hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
2154 ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n",
2155 ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
2157 drivespec[0] = tolower(root[0]);
2160 ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE;
2161 hr = IFileSystem3_DriveExists(fs3, drivespec, &ret);
2162 ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n",
2163 hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
2164 ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n",
2165 ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
2167 SysFreeString(drivespec);
2171 struct getdrivename_test {
2172 const WCHAR path[10];
2173 const WCHAR drive[5];
2176 static const struct getdrivename_test getdrivenametestdata[] = {
2177 { L"C:\\1.tst", L"C:" },
2178 { L"O:\\1.tst", L"O:" },
2179 { L"O:", L"O:" },
2180 { L"o:", L"o:" },
2181 { L"OO:" },
2182 { L":" },
2183 { L"O" },
2184 { L"" }
2187 static void test_GetDriveName(void)
2189 const struct getdrivename_test *ptr = getdrivenametestdata;
2190 HRESULT hr;
2191 BSTR name;
2193 hr = IFileSystem3_GetDriveName(fs3, NULL, NULL);
2194 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2196 name = (void*)0xdeadbeef;
2197 hr = IFileSystem3_GetDriveName(fs3, NULL, &name);
2198 ok(hr == S_OK, "got 0x%08x\n", hr);
2199 ok(name == NULL, "got %p\n", name);
2201 while (*ptr->path) {
2202 BSTR path = SysAllocString(ptr->path);
2203 name = (void*)0xdeadbeef;
2204 hr = IFileSystem3_GetDriveName(fs3, path, &name);
2205 ok(hr == S_OK, "got 0x%08x\n", hr);
2206 if (name)
2207 ok(!lstrcmpW(ptr->drive, name), "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive));
2208 else
2209 ok(!*ptr->drive, "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive));
2210 SysFreeString(path);
2211 SysFreeString(name);
2212 ptr++;
2216 struct getdrive_test {
2217 const WCHAR drivespec[12];
2218 HRESULT res;
2219 const WCHAR driveletter[2];
2222 static void test_GetDrive(void)
2224 HRESULT hr;
2225 IDrive *drive_fixed, *drive;
2226 BSTR dl_fixed, drivespec;
2227 WCHAR root[] = L"?:\\";
2229 drive = (void*)0xdeadbeef;
2230 hr = IFileSystem3_GetDrive(fs3, NULL, NULL);
2231 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2232 ok(drive == (void*)0xdeadbeef, "got %p\n", drive);
2234 for (root[0] = 'A'; root[0] <= 'Z'; root[0]++)
2235 if (GetDriveTypeW(root) == DRIVE_NO_ROOT_DIR)
2236 break;
2238 if (root[0] > 'Z')
2239 skip("All drive letters are occupied, skipping test for nonexisting drive.\n");
2240 else {
2241 drivespec = SysAllocString(root);
2242 drive = (void*)0xdeadbeef;
2243 hr = IFileSystem3_GetDrive(fs3, drivespec, &drive);
2244 ok(hr == CTL_E_DEVICEUNAVAILABLE, "got 0x%08x\n", hr);
2245 ok(drive == NULL, "got %p\n", drive);
2246 SysFreeString(drivespec);
2249 drive_fixed = get_fixed_drive();
2250 if (!drive_fixed) {
2251 skip("No fixed drive found, skipping test.\n");
2252 return;
2255 hr = IDrive_get_DriveLetter(drive_fixed, &dl_fixed);
2256 ok(hr == S_OK, "got 0x%08x\n", hr);
2258 if (FAILED(hr))
2259 skip("Could not retrieve drive letter of fixed drive, skipping test.\n");
2260 else {
2261 WCHAR dl_upper = toupper(dl_fixed[0]);
2262 WCHAR dl_lower = tolower(dl_fixed[0]);
2263 struct getdrive_test testdata[] = {
2264 { {dl_upper,0}, S_OK, {dl_upper,0} },
2265 { {dl_upper,':',0}, S_OK, {dl_upper,0} },
2266 { {dl_upper,':','\\',0}, S_OK, {dl_upper,0} },
2267 { {dl_lower,':','\\',0}, S_OK, {dl_upper,0} },
2268 { {dl_upper,'\\',0 }, E_INVALIDARG, L""},
2269 { {dl_lower,'\\',0 }, E_INVALIDARG, L""},
2270 { L"$:\\", E_INVALIDARG, L"" },
2271 { L"\\host\\share", E_INVALIDARG, L"" },
2272 { L"host\\share", E_INVALIDARG, L"" },
2273 { L"" },
2275 struct getdrive_test *ptr = &testdata[0];
2277 for (; *ptr->drivespec; ptr++) {
2278 drivespec = SysAllocString(ptr->drivespec);
2279 drive = (void*)0xdeadbeef;
2280 hr = IFileSystem3_GetDrive(fs3, drivespec, &drive);
2281 ok(hr == ptr->res, "got 0x%08x, expected 0x%08x for drive spec %s\n",
2282 hr, ptr->res, wine_dbgstr_w(ptr->drivespec));
2283 ok(!lstrcmpW(ptr->drivespec, drivespec), "GetDrive modified its DriveSpec argument\n");
2284 SysFreeString(drivespec);
2286 if (*ptr->driveletter) {
2287 BSTR driveletter;
2288 hr = IDrive_get_DriveLetter(drive, &driveletter);
2289 ok(hr == S_OK, "got 0x%08x for drive spec %s\n", hr, wine_dbgstr_w(ptr->drivespec));
2290 if (SUCCEEDED(hr)) {
2291 ok(!lstrcmpW(ptr->driveletter, driveletter), "got %s, expected %s for drive spec %s\n",
2292 wine_dbgstr_w(driveletter), wine_dbgstr_w(ptr->driveletter),
2293 wine_dbgstr_w(ptr->drivespec));
2294 SysFreeString(driveletter);
2296 test_provideclassinfo(drive, &CLSID_Drive);
2297 IDrive_Release(drive);
2298 } else
2299 ok(drive == NULL, "got %p for drive spec %s\n", drive, wine_dbgstr_w(ptr->drivespec));
2301 SysFreeString(dl_fixed);
2305 static void test_SerialNumber(void)
2307 IDrive *drive;
2308 LONG serial;
2309 HRESULT hr;
2310 BSTR name;
2312 drive = get_fixed_drive();
2313 if (!drive) {
2314 skip("No fixed drive found, skipping test.\n");
2315 return;
2318 hr = IDrive_get_SerialNumber(drive, NULL);
2319 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2321 serial = 0xdeadbeef;
2322 hr = IDrive_get_SerialNumber(drive, &serial);
2323 ok(hr == S_OK, "got 0x%08x\n", hr);
2324 ok(serial != 0xdeadbeef, "got %x\n", serial);
2326 hr = IDrive_get_FileSystem(drive, NULL);
2327 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2329 name = NULL;
2330 hr = IDrive_get_FileSystem(drive, &name);
2331 ok(hr == S_OK, "got 0x%08x\n", hr);
2332 ok(name != NULL, "got %p\n", name);
2333 SysFreeString(name);
2335 hr = IDrive_get_VolumeName(drive, NULL);
2336 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2338 name = NULL;
2339 hr = IDrive_get_VolumeName(drive, &name);
2340 ok(hr == S_OK, "got 0x%08x\n", hr);
2341 ok(name != NULL, "got %p\n", name);
2342 SysFreeString(name);
2344 IDrive_Release(drive);
2347 static const struct extension_test {
2348 WCHAR path[20];
2349 WCHAR ext[10];
2350 } extension_tests[] = {
2351 { L"noext", L"" },
2352 { L"n.o.ext", L"ext" },
2353 { L"n.o.eXt", L"eXt" },
2354 { L"" }
2357 static void test_GetExtensionName(void)
2359 BSTR path, ext;
2360 HRESULT hr;
2361 int i;
2363 for (i = 0; i < ARRAY_SIZE(extension_tests); i++) {
2365 path = SysAllocString(extension_tests[i].path);
2366 ext = NULL;
2367 hr = IFileSystem3_GetExtensionName(fs3, path, &ext);
2368 ok(hr == S_OK, "got 0x%08x\n", hr);
2369 if (*extension_tests[i].ext)
2370 ok(!lstrcmpW(ext, extension_tests[i].ext), "%d: path %s, got %s, expected %s\n", i,
2371 wine_dbgstr_w(path), wine_dbgstr_w(ext), wine_dbgstr_w(extension_tests[i].ext));
2372 else
2373 ok(ext == NULL, "%d: path %s, got %s, expected %s\n", i,
2374 wine_dbgstr_w(path), wine_dbgstr_w(ext), wine_dbgstr_w(extension_tests[i].ext));
2376 SysFreeString(path);
2377 SysFreeString(ext);
2381 static void test_GetSpecialFolder(void)
2383 WCHAR pathW[MAX_PATH];
2384 IFolder *folder;
2385 HRESULT hr;
2386 DWORD ret;
2387 BSTR path;
2389 hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, NULL);
2390 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2392 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, NULL);
2393 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2395 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, &folder);
2396 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2398 hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, &folder);
2399 ok(hr == S_OK, "got 0x%08x\n", hr);
2400 hr = IFolder_get_Path(folder, &path);
2401 ok(hr == S_OK, "got 0x%08x\n", hr);
2402 GetWindowsDirectoryW(pathW, ARRAY_SIZE(pathW));
2403 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2404 SysFreeString(path);
2405 IFolder_Release(folder);
2407 hr = IFileSystem3_GetSpecialFolder(fs3, SystemFolder, &folder);
2408 ok(hr == S_OK, "got 0x%08x\n", hr);
2409 hr = IFolder_get_Path(folder, &path);
2410 ok(hr == S_OK, "got 0x%08x\n", hr);
2411 GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW));
2412 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2413 SysFreeString(path);
2414 IFolder_Release(folder);
2416 hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder, &folder);
2417 ok(hr == S_OK, "got 0x%08x\n", hr);
2418 hr = IFolder_get_Path(folder, &path);
2419 ok(hr == S_OK, "got 0x%08x\n", hr);
2420 ret = GetTempPathW(ARRAY_SIZE(pathW), pathW);
2421 if (ret && pathW[ret-1] == '\\')
2422 pathW[ret-1] = 0;
2424 ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2425 SysFreeString(path);
2426 IFolder_Release(folder);
2429 static void test_MoveFile(void)
2431 ITextStream *stream;
2432 BSTR str, src, dst;
2433 HRESULT hr;
2435 str = SysAllocString(L"test.txt");
2436 hr = IFileSystem3_CreateTextFile(fs3, str, VARIANT_FALSE, VARIANT_FALSE, &stream);
2437 ok(hr == S_OK, "got 0x%08x\n", hr);
2438 SysFreeString(str);
2440 str = SysAllocString(L"test");
2441 hr = ITextStream_Write(stream, str);
2442 ok(hr == S_OK, "Write failed: %08x\n", hr);
2443 SysFreeString(str);
2445 ITextStream_Release(stream);
2447 str = SysAllocString(L"test2.txt");
2448 hr = IFileSystem3_CreateTextFile(fs3, str, VARIANT_FALSE, VARIANT_FALSE, &stream);
2449 ok(hr == S_OK, "got 0x%08x\n", hr);
2450 SysFreeString(str);
2451 ITextStream_Release(stream);
2453 src = SysAllocString(L"test.txt");
2454 dst = SysAllocString(L"test3.txt");
2455 hr = IFileSystem3_MoveFile(fs3, src, dst);
2456 ok(hr == S_OK, "got 0x%08x\n", hr);
2457 SysFreeString(src);
2458 SysFreeString(dst);
2460 str = SysAllocString(L"test.txt");
2461 hr = IFileSystem3_DeleteFile(fs3, str, VARIANT_TRUE);
2462 ok(hr == CTL_E_FILENOTFOUND, "DeleteFile returned %x, expected CTL_E_FILENOTFOUND\n", hr);
2463 SysFreeString(str);
2465 src = SysAllocString(L"test3.txt");
2466 dst = SysAllocString(L"test2.txt"); /* already exists */
2467 hr = IFileSystem3_MoveFile(fs3, src, dst);
2468 ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x, expected CTL_E_FILEALREADYEXISTS\n", hr);
2469 SysFreeString(src);
2470 SysFreeString(dst);
2472 src = SysAllocString(L"nonexistent.txt");
2473 dst = SysAllocString(L"test4.txt");
2474 hr = IFileSystem3_MoveFile(fs3, src, dst);
2475 ok(hr == CTL_E_FILENOTFOUND, "got 0x%08x, expected CTL_E_FILENOTFOUND\n", hr);
2476 SysFreeString(src);
2477 SysFreeString(dst);
2479 str = SysAllocString(L"test3.txt");
2480 hr = IFileSystem3_DeleteFile(fs3, str, VARIANT_TRUE);
2481 ok(hr == S_OK, "got 0x%08x\n", hr);
2482 SysFreeString(str);
2484 str = SysAllocString(L"test2.txt");
2485 hr = IFileSystem3_DeleteFile(fs3, str, VARIANT_TRUE);
2486 ok(hr == S_OK, "got 0x%08x\n", hr);
2487 SysFreeString(str);
2490 START_TEST(filesystem)
2492 HRESULT hr;
2494 CoInitialize(NULL);
2496 hr = CoCreateInstance(&CLSID_FileSystemObject, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2497 &IID_IFileSystem3, (void**)&fs3);
2498 if(FAILED(hr)) {
2499 win_skip("Could not create FileSystem object: %08x\n", hr);
2500 return;
2503 test_interfaces();
2504 test_createfolder();
2505 test_textstream();
2506 test_GetFileVersion();
2507 test_GetParentFolderName();
2508 test_GetFileName();
2509 test_GetBaseName();
2510 test_GetAbsolutePathName();
2511 test_GetFile();
2512 test_CopyFolder();
2513 test_BuildPath();
2514 test_GetFolder();
2515 test_FolderCollection();
2516 test_FileCollection();
2517 test_DriveCollection();
2518 test_CreateTextFile();
2519 test_WriteLine();
2520 test_ReadAll();
2521 test_Read();
2522 test_ReadLine();
2523 test_DriveExists();
2524 test_GetDriveName();
2525 test_GetDrive();
2526 test_SerialNumber();
2527 test_GetExtensionName();
2528 test_GetSpecialFolder();
2529 test_MoveFile();
2531 IFileSystem3_Release(fs3);
2533 CoUninitialize();