mirror of
https://github.com/reactos/reactos.git
synced 2024-09-29 14:09:10 +00:00
[SHELL32]
- Split SHELL32_GetItemAttributes to SHELL32_GetGuidItemAttributes and SHELL32_GetFSItemAttributes. - Add a couple helper functions that will reduce code duplication in folders with reg items: SHELL32_BindToGuidItem, SHELL32_GetDisplayNameOfGUIDItem svn path=/trunk/; revision=68729
This commit is contained in:
parent
ef89f318da
commit
8faea71a4d
|
@ -52,6 +52,21 @@ HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
|
|||
HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
|
||||
LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path);
|
||||
|
||||
HRESULT SHELL32_BindToGuidItem(LPCITEMIDLIST pidlRoot,
|
||||
PCUIDLIST_RELATIVE pidl,
|
||||
LPBC pbcReserved,
|
||||
REFIID riid,
|
||||
LPVOID *ppvOut);
|
||||
|
||||
HRESULT SHELL32_GetGuidItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes);
|
||||
|
||||
HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes);
|
||||
|
||||
HRESULT SHELL32_GetDisplayNameOfGUIDItem(IShellFolder2* psf, LPCWSTR pszFolderPath, PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet);
|
||||
|
||||
extern "C"
|
||||
BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey);
|
||||
|
||||
static __inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str)
|
||||
{
|
||||
return sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
|
|
|
@ -330,6 +330,45 @@ HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SHELL32_BindToGuidItem(LPCITEMIDLIST pidlRoot,
|
||||
PCUIDLIST_RELATIVE pidl,
|
||||
LPBC pbcReserved,
|
||||
REFIID riid,
|
||||
LPVOID *ppvOut)
|
||||
{
|
||||
CComPtr<IPersistFolder> pFolder;
|
||||
HRESULT hr;
|
||||
|
||||
GUID *pGUID = _ILGetGUIDPointer(pidl);
|
||||
if (!pGUID)
|
||||
{
|
||||
ERR("SHELL32_BindToGuidItem called for non guid item!\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
return pFolder->QueryInterface(riid, ppvOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
CComPtr<IShellFolder> psf;
|
||||
hr = pFolder->QueryInterface(IID_PPV_ARG(IShellFolder, &psf));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return psf->BindToObject(ILGetNext (pidl), pbcReserved, riid, ppvOut);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SHELL32_GetDisplayNameOfChild
|
||||
*
|
||||
|
@ -380,6 +419,85 @@ HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SHELL32_GetDisplayNameOfGUIDItem(IShellFolder2* psf, LPCWSTR pszFolderPath, PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
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)
|
||||
{
|
||||
int bWantsForParsing;
|
||||
|
||||
/*
|
||||
* We can only get a filesystem path from a shellfolder if the
|
||||
* value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
|
||||
*
|
||||
* Exception: The MyComputer folder doesn't have this key,
|
||||
* but any other filesystem backed folder it needs it.
|
||||
*/
|
||||
if (IsEqualIID (*clsid, CLSID_MyComputer))
|
||||
{
|
||||
bWantsForParsing = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
HKEY hkeyClass;
|
||||
if (HCR_RegOpenClassIDKey(*clsid, &hkeyClass))
|
||||
{
|
||||
LONG res = SHGetValueW(hkeyClass, L"Shellfolder", L"WantsForParsing", NULL, NULL, NULL);
|
||||
bWantsForParsing = (res == ERROR_SUCCESS);
|
||||
RegCloseKey(hkeyClass);
|
||||
}
|
||||
}
|
||||
|
||||
if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
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 (SUCCEEDED(hr))
|
||||
{
|
||||
strRet->uType = STRRET_WSTR;
|
||||
strRet->pOleStr = pszPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
CoTaskMemFree(pszPath);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SHELL32_GetItemAttributes
|
||||
*
|
||||
|
@ -399,26 +517,124 @@ HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf,
|
|||
* According to the MSDN documentation this function should not set flags. It claims only to reset flags when necessary.
|
||||
* However it turns out the native shell32.dll _sets_ flags in several cases - so do we.
|
||||
*/
|
||||
HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
|
||||
|
||||
static const DWORD dwSupportedAttr=
|
||||
SFGAO_CANCOPY | /*0x00000001 */
|
||||
SFGAO_CANMOVE | /*0x00000002 */
|
||||
SFGAO_CANLINK | /*0x00000004 */
|
||||
SFGAO_CANRENAME | /*0x00000010 */
|
||||
SFGAO_CANDELETE | /*0x00000020 */
|
||||
SFGAO_HASPROPSHEET | /*0x00000040 */
|
||||
SFGAO_DROPTARGET | /*0x00000100 */
|
||||
SFGAO_LINK | /*0x00010000 */
|
||||
SFGAO_READONLY | /*0x00040000 */
|
||||
SFGAO_HIDDEN | /*0x00080000 */
|
||||
SFGAO_FILESYSANCESTOR | /*0x10000000 */
|
||||
SFGAO_FOLDER | /*0x20000000 */
|
||||
SFGAO_FILESYSTEM | /*0x40000000 */
|
||||
SFGAO_HASSUBFOLDER; /*0x80000000 */
|
||||
|
||||
HRESULT SHELL32_GetGuidItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
|
||||
{
|
||||
if (!_ILIsSpecialFolder(pidl))
|
||||
{
|
||||
ERR("Got wrong type of pidl!\n");
|
||||
*pdwAttributes &= SFGAO_CANLINK;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (*pdwAttributes & ~dwSupportedAttr)
|
||||
{
|
||||
WARN ("attributes 0x%08x not implemented\n", (*pdwAttributes & ~dwSupportedAttr));
|
||||
*pdwAttributes &= dwSupportedAttr;
|
||||
}
|
||||
|
||||
/* First try to get them from the registry */
|
||||
if (HCR_GetFolderAttributes(pidl, pdwAttributes) && *pdwAttributes)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we can't get it from the registry we have to query the child */
|
||||
CComPtr<IShellFolder> psf2;
|
||||
if (SUCCEEDED(psf->BindToObject(pidl, 0, IID_PPV_ARG(IShellFolder, &psf2))))
|
||||
{
|
||||
return psf2->GetAttributesOf(0, NULL, pdwAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
*pdwAttributes &= SFGAO_CANLINK;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
|
||||
{
|
||||
DWORD dwAttributes;
|
||||
BOOL has_guid;
|
||||
static const DWORD dwSupportedAttr=
|
||||
SFGAO_CANCOPY | /*0x00000001 */
|
||||
SFGAO_CANMOVE | /*0x00000002 */
|
||||
SFGAO_CANLINK | /*0x00000004 */
|
||||
SFGAO_CANRENAME | /*0x00000010 */
|
||||
SFGAO_CANDELETE | /*0x00000020 */
|
||||
SFGAO_HASPROPSHEET | /*0x00000040 */
|
||||
SFGAO_DROPTARGET | /*0x00000100 */
|
||||
SFGAO_LINK | /*0x00010000 */
|
||||
SFGAO_READONLY | /*0x00040000 */
|
||||
SFGAO_HIDDEN | /*0x00080000 */
|
||||
SFGAO_FILESYSANCESTOR | /*0x10000000 */
|
||||
SFGAO_FOLDER | /*0x20000000 */
|
||||
SFGAO_FILESYSTEM | /*0x40000000 */
|
||||
SFGAO_HASSUBFOLDER; /*0x80000000 */
|
||||
|
||||
if (*pdwAttributes & ~dwSupportedAttr)
|
||||
{
|
||||
WARN ("attributes 0x%08x not implemented\n", (*pdwAttributes & ~dwSupportedAttr));
|
||||
*pdwAttributes &= dwSupportedAttr;
|
||||
}
|
||||
|
||||
dwAttributes = _ILGetFileAttributes(pidl, NULL, 0);
|
||||
if (!dwAttributes)
|
||||
{
|
||||
ERR("Got 0 attrs!\n");
|
||||
*pdwAttributes &= SFGAO_CANLINK;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* Set common attributes */
|
||||
*pdwAttributes |= SFGAO_FILESYSTEM | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANDELETE |
|
||||
SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANCOPY;
|
||||
|
||||
if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
*pdwAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR);
|
||||
}
|
||||
else
|
||||
*pdwAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR);
|
||||
|
||||
if (dwAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
*pdwAttributes |= SFGAO_HIDDEN;
|
||||
else
|
||||
*pdwAttributes &= ~SFGAO_HIDDEN;
|
||||
|
||||
if (dwAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
*pdwAttributes |= SFGAO_READONLY;
|
||||
else
|
||||
*pdwAttributes &= ~SFGAO_READONLY;
|
||||
|
||||
if (SFGAO_LINK & *pdwAttributes)
|
||||
{
|
||||
char ext[MAX_PATH];
|
||||
|
||||
if (!_ILGetExtension(pidl, ext, MAX_PATH) || lstrcmpiA(ext, "lnk"))
|
||||
*pdwAttributes &= ~SFGAO_LINK;
|
||||
}
|
||||
|
||||
if (SFGAO_HASSUBFOLDER & *pdwAttributes)
|
||||
{
|
||||
CComPtr<IShellFolder> psf2;
|
||||
if (SUCCEEDED(psf->BindToObject(pidl, 0, IID_PPV_ARG(IShellFolder, &psf2))))
|
||||
{
|
||||
CComPtr<IEnumIDList> pEnumIL;
|
||||
if (SUCCEEDED(psf2->EnumObjects(0, SHCONTF_FOLDERS, &pEnumIL)))
|
||||
{
|
||||
if (pEnumIL->Skip(1) != S_OK)
|
||||
*pdwAttributes &= ~SFGAO_HASSUBFOLDER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE ("-- 0x%08x\n", *pdwAttributes);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
|
||||
{
|
||||
TRACE ("0x%08x\n", *pdwAttributes);
|
||||
|
||||
if (*pdwAttributes & ~dwSupportedAttr)
|
||||
|
@ -427,79 +643,20 @@ HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWO
|
|||
*pdwAttributes &= dwSupportedAttr;
|
||||
}
|
||||
|
||||
has_guid = _ILGetGUIDPointer(pidl) != NULL;
|
||||
|
||||
dwAttributes = *pdwAttributes;
|
||||
|
||||
if (has_guid && HCR_GetFolderAttributes(pidl, &dwAttributes))
|
||||
*pdwAttributes = dwAttributes;
|
||||
else if (_ILGetDataPointer(pidl))
|
||||
if (_ILIsSpecialFolder(pidl))
|
||||
{
|
||||
return SHELL32_GetGuidItemAttributes(psf, pidl, pdwAttributes);
|
||||
}
|
||||
else if(_ILIsFolder(pidl) || _ILIsValue(pidl))
|
||||
{
|
||||
return SHELL32_GetFSItemAttributes(psf, pidl, pdwAttributes);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwAttributes = _ILGetFileAttributes(pidl, NULL, 0);
|
||||
|
||||
if (!dwAttributes && has_guid)
|
||||
{
|
||||
WCHAR path[MAX_PATH];
|
||||
STRRET strret;
|
||||
|
||||
/* File attributes are not present in the internal PIDL structure, so get them from the file system. */
|
||||
|
||||
HRESULT hr = psf->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = StrRetToBufW(&strret, pidl, path, MAX_PATH);
|
||||
|
||||
/* call GetFileAttributes() only for file system paths, not for parsing names like "::{...}" */
|
||||
if (SUCCEEDED(hr) && path[0]!=':')
|
||||
dwAttributes = GetFileAttributesW(path);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set common attributes */
|
||||
*pdwAttributes |= SFGAO_FILESYSTEM | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANDELETE |
|
||||
SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANCOPY;
|
||||
|
||||
if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
*pdwAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR);
|
||||
}
|
||||
else
|
||||
*pdwAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR);
|
||||
|
||||
if (dwAttributes & FILE_ATTRIBUTE_HIDDEN)
|
||||
*pdwAttributes |= SFGAO_HIDDEN;
|
||||
else
|
||||
*pdwAttributes &= ~SFGAO_HIDDEN;
|
||||
|
||||
if (dwAttributes & FILE_ATTRIBUTE_READONLY)
|
||||
*pdwAttributes |= SFGAO_READONLY;
|
||||
else
|
||||
*pdwAttributes &= ~SFGAO_READONLY;
|
||||
|
||||
if (SFGAO_LINK & *pdwAttributes)
|
||||
{
|
||||
char ext[MAX_PATH];
|
||||
|
||||
if (!_ILGetExtension(pidl, ext, MAX_PATH) || lstrcmpiA(ext, "lnk"))
|
||||
*pdwAttributes &= ~SFGAO_LINK;
|
||||
}
|
||||
|
||||
if (SFGAO_HASSUBFOLDER & *pdwAttributes)
|
||||
{
|
||||
CComPtr<IShellFolder> psf2;
|
||||
if (SUCCEEDED(psf->BindToObject(pidl, 0, IID_PPV_ARG(IShellFolder, &psf2))))
|
||||
{
|
||||
CComPtr<IEnumIDList> pEnumIL;
|
||||
if (SUCCEEDED(psf2->EnumObjects(0, SHCONTF_FOLDERS, &pEnumIL)))
|
||||
{
|
||||
if (pEnumIL->Skip(1) != S_OK)
|
||||
*pdwAttributes &= ~SFGAO_HASSUBFOLDER;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
*pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANRENAME|SFGAO_CANLINK;
|
||||
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;
|
||||
}
|
||||
|
||||
TRACE ("-- 0x%08x\n", *pdwAttributes);
|
||||
return S_OK;
|
||||
|
|
|
@ -222,7 +222,7 @@ BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LP
|
|||
*
|
||||
* Gets the icon for a filetype
|
||||
*/
|
||||
static BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey)
|
||||
BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey)
|
||||
{
|
||||
char xriid[50];
|
||||
sprintf( xriid, "CLSID\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
|
|
Loading…
Reference in a new issue