Reactos
1/*
2 * PROJECT: shell32
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: FolderItem(s) implementation
5 * COPYRIGHT: Copyright 2015-2018 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8#include "precomp.h"
9
10WINE_DEFAULT_DEBUG_CHANNEL(shell);
11
12
13CFolderItem::CFolderItem()
14{
15}
16
17CFolderItem::~CFolderItem()
18{
19}
20
21HRESULT CFolderItem::Initialize(Folder* folder, LPITEMIDLIST idlist)
22{
23 m_idlist.Attach(ILClone(idlist));
24 m_Folder = folder;
25 return S_OK;
26}
27
28// *** FolderItem methods ***
29HRESULT STDMETHODCALLTYPE CFolderItem::get_Application(IDispatch **ppid)
30{
31 TRACE("(%p, %p)\n", this, ppid);
32 return m_Folder->get_Application(ppid);
33}
34
35HRESULT STDMETHODCALLTYPE CFolderItem::get_Parent(IDispatch **ppid)
36{
37 TRACE("(%p, %p)\n", this, ppid);
38 if (ppid)
39 {
40 *ppid = m_Folder;
41 (*ppid)->AddRef();
42 }
43 return E_NOTIMPL;
44}
45
46HRESULT STDMETHODCALLTYPE CFolderItem::get_Name(BSTR *pbs)
47{
48 TRACE("(%p, %p)\n", this, pbs);
49
50 *pbs = NULL;
51
52 CComPtr<IShellFolder2> Parent;
53 LPCITEMIDLIST last_part;
54 HRESULT hr = SHBindToParent(m_idlist, IID_PPV_ARG(IShellFolder2, &Parent), &last_part);
55 if (FAILED_UNEXPECTEDLY(hr))
56 return hr;
57
58 STRRET strret;
59 hr = Parent->GetDisplayNameOf(last_part, SHGDN_INFOLDER, &strret);
60 if (!FAILED_UNEXPECTEDLY(hr))
61 hr = StrRetToBSTR(&strret, last_part, pbs);
62
63 return hr;
64}
65
66HRESULT STDMETHODCALLTYPE CFolderItem::put_Name(BSTR bs)
67{
68 TRACE("(%p, %s)\n", this, wine_dbgstr_w(bs));
69 return E_NOTIMPL;
70}
71
72HRESULT STDMETHODCALLTYPE CFolderItem::get_Path(BSTR *pbs)
73{
74 CComPtr<IShellFolder> psfDesktop;
75
76 HRESULT hr = SHGetDesktopFolder(&psfDesktop);
77 if (!SUCCEEDED(hr))
78 return hr;
79
80 STRRET strret;
81 hr = psfDesktop->GetDisplayNameOf(m_idlist, SHGDN_FORPARSING, &strret);
82 if (FAILED_UNEXPECTEDLY(hr))
83 return hr;
84
85 return StrRetToBSTR(&strret, NULL, pbs);
86}
87
88HRESULT STDMETHODCALLTYPE CFolderItem::get_GetLink(IDispatch **ppid)
89{
90 TRACE("(%p, %p)\n", this, ppid);
91 return E_NOTIMPL;
92}
93
94HRESULT STDMETHODCALLTYPE CFolderItem::get_GetFolder(IDispatch **ppid)
95{
96 TRACE("(%p, %p)\n", this, ppid);
97 return E_NOTIMPL;
98}
99
100HRESULT STDMETHODCALLTYPE CFolderItem::get_IsLink(VARIANT_BOOL *pb)
101{
102 TRACE("(%p, %p)\n", this, pb);
103 return E_NOTIMPL;
104}
105
106HRESULT STDMETHODCALLTYPE CFolderItem::get_IsFolder(VARIANT_BOOL *pb)
107{
108 TRACE("(%p, %p)\n", this, pb);
109 return E_NOTIMPL;
110}
111
112HRESULT STDMETHODCALLTYPE CFolderItem::get_IsFileSystem(VARIANT_BOOL *pb)
113{
114 TRACE("(%p, %p)\n", this, pb);
115 return E_NOTIMPL;
116}
117
118HRESULT STDMETHODCALLTYPE CFolderItem::get_IsBrowsable(VARIANT_BOOL *pb)
119{
120 TRACE("(%p, %p)\n", this, pb);
121 return E_NOTIMPL;
122}
123
124HRESULT STDMETHODCALLTYPE CFolderItem::get_ModifyDate(DATE *pdt)
125{
126 TRACE("(%p, %p)\n", this, pdt);
127 return E_NOTIMPL;
128}
129
130HRESULT STDMETHODCALLTYPE CFolderItem::put_ModifyDate(DATE dt)
131{
132 TRACE("(%p, %f)\n", this, dt);
133 return E_NOTIMPL;
134}
135
136HRESULT STDMETHODCALLTYPE CFolderItem::get_Size(LONG *pul)
137{
138 TRACE("(%p, %p)\n", this, pul);
139 return E_NOTIMPL;
140}
141
142HRESULT STDMETHODCALLTYPE CFolderItem::get_Type(BSTR *pbs)
143{
144 TRACE("(%p, %p)\n", this, pbs);
145 return E_NOTIMPL;
146}
147
148HRESULT STDMETHODCALLTYPE CFolderItem::Verbs(FolderItemVerbs **ppfic)
149{
150 if (!ppfic)
151 return E_POINTER;
152 CFolderItemVerbs* verbs = new CComObject<CFolderItemVerbs>();
153 HRESULT hr = verbs->Init(m_idlist);
154 if (FAILED_UNEXPECTEDLY(hr))
155 {
156 delete verbs;
157 return hr;
158 }
159 verbs->AddRef();
160 *ppfic = verbs;
161 return S_OK;
162}
163
164HRESULT STDMETHODCALLTYPE CFolderItem::InvokeVerb(VARIANT vVerb)
165{
166 TRACE("(%p, %s)\n", this, wine_dbgstr_variant(&vVerb));
167 return E_NOTIMPL;
168}
169
170
171
172CFolderItems::CFolderItems()
173 :m_Count(-1)
174{
175}
176
177CFolderItems::~CFolderItems()
178{
179}
180
181HRESULT CFolderItems::Initialize(LPITEMIDLIST idlist, Folder* parent)
182{
183 CComPtr<IShellFolder> psfDesktop, psfTarget;
184
185 m_idlist.Attach(ILClone(idlist));
186
187 HRESULT hr = SHGetDesktopFolder(&psfDesktop);
188 if (FAILED_UNEXPECTEDLY(hr))
189 return hr;
190
191 hr = psfDesktop->BindToObject(m_idlist, NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
192 if (FAILED_UNEXPECTEDLY(hr))
193 return hr;
194
195 hr = psfTarget->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &m_EnumIDList);
196
197 if (FAILED_UNEXPECTEDLY(hr))
198 return hr;
199
200 m_Folder = parent;
201 return S_OK;
202}
203
204// *** FolderItems methods ***
205HRESULT STDMETHODCALLTYPE CFolderItems::get_Count(long *plCount)
206{
207 if (!m_EnumIDList)
208 return E_FAIL;
209
210 if (!plCount)
211 return E_POINTER;
212
213 if (m_Count == -1)
214 {
215 long count = 0;
216
217 HRESULT hr = m_EnumIDList->Reset();
218 if (FAILED_UNEXPECTEDLY(hr))
219 return hr;
220
221 CComHeapPtr<ITEMIDLIST> Pidl;
222 while ((hr = m_EnumIDList->Next(1, &Pidl, 0)) != S_FALSE)
223 {
224 count++;
225 Pidl.Free();
226 }
227 m_Count = count;
228 }
229 *plCount = m_Count;
230
231 return S_OK;
232}
233
234HRESULT STDMETHODCALLTYPE CFolderItems::get_Application(IDispatch **ppid)
235{
236 TRACE("(%p, %p)\n", this, ppid);
237 return m_Folder->get_Application(ppid);
238}
239
240HRESULT STDMETHODCALLTYPE CFolderItems::get_Parent(IDispatch **ppid)
241{
242 TRACE("(%p, %p)\n", this, ppid);
243
244 if (ppid)
245 *ppid = NULL;
246
247 return E_NOTIMPL;
248}
249
250HRESULT STDMETHODCALLTYPE CFolderItems::Item(VARIANT var, FolderItem **ppid)
251{
252 CComVariant index;
253 HRESULT hr;
254
255 if (!m_EnumIDList)
256 return E_FAIL;
257
258 hr = VariantCopyInd(&index, &var);
259 if (FAILED(hr))
260 return hr;
261
262 if (V_VT(&index) == VT_I2)
263 VariantChangeType(&index, &index, 0, VT_I4);
264
265 if (V_VT(&index) == VT_I4)
266 {
267 ULONG count = V_UI4(&index);
268
269 hr = m_EnumIDList->Reset();
270 if (FAILED_UNEXPECTEDLY(hr))
271 return hr;
272
273 hr = m_EnumIDList->Skip(count);
274
275 if (FAILED_UNEXPECTEDLY(hr))
276 return hr;
277
278 CComHeapPtr<ITEMIDLIST> spPidl;
279 hr = m_EnumIDList->Next(1, &spPidl, 0);
280 if (FAILED_UNEXPECTEDLY(hr))
281 return hr;
282 hr = ShellObjectCreatorInit<CFolderItem>(m_Folder, static_cast<LPITEMIDLIST>(spPidl), IID_PPV_ARG(FolderItem, ppid));
283 if (FAILED_UNEXPECTEDLY(hr))
284 return hr;
285 return hr;
286 }
287 else if (V_VT(&index) == VT_BSTR)
288 {
289 if (!V_BSTR(&index))
290 return S_FALSE;
291
292 hr = m_Folder->ParseName(V_BSTR(&index), ppid);
293 if (FAILED_UNEXPECTEDLY(hr))
294 return hr;
295 return hr;
296 }
297
298 FIXME("Index type %d not handled.\n", V_VT(&index));
299 return E_NOTIMPL;
300}
301
302HRESULT STDMETHODCALLTYPE CFolderItems::_NewEnum(IUnknown **ppunk)
303{
304 return ShellObjectCreatorInit<CFolderItems>(static_cast<LPITEMIDLIST>(m_idlist), m_Folder, IID_FolderItems, reinterpret_cast<void**>(ppunk));
305}
306