ReactOS  0.4.15-dev-4863-gba0d16f
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 /****************************************************************************
28  * BuildPathsList
29  *
30  * Builds a list of paths like the one used in SHFileOperation from a table of
31  * PIDLs relative to the given base folder
32  */
33 static WCHAR* BuildPathsList(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls)
34 {
35  WCHAR *pwszPathsList = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) * cidl + 1);
36  WCHAR *pwszListPos = pwszPathsList;
37 
38  for (int i = 0; i < cidl; i++)
39  {
40  FileStructW* pDataW = _ILGetFileStructW(pidls[i]);
41  if (!pDataW)
42  {
43  ERR("Mistreating a pidl:\n");
44  pdump_always(pidls[i]);
45  continue;
46  }
47 
48  PathCombineW(pwszListPos, wszBasePath, pDataW->wszName);
49  pwszListPos += wcslen(pwszListPos) + 1;
50  }
51  *pwszListPos = 0;
52  return pwszPathsList;
53 }
54 
55 /****************************************************************************
56  * CFSDropTarget::_CopyItems
57  *
58  * copies items to this folder
59  * FIXME: We should not ask the parent folder: 'What is your path', and then manually build paths assuming everything is a simple pidl!
60  * We should be asking the parent folder: Give me a full name for this pidl (for each child!)
61  */
63  LPCITEMIDLIST * apidl, BOOL bCopy)
64 {
65  LPWSTR pszSrcList;
66  HRESULT hr;
67  WCHAR wszTargetPath[MAX_PATH + 1];
68 
69  wcscpy(wszTargetPath, m_sPathTarget);
70  //Double NULL terminate.
71  wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
72 
73  TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom, cidl, apidl);
74 
75  STRRET strretFrom;
76  hr = pSFFrom->GetDisplayNameOf(NULL, SHGDN_FORPARSING, &strretFrom);
78  return hr;
79 
80  pszSrcList = BuildPathsList(strretFrom.pOleStr, cidl, apidl);
81  TRACE("Source file (just the first) = %s, target path = %s, bCopy: %d\n", debugstr_w(pszSrcList), debugstr_w(m_sPathTarget), bCopy);
82  CoTaskMemFree(strretFrom.pOleStr);
83  if (!pszSrcList)
84  return E_OUTOFMEMORY;
85 
86  SHFILEOPSTRUCTW op = {0};
87  op.pFrom = pszSrcList;
88  op.pTo = wszTargetPath;
89  op.hwnd = m_hwndSite;
90  op.wFunc = bCopy ? FO_COPY : FO_MOVE;
92 
93  int res = SHFileOperationW(&op);
94 
95  HeapFree(GetProcessHeap(), 0, pszSrcList);
96 
97  if (res)
98  {
99  ERR("SHFileOperationW failed with 0x%x\n", res);
100  return E_FAIL;
101  }
102  return S_OK;
103 }
104 
106  m_cfShellIDList(0),
107  m_fAcceptFmt(FALSE),
108  m_sPathTarget(NULL),
109  m_hwndSite(NULL),
110  m_grfKeyState(0)
111 {
112 }
113 
115 {
116  if (!PathTarget)
117  return E_UNEXPECTED;
118 
120  if (!m_cfShellIDList)
121  return E_FAIL;
122 
123  m_sPathTarget = (WCHAR *)SHAlloc((wcslen(PathTarget) + 1) * sizeof(WCHAR));
124  if (!m_sPathTarget)
125  return E_OUTOFMEMORY;
126 
127  wcscpy(m_sPathTarget, PathTarget);
128 
129  return S_OK;
130 }
131 
133 {
135 }
136 
137 BOOL
138 CFSDropTarget::_GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
139 {
140  WCHAR wszLink[40];
141 
142  if (!bShortcut)
143  {
144  if (!LoadStringW(shell32_hInstance, IDS_LNK_FILE, wszLink, _countof(wszLink)))
145  wszLink[0] = L'\0';
146  }
147 
148  if (!bShortcut)
149  swprintf(pwszTarget, L"%s%s%s", wszLink, pwszBasePath, pwszExt);
150  else
151  swprintf(pwszTarget, L"%s%s", pwszBasePath, pwszExt);
152 
153  for (UINT i = 2; PathFileExistsW(pwszTarget); ++i)
154  {
155  if (!bShortcut)
156  swprintf(pwszTarget, L"%s%s (%u)%s", wszLink, pwszBasePath, i, pwszExt);
157  else
158  swprintf(pwszTarget, L"%s (%u)%s", pwszBasePath, i, pwszExt);
159  }
160 
161  return TRUE;
162 }
163 
164 /****************************************************************************
165  * IDropTarget implementation
166  */
168 {
169  /* TODO Windows does different drop effects if dragging across drives.
170  i.e., it will copy instead of move if the directories are on different disks. */
171 
172  DWORD dwEffect = m_dwDefaultEffect;
173 
174  *pdwEffect = DROPEFFECT_NONE;
175 
176  if (m_fAcceptFmt) { /* Does our interpretation of the keystate ... */
177  *pdwEffect = KeyStateToDropEffect (dwKeyState);
178 
179  if (*pdwEffect == DROPEFFECT_NONE)
180  *pdwEffect = dwEffect;
181 
182  /* ... matches the desired effect ? */
183  if (dwEffect & *pdwEffect) {
184  return TRUE;
185  }
186  }
187  return FALSE;
188 }
189 
190 HRESULT CFSDropTarget::_GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects)
191 {
193  if (!hmenu)
194  return E_OUTOFMEMORY;
195 
197 
198  if ((dwAvailableEffects & DROPEFFECT_COPY) == 0)
200  else if ((dwAvailableEffects & DROPEFFECT_MOVE) == 0)
202  else if ((dwAvailableEffects & DROPEFFECT_LINK) == 0)
204 
205  if ((*pdwEffect & DROPEFFECT_COPY))
207  else if ((*pdwEffect & DROPEFFECT_MOVE))
209  else if ((*pdwEffect & DROPEFFECT_LINK))
211 
212  /* FIXME: We need to support shell extensions here */
213 
214  /* We shouldn't use the site window here because the menu should work even when we don't have a site */
215  HWND hwndDummy = CreateWindowEx(0,
216  WC_STATIC,
217  NULL,
219  pt.x,
220  pt.y,
221  1,
222  1,
223  NULL,
224  NULL,
225  NULL,
226  NULL);
227 
228  UINT uCommand = TrackPopupMenu(hpopupmenu,
230  pt.x, pt.y, 0, hwndDummy, NULL);
231 
232  DestroyWindow(hwndDummy);
233 
234  if (uCommand == 0)
235  return S_FALSE;
236  else if (uCommand == IDM_COPYHERE)
237  *pdwEffect = DROPEFFECT_COPY;
238  else if (uCommand == IDM_MOVEHERE)
239  *pdwEffect = DROPEFFECT_MOVE;
240  else if (uCommand == IDM_LINKHERE)
241  *pdwEffect = DROPEFFECT_LINK;
242 
243  return S_OK;
244 }
245 
247 {
248  CComPtr<IFolderView> pfv;
249  POINT ptDrag;
250  HRESULT hr = psfv->QueryInterface(IID_PPV_ARG(IFolderView, &pfv));
251  if (FAILED_UNEXPECTEDLY(hr))
252  return hr;
253 
254  hr = psfv->GetDragPoint(&ptDrag);
255  if (FAILED_UNEXPECTEDLY(hr))
256  return hr;
257 
258  PIDLIST_ABSOLUTE pidlFolder;
259  PUITEMID_CHILD *apidl;
260  UINT cidl;
261  hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl);
262  if (FAILED_UNEXPECTEDLY(hr))
263  return hr;
264 
265  CComHeapPtr<POINT> apt;
266  if (!apt.Allocate(cidl))
267  {
268  SHFree(pidlFolder);
269  _ILFreeaPidl(apidl, cidl);
270  return E_OUTOFMEMORY;
271  }
272 
273  for (UINT i = 0; i<cidl; i++)
274  {
275  pfv->GetItemPosition(apidl[i], &apt[i]);
276  apt[i].x += pt.x - ptDrag.x;
277  apt[i].y += pt.y - ptDrag.y;
278  }
279 
280  pfv->SelectAndPositionItems(cidl, apidl, apt, SVSI_SELECT);
281 
282  SHFree(pidlFolder);
283  _ILFreeaPidl(apidl, cidl);
284  return S_OK;
285 }
286 
288  DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
289 {
290  TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
291 
292  if (*pdwEffect == DROPEFFECT_NONE)
293  return S_OK;
294 
295  FORMATETC fmt;
296  FORMATETC fmt2;
298 
299  InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
300  InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
301 
302  if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
303  m_fAcceptFmt = TRUE;
304  else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
305  m_fAcceptFmt = TRUE;
306 
307  m_grfKeyState = dwKeyState;
308 
309 #define D_NONE DROPEFFECT_NONE
310 #define D_COPY DROPEFFECT_COPY
311 #define D_MOVE DROPEFFECT_MOVE
312 #define D_LINK DROPEFFECT_LINK
313  m_dwDefaultEffect = *pdwEffect;
314  switch (*pdwEffect & (D_COPY | D_MOVE | D_LINK))
315  {
316  case D_COPY | D_MOVE:
317  if (dwKeyState & MK_CONTROL)
319  else
321  break;
322  case D_COPY | D_MOVE | D_LINK:
323  if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
325  else if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == MK_CONTROL)
327  else
329  break;
330  case D_COPY | D_LINK:
331  if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
333  else
335  break;
336  case D_MOVE | D_LINK:
337  if ((dwKeyState & (MK_SHIFT | MK_CONTROL)) == (MK_SHIFT | MK_CONTROL))
339  else
341  break;
342  }
343 
344  STGMEDIUM medium;
345  if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)))
346  {
347  WCHAR wstrFirstFile[MAX_PATH];
348  if (DragQueryFileW((HDROP)medium.hGlobal, 0, wstrFirstFile, _countof(wstrFirstFile)))
349  {
350  /* Check if the drive letter is different */
351  if (wstrFirstFile[0] != m_sPathTarget[0])
352  {
354  }
355  }
356  ReleaseStgMedium(&medium);
357  }
358 
359  if (!m_fAcceptFmt)
360  *pdwEffect = DROPEFFECT_NONE;
361  else
362  *pdwEffect = m_dwDefaultEffect;
363 
364  return S_OK;
365 }
366 
368  DWORD *pdwEffect)
369 {
370  TRACE("(%p)\n", this);
371 
372  if (!pdwEffect)
373  return E_INVALIDARG;
374 
375  m_grfKeyState = dwKeyState;
376 
377  _QueryDrop(dwKeyState, pdwEffect);
378 
379  return S_OK;
380 }
381 
383 {
384  TRACE("(%p)\n", this);
385 
387 
388  return S_OK;
389 }
390 
392  DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
393 {
394  TRACE("(%p) object dropped, effect %u\n", this, *pdwEffect);
395 
396  if (!pdwEffect)
397  return E_INVALIDARG;
398 
400 
401  DWORD dwAvailableEffects = *pdwEffect;
402 
403  _QueryDrop(dwKeyState, pdwEffect);
404 
405  TRACE("pdwEffect: 0x%x, m_dwDefaultEffect: 0x%x, dwAvailableEffects: 0x%x\n", *pdwEffect, m_dwDefaultEffect, dwAvailableEffects);
406 
408  {
409  HRESULT hr = _GetEffectFromMenu(pDataObject, pt, pdwEffect, dwAvailableEffects);
410  if (FAILED_UNEXPECTEDLY(hr) || hr == S_FALSE)
411  return hr;
412  }
413 
414  if (*pdwEffect == DROPEFFECT_MOVE && m_site)
415  {
416  CComPtr<IShellFolderView> psfv;
417  HRESULT hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellFolderView, &psfv));
418  if (SUCCEEDED(hr) && psfv->IsDropOnSource(this) == S_OK)
419  {
420  _RepositionItems(psfv, pDataObject, pt);
421  return S_OK;
422  }
423  }
424 
425  BOOL fIsOpAsync = FALSE;
426  CComPtr<IAsyncOperation> pAsyncOperation;
427 
428  if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
429  {
430  if (SUCCEEDED(pAsyncOperation->GetAsyncMode(&fIsOpAsync)) && fIsOpAsync)
431  {
432  _DoDropData *data = static_cast<_DoDropData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(_DoDropData)));
433  data->This = this;
434  // Need to maintain this class in case the window is closed or the class exists temporarily (when dropping onto a folder).
435  pDataObject->AddRef();
436  pAsyncOperation->StartOperation(NULL);
438  this->AddRef();
439  data->dwKeyState = dwKeyState;
440  data->pt = pt;
441  // Need to dereference as pdweffect gets freed.
442  data->pdwEffect = *pdwEffect;
444  return S_OK;
445  }
446  }
447  return this->_DoDrop(pDataObject, dwKeyState, pt, pdwEffect);
448 }
449 
450 HRESULT
451 WINAPI
453 {
454  m_site = pUnkSite;
455  return S_OK;
456 }
457 
458 HRESULT
459 WINAPI
461 {
462  if (!m_site)
463  return E_FAIL;
464 
465  return m_site->QueryInterface(riid, ppvSite);
466 }
467 
469  DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
470 {
471  TRACE("(%p) performing drop, effect %u\n", this, *pdwEffect);
472  FORMATETC fmt;
473  FORMATETC fmt2;
474  STGMEDIUM medium;
475 
476  InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
477  InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
478 
479  HRESULT hr;
480  bool bCopy = TRUE;
481  bool bLinking = FALSE;
482 
483  /* Figure out what drop operation we're doing */
484  if (pdwEffect)
485  {
486  TRACE("Current drop effect flag %i\n", *pdwEffect);
487  if ((*pdwEffect & DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
488  bCopy = FALSE;
489  if ((*pdwEffect & DROPEFFECT_LINK) == DROPEFFECT_LINK)
490  bLinking = TRUE;
491  }
492 
493  if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
494  {
495  hr = pDataObject->GetData(&fmt, &medium);
496  TRACE("CFSTR_SHELLIDLIST.\n");
497  if (FAILED(hr))
498  {
499  ERR("CFSTR_SHELLIDLIST failed\n");
500  }
501  /* lock the handle */
502  LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
503  if (!lpcida)
504  {
505  ReleaseStgMedium(&medium);
506  return E_FAIL;
507  }
508 
509  /* convert the data into pidl */
510  LPITEMIDLIST pidl;
511  LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
512  if (!apidl)
513  {
514  ReleaseStgMedium(&medium);
515  return E_FAIL;
516  }
517 
518  CComPtr<IShellFolder> psfDesktop;
519  CComPtr<IShellFolder> psfFrom = NULL;
520 
521  /* Grab the desktop shell folder */
522  hr = SHGetDesktopFolder(&psfDesktop);
523  if (FAILED(hr))
524  {
525  ERR("SHGetDesktopFolder failed\n");
526  SHFree(pidl);
527  _ILFreeaPidl(apidl, lpcida->cidl);
528  ReleaseStgMedium(&medium);
529  return E_FAIL;
530  }
531 
532  /* Find source folder, this is where the clipboard data was copied from */
533  if (_ILIsDesktop(pidl))
534  {
535  /* use desktop shell folder */
536  psfFrom = psfDesktop;
537  }
538  else
539  {
540  hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfFrom));
541  if (FAILED(hr))
542  {
543  ERR("no IShellFolder\n");
544  SHFree(pidl);
545  _ILFreeaPidl(apidl, lpcida->cidl);
546  ReleaseStgMedium(&medium);
547  return E_FAIL;
548  }
549  }
550 
551  if (bLinking)
552  {
553  WCHAR wszPath[MAX_PATH];
554  WCHAR wszTarget[MAX_PATH];
555 
556  TRACE("target path = %s\n", debugstr_w(m_sPathTarget));
557 
558  /* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */
559  for (UINT i = 0; i < lpcida->cidl; i++)
560  {
561  // Find out which file we're linking.
562  STRRET strFile;
563  hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strFile);
564  if (FAILED_UNEXPECTEDLY(hr))
565  break;
566 
567  hr = StrRetToBufW(&strFile, apidl[i], wszPath, _countof(wszPath));
568  if (FAILED_UNEXPECTEDLY(hr))
569  break;
570 
571  TRACE("source path = %s\n", debugstr_w(wszPath));
572 
573  WCHAR wszDisplayName[MAX_PATH];
574  LPWSTR pwszFileName = PathFindFileNameW(wszPath);
575  if (PathIsRootW(wszPath)) // Drive?
576  {
577  hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_NORMAL, &strFile);
578  if (FAILED_UNEXPECTEDLY(hr))
579  break;
580 
581  hr = StrRetToBufW(&strFile, apidl[i], wszDisplayName, _countof(wszDisplayName));
582  if (FAILED_UNEXPECTEDLY(hr))
583  break;
584 
585  // Delete a ':' in wszDisplayName.
586  LPWSTR pch0 = wcschr(wszDisplayName, L':');
587  if (pch0)
588  {
589  do
590  {
591  *pch0 = *(pch0 + 1);
592  ++pch0;
593  } while (*pch0);
594  }
595 
596  pwszFileName = wszDisplayName; // Use wszDisplayName
597  }
598  else if (wszPath[0] == L':' && wszPath[1] == L':') // ::{GUID}?
599  {
600  CLSID clsid;
601  hr = ::CLSIDFromString(&wszPath[2], &clsid);
602  if (SUCCEEDED(hr))
603  {
604  LPITEMIDLIST pidl = ILCreateFromPathW(wszPath);
605  if (pidl)
606  {
607  SHFILEINFOW fi = { NULL };
608  SHGetFileInfoW((LPCWSTR)pidl, 0, &fi, sizeof(fi),
610  if (fi.szDisplayName[0])
611  {
612  lstrcpynW(wszDisplayName, fi.szDisplayName, _countof(wszDisplayName));
613  pwszFileName = wszDisplayName; // Use wszDisplayName
614  }
615  ILFree(pidl);
616  }
617  }
618  }
619 
620  // Creating a buffer to hold the combined path.
621  WCHAR wszCombined[MAX_PATH];
622  PathCombineW(wszCombined, m_sPathTarget, pwszFileName);
623 
624  // Check to see if the source is a link
625  BOOL fSourceIsLink = FALSE;
626  if (!wcsicmp(PathFindExtensionW(wszPath), L".lnk"))
627  {
628  fSourceIsLink = TRUE;
629  PathRemoveExtensionW(wszCombined);
630  }
631 
632  // Create a pathname to save the new link.
633  _GetUniqueFileName(wszCombined, L".lnk", wszTarget, TRUE);
634 
635  CComPtr<IPersistFile> ppf;
636  if (fSourceIsLink)
637  {
639  if (FAILED_UNEXPECTEDLY(hr))
640  break;
641  }
642  else
643  {
644  CComPtr<IShellLinkW> pLink;
645  hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink));
646  if (FAILED_UNEXPECTEDLY(hr))
647  break;
648 
649  WCHAR szDirPath[MAX_PATH], *pwszFile;
650  GetFullPathName(wszPath, MAX_PATH, szDirPath, &pwszFile);
651  if (pwszFile)
652  pwszFile[0] = 0;
653 
654  hr = pLink->SetPath(wszPath);
655  if (FAILED_UNEXPECTEDLY(hr))
656  break;
657 
658  hr = pLink->SetWorkingDirectory(szDirPath);
659  if (FAILED_UNEXPECTEDLY(hr))
660  break;
661 
662  hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
663  if (FAILED_UNEXPECTEDLY(hr))
664  break;
665  }
666 
667  hr = ppf->Save(wszTarget, !fSourceIsLink);
668  if (FAILED_UNEXPECTEDLY(hr))
669  break;
670 
672  }
673  }
674  else
675  {
676  hr = _CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy);
677  }
678 
679  SHFree(pidl);
680  _ILFreeaPidl(apidl, lpcida->cidl);
681  ReleaseStgMedium(&medium);
682  }
683  else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
684  {
685  FORMATETC fmt2;
686  InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
687  if (SUCCEEDED(pDataObject->GetData(&fmt2, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/)
688  {
689  WCHAR wszTargetPath[MAX_PATH + 1];
690  LPWSTR pszSrcList;
691 
692  wcscpy(wszTargetPath, m_sPathTarget);
693  //Double NULL terminate.
694  wszTargetPath[wcslen(wszTargetPath) + 1] = '\0';
695 
696  LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal);
697  if (!lpdf)
698  {
699  ERR("Error locking global\n");
700  return E_FAIL;
701  }
702  pszSrcList = (LPWSTR) (((byte*) lpdf) + lpdf->pFiles);
703  ERR("Source file (just the first) = %s, target path = %s, bCopy: %d\n", debugstr_w(pszSrcList), debugstr_w(wszTargetPath), bCopy);
704 
706  ZeroMemory(&op, sizeof(op));
707  op.pFrom = pszSrcList;
708  op.pTo = wszTargetPath;
709  op.hwnd = m_hwndSite;
710  op.wFunc = bCopy ? FO_COPY : FO_MOVE;
712  int res = SHFileOperationW(&op);
713  if (res)
714  {
715  ERR("SHFileOperationW failed with 0x%x\n", res);
716  hr = E_FAIL;
717  }
718 
719  return hr;
720  }
721  ERR("Error calling GetData\n");
722  hr = E_FAIL;
723  }
724  else
725  {
726  ERR("No viable drop format.\n");
727  hr = E_FAIL;
728  }
729  return hr;
730 }
731 
733 {
735  _DoDropData *data = static_cast<_DoDropData*>(lpParameter);
736  CComPtr<IDataObject> pDataObject;
738 
739  if (SUCCEEDED(hr))
740  {
741  CComPtr<IAsyncOperation> pAsyncOperation;
742  hr = data->This->_DoDrop(pDataObject, data->dwKeyState, data->pt, &data->pdwEffect);
743  if (SUCCEEDED(pDataObject->QueryInterface(IID_PPV_ARG(IAsyncOperation, &pAsyncOperation))))
744  {
745  pAsyncOperation->EndOperation(hr, NULL, data->pdwEffect);
746  }
747  }
748  //Release the CFSFolder and data object holds in the copying thread.
749  data->This->Release();
750  //Release the parameter from the heap.
752  CoUninitialize();
753  return 0;
754 }
755 
757 {
758  return ShellObjectCreatorInit<CFSDropTarget>(sPathTarget, riid, ppvOut);
759 }
virtual HRESULT WINAPI Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
LPWSTR m_sPathTarget
Definition: CFSDropTarget.h:34
#define WS_DISABLED
Definition: pedump.c:621
struct _DROPFILES * LPDROPFILES
#define REFIID
Definition: guiddef.h:118
void WINAPI ILFree(LPITEMIDLIST pidl)
Definition: pidl.c:925
#define MK_SHIFT
Definition: winuser.h:2349
#define D_LINK
#define MF_BYCOMMAND
Definition: winuser.h:202
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
#define IDM_LINKHERE
Definition: shresdef.h:844
long y
Definition: polytest.cpp:48
HRESULT CFSDropTarget_CreateInstance(LPWSTR sPathTarget, REFIID riid, LPVOID *ppvOut)
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite)
#define CFSTR_SHELLIDLIST
Definition: shlobj.h:477
CComPtr< IUnknown > m_site
Definition: CFSDropTarget.h:38
HRESULT hr
Definition: shlfolder.c:183
static HMENU hmenu
Definition: win.c:66
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
long x
Definition: polytest.cpp:48
#define InitFormatEtc(fe, cf, med)
Definition: editor.h:32
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
#define TRUE
Definition: types.h:120
#define pt(x, y)
Definition: drawing.c:79
#define TPM_LEFTALIGN
Definition: winuser.h:2357
WINE_DEFAULT_DEBUG_CHANNEL(shell)
REFIID riid
Definition: precomp.h:44
UINT WINAPI RegisterClipboardFormatW(_In_ LPCWSTR)
#define FO_COPY
Definition: shellapi.h:134
#define TPM_RETURNCMD
Definition: winuser.h:2367
HRESULT WINAPI StrRetToBufW(LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, UINT len)
Definition: string.c:1522
WCHAR wszName[1]
Definition: shlfolder.c:1555
ITEMID_CHILD UNALIGNED * PUITEMID_CHILD
Definition: shtypes.idl:68
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
const char * fmt
Definition: wsprintf.c:30
HRESULT WINAPI CoGetInterfaceAndReleaseStream(LPSTREAM pStm, REFIID riid, LPVOID *ppv)
Definition: marshal.c:2144
HRESULT _CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy)
LPWSTR pOleStr
Definition: shtypes.idl:96
#define FOF_ALLOWUNDO
Definition: shellapi.h:144
HRESULT GetData([in, unique] FORMATETC *pformatetcIn, [out] STGMEDIUM *pmedium)
#define ZeroMemory
Definition: winbase.h:1667
const GUID IID_IDataObject
#define SID_IFolderView
#define IID_PPV_ARG(Itype, ppType)
#define E_FAIL
Definition: ddrawi.h:102
HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
Definition: ordinal.c:1329
virtual HRESULT WINAPI DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
BOOL WINAPI DestroyWindow(_In_ HWND)
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
Definition: shlfileop.cpp:1982
HRESULT WINAPI IUnknown_QueryService(IUnknown *, REFGUID, REFIID, LPVOID *)
Definition: ordinal.c:1494
LPITEMIDLIST * _ILCopyCidaToaPidl(LPITEMIDLIST *pidl, const CIDA *cida)
Definition: pidl.c:2684
#define lstrcpynW
Definition: compat.h:597
static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter)
const DWORD DROPEFFECT_COPY
Definition: oleidl.idl:930
#define FO_MOVE
Definition: shellapi.h:133
HRESULT GetDisplayNameOf([in] PCUITEMID_CHILD pidl, [in] SHGDNF uFlags, [out] STRRET *lpName)
#define IDM_DRAGFILE
Definition: shresdef.h:841
const DWORD DROPEFFECT_NONE
Definition: oleidl.idl:929
#define TPM_RIGHTBUTTON
Definition: winuser.h:2360
#define L(x)
Definition: ntvdm.h:50
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
void pdump_always(LPCITEMIDLIST pidl)
Definition: debughlp.cpp:319
#define FALSE
Definition: types.h:117
void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
Definition: path.c:823
#define WC_STATIC
Definition: commctrl.h:4682
unsigned int BOOL
Definition: ntddk_ex.h:94
virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite)
if SUCCEEDED(hr)
#define debugstr_w
Definition: kernel32.h:32
#define SHGFI_PIDL
Definition: shellapi.h:178
#define SS_LEFT
Definition: pedump.c:692
#define CreateWindowEx
Definition: winuser.h:5735
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE *ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl)
Definition: shlfolder.cpp:345
#define KeyStateToDropEffect(kst)
Definition: shell32_main.h:95
#define CF_HDROP
Definition: constants.h:410
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
#define SHGFI_DISPLAYNAME
Definition: shellapi.h:164
HRESULT _GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects)
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1776
static HMENU hpopupmenu
Definition: msg.c:17314
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:447
#define MK_RBUTTON
Definition: winuser.h:2348
BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
Definition: CBandSite.h:24
UINT m_cfShellIDList
Definition: CFSDropTarget.h:32
#define D_COPY
BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
Definition: path.c:1641
#define TRACE(s)
Definition: solgame.cpp:4
HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf)
#define WS_OVERLAPPED
Definition: pedump.c:615
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
#define D_MOVE
__wchar_t WCHAR
Definition: xmlstorage.h:180
DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path, DWORD dwFileAttributes, SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
Definition: shell32_main.c:414
LONG HRESULT
Definition: typedefs.h:79
BOOL _QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
BOOL WINAPI DeleteMenu(_In_ HMENU, _In_ UINT, _In_ UINT)
#define _countof(array)
Definition: sndvol32.h:68
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:82
#define MAX_PATH
Definition: compat.h:34
virtual HRESULT WINAPI DragLeave()
#define WINAPI
Definition: msvc.h:6
const DWORD DROPEFFECT_LINK
Definition: oleidl.idl:932
struct CIDA * LPIDA
UINT cidl
Definition: shlobj.h:499
unsigned long DWORD
Definition: ntddk_ex.h:95
UINT op
Definition: effect.c:236
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define TPM_NONOTIFY
Definition: winuser.h:2366
ULONG AddRef()
#define IDM_COPYHERE
Definition: shresdef.h:842
HRESULT _RepositionItems(IShellFolderView *psfv, IDataObject *pDataObject, POINTL pt)
#define wcsicmp
Definition: compat.h:15
HRESULT _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
EXTERN_C void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
REFCLSID clsid
Definition: msctf.c:82
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
DWORD m_dwDefaultEffect
Definition: CFSDropTarget.h:37
WCHAR szDisplayName[MAX_PATH]
Definition: shellapi.h:373
#define GetFullPathName
Definition: winbase.h:3682
BOOL _GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
int _cdecl swprintf(const WCHAR *,...)
#define IDS_LNK_FILE
Definition: shresdef.h:174
DWORD dwKeyState
Definition: CFSDropTarget.h:77
void _ILFreeaPidl(LPITEMIDLIST *apidl, UINT cidl)
Definition: pidl.c:2646
#define SHCNF_PATHW
Definition: shlobj.h:1764
HRESULT Initialize(LPWSTR PathTarget)
#define IDM_MOVEHERE
Definition: shresdef.h:843
#define ERR(fmt,...)
Definition: debug.h:110
HRESULT WINAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, LPUNKNOWN pUnk, LPSTREAM *ppStm)
Definition: marshal.c:2100
#define S_OK
Definition: intsafe.h:52
#define shell32_hInstance
#define WS_BORDER
Definition: pedump.c:625
static WCHAR * BuildPathsList(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls)
FileStructW * _ILGetFileStructW(LPCITEMIDLIST pidl)
Definition: pidl.c:2361
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
const DWORD DROPEFFECT_MOVE
Definition: oleidl.idl:931
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
HRESULT QueryGetData([in, unique] FORMATETC *pformatetc)
virtual HRESULT WINAPI DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
#define MK_CONTROL
Definition: winuser.h:2350
BOOL WINAPI SetMenuDefaultItem(_In_ HMENU, _In_ UINT, _In_ UINT)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define E_UNEXPECTED
Definition: winerror.h:2456
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:326
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
GLuint res
Definition: glext.h:9613
#define TPM_LEFTBUTTON
Definition: winuser.h:2359
uint32_t * LPDWORD
Definition: typedefs.h:59
HMENU WINAPI LoadMenuW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2338
DWORD m_grfKeyState
Definition: CFSDropTarget.h:36
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define SHCNE_CREATE
Definition: shlobj.h:1730
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:982
WCHAR * LPWSTR
Definition: xmlstorage.h:184
LPWSTR WINAPI PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile)
Definition: path.c:194
BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, VOID *pData, DWORD dwFlags, LPTHREAD_START_ROUTINE pfnCallback)
Definition: thread.c:356
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:622
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
#define FOF_NOCONFIRMMKDIR
Definition: shellapi.h:147
BOOL WINAPI TrackPopupMenu(_In_ HMENU, _In_ UINT, _In_ int, _In_ int, _Reserved_ int, _In_ HWND, _Reserved_ LPCRECT)
Definition: dsound.c:943
LPVOID WINAPI SHAlloc(SIZE_T len)
Definition: shellole.c:304
#define HeapFree(x, y, z)
Definition: compat.h:594
Definition: shlobj.h:498