Module: wine Branch: master Commit: bf41160c656b351a750a9e765b36bbe17276c66c URL: http://source.winehq.org/git/wine.git/?a=commit;h=bf41160c656b351a750a9e765b...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Sun May 10 22:45:52 2015 +0300
shell32: Implement FolderItemVerbs::Item().
---
dlls/shell32/shelldispatch.c | 100 +++++++++++++++++++++++++++++++------ dlls/shell32/tests/shelldispatch.c | 39 ++++++++++++++- 2 files changed, 121 insertions(+), 18 deletions(-)
diff --git a/dlls/shell32/shelldispatch.c b/dlls/shell32/shelldispatch.c index 650b7d3..f5eca28 100644 --- a/dlls/shell32/shelldispatch.c +++ b/dlls/shell32/shelldispatch.c @@ -74,13 +74,17 @@ typedef struct { FolderItemVerbs FolderItemVerbs_iface; LONG ref;
- IContextMenu *menu; + IContextMenu *contextmenu; + HMENU hMenu; LONG count; } FolderItemVerbsImpl;
typedef struct { FolderItemVerb FolderItemVerb_iface; LONG ref; + + IContextMenu *contextmenu; + BSTR name; } FolderItemVerbImpl;
static inline ShellDispatch *impl_from_IShellDispatch6(IShellDispatch6 *iface) @@ -209,7 +213,11 @@ static ULONG WINAPI FolderItemVerbImpl_Release(FolderItemVerb *iface) TRACE("(%p), new refcount=%i\n", iface, ref);
if (!ref) + { + IContextMenu_Release(This->contextmenu); + SysFreeString(This->name); HeapFree(GetProcessHeap(), 0, This); + }
return ref; } @@ -280,8 +288,12 @@ static HRESULT WINAPI FolderItemVerbImpl_get_Parent(FolderItemVerb *iface, IDisp
static HRESULT WINAPI FolderItemVerbImpl_get_Name(FolderItemVerb *iface, BSTR *name) { - FIXME("(%p, %p)\n", iface, name); - return E_NOTIMPL; + FolderItemVerbImpl *This = impl_from_FolderItemVerb(iface); + + TRACE("(%p, %p)\n", iface, name); + + *name = SysAllocString(This->name); + return *name ? S_OK : E_OUTOFMEMORY; }
static HRESULT WINAPI FolderItemVerbImpl_DoIt(FolderItemVerb *iface) @@ -304,11 +316,11 @@ static FolderItemVerbVtbl folderitemverbvtbl = { FolderItemVerbImpl_DoIt };
-static HRESULT FolderItemVerb_Constructor(FolderItemVerb **verb) +static HRESULT FolderItemVerb_Constructor(IContextMenu *contextmenu, BSTR name, FolderItemVerb **verb) { FolderItemVerbImpl *This;
- *verb = NULL; + TRACE("%p, %s\n", contextmenu, debugstr_w(name));
This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderItemVerbImpl)); if (!This) @@ -316,6 +328,9 @@ static HRESULT FolderItemVerb_Constructor(FolderItemVerb **verb)
This->FolderItemVerb_iface.lpVtbl = &folderitemverbvtbl; This->ref = 1; + This->contextmenu = contextmenu; + IContextMenu_AddRef(contextmenu); + This->name = name;
*verb = &This->FolderItemVerb_iface; return S_OK; @@ -365,7 +380,8 @@ static ULONG WINAPI FolderItemVerbsImpl_Release(FolderItemVerbs *iface)
if (!ref) { - IContextMenu_Release(This->menu); + IContextMenu_Release(This->contextmenu); + DestroyMenu(This->hMenu); HeapFree(GetProcessHeap(), 0, This); }
@@ -430,6 +446,9 @@ static HRESULT WINAPI FolderItemVerbsImpl_get_Count(FolderItemVerbs *iface, LONG
TRACE("(%p, %p)\n", iface, count);
+ if (!count) + return E_INVALIDARG; + *count = This->count; return S_OK; } @@ -448,8 +467,56 @@ static HRESULT WINAPI FolderItemVerbsImpl_get_Parent(FolderItemVerbs *iface, IDi
static HRESULT WINAPI FolderItemVerbsImpl_Item(FolderItemVerbs *iface, VARIANT index, FolderItemVerb **verb) { - FIXME("(%p, %s, %p)\n", iface, debugstr_variant(&index), verb); - return FolderItemVerb_Constructor(verb); + FolderItemVerbsImpl *This = impl_from_FolderItemVerbs(iface); + MENUITEMINFOW info; + HRESULT hr; + VARIANT v; + BSTR name; + + TRACE("(%p, %s, %p)\n", iface, debugstr_variant(&index), verb); + + if (!verb) + return E_INVALIDARG; + + *verb = NULL; + + VariantInit(&v); + VariantCopyInd(&v, &index); + + hr = VariantChangeType(&v, &v, 0, VT_I4); + if (FAILED(hr)) + { + FIXME("failed to coerce to VT_I4, %s\n", debugstr_variant(&v)); + return hr; + } + + if (V_I4(&v) > This->count) + return S_OK; + + if (V_I4(&v) == This->count) + name = SysAllocStringLen(NULL, 0); + else + { + /* get item name */ + memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + info.fMask = MIIM_STRING; + if (!GetMenuItemInfoW(This->hMenu, V_I4(&v), TRUE, &info)) + return E_FAIL; + + name = SysAllocStringLen(NULL, info.cch); + if (name) + { + info.dwTypeData = name; + info.cch++; + GetMenuItemInfoW(This->hMenu, V_I4(&v), TRUE, &info); + } + } + + if (!name) + return E_OUTOFMEMORY; + + return FolderItemVerb_Constructor(This->contextmenu, name, verb); }
static HRESULT WINAPI FolderItemVerbsImpl__NewEnum(FolderItemVerbs *iface, IUnknown **ret) @@ -480,7 +547,6 @@ static HRESULT FolderItemVerbs_Constructor(BSTR path, FolderItemVerbs **verbs) LPCITEMIDLIST child; LPITEMIDLIST pidl; HRESULT hr; - HMENU menu;
This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderItemVerbsImpl)); if (!This) @@ -488,7 +554,6 @@ static HRESULT FolderItemVerbs_Constructor(BSTR path, FolderItemVerbs **verbs)
This->FolderItemVerbs_iface.lpVtbl = &folderitemverbsvtbl; This->ref = 1; - This->count = 0;
/* build context menu for this path */ hr = SHParseDisplayName(path, NULL, &pidl, 0, NULL); @@ -500,17 +565,20 @@ static HRESULT FolderItemVerbs_Constructor(BSTR path, FolderItemVerbs **verbs) if (FAILED(hr)) goto failed;
- hr = IShellFolder_GetUIObjectOf(folder, NULL, 1, &child, &IID_IContextMenu, NULL, (void**)&This->menu); + hr = IShellFolder_GetUIObjectOf(folder, NULL, 1, &child, &IID_IContextMenu, NULL, (void**)&This->contextmenu); IShellFolder_Release(folder); if (FAILED(hr)) goto failed;
- menu = CreatePopupMenu(); - hr = IContextMenu_QueryContextMenu(This->menu, menu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL); - if (SUCCEEDED(hr)) - This->count = GetMenuItemCount(menu); - DestroyMenu(menu); + This->hMenu = CreatePopupMenu(); + hr = IContextMenu_QueryContextMenu(This->contextmenu, This->hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL); + if (FAILED(hr)) + { + FolderItemVerbs_Release(&This->FolderItemVerbs_iface); + return hr; + }
+ This->count = GetMenuItemCount(This->hMenu); *verbs = &This->FolderItemVerbs_iface; return S_OK;
diff --git a/dlls/shell32/tests/shelldispatch.c b/dlls/shell32/tests/shelldispatch.c index 167972b..f9d92ee 100644 --- a/dlls/shell32/tests/shelldispatch.c +++ b/dlls/shell32/tests/shelldispatch.c @@ -747,13 +747,15 @@ static void test_Verbs(void) { FolderItemVerbs *verbs; WCHAR pathW[MAX_PATH]; + FolderItemVerb *verb; IShellDispatch *sd; FolderItem *item; Folder2 *folder2; Folder *folder; HRESULT hr; - LONG count; + LONG count, i; VARIANT v; + BSTR str;
hr = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, &IID_IShellDispatch, (void**)&sd); @@ -778,15 +780,48 @@ if (0) { /* crashes on some systems */ hr = FolderItem_Verbs(item, NULL); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); } - hr = FolderItem_Verbs(item, &verbs); ok(hr == S_OK, "got 0x%08x\n", hr);
+if (0) { /* crashes on winxp/win2k3 */ + hr = FolderItemVerbs_get_Count(verbs, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); +} count = 0; hr = FolderItemVerbs_get_Count(verbs, &count); ok(hr == S_OK, "got 0x%08x\n", hr); ok(count > 0, "got count %d\n", count);
+if (0) { /* crashes on winxp/win2k3 */ + V_VT(&v) = VT_I4; + V_I4(&v) = 0; + hr = FolderItemVerbs_Item(verbs, v, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); +} + /* there's always one item more, so you can access [0,count], + instead of actual [0,count) */ + for (i = 0; i <= count; i++) { + V_VT(&v) = VT_I4; + V_I4(&v) = i; + hr = FolderItemVerbs_Item(verbs, v, &verb); + ok(hr == S_OK, "got 0x%08x\n", hr); + hr = FolderItemVerb_get_Name(verb, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(str != NULL, "%d: name %s\n", i, wine_dbgstr_w(str)); + if (i == count) + ok(str[0] == 0, "%d: got teminating item %s\n", i, wine_dbgstr_w(str)); + + SysFreeString(str); + FolderItemVerb_Release(verb); + } + + V_VT(&v) = VT_I4; + V_I4(&v) = count+1; + verb = NULL; + hr = FolderItemVerbs_Item(verbs, v, &verb); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(verb == NULL, "got %p\n", verb); + FolderItem_Release(item); IShellDispatch_Release(sd); }