xref: /reactos/dll/win32/shell32/CFolderItems.cpp (revision 31019e8c)
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 index, FolderItem **ppid)
251 {
252     if (!m_EnumIDList)
253         return E_FAIL;
254 
255     if (V_VT(&index) == VT_I2)
256         VariantChangeType(&index, &index, 0, VT_I4);
257 
258     if (V_VT(&index) == VT_I4)
259     {
260         ULONG count = V_UI4(&index);
261 
262         HRESULT hr = m_EnumIDList->Reset();
263         if (FAILED_UNEXPECTEDLY(hr))
264             return hr;
265 
266         hr = m_EnumIDList->Skip(count);
267 
268         if (FAILED_UNEXPECTEDLY(hr))
269             return hr;
270 
271         CComHeapPtr<ITEMIDLIST> spPidl;
272         hr = m_EnumIDList->Next(1, &spPidl, 0);
273         if (FAILED_UNEXPECTEDLY(hr))
274             return hr;
275         hr = ShellObjectCreatorInit<CFolderItem>(m_Folder, static_cast<LPITEMIDLIST>(spPidl), IID_PPV_ARG(FolderItem, ppid));
276         if (FAILED_UNEXPECTEDLY(hr))
277             return hr;
278         return hr;
279     }
280     else if (V_VT(&index) == VT_BSTR)
281     {
282         if (!V_BSTR(&index))
283             return S_FALSE;
284 
285         HRESULT hr = m_Folder->ParseName(V_BSTR(&index), ppid);
286         if (FAILED_UNEXPECTEDLY(hr))
287             return hr;
288         return hr;
289     }
290 
291     FIXME("Index type %d not handled.\n", V_VT(&index));
292     return E_NOTIMPL;
293 }
294 
295 HRESULT STDMETHODCALLTYPE CFolderItems::_NewEnum(IUnknown **ppunk)
296 {
297     return ShellObjectCreatorInit<CFolderItems>(static_cast<LPITEMIDLIST>(m_idlist), m_Folder, IID_FolderItems, reinterpret_cast<void**>(ppunk));
298 }
299 
300