* In this case the absolute path is built from pidlChild (eg. C:)
*/
static HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot,
- LPCITEMIDLIST pidlChild, REFCLSID clsid, LPVOID * ppvOut)
+ LPCITEMIDLIST pidlChild, REFCLSID clsid, IShellFolder** ppsfOut)
{
HRESULT hr;
CComPtr<IShellFolder> pShellFolder;
CComPtr<IPersistFolder> ppf;
CComPtr<IPersistFolder3> ppf3;
- if ((_ILIsFolder(pidlChild) || _ILIsDrive(pidlChild)) &&
- SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3))))
+ if (SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3))))
{
PERSIST_FOLDER_TARGET_INFO ppfti;
ILFree (pidlAbsolute);
}
- *ppvOut = pShellFolder.Detach();
+ *ppsfOut = pShellFolder.Detach();
- TRACE ("-- (%p) ret=0x%08x\n", *ppvOut, hr);
+ TRACE ("-- (%p) ret=0x%08x\n", *ppsfOut, hr);
return hr;
}
+void SHELL32_GetCLSIDForDirectory(LPCWSTR pathRoot, LPCITEMIDLIST pidl, CLSID* pclsidFolder)
+{
+ static const WCHAR wszDotShellClassInfo[] = {
+ '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0 };
+ static const WCHAR wszCLSID[] = {'C','L','S','I','D',0};
+ WCHAR wszCLSIDValue[CHARS_IN_GUID], wszFolderPath[MAX_PATH], *pwszPathTail = wszFolderPath;
+
+ /* see if folder CLSID should be overridden by desktop.ini file */
+ if (pathRoot) {
+ lstrcpynW(wszFolderPath, pathRoot, MAX_PATH);
+ pwszPathTail = PathAddBackslashW(wszFolderPath);
+ }
+
+ _ILSimpleGetTextW(pidl,pwszPathTail,MAX_PATH - (int)(pwszPathTail - wszFolderPath));
+
+ if (SHELL32_GetCustomFolderAttributeFromPath (wszFolderPath,
+ wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID))
+ CLSIDFromString (wszCLSIDValue, pclsidFolder);
+}
+
/***********************************************************************
- * SHELL32_BindToChild [Internal]
+ * SHELL32_BindToFS [Internal]
*
* Common code for IShellFolder_BindToObject.
*
* This function makes special assumptions on the shell namespace, which
* means you probably can't use it for your IShellFolder implementation.
*/
-HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
+HRESULT SHELL32_BindToFS (LPCITEMIDLIST pidlRoot,
LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut)
{
- static const WCHAR wszDotShellClassInfo[] = {
- '.','S','h','e','l','l','C','l','a','s','s','I','n','f','o',0 };
-
- GUID const *clsid;
CComPtr<IShellFolder> pSF;
HRESULT hr;
- LPITEMIDLIST pidlChild;
+ LPCITEMIDLIST pidlChild;
if (!pidlRoot || !ppvOut || !pidlComplete || !pidlComplete->mkid.cb)
return E_INVALIDARG;
+ if (_ILIsValue(pidlComplete))
+ {
+ ERR("Binding to file is unimplemented\n");
+ return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+ }
+ if (!_ILIsFolder(pidlComplete) && !_ILIsDrive(pidlComplete))
+ {
+ ERR("Got an unknown type of pidl!\n");
+ return E_FAIL;
+ }
+
*ppvOut = NULL;
- pidlChild = ILCloneFirst (pidlComplete);
-
- if ((clsid = _ILGetGUIDPointer (pidlChild))) {
- /* virtual folder */
- hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, *clsid, (LPVOID *)&pSF);
- } else {
- /* file system folder */
- CLSID clsidFolder = CLSID_ShellFSFolder;
- static const WCHAR wszCLSID[] = {'C','L','S','I','D',0};
- WCHAR wszCLSIDValue[CHARS_IN_GUID], wszFolderPath[MAX_PATH], *pwszPathTail = wszFolderPath;
-
- /* see if folder CLSID should be overridden by desktop.ini file */
- if (pathRoot) {
- lstrcpynW(wszFolderPath, pathRoot, MAX_PATH);
- pwszPathTail = PathAddBackslashW(wszFolderPath);
- }
+ pidlChild = (_ILIsPidlSimple (pidlComplete)) ? pidlComplete : ILCloneFirst (pidlComplete);
- _ILSimpleGetTextW(pidlChild,pwszPathTail,MAX_PATH - (int)(pwszPathTail - wszFolderPath));
+ CLSID clsidFolder = CLSID_ShellFSFolder;
+ DWORD attributes = _ILGetFileAttributes(ILFindLastID(pidlChild), NULL, 0);
+ if ((attributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0)
+ SHELL32_GetCLSIDForDirectory(pathRoot, pidlChild, &clsidFolder);
- if (SHELL32_GetCustomFolderAttributeFromPath (wszFolderPath,
- wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID))
- CLSIDFromString (wszCLSIDValue, &clsidFolder);
+ hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, clsidFolder, &pSF);
- hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild,
- clsidFolder, (LPVOID *)&pSF);
- }
- ILFree (pidlChild);
+ if (pidlChild != pidlComplete)
+ ILFree ((LPITEMIDLIST)pidlChild);
if (SUCCEEDED (hr)) {
if (_ILIsPidlSimple (pidlComplete)) {
CComPtr<IPersistFolder> pFolder;
HRESULT hr;
+ if (!pidlRoot || !ppvOut || !pidl || !pidl->mkid.cb)
+ return E_INVALIDARG;
+
+ *ppvOut = NULL;
+
GUID *pGUID = _ILGetGUIDPointer(pidl);
if (!pGUID)
{
ERR("SHELL32_BindToGuidItem called for non guid item!\n");
- return E_FAIL;
+ return E_INVALIDARG;
}
hr = SHCoCreateInstance(NULL, pGUID, NULL, IID_PPV_ARG(IPersistFolder, &pFolder));
if (FAILED(hr))
return hr;
- hr = pFolder->Initialize(ILCombine(pidlRoot, pidl));
- if (FAILED(hr))
- return hr;
-
if (_ILIsPidlSimple (pidl))
{
+ hr = pFolder->Initialize(ILCombine(pidlRoot, pidl));
+ if (FAILED(hr))
+ return hr;
+
return pFolder->QueryInterface(riid, ppvOut);
}
else
{
+ LPITEMIDLIST pidlChild = ILCloneFirst (pidl);
+ if (!pidlChild)
+ return E_OUTOFMEMORY;
+
+ hr = pFolder->Initialize(ILCombine(pidlRoot, pidlChild));
+ ILFree(pidlChild);
+ if (FAILED(hr))
+ return hr;
+
CComPtr<IShellFolder> psf;
hr = pFolder->QueryInterface(IID_PPV_ARG(IShellFolder, &psf));
if (FAILED(hr))
* virtual folders with the registry key WantsFORPARSING set.
*/
HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf,
- LPCITEMIDLIST pidl, DWORD dwFlags, LPWSTR szOut, DWORD dwOutLen)
+ LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
{
- LPITEMIDLIST pidlFirst;
- HRESULT hr = E_INVALIDARG;
-
- TRACE ("(%p)->(pidl=%p 0x%08x %p 0x%08x)\n", psf, pidl, dwFlags, szOut, dwOutLen);
- pdump (pidl);
+ LPITEMIDLIST pidlFirst = ILCloneFirst(pidl);
+ if (!pidlFirst)
+ return E_OUTOFMEMORY;
- pidlFirst = ILCloneFirst(pidl);
- if (pidlFirst)
+ CComPtr<IShellFolder> psfChild;
+ HRESULT hr = psf->BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
+ if (SUCCEEDED (hr))
{
- CComPtr<IShellFolder> psfChild;
-
- hr = psf->BindToObject(pidlFirst, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
- if (SUCCEEDED (hr))
- {
- STRRET strTemp;
- LPITEMIDLIST pidlNext = ILGetNext (pidl);
+ hr = psfChild->GetDisplayNameOf(ILGetNext (pidl), dwFlags, strRet);
+ }
+ ILFree (pidlFirst);
- hr = psfChild->GetDisplayNameOf(pidlNext, dwFlags, &strTemp);
- if (SUCCEEDED (hr))
- {
- if(!StrRetToStrNW (szOut, dwOutLen, &strTemp, pidlNext))
- hr = E_FAIL;
- }
- }
- ILFree (pidlFirst);
- } else
- hr = E_OUTOFMEMORY;
+ return hr;
+}
- TRACE ("-- ret=0x%08x %s\n", hr, debugstr_w(szOut));
+HRESULT HCR_GetClassName(REFIID riid, LPSTRRET strRet)
+{
+ BOOL bRet;
+ WCHAR wstrName[MAX_PATH+1];
+ bRet = HCR_GetClassNameW(CLSID_MyDocuments, wstrName, MAX_PATH);
+ if (!bRet)
+ return E_FAIL;
- return hr;
+ return SHSetStrRet(strRet, wstrName);
}
HRESULT SHELL32_GetDisplayNameOfGUIDItem(IShellFolder2* psf, LPCWSTR pszFolderPath, PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
{
- HRESULT hr = S_OK;
+ HRESULT hr;
GUID const *clsid = _ILGetGUIDPointer (pidl);
if (!strRet)
return E_INVALIDARG;
- LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
- if (!pszPath)
- return E_OUTOFMEMORY;
-
- if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
+ /* First of all check if we need to query the name from the child item */
+ if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING &&
+ GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL)
{
- int bWantsForParsing;
+ int bWantsForParsing = FALSE;
/*
* We can only get a filesystem path from a shellfolder if the
}
}
- if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
- bWantsForParsing)
+ if (bWantsForParsing)
{
/*
- * we need the filesystem path to the destination folder.
- * Only the folder itself can know it
- */
- hr = SHELL32_GetDisplayNameOfChild (psf, pidl, dwFlags,
- pszPath,
- MAX_PATH);
+ * we need the filesystem path to the destination folder.
+ * Only the folder itself can know it
+ */
+ return SHELL32_GetDisplayNameOfChild (psf, pidl, dwFlags, strRet);
}
- else
- {
- wcscpy(pszPath, pszFolderPath);
- PWCHAR pItemName = &pszPath[wcslen(pszPath)];
+ }
- /* parsing name like ::{...} */
- pItemName[0] = ':';
- pItemName[1] = ':';
- SHELL32_GUIDToStringW (*clsid, &pItemName[2]);
- }
+ /* Allocate the buffer for the result */
+ LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
+ if (!pszPath)
+ return E_OUTOFMEMORY;
+
+ hr = S_OK;
+
+ if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
+ {
+ wcscpy(pszPath, pszFolderPath);
+ PWCHAR pItemName = &pszPath[wcslen(pszPath)];
+
+ /* parsing name like ::{...} */
+ pItemName[0] = ':';
+ pItemName[1] = ':';
+ SHELL32_GUIDToStringW (*clsid, &pItemName[2]);
}
else
{
/* user friendly name */
- HCR_GetClassNameW (*clsid, pszPath, MAX_PATH);
+ if (!HCR_GetClassNameW (*clsid, pszPath, MAX_PATH))
+ hr = E_FAIL;
}
if (SUCCEEDED(hr))
return S_OK;
}
-HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
+HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
- TRACE ("0x%08x\n", *pdwAttributes);
+ SHELLDETAILS sd;
+ WCHAR wszItem1[MAX_PATH], wszItem2[MAX_PATH];
- if (*pdwAttributes & ~dwSupportedAttr)
+ isf->GetDetailsOf(pidl1, lParam, &sd);
+ StrRetToBufW(&sd.str, pidl1, wszItem1, MAX_PATH);
+ isf->GetDetailsOf(pidl2, lParam, &sd);
+ StrRetToBufW(&sd.str, pidl2, wszItem2, MAX_PATH);
+ int ret = wcsicmp(wszItem1, wszItem2);
+
+ return MAKE_COMPARE_HRESULT(ret);
+}
+
+HRESULT SHELL32_CompareGuidItems(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
+{
+ if (pidl1->mkid.cb == 0 || pidl2->mkid.cb == 0)
{
- WARN ("attributes 0x%08x not implemented\n", (*pdwAttributes & ~dwSupportedAttr));
- *pdwAttributes &= dwSupportedAttr;
+ ERR("Got an empty pidl!\n");
+ return E_INVALIDARG;
}
- if (_ILIsSpecialFolder(pidl))
+ BOOL bIsGuidFolder1 = _ILIsSpecialFolder(pidl1);
+ BOOL bIsGuidFolder2 = _ILIsSpecialFolder(pidl2);
+
+ if (!bIsGuidFolder1 && !bIsGuidFolder2)
{
- return SHELL32_GetGuidItemAttributes(psf, pidl, pdwAttributes);
+ ERR("Got no guid pidl!\n");
+ return E_INVALIDARG;
}
- else if(_ILIsFolder(pidl) || _ILIsValue(pidl))
+ else if (bIsGuidFolder1 && bIsGuidFolder2)
{
- return SHELL32_GetFSItemAttributes(psf, pidl, pdwAttributes);
+ return SHELL32_CompareDetails(isf, lParam, pidl1, pidl2);
+ }
+
+ /* Guid folders come first compared to everything else */
+ return MAKE_COMPARE_HRESULT(bIsGuidFolder1 ? -1 : 1);
+}
+
+HRESULT SH_ParseGuidDisplayName(IShellFolder2 * pFolder,
+ HWND hwndOwner,
+ LPBC pbc,
+ LPOLESTR lpszDisplayName,
+ DWORD *pchEaten,
+ PIDLIST_RELATIVE *ppidl,
+ DWORD *pdwAttributes)
+{
+ LPITEMIDLIST pidl;
+
+ if (!lpszDisplayName || !ppidl)
+ return E_INVALIDARG;
+
+ *ppidl = 0;
+
+ if (pchEaten)
+ *pchEaten = 0;
+
+ UINT cch = wcslen(lpszDisplayName);
+ if (cch < 39 || lpszDisplayName[0] != L':' || lpszDisplayName[1] != L':')
+ return E_FAIL;
+
+ pidl = _ILCreateGuidFromStrW(lpszDisplayName + 2);
+ if (pidl == NULL)
+ return E_FAIL;
+
+ if (cch < 41)
+ {
+ *ppidl = pidl;
+ if (pdwAttributes && *pdwAttributes)
+ {
+ SHELL32_GetGuidItemAttributes(pFolder, *ppidl, pdwAttributes);
+ }
}
else
{
- /* Set common attributes */
- ERR("We got a pidl that is neither a guid or an FS item!!! Type=0x%x\n",pidl->mkid.abID[0]);
- *pdwAttributes &= SFGAO_CANLINK;
+ HRESULT hr = SHELL32_ParseNextElement(pFolder, hwndOwner, pbc, &pidl, lpszDisplayName + 41, pchEaten, pdwAttributes);
+ if (SUCCEEDED(hr))
+ {
+ *ppidl = pidl;
+ }
+ return hr;
}
- TRACE ("-- 0x%08x\n", *pdwAttributes);
return S_OK;
}
-/***********************************************************************
- * SHELL32_CompareIDs
- */
-HRESULT SHELL32_CompareIDs(IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
+HRESULT SHELL32_SetNameOfGuidItem(PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
{
- int type1,
- type2;
- char szTemp1[MAX_PATH];
- char szTemp2[MAX_PATH];
- HRESULT nReturn;
- LPITEMIDLIST firstpidl;
- LPITEMIDLIST nextpidl1;
- LPITEMIDLIST nextpidl2;
- CComPtr<IShellFolder> psf;
-
- /* test for empty pidls */
- BOOL isEmpty1 = _ILIsDesktop(pidl1);
- BOOL isEmpty2 = _ILIsDesktop(pidl2);
-
- if (isEmpty1 && isEmpty2)
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
- if (isEmpty1)
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD) -1);
- if (isEmpty2)
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 1);
-
- /* test for different types. Sort order is the PT_* constant */
- type1 = _ILGetDataPointer(pidl1)->type;
- type2 = _ILGetDataPointer(pidl2)->type;
- if (type1 < type2)
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD) -1);
- else if (type1 > type2)
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 1);
-
- /* test for name of pidl */
- _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
- _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
- nReturn = lstrcmpiA(szTemp1, szTemp2);
- if (nReturn < 0)
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD) -1);
- else if (nReturn > 0)
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 1);
-
- /* test of complex pidls */
- firstpidl = ILCloneFirst(pidl1);
- nextpidl1 = ILGetNext(pidl1);
- nextpidl2 = ILGetNext(pidl2);
-
- /* optimizing: test special cases and bind not deeper */
- /* the deeper shellfolder would do the same */
- isEmpty1 = _ILIsDesktop(nextpidl1);
- isEmpty2 = _ILIsDesktop(nextpidl2);
-
- if (isEmpty1 && isEmpty2)
+ GUID const *clsid = _ILGetGUIDPointer (pidl);
+ LPOLESTR pStr;
+ HRESULT hr;
+ WCHAR szName[100];
+
+ if (!clsid)
{
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
+ ERR("Pidl is not reg item!\n");
+ return E_FAIL;
}
- else if (isEmpty1)
+
+ hr = StringFromCLSID(*clsid, &pStr);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ swprintf(szName, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr);
+
+ DWORD cbData = (wcslen(lpName) + 1) * sizeof(WCHAR);
+ LONG res = SHSetValueW(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, lpName, cbData);
+
+ CoTaskMemFree(pStr);
+
+ if (res == ERROR_SUCCESS)
{
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD) -1);
+ *pPidlOut = ILClone(pidl);
+ return S_OK;
}
- else if (isEmpty2)
+
+ return E_FAIL;
+}
+
+HRESULT SHELL32_GetDetailsOfGuidItem(IShellFolder2* psf, PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
+{
+ GUID const *clsid = _ILGetGUIDPointer (pidl);
+
+ if (!clsid)
{
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 1);
- /* optimizing end */
+ ERR("Pidl is not reg item!\n");
+ return E_FAIL;
}
- else if (SUCCEEDED(iface->BindToObject(firstpidl, NULL, IID_PPV_ARG(IShellFolder, &psf)))) {
- nReturn = psf->CompareIDs(lParam, nextpidl1, nextpidl2);
+
+ switch(iColumn)
+ {
+ case 0: /* name */
+ return psf->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
+ case 1: /* comment */
+ HKEY hKey;
+ if (HCR_RegOpenClassIDKey(*clsid, &hKey))
+ {
+ psd->str.cStr[0] = 0x00;
+ psd->str.uType = STRRET_CSTR;
+ RegLoadMUIStringA(hKey, "InfoTip", psd->str.cStr, MAX_PATH, NULL, 0, NULL);
+ RegCloseKey(hKey);
+ return S_OK;
+ }
}
- ILFree(firstpidl);
- return nReturn;
+ return E_FAIL;
}
/***********************************************************************