[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / folders / CFSFolder.cpp
index a7364af..2406fef 100644 (file)
@@ -364,7 +364,7 @@ HRESULT WINAPI CFSFolder::CreateViewObject(HWND hwndOwner,
         *ppvOut = NULL;
 
         if (IsEqualIID (riid, IID_IDropTarget))
-            hr = ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut);
+            hr = CFSDropTarget_CreateInstance(sPathTarget, riid, ppvOut);
         else if (IsEqualIID (riid, IID_IContextMenu))
         {
             FIXME ("IContextMenu not implemented\n");
@@ -510,7 +510,7 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner,
             if (cidl != 1 || FAILED(hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj)))
             {
                 IDropTarget * pDt = NULL;
-                hr = ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut);
+                hr = CFSDropTarget_CreateInstance(sPathTarget, riid, ppvOut);
                 pObj = pDt;
             }
         }
@@ -824,161 +824,6 @@ HRESULT WINAPI CFSFolder::MapColumnToSCID (UINT column,
     return E_NOTIMPL;
 }
 
-/****************************************************************************
- * BuildPathsList
- *
- * Builds a list of paths like the one used in SHFileOperation from a table of
- * PIDLs relative to the given base folder
- */
-WCHAR *
-BuildPathsList(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls)
-{
-    WCHAR *pwszPathsList;
-    WCHAR *pwszListPos;
-    int iPathLen, i;
-
-    iPathLen = wcslen(wszBasePath);
-    pwszPathsList = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) * cidl + 1);
-    pwszListPos = pwszPathsList;
-
-    for (i = 0; i < cidl; i++)
-    {
-        if (!_ILIsFolder(pidls[i]) && !_ILIsValue(pidls[i]))
-            continue;
-
-        wcscpy(pwszListPos, wszBasePath);
-        pwszListPos += iPathLen;
-        /* FIXME: abort if path too long */
-        _ILSimpleGetTextW(pidls[i], pwszListPos, MAX_PATH - iPathLen);
-        pwszListPos += wcslen(pwszListPos) + 1;
-    }
-    *pwszListPos = 0;
-    return pwszPathsList;
-}
-
-/****************************************************************************
- * CFSDropTarget::CopyItems
- *
- * copies items to this folder
- */
-HRESULT WINAPI CFSDropTarget::CopyItems(IShellFolder * pSFFrom, UINT cidl,
-                                    LPCITEMIDLIST * apidl, BOOL bCopy)
-{
-    CComPtr<IPersistFolder2> ppf2 = NULL;
-    WCHAR szSrcPath[MAX_PATH];
-    WCHAR szTargetPath[MAX_PATH];
-    SHFILEOPSTRUCTW op;
-    LPITEMIDLIST pidl;
-    LPWSTR pszSrc, pszTarget, pszSrcList, pszTargetList, pszFileName;
-    int res, length;
-    HRESULT hr;
-
-    TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom, cidl, apidl);
-
-    hr = pSFFrom->QueryInterface (IID_PPV_ARG(IPersistFolder2, &ppf2));
-    if (SUCCEEDED(hr))
-    {
-        hr = ppf2->GetCurFolder(&pidl);
-        if (FAILED(hr))
-        {
-            return hr;
-        }
-
-        hr = SHGetPathFromIDListW(pidl, szSrcPath);
-        SHFree(pidl);
-
-        if (FAILED(hr))
-            return hr;
-
-        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])
-        {
-            /* 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;
-        }
-        op.hwnd = GetActiveWindow();
-        op.wFunc = bCopy ? FO_COPY : FO_MOVE;
-        op.fFlags |= FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
-
-        res = SHFileOperationW(&op);
-
-        if (res == DE_SAMEFILE)
-        {
-            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);
-        }
-
-        HeapFree(GetProcessHeap(), 0, pszSrcList);
-        HeapFree(GetProcessHeap(), 0, pszTargetList);
-
-        if (res)
-            return E_FAIL;
-        else
-            return S_OK;
-    }
-    return E_FAIL;
-}
-
 /************************************************************************
  * CFSFolder::GetClassID
  */
@@ -1122,421 +967,6 @@ 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
-CFSDropTarget::GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
-{
-    WCHAR wszLink[40];
-
-    if (!bShortcut)
-    {
-        if (!LoadStringW(shell32_hInstance, IDS_LNK_FILE, wszLink, _countof(wszLink)))
-            wszLink[0] = L'\0';
-    }
-
-    if (!bShortcut)
-        swprintf(pwszTarget, L"%s%s%s", wszLink, pwszBasePath, pwszExt);
-    else
-        swprintf(pwszTarget, L"%s%s", pwszBasePath, pwszExt);
-
-    for (UINT i = 2; PathFileExistsW(pwszTarget); ++i)
-    {
-        if (!bShortcut)
-            swprintf(pwszTarget, L"%s%s (%u)%s", wszLink, pwszBasePath, i, pwszExt);
-        else
-            swprintf(pwszTarget, L"%s (%u)%s", pwszBasePath, i, pwszExt);
-    }
-
-    return TRUE;
-}
-
-/****************************************************************************
- * IDropTarget implementation
- */
-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. */
-
-    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 FALSE;
-}
-
-HRESULT WINAPI CFSDropTarget::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 CFSDropTarget::DragOver(DWORD dwKeyState, POINTL pt,
-                                       DWORD *pdwEffect)
-{
-    TRACE("(%p)\n", this);
-
-    if (!pdwEffect)
-        return E_INVALIDARG;
-
-    QueryDrop(dwKeyState, pdwEffect);
-
-    return S_OK;
-}
-
-HRESULT WINAPI CFSDropTarget::DragLeave()
-{
-    TRACE("(%p)\n", this);
-
-    fAcceptFmt = FALSE;
-
-    return S_OK;
-}
-
-HRESULT WINAPI CFSDropTarget::Drop(IDataObject *pDataObject,
-                                   DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
-{
-    TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect);
-    
-    if (!pdwEffect)
-        return E_INVALIDARG;
-
-    QueryDrop(dwKeyState, pdwEffect);
-
-    BOOL fIsOpAsync = FALSE;
-    CComPtr<IAsyncOperation> pAsyncOperation;
-
-    if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
-    {
-        if (SUCCEEDED(pAsyncOperation->GetAsyncMode(&fIsOpAsync)) && fIsOpAsync)
-        {
-            _DoDropData *data = static_cast<_DoDropData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(_DoDropData)));
-            data->This = this;
-            // Need to maintain this class in case the window is closed or the class exists temporarily (when dropping onto a folder).
-            pDataObject->AddRef();
-            pAsyncOperation->StartOperation(NULL);
-            CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &data->pStream);
-            this->AddRef();
-            data->dwKeyState = dwKeyState;
-            data->pt = pt;
-            // Need to dereference as pdweffect gets freed.
-            data->pdwEffect = *pdwEffect;
-            SHCreateThread(CFSDropTarget::_DoDropThreadProc, data, NULL, NULL);
-            return S_OK;
-        }
-    }
-    return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect);
-}
-
-HRESULT WINAPI CFSDropTarget::_DoDrop(IDataObject *pDataObject,
-                                      DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
-{
-    TRACE("(%p) performing drop, effect %u\n", this, *pdwEffect);
-    FORMATETC fmt;
-    FORMATETC fmt2;
-    STGMEDIUM medium;
-
-    InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
-    InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
-
-    HRESULT hr;
-    bool bCopy = TRUE;
-    bool bLinking = FALSE;
-
-    /* Figure out what drop operation we're doing */
-    if (pdwEffect)
-    {
-        TRACE("Current drop effect flag %i\n", *pdwEffect);
-        if ((*pdwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
-            bCopy = FALSE;
-        if ((*pdwEffect & DROPEFFECT_LINK) == DROPEFFECT_LINK)
-            bLinking = TRUE;
-    }
-
-    if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
-    {
-        hr = pDataObject->GetData(&fmt, &medium);
-        TRACE("CFSTR_SHELLIDLIST.\n");
-
-        /* lock the handle */
-        LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
-        if (!lpcida)
-        {
-            ReleaseStgMedium(&medium);
-            return E_FAIL;
-        }
-
-        /* convert the data into pidl */
-        LPITEMIDLIST pidl;
-        LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
-        if (!apidl)
-        {
-            ReleaseStgMedium(&medium);
-            return E_FAIL;
-        }
-
-        CComPtr<IShellFolder> psfDesktop;
-        CComPtr<IShellFolder> psfFrom = NULL;
-
-        /* Grab the desktop shell folder */
-        hr = SHGetDesktopFolder(&psfDesktop);
-        if (FAILED(hr))
-        {
-            ERR("SHGetDesktopFolder failed\n");
-            SHFree(pidl);
-            _ILFreeaPidl(apidl, lpcida->cidl);
-            ReleaseStgMedium(&medium);
-            return E_FAIL;
-        }
-
-        /* Find source folder, this is where the clipboard data was copied from */
-        if (_ILIsDesktop(pidl))
-        {
-            /* use desktop shell folder */
-            psfFrom = psfDesktop;
-        }
-        else 
-        {
-            hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom));
-            if (FAILED(hr))
-            {
-                ERR("no IShellFolder\n");
-                SHFree(pidl);
-                _ILFreeaPidl(apidl, lpcida->cidl);
-                ReleaseStgMedium(&medium);
-                return E_FAIL;
-            }
-        }
-
-        if (bLinking)
-        {
-            WCHAR wszTargetPath[MAX_PATH];
-            WCHAR wszPath[MAX_PATH];
-            WCHAR wszTarget[MAX_PATH];
-
-            wcscpy(wszTargetPath, sPathTarget);
-
-            TRACE("target path = %s", debugstr_w(wszTargetPath));
-
-            /* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */
-            for (UINT i = 0; i < lpcida->cidl; i++)
-            {
-                //Find out which file we're copying
-                STRRET strFile;
-                hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strFile);
-                if (FAILED(hr)) 
-                {
-                    ERR("Error source obtaining path");
-                    break;
-                }
-
-                hr = StrRetToBufW(&strFile, apidl[i], wszPath, _countof(wszPath));
-                if (FAILED(hr)) 
-                {
-                    ERR("Error putting source path into buffer");
-                    break;
-                }
-                TRACE("source path = %s", debugstr_w(wszPath));
-
-                // Creating a buffer to hold the combined path
-                WCHAR buffer_1[MAX_PATH] = L"";
-                WCHAR *lpStr1;
-                lpStr1 = buffer_1;
-
-                LPWSTR pwszFileName = PathFindFileNameW(wszPath);
-                LPWSTR pwszExt = PathFindExtensionW(wszPath);
-                LPWSTR placementPath = PathCombineW(lpStr1, sPathTarget, pwszFileName);
-                CComPtr<IPersistFile> ppf;
-
-                //Check to see if it's already a link. 
-                if (!wcsicmp(pwszExt, L".lnk"))
-                {
-                    //It's a link so, we create a new one which copies the old.
-                    if(!GetUniqueFileName(placementPath, pwszExt, wszTarget, TRUE)) 
-                    {
-                        ERR("Error getting unique file name");
-                        hr = E_FAIL;
-                        break;
-                    }
-                    hr = IShellLink_ConstructFromPath(wszPath, IID_PPV_ARG(IPersistFile, &ppf));
-                    if (FAILED(hr)) {
-                        ERR("Error constructing link from file");
-                        break;
-                    }
-
-                    hr = ppf->Save(wszTarget, FALSE);
-                                       if (FAILED(hr))
-                                               break;
-                                       SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL);
-                }
-                else
-                {
-                    //It's not a link, so build a new link using the creator class and fill it in.
-                    //Create a file name for the link
-                    if (!GetUniqueFileName(placementPath, L".lnk", wszTarget, TRUE))
-                    {
-                        ERR("Error creating unique file name");
-                        hr = E_FAIL;
-                        break;
-                    }
-
-                    CComPtr<IShellLinkW> pLink;
-                    hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink));
-                    if (FAILED(hr)) {
-                        ERR("Error instantiating IShellLinkW");
-                        break;
-                    }
-
-                    WCHAR szDirPath[MAX_PATH], *pwszFile;
-                    GetFullPathName(wszPath, MAX_PATH, szDirPath, &pwszFile);
-                    if (pwszFile) pwszFile[0] = 0;
-
-                    hr = pLink->SetPath(wszPath);
-                    if(FAILED(hr))
-                        break;
-
-                    hr = pLink->SetWorkingDirectory(szDirPath);
-                    if(FAILED(hr))
-                        break;
-
-                    hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
-                    if(FAILED(hr))
-                        break;
-
-                    hr = ppf->Save(wszTarget, TRUE);
-                                       if (FAILED(hr))
-                                               break;
-                                       SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL);
-                }
-            }
-        }
-        else 
-        {
-            hr = this->CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy);
-        }
-
-        SHFree(pidl);
-        _ILFreeaPidl(apidl, lpcida->cidl);
-        ReleaseStgMedium(&medium);
-    }
-    else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
-    {
-        FORMATETC fmt2;
-        InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
-        if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/)
-        {
-            WCHAR wszTargetPath[MAX_PATH + 1];
-            LPWSTR pszSrcList;
-
-            wcscpy(wszTargetPath, sPathTarget);
-            //Double NULL terminate.
-            wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
-            
-            LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal);
-            if (!lpdf)
-            {
-                ERR("Error locking global\n");
-                return E_FAIL;
-            }
-            pszSrcList = (LPWSTR) (((byte*) lpdf) + lpdf->pFiles);
-            TRACE("Source file (just the first) = %s\n", debugstr_w(pszSrcList));
-            TRACE("Target path = %s\n", debugstr_w(wszTargetPath));
-
-            SHFILEOPSTRUCTW op;
-            ZeroMemory(&op, sizeof(op));
-            op.pFrom = pszSrcList;
-            op.pTo = wszTargetPath;
-            op.hwnd = GetActiveWindow();
-            op.wFunc = bCopy ? FO_COPY : FO_MOVE;
-            op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
-            hr = SHFileOperationW(&op);
-            return hr;
-        }
-        ERR("Error calling GetData\n");
-        hr = E_FAIL;
-    }
-    else 
-    {
-        ERR("No viable drop format.\n");
-        hr = E_FAIL;
-    }    
-    return hr;
-}
-
-DWORD WINAPI CFSDropTarget::_DoDropThreadProc(LPVOID lpParameter)
-{
-    CoInitialize(NULL);
-    _DoDropData *data = static_cast<_DoDropData*>(lpParameter);
-    CComPtr<IDataObject> pDataObject;
-    HRESULT hr = CoGetInterfaceAndReleaseStream (data->pStream, IID_PPV_ARG(IDataObject, &pDataObject));
-
-    if (SUCCEEDED(hr))
-    {
-        CComPtr<IAsyncOperation> pAsyncOperation;
-        hr = data->This->_DoDrop(pDataObject, data->dwKeyState, data->pt, &data->pdwEffect);
-        if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
-        {
-            pAsyncOperation->EndOperation(hr, NULL, data->pdwEffect);
-        }
-    }
-    //Release the CFSFolder and data object holds in the copying thread.
-    data->This->Release();
-    //Release the parameter from the heap.
-    HeapFree(GetProcessHeap(), 0, data);
-    CoUninitialize();
-    return 0;
-}
-
 HRESULT WINAPI CFSFolder::_GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut) {
     HKEY hKey;
     HRESULT hr;