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 
46     if (ppid)
47         *ppid = NULL;
48 
49     return E_NOTIMPL;
50 }
51 
52 HRESULT STDMETHODCALLTYPE CFolderItemVerb::get_Parent(IDispatch **ppid)
53 {
54     TRACE("(%p, %p)\n", this, ppid);
55 
56     if (ppid)
57         *ppid = NULL;
58 
59     return E_NOTIMPL;
60 }
61 
62 HRESULT STDMETHODCALLTYPE CFolderItemVerb::get_Name(BSTR *pbs)
63 {
64     if (!pbs)
65         return E_POINTER;
66     *pbs = SysAllocString(m_name);
67     return S_OK;
68 }
69 
70 HRESULT STDMETHODCALLTYPE CFolderItemVerb::DoIt()
71 {
72     TRACE("(%p, %p)\n", this);
73     return E_NOTIMPL;
74 }
75 
76 
77 
78 
79 
80 
81 CFolderItemVerbs::CFolderItemVerbs()
82     :m_menu(NULL)
83     ,m_count(0)
84 {
85 }
86 
87 CFolderItemVerbs::~CFolderItemVerbs()
88 {
89     DestroyMenu(m_menu);
90 }
91 
92 HRESULT CFolderItemVerbs::Init(LPITEMIDLIST idlist)
93 {
94     CComPtr<IShellFolder> folder;
95     LPCITEMIDLIST child;
96     HRESULT hr = SHBindToParent(idlist, IID_PPV_ARG(IShellFolder, &folder), &child);
97     if (FAILED_UNEXPECTEDLY(hr))
98         return hr;
99 
100     hr = folder->GetUIObjectOf(NULL, 1, &child, IID_IContextMenu, NULL, (PVOID*)&m_contextmenu);
101     if (FAILED_UNEXPECTEDLY(hr))
102         return hr;
103 
104     m_menu = CreatePopupMenu();
105     hr = m_contextmenu->QueryContextMenu(m_menu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
106     if (!SUCCEEDED(hr))
107         return hr;
108 
109     m_count = GetMenuItemCount(m_menu);
110     return hr;
111 }
112 
113 
114 // *** FolderItemVerbs methods ***
115 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Count(LONG *plCount)
116 {
117     if (!plCount)
118         return E_INVALIDARG;
119     *plCount = m_count;
120     return S_OK;
121 }
122 
123 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Application(IDispatch **ppid)
124 {
125     TRACE("(%p, %p)\n", this, ppid);
126 
127     if (ppid)
128         *ppid = NULL;
129 
130     return E_NOTIMPL;
131 }
132 
133 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::get_Parent(IDispatch **ppid)
134 {
135     TRACE("(%p, %p)\n", this, ppid);
136 
137     if (ppid)
138         *ppid = NULL;
139 
140     return E_NOTIMPL;
141 }
142 
143 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::Item(VARIANT indexVar, FolderItemVerb **ppid)
144 {
145     if (!ppid)
146         return E_POINTER;
147 
148     CComVariant var;
149 
150     HRESULT hr = VariantChangeType(&var, &indexVar, 0, VT_I4);
151     if (FAILED_UNEXPECTEDLY(hr))
152         return E_INVALIDARG;
153 
154     int index = V_I4(&var);
155 
156     if (index > m_count)
157         return S_OK;
158 
159     BSTR name = NULL;
160 
161     if(index == m_count)
162     {
163         name = SysAllocStringLen(NULL, 0);
164     }
165     else
166     {
167         MENUITEMINFOW info = { sizeof(info), 0 };
168         info.fMask = MIIM_STRING;
169         if (!GetMenuItemInfoW(m_menu, index, TRUE, &info))
170             return E_FAIL;
171         name = SysAllocStringLen(NULL, info.cch);
172         if (name)
173         {
174             info.dwTypeData = name;
175             info.cch++;
176             GetMenuItemInfoW(m_menu, index, TRUE, &info);
177         }
178     }
179 
180     if (!name)
181         return E_OUTOFMEMORY;
182 
183     CFolderItemVerb* verb = new CComObject<CFolderItemVerb>();
184     verb->Init(m_contextmenu, name);
185     verb->AddRef();
186     *ppid = verb;
187 
188     return S_OK;
189 }
190 
191 HRESULT STDMETHODCALLTYPE CFolderItemVerbs::_NewEnum(IUnknown **ppunk)
192 {
193     TRACE("(%p, %p)\n", this, ppunk);
194     return E_NOTIMPL;
195 }
196 
197 
198