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