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