[SHELL32]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 29 Jul 2016 12:56:06 +0000 (12:56 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 29 Jul 2016 12:56:06 +0000 (12:56 +0000)
- Factor CFSDropTarget out of CFSFolder.
- For now their code is mixed (no code was moved), until we decide where exactly is should be kept.

svn path=/trunk/; revision=72047

reactos/dll/win32/shell32/folders/CFSFolder.cpp
reactos/dll/win32/shell32/folders/CFSFolder.h

index 4bd24f9..a7364af 100644 (file)
@@ -62,25 +62,11 @@ HRESULT WINAPI CFileSysEnum::Initialize(LPWSTR sPathTarget, DWORD dwFlags)
     return CreateFolderEnumList(sPathTarget, dwFlags);
 }
 
-/**************************************************************************
-* registers clipboardformat once
-*/
-void CFSFolder::SF_RegisterClipFmt()
-{
-    TRACE ("(%p)\n", this);
-
-    if (!cfShellIDList)
-        cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
-}
-
 CFSFolder::CFSFolder()
 {
     pclsid = (CLSID *)&CLSID_ShellFSFolder;
     sPathTarget = NULL;
     pidlRoot = NULL;
-    cfShellIDList = 0;
-    SF_RegisterClipFmt();
-    fAcceptFmt = FALSE;
     m_bGroupPolicyActive = 0;
 }
 
@@ -378,7 +364,7 @@ HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner,
         *ppvOut = NULL;
 
         if (IsEqualIID (riid, IID_IDropTarget))
-            hr = this->QueryInterface (IID_IDropTarget, ppvOut);
+            hr = ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut);
         else if (IsEqualIID (riid, IID_IContextMenu))
         {
             FIXME ("IContextMenu not implemented\n");
@@ -524,7 +510,7 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner,
             if (cidl != 1 || FAILED(hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj)))
             {
                 IDropTarget * pDt = NULL;
-                hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
+                hr = ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut);
                 pObj = pDt;
             }
         }
@@ -871,11 +857,11 @@ BuildPathsList(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls)
 }
 
 /****************************************************************************
- * CFSFolder::CopyItems
+ * CFSDropTarget::CopyItems
  *
  * copies items to this folder
  */
-HRESULT WINAPI CFSFolder::CopyItems(IShellFolder * pSFFrom, UINT cidl,
+HRESULT WINAPI CFSDropTarget::CopyItems(IShellFolder * pSFFrom, UINT cidl,
                                     LPCITEMIDLIST * apidl, BOOL bCopy)
 {
     CComPtr<IPersistFolder2> ppf2 = NULL;
@@ -1136,8 +1122,34 @@ HRESULT WINAPI CFSFolder::GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO * ppfti
     return E_NOTIMPL;
 }
 
+CFSDropTarget::CFSDropTarget():
+    cfShellIDList(0),
+    fAcceptFmt(FALSE),
+    sPathTarget(NULL)
+{
+}
+
+HRESULT WINAPI CFSDropTarget::Initialize(LPWSTR PathTarget)
+{
+    cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
+    if (!cfShellIDList)
+        return E_FAIL;
+
+    sPathTarget = (WCHAR *)SHAlloc((wcslen(PathTarget) + 1) * sizeof(WCHAR));
+    if (!sPathTarget)
+        return E_OUTOFMEMORY;
+    wcscpy(sPathTarget, PathTarget);
+
+    return S_OK;
+}
+
+CFSDropTarget::~CFSDropTarget()
+{
+    SHFree(sPathTarget);
+}
+
 BOOL
-CFSFolder::GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
+CFSDropTarget::GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
 {
     WCHAR wszLink[40];
 
@@ -1166,7 +1178,7 @@ CFSFolder::GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTa
 /****************************************************************************
  * IDropTarget implementation
  */
-BOOL CFSFolder::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
+BOOL CFSDropTarget::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. */
@@ -1189,8 +1201,8 @@ BOOL CFSFolder::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
     return FALSE;
 }
 
-HRESULT WINAPI CFSFolder::DragEnter(IDataObject *pDataObject,
-                                    DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
+HRESULT WINAPI CFSDropTarget::DragEnter(IDataObject *pDataObject,
+                                        DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 {
     TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
     FORMATETC fmt;
@@ -1209,8 +1221,8 @@ HRESULT WINAPI CFSFolder::DragEnter(IDataObject *pDataObject,
     return S_OK;
 }
 
-HRESULT WINAPI CFSFolder::DragOver(DWORD dwKeyState, POINTL pt,
-                                   DWORD *pdwEffect)
+HRESULT WINAPI CFSDropTarget::DragOver(DWORD dwKeyState, POINTL pt,
+                                       DWORD *pdwEffect)
 {
     TRACE("(%p)\n", this);
 
@@ -1222,7 +1234,7 @@ HRESULT WINAPI CFSFolder::DragOver(DWORD dwKeyState, POINTL pt,
     return S_OK;
 }
 
-HRESULT WINAPI CFSFolder::DragLeave()
+HRESULT WINAPI CFSDropTarget::DragLeave()
 {
     TRACE("(%p)\n", this);
 
@@ -1231,8 +1243,8 @@ HRESULT WINAPI CFSFolder::DragLeave()
     return S_OK;
 }
 
-HRESULT WINAPI CFSFolder::Drop(IDataObject *pDataObject,
-                               DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
+HRESULT WINAPI CFSDropTarget::Drop(IDataObject *pDataObject,
+                                   DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 {
     TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect);
     
@@ -1259,15 +1271,15 @@ HRESULT WINAPI CFSFolder::Drop(IDataObject *pDataObject,
             data->pt = pt;
             // Need to dereference as pdweffect gets freed.
             data->pdwEffect = *pdwEffect;
-            SHCreateThread(CFSFolder::_DoDropThreadProc, data, NULL, NULL);
+            SHCreateThread(CFSDropTarget::_DoDropThreadProc, data, NULL, NULL);
             return S_OK;
         }
     }
     return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect);
 }
 
-HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject,
-                               DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
+HRESULT WINAPI CFSDropTarget::_DoDrop(IDataObject *pDataObject,
+                                      DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
 {
     TRACE("(%p) performing drop, effect %u\n", this, *pdwEffect);
     FORMATETC fmt;
@@ -1315,17 +1327,6 @@ HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject,
 
         CComPtr<IShellFolder> psfDesktop;
         CComPtr<IShellFolder> psfFrom = NULL;
-        CComPtr<IShellFolder> psfTarget = NULL;
-
-        hr = this->QueryInterface(IID_PPV_ARG(IShellFolder, &psfTarget));
-        if (FAILED(hr))
-        {
-            ERR("psfTarget setting failed\n");
-            SHFree(pidl);
-            _ILFreeaPidl(apidl, lpcida->cidl);
-            ReleaseStgMedium(&medium);
-            return E_FAIL;
-        }
 
         /* Grab the desktop shell folder */
         hr = SHGetDesktopFolder(&psfDesktop);
@@ -1359,32 +1360,11 @@ HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject,
 
         if (bLinking)
         {
-            CComPtr<IPersistFolder2> ppf2 = NULL;
-            STRRET strFile;
             WCHAR wszTargetPath[MAX_PATH];
-            LPITEMIDLIST targetpidl;
             WCHAR wszPath[MAX_PATH];
             WCHAR wszTarget[MAX_PATH];
 
-            hr = this->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
-            if (SUCCEEDED(hr))
-            {
-                hr = ppf2->GetCurFolder(&targetpidl);
-                if (SUCCEEDED(hr))
-                {
-                    hr = psfDesktop->GetDisplayNameOf(targetpidl, SHGDN_FORPARSING, &strFile);
-                    ILFree(targetpidl);
-                    if (SUCCEEDED(hr)) 
-                    {
-                        hr = StrRetToBufW(&strFile, NULL, wszTargetPath, _countof(wszTargetPath));
-                    }
-                }
-            }
-
-            if (FAILED(hr)) 
-            {
-                ERR("Error obtaining target path");
-            }
+            wcscpy(wszTargetPath, sPathTarget);
 
             TRACE("target path = %s", debugstr_w(wszTargetPath));
 
@@ -1415,7 +1395,7 @@ HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject,
 
                 LPWSTR pwszFileName = PathFindFileNameW(wszPath);
                 LPWSTR pwszExt = PathFindExtensionW(wszPath);
-                LPWSTR placementPath = PathCombineW(lpStr1, wszTargetPath, pwszFileName);
+                LPWSTR placementPath = PathCombineW(lpStr1, sPathTarget, pwszFileName);
                 CComPtr<IPersistFile> ppf;
 
                 //Check to see if it's already a link. 
@@ -1428,7 +1408,7 @@ HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject,
                         hr = E_FAIL;
                         break;
                     }
-                    hr = IShellLink_ConstructFromFile(this, apidl[i], IID_PPV_ARG(IPersistFile, &ppf));
+                    hr = IShellLink_ConstructFromPath(wszPath, IID_PPV_ARG(IPersistFile, &ppf));
                     if (FAILED(hr)) {
                         ERR("Error constructing link from file");
                         break;
@@ -1495,41 +1475,13 @@ HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject,
         InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
         if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/)
         {
-            CComPtr<IPersistFolder2> ppf2 = NULL;
-            STRRET strFile;
             WCHAR wszTargetPath[MAX_PATH + 1];
             LPWSTR pszSrcList;
-            LPITEMIDLIST targetpidl;
-            CComPtr<IShellFolder> psfDesktop = NULL;
-            hr = SHGetDesktopFolder(&psfDesktop);
-            if (FAILED(hr))
-            {
-                ERR("SHGetDesktopFolder failed\n");
-                return E_FAIL;
-            }
-
-            hr = this->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
-            if (SUCCEEDED(hr))
-            {
-                hr = ppf2->GetCurFolder(&targetpidl);
-                if (SUCCEEDED(hr))
-                {
-                    hr = psfDesktop->GetDisplayNameOf(targetpidl, SHGDN_FORPARSING, &strFile);
-                    ILFree(targetpidl);
-                    if (SUCCEEDED(hr)) 
-                    {
-                        hr = StrRetToBufW(&strFile, NULL, wszTargetPath, _countof(wszTargetPath));
-                        //Double NULL terminate.
-                        wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
-                    }
-                }
-            }
-            if (FAILED(hr)) 
-            {
-                ERR("Error obtaining target path");
-                return E_FAIL;
-            }
 
+            wcscpy(wszTargetPath, sPathTarget);
+            //Double NULL terminate.
+            wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
+            
             LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal);
             if (!lpdf)
             {
@@ -1561,7 +1513,8 @@ HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject,
     return hr;
 }
 
-DWORD WINAPI CFSFolder::_DoDropThreadProc(LPVOID lpParameter) {
+DWORD WINAPI CFSDropTarget::_DoDropThreadProc(LPVOID lpParameter)
+{
     CoInitialize(NULL);
     _DoDropData *data = static_cast<_DoDropData*>(lpParameter);
     CComPtr<IDataObject> pDataObject;
@@ -1591,7 +1544,14 @@ HRESULT WINAPI CFSFolder::_GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut) {
     TRACE("CFSFolder::_GetDropTarget entered\n");
 
     if (_ILIsFolder (pidl))
-        return this->BindToObject(pidl, NULL, IID_IDropTarget, ppvOut);
+    {
+        CComPtr<IShellFolder> psfChild;
+        hr = this->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfChild));
+        if (FAILED_UNEXPECTEDLY(hr))
+            return hr;
+
+        return psfChild->CreateViewObject(NULL, IID_IDropTarget, ppvOut);
+    }
 
     STRRET strFile;
     hr = this->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strFile);
index 995efde..c32e5d7 100644 (file)
@@ -29,8 +29,7 @@ class CFSFolder :
     public CComCoClass<CFSFolder, &CLSID_ShellFSFolder>,
     public CComObjectRootEx<CComMultiThreadModelNoCS>,
     public IShellFolder2,
-    public IPersistFolder3,
-    public IDropTarget
+    public IPersistFolder3
 {
     private:
         CLSID *pclsid;
@@ -40,24 +39,15 @@ class CFSFolder :
 
         LPITEMIDLIST pidlRoot; /* absolute pidl */
 
-        UINT cfShellIDList;    /* clipboardformat for IDropTarget */
-        BOOL fAcceptFmt;       /* flag for pending Drop */
-        BOOL QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect);
         DWORD m_bGroupPolicyActive;
-        void SF_RegisterClipFmt();
-        BOOL GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut);
-        static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter);
-        virtual HRESULT WINAPI _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
         virtual HRESULT WINAPI _GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut);
         virtual HRESULT WINAPI _LoadDynamicDropTargetHandlerForKey(HKEY hRootKey, LPCWSTR pwcsname, LPVOID *ppvOut);
         virtual HRESULT WINAPI _LoadDynamicDropTargetHandler(const CLSID *pclsid, LPCWSTR pwcsname, LPVOID *ppvOut);
-        virtual HRESULT WINAPI CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy);
 
     public:
         CFSFolder();
         ~CFSFolder();
         
-
         // IShellFolder
         virtual HRESULT WINAPI ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes);
         virtual HRESULT WINAPI EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList);
@@ -92,12 +82,6 @@ class CFSFolder :
         virtual HRESULT WINAPI InitializeEx(IBindCtx *pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO *ppfti);
         virtual HRESULT WINAPI GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO *ppfti);
 
-        // IDropTarget
-        virtual HRESULT WINAPI DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
-        virtual HRESULT WINAPI DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
-        virtual HRESULT WINAPI DragLeave();
-        virtual HRESULT WINAPI Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
-
         DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER)
         DECLARE_NOT_AGGREGATABLE(CFSFolder)
 
@@ -110,16 +94,52 @@ class CFSFolder :
         COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
         COM_INTERFACE_ENTRY_IID(IID_IPersistFolder3, IPersistFolder3)
         COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
-        COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
         END_COM_MAP()
 };
 
 struct _DoDropData {
-    CFSFolder *This;
+    CFSDropTarget *This;
     IStream *pStream;
     DWORD dwKeyState;
     POINTL pt; 
     DWORD pdwEffect;
 };
 
+
+class CFSDropTarget :
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IDropTarget
+{
+    private:
+        UINT cfShellIDList;    /* clipboardformat for IDropTarget */
+        BOOL fAcceptFmt;       /* flag for pending Drop */
+        LPWSTR sPathTarget;
+
+        BOOL QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect);
+        virtual HRESULT WINAPI _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
+        virtual HRESULT WINAPI CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy);
+        BOOL GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut);
+        static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter);
+
+    public:
+        CFSDropTarget();
+        ~CFSDropTarget();
+        HRESULT WINAPI Initialize(LPWSTR PathTarget);
+
+        // IDropTarget
+        virtual HRESULT WINAPI DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
+        virtual HRESULT WINAPI DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
+        virtual HRESULT WINAPI DragLeave();
+        virtual HRESULT WINAPI Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
+
+        DECLARE_NOT_AGGREGATABLE(CFSDropTarget)
+
+        DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+        BEGIN_COM_MAP(CFSDropTarget)
+        COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
+        END_COM_MAP()
+
+};
+
 #endif /* _CFSFOLDER_H_ */