Author: akhaldi Date: Thu Jan 9 13:24:39 2014 New Revision: 61576
URL: http://svn.reactos.org/svn/reactos?rev=61576&view=rev Log: [SHELL32] * Add support for the CF_HDROP format in the shell drop targets. * Implement IAsyncOperation for the shell data object implementation, which is how one checks to see if it's safe to perform a background copy. * Actually check for the IAsyncOperation interface in the drop targets. * 7-zip and WinRAR are now mostly working correctly in terms of drag and drop. * Brought to you by Huw Campbell. CORE-3760
Modified: trunk/reactos/dll/win32/shell32/dataobject.cpp trunk/reactos/dll/win32/shell32/folders/desktop.cpp trunk/reactos/dll/win32/shell32/folders/fs.cpp trunk/reactos/dll/win32/shell32/folders/fs.h trunk/reactos/dll/win32/shell32/shlview.cpp
Modified: trunk/reactos/dll/win32/shell32/dataobject.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/dataobjec... ============================================================================== --- trunk/reactos/dll/win32/shell32/dataobject.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/dataobject.cpp [iso-8859-1] Thu Jan 9 13:24:39 2014 @@ -163,7 +163,8 @@
class IDataObjectImpl : public CComObjectRootEx<CComMultiThreadModelNoCS>, - public IDataObject + public IDataObject, + public IAsyncOperation { private: LPITEMIDLIST pidl; @@ -176,6 +177,7 @@ UINT cfFileNameA; UINT cfFileNameW; UINT cfPreferredDropEffect; + BOOL doasync; public: IDataObjectImpl(); ~IDataObjectImpl(); @@ -191,9 +193,15 @@ virtual HRESULT WINAPI DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection); virtual HRESULT WINAPI DUnadvise(DWORD dwConnection); virtual HRESULT WINAPI EnumDAdvise(IEnumSTATDATA **ppenumAdvise); + virtual HRESULT WINAPI GetAsyncMode(BOOL *pfIsOpAsync); + virtual HRESULT WINAPI InOperation(BOOL *pfInAsyncOp); + virtual HRESULT WINAPI SetAsyncMode(BOOL fDoOpAsync); + virtual HRESULT WINAPI StartOperation(IBindCtx *pbcReserved); + virtual HRESULT WINAPI EndOperation(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects);
BEGIN_COM_MAP(IDataObjectImpl) COM_INTERFACE_ENTRY_IID(IID_IDataObject, IDataObject) + COM_INTERFACE_ENTRY_IID(IID_IAsyncOperation, IAsyncOperation) END_COM_MAP() };
@@ -207,6 +215,7 @@ cfFileNameA = 0; cfFileNameW = 0; cfPreferredDropEffect = 0; + doasync = FALSE; }
IDataObjectImpl::~IDataObjectImpl() @@ -371,6 +380,37 @@ return E_NOTIMPL; }
+HRESULT WINAPI IDataObjectImpl::GetAsyncMode(BOOL *pfIsOpAsync) +{ + TRACE("(%p)->()\n", this); + *pfIsOpAsync = doasync; + return S_OK; +} +HRESULT WINAPI IDataObjectImpl::InOperation(BOOL *pfInAsyncOp) +{ + FIXME("(%p)->()\n", this); + return E_NOTIMPL; +} +HRESULT WINAPI IDataObjectImpl::SetAsyncMode(BOOL fDoOpAsync) +{ + TRACE("(%p)->()\n", this); + doasync = fDoOpAsync; + return S_OK; +} + +HRESULT WINAPI IDataObjectImpl::StartOperation(IBindCtx *pbcReserved) +{ + FIXME("(%p)->()\n", this); + return E_NOTIMPL; +} +HRESULT WINAPI IDataObjectImpl::EndOperation(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects) +{ + FIXME("(%p)->()\n", this); + return E_NOTIMPL; +} + + + /************************************************************************** * IDataObject_Constructor */
Modified: trunk/reactos/dll/win32/shell32/folders/desktop.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/folders/d... ============================================================================== --- trunk/reactos/dll/win32/shell32/folders/desktop.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/folders/desktop.cpp [iso-8859-1] Thu Jan 9 13:24:39 2014 @@ -1377,11 +1377,18 @@ 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); - fAcceptFmt = (S_OK == pDataObject->QueryGetData(&fmt)) ? - TRUE : FALSE; + 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; @@ -1413,32 +1420,45 @@ 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); - if (FAILED(hr)) - return hr; - - /* lock the handle */ - LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal); - if (!lpcida) - { + 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); - 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; - } - + } + else + { + InitFormatEtc (formatetc, CF_HDROP, TYMED_HGLOBAL); + if SUCCEEDED(pDataObject->QueryGetData(&formatetc)); + { + passthroughtofs = TRUE; + } + } /* We only want to really move files around if they don't already come from the desktop, or we're linking or copying */ - if ((!_ILIsDesktop(pidl)) || (dwKeyState & MK_CONTROL)) + if (passthroughtofs) { LPITEMIDLIST pidl = NULL;
@@ -1467,9 +1487,5 @@
/* Todo, rewrite the registry such that the icons are well placed. Blocked by no bags implementation. */ - - SHFree(pidl); - _ILFreeaPidl(apidl, lpcida->cidl); - ReleaseStgMedium(&medium); return hr; }
Modified: trunk/reactos/dll/win32/shell32/folders/fs.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/folders/f... ============================================================================== --- trunk/reactos/dll/win32/shell32/folders/fs.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/folders/fs.cpp [iso-8859-1] Thu Jan 9 13:24:39 2014 @@ -1376,17 +1376,18 @@ HRESULT WINAPI CFSFolder::DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) { + TRACE("(%p)->(DataObject=%p)\n", this, pDataObject); FORMATETC fmt; - TRACE("(%p)->(DataObject=%p)\n", this, pDataObject); + FORMATETC fmt2; + fAcceptFmt = FALSE; + InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL); - - fAcceptFmt = (S_OK == pDataObject->QueryGetData(&fmt)) ? TRUE : FALSE; - - if (!fAcceptFmt) - { - InitFormatEtc(fmt, RegisterClipboardFormatW(CFSTR_FILEDESCRIPTOR), TYMED_HGLOBAL); - fAcceptFmt = (S_OK == pDataObject->QueryGetData(&fmt)) ? TRUE : FALSE; - } + 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; @@ -1418,55 +1419,49 @@ DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) { TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect); - - _DoDropData *data = reinterpret_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). - data->This->AddRef(); - data->pDataObject = pDataObject; - // Also keep the data object in case it gets freed elsewhere. - data->pDataObject->AddRef(); - data->dwKeyState = dwKeyState; - data->pt = pt; - // Need to dereference as pdweffect is freed. - data->pdwEffect = *pdwEffect; - - SHCreateThread(reinterpret_cast<LPTHREAD_START_ROUTINE> (CFSFolder::_DoDropThreadProc), reinterpret_cast<void *> (data), NULL, NULL); - return S_OK; + + BOOL fIsOpAsync = FALSE; + CComPtr<IAsyncOperation> pAsyncOperation; + + if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation)))) + { + if (SUCCEEDED(pAsyncOperation->GetAsyncMode(&fIsOpAsync)) && fIsOpAsync) + { + _DoDropData *data = reinterpret_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). + this->AddRef(); + data->pDataObject = pDataObject; + data->pAsyncOperation = pAsyncOperation; + data->dwKeyState = dwKeyState; + data->pt = pt; + // Need to dereference as pdweffect gets freed. + data->pdwEffect = *pdwEffect; + data->pDataObject->AddRef(); + data->pAsyncOperation->StartOperation(NULL); + SHCreateThread(reinterpret_cast<LPTHREAD_START_ROUTINE> (CFSFolder::_DoDropThreadProc), reinterpret_cast<void *> (data), NULL, NULL); + return S_OK; + } + else + pAsyncOperation->Release(); + } + return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect); }
HRESULT WINAPI CFSFolder::_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; - - STGMEDIUM medium; - FORMATETC formatetc; - InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); - hr = pDataObject->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 data into pidl */ - LPITEMIDLIST pidl; - LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida); - if (!apidl) - { - ReleaseStgMedium(&medium); - return E_FAIL; - }
/* Figure out what drop operation we're doing */ if (pdwEffect) @@ -1478,183 +1473,276 @@ bLinking = TRUE; }
- 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); - 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_IShellFolder, (LPVOID*)&psfFrom); + 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; + CComPtr<IShellFolder> psfTarget = NULL; + + hr = this->QueryInterface(IID_PPV_ARG(IShellFolder, &psfTarget)); if (FAILED(hr)) { - ERR("no IShellFolder\n"); + ERR("psfTarget setting failed\n"); SHFree(pidl); _ILFreeaPidl(apidl, lpcida->cidl); ReleaseStgMedium(&medium); return E_FAIL; } - } - - 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_IPersistFolder2, (LPVOID *) &ppf2); - if (SUCCEEDED(hr)) - { - hr = ppf2->GetCurFolder(&targetpidl); + + /* 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_IShellFolder, (LPVOID*)&psfFrom); + if (FAILED(hr)) + { + ERR("no IShellFolder\n"); + SHFree(pidl); + _ILFreeaPidl(apidl, lpcida->cidl); + ReleaseStgMedium(&medium); + return E_FAIL; + } + } + + 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_IPersistFolder2, (LPVOID *) &ppf2); if (SUCCEEDED(hr)) { - hr = psfDesktop->GetDisplayNameOf(targetpidl, SHGDN_FORPARSING, &strFile); - ILFree(targetpidl); - if (SUCCEEDED(hr)) + hr = ppf2->GetCurFolder(&targetpidl); + if (SUCCEEDED(hr)) { - hr = StrRetToBufW(&strFile, NULL, wszTargetPath, _countof(wszTargetPath)); + 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"); - - } - 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)); + ERR("Error obtaining target path"); + } + + 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<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_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<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); + } + } + } + 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))*/) + { + 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_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)); + //Double NULL terminate. + wszTargetPath[wcslen(wszTargetPath) + 1] = '\0'; + } + } + } 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<IPersistFile> ppf; - - //Check to see if it's already a link. - if (!wcsicmp(pwszExt, L".lnk")) + ERR("Error obtaining target path"); + return E_FAIL; + } + + LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal); + if (!lpdf) { - //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<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); - } - } + 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 { - hr = this->CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy); - } - - SHFree(pidl); - _ILFreeaPidl(apidl, lpcida->cidl); - ReleaseStgMedium(&medium); - + ERR("No viable drop format.\n"); + hr = E_FAIL; + } return hr; }
DWORD CFSFolder::_DoDropThreadProc(LPVOID lpParameter) { _DoDropData *data = reinterpret_cast<_DoDropData*>(lpParameter); - data->This->_DoDrop(data->pDataObject, data->dwKeyState, data->pt, &data->pdwEffect); + HRESULT hr = data->This->_DoDrop(data->pDataObject, data->dwKeyState, data->pt, &data->pdwEffect); //Release the CFSFolder and data object holds in the copying thread. + data->pAsyncOperation->EndOperation(hr, NULL, data->pdwEffect); + data->pAsyncOperation->Release(); data->pDataObject->Release(); data->This->Release(); //Release the parameter from the heap.
Modified: trunk/reactos/dll/win32/shell32/folders/fs.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/folders/f... ============================================================================== --- trunk/reactos/dll/win32/shell32/folders/fs.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/folders/fs.h [iso-8859-1] Thu Jan 9 13:24:39 2014 @@ -120,6 +120,7 @@ struct _DoDropData { CFSFolder *This; IDataObject *pDataObject; + IAsyncOperation *pAsyncOperation; DWORD dwKeyState; POINTL pt; DWORD pdwEffect;
Modified: trunk/reactos/dll/win32/shell32/shlview.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shlview.c... ============================================================================== --- trunk/reactos/dll/win32/shell32/shlview.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/shlview.cpp [iso-8859-1] Thu Jan 9 13:24:39 2014 @@ -1686,10 +1686,16 @@ dwEffect |= DROPEFFECT_LINK; } } + + CComPtr<IAsyncOperation> piaso; + if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso)))) + { + piaso->SetAsyncMode(TRUE); + piaso->Release(); + }
if (pds) - { - DWORD dwEffect2; + { DWORD dwEffect2; DoDragDrop(pda, pds, dwEffect, &dwEffect2); } pda->Release();