New debug scheme with explicit debug channels declaration.
[wine/hacks.git] / dlls / shell32 / dataobject.c
blob05f900b241a8db3c2a8397f782a0cfcaeae55402
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 DEFAULT_DEBUG_CHANNEL(shell)
18 UINT cfShellIDList=0;
19 UINT cfFileGroupDesc=0;
20 UINT cfFileContents=0;
22 /***********************************************************************
23 * IEnumFORMATETC implementation
25 typedef struct
27 /* IUnknown fields */
28 ICOM_VTABLE(IEnumFORMATETC)* lpvtbl;
29 DWORD ref;
30 /* IEnumFORMATETC fields */
31 UINT posFmt;
32 UINT countFmt;
33 LPFORMATETC pFmt;
34 } IEnumFORMATETCImpl;
36 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
37 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
38 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
39 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
40 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
41 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
42 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
44 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
46 IEnumFORMATETC_fnQueryInterface,
47 IEnumFORMATETC_fnAddRef,
48 IEnumFORMATETC_fnRelease,
49 IEnumFORMATETC_fnNext,
50 IEnumFORMATETC_fnSkip,
51 IEnumFORMATETC_fnReset,
52 IEnumFORMATETC_fnClone
55 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
57 IEnumFORMATETCImpl* ef;
58 DWORD size=cfmt * sizeof(FORMATETC);
60 ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumFORMATETCImpl));
61 ef->ref=1;
62 ef->lpvtbl=&efvt;
64 ef->posFmt = 0;
65 ef->countFmt = cfmt;
66 ef->pFmt = SHAlloc (size);
68 if (ef->pFmt)
69 { memcpy(ef->pFmt, afmt, size);
72 TRACE(shell,"(%p)->()\n",ef);
73 shell32_ObjCount++;
74 return (LPENUMFORMATETC)ef;
76 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
78 ICOM_THIS(IEnumFORMATETCImpl,iface);
79 char xriid[50];
80 WINE_StringFromCLSID((LPCLSID)riid,xriid);
81 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
83 *ppvObj = NULL;
85 if(IsEqualIID(riid, &IID_IUnknown))
86 { *ppvObj = This;
88 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
89 { *ppvObj = (IDataObject*)This;
92 if(*ppvObj)
93 { IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
94 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
95 return S_OK;
97 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
98 return E_NOINTERFACE;
101 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
103 ICOM_THIS(IEnumFORMATETCImpl,iface);
104 TRACE(shell,"(%p)->(count=%lu)\n",This, This->ref);
105 shell32_ObjCount++;
106 return ++(This->ref);
108 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
110 ICOM_THIS(IEnumFORMATETCImpl,iface);
111 TRACE(shell,"(%p)->()\n",This);
113 shell32_ObjCount--;
115 if (!--(This->ref))
116 { TRACE(shell," destroying IEnumFORMATETC(%p)\n",This);
117 if (This->pFmt)
118 { SHFree (This->pFmt);
120 HeapFree(GetProcessHeap(),0,This);
121 return 0;
123 return This->ref;
125 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
127 ICOM_THIS(IEnumFORMATETCImpl,iface);
128 UINT cfetch;
129 HRESULT hres = S_FALSE;
131 TRACE (shell, "(%p)->()\n", This);
133 if (This->posFmt < This->countFmt)
134 { cfetch = This->countFmt - This->posFmt;
135 if (cfetch >= celt)
136 { cfetch = celt;
137 hres = S_OK;
139 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
140 This->posFmt += cfetch;
142 else
143 { cfetch = 0;
146 if (pceltFethed)
147 { *pceltFethed = cfetch;
150 return hres;
152 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
154 ICOM_THIS(IEnumFORMATETCImpl,iface);
155 FIXME (shell, "(%p)->(num=%lu)\n", This, celt);
157 This->posFmt += celt;
158 if (This->posFmt > This->countFmt)
159 { This->posFmt = This->countFmt;
160 return S_FALSE;
162 return S_OK;
164 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
166 ICOM_THIS(IEnumFORMATETCImpl,iface);
167 FIXME (shell, "(%p)->()\n", This);
169 This->posFmt = 0;
170 return S_OK;
172 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
174 ICOM_THIS(IEnumFORMATETCImpl,iface);
175 FIXME (shell, "(%p)->(ppenum=%p)\n", This, ppenum);
176 return E_NOTIMPL;
179 /***********************************************************************
180 * IDataObject implementation
183 typedef struct
185 /* IUnknown fields */
186 ICOM_VTABLE(IDataObject)* lpvtbl;
187 DWORD ref;
188 /* IDataObject fields */
189 LPSHELLFOLDER psf;
190 LPIDLLIST lpill; /* the data of the dataobject */
191 LPITEMIDLIST pidl;
192 } IDataObjectImpl;
194 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID* ppvObj);
195 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface);
196 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface);
197 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM* pmedium);
198 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM* pmedium);
199 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc);
200 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut);
201 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM* pmedium, BOOL fRelease);
202 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc);
203 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection);
204 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection);
205 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise);
207 static struct ICOM_VTABLE(IDataObject) dtovt =
209 IDataObject_fnQueryInterface,
210 IDataObject_fnAddRef,
211 IDataObject_fnRelease,
212 IDataObject_fnGetData,
213 IDataObject_fnGetDataHere,
214 IDataObject_fnQueryGetData,
215 IDataObject_fnGetCanonicalFormatEtc,
216 IDataObject_fnSetData,
217 IDataObject_fnEnumFormatEtc,
218 IDataObject_fnDAdvise,
219 IDataObject_fnDUnadvise,
220 IDataObject_fnEnumDAdvise
223 /**************************************************************************
224 * IDataObject_Constructor
226 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPSHELLFOLDER psf, LPITEMIDLIST * apidl, UINT cidl)
228 IDataObjectImpl* dto;
229 if (!(dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObjectImpl))))
230 return NULL;
232 dto->ref=1;
233 dto->lpvtbl=&dtovt;
234 dto->psf=psf;
235 dto->pidl=ILClone(((IGenericSFImpl*)psf)->pMyPidl); /* FIXME:add a reference and don't copy*/
237 /* fill the ItemID List List */
238 dto->lpill = IDLList_Constructor (8);
239 if (! dto->lpill )
240 return NULL;
242 dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl);
244 TRACE(shell,"(%p)->(sf=%p apidl=%p cidl=%u)\n",dto, psf, apidl, cidl);
245 shell32_ObjCount++;
246 return (LPDATAOBJECT)dto;
248 /***************************************************************************
249 * IDataObject_QueryInterface
251 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
253 ICOM_THIS(IDataObjectImpl,iface);
254 char xriid[50];
255 WINE_StringFromCLSID((LPCLSID)riid,xriid);
256 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
258 *ppvObj = NULL;
260 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
261 { *ppvObj = This;
263 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
264 { *ppvObj = (IDataObject*)This;
267 if(*ppvObj)
268 { IDataObject_AddRef((IDataObject*)*ppvObj);
269 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
270 return S_OK;
272 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
273 return E_NOINTERFACE;
275 /**************************************************************************
276 * IDataObject_AddRef
278 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
280 ICOM_THIS(IDataObjectImpl,iface);
282 TRACE(shell,"(%p)->(count=%lu)\n",This, This->ref);
284 shell32_ObjCount++;
285 return ++(This->ref);
287 /**************************************************************************
288 * IDataObject_Release
290 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
292 ICOM_THIS(IDataObjectImpl,iface);
293 TRACE(shell,"(%p)->()\n",This);
295 shell32_ObjCount--;
297 if (!--(This->ref))
298 { TRACE(shell," destroying IDataObject(%p)\n",This);
299 IDLList_Destructor(This->lpill);
300 HeapFree(GetProcessHeap(),0,This);
301 return 0;
303 return This->ref;
305 /**************************************************************************
306 * DATAOBJECT_InitShellIDList (internal)
308 * NOTES
309 * get or register the "Shell IDList Array" clipformat
311 static BOOL DATAOBJECT_InitShellIDList(void)
312 { if (cfShellIDList)
313 { return(TRUE);
316 cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
317 return(cfShellIDList != 0);
320 /**************************************************************************
321 * DATAOBJECT_InitFileGroupDesc (internal)
323 * NOTES
324 * get or register the "FileGroupDescriptor" clipformat
326 /* FIXME: DATAOBJECT_InitFileGroupDesc is not used (19981226)
327 static BOOL32 DATAOBJECT_InitFileGroupDesc(void)
328 { if (cfFileGroupDesc)
329 { return(TRUE);
332 cfFileGroupDesc = RegisterClipboardFormatA(CFSTR_FILEDESCRIPTORA);
333 return(cfFileGroupDesc != 0);
336 /**************************************************************************
337 * DATAOBJECT_InitFileContents (internal)
339 * NOTES
340 * get or register the "FileContents" clipformat
342 /* FIXME: DATAOBJECT_InitFileContents is not used (19981226)
343 static BOOL32 DATAOBJECT_InitFileContents(void)
344 { if (cfFileContents)
345 { return(TRUE);
348 cfFileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);
349 return(cfFileContents != 0);
353 /**************************************************************************
354 * interface implementation
356 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
358 ICOM_THIS(IDataObjectImpl,iface);
359 char temp[256];
360 UINT cItems;
361 DWORD size, size1, size2;
362 LPITEMIDLIST pidl;
363 LPCIDA pcida;
364 HGLOBAL hmem;
366 GetClipboardFormatNameA (pformatetcIn->cfFormat, temp, 256);
367 WARN (shell, "(%p)->(%p %p format=%s)semi-stub\n", This, pformatetcIn, pmedium, temp);
369 if (!DATAOBJECT_InitShellIDList()) /* is the clipformat registred? */
370 { return(E_UNEXPECTED);
373 if (pformatetcIn->cfFormat == cfShellIDList)
374 { if (pformatetcIn->ptd==NULL
375 && (pformatetcIn->dwAspect & DVASPECT_CONTENT)
376 && pformatetcIn->lindex==-1
377 && (pformatetcIn->tymed&TYMED_HGLOBAL))
378 { cItems = This->lpill->lpvtbl->fnGetCount(This->lpill);
379 if (cItems < 1)
380 { return(E_UNEXPECTED);
382 pidl = This->lpill->lpvtbl->fnGetElement(This->lpill, 0);
384 pdump(This->pidl);
385 pdump(pidl);
387 /*hack consider only the first item*/
388 cItems = 2;
389 size = sizeof(CIDA) + sizeof (UINT)*(cItems-1);
390 size1 = ILGetSize (This->pidl);
391 size2 = ILGetSize (pidl);
392 hmem = GlobalAlloc(GMEM_FIXED, size+size1+size2);
393 pcida = GlobalLock (hmem);
394 if (!pcida)
395 { return(E_OUTOFMEMORY);
398 pcida->cidl = 1;
399 pcida->aoffset[0] = size;
400 pcida->aoffset[1] = size+size1;
402 TRACE(shell,"-- %lu %lu %lu\n",size, size1, size2 );
403 TRACE(shell,"-- %p %p\n",This->pidl, pidl);
404 TRACE(shell,"-- %p %p %p\n",pcida, (LPBYTE)pcida+size,(LPBYTE)pcida+size+size1);
406 memcpy ((LPBYTE)pcida+size, This->pidl, size1);
407 memcpy ((LPBYTE)pcida+size+size1, pidl, size2);
408 TRACE(shell,"-- after copy\n");
410 GlobalUnlock(hmem);
412 pmedium->tymed = TYMED_HGLOBAL;
413 pmedium->u.hGlobal = (HGLOBAL)pcida;
414 pmedium->pUnkForRelease = NULL;
415 TRACE(shell,"-- ready\n");
416 return(NOERROR);
419 FIXME (shell, "-- clipformat not implemented\n");
420 return (E_INVALIDARG);
422 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
424 ICOM_THIS(IDataObjectImpl,iface);
425 FIXME (shell, "(%p)->()\n", This);
426 return E_NOTIMPL;
428 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
430 ICOM_THIS(IDataObjectImpl,iface);
431 FIXME (shell, "(%p)->()\n", This);
432 return E_NOTIMPL;
434 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
436 ICOM_THIS(IDataObjectImpl,iface);
437 FIXME (shell, "(%p)->()\n", This);
438 return E_NOTIMPL;
440 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
442 ICOM_THIS(IDataObjectImpl,iface);
443 FIXME (shell, "(%p)->()\n", This);
444 return E_NOTIMPL;
446 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
448 ICOM_THIS(IDataObjectImpl,iface);
449 FIXME (shell, "(%p)->()\n", This);
450 return E_NOTIMPL;
452 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
454 ICOM_THIS(IDataObjectImpl,iface);
455 FIXME (shell, "(%p)->()\n", This);
456 return E_NOTIMPL;
458 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
460 ICOM_THIS(IDataObjectImpl,iface);
461 FIXME (shell, "(%p)->()\n", This);
462 return E_NOTIMPL;
464 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
466 ICOM_THIS(IDataObjectImpl,iface);
467 FIXME (shell, "(%p)->()\n", This);
468 return E_NOTIMPL;