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 26 CMyDocsFolder::CMyDocsFolder() 27 { 28 m_pidlInner = NULL; 29 } 30 31 CMyDocsFolder::~CMyDocsFolder() 32 { 33 if(m_pidlInner) 34 SHFree(m_pidlInner); 35 } 36 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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