2 * Ole 2 Create functions implementation
4 * Copyright (C) 1999-2000 Abey George
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.
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.
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
25 #define NONAMELESSUNION
31 #include "wine/debug.h"
34 #include "compobj_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 /******************************************************************************
39 * OleQueryCreateFromData [OLE32.@]
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.
48 HRESULT WINAPI
OleQueryCreateFromData(IDataObject
*data
)
50 IEnumFORMATETC
*enum_fmt
;
52 BOOL found_static
= FALSE
;
55 hr
= IDataObject_EnumFormatEtc(data
, DATADIR_GET
, &enum_fmt
);
57 if(FAILED(hr
)) return hr
;
61 hr
= IEnumFORMATETC_Next(enum_fmt
, 1, &fmt
, NULL
);
64 if(fmt
.cfFormat
== embedded_object_clipboard_format
||
65 fmt
.cfFormat
== embed_source_clipboard_format
||
66 fmt
.cfFormat
== filename_clipboard_format
)
68 IEnumFORMATETC_Release(enum_fmt
);
72 if(fmt
.cfFormat
== CF_METAFILEPICT
||
73 fmt
.cfFormat
== CF_BITMAP
||
74 fmt
.cfFormat
== CF_DIB
)
79 IEnumFORMATETC_Release(enum_fmt
);
81 return found_static
? OLE_S_STATIC
: S_FALSE
;
84 static inline void init_fmtetc(FORMATETC
*fmt
, CLIPFORMAT cf
, TYMED tymed
)
88 fmt
->dwAspect
= DVASPECT_CONTENT
;
93 /***************************************************************************
96 * Retrieve an object's storage from a variety of sources.
100 static HRESULT
get_storage(IDataObject
*data
, IStorage
*stg
, UINT
*src_cf
, BOOL other_fmts
)
102 static const UINT fmt_id
[] = { CF_METAFILEPICT
, CF_BITMAP
, CF_DIB
};
107 IPersistStorage
*persist
;
110 if (src_cf
) *src_cf
= 0;
112 /* CF_EMBEDEDOBJECT */
113 init_fmtetc(&fmt
, embedded_object_clipboard_format
, TYMED_ISTORAGE
);
114 med
.tymed
= TYMED_ISTORAGE
;
116 med
.pUnkForRelease
= NULL
;
117 hr
= IDataObject_GetDataHere(data
, &fmt
, &med
);
120 if (src_cf
) *src_cf
= embedded_object_clipboard_format
;
125 init_fmtetc(&fmt
, embed_source_clipboard_format
, TYMED_ISTORAGE
);
126 med
.tymed
= TYMED_ISTORAGE
;
128 med
.pUnkForRelease
= NULL
;
129 hr
= IDataObject_GetDataHere(data
, &fmt
, &med
);
132 if (src_cf
) *src_cf
= embed_source_clipboard_format
;
138 for (i
= 0; i
< ARRAY_SIZE(fmt_id
); i
++)
140 init_fmtetc(&fmt
, fmt_id
[i
], TYMED_ISTORAGE
);
141 hr
= IDataObject_QueryGetData(data
, &fmt
);
144 if (src_cf
) *src_cf
= fmt_id
[i
];
150 /* IPersistStorage */
151 hr
= IDataObject_QueryInterface(data
, &IID_IPersistStorage
, (void**)&persist
);
152 if(FAILED(hr
)) return hr
;
154 hr
= IPersistStorage_GetClassID(persist
, &clsid
);
155 if(FAILED(hr
)) goto end
;
157 hr
= IStorage_SetClass(stg
, &clsid
);
158 if(FAILED(hr
)) goto end
;
160 hr
= IPersistStorage_Save(persist
, stg
, FALSE
);
161 if(FAILED(hr
)) goto end
;
163 hr
= IPersistStorage_SaveCompleted(persist
, NULL
);
166 IPersistStorage_Release(persist
);
171 /******************************************************************************
172 * OleCreateFromDataEx [OLE32.@]
174 * Creates an embedded object from data transfer object retrieved from
175 * the clipboard or OLE drag and drop.
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
)
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
);
189 hr
= get_storage(data
, stg
, &src_cf
, TRUE
);
190 if(FAILED(hr
)) return hr
;
192 hr
= OleLoad(stg
, iid
, client_site
, obj
);
193 if(FAILED(hr
)) return hr
;
195 /* FIXME: Init cache */
200 /******************************************************************************
201 * OleCreateFromData [OLE32.@]
203 HRESULT WINAPI
OleCreateFromData(LPDATAOBJECT data
, REFIID iid
,
204 DWORD renderopt
, LPFORMATETC fmt
,
205 LPOLECLIENTSITE client_site
, LPSTORAGE stg
,
208 DWORD advf
= ADVF_PRIMEFIRST
;
210 return OleCreateFromDataEx(data
, iid
, 0, renderopt
, fmt
? 1 : 0, fmt
? &advf
: NULL
,
211 fmt
, NULL
, NULL
, client_site
, stg
, obj
);
214 /******************************************************************************
215 * OleCreateLinkFromData [OLE32.@]
217 HRESULT WINAPI
OleCreateLinkFromData(IDataObject
*data
, REFIID iid
,
218 DWORD renderopt
, FORMATETC
*fmt
,
219 IOleClientSite
*client_site
, IStorage
*stg
,
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
);
227 /******************************************************************************
228 * OleCreateStaticFromData [OLE32.@]
230 HRESULT WINAPI
OleCreateStaticFromData(IDataObject
*data
, REFIID iid
,
231 DWORD renderopt
, FORMATETC
*fmt
,
232 IOleClientSite
*client_site
, IStorage
*stg
,
237 IOleObject
* ole_object
= NULL
;
238 IOleCache2
*ole_cache
= NULL
;
239 IPersistStorage
*persist
= NULL
;
242 LPOLESTR ole_typename
;
244 TRACE("(%p, %s, 0x%08x, %p, %p, %p, %p)\n",
245 data
, debugstr_guid(iid
), renderopt
, fmt
, client_site
, stg
, obj
);
250 if (renderopt
!= OLERENDER_FORMAT
)
252 FIXME("semi-stub\n");
253 return OleCreateFromData(data
, iid
, renderopt
, fmt
, client_site
, stg
, obj
);
259 hr
= IDataObject_GetData(data
, fmt
, &stgmedium
);
260 if (FAILED(hr
)) return hr
;
262 switch (fmt
->cfFormat
)
266 clsid
= CLSID_Picture_Dib
;
269 clsid
= CLSID_Picture_EnhMetafile
;
271 case CF_METAFILEPICT
:
272 clsid
= CLSID_Picture_Metafile
;
275 ReleaseStgMedium(&stgmedium
);
276 return DV_E_CLIPFORMAT
;
278 hr
= OleCreateDefaultHandler(&clsid
, NULL
, &IID_IOleObject
, (void **)&ole_object
);
279 if (FAILED(hr
)) goto end
;
283 hr
= IOleObject_SetClientSite(ole_object
, client_site
);
284 if (FAILED(hr
)) goto end
;
287 hr
= IOleObject_QueryInterface(ole_object
, &IID_IOleCache2
, (void **)&ole_cache
);
288 if (FAILED(hr
)) goto end
;
290 hr
= IOleObject_QueryInterface(ole_object
, &IID_IPersistStorage
, (void **)&persist
);
291 if (FAILED(hr
)) goto end
;
293 hr
= WriteClassStg(stg
, &clsid
);
294 if (FAILED(hr
)) goto end
;
296 hr
= IPersistStorage_InitNew(persist
, stg
);
297 if (FAILED(hr
)) goto end
;
299 hr
= IOleCache2_Cache(ole_cache
, fmt
, ADVF_PRIMEFIRST
, &connection
);
300 if (FAILED(hr
)) goto end
;
302 hr
= IOleCache2_SetData(ole_cache
, fmt
, &stgmedium
, TRUE
);
303 if (FAILED(hr
)) goto end
;
304 stgmedium
.tymed
= TYMED_NULL
;
306 hr
= IOleObject_GetUserType(ole_object
, USERCLASSTYPE_FULL
, &ole_typename
);
309 hr
= WriteFmtUserTypeStg(stg
, fmt
->cfFormat
, ole_typename
);
310 CoTaskMemFree(ole_typename
);
311 if (FAILED(hr
)) goto end
;
313 hr
= IPersistStorage_Save(persist
, stg
, TRUE
);
314 if (FAILED(hr
)) goto end
;
316 hr
= IPersistStorage_SaveCompleted(persist
, NULL
);
317 if (FAILED(hr
)) goto end
;
319 hr
= IOleObject_QueryInterface(ole_object
, iid
, obj
);
322 if (stgmedium
.tymed
== TYMED_NULL
)
323 ReleaseStgMedium(&stgmedium
);
325 IPersistStorage_Release(persist
);
327 IOleCache2_Release(ole_cache
);
329 IOleObject_Release(ole_object
);
333 /******************************************************************************
334 * OleCreateFromFileEx [OLE32.@]
336 HRESULT WINAPI
OleCreateFromFileEx(REFCLSID clsid
, const OLECHAR
*filename
, REFIID iid
, DWORD flags
,
337 DWORD renderopt
, ULONG num_fmts
, DWORD
*adv_flags
, FORMATETC
*fmts
, IAdviseSink
*sink
,
338 DWORD
*conns
, IOleClientSite
*client_site
, IStorage
*stg
, void **obj
)
343 IUnknown
*unk
= NULL
;
344 IOleCache
*cache
= NULL
;
347 TRACE("cls %s, %s, iid %s, flags %d, render opts %d, num fmts %d, adv flags %p, fmts %p\n", debugstr_guid(clsid
),
348 debugstr_w(filename
), debugstr_guid(iid
), flags
, renderopt
, num_fmts
, adv_flags
, fmts
);
349 TRACE("sink %p, conns %p, client site %p, storage %p, obj %p\n", sink
, conns
, client_site
, stg
, obj
);
350 for (i
= 0; i
< num_fmts
; i
++)
351 TRACE("\t%d: fmt %s adv flags %d\n", i
, debugstr_formatetc(fmts
+ i
), adv_flags
[i
]);
353 hr
= CreateFileMoniker( filename
, &mon
);
354 if (FAILED(hr
)) return hr
;
356 hr
= BindMoniker( mon
, 0, &IID_IDataObject
, (void**)&data
);
357 IMoniker_Release( mon
);
358 if (FAILED(hr
)) return hr
;
360 hr
= get_storage( data
, stg
, NULL
, FALSE
);
361 if (FAILED(hr
)) goto end
;
363 hr
= OleLoad( stg
, &IID_IUnknown
, client_site
, (void**)&unk
);
364 if (FAILED(hr
)) goto end
;
366 if (renderopt
== OLERENDER_FORMAT
)
368 hr
= IUnknown_QueryInterface( unk
, &IID_IOleCache
, (void**)&cache
);
369 if (FAILED(hr
)) goto end
;
371 for (i
= 0; i
< num_fmts
; i
++)
376 memset( &med
, 0, sizeof(med
) );
377 hr
= IDataObject_GetData( data
, fmts
+ i
, &med
);
378 if (FAILED(hr
)) goto end
;
379 hr
= IOleCache_Cache( cache
, fmts
+ i
, adv_flags
[i
], &dummy_conn
);
381 hr
= IOleCache_SetData( cache
, fmts
+ i
, &med
, TRUE
);
384 ReleaseStgMedium( &med
);
390 hr
= IUnknown_QueryInterface( unk
, iid
, obj
);
393 if (cache
) IOleCache_Release( cache
);
394 if (unk
) IUnknown_Release( unk
);
395 IDataObject_Release( data
);
399 /******************************************************************************
400 * OleCreateFromFile [OLE32.@]
402 HRESULT WINAPI
OleCreateFromFile(REFCLSID clsid
, const OLECHAR
*filename
, REFIID iid
, DWORD renderopt
,
403 FORMATETC
*fmt
, IOleClientSite
*client_site
, IStorage
*storage
, void **obj
)
405 DWORD advf
= ADVF_PRIMEFIRST
;
407 return OleCreateFromFileEx(clsid
, filename
, iid
, 0, renderopt
, fmt
? 1 : 0, fmt
? &advf
: NULL
, fmt
,
408 NULL
, NULL
, client_site
, storage
, obj
);
411 /******************************************************************************
412 * OleDuplicateData [OLE32.@]
414 * Duplicates clipboard data.
417 * hSrc [I] Handle of the source clipboard data.
418 * cfFormat [I] The clipboard format of hSrc.
419 * uiFlags [I] Flags to pass to GlobalAlloc.
422 * Success: handle to the duplicated data.
425 HANDLE WINAPI
OleDuplicateData(HANDLE hSrc
, CLIPFORMAT cfFormat
,
430 TRACE("(%p,%x,%x)\n", hSrc
, cfFormat
, uiFlags
);
432 if (!uiFlags
) uiFlags
= GMEM_MOVEABLE
;
437 hDst
= CopyEnhMetaFileW(hSrc
, NULL
);
439 case CF_METAFILEPICT
:
440 hDst
= CopyMetaFileW(hSrc
, NULL
);
444 LOGPALETTE
* logpalette
;
445 UINT nEntries
= GetPaletteEntries(hSrc
, 0, 0, NULL
);
446 if (!nEntries
) return NULL
;
447 logpalette
= HeapAlloc(GetProcessHeap(), 0,
448 FIELD_OFFSET(LOGPALETTE
, palPalEntry
[nEntries
]));
449 if (!logpalette
) return NULL
;
450 if (!GetPaletteEntries(hSrc
, 0, nEntries
, logpalette
->palPalEntry
))
452 HeapFree(GetProcessHeap(), 0, logpalette
);
455 logpalette
->palVersion
= 0x300;
456 logpalette
->palNumEntries
= (WORD
)nEntries
;
458 hDst
= CreatePalette(logpalette
);
460 HeapFree(GetProcessHeap(), 0, logpalette
);
467 if (!GetObjectW(hSrc
, sizeof(bm
), &bm
))
469 size
= GetBitmapBits(hSrc
, 0, NULL
);
470 if (!size
) return NULL
;
471 bm
.bmBits
= HeapAlloc(GetProcessHeap(), 0, size
);
472 if (!bm
.bmBits
) return NULL
;
473 if (GetBitmapBits(hSrc
, size
, bm
.bmBits
))
474 hDst
= CreateBitmapIndirect(&bm
);
475 HeapFree(GetProcessHeap(), 0, bm
.bmBits
);
480 SIZE_T size
= GlobalSize(hSrc
);
484 /* allocate space for object */
485 if (!size
) return NULL
;
486 hDst
= GlobalAlloc(uiFlags
, size
);
487 if (!hDst
) return NULL
;
490 pvSrc
= GlobalLock(hSrc
);
496 pvDst
= GlobalLock(hDst
);
504 memcpy(pvDst
, pvSrc
, size
);
512 TRACE("returning %p\n", hDst
);