From 315db4c011111afc05f9c9e2bf2a03461c7f6930 Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Tue, 19 Nov 2013 20:53:16 +0000 Subject: [PATCH] [shell32] - Implement cut and paste shortcut - Patch by Huw Campbell - CORE-7548 svn path=/trunk/; revision=61049 --- reactos/dll/win32/shell32/dataobject.cpp | 26 +- reactos/dll/win32/shell32/defcontextmenu.cpp | 369 +++++++++++++----- reactos/dll/win32/shell32/folders/desktop.cpp | 4 +- reactos/dll/win32/shell32/folders/desktop.h | 2 +- reactos/dll/win32/shell32/folders/fs.cpp | 4 +- reactos/dll/win32/shell32/folders/fs.h | 2 +- reactos/dll/win32/shell32/shellfolder.h | 2 +- 7 files changed, 314 insertions(+), 95 deletions(-) diff --git a/reactos/dll/win32/shell32/dataobject.cpp b/reactos/dll/win32/shell32/dataobject.cpp index 09c87cff9ed..0bffd877eff 100644 --- a/reactos/dll/win32/shell32/dataobject.cpp +++ b/reactos/dll/win32/shell32/dataobject.cpp @@ -159,7 +159,7 @@ HRESULT IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[], IEnumFORMA */ /* number of supported formats */ -#define MAX_FORMATS 4 +#define MAX_FORMATS 5 class IDataObjectImpl : public CComObjectRootEx, @@ -169,11 +169,13 @@ private: LPITEMIDLIST pidl; LPITEMIDLIST * apidl; UINT cidl; + DWORD dropeffect; FORMATETC pFormatEtc[MAX_FORMATS]; UINT cfShellIDList; UINT cfFileNameA; UINT cfFileNameW; + UINT cfPreferredDropEffect; public: IDataObjectImpl(); ~IDataObjectImpl(); @@ -200,9 +202,11 @@ IDataObjectImpl::IDataObjectImpl() pidl = NULL; apidl = NULL; cidl = 0; + dropeffect = 0; cfShellIDList = 0; cfFileNameA = 0; cfFileNameW = 0; + cfPreferredDropEffect = 0; } IDataObjectImpl::~IDataObjectImpl() @@ -219,14 +223,17 @@ HRESULT WINAPI IDataObjectImpl::Initialize(HWND hwndOwner, LPCITEMIDLIST pMyPidl if (pidl == NULL || apidl == NULL) return E_OUTOFMEMORY; cidl = cidlx; + dropeffect = DROPEFFECT_COPY; cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST); cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA); cfFileNameW = RegisterClipboardFormatW(CFSTR_FILENAMEW); + cfPreferredDropEffect = RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECTW); InitFormatEtc(pFormatEtc[0], cfShellIDList, TYMED_HGLOBAL); InitFormatEtc(pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL); InitFormatEtc(pFormatEtc[2], cfFileNameA, TYMED_HGLOBAL); InitFormatEtc(pFormatEtc[3], cfFileNameW, TYMED_HGLOBAL); + InitFormatEtc(pFormatEtc[4], cfPreferredDropEffect, TYMED_HGLOBAL); return S_OK; } @@ -261,6 +268,10 @@ HRESULT WINAPI IDataObjectImpl::GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pme if (cidl < 1) return(E_UNEXPECTED); pmedium->hGlobal = RenderFILENAMEW(pidl, apidl, cidl); } + else if (pformatetcIn->cfFormat == cfPreferredDropEffect) + { + pmedium->hGlobal = RenderPREFEREDDROPEFFECT(dropeffect); + } else { FIXME("-- expected clipformat not implemented\n"); @@ -311,6 +322,19 @@ HRESULT WINAPI IDataObjectImpl::GetCanonicalFormatEtc(LPFORMATETC pformatectIn, HRESULT WINAPI IDataObjectImpl::SetData(LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease) { + if (pformatetc->cfFormat == cfPreferredDropEffect) + { + const DWORD *src = (const DWORD *)GlobalLock(pmedium->hGlobal); + if (src != 0) + { + dropeffect = *src; + GlobalUnlock(pmedium->hGlobal); + return S_OK; + } + FIXME("Error setting data"); + return E_FAIL; + } + FIXME("(%p)->()\n", this); return E_NOTIMPL; } diff --git a/reactos/dll/win32/shell32/defcontextmenu.cpp b/reactos/dll/win32/shell32/defcontextmenu.cpp index d85a264c29b..1cc23dc3ec4 100644 --- a/reactos/dll/win32/shell32/defcontextmenu.cpp +++ b/reactos/dll/win32/shell32/defcontextmenu.cpp @@ -59,6 +59,7 @@ class CDefaultContextMenu : UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu); UINT BuildShellItemContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags); HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi); + HRESULT DoPasteLink(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoDelete(LPCMINVOKECOMMANDINFO lpcmi); @@ -950,77 +951,70 @@ CDefaultContextMenu::DoPaste( { HRESULT hr; - IDataObject *pda; - if (OleGetClipboard(&pda) != S_OK) - return E_FAIL; + CComPtr pda; + hr = OleGetClipboard(&pda); + if (FAILED(hr)) + return hr; STGMEDIUM medium; FORMATETC formatetc; InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); hr = pda->GetData(&formatetc, &medium); - if (FAILED(hr)) - { - pda->Release(); - return E_FAIL; - } + return hr; /* lock the handle */ LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal); if (!lpcida) { ReleaseStgMedium(&medium); - pda->Release(); return E_FAIL; } /* convert the data into pidl */ LPITEMIDLIST pidl; LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida); - if (!apidl) - return E_FAIL; - - IShellFolder *psfDesktop; - if (FAILED(SHGetDesktopFolder(&psfDesktop))) { - SHFree(pidl); - _ILFreeaPidl(apidl, lpcida->cidl); ReleaseStgMedium(&medium); - pda->Release(); return E_FAIL; } + CComPtr psfDesktop; + CComPtr psfFrom = NULL; + CComPtr psfTarget = NULL; + CComPtr psfhlpdst; + CComPtr psfhlpsrc; + bool bCopy = TRUE; + + hr = SHGetDesktopFolder(&psfDesktop); + if (FAILED(hr)) + goto cleanup; + /* Find source folder */ - IShellFolder *psfFrom = NULL; if (_ILIsDesktop(pidl)) { /* use desktop shellfolder */ psfFrom = psfDesktop; } - else if (FAILED(psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom)))) + else { - ERR("no IShellFolder\n"); - - psfDesktop->Release(); - SHFree(pidl); - _ILFreeaPidl(apidl, lpcida->cidl); - ReleaseStgMedium(&medium); - pda->Release(); - - return E_FAIL; + hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom)); + if (FAILED(hr)) + { + ERR("no IShellFolder\n"); + goto cleanup; + } } /* Find target folder */ - IShellFolder *psfTarget = NULL; if (m_Dcm.cidl) { - psfDesktop->Release(); hr = m_Dcm.psf->BindToObject(m_Dcm.apidl[0], NULL, IID_PPV_ARG(IShellFolder, &psfTarget)); } else { - IPersistFolder2 *ppf2 = NULL; + CComPtr ppf2 = NULL; LPITEMIDLIST pidl; /* cidl is zero due to explorer view */ @@ -1028,7 +1022,6 @@ CDefaultContextMenu::DoPaste( if (SUCCEEDED(hr)) { hr = ppf2->GetCurFolder(&pidl); - ppf2->Release(); if (SUCCEEDED(hr)) { if (_ILIsDesktop(pidl)) @@ -1041,7 +1034,7 @@ CDefaultContextMenu::DoPaste( /* retrieve target desktop folder */ hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfTarget)); } - TRACE("psfTarget %x %p, Desktop %u\n", hr, psfTarget, _ILIsDesktop(pidl)); + TRACE("psfTarget %x %p, Desktop %u\n", hr, psfTarget.p, _ILIsDesktop(pidl)); ILFree(pidl); } } @@ -1050,72 +1043,53 @@ CDefaultContextMenu::DoPaste( if (FAILED(hr)) { ERR("no IShellFolder\n"); - - psfFrom->Release(); - SHFree(pidl); - _ILFreeaPidl(apidl, lpcida->cidl); - ReleaseStgMedium(&medium); - pda->Release(); - - return E_FAIL; + goto cleanup; } /* get source and destination shellfolder */ - ISFHelper *psfhlpdst; - if (FAILED(psfTarget->QueryInterface(IID_PPV_ARG(ISFHelper, &psfhlpdst)))) + hr = psfTarget->QueryInterface(IID_PPV_ARG(ISFHelper, &psfhlpdst)); + if (FAILED(hr)) { ERR("no IID_ISFHelper for destination\n"); - - psfFrom->Release(); - psfTarget->Release(); - SHFree(pidl); - _ILFreeaPidl(apidl, lpcida->cidl); - ReleaseStgMedium(&medium); - pda->Release(); - - return E_FAIL; + goto cleanup; } - ISFHelper *psfhlpsrc; - if (FAILED(psfFrom->QueryInterface(IID_PPV_ARG(ISFHelper, &psfhlpsrc)))) + hr = psfFrom->QueryInterface(IID_PPV_ARG(ISFHelper, &psfhlpsrc)); + if (FAILED(hr)) { ERR("no IID_ISFHelper for source\n"); - - psfhlpdst->Release(); - psfFrom->Release(); - psfTarget->Release(); - SHFree(pidl); - _ILFreeaPidl(apidl, lpcida->cidl); - ReleaseStgMedium(&medium); - pda->Release(); - return E_FAIL; + goto cleanup; } - /* FIXXME - * do we want to perform a copy or move ??? - */ - hr = psfhlpdst->CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); + FORMATETC formatetc2; + STGMEDIUM medium2; + InitFormatEtc(formatetc2, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL); - psfhlpdst->Release(); - psfhlpsrc->Release(); - psfFrom->Release(); - psfTarget->Release(); + if SUCCEEDED(pda->GetData(&formatetc2, &medium2)) + { + DWORD * pdwFlag = (DWORD*)GlobalLock(medium2.hGlobal); + if (pdwFlag) + { + TRACE("Current drop effect flag %i\n", *pdwFlag); + if (*pdwFlag & DROPEFFECT_MOVE) + bCopy = FALSE; + } + GlobalUnlock(medium2.hGlobal); + } + + hr = psfhlpdst->CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy); + + NotifyShellViewWindow(lpcmi, TRUE); + +cleanup: SHFree(pidl); _ILFreeaPidl(apidl, lpcida->cidl); ReleaseStgMedium(&medium); - pda->Release(); + TRACE("CP result %x\n", hr); return S_OK; } -HRESULT -CDefaultContextMenu::DoOpenOrExplore( - LPCMINVOKECOMMANDINFO lpcmi) -{ - UNIMPLEMENTED; - return E_FAIL; -} - BOOL GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut) { @@ -1141,7 +1115,203 @@ GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL } return TRUE; +} +HRESULT +CDefaultContextMenu::DoPasteLink( + LPCMINVOKECOMMANDINFO lpcmi) +{ + HRESULT hr; + WCHAR wszPath[MAX_PATH]; + WCHAR wszTarget[MAX_PATH]; + + CComPtr pda; + hr = OleGetClipboard(&pda); + if (FAILED(hr)) + return hr; + + STGMEDIUM medium; + FORMATETC formatetc; + InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); + hr = pda->GetData(&formatetc, &medium); + if (FAILED(hr)) + return 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; + } + + CComPtr psfDesktop; + CComPtr ppf2 = NULL; + CComPtr psfFrom = NULL; + + /* Grab the desktop shell folder */ + hr = SHGetDesktopFolder(&psfDesktop); + if (FAILED(hr)) + { + ERR("SHGetDesktopFolder failed\n"); + goto cleanup; + } + + /* 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_IShellFolder, (LPVOID*)&psfFrom); + if (FAILED(hr)) + { + ERR("no IShellFolder\n"); + goto cleanup; + } + } + + /* Find the target path, where we will be saving the new links (where the user right clicked) */ + STRRET strFile; + WCHAR wszTargetPath[MAX_PATH]; + + LPITEMIDLIST targetpidl; + + hr = m_Dcm.psf->QueryInterface(IID_IPersistFolder2, (LPVOID *) &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"); + goto cleanup; + } + 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, wszTargetPath, pwszFileName); + CComPtr 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_ConstructFromFile(NULL, IID_IPersistFile, ILCombine(pidl, apidl[i]), (LPVOID*)&ppf); + if (FAILED(hr)) { + ERR("Error constructing link from file"); + break; + } + + hr = ppf->Save(wszTarget, FALSE); + } + 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 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); + } + } + + NotifyShellViewWindow(lpcmi, TRUE); + +cleanup: + SHFree(pidl); + _ILFreeaPidl(apidl, lpcida->cidl); + ReleaseStgMedium(&medium); + + return hr; +} + +HRESULT +CDefaultContextMenu::DoOpenOrExplore( + LPCMINVOKECOMMANDINFO lpcmi) +{ + UNIMPLEMENTED; + return E_FAIL; } HRESULT @@ -1153,15 +1323,17 @@ CDefaultContextMenu::DoCreateLink( HRESULT hr; STRRET strFile; - if (m_Dcm.psf->GetDisplayNameOf(m_Dcm.apidl[0], SHGDN_FORPARSING, &strFile) != S_OK) + hr = m_Dcm.psf->GetDisplayNameOf(m_Dcm.apidl[0], SHGDN_FORPARSING, &strFile); + if (FAILED(hr)) { ERR("IShellFolder_GetDisplayNameOf failed for apidl\n"); - return E_FAIL; + return hr; } WCHAR wszPath[MAX_PATH]; - if (StrRetToBufW(&strFile, m_Dcm.apidl[0], wszPath, _countof(wszPath)) != S_OK) - return E_FAIL; + hr = StrRetToBufW(&strFile, m_Dcm.apidl[0], wszPath, _countof(wszPath)); + if (FAILED(hr)) + return hr; LPWSTR pwszExt = PathFindExtensionW(wszPath); @@ -1170,8 +1342,17 @@ CDefaultContextMenu::DoCreateLink( if (!GetUniqueFileName(wszPath, pwszExt, wszTarget, TRUE)) return E_FAIL; - hr = IShellLink_ConstructFromFile(NULL, IID_IPersistFile, m_Dcm.apidl[0], (LPVOID*)&ppf); - if (hr != S_OK) + IPersistFolder2 *ppf2 = NULL; + LPITEMIDLIST pidl; + hr = m_Dcm.psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2)); + if (SUCCEEDED(hr)) + { + hr = ppf2->GetCurFolder(&pidl); + ppf2->Release(); + if (SUCCEEDED(hr)) + hr = IShellLink_ConstructFromFile(NULL, IID_IPersistFile, ILCombine(pidl, m_Dcm.apidl[0]), (LPVOID*)&ppf); + } + if (FAILED(hr)) return hr; hr = ppf->Save(wszTarget, FALSE); @@ -1282,6 +1463,19 @@ CDefaultContextMenu::DoCopyOrCut( if (SUCCEEDED(SHCreateDataObject(m_Dcm.pidlFolder, m_Dcm.cidl, m_Dcm.apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj)))) { + if (!bCopy) + { + FORMATETC formatetc; + STGMEDIUM medium; + InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL); + pDataObj->GetData(&formatetc, &medium); + DWORD * pdwFlag = (DWORD*)GlobalLock(medium.hGlobal); + if (pdwFlag) + *pdwFlag = DROPEFFECT_MOVE; + GlobalUnlock(medium.hGlobal); + pDataObj->SetData(&formatetc, &medium, TRUE); + } + hr = OleSetClipboard(pDataObj); pDataObj->Release(); return hr; @@ -1649,8 +1843,9 @@ CDefaultContextMenu::InvokeCommand( case FCIDM_SHVIEW_REFRESH: return NotifyShellViewWindow(lpcmi, FALSE); case FCIDM_SHVIEW_INSERT: - case FCIDM_SHVIEW_INSERTLINK: return DoPaste(lpcmi); + case FCIDM_SHVIEW_INSERTLINK: + return DoPasteLink(lpcmi); case FCIDM_SHVIEW_OPEN: case FCIDM_SHVIEW_EXPLORE: return DoOpenOrExplore(lpcmi); diff --git a/reactos/dll/win32/shell32/folders/desktop.cpp b/reactos/dll/win32/shell32/folders/desktop.cpp index d89faf526a0..934fdd5382b 100644 --- a/reactos/dll/win32/shell32/folders/desktop.cpp +++ b/reactos/dll/win32/shell32/folders/desktop.cpp @@ -1205,7 +1205,7 @@ HRESULT WINAPI CDesktopFolder::DeleteItems(UINT cidl, LPCITEMIDLIST *apidl) return ret; } -HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl) +HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, bool bCopy) { CComPtr ppf2; WCHAR szSrcPath[MAX_PATH]; @@ -1291,7 +1291,7 @@ HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCIT op.fFlags = FOF_MULTIDESTFILES; } op.hwnd = GetActiveWindow(); - op.wFunc = FO_COPY; + op.wFunc = bCopy ? FO_COPY : FO_MOVE; op.fFlags |= FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR; res = SHFileOperationW(&op); diff --git a/reactos/dll/win32/shell32/folders/desktop.h b/reactos/dll/win32/shell32/folders/desktop.h index 4ebc8da2abc..3ab15ac4ac7 100644 --- a/reactos/dll/win32/shell32/folders/desktop.h +++ b/reactos/dll/win32/shell32/folders/desktop.h @@ -76,7 +76,7 @@ class CDesktopFolder : virtual HRESULT WINAPI GetUniqueName(LPWSTR pwszName, UINT uLen); virtual HRESULT WINAPI AddFolder(HWND hwnd, LPCWSTR pwszName, LPITEMIDLIST *ppidlOut); virtual HRESULT WINAPI DeleteItems(UINT cidl, LPCITEMIDLIST *apidl); - virtual HRESULT WINAPI CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl); + virtual HRESULT WINAPI CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, bool bCopy); DECLARE_REGISTRY_RESOURCEID(IDR_SHELLDESKTOP) DECLARE_NOT_AGGREGATABLE(CDesktopFolder) diff --git a/reactos/dll/win32/shell32/folders/fs.cpp b/reactos/dll/win32/shell32/folders/fs.cpp index ddbced7c76e..0d788319bba 100644 --- a/reactos/dll/win32/shell32/folders/fs.cpp +++ b/reactos/dll/win32/shell32/folders/fs.cpp @@ -1035,7 +1035,7 @@ HRESULT WINAPI CFSFolder::DeleteItems(UINT cidl, LPCITEMIDLIST *apidl) * copies items to this folder */ HRESULT WINAPI CFSFolder::CopyItems(IShellFolder * pSFFrom, UINT cidl, - LPCITEMIDLIST * apidl) + LPCITEMIDLIST * apidl, bool bCopy) { IPersistFolder2 *ppf2 = NULL; WCHAR szSrcPath[MAX_PATH]; @@ -1131,7 +1131,7 @@ HRESULT WINAPI CFSFolder::CopyItems(IShellFolder * pSFFrom, UINT cidl, op.fFlags = FOF_MULTIDESTFILES; } op.hwnd = GetActiveWindow(); - op.wFunc = FO_COPY; + op.wFunc = bCopy ? FO_COPY : FO_MOVE; op.fFlags |= FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR; res = SHFileOperationW(&op); diff --git a/reactos/dll/win32/shell32/folders/fs.h b/reactos/dll/win32/shell32/folders/fs.h index a1f128fe948..fc88e353ff2 100644 --- a/reactos/dll/win32/shell32/folders/fs.h +++ b/reactos/dll/win32/shell32/folders/fs.h @@ -93,7 +93,7 @@ class CFSFolder : virtual HRESULT WINAPI GetUniqueName(LPWSTR pwszName, UINT uLen); virtual HRESULT WINAPI AddFolder(HWND hwnd, LPCWSTR pwszName, LPITEMIDLIST *ppidlOut); virtual HRESULT WINAPI DeleteItems(UINT cidl, LPCITEMIDLIST *apidl); - virtual HRESULT WINAPI CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl); + virtual HRESULT WINAPI CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, bool bCopy); DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER) DECLARE_NOT_AGGREGATABLE(CFSFolder) diff --git a/reactos/dll/win32/shell32/shellfolder.h b/reactos/dll/win32/shell32/shellfolder.h index 4558bfa4f9a..87f8873fbdb 100644 --- a/reactos/dll/win32/shell32/shellfolder.h +++ b/reactos/dll/win32/shell32/shellfolder.h @@ -42,7 +42,7 @@ DECLARE_INTERFACE_(ISFHelper,IUnknown) STDMETHOD(GetUniqueName)(THIS_ LPWSTR lpName, UINT uLen) PURE; STDMETHOD(AddFolder)(THIS_ HWND hwnd, LPCWSTR lpName, LPITEMIDLIST * ppidlOut) PURE; STDMETHOD(DeleteItems)(THIS_ UINT cidl, LPCITEMIDLIST * apidl) PURE; - STDMETHOD(CopyItems)(THIS_ IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl) PURE; + STDMETHOD(CopyItems)(THIS_ IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl, bool bCopy) PURE; }; #undef INTERFACE