ReactOS 0.4.16-dev-755-g88f105e
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
73/****************************************************************************
74 * CFSDropTarget::_CopyItems
75 *
76 * copies or moves items to this folder
77 */
79 LPCITEMIDLIST * apidl, BOOL bCopy)
80{
82 WCHAR wszDstPath[MAX_PATH + 1] = {0};
83 PWCHAR pwszSrcPathsList = (PWCHAR) HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) * cidl + 1);
84 if (!pwszSrcPathsList)
85 return E_OUTOFMEMORY;
86
87 PWCHAR pwszListPos = pwszSrcPathsList;
88 STRRET strretFrom;
90 BOOL bRenameOnCollision = FALSE;
91
92 /* Build a double null terminated list of C strings from source paths */
93 for (UINT i = 0; i < cidl; i++)
94 {
95 ret = pSFFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strretFrom);
96 if (FAILED(ret))
97 goto cleanup;
98
99 ret = StrRetToBufW(&strretFrom, NULL, pwszListPos, MAX_PATH);
100 if (FAILED(ret))
101 goto cleanup;
102
103 pwszListPos += lstrlenW(pwszListPos) + 1;
104 }
105 /* Append the final null. */
106 *pwszListPos = L'\0';
107
108 /* Build a double null terminated target (this path) */
110 if (FAILED(ret))
111 goto cleanup;
112
113 wszDstPath[lstrlenW(wszDstPath) + 1] = UNICODE_NULL;
114
115 /* Set bRenameOnCollision to TRUE if necesssary */
116 if (bCopy)
117 {
118 WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH];
119 GetFullPathNameW(pwszSrcPathsList, _countof(szPath1), szPath1, NULL);
120 GetFullPathNameW(wszDstPath, _countof(szPath2), szPath2, NULL);
121 PathRemoveFileSpecW(szPath1);
122 if (_wcsicmp(szPath1, szPath2) == 0)
123 bRenameOnCollision = TRUE;
124 }
125
126 ZeroMemory(&fop, sizeof(fop));
127 fop.hwnd = m_hwndSite;
128 fop.wFunc = bCopy ? FO_COPY : FO_MOVE;
129 fop.pFrom = pwszSrcPathsList;
130 fop.pTo = wszDstPath;
132 if (bRenameOnCollision)
134
135 ret = S_OK;
136
137 if (SHFileOperationW(&fop))
138 {
139 ERR("SHFileOperationW failed\n");
140 ret = E_FAIL;
141 }
142
143cleanup:
144 HeapFree(GetProcessHeap(), 0, pwszSrcPathsList);
145 return ret;
146}
147
149 m_cfShellIDList(0),
150 m_fAcceptFmt(FALSE),
151 m_sPathTarget(NULL),
152 m_hwndSite(NULL),
153 m_grfKeyState(0),
154 m_AllowedEffects(0)
155{
156}
157
159{
160 if (!PathTarget)
161 return E_UNEXPECTED;
162
164 if (!m_cfShellIDList)
165 return E_FAIL;
166
167 return SHStrDupW(PathTarget, &m_sPathTarget);
168}
169
171{
173}
174
175BOOL
176CFSDropTarget::_GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
177{
178 WCHAR wszLink[40];
179
180 if (!bShortcut)
181 {
182 if (!LoadStringW(shell32_hInstance, IDS_LNK_FILE, wszLink, _countof(wszLink)))
183 wszLink[0] = L'\0';
184 }
185
186 if (!bShortcut)
187 swprintf(pwszTarget, L"%s%s%s", wszLink, pwszBasePath, pwszExt);
188 else
189 swprintf(pwszTarget, L"%s%s", pwszBasePath, pwszExt);
190
191 for (UINT i = 2; PathFileExistsW(pwszTarget); ++i)
192 {
193 if (!bShortcut)
194 swprintf(pwszTarget, L"%s%s (%u)%s", wszLink, pwszBasePath, i, pwszExt);
195 else
196 swprintf(pwszTarget, L"%s (%u)%s", pwszBasePath, i, pwszExt);
197 }
198
199 return TRUE;
200}
201
202/****************************************************************************
203 * IDropTarget implementation
204 */
206{
207 /* TODO Windows does different drop effects if dragging across drives.
208 i.e., it will copy instead of move if the directories are on different disks. */
210
211 DWORD dwEffect = m_dwDefaultEffect;
212
213 *pdwEffect = DROPEFFECT_NONE;
214
215 if (m_fAcceptFmt) { /* Does our interpretation of the keystate ... */
216 *pdwEffect = KeyStateToDropEffect(dwKeyState);
217
218 // Transform disallowed move to a copy
219 if ((*pdwEffect & D_MOVE) && (m_AllowedEffects & (D_MOVE | D_COPY)) == D_COPY)
220 *pdwEffect = D_COPY;
221
222 *pdwEffect &= m_AllowedEffects;
223
224 if (*pdwEffect == DROPEFFECT_NONE)
225 *pdwEffect = dwEffect;
226
227 /* ... matches the desired effect ? */
228 if (dwEffect & *pdwEffect) {
229 return TRUE;
230 }
231 }
232 return FALSE;
233}
234
235HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects)
236{
238 if (!hmenu)
239 return E_OUTOFMEMORY;
240
242
243 SHELL_LimitDropEffectToItemAttributes(pDataObject, &dwAvailableEffects);
244 if ((dwAvailableEffects & DROPEFFECT_COPY) == 0)
246 if ((dwAvailableEffects & DROPEFFECT_MOVE) == 0)
248 if ((dwAvailableEffects & DROPEFFECT_LINK) == 0 && (dwAvailableEffects & (DROPEFFECT_COPY | DROPEFFECT_MOVE)))
250
252 if (*pdwEffect & dwAvailableEffects & DROPEFFECT_COPY)
254 else if (*pdwEffect & dwAvailableEffects & DROPEFFECT_MOVE)
256 else if (dwAvailableEffects & DROPEFFECT_LINK)
258
259 /* FIXME: We need to support shell extensions here */
260
261 /* We shouldn't use the site window here because the menu should work even when we don't have a site */
262 HWND hwndDummy = CreateWindowEx(0,
263 WC_STATIC,
264 NULL,
266 pt.x,
267 pt.y,
268 1,
269 1,
270 NULL,
271 NULL,
272 NULL,
273 NULL);
274
275 SetForegroundWindow(hwndDummy); // Required for aborting by pressing Esc when dragging from Explorer to desktop
276 UINT uCommand = TrackPopupMenu(hpopupmenu,
278 pt.x, pt.y, 0, hwndDummy, NULL);
279
280 DestroyWindow(hwndDummy);
281
282 if (uCommand == 0)
283 return S_FALSE;
284 else if (uCommand == IDM_COPYHERE)
285 *pdwEffect = DROPEFFECT_COPY;
286 else if (uCommand == IDM_MOVEHERE)
287 *pdwEffect = DROPEFFECT_MOVE;
288 else if (uCommand == IDM_LINKHERE)
289 *pdwEffect = DROPEFFECT_LINK;
290
291 return S_OK;
292}
293
295{
296 CComPtr<IFolderView> pfv;
297 POINT ptDrag;
300 return hr;
301
302 hr = psfv->GetDragPoint(&ptDrag);
304 return hr;
305
306 PIDLIST_ABSOLUTE pidlFolder;
307 PUITEMID_CHILD *apidl;
308 UINT cidl;
309 hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
311 return hr;
312
313 CComHeapPtr<POINT> apt;
314 if (!apt.Allocate(cidl))
315 {
316 SHFree(pidlFolder);
317 _ILFreeaPidl(apidl, cidl);
318 return E_OUTOFMEMORY;
319 }
320
321 for (UINT i = 0; i<cidl; i++)
322 {
323 pfv->GetItemPosition(apidl[i], &apt[i]);
324 apt[i].x += pt.x - ptDrag.x;
325 apt[i].y += pt.y - ptDrag.y;
326 }
327
328 pfv->SelectAndPositionItems(cidl, apidl, apt, SVSI_SELECT);
329
330 SHFree(pidlFolder);
331 _ILFreeaPidl(apidl, cidl);
332 return S_OK;
333}
334
336 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
337{
338 TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
339
340 const BOOL bAnyKeyMod = dwKeyState & (MK_SHIFT | MK_CONTROL);
341 m_AllowedEffects = *pdwEffect;
342
343 if (*pdwEffect == DROPEFFECT_NONE)
344 return S_OK;
345
346 FORMATETC fmt;
347 FORMATETC fmt2;
349
350 InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
351 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
352
353 if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
355 else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
357
358 m_grfKeyState = dwKeyState;
359
360 SHELL_LimitDropEffectToItemAttributes(pDataObject, pdwEffect);
361 m_AllowedEffects = *pdwEffect;
363 switch (*pdwEffect & (D_COPY | D_MOVE | D_LINK))
364 {
365 case D_COPY | D_MOVE:
366 if (dwKeyState & MK_CONTROL)
368 else
370 break;
371 case D_COPY | D_MOVE | D_LINK:
372 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
374 else if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == MK_CONTROL)
376 else
378 break;
379 case D_COPY | D_LINK:
380 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
382 else
384 break;
385 case D_MOVE | D_LINK:
386 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
388 else
390 break;
391 }
392
393 STGMEDIUM medium;
394 if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)))
395 {
396 WCHAR wstrFirstFile[MAX_PATH];
397 if (DragQueryFileW((HDROP)medium.hGlobal, 0, wstrFirstFile, _countof(wstrFirstFile)))
398 {
399 if (!PathIsSameDrive(wstrFirstFile, m_sPathTarget) && m_dwDefaultEffect != D_LINK)
400 {
402 }
403
404 if (!bAnyKeyMod && PathIsDriveRoot(wstrFirstFile) && (m_AllowedEffects & DROPEFFECT_LINK))
405 {
406 m_dwDefaultEffect = DROPEFFECT_LINK; // Don't copy a drive by default
407 }
408 }
409 ReleaseStgMedium(&medium);
410 }
411
412 if (!m_fAcceptFmt)
414 else
415 *pdwEffect = m_dwDefaultEffect;
416 *pdwEffect &= m_AllowedEffects;
417
418 return S_OK;
419}
420
422 DWORD *pdwEffect)
423{
424 TRACE("(%p)\n", this);
425
426 if (!pdwEffect)
427 return E_INVALIDARG;
428
429 m_grfKeyState = dwKeyState;
430
431 _QueryDrop(dwKeyState, pdwEffect);
432
433 return S_OK;
434}
435
437{
438 TRACE("(%p)\n", this);
439
441
442 return S_OK;
443}
444
446 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
447{
448 TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect);
449
450 if (!pdwEffect)
451 return E_INVALIDARG;
452
454
455 DWORD dwAvailableEffects = *pdwEffect;
456
457 _QueryDrop(dwKeyState, pdwEffect);
458
459 TRACE("pdwEffect: 0x%x, m_dwDefaultEffect: 0x%x, dwAvailableEffects: 0x%x\n", *pdwEffect, m_dwDefaultEffect, dwAvailableEffects);
460
462 {
463 HRESULT hr = _GetEffectFromMenu(pDataObject, pt, pdwEffect, dwAvailableEffects);
464 if (FAILED_UNEXPECTEDLY(hr) || hr == S_FALSE)
465 return hr;
466 }
467
468 if (*pdwEffect == DROPEFFECT_MOVE && m_site)
469 {
470 CComPtr<IShellFolderView> psfv;
472 if (SUCCEEDED(hr) && psfv->IsDropOnSource(this) == S_OK)
473 {
474 _RepositionItems(psfv, pDataObject, pt);
475 return S_OK;
476 }
477 }
478
479 BOOL fIsOpAsync = FALSE;
480 CComPtr<IAsyncOperation> pAsyncOperation;
481
482 if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
483 {
484 if (SUCCEEDED(pAsyncOperation->GetAsyncMode(&fIsOpAsync)) && fIsOpAsync)
485 {
486 _DoDropData *data = static_cast<_DoDropData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(_DoDropData)));
487 data->This = this;
488 // Need to maintain this class in case the window is closed or the class exists temporarily (when dropping onto a folder).
489 pDataObject->AddRef();
490 pAsyncOperation->StartOperation(NULL);
492 this->AddRef();
493 data->dwKeyState = dwKeyState;
494 data->pt = pt;
495 // Need to dereference as pdweffect gets freed.
496 data->pdwEffect = *pdwEffect;
498 return S_OK;
499 }
500 }
501 return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect);
502}
503
505WINAPI
507{
508 m_site = pUnkSite;
509 return S_OK;
510}
511
513WINAPI
515{
516 if (!m_site)
517 return E_FAIL;
518
519 return m_site->QueryInterface(riid, ppvSite);
520}
521
523 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
524{
525 TRACE("(%p) performing drop, effect %u\n", this, *pdwEffect);
526 FORMATETC fmt;
527 FORMATETC fmt2;
528 STGMEDIUM medium;
529
530 InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
531 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
532
533 HRESULT hr;
534 bool bCopy = TRUE;
535 bool bLinking = FALSE;
536
537 /* Figure out what drop operation we're doing */
538 if (pdwEffect)
539 {
540 TRACE("Current drop effect flag %i\n", *pdwEffect);
541 if ((*pdwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
542 bCopy = FALSE;
543 if ((*pdwEffect & DROPEFFECT_LINK) == DROPEFFECT_LINK)
544 bLinking = TRUE;
545 }
546
547 if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
548 {
549 hr = pDataObject->GetData(&fmt, &medium);
550 TRACE("CFSTR_SHELLIDLIST\n");
551 if (FAILED(hr))
552 {
553 ERR("CFSTR_SHELLIDLIST failed\n");
554 }
555 /* lock the handle */
556 LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
557 if (!lpcida)
558 {
559 ReleaseStgMedium(&medium);
560 return E_FAIL;
561 }
562
563 /* convert the data into pidl */
564 LPITEMIDLIST pidl;
565 LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
566 if (!apidl)
567 {
568 ReleaseStgMedium(&medium);
569 return E_FAIL;
570 }
571
572 CComPtr<IShellFolder> psfDesktop;
573 CComPtr<IShellFolder> psfFrom = NULL;
574
575 /* Grab the desktop shell folder */
576 hr = SHGetDesktopFolder(&psfDesktop);
577 if (FAILED(hr))
578 {
579 ERR("SHGetDesktopFolder failed\n");
580 SHFree(pidl);
581 _ILFreeaPidl(apidl, lpcida->cidl);
582 ReleaseStgMedium(&medium);
583 return E_FAIL;
584 }
585
586 /* Find source folder, this is where the clipboard data was copied from */
587 if (_ILIsDesktop(pidl))
588 {
589 /* use desktop shell folder */
590 psfFrom = psfDesktop;
591 }
592 else
593 {
594 hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom));
595 if (FAILED(hr))
596 {
597 ERR("no IShellFolder\n");
598 SHFree(pidl);
599 _ILFreeaPidl(apidl, lpcida->cidl);
600 ReleaseStgMedium(&medium);
601 return E_FAIL;
602 }
603 }
604
605 if (bLinking)
606 {
607 WCHAR wszNewLnk[MAX_PATH];
608
609 TRACE("target path = %s\n", debugstr_w(m_sPathTarget));
610
611 /* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */
612 for (UINT i = 0; i < lpcida->cidl; i++)
613 {
614 SFGAOF att = SHGetAttributes(psfFrom, apidl[i], SFGAO_FOLDER | SFGAO_STREAM | SFGAO_FILESYSTEM);
615 CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlFull;
616 hr = SHILCombine(pidl, apidl[i], &pidlFull);
617
618 WCHAR targetName[MAX_PATH];
619 if (SUCCEEDED(hr))
620 {
621 // If the target is a file, we use SHGDN_FORPARSING because "NeverShowExt" will hide the ".lnk" extension.
622 // If the target is a virtual item, we ask for the friendly name because SHGDN_FORPARSING will return a GUID.
623 BOOL UseParsing = (att & (SFGAO_FILESYSTEM | SFGAO_FOLDER)) == SFGAO_FILESYSTEM;
624 DWORD ShgdnFor = UseParsing ? SHGDN_FORPARSING : SHGDN_FOREDITING;
625 hr = Shell_DisplayNameOf(psfFrom, apidl[i], ShgdnFor | SHGDN_INFOLDER, targetName, _countof(targetName));
626 }
628 {
630 break;
631 }
633
634 WCHAR wszCombined[MAX_PATH + _countof(targetName)];
635 PathCombineW(wszCombined, m_sPathTarget, targetName);
636
637 // Check to see if the source is a link
638 BOOL fSourceIsLink = FALSE;
639 if (!_wcsicmp(PathFindExtensionW(targetName), L".lnk") && (att & (SFGAO_FOLDER | SFGAO_STREAM)) != SFGAO_FOLDER)
640 {
641 fSourceIsLink = TRUE;
642 PathRemoveExtensionW(wszCombined);
643 }
644
645 // Create a pathname to save the new link.
646 _GetUniqueFileName(wszCombined, L".lnk", wszNewLnk, TRUE);
647
648 CComPtr<IPersistFile> ppf;
649 if (fSourceIsLink)
650 {
651 PWSTR pwszTargetFull;
652 hr = SHGetNameFromIDList(pidlFull, SIGDN_DESKTOPABSOLUTEPARSING, &pwszTargetFull);
654 {
657 SHFree(pwszTargetFull);
658 }
659 }
660 else
661 {
662 CComPtr<IShellLinkW> pLink;
663 hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink));
665 {
666 hr = pLink->SetIDList(pidlFull);
668 hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
669
670 PWSTR pwszPath, pSep;
671 if ((att & SFGAO_FILESYSTEM) && SUCCEEDED(SHGetNameFromIDList(pidlFull, SIGDN_FILESYSPATH, &pwszPath)))
672 {
673 if ((pSep = PathFindFileNameW(pwszPath)) > pwszPath)
674 {
675 pSep[-1] = UNICODE_NULL;
676 pLink->SetWorkingDirectory(pwszPath);
677 }
678 SHFree(pwszPath);
679 }
680 }
681 }
682 if (SUCCEEDED(hr))
683 hr = ppf->Save(wszNewLnk, !fSourceIsLink);
685 {
687 break;
688 }
690 }
691 }
692 else
693 {
694 hr = _CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy);
695 }
696
697 SHFree(pidl);
698 _ILFreeaPidl(apidl, lpcida->cidl);
699 ReleaseStgMedium(&medium);
700 }
701 else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
702 {
703 FORMATETC fmt2;
704 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
705 if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/)
706 {
707 WCHAR wszTargetPath[MAX_PATH + 1];
708 LPWSTR pszSrcList;
709
710 wcscpy(wszTargetPath, m_sPathTarget);
711 //Double NULL terminate.
712 wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
713
714 LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal);
715 if (!lpdf)
716 {
717 ERR("Error locking global\n");
718 return E_FAIL;
719 }
720 pszSrcList = (LPWSTR) (((byte*) lpdf) + lpdf->pFiles);
721 ERR("Source file (just the first) = %s, target path = %s, bCopy: %d\n", debugstr_w(pszSrcList), debugstr_w(wszTargetPath), bCopy);
722
724 ZeroMemory(&op, sizeof(op));
725 op.pFrom = pszSrcList;
726 op.pTo = wszTargetPath;
727 op.hwnd = m_hwndSite;
728 op.wFunc = bCopy ? FO_COPY : FO_MOVE;
730 int res = SHFileOperationW(&op);
731 if (res)
732 {
733 ERR("SHFileOperationW failed with 0x%x\n", res);
734 hr = E_FAIL;
735 }
736
737 return hr;
738 }
739 ERR("Error calling GetData\n");
740 hr = E_FAIL;
741 }
742 else
743 {
744 ERR("No viable drop format\n");
745 hr = E_FAIL;
746 }
747 return hr;
748}
749
751{
752 _DoDropData *data = static_cast<_DoDropData*>(lpParameter);
753 CComPtr<IDataObject> pDataObject;
755
756 if (SUCCEEDED(hr))
757 {
758 CComPtr<IAsyncOperation> pAsyncOperation;
759 hr = data->This->_DoDrop(pDataObject, data->dwKeyState, data->pt, &data->pdwEffect);
760 if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
761 {
762 pAsyncOperation->EndOperation(hr, NULL, data->pdwEffect);
763 }
764 }
765 //Release the CFSFolder and data object holds in the copying thread.
766 data->This->Release();
767 //Release the parameter from the heap.
769 return 0;
770}
771
773{
774 return ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut);
775}
BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
Definition: CBandSite.h:24
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
static HRESULT SHELL_LimitDropEffectToItemAttributes(_In_ IDataObject *pDataObject, _Inout_ PDWORD pdwEffect)
static void GetDefaultCopyMoveEffect()
#define D_LINK
static bool PathIsSameDrive(LPCWSTR Path1, LPCWSTR Path2)
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:37
STDMETHOD() Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) override
CComPtr< IUnknown > m_site
Definition: CFSDropTarget.h:39
STDMETHOD() DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) override
DWORD m_AllowedEffects
Definition: CFSDropTarget.h:38
HRESULT Initialize(LPWSTR PathTarget)
STDMETHOD() GetSite(REFIID riid, void **ppvSite) override
LPWSTR m_sPathTarget
Definition: CFSDropTarget.h:34
static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter)
HRESULT _CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy)
BOOL _QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
UINT m_cfShellIDList
Definition: CFSDropTarget.h:32
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:36
STDMETHOD() DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) override
STDMETHOD() SetSite(IUnknown *pUnkSite) override
HRESULT _RepositionItems(IShellFolderView *psfv, IDataObject *pDataObject, POINTL pt)
wcscpy
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
#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
#define FAILED_UNEXPECTEDLY(hr)
Definition: precomp.h:121
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
HRESULT WINAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, LPUNKNOWN pUnk, LPSTREAM *ppStm)
Definition: marshal.c:2100
HRESULT WINAPI CoGetInterfaceAndReleaseStream(LPSTREAM pStm, REFIID riid, LPVOID *ppv)
Definition: marshal.c:2144
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
HRESULT Shell_DisplayNameOf(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwFlags, _Out_ LPWSTR pszBuf, _In_ UINT cchBuf)
Definition: utils.cpp:406
DWORD SHGetAttributes(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwAttributes)
Definition: utils.cpp:422
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:326
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:622
HRESULT WINAPI IUnknown_QueryService(IUnknown *, REFGUID, REFIID, LPVOID *)
Definition: ordinal.c:1501
HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
Definition: ordinal.c:1336
int WINAPI PathGetDriveNumberW(const WCHAR *path)
Definition: path.c:553
BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
Definition: path.c:629
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:447
void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
Definition: path.c:823
BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
Definition: path.c:1648
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1783
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR *dest)
Definition: string.c:2018
HRESULT WINAPI StrRetToBufW(LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, UINT len)
Definition: string.c:1530
BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, VOID *pData, DWORD dwFlags, LPTHREAD_START_ROUTINE pfnCallback)
Definition: thread.c:356
#define swprintf
Definition: precomp.h:40
#define pt(x, y)
Definition: drawing.c:79
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
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
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 debugstr_w
Definition: kernel32.h:32
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
static HMENU hpopupmenu
Definition: msg.c:17339
unsigned int UINT
Definition: ndis.h:50
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define UNICODE_NULL
#define L(x)
Definition: ntvdm.h:50
const GUID IID_IDataObject
#define PathCombineW
Definition: pathcch.h:317
#define WS_OVERLAPPED
Definition: pedump.c:615
#define WS_BORDER
Definition: pedump.c:625
DWORD * PDWORD
Definition: pedump.c:68
#define WS_DISABLED
Definition: pedump.c:621
#define SS_LEFT
Definition: pedump.c:692
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST *pidl, const CIDA *cida)
Definition: pidl.c:2641
HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWSTR *ppszName)
Definition: pidl.c:1568
void _ILFreeaPidl(LPITEMIDLIST *apidl, UINT cidl)
Definition: pidl.c:2603
#define WC_STATIC
Definition: commctrl.h:4687
#define REFIID
Definition: guiddef.h:118
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define KeyStateToDropEffect(kst)
Definition: shell32_main.h:113
#define FOF_ALLOWUNDO
Definition: shellapi.h:148
#define FO_COPY
Definition: shellapi.h:138
#define FOF_RENAMEONCOLLISION
Definition: shellapi.h:145
#define FOF_NOCONFIRMMKDIR
Definition: shellapi.h:151
#define FO_MOVE
Definition: shellapi.h:137
#define SHELL_ErrorBox
Definition: shellutils.h:126
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE *ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl)
Definition: shlfolder.cpp:402
EXTERN_C HRESULT WINAPI SHGetAttributesFromDataObject(IDataObject *pDataObject, DWORD dwAttributeMask, DWORD *pdwAttributes, UINT *pcItems)
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
Definition: shlfileop.cpp:1990
HRESULT hr
Definition: shlfolder.c:183
#define SID_IFolderView
#define CFSTR_SHELLIDLIST
Definition: shlobj.h:550
struct CIDA * LPIDA
#define SHCNE_CREATE
Definition: shlobj.h:1891
#define SHCNF_PATHW
Definition: shlobj.h:1925
struct _DROPFILES * LPDROPFILES
#define CTF_PROCESS_REF
Definition: shlwapi.h:1963
#define CTF_COINIT
Definition: shlwapi.h:1964
#define IDM_DRAGFILE
Definition: shresdef.h:874
#define IDM_MOVEHERE
Definition: shresdef.h:876
#define IDM_LINKHERE
Definition: shresdef.h:877
#define IDS_LNK_FILE
Definition: shresdef.h:178
#define IDM_COPYHERE
Definition: shresdef.h:875
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:572
UINT cidl
Definition: shlobj.h:572
DWORD pFiles
Definition: shlobj.h:2307
DWORD dwKeyState
Definition: CFSDropTarget.h:78
CFSDropTarget * This
Definition: CFSDropTarget.h:76
LPCWSTR pFrom
Definition: shellapi.h:358
FILEOP_FLAGS fFlags
Definition: shellapi.h:360
Definition: dsound.c:943
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
uint16_t * PWSTR
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:984
int ret
static HMENU hmenu
Definition: win.c:66
#define ZeroMemory
Definition: winbase.h:1737
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_UNEXPECTED
Definition: winerror.h:2456
#define MK_RBUTTON
Definition: winuser.h:2371
#define CreateWindowEx
Definition: winuser.h:5767
#define MK_SHIFT
Definition: winuser.h:2372
#define MF_BYCOMMAND
Definition: winuser.h:202
BOOL WINAPI SetMenuDefaultItem(_In_ HMENU, _In_ UINT, _In_ UINT)
#define TPM_RIGHTBUTTON
Definition: winuser.h:2383
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
BOOL WINAPI SetForegroundWindow(_In_ HWND)
UINT WINAPI RegisterClipboardFormatW(_In_ LPCWSTR)
BOOL WINAPI DeleteMenu(_In_ HMENU, _In_ UINT, _In_ UINT)
#define TPM_NONOTIFY
Definition: winuser.h:2389
LPWSTR WINAPI CharNextW(_In_ LPCWSTR)
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
#define MK_CONTROL
Definition: winuser.h:2373
#define TPM_LEFTALIGN
Definition: winuser.h:2380
#define TPM_LEFTBUTTON
Definition: winuser.h:2382
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
HMENU WINAPI LoadMenuW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
#define TPM_RETURNCMD
Definition: winuser.h:2390
BOOL WINAPI DestroyWindow(_In_ HWND)
#define IID_PPV_ARG(Itype, ppType)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185