Nikolay Sivov : shell32: Implement FolderItemVerbs::Item().
Alexandre Julliard
julliard at wine.codeweavers.com
Mon May 11 07:49:04 CDT 2015
Module: wine
Branch: master
Commit: bf41160c656b351a750a9e765b36bbe17276c66c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=bf41160c656b351a750a9e765b36bbe17276c66c
Author: Nikolay Sivov <nsivov at 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);
}
More information about the wine-cvs
mailing list