[SCRRUN_WINETEST]
authorAmine Khaldi <amine.khaldi@reactos.org>
Thu, 24 Apr 2014 16:00:38 +0000 (16:00 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Thu, 24 Apr 2014 16:00:38 +0000 (16:00 +0000)
* Sync with Wine 1.7.17.
CORE-8080

svn path=/trunk/; revision=62954

rostests/winetests/scrrun/CMakeLists.txt
rostests/winetests/scrrun/filesystem.c
rostests/winetests/scrrun/scrrun.idl

index 31f9392..fd12af1 100644 (file)
@@ -1,7 +1,5 @@
 
 
-add_definitions(
-    -D__ROS_LONG64__
-    -DUSE_WINE_TODOS)
+add_definitions(-DUSE_WINE_TODOS)
 
 list(APPEND SOURCE
     dictionary.c
 
 list(APPEND SOURCE
     dictionary.c
index e231f9a..c258a0f 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *
  * Copyright 2012 Alistair Leslie-Hughes
 /*
  *
  * Copyright 2012 Alistair Leslie-Hughes
+ * Copyright 2014 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 
 static IFileSystem3 *fs3;
 
 
 static IFileSystem3 *fs3;
 
+static inline ULONG get_refcount(IUnknown *iface)
+{
+    IUnknown_AddRef(iface);
+    return IUnknown_Release(iface);
+}
+
+static const WCHAR crlfW[] = {'\r','\n',0};
+
+#define GET_REFCOUNT(iface) \
+    get_refcount((IUnknown*)iface)
+
 static void test_interfaces(void)
 {
     static const WCHAR nonexistent_dirW[] = {
 static void test_interfaces(void)
 {
     static const WCHAR nonexistent_dirW[] = {
@@ -117,29 +129,38 @@ static void test_interfaces(void)
 
 static void test_createfolder(void)
 {
 
 static void test_createfolder(void)
 {
+    WCHAR pathW[MAX_PATH], buffW[MAX_PATH];
     HRESULT hr;
     HRESULT hr;
-    WCHAR pathW[MAX_PATH];
     BSTR path;
     IFolder *folder;
     BSTR path;
     IFolder *folder;
+    BOOL ret;
+
+    GetTempPathW(MAX_PATH, pathW);
+    GetTempFileNameW(pathW, NULL, 0, buffW);
+    DeleteFileW(buffW);
+    ret = CreateDirectoryW(buffW, NULL);
+    ok(ret, "got %d, %d\n", ret, GetLastError());
 
     /* create existing directory */
 
     /* create existing directory */
-    GetCurrentDirectoryW(sizeof(pathW)/sizeof(WCHAR), pathW);
-    path = SysAllocString(pathW);
+    path = SysAllocString(buffW);
     folder = (void*)0xdeabeef;
     hr = IFileSystem3_CreateFolder(fs3, path, &folder);
     ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
     ok(folder == NULL, "got %p\n", folder);
     SysFreeString(path);
     folder = (void*)0xdeabeef;
     hr = IFileSystem3_CreateFolder(fs3, path, &folder);
     ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
     ok(folder == NULL, "got %p\n", folder);
     SysFreeString(path);
+    RemoveDirectoryW(buffW);
 }
 
 static void test_textstream(void)
 {
 }
 
 static void test_textstream(void)
 {
-    static WCHAR testfileW[] = {'t','e','s','t','f','i','l','e','.','t','x','t',0};
+    static const WCHAR testfileW[] = {'t','e','s','t','f','i','l','e','.','t','x','t',0};
     ITextStream *stream;
     VARIANT_BOOL b;
     ITextStream *stream;
     VARIANT_BOOL b;
+    DWORD written;
     HANDLE file;
     HRESULT hr;
     BSTR name, data;
     HANDLE file;
     HRESULT hr;
     BSTR name, data;
+    BOOL ret;
 
     file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     CloseHandle(file);
 
     file = CreateFileW(testfileW, GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     CloseHandle(file);
@@ -150,15 +171,46 @@ static void test_textstream(void)
     ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
     ok(b == VARIANT_TRUE, "got %x\n", b);
 
     ok(hr == S_OK, "got 0x%08x, expected 0x%08x\n", hr, S_OK);
     ok(b == VARIANT_TRUE, "got %x\n", b);
 
+    /* different mode combinations */
+    hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    hr = IFileSystem3_OpenTextFile(fs3, name, ForReading | ForAppending, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting | ForReading, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = ITextStream_Read(stream, 1, &data);
+    ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+    ITextStream_Release(stream);
+
+    hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = ITextStream_Read(stream, 1, &data);
+    ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+    ITextStream_Release(stream);
+
     hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
     hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    /* try to write when open for reading */
+    hr = ITextStream_WriteLine(stream, name);
+    ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+
+    hr = ITextStream_Write(stream, name);
+    ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+
+    hr = ITextStream_get_AtEndOfStream(stream, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
     b = 10;
     hr = ITextStream_get_AtEndOfStream(stream, &b);
     b = 10;
     hr = ITextStream_get_AtEndOfStream(stream, &b);
-todo_wine {
-    ok(hr == S_FALSE || broken(hr == S_OK), "got 0x%08x\n", hr);
+    ok(hr == S_OK || broken(hr == S_FALSE), "got 0x%08x\n", hr);
     ok(b == VARIANT_TRUE, "got 0x%x\n", b);
     ok(b == VARIANT_TRUE, "got 0x%x\n", b);
-}
+
     ITextStream_Release(stream);
 
     hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
     ITextStream_Release(stream);
 
     hr = IFileSystem3_OpenTextFile(fs3, name, ForWriting, VARIANT_FALSE, TristateFalse, &stream);
@@ -166,10 +218,9 @@ todo_wine {
 
     b = 10;
     hr = ITextStream_get_AtEndOfStream(stream, &b);
 
     b = 10;
     hr = ITextStream_get_AtEndOfStream(stream, &b);
-todo_wine {
     ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
     ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
     ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
     ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
-}
+
     b = 10;
     hr = ITextStream_get_AtEndOfLine(stream, &b);
 todo_wine {
     b = 10;
     hr = ITextStream_get_AtEndOfLine(stream, &b);
 todo_wine {
@@ -189,14 +240,12 @@ todo_wine {
 
     hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
     hr = IFileSystem3_OpenTextFile(fs3, name, ForAppending, VARIANT_FALSE, TristateFalse, &stream);
     ok(hr == S_OK, "got 0x%08x\n", hr);
-    SysFreeString(name);
 
     b = 10;
     hr = ITextStream_get_AtEndOfStream(stream, &b);
 
     b = 10;
     hr = ITextStream_get_AtEndOfStream(stream, &b);
-todo_wine {
     ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
     ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
     ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
     ok(b == VARIANT_TRUE || broken(b == 10), "got 0x%x\n", b);
-}
+
     b = 10;
     hr = ITextStream_get_AtEndOfLine(stream, &b);
 todo_wine {
     b = 10;
     hr = ITextStream_get_AtEndOfLine(stream, &b);
 todo_wine {
@@ -214,6 +263,21 @@ todo_wine {
 
     ITextStream_Release(stream);
 
 
     ITextStream_Release(stream);
 
+    /* now with non-empty file */
+    file = CreateFileW(testfileW, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    ret = WriteFile(file, testfileW, sizeof(testfileW), &written, NULL);
+    ok(ret && written == sizeof(testfileW), "got %d\n", ret);
+    CloseHandle(file);
+
+    hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    b = 10;
+    hr = ITextStream_get_AtEndOfStream(stream, &b);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(b == VARIANT_FALSE, "got 0x%x\n", b);
+    ITextStream_Release(stream);
+
+    SysFreeString(name);
     DeleteFileW(testfileW);
 }
 
     DeleteFileW(testfileW);
 }
 
@@ -411,7 +475,7 @@ static void test_GetAbsolutePathName(void)
     hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
     GetFullPathNameW(cur_dir, MAX_PATH, buf, NULL);
     hr = IFileSystem3_GetAbsolutePathName(fs3, NULL, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
     GetFullPathNameW(cur_dir, MAX_PATH, buf, NULL);
-    ok(!lstrcmpW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
+    ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
     SysFreeString(result);
 
     find = FindFirstFileW(dir_match2, &fdata);
     SysFreeString(result);
 
     find = FindFirstFileW(dir_match2, &fdata);
@@ -425,26 +489,26 @@ static void test_GetAbsolutePathName(void)
     hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
     GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL);
     hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
     GetFullPathNameW(dir_match1, MAX_PATH, buf2, NULL);
-    ok(!lstrcmpW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2));
+    ok(!lstrcmpiW(buf2, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf2));
     SysFreeString(result);
 
     ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1));
     hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
     GetFullPathNameW(dir1, MAX_PATH, buf, NULL);
     SysFreeString(result);
 
     ok(CreateDirectoryW(dir1, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir1));
     hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
     GetFullPathNameW(dir1, MAX_PATH, buf, NULL);
-    ok(!lstrcmpW(buf, result) || broken(!lstrcmpW(buf2, result)), "result = %s, expected %s\n",
+    ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
                 wine_dbgstr_w(result), wine_dbgstr_w(buf));
     SysFreeString(result);
 
     ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2));
     hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
                 wine_dbgstr_w(result), wine_dbgstr_w(buf));
     SysFreeString(result);
 
     ok(CreateDirectoryW(dir2, NULL), "CreateDirectory(%s) failed\n", wine_dbgstr_w(dir2));
     hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
-    if(!lstrcmpW(buf, result) || !lstrcmpW(buf2, result)) {
-        ok(!lstrcmpW(buf, result) || broken(!lstrcmpW(buf2, result)), "result = %s, expected %s\n",
+    if(!lstrcmpiW(buf, result) || !lstrcmpiW(buf2, result)) {
+        ok(!lstrcmpiW(buf, result) || broken(!lstrcmpiW(buf2, result)), "result = %s, expected %s\n",
                 wine_dbgstr_w(result), wine_dbgstr_w(buf));
     }else {
         GetFullPathNameW(dir2, MAX_PATH, buf, NULL);
                 wine_dbgstr_w(result), wine_dbgstr_w(buf));
     }else {
         GetFullPathNameW(dir2, MAX_PATH, buf, NULL);
-        ok(!lstrcmpW(buf, result), "result = %s, expected %s\n",
+        ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n",
                 wine_dbgstr_w(result), wine_dbgstr_w(buf));
     }
     SysFreeString(result);
                 wine_dbgstr_w(result), wine_dbgstr_w(buf));
     }
     SysFreeString(result);
@@ -454,7 +518,7 @@ static void test_GetAbsolutePathName(void)
     hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
     GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL);
     hr = IFileSystem3_GetAbsolutePathName(fs3, path, &result);
     ok(hr == S_OK, "GetAbsolutePathName returned %x, expected S_OK\n", hr);
     GetFullPathNameW(dir_match2, MAX_PATH, buf, NULL);
-    ok(!lstrcmpW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
+    ok(!lstrcmpiW(buf, result), "result = %s, expected %s\n", wine_dbgstr_w(result), wine_dbgstr_w(buf));
     SysFreeString(result);
     SysFreeString(path);
 
     SysFreeString(result);
     SysFreeString(path);
 
@@ -651,6 +715,1009 @@ static void test_CopyFolder(void)
     SysFreeString(bsrc);
 }
 
     SysFreeString(bsrc);
 }
 
+static BSTR bstr_from_str(const char *str)
+{
+    int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+    BSTR ret = SysAllocStringLen(NULL, len - 1);  /* NUL character added automatically */
+    MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
+    return ret;
+}
+
+struct buildpath_test
+{
+    const char *path;
+    const char *name;
+    const char *result;
+};
+
+static struct buildpath_test buildpath_data[] =
+{
+    { "C:\\path", "..\\name.tmp", "C:\\path\\..\\name.tmp" },
+    { "C:\\path", "\\name.tmp", "C:\\path\\name.tmp" },
+    { "C:\\path", "name.tmp", "C:\\path\\name.tmp" },
+    { "C:\\path\\", "name.tmp", "C:\\path\\name.tmp" },
+    { "C:\\path", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
+    { "C:\\path\\", "\\name.tmp", "C:\\path\\name.tmp" },
+    { "C:\\path\\", "\\\\name.tmp", "C:\\path\\\\name.tmp" },
+    { "C:\\path\\\\", "\\\\name.tmp", "C:\\path\\\\\\name.tmp" },
+    { "C:\\\\", "\\name.tmp", "C:\\\\name.tmp" },
+    { "C:", "name.tmp", "C:name.tmp" },
+    { "C:", "\\\\name.tmp", "C:\\\\name.tmp" },
+    { NULL }
+};
+
+static void test_BuildPath(void)
+{
+    struct buildpath_test *ptr = buildpath_data;
+    BSTR ret, path;
+    HRESULT hr;
+    int i = 0;
+
+    hr = IFileSystem3_BuildPath(fs3, NULL, NULL, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    ret = (BSTR)0xdeadbeef;
+    hr = IFileSystem3_BuildPath(fs3, NULL, NULL, &ret);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(*ret == 0, "got %p\n", ret);
+    SysFreeString(ret);
+
+    ret = (BSTR)0xdeadbeef;
+    path = bstr_from_str("path");
+    hr = IFileSystem3_BuildPath(fs3, path, NULL, &ret);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
+    SysFreeString(ret);
+    SysFreeString(path);
+
+    ret = (BSTR)0xdeadbeef;
+    path = bstr_from_str("path");
+    hr = IFileSystem3_BuildPath(fs3, NULL, path, &ret);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(!lstrcmpW(ret, path), "got %s\n", wine_dbgstr_w(ret));
+    SysFreeString(ret);
+    SysFreeString(path);
+
+    while (ptr->path)
+    {
+        BSTR name, result;
+
+        ret = NULL;
+        path = bstr_from_str(ptr->path);
+        name = bstr_from_str(ptr->name);
+        result = bstr_from_str(ptr->result);
+        hr = IFileSystem3_BuildPath(fs3, path, name, &ret);
+        ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
+        if (hr == S_OK)
+        {
+            ok(!lstrcmpW(ret, result), "%d: got wrong path %s, expected %s\n", i, wine_dbgstr_w(ret),
+                wine_dbgstr_w(result));
+            SysFreeString(ret);
+        }
+        SysFreeString(path);
+        SysFreeString(name);
+        SysFreeString(result);
+
+        i++;
+        ptr++;
+    }
+}
+
+static void test_GetFolder(void)
+{
+    static const WCHAR dummyW[] = {'d','u','m','m','y',0};
+    WCHAR buffW[MAX_PATH];
+    IFolder *folder;
+    HRESULT hr;
+    BSTR str;
+
+    folder = (void*)0xdeadbeef;
+    hr = IFileSystem3_GetFolder(fs3, NULL, &folder);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(folder == NULL, "got %p\n", folder);
+
+    hr = IFileSystem3_GetFolder(fs3, NULL, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    /* something that doesn't exist */
+    str = SysAllocString(dummyW);
+
+    hr = IFileSystem3_GetFolder(fs3, str, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    folder = (void*)0xdeadbeef;
+    hr = IFileSystem3_GetFolder(fs3, str, &folder);
+    ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
+    ok(folder == NULL, "got %p\n", folder);
+    SysFreeString(str);
+
+    GetWindowsDirectoryW(buffW, MAX_PATH);
+    str = SysAllocString(buffW);
+    hr = IFileSystem3_GetFolder(fs3, str, &folder);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    SysFreeString(str);
+    IFolder_Release(folder);
+}
+
+/* Please keep the tests for IFolderCollection and IFileCollection in sync */
+static void test_FolderCollection(void)
+{
+    static const WCHAR fooW[] = {'f','o','o',0};
+    static const WCHAR aW[] = {'\\','a',0};
+    static const WCHAR bW[] = {'\\','b',0};
+    static const WCHAR cW[] = {'\\','c',0};
+    IFolderCollection *folders;
+    WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
+    IEnumVARIANT *enumvar, *clone;
+    LONG count, ref, ref2, i;
+    IUnknown *unk, *unk2;
+    IFolder *folder;
+    ULONG fetched;
+    VARIANT var, var2[2];
+    HRESULT hr;
+    BSTR str;
+    int found_a = 0, found_b = 0, found_c = 0;
+
+    GetTempPathW(MAX_PATH, pathW);
+    GetTempFileNameW(pathW, fooW, 0, buffW);
+    DeleteFileW(buffW);
+    CreateDirectoryW(buffW, NULL);
+
+    str = SysAllocString(buffW);
+    hr = IFileSystem3_GetFolder(fs3, str, &folder);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    SysFreeString(str);
+
+    hr = IFolder_get_SubFolders(folder, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    hr = IFolder_get_Path(folder, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    hr = IFolder_get_Path(folder, &str);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(!lstrcmpW(buffW, str), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
+    SysFreeString(str);
+
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, aW);
+    CreateDirectoryW(pathW, NULL);
+
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, bW);
+    CreateDirectoryW(pathW, NULL);
+
+    hr = IFolder_get_SubFolders(folder, &folders);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IFolder_Release(folder);
+
+    count = 0;
+    hr = IFolderCollection_get_Count(folders, &count);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(count == 2, "got %d\n", count);
+
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, cW);
+    CreateDirectoryW(pathW, NULL);
+
+    /* every time property is requested it scans directory */
+    count = 0;
+    hr = IFolderCollection_get_Count(folders, &count);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(count == 3, "got %d\n", count);
+
+    hr = IFolderCollection_get__NewEnum(folders, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    hr = IFolderCollection_QueryInterface(folders, &IID_IEnumVARIANT, (void**)&unk);
+    ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
+
+    /* NewEnum creates new instance each time it's called */
+    ref = GET_REFCOUNT(folders);
+
+    unk = NULL;
+    hr = IFolderCollection_get__NewEnum(folders, &unk);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    ref2 = GET_REFCOUNT(folders);
+    ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
+
+    unk2 = NULL;
+    hr = IFolderCollection_get__NewEnum(folders, &unk2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(unk != unk2, "got %p, %p\n", unk2, unk);
+    IUnknown_Release(unk2);
+
+    /* now get IEnumVARIANT */
+    ref = GET_REFCOUNT(folders);
+    hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ref2 = GET_REFCOUNT(folders);
+    ok(ref2 == ref, "got %d, %d\n", ref2, ref);
+
+    /* clone enumerator */
+    hr = IEnumVARIANT_Clone(enumvar, &clone);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
+    IEnumVARIANT_Release(clone);
+
+    hr = IEnumVARIANT_Reset(enumvar);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    for (i = 0; i < 3; i++)
+    {
+        VariantInit(&var);
+        fetched = 0;
+        hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
+        ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
+        ok(fetched == 1, "%d: got %d\n", i, fetched);
+        ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
+
+        hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        str = NULL;
+        hr = IFolder_get_Name(folder, &str);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        if (!lstrcmpW(str, aW + 1))
+            found_a++;
+        else if (!lstrcmpW(str, bW + 1))
+            found_b++;
+        else if (!lstrcmpW(str, cW + 1))
+            found_c++;
+        else
+            ok(0, "unexpected folder %s was found\n", wine_dbgstr_w(str));
+        SysFreeString(str);
+
+        IFolder_Release(folder);
+        VariantClear(&var);
+    }
+
+    ok(found_a == 1 && found_b == 1 && found_c == 1,
+       "each folder should be found 1 time instead of %d/%d/%d\n",
+       found_a, found_b, found_c);
+
+    VariantInit(&var);
+    fetched = -1;
+    hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
+    ok(hr == S_FALSE, "got 0x%08x\n", hr);
+    ok(fetched == 0, "got %d\n", fetched);
+
+    hr = IEnumVARIANT_Reset(enumvar);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = IEnumVARIANT_Skip(enumvar, 2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = IEnumVARIANT_Skip(enumvar, 0);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    VariantInit(&var2[0]);
+    VariantInit(&var2[1]);
+    fetched = -1;
+    hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(fetched == 0, "got %d\n", fetched);
+    fetched = -1;
+    hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
+    ok(hr == S_FALSE, "got 0x%08x\n", hr);
+    ok(fetched == 1, "got %d\n", fetched);
+    ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
+    VariantClear(&var2[0]);
+    VariantClear(&var2[1]);
+
+    IEnumVARIANT_Release(enumvar);
+    IUnknown_Release(unk);
+
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, aW);
+    RemoveDirectoryW(pathW);
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, bW);
+    RemoveDirectoryW(pathW);
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, cW);
+    RemoveDirectoryW(pathW);
+    RemoveDirectoryW(buffW);
+
+    IFolderCollection_Release(folders);
+}
+
+/* Please keep the tests for IFolderCollection and IFileCollection in sync */
+static void test_FileCollection(void)
+{
+    static const WCHAR fooW[] = {'\\','f','o','o',0};
+    static const WCHAR aW[] = {'\\','a',0};
+    static const WCHAR bW[] = {'\\','b',0};
+    static const WCHAR cW[] = {'\\','c',0};
+    WCHAR buffW[MAX_PATH], pathW[MAX_PATH];
+    IFolder *folder;
+    IFileCollection *files;
+    IFile *file;
+    IEnumVARIANT *enumvar, *clone;
+    LONG count, ref, ref2, i;
+    IUnknown *unk, *unk2;
+    ULONG fetched;
+    VARIANT var, var2[2];
+    HRESULT hr;
+    BSTR str;
+    HANDLE file_a, file_b, file_c;
+    int found_a = 0, found_b = 0, found_c = 0;
+
+    GetTempPathW(MAX_PATH, pathW);
+    GetTempFileNameW(pathW, fooW, 0, buffW);
+    DeleteFileW(buffW);
+    CreateDirectoryW(buffW, NULL);
+
+    str = SysAllocString(buffW);
+    hr = IFileSystem3_GetFolder(fs3, str, &folder);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    SysFreeString(str);
+
+    hr = IFolder_get_Files(folder, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, aW);
+    file_a = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                         FILE_FLAG_DELETE_ON_CLOSE, 0);
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, bW);
+    file_b = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                         FILE_FLAG_DELETE_ON_CLOSE, 0);
+
+    hr = IFolder_get_Files(folder, &files);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IFolder_Release(folder);
+
+    count = 0;
+    hr = IFileCollection_get_Count(files, &count);
+todo_wine
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+todo_wine
+    ok(count == 2, "got %d\n", count);
+
+    lstrcpyW(pathW, buffW);
+    lstrcatW(pathW, cW);
+    file_c = CreateFileW(pathW, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                         FILE_FLAG_DELETE_ON_CLOSE, 0);
+
+    /* every time property is requested it scans directory */
+    count = 0;
+    hr = IFileCollection_get_Count(files, &count);
+todo_wine
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+todo_wine
+    ok(count == 3, "got %d\n", count);
+
+    hr = IFileCollection_get__NewEnum(files, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    hr = IFileCollection_QueryInterface(files, &IID_IEnumVARIANT, (void**)&unk);
+    ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
+
+    /* NewEnum creates new instance each time it's called */
+    ref = GET_REFCOUNT(files);
+
+    unk = NULL;
+    hr = IFileCollection_get__NewEnum(files, &unk);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    ref2 = GET_REFCOUNT(files);
+    ok(ref2 == ref + 1, "got %d, %d\n", ref2, ref);
+
+    unk2 = NULL;
+    hr = IFileCollection_get__NewEnum(files, &unk2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(unk != unk2, "got %p, %p\n", unk2, unk);
+    IUnknown_Release(unk2);
+
+    /* now get IEnumVARIANT */
+    ref = GET_REFCOUNT(files);
+    hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (void**)&enumvar);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ref2 = GET_REFCOUNT(files);
+    ok(ref2 == ref, "got %d, %d\n", ref2, ref);
+
+    /* clone enumerator */
+    hr = IEnumVARIANT_Clone(enumvar, &clone);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(clone != enumvar, "got %p, %p\n", enumvar, clone);
+    IEnumVARIANT_Release(clone);
+
+    hr = IEnumVARIANT_Reset(enumvar);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    for (i = 0; i < 3; i++)
+    {
+        VariantInit(&var);
+        fetched = 0;
+        hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
+        ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
+        ok(fetched == 1, "%d: got %d\n", i, fetched);
+        ok(V_VT(&var) == VT_DISPATCH, "%d: got type %d\n", i, V_VT(&var));
+
+        hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFile, (void **)&file);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        str = NULL;
+        hr = IFile_get_Name(file, &str);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        if (!lstrcmpW(str, aW + 1))
+            found_a++;
+        else if (!lstrcmpW(str, bW + 1))
+            found_b++;
+        else if (!lstrcmpW(str, cW + 1))
+            found_c++;
+        else
+            ok(0, "unexpected file %s was found\n", wine_dbgstr_w(str));
+        SysFreeString(str);
+
+        IFile_Release(file);
+        VariantClear(&var);
+    }
+
+    ok(found_a == 1 && found_b == 1 && found_c == 1,
+       "each file should be found 1 time instead of %d/%d/%d\n",
+       found_a, found_b, found_c);
+
+    VariantInit(&var);
+    fetched = -1;
+    hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
+    ok(hr == S_FALSE, "got 0x%08x\n", hr);
+    ok(fetched == 0, "got %d\n", fetched);
+
+    hr = IEnumVARIANT_Reset(enumvar);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = IEnumVARIANT_Skip(enumvar, 2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = IEnumVARIANT_Skip(enumvar, 0);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    VariantInit(&var2[0]);
+    VariantInit(&var2[1]);
+    fetched = -1;
+    hr = IEnumVARIANT_Next(enumvar, 0, var2, &fetched);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(fetched == 0, "got %d\n", fetched);
+    fetched = -1;
+    hr = IEnumVARIANT_Next(enumvar, 2, var2, &fetched);
+    ok(hr == S_FALSE, "got 0x%08x\n", hr);
+    ok(fetched == 1, "got %d\n", fetched);
+    ok(V_VT(&var2[0]) == VT_DISPATCH, "got type %d\n", V_VT(&var2[0]));
+    VariantClear(&var2[0]);
+    VariantClear(&var2[1]);
+
+    IEnumVARIANT_Release(enumvar);
+    IUnknown_Release(unk);
+
+    CloseHandle(file_a);
+    CloseHandle(file_b);
+    CloseHandle(file_c);
+    RemoveDirectoryW(buffW);
+
+    IFileCollection_Release(files);
+}
+
+static void test_DriveCollection(void)
+{
+    IDriveCollection *drives;
+    IEnumVARIANT *enumvar;
+    ULONG fetched;
+    VARIANT var;
+    HRESULT hr;
+    LONG count;
+
+    hr = IFileSystem3_get_Drives(fs3, &drives);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IDriveCollection_get__NewEnum(drives, (IUnknown**)&enumvar);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IDriveCollection_get_Count(drives, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    count = 0;
+    hr = IDriveCollection_get_Count(drives, &count);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(count > 0, "got %d\n", count);
+
+    V_VT(&var) = VT_EMPTY;
+    fetched = -1;
+    hr = IEnumVARIANT_Next(enumvar, 0, &var, &fetched);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(fetched == 0, "got %d\n", fetched);
+
+    hr = IEnumVARIANT_Skip(enumvar, 0);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IEnumVARIANT_Skip(enumvar, count);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IEnumVARIANT_Skip(enumvar, 1);
+    ok(hr == S_FALSE, "got 0x%08x\n", hr);
+
+    /* reset and iterate again */
+    hr = IEnumVARIANT_Reset(enumvar);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    while (IEnumVARIANT_Next(enumvar, 1, &var, &fetched) == S_OK) {
+        IDrive *drive = (IDrive*)V_DISPATCH(&var);
+        DriveTypeConst type;
+        BSTR str;
+
+        hr = IDrive_get_DriveType(drive, &type);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        hr = IDrive_get_DriveLetter(drive, NULL);
+        ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+        hr = IDrive_get_DriveLetter(drive, &str);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok(SysStringLen(str) == 1, "got string %s\n", wine_dbgstr_w(str));
+        SysFreeString(str);
+
+        hr = IDrive_get_IsReady(drive, NULL);
+        ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+        hr = IDrive_get_TotalSize(drive, NULL);
+        ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+        hr = IDrive_get_AvailableSpace(drive, NULL);
+        ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+        hr = IDrive_get_FreeSpace(drive, NULL);
+        ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+        if (type == Fixed) {
+            VARIANT_BOOL ready = VARIANT_FALSE;
+            VARIANT size;
+
+            hr = IDrive_get_IsReady(drive, &ready);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(ready == VARIANT_TRUE, "got %x\n", ready);
+
+            V_VT(&size) = VT_EMPTY;
+            hr = IDrive_get_TotalSize(drive, &size);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
+            ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
+
+            V_VT(&size) = VT_EMPTY;
+            hr = IDrive_get_AvailableSpace(drive, &size);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
+            ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
+
+            V_VT(&size) = VT_EMPTY;
+            hr = IDrive_get_FreeSpace(drive, &size);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(V_VT(&size) == VT_R8, "got %d\n", V_VT(&size));
+            ok(V_R8(&size) > 0, "got %f\n", V_R8(&size));
+        }
+        VariantClear(&var);
+    }
+
+    IEnumVARIANT_Release(enumvar);
+    IDriveCollection_Release(drives);
+}
+
+static void test_CreateTextFile(void)
+{
+    static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
+    static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
+    static const WCHAR bomAW[] = {0xff,0xfe,0};
+    WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
+    ITextStream *stream;
+    BSTR nameW, str;
+    HANDLE file;
+    HRESULT hr;
+    BOOL ret;
+
+    GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
+    lstrcatW(pathW, scrrunW);
+    lstrcpyW(dirW, pathW);
+    lstrcatW(pathW, testfileW);
+
+    /* dir doesn't exist */
+    nameW = SysAllocString(pathW);
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
+    ok(hr == CTL_E_PATHNOTFOUND, "got 0x%08x\n", hr);
+
+    ret = CreateDirectoryW(dirW, NULL);
+    ok(ret, "got %d, %d\n", ret, GetLastError());
+
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = ITextStream_Read(stream, 1, &str);
+    ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+
+    ITextStream_Release(stream);
+
+    /* check it's created */
+    file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
+    CloseHandle(file);
+
+    /* try to create again with no-overwrite mode */
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
+    ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
+
+    /* now overwrite */
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ITextStream_Release(stream);
+
+    /* overwrite in Unicode mode, check for BOM */
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ITextStream_Release(stream);
+
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = ITextStream_ReadAll(stream, &str);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
+    ok(!lstrcmpW(str, bomAW), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+    ITextStream_Release(stream);
+
+    DeleteFileW(nameW);
+    RemoveDirectoryW(dirW);
+    SysFreeString(nameW);
+}
+
+static void test_WriteLine(void)
+{
+    static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
+    static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
+    WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
+    WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
+    char buffA[MAX_PATH];
+    ITextStream *stream;
+    DWORD r, len;
+    HANDLE file;
+    BSTR nameW;
+    HRESULT hr;
+    BOOL ret;
+
+    GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
+    lstrcatW(pathW, scrrunW);
+    lstrcpyW(dirW, pathW);
+    lstrcatW(pathW, testfileW);
+
+    ret = CreateDirectoryW(dirW, NULL);
+    ok(ret, "got %d, %d\n", ret, GetLastError());
+
+    /* create as ASCII file first */
+    nameW = SysAllocString(pathW);
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = ITextStream_WriteLine(stream, nameW);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ITextStream_Release(stream);
+
+    /* check contents */
+    file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
+    r = 0;
+    ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL);
+    ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
+
+    len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, sizeof(buffW)/sizeof(WCHAR));
+    buffW[len] = 0;
+    lstrcpyW(buff2W, nameW);
+    lstrcatW(buff2W, crlfW);
+    ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
+    CloseHandle(file);
+    DeleteFileW(nameW);
+
+    /* same for unicode file */
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = ITextStream_WriteLine(stream, nameW);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ITextStream_Release(stream);
+
+    /* check contents */
+    file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
+    r = 0;
+    ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL);
+    ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
+    buffW[r/sizeof(WCHAR)] = 0;
+
+    buff2W[0] = 0xfeff;
+    buff2W[1] = 0;
+    lstrcatW(buff2W, nameW);
+    lstrcatW(buff2W, crlfW);
+    ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
+    CloseHandle(file);
+    DeleteFileW(nameW);
+
+    RemoveDirectoryW(dirW);
+    SysFreeString(nameW);
+}
+
+static void test_ReadAll(void)
+{
+    static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
+    static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
+    static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
+    static const WCHAR aW[] = {'A',0};
+    WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
+    ITextStream *stream;
+    BSTR nameW;
+    HRESULT hr;
+    BOOL ret;
+    BSTR str;
+
+    GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
+    lstrcatW(pathW, scrrunW);
+    lstrcpyW(dirW, pathW);
+    lstrcatW(pathW, testfileW);
+
+    ret = CreateDirectoryW(dirW, NULL);
+    ok(ret, "got %d, %d\n", ret, GetLastError());
+
+    /* Unicode file -> read with ascii stream */
+    nameW = SysAllocString(pathW);
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = ITextStream_WriteLine(stream, nameW);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    str = SysAllocString(secondlineW);
+    hr = ITextStream_WriteLine(stream, str);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    SysFreeString(str);
+
+    hr = ITextStream_ReadAll(stream, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_ReadAll(stream, &str);
+    ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+    ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
+
+    ITextStream_Release(stream);
+
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = ITextStream_ReadAll(stream, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
+    str = NULL;
+    hr = ITextStream_ReadAll(stream, &str);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
+    ok(str[0] == 0x00ff && str[1] == 0x00fe, "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
+    SysFreeString(str);
+    ITextStream_Release(stream);
+
+    /* Unicode file -> read with unicode stream */
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    lstrcpyW(buffW, nameW);
+    lstrcatW(buffW, crlfW);
+    lstrcatW(buffW, secondlineW);
+    lstrcatW(buffW, crlfW);
+    str = NULL;
+    hr = ITextStream_ReadAll(stream, &str);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
+    ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+
+    /* ReadAll one more time */
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_ReadAll(stream, &str);
+    ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
+    ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
+
+    /* ReadLine fails the same way */
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_ReadLine(stream, &str);
+    ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
+    ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
+    ITextStream_Release(stream);
+
+    /* Open again and skip first line before ReadAll */
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    str = NULL;
+    hr = ITextStream_ReadLine(stream, &str);
+todo_wine {
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(str != NULL, "got %p\n", str);
+}
+    SysFreeString(str);
+
+    lstrcpyW(buffW, secondlineW);
+    lstrcatW(buffW, crlfW);
+    str = NULL;
+    hr = ITextStream_ReadAll(stream, &str);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
+todo_wine
+    ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+    ITextStream_Release(stream);
+
+    /* ASCII file, read with Unicode stream */
+    /* 1. one byte content, not enough for Unicode read */
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    str = SysAllocString(aW);
+    hr = ITextStream_Write(stream, str);
+    SysFreeString(str);
+    ITextStream_Release(stream);
+
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_ReadAll(stream, &str);
+    ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
+    ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
+
+    ITextStream_Release(stream);
+
+    DeleteFileW(nameW);
+    RemoveDirectoryW(dirW);
+    SysFreeString(nameW);
+}
+
+static void test_Read(void)
+{
+    static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
+    static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
+    static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
+    static const WCHAR aW[] = {'A',0};
+    WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
+    ITextStream *stream;
+    BSTR nameW;
+    HRESULT hr;
+    BOOL ret;
+    BSTR str;
+
+    GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
+    lstrcatW(pathW, scrrunW);
+    lstrcpyW(dirW, pathW);
+    lstrcatW(pathW, testfileW);
+
+    ret = CreateDirectoryW(dirW, NULL);
+    ok(ret, "got %d, %d\n", ret, GetLastError());
+
+    /* Unicode file -> read with ascii stream */
+    nameW = SysAllocString(pathW);
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = ITextStream_WriteLine(stream, nameW);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    str = SysAllocString(secondlineW);
+    hr = ITextStream_WriteLine(stream, str);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    SysFreeString(str);
+
+    hr = ITextStream_Read(stream, 0, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    hr = ITextStream_Read(stream, 1, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    hr = ITextStream_Read(stream, -1, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_Read(stream, 1, &str);
+    ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+    ok(str == NULL, "got %p\n", str);
+
+    ITextStream_Release(stream);
+
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = ITextStream_Read(stream, 1, NULL);
+    ok(hr == E_POINTER, "got 0x%08x\n", hr);
+
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_Read(stream, -1, &str);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(str == NULL, "got %p\n", str);
+
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_Read(stream, 0, &str);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(str == NULL, "got %p\n", str);
+
+    /* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
+    str = NULL;
+    hr = ITextStream_Read(stream, 2, &str);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(str[0] == 0x00ff && str[1] == 0x00fe, "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
+    ok(SysStringLen(str) == 2, "got %d\n", SysStringLen(str));
+    SysFreeString(str);
+    ITextStream_Release(stream);
+
+    /* Unicode file -> read with unicode stream */
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    lstrcpyW(buffW, nameW);
+    lstrcatW(buffW, crlfW);
+    lstrcatW(buffW, secondlineW);
+    lstrcatW(buffW, crlfW);
+    str = NULL;
+    hr = ITextStream_Read(stream, 500, &str);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
+    ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+
+    /* ReadAll one more time */
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_Read(stream, 10, &str);
+    ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
+    ok(str == NULL, "got %p\n", str);
+
+    /* ReadLine fails the same way */
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_ReadLine(stream, &str);
+    ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
+    ok(str == NULL || broken(str == (void*)0xdeadbeef), "got %p\n", str);
+    ITextStream_Release(stream);
+
+    /* Open again and skip first line before ReadAll */
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    str = NULL;
+    hr = ITextStream_ReadLine(stream, &str);
+todo_wine {
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(str != NULL, "got %p\n", str);
+}
+    SysFreeString(str);
+
+    lstrcpyW(buffW, secondlineW);
+    lstrcatW(buffW, crlfW);
+    str = NULL;
+    hr = ITextStream_Read(stream, 100, &str);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
+todo_wine
+    ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+    ITextStream_Release(stream);
+
+    /* ASCII file, read with Unicode stream */
+    /* 1. one byte content, not enough for Unicode read */
+    hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    str = SysAllocString(aW);
+    hr = ITextStream_Write(stream, str);
+    SysFreeString(str);
+    ITextStream_Release(stream);
+
+    hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    str = (void*)0xdeadbeef;
+    hr = ITextStream_Read(stream, 500, &str);
+    ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
+    ok(str == NULL, "got %p\n", str);
+
+    ITextStream_Release(stream);
+
+    DeleteFileW(nameW);
+    RemoveDirectoryW(dirW);
+    SysFreeString(nameW);
+}
+
 START_TEST(filesystem)
 {
     HRESULT hr;
 START_TEST(filesystem)
 {
     HRESULT hr;
@@ -674,6 +1741,15 @@ START_TEST(filesystem)
     test_GetAbsolutePathName();
     test_GetFile();
     test_CopyFolder();
     test_GetAbsolutePathName();
     test_GetFile();
     test_CopyFolder();
+    test_BuildPath();
+    test_GetFolder();
+    test_FolderCollection();
+    test_FileCollection();
+    test_DriveCollection();
+    test_CreateTextFile();
+    test_WriteLine();
+    test_ReadAll();
+    test_Read();
 
     IFileSystem3_Release(fs3);
 
 
     IFileSystem3_Release(fs3);
 
index 4b18af1..96835c7 100644 (file)
@@ -24,6 +24,7 @@ cpp_quote("#undef CopyFile")
 cpp_quote("#undef DeleteFile")
 cpp_quote("#undef MoveFile")
 cpp_quote("#endif")
 cpp_quote("#undef DeleteFile")
 cpp_quote("#undef MoveFile")
 cpp_quote("#endif")
+cpp_quote("#define CTL_E_ENDOFFILE STD_CTL_SCODE(62)") /* this is not defined in public headers */
 
 [
   uuid(420B2830-E718-11CF-893D-00A0C9054228),
 
 [
   uuid(420B2830-E718-11CF-893D-00A0C9054228),
@@ -33,23 +34,13 @@ library Scripting
 {
     importlib("stdole2.tlb");
 
 {
     importlib("stdole2.tlb");
 
-    interface IDictionary;
-    interface IDrive;
-    interface IDriveCollection;
-    interface IFile;
-    interface IFileCollection;
-    interface IFileSystem;
-    interface IFileSystem3;
     interface IFolder;
     interface IFolder;
-    interface IFolderCollection;
-    interface IScriptEncoder;
-    interface ITextStream;
 
     typedef enum CompareMethod
     {
 
     typedef enum CompareMethod
     {
-        BinaryCompare   = 0,
-        TextCompare     = 1,
-        DatabaseCompare = 2
+        BinaryCompare,
+        TextCompare,
+        DatabaseCompare
     } CompareMethod;
 
     typedef enum IOMode
     } CompareMethod;
 
     typedef enum IOMode
@@ -61,10 +52,10 @@ library Scripting
 
     typedef enum Tristate
     {
 
     typedef enum Tristate
     {
-        TristateTrue       = 0xffffffff,
-        TristateFalse      = 0,
-        TristateUseDefault = 0xfffffffe,
-        TristateMixed      = 0xfffffffe
+        TristateTrue       = -1,
+        TristateFalse      =  0,
+        TristateUseDefault = -2,
+        TristateMixed      = -2
     } Tristate;
 
     typedef enum FileAttribute
     } Tristate;
 
     typedef enum FileAttribute
@@ -82,26 +73,26 @@ library Scripting
 
     typedef enum SpecialFolderConst
     {
 
     typedef enum SpecialFolderConst
     {
-        WindowsFolder = 0,
-        SystemFolder = 1,
-        TemporaryFolder = 2
+        WindowsFolder,
+        SystemFolder,
+        TemporaryFolder
     } SpecialFolderConst;
 
     typedef enum DriveTypeConst
     {
     } SpecialFolderConst;
 
     typedef enum DriveTypeConst
     {
-        UnknownType = 0,
-        Removable = 1,
-        Fixed = 2,
-        Remote = 3,
-        CDRom = 4,
-        RamDisk = 5
+        UnknownType,
+        Removable,
+        Fixed,
+        Remote,
+        CDRom,
+        RamDisk
     } DriveTypeConst;
 
     typedef enum StandardStreamTypes
     {
     } DriveTypeConst;
 
     typedef enum StandardStreamTypes
     {
-        StdIn  = 0,
-        StdOut = 1,
-        StdErr = 2
+        StdIn,
+        StdOut,
+        StdErr
     } StandardStreamTypes;
 
     [
     } StandardStreamTypes;
 
     [
@@ -113,13 +104,13 @@ library Scripting
     ]
     interface IDictionary : IDispatch
     {
     ]
     interface IDictionary : IDispatch
     {
-        [id(00000000), propputref]
+        [id(DISPID_VALUE), propputref]
         HRESULT Item([in] VARIANT* Key, [in] VARIANT* pRetItem);
 
         HRESULT Item([in] VARIANT* Key, [in] VARIANT* pRetItem);
 
-        [id(00000000), propput]
+        [id(DISPID_VALUE), propput]
         HRESULT Item([in] VARIANT* Key, [in] VARIANT* pRetItem);
 
         HRESULT Item([in] VARIANT* Key, [in] VARIANT* pRetItem);
 
-        [id(00000000), propget]
+        [id(DISPID_VALUE), propget]
         HRESULT Item([in] VARIANT* Key, [out, retval] VARIANT* pRetItem);
 
         [id(0x00000001)]
         HRESULT Item([in] VARIANT* Key, [out, retval] VARIANT* pRetItem);
 
         [id(0x00000001)]
@@ -161,94 +152,52 @@ library Scripting
 
     [
       odl,
 
     [
       odl,
-      uuid(0AB5A3D0-E5B6-11D0-ABF5-00A0C90FFFC0),
+      uuid(C7C3F5A0-88A3-11D0-ABCB-00A0C90FFFC0),
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
-    interface IFileSystem : IDispatch
+    interface IDrive : IDispatch
     {
     {
-        [id(0x0000271a), propget]
-        HRESULT Drives([out, retval] IDriveCollection** ppdrives);
-
-        [id(0x00002710)]
-        HRESULT BuildPath([in] BSTR Path, [in] BSTR Name, [out, retval] BSTR* pbstrResult);
-
-        [id(0x00002714)]
-        HRESULT GetDriveName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
-
-        [id(0x00002715)]
-        HRESULT GetParentFolderName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
-
-        [id(0x00002716)]
-        HRESULT GetFileName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
-
-        [id(0x00002717)]
-        HRESULT GetBaseName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
-
-        [id(0x00002718)]
-        HRESULT GetExtensionName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
-
-        [id(0x00002712)]
-        HRESULT GetAbsolutePathName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
-
-        [id(0x00002713)]
-        HRESULT GetTempName([out, retval] BSTR* pbstrResult);
-
-        [id(0x0000271f)]
-        HRESULT DriveExists([in] BSTR DriveSpec, [out, retval] VARIANT_BOOL* pfExists);
-
-        [id(0x00002720)]
-        HRESULT FileExists([in] BSTR FileSpec, [out, retval] VARIANT_BOOL* pfExists);
-
-        [id(0x00002721)]
-        HRESULT FolderExists([in] BSTR FolderSpec, [out, retval] VARIANT_BOOL* pfExists);
-
-        [id(0x0000271b)]
-        HRESULT GetDrive([in] BSTR DriveSpec, [out, retval] IDrive** ppdrive);
+        [id(DISPID_VALUE), propget]
+        HRESULT Path([out, retval] BSTR* pbstrPath);
 
 
-        [id(0x0000271c)]
-        HRESULT GetFile([in] BSTR FilePath, [out, retval] IFile** ppfile);
+        [id(0x00002710), propget]
+        HRESULT DriveLetter([out, retval] BSTR* pbstrLetter);
 
 
-        [id(0x0000271d)]
-        HRESULT GetFolder([in] BSTR FolderPath, [out, retval] IFolder** ppfolder);
+        [id(0x00002711), propget]
+        HRESULT ShareName([out, retval] BSTR* pbstrShareName);
 
 
-        [id(0x0000271e)]
-        HRESULT GetSpecialFolder([in] SpecialFolderConst SpecialFolder, [out, retval] IFolder** ppfolder);
+        [id(0x00002712), propget]
+        HRESULT DriveType([out, retval] DriveTypeConst* pdt);
 
 
-        [id(0x000004b0)]
-        HRESULT DeleteFile([in] BSTR FileSpec, [in, optional, defaultvalue(0)] VARIANT_BOOL Force);
+        [id(0x00002713), propget]
+        HRESULT RootFolder([out, retval] IFolder** ppfolder);
 
 
-        [id(0x000004b1)]
-        HRESULT DeleteFolder([in] BSTR FolderSpec, [in, optional, defaultvalue(0)] VARIANT_BOOL Force);
+        [id(0x00002715), propget]
+        HRESULT AvailableSpace([out, retval] VARIANT* pvarAvail);
 
 
-        [id(0x000004b4), helpstring("Move a file"), helpcontext(0x00214bab)]
-        HRESULT MoveFile([in] BSTR Source, [in] BSTR Destination);
+        [id(0x00002714), propget]
+        HRESULT FreeSpace([out, retval] VARIANT* pvarFree);
 
 
-        [id(0x000004b5)]
-        HRESULT MoveFolder([in] BSTR Source, [in] BSTR Destination);
+        [id(0x00002716), propget]
+        HRESULT TotalSize([out, retval] VARIANT* pvarTotal);
 
 
-        [id(0x000004b2)]
-        HRESULT CopyFile([in] BSTR Source, [in] BSTR Destination,
-                         [in, optional, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+        [id(0x00002717), propget]
+        HRESULT VolumeName([out, retval] BSTR* pbstrName);
 
 
-        [id(0x000004b3)]
-        HRESULT CopyFolder([in] BSTR Source, [in] BSTR Destination,
-                           [in, optional, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+        [id(0x00002717), propput]
+        HRESULT VolumeName([in] BSTR pbstrName);
 
 
-        [id(0x00000460)]
-        HRESULT CreateFolder([in] BSTR Path, [out, retval] IFolder** ppfolder);
+        [id(0x00002718), propget]
+        HRESULT FileSystem([out, retval] BSTR* pbstrFileSystem);
 
 
-        [id(0x0000044d)]
-        HRESULT CreateTextFile([in] BSTR FileName, [in, optional, defaultvalue(-1)] VARIANT_BOOL Overwrite,
-                        [in, optional, defaultvalue(0)] VARIANT_BOOL Unicode, [out, retval] ITextStream** ppts);
+        [id(0x00002719), propget]
+        HRESULT SerialNumber([out, retval] long* pulSerialNumber);
 
 
-        [id(0x0000044c)]
-        HRESULT OpenTextFile([in] BSTR FileName, [in, optional, defaultvalue(1)] IOMode IOMode,
-                        [in, optional, defaultvalue(0)] VARIANT_BOOL Create,
-                        [in, optional, defaultvalue(0)] Tristate Format,
-                        [out, retval] ITextStream** ppts);
+        [id(0x0000271a), propget]
+        HRESULT IsReady([out, retval] VARIANT_BOOL* pfReady);
     }
 
     [
     }
 
     [
@@ -260,7 +209,7 @@ library Scripting
       oleautomation
     ]
     interface IDriveCollection : IDispatch {
       oleautomation
     ]
     interface IDriveCollection : IDispatch {
-        [id(00000000)]
+        [id(DISPID_VALUE), propget]
         HRESULT Item([in] VARIANT Key, [out, retval] IDrive** ppdrive);
 
         [id(DISPID_NEWENUM), propget, restricted, hidden]
         HRESULT Item([in] VARIANT Key, [out, retval] IDrive** ppdrive);
 
         [id(DISPID_NEWENUM), propget, restricted, hidden]
@@ -272,65 +221,65 @@ library Scripting
 
     [
       odl,
 
     [
       odl,
-      uuid(C7C3F5A0-88A3-11D0-ABCB-00A0C90FFFC0),
+      uuid(53BAD8C1-E718-11CF-893D-00A0C9054228),
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
-    interface IDrive : IDispatch
+    interface ITextStream : IDispatch
     {
     {
-        [id(00000000), propget]
-        HRESULT Path([out, retval] BSTR* pbstrPath);
-
         [id(0x00002710), propget]
         [id(0x00002710), propget]
-        HRESULT DriveLetter([out, retval] BSTR* pbstrLetter)
-;
-        [id(0x00002711), propget]
-        HRESULT ShareName([out, retval] BSTR* pbstrShareName);
+        HRESULT Line([out, retval] long* Line);
+
+        [id(0xfffffdef), propget]
+        HRESULT Column([out, retval] long* Column);
 
         [id(0x00002712), propget]
 
         [id(0x00002712), propget]
-        HRESULT DriveType([out, retval] DriveTypeConst* pdt);
+        HRESULT AtEndOfStream([out, retval] VARIANT_BOOL* EOS);
 
         [id(0x00002713), propget]
 
         [id(0x00002713), propget]
-        HRESULT RootFolder([out, retval] IFolder** ppfolder);
+        HRESULT AtEndOfLine([out, retval] VARIANT_BOOL* EOL);
 
 
-        [id(0x00002715), propget]
-        HRESULT AvailableSpace([out, retval] VARIANT* pvarAvail);
+        [id(0x00002714)]
+        HRESULT Read([in] long Characters, [out, retval] BSTR* Text);
 
 
-        [id(0x00002714), propget]
-        HRESULT FreeSpace([out, retval] VARIANT* pvarFree);
+        [id(0x00002715)]
+        HRESULT ReadLine([out, retval] BSTR* Text);
 
 
-        [id(0x00002716), propget]
-        HRESULT TotalSize([out, retval] VARIANT* pvarTotal);
+        [id(0x00002716)]
+        HRESULT ReadAll([out, retval] BSTR* Text);
 
 
-        [id(0x00002717), propget]
-        HRESULT VolumeName([out, retval] BSTR* pbstrName);
+        [id(0x00002717)]
+        HRESULT Write([in] BSTR Text);
 
 
-        [id(0x00002717), propput]
-        HRESULT VolumeName([in] BSTR pbstrName);
+        [id(0x00002718)]
+        HRESULT WriteLine([in, defaultvalue("")] BSTR Text);
 
 
-        [id(0x00002718), propget]
-        HRESULT FileSystem([out, retval] BSTR* pbstrFileSystem);
+        [id(0x00002719)]
+        HRESULT WriteBlankLines([in] long Lines);
 
 
-        [id(0x00002719), propget]
-        HRESULT SerialNumber([out, retval] long* pulSerialNumber);
+        [id(0x0000271a)]
+        HRESULT Skip([in] long Characters);
 
 
-        [id(0x0000271a), propget]
-        HRESULT IsReady([out, retval] VARIANT_BOOL* pfReady);
+        [id(0x0000271b)]
+        HRESULT SkipLine();
+
+        [id(0x0000271c)]
+        HRESULT Close();
     }
 
     [
       odl,
     }
 
     [
       odl,
-      uuid(C7C3F5A2-88A3-11D0-ABCB-00A0C90FFFC0),
+      uuid(C7C3F5A4-88A3-11D0-ABCB-00A0C90FFFC0),
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
-    interface IFolder : IDispatch
+    interface IFile : IDispatch
     {
     {
-        [id(00000000), propget]
+        [id(DISPID_VALUE), propget]
         HRESULT Path([out, retval] BSTR* pbstrPath);
 
         [id(0x000003e8), propget]
         HRESULT Path([out, retval] BSTR* pbstrPath);
 
         [id(0x000003e8), propget]
@@ -366,50 +315,130 @@ library Scripting
         [id(0x000003f0), propget]
         HRESULT DateLastAccessed([out, retval] DATE* pdate);
 
         [id(0x000003f0), propget]
         HRESULT DateLastAccessed([out, retval] DATE* pdate);
 
+        [id(0x000003f1), propget]
+        HRESULT Size([out, retval] VARIANT* pvarSize);
+
         [id(0x000003f2), propget]
         HRESULT Type([out, retval] BSTR* pbstrType);
 
         [id(0x000003f2), propget]
         HRESULT Type([out, retval] BSTR* pbstrType);
 
-        [id(0x000004b1)]
-        HRESULT Delete([in, optional, defaultvalue(0)] VARIANT_BOOL Force);
+        [id(0x000004b0)]
+        HRESULT Delete([in, defaultvalue(0)] VARIANT_BOOL Force);
 
 
-        [id(0x000004b3)]
-        HRESULT Copy([in] BSTR Destination, [in, optional, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+        [id(0x000004b2)]
+        HRESULT Copy([in] BSTR Destination, [in, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
 
 
-        [id(0x000004b5)]
+        [id(0x000004b4)]
         HRESULT Move([in] BSTR Destination);
 
         HRESULT Move([in] BSTR Destination);
 
-        [id(0x00002710), propget]
-        HRESULT IsRootFolder([out, retval] VARIANT_BOOL* pfRootFolder);
+        [id(0x0000044c)]
+        HRESULT OpenAsTextStream([in, defaultvalue(1)] IOMode IOMode,
+                        [in, defaultvalue(0)] Tristate Format, [out, retval] ITextStream** ppts);
+    }
 
 
-        [id(0x000003f1), propget]
-        HRESULT Size([out, retval] VARIANT* pvarSize);
+    [
+      odl,
+      uuid(0AB5A3D0-E5B6-11D0-ABF5-00A0C90FFFC0),
+      hidden,
+      dual,
+      nonextensible,
+      oleautomation
+    ]
+    interface IFileSystem : IDispatch
+    {
+        [id(0x0000271a), propget]
+        HRESULT Drives([out, retval] IDriveCollection** ppdrives);
 
 
-        [id(0x00002711), propget]
-        HRESULT SubFolders([out, retval] IFolderCollection** ppfolders);
+        [id(0x00002710)]
+        HRESULT BuildPath([in] BSTR Path, [in] BSTR Name, [out, retval] BSTR* pbstrResult);
 
 
-        [id(0x00002712), propget]
-        HRESULT Files([out, retval] IFileCollection** ppfiles);
+        [id(0x00002714)]
+        HRESULT GetDriveName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
+
+        [id(0x00002715)]
+        HRESULT GetParentFolderName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
+
+        [id(0x00002716)]
+        HRESULT GetFileName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
+
+        [id(0x00002717)]
+        HRESULT GetBaseName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
+
+        [id(0x00002718)]
+        HRESULT GetExtensionName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
+
+        [id(0x00002712)]
+        HRESULT GetAbsolutePathName([in] BSTR Path, [out, retval] BSTR* pbstrResult);
+
+        [id(0x00002713)]
+        HRESULT GetTempName([out, retval] BSTR* pbstrResult);
+
+        [id(0x0000271f)]
+        HRESULT DriveExists([in] BSTR DriveSpec, [out, retval] VARIANT_BOOL* pfExists);
+
+        [id(0x00002720)]
+        HRESULT FileExists([in] BSTR FileSpec, [out, retval] VARIANT_BOOL* pfExists);
+
+        [id(0x00002721)]
+        HRESULT FolderExists([in] BSTR FolderSpec, [out, retval] VARIANT_BOOL* pfExists);
+
+        [id(0x0000271b)]
+        HRESULT GetDrive([in] BSTR DriveSpec, [out, retval] IDrive** ppdrive);
+
+        [id(0x0000271c)]
+        HRESULT GetFile([in] BSTR FilePath, [out, retval] IFile** ppfile);
+
+        [id(0x0000271d)]
+        HRESULT GetFolder([in] BSTR FolderPath, [out, retval] IFolder** ppfolder);
+
+        [id(0x0000271e)]
+        HRESULT GetSpecialFolder([in] SpecialFolderConst SpecialFolder, [out, retval] IFolder** ppfolder);
+
+        [id(0x000004b0)]
+        HRESULT DeleteFile([in] BSTR FileSpec, [in, defaultvalue(0)] VARIANT_BOOL Force);
+
+        [id(0x000004b1)]
+        HRESULT DeleteFolder([in] BSTR FolderSpec, [in, defaultvalue(0)] VARIANT_BOOL Force);
+
+        [id(0x000004b4), helpstring("Move a file"), helpcontext(0x00214bab)]
+        HRESULT MoveFile([in] BSTR Source, [in] BSTR Destination);
+
+        [id(0x000004b5)]
+        HRESULT MoveFolder([in] BSTR Source, [in] BSTR Destination);
+
+        [id(0x000004b2)]
+        HRESULT CopyFile([in] BSTR Source, [in] BSTR Destination,
+                         [in, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+
+        [id(0x000004b3)]
+        HRESULT CopyFolder([in] BSTR Source, [in] BSTR Destination,
+                           [in, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+
+        [id(0x00000460)]
+        HRESULT CreateFolder([in] BSTR Path, [out, retval] IFolder** ppfolder);
 
         [id(0x0000044d)]
 
         [id(0x0000044d)]
-        HRESULT CreateTextFile([in] BSTR FileName, [in, optional, defaultvalue(-1)] VARIANT_BOOL Overwrite,
-                        [in, optional, defaultvalue(0)] VARIANT_BOOL Unicode, [out, retval] ITextStream** ppts);
+        HRESULT CreateTextFile([in] BSTR FileName, [in, defaultvalue(-1)] VARIANT_BOOL Overwrite,
+                        [in, defaultvalue(0)] VARIANT_BOOL Unicode, [out, retval] ITextStream** ppts);
+
+        [id(0x0000044c)]
+        HRESULT OpenTextFile([in] BSTR FileName, [in, defaultvalue(1)] IOMode IOMode,
+                        [in, defaultvalue(0)] VARIANT_BOOL Create,
+                        [in, defaultvalue(0)] Tristate Format,
+                        [out, retval] ITextStream** ppts);
     }
 
     [
       odl,
     }
 
     [
       odl,
-      uuid(C7C3F5A3-88A3-11D0-ABCB-00A0C90FFFC0),
+      uuid(C7C3F5A5-88A3-11D0-ABCB-00A0C90FFFC0),
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
-    interface IFolderCollection : IDispatch
+    interface IFileCollection : IDispatch
     {
     {
-        [id(0x00000002)]
-        HRESULT Add([in] BSTR Name, [out, retval] IFolder** ppfolder);
-
-        [id(00000000), propget]
-        HRESULT Item([in] VARIANT Key, [out, retval] IFolder** ppfolder);
+        [id(DISPID_VALUE), propget]
+        HRESULT Item([in] VARIANT Key, [out, retval] IFile** ppfile);
 
         [id(DISPID_NEWENUM), propget, restricted, hidden]
         HRESULT _NewEnum([out, retval] IUnknown** ppenum);
 
         [id(DISPID_NEWENUM), propget, restricted, hidden]
         HRESULT _NewEnum([out, retval] IUnknown** ppenum);
@@ -420,16 +449,19 @@ library Scripting
 
     [
       odl,
 
     [
       odl,
-      uuid(C7C3F5A5-88A3-11D0-ABCB-00A0C90FFFC0),
+      uuid(C7C3F5A3-88A3-11D0-ABCB-00A0C90FFFC0),
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
-    interface IFileCollection : IDispatch
+    interface IFolderCollection : IDispatch
     {
     {
-        [id(00000000), propget]
-        HRESULT Item([in] VARIANT Key, [out, retval] IFile** ppfile);
+        [id(0x00000002)]
+        HRESULT Add([in] BSTR Name, [out, retval] IFolder** ppfolder);
+
+        [id(DISPID_VALUE), propget]
+        HRESULT Item([in] VARIANT Key, [out, retval] IFolder** ppfolder);
 
         [id(DISPID_NEWENUM), propget, restricted, hidden]
         HRESULT _NewEnum([out, retval] IUnknown** ppenum);
 
         [id(DISPID_NEWENUM), propget, restricted, hidden]
         HRESULT _NewEnum([out, retval] IUnknown** ppenum);
@@ -440,15 +472,15 @@ library Scripting
 
     [
       odl,
 
     [
       odl,
-      uuid(C7C3F5A4-88A3-11D0-ABCB-00A0C90FFFC0),
+      uuid(C7C3F5A2-88A3-11D0-ABCB-00A0C90FFFC0),
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
       hidden,
       dual,
       nonextensible,
       oleautomation
     ]
-    interface IFile : IDispatch
+    interface IFolder : IDispatch
     {
     {
-        [id(00000000), propget]
+        [id(DISPID_VALUE), propget]
         HRESULT Path([out, retval] BSTR* pbstrPath);
 
         [id(0x000003e8), propget]
         HRESULT Path([out, retval] BSTR* pbstrPath);
 
         [id(0x000003e8), propget]
@@ -484,74 +516,33 @@ library Scripting
         [id(0x000003f0), propget]
         HRESULT DateLastAccessed([out, retval] DATE* pdate);
 
         [id(0x000003f0), propget]
         HRESULT DateLastAccessed([out, retval] DATE* pdate);
 
-        [id(0x000003f1), propget]
-        HRESULT Size([out, retval] VARIANT* pvarSize);
-
         [id(0x000003f2), propget]
         HRESULT Type([out, retval] BSTR* pbstrType);
 
         [id(0x000003f2), propget]
         HRESULT Type([out, retval] BSTR* pbstrType);
 
-        [id(0x000004b0)]
-        HRESULT Delete([in, optional, defaultvalue(0)] VARIANT_BOOL Force);
+        [id(0x000004b1)]
+        HRESULT Delete([in, defaultvalue(0)] VARIANT_BOOL Force);
 
 
-        [id(0x000004b2)]
-        HRESULT Copy([in] BSTR Destination, [in, optional, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
+        [id(0x000004b3)]
+        HRESULT Copy([in] BSTR Destination, [in, defaultvalue(-1)] VARIANT_BOOL OverWriteFiles);
 
 
-        [id(0x000004b4)]
+        [id(0x000004b5)]
         HRESULT Move([in] BSTR Destination);
 
         HRESULT Move([in] BSTR Destination);
 
-        [id(0x0000044c)]
-        HRESULT OpenAsTextStream([in, optional, defaultvalue(1)] IOMode IOMode,
-                        [in, optional, defaultvalue(0)] Tristate Format, [out, retval] ITextStream** ppts);
-    }
-
-    [
-      odl,
-      uuid(53BAD8C1-E718-11CF-893D-00A0C9054228),
-      hidden,
-      dual,
-      nonextensible,
-      oleautomation
-    ]
-    interface ITextStream : IDispatch
-    {
         [id(0x00002710), propget]
         [id(0x00002710), propget]
-        HRESULT Line([out, retval] long* Line);
-
-        [id(0xfffffdef), propget]
-        HRESULT Column([out, retval] long* Column);
-
-        [id(0x00002712), propget]
-        HRESULT AtEndOfStream([out, retval] VARIANT_BOOL* EOS);
-
-        [id(0x00002713), propget]
-        HRESULT AtEndOfLine([out, retval] VARIANT_BOOL* EOL);
-
-        [id(0x00002714)]
-        HRESULT Read([in] long Characters, [out, retval] BSTR* Text);
-
-        [id(0x00002715)]
-        HRESULT ReadLine([out, retval] BSTR* Text);
-
-        [id(0x00002716)]
-        HRESULT ReadAll([out, retval] BSTR* Text);
-
-        [id(0x00002717)]
-        HRESULT Write([in] BSTR Text);
-
-        [id(0x00002718)]
-        HRESULT WriteLine([in, optional, defaultvalue("")] BSTR Text);
+        HRESULT IsRootFolder([out, retval] VARIANT_BOOL* pfRootFolder);
 
 
-        [id(0x00002719)]
-        HRESULT WriteBlankLines([in] long Lines);
+        [id(0x000003f1), propget]
+        HRESULT Size([out, retval] VARIANT* pvarSize);
 
 
-        [id(0x0000271a)]
-        HRESULT Skip([in] long Characters);
+        [id(0x00002711), propget]
+        HRESULT SubFolders([out, retval] IFolderCollection** ppfolders);
 
 
-        [id(0x0000271b)]
-        HRESULT SkipLine();
+        [id(0x00002712), propget]
+        HRESULT Files([out, retval] IFileCollection** ppfiles);
 
 
-        [id(0x0000271c)]
-        HRESULT Close();
+        [id(0x0000044d)]
+        HRESULT CreateTextFile([in] BSTR FileName, [in, defaultvalue(-1)] VARIANT_BOOL Overwrite,
+                        [in, defaultvalue(0)] VARIANT_BOOL Unicode, [out, retval] ITextStream** ppts);
     }
 
     [
     }
 
     [
@@ -565,7 +556,7 @@ library Scripting
     {
         [id(0x00004e20)]
         HRESULT GetStandardStream([in] StandardStreamTypes StandardStreamType,
     {
         [id(0x00004e20)]
         HRESULT GetStandardStream([in] StandardStreamTypes StandardStreamType,
-                        [in, optional, defaultvalue(0)] VARIANT_BOOL Unicode, [out, retval] ITextStream** ppts);
+                        [in, defaultvalue(0)] VARIANT_BOOL Unicode, [out, retval] ITextStream** ppts);
 
         [id(0x00004e2a)]
         HRESULT GetFileVersion([in] BSTR FileName, [out, retval] BSTR* FileVersion);
 
         [id(0x00004e2a)]
         HRESULT GetFileVersion([in] BSTR FileName, [out, retval] BSTR* FileVersion);
@@ -579,7 +570,7 @@ library Scripting
     ]
     interface IScriptEncoder : IDispatch
     {
     ]
     interface IScriptEncoder : IDispatch
     {
-        [id(00000000)]
+        [id(DISPID_VALUE)]
         HRESULT EncodeScriptFile([in] BSTR szExt, [in] BSTR bstrStreamIn, [in] long cFlags,
                         [in] BSTR bstrDefaultLang, [out, retval] BSTR* pbstrStreamOut);
     }
         HRESULT EncodeScriptFile([in] BSTR szExt, [in] BSTR bstrStreamIn, [in] long cFlags,
                         [in] BSTR bstrDefaultLang, [out, retval] BSTR* pbstrStreamOut);
     }