winedbg: Don't dereference possibly NULL thread pointer.
[wine/zf.git] / dlls / shell32 / dataobject.c
blob5c0dbc6bf87d07e91e8cf6c65fc4c84a8ae79fff
1 /*
2 * IEnumFORMATETC, IDataObject
4 * selecting and dropping objects within the shell and/or common dialogs
6 * Copyright 1998, 1999 <juergen.schmied@metronet.de>
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.
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.
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
22 #include <string.h>
24 #define COBJMACROS
25 #define NONAMELESSUNION
27 #include "windef.h"
28 #include "wingdi.h"
29 #include "pidl.h"
30 #include "winerror.h"
31 #include "shell32_main.h"
32 #include "wine/debug.h"
33 #include "undocshell.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37 /***********************************************************************
38 * IEnumFORMATETC implementation
41 typedef struct
43 /* IUnknown fields */
44 IEnumFORMATETC IEnumFORMATETC_iface;
45 LONG ref;
46 /* IEnumFORMATETC fields */
47 UINT posFmt;
48 UINT countFmt;
49 LPFORMATETC pFmt;
50 } IEnumFORMATETCImpl;
52 static inline IEnumFORMATETCImpl *impl_from_IEnumFORMATETC(IEnumFORMATETC *iface)
54 return CONTAINING_RECORD(iface, IEnumFORMATETCImpl, IEnumFORMATETC_iface);
57 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(
58 LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
60 IEnumFORMATETCImpl *This = impl_from_IEnumFORMATETC(iface);
61 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
63 *ppvObj = NULL;
65 if(IsEqualIID(riid, &IID_IUnknown) ||
66 IsEqualIID(riid, &IID_IEnumFORMATETC))
68 *ppvObj = &This->IEnumFORMATETC_iface;
71 if(*ppvObj)
73 IUnknown_AddRef((IUnknown*)(*ppvObj));
74 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
75 return S_OK;
77 TRACE("-- Interface: E_NOINTERFACE\n");
78 return E_NOINTERFACE;
81 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
83 IEnumFORMATETCImpl *This = impl_from_IEnumFORMATETC(iface);
84 ULONG refCount = InterlockedIncrement(&This->ref);
86 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
88 return refCount;
91 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
93 IEnumFORMATETCImpl *This = impl_from_IEnumFORMATETC(iface);
94 ULONG refCount = InterlockedDecrement(&This->ref);
96 TRACE("(%p)->(%u)\n", This, refCount + 1);
98 if (!refCount)
100 TRACE(" destroying IEnumFORMATETC(%p)\n",This);
101 SHFree (This->pFmt);
102 heap_free(This);
104 return refCount;
107 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
109 IEnumFORMATETCImpl *This = impl_from_IEnumFORMATETC(iface);
110 UINT i;
112 TRACE("(%p)->(%u,%p)\n", This, celt, rgelt);
114 if(!This->pFmt)return S_FALSE;
115 if(!rgelt) return E_INVALIDARG;
116 if (pceltFethed) *pceltFethed = 0;
118 for(i = 0; This->posFmt < This->countFmt && celt > i; i++)
120 *rgelt++ = This->pFmt[This->posFmt++];
123 if (pceltFethed) *pceltFethed = i;
125 return ((i == celt) ? S_OK : S_FALSE);
128 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
130 IEnumFORMATETCImpl *This = impl_from_IEnumFORMATETC(iface);
131 TRACE("(%p)->(num=%u)\n", This, celt);
133 if((This->posFmt + celt) >= This->countFmt) return S_FALSE;
134 This->posFmt += celt;
135 return S_OK;
138 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
140 IEnumFORMATETCImpl *This = impl_from_IEnumFORMATETC(iface);
141 TRACE("(%p)->()\n", This);
143 This->posFmt = 0;
144 return S_OK;
147 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
149 IEnumFORMATETCImpl *This = impl_from_IEnumFORMATETC(iface);
150 TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
152 if (!ppenum) return E_INVALIDARG;
153 *ppenum = IEnumFORMATETC_Constructor(This->countFmt, This->pFmt);
154 if(*ppenum)
155 IEnumFORMATETC_fnSkip(*ppenum, This->posFmt);
156 return S_OK;
159 static const IEnumFORMATETCVtbl efvt =
161 IEnumFORMATETC_fnQueryInterface,
162 IEnumFORMATETC_fnAddRef,
163 IEnumFORMATETC_fnRelease,
164 IEnumFORMATETC_fnNext,
165 IEnumFORMATETC_fnSkip,
166 IEnumFORMATETC_fnReset,
167 IEnumFORMATETC_fnClone
170 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
172 IEnumFORMATETCImpl* ef;
173 DWORD size=cfmt * sizeof(FORMATETC);
175 ef = heap_alloc_zero(sizeof(*ef));
177 if(ef)
179 ef->ref=1;
180 ef->IEnumFORMATETC_iface.lpVtbl = &efvt;
182 ef->countFmt = cfmt;
183 ef->pFmt = SHAlloc (size);
185 if (ef->pFmt)
186 memcpy(ef->pFmt, afmt, size);
189 TRACE("(%p)->(%u,%p)\n",ef, cfmt, afmt);
190 return &ef->IEnumFORMATETC_iface;
194 /***********************************************************************
195 * IDataObject implementation
198 /* number of supported formats */
199 #define MAX_FORMATS 4
201 typedef struct
203 /* IUnknown fields */
204 IDataObject IDataObject_iface;
205 LONG ref;
207 /* IDataObject fields */
208 LPITEMIDLIST pidl;
209 LPITEMIDLIST * apidl;
210 UINT cidl;
212 FORMATETC pFormatEtc[MAX_FORMATS];
213 UINT cfShellIDList;
214 UINT cfFileNameA;
215 UINT cfFileNameW;
217 } IDataObjectImpl;
219 static inline IDataObjectImpl *impl_from_IDataObject(IDataObject *iface)
221 return CONTAINING_RECORD(iface, IDataObjectImpl, IDataObject_iface);
224 /***************************************************************************
225 * IDataObject_QueryInterface
227 static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject *iface, REFIID riid, LPVOID * ppvObj)
229 IDataObjectImpl *This = impl_from_IDataObject(iface);
230 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
232 *ppvObj = NULL;
234 if(IsEqualIID(riid, &IID_IUnknown) ||
235 IsEqualIID(riid, &IID_IDataObject))
237 *ppvObj = &This->IDataObject_iface;
240 if(*ppvObj)
242 IUnknown_AddRef((IUnknown*)*ppvObj);
243 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
244 return S_OK;
246 TRACE("-- Interface: E_NOINTERFACE\n");
247 return E_NOINTERFACE;
250 /**************************************************************************
251 * IDataObject_AddRef
253 static ULONG WINAPI IDataObject_fnAddRef(IDataObject *iface)
255 IDataObjectImpl *This = impl_from_IDataObject(iface);
256 ULONG refCount = InterlockedIncrement(&This->ref);
258 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
260 return refCount;
263 /**************************************************************************
264 * IDataObject_Release
266 static ULONG WINAPI IDataObject_fnRelease(IDataObject *iface)
268 IDataObjectImpl *This = impl_from_IDataObject(iface);
269 ULONG refCount = InterlockedDecrement(&This->ref);
271 TRACE("(%p)->(%u)\n", This, refCount + 1);
273 if (!refCount)
275 TRACE(" destroying IDataObject(%p)\n",This);
276 _ILFreeaPidl(This->apidl, This->cidl);
277 ILFree(This->pidl);
278 heap_free(This);
280 return refCount;
283 /**************************************************************************
284 * IDataObject_fnGetData
286 static HRESULT WINAPI IDataObject_fnGetData(IDataObject *iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
288 IDataObjectImpl *This = impl_from_IDataObject(iface);
290 char szTemp[256];
292 szTemp[0]=0;
293 GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
294 TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp);
296 if (pformatetcIn->cfFormat == This->cfShellIDList)
298 if (This->cidl < 1) return(E_UNEXPECTED);
299 pmedium->u.hGlobal = RenderSHELLIDLIST(This->pidl, This->apidl, This->cidl);
301 else if (pformatetcIn->cfFormat == CF_HDROP)
303 if (This->cidl < 1) return(E_UNEXPECTED);
304 pmedium->u.hGlobal = RenderHDROP(This->pidl, This->apidl, This->cidl);
306 else if (pformatetcIn->cfFormat == This->cfFileNameA)
308 if (This->cidl < 1) return(E_UNEXPECTED);
309 pmedium->u.hGlobal = RenderFILENAMEA(This->pidl, This->apidl, This->cidl);
311 else if (pformatetcIn->cfFormat == This->cfFileNameW)
313 if (This->cidl < 1) return(E_UNEXPECTED);
314 pmedium->u.hGlobal = RenderFILENAMEW(This->pidl, This->apidl, This->cidl);
316 else
318 FIXME("-- expected clipformat not implemented\n");
319 return (E_INVALIDARG);
321 if (pmedium->u.hGlobal)
323 pmedium->tymed = TYMED_HGLOBAL;
324 pmedium->pUnkForRelease = NULL;
325 return S_OK;
327 return E_OUTOFMEMORY;
330 static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject *iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
332 IDataObjectImpl *This = impl_from_IDataObject(iface);
333 FIXME("(%p)->()\n", This);
334 return E_NOTIMPL;
337 static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject *iface, LPFORMATETC pformatetc)
339 IDataObjectImpl *This = impl_from_IDataObject(iface);
340 UINT i;
342 TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", This, pformatetc->cfFormat, pformatetc->tymed);
344 if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
345 return DV_E_DVASPECT;
347 /* check our formats table what we have */
348 for (i=0; i<MAX_FORMATS; i++)
350 if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
351 && (This->pFormatEtc[i].tymed & pformatetc->tymed))
353 return S_OK;
357 return DV_E_TYMED;
360 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(IDataObject *iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
362 IDataObjectImpl *This = impl_from_IDataObject(iface);
363 FIXME("(%p)->()\n", This);
364 return E_NOTIMPL;
367 static HRESULT WINAPI IDataObject_fnSetData(IDataObject *iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
369 IDataObjectImpl *This = impl_from_IDataObject(iface);
370 FIXME("(%p)->()\n", This);
371 return E_NOTIMPL;
374 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject *iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
376 IDataObjectImpl *This = impl_from_IDataObject(iface);
378 TRACE("(%p)->()\n", This);
379 *ppenumFormatEtc=NULL;
381 /* only get data */
382 if (DATADIR_GET == dwDirection)
384 *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc);
385 return (*ppenumFormatEtc) ? S_OK : E_FAIL;
388 return E_NOTIMPL;
391 static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
393 IDataObjectImpl *This = impl_from_IDataObject(iface);
394 FIXME("(%p)->()\n", This);
395 return E_NOTIMPL;
397 static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject *iface, DWORD dwConnection)
399 IDataObjectImpl *This = impl_from_IDataObject(iface);
400 FIXME("(%p)->()\n", This);
401 return E_NOTIMPL;
403 static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject *iface, IEnumSTATDATA **ppenumAdvise)
405 IDataObjectImpl *This = impl_from_IDataObject(iface);
406 FIXME("(%p)->()\n", This);
407 return E_NOTIMPL;
410 static const IDataObjectVtbl dtovt =
412 IDataObject_fnQueryInterface,
413 IDataObject_fnAddRef,
414 IDataObject_fnRelease,
415 IDataObject_fnGetData,
416 IDataObject_fnGetDataHere,
417 IDataObject_fnQueryGetData,
418 IDataObject_fnGetCanonicalFormatEtc,
419 IDataObject_fnSetData,
420 IDataObject_fnEnumFormatEtc,
421 IDataObject_fnDAdvise,
422 IDataObject_fnDUnadvise,
423 IDataObject_fnEnumDAdvise
426 /**************************************************************************
427 * IDataObject_Constructor
429 IDataObject* IDataObject_Constructor(HWND hwndOwner,
430 LPCITEMIDLIST pMyPidl, LPCITEMIDLIST * apidl, UINT cidl)
432 IDataObjectImpl* dto;
434 dto = heap_alloc_zero(sizeof(*dto));
436 if (dto)
438 dto->ref = 1;
439 dto->IDataObject_iface.lpVtbl = &dtovt;
440 dto->pidl = ILClone(pMyPidl);
441 dto->apidl = _ILCopyaPidl(apidl, cidl);
442 dto->cidl = cidl;
444 dto->cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
445 dto->cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA);
446 dto->cfFileNameW = RegisterClipboardFormatW(CFSTR_FILENAMEW);
447 InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL);
448 InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL);
449 InitFormatEtc(dto->pFormatEtc[2], dto->cfFileNameA, TYMED_HGLOBAL);
450 InitFormatEtc(dto->pFormatEtc[3], dto->cfFileNameW, TYMED_HGLOBAL);
453 TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl);
454 return &dto->IDataObject_iface;