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