1c2c66affSColin Finck 2c2c66affSColin Finck /* 3c2c66affSColin Finck * file system folder drop target 4c2c66affSColin Finck * 5c2c66affSColin Finck * Copyright 1997 Marcus Meissner 6c2c66affSColin Finck * Copyright 1998, 1999, 2002 Juergen Schmied 7c2c66affSColin Finck * 8c2c66affSColin Finck * This library is free software; you can redistribute it and/or 9c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 10c2c66affSColin Finck * License as published by the Free Software Foundation; either 11c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 12c2c66affSColin Finck * 13c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 14c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 15c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16c2c66affSColin Finck * Lesser General Public License for more details. 17c2c66affSColin Finck * 18c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 19c2c66affSColin Finck * License along with this library; if not, write to the Free Software 20c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21c2c66affSColin Finck */ 22c2c66affSColin Finck 23c2c66affSColin Finck #include <precomp.h> 24c2c66affSColin Finck 25c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL (shell); 26c2c66affSColin Finck 27fa95a96eSWhindmar Saksit static void SHELL_StripIllegalFsNameCharacters(_Inout_ LPWSTR Buf) 28fa95a96eSWhindmar Saksit { 29fa95a96eSWhindmar Saksit for (LPWSTR src = Buf, dst = src;;) 30fa95a96eSWhindmar Saksit { 31fa95a96eSWhindmar Saksit *dst = *src; 32fa95a96eSWhindmar Saksit if (!*dst) 33fa95a96eSWhindmar Saksit break; 34fa95a96eSWhindmar Saksit else if (wcschr(INVALID_FILETITLE_CHARACTERSW, *dst)) 35fa95a96eSWhindmar Saksit src = CharNextW(src); 36fa95a96eSWhindmar Saksit else 37fa95a96eSWhindmar Saksit ++src, ++dst; 38fa95a96eSWhindmar Saksit } 39fa95a96eSWhindmar Saksit } 40fa95a96eSWhindmar Saksit 41fa95a96eSWhindmar Saksit static HRESULT 42fa95a96eSWhindmar Saksit SHELL_LimitDropEffectToItemAttributes(_In_ IDataObject *pDataObject, _Inout_ PDWORD pdwEffect) 43fa95a96eSWhindmar Saksit { 44fa95a96eSWhindmar Saksit DWORD att = *pdwEffect & (SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK); // DROPEFFECT maps perfectly to these SFGAO bits 45fa95a96eSWhindmar Saksit HRESULT hr = SHGetAttributesFromDataObject(pDataObject, att, &att, NULL); 46fa95a96eSWhindmar Saksit if (FAILED(hr)) 47fa95a96eSWhindmar Saksit return S_FALSE; 48fa95a96eSWhindmar Saksit *pdwEffect &= ~(SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK) | att; 49fa95a96eSWhindmar Saksit return hr; 50fa95a96eSWhindmar Saksit } 51fa95a96eSWhindmar Saksit 52fa95a96eSWhindmar Saksit static void GetDefaultCopyMoveEffect() 53fa95a96eSWhindmar Saksit { 54fa95a96eSWhindmar Saksit // FIXME: When the source is on a different volume than the target, change default from move to copy 55fa95a96eSWhindmar Saksit } 56c2c66affSColin Finck 57c2c66affSColin Finck /**************************************************************************** 58fd209faaSGiannis Adamopoulos * CFSDropTarget::_CopyItems 59c2c66affSColin Finck * 601273bbe4SHuw Campbell * copies or moves items to this folder 61c2c66affSColin Finck */ 62fd209faaSGiannis Adamopoulos HRESULT CFSDropTarget::_CopyItems(IShellFolder * pSFFrom, UINT cidl, 63c2c66affSColin Finck LPCITEMIDLIST * apidl, BOOL bCopy) 64c2c66affSColin Finck { 651273bbe4SHuw Campbell HRESULT ret; 661273bbe4SHuw Campbell WCHAR wszDstPath[MAX_PATH + 1] = {0}; 671273bbe4SHuw Campbell PWCHAR pwszSrcPathsList = (PWCHAR) HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) * cidl + 1); 681273bbe4SHuw Campbell if (!pwszSrcPathsList) 69c2c66affSColin Finck return E_OUTOFMEMORY; 70c2c66affSColin Finck 711273bbe4SHuw Campbell PWCHAR pwszListPos = pwszSrcPathsList; 721273bbe4SHuw Campbell STRRET strretFrom; 731273bbe4SHuw Campbell SHFILEOPSTRUCTW fop; 74520577a8SKatayama Hirofumi MZ BOOL bRenameOnCollision = FALSE; 75c2c66affSColin Finck 761273bbe4SHuw Campbell /* Build a double null terminated list of C strings from source paths */ 771273bbe4SHuw Campbell for (UINT i = 0; i < cidl; i++) 78a5a30fc2SKyle Katarn { 791273bbe4SHuw Campbell ret = pSFFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strretFrom); 801273bbe4SHuw Campbell if (FAILED(ret)) 811273bbe4SHuw Campbell goto cleanup; 821273bbe4SHuw Campbell 831273bbe4SHuw Campbell ret = StrRetToBufW(&strretFrom, NULL, pwszListPos, MAX_PATH); 841273bbe4SHuw Campbell if (FAILED(ret)) 851273bbe4SHuw Campbell goto cleanup; 861273bbe4SHuw Campbell 871273bbe4SHuw Campbell pwszListPos += lstrlenW(pwszListPos) + 1; 88a5a30fc2SKyle Katarn } 891273bbe4SHuw Campbell /* Append the final null. */ 901273bbe4SHuw Campbell *pwszListPos = L'\0'; 911273bbe4SHuw Campbell 921273bbe4SHuw Campbell /* Build a double null terminated target (this path) */ 931273bbe4SHuw Campbell ret = StringCchCopyW(wszDstPath, MAX_PATH, m_sPathTarget); 941273bbe4SHuw Campbell if (FAILED(ret)) 951273bbe4SHuw Campbell goto cleanup; 961273bbe4SHuw Campbell 97520577a8SKatayama Hirofumi MZ wszDstPath[lstrlenW(wszDstPath) + 1] = UNICODE_NULL; 98520577a8SKatayama Hirofumi MZ 99520577a8SKatayama Hirofumi MZ /* Set bRenameOnCollision to TRUE if necesssary */ 100520577a8SKatayama Hirofumi MZ if (bCopy) 101520577a8SKatayama Hirofumi MZ { 102520577a8SKatayama Hirofumi MZ WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH]; 103520577a8SKatayama Hirofumi MZ GetFullPathNameW(pwszSrcPathsList, _countof(szPath1), szPath1, NULL); 104520577a8SKatayama Hirofumi MZ GetFullPathNameW(wszDstPath, _countof(szPath2), szPath2, NULL); 105520577a8SKatayama Hirofumi MZ PathRemoveFileSpecW(szPath1); 106520577a8SKatayama Hirofumi MZ if (_wcsicmp(szPath1, szPath2) == 0) 107520577a8SKatayama Hirofumi MZ bRenameOnCollision = TRUE; 108520577a8SKatayama Hirofumi MZ } 1091273bbe4SHuw Campbell 1101273bbe4SHuw Campbell ZeroMemory(&fop, sizeof(fop)); 1111273bbe4SHuw Campbell fop.hwnd = m_hwndSite; 1121273bbe4SHuw Campbell fop.wFunc = bCopy ? FO_COPY : FO_MOVE; 1131273bbe4SHuw Campbell fop.pFrom = pwszSrcPathsList; 1141273bbe4SHuw Campbell fop.pTo = wszDstPath; 1151273bbe4SHuw Campbell fop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR; 116520577a8SKatayama Hirofumi MZ if (bRenameOnCollision) 117520577a8SKatayama Hirofumi MZ fop.fFlags |= FOF_RENAMEONCOLLISION; 118520577a8SKatayama Hirofumi MZ 1191273bbe4SHuw Campbell ret = S_OK; 1201273bbe4SHuw Campbell 1211273bbe4SHuw Campbell if (SHFileOperationW(&fop)) 1221273bbe4SHuw Campbell { 1231273bbe4SHuw Campbell ERR("SHFileOperationW failed\n"); 1241273bbe4SHuw Campbell ret = E_FAIL; 1251273bbe4SHuw Campbell } 1261273bbe4SHuw Campbell 1271273bbe4SHuw Campbell cleanup: 1281273bbe4SHuw Campbell HeapFree(GetProcessHeap(), 0, pwszSrcPathsList); 1291273bbe4SHuw Campbell return ret; 130c2c66affSColin Finck } 131c2c66affSColin Finck 132c2c66affSColin Finck CFSDropTarget::CFSDropTarget(): 133fd209faaSGiannis Adamopoulos m_cfShellIDList(0), 134fd209faaSGiannis Adamopoulos m_fAcceptFmt(FALSE), 135fd209faaSGiannis Adamopoulos m_sPathTarget(NULL), 1366d91269eSGiannis Adamopoulos m_hwndSite(NULL), 1376d91269eSGiannis Adamopoulos m_grfKeyState(0) 138c2c66affSColin Finck { 139c2c66affSColin Finck } 140c2c66affSColin Finck 141fd209faaSGiannis Adamopoulos HRESULT CFSDropTarget::Initialize(LPWSTR PathTarget) 142c2c66affSColin Finck { 143c2c66affSColin Finck if (!PathTarget) 144c2c66affSColin Finck return E_UNEXPECTED; 145c2c66affSColin Finck 146fd209faaSGiannis Adamopoulos m_cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST); 147fd209faaSGiannis Adamopoulos if (!m_cfShellIDList) 148c2c66affSColin Finck return E_FAIL; 149c2c66affSColin Finck 150fd209faaSGiannis Adamopoulos m_sPathTarget = (WCHAR *)SHAlloc((wcslen(PathTarget) + 1) * sizeof(WCHAR)); 151fd209faaSGiannis Adamopoulos if (!m_sPathTarget) 152c2c66affSColin Finck return E_OUTOFMEMORY; 153c2c66affSColin Finck 154fd209faaSGiannis Adamopoulos wcscpy(m_sPathTarget, PathTarget); 155c2c66affSColin Finck 156c2c66affSColin Finck return S_OK; 157c2c66affSColin Finck } 158c2c66affSColin Finck 159c2c66affSColin Finck CFSDropTarget::~CFSDropTarget() 160c2c66affSColin Finck { 161fd209faaSGiannis Adamopoulos SHFree(m_sPathTarget); 162c2c66affSColin Finck } 163c2c66affSColin Finck 164c2c66affSColin Finck BOOL 1650f5fb478SKatayama Hirofumi MZ CFSDropTarget::_GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut) 166c2c66affSColin Finck { 167c2c66affSColin Finck WCHAR wszLink[40]; 168c2c66affSColin Finck 169c2c66affSColin Finck if (!bShortcut) 170c2c66affSColin Finck { 171c2c66affSColin Finck if (!LoadStringW(shell32_hInstance, IDS_LNK_FILE, wszLink, _countof(wszLink))) 172c2c66affSColin Finck wszLink[0] = L'\0'; 173c2c66affSColin Finck } 174c2c66affSColin Finck 175c2c66affSColin Finck if (!bShortcut) 176c2c66affSColin Finck swprintf(pwszTarget, L"%s%s%s", wszLink, pwszBasePath, pwszExt); 177c2c66affSColin Finck else 178c2c66affSColin Finck swprintf(pwszTarget, L"%s%s", pwszBasePath, pwszExt); 179c2c66affSColin Finck 180c2c66affSColin Finck for (UINT i = 2; PathFileExistsW(pwszTarget); ++i) 181c2c66affSColin Finck { 182c2c66affSColin Finck if (!bShortcut) 183c2c66affSColin Finck swprintf(pwszTarget, L"%s%s (%u)%s", wszLink, pwszBasePath, i, pwszExt); 184c2c66affSColin Finck else 185c2c66affSColin Finck swprintf(pwszTarget, L"%s (%u)%s", pwszBasePath, i, pwszExt); 186c2c66affSColin Finck } 187c2c66affSColin Finck 188c2c66affSColin Finck return TRUE; 189c2c66affSColin Finck } 190c2c66affSColin Finck 191c2c66affSColin Finck /**************************************************************************** 192c2c66affSColin Finck * IDropTarget implementation 193c2c66affSColin Finck */ 194fd209faaSGiannis Adamopoulos BOOL CFSDropTarget::_QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect) 195c2c66affSColin Finck { 196c2c66affSColin Finck /* TODO Windows does different drop effects if dragging across drives. 197c2c66affSColin Finck i.e., it will copy instead of move if the directories are on different disks. */ 198fa95a96eSWhindmar Saksit GetDefaultCopyMoveEffect(); 199c2c66affSColin Finck 2006f25b42aSGiannis Adamopoulos DWORD dwEffect = m_dwDefaultEffect; 201c2c66affSColin Finck 202c2c66affSColin Finck *pdwEffect = DROPEFFECT_NONE; 203c2c66affSColin Finck 204fd209faaSGiannis Adamopoulos if (m_fAcceptFmt) { /* Does our interpretation of the keystate ... */ 205c2c66affSColin Finck *pdwEffect = KeyStateToDropEffect (dwKeyState); 206c2c66affSColin Finck 207c2c66affSColin Finck if (*pdwEffect == DROPEFFECT_NONE) 208c2c66affSColin Finck *pdwEffect = dwEffect; 209c2c66affSColin Finck 210c2c66affSColin Finck /* ... matches the desired effect ? */ 211c2c66affSColin Finck if (dwEffect & *pdwEffect) { 212c2c66affSColin Finck return TRUE; 213c2c66affSColin Finck } 214c2c66affSColin Finck } 215c2c66affSColin Finck return FALSE; 216c2c66affSColin Finck } 217c2c66affSColin Finck 2186f25b42aSGiannis Adamopoulos HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects) 2196d91269eSGiannis Adamopoulos { 2206d91269eSGiannis Adamopoulos HMENU hmenu = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(IDM_DRAGFILE)); 2216d91269eSGiannis Adamopoulos if (!hmenu) 2226d91269eSGiannis Adamopoulos return E_OUTOFMEMORY; 2236d91269eSGiannis Adamopoulos 2246f25b42aSGiannis Adamopoulos HMENU hpopupmenu = GetSubMenu(hmenu, 0); 2256f25b42aSGiannis Adamopoulos 226fa95a96eSWhindmar Saksit SHELL_LimitDropEffectToItemAttributes(pDataObject, &dwAvailableEffects); 2276f25b42aSGiannis Adamopoulos if ((dwAvailableEffects & DROPEFFECT_COPY) == 0) 2286f25b42aSGiannis Adamopoulos DeleteMenu(hpopupmenu, IDM_COPYHERE, MF_BYCOMMAND); 229fa95a96eSWhindmar Saksit if ((dwAvailableEffects & DROPEFFECT_MOVE) == 0) 2306f25b42aSGiannis Adamopoulos DeleteMenu(hpopupmenu, IDM_MOVEHERE, MF_BYCOMMAND); 231fa95a96eSWhindmar Saksit if ((dwAvailableEffects & DROPEFFECT_LINK) == 0 && (dwAvailableEffects & (DROPEFFECT_COPY | DROPEFFECT_MOVE))) 2326f25b42aSGiannis Adamopoulos DeleteMenu(hpopupmenu, IDM_LINKHERE, MF_BYCOMMAND); 2336f25b42aSGiannis Adamopoulos 234fa95a96eSWhindmar Saksit GetDefaultCopyMoveEffect(); 235fa95a96eSWhindmar Saksit if (*pdwEffect & dwAvailableEffects & DROPEFFECT_COPY) 2366f25b42aSGiannis Adamopoulos SetMenuDefaultItem(hpopupmenu, IDM_COPYHERE, FALSE); 237fa95a96eSWhindmar Saksit else if (*pdwEffect & dwAvailableEffects & DROPEFFECT_MOVE) 2386f25b42aSGiannis Adamopoulos SetMenuDefaultItem(hpopupmenu, IDM_MOVEHERE, FALSE); 239fa95a96eSWhindmar Saksit else if (dwAvailableEffects & DROPEFFECT_LINK) 2406f25b42aSGiannis Adamopoulos SetMenuDefaultItem(hpopupmenu, IDM_LINKHERE, FALSE); 2416f25b42aSGiannis Adamopoulos 2426d91269eSGiannis Adamopoulos /* FIXME: We need to support shell extensions here */ 2436d91269eSGiannis Adamopoulos 2441d55f459SGiannis Adamopoulos /* We shouldn't use the site window here because the menu should work even when we don't have a site */ 2451d55f459SGiannis Adamopoulos HWND hwndDummy = CreateWindowEx(0, 2461d55f459SGiannis Adamopoulos WC_STATIC, 2471d55f459SGiannis Adamopoulos NULL, 2481d55f459SGiannis Adamopoulos WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER | SS_LEFT, 2491d55f459SGiannis Adamopoulos pt.x, 2501d55f459SGiannis Adamopoulos pt.y, 2511d55f459SGiannis Adamopoulos 1, 2521d55f459SGiannis Adamopoulos 1, 2531d55f459SGiannis Adamopoulos NULL, 2541d55f459SGiannis Adamopoulos NULL, 2551d55f459SGiannis Adamopoulos NULL, 2561d55f459SGiannis Adamopoulos NULL); 2571d55f459SGiannis Adamopoulos 258fa95a96eSWhindmar Saksit SetForegroundWindow(hwndDummy); // Required for aborting by pressing Esc when dragging from Explorer to desktop 2596f25b42aSGiannis Adamopoulos UINT uCommand = TrackPopupMenu(hpopupmenu, 2606f25b42aSGiannis Adamopoulos TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY, 2611d55f459SGiannis Adamopoulos pt.x, pt.y, 0, hwndDummy, NULL); 2621d55f459SGiannis Adamopoulos 2631d55f459SGiannis Adamopoulos DestroyWindow(hwndDummy); 2641d55f459SGiannis Adamopoulos 2656d91269eSGiannis Adamopoulos if (uCommand == 0) 2666d91269eSGiannis Adamopoulos return S_FALSE; 2676d91269eSGiannis Adamopoulos else if (uCommand == IDM_COPYHERE) 2686d91269eSGiannis Adamopoulos *pdwEffect = DROPEFFECT_COPY; 2696d91269eSGiannis Adamopoulos else if (uCommand == IDM_MOVEHERE) 2706d91269eSGiannis Adamopoulos *pdwEffect = DROPEFFECT_MOVE; 2716d91269eSGiannis Adamopoulos else if (uCommand == IDM_LINKHERE) 2726d91269eSGiannis Adamopoulos *pdwEffect = DROPEFFECT_LINK; 2736d91269eSGiannis Adamopoulos 2746d91269eSGiannis Adamopoulos return S_OK; 2756d91269eSGiannis Adamopoulos } 2766d91269eSGiannis Adamopoulos 2776d91269eSGiannis Adamopoulos HRESULT CFSDropTarget::_RepositionItems(IShellFolderView *psfv, IDataObject *pdtobj, POINTL pt) 2786d91269eSGiannis Adamopoulos { 2796d91269eSGiannis Adamopoulos CComPtr<IFolderView> pfv; 2806d91269eSGiannis Adamopoulos POINT ptDrag; 2816d91269eSGiannis Adamopoulos HRESULT hr = psfv->QueryInterface(IID_PPV_ARG(IFolderView, &pfv)); 2826d91269eSGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr)) 2836d91269eSGiannis Adamopoulos return hr; 2846d91269eSGiannis Adamopoulos 2856d91269eSGiannis Adamopoulos hr = psfv->GetDragPoint(&ptDrag); 2866d91269eSGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr)) 2876d91269eSGiannis Adamopoulos return hr; 2886d91269eSGiannis Adamopoulos 2896d91269eSGiannis Adamopoulos PIDLIST_ABSOLUTE pidlFolder; 2906d91269eSGiannis Adamopoulos PUITEMID_CHILD *apidl; 2916d91269eSGiannis Adamopoulos UINT cidl; 2926d91269eSGiannis Adamopoulos hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl); 2936d91269eSGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr)) 2946d91269eSGiannis Adamopoulos return hr; 2956d91269eSGiannis Adamopoulos 2966d91269eSGiannis Adamopoulos CComHeapPtr<POINT> apt; 2976d91269eSGiannis Adamopoulos if (!apt.Allocate(cidl)) 2986d91269eSGiannis Adamopoulos { 2996d91269eSGiannis Adamopoulos SHFree(pidlFolder); 3006d91269eSGiannis Adamopoulos _ILFreeaPidl(apidl, cidl); 3016d91269eSGiannis Adamopoulos return E_OUTOFMEMORY; 3026d91269eSGiannis Adamopoulos } 3036d91269eSGiannis Adamopoulos 3046d91269eSGiannis Adamopoulos for (UINT i = 0; i<cidl; i++) 3056d91269eSGiannis Adamopoulos { 3066d91269eSGiannis Adamopoulos pfv->GetItemPosition(apidl[i], &apt[i]); 3076d91269eSGiannis Adamopoulos apt[i].x += pt.x - ptDrag.x; 3086d91269eSGiannis Adamopoulos apt[i].y += pt.y - ptDrag.y; 3096d91269eSGiannis Adamopoulos } 3106d91269eSGiannis Adamopoulos 3116d91269eSGiannis Adamopoulos pfv->SelectAndPositionItems(cidl, apidl, apt, SVSI_SELECT); 3126d91269eSGiannis Adamopoulos 3136d91269eSGiannis Adamopoulos SHFree(pidlFolder); 3146d91269eSGiannis Adamopoulos _ILFreeaPidl(apidl, cidl); 3156d91269eSGiannis Adamopoulos return S_OK; 3166d91269eSGiannis Adamopoulos } 3176d91269eSGiannis Adamopoulos 318c2c66affSColin Finck HRESULT WINAPI CFSDropTarget::DragEnter(IDataObject *pDataObject, 319c2c66affSColin Finck DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) 320c2c66affSColin Finck { 321c2c66affSColin Finck TRACE("(%p)->(DataObject=%p)\n", this, pDataObject); 3228f129932SKatayama Hirofumi MZ 3238f129932SKatayama Hirofumi MZ if (*pdwEffect == DROPEFFECT_NONE) 3248f129932SKatayama Hirofumi MZ return S_OK; 3258f129932SKatayama Hirofumi MZ 326c2c66affSColin Finck FORMATETC fmt; 327c2c66affSColin Finck FORMATETC fmt2; 328fd209faaSGiannis Adamopoulos m_fAcceptFmt = FALSE; 329c2c66affSColin Finck 330fd209faaSGiannis Adamopoulos InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL); 331c2c66affSColin Finck InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL); 332c2c66affSColin Finck 333c2c66affSColin Finck if (SUCCEEDED(pDataObject->QueryGetData(&fmt))) 334fd209faaSGiannis Adamopoulos m_fAcceptFmt = TRUE; 335c2c66affSColin Finck else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2))) 336fd209faaSGiannis Adamopoulos m_fAcceptFmt = TRUE; 337c2c66affSColin Finck 3386d91269eSGiannis Adamopoulos m_grfKeyState = dwKeyState; 339cd75a87cSKatayama Hirofumi MZ 340cd75a87cSKatayama Hirofumi MZ #define D_NONE DROPEFFECT_NONE 341cd75a87cSKatayama Hirofumi MZ #define D_COPY DROPEFFECT_COPY 342cd75a87cSKatayama Hirofumi MZ #define D_MOVE DROPEFFECT_MOVE 343cd75a87cSKatayama Hirofumi MZ #define D_LINK DROPEFFECT_LINK 344cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = *pdwEffect; 345cd75a87cSKatayama Hirofumi MZ switch (*pdwEffect & (D_COPY | D_MOVE | D_LINK)) 346cd75a87cSKatayama Hirofumi MZ { 347cd75a87cSKatayama Hirofumi MZ case D_COPY | D_MOVE: 348cd75a87cSKatayama Hirofumi MZ if (dwKeyState & MK_CONTROL) 349cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_COPY; 350cd75a87cSKatayama Hirofumi MZ else 351cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_MOVE; 352cd75a87cSKatayama Hirofumi MZ break; 353cd75a87cSKatayama Hirofumi MZ case D_COPY | D_MOVE | D_LINK: 354cd75a87cSKatayama Hirofumi MZ if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL)) 355cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_LINK; 356cd75a87cSKatayama Hirofumi MZ else if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == MK_CONTROL) 357cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_COPY; 358cd75a87cSKatayama Hirofumi MZ else 359cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_MOVE; 360cd75a87cSKatayama Hirofumi MZ break; 361cd75a87cSKatayama Hirofumi MZ case D_COPY | D_LINK: 362cd75a87cSKatayama Hirofumi MZ if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL)) 363cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_LINK; 364cd75a87cSKatayama Hirofumi MZ else 365cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_COPY; 366cd75a87cSKatayama Hirofumi MZ break; 367cd75a87cSKatayama Hirofumi MZ case D_MOVE | D_LINK: 368cd75a87cSKatayama Hirofumi MZ if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL)) 369cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_LINK; 370cd75a87cSKatayama Hirofumi MZ else 371cd75a87cSKatayama Hirofumi MZ m_dwDefaultEffect = D_MOVE; 372cd75a87cSKatayama Hirofumi MZ break; 373cd75a87cSKatayama Hirofumi MZ } 3746f25b42aSGiannis Adamopoulos 3756f25b42aSGiannis Adamopoulos STGMEDIUM medium; 3766f25b42aSGiannis Adamopoulos if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium))) 3776f25b42aSGiannis Adamopoulos { 3786f25b42aSGiannis Adamopoulos WCHAR wstrFirstFile[MAX_PATH]; 3796f25b42aSGiannis Adamopoulos if (DragQueryFileW((HDROP)medium.hGlobal, 0, wstrFirstFile, _countof(wstrFirstFile))) 3806f25b42aSGiannis Adamopoulos { 3816f25b42aSGiannis Adamopoulos /* Check if the drive letter is different */ 382fd209faaSGiannis Adamopoulos if (wstrFirstFile[0] != m_sPathTarget[0]) 3836f25b42aSGiannis Adamopoulos { 3846f25b42aSGiannis Adamopoulos m_dwDefaultEffect = DROPEFFECT_COPY; 3856f25b42aSGiannis Adamopoulos } 3866f25b42aSGiannis Adamopoulos } 3876f25b42aSGiannis Adamopoulos ReleaseStgMedium(&medium); 3886f25b42aSGiannis Adamopoulos } 3896d91269eSGiannis Adamopoulos 390cd75a87cSKatayama Hirofumi MZ if (!m_fAcceptFmt) 391cd75a87cSKatayama Hirofumi MZ *pdwEffect = DROPEFFECT_NONE; 392cd75a87cSKatayama Hirofumi MZ else 393cd75a87cSKatayama Hirofumi MZ *pdwEffect = m_dwDefaultEffect; 394cd75a87cSKatayama Hirofumi MZ 395c2c66affSColin Finck return S_OK; 396c2c66affSColin Finck } 397c2c66affSColin Finck 398c2c66affSColin Finck HRESULT WINAPI CFSDropTarget::DragOver(DWORD dwKeyState, POINTL pt, 399c2c66affSColin Finck DWORD *pdwEffect) 400c2c66affSColin Finck { 401c2c66affSColin Finck TRACE("(%p)\n", this); 402c2c66affSColin Finck 403c2c66affSColin Finck if (!pdwEffect) 404c2c66affSColin Finck return E_INVALIDARG; 405c2c66affSColin Finck 4066d91269eSGiannis Adamopoulos m_grfKeyState = dwKeyState; 4076d91269eSGiannis Adamopoulos 408fd209faaSGiannis Adamopoulos _QueryDrop(dwKeyState, pdwEffect); 409c2c66affSColin Finck 410c2c66affSColin Finck return S_OK; 411c2c66affSColin Finck } 412c2c66affSColin Finck 413c2c66affSColin Finck HRESULT WINAPI CFSDropTarget::DragLeave() 414c2c66affSColin Finck { 415c2c66affSColin Finck TRACE("(%p)\n", this); 416c2c66affSColin Finck 417fd209faaSGiannis Adamopoulos m_fAcceptFmt = FALSE; 418c2c66affSColin Finck 419c2c66affSColin Finck return S_OK; 420c2c66affSColin Finck } 421c2c66affSColin Finck 422c2c66affSColin Finck HRESULT WINAPI CFSDropTarget::Drop(IDataObject *pDataObject, 423c2c66affSColin Finck DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) 424c2c66affSColin Finck { 425c2c66affSColin Finck TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect); 426c2c66affSColin Finck 427c2c66affSColin Finck if (!pdwEffect) 428c2c66affSColin Finck return E_INVALIDARG; 429c2c66affSColin Finck 4306d91269eSGiannis Adamopoulos IUnknown_GetWindow(m_site, &m_hwndSite); 4316d91269eSGiannis Adamopoulos 4326f25b42aSGiannis Adamopoulos DWORD dwAvailableEffects = *pdwEffect; 4336f25b42aSGiannis Adamopoulos 434fd209faaSGiannis Adamopoulos _QueryDrop(dwKeyState, pdwEffect); 435c2c66affSColin Finck 4366f25b42aSGiannis Adamopoulos TRACE("pdwEffect: 0x%x, m_dwDefaultEffect: 0x%x, dwAvailableEffects: 0x%x\n", *pdwEffect, m_dwDefaultEffect, dwAvailableEffects); 4376f25b42aSGiannis Adamopoulos 4386d91269eSGiannis Adamopoulos if (m_grfKeyState & MK_RBUTTON) 4396d91269eSGiannis Adamopoulos { 4406f25b42aSGiannis Adamopoulos HRESULT hr = _GetEffectFromMenu(pDataObject, pt, pdwEffect, dwAvailableEffects); 4416d91269eSGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr) || hr == S_FALSE) 4426d91269eSGiannis Adamopoulos return hr; 4436d91269eSGiannis Adamopoulos } 4446d91269eSGiannis Adamopoulos 4456d91269eSGiannis Adamopoulos if (*pdwEffect == DROPEFFECT_MOVE && m_site) 4466d91269eSGiannis Adamopoulos { 4476d91269eSGiannis Adamopoulos CComPtr<IShellFolderView> psfv; 4486d91269eSGiannis Adamopoulos HRESULT hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellFolderView, &psfv)); 4496d91269eSGiannis Adamopoulos if (SUCCEEDED(hr) && psfv->IsDropOnSource(this) == S_OK) 4506d91269eSGiannis Adamopoulos { 4516d91269eSGiannis Adamopoulos _RepositionItems(psfv, pDataObject, pt); 4526d91269eSGiannis Adamopoulos return S_OK; 4536d91269eSGiannis Adamopoulos } 4546d91269eSGiannis Adamopoulos } 4556d91269eSGiannis Adamopoulos 456c2c66affSColin Finck BOOL fIsOpAsync = FALSE; 457c2c66affSColin Finck CComPtr<IAsyncOperation> pAsyncOperation; 458c2c66affSColin Finck 459c2c66affSColin Finck if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation)))) 460c2c66affSColin Finck { 461c2c66affSColin Finck if (SUCCEEDED(pAsyncOperation->GetAsyncMode(&fIsOpAsync)) && fIsOpAsync) 462c2c66affSColin Finck { 463c2c66affSColin Finck _DoDropData *data = static_cast<_DoDropData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(_DoDropData))); 464c2c66affSColin Finck data->This = this; 465c2c66affSColin Finck // Need to maintain this class in case the window is closed or the class exists temporarily (when dropping onto a folder). 466c2c66affSColin Finck pDataObject->AddRef(); 467c2c66affSColin Finck pAsyncOperation->StartOperation(NULL); 468c2c66affSColin Finck CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &data->pStream); 469c2c66affSColin Finck this->AddRef(); 470c2c66affSColin Finck data->dwKeyState = dwKeyState; 471c2c66affSColin Finck data->pt = pt; 472c2c66affSColin Finck // Need to dereference as pdweffect gets freed. 473c2c66affSColin Finck data->pdwEffect = *pdwEffect; 474c2c66affSColin Finck SHCreateThread(CFSDropTarget::_DoDropThreadProc, data, NULL, NULL); 475c2c66affSColin Finck return S_OK; 476c2c66affSColin Finck } 477c2c66affSColin Finck } 478c2c66affSColin Finck return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect); 479c2c66affSColin Finck } 480c2c66affSColin Finck 4816d91269eSGiannis Adamopoulos HRESULT 4826d91269eSGiannis Adamopoulos WINAPI 4836d91269eSGiannis Adamopoulos CFSDropTarget::SetSite(IUnknown *pUnkSite) 4846d91269eSGiannis Adamopoulos { 4856d91269eSGiannis Adamopoulos m_site = pUnkSite; 4866d91269eSGiannis Adamopoulos return S_OK; 4876d91269eSGiannis Adamopoulos } 4886d91269eSGiannis Adamopoulos 4896d91269eSGiannis Adamopoulos HRESULT 4906d91269eSGiannis Adamopoulos WINAPI 4916d91269eSGiannis Adamopoulos CFSDropTarget::GetSite(REFIID riid, void **ppvSite) 4926d91269eSGiannis Adamopoulos { 4936d91269eSGiannis Adamopoulos if (!m_site) 4946d91269eSGiannis Adamopoulos return E_FAIL; 4956d91269eSGiannis Adamopoulos 4966d91269eSGiannis Adamopoulos return m_site->QueryInterface(riid, ppvSite); 4976d91269eSGiannis Adamopoulos } 4986d91269eSGiannis Adamopoulos 499fd209faaSGiannis Adamopoulos HRESULT CFSDropTarget::_DoDrop(IDataObject *pDataObject, 500c2c66affSColin Finck DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) 501c2c66affSColin Finck { 502c2c66affSColin Finck TRACE("(%p) performing drop, effect %u\n", this, *pdwEffect); 503c2c66affSColin Finck FORMATETC fmt; 504c2c66affSColin Finck FORMATETC fmt2; 505c2c66affSColin Finck STGMEDIUM medium; 506c2c66affSColin Finck 507fd209faaSGiannis Adamopoulos InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL); 508c2c66affSColin Finck InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL); 509c2c66affSColin Finck 510c2c66affSColin Finck HRESULT hr; 511c2c66affSColin Finck bool bCopy = TRUE; 512c2c66affSColin Finck bool bLinking = FALSE; 513c2c66affSColin Finck 514c2c66affSColin Finck /* Figure out what drop operation we're doing */ 515c2c66affSColin Finck if (pdwEffect) 516c2c66affSColin Finck { 517c2c66affSColin Finck TRACE("Current drop effect flag %i\n", *pdwEffect); 518c2c66affSColin Finck if ((*pdwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE) 519c2c66affSColin Finck bCopy = FALSE; 520c2c66affSColin Finck if ((*pdwEffect & DROPEFFECT_LINK) == DROPEFFECT_LINK) 521c2c66affSColin Finck bLinking = TRUE; 522c2c66affSColin Finck } 523c2c66affSColin Finck 524c2c66affSColin Finck if (SUCCEEDED(pDataObject->QueryGetData(&fmt))) 525c2c66affSColin Finck { 526c2c66affSColin Finck hr = pDataObject->GetData(&fmt, &medium); 5276f91b6c0SJoachim Henze TRACE("CFSTR_SHELLIDLIST\n"); 528a5a30fc2SKyle Katarn if (FAILED(hr)) 529a5a30fc2SKyle Katarn { 530a5a30fc2SKyle Katarn ERR("CFSTR_SHELLIDLIST failed\n"); 531a5a30fc2SKyle Katarn } 532c2c66affSColin Finck /* lock the handle */ 533c2c66affSColin Finck LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal); 534c2c66affSColin Finck if (!lpcida) 535c2c66affSColin Finck { 536c2c66affSColin Finck ReleaseStgMedium(&medium); 537c2c66affSColin Finck return E_FAIL; 538c2c66affSColin Finck } 539c2c66affSColin Finck 540c2c66affSColin Finck /* convert the data into pidl */ 541c2c66affSColin Finck LPITEMIDLIST pidl; 542c2c66affSColin Finck LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida); 543c2c66affSColin Finck if (!apidl) 544c2c66affSColin Finck { 545c2c66affSColin Finck ReleaseStgMedium(&medium); 546c2c66affSColin Finck return E_FAIL; 547c2c66affSColin Finck } 548c2c66affSColin Finck 549c2c66affSColin Finck CComPtr<IShellFolder> psfDesktop; 550c2c66affSColin Finck CComPtr<IShellFolder> psfFrom = NULL; 551c2c66affSColin Finck 552c2c66affSColin Finck /* Grab the desktop shell folder */ 553c2c66affSColin Finck hr = SHGetDesktopFolder(&psfDesktop); 554c2c66affSColin Finck if (FAILED(hr)) 555c2c66affSColin Finck { 556c2c66affSColin Finck ERR("SHGetDesktopFolder failed\n"); 557c2c66affSColin Finck SHFree(pidl); 558c2c66affSColin Finck _ILFreeaPidl(apidl, lpcida->cidl); 559c2c66affSColin Finck ReleaseStgMedium(&medium); 560c2c66affSColin Finck return E_FAIL; 561c2c66affSColin Finck } 562c2c66affSColin Finck 563c2c66affSColin Finck /* Find source folder, this is where the clipboard data was copied from */ 564c2c66affSColin Finck if (_ILIsDesktop(pidl)) 565c2c66affSColin Finck { 566c2c66affSColin Finck /* use desktop shell folder */ 567c2c66affSColin Finck psfFrom = psfDesktop; 568c2c66affSColin Finck } 569c2c66affSColin Finck else 570c2c66affSColin Finck { 571c2c66affSColin Finck hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom)); 572c2c66affSColin Finck if (FAILED(hr)) 573c2c66affSColin Finck { 574c2c66affSColin Finck ERR("no IShellFolder\n"); 575c2c66affSColin Finck SHFree(pidl); 576c2c66affSColin Finck _ILFreeaPidl(apidl, lpcida->cidl); 577c2c66affSColin Finck ReleaseStgMedium(&medium); 578c2c66affSColin Finck return E_FAIL; 579c2c66affSColin Finck } 580c2c66affSColin Finck } 581c2c66affSColin Finck 582c2c66affSColin Finck if (bLinking) 583c2c66affSColin Finck { 584fa95a96eSWhindmar Saksit WCHAR wszNewLnk[MAX_PATH]; 585c2c66affSColin Finck 5860f5fb478SKatayama Hirofumi MZ TRACE("target path = %s\n", debugstr_w(m_sPathTarget)); 587c2c66affSColin Finck 588c2c66affSColin Finck /* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */ 589c2c66affSColin Finck for (UINT i = 0; i < lpcida->cidl; i++) 590c2c66affSColin Finck { 591cca9acfaSWhindmar Saksit SFGAOF att = SHGetAttributes(psfFrom, apidl[i], SFGAO_FOLDER | SFGAO_STREAM | SFGAO_FILESYSTEM); 592fa95a96eSWhindmar Saksit CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlFull; 593fa95a96eSWhindmar Saksit hr = SHILCombine(pidl, apidl[i], &pidlFull); 594c2c66affSColin Finck 595fa95a96eSWhindmar Saksit WCHAR targetName[MAX_PATH]; 5960f5fb478SKatayama Hirofumi MZ if (SUCCEEDED(hr)) 597cca9acfaSWhindmar Saksit { 598cca9acfaSWhindmar Saksit // If the target is a file, we use SHGDN_FORPARSING because "NeverShowExt" will hide the ".lnk" extension. 599cca9acfaSWhindmar Saksit // If the target is a virtual item, we ask for the friendly name because SHGDN_FORPARSING will return a GUID. 600cca9acfaSWhindmar Saksit BOOL UseParsing = (att & (SFGAO_FILESYSTEM | SFGAO_FOLDER)) == SFGAO_FILESYSTEM; 601cca9acfaSWhindmar Saksit DWORD ShgdnFor = UseParsing ? SHGDN_FORPARSING : SHGDN_FOREDITING; 602cca9acfaSWhindmar Saksit hr = Shell_DisplayNameOf(psfFrom, apidl[i], ShgdnFor | SHGDN_INFOLDER, targetName, _countof(targetName)); 603cca9acfaSWhindmar Saksit } 604fa95a96eSWhindmar Saksit if (FAILED_UNEXPECTEDLY(hr)) 6050f5fb478SKatayama Hirofumi MZ { 606fa95a96eSWhindmar Saksit SHELL_ErrorBox(m_hwndSite, hr); 607fa95a96eSWhindmar Saksit break; 6080f5fb478SKatayama Hirofumi MZ } 609fa95a96eSWhindmar Saksit SHELL_StripIllegalFsNameCharacters(targetName); 6100f5fb478SKatayama Hirofumi MZ 611fa95a96eSWhindmar Saksit WCHAR wszCombined[MAX_PATH + _countof(targetName)]; 612fa95a96eSWhindmar Saksit PathCombineW(wszCombined, m_sPathTarget, targetName); 6130f5fb478SKatayama Hirofumi MZ 6140f5fb478SKatayama Hirofumi MZ // Check to see if the source is a link 6150f5fb478SKatayama Hirofumi MZ BOOL fSourceIsLink = FALSE; 616*e4930be4STimo Kreuzer if (!_wcsicmp(PathFindExtensionW(targetName), L".lnk") && (att & (SFGAO_FOLDER | SFGAO_STREAM)) != SFGAO_FOLDER) 6170f5fb478SKatayama Hirofumi MZ { 6180f5fb478SKatayama Hirofumi MZ fSourceIsLink = TRUE; 6190f5fb478SKatayama Hirofumi MZ PathRemoveExtensionW(wszCombined); 6200f5fb478SKatayama Hirofumi MZ } 6210f5fb478SKatayama Hirofumi MZ 6220f5fb478SKatayama Hirofumi MZ // Create a pathname to save the new link. 623fa95a96eSWhindmar Saksit _GetUniqueFileName(wszCombined, L".lnk", wszNewLnk, TRUE); 6240f5fb478SKatayama Hirofumi MZ 625c2c66affSColin Finck CComPtr<IPersistFile> ppf; 6260f5fb478SKatayama Hirofumi MZ if (fSourceIsLink) 627c2c66affSColin Finck { 628fa95a96eSWhindmar Saksit PWSTR pwszTargetFull; 629fa95a96eSWhindmar Saksit hr = SHGetNameFromIDList(pidlFull, SIGDN_DESKTOPABSOLUTEPARSING, &pwszTargetFull); 630fa95a96eSWhindmar Saksit if (!FAILED_UNEXPECTEDLY(hr)) 631fa95a96eSWhindmar Saksit { 632fa95a96eSWhindmar Saksit hr = IShellLink_ConstructFromPath(pwszTargetFull, IID_PPV_ARG(IPersistFile, &ppf)); 633fa95a96eSWhindmar Saksit FAILED_UNEXPECTEDLY(hr); 634fa95a96eSWhindmar Saksit SHFree(pwszTargetFull); 635fa95a96eSWhindmar Saksit } 636c2c66affSColin Finck } 637c2c66affSColin Finck else 638c2c66affSColin Finck { 639c2c66affSColin Finck CComPtr<IShellLinkW> pLink; 640c2c66affSColin Finck hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink)); 641fa95a96eSWhindmar Saksit if (!FAILED_UNEXPECTEDLY(hr)) 642fa95a96eSWhindmar Saksit { 643fa95a96eSWhindmar Saksit hr = pLink->SetIDList(pidlFull); 644fa95a96eSWhindmar Saksit if (!FAILED_UNEXPECTEDLY(hr)) 645c2c66affSColin Finck hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf)); 646fa95a96eSWhindmar Saksit 647fa95a96eSWhindmar Saksit PWSTR pwszPath, pSep; 648fa95a96eSWhindmar Saksit if ((att & SFGAO_FILESYSTEM) && SUCCEEDED(SHGetNameFromIDList(pidlFull, SIGDN_FILESYSPATH, &pwszPath))) 649fa95a96eSWhindmar Saksit { 650fa95a96eSWhindmar Saksit if ((pSep = PathFindFileNameW(pwszPath)) > pwszPath) 651fa95a96eSWhindmar Saksit { 652fa95a96eSWhindmar Saksit pSep[-1] = UNICODE_NULL; 653fa95a96eSWhindmar Saksit pLink->SetWorkingDirectory(pwszPath); 654fa95a96eSWhindmar Saksit } 655fa95a96eSWhindmar Saksit SHFree(pwszPath); 656fa95a96eSWhindmar Saksit } 657fa95a96eSWhindmar Saksit } 658fa95a96eSWhindmar Saksit } 659fa95a96eSWhindmar Saksit if (SUCCEEDED(hr)) 660fa95a96eSWhindmar Saksit hr = ppf->Save(wszNewLnk, !fSourceIsLink); 6610f5fb478SKatayama Hirofumi MZ if (FAILED_UNEXPECTEDLY(hr)) 662fa95a96eSWhindmar Saksit { 663fa95a96eSWhindmar Saksit SHELL_ErrorBox(m_hwndSite, hr); 6640f5fb478SKatayama Hirofumi MZ break; 6650f5fb478SKatayama Hirofumi MZ } 666fa95a96eSWhindmar Saksit SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszNewLnk, NULL); 667c2c66affSColin Finck } 668c2c66affSColin Finck } 669c2c66affSColin Finck else 670c2c66affSColin Finck { 671fd209faaSGiannis Adamopoulos hr = _CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy); 672c2c66affSColin Finck } 673c2c66affSColin Finck 674c2c66affSColin Finck SHFree(pidl); 675c2c66affSColin Finck _ILFreeaPidl(apidl, lpcida->cidl); 676c2c66affSColin Finck ReleaseStgMedium(&medium); 677c2c66affSColin Finck } 678c2c66affSColin Finck else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2))) 679c2c66affSColin Finck { 680c2c66affSColin Finck FORMATETC fmt2; 681c2c66affSColin Finck InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL); 682c2c66affSColin Finck if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/) 683c2c66affSColin Finck { 684c2c66affSColin Finck WCHAR wszTargetPath[MAX_PATH + 1]; 685c2c66affSColin Finck LPWSTR pszSrcList; 686c2c66affSColin Finck 687fd209faaSGiannis Adamopoulos wcscpy(wszTargetPath, m_sPathTarget); 688c2c66affSColin Finck //Double NULL terminate. 689c2c66affSColin Finck wszTargetPath[wcslen(wszTargetPath) + 1] = '\0'; 690c2c66affSColin Finck 691c2c66affSColin Finck LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal); 692c2c66affSColin Finck if (!lpdf) 693c2c66affSColin Finck { 694c2c66affSColin Finck ERR("Error locking global\n"); 695c2c66affSColin Finck return E_FAIL; 696c2c66affSColin Finck } 697c2c66affSColin Finck pszSrcList = (LPWSTR) (((byte*) lpdf) + lpdf->pFiles); 698c2c66affSColin Finck ERR("Source file (just the first) = %s, target path = %s, bCopy: %d\n", debugstr_w(pszSrcList), debugstr_w(wszTargetPath), bCopy); 699c2c66affSColin Finck 700c2c66affSColin Finck SHFILEOPSTRUCTW op; 701c2c66affSColin Finck ZeroMemory(&op, sizeof(op)); 702c2c66affSColin Finck op.pFrom = pszSrcList; 703c2c66affSColin Finck op.pTo = wszTargetPath; 7046d91269eSGiannis Adamopoulos op.hwnd = m_hwndSite; 705c2c66affSColin Finck op.wFunc = bCopy ? FO_COPY : FO_MOVE; 706c2c66affSColin Finck op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR; 707a5a30fc2SKyle Katarn int res = SHFileOperationW(&op); 708a5a30fc2SKyle Katarn if (res) 709a5a30fc2SKyle Katarn { 710a5a30fc2SKyle Katarn ERR("SHFileOperationW failed with 0x%x\n", res); 711a5a30fc2SKyle Katarn hr = E_FAIL; 712a5a30fc2SKyle Katarn } 713a5a30fc2SKyle Katarn 714c2c66affSColin Finck return hr; 715c2c66affSColin Finck } 716c2c66affSColin Finck ERR("Error calling GetData\n"); 717c2c66affSColin Finck hr = E_FAIL; 718c2c66affSColin Finck } 719c2c66affSColin Finck else 720c2c66affSColin Finck { 7216f91b6c0SJoachim Henze ERR("No viable drop format\n"); 722c2c66affSColin Finck hr = E_FAIL; 723c2c66affSColin Finck } 724c2c66affSColin Finck return hr; 725c2c66affSColin Finck } 726c2c66affSColin Finck 727c2c66affSColin Finck DWORD WINAPI CFSDropTarget::_DoDropThreadProc(LPVOID lpParameter) 728c2c66affSColin Finck { 729c2c66affSColin Finck CoInitialize(NULL); 730c2c66affSColin Finck _DoDropData *data = static_cast<_DoDropData*>(lpParameter); 731c2c66affSColin Finck CComPtr<IDataObject> pDataObject; 732c2c66affSColin Finck HRESULT hr = CoGetInterfaceAndReleaseStream (data->pStream, IID_PPV_ARG(IDataObject, &pDataObject)); 733c2c66affSColin Finck 734c2c66affSColin Finck if (SUCCEEDED(hr)) 735c2c66affSColin Finck { 736c2c66affSColin Finck CComPtr<IAsyncOperation> pAsyncOperation; 737c2c66affSColin Finck hr = data->This->_DoDrop(pDataObject, data->dwKeyState, data->pt, &data->pdwEffect); 738c2c66affSColin Finck if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation)))) 739c2c66affSColin Finck { 740c2c66affSColin Finck pAsyncOperation->EndOperation(hr, NULL, data->pdwEffect); 741c2c66affSColin Finck } 742c2c66affSColin Finck } 743c2c66affSColin Finck //Release the CFSFolder and data object holds in the copying thread. 744c2c66affSColin Finck data->This->Release(); 745c2c66affSColin Finck //Release the parameter from the heap. 746c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, data); 747c2c66affSColin Finck CoUninitialize(); 748c2c66affSColin Finck return 0; 749c2c66affSColin Finck } 750c2c66affSColin Finck 751c2c66affSColin Finck HRESULT CFSDropTarget_CreateInstance(LPWSTR sPathTarget, REFIID riid, LPVOID * ppvOut) 752c2c66affSColin Finck { 753c2c66affSColin Finck return ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut); 754c2c66affSColin Finck } 755