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