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