diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c index 67f5ac80d84..29406bcb2ae 100644 --- a/dlls/shell32/shlview_cmenu.c +++ b/dlls/shell32/shlview_cmenu.c @@ -1134,115 +1134,147 @@ static void DoNewFolder(ContextMenu *This, IShellView *view) } } -static BOOL DoPaste(ContextMenu *This) +static HRESULT paste_pidls(ContextMenu *This, ITEMIDLIST **pidls, UINT count) { - BOOL bSuccess = TRUE; - IDataObject * pda; + IShellFolder *psfDesktop; + UINT i; + HRESULT hr = S_OK; + + /* bind to the source shellfolder */ + hr = SHGetDesktopFolder(&psfDesktop); + if (FAILED(hr)) + return hr; + + for (i = 0; SUCCEEDED(hr) && i < count; i++) { + ITEMIDLIST *pidl_dir = NULL; + ITEMIDLIST *pidl_item; + IShellFolder *psfFrom = NULL; + + pidl_dir = ILClone(pidls[i]); + ILRemoveLastID(pidl_dir); + pidl_item = ILFindLastID(pidls[i]); + hr = IShellFolder_BindToObject(psfDesktop, pidl_dir, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom); + + if (psfFrom) + { + /* get source and destination shellfolder */ + ISFHelper *psfhlpdst, *psfhlpsrc; + hr = IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst); + if (SUCCEEDED(hr)) + hr = IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc); + + /* do the copy/move */ + if (psfhlpdst && psfhlpsrc) + { + hr = ISFHelper_CopyItems(psfhlpdst, psfFrom, 1, (LPCITEMIDLIST*)&pidl_item); + /* FIXME handle move + ISFHelper_DeleteItems(psfhlpsrc, 1, &pidl_item); + */ + } + if(psfhlpdst) ISFHelper_Release(psfhlpdst); + if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); + IShellFolder_Release(psfFrom); + } + SHFree(pidl_dir); + } + + IShellFolder_Release(psfDesktop); + return hr; +} - TRACE("\n"); +static HRESULT DoPaste(ContextMenu *This) +{ + IDataObject * pda; + HRESULT hr; - if(SUCCEEDED(OleGetClipboard(&pda))) + TRACE("(%p)\n", This); + hr = OleGetClipboard(&pda); + if(SUCCEEDED(hr)) { STGMEDIUM medium; FORMATETC formatetc; + HRESULT format_hr; TRACE("pda=%p\n", pda); - /* Set the FORMATETC structure*/ InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW), TYMED_HGLOBAL); /* Get the pidls from IDataObject */ - if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium))) - { + format_hr = IDataObject_GetData(pda,&formatetc,&medium); + if(SUCCEEDED(format_hr)) + { LPITEMIDLIST * apidl; LPITEMIDLIST pidl; - IShellFolder *psfFrom = NULL, *psfDesktop; - int i; LPIDA lpcida = GlobalLock(medium.u.hGlobal); TRACE("cida=%p\n", lpcida); - - apidl = _ILCopyCidaToaPidl(&pidl, lpcida); - - for (i = 0; bSuccess && i < lpcida->cidl; i++) { - ITEMIDLIST *apidl_dir = NULL; - ITEMIDLIST *apidl_item; - - psfFrom = NULL; - /* bind to the source shellfolder */ - SHGetDesktopFolder(&psfDesktop); - if(psfDesktop) + if (lpcida) + { + apidl = _ILCopyCidaToaPidl(&pidl, lpcida); + if (apidl) { - apidl_dir = ILClone(apidl[i]); - ILRemoveLastID(apidl_dir); - apidl_item = ILFindLastID(apidl[i]); - IShellFolder_BindToObject(psfDesktop, apidl_dir, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom); - IShellFolder_Release(psfDesktop); + hr = paste_pidls(This, apidl, lpcida->cidl); + _ILFreeaPidl(apidl, lpcida->cidl); + SHFree(pidl); } + else + hr = HRESULT_FROM_WIN32(hr); + } + else + hr = HRESULT_FROM_WIN32(hr); + ReleaseStgMedium(&medium); + } - if (psfFrom) + if(FAILED(format_hr)) + { + InitFormatEtc(formatetc, CF_HDROP, TYMED_HGLOBAL); + format_hr = IDataObject_GetData(pda,&formatetc,&medium); + if(SUCCEEDED(format_hr)) + { + DROPFILES *dropfiles = GlobalLock(medium.u.hGlobal); + TRACE("CF_HDROP=%p\n", dropfiles); + if (dropfiles) { - /* get source and destination shellfolder */ - ISFHelper *psfhlpdst, *psfhlpsrc; - IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst); - IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc); + WCHAR path[MAX_PATH]; + UINT i, count; + ITEMIDLIST **pidls; - /* do the copy/move */ - if (psfhlpdst && psfhlpsrc) + count = DragQueryFileW(medium.u.hGlobal, -1, NULL, 0); + pidls = SHAlloc(count*sizeof(ITEMIDLIST**)); + if (pidls) { - HRESULT hr = ISFHelper_CopyItems(psfhlpdst, psfFrom, 1, (LPCITEMIDLIST*)&apidl_item); - if (FAILED(hr)) - bSuccess = FALSE; - /* FIXME handle move - ISFHelper_DeleteItems(psfhlpsrc, 1, &apidl_item); - */ + for (i = 0; i < count; i++) + { + DragQueryFileW(medium.u.hGlobal, i, path, ARRAY_SIZE(path)); + if ((pidls[i] = ILCreateFromPathW(path)) == NULL) + { + hr = E_FAIL; + break; + } + } + if (SUCCEEDED(hr)) + hr = paste_pidls(This, pidls, count); + _ILFreeaPidl(pidls, count); } - if(psfhlpdst) ISFHelper_Release(psfhlpdst); - if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); - IShellFolder_Release(psfFrom); + else + hr = HRESULT_FROM_WIN32(GetLastError()); + GlobalUnlock(medium.u.hGlobal); } else - bSuccess = FALSE; - SHFree(apidl_dir); + hr = HRESULT_FROM_WIN32(GetLastError()); + ReleaseStgMedium(&medium); } - - _ILFreeaPidl(apidl, lpcida->cidl); - SHFree(pidl); - - /* release the medium*/ - ReleaseStgMedium(&medium); } - else - bSuccess = FALSE; - IDataObject_Release(pda); - } - else - bSuccess = FALSE; -#if 0 - HGLOBAL hMem; - OpenClipboard(NULL); - hMem = GetClipboardData(CF_HDROP); - - if(hMem) - { - char * pDropFiles = GlobalLock(hMem); - if(pDropFiles) + if (FAILED(format_hr)) { - int len, offset = sizeof(DROPFILESTRUCT); - - while( pDropFiles[offset] != 0) - { - len = strlen(pDropFiles + offset); - TRACE("%s\n", pDropFiles + offset); - offset += len+1; - } + ERR("there are no supported and retrievable clipboard formats\n"); + hr = format_hr; } - GlobalUnlock(hMem); + IDataObject_Release(pda); } - CloseClipboard(); -#endif - return bSuccess; + + return hr; } static HRESULT WINAPI BackgroundMenu_InvokeCommand( diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 8e92a0896b5..29fcd0b7754 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -4387,7 +4387,17 @@ static void test_contextmenu(IContextMenu *menu, BOOL background) { trace("Got ID %d, verb %s, string %s.\n", mii.wID, debugstr_a(buf), debugstr_a(mii.dwTypeData)); if (!strcmp(buf, "copy")) + { + CMINVOKECOMMANDINFO cmi; ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_COPY, "wrong menu wID %d\n", mii.wID); + memset(&cmi, 0, sizeof(CMINVOKECOMMANDINFO)); + cmi.cbSize = sizeof(CMINVOKECOMMANDINFO); + cmi.lpVerb = "copy"; + hr = IContextMenu_InvokeCommand(menu, &cmi); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(IsClipboardFormatAvailable(RegisterClipboardFormatA(CFSTR_SHELLIDLISTA)), "CFSTR_SHELLIDLISTA not available\n"); + ok(IsClipboardFormatAvailable(CF_HDROP), "CF_HDROP not available\n"); + } else if (!strcmp(buf, "paste")) ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_INSERT, "wrong menu wID %d\n", mii.wID); else if (!strcmp(buf, "properties"))