Nikolay Sivov : scrrun: Implement Next() for folder collection.

Alexandre Julliard julliard at winehq.org
Mon Jan 6 14:47:12 CST 2014


Module: wine
Branch: master
Commit: b99b69aac228a48bf1432a9409d0adbb620cba6a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b99b69aac228a48bf1432a9409d0adbb620cba6a

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Jan  6 01:22:08 2014 +0400

scrrun: Implement Next() for folder collection.

---

 dlls/scrrun/filesystem.c       |  101 ++++++++++++++++++++++++++++++++++++++--
 dlls/scrrun/tests/filesystem.c |   16 ++++++-
 2 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c
index fa53950..81d6a07 100644
--- a/dlls/scrrun/filesystem.c
+++ b/dlls/scrrun/filesystem.c
@@ -36,6 +36,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(scrrun);
 
+static const WCHAR bsW[] = {'\\',0};
+
 struct enumdata {
     union
     {
@@ -125,6 +127,31 @@ static inline HRESULT create_error(DWORD err)
     }
 }
 
+static HRESULT create_folder(const WCHAR*, IFolder**);
+
+static inline BOOL is_dir_data(const WIN32_FIND_DATAW *data)
+{
+    static const WCHAR dotdotW[] = {'.','.',0};
+    static const WCHAR dotW[] = {'.',0};
+
+    return (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+            strcmpW(data->cFileName, dotdotW) &&
+            strcmpW(data->cFileName, dotW);
+}
+
+static BSTR get_full_path(BSTR path, const WIN32_FIND_DATAW *data)
+{
+    int len = SysStringLen(path);
+    WCHAR buffW[MAX_PATH];
+
+    strcpyW(buffW, path);
+    if (path[len-1] != '\\')
+        strcatW(buffW, bsW);
+    strcatW(buffW, data->cFileName);
+
+    return SysAllocString(buffW);
+}
+
 static BOOL textstream_check_iomode(struct textstream *This, enum iotype type)
 {
     if (type == IORead)
@@ -421,8 +448,75 @@ static ULONG WINAPI foldercoll_enumvariant_Release(IEnumVARIANT *iface)
 static HRESULT WINAPI foldercoll_enumvariant_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *var, ULONG *fetched)
 {
     struct enumvariant *This = impl_from_IEnumVARIANT(iface);
-    FIXME("(%p)->(%d %p %p): stub\n", This, celt, var, fetched);
-    return E_NOTIMPL;
+    HANDLE handle = This->data.u.foldercoll.find;
+    WIN32_FIND_DATAW data;
+    ULONG count = 0;
+
+    TRACE("(%p)->(%d %p %p)\n", This, celt, var, fetched);
+
+    if (fetched)
+        *fetched = 0;
+
+    if (!handle)
+    {
+        static const WCHAR allW[] = {'*',0};
+        WCHAR pathW[MAX_PATH];
+        BSTR parent = This->data.u.foldercoll.path;
+        int len;
+
+        strcpyW(pathW, parent);
+        len = SysStringLen(parent);
+        if (parent[len-1] != '\\')
+            strcatW(pathW, bsW);
+        strcatW(pathW, allW);
+        handle = FindFirstFileW(pathW, &data);
+        if (handle == INVALID_HANDLE_VALUE)
+            return S_FALSE;
+
+        /* find first dir */
+        while (1)
+        {
+            if (is_dir_data(&data))
+                break;
+            else
+                if (!FindNextFileW(handle, &data))
+                {
+                    FindClose(handle);
+                    return S_FALSE;
+                }
+        }
+
+        This->data.u.foldercoll.find = handle;
+    }
+
+    do
+    {
+        if (count >= celt) break;
+
+        if (is_dir_data(&data))
+        {
+            IFolder *folder;
+            HRESULT hr;
+            BSTR str;
+
+            str = get_full_path(This->data.u.foldercoll.path, &data);
+            hr = create_folder(str, &folder);
+            SysFreeString(str);
+            if (FAILED(hr)) return hr;
+
+            V_VT(&var[count]) = VT_DISPATCH;
+            V_DISPATCH(&var[count]) = (IDispatch*)folder;
+            count++;
+        }
+    } while (FindNextFileW(handle, &data));
+
+    if (count < celt)
+        return S_FALSE;
+
+    if (fetched)
+        *fetched = count;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI foldercoll_enumvariant_Skip(IEnumVARIANT *iface, ULONG celt)
@@ -972,7 +1066,7 @@ static const IFolderVtbl foldervtbl = {
     folder_CreateTextFile
 };
 
-static HRESULT create_folder(BSTR path, IFolder **folder)
+HRESULT create_folder(const WCHAR *path, IFolder **folder)
 {
     struct folder *This;
 
@@ -1466,7 +1560,6 @@ static HRESULT WINAPI filesys_BuildPath(IFileSystem3 *iface, BSTR Path,
         }
         else if (Path[path_len-1] != '\\' && Name[0] != '\\')
         {
-            static const WCHAR bsW[] = {'\\',0};
             ret = SysAllocStringLen(NULL, path_len + name_len + 1);
             if (ret)
             {
diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c
index be5131c..6d1b913 100644
--- a/dlls/scrrun/tests/filesystem.c
+++ b/dlls/scrrun/tests/filesystem.c
@@ -794,6 +794,8 @@ static void test_FolderCollection(void)
     LONG count, count2, ref, ref2;
     IUnknown *unk, *unk2;
     IFolder *folder;
+    ULONG fetched;
+    VARIANT var;
     HRESULT hr;
     BSTR str;
 
@@ -813,6 +815,7 @@ static void test_FolderCollection(void)
 
     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);
@@ -870,6 +873,18 @@ if (hr == S_OK) {
     hr = IEnumVARIANT_Reset(enumvar);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    VariantInit(&var);
+    fetched = 0;
+    hr = IEnumVARIANT_Next(enumvar, 1, &var, &fetched);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(fetched == 1, "got %d\n", fetched);
+    ok(V_VT(&var) == VT_DISPATCH, "got type %d\n", V_VT(&var));
+
+    hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IFolder, (void**)&folder);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IFolder_Release(folder);
+    VariantClear(&var);
+
     IEnumVARIANT_Release(enumvar);
     IUnknown_Release(unk);
 
@@ -877,7 +892,6 @@ if (hr == S_OK) {
     RemoveDirectoryW(path2W);
 
     IFolderCollection_Release(folders);
-    IFolder_Release(folder);
 }
 
 START_TEST(filesystem)




More information about the wine-cvs mailing list