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