[PATCH v12 2/3] shell32: Implement FolderItems_Item.
Alex Henrie
alexhenrie24 at gmail.com
Fri Sep 9 01:02:23 CDT 2016
Cc: Sebastian Lackner <sebastian at fds-team.de>
v12 fixes a compilation error that I somehow missed.
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
dlls/shell32/shell32_main.h | 9 +++
dlls/shell32/shelldispatch.c | 140 +++++++++++++++++++++++++++++++++++--
dlls/shell32/shelllink.c | 10 ---
dlls/shell32/tests/shelldispatch.c | 21 ------
4 files changed, 143 insertions(+), 37 deletions(-)
diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h
index 8cd1318..d1ad0cd 100644
--- a/dlls/shell32/shell32_main.h
+++ b/dlls/shell32/shell32_main.h
@@ -164,6 +164,15 @@ static inline WCHAR * __SHCloneStrAtoW(WCHAR ** target, const char * source)
return *target;
}
+static inline WCHAR * strdupW( const WCHAR *src )
+{
+ WCHAR *dst;
+ if (!src) return NULL;
+ dst = HeapAlloc(GetProcessHeap(), 0, (strlenW(src)+1)*sizeof(WCHAR));
+ if (dst) strcpyW(dst, src);
+ return dst;
+}
+
extern WCHAR swShell32Name[MAX_PATH] DECLSPEC_HIDDEN;
diff --git a/dlls/shell32/shelldispatch.c b/dlls/shell32/shelldispatch.c
index ac79302..0aa9bf0 100644
--- a/dlls/shell32/shelldispatch.c
+++ b/dlls/shell32/shelldispatch.c
@@ -68,6 +68,9 @@ typedef struct {
typedef struct {
FolderItems3 FolderItems3_iface;
LONG ref;
+ VARIANT dir;
+ WCHAR **item_filenames;
+ LONG item_count;
} FolderItemsImpl;
typedef struct {
@@ -989,11 +992,18 @@ static ULONG WINAPI FolderItemsImpl_Release(FolderItems3 *iface)
{
FolderItemsImpl *This = impl_from_FolderItems(iface);
ULONG ref = InterlockedDecrement(&This->ref);
+ LONG i;
TRACE("(%p), new refcount=%i\n", iface, ref);
if (!ref)
+ {
+ VariantClear(&This->dir);
+ for (i = 0; i < This->item_count; i++)
+ HeapFree(GetProcessHeap(), 0, This->item_filenames[i]);
+ HeapFree(GetProcessHeap(), 0, This->item_filenames);
HeapFree(GetProcessHeap(), 0, This);
+ }
return ref;
}
@@ -1079,10 +1089,57 @@ static HRESULT WINAPI FolderItemsImpl_get_Parent(FolderItems3 *iface, IDispatch
static HRESULT WINAPI FolderItemsImpl_Item(FolderItems3 *iface, VARIANT index, FolderItem **ppid)
{
- FIXME("(%p,%s,%p)\n", iface, debugstr_variant(&index), ppid);
+ FolderItemsImpl *This = impl_from_FolderItems(iface);
+ WCHAR path_str[MAX_PATH];
+ VARIANT path_var;
+ HRESULT ret;
+
+ TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&index), ppid);
*ppid = NULL;
- return E_NOTIMPL;
+
+ if (!PathIsDirectoryW(V_BSTR(&This->dir)))
+ return S_FALSE;
+
+ switch (V_VT(&index))
+ {
+ case VT_I2:
+ VariantChangeType(&index, &index, 0, VT_I4);
+ /* fall through */
+
+ case VT_I4:
+ if (V_I4(&index) >= This->item_count || V_I4(&index) < 0)
+ return S_FALSE;
+
+ if (!PathCombineW(path_str, V_BSTR(&This->dir), This->item_filenames[V_I4(&index)]))
+ return E_OUTOFMEMORY;
+
+ break;
+
+ case VT_BSTR:
+ if (!V_BSTR(&index))
+ return S_FALSE;
+
+ if (!PathCombineW(path_str, V_BSTR(&This->dir), V_BSTR(&index)))
+ return E_OUTOFMEMORY;
+
+ if (!PathFileExistsW(path_str))
+ return S_FALSE;
+
+ break;
+
+ case VT_ERROR:
+ return FolderItem_Constructor(&This->dir, ppid);
+
+ default:
+ return E_NOTIMPL;
+ }
+
+ V_VT(&path_var) = VT_BSTR;
+ V_BSTR(&path_var) = SysAllocString(path_str);
+ ret = FolderItem_Constructor(&path_var, ppid);
+ VariantClear(&path_var);
+ return ret;
}
static HRESULT WINAPI FolderItemsImpl__NewEnum(FolderItems3 *iface, IUnknown **ppunk)
@@ -1139,21 +1196,90 @@ static const FolderItems3Vtbl FolderItemsImpl_Vtbl = {
FolderItemsImpl_get_Verbs
};
-static HRESULT FolderItems_Constructor(FolderItems **ppfi)
+static HRESULT FolderItems_Constructor(VARIANT *dir, FolderItems **ppfi)
{
+ static const WCHAR backslash_star[] = {'\\','*',0};
+ static const WCHAR dot[] = {'.',0};
+ static const WCHAR dot_dot[] = {'.','.',0};
FolderItemsImpl *This;
+ LONG item_size;
+ WCHAR glob[MAX_PATH + 2];
+ HANDLE first_file;
+ WIN32_FIND_DATAW file_info;
+ WCHAR **filenames;
+ HRESULT ret;
- TRACE("\n");
+ TRACE("(%s,%p)\n", debugstr_variant(dir), ppfi);
*ppfi = NULL;
+ if (V_VT(dir) == VT_I4)
+ {
+ FIXME("special folder constants are not supported\n");
+ return E_NOTIMPL;
+ }
+
This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderItemsImpl));
if (!This) return E_OUTOFMEMORY;
This->FolderItems3_iface.lpVtbl = &FolderItemsImpl_Vtbl;
This->ref = 1;
+ VariantInit(&This->dir);
+ ret = VariantCopy(&This->dir, dir);
+ if (FAILED(ret))
+ {
+ HeapFree(GetProcessHeap(), 0, This);
+ return ret;
+ }
+
+ This->item_count = 0;
+ lstrcpyW(glob, V_BSTR(dir));
+ lstrcatW(glob, backslash_star);
+ first_file = FindFirstFileW(glob, &file_info);
+ if (first_file != INVALID_HANDLE_VALUE)
+ {
+ item_size = 128;
+ This->item_filenames = HeapAlloc(GetProcessHeap(), 0, item_size * sizeof(WCHAR*));
+ if (!This->item_filenames)
+ goto fail;
+
+ do
+ {
+ if (!strcmpW(file_info.cFileName, dot) || !strcmpW(file_info.cFileName, dot_dot))
+ continue;
+
+ if (This->item_count >= item_size)
+ {
+ item_size *= 2;
+ filenames = HeapReAlloc(GetProcessHeap(), 0, This->item_filenames, item_size * sizeof(WCHAR*));
+ if (!filenames)
+ goto fail;
+ This->item_filenames = filenames;
+ }
+
+ This->item_filenames[This->item_count] = strdupW(file_info.cFileName);
+ if (!This->item_filenames[This->item_count])
+ goto fail;
+ This->item_count++;
+ }
+ while (FindNextFileW(first_file, &file_info));
+
+ FindClose(first_file);
+ HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY,
+ This->item_filenames, This->item_count * sizeof(WCHAR*));
+ }
+ else
+ {
+ This->item_filenames = NULL;
+ }
+
*ppfi = (FolderItems*)&This->FolderItems3_iface;
return S_OK;
+
+fail:
+ FindClose(first_file);
+ FolderItems3_Release(&This->FolderItems3_iface);
+ return E_OUTOFMEMORY;
}
static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid,
@@ -1308,9 +1434,11 @@ static HRESULT WINAPI FolderImpl_get_ParentFolder(Folder3 *iface, Folder **ppsf)
static HRESULT WINAPI FolderImpl_Items(Folder3 *iface, FolderItems **ppid)
{
- FIXME("(%p,%p)\n", iface, ppid);
+ FolderImpl *This = impl_from_Folder(iface);
+
+ TRACE("(%p,%p)\n", iface, ppid);
- return FolderItems_Constructor(ppid);
+ return FolderItems_Constructor(&This->dir, ppid);
}
static HRESULT WINAPI FolderImpl_ParseName(Folder3 *iface, BSTR name, FolderItem **item)
diff --git a/dlls/shell32/shelllink.c b/dlls/shell32/shelllink.c
index bd3507e..3ac6364 100644
--- a/dlls/shell32/shelllink.c
+++ b/dlls/shell32/shelllink.c
@@ -215,16 +215,6 @@ static inline LPWSTR heap_strdupAtoW( LPCSTR str)
return p;
}
-static inline LPWSTR strdupW( LPCWSTR src )
-{
- LPWSTR dest;
- if (!src) return NULL;
- dest = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(src)+1)*sizeof(WCHAR) );
- if (dest)
- lstrcpyW(dest, src);
- return dest;
-}
-
/**************************************************************************
* IPersistFile_QueryInterface
*/
diff --git a/dlls/shell32/tests/shelldispatch.c b/dlls/shell32/tests/shelldispatch.c
index 149f3b9..e18bb6a 100644
--- a/dlls/shell32/tests/shelldispatch.c
+++ b/dlls/shell32/tests/shelldispatch.c
@@ -390,7 +390,6 @@ todo_wine
r = FolderItems_Item(items, var, NULL);
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
ok(!item, "item is not null\n");
@@ -446,9 +445,7 @@ todo_wine
V_BSTR(&var) = SysAllocString(wstr);
item = (FolderItem*)0xdeadbeef;
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_OK, "FolderItems::Item failed: %08x\n", r);
-todo_wine
ok(!!item, "item is null\n");
VariantClear(&var);
@@ -483,24 +480,19 @@ todo_wine
V_I2(&var) = 0;
item = NULL;
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_OK, "FolderItems::Item failed: %08x\n", r);
-todo_wine
ok(!!item, "item is null\n");
V_VT(&var) = VT_I4;
V_I4(&var) = 0;
item = NULL;
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_OK, "FolderItems::Item failed: %08x\n", r);
-todo_wine
ok(!!item, "item is null\n");
V_I4(&var) = -1;
item = (FolderItem*)0xdeadbeef;
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
ok(!item, "item is not null\n");
@@ -510,11 +502,8 @@ todo_wine
V_ERROR(&var) = i;
item = NULL;
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_OK, "expected S_OK, got %08x\n", r);
-todo_wine
ok(!!item, "item is null\n");
- if (!item) continue;
bstr = NULL;
r = FolderItem_get_Path(item, &bstr);
@@ -539,11 +528,8 @@ todo_wine
item = NULL;
r = FolderItems_Item(items, int_index, &item);
-todo_wine
ok(r == S_OK, "file_defs[%d]: FolderItems::Item failed: %08x\n", i, r);
-todo_wine
ok(!!item, "file_defs[%d]: item is null\n", i);
- if (!item) goto cleanup;
item2 = NULL;
r = FolderItems_Item(items, int_index, &item2);
@@ -576,7 +562,6 @@ todo_wine
FolderItem_Release(item);
-cleanup:
if (file_defs[i].type == DIRECTORY)
{
PathCombineA(buf, file_defs[i].name, "foo.txt");
@@ -585,9 +570,7 @@ cleanup:
V_BSTR(&var) = SysAllocString(wstr2);
item2 = NULL;
r = FolderItems_Item(items, var, &item2);
-todo_wine
ok(r == S_OK, "file_defs[%d]: FolderItems::Item failed: %08x\n", i, r);
-todo_wine
ok(!!item2, "file_defs[%d]: item is null\n", i);
if (item2) FolderItem_Release(item2);
VariantClear(&var);
@@ -599,7 +582,6 @@ todo_wine
{
ok(DeleteFileW(wstr), "file_defs[%d]: DeleteFile failed: %08x\n", i, GetLastError());
}
- if (!item) continue;
item = NULL;
r = FolderItems_Item(items, int_index, &item);
@@ -629,7 +611,6 @@ todo_wine
V_I4(&var) = sizeof(file_defs)/sizeof(file_defs[0]);
item = (FolderItem*)0xdeadbeef;
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
ok(!item, "item is not null\n");
@@ -705,7 +686,6 @@ todo_wine
V_I4(&var) = 0;
item = (FolderItem*)0xdeadbeef;
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
ok(!item, "item is not null\n");
@@ -714,7 +694,6 @@ todo_wine
V_BSTR(&var) = SysAllocString(wstr);
item = (FolderItem*)0xdeadbeef;
r = FolderItems_Item(items, var, &item);
-todo_wine
ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r);
ok(!item, "item is not null\n");
VariantClear(&var);
--
2.9.3
More information about the wine-patches
mailing list