OSDN Git Service

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