4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
8 * Copyright 2008 Kirill K. Smirnov
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.
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.
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
26 * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well..
27 * Lots of methods are just stubs.
30 * NOTES (or things that msdn doesn't tell you)
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).
56 #include "wine/debug.h"
58 WINE_DEFAULT_DEBUG_CHANNEL(olepicture
);
60 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
61 #define BITMAP_FORMAT_JPEG 0xd8ff
62 #define BITMAP_FORMAT_GIF 0x4947
63 #define BITMAP_FORMAT_PNG 0x5089
64 #define BITMAP_FORMAT_APM 0xcdd7
68 /* Header for Aldus Placable Metafiles - a standard metafile follows */
69 typedef struct _APM_HEADER
91 } CURSORICONFILEDIRENTRY
;
98 CURSORICONFILEDIRENTRY idEntries
[1];
103 /*************************************************************************
104 * Declaration of implementation class
107 typedef struct OLEPictureImpl
{
110 * IPicture handles IUnknown
113 IPicture IPicture_iface
;
114 IDispatch IDispatch_iface
;
115 IPersistStream IPersistStream_iface
;
116 IConnectionPointContainer IConnectionPointContainer_iface
;
118 /* Object reference count */
121 /* We own the object and must destroy it ourselves */
124 /* Picture description */
127 /* These are the pixel size of a bitmap */
131 /* And these are the size of the picture converted into HIMETRIC units */
132 OLE_XSIZE_HIMETRIC himetricWidth
;
133 OLE_YSIZE_HIMETRIC himetricHeight
;
135 IConnectionPoint
*pCP
;
139 HBITMAP stock_bitmap
;
141 /* Bitmap transparency mask */
149 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
150 unsigned int loadtime_magic
; /* If a length header was found, saves value */
151 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
154 static inline OLEPictureImpl
*impl_from_IPicture(IPicture
*iface
)
156 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPicture_iface
);
159 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
161 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IDispatch_iface
);
164 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
166 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPersistStream_iface
);
169 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
171 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IConnectionPointContainer_iface
);
175 * Predeclare VTables. They get initialized at the end.
177 static const IPictureVtbl OLEPictureImpl_VTable
;
178 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
179 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
180 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
182 /* pixels to HIMETRIC units conversion */
183 static inline OLE_XSIZE_HIMETRIC
xpixels_to_himetric(INT pixels
, HDC hdc
)
185 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
188 static inline OLE_YSIZE_HIMETRIC
ypixels_to_himetric(INT pixels
, HDC hdc
)
190 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
193 /***********************************************************************
194 * Implementation of the OLEPictureImpl class.
197 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
)
202 TRACE("bitmap handle %p\n", This
->desc
.bmp
.hbitmap
);
203 if(GetObjectW(This
->desc
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
204 ERR("GetObject fails\n");
207 This
->origWidth
= bm
.bmWidth
;
208 This
->origHeight
= bm
.bmHeight
;
210 TRACE("width %d, height %d, bpp %d\n", bm
.bmWidth
, bm
.bmHeight
, bm
.bmBitsPixel
);
212 /* The width and height are stored in HIMETRIC units (0.01 mm),
213 so we take our pixel width divide by pixels per inch and
214 multiply by 25.4 * 100 */
215 /* Should we use GetBitmapDimension if available? */
216 hdcRef
= CreateCompatibleDC(0);
218 This
->himetricWidth
= xpixels_to_himetric(bm
.bmWidth
, hdcRef
);
219 This
->himetricHeight
= ypixels_to_himetric(bm
.bmHeight
, hdcRef
);
220 This
->stock_bitmap
= GetCurrentObject( hdcRef
, OBJ_BITMAP
);
222 This
->loadtime_format
= BITMAP_FORMAT_BMP
;
227 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
231 TRACE("icon handle %p\n", This
->desc
.icon
.hicon
);
232 if (GetIconInfo(This
->desc
.icon
.hicon
, &infoIcon
)) {
236 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
237 if(GetObjectW(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
238 ERR("GetObject fails on icon bitmap\n");
242 This
->origWidth
= bm
.bmWidth
;
243 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
244 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
247 This
->himetricWidth
= xpixels_to_himetric(This
->origWidth
, hdcRef
);
248 This
->himetricHeight
= ypixels_to_himetric(This
->origHeight
, hdcRef
);
250 ReleaseDC(0, hdcRef
);
252 DeleteObject(infoIcon
.hbmMask
);
253 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
255 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.icon
.hicon
);
259 /************************************************************************
260 * OLEPictureImpl_Construct
262 * This method will construct a new instance of the OLEPictureImpl
265 * The caller of this method must release the object when it's
268 static HRESULT
OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
, OLEPictureImpl
**pict
)
270 OLEPictureImpl
*newObject
;
274 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
277 * Allocate space for the object.
279 newObject
= calloc(1, sizeof(OLEPictureImpl
));
281 return E_OUTOFMEMORY
;
284 * Initialize the virtual function table.
286 newObject
->IPicture_iface
.lpVtbl
= &OLEPictureImpl_VTable
;
287 newObject
->IDispatch_iface
.lpVtbl
= &OLEPictureImpl_IDispatch_VTable
;
288 newObject
->IPersistStream_iface
.lpVtbl
= &OLEPictureImpl_IPersistStream_VTable
;
289 newObject
->IConnectionPointContainer_iface
.lpVtbl
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
291 newObject
->pCP
= NULL
;
292 hr
= CreateConnectionPoint((IUnknown
*)&newObject
->IPicture_iface
, &IID_IPropertyNotifySink
,
301 * Start with one reference count. The caller of this function
302 * must release the interface pointer when it is done.
305 newObject
->hDCCur
= 0;
307 newObject
->fOwn
= fOwn
;
309 /* dunno about original value */
310 newObject
->keepOrigFormat
= TRUE
;
312 newObject
->hbmMask
= NULL
;
313 newObject
->hbmXor
= NULL
;
314 newObject
->loadtime_magic
= 0xdeadbeef;
315 newObject
->loadtime_format
= 0;
316 newObject
->bIsDirty
= FALSE
;
319 newObject
->desc
= *pictDesc
;
321 switch(pictDesc
->picType
) {
323 OLEPictureImpl_SetBitmap(newObject
);
326 case PICTYPE_METAFILE
:
327 TRACE("metafile handle %p\n", pictDesc
->wmf
.hmeta
);
328 newObject
->himetricWidth
= pictDesc
->wmf
.xExt
;
329 newObject
->himetricHeight
= pictDesc
->wmf
.yExt
;
333 /* not sure what to do here */
334 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
338 OLEPictureImpl_SetIcon(newObject
);
341 case PICTYPE_ENHMETAFILE
:
342 FIXME("EMF is not supported\n");
343 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
347 WARN("Unsupported type %d\n", pictDesc
->picType
);
348 IPicture_Release(&newObject
->IPicture_iface
);
352 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
355 TRACE("returning %p\n", newObject
);
360 /************************************************************************
361 * OLEPictureImpl_Destroy
363 * This method is called by the Release method when the reference
364 * count goes down to 0. It will free all resources used by
366 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
368 TRACE("(%p)\n", Obj
);
371 IConnectionPoint_Release(Obj
->pCP
);
373 if(Obj
->fOwn
) { /* We need to destroy the picture */
374 switch(Obj
->desc
.picType
) {
376 DeleteObject(Obj
->desc
.bmp
.hbitmap
);
377 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
378 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
380 case PICTYPE_METAFILE
:
381 DeleteMetaFile(Obj
->desc
.wmf
.hmeta
);
384 DestroyIcon(Obj
->desc
.icon
.hicon
);
386 case PICTYPE_ENHMETAFILE
:
387 DeleteEnhMetaFile(Obj
->desc
.emf
.hemf
);
390 case PICTYPE_UNINITIALIZED
:
394 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
402 static ULONG WINAPI
OLEPictureImpl_AddRef(
405 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
406 ULONG refCount
= InterlockedIncrement(&This
->ref
);
408 TRACE("%p, refcount %lu.\n", iface
, refCount
);
413 static ULONG WINAPI
OLEPictureImpl_Release(
416 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
417 ULONG refCount
= InterlockedDecrement(&This
->ref
);
419 TRACE("%p, refcount %lu.\n", iface
, refCount
);
421 if (!refCount
) OLEPictureImpl_Destroy(This
);
426 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
431 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
433 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
440 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
441 *ppvObject
= &This
->IPicture_iface
;
442 else if (IsEqualIID(&IID_IDispatch
, riid
))
443 *ppvObject
= &This
->IDispatch_iface
;
444 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
445 *ppvObject
= &This
->IDispatch_iface
;
446 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
447 *ppvObject
= &This
->IPersistStream_iface
;
448 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
449 *ppvObject
= &This
->IConnectionPointContainer_iface
;
453 FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
454 return E_NOINTERFACE
;
457 IPicture_AddRef(iface
);
462 /***********************************************************************
463 * OLEPicture_SendNotify (internal)
465 * Sends notification messages of changed properties to any interested
468 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
470 IEnumConnections
*pEnum
;
473 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
) != S_OK
)
475 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
476 IPropertyNotifySink
*sink
;
478 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
479 IPropertyNotifySink_OnChanged(sink
, dispID
);
480 IPropertyNotifySink_Release(sink
);
481 IUnknown_Release(CD
.pUnk
);
483 IEnumConnections_Release(pEnum
);
486 /************************************************************************
487 * OLEPictureImpl_get_Handle
489 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
492 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
493 TRACE("(%p)->(%p)\n", This
, phandle
);
498 switch(This
->desc
.picType
) {
500 case PICTYPE_UNINITIALIZED
:
504 *phandle
= HandleToUlong(This
->desc
.bmp
.hbitmap
);
506 case PICTYPE_METAFILE
:
507 *phandle
= HandleToUlong(This
->desc
.wmf
.hmeta
);
510 *phandle
= HandleToUlong(This
->desc
.icon
.hicon
);
512 case PICTYPE_ENHMETAFILE
:
513 *phandle
= HandleToUlong(This
->desc
.emf
.hemf
);
516 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
519 TRACE("returning handle %08x\n", *phandle
);
523 /************************************************************************
524 * OLEPictureImpl_get_hPal
526 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
529 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
531 TRACE("(%p)->(%p)\n", This
, phandle
);
533 if (!phandle
) return E_POINTER
;
535 if (This
->desc
.picType
== PICTYPE_BITMAP
)
537 *phandle
= HandleToUlong(This
->desc
.bmp
.hpal
);
544 /************************************************************************
545 * OLEPictureImpl_get_Type
547 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
550 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
551 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
556 *ptype
= This
->desc
.picType
;
560 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
, OLE_XSIZE_HIMETRIC
*pwidth
)
562 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
563 TRACE("%p, %p.\n", iface
, pwidth
);
564 *pwidth
= This
->himetricWidth
;
568 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
, OLE_YSIZE_HIMETRIC
*pheight
)
570 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
571 TRACE("%p, %p.\n", iface
, pheight
);
572 *pheight
= This
->himetricHeight
;
576 static void render_masked_bitmap(OLEPictureImpl
*This
, HDC hdc
,
577 LONG x
, LONG y
, LONG cx
, LONG cy
, OLE_XPOS_HIMETRIC xSrc
, OLE_YPOS_HIMETRIC ySrc
,
578 OLE_XSIZE_HIMETRIC cxSrc
, OLE_YSIZE_HIMETRIC cySrc
, HBITMAP hbmMask
, HBITMAP hbmXor
)
582 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
583 * NB y-axis gets flipped
586 hdcBmp
= CreateCompatibleDC(0);
587 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
588 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
589 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
590 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
591 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
595 SetBkColor(hdc
, RGB(255, 255, 255));
596 SetTextColor(hdc
, RGB(0, 0, 0));
598 SelectObject(hdcBmp
, hbmMask
);
599 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
603 SelectObject(hdcBmp
, hbmXor
);
604 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
606 else StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
- This
->himetricHeight
,
607 cxSrc
, cySrc
, SRCPAINT
);
611 SelectObject(hdcBmp
, hbmXor
);
612 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
618 /************************************************************************
619 * OLEPictureImpl_Render
621 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
622 LONG x
, LONG y
, LONG cx
, LONG cy
,
623 OLE_XPOS_HIMETRIC xSrc
,
624 OLE_YPOS_HIMETRIC ySrc
,
625 OLE_XSIZE_HIMETRIC cxSrc
,
626 OLE_YSIZE_HIMETRIC cySrc
,
629 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
630 TRACE("%p, %p, (%ld,%ld), (%ld,%ld), (%ld,%ld), (%ld,%ld), %p)\n", iface
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
,
631 cxSrc
, cySrc
, prcWBounds
);
633 TRACE("prcWBounds %s\n", wine_dbgstr_rect(prcWBounds
));
635 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
636 return CTL_E_INVALIDPROPERTYVALUE
;
640 * While the documentation suggests this to be here (or after rendering?)
641 * it does cause an endless recursion in my sample app. -MM 20010804
642 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
645 switch(This
->desc
.picType
) {
646 case PICTYPE_UNINITIALIZED
:
652 HBITMAP hbmMask
, hbmXor
;
656 hbmMask
= This
->hbmMask
;
657 hbmXor
= This
->hbmXor
;
662 hbmXor
= This
->desc
.bmp
.hbitmap
;
665 render_masked_bitmap(This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, hbmMask
, hbmXor
);
673 if (!GetIconInfo(This
->desc
.icon
.hicon
, &info
))
676 render_masked_bitmap(This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, info
.hbmMask
, info
.hbmColor
);
678 DeleteObject(info
.hbmMask
);
679 if (info
.hbmColor
) DeleteObject(info
.hbmColor
);
683 case PICTYPE_METAFILE
:
685 POINT prevOrg
, prevWndOrg
;
686 SIZE prevExt
, prevWndExt
;
689 /* Render the WMF to the appropriate location by setting the
690 appropriate ratio between "device units" and "logical units" */
691 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
692 /* For the "source rectangle" the y-axis must be inverted */
693 SetWindowOrgEx(hdc
, xSrc
, This
->himetricHeight
-ySrc
, &prevWndOrg
);
694 SetWindowExtEx(hdc
, cxSrc
, -cySrc
, &prevWndExt
);
695 /* For the "destination rectangle" no inversion is necessary */
696 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
697 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
699 if (!PlayMetaFile(hdc
, This
->desc
.wmf
.hmeta
))
700 ERR("PlayMetaFile failed!\n");
702 /* We're done, restore the DC to the previous settings for converting
703 logical units to device units */
704 SetWindowExtEx(hdc
, prevWndExt
.cx
, prevWndExt
.cy
, NULL
);
705 SetWindowOrgEx(hdc
, prevWndOrg
.x
, prevWndOrg
.y
, NULL
);
706 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
707 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
708 SetMapMode(hdc
, oldmode
);
712 case PICTYPE_ENHMETAFILE
:
714 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
715 PlayEnhMetaFile(hdc
, This
->desc
.emf
.hemf
, &rc
);
720 FIXME("type %d not implemented\n", This
->desc
.picType
);
726 /************************************************************************
727 * OLEPictureImpl_set_hPal
729 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
732 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
734 TRACE("(%p)->(%08x)\n", This
, hpal
);
736 if (This
->desc
.picType
== PICTYPE_BITMAP
)
738 This
->desc
.bmp
.hpal
= ULongToHandle(hpal
);
739 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
746 /************************************************************************
747 * OLEPictureImpl_get_CurDC
749 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
752 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
753 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
754 if (phdc
) *phdc
= This
->hDCCur
;
758 /************************************************************************
759 * OLEPictureImpl_SelectPicture
761 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
764 OLE_HANDLE
*phbmpOut
)
766 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
767 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
768 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
770 *phdcOut
= This
->hDCCur
;
771 if (This
->hDCCur
) SelectObject(This
->hDCCur
,This
->stock_bitmap
);
772 if (hdcIn
) SelectObject(hdcIn
,This
->desc
.bmp
.hbitmap
);
773 This
->hDCCur
= hdcIn
;
775 *phbmpOut
= HandleToUlong(This
->desc
.bmp
.hbitmap
);
778 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
783 /************************************************************************
784 * OLEPictureImpl_get_KeepOriginalFormat
786 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
789 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
790 TRACE("(%p)->(%p)\n", This
, pfKeep
);
793 *pfKeep
= This
->keepOrigFormat
;
797 /************************************************************************
798 * OLEPictureImpl_put_KeepOriginalFormat
800 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
803 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
804 TRACE("(%p)->(%d)\n", This
, keep
);
805 This
->keepOrigFormat
= keep
;
806 /* FIXME: what DISPID notification here? */
810 /************************************************************************
811 * OLEPictureImpl_PictureChanged
813 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
815 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
816 TRACE("(%p)->()\n", This
);
817 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
818 This
->bIsDirty
= TRUE
;
822 /************************************************************************
823 * OLEPictureImpl_SaveAsFile
825 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
830 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
831 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
832 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
835 /************************************************************************
836 * OLEPictureImpl_get_Attributes
838 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
841 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
842 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
848 switch (This
->desc
.picType
) {
849 case PICTYPE_UNINITIALIZED
:
850 case PICTYPE_NONE
: break;
851 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
852 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
853 case PICTYPE_ENHMETAFILE
: /* fall through */
854 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
855 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
861 /************************************************************************
862 * IConnectionPointContainer
864 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
865 IConnectionPointContainer
* iface
,
869 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
871 return IPicture_QueryInterface(&This
->IPicture_iface
,riid
,ppvoid
);
874 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
875 IConnectionPointContainer
* iface
)
877 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
879 return IPicture_AddRef(&This
->IPicture_iface
);
882 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
883 IConnectionPointContainer
* iface
)
885 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
887 return IPicture_Release(&This
->IPicture_iface
);
890 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
891 IConnectionPointContainer
* iface
,
892 IEnumConnectionPoints
** ppEnum
)
894 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
896 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
900 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
901 IConnectionPointContainer
* iface
,
903 IConnectionPoint
**ppCP
)
905 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
906 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
910 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
911 return IConnectionPoint_QueryInterface(This
->pCP
, &IID_IConnectionPoint
, (void**)ppCP
);
912 FIXME("no connection point for %s\n",debugstr_guid(riid
));
913 return CONNECT_E_NOCONNECTION
;
917 /************************************************************************
921 /************************************************************************
922 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
924 * See Windows documentation for more details on IUnknown methods.
926 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
927 IPersistStream
* iface
,
931 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
933 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
936 /************************************************************************
937 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
939 * See Windows documentation for more details on IUnknown methods.
941 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
942 IPersistStream
* iface
)
944 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
946 return IPicture_AddRef(&This
->IPicture_iface
);
949 /************************************************************************
950 * OLEPictureImpl_IPersistStream_Release (IUnknown)
952 * See Windows documentation for more details on IUnknown methods.
954 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
955 IPersistStream
* iface
)
957 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
959 return IPicture_Release(&This
->IPicture_iface
);
962 /************************************************************************
963 * OLEPictureImpl_IPersistStream_GetClassID
965 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
966 IPersistStream
* iface
,CLSID
* pClassID
)
968 TRACE("(%p)\n", pClassID
);
969 *pClassID
= CLSID_StdPicture
;
973 /************************************************************************
974 * OLEPictureImpl_IPersistStream_IsDirty
976 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
977 IPersistStream
* iface
)
979 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
980 FIXME("(%p),stub!\n",This
);
984 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
986 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
987 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
990 /* Does not matter whether this is a coreheader or not, we only use
991 * components which are in both
994 This
->desc
.bmp
.hbitmap
= CreateDIBitmap(
1002 ReleaseDC(0, hdcref
);
1003 if (This
->desc
.bmp
.hbitmap
== 0)
1005 This
->desc
.picType
= PICTYPE_BITMAP
;
1006 OLEPictureImpl_SetBitmap(This
);
1010 static HRESULT
OLEPictureImpl_LoadWICSource(OLEPictureImpl
*This
, IWICBitmapSource
*src
)
1013 BITMAPINFOHEADER bih
;
1016 UINT stride
, buffersize
;
1019 IWICBitmapSource
*real_source
;
1021 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1022 BOOL has_alpha
=FALSE
;
1024 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
, src
, &real_source
);
1025 if (FAILED(hr
)) return hr
;
1027 hr
= IWICBitmapSource_GetSize(real_source
, &width
, &height
);
1028 if (FAILED(hr
)) goto end
;
1030 bih
.biSize
= sizeof(bih
);
1031 bih
.biWidth
= width
;
1032 bih
.biHeight
= -height
;
1034 bih
.biBitCount
= 32;
1035 bih
.biCompression
= BI_RGB
;
1036 bih
.biSizeImage
= 0;
1037 bih
.biXPelsPerMeter
= 4085; /* olepicture ignores the stored resolution */
1038 bih
.biYPelsPerMeter
= 4085;
1040 bih
.biClrImportant
= 0;
1043 buffersize
= stride
* height
;
1045 bits
= malloc(buffersize
);
1056 hr
= IWICBitmapSource_CopyPixels(real_source
, &rc
, stride
, buffersize
, bits
);
1061 This
->desc
.bmp
.hbitmap
= CreateDIBitmap(
1069 if (This
->desc
.bmp
.hbitmap
== 0)
1072 ReleaseDC(0, hdcref
);
1076 This
->desc
.picType
= PICTYPE_BITMAP
;
1077 OLEPictureImpl_SetBitmap(This
);
1079 /* set transparent pixels to black, all others to white */
1080 for(y
= 0; y
< height
; y
++){
1081 for(x
= 0; x
< width
; x
++){
1082 DWORD
*pixel
= (DWORD
*)(bits
+ stride
*y
+ 4*x
);
1083 if((*pixel
& 0x80000000) == 0)
1095 HDC hdcBmp
, hdcXor
, hdcMask
;
1096 HBITMAP hbmoldBmp
, hbmoldXor
, hbmoldMask
;
1098 This
->hbmXor
= CreateDIBitmap(
1107 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1108 hdcBmp
= CreateCompatibleDC(NULL
);
1109 hdcXor
= CreateCompatibleDC(NULL
);
1110 hdcMask
= CreateCompatibleDC(NULL
);
1112 hbmoldBmp
= SelectObject(hdcBmp
,This
->desc
.bmp
.hbitmap
);
1113 hbmoldXor
= SelectObject(hdcXor
,This
->hbmXor
);
1114 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1116 SetBkColor(hdcXor
,black
);
1117 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1118 BitBlt(hdcXor
,0,0,width
,height
,hdcBmp
,0,0,SRCAND
);
1120 SelectObject(hdcBmp
,hbmoldBmp
);
1121 SelectObject(hdcXor
,hbmoldXor
);
1122 SelectObject(hdcMask
,hbmoldMask
);
1129 ReleaseDC(0, hdcref
);
1133 IWICBitmapSource_Release(real_source
);
1137 static HRESULT
OLEPictureImpl_LoadWICDecoder(OLEPictureImpl
*This
, REFCLSID decoder_clsid
, BYTE
*xbuf
, ULONG xread
)
1140 IWICImagingFactory
*factory
;
1141 IWICBitmapDecoder
*decoder
;
1142 IWICBitmapFrameDecode
*framedecode
;
1146 initresult
= CoInitialize(NULL
);
1148 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
1149 &IID_IWICImagingFactory
, (void**)&factory
);
1150 if (SUCCEEDED(hr
)) /* created factory */
1152 hr
= IWICImagingFactory_CreateStream(factory
, &stream
);
1153 IWICImagingFactory_Release(factory
);
1156 if (SUCCEEDED(hr
)) /* created stream */
1158 hr
= IWICStream_InitializeFromMemory(stream
, xbuf
, xread
);
1160 if (SUCCEEDED(hr
)) /* initialized stream */
1162 hr
= CoCreateInstance(decoder_clsid
, NULL
, CLSCTX_INPROC_SERVER
,
1163 &IID_IWICBitmapDecoder
, (void**)&decoder
);
1164 if (SUCCEEDED(hr
)) /* created decoder */
1166 hr
= IWICBitmapDecoder_Initialize(decoder
, (IStream
*)stream
, WICDecodeMetadataCacheOnLoad
);
1168 if (SUCCEEDED(hr
)) /* initialized decoder */
1169 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
1171 IWICBitmapDecoder_Release(decoder
);
1175 IWICStream_Release(stream
);
1178 if (SUCCEEDED(hr
)) /* got framedecode */
1180 hr
= OLEPictureImpl_LoadWICSource(This
, (IWICBitmapSource
*)framedecode
);
1181 IWICBitmapFrameDecode_Release(framedecode
);
1184 if (SUCCEEDED(initresult
)) CoUninitialize();
1188 /*****************************************************
1189 * start of Icon-specific code
1192 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1195 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1199 TRACE("(this %p, xbuf %p, xread %lu)\n", This
, xbuf
, xread
);
1202 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1203 FIXME("icon.idType=%d\n",cifd->idType);
1204 FIXME("icon.idCount=%d\n",cifd->idCount);
1206 for (i=0;i<cifd->idCount;i++) {
1207 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1208 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1209 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1210 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1211 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1212 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1213 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1214 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1218 /* Need at least one icon to do something. */
1221 ERR("Invalid icon count of zero.\n");
1225 /* If we have more than one icon, try to find the best.
1226 * this currently means '32 pixel wide'.
1228 if (cifd
->idCount
!=1) {
1229 for (i
=0;i
<cifd
->idCount
;i
++) {
1230 if (cifd
->idEntries
[i
].bWidth
== 32)
1233 if (i
==cifd
->idCount
) i
=0;
1235 if (xread
< cifd
->idEntries
[i
].dwDIBOffset
+ cifd
->idEntries
[i
].dwDIBSize
)
1237 ERR("Icon data address %lu is over %lu bytes available.\n",
1238 cifd
->idEntries
[i
].dwDIBOffset
+ cifd
->idEntries
[i
].dwDIBSize
, xread
);
1241 if (cifd
->idType
== 2)
1243 BYTE
*buf
= malloc(cifd
->idEntries
[i
].dwDIBSize
+ 4);
1244 memcpy(buf
, &cifd
->idEntries
[i
].xHotspot
, 4);
1245 memcpy(buf
+ 4, xbuf
+cifd
->idEntries
[i
].dwDIBOffset
, cifd
->idEntries
[i
].dwDIBSize
);
1246 hicon
= CreateIconFromResourceEx(
1248 cifd
->idEntries
[i
].dwDIBSize
+ 4,
1249 FALSE
, /* is cursor */
1251 cifd
->idEntries
[i
].bWidth
,
1252 cifd
->idEntries
[i
].bHeight
,
1259 hicon
= CreateIconFromResourceEx(
1260 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1261 cifd
->idEntries
[i
].dwDIBSize
,
1264 cifd
->idEntries
[i
].bWidth
,
1265 cifd
->idEntries
[i
].bHeight
,
1270 ERR("CreateIcon failed.\n");
1273 This
->desc
.picType
= PICTYPE_ICON
;
1274 This
->desc
.icon
.hicon
= hicon
;
1275 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1276 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1277 hdcRef
= CreateCompatibleDC(0);
1278 This
->himetricWidth
= xpixels_to_himetric(cifd
->idEntries
[i
].bWidth
, hdcRef
);
1279 This
->himetricHeight
= ypixels_to_himetric(cifd
->idEntries
[i
].bHeight
, hdcRef
);
1285 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1286 const BYTE
*data
, ULONG size
)
1291 hemf
= SetEnhMetaFileBits(size
, data
);
1292 if (!hemf
) return E_FAIL
;
1294 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1296 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1297 This
->desc
.emf
.hemf
= hemf
;
1299 This
->origWidth
= 0;
1300 This
->origHeight
= 0;
1301 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1302 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1307 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1308 const BYTE
*data
, ULONG size
)
1310 const APM_HEADER
*header
= (const APM_HEADER
*)data
;
1313 if (size
< sizeof(APM_HEADER
))
1315 if (header
->key
!= 0x9ac6cdd7)
1318 /* SetMetaFileBitsEx performs data check on its own */
1319 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1320 if (!hmf
) return E_FAIL
;
1322 This
->desc
.picType
= PICTYPE_METAFILE
;
1323 This
->desc
.wmf
.hmeta
= hmf
;
1324 This
->desc
.wmf
.xExt
= 0;
1325 This
->desc
.wmf
.yExt
= 0;
1327 This
->origWidth
= 0;
1328 This
->origHeight
= 0;
1329 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1330 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1334 /************************************************************************
1335 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1337 * Loads the binary data from the IStream. Starts at current position.
1338 * There appears to be an 2 DWORD header:
1342 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
1344 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
, IStream
*pStm
) {
1347 BOOL statfailed
= FALSE
;
1348 ULONG xread
, toread
;
1354 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1356 TRACE("(%p,%p)\n",This
,pStm
);
1358 /****************************************************************************************
1359 * Part 1: Load the data
1361 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1362 * out whether we do.
1364 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1365 * compound file. This may explain most, if not all, of the cases of "no
1366 * header", and the header validation should take this into account.
1367 * At least in Visual Basic 6, resource streams, valid headers are
1368 * header[0] == "lt\0\0",
1369 * header[1] == length_of_stream.
1371 * Also handle streams where we do not have a working "Stat" method by
1372 * reading all data until the end of the stream.
1374 hr
= IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1376 TRACE("stat failed with hres %#lx, proceeding to read all data.\n",hr
);
1378 /* we will read at least 8 byte ... just right below */
1379 statstg
.cbSize
.QuadPart
= 8;
1384 headerisdata
= FALSE
;
1386 hr
= IStream_Read(pStm
, header
, 8, &xread
);
1387 if (hr
!= S_OK
|| xread
!=8) {
1388 ERR("Failure while reading picture header (hr is %#lx, nread is %ld).\n",hr
,xread
);
1389 return (hr
?hr
:E_FAIL
);
1391 headerread
+= xread
;
1394 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1395 if (toread
!= 0 && toread
!= header
[1])
1396 FIXME("varying lengths of image data (prev=%lu curr=%lu), only last one will be used\n",
1401 statstg
.cbSize
.QuadPart
= header
[1] + 8;
1404 if (toread
== 0) break;
1406 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1407 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1408 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1409 (header
[0] == EMR_HEADER
) || /* EMF header */
1410 (header
[0] == 0x10000) || /* icon: idReserved 0, idType 1 */
1411 (header
[0] == 0x20000) || /* cursor: idReserved 0, idType 2 */
1412 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1414 ) {/* Found start of bitmap data */
1415 headerisdata
= TRUE
;
1417 toread
= statstg
.cbSize
.QuadPart
-8;
1421 FIXME("Unknown stream header magic: %#lx.\n", header
[0]);
1425 } while (!headerisdata
);
1427 if (statfailed
) { /* we don't know the size ... read all we get */
1428 unsigned int sizeinc
= 4096;
1429 unsigned int origsize
= sizeinc
;
1432 TRACE("Reading all data from stream.\n");
1433 xbuf
= calloc(1, origsize
);
1435 memcpy (xbuf
, header
, 8);
1437 while (xread
< origsize
) {
1438 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1440 if (hr
!= S_OK
|| !nread
)
1443 if (!nread
|| hr
!= S_OK
) /* done, or error */
1445 if (xread
== origsize
) {
1446 sizeinc
= 2*sizeinc
; /* exponential increase */
1447 xbuf
= realloc(xbuf
, origsize
+ sizeinc
);
1448 memset(xbuf
+ origsize
, 0, sizeinc
);
1449 origsize
+= sizeinc
;
1453 TRACE("hr in no-stat loader case is %#lx.\n", hr
);
1454 TRACE("loaded %ld bytes.\n", xread
);
1455 This
->datalen
= xread
;
1458 This
->datalen
= toread
+(headerisdata
?8:0);
1459 xbuf
= This
->data
= calloc(1, This
->datalen
);
1461 return E_OUTOFMEMORY
;
1464 memcpy (xbuf
, header
, 8);
1466 while (xread
< This
->datalen
) {
1468 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1470 if (hr
!= S_OK
|| !nread
)
1473 if (xread
!= This
->datalen
)
1474 ERR("Could only read %ld of %d bytes out of stream?\n", xread
, This
->datalen
);
1476 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1477 This
->desc
.picType
= PICTYPE_NONE
;
1482 /****************************************************************************************
1483 * Part 2: Process the loaded data
1486 magic
= xbuf
[0] + (xbuf
[1]<<8);
1487 This
->loadtime_format
= magic
;
1490 case BITMAP_FORMAT_GIF
: /* GIF */
1491 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICGifDecoder
, xbuf
, xread
);
1493 case BITMAP_FORMAT_JPEG
: /* JPEG */
1494 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICJpegDecoder
, xbuf
, xread
);
1496 case BITMAP_FORMAT_BMP
: /* Bitmap */
1497 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1499 case BITMAP_FORMAT_PNG
: /* PNG */
1500 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICPngDecoder
, xbuf
, xread
);
1502 case BITMAP_FORMAT_APM
: /* APM */
1503 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1505 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1506 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1513 /* let's see if it's a EMF */
1514 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1515 if (hr
== S_OK
) break;
1517 FIXME("Unknown magic %04x, %ld read bytes:\n", magic
, xread
);
1519 for (i
=0;i
<xread
+8;i
++) {
1520 if (i
<8) FIXME("%02x ",((unsigned char*)header
)[i
]);
1521 else FIXME("%02x ",xbuf
[i
-8]);
1522 if (i
% 10 == 9) FIXME("\n");
1528 This
->bIsDirty
= FALSE
;
1530 /* FIXME: this notify is not really documented */
1532 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1536 /* pass NULL buffer to fetch size */
1537 static HRESULT
serializeBMP(HBITMAP hbmp
, void **buffer
, unsigned int *length
)
1539 char infobuf
[sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
)] = { 0 };
1540 BITMAPINFO
*info
= (BITMAPINFO
*)infobuf
;
1542 BITMAPFILEHEADER
*filehdr
;
1546 unsigned char *data
= NULL
;
1548 /* Find out bitmap size and padded length */
1550 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1551 if (!GetDIBits(hdc
, hbmp
, 0, 0, NULL
, info
, DIB_RGB_COLORS
)) {
1556 /* Calculate the total length required for the BMP data */
1557 if (info
->bmiHeader
.biClrUsed
!= 0) {
1558 numentries
= info
->bmiHeader
.biClrUsed
;
1559 if (numentries
> 256)
1562 if (info
->bmiHeader
.biBitCount
<= 8)
1563 numentries
= 1 << info
->bmiHeader
.biBitCount
;
1569 sizeof(BITMAPFILEHEADER
) +
1570 sizeof(BITMAPINFOHEADER
) +
1571 numentries
* sizeof(RGBQUAD
) +
1572 info
->bmiHeader
.biSizeImage
;
1577 /* Fetch bitmap palette & pixel data */
1578 if (!(data
= malloc(info
->bmiHeader
.biSizeImage
))) {
1583 if (!GetDIBits(hdc
, hbmp
, 0, info
->bmiHeader
.biHeight
, data
, info
, DIB_RGB_COLORS
)) {
1588 if (!(*buffer
= malloc(*length
))) {
1593 /* Fill the BITMAPFILEHEADER */
1595 filehdr
->bfType
= BITMAP_FORMAT_BMP
;
1596 filehdr
->bfSize
= *length
;
1597 filehdr
->bfOffBits
=
1598 sizeof(BITMAPFILEHEADER
) +
1599 sizeof(BITMAPINFOHEADER
) +
1600 numentries
* sizeof(RGBQUAD
);
1602 /* Fill the BITMAPINFOHEADER and the palette data */
1603 bitmap
= (BITMAPINFO
*)((unsigned char *)(*buffer
) + sizeof(BITMAPFILEHEADER
));
1604 memcpy(bitmap
, info
, sizeof(BITMAPINFOHEADER
) + numentries
* sizeof(RGBQUAD
));
1605 memcpy((unsigned char *)(*buffer
) + filehdr
->bfOffBits
, data
, bitmap
->bmiHeader
.biSizeImage
);
1613 static BOOL
serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1616 BOOL success
= FALSE
;
1618 *ppBuffer
= NULL
; *pLength
= 0;
1619 if (GetIconInfo(hIcon
, &infoIcon
)) {
1621 BITMAPINFO
* pInfoBitmap
;
1622 unsigned char * pIconData
= NULL
;
1623 unsigned int iDataSize
= 0;
1625 pInfoBitmap
= calloc(1, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1627 /* Find out icon size */
1629 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1630 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1632 /* Auxiliary pointers */
1633 CURSORICONFILEDIR
* pIconDir
;
1634 CURSORICONFILEDIRENTRY
* pIconEntry
;
1635 BITMAPINFOHEADER
* pIconBitmapHeader
;
1636 unsigned int iOffsetPalette
;
1637 unsigned int iOffsetColorData
;
1638 unsigned int iOffsetMaskData
;
1640 unsigned int iLengthScanLineMask
;
1641 unsigned int iNumEntriesPalette
;
1643 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1645 FIXME("DEBUG: bitmap size is %d x %d\n",
1646 pInfoBitmap->bmiHeader.biWidth,
1647 pInfoBitmap->bmiHeader.biHeight);
1648 FIXME("DEBUG: bitmap bpp is %d\n",
1649 pInfoBitmap->bmiHeader.biBitCount);
1650 FIXME("DEBUG: bitmap nplanes is %d\n",
1651 pInfoBitmap->bmiHeader.biPlanes);
1652 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1653 pInfoBitmap->bmiHeader.biSizeImage);
1655 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1656 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1657 pIconData
= calloc(1, iDataSize
);
1659 /* Fill out the CURSORICONFILEDIR */
1660 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1661 pIconDir
->idType
= 1;
1662 pIconDir
->idCount
= 1;
1663 pIconDir
->idReserved
= 0;
1665 /* Fill out the CURSORICONFILEDIRENTRY */
1666 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1667 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1668 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1669 pIconEntry
->bColorCount
=
1670 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1671 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1673 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1674 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1675 pIconEntry
->dwDIBSize
= 0;
1676 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1678 /* Fill out the BITMAPINFOHEADER */
1679 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1680 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
1682 /* Find out whether a palette exists for the bitmap */
1683 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1684 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1685 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1686 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1687 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1688 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1689 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1690 iNumEntriesPalette
= 3;
1691 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1692 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1694 iNumEntriesPalette
= 0;
1697 /* Add bitmap size and header size to icon data size. */
1698 iOffsetPalette
= iDataSize
;
1699 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1700 iOffsetColorData
= iDataSize
;
1701 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1702 iOffsetMaskData
= iDataSize
;
1703 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1704 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1705 pIconBitmapHeader
->biHeight
*= 2;
1706 pIconData
= realloc(pIconData
, iDataSize
);
1707 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1708 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1709 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1711 /* Get the actual bitmap data from the icon bitmap */
1712 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1713 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1714 if (iNumEntriesPalette
> 0) {
1715 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1716 iNumEntriesPalette
* sizeof(RGBQUAD
));
1719 /* Reset all values so that GetDIBits call succeeds */
1720 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1721 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1722 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1724 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1725 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1726 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1728 printf("ERROR: unable to get bitmap mask (error %u)\n",
1733 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1734 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1736 /* Write out everything produced so far to the stream */
1737 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1741 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1746 Remarks (from MSDN entry on GetIconInfo):
1748 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1749 members of ICONINFO. The calling application must manage
1750 these bitmaps and delete them when they are no longer
1753 if (hDC
) ReleaseDC(0, hDC
);
1754 DeleteObject(infoIcon
.hbmMask
);
1755 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1758 ERR("Unable to get icon information (error %lu)\n", GetLastError());
1763 static HRESULT WINAPI
OLEPictureImpl_Save(
1764 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1766 HRESULT hResult
= E_NOTIMPL
;
1768 unsigned int iDataSize
;
1771 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1773 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
1775 switch (This
->desc
.picType
) {
1777 header
[0] = 0x0000746c;
1779 hResult
= IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1783 if (This
->bIsDirty
|| !This
->data
) {
1784 if (!serializeIcon(This
->desc
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1785 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
1790 This
->data
= pIconData
;
1791 This
->datalen
= iDataSize
;
1794 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1795 header
[1] = This
->datalen
;
1796 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1797 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1800 case PICTYPE_BITMAP
:
1801 if (This
->bIsDirty
|| !This
->data
) {
1802 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
1803 case BITMAP_FORMAT_BMP
:
1804 hResult
= serializeBMP(This
->desc
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1806 case BITMAP_FORMAT_JPEG
:
1807 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1809 case BITMAP_FORMAT_GIF
:
1810 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1812 case BITMAP_FORMAT_PNG
:
1813 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
1816 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1820 if (hResult
!= S_OK
)
1824 This
->data
= pIconData
;
1825 This
->datalen
= iDataSize
;
1828 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1829 header
[1] = This
->datalen
;
1830 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1831 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1834 case PICTYPE_METAFILE
:
1835 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1837 case PICTYPE_ENHMETAFILE
:
1838 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1841 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1844 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1848 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(IPersistStream
*iface
, ULARGE_INTEGER
*size
)
1850 HRESULT hr
= E_NOTIMPL
;
1851 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1852 unsigned int datasize
= This
->datalen
;
1854 FIXME("(%p,%p), partial stub!\n", This
, size
);
1857 return E_INVALIDARG
;
1859 switch (This
->desc
.picType
) {
1864 FIXME("(%p), PICTYPE_ICON not implemented!\n",This
);
1866 case PICTYPE_BITMAP
:
1867 if (This
->bIsDirty
|| !This
->data
) {
1868 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
1869 case BITMAP_FORMAT_BMP
:
1870 hr
= serializeBMP(This
->desc
.bmp
.hbitmap
, NULL
, &datasize
);
1872 case BITMAP_FORMAT_JPEG
:
1873 FIXME("(%p), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
);
1875 case BITMAP_FORMAT_GIF
:
1876 FIXME("(%p), PICTYPE_BITMAP (format GIF) not implemented!\n",This
);
1878 case BITMAP_FORMAT_PNG
:
1879 FIXME("(%p), PICTYPE_BITMAP (format PNG) not implemented!\n",This
);
1882 FIXME("(%p), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
);
1888 case PICTYPE_METAFILE
:
1889 FIXME("(%p), PICTYPE_METAFILE not implemented!\n",This
);
1891 case PICTYPE_ENHMETAFILE
:
1892 FIXME("(%p), PICTYPE_ENHMETAFILE not implemented!\n",This
);
1895 FIXME("(%p), [unknown type] not implemented!\n",This
);
1900 size
->LowPart
= datasize
+ 8;
1905 /************************************************************************
1909 /************************************************************************
1910 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1912 * See Windows documentation for more details on IUnknown methods.
1914 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1919 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1921 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
1924 /************************************************************************
1925 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1927 * See Windows documentation for more details on IUnknown methods.
1929 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1932 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1934 return IPicture_AddRef(&This
->IPicture_iface
);
1937 /************************************************************************
1938 * OLEPictureImpl_IDispatch_Release (IUnknown)
1940 * See Windows documentation for more details on IUnknown methods.
1942 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1945 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1947 return IPicture_Release(&This
->IPicture_iface
);
1950 /************************************************************************
1951 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1953 * See Windows documentation for more details on IDispatch methods.
1955 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1957 unsigned int* pctinfo
)
1959 TRACE("(%p)\n", pctinfo
);
1966 /************************************************************************
1967 * OLEPictureImpl_GetTypeInfo (IDispatch)
1969 * See Windows documentation for more details on IDispatch methods.
1971 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1975 ITypeInfo
** ppTInfo
)
1980 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
1985 hres
= LoadTypeLib(L
"stdole2.tlb", &tl
);
1988 ERR("Could not load stdole2.tlb\n");
1992 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
1994 ERR("Did not get IPictureDisp typeinfo from typelib, hres %#lx.\n", hres
);
1999 /************************************************************************
2000 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2002 * See Windows documentation for more details on IDispatch methods.
2004 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
2007 LPOLESTR
* rgszNames
,
2015 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
2016 rgszNames
, cNames
, (int)lcid
, rgDispId
);
2020 return E_INVALIDARG
;
2024 /* retrieve type information */
2025 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
2029 ERR("GetTypeInfo failed.\n");
2033 /* convert names to DISPIDs */
2034 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
2035 ITypeInfo_Release(pTInfo
);
2041 /************************************************************************
2042 * OLEPictureImpl_Invoke (IDispatch)
2044 * See Windows documentation for more details on IDispatch methods.
2046 static HRESULT WINAPI
OLEPictureImpl_Invoke(
2048 DISPID dispIdMember
,
2052 DISPPARAMS
* pDispParams
,
2053 VARIANT
* pVarResult
,
2054 EXCEPINFO
* pExepInfo
,
2057 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2060 /* validate parameters */
2062 if (!IsEqualIID(riid
, &IID_NULL
))
2064 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2065 return DISP_E_UNKNOWNNAME
;
2070 ERR("null pDispParams not allowed\n");
2071 return DISP_E_PARAMNOTOPTIONAL
;
2074 if (wFlags
& DISPATCH_PROPERTYGET
)
2076 if (pDispParams
->cArgs
!= 0)
2078 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2079 return DISP_E_BADPARAMCOUNT
;
2083 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2084 return DISP_E_PARAMNOTOPTIONAL
;
2087 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2089 if (pDispParams
->cArgs
!= 1)
2091 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2092 return DISP_E_BADPARAMCOUNT
;
2096 switch (dispIdMember
)
2098 case DISPID_PICT_HANDLE
:
2099 if (wFlags
& DISPATCH_PROPERTYGET
)
2101 TRACE("DISPID_PICT_HANDLE\n");
2102 V_VT(pVarResult
) = VT_I4
;
2103 return IPicture_get_Handle(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2106 case DISPID_PICT_HPAL
:
2107 if (wFlags
& DISPATCH_PROPERTYGET
)
2109 TRACE("DISPID_PICT_HPAL\n");
2110 V_VT(pVarResult
) = VT_I4
;
2111 return IPicture_get_hPal(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2113 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2117 TRACE("DISPID_PICT_HPAL\n");
2119 VariantInit(&vararg
);
2120 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2124 hr
= IPicture_set_hPal(&This
->IPicture_iface
, V_I4(&vararg
));
2126 VariantClear(&vararg
);
2130 case DISPID_PICT_TYPE
:
2131 if (wFlags
& DISPATCH_PROPERTYGET
)
2133 TRACE("DISPID_PICT_TYPE\n");
2134 V_VT(pVarResult
) = VT_I2
;
2135 return OLEPictureImpl_get_Type(&This
->IPicture_iface
, &V_I2(pVarResult
));
2138 case DISPID_PICT_WIDTH
:
2139 if (wFlags
& DISPATCH_PROPERTYGET
)
2141 TRACE("DISPID_PICT_WIDTH\n");
2142 V_VT(pVarResult
) = VT_I4
;
2143 return IPicture_get_Width(&This
->IPicture_iface
, &V_I4(pVarResult
));
2146 case DISPID_PICT_HEIGHT
:
2147 if (wFlags
& DISPATCH_PROPERTYGET
)
2149 TRACE("DISPID_PICT_HEIGHT\n");
2150 V_VT(pVarResult
) = VT_I4
;
2151 return IPicture_get_Height(&This
->IPicture_iface
, &V_I4(pVarResult
));
2154 case DISPID_PICT_RENDER
:
2155 if (wFlags
& DISPATCH_METHOD
)
2157 VARIANTARG
*args
= pDispParams
->rgvarg
;
2160 TRACE("DISPID_PICT_RENDER\n");
2162 if (pDispParams
->cArgs
!= 10)
2163 return DISP_E_BADPARAMCOUNT
;
2165 /* All parameters are supposed to be VT_I4 (on 64 bits too). */
2166 for (i
= 0; i
< pDispParams
->cArgs
; i
++)
2167 if (V_VT(&args
[i
]) != VT_I4
)
2169 ERR("DISPID_PICT_RENDER: wrong argument type %d:%d\n", i
, V_VT(&args
[i
]));
2170 return DISP_E_TYPEMISMATCH
;
2173 /* FIXME: rectangle pointer argument handling seems broken on 64 bits,
2174 currently Render() doesn't use it at all so for now NULL is passed. */
2175 return IPicture_Render(&This
->IPicture_iface
,
2176 LongToHandle(V_I4(&args
[9])),
2190 ERR("invalid dispid %#lx or wFlags 0x%x\n", dispIdMember
, wFlags
);
2191 return DISP_E_MEMBERNOTFOUND
;
2195 static const IPictureVtbl OLEPictureImpl_VTable
=
2197 OLEPictureImpl_QueryInterface
,
2198 OLEPictureImpl_AddRef
,
2199 OLEPictureImpl_Release
,
2200 OLEPictureImpl_get_Handle
,
2201 OLEPictureImpl_get_hPal
,
2202 OLEPictureImpl_get_Type
,
2203 OLEPictureImpl_get_Width
,
2204 OLEPictureImpl_get_Height
,
2205 OLEPictureImpl_Render
,
2206 OLEPictureImpl_set_hPal
,
2207 OLEPictureImpl_get_CurDC
,
2208 OLEPictureImpl_SelectPicture
,
2209 OLEPictureImpl_get_KeepOriginalFormat
,
2210 OLEPictureImpl_put_KeepOriginalFormat
,
2211 OLEPictureImpl_PictureChanged
,
2212 OLEPictureImpl_SaveAsFile
,
2213 OLEPictureImpl_get_Attributes
2216 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2218 OLEPictureImpl_IDispatch_QueryInterface
,
2219 OLEPictureImpl_IDispatch_AddRef
,
2220 OLEPictureImpl_IDispatch_Release
,
2221 OLEPictureImpl_GetTypeInfoCount
,
2222 OLEPictureImpl_GetTypeInfo
,
2223 OLEPictureImpl_GetIDsOfNames
,
2224 OLEPictureImpl_Invoke
2227 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2229 OLEPictureImpl_IPersistStream_QueryInterface
,
2230 OLEPictureImpl_IPersistStream_AddRef
,
2231 OLEPictureImpl_IPersistStream_Release
,
2232 OLEPictureImpl_GetClassID
,
2233 OLEPictureImpl_IsDirty
,
2234 OLEPictureImpl_Load
,
2235 OLEPictureImpl_Save
,
2236 OLEPictureImpl_GetSizeMax
2239 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2241 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2242 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2243 OLEPictureImpl_IConnectionPointContainer_Release
,
2244 OLEPictureImpl_EnumConnectionPoints
,
2245 OLEPictureImpl_FindConnectionPoint
2248 /***********************************************************************
2249 * OleCreatePictureIndirect (OLEAUT32.419)
2251 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2252 BOOL Own
, void **ppvObj
)
2254 OLEPictureImpl
* newPict
;
2257 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), Own
, ppvObj
);
2261 hr
= OLEPictureImpl_Construct(lpPictDesc
, Own
, &newPict
);
2262 if (hr
!= S_OK
) return hr
;
2265 * Make sure it supports the interface required by the caller.
2267 hr
= IPicture_QueryInterface(&newPict
->IPicture_iface
, riid
, ppvObj
);
2270 * Release the reference obtained in the constructor. If
2271 * the QueryInterface was unsuccessful, it will free the class.
2273 IPicture_Release(&newPict
->IPicture_iface
);
2279 /***********************************************************************
2280 * OleLoadPicture (OLEAUT32.418)
2282 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2283 REFIID riid
, LPVOID
*ppvObj
)
2289 TRACE("%p, %ld, %d, %s, %p), partially implemented.\n",
2290 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2292 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2295 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2297 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2298 IPicture_Release(newpic
);
2302 hr
= IPersistStream_Load(ps
,lpstream
);
2303 IPersistStream_Release(ps
);
2306 ERR("IPersistStream_Load failed\n");
2307 IPicture_Release(newpic
);
2311 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2313 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2314 IPicture_Release(newpic
);
2318 /***********************************************************************
2319 * OleLoadPictureEx (OLEAUT32.401)
2321 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2322 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2328 FIXME("%p, %ld, %d, %s, %lu, %lu, %#lx, %p, partially implemented.\n",
2329 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2331 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2334 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2336 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2337 IPicture_Release(newpic
);
2341 hr
= IPersistStream_Load(ps
,lpstream
);
2342 IPersistStream_Release(ps
);
2345 ERR("IPersistStream_Load failed\n");
2346 IPicture_Release(newpic
);
2350 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2352 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2353 IPicture_Release(newpic
);
2357 static HRESULT
create_stream(const WCHAR
*filename
, IStream
**stream
)
2361 HGLOBAL hGlobal
= NULL
;
2365 hFile
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
2366 if (hFile
== INVALID_HANDLE_VALUE
)
2367 return HRESULT_FROM_WIN32(GetLastError());
2369 dwFileSize
= GetFileSize(hFile
, NULL
);
2370 if (dwFileSize
!= INVALID_FILE_SIZE
)
2372 hGlobal
= GlobalAlloc(GMEM_FIXED
, dwFileSize
);
2377 if (!ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
))
2379 GlobalFree(hGlobal
);
2380 hr
= HRESULT_FROM_WIN32(GetLastError());
2387 if (FAILED(hr
)) return hr
;
2389 hr
= CreateStreamOnHGlobal(hGlobal
, TRUE
, stream
);
2391 GlobalFree(hGlobal
);
2396 /***********************************************************************
2397 * OleLoadPictureFile (OLEAUT32.422)
2399 HRESULT WINAPI
OleLoadPictureFile(VARIANT filename
, IDispatch
**picture
)
2404 TRACE("(%s,%p)\n", wine_dbgstr_variant(&filename
), picture
);
2406 if (V_VT(&filename
) != VT_BSTR
)
2407 return CTL_E_FILENOTFOUND
;
2409 hr
= create_stream(V_BSTR(&filename
), &stream
);
2412 if (hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
))
2413 return CTL_E_FILENOTFOUND
;
2415 return CTL_E_PATHFILEACCESSERROR
;
2418 hr
= OleLoadPicture(stream
, 0, FALSE
, &IID_IDispatch
, (void **)picture
);
2419 IStream_Release(stream
);
2423 /***********************************************************************
2424 * OleSavePictureFile (OLEAUT32.423)
2426 HRESULT WINAPI
OleSavePictureFile(IDispatch
*picture
, BSTR filename
)
2428 FIXME("(%p %s): stub\n", picture
, debugstr_w(filename
));
2429 return CTL_E_FILENOTFOUND
;
2432 /***********************************************************************
2433 * OleLoadPicturePath (OLEAUT32.424)
2435 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2436 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2441 WCHAR
*file_candidate
;
2442 WCHAR path_buf
[MAX_PATH
];
2444 TRACE("%s, %p, %ld, %#lx, %s, %p.\n", debugstr_w(szURLorPath
), punkCaller
, dwReserved
,
2445 clrReserved
, debugstr_guid(riid
), ppvRet
);
2447 if (!szURLorPath
|| !ppvRet
)
2448 return E_INVALIDARG
;
2452 /* Convert file URLs to DOS paths. */
2453 if (wcsncmp(szURLorPath
, L
"file:", 5) == 0) {
2455 hRes
= CoInternetParseUrl(szURLorPath
, PARSE_PATH_FROM_URL
, 0, path_buf
,
2456 ARRAY_SIZE(path_buf
), &size
, 0);
2460 file_candidate
= path_buf
;
2463 file_candidate
= szURLorPath
;
2465 /* Handle candidate DOS paths separately. */
2466 if (file_candidate
[1] == ':') {
2467 hRes
= create_stream(file_candidate
, &stream
);
2469 return INET_E_RESOURCE_NOT_FOUND
;
2474 hRes
= CreateBindCtx(0, &pbc
);
2475 if (SUCCEEDED(hRes
))
2477 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2478 if (SUCCEEDED(hRes
))
2480 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2481 IMoniker_Release(pmnk
);
2483 IBindCtx_Release(pbc
);
2489 hRes
= OleLoadPicture(stream
, 0, FALSE
, riid
, ppvRet
);
2491 IStream_Release(stream
);
2496 /*******************************************************************************
2497 * StdPic ClassFactory
2501 /* IUnknown fields */
2502 IClassFactory IClassFactory_iface
;
2504 } IClassFactoryImpl
;
2506 static inline IClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
2508 return CONTAINING_RECORD(iface
, IClassFactoryImpl
, IClassFactory_iface
);
2511 static HRESULT WINAPI
2512 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2513 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2515 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2516 return E_NOINTERFACE
;
2520 SPCF_AddRef(LPCLASSFACTORY iface
) {
2521 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2522 return InterlockedIncrement(&This
->ref
);
2525 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2526 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2527 /* static class, won't be freed */
2528 return InterlockedDecrement(&This
->ref
);
2531 static HRESULT WINAPI
SPCF_CreateInstance(
2532 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2534 /* Creates an uninitialized picture */
2535 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2539 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2540 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2541 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2545 static const IClassFactoryVtbl SPCF_Vtbl
= {
2546 SPCF_QueryInterface
,
2549 SPCF_CreateInstance
,
2552 static IClassFactoryImpl STDPIC_CF
= {{&SPCF_Vtbl
}, 1 };
2554 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= &STDPIC_CF
; }