Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore_win32 / ecore_win32_dnd_data_object.cpp
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include <assert.h>
10
11 #define WIN32_LEAN_AND_MEAN
12 #include <windows.h>
13 #undef WIN32_LEAN_AND_MEAN
14 #include <ole2.h>
15
16 #include "Ecore_Win32.h"
17 #include "ecore_win32_private.h"
18
19 #include "ecore_win32_dnd_enumformatetc.h"
20 #include "ecore_win32_dnd_data_object.h"
21
22
23 static HGLOBAL DupGlobalMem(HGLOBAL hMem)
24 {
25    DWORD len = (DWORD)GlobalSize(hMem);
26    PVOID source = GlobalLock(hMem);
27    PVOID dest = GlobalAlloc(GMEM_FIXED, len);
28    memcpy(dest, source, len);
29    GlobalUnlock(hMem);
30    return dest;
31 }
32
33 // structors
34
35 DataObject::DataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count)
36 {
37    assert(fmtetc != NULL);
38    assert(stgmed != NULL);
39    assert(count > 0);
40
41    // reference count must ALWAYS start at 1
42    ref_count_ = 1;
43    formats_num_ = count;
44
45    format_etc_ = new FORMATETC[count];
46    stg_medium_ = new STGMEDIUM[count];
47
48    for(int i = 0; i < count; i++)
49    {
50       format_etc_[i] = fmtetc[i];
51       stg_medium_[i] = stgmed[i];
52    }
53 }
54
55 DataObject::~DataObject()
56 {
57    delete[] format_etc_;
58    delete[] stg_medium_;
59 }
60
61
62 // IUnknown
63
64 HRESULT DataObject::QueryInterface(REFIID iid, void **ppvObject)
65 {
66    // check to see what interface has been requested
67    if ((iid == IID_IDataObject) || (iid == IID_IUnknown))
68    {
69       AddRef();
70       *ppvObject = this;
71       return S_OK;
72    }
73    *ppvObject = 0;
74    return E_NOINTERFACE;
75 }
76
77 ULONG DataObject::AddRef()
78 {
79    return InterlockedIncrement(&ref_count_);
80 }
81
82 ULONG DataObject::Release()
83 {
84    LONG count = InterlockedDecrement(&ref_count_);
85    if(count == 0)
86    {
87       delete this;
88       return 0;
89    }
90    return count;
91 }
92
93 // IDataObject
94
95 HRESULT DataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
96 {
97    assert(pMedium != NULL);
98    int idx;
99
100    // try to match the specified FORMATETC with one of our supported formats
101    if((idx = lookup_format_etc(pFormatEtc)) == -1)
102       return DV_E_FORMATETC;
103
104    // found a match - transfer data into supplied storage medium
105    pMedium->tymed = format_etc_[idx].tymed;
106    pMedium->pUnkForRelease = 0;
107
108    // copy the data into the caller's storage medium
109    switch(format_etc_[idx].tymed)
110    {
111    case TYMED_HGLOBAL:
112       pMedium->hGlobal = DupGlobalMem(stg_medium_[idx].hGlobal);
113       break;
114
115    default:
116       return DV_E_FORMATETC;
117    }
118
119    return S_OK;
120 }
121
122 HRESULT DataObject::GetDataHere(FORMATETC *pFormatEtc __UNUSED__, STGMEDIUM *pmedium __UNUSED__)
123 {
124    return DATA_E_FORMATETC;
125 }
126
127 HRESULT DataObject::QueryGetData(FORMATETC *pFormatEtc)
128 {
129    return (lookup_format_etc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
130 }
131
132 HRESULT DataObject::GetCanonicalFormatEtc(FORMATETC *pFormatEct __UNUSED__, FORMATETC *pFormatEtcOut)
133 {
134    // Apparently we have to set this field to NULL even though we don't do anything else
135    pFormatEtcOut->ptd = NULL;
136    return E_NOTIMPL;
137 }
138
139 HRESULT DataObject::SetData(FORMATETC *pFormatEtc __UNUSED__, STGMEDIUM *pMedium __UNUSED__,  BOOL fRelease __UNUSED__)
140 {
141    return E_NOTIMPL;
142 }
143
144 HRESULT DataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc)
145 {
146    // only the get direction is supported for OLE
147    if(dwDirection == DATADIR_GET)
148    {
149       // for Win2k+ you can use the SHCreateStdEnumFmtEtc API call, however
150       // to support all Windows platforms we need to implement IEnumFormatEtc ourselves.
151       return CreateEnumFormatEtc(formats_num_, format_etc_, ppEnumFormatEtc);
152    }
153    else
154    {
155       // the direction specified is not supported for drag+drop
156       return E_NOTIMPL;
157    }
158 }
159
160 HRESULT DataObject::DAdvise(FORMATETC *pFormatEtc __UNUSED__,  DWORD advf __UNUSED__, IAdviseSink *, DWORD *)
161 {
162    return OLE_E_ADVISENOTSUPPORTED;
163 }
164
165 HRESULT DataObject::DUnadvise(DWORD dwConnection __UNUSED__)
166 {
167    return OLE_E_ADVISENOTSUPPORTED;
168 }
169
170 HRESULT DataObject::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise __UNUSED__)
171 {
172    return OLE_E_ADVISENOTSUPPORTED;
173 }
174
175 // internal helper function
176
177 int DataObject::lookup_format_etc(FORMATETC *pFormatEtc)
178 {
179    // check each of our formats in turn to see if one matches
180    for(int i = 0; i < formats_num_; i++)
181    {
182       if((format_etc_[i].tymed & pFormatEtc->tymed) &&
183          (format_etc_[i].cfFormat == pFormatEtc->cfFormat) &&
184          (format_etc_[i].dwAspect == pFormatEtc->dwAspect))
185       {
186          // return index of stored format
187          return i;
188       }
189    }
190
191    // error, format not found
192    return -1;
193 }
194
195 void *_ecore_win32_dnd_data_object_new(void *fmtetc, void *stgmeds, int count)
196 {
197    IDataObject *object = new DataObject((FORMATETC *)fmtetc, (STGMEDIUM *)stgmeds, (UINT)count);
198    assert(object != NULL);
199    return object;
200 }
201
202 void _ecore_win32_dnd_data_object_free(void *data_object)
203 {
204    if (!data_object)
205      return;
206
207    IDataObject *object = (IDataObject *)data_object;
208    object->Release();
209 }