[SHELL32]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 7 Jul 2017 20:34:27 +0000 (20:34 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 7 Jul 2017 20:34:27 +0000 (20:34 +0000)
- 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

reactos/dll/win32/shell32/folders/CAdminToolsFolder.cpp
reactos/dll/win32/shell32/folders/CDesktopFolder.cpp
reactos/dll/win32/shell32/folders/CDrivesFolder.cpp
reactos/dll/win32/shell32/folders/CFSFolder.cpp
reactos/dll/win32/shell32/folders/CFontsFolder.cpp
reactos/dll/win32/shell32/folders/CMyDocsFolder.cpp
reactos/dll/win32/shell32/folders/CNetFolder.cpp
reactos/dll/win32/shell32/folders/CRegFolder.cpp
reactos/dll/win32/shell32/shfldr.h
reactos/dll/win32/shell32/shlfolder.cpp

index b55db6b..47a6415 100644 (file)
@@ -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));
index cf1656f..cead72f 100644 (file)
@@ -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));
index 1accb7a..f12f114 100644 (file)
@@ -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<IShellFolder> 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;
 }
 
 /**************************************************************************
index 518877b..0c98627 100644 (file)
@@ -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<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)
+                    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<IShellFolder> 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;
+
 }
 
 /**************************************************************************
index 6e78d11..3b9a3d8 100644 (file)
@@ -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));
index d3b14f5..0e1ae1b 100644 (file)
@@ -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));
index b0bfdce..35e2ef7 100644 (file)
@@ -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<IShellFolder> 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
index 99bdef2..92eeee6 100644 (file)
@@ -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<IShellFolder> 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);
+
         }
     }
 
index 504a94c..448fccc 100644 (file)
@@ -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);
index 00538a2..4a53117 100644 (file)
 
 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<IShellFolder> 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<IPersistFolder> ppf;
     CComPtr<IPersistFolder3> 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<IShellFolder> 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<IShellFolder> 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<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)
-                    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);