- IShellFolder and IEnumIDList are using the new COM headers
[wine/wine-kai.git] / dlls / shell32 / dataobject.c
blob96111104216822b41b8e18e6a1bae1c3e1c3fddf
1 /*
2 * IEnumFORMATETC, IDataObject
4 * selecting and droping objects within the shell and/or common dialogs
6 * Copyright 1998 <juergen.schmied@metronet.de>
7 */
8 #include <string.h>
10 #include "oleidl.h"
11 #include "pidl.h"
12 #include "winerror.h"
13 #include "shell32_main.h"
14 #include "debug.h"
16 UINT cfShellIDList=0;
17 UINT cfFileGroupDesc=0;
18 UINT cfFileContents=0;
20 /***********************************************************************
21 * IEnumFORMATETC implementation
23 typedef struct
25 /* IUnknown fields */
26 ICOM_VTABLE(IEnumFORMATETC)* lpvtbl;
27 DWORD ref;
28 /* IEnumFORMATETC fields */
29 UINT posFmt;
30 UINT countFmt;
31 LPFORMATETC pFmt;
32 } IEnumFORMATETCImpl;
34 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
35 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
36 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
37 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
38 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
39 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
40 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
42 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
44 IEnumFORMATETC_fnQueryInterface,
45 IEnumFORMATETC_fnAddRef,
46 IEnumFORMATETC_fnRelease,
47 IEnumFORMATETC_fnNext,
48 IEnumFORMATETC_fnSkip,
49 IEnumFORMATETC_fnReset,
50 IEnumFORMATETC_fnClone
53 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
55 IEnumFORMATETCImpl* ef;
56 DWORD size=cfmt * sizeof(FORMATETC);
58 ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumFORMATETCImpl));
59 ef->ref=1;
60 ef->lpvtbl=&efvt;
62 ef->posFmt = 0;
63 ef->countFmt = cfmt;
64 ef->pFmt = SHAlloc (size);
66 if (ef->pFmt)
67 { memcpy(ef->pFmt, afmt, size);
70 TRACE(shell,"(%p)->()\n",ef);
71 shell32_ObjCount++;
72 return (LPENUMFORMATETC)ef;
74 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
76 ICOM_THIS(IEnumFORMATETCImpl,iface);
77 char xriid[50];
78 WINE_StringFromCLSID((LPCLSID)riid,xriid);
79 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
81 *ppvObj = NULL;
83 if(IsEqualIID(riid, &IID_IUnknown))
84 { *ppvObj = This;
86 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
87 { *ppvObj = (IDataObject*)This;
90 if(*ppvObj)
91 { IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
92 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
93 return S_OK;
95 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
96 return E_NOINTERFACE;
99 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
101 ICOM_THIS(IEnumFORMATETCImpl,iface);
102 TRACE(shell,"(%p)->(count=%lu)\n",This,(This->ref)+1);
103 shell32_ObjCount++;
104 return ++(This->ref);
106 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
108 ICOM_THIS(IEnumFORMATETCImpl,iface);
109 TRACE(shell,"(%p)->()\n",This);
111 shell32_ObjCount--;
113 if (!--(This->ref))
114 { TRACE(shell," destroying IEnumFORMATETC(%p)\n",This);
115 if (This->pFmt)
116 { SHFree (This->pFmt);
118 HeapFree(GetProcessHeap(),0,This);
119 return 0;
121 return This->ref;
123 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
125 ICOM_THIS(IEnumFORMATETCImpl,iface);
126 UINT cfetch;
127 HRESULT hres = S_FALSE;
129 TRACE (shell, "(%p)->()\n", This);
131 if (This->posFmt < This->countFmt)
132 { cfetch = This->countFmt - This->posFmt;
133 if (cfetch >= celt)
134 { cfetch = celt;
135 hres = S_OK;
137 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
138 This->posFmt += cfetch;
140 else
141 { cfetch = 0;
144 if (pceltFethed)
145 { *pceltFethed = cfetch;
148 return hres;
150 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
152 ICOM_THIS(IEnumFORMATETCImpl,iface);
153 FIXME (shell, "(%p)->(num=%lu)\n", This, celt);
155 This->posFmt += celt;
156 if (This->posFmt > This->countFmt)
157 { This->posFmt = This->countFmt;
158 return S_FALSE;
160 return S_OK;
162 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
164 ICOM_THIS(IEnumFORMATETCImpl,iface);
165 FIXME (shell, "(%p)->()\n", This);
167 This->posFmt = 0;
168 return S_OK;
170 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
172 ICOM_THIS(IEnumFORMATETCImpl,iface);
173 FIXME (shell, "(%p)->(ppenum=%p)\n", This, ppenum);
174 return E_NOTIMPL;
177 /***********************************************************************
178 * IDataObject implementation
181 typedef struct
183 /* IUnknown fields */
184 ICOM_VTABLE(IDataObject)* lpvtbl;
185 DWORD ref;
186 /* IDataObject fields */
187 LPSHELLFOLDER psf;
188 LPIDLLIST lpill; /* the data of the dataobject */
189 LPITEMIDLIST pidl;
190 } IDataObjectImpl;
192 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID* ppvObj);
193 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface);
194 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface);
195 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM* pmedium);
196 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM* pmedium);
197 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc);
198 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut);
199 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM* pmedium, BOOL fRelease);
200 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc);
201 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, LPFORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection);
202 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection);
203 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise);
205 static struct ICOM_VTABLE(IDataObject) dtovt =
207 IDataObject_fnQueryInterface,
208 IDataObject_fnAddRef,
209 IDataObject_fnRelease,
210 IDataObject_fnGetData,
211 IDataObject_fnGetDataHere,
212 IDataObject_fnQueryGetData,
213 IDataObject_fnGetCanonicalFormatEtc,
214 IDataObject_fnSetData,
215 IDataObject_fnEnumFormatEtc,
216 IDataObject_fnDAdvise,
217 IDataObject_fnDUnadvise,
218 IDataObject_fnEnumDAdvise
221 /**************************************************************************
222 * IDataObject_Constructor
224 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPSHELLFOLDER psf, LPITEMIDLIST * apidl, UINT cidl)
226 IDataObjectImpl* dto;
227 if (!(dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObjectImpl))))
228 return NULL;
230 dto->ref=1;
231 dto->lpvtbl=&dtovt;
232 dto->psf=psf;
233 dto->pidl=ILClone(((IGenericSFImpl*)psf)->pMyPidl); /* FIXME:add a reference and don't copy*/
235 /* fill the ItemID List List */
236 dto->lpill = IDLList_Constructor (8);
237 if (! dto->lpill )
238 return NULL;
240 dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl);
242 TRACE(shell,"(%p)->(sf=%p apidl=%p cidl=%u)\n",dto, psf, apidl, cidl);
243 shell32_ObjCount++;
244 return (LPDATAOBJECT)dto;
246 /***************************************************************************
247 * IDataObject_QueryInterface
249 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
251 ICOM_THIS(IDataObjectImpl,iface);
252 char xriid[50];
253 WINE_StringFromCLSID((LPCLSID)riid,xriid);
254 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
256 *ppvObj = NULL;
258 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
259 { *ppvObj = This;
261 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
262 { *ppvObj = (IDataObject*)This;
265 if(*ppvObj)
266 { IDataObject_AddRef((IDataObject*)*ppvObj);
267 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
268 return S_OK;
270 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
271 return E_NOINTERFACE;
273 /**************************************************************************
274 * IDataObject_AddRef
276 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
278 ICOM_THIS(IDataObjectImpl,iface);
280 TRACE(shell,"(%p)->(count=%lu)\n",This,(This->ref)+1);
282 shell32_ObjCount++;
283 return ++(This->ref);
285 /**************************************************************************
286 * IDataObject_Release
288 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
290 ICOM_THIS(IDataObjectImpl,iface);
291 TRACE(shell,"(%p)->()\n",This);
293 shell32_ObjCount--;
295 if (!--(This->ref))
296 { TRACE(shell," destroying IDataObject(%p)\n",This);
297 IDLList_Destructor(This->lpill);
298 HeapFree(GetProcessHeap(),0,This);
299 return 0;
301 return This->ref;
303 /**************************************************************************
304 * DATAOBJECT_InitShellIDList (internal)
306 * NOTES
307 * get or register the "Shell IDList Array" clipformat
309 static BOOL DATAOBJECT_InitShellIDList(void)
310 { if (cfShellIDList)
311 { return(TRUE);
314 cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
315 return(cfShellIDList != 0);
318 /**************************************************************************
319 * DATAOBJECT_InitFileGroupDesc (internal)
321 * NOTES
322 * get or register the "FileGroupDescriptor" clipformat
324 /* FIXME: DATAOBJECT_InitFileGroupDesc is not used (19981226)
325 static BOOL32 DATAOBJECT_InitFileGroupDesc(void)
326 { if (cfFileGroupDesc)
327 { return(TRUE);
330 cfFileGroupDesc = RegisterClipboardFormatA(CFSTR_FILEDESCRIPTORA);
331 return(cfFileGroupDesc != 0);
334 /**************************************************************************
335 * DATAOBJECT_InitFileContents (internal)
337 * NOTES
338 * get or register the "FileContents" clipformat
340 /* FIXME: DATAOBJECT_InitFileContents is not used (19981226)
341 static BOOL32 DATAOBJECT_InitFileContents(void)
342 { if (cfFileContents)
343 { return(TRUE);
346 cfFileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);
347 return(cfFileContents != 0);
351 /**************************************************************************
352 * interface implementation
354 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
356 ICOM_THIS(IDataObjectImpl,iface);
357 char temp[256];
358 UINT cItems;
359 DWORD size, size1, size2;
360 LPITEMIDLIST pidl;
361 LPCIDA pcida;
362 HGLOBAL hmem;
364 GetClipboardFormatNameA (pformatetcIn->cfFormat, temp, 256);
365 WARN (shell, "(%p)->(%p %p format=%s)semi-stub\n", This, pformatetcIn, pmedium, temp);
367 if (!DATAOBJECT_InitShellIDList()) /* is the clipformat registred? */
368 { return(E_UNEXPECTED);
371 if (pformatetcIn->cfFormat == cfShellIDList)
372 { if (pformatetcIn->ptd==NULL
373 && (pformatetcIn->dwAspect & DVASPECT_CONTENT)
374 && pformatetcIn->lindex==-1
375 && (pformatetcIn->tymed&TYMED_HGLOBAL))
376 { cItems = This->lpill->lpvtbl->fnGetCount(This->lpill);
377 if (cItems < 1)
378 { return(E_UNEXPECTED);
380 pidl = This->lpill->lpvtbl->fnGetElement(This->lpill, 0);
382 pdump(This->pidl);
383 pdump(pidl);
385 /*hack consider only the first item*/
386 cItems = 2;
387 size = sizeof(CIDA) + sizeof (UINT)*(cItems-1);
388 size1 = ILGetSize (This->pidl);
389 size2 = ILGetSize (pidl);
390 hmem = GlobalAlloc(GMEM_FIXED, size+size1+size2);
391 pcida = GlobalLock (hmem);
392 if (!pcida)
393 { return(E_OUTOFMEMORY);
396 pcida->cidl = 1;
397 pcida->aoffset[0] = size;
398 pcida->aoffset[1] = size+size1;
400 TRACE(shell,"-- %lu %lu %lu\n",size, size1, size2 );
401 TRACE(shell,"-- %p %p\n",This->pidl, pidl);
402 TRACE(shell,"-- %p %p %p\n",pcida, (LPBYTE)pcida+size,(LPBYTE)pcida+size+size1);
404 memcpy ((LPBYTE)pcida+size, This->pidl, size1);
405 memcpy ((LPBYTE)pcida+size+size1, pidl, size2);
406 TRACE(shell,"-- after copy\n");
408 GlobalUnlock(hmem);
410 pmedium->tymed = TYMED_HGLOBAL;
411 pmedium->u.hGlobal = (HGLOBAL)pcida;
412 pmedium->pUnkForRelease = NULL;
413 TRACE(shell,"-- ready\n");
414 return(NOERROR);
417 FIXME (shell, "-- clipformat not implemented\n");
418 return (E_INVALIDARG);
420 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
422 ICOM_THIS(IDataObjectImpl,iface);
423 FIXME (shell, "(%p)->()\n", This);
424 return E_NOTIMPL;
426 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
428 ICOM_THIS(IDataObjectImpl,iface);
429 FIXME (shell, "(%p)->()\n", This);
430 return E_NOTIMPL;
432 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
434 ICOM_THIS(IDataObjectImpl,iface);
435 FIXME (shell, "(%p)->()\n", This);
436 return E_NOTIMPL;
438 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
440 ICOM_THIS(IDataObjectImpl,iface);
441 FIXME (shell, "(%p)->()\n", This);
442 return E_NOTIMPL;
444 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
446 ICOM_THIS(IDataObjectImpl,iface);
447 FIXME (shell, "(%p)->()\n", This);
448 return E_NOTIMPL;
450 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, LPFORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
452 ICOM_THIS(IDataObjectImpl,iface);
453 FIXME (shell, "(%p)->()\n", This);
454 return E_NOTIMPL;
456 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
458 ICOM_THIS(IDataObjectImpl,iface);
459 FIXME (shell, "(%p)->()\n", This);
460 return E_NOTIMPL;
462 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
464 ICOM_THIS(IDataObjectImpl,iface);
465 FIXME (shell, "(%p)->()\n", This);
466 return E_NOTIMPL;