[SHELL32] Implement support for IID_IDropTarget in CDesktopFolder::GetUIObjectOf...
[reactos.git] / reactos / dll / win32 / shell32 / folders / CDesktopFolder.cpp
index 700896d..8d7b4eb 100644 (file)
@@ -44,12 +44,6 @@ always shows My Computer.
 /* Undocumented functions from shdocvw */
 extern "C" HRESULT WINAPI IEParseDisplayNameWithBCW(DWORD codepage, LPCWSTR lpszDisplayName, LPBC pbc, LPITEMIDLIST *ppidl);
 
-/***********************************************************************
-*     Desktopfolder implementation
-*/
-
-class CDesktopFolder;
-
 class CDesktopFolderEnum :
     public CEnumIDListBase
 {
@@ -69,14 +63,24 @@ class CDesktopFolderEnum :
 int SHELL_ConfirmMsgBox(HWND hWnd, LPWSTR lpszText, LPWSTR lpszCaption, HICON hIcon, BOOL bYesToAll);
 
 static const shvheader DesktopSFHeader[] = {
-    {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
+    {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 15},
     {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
-    {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
-    {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
-    {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
+    {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 10},
+    {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 12},
 };
 
-#define DESKTOPSHELLVIEWCOLUMNS 5
+#define DESKTOPSHELLVIEWCOLUMNS 4
+
+static const DWORD dwDesktopAttributes =
+    SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
+    SFGAO_STORAGEANCESTOR | SFGAO_HASPROPSHEET | SFGAO_STORAGE | SFGAO_CANLINK;
+static const DWORD dwMyComputerAttributes =
+    SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
+    SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
+static DWORD dwMyNetPlacesAttributes =
+    SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
+    SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
+
 
 CDesktopFolderEnum::CDesktopFolderEnum()
 {
@@ -109,18 +113,6 @@ IsNamespaceExtensionHidden(const WCHAR *iid)
     return Result;
 }
 
-static VOID
-SetNamespaceExtensionVisibleStatus(const WCHAR * iid, DWORD dwStatus)
-{
-    HKEY hKey;
-
-    if (RegOpenKeyExW(HKEY_CURRENT_USER, ClassicStartMenuW, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
-    {
-        RegSetValueExW(hKey, iid, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(DWORD));
-        RegCloseKey(hKey);
-    }
-}
-
 /**************************************************************************
  *  CreateDesktopEnumList()
  */
@@ -254,21 +246,10 @@ HRESULT WINAPI CDesktopFolderEnum::Initialize(CDesktopFolder *desktopFolder, HWN
     return ret ? S_OK : E_FAIL;
 }
 
-void CDesktopFolder::SF_RegisterClipFmt()
+CDesktopFolder::CDesktopFolder() :
+    sPathTarget(NULL),
+    pidlRoot(NULL)
 {
-    TRACE ("(%p)\n", this);
-
-    if (!cfShellIDList)
-        cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
-}
-
-CDesktopFolder::CDesktopFolder()
-{
-    pidlRoot = NULL;
-    sPathTarget = NULL;
-    cfShellIDList = 0;
-    SF_RegisterClipFmt();
-    fAcceptFmt = FALSE;
 }
 
 CDesktopFolder::~CDesktopFolder()
@@ -277,17 +258,74 @@ CDesktopFolder::~CDesktopFolder()
 
 HRESULT WINAPI CDesktopFolder::FinalConstruct()
 {
-    WCHAR                                szMyPath[MAX_PATH];
+    WCHAR szMyPath[MAX_PATH];
+    HRESULT hr;
+
+    /* Create the root pidl */
+    pidlRoot = _ILCreateDesktop();
+    if (!pidlRoot)
+        return E_OUTOFMEMORY;
+
+    /* Create the inner fs folder */
+    hr = SHELL32_CoCreateInitSF(pidlRoot, 
+                                NULL,
+                                NULL,
+                                &CLSID_ShellFSFolder,
+                                CSIDL_DESKTOPDIRECTORY,
+                                IID_PPV_ARG(IShellFolder2, &m_DesktopFSFolder));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
+    /* 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));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    /* Create the inner reg folder */
+    hr = CRegFolder_CreateInstance(&CLSID_ShellDesktop,
+                                   pidlRoot,
+                                   L"", 
+                                   IID_PPV_ARG(IShellFolder2, &m_regFolder));
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    /* Cache the path to the user desktop directory */
     if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE ))
         return E_UNEXPECTED;
 
-    pidlRoot = _ILCreateDesktop();    /* my qualified pidl */
     sPathTarget = (LPWSTR)SHAlloc((wcslen(szMyPath) + 1) * sizeof(WCHAR));
+    if (!sPathTarget)
+        return E_OUTOFMEMORY;
+
     wcscpy(sPathTarget, szMyPath);
     return S_OK;
 }
 
+HRESULT CDesktopFolder::_GetSFFromPidl(LPCITEMIDLIST pidl, IShellFolder2** psf)
+{
+    WCHAR szFileName[MAX_PATH];
+
+    if (_ILIsSpecialFolder(pidl))
+        return m_regFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
+
+    lstrcpynW(szFileName, sPathTarget, MAX_PATH - 1);
+    PathAddBackslashW(szFileName);
+    int cLen = wcslen(szFileName);
+
+    if (!_ILSimpleGetTextW(pidl, szFileName + cLen, MAX_PATH - cLen))
+        return E_FAIL;
+
+    if (GetFileAttributes(szFileName) == INVALID_FILE_ATTRIBUTES)
+        return m_SharedDesktopFSFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
+    else
+        return m_DesktopFSFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
+}
+
 /**************************************************************************
  *    CDesktopFolder::ParseDisplayName
  *
@@ -303,12 +341,10 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
     PIDLIST_RELATIVE *ppidl,
     DWORD *pdwAttributes)
 {
-    WCHAR szElement[MAX_PATH];
     LPCWSTR szNext = NULL;
     LPITEMIDLIST pidlTemp = NULL;
     PARSEDURLW urldata;
     HRESULT hr = S_OK;
-    CLSID clsid;
 
     TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
            this, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
@@ -317,13 +353,10 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
     if (!ppidl)
         return E_INVALIDARG;
 
+    *ppidl = NULL;
+
     if (!lpszDisplayName)
-    {
-        *ppidl = NULL;
         return E_INVALIDARG;
-    }
-
-    *ppidl = NULL;
 
     if (pchEaten)
         *pchEaten = 0;        /* strange but like the original */
@@ -332,10 +365,7 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
 
     if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
     {
-        szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
-        TRACE ("-- element: %s\n", debugstr_w (szElement));
-        CLSIDFromString (szElement + 2, &clsid);
-        pidlTemp = _ILCreateGuid (PT_GUID, clsid);
+        return m_regFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
     }
     else if (PathGetDriveNumberW (lpszDisplayName) >= 0)
     {
@@ -358,34 +388,21 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
         if (urldata.nScheme == URL_SCHEME_SHELL) /* handle shell: urls */
         {
             TRACE ("-- shell url: %s\n", debugstr_w(urldata.pszSuffix));
-            SHCLSIDFromStringW (urldata.pszSuffix + 2, &clsid);
-            pidlTemp = _ILCreateGuid (PT_GUID, clsid);
+            pidlTemp = _ILCreateGuidFromStrW(urldata.pszSuffix + 2);
         }
         else
             return IEParseDisplayNameWithBCW(CP_ACP, lpszDisplayName, pbc, ppidl);
     }
     else
     {
-        /* it's a filesystem path on the desktop. Let a FSFolder parse it */
-
         if (*lpszDisplayName)
         {
-            WCHAR szPath[MAX_PATH];
-            LPWSTR pathPtr;
+            /* it's a filesystem path on the desktop. Let a FSFolder parse it */
+            hr = m_DesktopFSFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
+            if (SUCCEEDED(hr))
+                return hr;
 
-            /* build a complete path to create a simple pidl */
-            lstrcpynW(szPath, sPathTarget, MAX_PATH);
-            pathPtr = PathAddBackslashW(szPath);
-            if (pathPtr)
-            {
-                lstrcpynW(pathPtr, lpszDisplayName, MAX_PATH - (pathPtr - szPath));
-                hr = _ILCreateFromPathW(szPath, &pidlTemp);
-            }
-            else
-            {
-                /* should never reach here, but for completeness */
-                hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
-            }
+            return m_SharedDesktopFSFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
         }
         else
             pidlTemp = _ILCreateMyComputer();
@@ -403,8 +420,9 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
         else
         {
             if (pdwAttributes && *pdwAttributes)
-                hr = SHELL32_GetItemAttributes((IShellFolder *)this,
-                                               pidlTemp, pdwAttributes);
+            {
+                GetAttributesOf(1, &pidlTemp, pdwAttributes);
+            }
         }
     }
 
@@ -435,10 +453,15 @@ HRESULT WINAPI CDesktopFolder::BindToObject(
     REFIID riid,
     LPVOID *ppvOut)
 {
-    TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n",
-           this, pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
+    if (!pidl)
+        return E_INVALIDARG;
+
+    CComPtr<IShellFolder2> psf;
+    HRESULT hr = _GetSFFromPidl(pidl, &psf);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-    return SHELL32_BindToChild( pidlRoot, sPathTarget, pidl, riid, ppvOut );
+    return psf->BindToObject(pidl, pbcReserved, riid, ppvOut);
 }
 
 /**************************************************************************
@@ -462,12 +485,23 @@ HRESULT WINAPI CDesktopFolder::BindToStorage(
  */
 HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 {
-    int nReturn;
+    bool bIsDesktopFolder1, bIsDesktopFolder2;
+
+    if (!pidl1 || !pidl2)
+    {
+        ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam, pidl1, pidl2);
+        return E_INVALIDARG;
+    }
+
+    bIsDesktopFolder1 = _ILIsDesktop(pidl1);
+    bIsDesktopFolder2 = _ILIsDesktop(pidl2);
+    if (bIsDesktopFolder1 || bIsDesktopFolder2)
+        return MAKE_COMPARE_HRESULT(bIsDesktopFolder1 - bIsDesktopFolder2);
 
-    TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
-    nReturn = SHELL32_CompareIDs ((IShellFolder *)this, lParam, pidl1, pidl2);
-    TRACE ("-- %i\n", nReturn);
-    return nReturn;
+    if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2))
+        return m_regFolder->CompareIDs(lParam, pidl1, pidl2);
+
+    return m_DesktopFSFolder->CompareIDs(lParam, pidl1, pidl2);
 }
 
 /**************************************************************************
@@ -491,12 +525,25 @@ HRESULT WINAPI CDesktopFolder::CreateViewObject(
 
     if (IsEqualIID (riid, IID_IDropTarget))
     {
-        hr = this->QueryInterface (IID_IDropTarget, ppvOut);
+        hr = m_DesktopFSFolder->CreateViewObject(hwndOwner, riid, ppvOut);
     }
     else if (IsEqualIID (riid, IID_IContextMenu))
     {
-        WARN ("IContextMenu not implemented\n");
-        hr = E_NOTIMPL;
+            HKEY hKeys[16];
+            UINT cKeys = 0;
+            AddClassKeyToArray(L"Directory\\Background", hKeys, &cKeys);
+
+            DEFCONTEXTMENU dcm;
+            dcm.hwnd = hwndOwner;
+            dcm.pcmcb = this;
+            dcm.pidlFolder = pidlRoot;
+            dcm.psf = this;
+            dcm.cidl = 0;
+            dcm.apidl = NULL;
+            dcm.cKeys = cKeys;
+            dcm.aKeys = hKeys;
+            dcm.punkAssociationInfo = NULL;
+            hr = SHCreateDefaultContextMenu (&dcm, riid, ppvOut);
     }
     else if (IsEqualIID (riid, IID_IShellView))
     {
@@ -517,15 +564,6 @@ HRESULT WINAPI CDesktopFolder::GetAttributesOf(
     DWORD *rgfInOut)
 {
     HRESULT hr = S_OK;
-    static const DWORD dwDesktopAttributes =
-        SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
-        SFGAO_STORAGEANCESTOR | SFGAO_HASPROPSHEET | SFGAO_STORAGE | SFGAO_CANLINK;
-    static const DWORD dwMyComputerAttributes =
-        SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
-        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
-    static DWORD dwMyNetPlacesAttributes =
-        SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
-        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
 
     TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
           this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
@@ -550,8 +588,17 @@ HRESULT WINAPI CDesktopFolder::GetAttributesOf(
                 *rgfInOut &= dwMyComputerAttributes;
             else if (_ILIsNetHood(apidl[i]))
                 *rgfInOut &= dwMyNetPlacesAttributes;
+            else if (_ILIsFolder(apidl[i]) || _ILIsValue(apidl[i]) || _ILIsSpecialFolder(apidl[i]))
+            {
+                CComPtr<IShellFolder2> psf;
+                HRESULT hr = _GetSFFromPidl(apidl[i], &psf);
+                if (FAILED_UNEXPECTEDLY(hr))
+                    continue;
+
+                psf->GetAttributesOf(1, &apidl[i], rgfInOut);
+            }
             else
-                SHELL32_GetItemAttributes((IShellFolder *)this, apidl[i], rgfInOut);
+                ERR("Got an unknown pidl type!!!\n");
         }
     }
     /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
@@ -582,8 +629,7 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
     UINT *prgfInOut,
     LPVOID *ppvOut)
 {
-    LPITEMIDLIST pidl;
-    IUnknown *pObj = NULL;
+    LPVOID pObj = NULL;
     HRESULT hr = E_INVALIDARG;
 
     TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
@@ -594,44 +640,60 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
 
     *ppvOut = NULL;
 
+    if (cidl == 1 && !_ILIsSpecialFolder(apidl[0]))
+    {
+        CComPtr<IShellFolder2> psf;
+        HRESULT hr = _GetSFFromPidl(apidl[0], &psf);
+        if (FAILED_UNEXPECTEDLY(hr))
+            return hr;
+
+        return psf->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
+    }
+
     if (IsEqualIID (riid, IID_IContextMenu))
     {
-        hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder *)this, NULL, 0, NULL, (IContextMenu **)&pObj);
+        if (_ILIsSpecialFolder(apidl[0]))
+        {
+            hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj);
+        }
+        else
+        {
+            /* Do not use the context menu of the CFSFolder here. */
+            /* We need to pass a pointer of the CDesktopFolder so as the data object that the context menu gets is rooted to the desktop */
+            /* Otherwise operations like that involve items from both user and shared desktop will not work */
+            HKEY hKeys[16];
+            UINT cKeys = 0;
+            AddFSClassKeysToArray(apidl[0], hKeys, &cKeys);
+
+            DEFCONTEXTMENU dcm;
+            dcm.hwnd = hwndOwner;
+            dcm.pcmcb = this;
+            dcm.pidlFolder = pidlRoot;
+            dcm.psf = this;
+            dcm.cidl = cidl;
+            dcm.apidl = apidl;
+            dcm.cKeys = cKeys;
+            dcm.aKeys = hKeys;
+            dcm.punkAssociationInfo = NULL;
+            hr = SHCreateDefaultContextMenu (&dcm, riid, &pObj);
+        }
     }
     else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
     {
         hr = IDataObject_Constructor( hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj);
     }
-    else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
-    {
-        pidl = ILCombine (pidlRoot, apidl[0]);
-        pObj = IExtractIconA_Constructor (pidl);
-        SHFree (pidl);
-        hr = S_OK;
-    }
-    else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
-    {
-        pidl = ILCombine (pidlRoot, apidl[0]);
-        pObj = IExtractIconW_Constructor (pidl);
-        SHFree (pidl);
-        hr = S_OK;
-    }
-    else if (IsEqualIID (riid, IID_IDropTarget))
+    else if ((IsEqualIID (riid, IID_IExtractIconA) || IsEqualIID (riid, IID_IExtractIconW)) && (cidl == 1))
     {
-        /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
-        if (cidl != 1 || FAILED(hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj)))
-        {
-            IDropTarget * pDt = NULL;
-            hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
-            pObj = pDt;
-        }
+        hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj);
     }
-    else if ((IsEqualIID(riid, IID_IShellLinkW) ||
-              IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
+    else if (IsEqualIID (riid, IID_IDropTarget) && (cidl == 1))
     {
-        pidl = ILCombine (pidlRoot, apidl[0]);
-        hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
-        SHFree (pidl);
+        CComPtr<IShellFolder> psfChild;
+        hr = this->BindToObject(apidl[0], NULL, IID_PPV_ARG(IShellFolder, &psfChild));
+        if (FAILED_UNEXPECTEDLY(hr))
+            return hr;
+
+        return psfChild->CreateViewObject(NULL, riid, ppvOut);
     }
     else
         hr = E_NOINTERFACE;
@@ -652,163 +714,31 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
  */
 HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
 {
-    HRESULT hr = S_OK;
-    LPWSTR pszPath;
-
     TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
     pdump (pidl);
 
     if (!strRet)
         return E_INVALIDARG;
 
-    pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
-    if (!pszPath)
-        return E_OUTOFMEMORY;
-
-    if (_ILIsDesktop (pidl))
+    if (!_ILIsPidlSimple (pidl))
     {
-        if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
-                (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING))
-            wcscpy(pszPath, sPathTarget);
-        else
-            HCR_GetClassNameW(CLSID_ShellDesktop, pszPath, MAX_PATH);
+        return SHELL32_GetDisplayNameOfChild(this, pidl, dwFlags, strRet);
     }
-    else if (_ILIsPidlSimple (pidl))
+    else if (_ILIsDesktop(pidl))
     {
-        GUID const *clsid;
-
-        if ((clsid = _ILGetGUIDPointer (pidl)))
-        {
-            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
-                {
-                    /* get the "WantsFORPARSING" flag from the registry */
-                    static const WCHAR clsidW[] =
-                    { 'C', 'L', 'S', 'I', 'D', '\\', 0 };
-                    static const WCHAR shellfolderW[] =
-                    { '\\', 's', 'h', 'e', 'l', 'l', 'f', 'o', 'l', 'd', 'e', 'r', 0 };
-                    static const WCHAR wantsForParsingW[] =
-                    {   'W', 'a', 'n', 't', 's', 'F', 'o', 'r', 'P', 'a', 'r', 's', 'i', 'n',
-                        'g', 0
-                    };
-                    WCHAR szRegPath[100];
-                    LONG r;
-
-                    wcscpy (szRegPath, clsidW);
-                    SHELL32_GUIDToStringW (*clsid, &szRegPath[6]);
-                    wcscat (szRegPath, shellfolderW);
-                    r = SHGetValueW(HKEY_CLASSES_ROOT, szRegPath,
-                                    wantsForParsingW, NULL, NULL, NULL);
-                    if (r == ERROR_SUCCESS)
-                        bWantsForParsing = TRUE;
-                    else
-                        bWantsForParsing = FALSE;
-                }
-
-                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 (this, pidl, dwFlags,
-                                                        pszPath,
-                                                        MAX_PATH);
-                }
-                else
-                {
-                    /* parsing name like ::{...} */
-                    pszPath[0] = ':';
-                    pszPath[1] = ':';
-                    SHELL32_GUIDToStringW (*clsid, &pszPath[2]);
-                }
-            }
-            else
-            {
-                /* user friendly name */
-                HCR_GetClassNameW (*clsid, pszPath, MAX_PATH);
-            }
-        }
+        if ((GET_SHGDN_RELATION(dwFlags) == SHGDN_NORMAL) && (GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING))
+            return SHSetStrRet(strRet, sPathTarget);
         else
-        {
-            int cLen = 0;
-
-            /* file system folder or file rooted at the desktop */
-            if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) &&
-                    (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
-            {
-                lstrcpynW(pszPath, sPathTarget, MAX_PATH - 1);
-                PathAddBackslashW(pszPath);
-                cLen = wcslen(pszPath);
-            }
-
-            _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen);
-            if (!_ILIsFolder(pidl))
-                SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
-
-            if (GetFileAttributes(pszPath) == INVALID_FILE_ATTRIBUTES)
-            {
-                /* file system folder or file rooted at the AllUsers desktop */
-                if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) &&
-                        (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
-                {
-                    SHGetSpecialFolderPathW(0, pszPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE);
-                    PathAddBackslashW(pszPath);
-                    cLen = wcslen(pszPath);
-                }
-
-                _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen);
-                if (!_ILIsFolder(pidl))
-                    SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
-            }
-        }
-    }
-    else
-    {
-        /* a complex pidl, let the subfolder do the work */
-        hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags,
-                                            pszPath, MAX_PATH);
+            return m_regFolder->GetDisplayNameOf(pidl, dwFlags, strRet);
     }
 
-    if (SUCCEEDED(hr))
-    {
-        /* Win9x always returns ANSI strings, NT always returns Unicode strings */
-        if (GetVersion() & 0x80000000)
-        {
-            strRet->uType = STRRET_CSTR;
-            if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->cStr, MAX_PATH,
-                                     NULL, NULL))
-                strRet->cStr[0] = '\0';
-            CoTaskMemFree(pszPath);
-        }
-        else
-        {
-            strRet->uType = STRRET_WSTR;
-            strRet->pOleStr = pszPath;
-        }
-    }
-    else
-        CoTaskMemFree(pszPath);
+    /* file system folder or file rooted at the desktop */
+    CComPtr<IShellFolder2> psf;
+    HRESULT hr = _GetSFFromPidl(pidl, &psf);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-    TRACE ("-- (%p)->(%s,0x%08x)\n", this,
-           strRet->uType == STRRET_CSTR ? strRet->cStr :
-           debugstr_w(strRet->pOleStr), hr);
-    return hr;
+    return psf->GetDisplayNameOf(pidl, dwFlags, strRet);
 }
 
 /**************************************************************************
@@ -830,71 +760,12 @@ HRESULT WINAPI CDesktopFolder::SetNameOf(
     DWORD dwFlags,
     PITEMID_CHILD *pPidlOut)
 {
-    CComPtr<IShellFolder2>                psf;
-    HRESULT hr;
-    WCHAR szSrc[MAX_PATH + 1], szDest[MAX_PATH + 1];
-    LPWSTR ptr;
-    BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl));
-
-    TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl,
-           debugstr_w (lpName), dwFlags, pPidlOut);
-
-    if (_ILGetGUIDPointer(pidl))
-    {
-        if (SUCCEEDED(BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder2, &psf))))
-        {
-            hr = psf->SetNameOf(hwndOwner, pidl, lpName, dwFlags, pPidlOut);
-            return hr;
-        }
-    }
-
-    /* build source path */
-    lstrcpynW(szSrc, sPathTarget, MAX_PATH);
-    ptr = PathAddBackslashW (szSrc);
-    if (ptr)
-        _ILSimpleGetTextW (pidl, ptr, MAX_PATH + 1 - (ptr - szSrc));
-
-    /* build destination path */
-    if (dwFlags == SHGDN_NORMAL || dwFlags & SHGDN_INFOLDER) {
-        lstrcpynW(szDest, sPathTarget, MAX_PATH);
-        ptr = PathAddBackslashW (szDest);
-        if (ptr)
-            lstrcpynW(ptr, lpName, MAX_PATH + 1 - (ptr - szDest));
-    } else
-        lstrcpynW(szDest, lpName, MAX_PATH);
-
-    if(!(dwFlags & SHGDN_FORPARSING) && SHELL_FS_HideExtension(szSrc)) {
-        WCHAR *ext = PathFindExtensionW(szSrc);
-        if(*ext != '\0') {
-            INT len = wcslen(szDest);
-            lstrcpynW(szDest + len, ext, MAX_PATH - len);
-        }
-    }
-
-    if (!memcmp(szSrc, szDest, (wcslen(szDest) + 1) * sizeof(WCHAR)))
-    {
-        /* src and destination is the same */
-        hr = S_OK;
-        if (pPidlOut)
-            hr = _ILCreateFromPathW(szDest, pPidlOut);
-
+    CComPtr<IShellFolder2> psf;
+    HRESULT hr = _GetSFFromPidl(pidl, &psf);
+    if (FAILED_UNEXPECTEDLY(hr))
         return hr;
-    }
-
-    TRACE ("src=%s dest=%s\n", debugstr_w(szSrc), debugstr_w(szDest));
-    if (MoveFileW (szSrc, szDest))
-    {
-        hr = S_OK;
-
-        if (pPidlOut)
-            hr = _ILCreateFromPathW(szDest, pPidlOut);
 
-        SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM,
-                        SHCNF_PATHW, szSrc, szDest);
-
-        return hr;
-    }
-    return E_FAIL;
+    return psf->SetNameOf(hwndOwner, pidl, lpName, dwFlags, pPidlOut);
 }
 
 HRESULT WINAPI CDesktopFolder::GetDefaultSearchGUID(GUID *pguid)
@@ -948,10 +819,6 @@ HRESULT WINAPI CDesktopFolder::GetDetailsOf(
     UINT iColumn,
     SHELLDETAILS *psd)
 {
-    HRESULT hr = S_OK;
-
-    TRACE ("(%p)->(%p %i %p)\n", this, pidl, iColumn, psd);
-
     if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
         return E_INVALIDARG;
 
@@ -959,33 +826,17 @@ HRESULT WINAPI CDesktopFolder::GetDetailsOf(
     {
         psd->fmt = DesktopSFHeader[iColumn].fmt;
         psd->cxChar = DesktopSFHeader[iColumn].cxChar;
-        psd->str.uType = STRRET_CSTR;
-        LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid,
-                     psd->str.cStr, MAX_PATH);
-        return S_OK;
+        return SHSetStrRet(&psd->str, DesktopSFHeader[iColumn].colnameid);
     }
 
-    /* the data from the pidl */
-    psd->str.uType = STRRET_CSTR;
-    switch (iColumn)
-    {
-        case 0:        /* name */
-            hr = GetDisplayNameOf(pidl,
-                                  SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
-            break;
-        case 1:        /* size */
-            _ILGetFileSize (pidl, psd->str.cStr, MAX_PATH);
-            break;
-        case 2:        /* type */
-            _ILGetFileType (pidl, psd->str.cStr, MAX_PATH);
-            break;
-        case 3:        /* date */
-            _ILGetFileDate (pidl, psd->str.cStr, MAX_PATH);
-            break;
-        case 4:        /* attributes */
-            _ILGetFileAttributes (pidl, psd->str.cStr, MAX_PATH);
-            break;
-    }
+    CComPtr<IShellFolder2> psf;
+    HRESULT hr = _GetSFFromPidl(pidl, &psf);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
+
+    hr =  psf->GetDetailsOf(pidl, iColumn, psd);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
     return hr;
 }
@@ -1012,499 +863,68 @@ HRESULT WINAPI CDesktopFolder::Initialize(LPCITEMIDLIST pidl)
 {
     TRACE ("(%p)->(%p)\n", this, pidl);
 
-    return E_NOTIMPL;
+    return E_INVALIDARG;
 }
 
 HRESULT WINAPI CDesktopFolder::GetCurFolder(LPITEMIDLIST * pidl)
 {
     TRACE ("(%p)->(%p)\n", this, pidl);
 
-    if (!pidl) return E_POINTER;
+    if (!pidl) 
+        return E_INVALIDARG; /* xp doesn't have this check and crashes on NULL */
     *pidl = ILClone (pidlRoot);
     return S_OK;
 }
 
-HRESULT WINAPI CDesktopFolder::GetUniqueName(LPWSTR pwszName, UINT uLen)
-{
-    CComPtr<IEnumIDList>                penum;
-    HRESULT hr;
-    WCHAR wszText[MAX_PATH];
-    WCHAR wszNewFolder[25];
-    const WCHAR wszFormat[] = {'%', 's', ' ', '%', 'd', 0 };
-
-    LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder,  sizeof(wszNewFolder) / sizeof(WCHAR));
-
-    TRACE ("(%p)(%p %u)\n", this, pwszName, uLen);
-
-    if (uLen < sizeof(wszNewFolder) / sizeof(WCHAR) + 3)
-        return E_POINTER;
-
-    lstrcpynW (pwszName, wszNewFolder, uLen);
-
-    hr = EnumObjects(0,
-                     SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
-    if (penum) {
-        LPITEMIDLIST pidl;
-        DWORD dwFetched;
-        int i = 1;
-
-next:
-        penum->Reset ();
-        while (S_OK == penum->Next(1, &pidl, &dwFetched) &&
-                dwFetched) {
-            _ILSimpleGetTextW (pidl, wszText, MAX_PATH);
-            if (0 == lstrcmpiW (wszText, pwszName)) {
-                _snwprintf (pwszName, uLen, wszFormat, wszNewFolder, i++);
-                if (i > 99) {
-                    hr = E_FAIL;
-                    break;
-                }
-                goto next;
-            }
-        }
-
-    }
-    return hr;
-}
-
-HRESULT WINAPI CDesktopFolder::AddFolder(HWND hwnd, LPCWSTR pwszName, LPITEMIDLIST *ppidlOut)
-{
-    WCHAR wszNewDir[MAX_PATH];
-    DWORD bRes;
-    HRESULT hres = E_FAIL;
-
-    TRACE ("(%p)(%s %p)\n", this, debugstr_w(pwszName), ppidlOut);
-
-    wszNewDir[0] = 0;
-    if (sPathTarget)
-        lstrcpynW(wszNewDir, sPathTarget, MAX_PATH);
-    PathAppendW(wszNewDir, pwszName);
-    bRes = CreateDirectoryW (wszNewDir, NULL);
-    if (bRes)
-    {
-        SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHW, wszNewDir, NULL);
-        hres = S_OK;
-        if (ppidlOut)
-            hres = _ILCreateFromPathW(wszNewDir, ppidlOut);
-    }
-
-    return hres;
-}
-
-HRESULT WINAPI CDesktopFolder::DeleteItems(UINT cidl, LPCITEMIDLIST *apidl)
+HRESULT WINAPI CDesktopFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-    UINT i;
-    SHFILEOPSTRUCTW op;
-    WCHAR wszPath[MAX_PATH];
-    WCHAR wszCaption[50];
-    WCHAR *wszPathsList;
-    HRESULT ret;
-    WCHAR *wszCurrentPath;
-    UINT bRestoreWithDeskCpl = FALSE;
-    int res;
-
-    TRACE ("(%p)(%u %p)\n", this, cidl, apidl);
-    if (cidl == 0) return S_OK;
-
-    for(i = 0; i < cidl; i++)
-    {
-        if (_ILIsMyComputer(apidl[i]))
-            bRestoreWithDeskCpl++;
-        else if (_ILIsNetHood(apidl[i]))
-            bRestoreWithDeskCpl++;
-        else if (_ILIsMyDocuments(apidl[i]))
-            bRestoreWithDeskCpl++;
-    }
-
-    if (bRestoreWithDeskCpl)
-    {
-        /* FIXME use FormatMessage
-         * use a similar message resource as in windows
-         */
-        LoadStringW(shell32_hInstance, IDS_DELETEMULTIPLE_TEXT, wszPath, sizeof(wszPath) / sizeof(WCHAR));
-        wszPath[(sizeof(wszPath)/sizeof(WCHAR))-1] = 0;
-
-        LoadStringW(shell32_hInstance, IDS_DELETEITEM_CAPTION, wszCaption, sizeof(wszCaption) / sizeof(WCHAR));
-        wszCaption[(sizeof(wszCaption)/sizeof(WCHAR))-1] = 0;
-
-        res = SHELL_ConfirmMsgBox(GetActiveWindow(), wszPath, wszCaption, NULL, cidl > 1);
-        if (res == IDC_YESTOALL || res == IDYES)
-        {
-            for(i = 0; i < cidl; i++)
-            {
-                if (_ILIsMyComputer(apidl[i]))
-                    SetNamespaceExtensionVisibleStatus(L"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0x1);
-                else if (_ILIsNetHood(apidl[i]))
-                    SetNamespaceExtensionVisibleStatus(L"{208D2C60-3AEA-1069-A2D7-08002B30309D}", 0x1);
-                else if (_ILIsMyDocuments(apidl[i]))
-                    SetNamespaceExtensionVisibleStatus(L"{450D8FBA-AD25-11D0-98A8-0800361B1103}", 0x1);
-            }
-        }
-    }
-    if (sPathTarget)
-        lstrcpynW(wszPath, sPathTarget, MAX_PATH);
-    else
-        wszPath[0] = '\0';
-
-    PathAddBackslashW(wszPath);
-    wszPathsList = BuildPathsList(wszPath, cidl, apidl);
-
-    ZeroMemory(&op, sizeof(op));
-    op.hwnd = GetActiveWindow();
-    op.wFunc = FO_DELETE;
-    op.pFrom = wszPathsList;
-    op.fFlags = FOF_ALLOWUNDO;
-    if (SHFileOperationW(&op))
-    {
-        WARN("SHFileOperation failed\n");
-        ret = E_FAIL;
-    }
-    else
-        ret = S_OK;
-
-    /* we currently need to manually send the notifies */
-    wszCurrentPath = wszPathsList;
-    for (i = 0; i < cidl; i++)
-    {
-        LONG wEventId;
-
-        if (_ILIsFolder(apidl[i]))
-            wEventId = SHCNE_RMDIR;
-        else if (_ILIsValue(apidl[i]))
-            wEventId = SHCNE_DELETE;
-        else
-            continue;
-
-        /* check if file exists */
-        if (GetFileAttributesW(wszCurrentPath) == INVALID_FILE_ATTRIBUTES)
-        {
-            LPITEMIDLIST pidl = ILCombine(pidlRoot, apidl[i]);
-            SHChangeNotify(wEventId, SHCNF_IDLIST, pidl, NULL);
-            SHFree(pidl);
-        }
-
-        wszCurrentPath += wcslen(wszCurrentPath) + 1;
-    }
-    HeapFree(GetProcessHeap(), 0, wszPathsList);
-    return ret;
-}
+    if (uMsg != DFM_MERGECONTEXTMENU && uMsg != DFM_INVOKECOMMAND)
+        return S_OK;
 
-HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy)
-{
-    CComPtr<IPersistFolder2> ppf2;
-    WCHAR szSrcPath[MAX_PATH];
-    WCHAR szTargetPath[MAX_PATH];
-    SHFILEOPSTRUCTW op;
-    LPITEMIDLIST pidl;
-    LPWSTR pszSrc, pszTarget, pszSrcList, pszTargetList, pszFileName;
-    int res, length;
-    STRRET strRet;
-
-    TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom, cidl, apidl);
-
-    pSFFrom->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
-    if (ppf2)
+    /* no data object means no selection */
+    if (!pdtobj)
     {
-        if (FAILED(ppf2->GetCurFolder(&pidl)))
-            return E_FAIL;
-
-        if (FAILED(pSFFrom->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strRet)))
-        {
-            SHFree (pidl);
-            return E_FAIL;
-        }
-
-        if (FAILED(StrRetToBufW(&strRet, pidl, szSrcPath, MAX_PATH)))
-        {
-            SHFree (pidl);
-            return E_FAIL;
-        }
-        SHFree (pidl);
-
-        pszSrc = PathAddBackslashW (szSrcPath);
-
-        wcscpy(szTargetPath, sPathTarget);
-        pszTarget = PathAddBackslashW (szTargetPath);
-
-        pszSrcList = BuildPathsList(szSrcPath, cidl, apidl);
-        pszTargetList = BuildPathsList(szTargetPath, cidl, apidl);
-
-        if (!pszSrcList || !pszTargetList)
-        {
-            if (pszSrcList)
-                HeapFree(GetProcessHeap(), 0, pszSrcList);
-
-            if (pszTargetList)
-                HeapFree(GetProcessHeap(), 0, pszTargetList);
-
-            SHFree (pidl);
-            return E_OUTOFMEMORY;
-        }
-        ZeroMemory(&op, sizeof(op));
-        if (!pszSrcList[0])
+        if (uMsg == DFM_INVOKECOMMAND && wParam == DFM_CMD_PROPERTIES)
         {
-            /* remove trailing backslash */
-            pszSrc--;
-            pszSrc[0] = L'\0';
-            op.pFrom = szSrcPath;
-        }
-        else
-        {
-            op.pFrom = pszSrcList;
-        }
-
-        if (!pszTargetList[0])
-        {
-            /* remove trailing backslash */
-            if (pszTarget - szTargetPath > 3)
-            {
-                pszTarget--;
-                pszTarget[0] = L'\0';
-            }
-            else
-            {
-                pszTarget[1] = L'\0';
-            }
-
-            op.pTo = szTargetPath;
-            op.fFlags = 0;
-        }
-        else
-        {
-            op.pTo = pszTargetList;
-            op.fFlags = FOF_MULTIDESTFILES;
+            if (32 >= (UINT)ShellExecuteW(hwndOwner, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL))
+                return E_FAIL;
+            return S_OK;
         }
-        op.hwnd = GetActiveWindow();
-        op.wFunc = bCopy ? FO_COPY : FO_MOVE;
-        op.fFlags |= FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
-
-        res = SHFileOperationW(&op);
-
-        if (res == DE_SAMEFILE)
+        else if (uMsg == DFM_MERGECONTEXTMENU)
         {
-            length = wcslen(szTargetPath);
-
-
-            pszFileName = wcsrchr(pszSrcList, '\\');
-            pszFileName++;
-
-            if (LoadStringW(shell32_hInstance, IDS_COPY_OF, pszTarget, MAX_PATH - length))
-            {
-                wcscat(szTargetPath, L" ");
-            }
-
-            wcscat(szTargetPath, pszFileName);
-            op.pTo = szTargetPath;
-
-            res = SHFileOperationW(&op);
+            QCMINFO *pqcminfo = (QCMINFO *)lParam;
+            _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
+            _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
         }
 
-
-        HeapFree(GetProcessHeap(), 0, pszSrcList);
-        HeapFree(GetProcessHeap(), 0, pszTargetList);
-
-        if (res)
-            return E_FAIL;
-        else
-            return S_OK;
-    }
-    return E_FAIL;
-}
-
-/****************************************************************************
- * IDropTarget implementation
- *
- * This should allow two somewhat separate things, copying files to the users directory,
- * as well as allowing icons to be moved anywhere and updating the registry to save.
- *
- * The first thing I think is best done using fs.cpp to prevent WET code. So we'll simulate
- * a drop to the user's home directory. The second will look at the pointer location and
- * set sensible places for the icons to live.
- *
- */
-BOOL CDesktopFolder::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
-{
-    /* TODO Windows does different drop effects if dragging across drives.
-    i.e., it will copy instead of move if the directories are on different disks. */
-
-    DWORD dwEffect = DROPEFFECT_MOVE;
-
-    *pdwEffect = DROPEFFECT_NONE;
-
-    if (fAcceptFmt) { /* Does our interpretation of the keystate ... */
-        *pdwEffect = KeyStateToDropEffect (dwKeyState);
-
-        if (*pdwEffect == DROPEFFECT_NONE)
-            *pdwEffect = dwEffect;
-
-        /* ... matches the desired effect ? */
-        if (dwEffect & *pdwEffect) {
-            return TRUE;
-        }
+        return S_OK;
     }
-    return FALSE;
-}
-
-HRESULT WINAPI CDesktopFolder::DragEnter(IDataObject *pDataObject,
-                                    DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
-{
-    TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
-    FORMATETC fmt;
-    FORMATETC fmt2;
-    fAcceptFmt = FALSE;
-
-    InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
-    InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
 
-    if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
-        fAcceptFmt = TRUE;
-    else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
-        fAcceptFmt = TRUE;
-
-    QueryDrop(dwKeyState, pdwEffect);
-    return S_OK;
-}
-
-HRESULT WINAPI CDesktopFolder::DragOver(DWORD dwKeyState, POINTL pt,
-                                   DWORD *pdwEffect)
-{
-    TRACE("(%p)\n", this);
-
-    if (!pdwEffect)
-        return E_INVALIDARG;
-
-    QueryDrop(dwKeyState, pdwEffect);
-
-    return S_OK;
-}
+    PIDLIST_ABSOLUTE pidlFolder;
+    PUITEMID_CHILD *apidl;
+    UINT cidl;
+    HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
+    if (FAILED_UNEXPECTEDLY(hr))
+        return hr;
 
-HRESULT WINAPI CDesktopFolder::DragLeave()
-{
-    TRACE("(%p)\n", this);
-    fAcceptFmt = FALSE;
-    return S_OK;
-}
+    if (cidl > 1)
+        ERR("SHMultiFileProperties is not yet implemented\n");
 
-HRESULT WINAPI CDesktopFolder::Drop(IDataObject *pDataObject,
-                               DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
-{
-    TRACE("(%p) object dropped desktop\n", this);
-
-    STGMEDIUM medium;
-    bool passthroughtofs = FALSE;
-    FORMATETC formatetc;
-    InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
-    
-    HRESULT hr = pDataObject->GetData(&formatetc, &medium);
+    STRRET strFile;
+    hr = GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strFile);
     if (SUCCEEDED(hr))
     {
-        /* lock the handle */
-        LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
-        if (!lpcida)
-        {
-            ReleaseStgMedium(&medium);
-            return E_FAIL;
-        }
-
-        /* convert the clipboard data into pidl (pointer to id list) */
-        LPITEMIDLIST pidl;
-        LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
-        if (!apidl)
-        {
-            ReleaseStgMedium(&medium);
-            return E_FAIL;
-        }
-        passthroughtofs = !_ILIsDesktop(pidl) || (dwKeyState & MK_CONTROL);
-        SHFree(pidl);
-        _ILFreeaPidl(apidl, lpcida->cidl);
-        ReleaseStgMedium(&medium);
+        hr = SH_ShowPropertiesDialog(strFile.pOleStr, pidlFolder, apidl);
+        if (FAILED(hr))
+            ERR("SH_ShowPropertiesDialog failed\n");
     }
     else
     {
-        InitFormatEtc (formatetc, CF_HDROP, TYMED_HGLOBAL);
-        if (SUCCEEDED(pDataObject->QueryGetData(&formatetc)))
-        {
-            passthroughtofs = TRUE;
-        }
+        ERR("Failed to get display name\n");
     }
-    /* We only want to really move files around if they don't already
-       come from the desktop, or we're linking or copying */
-    if (passthroughtofs)
-    {
-        LPITEMIDLIST pidl = NULL;
-
-        WCHAR szPath[MAX_PATH];
-        //LPWSTR pathPtr;
-
-        /* build a complete path to create a simple pidl */
-        lstrcpynW(szPath, sPathTarget, MAX_PATH);
-        /*pathPtr = */PathAddBackslashW(szPath);
-        //hr = _ILCreateFromPathW(szPath, &pidl);
-        hr = this->ParseDisplayName(NULL, NULL, szPath, NULL, &pidl, NULL);
-
-        if (SUCCEEDED(hr))
-        {
-            CComPtr<IDropTarget> pDT;
-            hr = this->BindToObject(pidl, NULL, IID_PPV_ARG(IDropTarget, &pDT));
-            CoTaskMemFree(pidl);
-            if (SUCCEEDED(hr))
-                SHSimulateDrop(pDT, pDataObject, dwKeyState, NULL, pdwEffect);
-            else
-                ERR("Error Binding");
-        }
-        else
-            ERR("Error creating from %s\n", debugstr_w(szPath));
-    }
-
-    /* Todo, rewrite the registry such that the icons are well placed.
-    Blocked by no bags implementation. */
-    return hr;
-}
-
-HRESULT WINAPI CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut) {
-    HRESULT hr;
-
-    TRACE("CFSFolder::_GetDropTarget entered\n");
-
-    if (_ILGetGUIDPointer (pidl) || _ILIsFolder (pidl))
-        return this->BindToObject(pidl, NULL, IID_IDropTarget, ppvOut);
-
-    LPITEMIDLIST pidlNext = NULL;
 
-    STRRET strFile;
-    hr = this->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strFile);
-    if (SUCCEEDED(hr))
-    {
-        WCHAR wszPath[MAX_PATH];
-        hr = StrRetToBufW(&strFile, pidl, wszPath, _countof(wszPath));
-
-        if (SUCCEEDED(hr))
-        {
-            PathRemoveFileSpecW (wszPath);
-            hr = this->ParseDisplayName(NULL, NULL, wszPath, NULL, &pidlNext, NULL);
-
-            if (SUCCEEDED(hr))
-            {
-                CComPtr<IShellFolder> psf;
-                hr = this->BindToObject(pidlNext, NULL, IID_PPV_ARG(IShellFolder, &psf));
-                CoTaskMemFree(pidlNext);
-                if (SUCCEEDED(hr))
-                {
-                    hr = psf->GetUIObjectOf(NULL, 1, &pidl, IID_IDropTarget, NULL, ppvOut);
-                    if (FAILED(hr))
-                        ERR("FS GetUIObjectOf failed: %x\n", hr);
-                }
-                else 
-                    ERR("BindToObject failed: %x\n", hr);
-            }
-            else
-                ERR("ParseDisplayName failed: %x\n", hr);
-        }
-        else
-            ERR("StrRetToBufW failed: %x\n", hr);
-    }    
-    else
-        ERR("GetDisplayNameOf failed: %x\n", hr);
+    SHFree(pidlFolder);
+    _ILFreeaPidl(apidl, cidl);
 
     return hr;
 }