1c2c66affSColin Finck /* 2c2c66affSColin Finck * Shell Folder stuff 3c2c66affSColin Finck * 4c2c66affSColin Finck * Copyright 1997 Marcus Meissner 5c2c66affSColin Finck * Copyright 1998, 1999, 2002 Juergen Schmied 655469633SKatayama Hirofumi MZ * Copyright 2018 Katayama Hirofumi MZ 7c2c66affSColin Finck * 8c2c66affSColin Finck * IShellFolder2 and related interfaces 9c2c66affSColin Finck * 10c2c66affSColin Finck * This library is free software; you can redistribute it and/or 11c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 12c2c66affSColin Finck * License as published by the Free Software Foundation; either 13c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 14c2c66affSColin Finck * 15c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 16c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 17c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18c2c66affSColin Finck * Lesser General Public License for more details. 19c2c66affSColin Finck * 20c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 21c2c66affSColin Finck * License along with this library; if not, write to the Free Software 22c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23c2c66affSColin Finck */ 24c2c66affSColin Finck 25c2c66affSColin Finck #include "precomp.h" 26c2c66affSColin Finck 27c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(shell); 28c2c66affSColin Finck 29bc5603d9SMark Jansen 30c2c66affSColin Finck /*************************************************************************** 31c2c66affSColin Finck * GetNextElement (internal function) 32c2c66affSColin Finck * 33c2c66affSColin Finck * Gets a part of a string till the first backslash. 34c2c66affSColin Finck * 35c2c66affSColin Finck * PARAMETERS 36c2c66affSColin Finck * pszNext [IN] string to get the element from 37c2c66affSColin Finck * pszOut [IN] pointer to buffer which receives string 38c2c66affSColin Finck * dwOut [IN] length of pszOut 39c2c66affSColin Finck * 40c2c66affSColin Finck * RETURNS 41c2c66affSColin Finck * LPSTR pointer to first, not yet parsed char 42c2c66affSColin Finck */ 43c2c66affSColin Finck 44c2c66affSColin Finck LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut) 45c2c66affSColin Finck { 46c2c66affSColin Finck LPCWSTR pszTail = pszNext; 47c2c66affSColin Finck DWORD dwCopy; 48c2c66affSColin Finck 49c2c66affSColin Finck TRACE ("(%s %p 0x%08x)\n", debugstr_w (pszNext), pszOut, dwOut); 50c2c66affSColin Finck 51c2c66affSColin Finck *pszOut = 0x0000; 52c2c66affSColin Finck 53c2c66affSColin Finck if (!pszNext || !*pszNext) 54c2c66affSColin Finck return NULL; 55c2c66affSColin Finck 56c2c66affSColin Finck while (*pszTail && (*pszTail != (WCHAR) '\\')) 57c2c66affSColin Finck pszTail++; 58c2c66affSColin Finck 59c2c66affSColin Finck dwCopy = pszTail - pszNext + 1; 60c2c66affSColin Finck lstrcpynW (pszOut, pszNext, (dwOut < dwCopy) ? dwOut : dwCopy); 61c2c66affSColin Finck 62c2c66affSColin Finck if (*pszTail) 63c2c66affSColin Finck pszTail++; 64c2c66affSColin Finck else 65c2c66affSColin Finck pszTail = NULL; 66c2c66affSColin Finck 67c2c66affSColin Finck TRACE ("--(%s %s 0x%08x %p)\n", debugstr_w (pszNext), debugstr_w (pszOut), dwOut, pszTail); 68c2c66affSColin Finck return pszTail; 69c2c66affSColin Finck } 70c2c66affSColin Finck 71c2c66affSColin Finck HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, 72c2c66affSColin Finck LPITEMIDLIST * pidlInOut, LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes) 73c2c66affSColin Finck { 74c2c66affSColin Finck HRESULT hr = E_INVALIDARG; 75c2c66affSColin Finck LPITEMIDLIST pidlIn = pidlInOut ? *pidlInOut : NULL; 76c2c66affSColin Finck LPITEMIDLIST pidlOut = NULL; 77c2c66affSColin Finck LPITEMIDLIST pidlTemp = NULL; 78c2c66affSColin Finck CComPtr<IShellFolder> psfChild; 79c2c66affSColin Finck 80c2c66affSColin Finck TRACE ("(%p, %p, %p, %s)\n", psf, pbc, pidlIn, debugstr_w (szNext)); 81c2c66affSColin Finck 82c2c66affSColin Finck /* get the shellfolder for the child pidl and let it analyse further */ 83c2c66affSColin Finck hr = psf->BindToObject(pidlIn, pbc, IID_PPV_ARG(IShellFolder, &psfChild)); 84c2c66affSColin Finck if (FAILED(hr)) 85c2c66affSColin Finck return hr; 86c2c66affSColin Finck 87c2c66affSColin Finck hr = psfChild->ParseDisplayName(hwndOwner, pbc, szNext, pEaten, &pidlOut, pdwAttributes); 88c2c66affSColin Finck if (FAILED(hr)) 89c2c66affSColin Finck return hr; 90c2c66affSColin Finck 91c2c66affSColin Finck pidlTemp = ILCombine (pidlIn, pidlOut); 92c2c66affSColin Finck if (!pidlTemp) 93c2c66affSColin Finck { 94c2c66affSColin Finck hr = E_OUTOFMEMORY; 95c2c66affSColin Finck if (pidlOut) 96c2c66affSColin Finck ILFree(pidlOut); 97c2c66affSColin Finck return hr; 98c2c66affSColin Finck } 99c2c66affSColin Finck 100c2c66affSColin Finck if (pidlOut) 101c2c66affSColin Finck ILFree (pidlOut); 102c2c66affSColin Finck 103c2c66affSColin Finck if (pidlIn) 104c2c66affSColin Finck ILFree (pidlIn); 105c2c66affSColin Finck 106c2c66affSColin Finck *pidlInOut = pidlTemp; 107c2c66affSColin Finck 108c2c66affSColin Finck TRACE ("-- pidl=%p ret=0x%08x\n", pidlInOut ? *pidlInOut : NULL, hr); 109c2c66affSColin Finck return S_OK; 110c2c66affSColin Finck } 111c2c66affSColin Finck 112c2c66affSColin Finck /*********************************************************************** 113c2c66affSColin Finck * SHELL32_CoCreateInitSF 114c2c66affSColin Finck * 115c2c66affSColin Finck * Creates a shell folder and initializes it with a pidl and a root folder 116c2c66affSColin Finck * via IPersistFolder3 or IPersistFolder. 117c2c66affSColin Finck * 118c2c66affSColin Finck * NOTES 119c2c66affSColin Finck * pathRoot can be NULL for Folders being a drive. 120c2c66affSColin Finck * In this case the absolute path is built from pidlChild (eg. C:) 121c2c66affSColin Finck */ 122c2c66affSColin Finck HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti, 123c2c66affSColin Finck LPCITEMIDLIST pidlChild, const GUID* clsid, REFIID riid, LPVOID *ppvOut) 124c2c66affSColin Finck { 125c2c66affSColin Finck HRESULT hr; 126c2c66affSColin Finck CComPtr<IShellFolder> pShellFolder; 127c2c66affSColin Finck 128c2c66affSColin Finck hr = SHCoCreateInstance(NULL, clsid, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder)); 129c2c66affSColin Finck if (FAILED(hr)) 130c2c66affSColin Finck return hr; 131c2c66affSColin Finck 132c2c66affSColin Finck LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild); 133c2c66affSColin Finck CComPtr<IPersistFolder> ppf; 134c2c66affSColin Finck CComPtr<IPersistFolder3> ppf3; 135c2c66affSColin Finck 136c2c66affSColin Finck if (ppfti && SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3)))) 137c2c66affSColin Finck { 138c2c66affSColin Finck ppf3->InitializeEx(NULL, pidlAbsolute, ppfti); 139c2c66affSColin Finck } 140c2c66affSColin Finck else if (SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder, &ppf)))) 141c2c66affSColin Finck { 142c2c66affSColin Finck ppf->Initialize(pidlAbsolute); 143c2c66affSColin Finck } 144c2c66affSColin Finck ILFree (pidlAbsolute); 145c2c66affSColin Finck 146c2c66affSColin Finck return pShellFolder->QueryInterface(riid, ppvOut); 147c2c66affSColin Finck } 148c2c66affSColin Finck 149c2c66affSColin Finck HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, const GUID* clsid, 150c2c66affSColin Finck int csidl, REFIID riid, LPVOID *ppvOut) 151c2c66affSColin Finck { 152c2c66affSColin Finck /* fill the PERSIST_FOLDER_TARGET_INFO */ 153c2c66affSColin Finck PERSIST_FOLDER_TARGET_INFO pfti = {0}; 154c2c66affSColin Finck pfti.dwAttributes = -1; 155c2c66affSColin Finck pfti.csidl = csidl; 156c2c66affSColin Finck 157c2c66affSColin Finck return SHELL32_CoCreateInitSF(pidlRoot, &pfti, NULL, clsid, riid, ppvOut); 158c2c66affSColin Finck } 159c2c66affSColin Finck 160c2c66affSColin Finck HRESULT SHELL32_BindToSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti, 161c2c66affSColin Finck LPCITEMIDLIST pidl, const GUID* clsid, REFIID riid, LPVOID *ppvOut) 162c2c66affSColin Finck { 163c2c66affSColin Finck PITEMID_CHILD pidlChild = ILCloneFirst (pidl); 164c2c66affSColin Finck if (!pidlChild) 165c2c66affSColin Finck return E_FAIL; 166c2c66affSColin Finck 167c2c66affSColin Finck CComPtr<IShellFolder> psf; 168c2c66affSColin Finck HRESULT hr = SHELL32_CoCreateInitSF(pidlRoot, 169c2c66affSColin Finck ppfti, 170c2c66affSColin Finck pidlChild, 171c2c66affSColin Finck clsid, 172c2c66affSColin Finck IID_PPV_ARG(IShellFolder, &psf)); 173c2c66affSColin Finck ILFree(pidlChild); 174c2c66affSColin Finck 175c2c66affSColin Finck if (FAILED_UNEXPECTEDLY(hr)) 176c2c66affSColin Finck return hr; 177c2c66affSColin Finck 178c2c66affSColin Finck if (_ILIsPidlSimple (pidl)) 179c2c66affSColin Finck return psf->QueryInterface(riid, ppvOut); 180c2c66affSColin Finck else 181c2c66affSColin Finck return psf->BindToObject(ILGetNext (pidl), NULL, riid, ppvOut); 182c2c66affSColin Finck } 183c2c66affSColin Finck 184c2c66affSColin Finck /*********************************************************************** 185c2c66affSColin Finck * SHELL32_GetDisplayNameOfChild 186c2c66affSColin Finck * 187c2c66affSColin Finck * Retrieves the display name of a child object of a shellfolder. 188c2c66affSColin Finck * 189c2c66affSColin Finck * For a pidl eg. [subpidl1][subpidl2][subpidl3]: 190c2c66affSColin Finck * - it binds to the child shellfolder [subpidl1] 191c2c66affSColin Finck * - asks it for the displayname of [subpidl2][subpidl3] 192c2c66affSColin Finck * 193c2c66affSColin Finck * Is possible the pidl is a simple pidl. In this case it asks the 194c2c66affSColin Finck * subfolder for the displayname of an empty pidl. The subfolder 195c2c66affSColin Finck * returns the own displayname eg. "::{guid}". This is used for 196c2c66affSColin Finck * virtual folders with the registry key WantsFORPARSING set. 197c2c66affSColin Finck */ 198c2c66affSColin Finck HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, 199c2c66affSColin Finck LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet) 200c2c66affSColin Finck { 201c2c66affSColin Finck LPITEMIDLIST pidlFirst = ILCloneFirst(pidl); 202c2c66affSColin Finck if (!pidlFirst) 203c2c66affSColin Finck return E_OUTOFMEMORY; 204c2c66affSColin Finck 205c2c66affSColin Finck CComPtr<IShellFolder> psfChild; 206c2c66affSColin Finck HRESULT hr = psf->BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild)); 207c2c66affSColin Finck if (SUCCEEDED (hr)) 208c2c66affSColin Finck { 209c2c66affSColin Finck hr = psfChild->GetDisplayNameOf(ILGetNext (pidl), dwFlags, strRet); 210c2c66affSColin Finck } 211c2c66affSColin Finck ILFree (pidlFirst); 212c2c66affSColin Finck 213c2c66affSColin Finck return hr; 214c2c66affSColin Finck } 215c2c66affSColin Finck 216c2c66affSColin Finck HRESULT SHELL32_CompareChildren(IShellFolder2* psf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) 217c2c66affSColin Finck { 218c2c66affSColin Finck PUIDLIST_RELATIVE nextpidl1 = ILGetNext (pidl1); 219c2c66affSColin Finck PUIDLIST_RELATIVE nextpidl2 = ILGetNext (pidl2); 220c2c66affSColin Finck 221c2c66affSColin Finck bool isEmpty1 = _ILIsDesktop(nextpidl1); 222c2c66affSColin Finck bool isEmpty2 = _ILIsDesktop(nextpidl2); 223c2c66affSColin Finck if (isEmpty1 || isEmpty2) 224c2c66affSColin Finck return MAKE_COMPARE_HRESULT(isEmpty2 - isEmpty1); 225c2c66affSColin Finck 226c2c66affSColin Finck PITEMID_CHILD firstpidl = ILCloneFirst (pidl1); 227c2c66affSColin Finck if (!firstpidl) 228c2c66affSColin Finck return E_OUTOFMEMORY; 229c2c66affSColin Finck 230c2c66affSColin Finck CComPtr<IShellFolder> psf2; 231c2c66affSColin Finck HRESULT hr = psf->BindToObject(firstpidl, 0, IID_PPV_ARG(IShellFolder, &psf2)); 232c2c66affSColin Finck ILFree(firstpidl); 233c2c66affSColin Finck if (FAILED(hr)) 234c2c66affSColin Finck return MAKE_COMPARE_HRESULT(0); 235c2c66affSColin Finck 236c2c66affSColin Finck return psf2->CompareIDs(lParam, nextpidl1, nextpidl2); 237c2c66affSColin Finck } 238c2c66affSColin Finck 239c2c66affSColin Finck HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) 240c2c66affSColin Finck { 241c2c66affSColin Finck SHELLDETAILS sd; 242c2c66affSColin Finck WCHAR wszItem1[MAX_PATH], wszItem2[MAX_PATH]; 243c2c66affSColin Finck HRESULT hres; 244*34066e47SWhindmar Saksit UINT col = LOWORD(lParam); // Column index without SHCIDS_* flags 245c2c66affSColin Finck 246*34066e47SWhindmar Saksit hres = isf->GetDetailsOf(pidl1, col, &sd); 247c2c66affSColin Finck if (FAILED(hres)) 248c2c66affSColin Finck return MAKE_COMPARE_HRESULT(1); 249c2c66affSColin Finck 250c2c66affSColin Finck hres = StrRetToBufW(&sd.str, pidl1, wszItem1, MAX_PATH); 251c2c66affSColin Finck if (FAILED(hres)) 252c2c66affSColin Finck return MAKE_COMPARE_HRESULT(1); 253c2c66affSColin Finck 254*34066e47SWhindmar Saksit hres = isf->GetDetailsOf(pidl2, col, &sd); 255c2c66affSColin Finck if (FAILED(hres)) 256c2c66affSColin Finck return MAKE_COMPARE_HRESULT(1); 257c2c66affSColin Finck 258c2c66affSColin Finck hres = StrRetToBufW(&sd.str, pidl2, wszItem2, MAX_PATH); 259c2c66affSColin Finck if (FAILED(hres)) 260c2c66affSColin Finck return MAKE_COMPARE_HRESULT(1); 261c2c66affSColin Finck 262c2c66affSColin Finck int ret = wcsicmp(wszItem1, wszItem2); 263c2c66affSColin Finck if (ret == 0) 264c2c66affSColin Finck return SHELL32_CompareChildren(isf, lParam, pidl1, pidl2); 265c2c66affSColin Finck 266c2c66affSColin Finck return MAKE_COMPARE_HRESULT(ret); 267c2c66affSColin Finck } 268c2c66affSColin Finck 269c2c66affSColin Finck void AddClassKeyToArray(const WCHAR * szClass, HKEY* array, UINT* cKeys) 270c2c66affSColin Finck { 271c2c66affSColin Finck if (*cKeys >= 16) 272c2c66affSColin Finck return; 273c2c66affSColin Finck 274c2c66affSColin Finck HKEY hkey; 275c2c66affSColin Finck LSTATUS result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ | KEY_QUERY_VALUE, &hkey); 276c2c66affSColin Finck if (result != ERROR_SUCCESS) 277c2c66affSColin Finck return; 278c2c66affSColin Finck 279c2c66affSColin Finck array[*cKeys] = hkey; 280c2c66affSColin Finck *cKeys += 1; 281c2c66affSColin Finck } 282c2c66affSColin Finck 283c2c66affSColin Finck void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys) 284c2c66affSColin Finck { 285c2c66affSColin Finck if (_ILIsValue(pidl)) 286c2c66affSColin Finck { 287c2c66affSColin Finck FileStructW* pFileData = _ILGetFileStructW(pidl); 288c2c66affSColin Finck LPWSTR extension = PathFindExtension(pFileData->wszName); 289c2c66affSColin Finck 290c2c66affSColin Finck if (extension) 291c2c66affSColin Finck { 292c2c66affSColin Finck AddClassKeyToArray(extension, array, cKeys); 293c2c66affSColin Finck 294c2c66affSColin Finck WCHAR wszClass[MAX_PATH], wszClass2[MAX_PATH]; 295c2c66affSColin Finck DWORD dwSize = sizeof(wszClass); 296c2c66affSColin Finck if (RegGetValueW(HKEY_CLASSES_ROOT, extension, NULL, RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS) 297c2c66affSColin Finck { 298c2c66affSColin Finck swprintf(wszClass2, L"%s//%s", extension, wszClass); 299c2c66affSColin Finck 300c2c66affSColin Finck AddClassKeyToArray(wszClass, array, cKeys); 301c2c66affSColin Finck AddClassKeyToArray(wszClass2, array, cKeys); 302c2c66affSColin Finck } 303c2c66affSColin Finck 304c2c66affSColin Finck swprintf(wszClass2, L"SystemFileAssociations//%s", extension); 305c2c66affSColin Finck AddClassKeyToArray(wszClass2, array, cKeys); 306c2c66affSColin Finck 307c2c66affSColin Finck if (RegGetValueW(HKEY_CLASSES_ROOT, extension, L"PerceivedType ", RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS) 308c2c66affSColin Finck { 309c2c66affSColin Finck swprintf(wszClass2, L"SystemFileAssociations//%s", wszClass); 310c2c66affSColin Finck AddClassKeyToArray(wszClass2, array, cKeys); 311c2c66affSColin Finck } 312c2c66affSColin Finck } 313c2c66affSColin Finck 314c2c66affSColin Finck AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys); 315c2c66affSColin Finck AddClassKeyToArray(L"*", array, cKeys); 316c2c66affSColin Finck } 317c2c66affSColin Finck else if (_ILIsFolder(pidl)) 318c2c66affSColin Finck { 319c2c66affSColin Finck AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys); 320c2c66affSColin Finck AddClassKeyToArray(L"Directory", array, cKeys); 321c2c66affSColin Finck AddClassKeyToArray(L"Folder", array, cKeys); 322c2c66affSColin Finck } 323c2c66affSColin Finck else 324c2c66affSColin Finck { 325c2c66affSColin Finck ERR("Got non FS pidl\n"); 326c2c66affSColin Finck } 327c2c66affSColin Finck } 328c2c66affSColin Finck 329c2c66affSColin Finck HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl) 330c2c66affSColin Finck { 331fa0f5cc4SMark Jansen CDataObjectHIDA cida(pDataObject); 332c2c66affSColin Finck 333fa0f5cc4SMark Jansen if (FAILED_UNEXPECTEDLY(cida.hr())) 334fa0f5cc4SMark Jansen return cida.hr(); 335c2c66affSColin Finck 336c2c66affSColin Finck /* convert the data into pidl */ 337c2c66affSColin Finck LPITEMIDLIST pidl; 338fa0f5cc4SMark Jansen LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, cida); 339c2c66affSColin Finck if (!apidl) 340c2c66affSColin Finck { 341c2c66affSColin Finck return E_OUTOFMEMORY; 342c2c66affSColin Finck } 343c2c66affSColin Finck 344c2c66affSColin Finck *ppidlfolder = pidl; 345c2c66affSColin Finck *apidlItems = apidl; 346fa0f5cc4SMark Jansen *pcidl = cida->cidl; 347c2c66affSColin Finck 348c2c66affSColin Finck return S_OK; 349c2c66affSColin Finck } 350c2c66affSColin Finck 351c2c66affSColin Finck /*********************************************************************** 352c2c66affSColin Finck * SHCreateLinks 353c2c66affSColin Finck * 354c2c66affSColin Finck * Undocumented. 355c2c66affSColin Finck */ 356c2c66affSColin Finck HRESULT WINAPI SHCreateLinks( HWND hWnd, LPCSTR lpszDir, IDataObject * lpDataObject, 357c2c66affSColin Finck UINT uFlags, LPITEMIDLIST *lppidlLinks) 358c2c66affSColin Finck { 359c2c66affSColin Finck FIXME("%p %s %p %08x %p\n", hWnd, lpszDir, lpDataObject, uFlags, lppidlLinks); 360c2c66affSColin Finck return E_NOTIMPL; 361c2c66affSColin Finck } 362c2c66affSColin Finck 363c2c66affSColin Finck /*********************************************************************** 364c2c66affSColin Finck * SHOpenFolderAndSelectItems 365c2c66affSColin Finck * 366c2c66affSColin Finck * Unimplemented. 367c2c66affSColin Finck */ 368c2c66affSColin Finck EXTERN_C HRESULT 369c2c66affSColin Finck WINAPI 370aee6cbc5SThomas Faber SHOpenFolderAndSelectItems(PCIDLIST_ABSOLUTE pidlFolder, 371c2c66affSColin Finck UINT cidl, 372c2c66affSColin Finck PCUITEMID_CHILD_ARRAY apidl, 373c2c66affSColin Finck DWORD dwFlags) 374c2c66affSColin Finck { 375c2c66affSColin Finck ERR("SHOpenFolderAndSelectItems() is hackplemented\n"); 376c2c66affSColin Finck PCIDLIST_ABSOLUTE pidlItem; 377c2c66affSColin Finck if (cidl) 378c2c66affSColin Finck { 379c2c66affSColin Finck /* Firefox sends a full pidl here dispite the fact it is a PCUITEMID_CHILD_ARRAY -_- */ 380c2c66affSColin Finck if (ILGetNext(apidl[0]) != NULL) 381c2c66affSColin Finck { 382c2c66affSColin Finck pidlItem = apidl[0]; 383c2c66affSColin Finck } 384c2c66affSColin Finck else 385c2c66affSColin Finck { 386c2c66affSColin Finck pidlItem = ILCombine(pidlFolder, apidl[0]); 387c2c66affSColin Finck } 388c2c66affSColin Finck } 389c2c66affSColin Finck else 390c2c66affSColin Finck { 391c2c66affSColin Finck pidlItem = pidlFolder; 392c2c66affSColin Finck } 393c2c66affSColin Finck 394c2c66affSColin Finck CComPtr<IShellFolder> psfDesktop; 395c2c66affSColin Finck 396c2c66affSColin Finck HRESULT hr = SHGetDesktopFolder(&psfDesktop); 397c2c66affSColin Finck if (FAILED_UNEXPECTEDLY(hr)) 398c2c66affSColin Finck return hr; 399c2c66affSColin Finck 400c2c66affSColin Finck STRRET strret; 401c2c66affSColin Finck hr = psfDesktop->GetDisplayNameOf(pidlItem, SHGDN_FORPARSING, &strret); 402c2c66affSColin Finck if (FAILED_UNEXPECTEDLY(hr)) 403c2c66affSColin Finck return hr; 404c2c66affSColin Finck 405c2c66affSColin Finck WCHAR wszBuf[MAX_PATH]; 406c2c66affSColin Finck hr = StrRetToBufW(&strret, pidlItem, wszBuf, _countof(wszBuf)); 407c2c66affSColin Finck if (FAILED_UNEXPECTEDLY(hr)) 408c2c66affSColin Finck return hr; 409c2c66affSColin Finck 410c2c66affSColin Finck WCHAR wszParams[MAX_PATH]; 411c2c66affSColin Finck wcscpy(wszParams, L"/select,"); 412c2c66affSColin Finck wcscat(wszParams, wszBuf); 413c2c66affSColin Finck 414c2c66affSColin Finck SHELLEXECUTEINFOW sei; 415c2c66affSColin Finck memset(&sei, 0, sizeof sei); 416c2c66affSColin Finck sei.cbSize = sizeof sei; 417c2c66affSColin Finck sei.fMask = SEE_MASK_WAITFORINPUTIDLE; 418c2c66affSColin Finck sei.lpFile = L"explorer.exe"; 419c2c66affSColin Finck sei.lpParameters = wszParams; 420c2c66affSColin Finck 421c2c66affSColin Finck if (ShellExecuteExW(&sei)) 422c2c66affSColin Finck return S_OK; 423c2c66affSColin Finck else 424c2c66affSColin Finck return E_FAIL; 425c2c66affSColin Finck } 42655469633SKatayama Hirofumi MZ 42755469633SKatayama Hirofumi MZ 428bc5603d9SMark Jansen 429bc5603d9SMark Jansen static 430bc5603d9SMark Jansen DWORD WINAPI 431bc5603d9SMark Jansen _ShowPropertiesDialogThread(LPVOID lpParameter) 432bc5603d9SMark Jansen { 433bc5603d9SMark Jansen CComPtr<IDataObject> pDataObject; 434bc5603d9SMark Jansen pDataObject.Attach((IDataObject*)lpParameter); 435bc5603d9SMark Jansen 436bc5603d9SMark Jansen CDataObjectHIDA cida(pDataObject); 437bc5603d9SMark Jansen 438bc5603d9SMark Jansen if (FAILED_UNEXPECTEDLY(cida.hr())) 439bc5603d9SMark Jansen return cida.hr(); 440bc5603d9SMark Jansen 441bc5603d9SMark Jansen if (cida->cidl > 1) 44255469633SKatayama Hirofumi MZ { 44355469633SKatayama Hirofumi MZ ERR("SHMultiFileProperties is not yet implemented\n"); 44455469633SKatayama Hirofumi MZ return E_FAIL; 44555469633SKatayama Hirofumi MZ } 44655469633SKatayama Hirofumi MZ 4476a1f2878SMark Jansen CComHeapPtr<ITEMIDLIST> completePidl(ILCombine(HIDA_GetPIDLFolder(cida), HIDA_GetPIDLItem(cida, 0))); 4486a1f2878SMark Jansen CComHeapPtr<WCHAR> wszName; 4496a1f2878SMark Jansen if (FAILED_UNEXPECTEDLY(SHGetNameFromIDList(completePidl, SIGDN_PARENTRELATIVEPARSING, &wszName))) 4506a1f2878SMark Jansen return 0; 451bc5603d9SMark Jansen 4526a1f2878SMark Jansen BOOL bSuccess = SH_ShowPropertiesDialog(wszName, pDataObject); 453bc5603d9SMark Jansen if (!bSuccess) 45455469633SKatayama Hirofumi MZ ERR("SH_ShowPropertiesDialog failed\n"); 45555469633SKatayama Hirofumi MZ 456bc5603d9SMark Jansen return 0; 457bc5603d9SMark Jansen } 45855469633SKatayama Hirofumi MZ 459bc5603d9SMark Jansen /* 460bc5603d9SMark Jansen * for internal use 461bc5603d9SMark Jansen */ 462bc5603d9SMark Jansen HRESULT WINAPI 463bc5603d9SMark Jansen Shell_DefaultContextMenuCallBack(IShellFolder *psf, IDataObject *pdtobj) 464bc5603d9SMark Jansen { 465bc5603d9SMark Jansen pdtobj->AddRef(); 466bc5603d9SMark Jansen if (!SHCreateThread(_ShowPropertiesDialogThread, pdtobj, CTF_INSIST | CTF_COINIT, NULL)) 467bc5603d9SMark Jansen { 468bc5603d9SMark Jansen pdtobj->Release(); 469bc5603d9SMark Jansen return HRESULT_FROM_WIN32(GetLastError()); 470bc5603d9SMark Jansen } 471bc5603d9SMark Jansen else 472bc5603d9SMark Jansen { 473bc5603d9SMark Jansen return S_OK; 474bc5603d9SMark Jansen } 47555469633SKatayama Hirofumi MZ } 476