Fixed differences between SetRectRgn16 and SetRectRgn32. Also a bug fix for
[wine/multimedia.git] / dlls / shell32 / dataobject.c
blobe5ad445e6546f4cb9e48861b1a6152c4b1fea775
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 "debug.h"
9 #include "shlobj.h"
10 #include "pidl.h"
11 #include "winerror.h"
12 #include "shell32_main.h"
14 UINT32 cfShellIDList=0;
15 UINT32 cfFileGroupDesc=0;
16 UINT32 cfFileContents=0;
18 /***********************************************************************
19 * IEnumFORMATETC implementation
21 static HRESULT WINAPI IEnumFORMATETC_QueryInterface (LPENUMFORMATETC this, REFIID riid, LPVOID * ppvObj);
22 static ULONG WINAPI IEnumFORMATETC_AddRef (LPENUMFORMATETC this);
23 static ULONG WINAPI IEnumFORMATETC_Release (LPENUMFORMATETC this);
24 static HRESULT WINAPI IEnumFORMATETC_Next(LPENUMFORMATETC this, ULONG celt, FORMATETC32 *rgelt, ULONG *pceltFethed);
25 static HRESULT WINAPI IEnumFORMATETC_Skip(LPENUMFORMATETC this, ULONG celt);
26 static HRESULT WINAPI IEnumFORMATETC_Reset(LPENUMFORMATETC this);
27 static HRESULT WINAPI IEnumFORMATETC_Clone(LPENUMFORMATETC this, LPENUMFORMATETC* ppenum);
29 static struct IEnumFORMATETC_VTable efvt =
30 { IEnumFORMATETC_QueryInterface,
31 IEnumFORMATETC_AddRef,
32 IEnumFORMATETC_Release,
33 IEnumFORMATETC_Next,
34 IEnumFORMATETC_Skip,
35 IEnumFORMATETC_Reset,
36 IEnumFORMATETC_Clone
39 extern LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT32 cfmt, const FORMATETC32 afmt[])
40 { LPENUMFORMATETC ef;
41 DWORD size=cfmt * sizeof(FORMATETC32);
43 ef=(LPENUMFORMATETC)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumFORMATETC));
44 ef->ref=1;
45 ef->lpvtbl=&efvt;
47 ef->posFmt = 0;
48 ef->countFmt = cfmt;
49 ef->pFmt = SHAlloc (size);
51 if (ef->pFmt)
52 { memcpy(ef->pFmt, afmt, size);
55 TRACE(shell,"(%p)->()\n",ef);
56 return ef;
58 static HRESULT WINAPI IEnumFORMATETC_QueryInterface (LPENUMFORMATETC this, REFIID riid, LPVOID * ppvObj)
59 { char xriid[50];
60 WINE_StringFromCLSID((LPCLSID)riid,xriid);
61 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
63 *ppvObj = NULL;
65 if(IsEqualIID(riid, &IID_IUnknown))
66 { *ppvObj = this;
68 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
69 { *ppvObj = (IDataObject*)this;
72 if(*ppvObj)
73 { (*(LPENUMFORMATETC*)ppvObj)->lpvtbl->fnAddRef(this);
74 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
75 return S_OK;
77 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
78 return E_NOINTERFACE;
81 static ULONG WINAPI IEnumFORMATETC_AddRef (LPENUMFORMATETC this)
82 { TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
83 return ++(this->ref);
85 static ULONG WINAPI IEnumFORMATETC_Release (LPENUMFORMATETC this)
86 { TRACE(shell,"(%p)->()\n",this);
87 if (!--(this->ref))
88 { TRACE(shell," destroying IEnumFORMATETC(%p)\n",this);
89 if (this->pFmt)
90 { SHFree (this->pFmt);
92 HeapFree(GetProcessHeap(),0,this);
93 return 0;
95 return this->ref;
97 static HRESULT WINAPI IEnumFORMATETC_Next(LPENUMFORMATETC this, ULONG celt, FORMATETC32 *rgelt, ULONG *pceltFethed)
98 { UINT32 cfetch;
99 HRESULT hres = S_FALSE;
101 TRACE (shell, "(%p)->()\n", this);
103 if (this->posFmt < this->countFmt)
104 { cfetch = this->countFmt - this->posFmt;
105 if (cfetch >= celt)
106 { cfetch = celt;
107 hres = S_OK;
109 memcpy(rgelt, &this->pFmt[this->posFmt], cfetch * sizeof(FORMATETC32));
110 this->posFmt += cfetch;
112 else
113 { cfetch = 0;
116 if (pceltFethed)
117 { *pceltFethed = cfetch;
120 return hres;
122 static HRESULT WINAPI IEnumFORMATETC_Skip(LPENUMFORMATETC this, ULONG celt)
123 { FIXME (shell, "(%p)->(num=%lu)\n", this, celt);
125 this->posFmt += celt;
126 if (this->posFmt > this->countFmt)
127 { this->posFmt = this->countFmt;
128 return S_FALSE;
130 return S_OK;
132 static HRESULT WINAPI IEnumFORMATETC_Reset(LPENUMFORMATETC this)
133 { FIXME (shell, "(%p)->()\n", this);
135 this->posFmt = 0;
136 return S_OK;
138 static HRESULT WINAPI IEnumFORMATETC_Clone(LPENUMFORMATETC this, LPENUMFORMATETC* ppenum)
139 { FIXME (shell, "(%p)->(ppenum=%p)\n", this, ppenum);
140 return E_NOTIMPL;
143 /***********************************************************************
144 * IDataObject implementation
147 static HRESULT WINAPI IDataObject_QueryInterface (LPDATAOBJECT, REFIID riid, LPVOID * ppvObj);
148 static ULONG WINAPI IDataObject_AddRef (LPDATAOBJECT);
149 static ULONG WINAPI IDataObject_Release (LPDATAOBJECT);
150 static HRESULT WINAPI IDataObject_GetData (LPDATAOBJECT, LPFORMATETC32 pformatetcIn, STGMEDIUM32 *pmedium);
151 static HRESULT WINAPI IDataObject_GetDataHere(LPDATAOBJECT, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium);
152 static HRESULT WINAPI IDataObject_QueryGetData(LPDATAOBJECT, LPFORMATETC32 pformatetc);
153 static HRESULT WINAPI IDataObject_GetCanonicalFormatEtc(LPDATAOBJECT, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut);
154 static HRESULT WINAPI IDataObject_SetData(LPDATAOBJECT, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium, BOOL32 fRelease);
155 static HRESULT WINAPI IDataObject_EnumFormatEtc(LPDATAOBJECT, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc);
156 static HRESULT WINAPI IDataObject_DAdvise (LPDATAOBJECT, LPFORMATETC32 *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
157 static HRESULT WINAPI IDataObject_DUnadvise(LPDATAOBJECT, DWORD dwConnection);
158 static HRESULT WINAPI IDataObject_EnumDAdvise(LPDATAOBJECT, IEnumSTATDATA **ppenumAdvise);
160 static struct IDataObject_VTable dtovt =
161 { IDataObject_QueryInterface,
162 IDataObject_AddRef,
163 IDataObject_Release,
164 IDataObject_GetData,
165 IDataObject_GetDataHere,
166 IDataObject_QueryGetData,
167 IDataObject_GetCanonicalFormatEtc,
168 IDataObject_SetData,
169 IDataObject_EnumFormatEtc,
170 IDataObject_DAdvise,
171 IDataObject_DUnadvise,
172 IDataObject_EnumDAdvise
175 /**************************************************************************
176 * IDataObject_Constructor
178 LPDATAOBJECT IDataObject_Constructor(HWND32 hwndOwner, LPSHELLFOLDER psf, LPITEMIDLIST * apidl, UINT32 cidl)
179 { LPDATAOBJECT dto;
180 if (!(dto = (LPDATAOBJECT)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObject))))
181 return NULL;
183 dto->ref=1;
184 dto->lpvtbl=&dtovt;
185 dto->psf=psf;
186 dto->pidl=ILClone(psf->mpidl); /* FIXME:add a reference and don't copy*/
188 /* fill the ItemID List List */
189 dto->lpill = IDLList_Constructor (8);
190 if (! dto->lpill )
191 return NULL;
193 dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl);
195 TRACE(shell,"(%p)->(sf=%p apidl=%p cidl=%u)\n",dto, psf, apidl, cidl);
196 return dto;
198 /***************************************************************************
199 * IDataObject_QueryInterface
201 static HRESULT WINAPI IDataObject_QueryInterface (LPDATAOBJECT this, REFIID riid, LPVOID * ppvObj)
202 { char xriid[50];
203 WINE_StringFromCLSID((LPCLSID)riid,xriid);
204 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
206 *ppvObj = NULL;
208 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
209 { *ppvObj = this;
211 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
212 { *ppvObj = (IDataObject*)this;
215 if(*ppvObj)
216 { (*(LPDATAOBJECT*)ppvObj)->lpvtbl->fnAddRef(this);
217 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
218 return S_OK;
220 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
221 return E_NOINTERFACE;
223 /**************************************************************************
224 * IDataObject_AddRef
226 static ULONG WINAPI IDataObject_AddRef(LPDATAOBJECT this)
227 { TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
228 return ++(this->ref);
230 /**************************************************************************
231 * IDataObject_Release
233 static ULONG WINAPI IDataObject_Release(LPDATAOBJECT this)
234 { TRACE(shell,"(%p)->()\n",this);
235 if (!--(this->ref))
236 { TRACE(shell," destroying IDataObject(%p)\n",this);
237 IDLList_Destructor(this->lpill);
238 HeapFree(GetProcessHeap(),0,this);
239 return 0;
241 return this->ref;
243 /**************************************************************************
244 * DATAOBJECT_InitShellIDList (internal)
246 * NOTES
247 * get or register the "Shell IDList Array" clipformat
249 static BOOL32 DATAOBJECT_InitShellIDList()
250 { if (cfShellIDList)
251 { return(TRUE);
254 cfShellIDList = RegisterClipboardFormat32A(CFSTR_SHELLIDLIST);
255 return(cfShellIDList != 0);
258 /**************************************************************************
259 * DATAOBJECT_InitFileGroupDesc (internal)
261 * NOTES
262 * get or register the "FileGroupDescriptor" clipformat
264 static BOOL32 DATAOBJECT_InitFileGroupDesc()
265 { if (cfFileGroupDesc)
266 { return(TRUE);
269 cfFileGroupDesc = RegisterClipboardFormat32A(CFSTR_FILEDESCRIPTORA);
270 return(cfFileGroupDesc != 0);
272 /**************************************************************************
273 * DATAOBJECT_InitFileContents (internal)
275 * NOTES
276 * get or register the "FileContents" clipformat
278 static BOOL32 DATAOBJECT_InitFileContents()
279 { if (cfFileContents)
280 { return(TRUE);
283 cfFileContents = RegisterClipboardFormat32A(CFSTR_FILECONTENTS);
284 return(cfFileContents != 0);
288 /**************************************************************************
289 * interface implementation
291 static HRESULT WINAPI IDataObject_GetData (LPDATAOBJECT this, LPFORMATETC32 pformatetcIn, STGMEDIUM32 *pmedium)
292 { char temp[256];
293 UINT32 cItems;
294 DWORD size, size1, size2;
295 LPITEMIDLIST pidl;
296 LPCIDA pcida;
297 HGLOBAL32 hmem;
299 GetClipboardFormatName32A (pformatetcIn->cfFormat, temp, 256);
300 FIXME (shell, "(%p)->(%p %p format=%s)\n", this, pformatetcIn, pmedium, temp);
302 if (!DATAOBJECT_InitShellIDList()) /* is the clipformat registred? */
303 { return(E_UNEXPECTED);
306 if (pformatetcIn->cfFormat == cfShellIDList)
307 { if (pformatetcIn->ptd==NULL
308 && (pformatetcIn->dwAspect & DVASPECT_CONTENT)
309 && pformatetcIn->lindex==-1
310 && (pformatetcIn->tymed&TYMED_HGLOBAL))
311 { cItems = this->lpill->lpvtbl->fnGetCount(this->lpill);
312 if (cItems < 1)
313 { return(E_UNEXPECTED);
315 pidl = this->lpill->lpvtbl->fnGetElement(this->lpill, 0);
317 pdump(this->pidl);
318 pdump(pidl);
320 /*hack consider only the first item*/
321 cItems = 2;
322 size = sizeof(CIDA) + sizeof (UINT32)*(cItems-1);
323 size1 = ILGetSize (this->pidl);
324 size2 = ILGetSize (pidl);
325 hmem = GlobalAlloc32(GMEM_FIXED, size+size1+size2);
326 pcida = GlobalLock32 (hmem);
327 if (!pcida)
328 { return(E_OUTOFMEMORY);
331 pcida->cidl = 1;
332 pcida->aoffset[0] = size;
333 pcida->aoffset[1] = size+size1;
335 TRACE(shell,"-- %lu %lu %lu\n",size, size1, size2 );
336 TRACE(shell,"-- %p %p\n",this->pidl, pidl);
337 TRACE(shell,"-- %p %p %p\n",pcida, (void*)pcida+size,(void*)pcida+size+size1);
339 memcpy ((void*)pcida+size, this->pidl, size1);
340 memcpy ((void*)pcida+size+size1, pidl, size2);
341 TRACE(shell,"-- after copy\n");
343 GlobalUnlock32(hmem);
345 pmedium->tymed = TYMED_HGLOBAL;
346 pmedium->u.hGlobal = (HGLOBAL32)pcida;
347 pmedium->pUnkForRelease = NULL;
348 TRACE(shell,"-- ready\n");
349 return(NOERROR);
352 FIXME (shell, "-- clipformat not implemented\n");
353 return (E_INVALIDARG);
355 static HRESULT WINAPI IDataObject_GetDataHere(LPDATAOBJECT this, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium)
356 { FIXME (shell, "(%p)->()\n", this);
357 return E_NOTIMPL;
359 static HRESULT WINAPI IDataObject_QueryGetData(LPDATAOBJECT this, LPFORMATETC32 pformatetc)
360 { FIXME (shell, "(%p)->()\n", this);
361 return E_NOTIMPL;
363 static HRESULT WINAPI IDataObject_GetCanonicalFormatEtc(LPDATAOBJECT this, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut)
364 { FIXME (shell, "(%p)->()\n", this);
365 return E_NOTIMPL;
367 static HRESULT WINAPI IDataObject_SetData(LPDATAOBJECT this, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium, BOOL32 fRelease)
368 { FIXME (shell, "(%p)->()\n", this);
369 return E_NOTIMPL;
371 static HRESULT WINAPI IDataObject_EnumFormatEtc(LPDATAOBJECT this, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
372 { FIXME (shell, "(%p)->()\n", this);
373 return E_NOTIMPL;
375 static HRESULT WINAPI IDataObject_DAdvise (LPDATAOBJECT this, LPFORMATETC32 *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
376 { FIXME (shell, "(%p)->()\n", this);
377 return E_NOTIMPL;
379 static HRESULT WINAPI IDataObject_DUnadvise(LPDATAOBJECT this, DWORD dwConnection)
380 { FIXME (shell, "(%p)->()\n", this);
381 return E_NOTIMPL;
383 static HRESULT WINAPI IDataObject_EnumDAdvise(LPDATAOBJECT this, IEnumSTATDATA **ppenumAdvise)
384 { FIXME (shell, "(%p)->()\n", this);
385 return E_NOTIMPL;