From: Alex Henrie Subject: [PATCH 2/3] shell32: Implement FolderItems_Item. Message-Id: <20160721044600.16264-2-alexhenrie24@gmail.com> Date: Wed, 20 Jul 2016 22:45:29 -0600 In-Reply-To: <20160721044600.16264-1-alexhenrie24@gmail.com> References: <20160721044600.16264-1-alexhenrie24@gmail.com> Signed-off-by: Alex Henrie --- 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