1 /* 2 * OLE Picture object 3 * 4 * Implementation of OLE IPicture and related interfaces 5 * 6 * Copyright 2000 Huw D M Davies for CodeWeavers. 7 * Copyright 2001 Marcus Meissner 8 * Copyright 2008 Kirill K. Smirnov 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 * 24 * BUGS 25 * 26 * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well.. 27 * Lots of methods are just stubs. 28 * 29 * 30 * NOTES (or things that msdn doesn't tell you) 31 * 32 * The width and height properties are returned in HIMETRIC units (0.01mm) 33 * IPicture::Render also uses these to select a region of the src picture. 34 * A bitmap's size is converted into these units by using the screen resolution 35 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540). 36 * 37 */ 38 39 #include "config.h" 40 #include "wine/port.h" 41 42 #ifdef HAVE_UNISTD_H 43 # include <unistd.h> 44 #endif 45 #include <stdarg.h> 46 #include <stdio.h> 47 #include <string.h> 48 49 #define COBJMACROS 50 #define NONAMELESSUNION 51 52 #include "winerror.h" 53 #include "windef.h" 54 #include "winbase.h" 55 #include "wingdi.h" 56 #include "winuser.h" 57 #include "ole2.h" 58 #include "olectl.h" 59 #include "oleauto.h" 60 #include "connpt.h" 61 #include "urlmon.h" 62 #include "initguid.h" 63 #include "wincodec.h" 64 #include "wine/debug.h" 65 #include "wine/unicode.h" 66 #include "wine/library.h" 67 68 WINE_DEFAULT_DEBUG_CHANNEL(olepicture); 69 70 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */ 71 #define BITMAP_FORMAT_JPEG 0xd8ff 72 #define BITMAP_FORMAT_GIF 0x4947 73 #define BITMAP_FORMAT_PNG 0x5089 74 #define BITMAP_FORMAT_APM 0xcdd7 75 76 #include "pshpack1.h" 77 78 /* Header for Aldus Placable Metafiles - a standard metafile follows */ 79 typedef struct _APM_HEADER 80 { 81 DWORD key; 82 WORD handle; 83 SHORT left; 84 SHORT top; 85 SHORT right; 86 SHORT bottom; 87 WORD inch; 88 DWORD reserved; 89 WORD checksum; 90 } APM_HEADER; 91 92 typedef struct { 93 BYTE bWidth; 94 BYTE bHeight; 95 BYTE bColorCount; 96 BYTE bReserved; 97 WORD xHotspot; 98 WORD yHotspot; 99 DWORD dwDIBSize; 100 DWORD dwDIBOffset; 101 } CURSORICONFILEDIRENTRY; 102 103 typedef struct 104 { 105 WORD idReserved; 106 WORD idType; 107 WORD idCount; 108 CURSORICONFILEDIRENTRY idEntries[1]; 109 } CURSORICONFILEDIR; 110 111 #include "poppack.h" 112 113 /************************************************************************* 114 * Declaration of implementation class 115 */ 116 117 typedef struct OLEPictureImpl { 118 119 /* 120 * IPicture handles IUnknown 121 */ 122 123 IPicture IPicture_iface; 124 IDispatch IDispatch_iface; 125 IPersistStream IPersistStream_iface; 126 IConnectionPointContainer IConnectionPointContainer_iface; 127 128 /* Object reference count */ 129 LONG ref; 130 131 /* We own the object and must destroy it ourselves */ 132 BOOL fOwn; 133 134 /* Picture description */ 135 PICTDESC desc; 136 137 /* These are the pixel size of a bitmap */ 138 DWORD origWidth; 139 DWORD origHeight; 140 141 /* And these are the size of the picture converted into HIMETRIC units */ 142 OLE_XSIZE_HIMETRIC himetricWidth; 143 OLE_YSIZE_HIMETRIC himetricHeight; 144 145 IConnectionPoint *pCP; 146 147 BOOL keepOrigFormat; 148 HDC hDCCur; 149 HBITMAP stock_bitmap; 150 151 /* Bitmap transparency mask */ 152 HBITMAP hbmMask; 153 HBITMAP hbmXor; 154 COLORREF rgbTrans; 155 156 /* data */ 157 void* data; 158 int datalen; 159 BOOL bIsDirty; /* Set to TRUE if picture has changed */ 160 unsigned int loadtime_magic; /* If a length header was found, saves value */ 161 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */ 162 } OLEPictureImpl; 163 164 static inline OLEPictureImpl *impl_from_IPicture(IPicture *iface) 165 { 166 return CONTAINING_RECORD(iface, OLEPictureImpl, IPicture_iface); 167 } 168 169 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface ) 170 { 171 return CONTAINING_RECORD(iface, OLEPictureImpl, IDispatch_iface); 172 } 173 174 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface ) 175 { 176 return CONTAINING_RECORD(iface, OLEPictureImpl, IPersistStream_iface); 177 } 178 179 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface ) 180 { 181 return CONTAINING_RECORD(iface, OLEPictureImpl, IConnectionPointContainer_iface); 182 } 183 184 /* 185 * Predeclare VTables. They get initialized at the end. 186 */ 187 static const IPictureVtbl OLEPictureImpl_VTable; 188 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable; 189 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable; 190 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable; 191 192 /* pixels to HIMETRIC units conversion */ 193 static inline OLE_XSIZE_HIMETRIC xpixels_to_himetric(INT pixels, HDC hdc) 194 { 195 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSX)); 196 } 197 198 static inline OLE_YSIZE_HIMETRIC ypixels_to_himetric(INT pixels, HDC hdc) 199 { 200 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSY)); 201 } 202 203 /*********************************************************************** 204 * Implementation of the OLEPictureImpl class. 205 */ 206 207 static void OLEPictureImpl_SetBitmap(OLEPictureImpl *This) 208 { 209 BITMAP bm; 210 HDC hdcRef; 211 212 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap); 213 if(GetObjectW(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) { 214 ERR("GetObject fails\n"); 215 return; 216 } 217 This->origWidth = bm.bmWidth; 218 This->origHeight = bm.bmHeight; 219 220 TRACE("width %d, height %d, bpp %d\n", bm.bmWidth, bm.bmHeight, bm.bmBitsPixel); 221 222 /* The width and height are stored in HIMETRIC units (0.01 mm), 223 so we take our pixel width divide by pixels per inch and 224 multiply by 25.4 * 100 */ 225 /* Should we use GetBitmapDimension if available? */ 226 hdcRef = CreateCompatibleDC(0); 227 228 This->himetricWidth = xpixels_to_himetric(bm.bmWidth, hdcRef); 229 This->himetricHeight = ypixels_to_himetric(bm.bmHeight, hdcRef); 230 This->stock_bitmap = GetCurrentObject( hdcRef, OBJ_BITMAP ); 231 232 This->loadtime_format = BITMAP_FORMAT_BMP; 233 234 DeleteDC(hdcRef); 235 } 236 237 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This) 238 { 239 ICONINFO infoIcon; 240 241 TRACE("icon handle %p\n", This->desc.u.icon.hicon); 242 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) { 243 HDC hdcRef; 244 BITMAP bm; 245 246 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor); 247 if(GetObjectW(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) { 248 ERR("GetObject fails on icon bitmap\n"); 249 return; 250 } 251 252 This->origWidth = bm.bmWidth; 253 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2; 254 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */ 255 hdcRef = GetDC(0); 256 257 This->himetricWidth = xpixels_to_himetric(This->origWidth, hdcRef); 258 This->himetricHeight = ypixels_to_himetric(This->origHeight, hdcRef); 259 260 ReleaseDC(0, hdcRef); 261 262 DeleteObject(infoIcon.hbmMask); 263 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor); 264 } else { 265 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon); 266 } 267 } 268 269 static void OLEPictureImpl_SetEMF(OLEPictureImpl *This) 270 { 271 ENHMETAHEADER emh; 272 273 GetEnhMetaFileHeader(This->desc.u.emf.hemf, sizeof(emh), &emh); 274 275 This->origWidth = 0; 276 This->origHeight = 0; 277 This->himetricWidth = emh.rclFrame.right - emh.rclFrame.left; 278 This->himetricHeight = emh.rclFrame.bottom - emh.rclFrame.top; 279 } 280 281 /************************************************************************ 282 * OLEPictureImpl_Construct 283 * 284 * This method will construct a new instance of the OLEPictureImpl 285 * class. 286 * 287 * The caller of this method must release the object when it's 288 * done with it. 289 */ 290 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn) 291 { 292 OLEPictureImpl* newObject = 0; 293 294 if (pictDesc) 295 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType); 296 297 /* 298 * Allocate space for the object. 299 */ 300 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl)); 301 302 if (newObject==0) 303 return newObject; 304 305 /* 306 * Initialize the virtual function table. 307 */ 308 newObject->IPicture_iface.lpVtbl = &OLEPictureImpl_VTable; 309 newObject->IDispatch_iface.lpVtbl = &OLEPictureImpl_IDispatch_VTable; 310 newObject->IPersistStream_iface.lpVtbl = &OLEPictureImpl_IPersistStream_VTable; 311 newObject->IConnectionPointContainer_iface.lpVtbl = &OLEPictureImpl_IConnectionPointContainer_VTable; 312 313 newObject->pCP = NULL; 314 CreateConnectionPoint((IUnknown*)&newObject->IPicture_iface, &IID_IPropertyNotifySink, 315 &newObject->pCP); 316 if (!newObject->pCP) 317 { 318 HeapFree(GetProcessHeap(), 0, newObject); 319 return NULL; 320 } 321 322 /* 323 * Start with one reference count. The caller of this function 324 * must release the interface pointer when it is done. 325 */ 326 newObject->ref = 1; 327 newObject->hDCCur = 0; 328 329 newObject->fOwn = fOwn; 330 331 /* dunno about original value */ 332 newObject->keepOrigFormat = TRUE; 333 334 newObject->hbmMask = NULL; 335 newObject->hbmXor = NULL; 336 newObject->loadtime_magic = 0xdeadbeef; 337 newObject->loadtime_format = 0; 338 newObject->bIsDirty = FALSE; 339 340 if (pictDesc) { 341 newObject->desc = *pictDesc; 342 343 switch(pictDesc->picType) { 344 case PICTYPE_BITMAP: 345 OLEPictureImpl_SetBitmap(newObject); 346 break; 347 348 case PICTYPE_METAFILE: 349 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta); 350 newObject->himetricWidth = pictDesc->u.wmf.xExt; 351 newObject->himetricHeight = pictDesc->u.wmf.yExt; 352 break; 353 354 case PICTYPE_NONE: 355 /* not sure what to do here */ 356 newObject->himetricWidth = newObject->himetricHeight = 0; 357 break; 358 359 case PICTYPE_ICON: 360 OLEPictureImpl_SetIcon(newObject); 361 break; 362 363 case PICTYPE_ENHMETAFILE: 364 OLEPictureImpl_SetEMF(newObject); 365 break; 366 367 default: 368 FIXME("Unsupported type %d\n", pictDesc->picType); 369 newObject->himetricWidth = newObject->himetricHeight = 0; 370 break; 371 } 372 } else { 373 newObject->desc.picType = PICTYPE_UNINITIALIZED; 374 } 375 376 TRACE("returning %p\n", newObject); 377 return newObject; 378 } 379 380 /************************************************************************ 381 * OLEPictureImpl_Destroy 382 * 383 * This method is called by the Release method when the reference 384 * count goes down to 0. It will free all resources used by 385 * this object. */ 386 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj) 387 { 388 TRACE("(%p)\n", Obj); 389 390 if (Obj->pCP) 391 IConnectionPoint_Release(Obj->pCP); 392 393 if(Obj->fOwn) { /* We need to destroy the picture */ 394 switch(Obj->desc.picType) { 395 case PICTYPE_BITMAP: 396 DeleteObject(Obj->desc.u.bmp.hbitmap); 397 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask); 398 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor); 399 break; 400 case PICTYPE_METAFILE: 401 DeleteMetaFile(Obj->desc.u.wmf.hmeta); 402 break; 403 case PICTYPE_ICON: 404 DestroyIcon(Obj->desc.u.icon.hicon); 405 break; 406 case PICTYPE_ENHMETAFILE: 407 DeleteEnhMetaFile(Obj->desc.u.emf.hemf); 408 break; 409 case PICTYPE_NONE: 410 case PICTYPE_UNINITIALIZED: 411 /* Nothing to do */ 412 break; 413 default: 414 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType); 415 break; 416 } 417 } 418 HeapFree(GetProcessHeap(), 0, Obj->data); 419 HeapFree(GetProcessHeap(), 0, Obj); 420 } 421 422 423 /************************************************************************ 424 * OLEPictureImpl_AddRef (IUnknown) 425 * 426 * See Windows documentation for more details on IUnknown methods. 427 */ 428 static ULONG WINAPI OLEPictureImpl_AddRef( 429 IPicture* iface) 430 { 431 OLEPictureImpl *This = impl_from_IPicture(iface); 432 ULONG refCount = InterlockedIncrement(&This->ref); 433 434 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1); 435 436 return refCount; 437 } 438 439 /************************************************************************ 440 * OLEPictureImpl_Release (IUnknown) 441 * 442 * See Windows documentation for more details on IUnknown methods. 443 */ 444 static ULONG WINAPI OLEPictureImpl_Release( 445 IPicture* iface) 446 { 447 OLEPictureImpl *This = impl_from_IPicture(iface); 448 ULONG refCount = InterlockedDecrement(&This->ref); 449 450 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1); 451 452 /* 453 * If the reference count goes down to 0, perform suicide. 454 */ 455 if (!refCount) OLEPictureImpl_Destroy(This); 456 457 return refCount; 458 } 459 460 /************************************************************************ 461 * OLEPictureImpl_QueryInterface (IUnknown) 462 * 463 * See Windows documentation for more details on IUnknown methods. 464 */ 465 static HRESULT WINAPI OLEPictureImpl_QueryInterface( 466 IPicture* iface, 467 REFIID riid, 468 void** ppvObject) 469 { 470 OLEPictureImpl *This = impl_from_IPicture(iface); 471 472 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject); 473 474 if (!ppvObject) 475 return E_INVALIDARG; 476 477 *ppvObject = 0; 478 479 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid)) 480 *ppvObject = &This->IPicture_iface; 481 else if (IsEqualIID(&IID_IDispatch, riid)) 482 *ppvObject = &This->IDispatch_iface; 483 else if (IsEqualIID(&IID_IPictureDisp, riid)) 484 *ppvObject = &This->IDispatch_iface; 485 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid)) 486 *ppvObject = &This->IPersistStream_iface; 487 else if (IsEqualIID(&IID_IConnectionPointContainer, riid)) 488 *ppvObject = &This->IConnectionPointContainer_iface; 489 490 if (!*ppvObject) 491 { 492 FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid)); 493 return E_NOINTERFACE; 494 } 495 496 IPicture_AddRef(iface); 497 498 return S_OK; 499 } 500 501 /*********************************************************************** 502 * OLEPicture_SendNotify (internal) 503 * 504 * Sends notification messages of changed properties to any interested 505 * connections. 506 */ 507 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID) 508 { 509 IEnumConnections *pEnum; 510 CONNECTDATA CD; 511 512 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum) != S_OK) 513 return; 514 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) { 515 IPropertyNotifySink *sink; 516 517 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink); 518 IPropertyNotifySink_OnChanged(sink, dispID); 519 IPropertyNotifySink_Release(sink); 520 IUnknown_Release(CD.pUnk); 521 } 522 IEnumConnections_Release(pEnum); 523 } 524 525 /************************************************************************ 526 * OLEPictureImpl_get_Handle 527 */ 528 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface, 529 OLE_HANDLE *phandle) 530 { 531 OLEPictureImpl *This = impl_from_IPicture(iface); 532 TRACE("(%p)->(%p)\n", This, phandle); 533 534 if(!phandle) 535 return E_POINTER; 536 537 switch(This->desc.picType) { 538 case PICTYPE_NONE: 539 case PICTYPE_UNINITIALIZED: 540 *phandle = 0; 541 break; 542 case PICTYPE_BITMAP: 543 *phandle = HandleToUlong(This->desc.u.bmp.hbitmap); 544 break; 545 case PICTYPE_METAFILE: 546 *phandle = HandleToUlong(This->desc.u.wmf.hmeta); 547 break; 548 case PICTYPE_ICON: 549 *phandle = HandleToUlong(This->desc.u.icon.hicon); 550 break; 551 case PICTYPE_ENHMETAFILE: 552 *phandle = HandleToUlong(This->desc.u.emf.hemf); 553 break; 554 default: 555 FIXME("Unimplemented type %d\n", This->desc.picType); 556 return E_NOTIMPL; 557 } 558 TRACE("returning handle %08x\n", *phandle); 559 return S_OK; 560 } 561 562 /************************************************************************ 563 * OLEPictureImpl_get_hPal 564 */ 565 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface, 566 OLE_HANDLE *phandle) 567 { 568 OLEPictureImpl *This = impl_from_IPicture(iface); 569 HRESULT hres; 570 TRACE("(%p)->(%p)\n", This, phandle); 571 572 if (!phandle) 573 return E_POINTER; 574 575 switch (This->desc.picType) { 576 case (UINT)PICTYPE_UNINITIALIZED: 577 case PICTYPE_NONE: 578 *phandle = 0; 579 hres = S_FALSE; 580 break; 581 case PICTYPE_BITMAP: 582 *phandle = HandleToUlong(This->desc.u.bmp.hpal); 583 hres = S_OK; 584 break; 585 case PICTYPE_METAFILE: 586 hres = E_FAIL; 587 break; 588 case PICTYPE_ICON: 589 case PICTYPE_ENHMETAFILE: 590 default: 591 FIXME("unimplemented for type %d. Returning 0 palette.\n", 592 This->desc.picType); 593 *phandle = 0; 594 hres = S_OK; 595 } 596 597 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle); 598 return hres; 599 } 600 601 /************************************************************************ 602 * OLEPictureImpl_get_Type 603 */ 604 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface, 605 short *ptype) 606 { 607 OLEPictureImpl *This = impl_from_IPicture(iface); 608 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType); 609 610 if(!ptype) 611 return E_POINTER; 612 613 *ptype = This->desc.picType; 614 return S_OK; 615 } 616 617 /************************************************************************ 618 * OLEPictureImpl_get_Width 619 */ 620 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface, 621 OLE_XSIZE_HIMETRIC *pwidth) 622 { 623 OLEPictureImpl *This = impl_from_IPicture(iface); 624 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth); 625 *pwidth = This->himetricWidth; 626 return S_OK; 627 } 628 629 /************************************************************************ 630 * OLEPictureImpl_get_Height 631 */ 632 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface, 633 OLE_YSIZE_HIMETRIC *pheight) 634 { 635 OLEPictureImpl *This = impl_from_IPicture(iface); 636 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight); 637 *pheight = This->himetricHeight; 638 return S_OK; 639 } 640 641 /************************************************************************ 642 * OLEPictureImpl_Render 643 */ 644 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc, 645 LONG x, LONG y, LONG cx, LONG cy, 646 OLE_XPOS_HIMETRIC xSrc, 647 OLE_YPOS_HIMETRIC ySrc, 648 OLE_XSIZE_HIMETRIC cxSrc, 649 OLE_YSIZE_HIMETRIC cySrc, 650 LPCRECT prcWBounds) 651 { 652 OLEPictureImpl *This = impl_from_IPicture(iface); 653 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n", 654 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds); 655 if(prcWBounds) 656 TRACE("prcWBounds %s\n", wine_dbgstr_rect(prcWBounds)); 657 658 if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){ 659 return CTL_E_INVALIDPROPERTYVALUE; 660 } 661 662 /* 663 * While the documentation suggests this to be here (or after rendering?) 664 * it does cause an endless recursion in my sample app. -MM 20010804 665 OLEPicture_SendNotify(This,DISPID_PICT_RENDER); 666 */ 667 668 switch(This->desc.picType) { 669 case PICTYPE_UNINITIALIZED: 670 case PICTYPE_NONE: 671 /* nothing to do */ 672 return S_OK; 673 case PICTYPE_BITMAP: 674 { 675 HBITMAP hbmpOld; 676 HDC hdcBmp; 677 678 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units. 679 NB y-axis gets flipped */ 680 681 hdcBmp = CreateCompatibleDC(0); 682 SetMapMode(hdcBmp, MM_ANISOTROPIC); 683 SetWindowOrgEx(hdcBmp, 0, 0, NULL); 684 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL); 685 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL); 686 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL); 687 688 if (This->hbmMask) { 689 HDC hdcMask = CreateCompatibleDC(0); 690 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask); 691 692 hbmpOld = SelectObject(hdcBmp, This->hbmXor); 693 694 SetMapMode(hdcMask, MM_ANISOTROPIC); 695 SetWindowOrgEx(hdcMask, 0, 0, NULL); 696 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL); 697 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL); 698 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL); 699 700 SetBkColor(hdc, RGB(255, 255, 255)); 701 SetTextColor(hdc, RGB(0, 0, 0)); 702 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND); 703 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT); 704 705 SelectObject(hdcMask, hOldbm); 706 DeleteDC(hdcMask); 707 } else { 708 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap); 709 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY); 710 } 711 712 SelectObject(hdcBmp, hbmpOld); 713 DeleteDC(hdcBmp); 714 } 715 break; 716 case PICTYPE_ICON: 717 FIXME("Not quite correct implementation of rendering icons...\n"); 718 DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL); 719 break; 720 721 case PICTYPE_METAFILE: 722 { 723 POINT prevOrg, prevWndOrg; 724 SIZE prevExt, prevWndExt; 725 int oldmode; 726 727 /* Render the WMF to the appropriate location by setting the 728 appropriate ratio between "device units" and "logical units" */ 729 oldmode = SetMapMode(hdc, MM_ANISOTROPIC); 730 /* For the "source rectangle" the y-axis must be inverted */ 731 SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg); 732 SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt); 733 /* For the "destination rectangle" no inversion is necessary */ 734 SetViewportOrgEx(hdc, x, y, &prevOrg); 735 SetViewportExtEx(hdc, cx, cy, &prevExt); 736 737 if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta)) 738 ERR("PlayMetaFile failed!\n"); 739 740 /* We're done, restore the DC to the previous settings for converting 741 logical units to device units */ 742 SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL); 743 SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL); 744 SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL); 745 SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL); 746 SetMapMode(hdc, oldmode); 747 break; 748 } 749 750 case PICTYPE_ENHMETAFILE: 751 { 752 RECT rc = { x, y, x + cx, y + cy }; 753 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc); 754 break; 755 } 756 757 default: 758 FIXME("type %d not implemented\n", This->desc.picType); 759 return E_NOTIMPL; 760 } 761 return S_OK; 762 } 763 764 /************************************************************************ 765 * OLEPictureImpl_set_hPal 766 */ 767 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface, 768 OLE_HANDLE hpal) 769 { 770 OLEPictureImpl *This = impl_from_IPicture(iface); 771 FIXME("(%p)->(%08x): stub\n", This, hpal); 772 OLEPicture_SendNotify(This,DISPID_PICT_HPAL); 773 return E_NOTIMPL; 774 } 775 776 /************************************************************************ 777 * OLEPictureImpl_get_CurDC 778 */ 779 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface, 780 HDC *phdc) 781 { 782 OLEPictureImpl *This = impl_from_IPicture(iface); 783 TRACE("(%p), returning %p\n", This, This->hDCCur); 784 if (phdc) *phdc = This->hDCCur; 785 return S_OK; 786 } 787 788 /************************************************************************ 789 * OLEPictureImpl_SelectPicture 790 */ 791 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface, 792 HDC hdcIn, 793 HDC *phdcOut, 794 OLE_HANDLE *phbmpOut) 795 { 796 OLEPictureImpl *This = impl_from_IPicture(iface); 797 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut); 798 if (This->desc.picType == PICTYPE_BITMAP) { 799 if (phdcOut) 800 *phdcOut = This->hDCCur; 801 if (This->hDCCur) SelectObject(This->hDCCur,This->stock_bitmap); 802 if (hdcIn) SelectObject(hdcIn,This->desc.u.bmp.hbitmap); 803 This->hDCCur = hdcIn; 804 if (phbmpOut) 805 *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap); 806 return S_OK; 807 } else { 808 FIXME("Don't know how to select picture type %d\n",This->desc.picType); 809 return E_FAIL; 810 } 811 } 812 813 /************************************************************************ 814 * OLEPictureImpl_get_KeepOriginalFormat 815 */ 816 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface, 817 BOOL *pfKeep) 818 { 819 OLEPictureImpl *This = impl_from_IPicture(iface); 820 TRACE("(%p)->(%p)\n", This, pfKeep); 821 if (!pfKeep) 822 return E_POINTER; 823 *pfKeep = This->keepOrigFormat; 824 return S_OK; 825 } 826 827 /************************************************************************ 828 * OLEPictureImpl_put_KeepOriginalFormat 829 */ 830 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface, 831 BOOL keep) 832 { 833 OLEPictureImpl *This = impl_from_IPicture(iface); 834 TRACE("(%p)->(%d)\n", This, keep); 835 This->keepOrigFormat = keep; 836 /* FIXME: what DISPID notification here? */ 837 return S_OK; 838 } 839 840 /************************************************************************ 841 * OLEPictureImpl_PictureChanged 842 */ 843 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface) 844 { 845 OLEPictureImpl *This = impl_from_IPicture(iface); 846 TRACE("(%p)->()\n", This); 847 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE); 848 This->bIsDirty = TRUE; 849 return S_OK; 850 } 851 852 /************************************************************************ 853 * OLEPictureImpl_get_Attributes 854 */ 855 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface, 856 DWORD *pdwAttr) 857 { 858 OLEPictureImpl *This = impl_from_IPicture(iface); 859 TRACE("(%p)->(%p).\n", This, pdwAttr); 860 861 if(!pdwAttr) 862 return E_POINTER; 863 864 *pdwAttr = 0; 865 switch (This->desc.picType) { 866 case PICTYPE_UNINITIALIZED: 867 case PICTYPE_NONE: break; 868 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */ 869 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break; 870 case PICTYPE_ENHMETAFILE: /* fall through */ 871 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break; 872 default:FIXME("Unknown pictype %d\n",This->desc.picType);break; 873 } 874 return S_OK; 875 } 876 877 878 /************************************************************************ 879 * IConnectionPointContainer 880 */ 881 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface( 882 IConnectionPointContainer* iface, 883 REFIID riid, 884 VOID** ppvoid) 885 { 886 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 887 888 return IPicture_QueryInterface(&This->IPicture_iface,riid,ppvoid); 889 } 890 891 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef( 892 IConnectionPointContainer* iface) 893 { 894 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 895 896 return IPicture_AddRef(&This->IPicture_iface); 897 } 898 899 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release( 900 IConnectionPointContainer* iface) 901 { 902 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 903 904 return IPicture_Release(&This->IPicture_iface); 905 } 906 907 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints( 908 IConnectionPointContainer* iface, 909 IEnumConnectionPoints** ppEnum) 910 { 911 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 912 913 FIXME("(%p,%p), stub!\n",This,ppEnum); 914 return E_NOTIMPL; 915 } 916 917 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint( 918 IConnectionPointContainer* iface, 919 REFIID riid, 920 IConnectionPoint **ppCP) 921 { 922 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface); 923 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP); 924 if (!ppCP) 925 return E_POINTER; 926 *ppCP = NULL; 927 if (IsEqualGUID(riid,&IID_IPropertyNotifySink)) 928 return IConnectionPoint_QueryInterface(This->pCP, &IID_IConnectionPoint, (void**)ppCP); 929 FIXME("no connection point for %s\n",debugstr_guid(riid)); 930 return CONNECT_E_NOCONNECTION; 931 } 932 933 934 /************************************************************************ 935 * IPersistStream 936 */ 937 938 /************************************************************************ 939 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown) 940 * 941 * See Windows documentation for more details on IUnknown methods. 942 */ 943 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface( 944 IPersistStream* iface, 945 REFIID riid, 946 VOID** ppvoid) 947 { 948 OLEPictureImpl *This = impl_from_IPersistStream(iface); 949 950 return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid); 951 } 952 953 /************************************************************************ 954 * OLEPictureImpl_IPersistStream_AddRef (IUnknown) 955 * 956 * See Windows documentation for more details on IUnknown methods. 957 */ 958 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef( 959 IPersistStream* iface) 960 { 961 OLEPictureImpl *This = impl_from_IPersistStream(iface); 962 963 return IPicture_AddRef(&This->IPicture_iface); 964 } 965 966 /************************************************************************ 967 * OLEPictureImpl_IPersistStream_Release (IUnknown) 968 * 969 * See Windows documentation for more details on IUnknown methods. 970 */ 971 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release( 972 IPersistStream* iface) 973 { 974 OLEPictureImpl *This = impl_from_IPersistStream(iface); 975 976 return IPicture_Release(&This->IPicture_iface); 977 } 978 979 /************************************************************************ 980 * OLEPictureImpl_IPersistStream_GetClassID 981 */ 982 static HRESULT WINAPI OLEPictureImpl_GetClassID( 983 IPersistStream* iface,CLSID* pClassID) 984 { 985 TRACE("(%p)\n", pClassID); 986 *pClassID = CLSID_StdPicture; 987 return S_OK; 988 } 989 990 /************************************************************************ 991 * OLEPictureImpl_IPersistStream_IsDirty 992 */ 993 static HRESULT WINAPI OLEPictureImpl_IsDirty( 994 IPersistStream* iface) 995 { 996 OLEPictureImpl *This = impl_from_IPersistStream(iface); 997 FIXME("(%p),stub!\n",This); 998 return E_NOTIMPL; 999 } 1000 1001 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src) 1002 { 1003 HRESULT hr; 1004 BITMAPINFOHEADER bih; 1005 UINT width, height; 1006 UINT stride, buffersize; 1007 BYTE *bits, *mask = NULL; 1008 WICRect rc; 1009 IWICBitmapSource *real_source; 1010 UINT x, y; 1011 COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0); 1012 BOOL has_alpha=FALSE; 1013 1014 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source); 1015 if (FAILED(hr)) return hr; 1016 1017 hr = IWICBitmapSource_GetSize(real_source, &width, &height); 1018 if (FAILED(hr)) goto end; 1019 1020 bih.biSize = sizeof(bih); 1021 bih.biWidth = width; 1022 bih.biHeight = -height; 1023 bih.biPlanes = 1; 1024 bih.biBitCount = 32; 1025 bih.biCompression = BI_RGB; 1026 bih.biSizeImage = 0; 1027 bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */ 1028 bih.biYPelsPerMeter = 4085; 1029 bih.biClrUsed = 0; 1030 bih.biClrImportant = 0; 1031 1032 stride = 4 * width; 1033 buffersize = stride * height; 1034 1035 mask = HeapAlloc(GetProcessHeap(), 0, buffersize); 1036 if (!mask) 1037 { 1038 hr = E_OUTOFMEMORY; 1039 goto end; 1040 } 1041 1042 This->desc.u.bmp.hbitmap = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void **)&bits, NULL, 0); 1043 if (This->desc.u.bmp.hbitmap == 0) 1044 { 1045 hr = E_FAIL; 1046 goto end; 1047 } 1048 1049 rc.X = 0; 1050 rc.Y = 0; 1051 rc.Width = width; 1052 rc.Height = height; 1053 hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits); 1054 if (FAILED(hr)) 1055 { 1056 DeleteObject(This->desc.u.bmp.hbitmap); 1057 goto end; 1058 } 1059 1060 This->desc.picType = PICTYPE_BITMAP; 1061 OLEPictureImpl_SetBitmap(This); 1062 1063 /* set transparent pixels to black, all others to white */ 1064 for(y = 0; y < height; y++){ 1065 for(x = 0; x < width; x++){ 1066 DWORD *pixel = (DWORD*)(bits + stride*y + 4*x); 1067 if((*pixel & 0x80000000) == 0) 1068 { 1069 has_alpha = TRUE; 1070 *(DWORD *)(mask + stride * y + 4 * x) = black; 1071 } 1072 else 1073 *(DWORD *)(mask + stride * y + 4 * x) = white; 1074 } 1075 } 1076 1077 if (has_alpha) 1078 { 1079 HDC hdcref, hdcBmp, hdcXor, hdcMask; 1080 HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask; 1081 1082 hdcref = GetDC(0); 1083 1084 This->hbmXor = CreateDIBitmap( 1085 hdcref, 1086 &bih, 1087 CBM_INIT, 1088 mask, 1089 (BITMAPINFO*)&bih, 1090 DIB_RGB_COLORS 1091 ); 1092 1093 This->hbmMask = CreateBitmap(width,-height,1,1,NULL); 1094 hdcBmp = CreateCompatibleDC(NULL); 1095 hdcXor = CreateCompatibleDC(NULL); 1096 hdcMask = CreateCompatibleDC(NULL); 1097 1098 hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap); 1099 hbmoldXor = SelectObject(hdcXor,This->hbmXor); 1100 hbmoldMask = SelectObject(hdcMask,This->hbmMask); 1101 1102 SetBkColor(hdcXor,black); 1103 BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY); 1104 BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND); 1105 1106 SelectObject(hdcBmp,hbmoldBmp); 1107 SelectObject(hdcXor,hbmoldXor); 1108 SelectObject(hdcMask,hbmoldMask); 1109 1110 DeleteDC(hdcBmp); 1111 DeleteDC(hdcXor); 1112 DeleteDC(hdcMask); 1113 ReleaseDC(0, hdcref); 1114 } 1115 1116 end: 1117 HeapFree(GetProcessHeap(), 0, mask); 1118 IWICBitmapSource_Release(real_source); 1119 return hr; 1120 } 1121 1122 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread) 1123 { 1124 HRESULT hr; 1125 IWICImagingFactory *factory; 1126 IWICBitmapDecoder *decoder; 1127 IWICBitmapFrameDecode *framedecode; 1128 HRESULT initresult; 1129 IWICStream *stream; 1130 1131 initresult = CoInitialize(NULL); 1132 1133 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, 1134 &IID_IWICImagingFactory, (void**)&factory); 1135 if (SUCCEEDED(hr)) /* created factory */ 1136 { 1137 hr = IWICImagingFactory_CreateStream(factory, &stream); 1138 IWICImagingFactory_Release(factory); 1139 } 1140 1141 if (SUCCEEDED(hr)) /* created stream */ 1142 { 1143 hr = IWICStream_InitializeFromMemory(stream, xbuf, xread); 1144 1145 if (SUCCEEDED(hr)) /* initialized stream */ 1146 { 1147 hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER, 1148 &IID_IWICBitmapDecoder, (void**)&decoder); 1149 if (SUCCEEDED(hr)) /* created decoder */ 1150 { 1151 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad); 1152 1153 if (SUCCEEDED(hr)) /* initialized decoder */ 1154 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode); 1155 1156 IWICBitmapDecoder_Release(decoder); 1157 } 1158 } 1159 1160 IWICStream_Release(stream); 1161 } 1162 1163 if (SUCCEEDED(hr)) /* got framedecode */ 1164 { 1165 hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode); 1166 IWICBitmapFrameDecode_Release(framedecode); 1167 } 1168 1169 if (SUCCEEDED(initresult)) CoUninitialize(); 1170 return hr; 1171 } 1172 1173 /***************************************************** 1174 * start of Icon-specific code 1175 */ 1176 1177 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread) 1178 { 1179 HICON hicon; 1180 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf; 1181 HDC hdcRef; 1182 int i; 1183 1184 TRACE("(this %p, xbuf %p, xread %u)\n", This, xbuf, xread); 1185 1186 /* 1187 FIXME("icon.idReserved=%d\n",cifd->idReserved); 1188 FIXME("icon.idType=%d\n",cifd->idType); 1189 FIXME("icon.idCount=%d\n",cifd->idCount); 1190 1191 for (i=0;i<cifd->idCount;i++) { 1192 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth); 1193 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight); 1194 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount); 1195 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved); 1196 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot); 1197 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot); 1198 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize); 1199 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset); 1200 } 1201 */ 1202 1203 /* Need at least one icon to do something. */ 1204 if (!cifd->idCount) 1205 { 1206 ERR("Invalid icon count of zero.\n"); 1207 return E_FAIL; 1208 } 1209 i=0; 1210 /* If we have more than one icon, try to find the best. 1211 * this currently means '32 pixel wide'. 1212 */ 1213 if (cifd->idCount!=1) { 1214 for (i=0;i<cifd->idCount;i++) { 1215 if (cifd->idEntries[i].bWidth == 32) 1216 break; 1217 } 1218 if (i==cifd->idCount) i=0; 1219 } 1220 if (xread < cifd->idEntries[i].dwDIBOffset + cifd->idEntries[i].dwDIBSize) 1221 { 1222 ERR("Icon data address %u is over %u bytes available.\n", 1223 cifd->idEntries[i].dwDIBOffset + cifd->idEntries[i].dwDIBSize, xread); 1224 return E_FAIL; 1225 } 1226 if (cifd->idType == 2) 1227 { 1228 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, cifd->idEntries[i].dwDIBSize + 4); 1229 memcpy(buf, &cifd->idEntries[i].xHotspot, 4); 1230 memcpy(buf + 4, xbuf+cifd->idEntries[i].dwDIBOffset, cifd->idEntries[i].dwDIBSize); 1231 hicon = CreateIconFromResourceEx( 1232 buf, 1233 cifd->idEntries[i].dwDIBSize + 4, 1234 FALSE, /* is cursor */ 1235 0x00030000, 1236 cifd->idEntries[i].bWidth, 1237 cifd->idEntries[i].bHeight, 1238 0 1239 ); 1240 HeapFree(GetProcessHeap(), 0, buf); 1241 } 1242 else 1243 { 1244 hicon = CreateIconFromResourceEx( 1245 xbuf+cifd->idEntries[i].dwDIBOffset, 1246 cifd->idEntries[i].dwDIBSize, 1247 TRUE, /* is icon */ 1248 0x00030000, 1249 cifd->idEntries[i].bWidth, 1250 cifd->idEntries[i].bHeight, 1251 0 1252 ); 1253 } 1254 if (!hicon) { 1255 ERR("CreateIcon failed.\n"); 1256 return E_FAIL; 1257 } else { 1258 This->desc.picType = PICTYPE_ICON; 1259 This->desc.u.icon.hicon = hicon; 1260 This->origWidth = cifd->idEntries[i].bWidth; 1261 This->origHeight = cifd->idEntries[i].bHeight; 1262 hdcRef = CreateCompatibleDC(0); 1263 This->himetricWidth = xpixels_to_himetric(cifd->idEntries[i].bWidth, hdcRef); 1264 This->himetricHeight= ypixels_to_himetric(cifd->idEntries[i].bHeight, hdcRef); 1265 DeleteDC(hdcRef); 1266 return S_OK; 1267 } 1268 } 1269 1270 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This, 1271 const BYTE *data, ULONG size) 1272 { 1273 HENHMETAFILE hemf; 1274 ENHMETAHEADER hdr; 1275 1276 hemf = SetEnhMetaFileBits(size, data); 1277 if (!hemf) return E_FAIL; 1278 1279 GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr); 1280 1281 This->desc.picType = PICTYPE_ENHMETAFILE; 1282 This->desc.u.emf.hemf = hemf; 1283 1284 This->origWidth = 0; 1285 This->origHeight = 0; 1286 This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left; 1287 This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top; 1288 1289 return S_OK; 1290 } 1291 1292 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This, 1293 const BYTE *data, ULONG size) 1294 { 1295 const APM_HEADER *header = (const APM_HEADER *)data; 1296 HMETAFILE hmf; 1297 1298 if (size < sizeof(APM_HEADER)) 1299 return E_FAIL; 1300 if (header->key != 0x9ac6cdd7) 1301 return E_FAIL; 1302 1303 /* SetMetaFileBitsEx performs data check on its own */ 1304 hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header)); 1305 if (!hmf) return E_FAIL; 1306 1307 This->desc.picType = PICTYPE_METAFILE; 1308 This->desc.u.wmf.hmeta = hmf; 1309 This->desc.u.wmf.xExt = 0; 1310 This->desc.u.wmf.yExt = 0; 1311 1312 This->origWidth = 0; 1313 This->origHeight = 0; 1314 This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch); 1315 This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch); 1316 return S_OK; 1317 } 1318 1319 /************************************************************************ 1320 * OLEPictureImpl_IPersistStream_Load (IUnknown) 1321 * 1322 * Loads the binary data from the IStream. Starts at current position. 1323 * There appears to be an 2 DWORD header: 1324 * DWORD magic; 1325 * DWORD len; 1326 * 1327 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF 1328 */ 1329 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm) { 1330 HRESULT hr; 1331 BOOL headerisdata; 1332 BOOL statfailed = FALSE; 1333 ULONG xread, toread; 1334 ULONG headerread; 1335 BYTE *xbuf; 1336 DWORD header[2]; 1337 WORD magic; 1338 STATSTG statstg; 1339 OLEPictureImpl *This = impl_from_IPersistStream(iface); 1340 1341 TRACE("(%p,%p)\n",This,pStm); 1342 1343 /**************************************************************************************** 1344 * Part 1: Load the data 1345 */ 1346 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find 1347 * out whether we do. 1348 * 1349 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a 1350 * compound file. This may explain most, if not all, of the cases of "no 1351 * header", and the header validation should take this into account. 1352 * At least in Visual Basic 6, resource streams, valid headers are 1353 * header[0] == "lt\0\0", 1354 * header[1] == length_of_stream. 1355 * 1356 * Also handle streams where we do not have a working "Stat" method by 1357 * reading all data until the end of the stream. 1358 */ 1359 hr = IStream_Stat(pStm,&statstg,STATFLAG_NONAME); 1360 if (hr != S_OK) { 1361 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr); 1362 statfailed = TRUE; 1363 /* we will read at least 8 byte ... just right below */ 1364 statstg.cbSize.QuadPart = 8; 1365 } 1366 1367 toread = 0; 1368 headerread = 0; 1369 headerisdata = FALSE; 1370 do { 1371 hr = IStream_Read(pStm, header, 8, &xread); 1372 if (hr != S_OK || xread!=8) { 1373 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread); 1374 return (hr?hr:E_FAIL); 1375 } 1376 headerread += xread; 1377 xread = 0; 1378 1379 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) { 1380 if (toread != 0 && toread != header[1]) 1381 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n", 1382 toread, header[1]); 1383 toread = header[1]; 1384 if (statfailed) 1385 { 1386 statstg.cbSize.QuadPart = header[1] + 8; 1387 statfailed = FALSE; 1388 } 1389 if (toread == 0) break; 1390 } else { 1391 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */ 1392 !memcmp(&(header[0]), "BM", 2) || /* BMP header */ 1393 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */ 1394 (header[0] == EMR_HEADER) || /* EMF header */ 1395 (header[0] == 0x10000) || /* icon: idReserved 0, idType 1 */ 1396 (header[0] == 0x20000) || /* cursor: idReserved 0, idType 2 */ 1397 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */ 1398 (header[1]==0) 1399 ) {/* Found start of bitmap data */ 1400 headerisdata = TRUE; 1401 if (toread == 0) 1402 toread = statstg.cbSize.QuadPart-8; 1403 else toread -= 8; 1404 xread = 8; 1405 } else { 1406 FIXME("Unknown stream header magic: %08x\n", header[0]); 1407 toread = header[1]; 1408 } 1409 } 1410 } while (!headerisdata); 1411 1412 if (statfailed) { /* we don't know the size ... read all we get */ 1413 unsigned int sizeinc = 4096; 1414 unsigned int origsize = sizeinc; 1415 ULONG nread = 42; 1416 1417 TRACE("Reading all data from stream.\n"); 1418 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize); 1419 if (headerisdata) 1420 memcpy (xbuf, header, 8); 1421 while (1) { 1422 while (xread < origsize) { 1423 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread); 1424 xread += nread; 1425 if (hr != S_OK || !nread) 1426 break; 1427 } 1428 if (!nread || hr != S_OK) /* done, or error */ 1429 break; 1430 if (xread == origsize) { 1431 origsize += sizeinc; 1432 sizeinc = 2*sizeinc; /* exponential increase */ 1433 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize); 1434 } 1435 } 1436 if (hr != S_OK) 1437 TRACE("hr in no-stat loader case is %08x\n", hr); 1438 TRACE("loaded %d bytes.\n", xread); 1439 This->datalen = xread; 1440 This->data = xbuf; 1441 } else { 1442 This->datalen = toread+(headerisdata?8:0); 1443 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen); 1444 if (!xbuf) 1445 return E_OUTOFMEMORY; 1446 1447 if (headerisdata) 1448 memcpy (xbuf, header, 8); 1449 1450 while (xread < This->datalen) { 1451 ULONG nread; 1452 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread); 1453 xread += nread; 1454 if (hr != S_OK || !nread) 1455 break; 1456 } 1457 if (xread != This->datalen) 1458 ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen); 1459 } 1460 if (This->datalen == 0) { /* Marks the "NONE" picture */ 1461 This->desc.picType = PICTYPE_NONE; 1462 return S_OK; 1463 } 1464 1465 1466 /**************************************************************************************** 1467 * Part 2: Process the loaded data 1468 */ 1469 1470 magic = xbuf[0] + (xbuf[1]<<8); 1471 This->loadtime_format = magic; 1472 1473 switch (magic) { 1474 case BITMAP_FORMAT_GIF: /* GIF */ 1475 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread); 1476 break; 1477 case BITMAP_FORMAT_JPEG: /* JPEG */ 1478 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread); 1479 break; 1480 case BITMAP_FORMAT_BMP: /* Bitmap */ 1481 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICBmpDecoder, xbuf, xread); 1482 break; 1483 case BITMAP_FORMAT_PNG: /* PNG */ 1484 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread); 1485 break; 1486 case BITMAP_FORMAT_APM: /* APM */ 1487 hr = OLEPictureImpl_LoadAPM(This, xbuf, xread); 1488 break; 1489 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */ 1490 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread); 1491 break; 1492 } 1493 default: 1494 { 1495 unsigned int i; 1496 1497 /* let's see if it's a EMF */ 1498 hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread); 1499 if (hr == S_OK) break; 1500 1501 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread); 1502 hr=E_FAIL; 1503 for (i=0;i<xread+8;i++) { 1504 if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]); 1505 else MESSAGE("%02x ",xbuf[i-8]); 1506 if (i % 10 == 9) MESSAGE("\n"); 1507 } 1508 MESSAGE("\n"); 1509 break; 1510 } 1511 } 1512 This->bIsDirty = FALSE; 1513 1514 /* FIXME: this notify is not really documented */ 1515 if (hr==S_OK) 1516 OLEPicture_SendNotify(This,DISPID_PICT_TYPE); 1517 return hr; 1518 } 1519 1520 static BOOL serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength) 1521 { 1522 BOOL success = FALSE; 1523 HDC hDC; 1524 BITMAPINFO * pInfoBitmap; 1525 int iNumPaletteEntries; 1526 unsigned char * pPixelData; 1527 BITMAPFILEHEADER * pFileHeader; 1528 BITMAPINFO * pInfoHeader; 1529 1530 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1531 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 1532 1533 /* Find out bitmap size and padded length */ 1534 hDC = GetDC(0); 1535 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); 1536 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); 1537 1538 /* Fetch bitmap palette & pixel data */ 1539 1540 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage); 1541 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS); 1542 1543 /* Calculate the total length required for the BMP data */ 1544 if (pInfoBitmap->bmiHeader.biClrUsed != 0) { 1545 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed; 1546 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256; 1547 } else { 1548 if (pInfoBitmap->bmiHeader.biBitCount <= 8) 1549 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount; 1550 else 1551 iNumPaletteEntries = 0; 1552 } 1553 *pLength = 1554 sizeof(BITMAPFILEHEADER) + 1555 sizeof(BITMAPINFOHEADER) + 1556 iNumPaletteEntries * sizeof(RGBQUAD) + 1557 pInfoBitmap->bmiHeader.biSizeImage; 1558 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength); 1559 1560 /* Fill the BITMAPFILEHEADER */ 1561 pFileHeader = *ppBuffer; 1562 pFileHeader->bfType = BITMAP_FORMAT_BMP; 1563 pFileHeader->bfSize = *pLength; 1564 pFileHeader->bfOffBits = 1565 sizeof(BITMAPFILEHEADER) + 1566 sizeof(BITMAPINFOHEADER) + 1567 iNumPaletteEntries * sizeof(RGBQUAD); 1568 1569 /* Fill the BITMAPINFOHEADER and the palette data */ 1570 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER)); 1571 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD)); 1572 memcpy( 1573 (unsigned char *)(*ppBuffer) + 1574 sizeof(BITMAPFILEHEADER) + 1575 sizeof(BITMAPINFOHEADER) + 1576 iNumPaletteEntries * sizeof(RGBQUAD), 1577 pPixelData, pInfoBitmap->bmiHeader.biSizeImage); 1578 success = TRUE; 1579 1580 HeapFree(GetProcessHeap(), 0, pPixelData); 1581 HeapFree(GetProcessHeap(), 0, pInfoBitmap); 1582 return success; 1583 } 1584 1585 static BOOL serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) 1586 { 1587 ICONINFO infoIcon; 1588 BOOL success = FALSE; 1589 1590 *ppBuffer = NULL; *pLength = 0; 1591 if (GetIconInfo(hIcon, &infoIcon)) { 1592 HDC hDC; 1593 BITMAPINFO * pInfoBitmap; 1594 unsigned char * pIconData = NULL; 1595 unsigned int iDataSize = 0; 1596 1597 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 1598 1599 /* Find out icon size */ 1600 hDC = GetDC(0); 1601 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); 1602 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); 1603 if (1) { 1604 /* Auxiliary pointers */ 1605 CURSORICONFILEDIR * pIconDir; 1606 CURSORICONFILEDIRENTRY * pIconEntry; 1607 BITMAPINFOHEADER * pIconBitmapHeader; 1608 unsigned int iOffsetPalette; 1609 unsigned int iOffsetColorData; 1610 unsigned int iOffsetMaskData; 1611 1612 unsigned int iLengthScanLineMask; 1613 unsigned int iNumEntriesPalette; 1614 1615 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2; 1616 /* 1617 FIXME("DEBUG: bitmap size is %d x %d\n", 1618 pInfoBitmap->bmiHeader.biWidth, 1619 pInfoBitmap->bmiHeader.biHeight); 1620 FIXME("DEBUG: bitmap bpp is %d\n", 1621 pInfoBitmap->bmiHeader.biBitCount); 1622 FIXME("DEBUG: bitmap nplanes is %d\n", 1623 pInfoBitmap->bmiHeader.biPlanes); 1624 FIXME("DEBUG: bitmap biSizeImage is %u\n", 1625 pInfoBitmap->bmiHeader.biSizeImage); 1626 */ 1627 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */ 1628 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER); 1629 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize); 1630 1631 /* Fill out the CURSORICONFILEDIR */ 1632 pIconDir = (CURSORICONFILEDIR *)pIconData; 1633 pIconDir->idType = 1; 1634 pIconDir->idCount = 1; 1635 pIconDir->idReserved = 0; 1636 1637 /* Fill out the CURSORICONFILEDIRENTRY */ 1638 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); 1639 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth; 1640 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight; 1641 pIconEntry->bColorCount = 1642 (pInfoBitmap->bmiHeader.biBitCount < 8) 1643 ? 1 << pInfoBitmap->bmiHeader.biBitCount 1644 : 0; 1645 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes; 1646 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount; 1647 pIconEntry->dwDIBSize = 0; 1648 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY); 1649 1650 /* Fill out the BITMAPINFOHEADER */ 1651 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); 1652 *pIconBitmapHeader = pInfoBitmap->bmiHeader; 1653 1654 /* Find out whether a palette exists for the bitmap */ 1655 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB) 1656 || (pInfoBitmap->bmiHeader.biBitCount == 24) 1657 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) { 1658 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed; 1659 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; 1660 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32) 1661 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) { 1662 iNumEntriesPalette = 3; 1663 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) { 1664 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount; 1665 } else { 1666 iNumEntriesPalette = 0; 1667 } 1668 1669 /* Add bitmap size and header size to icon data size. */ 1670 iOffsetPalette = iDataSize; 1671 iDataSize += iNumEntriesPalette * sizeof(DWORD); 1672 iOffsetColorData = iDataSize; 1673 iDataSize += pIconBitmapHeader->biSizeImage; 1674 iOffsetMaskData = iDataSize; 1675 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask; 1676 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask; 1677 pIconBitmapHeader->biHeight *= 2; 1678 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize); 1679 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); 1680 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); 1681 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); 1682 1683 /* Get the actual bitmap data from the icon bitmap */ 1684 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight, 1685 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS); 1686 if (iNumEntriesPalette > 0) { 1687 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors, 1688 iNumEntriesPalette * sizeof(RGBQUAD)); 1689 } 1690 1691 /* Reset all values so that GetDIBits call succeeds */ 1692 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData); 1693 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 1694 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); 1695 /* 1696 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS) 1697 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, 1698 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) { 1699 1700 printf("ERROR: unable to get bitmap mask (error %u)\n", 1701 GetLastError()); 1702 1703 } 1704 */ 1705 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); 1706 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS); 1707 1708 /* Write out everything produced so far to the stream */ 1709 *ppBuffer = pIconData; *pLength = iDataSize; 1710 success = TRUE; 1711 } else { 1712 /* 1713 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n", 1714 GetLastError()); 1715 */ 1716 } 1717 /* 1718 Remarks (from MSDN entry on GetIconInfo): 1719 1720 GetIconInfo creates bitmaps for the hbmMask and hbmColor 1721 members of ICONINFO. The calling application must manage 1722 these bitmaps and delete them when they are no longer 1723 necessary. 1724 */ 1725 if (hDC) ReleaseDC(0, hDC); 1726 DeleteObject(infoIcon.hbmMask); 1727 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor); 1728 HeapFree(GetProcessHeap(), 0, pInfoBitmap); 1729 } else { 1730 printf("ERROR: Unable to get icon information (error %u)\n", 1731 GetLastError()); 1732 } 1733 return success; 1734 } 1735 1736 static BOOL serializeEMF(HENHMETAFILE hemf, void **buf, unsigned *size) 1737 { 1738 *size = GetEnhMetaFileBits(hemf, 0, NULL); 1739 if (!*size) return FALSE; 1740 1741 *buf = HeapAlloc(GetProcessHeap(), 0, *size); 1742 if (!*buf) return FALSE; 1743 1744 return GetEnhMetaFileBits(hemf, *size, *buf) != 0; 1745 } 1746 1747 static HRESULT WINAPI OLEPictureImpl_Save( 1748 IPersistStream* iface,IStream*pStm,BOOL fClearDirty) 1749 { 1750 HRESULT hResult = E_NOTIMPL; 1751 void * pIconData; 1752 unsigned int iDataSize; 1753 DWORD header[2]; 1754 ULONG dummy; 1755 BOOL serializeResult = FALSE; 1756 OLEPictureImpl *This = impl_from_IPersistStream(iface); 1757 1758 TRACE("%p %p %d\n", This, pStm, fClearDirty); 1759 1760 switch (This->desc.picType) { 1761 case PICTYPE_NONE: 1762 header[0] = 0x0000746c; 1763 header[1] = 0; 1764 hResult = IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); 1765 break; 1766 1767 case PICTYPE_ICON: 1768 if (This->bIsDirty || !This->data) { 1769 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) { 1770 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty); 1771 hResult = E_FAIL; 1772 break; 1773 } 1774 HeapFree(GetProcessHeap(), 0, This->data); 1775 This->data = pIconData; 1776 This->datalen = iDataSize; 1777 } 1778 1779 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c; 1780 header[1] = This->datalen; 1781 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); 1782 IStream_Write(pStm, This->data, This->datalen, &dummy); 1783 hResult = S_OK; 1784 break; 1785 case PICTYPE_BITMAP: 1786 if (This->bIsDirty || !This->data) { 1787 switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) { 1788 case BITMAP_FORMAT_BMP: 1789 serializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize); 1790 break; 1791 case BITMAP_FORMAT_JPEG: 1792 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty); 1793 break; 1794 case BITMAP_FORMAT_GIF: 1795 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty); 1796 break; 1797 case BITMAP_FORMAT_PNG: 1798 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty); 1799 break; 1800 default: 1801 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty); 1802 break; 1803 } 1804 1805 if (!serializeResult) 1806 { 1807 hResult = E_FAIL; 1808 break; 1809 } 1810 1811 HeapFree(GetProcessHeap(), 0, This->data); 1812 This->data = pIconData; 1813 This->datalen = iDataSize; 1814 } 1815 1816 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c; 1817 header[1] = This->datalen; 1818 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); 1819 IStream_Write(pStm, This->data, This->datalen, &dummy); 1820 hResult = S_OK; 1821 break; 1822 1823 case PICTYPE_ENHMETAFILE: 1824 if (This->bIsDirty || !This->data) 1825 { 1826 serializeResult = serializeEMF(This->desc.u.emf.hemf, &pIconData, &iDataSize); 1827 if (!serializeResult) 1828 { 1829 hResult = E_FAIL; 1830 break; 1831 } 1832 1833 HeapFree(GetProcessHeap(), 0, This->data); 1834 This->data = pIconData; 1835 This->datalen = iDataSize; 1836 } 1837 header[0] = 0x0000746c; 1838 header[1] = This->datalen; 1839 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); 1840 IStream_Write(pStm, This->data, This->datalen, &dummy); 1841 hResult = S_OK; 1842 break; 1843 1844 case PICTYPE_METAFILE: 1845 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty); 1846 break; 1847 default: 1848 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty); 1849 break; 1850 } 1851 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE; 1852 return hResult; 1853 } 1854 1855 static HRESULT WINAPI OLEPictureImpl_GetSizeMax( 1856 IPersistStream* iface,ULARGE_INTEGER*pcbSize) 1857 { 1858 OLEPictureImpl *This = impl_from_IPersistStream(iface); 1859 FIXME("(%p,%p),stub!\n",This,pcbSize); 1860 return E_NOTIMPL; 1861 } 1862 1863 /************************************************************************ 1864 * OLEPictureImpl_SaveAsFile 1865 */ 1866 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface, 1867 IStream *stream, BOOL mem_copy, LONG *size) 1868 { 1869 OLEPictureImpl *This = impl_from_IPicture(iface); 1870 void *data; 1871 unsigned data_size; 1872 ULONG written; 1873 HRESULT hr; 1874 1875 FIXME("(%p)->(%p,%d,%p): semi-stub\n", This, stream, mem_copy, size); 1876 1877 switch (This->desc.picType) 1878 { 1879 case PICTYPE_NONE: 1880 return S_OK; 1881 1882 case PICTYPE_ICON: 1883 if (!mem_copy) return E_FAIL; 1884 1885 if (This->bIsDirty || !This->data) 1886 { 1887 if (!serializeIcon(This->desc.u.icon.hicon, &data, &data_size)) 1888 return E_FAIL; 1889 HeapFree(GetProcessHeap(), 0, This->data); 1890 This->data = data; 1891 This->datalen = data_size; 1892 } 1893 hr = IStream_Write(stream, This->data, This->datalen, &written); 1894 if (hr == S_OK && size) *size = written; 1895 return hr; 1896 1897 case PICTYPE_BITMAP: 1898 if (!mem_copy) return E_FAIL; 1899 1900 if (This->bIsDirty || !This->data) 1901 { 1902 switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) 1903 { 1904 case BITMAP_FORMAT_BMP: 1905 if (!serializeBMP(This->desc.u.bmp.hbitmap, &data, &data_size)) 1906 return E_FAIL; 1907 break; 1908 case BITMAP_FORMAT_JPEG: 1909 FIXME("BITMAP_FORMAT_JPEG is not implemented\n"); 1910 return E_NOTIMPL; 1911 case BITMAP_FORMAT_GIF: 1912 FIXME("BITMAP_FORMAT_GIF is not implemented\n"); 1913 return E_NOTIMPL; 1914 case BITMAP_FORMAT_PNG: 1915 FIXME("BITMAP_FORMAT_PNG is not implemented\n"); 1916 return E_NOTIMPL; 1917 default: 1918 FIXME("PICTYPE_BITMAP/%#x is not implemented\n", This->loadtime_format); 1919 return E_NOTIMPL; 1920 } 1921 1922 HeapFree(GetProcessHeap(), 0, This->data); 1923 This->data = data; 1924 This->datalen = data_size; 1925 } 1926 hr = IStream_Write(stream, This->data, This->datalen, &written); 1927 if (hr == S_OK && size) *size = written; 1928 return hr; 1929 1930 case PICTYPE_METAFILE: 1931 FIXME("PICTYPE_METAFILE is not implemented\n"); 1932 return E_NOTIMPL; 1933 1934 case PICTYPE_ENHMETAFILE: 1935 if (!mem_copy) return E_FAIL; 1936 1937 if (This->bIsDirty || !This->data) 1938 { 1939 if (!serializeEMF(This->desc.u.emf.hemf, &data, &data_size)) 1940 return E_FAIL; 1941 HeapFree(GetProcessHeap(), 0, This->data); 1942 This->data = data; 1943 This->datalen = data_size; 1944 } 1945 hr = IStream_Write(stream, This->data, This->datalen, &written); 1946 if (hr == S_OK && size) *size = written; 1947 return hr; 1948 1949 default: 1950 FIXME("%#x is not implemented\n", This->desc.picType); 1951 break; 1952 } 1953 return E_NOTIMPL; 1954 } 1955 1956 /************************************************************************ 1957 * IDispatch 1958 */ 1959 1960 /************************************************************************ 1961 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown) 1962 * 1963 * See Windows documentation for more details on IUnknown methods. 1964 */ 1965 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface( 1966 IDispatch* iface, 1967 REFIID riid, 1968 VOID** ppvoid) 1969 { 1970 OLEPictureImpl *This = impl_from_IDispatch(iface); 1971 1972 return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid); 1973 } 1974 1975 /************************************************************************ 1976 * OLEPictureImpl_IDispatch_AddRef (IUnknown) 1977 * 1978 * See Windows documentation for more details on IUnknown methods. 1979 */ 1980 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef( 1981 IDispatch* iface) 1982 { 1983 OLEPictureImpl *This = impl_from_IDispatch(iface); 1984 1985 return IPicture_AddRef(&This->IPicture_iface); 1986 } 1987 1988 /************************************************************************ 1989 * OLEPictureImpl_IDispatch_Release (IUnknown) 1990 * 1991 * See Windows documentation for more details on IUnknown methods. 1992 */ 1993 static ULONG WINAPI OLEPictureImpl_IDispatch_Release( 1994 IDispatch* iface) 1995 { 1996 OLEPictureImpl *This = impl_from_IDispatch(iface); 1997 1998 return IPicture_Release(&This->IPicture_iface); 1999 } 2000 2001 /************************************************************************ 2002 * OLEPictureImpl_GetTypeInfoCount (IDispatch) 2003 * 2004 * See Windows documentation for more details on IDispatch methods. 2005 */ 2006 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount( 2007 IDispatch* iface, 2008 unsigned int* pctinfo) 2009 { 2010 TRACE("(%p)\n", pctinfo); 2011 2012 *pctinfo = 1; 2013 2014 return S_OK; 2015 } 2016 2017 /************************************************************************ 2018 * OLEPictureImpl_GetTypeInfo (IDispatch) 2019 * 2020 * See Windows documentation for more details on IDispatch methods. 2021 */ 2022 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo( 2023 IDispatch* iface, 2024 UINT iTInfo, 2025 LCID lcid, 2026 ITypeInfo** ppTInfo) 2027 { 2028 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0}; 2029 ITypeLib *tl; 2030 HRESULT hres; 2031 2032 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo); 2033 2034 if (iTInfo != 0) 2035 return E_FAIL; 2036 2037 hres = LoadTypeLib(stdole2tlb, &tl); 2038 if (FAILED(hres)) 2039 { 2040 ERR("Could not load stdole2.tlb\n"); 2041 return hres; 2042 } 2043 2044 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo); 2045 if (FAILED(hres)) 2046 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres); 2047 2048 return hres; 2049 } 2050 2051 /************************************************************************ 2052 * OLEPictureImpl_GetIDsOfNames (IDispatch) 2053 * 2054 * See Windows documentation for more details on IDispatch methods. 2055 */ 2056 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames( 2057 IDispatch* iface, 2058 REFIID riid, 2059 LPOLESTR* rgszNames, 2060 UINT cNames, 2061 LCID lcid, 2062 DISPID* rgDispId) 2063 { 2064 ITypeInfo * pTInfo; 2065 HRESULT hres; 2066 2067 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid), 2068 rgszNames, cNames, (int)lcid, rgDispId); 2069 2070 if (cNames == 0) 2071 { 2072 return E_INVALIDARG; 2073 } 2074 else 2075 { 2076 /* retrieve type information */ 2077 hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo); 2078 2079 if (FAILED(hres)) 2080 { 2081 ERR("GetTypeInfo failed.\n"); 2082 return hres; 2083 } 2084 2085 /* convert names to DISPIDs */ 2086 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId); 2087 ITypeInfo_Release(pTInfo); 2088 2089 return hres; 2090 } 2091 } 2092 2093 /************************************************************************ 2094 * OLEPictureImpl_Invoke (IDispatch) 2095 * 2096 * See Windows documentation for more details on IDispatch methods. 2097 */ 2098 static HRESULT WINAPI OLEPictureImpl_Invoke( 2099 IDispatch* iface, 2100 DISPID dispIdMember, 2101 REFIID riid, 2102 LCID lcid, 2103 WORD wFlags, 2104 DISPPARAMS* pDispParams, 2105 VARIANT* pVarResult, 2106 EXCEPINFO* pExepInfo, 2107 UINT* puArgErr) 2108 { 2109 OLEPictureImpl *This = impl_from_IDispatch(iface); 2110 HRESULT hr; 2111 2112 /* validate parameters */ 2113 2114 if (!IsEqualIID(riid, &IID_NULL)) 2115 { 2116 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid)); 2117 return DISP_E_UNKNOWNNAME; 2118 } 2119 2120 if (!pDispParams) 2121 { 2122 ERR("null pDispParams not allowed\n"); 2123 return DISP_E_PARAMNOTOPTIONAL; 2124 } 2125 2126 if (wFlags & DISPATCH_PROPERTYGET) 2127 { 2128 if (pDispParams->cArgs != 0) 2129 { 2130 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs); 2131 return DISP_E_BADPARAMCOUNT; 2132 } 2133 if (!pVarResult) 2134 { 2135 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n"); 2136 return DISP_E_PARAMNOTOPTIONAL; 2137 } 2138 } 2139 else if (wFlags & DISPATCH_PROPERTYPUT) 2140 { 2141 if (pDispParams->cArgs != 1) 2142 { 2143 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs); 2144 return DISP_E_BADPARAMCOUNT; 2145 } 2146 } 2147 2148 switch (dispIdMember) 2149 { 2150 case DISPID_PICT_HANDLE: 2151 if (wFlags & DISPATCH_PROPERTYGET) 2152 { 2153 TRACE("DISPID_PICT_HANDLE\n"); 2154 V_VT(pVarResult) = VT_I4; 2155 return IPicture_get_Handle(&This->IPicture_iface, &V_UINT(pVarResult)); 2156 } 2157 break; 2158 case DISPID_PICT_HPAL: 2159 if (wFlags & DISPATCH_PROPERTYGET) 2160 { 2161 TRACE("DISPID_PICT_HPAL\n"); 2162 V_VT(pVarResult) = VT_I4; 2163 return IPicture_get_hPal(&This->IPicture_iface, &V_UINT(pVarResult)); 2164 } 2165 else if (wFlags & DISPATCH_PROPERTYPUT) 2166 { 2167 VARIANTARG vararg; 2168 2169 TRACE("DISPID_PICT_HPAL\n"); 2170 2171 VariantInit(&vararg); 2172 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4); 2173 if (FAILED(hr)) 2174 return hr; 2175 2176 hr = IPicture_set_hPal(&This->IPicture_iface, V_I4(&vararg)); 2177 2178 VariantClear(&vararg); 2179 return hr; 2180 } 2181 break; 2182 case DISPID_PICT_TYPE: 2183 if (wFlags & DISPATCH_PROPERTYGET) 2184 { 2185 TRACE("DISPID_PICT_TYPE\n"); 2186 V_VT(pVarResult) = VT_I2; 2187 return OLEPictureImpl_get_Type(&This->IPicture_iface, &V_I2(pVarResult)); 2188 } 2189 break; 2190 case DISPID_PICT_WIDTH: 2191 if (wFlags & DISPATCH_PROPERTYGET) 2192 { 2193 TRACE("DISPID_PICT_WIDTH\n"); 2194 V_VT(pVarResult) = VT_I4; 2195 return IPicture_get_Width(&This->IPicture_iface, &V_I4(pVarResult)); 2196 } 2197 break; 2198 case DISPID_PICT_HEIGHT: 2199 if (wFlags & DISPATCH_PROPERTYGET) 2200 { 2201 TRACE("DISPID_PICT_HEIGHT\n"); 2202 V_VT(pVarResult) = VT_I4; 2203 return IPicture_get_Height(&This->IPicture_iface, &V_I4(pVarResult)); 2204 } 2205 break; 2206 case DISPID_PICT_RENDER: 2207 if (wFlags & DISPATCH_METHOD) 2208 { 2209 VARIANTARG *args = pDispParams->rgvarg; 2210 int i; 2211 2212 TRACE("DISPID_PICT_RENDER\n"); 2213 2214 if (pDispParams->cArgs != 10) 2215 return DISP_E_BADPARAMCOUNT; 2216 2217 /* All parameters are supposed to be VT_I4 (on 64 bits too). */ 2218 for (i = 0; i < pDispParams->cArgs; i++) 2219 if (V_VT(&args[i]) != VT_I4) 2220 { 2221 ERR("DISPID_PICT_RENDER: wrong argument type %d:%d\n", i, V_VT(&args[i])); 2222 return DISP_E_TYPEMISMATCH; 2223 } 2224 2225 /* FIXME: rectangle pointer argument handling seems broken on 64 bits, 2226 currently Render() doesn't use it at all so for now NULL is passed. */ 2227 return IPicture_Render(&This->IPicture_iface, 2228 LongToHandle(V_I4(&args[9])), 2229 V_I4(&args[8]), 2230 V_I4(&args[7]), 2231 V_I4(&args[6]), 2232 V_I4(&args[5]), 2233 V_I4(&args[4]), 2234 V_I4(&args[3]), 2235 V_I4(&args[2]), 2236 V_I4(&args[1]), 2237 NULL); 2238 } 2239 break; 2240 } 2241 2242 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags); 2243 return DISP_E_MEMBERNOTFOUND; 2244 } 2245 2246 2247 static const IPictureVtbl OLEPictureImpl_VTable = 2248 { 2249 OLEPictureImpl_QueryInterface, 2250 OLEPictureImpl_AddRef, 2251 OLEPictureImpl_Release, 2252 OLEPictureImpl_get_Handle, 2253 OLEPictureImpl_get_hPal, 2254 OLEPictureImpl_get_Type, 2255 OLEPictureImpl_get_Width, 2256 OLEPictureImpl_get_Height, 2257 OLEPictureImpl_Render, 2258 OLEPictureImpl_set_hPal, 2259 OLEPictureImpl_get_CurDC, 2260 OLEPictureImpl_SelectPicture, 2261 OLEPictureImpl_get_KeepOriginalFormat, 2262 OLEPictureImpl_put_KeepOriginalFormat, 2263 OLEPictureImpl_PictureChanged, 2264 OLEPictureImpl_SaveAsFile, 2265 OLEPictureImpl_get_Attributes 2266 }; 2267 2268 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable = 2269 { 2270 OLEPictureImpl_IDispatch_QueryInterface, 2271 OLEPictureImpl_IDispatch_AddRef, 2272 OLEPictureImpl_IDispatch_Release, 2273 OLEPictureImpl_GetTypeInfoCount, 2274 OLEPictureImpl_GetTypeInfo, 2275 OLEPictureImpl_GetIDsOfNames, 2276 OLEPictureImpl_Invoke 2277 }; 2278 2279 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable = 2280 { 2281 OLEPictureImpl_IPersistStream_QueryInterface, 2282 OLEPictureImpl_IPersistStream_AddRef, 2283 OLEPictureImpl_IPersistStream_Release, 2284 OLEPictureImpl_GetClassID, 2285 OLEPictureImpl_IsDirty, 2286 OLEPictureImpl_Load, 2287 OLEPictureImpl_Save, 2288 OLEPictureImpl_GetSizeMax 2289 }; 2290 2291 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable = 2292 { 2293 OLEPictureImpl_IConnectionPointContainer_QueryInterface, 2294 OLEPictureImpl_IConnectionPointContainer_AddRef, 2295 OLEPictureImpl_IConnectionPointContainer_Release, 2296 OLEPictureImpl_EnumConnectionPoints, 2297 OLEPictureImpl_FindConnectionPoint 2298 }; 2299 2300 /*********************************************************************** 2301 * OleCreatePictureIndirect (OLEAUT32.419) 2302 */ 2303 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid, 2304 BOOL Own, void **ppvObj ) 2305 { 2306 OLEPictureImpl* newPict; 2307 HRESULT hr; 2308 2309 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), Own, ppvObj); 2310 2311 *ppvObj = NULL; 2312 2313 newPict = OLEPictureImpl_Construct(lpPictDesc, Own); 2314 2315 if (newPict == NULL) 2316 return E_OUTOFMEMORY; 2317 2318 /* 2319 * Make sure it supports the interface required by the caller. 2320 */ 2321 hr = IPicture_QueryInterface(&newPict->IPicture_iface, riid, ppvObj); 2322 2323 /* 2324 * Release the reference obtained in the constructor. If 2325 * the QueryInterface was unsuccessful, it will free the class. 2326 */ 2327 IPicture_Release(&newPict->IPicture_iface); 2328 2329 return hr; 2330 } 2331 2332 2333 /*********************************************************************** 2334 * OleLoadPicture (OLEAUT32.418) 2335 */ 2336 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode, 2337 REFIID riid, LPVOID *ppvObj ) 2338 { 2339 LPPERSISTSTREAM ps; 2340 IPicture *newpic; 2341 HRESULT hr; 2342 2343 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n", 2344 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj); 2345 2346 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic); 2347 if (hr != S_OK) 2348 return hr; 2349 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps); 2350 if (hr != S_OK) { 2351 ERR("Could not get IPersistStream iface from Ole Picture?\n"); 2352 IPicture_Release(newpic); 2353 *ppvObj = NULL; 2354 return hr; 2355 } 2356 hr = IPersistStream_Load(ps,lpstream); 2357 IPersistStream_Release(ps); 2358 if (FAILED(hr)) 2359 { 2360 ERR("IPersistStream_Load failed\n"); 2361 IPicture_Release(newpic); 2362 *ppvObj = NULL; 2363 return hr; 2364 } 2365 hr = IPicture_QueryInterface(newpic,riid,ppvObj); 2366 if (hr != S_OK) 2367 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid)); 2368 IPicture_Release(newpic); 2369 return hr; 2370 } 2371 2372 /*********************************************************************** 2373 * OleLoadPictureEx (OLEAUT32.401) 2374 */ 2375 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode, 2376 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj ) 2377 { 2378 LPPERSISTSTREAM ps; 2379 IPicture *newpic; 2380 HRESULT hr; 2381 2382 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n", 2383 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj); 2384 2385 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic); 2386 if (hr != S_OK) 2387 return hr; 2388 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps); 2389 if (hr != S_OK) { 2390 ERR("Could not get IPersistStream iface from Ole Picture?\n"); 2391 IPicture_Release(newpic); 2392 *ppvObj = NULL; 2393 return hr; 2394 } 2395 hr = IPersistStream_Load(ps,lpstream); 2396 IPersistStream_Release(ps); 2397 if (FAILED(hr)) 2398 { 2399 ERR("IPersistStream_Load failed\n"); 2400 IPicture_Release(newpic); 2401 *ppvObj = NULL; 2402 return hr; 2403 } 2404 hr = IPicture_QueryInterface(newpic,riid,ppvObj); 2405 if (hr != S_OK) 2406 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid)); 2407 IPicture_Release(newpic); 2408 return hr; 2409 } 2410 2411 static HRESULT create_stream(const WCHAR *filename, IStream **stream) 2412 { 2413 HANDLE hFile; 2414 DWORD dwFileSize; 2415 HGLOBAL hGlobal = NULL; 2416 DWORD dwBytesRead; 2417 HRESULT hr = S_OK; 2418 2419 hFile = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 2420 if (hFile == INVALID_HANDLE_VALUE) 2421 return HRESULT_FROM_WIN32(GetLastError()); 2422 2423 dwFileSize = GetFileSize(hFile, NULL); 2424 if (dwFileSize != INVALID_FILE_SIZE) 2425 { 2426 hGlobal = GlobalAlloc(GMEM_FIXED, dwFileSize); 2427 if (!hGlobal) 2428 hr = E_OUTOFMEMORY; 2429 else 2430 { 2431 if (!ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL)) 2432 { 2433 GlobalFree(hGlobal); 2434 hr = HRESULT_FROM_WIN32(GetLastError()); 2435 } 2436 } 2437 } 2438 2439 CloseHandle(hFile); 2440 2441 if (FAILED(hr)) return hr; 2442 2443 hr = CreateStreamOnHGlobal(hGlobal, TRUE, stream); 2444 if (FAILED(hr)) 2445 GlobalFree(hGlobal); 2446 2447 return hr; 2448 } 2449 2450 /*********************************************************************** 2451 * OleLoadPictureFile (OLEAUT32.422) 2452 */ 2453 HRESULT WINAPI OleLoadPictureFile(VARIANT filename, IDispatch **picture) 2454 { 2455 IStream *stream; 2456 HRESULT hr; 2457 2458 TRACE("(%s,%p)\n", wine_dbgstr_variant(&filename), picture); 2459 2460 if (V_VT(&filename) != VT_BSTR) 2461 return CTL_E_FILENOTFOUND; 2462 2463 hr = create_stream(V_BSTR(&filename), &stream); 2464 if (hr != S_OK) 2465 { 2466 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) 2467 return CTL_E_FILENOTFOUND; 2468 2469 return CTL_E_PATHFILEACCESSERROR; 2470 } 2471 2472 hr = OleLoadPicture(stream, 0, FALSE, &IID_IDispatch, (void **)picture); 2473 IStream_Release(stream); 2474 return hr; 2475 } 2476 2477 /*********************************************************************** 2478 * OleSavePictureFile (OLEAUT32.423) 2479 */ 2480 HRESULT WINAPI OleSavePictureFile(IDispatch *picture, BSTR filename) 2481 { 2482 FIXME("(%p %s): stub\n", picture, debugstr_w(filename)); 2483 return CTL_E_FILENOTFOUND; 2484 } 2485 2486 /*********************************************************************** 2487 * OleLoadPicturePath (OLEAUT32.424) 2488 */ 2489 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller, 2490 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid, 2491 LPVOID *ppvRet ) 2492 { 2493 static const WCHAR file[] = { 'f','i','l','e',':',0 }; 2494 IStream *stream; 2495 HRESULT hRes; 2496 WCHAR *file_candidate; 2497 WCHAR path_buf[MAX_PATH]; 2498 2499 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n", 2500 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved, 2501 debugstr_guid(riid), ppvRet); 2502 2503 if (!szURLorPath || !ppvRet) 2504 return E_INVALIDARG; 2505 2506 *ppvRet = NULL; 2507 2508 /* Convert file URLs to DOS paths. */ 2509 if (strncmpW(szURLorPath, file, 5) == 0) { 2510 DWORD size; 2511 hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf, 2512 sizeof(path_buf)/sizeof(WCHAR), &size, 0); 2513 if (FAILED(hRes)) 2514 return hRes; 2515 2516 file_candidate = path_buf; 2517 } 2518 else 2519 file_candidate = szURLorPath; 2520 2521 /* Handle candidate DOS paths separately. */ 2522 if (file_candidate[1] == ':') { 2523 hRes = create_stream(file_candidate, &stream); 2524 if (FAILED(hRes)) 2525 return INET_E_RESOURCE_NOT_FOUND; 2526 } else { 2527 IMoniker *pmnk; 2528 IBindCtx *pbc; 2529 2530 hRes = CreateBindCtx(0, &pbc); 2531 if (SUCCEEDED(hRes)) 2532 { 2533 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk); 2534 if (SUCCEEDED(hRes)) 2535 { 2536 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream); 2537 IMoniker_Release(pmnk); 2538 } 2539 IBindCtx_Release(pbc); 2540 } 2541 if (FAILED(hRes)) 2542 return hRes; 2543 } 2544 2545 hRes = OleLoadPicture(stream, 0, FALSE, riid, ppvRet); 2546 2547 IStream_Release(stream); 2548 2549 return hRes; 2550 } 2551 2552 /******************************************************************************* 2553 * StdPic ClassFactory 2554 */ 2555 typedef struct 2556 { 2557 /* IUnknown fields */ 2558 IClassFactory IClassFactory_iface; 2559 LONG ref; 2560 } IClassFactoryImpl; 2561 2562 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) 2563 { 2564 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); 2565 } 2566 2567 static HRESULT WINAPI 2568 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { 2569 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 2570 2571 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj); 2572 return E_NOINTERFACE; 2573 } 2574 2575 static ULONG WINAPI 2576 SPCF_AddRef(LPCLASSFACTORY iface) { 2577 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 2578 return InterlockedIncrement(&This->ref); 2579 } 2580 2581 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) { 2582 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 2583 /* static class, won't be freed */ 2584 return InterlockedDecrement(&This->ref); 2585 } 2586 2587 static HRESULT WINAPI SPCF_CreateInstance( 2588 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj 2589 ) { 2590 /* Creates an uninitialized picture */ 2591 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj); 2592 2593 } 2594 2595 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { 2596 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 2597 FIXME("(%p)->(%d),stub!\n",This,dolock); 2598 return S_OK; 2599 } 2600 2601 static const IClassFactoryVtbl SPCF_Vtbl = { 2602 SPCF_QueryInterface, 2603 SPCF_AddRef, 2604 SPCF_Release, 2605 SPCF_CreateInstance, 2606 SPCF_LockServer 2607 }; 2608 static IClassFactoryImpl STDPIC_CF = {{&SPCF_Vtbl}, 1 }; 2609 2610 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; } 2611