ReactOS 0.4.16-dev-197-g92996da
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
28{
29 for (LPWSTR src = Buf, dst = src;;)
30 {
31 *dst = *src;
32 if (!*dst)
33 break;
35 src = CharNextW(src);
36 else
37 ++src, ++dst;
38 }
39}
40
41static HRESULT
43{
44 DWORD att = *pdwEffect & (SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK); // DROPEFFECT maps perfectly to these SFGAO bits
45 HRESULT hr = SHGetAttributesFromDataObject(pDataObject, att, &att, NULL);
46 if (FAILED(hr))
47 return S_FALSE;
48 *pdwEffect &= ~(SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANLINK) | att;
49 return hr;
50}
51
53{
54 // FIXME: When the source is on a different volume than the target, change default from move to copy
55}
56
57/****************************************************************************
58 * CFSDropTarget::_CopyItems
59 *
60 * copies or moves items to this folder
61 */
63 LPCITEMIDLIST * apidl, BOOL bCopy)
64{
66 WCHAR wszDstPath[MAX_PATH + 1] = {0};
67 PWCHAR pwszSrcPathsList = (PWCHAR) HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) * cidl + 1);
68 if (!pwszSrcPathsList)
69 return E_OUTOFMEMORY;
70
71 PWCHAR pwszListPos = pwszSrcPathsList;
72 STRRET strretFrom;
74 BOOL bRenameOnCollision = FALSE;
75
76 /* Build a double null terminated list of C strings from source paths */
77 for (UINT i = 0; i < cidl; i++)
78 {
79 ret = pSFFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strretFrom);
80 if (FAILED(ret))
81 goto cleanup;
82
83 ret = StrRetToBufW(&strretFrom, NULL, pwszListPos, MAX_PATH);
84 if (FAILED(ret))
85 goto cleanup;
86
87 pwszListPos += lstrlenW(pwszListPos) + 1;
88 }
89 /* Append the final null. */
90 *pwszListPos = L'\0';
91
92 /* Build a double null terminated target (this path) */
94 if (FAILED(ret))
95 goto cleanup;
96
97 wszDstPath[lstrlenW(wszDstPath) + 1] = UNICODE_NULL;
98
99 /* Set bRenameOnCollision to TRUE if necesssary */
100 if (bCopy)
101 {
102 WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH];
103 GetFullPathNameW(pwszSrcPathsList, _countof(szPath1), szPath1, NULL);
104 GetFullPathNameW(wszDstPath, _countof(szPath2), szPath2, NULL);
105 PathRemoveFileSpecW(szPath1);
106 if (_wcsicmp(szPath1, szPath2) == 0)
107 bRenameOnCollision = TRUE;
108 }
109
110 ZeroMemory(&fop, sizeof(fop));
111 fop.hwnd = m_hwndSite;
112 fop.wFunc = bCopy ? FO_COPY : FO_MOVE;
113 fop.pFrom = pwszSrcPathsList;
114 fop.pTo = wszDstPath;
116 if (bRenameOnCollision)
118
119 ret = S_OK;
120
121 if (SHFileOperationW(&fop))
122 {
123 ERR("SHFileOperationW failed\n");
124 ret = E_FAIL;
125 }
126
127cleanup:
128 HeapFree(GetProcessHeap(), 0, pwszSrcPathsList);
129 return ret;
130}
131
133 m_cfShellIDList(0),
134 m_fAcceptFmt(FALSE),
135 m_sPathTarget(NULL),
136 m_hwndSite(NULL),
137 m_grfKeyState(0)
138{
139}
140
142{
143 if (!PathTarget)
144 return E_UNEXPECTED;
145
147 if (!m_cfShellIDList)
148 return E_FAIL;
149
150 m_sPathTarget = (WCHAR *)SHAlloc((wcslen(PathTarget) + 1) * sizeof(WCHAR));
151 if (!m_sPathTarget)
152 return E_OUTOFMEMORY;
153
154 wcscpy(m_sPathTarget, PathTarget);
155
156 return S_OK;
157}
158
160{
162}
163
164BOOL
165CFSDropTarget::_GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
166{
167 WCHAR wszLink[40];
168
169 if (!bShortcut)
170 {
171 if (!LoadStringW(shell32_hInstance, IDS_LNK_FILE, wszLink, _countof(wszLink)))
172 wszLink[0] = L'\0';
173 }
174
175 if (!bShortcut)
176 swprintf(pwszTarget, L"%s%s%s", wszLink, pwszBasePath, pwszExt);
177 else
178 swprintf(pwszTarget, L"%s%s", pwszBasePath, pwszExt);
179
180 for (UINT i = 2; PathFileExistsW(pwszTarget); ++i)
181 {
182 if (!bShortcut)
183 swprintf(pwszTarget, L"%s%s (%u)%s", wszLink, pwszBasePath, i, pwszExt);
184 else
185 swprintf(pwszTarget, L"%s (%u)%s", pwszBasePath, i, pwszExt);
186 }
187
188 return TRUE;
189}
190
191/****************************************************************************
192 * IDropTarget implementation
193 */
195{
196 /* TODO Windows does different drop effects if dragging across drives.
197 i.e., it will copy instead of move if the directories are on different disks. */
199
200 DWORD dwEffect = m_dwDefaultEffect;
201
202 *pdwEffect = DROPEFFECT_NONE;
203
204 if (m_fAcceptFmt) { /* Does our interpretation of the keystate ... */
205 *pdwEffect = KeyStateToDropEffect (dwKeyState);
206
207 if (*pdwEffect == DROPEFFECT_NONE)
208 *pdwEffect = dwEffect;
209
210 /* ... matches the desired effect ? */
211 if (dwEffect & *pdwEffect) {
212 return TRUE;
213 }
214 }
215 return FALSE;
216}
217
218HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects)
219{
221 if (!hmenu)
222 return E_OUTOFMEMORY;
223
225
226 SHELL_LimitDropEffectToItemAttributes(pDataObject, &dwAvailableEffects);
227 if ((dwAvailableEffects & DROPEFFECT_COPY) == 0)
229 if ((dwAvailableEffects & DROPEFFECT_MOVE) == 0)
231 if ((dwAvailableEffects & DROPEFFECT_LINK) == 0 && (dwAvailableEffects & (DROPEFFECT_COPY | DROPEFFECT_MOVE)))
233
235 if (*pdwEffect & dwAvailableEffects & DROPEFFECT_COPY)
237 else if (*pdwEffect & dwAvailableEffects & DROPEFFECT_MOVE)
239 else if (dwAvailableEffects & DROPEFFECT_LINK)
241
242 /* FIXME: We need to support shell extensions here */
243
244 /* We shouldn't use the site window here because the menu should work even when we don't have a site */
245 HWND hwndDummy = CreateWindowEx(0,
246 WC_STATIC,
247 NULL,
249 pt.x,
250 pt.y,
251 1,
252 1,
253 NULL,
254 NULL,
255 NULL,
256 NULL);
257
258 SetForegroundWindow(hwndDummy); // Required for aborting by pressing Esc when dragging from Explorer to desktop
259 UINT uCommand = TrackPopupMenu(hpopupmenu,
261 pt.x, pt.y, 0, hwndDummy, NULL);
262
263 DestroyWindow(hwndDummy);
264
265 if (uCommand == 0)
266 return S_FALSE;
267 else if (uCommand == IDM_COPYHERE)
268 *pdwEffect = DROPEFFECT_COPY;
269 else if (uCommand == IDM_MOVEHERE)
270 *pdwEffect = DROPEFFECT_MOVE;
271 else if (uCommand == IDM_LINKHERE)
272 *pdwEffect = DROPEFFECT_LINK;
273
274 return S_OK;
275}
276
278{
279 CComPtr<IFolderView> pfv;
280 POINT ptDrag;
283 return hr;
284
285 hr = psfv->GetDragPoint(&ptDrag);
287 return hr;
288
289 PIDLIST_ABSOLUTE pidlFolder;
290 PUITEMID_CHILD *apidl;
291 UINT cidl;
292 hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
294 return hr;
295
296 CComHeapPtr<POINT> apt;
297 if (!apt.Allocate(cidl))
298 {
299 SHFree(pidlFolder);
300 _ILFreeaPidl(apidl, cidl);
301 return E_OUTOFMEMORY;
302 }
303
304 for (UINT i = 0; i<cidl; i++)
305 {
306 pfv->GetItemPosition(apidl[i], &apt[i]);
307 apt[i].x += pt.x - ptDrag.x;
308 apt[i].y += pt.y - ptDrag.y;
309 }
310
311 pfv->SelectAndPositionItems(cidl, apidl, apt, SVSI_SELECT);
312
313 SHFree(pidlFolder);
314 _ILFreeaPidl(apidl, cidl);
315 return S_OK;
316}
317
319 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
320{
321 TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
322
323 if (*pdwEffect == DROPEFFECT_NONE)
324 return S_OK;
325
326 FORMATETC fmt;
327 FORMATETC fmt2;
329
330 InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
331 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
332
333 if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
335 else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
337
338 m_grfKeyState = dwKeyState;
339
340#define D_NONE DROPEFFECT_NONE
341#define D_COPY DROPEFFECT_COPY
342#define D_MOVE DROPEFFECT_MOVE
343#define D_LINK DROPEFFECT_LINK
344 m_dwDefaultEffect = *pdwEffect;
345 switch (*pdwEffect & (D_COPY | D_MOVE | D_LINK))
346 {
347 case D_COPY | D_MOVE:
348 if (dwKeyState & MK_CONTROL)
350 else
352 break;
353 case D_COPY | D_MOVE | D_LINK:
354 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
356 else if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == MK_CONTROL)
358 else
360 break;
361 case D_COPY | D_LINK:
362 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
364 else
366 break;
367 case D_MOVE | D_LINK:
368 if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
370 else
372 break;
373 }
374
375 STGMEDIUM medium;
376 if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)))
377 {
378 WCHAR wstrFirstFile[MAX_PATH];
379 if (DragQueryFileW((HDROP)medium.hGlobal, 0, wstrFirstFile, _countof(wstrFirstFile)))
380 {
381 /* Check if the drive letter is different */
382 if (wstrFirstFile[0] != m_sPathTarget[0])
383 {
385 }
386 }
387 ReleaseStgMedium(&medium);
388 }
389
390 if (!m_fAcceptFmt)
391 *pdwEffect = DROPEFFECT_NONE;
392 else
393 *pdwEffect = m_dwDefaultEffect;
394
395 return S_OK;
396}
397
399 DWORD *pdwEffect)
400{
401 TRACE("(%p)\n", this);
402
403 if (!pdwEffect)
404 return E_INVALIDARG;
405
406 m_grfKeyState = dwKeyState;
407
408 _QueryDrop(dwKeyState, pdwEffect);
409
410 return S_OK;
411}
412
414{
415 TRACE("(%p)\n", this);
416
418
419 return S_OK;
420}
421
423 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
424{
425 TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect);
426
427 if (!pdwEffect)
428 return E_INVALIDARG;
429
431
432 DWORD dwAvailableEffects = *pdwEffect;
433
434 _QueryDrop(dwKeyState, pdwEffect);
435
436 TRACE("pdwEffect: 0x%x, m_dwDefaultEffect: 0x%x, dwAvailableEffects: 0x%x\n", *pdwEffect, m_dwDefaultEffect, dwAvailableEffects);
437
439 {
440 HRESULT hr = _GetEffectFromMenu(pDataObject, pt, pdwEffect, dwAvailableEffects);
441 if (FAILED_UNEXPECTEDLY(hr) || hr == S_FALSE)
442 return hr;
443 }
444
445 if (*pdwEffect == DROPEFFECT_MOVE && m_site)
446 {
447 CComPtr<IShellFolderView> psfv;
449 if (SUCCEEDED(hr) && psfv->IsDropOnSource(this) == S_OK)
450 {
451 _RepositionItems(psfv, pDataObject, pt);
452 return S_OK;
453 }
454 }
455
456 BOOL fIsOpAsync = FALSE;
457 CComPtr<IAsyncOperation> pAsyncOperation;
458
459 if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
460 {
461 if (SUCCEEDED(pAsyncOperation->GetAsyncMode(&fIsOpAsync)) && fIsOpAsync)
462 {
463 _DoDropData *data = static_cast<_DoDropData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(_DoDropData)));
464 data->This = this;
465 // Need to maintain this class in case the window is closed or the class exists temporarily (when dropping onto a folder).
466 pDataObject->AddRef();
467 pAsyncOperation->StartOperation(NULL);
469 this->AddRef();
470 data->dwKeyState = dwKeyState;
471 data->pt = pt;
472 // Need to dereference as pdweffect gets freed.
473 data->pdwEffect = *pdwEffect;
475 return S_OK;
476 }
477 }
478 return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect);
479}
480
482WINAPI
484{
485 m_site = pUnkSite;
486 return S_OK;
487}
488
490WINAPI
492{
493 if (!m_site)
494 return E_FAIL;
495
496 return m_site->QueryInterface(riid, ppvSite);
497}
498
500 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
501{
502 TRACE("(%p) performing drop, effect %u\n", this, *pdwEffect);
503 FORMATETC fmt;
504 FORMATETC fmt2;
505 STGMEDIUM medium;
506
507 InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
508 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
509
510 HRESULT hr;
511 bool bCopy = TRUE;
512 bool bLinking = FALSE;
513
514 /* Figure out what drop operation we're doing */
515 if (pdwEffect)
516 {
517 TRACE("Current drop effect flag %i\n", *pdwEffect);
518 if ((*pdwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
519 bCopy = FALSE;
520 if ((*pdwEffect & DROPEFFECT_LINK) == DROPEFFECT_LINK)
521 bLinking = TRUE;
522 }
523
524 if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
525 {
526 hr = pDataObject->GetData(&fmt, &medium);
527 TRACE("CFSTR_SHELLIDLIST\n");
528 if (FAILED(hr))
529 {
530 ERR("CFSTR_SHELLIDLIST failed\n");
531 }
532 /* lock the handle */
533 LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
534 if (!lpcida)
535 {
536 ReleaseStgMedium(&medium);
537 return E_FAIL;
538 }
539
540 /* convert the data into pidl */
541 LPITEMIDLIST pidl;
542 LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
543 if (!apidl)
544 {
545 ReleaseStgMedium(&medium);
546 return E_FAIL;
547 }
548
549 CComPtr<IShellFolder> psfDesktop;
550 CComPtr<IShellFolder> psfFrom = NULL;
551
552 /* Grab the desktop shell folder */
553 hr = SHGetDesktopFolder(&psfDesktop);
554 if (FAILED(hr))
555 {
556 ERR("SHGetDesktopFolder failed\n");
557 SHFree(pidl);
558 _ILFreeaPidl(apidl, lpcida->cidl);
559 ReleaseStgMedium(&medium);
560 return E_FAIL;
561 }
562
563 /* Find source folder, this is where the clipboard data was copied from */
564 if (_ILIsDesktop(pidl))
565 {
566 /* use desktop shell folder */
567 psfFrom = psfDesktop;
568 }
569 else
570 {
571 hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom));
572 if (FAILED(hr))
573 {
574 ERR("no IShellFolder\n");
575 SHFree(pidl);
576 _ILFreeaPidl(apidl, lpcida->cidl);
577 ReleaseStgMedium(&medium);
578 return E_FAIL;
579 }
580 }
581
582 if (bLinking)
583 {
584 WCHAR wszNewLnk[MAX_PATH];
585
586 TRACE("target path = %s\n", debugstr_w(m_sPathTarget));
587
588 /* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */
589 for (UINT i = 0; i < lpcida->cidl; i++)
590 {
591 SFGAOF att = SHGetAttributes(psfFrom, apidl[i], SFGAO_FOLDER | SFGAO_STREAM | SFGAO_FILESYSTEM);
592 CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlFull;
593 hr = SHILCombine(pidl, apidl[i], &pidlFull);
594
595 WCHAR targetName[MAX_PATH];
596 if (SUCCEEDED(hr))
597 {
598 // If the target is a file, we use SHGDN_FORPARSING because "NeverShowExt" will hide the ".lnk" extension.
599 // If the target is a virtual item, we ask for the friendly name because SHGDN_FORPARSING will return a GUID.
600 BOOL UseParsing = (att & (SFGAO_FILESYSTEM | SFGAO_FOLDER)) == SFGAO_FILESYSTEM;
601 DWORD ShgdnFor = UseParsing ? SHGDN_FORPARSING : SHGDN_FOREDITING;
602 hr = Shell_DisplayNameOf(psfFrom, apidl[i], ShgdnFor | SHGDN_INFOLDER, targetName, _countof(targetName));
603 }
605 {
606 SHELL_ErrorBox(m_hwndSite, hr);
607 break;
608 }
610
611 WCHAR wszCombined[MAX_PATH + _countof(targetName)];
612 PathCombineW(wszCombined, m_sPathTarget, targetName);
613
614 // Check to see if the source is a link
615 BOOL fSourceIsLink = FALSE;
616 if (!_wcsicmp(PathFindExtensionW(targetName), L".lnk") && (att & (SFGAO_FOLDER | SFGAO_STREAM)) != SFGAO_FOLDER)
617 {
618 fSourceIsLink = TRUE;
619 PathRemoveExtensionW(wszCombined);
620 }
621
622 // Create a pathname to save the new link.
623 _GetUniqueFileName(wszCombined, L".lnk", wszNewLnk, TRUE);
624
625 CComPtr<IPersistFile> ppf;
626 if (fSourceIsLink)
627 {
628 PWSTR pwszTargetFull;
629 hr = SHGetNameFromIDList(pidlFull, SIGDN_DESKTOPABSOLUTEPARSING, &pwszTargetFull);
631 {
634 SHFree(pwszTargetFull);
635 }
636 }
637 else
638 {
639 CComPtr<IShellLinkW> pLink;
640 hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink));
642 {
643 hr = pLink->SetIDList(pidlFull);
645 hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
646
647 PWSTR pwszPath, pSep;
648 if ((att & SFGAO_FILESYSTEM) && SUCCEEDED(SHGetNameFromIDList(pidlFull, SIGDN_FILESYSPATH, &pwszPath)))
649 {
650 if ((pSep = PathFindFileNameW(pwszPath)) > pwszPath)
651 {
652 pSep[-1] = UNICODE_NULL;
653 pLink->SetWorkingDirectory(pwszPath);
654 }
655 SHFree(pwszPath);
656 }
657 }
658 }
659 if (SUCCEEDED(hr))
660 hr = ppf->Save(wszNewLnk, !fSourceIsLink);
662 {
663 SHELL_ErrorBox(m_hwndSite, hr);
664 break;
665 }
667 }
668 }
669 else
670 {
671 hr = _CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy);
672 }
673
674 SHFree(pidl);
675 _ILFreeaPidl(apidl, lpcida->cidl);
676 ReleaseStgMedium(&medium);
677 }
678 else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
679 {
680 FORMATETC fmt2;
681 InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
682 if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/)
683 {
684 WCHAR wszTargetPath[MAX_PATH + 1];
685 LPWSTR pszSrcList;
686
687 wcscpy(wszTargetPath, m_sPathTarget);
688 //Double NULL terminate.
689 wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
690
691 LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal);
692 if (!lpdf)
693 {
694 ERR("Error locking global\n");
695 return E_FAIL;
696 }
697 pszSrcList = (LPWSTR) (((byte*) lpdf) + lpdf->pFiles);
698 ERR("Source file (just the first) = %s, target path = %s, bCopy: %d\n", debugstr_w(pszSrcList), debugstr_w(wszTargetPath), bCopy);
699
701 ZeroMemory(&op, sizeof(op));
702 op.pFrom = pszSrcList;
703 op.pTo = wszTargetPath;
704 op.hwnd = m_hwndSite;
705 op.wFunc = bCopy ? FO_COPY : FO_MOVE;
707 int res = SHFileOperationW(&op);
708 if (res)
709 {
710 ERR("SHFileOperationW failed with 0x%x\n", res);
711 hr = E_FAIL;
712 }
713
714 return hr;
715 }
716 ERR("Error calling GetData\n");
717 hr = E_FAIL;
718 }
719 else
720 {
721 ERR("No viable drop format\n");
722 hr = E_FAIL;
723 }
724 return hr;
725}
726
728{
730 _DoDropData *data = static_cast<_DoDropData*>(lpParameter);
731 CComPtr<IDataObject> pDataObject;
733
734 if (SUCCEEDED(hr))
735 {
736 CComPtr<IAsyncOperation> pAsyncOperation;
737 hr = data->This->_DoDrop(pDataObject, data->dwKeyState, data->pt, &data->pdwEffect);
738 if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
739 {
740 pAsyncOperation->EndOperation(hr, NULL, data->pdwEffect);
741 }
742 }
743 //Release the CFSFolder and data object holds in the copying thread.
744 data->This->Release();
745 //Release the parameter from the heap.
748 return 0;
749}
750
752{
753 return ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut);
754}
BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
Definition: CBandSite.h:24
HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf)
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
#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:38
STDMETHOD() DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) override
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)
#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 CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
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:230
DWORD SHGetAttributes(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwAttributes)
Definition: utils.cpp:246
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:326
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:622
LPVOID WINAPI SHAlloc(SIZE_T len)
Definition: shellole.c:304
HRESULT WINAPI IUnknown_QueryService(IUnknown *, REFGUID, REFIID, LPVOID *)
Definition: ordinal.c:1501
HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
Definition: ordinal.c:1336
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 PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1777
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
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
unsigned int UINT
Definition: ndis.h:50
#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:2638
HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWSTR *ppszName)
Definition: pidl.c:1462
void _ILFreeaPidl(LPITEMIDLIST *apidl, UINT cidl)
Definition: pidl.c:2600
#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)
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define KeyStateToDropEffect(kst)
Definition: shell32_main.h:103
#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
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE *ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl)
Definition: shlfolder.cpp:396
EXTERN_C HRESULT WINAPI SHGetAttributesFromDataObject(IDataObject *pDataObject, DWORD dwAttributeMask, DWORD *pdwAttributes, UINT *pcItems)
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
Definition: shlfileop.cpp:1991
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 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:77
CFSDropTarget * This
Definition: CFSDropTarget.h:75
LPCWSTR pFrom
Definition: shellapi.h:357
FILEOP_FLAGS fFlags
Definition: shellapi.h:359
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:929
int ret
static HMENU hmenu
Definition: win.c:66
#define ZeroMemory
Definition: winbase.h:1736
#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