OSDN Git Service

merge original branch.
[tortoisegit/TortoiseGitJp.git] / src / Utils / DragDropImpl.cpp
1 /**************************************************************************\r
2    THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF\r
3    ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO\r
4    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A\r
5    PARTICULAR PURPOSE.\r
6    Author: Leon Finker  1/2001\r
7 **************************************************************************/\r
8 // IDataObjectImpl.cpp: implementation of the CIDataObjectImpl class.\r
9 //////////////////////////////////////////////////////////////////////\r
10 #include <stdafx.h>\r
11 #include <shlobj.h>\r
12 #include <atlbase.h>\r
13 #include "DragDropImpl.h"\r
14 \r
15 //////////////////////////////////////////////////////////////////////\r
16 // CIDataObject Class\r
17 //////////////////////////////////////////////////////////////////////\r
18 \r
19 CIDataObject::CIDataObject(CIDropSource* pDropSource):\r
20 m_cRefCount(0), m_pDropSource(pDropSource)\r
21 {\r
22 }\r
23 \r
24 CIDataObject::~CIDataObject()\r
25 {\r
26         for(int i = 0; i < m_StgMedium.GetSize(); ++i)\r
27         {\r
28                 ReleaseStgMedium(m_StgMedium[i]);\r
29                 delete m_StgMedium[i];\r
30         }\r
31         for(int j = 0; j < m_ArrFormatEtc.GetSize(); ++j)\r
32                 delete m_ArrFormatEtc[j];\r
33 }\r
34 \r
35 STDMETHODIMP CIDataObject::QueryInterface(/* [in] */ REFIID riid,\r
36 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)\r
37 {\r
38         *ppvObject = NULL;\r
39         if (IID_IUnknown==riid || IID_IDataObject==riid)\r
40              *ppvObject=this;\r
41         /*if(riid == IID_IAsyncOperation)\r
42                 *ppvObject=(IAsyncOperation*)this;*/\r
43     if (NULL!=*ppvObject)\r
44     {\r
45         ((LPUNKNOWN)*ppvObject)->AddRef();\r
46         return S_OK;\r
47     }\r
48     return E_NOINTERFACE;\r
49 }\r
50 \r
51 STDMETHODIMP_(ULONG) CIDataObject::AddRef( void)\r
52 {\r
53         return ++m_cRefCount;\r
54 }\r
55 \r
56 STDMETHODIMP_(ULONG) CIDataObject::Release( void)\r
57 {\r
58    long nTemp;\r
59    nTemp = --m_cRefCount;\r
60    if(nTemp==0)\r
61       delete this;\r
62    return nTemp;\r
63 }\r
64 \r
65 STDMETHODIMP CIDataObject::GetData( \r
66     /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,\r
67     /* [out] */ STGMEDIUM __RPC_FAR *pmedium)\r
68\r
69         if(pformatetcIn == NULL || pmedium == NULL)\r
70                 return E_INVALIDARG;\r
71         pmedium->hGlobal = NULL;\r
72 \r
73         ATLASSERT(m_StgMedium.GetSize() == m_ArrFormatEtc.GetSize());\r
74         for(int i=0; i < m_ArrFormatEtc.GetSize(); ++i)\r
75         {\r
76                 if(pformatetcIn->tymed & m_ArrFormatEtc[i]->tymed &&\r
77                    pformatetcIn->dwAspect == m_ArrFormatEtc[i]->dwAspect &&\r
78                    pformatetcIn->cfFormat == m_ArrFormatEtc[i]->cfFormat)\r
79                 {\r
80                         CopyMedium(pmedium, m_StgMedium[i], m_ArrFormatEtc[i]);\r
81                         return S_OK;\r
82                 }\r
83         }\r
84         return DV_E_FORMATETC;\r
85 }\r
86 \r
87 STDMETHODIMP CIDataObject::GetDataHere( \r
88     /* [unique][in] */ FORMATETC __RPC_FAR * /*pformatetc*/,\r
89     /* [out][in] */ STGMEDIUM __RPC_FAR * /*pmedium*/)\r
90 {\r
91         return E_NOTIMPL;\r
92 }\r
93 \r
94 STDMETHODIMP CIDataObject::QueryGetData( \r
95    /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc)\r
96\r
97         if(pformatetc == NULL)\r
98                 return E_INVALIDARG;\r
99 \r
100         //support others if needed DVASPECT_THUMBNAIL  //DVASPECT_ICON   //DVASPECT_DOCPRINT\r
101         if (!(DVASPECT_CONTENT & pformatetc->dwAspect))\r
102                 return (DV_E_DVASPECT);\r
103         HRESULT  hr = DV_E_TYMED;\r
104         for(int i = 0; i < m_ArrFormatEtc.GetSize(); ++i)\r
105         {\r
106            if(pformatetc->tymed & m_ArrFormatEtc[i]->tymed)\r
107            {\r
108                   if(pformatetc->cfFormat == m_ArrFormatEtc[i]->cfFormat)\r
109                          return S_OK;\r
110                   else\r
111                          hr = DV_E_CLIPFORMAT;\r
112            }\r
113            else\r
114                   hr = DV_E_TYMED;\r
115         }\r
116         return hr;\r
117 }\r
118 \r
119 STDMETHODIMP CIDataObject::GetCanonicalFormatEtc( \r
120     /* [unique][in] */ FORMATETC __RPC_FAR * /*pformatectIn*/,\r
121     /* [out] */ FORMATETC __RPC_FAR *pformatetcOut)\r
122\r
123         if (pformatetcOut == NULL)\r
124                 return E_INVALIDARG;\r
125         return DATA_S_SAMEFORMATETC;\r
126 }\r
127 \r
128 STDMETHODIMP CIDataObject::SetData( \r
129     /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,\r
130     /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,\r
131     /* [in] */ BOOL fRelease)\r
132\r
133         if(pformatetc == NULL || pmedium == NULL)\r
134       return E_INVALIDARG;\r
135 \r
136         ATLASSERT(pformatetc->tymed == pmedium->tymed);\r
137         FORMATETC* fetc=new FORMATETC;\r
138         STGMEDIUM* pStgMed = new STGMEDIUM;\r
139 \r
140         if(fetc == NULL || pStgMed == NULL)\r
141                 return E_OUTOFMEMORY;\r
142 \r
143         SecureZeroMemory(fetc,sizeof(FORMATETC));\r
144         SecureZeroMemory(pStgMed,sizeof(STGMEDIUM));\r
145 \r
146         *fetc = *pformatetc;\r
147         m_ArrFormatEtc.Add(fetc);\r
148 \r
149     if(fRelease)\r
150       *pStgMed = *pmedium;\r
151     else\r
152     {\r
153                 CopyMedium(pStgMed, pmedium, pformatetc);\r
154         }\r
155         m_StgMedium.Add(pStgMed);\r
156 \r
157     return S_OK;\r
158 }\r
159 void CIDataObject::CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc)\r
160 {\r
161                 switch(pMedSrc->tymed)\r
162                 {\r
163                 case TYMED_HGLOBAL:\r
164                         pMedDest->hGlobal = (HGLOBAL)OleDuplicateData(pMedSrc->hGlobal,pFmtSrc->cfFormat, NULL);\r
165                         break;\r
166                 case TYMED_GDI:\r
167                         pMedDest->hBitmap = (HBITMAP)OleDuplicateData(pMedSrc->hBitmap,pFmtSrc->cfFormat, NULL);\r
168                         break;\r
169                 case TYMED_MFPICT:\r
170                         pMedDest->hMetaFilePict = (HMETAFILEPICT)OleDuplicateData(pMedSrc->hMetaFilePict,pFmtSrc->cfFormat, NULL);\r
171                         break;\r
172                 case TYMED_ENHMF:\r
173                         pMedDest->hEnhMetaFile = (HENHMETAFILE)OleDuplicateData(pMedSrc->hEnhMetaFile,pFmtSrc->cfFormat, NULL);\r
174                         break;\r
175                 case TYMED_FILE:\r
176                         pMedSrc->lpszFileName = (LPOLESTR)OleDuplicateData(pMedSrc->lpszFileName,pFmtSrc->cfFormat, NULL);\r
177                         break;\r
178                 case TYMED_ISTREAM:\r
179                         pMedDest->pstm = pMedSrc->pstm;\r
180                         pMedSrc->pstm->AddRef();\r
181                         break;\r
182                 case TYMED_ISTORAGE:\r
183                         pMedDest->pstg = pMedSrc->pstg;\r
184                         pMedSrc->pstg->AddRef();\r
185                         break;\r
186                 case TYMED_NULL:\r
187                 default:\r
188                         break;\r
189                 }\r
190                 pMedDest->tymed = pMedSrc->tymed;\r
191                 pMedDest->pUnkForRelease = NULL;\r
192                 if(pMedSrc->pUnkForRelease != NULL)\r
193                 {\r
194                         pMedDest->pUnkForRelease = pMedSrc->pUnkForRelease;\r
195                         pMedSrc->pUnkForRelease->AddRef();\r
196                 }\r
197 }\r
198 STDMETHODIMP CIDataObject::EnumFormatEtc(\r
199    /* [in] */ DWORD dwDirection,\r
200    /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc)\r
201\r
202         if(ppenumFormatEtc == NULL)\r
203       return E_POINTER;\r
204 \r
205         *ppenumFormatEtc=NULL;\r
206         switch (dwDirection)\r
207     {\r
208       case DATADIR_GET:\r
209          *ppenumFormatEtc= new CEnumFormatEtc(m_ArrFormatEtc);\r
210                  if(*ppenumFormatEtc == NULL)\r
211                          return E_OUTOFMEMORY;\r
212          (*ppenumFormatEtc)->AddRef(); \r
213          break;\r
214       \r
215           case DATADIR_SET:\r
216       default:\r
217                  return E_NOTIMPL;\r
218          break;\r
219     }\r
220 \r
221    return S_OK;\r
222 }\r
223 \r
224 STDMETHODIMP CIDataObject::DAdvise( \r
225    /* [in] */ FORMATETC __RPC_FAR * /*pformatetc*/,\r
226    /* [in] */ DWORD /*advf*/,\r
227    /* [unique][in] */ IAdviseSink __RPC_FAR * /*pAdvSink*/,\r
228    /* [out] */ DWORD __RPC_FAR * /*pdwConnection*/)\r
229\r
230         return OLE_E_ADVISENOTSUPPORTED;\r
231 }\r
232 \r
233 STDMETHODIMP CIDataObject::DUnadvise( \r
234    /* [in] */ DWORD /*dwConnection*/)\r
235 {\r
236         return E_NOTIMPL;\r
237 }\r
238 \r
239 HRESULT STDMETHODCALLTYPE CIDataObject::EnumDAdvise( \r
240    /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR * /*ppenumAdvise*/)\r
241 {\r
242         return OLE_E_ADVISENOTSUPPORTED;\r
243 }\r
244 \r
245 //////////////////////////////////////////////////////////////////////\r
246 // CIDropSource Class\r
247 //////////////////////////////////////////////////////////////////////\r
248 \r
249 STDMETHODIMP CIDropSource::QueryInterface(/* [in] */ REFIID riid,\r
250                                                                                  /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)\r
251 {\r
252    *ppvObject = NULL;\r
253    if (IID_IUnknown==riid || IID_IDropSource==riid)\r
254        *ppvObject=this;\r
255 \r
256     if (*ppvObject != NULL)\r
257     {\r
258        ((LPUNKNOWN)*ppvObject)->AddRef();\r
259         return S_OK;\r
260     }\r
261     return E_NOINTERFACE;\r
262 }\r
263 \r
264 STDMETHODIMP_(ULONG) CIDropSource::AddRef( void)\r
265 {\r
266         return ++m_cRefCount;\r
267 }\r
268 \r
269 STDMETHODIMP_(ULONG) CIDropSource::Release( void)\r
270 {\r
271    long nTemp;\r
272    nTemp = --m_cRefCount;\r
273    ATLASSERT(nTemp >= 0);\r
274    if(nTemp==0)\r
275       delete this;\r
276    return nTemp;\r
277 }\r
278 \r
279 STDMETHODIMP CIDropSource::QueryContinueDrag( \r
280     /* [in] */ BOOL fEscapePressed,\r
281     /* [in] */ DWORD grfKeyState)\r
282 {\r
283    if(fEscapePressed)\r
284       return DRAGDROP_S_CANCEL;\r
285    if(!(grfKeyState & (MK_LBUTTON|MK_RBUTTON)))\r
286    {\r
287           m_bDropped = true;\r
288       return DRAGDROP_S_DROP;\r
289    }\r
290 \r
291    return S_OK;\r
292 \r
293 }\r
294 \r
295 STDMETHODIMP CIDropSource::GiveFeedback(\r
296     /* [in] */ DWORD /*dwEffect*/)\r
297 {\r
298         return DRAGDROP_S_USEDEFAULTCURSORS;\r
299 }\r
300 \r
301 //////////////////////////////////////////////////////////////////////\r
302 // CEnumFormatEtc Class\r
303 //////////////////////////////////////////////////////////////////////\r
304 \r
305 CEnumFormatEtc::CEnumFormatEtc(const CSimpleArray<FORMATETC>& ArrFE):\r
306 m_cRefCount(0),m_iCur(0)\r
307 {\r
308    ATLTRACE("CEnumFormatEtc::CEnumFormatEtc()\n");\r
309    for(int i = 0; i < ArrFE.GetSize(); ++i)\r
310                 m_pFmtEtc.Add(ArrFE[i]);\r
311 }\r
312 \r
313 CEnumFormatEtc::CEnumFormatEtc(const CSimpleArray<FORMATETC*>& ArrFE):\r
314 m_cRefCount(0),m_iCur(0)\r
315 {\r
316    for(int i = 0; i < ArrFE.GetSize(); ++i)\r
317                 m_pFmtEtc.Add(*ArrFE[i]);\r
318 }\r
319 \r
320 STDMETHODIMP  CEnumFormatEtc::QueryInterface(REFIID refiid, void FAR* FAR* ppv)\r
321 {\r
322    *ppv = NULL;\r
323    if (IID_IUnknown==refiid || IID_IEnumFORMATETC==refiid)\r
324              *ppv=this;\r
325 \r
326     if (*ppv != NULL)\r
327     {\r
328         ((LPUNKNOWN)*ppv)->AddRef();\r
329         return S_OK;\r
330     }\r
331     return E_NOINTERFACE;\r
332 }\r
333 \r
334 STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef(void)\r
335 {\r
336    return ++m_cRefCount;\r
337 }\r
338 \r
339 STDMETHODIMP_(ULONG) CEnumFormatEtc::Release(void)\r
340 {\r
341    long nTemp = --m_cRefCount;\r
342    ATLASSERT(nTemp >= 0);\r
343    if(nTemp == 0)\r
344      delete this;\r
345 \r
346    return nTemp; \r
347 }\r
348 \r
349 STDMETHODIMP CEnumFormatEtc::Next( ULONG celt,LPFORMATETC lpFormatEtc, ULONG FAR *pceltFetched)\r
350 {\r
351    if(pceltFetched != NULL)\r
352            *pceltFetched=0;\r
353         \r
354    ULONG cReturn = celt;\r
355 \r
356    if(celt <= 0 || lpFormatEtc == NULL || m_iCur >= m_pFmtEtc.GetSize())\r
357       return S_FALSE;\r
358 \r
359    if(pceltFetched == NULL && celt != 1) // pceltFetched can be NULL only for 1 item request\r
360       return S_FALSE;\r
361 \r
362         while (m_iCur < m_pFmtEtc.GetSize() && cReturn > 0)\r
363         {\r
364                 *lpFormatEtc++ = m_pFmtEtc[m_iCur++];\r
365                 --cReturn;\r
366         }\r
367         if (pceltFetched != NULL)\r
368                 *pceltFetched = celt - cReturn;\r
369 \r
370     return (cReturn == 0) ? S_OK : S_FALSE;\r
371 }\r
372    \r
373 STDMETHODIMP CEnumFormatEtc::Skip(ULONG celt)\r
374 {\r
375         if((m_iCur + int(celt)) >= m_pFmtEtc.GetSize())\r
376                 return S_FALSE;\r
377         m_iCur += celt;\r
378         return S_OK;\r
379 }\r
380 \r
381 STDMETHODIMP CEnumFormatEtc::Reset(void)\r
382 {\r
383    m_iCur = 0;\r
384    return S_OK;\r
385 }\r
386                \r
387 STDMETHODIMP CEnumFormatEtc::Clone(IEnumFORMATETC FAR * FAR*ppCloneEnumFormatEtc)\r
388 {\r
389   if(ppCloneEnumFormatEtc == NULL)\r
390       return E_POINTER;\r
391       \r
392   CEnumFormatEtc *newEnum = new CEnumFormatEtc(m_pFmtEtc);\r
393   if(newEnum ==NULL)\r
394                 return E_OUTOFMEMORY;   \r
395   newEnum->AddRef();\r
396   newEnum->m_iCur = m_iCur;\r
397   *ppCloneEnumFormatEtc = newEnum;\r
398   return S_OK;\r
399 }\r
400 \r
401 //////////////////////////////////////////////////////////////////////\r
402 // CIDropTarget Class\r
403 //////////////////////////////////////////////////////////////////////\r
404 CIDropTarget::CIDropTarget(HWND hTargetWnd): \r
405         m_hTargetWnd(hTargetWnd),\r
406         m_cRefCount(0), m_bAllowDrop(false),\r
407         m_pDropTargetHelper(NULL), m_pSupportedFrmt(NULL)\r
408 {\r
409         if(FAILED(CoCreateInstance(CLSID_DragDropHelper,NULL,CLSCTX_INPROC_SERVER,\r
410                      IID_IDropTargetHelper,(LPVOID*)&m_pDropTargetHelper)))\r
411                 m_pDropTargetHelper = NULL;\r
412 }\r
413 \r
414 CIDropTarget::~CIDropTarget()\r
415 {\r
416         if(m_pDropTargetHelper != NULL)\r
417         {\r
418                 m_pDropTargetHelper->Release();\r
419                 m_pDropTargetHelper = NULL;\r
420         }\r
421 }\r
422 \r
423 HRESULT STDMETHODCALLTYPE CIDropTarget::QueryInterface( /* [in] */ REFIID riid,\r
424                                                 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)\r
425 {\r
426    *ppvObject = NULL;\r
427    if (IID_IUnknown==riid || IID_IDropTarget==riid)\r
428                          *ppvObject=this;\r
429 \r
430         if (*ppvObject != NULL)\r
431         {\r
432                 ((LPUNKNOWN)*ppvObject)->AddRef();\r
433                 return S_OK;\r
434         }\r
435         return E_NOINTERFACE;\r
436 }\r
437 \r
438 ULONG STDMETHODCALLTYPE CIDropTarget::Release( void)\r
439 {\r
440    long nTemp;\r
441    nTemp = --m_cRefCount;\r
442    ATLASSERT(nTemp >= 0);\r
443    if(nTemp==0)\r
444           delete this;\r
445    return nTemp;\r
446 }\r
447 \r
448 bool CIDropTarget::QueryDrop(DWORD grfKeyState, LPDWORD pdwEffect)\r
449 {  \r
450         DWORD dwOKEffects = *pdwEffect; \r
451 \r
452         if(!m_bAllowDrop)\r
453         {\r
454            *pdwEffect = DROPEFFECT_NONE;\r
455            return false;\r
456         }\r
457         //CTRL+SHIFT  -- DROPEFFECT_LINK\r
458         //CTRL        -- DROPEFFECT_COPY\r
459         //SHIFT       -- DROPEFFECT_MOVE\r
460         //no modifier -- DROPEFFECT_MOVE or whatever is allowed by src\r
461         *pdwEffect = (grfKeyState & MK_CONTROL) ?\r
462                                  ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY ):\r
463                                  ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_MOVE : 0 );\r
464         if(*pdwEffect == 0) \r
465         {\r
466            // No modifier keys used by user while dragging. \r
467            if (DROPEFFECT_MOVE & dwOKEffects)\r
468                   *pdwEffect = DROPEFFECT_MOVE;\r
469            else if (DROPEFFECT_COPY & dwOKEffects)\r
470                   *pdwEffect = DROPEFFECT_COPY; \r
471            else if (DROPEFFECT_LINK & dwOKEffects)\r
472                   *pdwEffect = DROPEFFECT_LINK; \r
473            else \r
474            {\r
475                   *pdwEffect = DROPEFFECT_NONE;\r
476            }\r
477         } \r
478         else\r
479         {\r
480            // Check if the drag source application allows the drop effect desired by user.\r
481            // The drag source specifies this in DoDragDrop\r
482            if(!(*pdwEffect & dwOKEffects))\r
483                   *pdwEffect = DROPEFFECT_NONE;\r
484         }  \r
485 \r
486         return (DROPEFFECT_NONE == *pdwEffect)?false:true;\r
487 }   \r
488 \r
489 HRESULT STDMETHODCALLTYPE CIDropTarget::DragEnter(\r
490     /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,\r
491     /* [in] */ DWORD grfKeyState,\r
492     /* [in] */ POINTL pt,\r
493     /* [out][in] */ DWORD __RPC_FAR *pdwEffect)\r
494 {\r
495         if(pDataObj == NULL)\r
496                 return E_INVALIDARG;\r
497 \r
498         if(m_pDropTargetHelper)\r
499                 m_pDropTargetHelper->DragEnter(m_hTargetWnd, pDataObj, (LPPOINT)&pt, *pdwEffect);\r
500         //IEnumFORMATETC* pEnum;\r
501         //pDataObj->EnumFormatEtc(DATADIR_GET,&pEnum);\r
502         //FORMATETC ftm;\r
503         //for()\r
504         //pEnum->Next(1,&ftm,0);\r
505         //pEnum->Release();\r
506         m_pSupportedFrmt = NULL;\r
507         for(int i =0; i<m_formatetc.GetSize(); ++i)\r
508         {\r
509                 m_bAllowDrop = (pDataObj->QueryGetData(&m_formatetc[i]) == S_OK)?true:false;\r
510                 if(m_bAllowDrop)\r
511                 {\r
512                         m_pSupportedFrmt = &m_formatetc[i];\r
513                         break;\r
514                 }\r
515         }\r
516 \r
517         QueryDrop(grfKeyState, pdwEffect);\r
518         return S_OK;\r
519 }\r
520 \r
521 HRESULT STDMETHODCALLTYPE CIDropTarget::DragOver( \r
522         /* [in] */ DWORD grfKeyState,\r
523         /* [in] */ POINTL pt,\r
524         /* [out][in] */ DWORD __RPC_FAR *pdwEffect)\r
525 {\r
526         if(m_pDropTargetHelper)\r
527                 m_pDropTargetHelper->DragOver((LPPOINT)&pt, *pdwEffect);\r
528         QueryDrop(grfKeyState, pdwEffect);\r
529         return S_OK;\r
530 }\r
531 \r
532 HRESULT STDMETHODCALLTYPE CIDropTarget::DragLeave( void)\r
533 {\r
534         if(m_pDropTargetHelper)\r
535                 m_pDropTargetHelper->DragLeave();\r
536         \r
537         m_bAllowDrop = false;\r
538         m_pSupportedFrmt = NULL;\r
539         return S_OK;\r
540 }\r
541 \r
542 HRESULT STDMETHODCALLTYPE CIDropTarget::Drop(\r
543         /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,\r
544     /* [in] */ DWORD grfKeyState, /* [in] */ POINTL pt, \r
545         /* [out][in] */ DWORD __RPC_FAR *pdwEffect)\r
546 {\r
547         if (pDataObj == NULL)\r
548                 return E_INVALIDARG;    \r
549 \r
550         if(m_pDropTargetHelper)\r
551                 m_pDropTargetHelper->Drop(pDataObj, (LPPOINT)&pt, *pdwEffect);\r
552 \r
553         if(QueryDrop(grfKeyState, pdwEffect))\r
554         {\r
555                 if(m_bAllowDrop && m_pSupportedFrmt != NULL)\r
556                 {\r
557                         STGMEDIUM medium;\r
558                         if(pDataObj->GetData(m_pSupportedFrmt, &medium) == S_OK)\r
559                         {\r
560                                 if(OnDrop(m_pSupportedFrmt, medium, pdwEffect, pt)) //does derive class wants us to free medium?\r
561                                         ReleaseStgMedium(&medium);\r
562                         }\r
563                 }\r
564         }\r
565         m_bAllowDrop=false;\r
566         *pdwEffect = DROPEFFECT_NONE;\r
567         m_pSupportedFrmt = NULL;\r
568         return S_OK;\r
569 }\r
570 \r
571 //////////////////////////////////////////////////////////////////////\r
572 // CIDragSourceHelper Class\r
573 //////////////////////////////////////////////////////////////////////\r