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 < ARRAY_SIZE(fmt_id); 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 HRESULT hr; 236 CLSID clsid; 237 IOleObject * ole_object = NULL; 238 IOleCache2 *ole_cache = NULL; 239 IPersistStorage *persist = NULL; 240 DWORD connection; 241 STGMEDIUM stgmedium; 242 LPOLESTR ole_typename; 243 244 TRACE("(%p, %s, 0x%08x, %p, %p, %p, %p)\n", 245 data, debugstr_guid(iid), renderopt, fmt, client_site, stg, obj); 246 247 if (!obj || !stg) 248 return E_INVALIDARG; 249 250 if (renderopt != OLERENDER_FORMAT) 251 { 252 FIXME("semi-stub\n"); 253 return OleCreateFromData(data, iid, renderopt, fmt, client_site, stg, obj); 254 } 255 256 if (!fmt) 257 return E_INVALIDARG; 258 259 hr = IDataObject_GetData(data, fmt, &stgmedium); 260 if (FAILED(hr)) return hr; 261 262 switch (fmt->cfFormat) 263 { 264 case CF_BITMAP: 265 case CF_DIB: 266 clsid = CLSID_Picture_Dib; 267 break; 268 case CF_ENHMETAFILE: 269 clsid = CLSID_Picture_EnhMetafile; 270 break; 271 case CF_METAFILEPICT: 272 clsid = CLSID_Picture_Metafile; 273 break; 274 default: 275 ReleaseStgMedium(&stgmedium); 276 return DV_E_CLIPFORMAT; 277 } 278 hr = OleCreateDefaultHandler(&clsid, NULL, &IID_IOleObject, (void **)&ole_object); 279 if (FAILED(hr)) goto end; 280 281 if (client_site) 282 { 283 hr = IOleObject_SetClientSite(ole_object, client_site); 284 if (FAILED(hr)) goto end; 285 } 286 287 hr = IOleObject_QueryInterface(ole_object, &IID_IOleCache2, (void **)&ole_cache); 288 if (FAILED(hr)) goto end; 289 290 hr = IOleObject_QueryInterface(ole_object, &IID_IPersistStorage, (void **)&persist); 291 if (FAILED(hr)) goto end; 292 293 hr = WriteClassStg(stg, &clsid); 294 if (FAILED(hr)) goto end; 295 296 hr = IPersistStorage_InitNew(persist, stg); 297 if (FAILED(hr)) goto end; 298 299 hr = IOleCache2_Cache(ole_cache, fmt, ADVF_PRIMEFIRST, &connection); 300 if (FAILED(hr)) goto end; 301 302 hr = IOleCache2_SetData(ole_cache, fmt, &stgmedium, TRUE); 303 if (FAILED(hr)) goto end; 304 stgmedium.tymed = TYMED_NULL; 305 306 hr = IOleObject_GetUserType(ole_object, USERCLASSTYPE_FULL, &ole_typename); 307 if(FAILED(hr)) 308 ole_typename = NULL; 309 hr = WriteFmtUserTypeStg(stg, fmt->cfFormat, ole_typename); 310 CoTaskMemFree(ole_typename); 311 if (FAILED(hr)) goto end; 312 313 hr = IPersistStorage_Save(persist, stg, TRUE); 314 if (FAILED(hr)) goto end; 315 316 hr = IPersistStorage_SaveCompleted(persist, NULL); 317 if (FAILED(hr)) goto end; 318 319 hr = IOleObject_QueryInterface(ole_object, iid, obj); 320 321 end: 322 if (stgmedium.tymed == TYMED_NULL) 323 ReleaseStgMedium(&stgmedium); 324 if (persist) 325 IPersistStorage_Release(persist); 326 if (ole_cache) 327 IOleCache2_Release(ole_cache); 328 if (ole_object) 329 IOleObject_Release(ole_object); 330 return hr; 331 } 332 333 /****************************************************************************** 334 * OleCreateFromFileEx [OLE32.@] 335 */ 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) 339 { 340 HRESULT hr; 341 IMoniker *mon; 342 IDataObject *data; 343 IUnknown *unk = NULL; 344 IOleCache *cache = NULL; 345 ULONG i; 346 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]); 352 353 hr = CreateFileMoniker( filename, &mon ); 354 if (FAILED(hr)) return hr; 355 356 hr = BindMoniker( mon, 0, &IID_IDataObject, (void**)&data ); 357 IMoniker_Release( mon ); 358 if (FAILED(hr)) return hr; 359 360 hr = get_storage( data, stg, NULL, FALSE ); 361 if (FAILED(hr)) goto end; 362 363 hr = OleLoad( stg, &IID_IUnknown, client_site, (void**)&unk ); 364 if (FAILED(hr)) goto end; 365 366 if (renderopt == OLERENDER_FORMAT) 367 { 368 hr = IUnknown_QueryInterface( unk, &IID_IOleCache, (void**)&cache ); 369 if (FAILED(hr)) goto end; 370 371 for (i = 0; i < num_fmts; i++) 372 { 373 STGMEDIUM med; 374 DWORD dummy_conn; 375 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 ); 380 if (SUCCEEDED(hr)) 381 hr = IOleCache_SetData( cache, fmts + i, &med, TRUE ); 382 if (FAILED(hr)) 383 { 384 ReleaseStgMedium( &med ); 385 goto end; 386 } 387 } 388 } 389 390 hr = IUnknown_QueryInterface( unk, iid, obj ); 391 392 end: 393 if (cache) IOleCache_Release( cache ); 394 if (unk) IUnknown_Release( unk ); 395 IDataObject_Release( data ); 396 return hr; 397 } 398 399 /****************************************************************************** 400 * OleCreateFromFile [OLE32.@] 401 */ 402 HRESULT WINAPI OleCreateFromFile(REFCLSID clsid, const OLECHAR *filename, REFIID iid, DWORD renderopt, 403 FORMATETC *fmt, IOleClientSite *client_site, IStorage *storage, void **obj) 404 { 405 DWORD advf = ADVF_PRIMEFIRST; 406 407 return OleCreateFromFileEx(clsid, filename, iid, 0, renderopt, fmt ? 1 : 0, fmt ? &advf : NULL, fmt, 408 NULL, NULL, client_site, storage, obj); 409 } 410 411 /****************************************************************************** 412 * OleDuplicateData [OLE32.@] 413 * 414 * Duplicates clipboard data. 415 * 416 * PARAMS 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. 420 * 421 * RETURNS 422 * Success: handle to the duplicated data. 423 * Failure: NULL. 424 */ 425 HANDLE WINAPI OleDuplicateData(HANDLE hSrc, CLIPFORMAT cfFormat, 426 UINT uiFlags) 427 { 428 HANDLE hDst = NULL; 429 430 TRACE("(%p,%x,%x)\n", hSrc, cfFormat, uiFlags); 431 432 if (!uiFlags) uiFlags = GMEM_MOVEABLE; 433 434 switch (cfFormat) 435 { 436 case CF_ENHMETAFILE: 437 hDst = CopyEnhMetaFileW(hSrc, NULL); 438 break; 439 case CF_METAFILEPICT: 440 hDst = CopyMetaFileW(hSrc, NULL); 441 break; 442 case CF_PALETTE: 443 { 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)) 451 { 452 HeapFree(GetProcessHeap(), 0, logpalette); 453 return NULL; 454 } 455 logpalette->palVersion = 0x300; 456 logpalette->palNumEntries = (WORD)nEntries; 457 458 hDst = CreatePalette(logpalette); 459 460 HeapFree(GetProcessHeap(), 0, logpalette); 461 break; 462 } 463 case CF_BITMAP: 464 { 465 LONG size; 466 BITMAP bm; 467 if (!GetObjectW(hSrc, sizeof(bm), &bm)) 468 return NULL; 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); 476 break; 477 } 478 default: 479 { 480 SIZE_T size = GlobalSize(hSrc); 481 LPVOID pvSrc = NULL; 482 LPVOID pvDst = NULL; 483 484 /* allocate space for object */ 485 if (!size) return NULL; 486 hDst = GlobalAlloc(uiFlags, size); 487 if (!hDst) return NULL; 488 489 /* lock pointers */ 490 pvSrc = GlobalLock(hSrc); 491 if (!pvSrc) 492 { 493 GlobalFree(hDst); 494 return NULL; 495 } 496 pvDst = GlobalLock(hDst); 497 if (!pvDst) 498 { 499 GlobalUnlock(hSrc); 500 GlobalFree(hDst); 501 return NULL; 502 } 503 /* copy data */ 504 memcpy(pvDst, pvSrc, size); 505 506 /* cleanup */ 507 GlobalUnlock(hDst); 508 GlobalUnlock(hSrc); 509 } 510 } 511 512 TRACE("returning %p\n", hDst); 513 return hDst; 514 } 515