1 /*
2  * FolderItemVerb(s) implementation
3  *
4  * Copyright 2015 Mark Jansen
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "precomp.h"
22 
23 WINE_DEFAULT_DEBUG_CHANNEL(shell);
24 
25 
26 CFolderItemVerb::CFolderItemVerb()
27 {
28 }
29 
30 CFolderItemVerb::~CFolderItemVerb()
31 {
32 }
33 
34 void CFolderItemVerb::Init(IContextMenu* menu, BSTR name)
35 {
36     m_contextmenu = menu;
37     m_name.m_str = name;
38 }
39 
40 // *** FolderItemVerb methods ***
41 
42 HRESULT STDMETHODCALLTYPE CFolderItemVerb::get_Application(IDispatch **ppid)
43 {
44     TRACE("(%p, %p)\n", this, ppid);
45     return E_NOTIMPL;
46 }
47 
48 HRESULT STDMETHODCALLTYPE CFolderItemVerb::get_Parent(IDispatch **ppid)
49 {
50     TRACE("(%p, %p)\n", this, ppid);
51     return E_NOTIMPL;
52 }
53 
54 HRESULT STDMETHODCALLTYPE CFolderItemVerb::get_Name(BSTR *pbs)
55 {
56     if (!pbs)
57         return E_POINTER;
58     *pbs = SysAllocString(m_name);
59     return S_OK;
60 }
61 
62 HRESULT STDMETHODCALLTYPE CFolderItemVerb::DoIt()
63 {
64     TRACE("(%p, %p)\n", this);
65     return E_NOTIMPL;
66 }
67 
68 
69 
70 
71 
72 
73 CFolderItemVerbs::CFolderItemVerbs()
74     :m_menu(NULL)
75     ,m_count(0)
76 {
77 }
78 
79 CFolderItemVerbs::~CFolderItemVerbs()
80 {
81     DestroyMenu(m_menu);
82 }
83 
84 HRESULT CFolderItemVerbs::Init(LPITEMIDLIST idlist)
85 {
86     CComPtr<IShellFolder> folder;
87     LPCITEMIDLIST child;
88     HRESULT hr = SHBindToParent(idlist, IID_PPV_ARG(IShellFolder, &folder), &child);
89     if (FAILED_UNEXPECTEDLY(hr))
90         return hr;
91 
92     hr = folder->GetUIObjectOf(NULL, 1, &child, IID_IContextMenu, NULL, (PVOID*)&m_contextmenu);
93     if (FAILED_UNEXPECTEDLY(hr))
94         return hr;
95 
96     m_menu = CreatePopupMenu();
97     hr = m_contextmenu->QueryContextMenu(m_menu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
98     if (!SUCCEEDED(hr))
99         return hr;
100 
101     m_count = GetMenuItemCount(m_menu);
102     return hr;
103 }
104 
105 
106 // *** FolderItemVerbs methods ***
107 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Count(LONG *plCount)
108 {
109     if (!plCount)
110         return E_INVALIDARG;
111     *plCount = m_count;
112     return S_OK;
113 }
114 
115 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Application(IDispatch **ppid)
116 {
117     TRACE("(%p, %p)\n", this, ppid);
118 
119     if (ppid)
120         *ppid = NULL;
121 
122     return E_NOTIMPL;
123 }
124 
125 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Parent(IDispatch **ppid)
126 {
127     TRACE("(%p, %p)\n", this, ppid);
128 
129     if (ppid)
130         *ppid = NULL;
131 
132     return E_NOTIMPL;
133 }
134 
135 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::Item(VARIANT indexVar, FolderItemVerb **ppid)
136 {
137     if (!ppid)
138         return E_POINTER;
139 
140     CComVariant var;
141 
142     HRESULT hr = VariantChangeType(&var, &indexVar, 0, VT_I4);
143     if (FAILED_UNEXPECTEDLY(hr))
144         return E_INVALIDARG;
145 
146     int index = V_I4(&var);
147 
148     if (index > m_count)
149         return S_OK;
150 
151     BSTR name = NULL;
152 
153     if(index == m_count)
154     {
155         name = SysAllocStringLen(NULL, 0);
156     }
157     else
158     {
159         MENUITEMINFOW info = { sizeof(info), 0 };
160         info.fMask = MIIM_STRING;
161         if (!GetMenuItemInfoW(m_menu, index, TRUE, &info))
162             return E_FAIL;
163         name = SysAllocStringLen(NULL, info.cch);
164         if (name)
165         {
166             info.dwTypeData = name;
167             info.cch++;
168             GetMenuItemInfoW(m_menu, index, TRUE, &info);
169         }
170     }
171 
172     if (!name)
173         return E_OUTOFMEMORY;
174 
175     CFolderItemVerb* verb = new CComObject<CFolderItemVerb>();
176     verb->Init(m_contextmenu, name);
177     verb->AddRef();
178     *ppid = verb;
179 
180     return S_OK;
181 }
182 
183 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::_NewEnum(IUnknown **ppunk)
184 {
185     TRACE("(%p, %p)\n", this, ppunk);
186     return E_NOTIMPL;
187 }
188 
189 
190