diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp b/libraries/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp new file mode 100644 index 0000000..75e26f5 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_win32/ecore_win32_dnd_data_object.cpp | |||
@@ -0,0 +1,209 @@ | |||
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 | } | ||