From: Giannis Adamopoulos Date: Fri, 7 Jul 2017 20:34:27 +0000 (+0000) Subject: [SHELL32] X-Git-Tag: ReactOS-0.4.6~114 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=201f83b4b1e85f4f82ab3cfe31eb04bbcb5a9091 [SHELL32] - Simplify SHELL32_CoCreateInitSF by letting the callers fill the PERSIST_FOLDER_TARGET_INFO. This lets us stop using _ILSimpleGetTextW in it which breaks the logic that pidls should be read only by their shell folder. Also add an overload for SHELL32_CoCreateInitSF that makes it simpler to create a shell folder with a csidl. - Add a SHELL32_BindToSF helper to share some logic that was duplicated in several shell folders. - Move SHELL32_GetCustomFolderAttributeFromPath, SHELL32_GetCLSIDForDirectory and SHELL32_GetFSItemAttributes, SHELL32_BindToFS to CFSFolder.cpp as these were fs specific. - These changes give finer control to shell folders for how the bind will be done and shares more logic that can be shared. svn path=/trunk/; revision=75301 --- diff --git a/reactos/dll/win32/shell32/folders/CAdminToolsFolder.cpp b/reactos/dll/win32/shell32/folders/CAdminToolsFolder.cpp index b55db6be0ab..47a6415f6a3 100644 --- a/reactos/dll/win32/shell32/folders/CAdminToolsFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CAdminToolsFolder.cpp @@ -175,8 +175,6 @@ HRESULT WINAPI CAdminToolsFolder::Initialize(LPCITEMIDLIST pidl) return E_OUTOFMEMORY; return SHELL32_CoCreateInitSF(m_pidlInner, - NULL, - NULL, &CLSID_ShellFSFolder, CSIDL_COMMON_ADMINTOOLS, IID_PPV_ARG(IShellFolder2, &m_pisfInner)); diff --git a/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp b/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp index cf1656fc4b4..cead72f311a 100644 --- a/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDesktopFolder.cpp @@ -270,8 +270,6 @@ HRESULT WINAPI CDesktopFolder::FinalConstruct() /* Create the inner fs folder */ hr = SHELL32_CoCreateInitSF(pidlRoot, - NULL, - NULL, &CLSID_ShellFSFolder, CSIDL_DESKTOPDIRECTORY, IID_PPV_ARG(IShellFolder2, &m_DesktopFSFolder)); @@ -280,8 +278,6 @@ HRESULT WINAPI CDesktopFolder::FinalConstruct() /* Create the inner shared fs folder. Dont fail on failure. */ hr = SHELL32_CoCreateInitSF(pidlRoot, - NULL, - NULL, &CLSID_ShellFSFolder, CSIDL_COMMON_DESKTOPDIRECTORY, IID_PPV_ARG(IShellFolder2, &m_SharedDesktopFSFolder)); diff --git a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp index 1accb7a8b26..f12f1144ef1 100644 --- a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -390,31 +390,25 @@ HRESULT WINAPI CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcRese if (_ILIsSpecialFolder(pidl)) return m_regFolder->BindToObject(pidl, pbcReserved, riid, ppvOut); - LPITEMIDLIST pidlChild = ILCloneFirst (pidl); - if (!pidlChild) - return E_OUTOFMEMORY; - - CComPtr psf; - HRESULT hr = SHELL32_CoCreateInitSF(pidlRoot, - NULL, - pidlChild, - &CLSID_ShellFSFolder, - -1, - IID_PPV_ARG(IShellFolder, &psf)); - - ILFree(pidlChild); - - if (FAILED(hr)) + CHAR* pchDrive = _ILGetDataPointer(pidl)->u.drive.szDriveName; + + PERSIST_FOLDER_TARGET_INFO pfti = {0}; + pfti.dwAttributes = -1; + pfti.csidl = -1; + pfti.szTargetParsingName[0] = *pchDrive; + pfti.szTargetParsingName[1] = L':'; + pfti.szTargetParsingName[2] = L'\\'; + + HRESULT hr = SHELL32_BindToSF(pidlRoot, + &pfti, + pidl, + &CLSID_ShellFSFolder, + riid, + ppvOut); + if (FAILED_UNEXPECTEDLY(hr)) return hr; - if (_ILIsPidlSimple (pidl)) - { - return psf->QueryInterface(riid, ppvOut); - } - else - { - return psf->BindToObject(ILGetNext (pidl), pbcReserved, riid, ppvOut); - } + return S_OK; } /************************************************************************** diff --git a/reactos/dll/win32/shell32/folders/CFSFolder.cpp b/reactos/dll/win32/shell32/folders/CFSFolder.cpp index 518877bc2fc..0c986270ee6 100644 --- a/reactos/dll/win32/shell32/folders/CFSFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CFSFolder.cpp @@ -130,6 +130,110 @@ LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path) return pidl; } +void SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir, CLSID* pclsidFolder) +{ + WCHAR wszCLSIDValue[CHARS_IN_GUID]; + WCHAR wszDesktopIni[MAX_PATH]; + StringCchCopyW(wszDesktopIni, MAX_PATH, pwszDir); + StringCchCatW(wszDesktopIni, MAX_PATH, L"\\desktop.ini"); + + if (GetPrivateProfileStringW(L".ShellClassInfo", + L"CLSID", + L"", + wszCLSIDValue, + CHARS_IN_GUID, + wszDesktopIni)) + { + CLSIDFromString (wszCLSIDValue, pclsidFolder); + } +} + + +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_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes) +{ + DWORD dwFileAttributes, dwShellAttributes; + + if (!_ILIsFolder(pidl) && !_ILIsValue(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; + } + + dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0); + + /* Set common attributes */ + dwShellAttributes = *pdwAttributes; + dwShellAttributes |= SFGAO_FILESYSTEM | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANDELETE | + SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANCOPY; + + if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + dwShellAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); + } + else + dwShellAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); + + if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + dwShellAttributes |= SFGAO_HIDDEN; + else + dwShellAttributes &= ~SFGAO_HIDDEN; + + if (dwFileAttributes & FILE_ATTRIBUTE_READONLY) + dwShellAttributes |= SFGAO_READONLY; + else + dwShellAttributes &= ~SFGAO_READONLY; + + if (SFGAO_LINK & *pdwAttributes) + { + char ext[MAX_PATH]; + + if (!_ILGetExtension(pidl, ext, MAX_PATH) || lstrcmpiA(ext, "lnk")) + dwShellAttributes &= ~SFGAO_LINK; + } + + if (SFGAO_HASSUBFOLDER & *pdwAttributes) + { + CComPtr psf2; + if (SUCCEEDED(psf->BindToObject(pidl, 0, IID_PPV_ARG(IShellFolder, &psf2)))) + { + CComPtr pEnumIL; + if (SUCCEEDED(psf2->EnumObjects(0, SHCONTF_FOLDERS, &pEnumIL))) + { + if (pEnumIL->Skip(1) != S_OK) + dwShellAttributes &= ~SFGAO_HASSUBFOLDER; + } + } + } + + *pdwAttributes &= dwShellAttributes; + + TRACE ("-- 0x%08x\n", *pdwAttributes); + return S_OK; +} + /************************************************************************** * CFSFolder::ParseDisplayName {SHELL32} * @@ -274,7 +378,48 @@ HRESULT WINAPI CFSFolder::BindToObject( TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl, pbc, shdebugstr_guid(&riid), ppvOut); - return SHELL32_BindToFS(pidlRoot, sPathTarget, pidl, riid, ppvOut); + CComPtr pSF; + HRESULT hr; + + if (!pidlRoot || !ppvOut || !pidl || !pidl->mkid.cb) + return E_INVALIDARG; + + if (_ILIsValue(pidl)) + { + ERR("Binding to file is unimplemented\n"); + return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + } + if (!_ILIsFolder(pidl)) + { + ERR("Got an unknown type of pidl!\n"); + return E_FAIL; + } + + *ppvOut = NULL; + + /* Get the pidl data */ + FileStruct* pData = &_ILGetDataPointer(pidl)->u.file; + FileStructW* pDataW = _ILGetFileStructW(pidl); + + /* Create the target folder info */ + PERSIST_FOLDER_TARGET_INFO pfti = {0}; + pfti.dwAttributes = -1; + pfti.csidl = -1; + PathCombineW(pfti.szTargetParsingName, sPathTarget, pDataW->wszName); + + /* Get the CLSID to bind to */ + CLSID clsidFolder = CLSID_ShellFSFolder; + if ((pData->uFileAttribs & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)) != 0) + SHELL32_GetCLSIDForDirectory(pfti.szTargetParsingName, &clsidFolder); + + hr = SHELL32_BindToSF(pidlRoot, &pfti, pidl, &clsidFolder, riid, ppvOut); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + TRACE ("-- returning (%p) %08x\n", *ppvOut, hr); + + return S_OK; + } /************************************************************************** diff --git a/reactos/dll/win32/shell32/folders/CFontsFolder.cpp b/reactos/dll/win32/shell32/folders/CFontsFolder.cpp index 6e78d113d1f..3b9a3d83434 100644 --- a/reactos/dll/win32/shell32/folders/CFontsFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CFontsFolder.cpp @@ -175,9 +175,7 @@ HRESULT WINAPI CFontsFolder::Initialize(LPCITEMIDLIST pidl) if (!m_pidlInner) return E_OUTOFMEMORY; - return SHELL32_CoCreateInitSF(m_pidlInner, - NULL, - NULL, + return SHELL32_CoCreateInitSF(m_pidlInner, &CLSID_ShellFSFolder, CSIDL_FONTS, IID_PPV_ARG(IShellFolder2, &m_pisfInner)); diff --git a/reactos/dll/win32/shell32/folders/CMyDocsFolder.cpp b/reactos/dll/win32/shell32/folders/CMyDocsFolder.cpp index d3b14f5a898..0e1ae1b93ca 100644 --- a/reactos/dll/win32/shell32/folders/CMyDocsFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CMyDocsFolder.cpp @@ -175,8 +175,6 @@ HRESULT WINAPI CMyDocsFolder::Initialize(LPCITEMIDLIST pidl) return E_OUTOFMEMORY; return SHELL32_CoCreateInitSF(m_pidlInner, - NULL, - NULL, &CLSID_ShellFSFolder, CSIDL_PERSONAL, IID_PPV_ARG(IShellFolder2, &m_pisfInner)); diff --git a/reactos/dll/win32/shell32/folders/CNetFolder.cpp b/reactos/dll/win32/shell32/folders/CNetFolder.cpp index b0bfdce1dc9..35e2ef7eb77 100644 --- a/reactos/dll/win32/shell32/folders/CNetFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CNetFolder.cpp @@ -283,31 +283,13 @@ HRESULT WINAPI CNetFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLI HRESULT WINAPI CNetFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) { #ifdef HACKY_UNC_PATHS - PITEMID_CHILD pidlChild = ILCloneFirst (pidl); - if (!pidlChild) - return E_FAIL; - - PIDLIST_ABSOLUTE pidlAbsolute = ILCombine(pidlRoot,pidlChild); - if (!pidlAbsolute) - return E_FAIL; - - CComPtr psf; - HRESULT hr = SHELL32_CoCreateInitSF(pidlAbsolute, - (WCHAR*)pidl->mkid.abID, - NULL, - &CLSID_ShellFSFolder, - -1, - IID_PPV_ARG(IShellFolder, &psf)); - ILFree(pidlChild); - ILFree(pidlAbsolute); + /* Create the target folder info */ + PERSIST_FOLDER_TARGET_INFO pfti = {0}; + pfti.dwAttributes = -1; + pfti.csidl = -1; + StringCchCopyW(pfti.szTargetParsingName, MAX_PATH, (WCHAR*)pidl->mkid.abID); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - if (_ILIsPidlSimple (pidl)) - return psf->QueryInterface(riid, ppvOut); - else - return psf->BindToObject(ILGetNext (pidl), pbcReserved, riid, ppvOut); + return SHELL32_BindToSF(pidlRoot, &pfti, pidl, &CLSID_ShellFSFolder, riid, ppvOut); #else return E_NOTIMPL; #endif diff --git a/reactos/dll/win32/shell32/folders/CRegFolder.cpp b/reactos/dll/win32/shell32/folders/CRegFolder.cpp index 99bdef27021..92eeee61eee 100644 --- a/reactos/dll/win32/shell32/folders/CRegFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CRegFolder.cpp @@ -339,24 +339,11 @@ HRESULT WINAPI CRegFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserve return E_INVALIDARG; } - LPITEMIDLIST pidlChild = ILCloneFirst (pidl); - if (!pidlChild) - return E_OUTOFMEMORY; - - CComPtr psf; - hr = SHELL32_CoCreateInitSF(m_pidlRoot, NULL, pidlChild, pGUID, -1, IID_PPV_ARG(IShellFolder, &psf)); - ILFree(pidlChild); - if (FAILED(hr)) + hr = SHELL32_BindToSF(m_pidlRoot, NULL, pidl, pGUID, riid, ppvOut); + if (FAILED_UNEXPECTEDLY(hr)) return hr; - if (_ILIsPidlSimple (pidl)) - { - return psf->QueryInterface(riid, ppvOut); - } - else - { - return psf->BindToObject(ILGetNext (pidl), pbcReserved, riid, ppvOut); - } + return S_OK; } HRESULT WINAPI CRegFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) @@ -485,7 +472,14 @@ HRESULT WINAPI CRegFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, } else { - return HCR_GetClassName(m_guid, strRet); + BOOL bRet; + WCHAR wstrName[MAX_PATH+1]; + bRet = HCR_GetClassNameW(m_guid, wstrName, MAX_PATH); + if (!bRet) + return E_FAIL; + + return SHSetStrRet(strRet, wstrName); + } } diff --git a/reactos/dll/win32/shell32/shfldr.h b/reactos/dll/win32/shell32/shfldr.h index 504a94c0f2a..448fccc37ac 100644 --- a/reactos/dll/win32/shell32/shfldr.h +++ b/reactos/dll/win32/shell32/shfldr.h @@ -40,13 +40,8 @@ LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut); HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut, LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes); -HRESULT HCR_GetClassName(REFIID riid, LPSTRRET strRet); - HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet); -HRESULT SHELL32_BindToFS (LPCITEMIDLIST pidlRoot, - LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut); - LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path); HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes); @@ -55,8 +50,16 @@ HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST HRESULT SHELL32_CompareChildren(IShellFolder2* psf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); -HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, - LPCITEMIDLIST pidlChild, const GUID* clsid, int csidl, REFIID riid, LPVOID *ppvOut); +#ifdef __cplusplus +HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti, + LPCITEMIDLIST pidlChild, const GUID* clsid, REFIID riid, LPVOID *ppvOut); + +HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, const GUID* clsid, + int csidl, REFIID riid, LPVOID *ppvOut); +#endif + +HRESULT SHELL32_BindToSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti, + LPCITEMIDLIST pidl, const GUID* clsid, REFIID riid, LPVOID *ppvOut); extern "C" BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey); diff --git a/reactos/dll/win32/shell32/shlfolder.cpp b/reactos/dll/win32/shell32/shlfolder.cpp index 00538a239dd..4a53117c4f2 100644 --- a/reactos/dll/win32/shell32/shlfolder.cpp +++ b/reactos/dll/win32/shell32/shlfolder.cpp @@ -25,37 +25,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); -/*************************************************************************** - * SHELL32_GetCustomFolderAttributeFromPath (internal function) - * - * Gets a value from the folder's desktop.ini file, if one exists. - * - * PARAMETERS - * pwszFolderPath[I] Folder containing the desktop.ini file. - * pwszHeading [I] Heading in .ini file. - * pwszAttribute [I] Attribute in .ini file. - * pwszValue [O] Buffer to store value into. - * cchValue [I] Size in characters including NULL of buffer pointed to - * by pwszValue. - * - * RETURNS - * TRUE if returned non-NULL value. - * FALSE otherwise. - */ -static BOOL __inline SHELL32_GetCustomFolderAttributeFromPath( - LPWSTR pwszFolderPath, LPCWSTR pwszHeading, LPCWSTR pwszAttribute, - LPWSTR pwszValue, DWORD cchValue) -{ - static const WCHAR wszDesktopIni[] = - {'d','e','s','k','t','o','p','.','i','n','i',0}; - static const WCHAR wszDefault[] = {0}; - - PathAddBackslashW(pwszFolderPath); - PathAppendW(pwszFolderPath, wszDesktopIni); - return GetPrivateProfileStringW(pwszHeading, pwszAttribute, wszDefault, - pwszValue, cchValue, pwszFolderPath); -} - /*************************************************************************** * GetNextElement (internal function) * @@ -148,14 +117,12 @@ HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, * pathRoot can be NULL for Folders being a drive. * In this case the absolute path is built from pidlChild (eg. C:) */ -HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, - LPCITEMIDLIST pidlChild, const GUID* clsid, int csidl, REFIID riid, LPVOID *ppvOut) +HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti, + LPCITEMIDLIST pidlChild, const GUID* clsid, REFIID riid, LPVOID *ppvOut) { HRESULT hr; CComPtr pShellFolder; - TRACE ("%p %s %p\n", pidlRoot, debugstr_w(pathRoot), pidlChild); - hr = SHCoCreateInstance(NULL, clsid, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder)); if (FAILED(hr)) return hr; @@ -164,32 +131,9 @@ HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, CComPtr ppf; CComPtr ppf3; - if (SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3)))) + if (ppfti && SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3)))) { - PERSIST_FOLDER_TARGET_INFO ppfti; - - ZeroMemory (&ppfti, sizeof (ppfti)); - - /* fill the PERSIST_FOLDER_TARGET_INFO */ - ppfti.dwAttributes = -1; - ppfti.csidl = csidl; - - /* build path */ - if (pathRoot) - { - lstrcpynW (ppfti.szTargetParsingName, pathRoot, MAX_PATH - 1); - PathAddBackslashW(ppfti.szTargetParsingName); /* FIXME: why have drives a backslash here ? */ - } - - if (pidlChild) - { - int len = wcslen(ppfti.szTargetParsingName); - - if (!_ILSimpleGetTextW(pidlChild, ppfti.szTargetParsingName + len, MAX_PATH - len)) - hr = E_INVALIDARG; - } - - ppf3->InitializeEx(NULL, pidlAbsolute, &ppfti); + ppf3->InitializeEx(NULL, pidlAbsolute, ppfti); } else if (SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder, &ppf)))) { @@ -200,91 +144,39 @@ HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot, return pShellFolder->QueryInterface(riid, ppvOut); } -void SHELL32_GetCLSIDForDirectory(LPCWSTR pathRoot, LPCITEMIDLIST pidl, CLSID* pclsidFolder) +HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, const GUID* clsid, + int csidl, REFIID riid, LPVOID *ppvOut) { - 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)); + /* fill the PERSIST_FOLDER_TARGET_INFO */ + PERSIST_FOLDER_TARGET_INFO pfti = {0}; + pfti.dwAttributes = -1; + pfti.csidl = csidl; - if (SHELL32_GetCustomFolderAttributeFromPath (wszFolderPath, - wszDotShellClassInfo, wszCLSID, wszCLSIDValue, CHARS_IN_GUID)) - CLSIDFromString (wszCLSIDValue, pclsidFolder); + return SHELL32_CoCreateInitSF(pidlRoot, &pfti, NULL, clsid, riid, ppvOut); } -/*********************************************************************** - * SHELL32_BindToFS [Internal] - * - * Common code for IShellFolder_BindToObject. - * - * PARAMS - * pidlRoot [I] The parent shell folder's absolute pidl. - * pathRoot [I] Absolute dos path of the parent shell folder. - * pidlComplete [I] PIDL of the child. Relative to pidlRoot. - * riid [I] GUID of the interface, which ppvOut shall be bound to. - * ppvOut [O] A reference to the child's interface (riid). - * - * NOTES - * pidlComplete has to contain at least one non empty SHITEMID. - * This function makes special assumptions on the shell namespace, which - * means you probably can't use it for your IShellFolder implementation. - */ -HRESULT SHELL32_BindToFS (LPCITEMIDLIST pidlRoot, - LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut) +HRESULT SHELL32_BindToSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti, + LPCITEMIDLIST pidl, const GUID* clsid, REFIID riid, LPVOID *ppvOut) { - CComPtr pSF; - HRESULT hr; - 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)) - { - ERR("Got an unknown type of pidl!\n"); + PITEMID_CHILD pidlChild = ILCloneFirst (pidl); + if (!pidlChild) return E_FAIL; - } - *ppvOut = NULL; + CComPtr psf; + HRESULT hr = SHELL32_CoCreateInitSF(pidlRoot, + ppfti, + pidlChild, + clsid, + IID_PPV_ARG(IShellFolder, &psf)); + ILFree(pidlChild); - pidlChild = (_ILIsPidlSimple (pidlComplete)) ? pidlComplete : ILCloneFirst (pidlComplete); - - 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); - - hr = SHELL32_CoCreateInitSF (pidlRoot, pathRoot, pidlChild, &clsidFolder, -1, IID_PPV_ARG(IShellFolder, &pSF)); - - if (pidlChild != pidlComplete) - ILFree ((LPITEMIDLIST)pidlChild); - - if (SUCCEEDED (hr)) { - if (_ILIsPidlSimple (pidlComplete)) { - /* no sub folders */ - hr = pSF->QueryInterface(riid, ppvOut); - } else { - /* go deeper */ - hr = pSF->BindToObject(ILGetNext (pidlComplete), NULL, riid, ppvOut); - } - } - - TRACE ("-- returning (%p) %08x\n", *ppvOut, hr); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; - return hr; + if (_ILIsPidlSimple (pidl)) + return psf->QueryInterface(riid, ppvOut); + else + return psf->BindToObject(ILGetNext (pidl), NULL, riid, ppvOut); } /*********************************************************************** @@ -319,122 +211,6 @@ HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, return hr; } -HRESULT HCR_GetClassName(REFIID riid, LPSTRRET strRet) -{ - BOOL bRet; - WCHAR wstrName[MAX_PATH+1]; - bRet = HCR_GetClassNameW(riid, wstrName, MAX_PATH); - if (!bRet) - return E_FAIL; - - return SHSetStrRet(strRet, wstrName); -} - -/*********************************************************************** - * SHELL32_GetItemAttributes - * - * NOTES - * Observed values: - * folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER - * file: 0x40000177 FILESYSTEM - * drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR - * mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR - * (seems to be default for shell extensions if no registry entry exists) - * - * win2k: - * folder: 0xF0400177 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER - * file: 0x40400177 FILESYSTEM | CANMONIKER - * drive 0xF0400154 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR | CANMONIKER | CANRENAME (LABEL) - * - * 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. - */ - -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_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes) -{ - DWORD dwFileAttributes, dwShellAttributes; - - if (!_ILIsFolder(pidl) && !_ILIsValue(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; - } - - dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0); - - /* Set common attributes */ - dwShellAttributes = *pdwAttributes; - dwShellAttributes |= SFGAO_FILESYSTEM | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANDELETE | - SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANCOPY; - - if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - dwShellAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); - } - else - dwShellAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); - - if (dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) - dwShellAttributes |= SFGAO_HIDDEN; - else - dwShellAttributes &= ~SFGAO_HIDDEN; - - if (dwFileAttributes & FILE_ATTRIBUTE_READONLY) - dwShellAttributes |= SFGAO_READONLY; - else - dwShellAttributes &= ~SFGAO_READONLY; - - if (SFGAO_LINK & *pdwAttributes) - { - char ext[MAX_PATH]; - - if (!_ILGetExtension(pidl, ext, MAX_PATH) || lstrcmpiA(ext, "lnk")) - dwShellAttributes &= ~SFGAO_LINK; - } - - if (SFGAO_HASSUBFOLDER & *pdwAttributes) - { - CComPtr psf2; - if (SUCCEEDED(psf->BindToObject(pidl, 0, IID_PPV_ARG(IShellFolder, &psf2)))) - { - CComPtr pEnumIL; - if (SUCCEEDED(psf2->EnumObjects(0, SHCONTF_FOLDERS, &pEnumIL))) - { - if (pEnumIL->Skip(1) != S_OK) - dwShellAttributes &= ~SFGAO_HASSUBFOLDER; - } - } - } - - *pdwAttributes &= dwShellAttributes; - - TRACE ("-- 0x%08x\n", *pdwAttributes); - return S_OK; -} - HRESULT SHELL32_CompareChildren(IShellFolder2* psf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) { PUIDLIST_RELATIVE nextpidl1 = ILGetNext (pidl1);