ReactOS 0.4.17-dev-806-gffa4164
CFSDropTarget.cpp
Go to the documentation of this file.
1
2/*
3 * file system folder drop target
4 *
5 * Copyright 1997 Marcus Meissner
6 * Copyright 1998, 1999, 2002 Juergen Schmied
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23#include <precomp.h>
24
26
27#define D_NONE DROPEFFECT_NONE
28#define D_COPY DROPEFFECT_COPY
29#define D_MOVE DROPEFFECT_MOVE
30#define D_LINK DROPEFFECT_LINK
31
33{
34 for (LPWSTR src = Buf, dst = src;;)
35 {
36 *dst = *src;
37 if (!*dst)
38 break;
40 src = CharNextW(src);
41 else
42 ++src, ++dst;
43 }
44}
45
46static bool PathIsSameDrive(LPCWSTR Path1, LPCWSTR Path2)
47{
48 int d1 = PathGetDriveNumberW(Path1), d2 = PathGetDriveNumberW(Path2);
49 return d1 == d2 && d2 >= 0;
50}
51
53{
55}
56
57static HRESULT
59{
60 DWORD att = *pdwEffect & (SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK); // DROPEFFECT maps perfectly to these SFGAO bits
61 HRESULT hr = SHGetAttributesFromDataObject(pDataObject, att, &att, NULL);
62 if (FAILED(hr))
63 return S_FALSE;
64 *pdwEffect &= ~(SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK) | att;
65 return hr;
66}
67
69{
70 // FIXME: When the source is on a different volume than the target, change default from move to copy
71}
72
74
76{
78 g_cf_FileOpFlags = RegisterClipboardFormatW(L"FileOpFlags"); // github.com/dotnet/winforms/issues/5884?timeline_page=1
79 return DataObj_GetDWORD(pDO, g_cf_FileOpFlags, fDefault);
80}
81
82/****************************************************************************
83 * CFSDropTarget::_CopyItems
84 *
85 * copies or moves items to this folder
86 */
88 UINT cidl, LPCITEMIDLIST * apidl, BOOL bCopy)
89{
91 WCHAR wszDstPath[MAX_PATH + 1] = {0};
92 PWCHAR pwszSrcPathsList = (PWCHAR) HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) * cidl + 1);
93 if (!pwszSrcPathsList)
94 return E_OUTOFMEMORY;
95
96 PWCHAR pwszListPos = pwszSrcPathsList;
97 STRRET strretFrom;
99 BOOL bRenameOnCollision = FALSE;
100
101 /* Build a double null terminated list of C strings from source paths */
102 for (UINT i = 0; i < cidl; i++)
103 {
104 ret = pSFFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strretFrom);
105 if (FAILED(ret))
106 goto cleanup;
107
108 ret = StrRetToBufW(&strretFrom, NULL, pwszListPos, MAX_PATH);
109 if (FAILED(ret))
110 goto cleanup;
111
112 pwszListPos += lstrlenW(pwszListPos) + 1;
113 }
114 /* Append the final null. */
115 *pwszListPos = L'\0';
116
117 /* Build a double null terminated target (this path) */
119 if (FAILED(ret))
120 goto cleanup;
121
122 wszDstPath[lstrlenW(wszDstPath) + 1] = UNICODE_NULL;
123
124 /* Set bRenameOnCollision to TRUE if necesssary */
125 if (bCopy)
126 {
127 WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH];
128 GetFullPathNameW(pwszSrcPathsList, _countof(szPath1), szPath1, NULL);
129 GetFullPathNameW(wszDstPath, _countof(szPath2), szPath2, NULL);
130 PathRemoveFileSpecW(szPath1);
131 if (_wcsicmp(szPath1, szPath2) == 0)
132 bRenameOnCollision = TRUE;
133 }
134
135 ZeroMemory(&fop, sizeof(fop));
136 fop.hwnd = m_hwndSite;
137 fop.wFunc = bCopy ? FO_COPY : FO_MOVE;
138 fop.pFrom = pwszSrcPathsList;
139 fop.pTo = wszDstPath;
140 fop.fFlags = GetDefaultFileOpFlags(pDO);
141 if (bRenameOnCollision)
143
144 ret = S_OK;
145
146 if (SHFileOperationW(&fop))
147 {
148 ERR("SHFileOperationW failed\n");
149 ret = E_FAIL;
150 }
151
152cleanup:
153 HeapFree(GetProcessHeap(), 0, pwszSrcPathsList);
154 return ret;
155}
156
158 m_cfShellIDList(0),
159 m_fAcceptFmt(FALSE),
160 m_sPathTarget(NULL),
161 m_hwndSite(NULL),
162 m_grfKeyState(0),
163 m_AllowedEffects(0)
164{
165}
166
168{
169 if (!PathTarget)
170 return E_UNEXPECTED;
171
173 if (!m_cfShellIDList)
174 return E_FAIL;
175
176 return SHStrDupW(PathTarget, &m_sPathTarget);
177}
178
180{
182}
183
184BOOL
185CFSDropTarget::_GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
186{
187 WCHAR wszLink[40];
188
189 if (!bShortcut)
190 {
191 if (!LoadStringW(shell32_hInstance, IDS_LNK_FILE, wszLink, _countof(wszLink)))
192 wszLink[0] = L'\0';
193 }
194
195 if (!bShortcut)
196 _swprintf(pwszTarget, L"%s%s%s", wszLink, pwszBasePath, pwszExt);
197 else
198 _swprintf(pwszTarget, L"%s%s", pwszBasePath, pwszExt);
199
200 for (UINT i = 2; PathFileExistsW(pwszTarget); ++i)
201 {
202 if (!bShortcut)
203 _swprintf(pwszTarget, L"%s%s (%u)%s", wszLink, pwszBasePath, i, pwszExt);
204 else
205 _swprintf(pwszTarget, L"%s (%u)%s", pwszBasePath, i, pwszExt);
206 }
207
208 return TRUE;
209}
210
211/****************************************************************************
212 * IDropTarget implementation
213 */
215{
216 /* TODO Windows does different drop effects if dragging across drives.
217 i.e., it will copy instead of move if the directories are on different disks. */
219
220 DWORD dwEffect = m_dwDefaultEffect;
221
222 *pdwEffect = DROPEFFECT_NONE;
223
224 if (m_fAcceptFmt) { /* Does our interpretation of the keystate ... */
225 *pdwEffect = KeyStateToDropEffect(dwKeyState);
226
227 // Transform disallowed move to a copy
228 if ((*pdwEffect & D_MOVE) && (m_AllowedEffects & (D_MOVE | D_COPY)) == D_COPY)
229 *pdwEffect = D_COPY;
230
231 *pdwEffect &= m_AllowedEffects;
232
233 if (*pdwEffect == DROPEFFECT_NONE)
234 *pdwEffect = dwEffect;
235
236 /* ... matches the desired effect ? */
237 if (dwEffect & *pdwEffect) {
238 return TRUE;
239 }
240 }
241 return FALSE;
242}
243
245{
246 /* We shouldn't use the site window here because the menu should work even when we don't have a site */
248 pt.x, pt.y, 1, 1, NULL, NULL, NULL, NULL);
249
250 SetForegroundWindow(hwndDummy); // Required for aborting by pressing Esc when dragging from Explorer to desktop
252 pt.x, pt.y, 0, hwndDummy, NULL);
253 DestroyWindow(hwndDummy);
254 return uCommand;
255}
256
257HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects)
258{
260 if (!hmenu)
261 return E_OUTOFMEMORY;
263
264 SHELL_LimitDropEffectToItemAttributes(pDataObject, &dwAvailableEffects);
265 if ((dwAvailableEffects & DROPEFFECT_COPY) == 0)
267 if ((dwAvailableEffects & DROPEFFECT_MOVE) == 0)
269 if ((dwAvailableEffects & DROPEFFECT_LINK) == 0 && (dwAvailableEffects & (DROPEFFECT_COPY | DROPEFFECT_MOVE)))
271
273 if (*pdwEffect & dwAvailableEffects & DROPEFFECT_COPY)
275 else if (*pdwEffect & dwAvailableEffects & DROPEFFECT_MOVE)
277 else if (dwAvailableEffects & DROPEFFECT_LINK)
279
281 HDCIA hDCIA = DCIA_Create();
282 HDCMA hDCMA = DCMA_Create();
283 CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlFolder(SHELL32_CreateSimpleIDListFromPath(m_sPathTarget, FILE_ATTRIBUTE_DIRECTORY));
284 if (hDCMA && hDCIA && pidlFolder)
285 {
286 AddPidlClassKeysToArray(pidlFolder, keys, keys);
287 for (UINT i = 0; i < keys; ++i)
288 DCIA_AddShellExSubkey(hDCIA, keys[i], L"DragDropHandlers");
289
291 DCMA_InsertMenuItems(hDCMA, hDCIA, pidlFolder, pDataObject, keys, keys, &qcmi, 0, m_site);
292 }
293
294 UINT uCommand = TrackPopupMenu(hpopupmenu, pt);
295
296 HRESULT hr = S_FALSE; // S_FALSE means we did not handle the command
298 IDM_LINKHERE < DROPIDM_EXTFIRST && DROPIDM_EXTFIRST > 0);
299 if (uCommand >= DROPIDM_EXTFIRST && uCommand <= DROPIDM_EXTLAST)
300 {
301 CMINVOKECOMMANDINFO ici = { sizeof(ici), 0, m_hwndSite, MAKEINTRESOURCEA(uCommand - DROPIDM_EXTFIRST) };
302 ici.nShow = SW_SHOW;
304 ici.fMask |= CMIC_MASK_SHIFT_DOWN;
306 ici.fMask |= CMIC_MASK_CONTROL_DOWN;
307 DCMA_InvokeCommand(hDCMA, &ici);
308 hr = S_OK;
309 *pdwEffect = DROPEFFECT_NONE;
310 }
311 else if (uCommand == 0)
312 {
313 hr = S_OK;
314 *pdwEffect = DROPEFFECT_NONE;
315 }
316 else if (uCommand == IDM_COPYHERE)
317 *pdwEffect = DROPEFFECT_COPY;
318 else if (uCommand == IDM_MOVEHERE)
319 *pdwEffect = DROPEFFECT_MOVE;
320 else if (uCommand == IDM_LINKHERE)
321 *pdwEffect = DROPEFFECT_LINK;
322 else
324
325 DCMA_Destroy(hDCMA);
326 DCIA_Destroy(hDCIA);
328 return hr;
329}
330
332{
333 CComPtr<IFolderView> pfv;
334 POINT ptDrag;
337 return hr;
338
339 hr = psfv->GetDragPoint(&ptDrag);
341 return hr;
342
343 PIDLIST_ABSOLUTE pidlFolder;
344 PUITEMID_CHILD *apidl;
345 UINT cidl;
346 hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
348 return hr;
349
350 CComHeapPtr<POINT> apt;
351 if (!apt.Allocate(cidl))
352 {
353 SHFree(pidlFolder);
354 _ILFreeaPidl(apidl, cidl);
355 return E_OUTOFMEMORY;
356 }
357
358 for (UINT i = 0; i<cidl; i++)
359 {
360 pfv->GetItemPosition(apidl[i], &apt[i]);
361 apt[i].x += pt.x - ptDrag.x;
362 apt[i].y += pt.y - ptDrag.y;
363 }
364
365 pfv->SelectAndPositionItems(cidl, apidl, apt, SVSI_SELECT);
366
367 SHFree(pidlFolder);
368 _ILFreeaPidl(apidl, cidl);
369 return S_OK;
370}
371
373 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
374{
375 TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
376
377 const BOOL bAnyKeyMod = dwKeyState & (MK_SHIFT | MK_CONTROL);
378 m_AllowedEffects = *pdwEffect;
379
380 if (*pdwEffect == DROPEFFECT_NONE)
381 return S_OK;
382
383 FORMATETC fmt;
384 FORMATETC fmt2;
386
387 InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
388 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
389
390 if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
392 else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
394
395 m_grfKeyState = dwKeyState;
396
397 SHELL_LimitDropEffectToItemAttributes(pDataObject, pdwEffect);
398 m_AllowedEffects = *pdwEffect;
400 switch (*pdwEffect & (D_COPY | D_MOVE | D_LINK))
401 {
402 case D_COPY | D_MOVE:
403 if (dwKeyState & MK_CONTROL)
405 else
407 break;
408 case D_COPY | D_MOVE | D_LINK:
409 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
411 else if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == MK_CONTROL)
413 else
415 break;
416 case D_COPY | D_LINK:
417 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
419 else
421 break;
422 case D_MOVE | D_LINK:
423 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
425 else
427 break;
428 }
429
430 STGMEDIUM medium;
431 if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)))
432 {
433 WCHAR wstrFirstFile[MAX_PATH];
434 if (DragQueryFileW((HDROP)medium.hGlobal, 0, wstrFirstFile, _countof(wstrFirstFile)))
435 {
436 if (!PathIsSameDrive(wstrFirstFile, m_sPathTarget) && m_dwDefaultEffect != D_LINK)
437 {
439 }
440
441 if (!bAnyKeyMod && PathIsDriveRoot(wstrFirstFile) && (m_AllowedEffects & DROPEFFECT_LINK))
442 {
443 m_dwDefaultEffect = DROPEFFECT_LINK; // Don't copy a drive by default
444 }
445 }
446 ReleaseStgMedium(&medium);
447 }
448
449 if (!m_fAcceptFmt)
451 else
452 *pdwEffect = m_dwDefaultEffect;
453 *pdwEffect &= m_AllowedEffects;
454
455 return S_OK;
456}
457
459 DWORD *pdwEffect)
460{
461 TRACE("(%p)\n", this);
462
463 if (!pdwEffect)
464 return E_INVALIDARG;
465
466 m_grfKeyState = dwKeyState;
467
468 _QueryDrop(dwKeyState, pdwEffect);
469
470 return S_OK;
471}
472
474{
475 TRACE("(%p)\n", this);
476
478
479 return S_OK;
480}
481
483 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
484{
485 TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect);
486
487 if (!pdwEffect)
488 return E_INVALIDARG;
489
491
492 DWORD dwAvailableEffects = *pdwEffect;
493
494 _QueryDrop(dwKeyState, pdwEffect);
495
496 TRACE("pdwEffect: 0x%x, m_dwDefaultEffect: 0x%x, dwAvailableEffects: 0x%x\n", *pdwEffect, m_dwDefaultEffect, dwAvailableEffects);
497
499 {
500 HRESULT hr = _GetEffectFromMenu(pDataObject, pt, pdwEffect, dwAvailableEffects);
501 if (FAILED_UNEXPECTEDLY(hr) || hr == S_OK)
502 return hr;
503 }
504
505 if (*pdwEffect == DROPEFFECT_MOVE && m_site)
506 {
507 CComPtr<IShellFolderView> psfv;
508 HRESULT hr = IUnknown_QueryService(m_site, SID_SFolderView, IID_PPV_ARG(IShellFolderView, &psfv));
509 if (SUCCEEDED(hr) && psfv->IsDropOnSource(this) == S_OK)
510 {
511 _RepositionItems(psfv, pDataObject, pt);
512 return S_OK;
513 }
514 }
515
516 BOOL fIsOpAsync = FALSE;
517 CComPtr<IAsyncOperation> pAsyncOperation;
518
519 if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
520 {
521 if (SUCCEEDED(pAsyncOperation->GetAsyncMode(&fIsOpAsync)) && fIsOpAsync)
522 {
523 _DoDropData *data = static_cast<_DoDropData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(_DoDropData)));
524 data->This = this;
525 // Need to maintain this class in case the window is closed or the class exists temporarily (when dropping onto a folder).
526 pDataObject->AddRef();
527 pAsyncOperation->StartOperation(NULL);
529 this->AddRef();
530 data->dwKeyState = dwKeyState;
531 data->pt = pt;
532 // Need to dereference as pdweffect gets freed.
533 data->pdwEffect = *pdwEffect;
535 return S_OK;
536 }
537 }
538 return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect);
539}
540
542WINAPI
544{
545 m_site = pUnkSite;
546 return S_OK;
547}
548
550WINAPI
552{
553 if (!m_site)
554 return E_FAIL;
555
556 return m_site->QueryInterface(riid, ppvSite);
557}
558
560 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
561{
562 TRACE("(%p) performing drop, effect %u\n", this, *pdwEffect);
563 FORMATETC fmt;
564 FORMATETC fmt2;
565 STGMEDIUM medium;
566
567 InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
568 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
569
570 HRESULT hr;
571 bool bCopy = TRUE;
572 bool bLinking = FALSE;
573
574 /* Figure out what drop operation we're doing */
575 if (pdwEffect)
576 {
577 TRACE("Current drop effect flag %i\n", *pdwEffect);
578 if ((*pdwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
579 bCopy = FALSE;
580 if ((*pdwEffect & DROPEFFECT_LINK) == DROPEFFECT_LINK)
581 bLinking = TRUE;
582 }
583
584 if (SUCCEEDED(hr = pDataObject->QueryGetData(&fmt)))
585 {
586 hr = pDataObject->GetData(&fmt, &medium);
587 TRACE("CFSTR_SHELLIDLIST\n");
588 if (FAILED(hr))
589 {
590 ERR("CFSTR_SHELLIDLIST failed\n");
591 }
592 /* lock the handle */
593 LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
594 if (!lpcida)
595 {
596 ReleaseStgMedium(&medium);
597 return E_FAIL;
598 }
599
600 /* convert the data into pidl */
601 LPITEMIDLIST pidl;
602 LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
603 if (!apidl)
604 {
605 ReleaseStgMedium(&medium);
606 return E_FAIL;
607 }
608
609 CComPtr<IShellFolder> psfDesktop;
610 CComPtr<IShellFolder> psfFrom = NULL;
611
612 /* Grab the desktop shell folder */
613 hr = SHGetDesktopFolder(&psfDesktop);
614 if (FAILED(hr))
615 {
616 ERR("SHGetDesktopFolder failed\n");
617 SHFree(pidl);
618 _ILFreeaPidl(apidl, lpcida->cidl);
619 ReleaseStgMedium(&medium);
620 return E_FAIL;
621 }
622
623 /* Find source folder, this is where the clipboard data was copied from */
624 if (_ILIsDesktop(pidl))
625 {
626 /* use desktop shell folder */
627 psfFrom = psfDesktop;
628 }
629 else
630 {
631 hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom));
632 if (FAILED(hr))
633 {
634 ERR("no IShellFolder\n");
635 SHFree(pidl);
636 _ILFreeaPidl(apidl, lpcida->cidl);
637 ReleaseStgMedium(&medium);
638 return E_FAIL;
639 }
640 }
641
642 if (bLinking)
643 {
644 WCHAR wszNewLnk[MAX_PATH];
645
646 TRACE("target path = %s\n", debugstr_w(m_sPathTarget));
647
648 /* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */
649 for (UINT i = 0; i < lpcida->cidl; i++)
650 {
651 SFGAOF att = SHGetAttributes(psfFrom, apidl[i], SFGAO_FOLDER | SFGAO_STREAM | SFGAO_FILESYSTEM);
652 CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlFull;
653 hr = SHILCombine(pidl, apidl[i], &pidlFull);
654
655 WCHAR targetName[MAX_PATH];
656 if (SUCCEEDED(hr))
657 {
658 // If the target is a file, we use SHGDN_FORPARSING because "NeverShowExt" will hide the ".lnk" extension.
659 // If the target is a virtual item, we ask for the friendly name because SHGDN_FORPARSING will return a GUID.
660 BOOL UseParsing = (att & (SFGAO_FILESYSTEM | SFGAO_FOLDER)) == SFGAO_FILESYSTEM;
661 DWORD ShgdnFor = UseParsing ? SHGDN_FORPARSING : SHGDN_FOREDITING;
662 hr = DisplayNameOfW(psfFrom, apidl[i], ShgdnFor | SHGDN_INFOLDER, targetName, _countof(targetName));
663 }
665 {
667 break;
668 }
670
671 WCHAR wszCombined[MAX_PATH + _countof(targetName)];
672 PathCombineW(wszCombined, m_sPathTarget, targetName);
673
674 // Check to see if the source is a link
675 BOOL fSourceIsLink = FALSE;
676 if (!_wcsicmp(PathFindExtensionW(targetName), L".lnk") && (att & (SFGAO_FOLDER | SFGAO_STREAM)) != SFGAO_FOLDER)
677 {
678 fSourceIsLink = TRUE;
679 PathRemoveExtensionW(wszCombined);
680 }
681
682 // Create a pathname to save the new link.
683 _GetUniqueFileName(wszCombined, L".lnk", wszNewLnk, TRUE);
684
685 CComPtr<IPersistFile> ppf;
686 if (fSourceIsLink)
687 {
688 PWSTR pwszTargetFull;
689 hr = SHGetNameFromIDList(pidlFull, SIGDN_DESKTOPABSOLUTEPARSING, &pwszTargetFull);
691 {
694 SHFree(pwszTargetFull);
695 }
696 }
697 else
698 {
699 CComPtr<IShellLinkW> pLink;
700 hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink));
702 {
703 hr = pLink->SetIDList(pidlFull);
705 hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
706
707 PWSTR pwszPath, pSep;
708 if ((att & SFGAO_FILESYSTEM) && SUCCEEDED(SHGetNameFromIDList(pidlFull, SIGDN_FILESYSPATH, &pwszPath)))
709 {
710 if ((pSep = PathFindFileNameW(pwszPath)) > pwszPath)
711 {
712 pSep[-1] = UNICODE_NULL;
713 pLink->SetWorkingDirectory(pwszPath);
714 }
715 SHFree(pwszPath);
716 }
717 }
718 }
719 if (SUCCEEDED(hr))
720 hr = ppf->Save(wszNewLnk, !fSourceIsLink);
722 {
724 break;
725 }
727 }
728 }
729 else
730 {
731 hr = _CopyItems(pDataObject, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy);
732 }
733
734 SHFree(pidl);
735 _ILFreeaPidl(apidl, lpcida->cidl);
736 ReleaseStgMedium(&medium);
737 }
738 else if (SUCCEEDED(hr = pDataObject->QueryGetData(&fmt2)))
739 {
740 FORMATETC fmt2;
741 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
742 if (SUCCEEDED(hr = pDataObject->GetData(&fmt2, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/)
743 {
744 WCHAR wszTargetPath[MAX_PATH + 1];
745 LPWSTR pszSrcList;
746
747 wcscpy(wszTargetPath, m_sPathTarget);
748 //Double NULL terminate.
749 wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
750
751 LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal);
752 if (!lpdf)
753 {
754 ERR("Error locking global\n");
755 return E_FAIL;
756 }
757 pszSrcList = (LPWSTR) (((byte*) lpdf) + lpdf->pFiles);
758 ERR("Source file (just the first) = %s, target path = %s, bCopy: %d\n", debugstr_w(pszSrcList), debugstr_w(wszTargetPath), bCopy);
759
761 ZeroMemory(&op, sizeof(op));
762 op.pFrom = pszSrcList;
763 op.pTo = wszTargetPath;
764 op.hwnd = m_hwndSite;
765 op.wFunc = bCopy ? FO_COPY : FO_MOVE;
766 op.fFlags = GetDefaultFileOpFlags(pDataObject);
767 int res = SHFileOperationW(&op);
768 if (res)
769 {
770 ERR("SHFileOperationW failed with 0x%x\n", res);
771 hr = E_FAIL;
772 }
773
774 return hr;
775 }
776 ERR("Error calling GetData\n");
777 hr = E_FAIL;
778 }
779 else
780 {
781 ERR("No viable drop format\n");
782 hr = E_FAIL;
783 }
784 return hr;
785}
786
788{
789 _DoDropData *data = static_cast<_DoDropData*>(lpParameter);
790 CComPtr<IDataObject> pDataObject;
792
793 if (SUCCEEDED(hr))
794 {
795 CComPtr<IAsyncOperation> pAsyncOperation;
796 hr = data->This->_DoDrop(pDataObject, data->dwKeyState, data->pt, &data->pdwEffect);
797 if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
798 {
799 pAsyncOperation->EndOperation(hr, NULL, data->pdwEffect);
800 }
801 }
802 //Release the CFSFolder and data object holds in the copying thread.
803 data->This->Release();
804 //Release the parameter from the heap.
806 return 0;
807}
808
810{
811 return ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut);
812}
BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
Definition: CBandSite.h:24
UINT DCMA_InsertMenuItems(_In_ HDCMA hDCMA, _In_ HDCIA hDCIA, _In_opt_ LPCITEMIDLIST pidlFolder, _In_opt_ IDataObject *pDO, _In_opt_ HKEY *pKeys, _In_opt_ UINT nKeys, _In_ QCMINFO *pQCMI, _In_opt_ UINT fCmf, _In_opt_ IUnknown *pUnkSite)
void DCMA_Destroy(HDCMA hDCMA)
HRESULT DCMA_InvokeCommand(HDCMA hDCMA, CMINVOKECOMMANDINFO *pICI)
HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf)
static bool PathIsDriveRoot(LPCWSTR Path)
HRESULT CFSDropTarget_CreateInstance(LPWSTR sPathTarget, REFIID riid, LPVOID *ppvOut)
#define D_COPY
static void SHELL_StripIllegalFsNameCharacters(_Inout_ LPWSTR Buf)
#define D_MOVE
UINT g_cf_FileOpFlags
static HRESULT SHELL_LimitDropEffectToItemAttributes(_In_ IDataObject *pDataObject, _Inout_ PDWORD pdwEffect)
static void GetDefaultCopyMoveEffect()
static DWORD GetDefaultFileOpFlags(IDataObject *pDO, DWORD fDefault=FOF_ALLOWUNDO|FOF_NOCONFIRMMKDIR)
#define D_LINK
static bool PathIsSameDrive(LPCWSTR Path1, LPCWSTR Path2)
#define DROPIDM_EXTFIRST
Definition: CFSDropTarget.h:26
#define DROPIDM_EXTLAST
Definition: CFSDropTarget.h:27
static HRESULT WINAPI DisplayNameOfW(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwFlags, _Out_ LPWSTR pszBuf, _In_ UINT cchBuf)
Definition: CFindFolder.cpp:15
#define IID_PPV_ARG(Itype, ppType)
PRTL_UNICODE_STRING_BUFFER Path
#define shell32_hInstance
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define CF_HDROP
Definition: constants.h:410
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define ERR(fmt,...)
Definition: precomp.h:57
EXTERN_C void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
DWORD m_dwDefaultEffect
Definition: CFSDropTarget.h:40
STDMETHOD() Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) override
CComPtr< IUnknown > m_site
Definition: CFSDropTarget.h:42
HRESULT _CopyItems(IDataObject *pDO, IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy)
STDMETHOD() DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) override
DWORD m_AllowedEffects
Definition: CFSDropTarget.h:41
HRESULT Initialize(LPWSTR PathTarget)
STDMETHOD() GetSite(REFIID riid, void **ppvSite) override
LPWSTR m_sPathTarget
Definition: CFSDropTarget.h:37
static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter)
BOOL _QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
UINT m_cfShellIDList
Definition: CFSDropTarget.h:35
static UINT TrackPopupMenu(HMENU hMenu, const POINTL &pt)
HRESULT _GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects)
STDMETHOD() DragLeave() override
HRESULT _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
BOOL _GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
DWORD m_grfKeyState
Definition: CFSDropTarget.h:39
STDMETHOD() DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) override
STDMETHOD() SetSite(IUnknown *pUnkSite) override
HRESULT _RepositionItems(IShellFolderView *psfv, IDataObject *pDataObject, POINTL pt)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
HRESULT WINAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, IUnknown *unk, IStream **stream)
Definition: marshal.c:154
HRESULT WINAPI CoGetInterfaceAndReleaseStream(IStream *stream, REFIID riid, void **obj)
Definition: marshal.c:139
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrlenW
Definition: compat.h:750
static void cleanup(void)
Definition: main.c:1335
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
const UINT * keys
Definition: locale.c:418
void WINAPI PathRemoveExtensionW(WCHAR *path)
Definition: path.c:1922
int WINAPI PathGetDriveNumberW(const WCHAR *path)
Definition: path.c:1786
WCHAR *WINAPI PathFindFileNameW(const WCHAR *path)
Definition: path.c:1677
BOOL WINAPI PathRemoveFileSpecW(WCHAR *path)
Definition: path.c:1121
LPWSTR WINAPI PathFindExtensionW(const WCHAR *path)
Definition: path.c:1250
BOOL WINAPI PathFileExistsW(const WCHAR *path)
Definition: path.c:2583
BOOL WINAPI PathIsRootW(const WCHAR *path)
Definition: path.c:1077
LPWSTR WINAPI CharNextW(const WCHAR *x)
Definition: string.c:1165
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:164
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2014
HRESULT WINAPI IUnknown_QueryService(IUnknown *obj, REFGUID sid, REFIID iid, void **out)
Definition: main.c:181
HRESULT WINAPI SHStrDupW(const WCHAR *src, WCHAR **dest)
Definition: main.c:1692
BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE thread_proc, void *data, DWORD flags, LPTHREAD_START_ROUTINE callback)
Definition: main.c:1628
DWORD DataObj_GetDWORD(IDataObject *pdtobj, UINT cf, DWORD dwDefault)
DWORD SHGetAttributes(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwAttributes)
Definition: utils.cpp:496
#define DCMA_Create()
Definition: precomp.h:195
void DCIA_AddShellExSubkey(HDCIA hDCIA, HKEY hProgId, PCWSTR pszSubkey)
Definition: utils.cpp:1896
#define DCIA_Destroy(hDCIA)
Definition: utils.h:125
#define DCIA_Create()
Definition: utils.h:124
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:370
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:666
HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
Definition: ordinal.c:988
HRESULT WINAPI StrRetToBufW(LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, UINT len)
Definition: string.c:248
#define FAILED_UNEXPECTEDLY
Definition: utils.cpp:33
#define pt(x, y)
Definition: drawing.c:79
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
static IShellFolder IShellItem **static IBindCtx LPITEMIDLIST SFGAOF
Definition: ebrowser.c:83
#define InitFormatEtc(fe, cf, med)
Definition: editor.h:32
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int UINT
Definition: sysinfo.c:13
REFIID riid
Definition: atlbase.h:39
HRESULT GetData([in, unique] FORMATETC *pformatetcIn, [out] STGMEDIUM *pmedium)
HRESULT QueryGetData([in, unique] FORMATETC *pformatetc)
const DWORD DROPEFFECT_NONE
Definition: oleidl.idl:929
const DWORD DROPEFFECT_LINK
Definition: oleidl.idl:932
const DWORD DROPEFFECT_COPY
Definition: oleidl.idl:930
const DWORD DROPEFFECT_MOVE
Definition: oleidl.idl:931
HRESULT GetDisplayNameOf([in] PCUITEMID_CHILD pidl, [in] SHGDNF uFlags, [out] STRRET *lpName)
ULONG AddRef()
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
ULONG Release()
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define C_ASSERT(e)
Definition: intsafe.h:73
static ERESOURCE GlobalLock
Definition: sys_arch.c:8
#define debugstr_w
Definition: kernel32.h:32
#define ZeroMemory
Definition: minwinbase.h:31
#define _swprintf(buf, format,...)
Definition: sprintf.c:56
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
static HMENU hpopupmenu
Definition: msg.c:19998
static HMENU hmenu
Definition: win.c:78
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define UNICODE_NULL
const GUID IID_IDataObject
#define PathCombineW
Definition: pathcch.h:318
short WCHAR
Definition: pedump.c:58
#define WS_BORDER
Definition: pedump.c:625
DWORD * PDWORD
Definition: pedump.c:68
#define WS_DISABLED
Definition: pedump.c:621
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST *pidl, const CIDA *cida)
Definition: pidl.c:2656
HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWSTR *ppszName)
Definition: pidl.c:1610
void _ILFreeaPidl(LPITEMIDLIST *apidl, UINT cidl)
Definition: pidl.c:2616
LPITEMIDLIST SHELL32_CreateSimpleIDListFromPath(LPCWSTR pszPath, DWORD dwAttributes)
Definition: pidl.c:1195
#define WC_STATIC
Definition: commctrl.h:4687
#define REFIID
Definition: guiddef.h:118
@ CTF_PROCESS_REF
Definition: shlwapi.h:73
@ CTF_COINIT
Definition: shlwapi.h:75
wcscpy
#define LoadStringW
Definition: utils.h:64
#define KeyStateToDropEffect(kst)
Definition: shell32_main.h:156
#define FOF_ALLOWUNDO
Definition: shellapi.h:147
#define FO_COPY
Definition: shellapi.h:137
#define FOF_RENAMEONCOLLISION
Definition: shellapi.h:144
#define FOF_NOCONFIRMMKDIR
Definition: shellapi.h:150
#define FO_MOVE
Definition: shellapi.h:136
#define SHELL_ErrorBox
Definition: shellutils.h:126
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE *ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl)
Definition: shlfolder.cpp:542
void AddPidlClassKeysToArray(LPCITEMIDLIST pidl, HKEY *array, UINT *cKeys)
Definition: shlfolder.cpp:536
EXTERN_C HRESULT WINAPI SHGetAttributesFromDataObject(IDataObject *pDataObject, DWORD dwAttributeMask, DWORD *pdwAttributes, UINT *pcItems)
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
Definition: shlfileop.cpp:2200
#define CFSTR_SHELLIDLIST
Definition: shlobj.h:560
struct CIDA * LPIDA
#define SHCNE_CREATE
Definition: shlobj.h:1908
#define SHCNF_PATHW
Definition: shlobj.h:1943
struct _DROPFILES * LPDROPFILES
#define IDM_DRAGFILE
Definition: shresdef.h:918
#define IDM_MOVEHERE
Definition: shresdef.h:920
#define IDM_LINKHERE
Definition: shresdef.h:921
#define IDS_LNK_FILE
Definition: shresdef.h:178
#define IDM_COPYHERE
Definition: shresdef.h:919
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
ITEMID_CHILD UNALIGNED * PUITEMID_CHILD
Definition: shtypes.idl:68
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
Definition: shlobj.h:582
UINT cidl
Definition: shlobj.h:582
DWORD pFiles
Definition: shlobj.h:2325
Definition: dsa.c:45
DWORD dwKeyState
Definition: CFSDropTarget.h:83
CFSDropTarget * This
Definition: CFSDropTarget.h:81
LPCWSTR pFrom
Definition: shellapi.h:369
FILEOP_FLAGS fFlags
Definition: shellapi.h:371
Definition: dsound.c:943
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * LPCWSTR
Definition: typedefs.h:57
uint16_t * LPWSTR
Definition: typedefs.h:56
uint32_t * LPDWORD
Definition: typedefs.h:59
uint16_t * PWCHAR
Definition: typedefs.h:56
#define INVALID_FILETITLE_CHARACTERSW
Definition: undocshell.h:1084
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
#define E_UNEXPECTED
Definition: winerror.h:3528
#define MK_RBUTTON
Definition: winuser.h:2404
#define CreateWindowEx
Definition: winuser.h:5921
#define MK_SHIFT
Definition: winuser.h:2405
#define MF_BYCOMMAND
Definition: winuser.h:202
BOOL WINAPI SetMenuDefaultItem(_In_ HMENU, _In_ UINT, _In_ UINT)
#define TPM_RIGHTBUTTON
Definition: winuser.h:2416
BOOL WINAPI SetForegroundWindow(_In_ HWND)
UINT WINAPI RegisterClipboardFormatW(_In_ LPCWSTR)
BOOL WINAPI DeleteMenu(_In_ HMENU, _In_ UINT, _In_ UINT)
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
#define MK_CONTROL
Definition: winuser.h:2406
#define TPM_LEFTBUTTON
Definition: winuser.h:2415
#define MAKEINTRESOURCEA(i)
Definition: winuser.h:581
BOOL WINAPI DestroyMenu(_In_ HMENU)
#define SW_SHOW
Definition: winuser.h:786
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
HMENU WINAPI LoadMenuW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
#define TPM_RETURNCMD
Definition: winuser.h:2423
BOOL WINAPI DestroyWindow(_In_ HWND)