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