1 /*
2 * Virtual MyDocuments Folder
3 *
4 * Copyright 2007 Johannes Anderwald
5 * Copyright 2009 Andrew Hill
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <precomp.h>
23
24 WINE_DEFAULT_DEBUG_CHANNEL (mydocs);
25
CMyDocsFolder()26 CMyDocsFolder::CMyDocsFolder()
27 {
28 m_pidlInner = NULL;
29 }
30
~CMyDocsFolder()31 CMyDocsFolder::~CMyDocsFolder()
32 {
33 if(m_pidlInner)
34 SHFree(m_pidlInner);
35 }
36
FinalConstruct()37 HRESULT WINAPI CMyDocsFolder::FinalConstruct()
38 {
39 m_pidlInner = _ILCreateMyDocuments();
40
41 if (!m_pidlInner)
42 return E_OUTOFMEMORY;
43
44 return S_OK;
45 }
46
EnsureFolder()47 HRESULT CMyDocsFolder::EnsureFolder()
48 {
49 ATLASSERT(m_pidlInner);
50
51 if (m_pisfInner)
52 return S_OK;
53
54
55 HRESULT hr = SHELL32_CoCreateInitSF(m_pidlInner,
56 &CLSID_ShellFSFolder,
57 CSIDL_PERSONAL,
58 IID_PPV_ARG(IShellFolder2, &m_pisfInner));
59
60 if (FAILED_UNEXPECTEDLY(hr))
61 return hr;
62
63 return S_OK;
64 }
65
ParseDisplayName(HWND hwndOwner,LPBC pbc,LPOLESTR lpszDisplayName,ULONG * pchEaten,PIDLIST_RELATIVE * ppidl,ULONG * pdwAttributes)66 HRESULT WINAPI CMyDocsFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
67 ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes)
68 {
69 HRESULT hr = EnsureFolder();
70 if (FAILED(hr))
71 return hr;
72
73 return m_pisfInner->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
74 }
75
EnumObjects(HWND hwndOwner,DWORD dwFlags,LPENUMIDLIST * ppEnumIDList)76 HRESULT WINAPI CMyDocsFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
77 {
78 HRESULT hr = EnsureFolder();
79 if (FAILED(hr))
80 return hr;
81
82 return m_pisfInner->EnumObjects(hwndOwner, dwFlags, ppEnumIDList);
83 }
84
BindToObject(PCUIDLIST_RELATIVE pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut)85 HRESULT WINAPI CMyDocsFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
86 {
87 HRESULT hr = EnsureFolder();
88 if (FAILED(hr))
89 return hr;
90
91 return m_pisfInner->BindToObject(pidl, pbcReserved, riid, ppvOut);
92 }
93
BindToStorage(PCUIDLIST_RELATIVE pidl,LPBC pbcReserved,REFIID riid,LPVOID * ppvOut)94 HRESULT WINAPI CMyDocsFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
95 {
96 HRESULT hr = EnsureFolder();
97 if (FAILED(hr))
98 return hr;
99
100 return m_pisfInner->BindToStorage(pidl, pbcReserved, riid, ppvOut);
101 }
102
CompareIDs(LPARAM lParam,PCUIDLIST_RELATIVE pidl1,PCUIDLIST_RELATIVE pidl2)103 HRESULT WINAPI CMyDocsFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
104 {
105 HRESULT hr = EnsureFolder();
106 if (FAILED(hr))
107 return hr;
108
109 return m_pisfInner->CompareIDs(lParam, pidl1, pidl2);
110 }
111
CreateViewObject(HWND hwndOwner,REFIID riid,LPVOID * ppvOut)112 HRESULT WINAPI CMyDocsFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
113 {
114 HRESULT hr = EnsureFolder();
115 if (FAILED(hr))
116 return hr;
117
118 return m_pisfInner->CreateViewObject(hwndOwner, riid, ppvOut);
119 }
120
GetAttributesOf(UINT cidl,PCUITEMID_CHILD_ARRAY apidl,DWORD * rgfInOut)121 HRESULT WINAPI CMyDocsFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
122 {
123 static const DWORD dwMyDocumentsAttributes =
124 SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_CANCOPY |
125 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE;
126
127 HRESULT hr = EnsureFolder();
128 if (FAILED(hr))
129 return hr;
130
131 if(cidl)
132 return m_pisfInner->GetAttributesOf(cidl, apidl, rgfInOut);
133
134 if (!rgfInOut)
135 return E_INVALIDARG;
136
137 if (*rgfInOut == 0)
138 *rgfInOut = ~0;
139
140 *rgfInOut &= dwMyDocumentsAttributes;
141
142 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
143 *rgfInOut &= ~SFGAO_VALIDATE;
144
145 return S_OK;
146 }
147
GetUIObjectOf(HWND hwndOwner,UINT cidl,PCUITEMID_CHILD_ARRAY apidl,REFIID riid,UINT * prgfInOut,LPVOID * ppvOut)148 HRESULT WINAPI CMyDocsFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
149 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
150 {
151 HRESULT hr = EnsureFolder();
152 if (FAILED(hr))
153 return hr;
154
155 return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
156 }
157
GetDisplayNameOf(PCUITEMID_CHILD pidl,DWORD dwFlags,LPSTRRET strRet)158 HRESULT WINAPI CMyDocsFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
159 {
160 if (!strRet || !pidl)
161 return E_INVALIDARG;
162
163 HRESULT hr = EnsureFolder();
164 if (FAILED(hr))
165 return hr;
166
167 /* If we got an fs item just forward to the fs folder */
168 if (!_ILIsSpecialFolder(pidl))
169 return m_pisfInner->GetDisplayNameOf(pidl, dwFlags, strRet);
170
171 /* The caller wants our path. Let fs folder handle it */
172 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
173 (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING))
174 {
175 /* Give an empty pidl to the fs folder to make it tell us its path */
176 if (pidl->mkid.cb)
177 pidl = ILGetNext(pidl);
178 return m_pisfInner->GetDisplayNameOf(pidl, dwFlags, strRet);
179 }
180
181 ERR("Got empty pidl without SHGDN_FORPARSING\n");
182 return E_INVALIDARG;
183 }
184
SetNameOf(HWND hwndOwner,PCUITEMID_CHILD pidl,LPCOLESTR lpName,DWORD dwFlags,PITEMID_CHILD * pPidlOut)185 HRESULT WINAPI CMyDocsFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /* simple pidl */
186 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
187 {
188 HRESULT hr = EnsureFolder();
189 if (FAILED(hr))
190 return hr;
191
192 return m_pisfInner->SetNameOf(hwndOwner, pidl, lpName, dwFlags, pPidlOut);
193 }
194
GetDefaultSearchGUID(GUID * pguid)195 HRESULT WINAPI CMyDocsFolder::GetDefaultSearchGUID(GUID *pguid)
196 {
197 HRESULT hr = EnsureFolder();
198 if (FAILED(hr))
199 return hr;
200
201 return m_pisfInner->GetDefaultSearchGUID(pguid);
202 }
203
EnumSearches(IEnumExtraSearch ** ppenum)204 HRESULT WINAPI CMyDocsFolder::EnumSearches(IEnumExtraSearch ** ppenum)
205 {
206 HRESULT hr = EnsureFolder();
207 if (FAILED(hr))
208 return hr;
209
210 return m_pisfInner->EnumSearches(ppenum);
211 }
212
GetDefaultColumn(DWORD dwRes,ULONG * pSort,ULONG * pDisplay)213 HRESULT WINAPI CMyDocsFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
214 {
215 HRESULT hr = EnsureFolder();
216 if (FAILED(hr))
217 return hr;
218
219 return m_pisfInner->GetDefaultColumn(dwRes, pSort, pDisplay);
220 }
221
GetDefaultColumnState(UINT iColumn,DWORD * pcsFlags)222 HRESULT WINAPI CMyDocsFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
223 {
224 HRESULT hr = EnsureFolder();
225 if (FAILED(hr))
226 return hr;
227
228 return m_pisfInner->GetDefaultColumnState(iColumn, pcsFlags);
229 }
230
GetDetailsEx(PCUITEMID_CHILD pidl,const SHCOLUMNID * pscid,VARIANT * pv)231 HRESULT WINAPI CMyDocsFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
232 {
233 HRESULT hr = EnsureFolder();
234 if (FAILED(hr))
235 return hr;
236
237 return m_pisfInner->GetDetailsEx(pidl, pscid, pv);
238 }
239
GetDetailsOf(PCUITEMID_CHILD pidl,UINT iColumn,SHELLDETAILS * psd)240 HRESULT WINAPI CMyDocsFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
241 {
242 HRESULT hr = EnsureFolder();
243 if (FAILED(hr))
244 return hr;
245
246 return m_pisfInner->GetDetailsOf(pidl, iColumn, psd);
247 }
248
MapColumnToSCID(UINT column,SHCOLUMNID * pscid)249 HRESULT WINAPI CMyDocsFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
250 {
251 HRESULT hr = EnsureFolder();
252 if (FAILED(hr))
253 return hr;
254
255 return m_pisfInner->MapColumnToSCID(column, pscid);
256 }
257
GetClassID(CLSID * lpClassId)258 HRESULT WINAPI CMyDocsFolder::GetClassID(CLSID *lpClassId)
259 {
260 if (!lpClassId)
261 return E_POINTER;
262
263 memcpy(lpClassId, &CLSID_MyDocuments, sizeof(GUID));
264
265 return S_OK;
266 }
267
Initialize(PCIDLIST_ABSOLUTE pidl)268 HRESULT WINAPI CMyDocsFolder::Initialize(PCIDLIST_ABSOLUTE pidl)
269 {
270 if (m_pisfInner)
271 return E_INVALIDARG;
272
273 if (m_pidlInner)
274 SHFree(m_pidlInner);
275
276 m_pidlInner = ILClone(pidl);
277
278 if (!m_pidlInner)
279 return E_OUTOFMEMORY;
280
281 return EnsureFolder();
282 }
283
GetCurFolder(PIDLIST_ABSOLUTE * pidl)284 HRESULT WINAPI CMyDocsFolder::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
285 {
286 if (!pidl)
287 return E_POINTER;
288 *pidl = ILClone(m_pidlInner);
289 return S_OK;
290 }
291