title: Somthing confused with ole drag and drop implementation
body: <p>I wish to finish a little demo to implement OLE drag and drop(drag a file from my application to windows explorer).</p>
  
  <p>But here comes a problem:DoDragDrop return DRAGDROP_S_DROP which means the ole drag and drop operation has successfully done,but also get DROPEFFECT_NONE which means drop target cannot accept the data.</p>
  
  <p>I debug into it but I get a mess with them,help me,please:(</p>
  
  <p>Here is the gui:
  <img src="https://i.stack.imgur.com/evvZg.png" alt="enter image description here"></p>
  
  <p>Critical code comes:
  1.MainWindow.h</p>
  
  <pre><code>#ifndef MainWindowH
  #define MainWindowH
  //---------------------------------------------------------------------------
  #include &lt;Classes.hpp&gt;
  #include &lt;Controls.hpp&gt;
  #include &lt;StdCtrls.hpp&gt;
  #include &lt;Forms.hpp&gt;
  #include &lt;Ole2.h&gt;
  #include "MyDataObject.h"
  #include "MyDropSource.h"
  //---------------------------------------------------------------------------
  class TForm1 : public TForm
  {
  __published:    // IDE-managed Components
      TLabel *Label1;
      void __fastcall Label1StartDrag(TObject *Sender, TDragObject *&amp;DragObject);
      void __fastcall Label1EndDrag(TObject *Sender, TObject *Target, int X, int Y);
      void __fastcall FormCreate(TObject *Sender);
      void __fastcall FormDestroy(TObject *Sender);
  private:    // User declarations
      //准备两个接口实例
      IDataObject *pDataObject;
      IDropSource *pDropSource;
  
      //
      STGMEDIUM stgmed;
      FORMATETC fmtetc;
  
  public:     // User declarations
      __fastcall TForm1(TComponent* Owner);
  };
  //---------------------------------------------------------------------------
  extern PACKAGE TForm1 *Form1;
  //---------------------------------------------------------------------------
  #endif
  </code></pre>
  
  <p>2.DoDragDrop invoke in MainWindow.cpp</p>
  
  <pre><code>   void __fastcall TForm1::Label1StartDrag(TObject *Sender, TDragObject *&amp;DragObject)
  {
      Label1-&gt;Caption = "Start drag";
  
      //Source file
      char tFileName[256] = "D:\\119.dat";
  
      //Prepare FOTMATETC
      fmtetc.cfFormat = CF_HDROP;
      fmtetc.dwAspect = DVASPECT_CONTENT;
      fmtetc.lindex = -1;
      fmtetc.ptd = (void*)0;
      fmtetc.tymed = TYMED_HGLOBAL;
  
      //Prepare DROPFILES
      DROPFILES* tDropFiles;
      //Fill the filename
      HGLOBAL hGblFiles;
      LPSTR lpData;
      stgmed.hGlobal = GlobalAlloc(GHND, sizeof(DROPFILES)+strlen(tFileName)+ 2);
      if(0 == stgmed.hGlobal)
          MessageBoxA(NULL, "OUT_OF_MEMORY!!!", "OUT_OF_MEMORY", 0);
  
      tDropFiles = (DROPFILES*)GlobalLock(stgmed.hGlobal);
      ZeroMemory(tDropFiles, sizeof(DROPFILES)+strlen(tFileName)+2);
      strcpy(((char*)tDropFiles)+sizeof(DROPFILES), tFileName);
      GlobalUnlock(stgmed.hGlobal);
  
      tDropFiles-&gt;fNC     = true;
      tDropFiles-&gt;fWide   = false;
      tDropFiles-&gt;pFiles  = sizeof(DROPFILES);
      tDropFiles-&gt;pt.x    = 0;
      tDropFiles-&gt;pt.y    = 0;
  
      //set hGlobal
      stgmed.tymed = TYMED_HGLOBAL;
      stgmed.hGlobal = tDropFiles;
      stgmed.pUnkForRelease = 0;
  
      //Create Instance of IDropSource and IDataObject
      pDropSource  = new MyDropSource();
      pDropSource-&gt;AddRef();
      pDataObject  = new MyDataObject();
      pDataObject-&gt;AddRef();
  
      //SetData
      pDataObject-&gt;SetData(&amp;fmtetc, &amp;stgmed, true);
  
      OleInitialize(0);
  
      //Invoke DoDragDrop
      DWORD dwEffect;
      HRESULT tResult = DoDragDrop((IDataObject*)pDataObject, (IDropSource*)pDropSource, DROPEFFECT_MOVE, &amp;dwEffect);
  
      //Ckeck drag&amp;drop result
      if(tResult != DRAGDROP_S_DROP)
          {
          if(tResult == DRAGDROP_S_CANCEL)
              MessageBoxA(NULL, "DRAGDROP_S_CANCEL!", "DRAGDROP_S_DROP", 0);
          else
              MessageBoxA(NULL, "E_UNSPEC!", "DRAGDROP_S_DROP", 0);
          return;
          }
  
      if((dwEffect &amp; DROPEFFECT_MOVE) == DROPEFFECT_MOVE)
          MessageBoxA(NULL, "Ole drag&amp;drop OK!!", "DRAGDROP_S_DROP", 0);
      else
          {
          if((dwEffect &amp; DROPEFFECT_NONE) == DROPEFFECT_NONE)
              MessageBoxA(NULL, "DROPEFFECT_NONE!!", "DRAGDROP_S_DROP", 0);
          }
  
      //Clean
      pDropSource-&gt;Release();
      pDataObject-&gt;Release();
  
      OleUninitialize();
  
      return;
  }
  </code></pre>
  
  <p>3.MyDataObject.h</p>
  
  <pre><code>#ifndef _MYDATAOBJECT_H_
  #define _MYDATAOBJECT_H_
  
  #include &lt;stdio.h&gt;
  #include "IDragDemo.h"
  #include "MyDropSource.h"
  
  #ifndef SAFE_DELETE
  #define SAFE_DELETE(p) { if(p){delete(p);  (p)=NULL;} }
  #endif
  
  HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc);
  
  class MyDataObject : public IDataObject
  {
  public:
      //IUnknown implementation
      ULONG __stdcall AddRef();
      ULONG __stdcall Release();
      STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
  
      //IDataObject members
      STDMETHODIMP GetData               (FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
      STDMETHODIMP GetDataHere           (FORMATETC *pformatetc,   STGMEDIUM *pmedium);
      STDMETHODIMP QueryGetData          (FORMATETC *pformatetc);
      STDMETHODIMP GetCanonicalFormatEtc (FORMATETC *pformatectIn, FORMATETC *pformatetcOut);
      STDMETHODIMP SetData               (FORMATETC *pformatetc,   STGMEDIUM *pmedium,  BOOL fRelease);
      STDMETHODIMP EnumFormatEtc         (DWORD     dwDirection,   IEnumFORMATETC **ppenumFormatEtc);
      STDMETHODIMP DAdvise               (FORMATETC *pformatetc,   DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
      STDMETHODIMP DUnadvise             (DWORD     dwConnection);
      STDMETHODIMP EnumDAdvise           (IEnumSTATDATA **ppenumAdvise);
  public:
      MyDataObject();
      ~MyDataObject();
  private:
      LONG refcount;
  
      FORMATETC* m_AcceptFormat;
      STGMEDIUM* m_StorageMedium;
  
      HGLOBAL DupGlobalMem(HGLOBAL hMem);
  
      //Helper function
      HRESULT CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc);
      HRESULT SetBlob(CLIPFORMAT cf, const void *pvBlob, UINT cbBlob);
  
      LONG m_RefCount;
  };
  //----------------MyEnumFormatEtc-----------------------------------------------------------
  class MyEnumFormatEtc : public IEnumFORMATETC
  {
  public:
      // IUnknown members
      HRESULT __stdcall  QueryInterface (REFIID iid, void ** ppv)
      {
          if((iid==IID_IUnknown)||(iid==IID_IEnumFORMATETC))
          {
              *ppv=this;
              AddRef();
              return S_OK;
          }
          else
          {
              *ppv=NULL;
              return E_NOINTERFACE;
          }
      }
      ULONG   __stdcall AddRef (void) { return ++_iRefCount; }
      ULONG   __stdcall Release (void)  { if(--_iRefCount==0){delete this;  return 0;} return _iRefCount; }
  
      // IEnumFormatEtc members
      HRESULT __stdcall  Next  (ULONG celt, FORMATETC * rgelt, ULONG * pceltFetched);
      HRESULT __stdcall  Skip  (ULONG celt)
      {
          _nIndex += celt;
          return (_nIndex &lt;= _nNumFormats) ? S_OK : S_FALSE;
      }
      HRESULT __stdcall  Reset (void)
      {
          _nIndex = 0;
          return S_OK;
      }
      HRESULT __stdcall  Clone (IEnumFORMATETC ** ppEnumFormatEtc)
      {
          HRESULT hResult;
          hResult = CreateEnumFormatEtc(_nNumFormats, _pFormatEtc, ppEnumFormatEtc);
          if(hResult == S_OK)
          {
              ((MyEnumFormatEtc *)*ppEnumFormatEtc)-&gt;_nIndex = _nIndex;
          }
          return hResult;
      }
  
      // Construction / Destruction
      MyEnumFormatEtc(FORMATETC *pFormatEtc, ULONG nNumFormats);
      ~MyEnumFormatEtc();
  
  private:
      LONG        _iRefCount;        
      ULONG       _nIndex;        
      ULONG       _nNumFormats;      
      FORMATETC * _pFormatEtc; 
  };
  //---------------------------------------------------------------------------
  
  #endif
  </code></pre>
  
  <p>4.MyDataObject.cpp</p>
  
  <pre><code> #include "MyDataObject.h"
   #include "MyDropSource.h"
   #include &lt;Urlmon.h&gt;
  
  
  MyDataObject::MyDataObject(MyDropSource* vDropSource)
  {
      m_RefCount = 0;
      m_DropSource = vDropSource;
  }
  
  
  MyDataObject::~MyDataObject()
  {
      refcount = 0;
  
      SAFE_DELETE(m_StorageMedium);
      SAFE_DELETE(m_AcceptFormat);
  }
  
  
  ULONG __stdcall MyDataObject::AddRef()
  {
      return InterlockedIncrement(&amp;m_RefCount);
  }
  
  ULONG __stdcall MyDataObject::Release()
  {
      ULONG nRefCount = InterlockedDecrement(&amp;m_RefCount);
  
      if (nRefCount == 0)
          delete this;
  
      return nRefCount;
  }
  
  STDMETHODIMP MyDataObject::QueryInterface(REFIID riid, void **ppvObject) {
  
  if (!ppvObject)
          return E_POINTER;
  
      if (riid == IID_IDataObject)
          *ppvObject = (IDataObject*)this;
      else if (riid == IID_IUnknown)
          *ppvObject = (IUnknown*)this;
      else
      {
          *ppvObject = 0;
          return E_NOINTERFACE;
      }
  
      AddRef();
      return S_OK;
  
  
  }
  
  
  STDMETHODIMP MyDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
  {
  
      if ( (NULL == pformatetcIn) || (NULL == pmedium) )
      {
          return E_INVALIDARG;
      }
  
      pmedium-&gt;hGlobal = NULL;
  
      if( (pformatetcIn-&gt;tymed &amp; m_AcceptFormat-&gt;tymed) &amp;&amp;
          (pformatetcIn-&gt;dwAspect == m_AcceptFormat-&gt;dwAspect) &amp;&amp;
          (pformatetcIn-&gt;cfFormat == m_AcceptFormat-&gt;cfFormat) )
          {
              return CopyMedium(pmedium, m_StorageMedium, m_AcceptFormat);
          }
  
      return DV_E_FORMATETC;
  }
  
  STDMETHODIMP MyDataObject::GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium)
  {
      return E_NOTIMPL;
  }
  
  STDMETHODIMP MyDataObject::QueryGetData(FORMATETC *pformatetc)
  {
      if(NULL == pformatetc )
      {
          return E_INVALIDARG;
      }
      if(!(DVASPECT_CONTENT &amp; pformatetc-&gt;dwAspect))
      {
          return DV_E_DVASPECT;
      }
      HRESULT hr = DV_E_TYMED;
  
      if(m_AcceptFormat-&gt;tymed &amp; pformatetc-&gt;tymed )
          {
          if(m_AcceptFormat-&gt;cfFormat == pformatetc-&gt;cfFormat )
              {
              return S_OK;
              }
          else
              {
              hr = DV_E_CLIPFORMAT;
              }
          }
      else
          {
              hr = DV_E_TYMED;
          }
      return hr;
  }
  
  STDMETHODIMP MyDataObject::GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut)
  {
      pformatetcOut-&gt;ptd = NULL;
      return E_NOTIMPL;
  }
  
  STDMETHODIMP MyDataObject::SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
  {
      if ( (NULL == pformatetc) || (NULL == pmedium) )
          return E_INVALIDARG;
  
  
      if ( pformatetc-&gt;tymed != pmedium-&gt;tymed )
          return E_FAIL;
  
      m_AcceptFormat = new FORMATETC;
      m_StorageMedium = new STGMEDIUM;
      ZeroMemory(m_AcceptFormat, sizeof(FORMATETC));
      ZeroMemory(m_StorageMedium, sizeof(STGMEDIUM));
  
      if ( TRUE == fRelease )
      {
          *m_StorageMedium = *pmedium;
      }
      else
      {
          CopyMedium(m_StorageMedium, pmedium, pformatetc);
      }
  
      return S_OK;
  }
  
  STDMETHODIMP MyDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
  {
      if(NULL == ppenumFormatEtc)
      {
          return E_INVALIDARG;
      }
      *ppenumFormatEtc = NULL;
      HRESULT hr = E_NOTIMPL;
      if (DATADIR_GET == dwDirection )
      {
          FORMATETC rgfmtetc[] =
          {
              { CF_HDROP, NULL, DVASPECT_CONTENT, 0, TYMED_HGLOBAL },
          };
          hr = CreateEnumFormatEtc(ARRAYSIZE(rgfmtetc), rgfmtetc, ppenumFormatEtc);
      }
      return hr;
  }
  //Advises:OLE_E_ADVISENOTSUPPORTED
  STDMETHODIMP MyDataObject::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
  {
      UNREFERENCED_PARAMETER(pformatetc);
      UNREFERENCED_PARAMETER(advf);
      UNREFERENCED_PARAMETER(pAdvSink);
      UNREFERENCED_PARAMETER(pdwConnection);
      return E_NOTIMPL;
  }
  
  STDMETHODIMP MyDataObject::DUnadvise(DWORD dwConnection)
  {
      UNREFERENCED_PARAMETER(dwConnection);
      return E_NOTIMPL;
  }
  
  STDMETHODIMP MyDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
  {
      UNREFERENCED_PARAMETER(ppenumAdvise);
      return E_NOTIMPL;
  }
  //Advises:OLE_E_ADVISENOTSUPPORTED
  
  HGLOBAL MyDataObject::DupGlobalMem(HGLOBAL hMem)
  {
      DWORD   len    = GlobalSize(hMem);
      PVOID   source = GlobalLock(hMem);
      PVOID   dest   = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, len);
  
      memcpy(dest, source, len);
      GlobalUnlock(hMem);
      return dest;
  }
  
  HRESULT MyDataObject::CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc)
  {
      if ( (NULL == pMedDest) || (NULL ==pMedSrc) || (NULL == pFmtSrc) )
      {
          return E_INVALIDARG;
      }
      switch(pMedSrc-&gt;tymed)
      {
      case TYMED_HGLOBAL:
          pMedDest-&gt;hGlobal = (HGLOBAL)OleDuplicateData(pMedSrc-&gt;hGlobal, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_GDI:
          pMedDest-&gt;hBitmap = (HBITMAP)OleDuplicateData(pMedSrc-&gt;hBitmap, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_MFPICT:
          pMedDest-&gt;hMetaFilePict = (HMETAFILEPICT)OleDuplicateData(pMedSrc-&gt;hMetaFilePict, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_ENHMF:
          pMedDest-&gt;hEnhMetaFile = (HENHMETAFILE)OleDuplicateData(pMedSrc-&gt;hEnhMetaFile, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_FILE:
          pMedSrc-&gt;lpszFileName = (LPOLESTR)OleDuplicateData(pMedSrc-&gt;lpszFileName, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_ISTREAM:
          pMedDest-&gt;pstm = pMedSrc-&gt;pstm;
          pMedSrc-&gt;pstm-&gt;AddRef();
          break;
      case TYMED_ISTORAGE:
          pMedDest-&gt;pstg = pMedSrc-&gt;pstg;
          pMedSrc-&gt;pstg-&gt;AddRef();
          break;
      case TYMED_NULL:
      default:
          break;
      }
      pMedDest-&gt;tymed = pMedSrc-&gt;tymed;
      pMedDest-&gt;pUnkForRelease = NULL;
      if(pMedSrc-&gt;pUnkForRelease != NULL)
      {
          pMedDest-&gt;pUnkForRelease = pMedSrc-&gt;pUnkForRelease;
          pMedSrc-&gt;pUnkForRelease-&gt;AddRef();
      }
      return S_OK;
  }
  HRESULT MyDataObject::SetBlob(CLIPFORMAT cf, const void *pvBlob, UINT cbBlob)
  {
      void *pv = GlobalAlloc(GPTR, cbBlob);
      HRESULT hr = pv ? S_OK : E_OUTOFMEMORY;
      if ( SUCCEEDED(hr) )
      {
          CopyMemory(pv, pvBlob, cbBlob);
          FORMATETC fmte = {cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
          STGMEDIUM medium = {};
          medium.tymed = TYMED_HGLOBAL;
          medium.hGlobal = pv;
          hr = this-&gt;SetData(&amp;fmte, &amp;medium, TRUE);
          if (FAILED(hr))
          {
              GlobalFree(pv);
          }
      }
      return hr;
  }
  
  HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc)
  {
      if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
          return E_INVALIDARG;
  
      *ppEnumFormatEtc = new MyEnumFormatEtc(afmt, cfmt);
      return (*ppEnumFormatEtc) ? S_OK: E_OUTOFMEMORY;
  }
  
  void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source)
  {
      *dest = *source;
      if(source-&gt;ptd)
      {
          dest-&gt;ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
          *(dest-&gt;ptd) = *(source-&gt;ptd);
      }
  }
  
  MyEnumFormatEtc::MyEnumFormatEtc(FORMATETC *pFormatEtc, ULONG nNumFormats)
      :_iRefCount(1),_nIndex(0),_nNumFormats(nNumFormats)
  {
      _pFormatEtc  = new FORMATETC[nNumFormats];
      // make a new copy of each FORMATETC structure
      for(ULONG i = 0; i &lt; nNumFormats; i++)
      {
          DeepCopyFormatEtc (&amp;_pFormatEtc[i], &amp;pFormatEtc[i]);
      }
  }
  MyEnumFormatEtc::~MyEnumFormatEtc()
  {
      // first free any DVTARGETDEVICE structures
      for(ULONG i = 0; i &lt; _nNumFormats; i++)
      {
          if(_pFormatEtc[i].ptd)
              CoTaskMemFree(_pFormatEtc[i].ptd);
      }
      // now free the main array
      delete[] _pFormatEtc;
  }
  
  HRESULT __stdcall MyEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)
  {
      ULONG copied = 0;
      // copy the FORMATETC structures into the caller's buffer
      while (_nIndex &lt; _nNumFormats &amp;&amp; copied &lt; celt)
      {
          DeepCopyFormatEtc (&amp;pFormatEtc [copied], &amp;_pFormatEtc [_nIndex]);
          copied++;
          _nIndex++;
      }
      // store result
      if(pceltFetched != 0)
          *pceltFetched = copied;
      // did we copy all that was requested?
      return (copied == celt) ? S_OK : S_FALSE;
  }
  </code></pre>
  
  <p>5.MyDropSource.h</p>
  
  <pre><code>#ifndef _MYDROPSOURCE_H_
  #define _MYDROPSOURCE_H_
  
  #include &lt;stdio.h&gt;
  #include "IDragDemo.h"
  
  class MyDropSource : public IDropSource
  {
  public:
  
      //IUnknown implementation
      ULONG __stdcall AddRef();
      ULONG __stdcall Release();
      STDMETHODIMP    QueryInterface(REFIID riid, void **ppvObject);
  
      //IDropSource members
      STDMETHODIMP QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
      STDMETHODIMP GiveFeedback(DWORD dwEffect);
  
      //Cons/Destructors
      MyDropSource();
      ~MyDropSource();
  private:
      LONG refcount;
  };
  #endif
  </code></pre>
  
  <p>6.MyDropSource.cpp</p>
  
  <pre><code>#include "MyDataObject.h"
   #include "MyDropSource.h"
   #include &lt;Urlmon.h&gt;
  
  //Constructors
  MyDataObject::MyDataObject(MyDropSource* vDropSource)
  {
      m_RefCount = 0;
      m_DropSource = vDropSource;
  }
  
  //Destructors
  MyDataObject::~MyDataObject()
  {
      refcount = 0;
  
      SAFE_DELETE(m_StorageMedium);
      SAFE_DELETE(m_AcceptFormat);
  }
  
  //IUnkown implementation
  ULONG __stdcall MyDataObject::AddRef()
  {
      return InterlockedIncrement(&amp;m_RefCount);
  }
  
  ULONG __stdcall MyDataObject::Release()
  {
      ULONG nRefCount = InterlockedDecrement(&amp;m_RefCount);
  
      if (nRefCount == 0)
          delete this;
  
      return nRefCount;
  }
  
  STDMETHODIMP MyDataObject::QueryInterface(REFIID riid, void **ppvObject) {
      if (!ppvObject)
      return E_POINTER;
  
  if (riid == IID_IDataObject)
      *ppvObject = (IDataObject*)this;
  else if (riid == IID_IUnknown)
      *ppvObject = (IUnknown*)this;
  else
  {
      *ppvObject = 0;
      return E_NOINTERFACE;
  }
  
  AddRef();
  return S_OK;
  }
  
  STDMETHODIMP MyDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
  {
      //入参检查
      if ( (NULL == pformatetcIn) || (NULL == pmedium) )
      {
          return E_INVALIDARG;
      }
  
      pmedium-&gt;hGlobal = NULL;
  
      if( (pformatetcIn-&gt;tymed &amp; m_AcceptFormat-&gt;tymed) &amp;&amp;
          (pformatetcIn-&gt;dwAspect == m_AcceptFormat-&gt;dwAspect) &amp;&amp;
          (pformatetcIn-&gt;cfFormat == m_AcceptFormat-&gt;cfFormat) )
          {
              return CopyMedium(pmedium, m_StorageMedium, m_AcceptFormat);
          }
  
      return DV_E_FORMATETC;
  }
  
  STDMETHODIMP MyDataObject::GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium)
  {
      return E_NOTIMPL;
  }
  
  STDMETHODIMP MyDataObject::QueryGetData(FORMATETC *pformatetc)
  {
      if(NULL == pformatetc )
      {
          return E_INVALIDARG;
      }
      if(!(DVASPECT_CONTENT &amp; pformatetc-&gt;dwAspect))
      {
          return DV_E_DVASPECT;
      }
      HRESULT hr = DV_E_TYMED;
  
      if(m_AcceptFormat-&gt;tymed &amp; pformatetc-&gt;tymed )
          {
          if(m_AcceptFormat-&gt;cfFormat == pformatetc-&gt;cfFormat )
              {
              return S_OK;
              }
          else
              {
              hr = DV_E_CLIPFORMAT;
              }
          }
      else
          {
              hr = DV_E_TYMED;
          }
      return hr;
  }
  
  STDMETHODIMP MyDataObject::GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut)
  {
      pformatetcOut-&gt;ptd = NULL;
      return E_NOTIMPL;
  }
  
  STDMETHODIMP MyDataObject::SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
  {
      if ( (NULL == pformatetc) || (NULL == pmedium) )
          return E_INVALIDARG;
  
  
      if ( pformatetc-&gt;tymed != pmedium-&gt;tymed )
          return E_FAIL;
  
      m_AcceptFormat = new FORMATETC;
      m_StorageMedium = new STGMEDIUM;
      ZeroMemory(m_AcceptFormat, sizeof(FORMATETC));
      ZeroMemory(m_StorageMedium, sizeof(STGMEDIUM));
  
      if ( TRUE == fRelease )
      {
          *m_StorageMedium = *pmedium;
      }
      else
      {
          CopyMedium(m_StorageMedium, pmedium, pformatetc);
      }
  
      return S_OK;
  }
  
  STDMETHODIMP MyDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
  {
      if(NULL == ppenumFormatEtc)
      {
          return E_INVALIDARG;
      }
      *ppenumFormatEtc = NULL;
      HRESULT hr = E_NOTIMPL;
      if (DATADIR_GET == dwDirection )
      {
          FORMATETC rgfmtetc[] =
          {
              { CF_HDROP, NULL, DVASPECT_CONTENT, 0, TYMED_HGLOBAL },
          };
          hr = CreateEnumFormatEtc(ARRAYSIZE(rgfmtetc), rgfmtetc, ppenumFormatEtc);
      }
      return hr;
  }
  //Advises:OLE_E_ADVISENOTSUPPORTED
  STDMETHODIMP MyDataObject::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
  {
      UNREFERENCED_PARAMETER(pformatetc);
      UNREFERENCED_PARAMETER(advf);
      UNREFERENCED_PARAMETER(pAdvSink);
      UNREFERENCED_PARAMETER(pdwConnection);
      return E_NOTIMPL;
  }
  
  STDMETHODIMP MyDataObject::DUnadvise(DWORD dwConnection)
  {
      UNREFERENCED_PARAMETER(dwConnection);
      return E_NOTIMPL;
  }
  
  STDMETHODIMP MyDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
  {
      UNREFERENCED_PARAMETER(ppenumAdvise);
      return E_NOTIMPL;
  }
  //Advises:OLE_E_ADVISENOTSUPPORTED
  
  HGLOBAL MyDataObject::DupGlobalMem(HGLOBAL hMem)
  {
      DWORD   len    = GlobalSize(hMem);
      PVOID   source = GlobalLock(hMem);
      PVOID   dest   = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, len);
  
      memcpy(dest, source, len);
      GlobalUnlock(hMem);
      return dest;
  }
  
  HRESULT MyDataObject::CopyMedium(STGMEDIUM* pMedDest, STGMEDIUM* pMedSrc, FORMATETC* pFmtSrc)
  {
      if ( (NULL == pMedDest) || (NULL ==pMedSrc) || (NULL == pFmtSrc) )
      {
          return E_INVALIDARG;
      }
      switch(pMedSrc-&gt;tymed)
      {
      case TYMED_HGLOBAL:
          pMedDest-&gt;hGlobal = (HGLOBAL)OleDuplicateData(pMedSrc-&gt;hGlobal, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_GDI:
          pMedDest-&gt;hBitmap = (HBITMAP)OleDuplicateData(pMedSrc-&gt;hBitmap, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_MFPICT:
          pMedDest-&gt;hMetaFilePict = (HMETAFILEPICT)OleDuplicateData(pMedSrc-&gt;hMetaFilePict, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_ENHMF:
          pMedDest-&gt;hEnhMetaFile = (HENHMETAFILE)OleDuplicateData(pMedSrc-&gt;hEnhMetaFile, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_FILE:
          pMedSrc-&gt;lpszFileName = (LPOLESTR)OleDuplicateData(pMedSrc-&gt;lpszFileName, pFmtSrc-&gt;cfFormat, NULL);
          break;
      case TYMED_ISTREAM:
          pMedDest-&gt;pstm = pMedSrc-&gt;pstm;
          pMedSrc-&gt;pstm-&gt;AddRef();
          break;
      case TYMED_ISTORAGE:
          pMedDest-&gt;pstg = pMedSrc-&gt;pstg;
          pMedSrc-&gt;pstg-&gt;AddRef();
          break;
      case TYMED_NULL:
      default:
          break;
      }
      pMedDest-&gt;tymed = pMedSrc-&gt;tymed;
      pMedDest-&gt;pUnkForRelease = NULL;
      if(pMedSrc-&gt;pUnkForRelease != NULL)
      {
          pMedDest-&gt;pUnkForRelease = pMedSrc-&gt;pUnkForRelease;
          pMedSrc-&gt;pUnkForRelease-&gt;AddRef();
      }
      return S_OK;
  }
  HRESULT MyDataObject::SetBlob(CLIPFORMAT cf, const void *pvBlob, UINT cbBlob)
  {
      void *pv = GlobalAlloc(GPTR, cbBlob);
      HRESULT hr = pv ? S_OK : E_OUTOFMEMORY;
      if ( SUCCEEDED(hr) )
      {
          CopyMemory(pv, pvBlob, cbBlob);
          FORMATETC fmte = {cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
          STGMEDIUM medium = {};
          medium.tymed = TYMED_HGLOBAL;
          medium.hGlobal = pv;
          hr = this-&gt;SetData(&amp;fmte, &amp;medium, TRUE);
          if (FAILED(hr))
          {
              GlobalFree(pv);
          }
      }
      return hr;
  }
  
  HRESULT CreateEnumFormatEtc(UINT cfmt, FORMATETC *afmt, IEnumFORMATETC **ppEnumFormatEtc)
  {
      if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
          return E_INVALIDARG;
  
      *ppEnumFormatEtc = new MyEnumFormatEtc(afmt, cfmt);
      return (*ppEnumFormatEtc) ? S_OK: E_OUTOFMEMORY;
  }
  
  void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source)
  {
      // copy the source FORMATETC into dest
      *dest = *source;
      if(source-&gt;ptd)
      {
          // allocate memory for the DVTARGETDEVICE if necessary
          dest-&gt;ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
          // copy the contents of the source DVTARGETDEVICE into dest-&gt;ptd
          *(dest-&gt;ptd) = *(source-&gt;ptd);
      }
  }
  
  MyEnumFormatEtc::MyEnumFormatEtc(FORMATETC *pFormatEtc, ULONG nNumFormats)
      :_iRefCount(1),_nIndex(0),_nNumFormats(nNumFormats)
  {
      _pFormatEtc  = new FORMATETC[nNumFormats];
      // make a new copy of each FORMATETC structure
      for(ULONG i = 0; i &lt; nNumFormats; i++)
      {
          DeepCopyFormatEtc (&amp;_pFormatEtc[i], &amp;pFormatEtc[i]);
      }
  }
  MyEnumFormatEtc::~MyEnumFormatEtc()
  {
      // first free any DVTARGETDEVICE structures
      for(ULONG i = 0; i &lt; _nNumFormats; i++)
      {
          if(_pFormatEtc[i].ptd)
              CoTaskMemFree(_pFormatEtc[i].ptd);
      }
      // now free the main array
      delete[] _pFormatEtc;
  }
  
  HRESULT __stdcall MyEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)
  {
      ULONG copied = 0;
      // copy the FORMATETC structures into the caller's buffer
      while (_nIndex &lt; _nNumFormats &amp;&amp; copied &lt; celt)
      {
          DeepCopyFormatEtc (&amp;pFormatEtc [copied], &amp;_pFormatEtc [_nIndex]);
          copied++;
          _nIndex++;
      }
      // store result
      if(pceltFetched != 0)
          *pceltFetched = copied;
      // did we copy all that was requested?
      return (copied == celt) ? S_OK : S_FALSE;
  }
  </code></pre>
  
  <p>7.IDragDemo.h</p>
  
  <pre><code>#ifndef _DRAGDROP_H_
  #define _DRAGDROP_H_
  #include &lt;windows.h&gt;
  #include &lt;ole2.h&gt;
  #include &lt;Shlobj.h&gt;
  #endif //_DRAGDROP_H_
  </code></pre>
  
  <p>Complete Code can be get here:<a href="https://github.com/cyfingm/cb_ole_dragdrop" rel="nofollow noreferrer">https://github.com/cyfingm/cb_ole_dragdrop</a></p>