xref: /reactos/dll/win32/ole32/ole2impl.c (revision 5100859e)
1 /*
2  * Ole 2 Create functions implementation
3  *
4  * Copyright (C) 1999-2000 Abey George
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdarg.h>
22 #include <string.h>
23 
24 #define COBJMACROS
25 #define NONAMELESSUNION
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "wine/debug.h"
32 #include "ole2.h"
33 #include "olestd.h"
34 #include "compobj_private.h"
35 
36 WINE_DEFAULT_DEBUG_CHANNEL(ole);
37 
38 /******************************************************************************
39  *		OleQueryCreateFromData [OLE32.@]
40  *
41  * Checks whether an object can become an embedded object.
42  * the clipboard or OLE drag and drop.
43  * Returns  : S_OK - Format that supports Embedded object creation are present.
44  *            OLE_E_STATIC - Format that supports static object creation are present.
45  *            S_FALSE - No acceptable format is available.
46  */
47 
48 HRESULT WINAPI OleQueryCreateFromData(IDataObject *data)
49 {
50     IEnumFORMATETC *enum_fmt;
51     FORMATETC fmt;
52     BOOL found_static = FALSE;
53     HRESULT hr;
54 
55     hr = IDataObject_EnumFormatEtc(data, DATADIR_GET, &enum_fmt);
56 
57     if(FAILED(hr)) return hr;
58 
59     do
60     {
61         hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
62         if(hr == S_OK)
63         {
64             if(fmt.cfFormat == embedded_object_clipboard_format ||
65                fmt.cfFormat == embed_source_clipboard_format ||
66                fmt.cfFormat == filename_clipboard_format)
67             {
68                 IEnumFORMATETC_Release(enum_fmt);
69                 return S_OK;
70             }
71 
72             if(fmt.cfFormat == CF_METAFILEPICT ||
73                fmt.cfFormat == CF_BITMAP ||
74                fmt.cfFormat == CF_DIB)
75                 found_static = TRUE;
76         }
77     } while (hr == S_OK);
78 
79     IEnumFORMATETC_Release(enum_fmt);
80 
81     return found_static ? OLE_S_STATIC : S_FALSE;
82 }
83 
84 static inline void init_fmtetc(FORMATETC *fmt, CLIPFORMAT cf, TYMED tymed)
85 {
86     fmt->cfFormat = cf;
87     fmt->ptd = NULL;
88     fmt->dwAspect = DVASPECT_CONTENT;
89     fmt->lindex = -1;
90     fmt->tymed = tymed;
91 }
92 
93 /***************************************************************************
94  *         get_storage
95  *
96  * Retrieve an object's storage from a variety of sources.
97  *
98  * FIXME: CF_FILENAME.
99  */
100 static HRESULT get_storage(IDataObject *data, IStorage *stg, UINT *src_cf, BOOL other_fmts)
101 {
102     static const UINT fmt_id[] = { CF_METAFILEPICT, CF_BITMAP, CF_DIB };
103     UINT i;
104     HRESULT hr;
105     FORMATETC fmt;
106     STGMEDIUM med;
107     IPersistStorage *persist;
108     CLSID clsid;
109 
110     if (src_cf) *src_cf = 0;
111 
112     /* CF_EMBEDEDOBJECT */
113     init_fmtetc(&fmt, embedded_object_clipboard_format, TYMED_ISTORAGE);
114     med.tymed = TYMED_ISTORAGE;
115     med.u.pstg = stg;
116     med.pUnkForRelease = NULL;
117     hr = IDataObject_GetDataHere(data, &fmt, &med);
118     if(SUCCEEDED(hr))
119     {
120         if (src_cf) *src_cf = embedded_object_clipboard_format;
121         return hr;
122     }
123 
124     /* CF_EMBEDSOURCE */
125     init_fmtetc(&fmt, embed_source_clipboard_format, TYMED_ISTORAGE);
126     med.tymed = TYMED_ISTORAGE;
127     med.u.pstg = stg;
128     med.pUnkForRelease = NULL;
129     hr = IDataObject_GetDataHere(data, &fmt, &med);
130     if(SUCCEEDED(hr))
131     {
132         if (src_cf) *src_cf = embed_source_clipboard_format;
133         return hr;
134     }
135 
136     if (other_fmts)
137     {
138         for (i = 0; i < sizeof(fmt_id)/sizeof(fmt_id[0]); i++)
139         {
140             init_fmtetc(&fmt, fmt_id[i], TYMED_ISTORAGE);
141             hr = IDataObject_QueryGetData(data, &fmt);
142             if (SUCCEEDED(hr))
143             {
144                 if (src_cf) *src_cf = fmt_id[i];
145                 return hr;
146             }
147         }
148     }
149 
150     /* IPersistStorage */
151     hr = IDataObject_QueryInterface(data, &IID_IPersistStorage, (void**)&persist);
152     if(FAILED(hr)) return hr;
153 
154     hr = IPersistStorage_GetClassID(persist, &clsid);
155     if(FAILED(hr)) goto end;
156 
157     hr = IStorage_SetClass(stg, &clsid);
158     if(FAILED(hr)) goto end;
159 
160     hr = IPersistStorage_Save(persist, stg, FALSE);
161     if(FAILED(hr)) goto end;
162 
163     hr = IPersistStorage_SaveCompleted(persist, NULL);
164 
165 end:
166     IPersistStorage_Release(persist);
167 
168     return hr;
169 }
170 
171 /******************************************************************************
172  *		OleCreateFromDataEx        [OLE32.@]
173  *
174  * Creates an embedded object from data transfer object retrieved from
175  * the clipboard or OLE drag and drop.
176  */
177 HRESULT WINAPI OleCreateFromDataEx(IDataObject *data, REFIID iid, DWORD flags,
178                                    DWORD renderopt, ULONG num_cache_fmts, DWORD *adv_flags, FORMATETC *cache_fmts,
179                                    IAdviseSink *sink, DWORD *conns,
180                                    IOleClientSite *client_site, IStorage *stg, void **obj)
181 {
182     HRESULT hr;
183     UINT src_cf;
184 
185     FIXME("(%p, %s, %08x, %08x, %d, %p, %p, %p, %p, %p, %p, %p): stub\n",
186           data, debugstr_guid(iid), flags, renderopt, num_cache_fmts, adv_flags, cache_fmts,
187           sink, conns, client_site, stg, obj);
188 
189     hr = get_storage(data, stg, &src_cf, TRUE);
190     if(FAILED(hr)) return hr;
191 
192     hr = OleLoad(stg, iid, client_site, obj);
193     if(FAILED(hr)) return hr;
194 
195     /* FIXME: Init cache */
196 
197     return hr;
198 }
199 
200 /******************************************************************************
201  *		OleCreateFromData        [OLE32.@]
202  */
203 HRESULT WINAPI OleCreateFromData(LPDATAOBJECT data, REFIID iid,
204                                  DWORD renderopt, LPFORMATETC fmt,
205                                  LPOLECLIENTSITE client_site, LPSTORAGE stg,
206                                  LPVOID* obj)
207 {
208     DWORD advf = ADVF_PRIMEFIRST;
209 
210     return OleCreateFromDataEx(data, iid, 0, renderopt, fmt ? 1 : 0, fmt ? &advf : NULL,
211                                fmt, NULL, NULL, client_site, stg, obj);
212 }
213 
214 /******************************************************************************
215  *              OleCreateLinkFromData        [OLE32.@]
216  */
217 HRESULT WINAPI OleCreateLinkFromData(IDataObject *data, REFIID iid,
218                                      DWORD renderopt, FORMATETC *fmt,
219                                      IOleClientSite *client_site, IStorage *stg,
220                                      void **obj)
221 {
222     FIXME("%p,%s,%08x,%p,%p,%p,%p: semi-stub\n",
223           data, debugstr_guid(iid), renderopt, fmt, client_site, stg, obj);
224     return OleCreateFromData(data, iid, renderopt, fmt, client_site, stg, obj);
225 }
226 
227 /******************************************************************************
228  *              OleCreateStaticFromData        [OLE32.@]
229  */
230 HRESULT WINAPI OleCreateStaticFromData(IDataObject *data, REFIID iid,
231                                        DWORD renderopt, FORMATETC *fmt,
232                                        IOleClientSite *client_site, IStorage *stg,
233                                        void **obj)
234 {
235     FIXME("%p,%s,%08x,%p,%p,%p,%p: semi-stub\n",
236           data, debugstr_guid(iid), renderopt, fmt, client_site, stg, obj);
237     return OleCreateFromData(data, iid, renderopt, fmt, client_site, stg, obj);
238 }
239 
240 /******************************************************************************
241  *              OleCreateFromFileEx        [OLE32.@]
242  */
243 HRESULT WINAPI OleCreateFromFileEx(REFCLSID clsid, const OLECHAR *filename, REFIID iid, DWORD flags,
244                                    DWORD renderopt, ULONG num_fmts, DWORD *adv_flags, FORMATETC *fmts, IAdviseSink *sink,
245                                    DWORD *conns, IOleClientSite *client_site, IStorage *stg, void **obj)
246 {
247     HRESULT hr;
248     IMoniker *mon;
249     IDataObject *data;
250     IUnknown *unk = NULL;
251     IOleCache *cache = NULL;
252     ULONG i;
253 
254     TRACE("cls %s, %s, iid %s, flags %d, render opts %d, num fmts %d, adv flags %p, fmts %p\n", debugstr_guid(clsid),
255           debugstr_w(filename), debugstr_guid(iid), flags, renderopt, num_fmts, adv_flags, fmts);
256     TRACE("sink %p, conns %p, client site %p, storage %p, obj %p\n", sink, conns, client_site, stg, obj);
257     for (i = 0; i < num_fmts; i++)
258         TRACE("\t%d: fmt %s adv flags %d\n", i, debugstr_formatetc(fmts + i), adv_flags[i]);
259 
260     hr = CreateFileMoniker( filename, &mon );
261     if (FAILED(hr)) return hr;
262 
263     hr = BindMoniker( mon, 0, &IID_IDataObject, (void**)&data );
264     IMoniker_Release( mon );
265     if (FAILED(hr)) return hr;
266 
267     hr = get_storage( data, stg, NULL, FALSE );
268     if (FAILED(hr)) goto end;
269 
270     hr = OleLoad( stg, &IID_IUnknown, client_site, (void**)&unk );
271     if (FAILED(hr)) goto end;
272 
273     if (renderopt == OLERENDER_FORMAT)
274     {
275         hr = IUnknown_QueryInterface( unk, &IID_IOleCache, (void**)&cache );
276         if (FAILED(hr)) goto end;
277 
278         for (i = 0; i < num_fmts; i++)
279         {
280             STGMEDIUM med;
281             DWORD dummy_conn;
282 
283             memset( &med, 0, sizeof(med) );
284             hr = IDataObject_GetData( data, fmts + i, &med );
285             if (FAILED(hr)) goto end;
286             hr = IOleCache_Cache( cache, fmts + i, adv_flags[i], &dummy_conn );
287             if (SUCCEEDED(hr))
288                 hr = IOleCache_SetData( cache, fmts + i, &med, TRUE );
289             if (FAILED(hr))
290             {
291                 ReleaseStgMedium( &med );
292                 goto end;
293             }
294         }
295     }
296 
297     hr = IUnknown_QueryInterface( unk, iid, obj );
298 
299 end:
300     if (cache) IOleCache_Release( cache );
301     if (unk) IUnknown_Release( unk );
302     IDataObject_Release( data );
303     return hr;
304 }
305 
306 /******************************************************************************
307  *              OleCreateFromFile        [OLE32.@]
308  */
309 HRESULT WINAPI OleCreateFromFile(REFCLSID clsid, const OLECHAR *filename, REFIID iid, DWORD renderopt,
310                                  FORMATETC *fmt, IOleClientSite *client_site, IStorage *storage, void **obj)
311 {
312     DWORD advf = ADVF_PRIMEFIRST;
313 
314     return OleCreateFromFileEx(clsid, filename, iid, 0, renderopt, fmt ? 1 : 0, fmt ? &advf : NULL, fmt,
315                                NULL, NULL, client_site, storage, obj);
316 }
317 
318 /******************************************************************************
319  *              OleDuplicateData        [OLE32.@]
320  *
321  * Duplicates clipboard data.
322  *
323  * PARAMS
324  *  hSrc     [I] Handle of the source clipboard data.
325  *  cfFormat [I] The clipboard format of hSrc.
326  *  uiFlags  [I] Flags to pass to GlobalAlloc.
327  *
328  * RETURNS
329  *  Success: handle to the duplicated data.
330  *  Failure: NULL.
331  */
332 HANDLE WINAPI OleDuplicateData(HANDLE hSrc, CLIPFORMAT cfFormat,
333 	                          UINT uiFlags)
334 {
335     HANDLE hDst = NULL;
336 
337     TRACE("(%p,%x,%x)\n", hSrc, cfFormat, uiFlags);
338 
339     if (!uiFlags) uiFlags = GMEM_MOVEABLE;
340 
341     switch (cfFormat)
342     {
343     case CF_ENHMETAFILE:
344         hDst = CopyEnhMetaFileW(hSrc, NULL);
345         break;
346     case CF_METAFILEPICT:
347         hDst = CopyMetaFileW(hSrc, NULL);
348         break;
349     case CF_PALETTE:
350         {
351             LOGPALETTE * logpalette;
352             UINT nEntries = GetPaletteEntries(hSrc, 0, 0, NULL);
353             if (!nEntries) return NULL;
354             logpalette = HeapAlloc(GetProcessHeap(), 0,
355                 FIELD_OFFSET(LOGPALETTE, palPalEntry[nEntries]));
356             if (!logpalette) return NULL;
357             if (!GetPaletteEntries(hSrc, 0, nEntries, logpalette->palPalEntry))
358             {
359                 HeapFree(GetProcessHeap(), 0, logpalette);
360                 return NULL;
361             }
362             logpalette->palVersion = 0x300;
363             logpalette->palNumEntries = (WORD)nEntries;
364 
365             hDst = CreatePalette(logpalette);
366 
367             HeapFree(GetProcessHeap(), 0, logpalette);
368             break;
369         }
370     case CF_BITMAP:
371         {
372             LONG size;
373             BITMAP bm;
374             if (!GetObjectW(hSrc, sizeof(bm), &bm))
375                 return NULL;
376             size = GetBitmapBits(hSrc, 0, NULL);
377             if (!size) return NULL;
378             bm.bmBits = HeapAlloc(GetProcessHeap(), 0, size);
379             if (!bm.bmBits) return NULL;
380             if (GetBitmapBits(hSrc, size, bm.bmBits))
381                 hDst = CreateBitmapIndirect(&bm);
382             HeapFree(GetProcessHeap(), 0, bm.bmBits);
383             break;
384         }
385     default:
386         {
387             SIZE_T size = GlobalSize(hSrc);
388             LPVOID pvSrc = NULL;
389             LPVOID pvDst = NULL;
390 
391             /* allocate space for object */
392             if (!size) return NULL;
393             hDst = GlobalAlloc(uiFlags, size);
394             if (!hDst) return NULL;
395 
396             /* lock pointers */
397             pvSrc = GlobalLock(hSrc);
398             if (!pvSrc)
399             {
400                 GlobalFree(hDst);
401                 return NULL;
402             }
403             pvDst = GlobalLock(hDst);
404             if (!pvDst)
405             {
406                 GlobalUnlock(hSrc);
407                 GlobalFree(hDst);
408                 return NULL;
409             }
410             /* copy data */
411             memcpy(pvDst, pvSrc, size);
412 
413             /* cleanup */
414             GlobalUnlock(hDst);
415             GlobalUnlock(hSrc);
416         }
417     }
418 
419     TRACE("returning %p\n", hDst);
420     return hDst;
421 }
422