ReactOS  0.4.13-dev-39-g8b6696f
filesystem.c
Go to the documentation of this file.
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 
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 
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);
61 }
62 
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) {
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__)
105 static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line)
106 {
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),
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 
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;
146  VARIANT_BOOL b;
147  BSTR path;
148  WCHAR windows_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);
179 
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);
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);
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");
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");
209 
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");
215 
216  IDispatch_Release(disp);
217 }
218 
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);
238  RemoveDirectoryW(buffW);
239 }
240 
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 
252  CloseHandle(file);
253 
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 */
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 
368 }
369 
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 
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));
389 
390  lstrcpyW(filenameW, pathW);
391  lstrcatW(filenameW, k33W);
392 
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));
401  }
402  else
403  ok(version == (void*)0xdeadbeef, "got %p\n", version);
405 }
406 
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));
452  }
453 }
454 
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));
495  }
496 }
497 
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));
541  }
542 }
543 
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));
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));
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);
585  ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
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",
595  }else {
597  ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n",
599  }
601 
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));
610 
611  RemoveDirectoryW(dir1);
612  RemoveDirectoryW(dir2);
613 }
614 
615 static void test_GetFile(void)
616 {
617  static const WCHAR slW[] = {'\\',0};
618  BSTR path, str;
619  WCHAR pathW[MAX_PATH];
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 
643  if(hf == INVALID_HANDLE_VALUE) {
644  skip("Can't create temporary file\n");
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));
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);
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 
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);
723 
724  RemoveDirectoryW(pathW);
725 }
726 
727 static inline BOOL create_file(const WCHAR *name)
728 {
730  CloseHandle(f);
731  return f != INVALID_HANDLE_VALUE;
732 }
733 
734 static inline void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret)
735 {
737  memmove(ret, folder, len*sizeof(WCHAR));
738  ret[len] = '\\';
739  memmove(ret+len+1, name, (lstrlenW(name)+1)*sizeof(WCHAR));
740 }
741 
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);
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);
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);
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 
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 
860 {
861  const char *path;
862  const char *name;
863  const char *result;
864 };
865 
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 
882 static void test_BuildPath(void)
883 {
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);
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));
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));
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),
929  }
933 
934  i++;
935  ptr++;
936  }
937 }
938 
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 */
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);
966 
968  str = SysAllocString(buffW);
969  hr = IFileSystem3_GetFolder(fs3, str, &folder);
970  ok(hr == S_OK, "got 0x%08x\n", hr);
972  test_provideclassinfo(folder, &CLSID_Folder);
973  IFolder_Release(folder);
974 }
975 
976 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
977 static void test_FolderCollection(void)
978 {
979  static const WCHAR fooW[] = {'f','o','o',0};
980  static const WCHAR aW[] = {'\\','a',0};
981  static const WCHAR bW[] = {'\\','b',0};
982  static const WCHAR cW[] = {'\\','c',0};
983  IFolderCollection *folders;
984  WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
985  IEnumVARIANT *enumvar, *clone;
986  LONG count, ref, ref2, i;
987  IUnknown *unk, *unk2;
988  IFolder *folder;
989  ULONG fetched;
990  VARIANT var, var2[2];
991  HRESULT hr;
992  BSTR str;
993  int found_a = 0, found_b = 0, found_c = 0;
994 
995  get_temp_path(fooW, buffW);
996  CreateDirectoryW(buffW, NULL);
997 
998  str = SysAllocString(buffW);
999  hr = IFileSystem3_GetFolder(fs3, str, &folder);
1000  ok(hr == S_OK, "got 0x%08x\n", hr);
1001  SysFreeString(str);
1002 
1003  hr = IFolder_get_SubFolders(folder, NULL);
1004  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1005 
1006  hr = IFolder_get_Path(folder, NULL);
1007  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1008 
1009  hr = IFolder_get_Path(folder, &str);
1010  ok(hr == S_OK, "got 0x%08x\n", hr);
1011  ok(!lstrcmpiW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1012  SysFreeString(str);
1013 
1014  lstrcpyW(pathW, buffW);
1015  lstrcatW(pathW, aW);
1016  CreateDirectoryW(pathW, NULL);
1017 
1018  lstrcpyW(pathW, buffW);
1019  lstrcatW(pathW, bW);
1020  CreateDirectoryW(pathW, NULL);
1021 
1022  hr = IFolder_get_SubFolders(folder, &folders);
1023  ok(hr == S_OK, "got 0x%08x\n", hr);
1024  test_provideclassinfo(folders, &CLSID_Folders);
1025  IFolder_Release(folder);
1026 
1027  count = 0;
1028  hr = IFolderCollection_get_Count(folders, &count);
1029  ok(hr == S_OK, "got 0x%08x\n", hr);
1030  ok(count == 2, "got %d\n", count);
1031 
1032  lstrcpyW(pathW, buffW);
1033  lstrcatW(pathW, cW);
1034  CreateDirectoryW(pathW, NULL);
1035 
1036  /* every time property is requested it scans directory */
1037  count = 0;
1038  hr = IFolderCollection_get_Count(folders, &count);
1039  ok(hr == S_OK, "got 0x%08x\n", hr);
1040  ok(count == 3, "got %d\n", count);
1041 
1042  hr = IFolderCollection_get__NewEnum(folders, NULL);
1043  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1044 
1045  hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk);
1046  ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1047 
1048  /* NewEnum creates new instance each time it's called */
1049  ref = GET_REFCOUNT(folders);
1050 
1051  unk = NULL;
1052  hr = IFolderCollection_get__NewEnum(folders, &unk);
1053  ok(hr == S_OK, "got 0x%08x\n", hr);
1054 
1055  ref2 = GET_REFCOUNT(folders);
1056  ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1057 
1058  unk2 = NULL;
1059  hr = IFolderCollection_get__NewEnum(folders, &unk2);
1060  ok(hr == S_OK, "got 0x%08x\n", hr);
1061  ok(unk != unk2, "got %p, %p\n", unk2, unk);
1062  IUnknown_Release(unk2);
1063 
1064  /* now get IEnumVARIANT */
1065  ref = GET_REFCOUNT(folders);
1066  hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1067  ok(hr == S_OK, "got 0x%08x\n", hr);
1068  ref2 = GET_REFCOUNT(folders);
1069  ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1070 
1071  /* clone enumerator */
1072  hr = IEnumVARIANT_Clone(enumvar, &clone);
1073  ok(hr == S_OK, "got 0x%08x\n", hr);
1074  ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
1075  IEnumVARIANT_Release(clone);
1076 
1077  hr = IEnumVARIANT_Reset(enumvar);
1078  ok(hr == S_OK, "got 0x%08x\n", hr);
1079 
1080  for (i = 0; i < 3; i++)
1081  {
1082  VariantInit(&var);
1083  fetched = 0;
1084  hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1085  ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1086  ok(fetched == 1, "%d: got %d\n", i, fetched);
1087  ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1088 
1089  hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder);
1090  ok(hr == S_OK, "got 0x%08x\n", hr);
1091 
1092  str = NULL;
1093  hr = IFolder_get_Name(folder, &str);
1094  ok(hr == S_OK, "got 0x%08x\n", hr);
1095  if (!lstrcmpW(str, aW + 1))
1096  found_a++;
1097  else if (!lstrcmpW(str, bW + 1))
1098  found_b++;
1099  else if (!lstrcmpW(str, cW + 1))
1100  found_c++;
1101  else
1102  ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str));
1103  SysFreeString(str);
1104 
1105  IFolder_Release(folder);
1106  VariantClear(&var);
1107  }
1108 
1109  ok(found_a == 1 && found_b == 1 && found_c == 1,
1110  "each folder should be found 1 time instead of %d/%d/%d\n",
1111  found_a, found_b, found_c);
1112 
1113  VariantInit(&var);
1114  fetched = -1;
1115  hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1116  ok(hr == S_FALSE, "got 0x%08x\n", hr);
1117  ok(fetched == 0, "got %d\n", fetched);
1118 
1119  hr = IEnumVARIANT_Reset(enumvar);
1120  ok(hr == S_OK, "got 0x%08x\n", hr);
1121  hr = IEnumVARIANT_Skip(enumvar, 2);
1122  ok(hr == S_OK, "got 0x%08x\n", hr);
1123  hr = IEnumVARIANT_Skip(enumvar, 0);
1124  ok(hr == S_OK, "got 0x%08x\n", hr);
1125 
1126  VariantInit(&var2[0]);
1127  VariantInit(&var2[1]);
1128  fetched = -1;
1129  hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1130  ok(hr == S_OK, "got 0x%08x\n", hr);
1131  ok(fetched == 0, "got %d\n", fetched);
1132  fetched = -1;
1133  hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1134  ok(hr == S_FALSE, "got 0x%08x\n", hr);
1135  ok(fetched == 1, "got %d\n", fetched);
1136  ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1137  VariantClear(&var2[0]);
1138  VariantClear(&var2[1]);
1139 
1140  IEnumVARIANT_Release(enumvar);
1141  IUnknown_Release(unk);
1142 
1143  lstrcpyW(pathW, buffW);
1144  lstrcatW(pathW, aW);
1145  RemoveDirectoryW(pathW);
1146  lstrcpyW(pathW, buffW);
1147  lstrcatW(pathW, bW);
1148  RemoveDirectoryW(pathW);
1149  lstrcpyW(pathW, buffW);
1150  lstrcatW(pathW, cW);
1151  RemoveDirectoryW(pathW);
1152  RemoveDirectoryW(buffW);
1153 
1154  IFolderCollection_Release(folders);
1155 }
1156 
1157 /* Please keep the tests for IFolderCollection and IFileCollection in sync */
1158 static void test_FileCollection(void)
1159 {
1160  static const WCHAR fooW[] = {'\\','f','o','o',0};
1161  static const WCHAR aW[] = {'\\','a',0};
1162  static const WCHAR bW[] = {'\\','b',0};
1163  static const WCHAR cW[] = {'\\','c',0};
1164  WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
1165  IFolder *folder;
1166  IFileCollection *files;
1167  IFile *file;
1168  IEnumVARIANT *enumvar, *clone;
1169  LONG count, ref, ref2, i;
1170  IUnknown *unk, *unk2;
1171  ULONG fetched;
1172  VARIANT var, var2[2];
1173  HRESULT hr;
1174  BSTR str;
1175  HANDLE file_a, file_b, file_c;
1176  int found_a = 0, found_b = 0, found_c = 0;
1177 
1178  get_temp_path(fooW, buffW);
1179  CreateDirectoryW(buffW, NULL);
1180 
1181  str = SysAllocString(buffW);
1182  hr = IFileSystem3_GetFolder(fs3, str, &folder);
1183  ok(hr == S_OK, "got 0x%08x\n", hr);
1184  SysFreeString(str);
1185 
1186  hr = IFolder_get_Files(folder, NULL);
1187  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1188 
1189  lstrcpyW(pathW, buffW);
1190  lstrcatW(pathW, aW);
1191  file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1193  lstrcpyW(pathW, buffW);
1194  lstrcatW(pathW, bW);
1195  file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1197 
1198  hr = IFolder_get_Files(folder, &files);
1199  ok(hr == S_OK, "got 0x%08x\n", hr);
1200  test_provideclassinfo(files, &CLSID_Files);
1201  IFolder_Release(folder);
1202 
1203  count = 0;
1204  hr = IFileCollection_get_Count(files, &count);
1205  ok(hr == S_OK, "got 0x%08x\n", hr);
1206  ok(count == 2, "got %d\n", count);
1207 
1208  lstrcpyW(pathW, buffW);
1209  lstrcatW(pathW, cW);
1210  file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1212 
1213  /* every time property is requested it scans directory */
1214  count = 0;
1215  hr = IFileCollection_get_Count(files, &count);
1216  ok(hr == S_OK, "got 0x%08x\n", hr);
1217  ok(count == 3, "got %d\n", count);
1218 
1219  hr = IFileCollection_get__NewEnum(files, NULL);
1220  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1221 
1222  hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk);
1223  ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
1224 
1225  /* NewEnum creates new instance each time it's called */
1226  ref = GET_REFCOUNT(files);
1227 
1228  unk = NULL;
1229  hr = IFileCollection_get__NewEnum(files, &unk);
1230  ok(hr == S_OK, "got 0x%08x\n", hr);
1231 
1232  ref2 = GET_REFCOUNT(files);
1233  ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
1234 
1235  unk2 = NULL;
1236  hr = IFileCollection_get__NewEnum(files, &unk2);
1237  ok(hr == S_OK, "got 0x%08x\n", hr);
1238  ok(unk != unk2, "got %p, %p\n", unk2, unk);
1239  IUnknown_Release(unk2);
1240 
1241  /* now get IEnumVARIANT */
1242  ref = GET_REFCOUNT(files);
1243  hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
1244  ok(hr == S_OK, "got 0x%08x\n", hr);
1245  ref2 = GET_REFCOUNT(files);
1246  ok(ref2 == ref, "got %d, %d\n", ref2, ref);
1247 
1248  /* clone enumerator */
1249  hr = IEnumVARIANT_Clone(enumvar, &clone);
1250  ok(hr == S_OK, "got 0x%08x\n", hr);
1251  ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
1252  IEnumVARIANT_Release(clone);
1253 
1254  hr = IEnumVARIANT_Reset(enumvar);
1255  ok(hr == S_OK, "got 0x%08x\n", hr);
1256 
1257  for (i = 0; i < 3; i++)
1258  {
1259  VariantInit(&var);
1260  fetched = 0;
1261  hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1262  ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
1263  ok(fetched == 1, "%d: got %d\n", i, fetched);
1264  ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
1265 
1266  hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file);
1267  ok(hr == S_OK, "got 0x%08x\n", hr);
1268  test_provideclassinfo(file, &CLSID_File);
1269 
1270  str = NULL;
1271  hr = IFile_get_Name(file, &str);
1272  ok(hr == S_OK, "got 0x%08x\n", hr);
1273  if (!lstrcmpW(str, aW + 1))
1274  found_a++;
1275  else if (!lstrcmpW(str, bW + 1))
1276  found_b++;
1277  else if (!lstrcmpW(str, cW + 1))
1278  found_c++;
1279  else
1280  ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str));
1281  SysFreeString(str);
1282 
1283  IFile_Release(file);
1284  VariantClear(&var);
1285  }
1286 
1287  ok(found_a == 1 && found_b == 1 && found_c == 1,
1288  "each file should be found 1 time instead of %d/%d/%d\n",
1289  found_a, found_b, found_c);
1290 
1291  VariantInit(&var);
1292  fetched = -1;
1293  hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
1294  ok(hr == S_FALSE, "got 0x%08x\n", hr);
1295  ok(fetched == 0, "got %d\n", fetched);
1296 
1297  hr = IEnumVARIANT_Reset(enumvar);
1298  ok(hr == S_OK, "got 0x%08x\n", hr);
1299  hr = IEnumVARIANT_Skip(enumvar, 2);
1300  ok(hr == S_OK, "got 0x%08x\n", hr);
1301  hr = IEnumVARIANT_Skip(enumvar, 0);
1302  ok(hr == S_OK, "got 0x%08x\n", hr);
1303 
1304  VariantInit(&var2[0]);
1305  VariantInit(&var2[1]);
1306  fetched = -1;
1307  hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
1308  ok(hr == S_OK, "got 0x%08x\n", hr);
1309  ok(fetched == 0, "got %d\n", fetched);
1310  fetched = -1;
1311  hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
1312  ok(hr == S_FALSE, "got 0x%08x\n", hr);
1313  ok(fetched == 1, "got %d\n", fetched);
1314  ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
1315  VariantClear(&var2[0]);
1316  VariantClear(&var2[1]);
1317 
1318  IEnumVARIANT_Release(enumvar);
1319  IUnknown_Release(unk);
1320 
1321  CloseHandle(file_a);
1322  CloseHandle(file_b);
1323  CloseHandle(file_c);
1324  RemoveDirectoryW(buffW);
1325 
1326  IFileCollection_Release(files);
1327 }
1328 
1329 static void test_DriveCollection(void)
1330 {
1331  IDriveCollection *drives;
1333  ULONG fetched;
1334  VARIANT var;
1335  HRESULT hr;
1336  LONG count;
1337 
1338  hr = IFileSystem3_get_Drives(fs3, &drives);
1339  ok(hr == S_OK, "got 0x%08x\n", hr);
1340 
1341  test_provideclassinfo(drives, &CLSID_Drives);
1342 
1343  hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar);
1344  ok(hr == S_OK, "got 0x%08x\n", hr);
1345 
1346  hr = IDriveCollection_get_Count(drives, NULL);
1347  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1348 
1349  count = 0;
1350  hr = IDriveCollection_get_Count(drives, &count);
1351  ok(hr == S_OK, "got 0x%08x\n", hr);
1352  ok(count > 0, "got %d\n", count);
1353 
1354  V_VT(&var) = VT_EMPTY;
1355  fetched = -1;
1356  hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched);
1357  ok(hr == S_OK, "got 0x%08x\n", hr);
1358  ok(fetched == 0, "got %d\n", fetched);
1359 
1360  hr = IEnumVARIANT_Skip(enumvar, 0);
1361  ok(hr == S_OK, "got 0x%08x\n", hr);
1362 
1363  hr = IEnumVARIANT_Skip(enumvar, count);
1364  ok(hr == S_OK, "got 0x%08x\n", hr);
1365 
1366  hr = IEnumVARIANT_Skip(enumvar, 1);
1367  ok(hr == S_FALSE, "got 0x%08x\n", hr);
1368 
1369  /* reset and iterate again */
1370  hr = IEnumVARIANT_Reset(enumvar);
1371  ok(hr == S_OK, "got 0x%08x\n", hr);
1372 
1373  while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) {
1374  IDrive *drive = (IDrive*)V_DISPATCH(&var);
1376  BSTR str;
1377 
1378  hr = IDrive_get_DriveType(drive, &type);
1379  ok(hr == S_OK, "got 0x%08x\n", hr);
1380 
1381  hr = IDrive_get_DriveLetter(drive, NULL);
1382  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1383 
1384  hr = IDrive_get_DriveLetter(drive, &str);
1385  ok(hr == S_OK, "got 0x%08x\n", hr);
1386  ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str));
1387  SysFreeString(str);
1388 
1389  hr = IDrive_get_IsReady(drive, NULL);
1390  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1391 
1392  hr = IDrive_get_TotalSize(drive, NULL);
1393  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1394 
1395  hr = IDrive_get_AvailableSpace(drive, NULL);
1396  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1397 
1398  hr = IDrive_get_FreeSpace(drive, NULL);
1399  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1400 
1401  if (type == Fixed) {
1402  VARIANT_BOOL ready = VARIANT_FALSE;
1403  VARIANT size;
1404 
1405  hr = IDrive_get_IsReady(drive, &ready);
1406  ok(hr == S_OK, "got 0x%08x\n", hr);
1407  ok(ready == VARIANT_TRUE, "got %x\n", ready);
1408 
1409  if (ready != VARIANT_TRUE) {
1410  hr = IDrive_get_DriveLetter(drive, &str);
1411  ok(hr == S_OK, "got 0x%08x\n", hr);
1412 
1413  skip("Drive %s is not ready, skipping some tests\n", wine_dbgstr_w(str));
1414 
1415  VariantClear(&var);
1416  SysFreeString(str);
1417  continue;
1418  }
1419 
1420  V_VT(&size) = VT_EMPTY;
1421  hr = IDrive_get_TotalSize(drive, &size);
1422  ok(hr == S_OK, "got 0x%08x\n", hr);
1423  ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1424  if (V_VT(&size) == VT_R8)
1425  ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1426  else
1427  ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1428 
1429  V_VT(&size) = VT_EMPTY;
1430  hr = IDrive_get_AvailableSpace(drive, &size);
1431  ok(hr == S_OK, "got 0x%08x\n", hr);
1432  ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1433  if (V_VT(&size) == VT_R8)
1434  ok(V_R8(&size) > (double)INT_MAX, "got %f\n", V_R8(&size));
1435  else
1436  ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1437 
1438  V_VT(&size) = VT_EMPTY;
1439  hr = IDrive_get_FreeSpace(drive, &size);
1440  ok(hr == S_OK, "got 0x%08x\n", hr);
1441  ok(V_VT(&size) == VT_R8 || V_VT(&size) == VT_I4, "got %d\n", V_VT(&size));
1442  if (V_VT(&size) == VT_R8)
1443  ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
1444  else
1445  ok(V_I4(&size) > 0, "got %d\n", V_I4(&size));
1446  }
1447  VariantClear(&var);
1448  }
1449 
1450  IEnumVARIANT_Release(enumvar);
1451  IDriveCollection_Release(drives);
1452 }
1453 
1455 {
1456  static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
1457 
1459  lstrcatW(path, scrrunW);
1460  lstrcpyW(dir, path);
1462 }
1463 
1464 static void test_CreateTextFile(void)
1465 {
1466  WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[10];
1467  ITextStream *stream;
1468  BSTR nameW, str;
1469  HANDLE file;
1470  HRESULT hr;
1471  BOOL ret;
1472 
1473  get_temp_filepath(testfileW, pathW, dirW);
1474 
1475  /* dir doesn't exist */
1476  nameW = SysAllocString(pathW);
1477  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1478  ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
1479 
1480  ret = CreateDirectoryW(dirW, NULL);
1481  ok(ret, "got %d, %d\n", ret, GetLastError());
1482 
1483  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1484  ok(hr == S_OK, "got 0x%08x\n", hr);
1485 
1486  test_provideclassinfo(stream, &CLSID_TextStream);
1487 
1488  hr = ITextStream_Read(stream, 1, &str);
1489  ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1490 
1491  hr = ITextStream_Close(stream);
1492  ok(hr == S_OK, "got 0x%08x\n", hr);
1493 
1494  hr = ITextStream_Read(stream, 1, &str);
1495  ok(hr == CTL_E_BADFILEMODE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr);
1496 
1497  hr = ITextStream_Close(stream);
1498  ok(hr == S_FALSE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr);
1499 
1500  ITextStream_Release(stream);
1501 
1502  /* check it's created */
1504  ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1505  CloseHandle(file);
1506 
1507  /* try to create again with no-overwrite mode */
1508  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1509  ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
1510 
1511  /* now overwrite */
1512  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1513  ok(hr == S_OK, "got 0x%08x\n", hr);
1514  ITextStream_Release(stream);
1515 
1516  /* overwrite in Unicode mode, check for BOM */
1517  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
1518  ok(hr == S_OK, "got 0x%08x\n", hr);
1519  ITextStream_Release(stream);
1520 
1521  /* File was created in Unicode mode, it contains 0xfffe BOM. Opening it in non-Unicode mode
1522  treats BOM like a valuable data with appropriate CP_ACP -> WCHAR conversion. */
1523  buffW[0] = 0;
1524  MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1525 
1526  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1527  ok(hr == S_OK, "got 0x%08x\n", hr);
1528  hr = ITextStream_ReadAll(stream, &str);
1529  ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1530  ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1531  SysFreeString(str);
1532  ITextStream_Release(stream);
1533 
1534  DeleteFileW(nameW);
1535  RemoveDirectoryW(dirW);
1537 }
1538 
1539 static void test_WriteLine(void)
1540 {
1541  WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
1542  WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
1543  char buffA[MAX_PATH];
1544  ITextStream *stream;
1545  DWORD r, len;
1546  HANDLE file;
1547  BSTR nameW;
1548  HRESULT hr;
1549  BOOL ret;
1550 
1551  get_temp_filepath(testfileW, pathW, dirW);
1552 
1553  ret = CreateDirectoryW(dirW, NULL);
1554  ok(ret, "got %d, %d\n", ret, GetLastError());
1555 
1556  /* create as ASCII file first */
1557  nameW = SysAllocString(pathW);
1558  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
1559  ok(hr == S_OK, "got 0x%08x\n", hr);
1560 
1561  hr = ITextStream_WriteLine(stream, nameW);
1562  ok(hr == S_OK, "got 0x%08x\n", hr);
1563  ITextStream_Release(stream);
1564 
1565  /* check contents */
1567  ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1568  r = 0;
1569  ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL);
1570  ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1571 
1572  len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, ARRAY_SIZE(buffW));
1573  buffW[len] = 0;
1574  lstrcpyW(buff2W, nameW);
1575  lstrcatW(buff2W, crlfW);
1576  ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1577  CloseHandle(file);
1578  DeleteFileW(nameW);
1579 
1580  /* same for unicode file */
1581  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1582  ok(hr == S_OK, "got 0x%08x\n", hr);
1583 
1584  hr = ITextStream_WriteLine(stream, nameW);
1585  ok(hr == S_OK, "got 0x%08x\n", hr);
1586  ITextStream_Release(stream);
1587 
1588  /* check contents */
1590  ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
1591  r = 0;
1592  ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL);
1593  ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
1594  buffW[r/sizeof(WCHAR)] = 0;
1595 
1596  buff2W[0] = 0xfeff;
1597  buff2W[1] = 0;
1598  lstrcatW(buff2W, nameW);
1599  lstrcatW(buff2W, crlfW);
1600  ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
1601  CloseHandle(file);
1602  DeleteFileW(nameW);
1603 
1604  RemoveDirectoryW(dirW);
1606 }
1607 
1608 static void test_ReadAll(void)
1609 {
1610  static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1611  static const WCHAR aW[] = {'A',0};
1612  WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1613  ITextStream *stream;
1614  BSTR nameW;
1615  HRESULT hr;
1616  BOOL ret;
1617  BSTR str;
1618 
1619  get_temp_filepath(testfileW, pathW, dirW);
1620 
1621  ret = CreateDirectoryW(dirW, NULL);
1622  ok(ret, "got %d, %d\n", ret, GetLastError());
1623 
1624  /* Unicode file -> read with ascii stream */
1625  nameW = SysAllocString(pathW);
1626  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1627  ok(hr == S_OK, "got 0x%08x\n", hr);
1628 
1629  hr = ITextStream_WriteLine(stream, nameW);
1630  ok(hr == S_OK, "got 0x%08x\n", hr);
1631 
1632  str = SysAllocString(secondlineW);
1633  hr = ITextStream_WriteLine(stream, str);
1634  ok(hr == S_OK, "got 0x%08x\n", hr);
1635  SysFreeString(str);
1636 
1637  hr = ITextStream_ReadAll(stream, NULL);
1638  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1639 
1640  str = (void*)0xdeadbeef;
1641  hr = ITextStream_ReadAll(stream, &str);
1642  ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1643  ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1644 
1645  ITextStream_Release(stream);
1646 
1647  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1648  ok(hr == S_OK, "got 0x%08x\n", hr);
1649 
1650  hr = ITextStream_ReadAll(stream, NULL);
1651  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1652 
1653  /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1654  str = NULL;
1655  hr = ITextStream_ReadAll(stream, &str);
1656  ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1657  buffW[0] = 0;
1658  MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1659  ok(str[0] == buffW[0] && str[1] == buffW[1], "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
1660  SysFreeString(str);
1661  ITextStream_Release(stream);
1662 
1663  /* Unicode file -> read with unicode stream */
1664  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1665  ok(hr == S_OK, "got 0x%08x\n", hr);
1666 
1667  lstrcpyW(buffW, nameW);
1668  lstrcatW(buffW, crlfW);
1669  lstrcatW(buffW, secondlineW);
1670  lstrcatW(buffW, crlfW);
1671  str = NULL;
1672  hr = ITextStream_ReadAll(stream, &str);
1673  ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1674  ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1675  SysFreeString(str);
1676 
1677  /* ReadAll one more time */
1678  str = (void*)0xdeadbeef;
1679  hr = ITextStream_ReadAll(stream, &str);
1680  ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1681  ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1682 
1683  /* ReadLine fails the same way */
1684  str = (void*)0xdeadbeef;
1685  hr = ITextStream_ReadLine(stream, &str);
1686  ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1687  ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1688  ITextStream_Release(stream);
1689 
1690  /* Open again and skip first line before ReadAll */
1691  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1692  ok(hr == S_OK, "got 0x%08x\n", hr);
1693 
1694  str = NULL;
1695  hr = ITextStream_ReadLine(stream, &str);
1696 todo_wine {
1697  ok(hr == S_OK, "got 0x%08x\n", hr);
1698  ok(str != NULL, "got %p\n", str);
1699 }
1700  SysFreeString(str);
1701 
1702  lstrcpyW(buffW, secondlineW);
1703  lstrcatW(buffW, crlfW);
1704  str = NULL;
1705  hr = ITextStream_ReadAll(stream, &str);
1706  ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1707 todo_wine
1708  ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1709  SysFreeString(str);
1710  ITextStream_Release(stream);
1711 
1712  /* ASCII file, read with Unicode stream */
1713  /* 1. one byte content, not enough for Unicode read */
1714  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1715  ok(hr == S_OK, "got 0x%08x\n", hr);
1716  str = SysAllocString(aW);
1717  hr = ITextStream_Write(stream, str);
1718  ok(hr == S_OK, "got 0x%08x\n", hr);
1719  SysFreeString(str);
1720  ITextStream_Release(stream);
1721 
1722  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1723  ok(hr == S_OK, "got 0x%08x\n", hr);
1724 
1725  str = (void*)0xdeadbeef;
1726  hr = ITextStream_ReadAll(stream, &str);
1727  ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1728  ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
1729 
1730  ITextStream_Release(stream);
1731 
1732  DeleteFileW(nameW);
1733  RemoveDirectoryW(dirW);
1735 }
1736 
1737 static void test_Read(void)
1738 {
1739  static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
1740  static const WCHAR aW[] = {'A',0};
1741  WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
1742  ITextStream *stream;
1743  BSTR nameW;
1744  HRESULT hr;
1745  BOOL ret;
1746  BSTR str;
1747 
1748  get_temp_filepath(testfileW, pathW, dirW);
1749 
1750  ret = CreateDirectoryW(dirW, NULL);
1751  ok(ret, "got %d, %d\n", ret, GetLastError());
1752 
1753  /* Unicode file -> read with ascii stream */
1754  nameW = SysAllocString(pathW);
1755  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
1756  ok(hr == S_OK, "got 0x%08x\n", hr);
1757 
1758  hr = ITextStream_WriteLine(stream, nameW);
1759  ok(hr == S_OK, "got 0x%08x\n", hr);
1760 
1761  str = SysAllocString(secondlineW);
1762  hr = ITextStream_WriteLine(stream, str);
1763  ok(hr == S_OK, "got 0x%08x\n", hr);
1764  SysFreeString(str);
1765 
1766  hr = ITextStream_Read(stream, 0, NULL);
1767  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1768 
1769  hr = ITextStream_Read(stream, 1, NULL);
1770  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1771 
1772  hr = ITextStream_Read(stream, -1, NULL);
1773  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1774 
1775  str = (void*)0xdeadbeef;
1776  hr = ITextStream_Read(stream, 1, &str);
1777  ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
1778  ok(str == NULL, "got %p\n", str);
1779 
1780  ITextStream_Release(stream);
1781 
1782  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
1783  ok(hr == S_OK, "got 0x%08x\n", hr);
1784 
1785  hr = ITextStream_Read(stream, 1, NULL);
1786  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1787 
1788  str = (void*)0xdeadbeef;
1789  hr = ITextStream_Read(stream, -1, &str);
1790  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1791  ok(str == NULL, "got %p\n", str);
1792 
1793  str = (void*)0xdeadbeef;
1794  hr = ITextStream_Read(stream, 0, &str);
1795  ok(hr == S_OK, "got 0x%08x\n", hr);
1796  ok(str == NULL, "got %p\n", str);
1797 
1798  /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
1799  str = NULL;
1800  hr = ITextStream_Read(stream, 2, &str);
1801  ok(hr == S_OK, "got 0x%08x\n", hr);
1802 
1803  buffW[0] = 0;
1804  MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
1805 
1806  ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
1807  ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str));
1808  SysFreeString(str);
1809  ITextStream_Release(stream);
1810 
1811  /* Unicode file -> read with unicode stream */
1812  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1813  ok(hr == S_OK, "got 0x%08x\n", hr);
1814 
1815  lstrcpyW(buffW, nameW);
1816  lstrcatW(buffW, crlfW);
1817  lstrcatW(buffW, secondlineW);
1818  lstrcatW(buffW, crlfW);
1819  str = NULL;
1820  hr = ITextStream_Read(stream, 500, &str);
1821  ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1822  ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1823  SysFreeString(str);
1824 
1825  /* ReadAll one more time */
1826  str = (void*)0xdeadbeef;
1827  hr = ITextStream_Read(stream, 10, &str);
1828  ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1829  ok(str == NULL, "got %p\n", str);
1830 
1831  /* ReadLine fails the same way */
1832  str = (void*)0xdeadbeef;
1833  hr = ITextStream_ReadLine(stream, &str);
1834  ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1835  ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str);
1836  ITextStream_Release(stream);
1837 
1838  /* Open again and skip first line before ReadAll */
1839  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1840  ok(hr == S_OK, "got 0x%08x\n", hr);
1841 
1842  str = NULL;
1843  hr = ITextStream_ReadLine(stream, &str);
1844 todo_wine {
1845  ok(hr == S_OK, "got 0x%08x\n", hr);
1846  ok(str != NULL, "got %p\n", str);
1847 }
1848  SysFreeString(str);
1849 
1850  lstrcpyW(buffW, secondlineW);
1851  lstrcatW(buffW, crlfW);
1852  str = NULL;
1853  hr = ITextStream_Read(stream, 100, &str);
1854  ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
1855 todo_wine
1856  ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
1857  SysFreeString(str);
1858  ITextStream_Release(stream);
1859 
1860  /* ASCII file, read with Unicode stream */
1861  /* 1. one byte content, not enough for Unicode read */
1862  hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
1863  ok(hr == S_OK, "got 0x%08x\n", hr);
1864  str = SysAllocString(aW);
1865  hr = ITextStream_Write(stream, str);
1866  ok(hr == S_OK, "got 0x%08x\n", hr);
1867  SysFreeString(str);
1868  ITextStream_Release(stream);
1869 
1870  hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
1871  ok(hr == S_OK, "got 0x%08x\n", hr);
1872 
1873  str = (void*)0xdeadbeef;
1874  hr = ITextStream_Read(stream, 500, &str);
1875  ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
1876  ok(str == NULL, "got %p\n", str);
1877 
1878  ITextStream_Release(stream);
1879 
1880  DeleteFileW(nameW);
1881  RemoveDirectoryW(dirW);
1883 }
1884 
1886  const WCHAR drivespec[10];
1889 };
1890 
1891 /* If 'drivetype' != -1, the first character of 'drivespec' will be replaced
1892  * with the drive letter of a drive of this type. If such a drive does not exist,
1893  * the test will be skipped. */
1894 static const struct driveexists_test driveexiststestdata[] = {
1895  { {'N',':','\\',0}, DRIVE_NO_ROOT_DIR, VARIANT_FALSE },
1896  { {'R',':','\\',0}, DRIVE_REMOVABLE, VARIANT_TRUE },
1897  { {'F',':','\\',0}, DRIVE_FIXED, VARIANT_TRUE },
1898  { {'F',':',0}, DRIVE_FIXED, VARIANT_TRUE },
1899  { {'F','?',0}, DRIVE_FIXED, VARIANT_FALSE },
1900  { {'F',0}, DRIVE_FIXED, VARIANT_TRUE },
1901  { {'?',0}, -1, VARIANT_FALSE },
1902  { { 0 } }
1903 };
1904 
1905 static void test_DriveExists(void)
1906 {
1907  const struct driveexists_test *ptr = driveexiststestdata;
1908  HRESULT hr;
1909  VARIANT_BOOL ret;
1910  BSTR drivespec;
1911  WCHAR root[] = {'?',':','\\',0};
1912 
1913  hr = IFileSystem3_DriveExists(fs3, NULL, NULL);
1914  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1915 
1916  ret = VARIANT_TRUE;
1917  hr = IFileSystem3_DriveExists(fs3, NULL, &ret);
1918  ok(hr == S_OK, "got 0x%08x\n", hr);
1919  ok(ret == VARIANT_FALSE, "got %x\n", ret);
1920 
1922  hr = IFileSystem3_DriveExists(fs3, drivespec, NULL);
1923  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1925 
1926  for (; *ptr->drivespec; ptr++) {
1927  drivespec = SysAllocString(ptr->drivespec);
1928  if (ptr->drivetype != -1) {
1929  for (root[0] = 'A'; root[0] <= 'Z'; root[0]++)
1930  if (GetDriveTypeW(root) == ptr->drivetype)
1931  break;
1932  if (root[0] > 'Z') {
1933  skip("No drive with type 0x%x found, skipping test %s.\n",
1934  ptr->drivetype, wine_dbgstr_w(ptr->drivespec));
1936  continue;
1937  }
1938 
1939  /* Test both upper and lower case drive letters. */
1940  drivespec[0] = root[0];
1941  ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE;
1942  hr = IFileSystem3_DriveExists(fs3, drivespec, &ret);
1943  ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n",
1944  hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
1945  ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n",
1946  ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
1947 
1948  drivespec[0] = tolower(root[0]);
1949  }
1950 
1951  ret = ptr->expected_ret == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE;
1952  hr = IFileSystem3_DriveExists(fs3, drivespec, &ret);
1953  ok(hr == S_OK, "got 0x%08x for drive spec %s (%s)\n",
1954  hr, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
1955  ok(ret == ptr->expected_ret, "got %d, expected %d for drive spec %s (%s)\n",
1956  ret, ptr->expected_ret, wine_dbgstr_w(drivespec), wine_dbgstr_w(ptr->drivespec));
1957 
1959  }
1960 }
1961 
1963  const WCHAR path[10];
1964  const WCHAR drive[5];
1965 };
1966 
1967 static const struct getdrivename_test getdrivenametestdata[] = {
1968  { {'C',':','\\','1','.','t','s','t',0}, {'C',':',0} },
1969  { {'O',':','\\','1','.','t','s','t',0}, {'O',':',0} },
1970  { {'O',':',0}, {'O',':',0} },
1971  { {'o',':',0}, {'o',':',0} },
1972  { {'O','O',':',0} },
1973  { {':',0} },
1974  { {'O',0} },
1975  { { 0 } }
1976 };
1977 
1978 static void test_GetDriveName(void)
1979 {
1980  const struct getdrivename_test *ptr = getdrivenametestdata;
1981  HRESULT hr;
1982  BSTR name;
1983 
1984  hr = IFileSystem3_GetDriveName(fs3, NULL, NULL);
1985  ok(hr == E_POINTER, "got 0x%08x\n", hr);
1986 
1987  name = (void*)0xdeadbeef;
1988  hr = IFileSystem3_GetDriveName(fs3, NULL, &name);
1989  ok(hr == S_OK, "got 0x%08x\n", hr);
1990  ok(name == NULL, "got %p\n", name);
1991 
1992  while (*ptr->path) {
1993  BSTR path = SysAllocString(ptr->path);
1994  name = (void*)0xdeadbeef;
1995  hr = IFileSystem3_GetDriveName(fs3, path, &name);
1996  ok(hr == S_OK, "got 0x%08x\n", hr);
1997  if (name)
1998  ok(!lstrcmpW(ptr->drive, name), "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive));
1999  else
2000  ok(!*ptr->drive, "got %s, expected %s\n", wine_dbgstr_w(name), wine_dbgstr_w(ptr->drive));
2003  ptr++;
2004  }
2005 }
2006 
2008  const WCHAR drivespec[12];
2010  const WCHAR driveletter[2];
2011 };
2012 
2013 static void test_GetDrive(void)
2014 {
2015  HRESULT hr;
2016  IDrive *drive_fixed, *drive;
2017  BSTR dl_fixed, drivespec;
2018  WCHAR root[] = {'?',':','\\',0};
2019 
2020  drive = (void*)0xdeadbeef;
2021  hr = IFileSystem3_GetDrive(fs3, NULL, NULL);
2022  ok(hr == E_POINTER, "got 0x%08x\n", hr);
2023  ok(drive == (void*)0xdeadbeef, "got %p\n", drive);
2024 
2025  for (root[0] = 'A'; root[0] <= 'Z'; root[0]++)
2027  break;
2028 
2029  if (root[0] > 'Z')
2030  skip("All drive letters are occupied, skipping test for nonexisting drive.\n");
2031  else {
2032  drivespec = SysAllocString(root);
2033  drive = (void*)0xdeadbeef;
2034  hr = IFileSystem3_GetDrive(fs3, drivespec, &drive);
2035  ok(hr == CTL_E_DEVICEUNAVAILABLE, "got 0x%08x\n", hr);
2036  ok(drive == NULL, "got %p\n", drive);
2037  SysFreeString(drivespec);
2038  }
2039 
2040  drive_fixed = get_fixed_drive();
2041  if (!drive_fixed) {
2042  skip("No fixed drive found, skipping test.\n");
2043  return;
2044  }
2045 
2046  hr = IDrive_get_DriveLetter(drive_fixed, &dl_fixed);
2047  ok(hr == S_OK, "got 0x%08x\n", hr);
2048 
2049  if (FAILED(hr))
2050  skip("Could not retrieve drive letter of fixed drive, skipping test.\n");
2051  else {
2052  WCHAR dl_upper = toupper(dl_fixed[0]);
2053  WCHAR dl_lower = tolower(dl_fixed[0]);
2054  struct getdrive_test testdata[] = {
2055  { {dl_upper,0}, S_OK, {dl_upper,0} },
2056  { {dl_upper,':',0}, S_OK, {dl_upper,0} },
2057  { {dl_upper,':','\\',0}, S_OK, {dl_upper,0} },
2058  { {dl_lower,':','\\',0}, S_OK, {dl_upper,0} },
2059  { {dl_upper,'\\',0}, E_INVALIDARG, { 0 } },
2060  { {dl_lower,'\\',0}, E_INVALIDARG, { 0 } },
2061  { {'$',':','\\',0}, E_INVALIDARG, { 0 } },
2062  { {'\\','h','o','s','t','\\','s','h','a','r','e',0}, E_INVALIDARG, { 0 } },
2063  { {'h','o','s','t','\\','s','h','a','r','e',0}, E_INVALIDARG, { 0 } },
2064  { { 0 } },
2065  };
2066  struct getdrive_test *ptr = &testdata[0];
2067 
2068  for (; *ptr->drivespec; ptr++) {
2069  drivespec = SysAllocString(ptr->drivespec);
2070  drive = (void*)0xdeadbeef;
2071  hr = IFileSystem3_GetDrive(fs3, drivespec, &drive);
2072  ok(hr == ptr->res, "got 0x%08x, expected 0x%08x for drive spec %s\n",
2073  hr, ptr->res, wine_dbgstr_w(ptr->drivespec));
2074  ok(!lstrcmpW(ptr->drivespec, drivespec), "GetDrive modified its DriveSpec argument\n");
2076 
2077  if (*ptr->driveletter) {
2078  BSTR driveletter;
2079  hr = IDrive_get_DriveLetter(drive, &driveletter);
2080  ok(hr == S_OK, "got 0x%08x for drive spec %s\n", hr, wine_dbgstr_w(ptr->drivespec));
2081  if (SUCCEEDED(hr)) {
2082  ok(!lstrcmpW(ptr->driveletter, driveletter), "got %s, expected %s for drive spec %s\n",
2083  wine_dbgstr_w(driveletter), wine_dbgstr_w(ptr->driveletter),
2084  wine_dbgstr_w(ptr->drivespec));
2086  }
2087  test_provideclassinfo(drive, &CLSID_Drive);
2088  IDrive_Release(drive);
2089  } else
2090  ok(drive == NULL, "got %p for drive spec %s\n", drive, wine_dbgstr_w(ptr->drivespec));
2091  }
2092  SysFreeString(dl_fixed);
2093  }
2094 }
2095 
2096 static void test_SerialNumber(void)
2097 {
2098  IDrive *drive;
2099  LONG serial;
2100  HRESULT hr;
2101  BSTR name;
2102 
2103  drive = get_fixed_drive();
2104  if (!drive) {
2105  skip("No fixed drive found, skipping test.\n");
2106  return;
2107  }
2108 
2109  hr = IDrive_get_SerialNumber(drive, NULL);
2110  ok(hr == E_POINTER, "got 0x%08x\n", hr);
2111 
2112  serial = 0xdeadbeef;
2113  hr = IDrive_get_SerialNumber(drive, &serial);
2114  ok(hr == S_OK, "got 0x%08x\n", hr);
2115  ok(serial != 0xdeadbeef, "got %x\n", serial);
2116 
2117  hr = IDrive_get_FileSystem(drive, NULL);
2118  ok(hr == E_POINTER, "got 0x%08x\n", hr);
2119 
2120  name = NULL;
2121  hr = IDrive_get_FileSystem(drive, &name);
2122  ok(hr == S_OK, "got 0x%08x\n", hr);
2123  ok(name != NULL, "got %p\n", name);
2125 
2126  hr = IDrive_get_VolumeName(drive, NULL);
2127  ok(hr == E_POINTER, "got 0x%08x\n", hr);
2128 
2129  name = NULL;
2130  hr = IDrive_get_VolumeName(drive, &name);
2131  ok(hr == S_OK, "got 0x%08x\n", hr);
2132  ok(name != NULL, "got %p\n", name);
2134 
2135  IDrive_Release(drive);
2136 }
2137 
2138 static const struct extension_test {
2140  WCHAR ext[10];
2141 } extension_tests[] = {
2142  { {'n','o','e','x','t',0}, {0} },
2143  { {'n','.','o','.','e','x','t',0}, {'e','x','t',0} },
2144  { {'n','.','o','.','e','X','t',0}, {'e','X','t',0} },
2145  { { 0 } }
2146 };
2147 
2148 static void test_GetExtensionName(void)
2149 {
2150  BSTR path, ext;
2151  HRESULT hr;
2152  int i;
2153 
2154  for (i = 0; i < ARRAY_SIZE(extension_tests); i++) {
2155 
2157  ext = NULL;
2158  hr = IFileSystem3_GetExtensionName(fs3, path, &ext);
2159  ok(hr == S_OK, "got 0x%08x\n", hr);
2160  if (*extension_tests[i].ext)
2161  ok(!lstrcmpW(ext, extension_tests[i].ext), "%d: path %s, got %s, expected %s\n", i,
2163  else
2164  ok(ext == NULL, "%d: path %s, got %s, expected %s\n", i,
2166 
2168  SysFreeString(ext);
2169  }
2170 }
2171 
2172 static void test_GetSpecialFolder(void)
2173 {
2174  WCHAR pathW[MAX_PATH];
2175  IFolder *folder;
2176  HRESULT hr;
2177  DWORD ret;
2178  BSTR path;
2179 
2180  hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, NULL);
2181  ok(hr == E_POINTER, "got 0x%08x\n", hr);
2182 
2183  hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, NULL);
2184  ok(hr == E_POINTER, "got 0x%08x\n", hr);
2185 
2186  hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder+1, &folder);
2187  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2188 
2189  hr = IFileSystem3_GetSpecialFolder(fs3, WindowsFolder, &folder);
2190  ok(hr == S_OK, "got 0x%08x\n", hr);
2191  hr = IFolder_get_Path(folder, &path);
2192  ok(hr == S_OK, "got 0x%08x\n", hr);
2193  GetWindowsDirectoryW(pathW, ARRAY_SIZE(pathW));
2194  ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2196  IFolder_Release(folder);
2197 
2198  hr = IFileSystem3_GetSpecialFolder(fs3, SystemFolder, &folder);
2199  ok(hr == S_OK, "got 0x%08x\n", hr);
2200  hr = IFolder_get_Path(folder, &path);
2201  ok(hr == S_OK, "got 0x%08x\n", hr);
2202  GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW));
2203  ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2205  IFolder_Release(folder);
2206 
2207  hr = IFileSystem3_GetSpecialFolder(fs3, TemporaryFolder, &folder);
2208  ok(hr == S_OK, "got 0x%08x\n", hr);
2209  hr = IFolder_get_Path(folder, &path);
2210  ok(hr == S_OK, "got 0x%08x\n", hr);
2211  ret = GetTempPathW(ARRAY_SIZE(pathW), pathW);
2212  if (ret && pathW[ret-1] == '\\')
2213  pathW[ret-1] = 0;
2214 
2215  ok(!lstrcmpiW(pathW, path), "got %s, expected %s\n", wine_dbgstr_w(path), wine_dbgstr_w(pathW));
2217  IFolder_Release(folder);
2218 }
2219 
2221 {
2222  HRESULT hr;
2223 
2224  CoInitialize(NULL);
2225 
2226  hr = CoCreateInstance(&CLSID_FileSystemObject, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2227  &IID_IFileSystem3, (void**)&fs3);
2228  if(FAILED(hr)) {
2229  win_skip("Could not create FileSystem object: %08x\n", hr);
2230  return;
2231  }
2232 
2233  test_interfaces();
2235  test_textstream();
2238  test_GetFileName();
2239  test_GetBaseName();
2241  test_GetFile();
2242  test_CopyFolder();
2243  test_BuildPath();
2244  test_GetFolder();
2249  test_WriteLine();
2250  test_ReadAll();
2251  test_Read();
2252  test_DriveExists();
2254  test_GetDrive();
2258 
2259  IFileSystem3_Release(fs3);
2260 
2261  CoUninitialize();
2262 }
#define CTL_E_FILENOTFOUND
Definition: olectl.h:274
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
static const WCHAR path2[]
Definition: path.c:29
disp
Definition: i386-dis.c:3181
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
static void test_GetParentFolderName(void)
Definition: filesystem.c:407
struct param_test tests[]
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
static const WCHAR crlfW[]
Definition: filesystem.c:47
#define TRUE
Definition: types.h:120
#define GET_REFCOUNT(iface)
Definition: filesystem.c:51
#define CloseHandle
Definition: compat.h:398
const char * path
Definition: filesystem.c:861
static IFileSystem3 * fs3
Definition: filesystem.c:36
#define E_NOINTERFACE
Definition: winerror.h:2364
Definition: compat.h:1932
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
Definition: fci.c:115
static void test_WriteLine(void)
Definition: filesystem.c:1539
static const struct getdrivename_test getdrivenametestdata[]
Definition: filesystem.c:1967
DriveTypeConst
Definition: scrrun.idl:87
const INT drivetype
Definition: filesystem.c:1887
#define INT_MAX
Definition: limits.h:40
static struct buildpath_test buildpath_data[]
Definition: filesystem.c:866
HRESULT hr
Definition: shlfolder.c:183
BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len)
Definition: oleaut.c:342
static IActiveScriptSite * site
Definition: script.c:149
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static void test_DriveExists(void)
Definition: filesystem.c:1905
GLsizei const GLchar ** path
Definition: glext.h:7234
static void create_path(const WCHAR *folder, const WCHAR *name, WCHAR *ret)
Definition: filesystem.c:734
static void get_temp_filepath(const WCHAR *filename, WCHAR *path, WCHAR *dir)
Definition: filesystem.c:1454
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static const WCHAR empty[]
Definition: main.c:49
#define CP_ACP
Definition: compat.h:99
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define V_R8(A)
Definition: oleauto.h:262
static void test_ReadAll(void)
Definition: filesystem.c:1608
START_TEST(filesystem)
Definition: filesystem.c:2220
double DATE
Definition: compat.h:1887
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
FileAttribute
Definition: scrrun.idl:67
static void test_GetDriveName(void)
Definition: filesystem.c:1978
const char * wine_dbgstr_guid(const GUID *guid)
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
classinfo
Definition: clsfactory.c:43
static void test_GetFileName(void)
Definition: filesystem.c:455
static const WCHAR path3[]
Definition: misc.c:318
OLECHAR * BSTR
Definition: compat.h:1927
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:571
const char * filename
Definition: ioapi.h:135
#define lstrlenW
Definition: compat.h:407
int32_t INT
Definition: typedefs.h:56
short VARIANT_BOOL
Definition: compat.h:1924
Definition: send.c:47
#define DRIVE_REMOVABLE
Definition: winbase.h:248
#define V_I4(A)
Definition: oleauto.h:247
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2351
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
static void test_GetAbsolutePathName(void)
Definition: filesystem.c:544
#define V_DISPATCH(A)
Definition: oleauto.h:239
static const WCHAR filenameW[]
Definition: amstream.c:41
static const struct extension_test extension_tests[]
const WCHAR driveletter[2]
Definition: filesystem.c:2010
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const GUID * guid
static void test_GetFile(void)
Definition: filesystem.c:615
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2079
static const WCHAR path5[]
Definition: path.c:32
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:802
const GUID IID_IProvideClassInfo
#define GENERIC_WRITE
Definition: nt_native.h:90
static const WCHAR testfileW[]
Definition: filesystem.c:49
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
char * wine_dbgstr_w(const wchar_t *wstr)
Definition: CString.cpp:62
#define S_FALSE
Definition: winerror.h:2357
static void test_createfolder(void)
Definition: filesystem.c:219
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
static const WCHAR aW[]
Definition: htmlelem.c:21
static void test_textstream(void)
Definition: filesystem.c:241
#define E_VAR_NOT_SET
Definition: filesystem.c:39
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
char ext[3]
Definition: mkdosfs.c:358
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:241
#define CTL_E_DEVICEUNAVAILABLE
Definition: olectl.h:284
Definition: parser.c:48
static void test_FileCollection(void)
Definition: filesystem.c:1158
const char * result
Definition: filesystem.c:863
unsigned int dir
Definition: maze.c:112
struct CFFOLDER folder
Definition: fdi.c:110
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
BOOL WINAPI RemoveDirectoryW(IN LPCWSTR lpPathName)
Definition: dir.c:732
#define OPEN_EXISTING
Definition: compat.h:426
#define b
Definition: ke_i.h:79
const VARIANT_BOOL expected_ret
Definition: filesystem.c:1888
#define ok(value,...)
Definition: CComObject.cpp:34
static const WCHAR path1[]
Definition: path.c:28
static const WCHAR nameW[]
Definition: main.c:46
#define test_provideclassinfo(a, b)
Definition: filesystem.c:104
static void test_GetExtensionName(void)
Definition: filesystem.c:2148
static const WCHAR path4[]
Definition: misc.c:319
GLfloat f
Definition: glext.h:7540
int toupper(int c)
Definition: utclib.c:881
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLsizeiptr size
Definition: glext.h:5919
#define CTL_E_PERMISSIONDENIED
Definition: olectl.h:285
static void test_FolderCollection(void)
Definition: filesystem.c:977
#define d
Definition: ke_i.h:81
const WCHAR drivespec[12]
Definition: filesystem.c:2008
__wchar_t WCHAR
Definition: xmlstorage.h:180
static void test_GetDrive(void)
Definition: filesystem.c:2013
LONG HRESULT
Definition: typedefs.h:77
struct S1 s1
const GUID IID_IUnknown
static void test_interfaces(void)
Definition: filesystem.c:135
static void test_GetFolder(void)
Definition: filesystem.c:939
#define MAX_PATH
Definition: compat.h:26
const char file[]
Definition: icontest.c:11
static void test_CreateTextFile(void)
Definition: filesystem.c:1464
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
#define FILE_FLAG_DELETE_ON_CLOSE
Definition: disk.h:42
static const WCHAR fooW[]
Definition: locale.c:44
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
const IID IID_IObjectWithSite
unsigned long DWORD
Definition: ntddk_ex.h:95
Definition: cookie.c:170
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define CTL_E_FILEALREADYEXISTS
Definition: olectl.h:278
const GUID IID_IDispatch
int ret
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
const WCHAR drivespec[10]
Definition: filesystem.c:1886
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:651
__u8 attr
Definition: mkdosfs.c:359
#define todo_wine
Definition: test.h:154
Definition: parse.h:22
static void get_temp_path(const WCHAR *prefix, WCHAR *path)
Definition: filesystem.c:54
GLuint GLuint stream
Definition: glext.h:7522
#define V_VT(A)
Definition: oleauto.h:211
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:199
#define GENERIC_READ
Definition: compat.h:124
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
static void test_Read(void)
Definition: filesystem.c:1737
#define DRIVE_NO_ROOT_DIR
Definition: winbase.h:254
#define broken(x)
Definition: _sntprintf.h:21
#define DRIVE_FIXED
Definition: winbase.h:249
static const WCHAR dummyW[]
Definition: directory.c:79
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3234
static BOOL create_file(const WCHAR *name)
Definition: filesystem.c:727
static void test_GetSpecialFolder(void)
Definition: filesystem.c:2172
#define S_OK
Definition: intsafe.h:59
#define CREATE_ALWAYS
Definition: disk.h:72
static char drive[2]
Definition: batch.c:28
uint32_t serial
Definition: fsck.fat.h:64
#define lstrcpyW
Definition: compat.h:406
static void test_CopyFolder(void)
Definition: filesystem.c:742
#define FILE_ATTR_MASK
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:1991
#define ARRAY_SIZE(a)
Definition: main.h:24
__u16 date
Definition: mkdosfs.c:366
static BSTR bstr_from_str(const char *str)
Definition: filesystem.c:851
#define skip(...)
Definition: CString.cpp:57
static void test_DriveCollection(void)
Definition: filesystem.c:1329
Definition: services.c:325
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2312
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:274
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4021
static void test_BuildPath(void)
Definition: filesystem.c:882
#define MultiByteToWideChar
Definition: compat.h:100
#define CreateFileW
Definition: compat.h:400
#define CTL_E_PATHNOTFOUND
Definition: olectl.h:288
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1897
static TAGID TAGID find
Definition: db.cpp:153
static const WCHAR path6[]
Definition: path.c:33
Definition: name.c:36
static const struct driveexists_test driveexiststestdata[]
Definition: filesystem.c:1894
unsigned int ULONG
Definition: retypes.h:1
#define CREATE_NEW
Definition: disk.h:69
static const char utf16bom[]
Definition: filesystem.c:48
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
static ULONG get_refcount(IUnknown *iface)
Definition: filesystem.c:41
#define E_POINTER
Definition: winerror.h:2365
static void _test_provideclassinfo(IDispatch *disp, const GUID *guid, int line)
Definition: filesystem.c:105
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
static IDrive * get_fixed_drive(void)
Definition: filesystem.c:63
static void test_GetFileVersion(void)
Definition: filesystem.c:370
GLuint64EXT * result
Definition: glext.h:11304
int tolower(int c)
Definition: utclib.c:902
static void test_SerialNumber(void)
Definition: filesystem.c:2096
const char * name
Definition: filesystem.c:862
#define win_skip
Definition: test.h:141
WCHAR ext[10]
Definition: filesystem.c:2140
static void test_GetBaseName(void)
Definition: filesystem.c:498
Definition: compat.h:1934
#define SUCCEEDED(hr)
Definition: intsafe.h:57
#define ok_(x1, x2)
Definition: CString.cpp:56
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
TCHAR file_path[MAX_PATH]
Definition: sndrec32.cpp:57
Definition: fci.c:126
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
f_args fa
Definition: format.c:280
#define CTL_E_BADFILEMODE
Definition: olectl.h:275
GLuint const GLchar * name
Definition: glext.h:6031