Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

418 lines
9.7 KiB

  1. /**************************************************************************
  2. THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright 1998 Microsoft Corporation. All Rights Reserved.
  7. **************************************************************************/
  8. /**************************************************************************
  9. File: DropTgt.cpp
  10. Description: Implements CDropTarget.
  11. **************************************************************************/
  12. /**************************************************************************
  13. #include statements
  14. **************************************************************************/
  15. #include "DropTgt.h"
  16. #include "Utility.h"
  17. /**************************************************************************
  18. CDropTarget::CDropTarget()
  19. **************************************************************************/
  20. CDropTarget::CDropTarget(CShellFolder *psfParent)
  21. {
  22. g_DllRefCount++;
  23. m_psfParent = psfParent;
  24. if(m_psfParent)
  25. m_psfParent->AddRef();
  26. else
  27. {
  28. delete this;
  29. return;
  30. }
  31. m_pPidlMgr = new CPidlMgr();
  32. if(!m_pPidlMgr)
  33. {
  34. delete this;
  35. return;
  36. }
  37. SHGetMalloc(&m_pMalloc);
  38. if(!m_pMalloc)
  39. {
  40. delete this;
  41. return;
  42. }
  43. m_ObjRefCount = 1;
  44. m_fAcceptFmt = FALSE;
  45. m_cfPrivateData = RegisterClipboardFormat(CFSTR_SAMPVIEWDATA);
  46. }
  47. /**************************************************************************
  48. CDropTarget::~CDropTarget()
  49. **************************************************************************/
  50. CDropTarget::~CDropTarget()
  51. {
  52. if(m_psfParent)
  53. m_psfParent->Release();
  54. if(m_pPidlMgr)
  55. delete m_pPidlMgr;
  56. if(m_pMalloc)
  57. m_pMalloc->Release();
  58. g_DllRefCount--;
  59. }
  60. ///////////////////////////////////////////////////////////////////////////
  61. //
  62. // IUnknown Implementation
  63. //
  64. /**************************************************************************
  65. CDropTarget::QueryInterface()
  66. **************************************************************************/
  67. STDMETHODIMP CDropTarget::QueryInterface(REFIID riid, LPVOID *ppReturn)
  68. {
  69. *ppReturn = NULL;
  70. //IUnknown
  71. if(IsEqualIID(riid, IID_IUnknown))
  72. {
  73. *ppReturn = this;
  74. }
  75. //IDropTarget
  76. else if(IsEqualIID(riid, IID_IDropTarget))
  77. {
  78. *ppReturn = (IDropTarget*)this;
  79. }
  80. if(*ppReturn)
  81. {
  82. (*(LPUNKNOWN*)ppReturn)->AddRef();
  83. return S_OK;
  84. }
  85. return E_NOINTERFACE;
  86. }
  87. /**************************************************************************
  88. CDropTarget::AddRef()
  89. **************************************************************************/
  90. STDMETHODIMP_(DWORD) CDropTarget::AddRef(VOID)
  91. {
  92. return ++m_ObjRefCount;
  93. }
  94. /**************************************************************************
  95. CDropTarget::Release()
  96. **************************************************************************/
  97. STDMETHODIMP_(DWORD) CDropTarget::Release(VOID)
  98. {
  99. if(--m_ObjRefCount == 0)
  100. {
  101. delete this;
  102. return 0;
  103. }
  104. return m_ObjRefCount;
  105. }
  106. ///////////////////////////////////////////////////////////////////////////
  107. //
  108. // IDropTarget Implementation
  109. //
  110. /**************************************************************************
  111. CDropTarget::DragEnter()
  112. **************************************************************************/
  113. STDMETHODIMP CDropTarget::DragEnter( LPDATAOBJECT pDataObj,
  114. DWORD dwKeyState,
  115. POINTL pt,
  116. LPDWORD pdwEffect)
  117. {
  118. FORMATETC fmtetc;
  119. fmtetc.cfFormat = m_cfPrivateData;
  120. fmtetc.ptd = NULL;
  121. fmtetc.dwAspect = DVASPECT_CONTENT;
  122. fmtetc.lindex = -1;
  123. fmtetc.tymed = TYMED_HGLOBAL;
  124. //does the drag source provide our data type?
  125. m_fAcceptFmt = (S_OK == pDataObj->QueryGetData(&fmtetc)) ? TRUE : FALSE;
  126. QueryDrop(dwKeyState, pdwEffect);
  127. return S_OK;
  128. }
  129. /**************************************************************************
  130. CDropTarget::DragOver()
  131. **************************************************************************/
  132. STDMETHODIMP CDropTarget::DragOver(DWORD dwKeyState, POINTL pt, LPDWORD pdwEffect)
  133. {
  134. QueryDrop(dwKeyState, pdwEffect);
  135. return S_OK;
  136. }
  137. /**************************************************************************
  138. CDropTarget::DragLeave()
  139. **************************************************************************/
  140. STDMETHODIMP CDropTarget::DragLeave(VOID)
  141. {
  142. m_fAcceptFmt = FALSE;
  143. return S_OK;
  144. }
  145. /**************************************************************************
  146. CDropTarget::Drop()
  147. **************************************************************************/
  148. STDMETHODIMP CDropTarget::Drop( LPDATAOBJECT pDataObj,
  149. DWORD dwKeyState,
  150. POINTL pt,
  151. LPDWORD pdwEffect)
  152. {
  153. HRESULT hr = E_FAIL;
  154. if(QueryDrop(dwKeyState, pdwEffect))
  155. {
  156. FORMATETC fmtetc;
  157. STGMEDIUM medium;
  158. fmtetc.cfFormat = m_cfPrivateData;
  159. fmtetc.ptd = NULL;
  160. fmtetc.dwAspect = DVASPECT_CONTENT;
  161. fmtetc.lindex = -1;
  162. fmtetc.tymed = TYMED_HGLOBAL;
  163. //The user has dropped on us. Get the data from the data object.
  164. hr = pDataObj->GetData(&fmtetc, &medium);
  165. if(SUCCEEDED(hr))
  166. {
  167. DoDrop(medium.hGlobal, DROPEFFECT_MOVE == *pdwEffect);
  168. //release the STGMEDIUM
  169. ReleaseStgMedium(&medium);
  170. return S_OK;
  171. }
  172. }
  173. *pdwEffect = DROPEFFECT_NONE;
  174. return hr;
  175. }
  176. /**************************************************************************
  177. CDropTarget::QueryDrop()
  178. **************************************************************************/
  179. BOOL CDropTarget::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
  180. {
  181. DWORD dwOKEffects = *pdwEffect;
  182. *pdwEffect = DROPEFFECT_NONE;
  183. if(m_fAcceptFmt)
  184. {
  185. *pdwEffect = GetDropEffectFromKeyState(dwKeyState);
  186. //we don't accept links
  187. if(DROPEFFECT_LINK == *pdwEffect)
  188. *pdwEffect = DROPEFFECT_NONE;
  189. /*
  190. Check if the drag source application allows the drop effect desired by the
  191. user. The drag source specifies this in DoDragDrop.
  192. */
  193. if(*pdwEffect & dwOKEffects)
  194. return TRUE;
  195. }
  196. return FALSE;
  197. }
  198. /**************************************************************************
  199. CDropTarget::GetDropEffectFromKeyState()
  200. **************************************************************************/
  201. DWORD CDropTarget::GetDropEffectFromKeyState(DWORD dwKeyState)
  202. {
  203. //move is the default
  204. DWORD dwDropEffect = DROPEFFECT_MOVE;
  205. if(dwKeyState & MK_CONTROL)
  206. {
  207. if(dwKeyState & MK_SHIFT)
  208. {
  209. dwDropEffect = DROPEFFECT_LINK;
  210. }
  211. else
  212. {
  213. dwDropEffect = DROPEFFECT_COPY;
  214. }
  215. }
  216. return dwDropEffect;
  217. }
  218. /**************************************************************************
  219. CDropTarget::DoDrop()
  220. **************************************************************************/
  221. BOOL CDropTarget::DoDrop(HGLOBAL hMem, BOOL fCut)
  222. {
  223. BOOL fSuccess = FALSE;
  224. if(hMem)
  225. {
  226. LPPRIVCLIPDATA pData = (LPPRIVCLIPDATA)GlobalLock(hMem);
  227. if(pData)
  228. {
  229. CShellFolder *psfFrom = NULL;
  230. IShellFolder *psfDesktop;
  231. LPITEMIDLIST pidl;
  232. pidl = (LPITEMIDLIST)((LPBYTE)(pData) + pData->aoffset[0]);
  233. /*
  234. This is a fully qualified PIDL, so use the desktop folder to get the
  235. IShellFolder for this folder.
  236. */
  237. SHGetDesktopFolder(&psfDesktop);
  238. if(psfDesktop)
  239. {
  240. psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (LPVOID*)&psfFrom);
  241. psfDesktop->Release();
  242. }
  243. if(psfFrom)
  244. {
  245. LPITEMIDLIST *aPidls;
  246. //allocate an array of PIDLS
  247. aPidls = AllocPidlTable(pData->cidl - 1);
  248. if(aPidls)
  249. {
  250. UINT i;
  251. //fill in the PIDL array
  252. for(i = 0; i < pData->cidl - 1; i++)
  253. {
  254. aPidls[i] = m_pPidlMgr->Copy((LPITEMIDLIST)((LPBYTE)(pData) + pData->aoffset[i + 1]));
  255. }
  256. if(SUCCEEDED(m_psfParent->CopyItems(psfFrom, aPidls, pData->cidl - 1)))
  257. {
  258. fSuccess = TRUE;
  259. if(fCut)
  260. {
  261. psfFrom->DeleteItems(aPidls, pData->cidl - 1);
  262. }
  263. }
  264. FreePidlTable(aPidls);
  265. }
  266. psfFrom->Release();
  267. }
  268. GlobalUnlock(hMem);
  269. }
  270. }
  271. return fSuccess;
  272. }
  273. /**************************************************************************
  274. CDropTarget::AllocPidlTable()
  275. **************************************************************************/
  276. LPITEMIDLIST* CDropTarget::AllocPidlTable(DWORD dwEntries)
  277. {
  278. LPITEMIDLIST *aPidls;
  279. dwEntries++;
  280. aPidls = (LPITEMIDLIST*)m_pMalloc->Alloc(dwEntries * sizeof(LPITEMIDLIST));
  281. if(aPidls)
  282. {
  283. //set all of the entries to NULL
  284. ZeroMemory(aPidls, dwEntries * sizeof(LPITEMIDLIST));
  285. }
  286. return aPidls;
  287. }
  288. /**************************************************************************
  289. CDropTarget::FreePidlTable()
  290. **************************************************************************/
  291. VOID CDropTarget::FreePidlTable(LPITEMIDLIST *aPidls)
  292. {
  293. if(aPidls && m_pPidlMgr)
  294. {
  295. UINT i;
  296. for(i = 0; aPidls[i]; i++)
  297. m_pPidlMgr->Delete(aPidls[i]);
  298. m_pMalloc->Free(aPidls);
  299. }
  300. }