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

Alexandre Julliard julliard at winehq.org
Tue Jan 7 13:21:17 CST 2014


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Jan  7 03:25:02 2014 +0400

scrrun: Implement Next() for file collection.

---

 dlls/scrrun/filesystem.c |   99 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 95 insertions(+), 4 deletions(-)

diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c
index 94d894f..eb75a1f 100644
--- a/dlls/scrrun/filesystem.c
+++ b/dlls/scrrun/filesystem.c
@@ -50,6 +50,8 @@ struct enumdata {
         struct
         {
             IFileCollection *coll;
+            HANDLE find;
+            BSTR path;
         } filecoll;
     } u;
 };
@@ -70,6 +72,7 @@ struct foldercollection {
 struct filecollection {
     IFileCollection IFileCollection_iface;
     LONG ref;
+    BSTR path;
 };
 
 struct folder {
@@ -142,6 +145,7 @@ static inline HRESULT create_error(DWORD err)
 }
 
 static HRESULT create_folder(const WCHAR*, IFolder**);
+static HRESULT create_file(BSTR, IFile**);
 
 static inline BOOL is_dir_data(const WIN32_FIND_DATAW *data)
 {
@@ -153,6 +157,11 @@ static inline BOOL is_dir_data(const WIN32_FIND_DATAW *data)
             strcmpW(data->cFileName, dotW);
 }
 
+static inline BOOL is_file_data(const WIN32_FIND_DATAW *data)
+{
+    return !(data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+}
+
 static BSTR get_full_path(BSTR path, const WIN32_FIND_DATAW *data)
 {
     int len = SysStringLen(path);
@@ -606,6 +615,7 @@ static ULONG WINAPI filecoll_enumvariant_Release(IEnumVARIANT *iface)
     if (!ref)
     {
         IFileCollection_Release(This->data.u.filecoll.coll);
+        SysFreeString(This->data.u.filecoll.path);
         heap_free(This);
     }
 
@@ -615,8 +625,74 @@ static ULONG WINAPI filecoll_enumvariant_Release(IEnumVARIANT *iface)
 static HRESULT WINAPI filecoll_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.filecoll.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.filecoll.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;
+
+        while (1)
+        {
+            if (is_file_data(&data))
+                break;
+            else
+                if (!FindNextFileW(handle, &data))
+                {
+                    FindClose(handle);
+                    return S_FALSE;
+                }
+        }
+
+        This->data.u.filecoll.find = handle;
+    }
+
+    do
+    {
+        if (count >= celt) break;
+
+        if (is_file_data(&data))
+        {
+            IFile *file;
+            HRESULT hr;
+            BSTR str;
+
+            str = get_full_path(This->data.u.filecoll.path, &data);
+            hr = create_file(str, &file);
+            SysFreeString(str);
+            if (FAILED(hr)) return hr;
+
+            V_VT(&var[count]) = VT_DISPATCH;
+            V_DISPATCH(&var[count]) = (IDispatch*)file;
+            count++;
+        }
+    } while (FindNextFileW(handle, &data));
+
+    if (count < celt)
+        return S_FALSE;
+
+    if (fetched)
+        *fetched = count;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI filecoll_enumvariant_Skip(IEnumVARIANT *iface, ULONG celt)
@@ -661,6 +737,12 @@ static HRESULT create_filecoll_enum(struct filecollection *collection, IUnknown
 
     This->IEnumVARIANT_iface.lpVtbl = &filecollenumvariantvtbl;
     This->ref = 1;
+    This->data.u.filecoll.path = SysAllocString(collection->path);
+    if (!This->data.u.filecoll.path)
+    {
+        heap_free(This);
+        return E_OUTOFMEMORY;
+    }
 
     This->data.u.filecoll.coll = &collection->IFileCollection_iface;
     IFileCollection_AddRef(This->data.u.filecoll.coll);
@@ -903,7 +985,10 @@ static ULONG WINAPI filecoll_Release(IFileCollection *iface)
     TRACE("(%p)->(%d)\n", This, ref);
 
     if (!ref)
+    {
+        SysFreeString(This->path);
         heap_free(This);
+    }
 
     return ref;
 }
@@ -1006,7 +1091,7 @@ static const IFileCollectionVtbl filecollectionvtbl = {
     filecoll_get_Count
 };
 
-static HRESULT create_filecoll(IFileCollection **files)
+static HRESULT create_filecoll(BSTR path, IFileCollection **files)
 {
     struct filecollection *This;
 
@@ -1017,6 +1102,12 @@ static HRESULT create_filecoll(IFileCollection **files)
 
     This->IFileCollection_iface.lpVtbl = &filecollectionvtbl;
     This->ref = 1;
+    This->path = SysAllocString(path);
+    if (!This->path)
+    {
+        heap_free(This);
+        return E_OUTOFMEMORY;
+    }
 
     *files = &This->IFileCollection_iface;
     return S_OK;
@@ -1290,7 +1381,7 @@ static HRESULT WINAPI folder_get_Files(IFolder *iface, IFileCollection **files)
     if(!files)
         return E_POINTER;
 
-    return create_filecoll(files);
+    return create_filecoll(This->path, files);
 }
 
 static HRESULT WINAPI folder_CreateTextFile(IFolder *iface, BSTR filename, VARIANT_BOOL overwrite,




More information about the wine-cvs mailing list