Revert an unwanted change from r66575.
[reactos.git] / reactos / dll / win32 / shell32 / dataobject.c
1 /*
2 * IEnumFORMATETC, IDataObject
3 *
4 * selecting and droping objects within the shell and/or common dialogs
5 *
6 * Copyright 1998, 1999 <juergen.schmied@metronet.de>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 #include <precomp.h>
24
25 WINE_DEFAULT_DEBUG_CHANNEL(shell);
26
27 /***********************************************************************
28 * IEnumFORMATETC implementation
29 */
30
31 typedef struct
32 {
33 /* IUnknown fields */
34 const IEnumFORMATETCVtbl *lpVtbl;
35 LONG ref;
36 /* IEnumFORMATETC fields */
37 UINT posFmt;
38 UINT countFmt;
39 LPFORMATETC pFmt;
40 } IEnumFORMATETCImpl;
41
42 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(
43 LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
44 {
45 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
46 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
47
48 *ppvObj = NULL;
49
50 if(IsEqualIID(riid, &IID_IUnknown))
51 {
52 *ppvObj = This;
53 }
54 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
55 {
56 *ppvObj = (IEnumFORMATETC*)This;
57 }
58
59 if(*ppvObj)
60 {
61 IUnknown_AddRef((IUnknown*)(*ppvObj));
62 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
63 return S_OK;
64 }
65 TRACE("-- Interface: E_NOINTERFACE\n");
66 return E_NOINTERFACE;
67 }
68
69 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
70 {
71 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
72 ULONG refCount = InterlockedIncrement(&This->ref);
73
74 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
75
76 return refCount;
77 }
78
79 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
80 {
81 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
82 ULONG refCount = InterlockedDecrement(&This->ref);
83
84 TRACE("(%p)->(%u)\n", This, refCount + 1);
85
86 if (!refCount)
87 {
88 TRACE(" destroying IEnumFORMATETC(%p)\n",This);
89 SHFree (This->pFmt);
90 HeapFree(GetProcessHeap(),0,This);
91 return 0;
92 }
93 return refCount;
94 }
95
96 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
97 {
98 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
99 UINT i;
100
101 TRACE("(%p)->(%u,%p)\n", This, celt, rgelt);
102
103 if(!This->pFmt)return S_FALSE;
104 if(!rgelt) return E_INVALIDARG;
105 if (pceltFethed) *pceltFethed = 0;
106
107 for(i = 0; This->posFmt < This->countFmt && celt > i; i++)
108 {
109 *rgelt++ = This->pFmt[This->posFmt++];
110 }
111
112 if (pceltFethed) *pceltFethed = i;
113
114 return ((i == celt) ? S_OK : S_FALSE);
115 }
116
117 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
118 {
119 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
120 TRACE("(%p)->(num=%u)\n", This, celt);
121
122 if((This->posFmt + celt) >= This->countFmt) return S_FALSE;
123 This->posFmt += celt;
124 return S_OK;
125 }
126
127 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
128 {
129 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
130 TRACE("(%p)->()\n", This);
131
132 This->posFmt = 0;
133 return S_OK;
134 }
135
136 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
137 {
138 IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
139 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
140
141 if (!ppenum) return E_INVALIDARG;
142 *ppenum = IEnumFORMATETC_Constructor(This->countFmt, This->pFmt);
143 if(*ppenum)
144 IEnumFORMATETC_fnSkip(*ppenum, This->posFmt);
145 return S_OK;
146 }
147
148 static const IEnumFORMATETCVtbl efvt =
149 {
150 IEnumFORMATETC_fnQueryInterface,
151 IEnumFORMATETC_fnAddRef,
152 IEnumFORMATETC_fnRelease,
153 IEnumFORMATETC_fnNext,
154 IEnumFORMATETC_fnSkip,
155 IEnumFORMATETC_fnReset,
156 IEnumFORMATETC_fnClone
157 };
158
159 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
160 {
161 IEnumFORMATETCImpl* ef;
162 DWORD size=cfmt * sizeof(FORMATETC);
163
164 ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
165
166 if(ef)
167 {
168 ef->ref=1;
169 ef->lpVtbl=&efvt;
170
171 ef->countFmt = cfmt;
172 ef->pFmt = SHAlloc (size);
173
174 if (ef->pFmt)
175 memcpy(ef->pFmt, afmt, size);
176 }
177
178 TRACE("(%p)->(%u,%p)\n",ef, cfmt, afmt);
179 return (LPENUMFORMATETC)ef;
180 }
181
182
183 /***********************************************************************
184 * IDataObject implementation
185 */
186
187 /* number of supported formats */
188 #define MAX_FORMATS 4
189
190 typedef struct
191 {
192 /* IUnknown fields */
193 const IDataObjectVtbl *lpVtbl;
194 LONG ref;
195
196 /* IDataObject fields */
197 LPITEMIDLIST pidl;
198 LPITEMIDLIST * apidl;
199 UINT cidl;
200
201 FORMATETC pFormatEtc[MAX_FORMATS];
202 UINT cfShellIDList;
203 UINT cfFileNameA;
204 UINT cfFileNameW;
205
206 } IDataObjectImpl;
207
208 /***************************************************************************
209 * IDataObject_QueryInterface
210 */
211 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
212 {
213 IDataObjectImpl *This = (IDataObjectImpl *)iface;
214 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
215
216 *ppvObj = NULL;
217
218 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
219 {
220 *ppvObj = This;
221 }
222 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
223 {
224 *ppvObj = (IDataObject*)This;
225 }
226
227 if(*ppvObj)
228 {
229 IUnknown_AddRef((IUnknown*)*ppvObj);
230 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
231 return S_OK;
232 }
233 TRACE("-- Interface: E_NOINTERFACE\n");
234 return E_NOINTERFACE;
235 }
236
237 /**************************************************************************
238 * IDataObject_AddRef
239 */
240 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
241 {
242 IDataObjectImpl *This = (IDataObjectImpl *)iface;
243 ULONG refCount = InterlockedIncrement(&This->ref);
244
245 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
246
247 return refCount;
248 }
249
250 /**************************************************************************
251 * IDataObject_Release
252 */
253 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
254 {
255 IDataObjectImpl *This = (IDataObjectImpl *)iface;
256 ULONG refCount = InterlockedDecrement(&This->ref);
257
258 TRACE("(%p)->(%u)\n", This, refCount + 1);
259
260 if (!refCount)
261 {
262 TRACE(" destroying IDataObject(%p)\n",This);
263 _ILFreeaPidl(This->apidl, This->cidl);
264 ILFree(This->pidl),
265 HeapFree(GetProcessHeap(),0,This);
266 }
267 return refCount;
268 }
269
270 /**************************************************************************
271 * IDataObject_fnGetData
272 */
273 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
274 {
275 IDataObjectImpl *This = (IDataObjectImpl *)iface;
276
277 char szTemp[256];
278
279 szTemp[0]=0;
280 GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
281 TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp);
282
283 if (pformatetcIn->cfFormat == This->cfShellIDList)
284 {
285 if (This->cidl < 1) return(E_UNEXPECTED);
286 pmedium->u.hGlobal = RenderSHELLIDLIST(This->pidl, This->apidl, This->cidl);
287 }
288 else if (pformatetcIn->cfFormat == CF_HDROP)
289 {
290 if (This->cidl < 1) return(E_UNEXPECTED);
291 pmedium->u.hGlobal = RenderHDROP(This->pidl, This->apidl, This->cidl);
292 }
293 else if (pformatetcIn->cfFormat == This->cfFileNameA)
294 {
295 if (This->cidl < 1) return(E_UNEXPECTED);
296 pmedium->u.hGlobal = RenderFILENAMEA(This->pidl, This->apidl, This->cidl);
297 }
298 else if (pformatetcIn->cfFormat == This->cfFileNameW)
299 {
300 if (This->cidl < 1) return(E_UNEXPECTED);
301 pmedium->u.hGlobal = RenderFILENAMEW(This->pidl, This->apidl, This->cidl);
302 }
303 else
304 {
305 FIXME("-- expected clipformat not implemented\n");
306 return (E_INVALIDARG);
307 }
308 if (pmedium->u.hGlobal)
309 {
310 pmedium->tymed = TYMED_HGLOBAL;
311 pmedium->pUnkForRelease = NULL;
312 return S_OK;
313 }
314 return E_OUTOFMEMORY;
315 }
316
317 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
318 {
319 IDataObjectImpl *This = (IDataObjectImpl *)iface;
320 FIXME("(%p)->()\n", This);
321 return E_NOTIMPL;
322 }
323
324 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
325 {
326 IDataObjectImpl *This = (IDataObjectImpl *)iface;
327 UINT i;
328
329 TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", This, pformatetc->cfFormat, pformatetc->tymed);
330
331 if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
332 return DV_E_DVASPECT;
333
334 /* check our formats table what we have */
335 for (i=0; i<MAX_FORMATS; i++)
336 {
337 if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
338 && (This->pFormatEtc[i].tymed == pformatetc->tymed))
339 {
340 return S_OK;
341 }
342 }
343
344 return DV_E_TYMED;
345 }
346
347 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
348 {
349 IDataObjectImpl *This = (IDataObjectImpl *)iface;
350 FIXME("(%p)->()\n", This);
351 return E_NOTIMPL;
352 }
353
354 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
355 {
356 IDataObjectImpl *This = (IDataObjectImpl *)iface;
357 FIXME("(%p)->()\n", This);
358 return E_NOTIMPL;
359 }
360
361 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
362 {
363 IDataObjectImpl *This = (IDataObjectImpl *)iface;
364
365 TRACE("(%p)->()\n", This);
366 *ppenumFormatEtc=NULL;
367
368 /* only get data */
369 if (DATADIR_GET == dwDirection)
370 {
371 *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc);
372 return (*ppenumFormatEtc) ? S_OK : E_FAIL;
373 }
374
375 return E_NOTIMPL;
376 }
377
378 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
379 {
380 IDataObjectImpl *This = (IDataObjectImpl *)iface;
381 FIXME("(%p)->()\n", This);
382 return E_NOTIMPL;
383 }
384 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
385 {
386 IDataObjectImpl *This = (IDataObjectImpl *)iface;
387 FIXME("(%p)->()\n", This);
388 return E_NOTIMPL;
389 }
390 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
391 {
392 IDataObjectImpl *This = (IDataObjectImpl *)iface;
393 FIXME("(%p)->()\n", This);
394 return E_NOTIMPL;
395 }
396
397 static const IDataObjectVtbl dtovt =
398 {
399 IDataObject_fnQueryInterface,
400 IDataObject_fnAddRef,
401 IDataObject_fnRelease,
402 IDataObject_fnGetData,
403 IDataObject_fnGetDataHere,
404 IDataObject_fnQueryGetData,
405 IDataObject_fnGetCanonicalFormatEtc,
406 IDataObject_fnSetData,
407 IDataObject_fnEnumFormatEtc,
408 IDataObject_fnDAdvise,
409 IDataObject_fnDUnadvise,
410 IDataObject_fnEnumDAdvise
411 };
412
413 /**************************************************************************
414 * IDataObject_Constructor
415 */
416 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner,
417 LPCITEMIDLIST pMyPidl, LPCITEMIDLIST * apidl, UINT cidl)
418 {
419 IDataObjectImpl* dto;
420
421 dto = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl));
422
423 if (dto)
424 {
425 dto->ref = 1;
426 dto->lpVtbl = &dtovt;
427 dto->pidl = ILClone(pMyPidl);
428 dto->apidl = _ILCopyaPidl(apidl, cidl);
429 dto->cidl = cidl;
430
431 dto->cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
432 dto->cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA);
433 dto->cfFileNameW = RegisterClipboardFormatW(CFSTR_FILENAMEW);
434 InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL);
435 InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL);
436 InitFormatEtc(dto->pFormatEtc[2], dto->cfFileNameA, TYMED_HGLOBAL);
437 InitFormatEtc(dto->pFormatEtc[3], dto->cfFileNameW, TYMED_HGLOBAL);
438 }
439
440 TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl);
441 return (LPDATAOBJECT)dto;
442 }
443
444 /*************************************************************************
445 * SHCreateDataObject [SHELL32.@]
446 *
447 */
448
449 HRESULT WINAPI SHCreateDataObject(LPCITEMIDLIST pidlFolder, UINT cidl, LPCITEMIDLIST* apidl, IDataObject *pdtInner, REFIID riid, void **ppv)
450 {
451 if (IsEqualIID(riid, &IID_IDataObject))
452 {
453 return CIDLData_CreateFromIDArray(pidlFolder, cidl, apidl, (IDataObject**)ppv);
454 }
455 return E_FAIL;
456 }