xref: /reactos/dll/win32/shell32/CFolderItems.cpp (revision 53221834)
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 
10 WINE_DEFAULT_DEBUG_CHANNEL(shell);
11 
12 
13 CFolderItem::CFolderItem()
14 {
15 }
16 
17 CFolderItem::~CFolderItem()
18 {
19 }
20 
21 HRESULT 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 ***
29 HRESULT STDMETHODCALLTYPE CFolderItem::get_Application(IDispatch **ppid)
30 {
31     TRACE("(%p, %p)\n", this, ppid);
32     return m_Folder->get_Application(ppid);
33 }
34 
35 HRESULT STDMETHODCALLTYPE CFolderItem::get_Parent(IDispatch **ppid)
36 {
37     TRACE("(%p, %p)\n", this, ppid);
38     if (ppid)
39     {
40         *ppid = m_Folder;
41         m_Folder->AddRef();
42     }
43     return E_NOTIMPL;
44 }
45 
46 HRESULT 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 
66 HRESULT STDMETHODCALLTYPE CFolderItem::put_Name(BSTR bs)
67 {
68     TRACE("(%p, %s)\n", this, wine_dbgstr_w(bs));
69     return E_NOTIMPL;
70 }
71 
72 HRESULT 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 
88 HRESULT STDMETHODCALLTYPE CFolderItem::get_GetLink(IDispatch **ppid)
89 {
90     TRACE("(%p, %p)\n", this, ppid);
91     return E_NOTIMPL;
92 }
93 
94 HRESULT STDMETHODCALLTYPE CFolderItem::get_GetFolder(IDispatch **ppid)
95 {
96     TRACE("(%p, %p)\n", this, ppid);
97     return E_NOTIMPL;
98 }
99 
100 HRESULT STDMETHODCALLTYPE CFolderItem::get_IsLink(VARIANT_BOOL *pb)
101 {
102     TRACE("(%p, %p)\n", this, pb);
103     return E_NOTIMPL;
104 }
105 
106 HRESULT STDMETHODCALLTYPE CFolderItem::get_IsFolder(VARIANT_BOOL *pb)
107 {
108     TRACE("(%p, %p)\n", this, pb);
109     return E_NOTIMPL;
110 }
111 
112 HRESULT STDMETHODCALLTYPE CFolderItem::get_IsFileSystem(VARIANT_BOOL *pb)
113 {
114     TRACE("(%p, %p)\n", this, pb);
115     return E_NOTIMPL;
116 }
117 
118 HRESULT STDMETHODCALLTYPE CFolderItem::get_IsBrowsable(VARIANT_BOOL *pb)
119 {
120     TRACE("(%p, %p)\n", this, pb);
121     return E_NOTIMPL;
122 }
123 
124 HRESULT STDMETHODCALLTYPE CFolderItem::get_ModifyDate(DATE *pdt)
125 {
126     TRACE("(%p, %p)\n", this, pdt);
127     return E_NOTIMPL;
128 }
129 
130 HRESULT STDMETHODCALLTYPE CFolderItem::put_ModifyDate(DATE dt)
131 {
132     TRACE("(%p, %f)\n", this, dt);
133     return E_NOTIMPL;
134 }
135 
136 HRESULT STDMETHODCALLTYPE CFolderItem::get_Size(LONG *pul)
137 {
138     TRACE("(%p, %p)\n", this, pul);
139     return E_NOTIMPL;
140 }
141 
142 HRESULT STDMETHODCALLTYPE CFolderItem::get_Type(BSTR *pbs)
143 {
144     TRACE("(%p, %p)\n", this, pbs);
145     return E_NOTIMPL;
146 }
147 
148 HRESULT 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 
164 HRESULT STDMETHODCALLTYPE CFolderItem::InvokeVerb(VARIANT vVerb)
165 {
166     TRACE("(%p, %s)\n", this, wine_dbgstr_variant(&vVerb));
167     return E_NOTIMPL;
168 }
169 
170 
171 
172 CFolderItems::CFolderItems()
173     :m_Count(-1)
174 {
175 }
176 
177 CFolderItems::~CFolderItems()
178 {
179 }
180 
181 HRESULT 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 ***
205 HRESULT 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 
234 HRESULT STDMETHODCALLTYPE CFolderItems::get_Application(IDispatch **ppid)
235 {
236     TRACE("(%p, %p)\n", this, ppid);
237     return m_Folder->get_Application(ppid);
238 }
239 
240 HRESULT 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 
250 HRESULT 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 
302 HRESULT 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 
307