[PATCH 2/3] shell32: Implement FolderItems_Item.
Alex Henrie
alexhenrie24 at gmail.com
Wed Jul 20 23:45:29 CDT 2016
Signed-off-by: Alex Henrie <alexhenrie24 at gmail.com>
---
dlls/shell32/shelldispatch.c | 98 +++++++++++++++++++++++++++++++++++---
dlls/shell32/tests/shelldispatch.c | 17 +++++--
2 files changed, 104 insertions(+), 11 deletions(-)
diff --git a/dlls/shell32/shelldispatch.c b/dlls/shell32/shelldispatch.c
index ac79302..aa2e916 100644
--- a/dlls/shell32/shelldispatch.c
+++ b/dlls/shell32/shelldispatch.c
@@ -37,6 +37,7 @@
#include "shell32_main.h"
#include "wine/debug.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
@@ -66,8 +67,14 @@ typedef struct {
} FolderImpl;
typedef struct {
+ struct list entry;
+ BSTR path;
+} folder_item;
+
+typedef struct {
FolderItems3 FolderItems3_iface;
LONG ref;
+ struct list items;
} FolderItemsImpl;
typedef struct {
@@ -989,11 +996,19 @@ static ULONG WINAPI FolderItemsImpl_Release(FolderItems3 *iface)
{
FolderItemsImpl *This = impl_from_FolderItems(iface);
ULONG ref = InterlockedDecrement(&This->ref);
+ folder_item *item, *item2;
TRACE("(%p), new refcount=%i\n", iface, ref);
if (!ref)
+ {
+ LIST_FOR_EACH_ENTRY_SAFE(item, item2, &This->items, folder_item, entry)
+ {
+ SysFreeString(item->path);
+ HeapFree(GetProcessHeap(), 0, item);
+ }
HeapFree(GetProcessHeap(), 0, This);
+ }
return ref;
}
@@ -1079,10 +1094,29 @@ 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);
+ VARIANT path;
+ struct list *node = list_head(&This->items);
+ int i;
+
+ TRACE("(%p,%s,%p)\n", iface, debugstr_variant(&index), ppid);
*ppid = NULL;
- return E_NOTIMPL;
+
+ if (!node)
+ return S_FALSE;
+
+ for (i = 0; i < V_I4(&index); i++)
+ {
+ node = list_next(&This->items, node);
+ if (!node)
+ return S_FALSE;
+ }
+
+ V_VT(&path) = VT_BSTR;
+ V_BSTR(&path) = LIST_ENTRY(node, folder_item, entry)->path;
+
+ return FolderItem_Constructor(&path, ppid);
}
static HRESULT WINAPI FolderItemsImpl__NewEnum(FolderItems3 *iface, IUnknown **ppunk)
@@ -1139,9 +1173,17 @@ 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;
+ WCHAR path[MAX_PATH];
+ HANDLE first_file;
+ WIN32_FIND_DATAW file_info;
+ folder_item *item;
+ HRESULT ret = S_OK;
TRACE("\n");
@@ -1152,8 +1194,50 @@ static HRESULT FolderItems_Constructor(FolderItems **ppfi)
This->FolderItems3_iface.lpVtbl = &FolderItemsImpl_Vtbl;
This->ref = 1;
+ lstrcpyW(path, V_BSTR(dir));
+ lstrcatW(path, backslash_star);
+ list_init(&This->items);
+ first_file = FindFirstFileW(path, &file_info);
+ if (first_file != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (!lstrcmpW(file_info.cFileName, dot) || !lstrcmpW(file_info.cFileName, dot_dot))
+ continue;
+
+ if (!PathCombineW(path, V_BSTR(dir), file_info.cFileName))
+ {
+ ret = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ item = HeapAlloc(GetProcessHeap(), 0, sizeof(folder_item));
+ if (!item)
+ {
+ ret = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ list_add_tail(&This->items, &item->entry);
+
+ item->path = SysAllocString(path);
+ if (!item->path)
+ {
+ ret = E_OUTOFMEMORY;
+ goto fail;
+ }
+ }
+ while (FindNextFileW(first_file, &file_info));
+
+ FindClose(first_file);
+ }
+
*ppfi = (FolderItems*)&This->FolderItems3_iface;
- return S_OK;
+ return ret;
+
+fail:
+ FolderItems3_Release(&This->FolderItems3_iface);
+ return ret;
}
static HRESULT WINAPI FolderImpl_QueryInterface(Folder3 *iface, REFIID riid,
@@ -1308,9 +1392,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/tests/shelldispatch.c b/dlls/shell32/tests/shelldispatch.c
index 315f3a5..b143c5f 100644
--- a/dlls/shell32/tests/shelldispatch.c
+++ b/dlls/shell32/tests/shelldispatch.c
@@ -389,7 +389,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");
@@ -476,11 +475,8 @@ todo_wine
item = NULL;
r = FolderItems_Item(items, var, &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) continue;
r = FolderItems_Item(items, var, &item2);
ok(r == S_OK, "file_defs[%d]: FolderItems::Item failed: %08x\n", i, r);
@@ -489,13 +485,17 @@ todo_wine
disp = NULL;
r = FolderItem_get_Application(item, &disp);
+todo_wine
ok(r == S_OK, "file_defs[%d]: FolderItem::get_Application failed: %08x\n", i, r);
+todo_wine
ok(!!disp, "file_defs[%d]: disp is null\n", i);
if (disp) IDispatch_Release(disp);
disp = NULL;
r = FolderItem_get_Parent(item, &disp);
+todo_wine
ok(r == S_OK, "file_defs[%d]: FolderItem::get_Parent failed: %08x\n", i, r);
+todo_wine
ok(!!disp, "file_defs[%d]: disp is null\n", i);
if (disp) IDispatch_Release(disp);
@@ -524,7 +524,9 @@ todo_wine
r = FolderItem_get_GetLink(item, &disp);
if (!lstrcmpA(PathFindExtensionA(file_defs[i].name), ".lnk"))
{
+todo_wine
ok(r == S_OK, "file_defs[%d]: FolderItem::get_GetLink failed: %08x\n", i, r);
+todo_wine
ok(!!disp, "file_defs[%d]: disp is null\n", i);
}
else
@@ -539,11 +541,14 @@ todo_wine
r = FolderItem_get_GetFolder(item, &disp);
if (file_defs[i].type == DIRECTORY)
{
+todo_wine
ok(r == S_OK, "file_defs[%d]: FolderItem::get_GetFolder failed: %08x\n", i, r);
+todo_wine
ok(!!disp, "file_defs[%d]: disp is null\n", i);
}
else
{
+todo_wine
ok(r == E_FAIL || broken(r == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) /* xp */,
"file_defs[%d]: expected E_FAIL, got %08x\n", i, r);
ok(!disp, "file_defs[%d]: disp is not null\n", i);
@@ -552,10 +557,13 @@ todo_wine
lcount = -1;
r = FolderItem_get_Size(item, &lcount);
+todo_wine
ok(r == S_OK, "file_defs[%d]: FolderItem::get_Size failed: %08x\n", i, r);
if (file_defs[i].type == DIRECTORY || file_defs[i].type == EMPTY)
+todo_wine
ok(!lcount, "file_defs[%d]: got %d\n", i, lcount);
else
+todo_wine
ok(lcount > 0, "file_defs[%d]: got %d\n", i, lcount);
verbs = NULL;
@@ -570,7 +578,6 @@ todo_wine
V_I4(&var) = sizeof(file_defs)/sizeof(file_defs[0]);
item = 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");
--
2.9.0
More information about the wine-patches
mailing list