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).
44 #define NONAMELESSUNION
58 #include "wine/debug.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(olepicture
);
62 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
63 #define BITMAP_FORMAT_JPEG 0xd8ff
64 #define BITMAP_FORMAT_GIF 0x4947
65 #define BITMAP_FORMAT_PNG 0x5089
66 #define BITMAP_FORMAT_APM 0xcdd7
70 /* Header for Aldus Placable Metafiles - a standard metafile follows */
71 typedef struct _APM_HEADER
93 } CURSORICONFILEDIRENTRY
;
100 CURSORICONFILEDIRENTRY idEntries
[1];
105 /*************************************************************************
106 * Declaration of implementation class
109 typedef struct OLEPictureImpl
{
112 * IPicture handles IUnknown
115 IPicture IPicture_iface
;
116 IDispatch IDispatch_iface
;
117 IPersistStream IPersistStream_iface
;
118 IConnectionPointContainer IConnectionPointContainer_iface
;
120 /* Object reference count */
123 /* We own the object and must destroy it ourselves */
126 /* Picture description */
129 /* These are the pixel size of a bitmap */
133 /* And these are the size of the picture converted into HIMETRIC units */
134 OLE_XSIZE_HIMETRIC himetricWidth
;
135 OLE_YSIZE_HIMETRIC himetricHeight
;
137 IConnectionPoint
*pCP
;
141 HBITMAP stock_bitmap
;
143 /* Bitmap transparency mask */
151 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
152 unsigned int loadtime_magic
; /* If a length header was found, saves value */
153 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
156 static inline OLEPictureImpl
*impl_from_IPicture(IPicture
*iface
)
158 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPicture_iface
);
161 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
163 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IDispatch_iface
);
166 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
168 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPersistStream_iface
);
171 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
173 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IConnectionPointContainer_iface
);
177 * Predeclare VTables. They get initialized at the end.
179 static const IPictureVtbl OLEPictureImpl_VTable
;
180 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
181 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
182 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
184 /* pixels to HIMETRIC units conversion */
185 static inline OLE_XSIZE_HIMETRIC
xpixels_to_himetric(INT pixels
, HDC hdc
)
187 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
190 static inline OLE_YSIZE_HIMETRIC
ypixels_to_himetric(INT pixels
, HDC hdc
)
192 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
195 /***********************************************************************
196 * Implementation of the OLEPictureImpl class.
199 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
)
204 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
205 if(GetObjectW(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
206 ERR("GetObject fails\n");
209 This
->origWidth
= bm
.bmWidth
;
210 This
->origHeight
= bm
.bmHeight
;
212 TRACE("width %d, height %d, bpp %d\n", bm
.bmWidth
, bm
.bmHeight
, bm
.bmBitsPixel
);
214 /* The width and height are stored in HIMETRIC units (0.01 mm),
215 so we take our pixel width divide by pixels per inch and
216 multiply by 25.4 * 100 */
217 /* Should we use GetBitmapDimension if available? */
218 hdcRef
= CreateCompatibleDC(0);
220 This
->himetricWidth
= xpixels_to_himetric(bm
.bmWidth
, hdcRef
);
221 This
->himetricHeight
= ypixels_to_himetric(bm
.bmHeight
, hdcRef
);
222 This
->stock_bitmap
= GetCurrentObject( hdcRef
, OBJ_BITMAP
);
224 This
->loadtime_format
= BITMAP_FORMAT_BMP
;
229 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
233 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
234 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
238 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
239 if(GetObjectW(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
240 ERR("GetObject fails on icon bitmap\n");
244 This
->origWidth
= bm
.bmWidth
;
245 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
246 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
249 This
->himetricWidth
= xpixels_to_himetric(This
->origWidth
, hdcRef
);
250 This
->himetricHeight
= ypixels_to_himetric(This
->origHeight
, hdcRef
);
252 ReleaseDC(0, hdcRef
);
254 DeleteObject(infoIcon
.hbmMask
);
255 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
257 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
261 /************************************************************************
262 * OLEPictureImpl_Construct
264 * This method will construct a new instance of the OLEPictureImpl
267 * The caller of this method must release the object when it's
270 static HRESULT
OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
, OLEPictureImpl
**pict
)
272 OLEPictureImpl
*newObject
;
276 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
279 * Allocate space for the object.
281 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
283 return E_OUTOFMEMORY
;
286 * Initialize the virtual function table.
288 newObject
->IPicture_iface
.lpVtbl
= &OLEPictureImpl_VTable
;
289 newObject
->IDispatch_iface
.lpVtbl
= &OLEPictureImpl_IDispatch_VTable
;
290 newObject
->IPersistStream_iface
.lpVtbl
= &OLEPictureImpl_IPersistStream_VTable
;
291 newObject
->IConnectionPointContainer_iface
.lpVtbl
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
293 newObject
->pCP
= NULL
;
294 hr
= CreateConnectionPoint((IUnknown
*)&newObject
->IPicture_iface
, &IID_IPropertyNotifySink
,
298 HeapFree(GetProcessHeap(), 0, newObject
);
303 * Start with one reference count. The caller of this function
304 * must release the interface pointer when it is done.
307 newObject
->hDCCur
= 0;
309 newObject
->fOwn
= fOwn
;
311 /* dunno about original value */
312 newObject
->keepOrigFormat
= TRUE
;
314 newObject
->hbmMask
= NULL
;
315 newObject
->hbmXor
= NULL
;
316 newObject
->loadtime_magic
= 0xdeadbeef;
317 newObject
->loadtime_format
= 0;
318 newObject
->bIsDirty
= FALSE
;
321 newObject
->desc
= *pictDesc
;
323 switch(pictDesc
->picType
) {
325 OLEPictureImpl_SetBitmap(newObject
);
328 case PICTYPE_METAFILE
:
329 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
330 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
331 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
335 /* not sure what to do here */
336 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
340 OLEPictureImpl_SetIcon(newObject
);
343 case PICTYPE_ENHMETAFILE
:
344 FIXME("EMF is not supported\n");
345 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
349 WARN("Unsupported type %d\n", pictDesc
->picType
);
350 IPicture_Release(&newObject
->IPicture_iface
);
354 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
357 TRACE("returning %p\n", newObject
);
362 /************************************************************************
363 * OLEPictureImpl_Destroy
365 * This method is called by the Release method when the reference
366 * count goes down to 0. It will free all resources used by
368 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
370 TRACE("(%p)\n", Obj
);
373 IConnectionPoint_Release(Obj
->pCP
);
375 if(Obj
->fOwn
) { /* We need to destroy the picture */
376 switch(Obj
->desc
.picType
) {
378 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
379 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
380 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
382 case PICTYPE_METAFILE
:
383 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
386 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
388 case PICTYPE_ENHMETAFILE
:
389 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
392 case PICTYPE_UNINITIALIZED
:
396 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
400 HeapFree(GetProcessHeap(), 0, Obj
->data
);
401 HeapFree(GetProcessHeap(), 0, Obj
);
405 /************************************************************************
406 * OLEPictureImpl_AddRef (IUnknown)
408 * See Windows documentation for more details on IUnknown methods.
410 static ULONG WINAPI
OLEPictureImpl_AddRef(
413 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
414 ULONG refCount
= InterlockedIncrement(&This
->ref
);
416 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
421 /************************************************************************
422 * OLEPictureImpl_Release (IUnknown)
424 * See Windows documentation for more details on IUnknown methods.
426 static ULONG WINAPI
OLEPictureImpl_Release(
429 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
430 ULONG refCount
= InterlockedDecrement(&This
->ref
);
432 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
435 * If the reference count goes down to 0, perform suicide.
437 if (!refCount
) OLEPictureImpl_Destroy(This
);
442 /************************************************************************
443 * OLEPictureImpl_QueryInterface (IUnknown)
445 * See Windows documentation for more details on IUnknown methods.
447 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
452 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
454 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
461 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
462 *ppvObject
= &This
->IPicture_iface
;
463 else if (IsEqualIID(&IID_IDispatch
, riid
))
464 *ppvObject
= &This
->IDispatch_iface
;
465 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
466 *ppvObject
= &This
->IDispatch_iface
;
467 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
468 *ppvObject
= &This
->IPersistStream_iface
;
469 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
470 *ppvObject
= &This
->IConnectionPointContainer_iface
;
474 FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
475 return E_NOINTERFACE
;
478 IPicture_AddRef(iface
);
483 /***********************************************************************
484 * OLEPicture_SendNotify (internal)
486 * Sends notification messages of changed properties to any interested
489 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
491 IEnumConnections
*pEnum
;
494 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
) != S_OK
)
496 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
497 IPropertyNotifySink
*sink
;
499 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
500 IPropertyNotifySink_OnChanged(sink
, dispID
);
501 IPropertyNotifySink_Release(sink
);
502 IUnknown_Release(CD
.pUnk
);
504 IEnumConnections_Release(pEnum
);
507 /************************************************************************
508 * OLEPictureImpl_get_Handle
510 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
513 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
514 TRACE("(%p)->(%p)\n", This
, phandle
);
519 switch(This
->desc
.picType
) {
521 case PICTYPE_UNINITIALIZED
:
525 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
527 case PICTYPE_METAFILE
:
528 *phandle
= HandleToUlong(This
->desc
.u
.wmf
.hmeta
);
531 *phandle
= HandleToUlong(This
->desc
.u
.icon
.hicon
);
533 case PICTYPE_ENHMETAFILE
:
534 *phandle
= HandleToUlong(This
->desc
.u
.emf
.hemf
);
537 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
540 TRACE("returning handle %08x\n", *phandle
);
544 /************************************************************************
545 * OLEPictureImpl_get_hPal
547 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
550 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
552 TRACE("(%p)->(%p)\n", This
, phandle
);
554 if (!phandle
) return E_POINTER
;
556 if (This
->desc
.picType
== PICTYPE_BITMAP
)
558 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hpal
);
565 /************************************************************************
566 * OLEPictureImpl_get_Type
568 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
571 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
572 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
577 *ptype
= This
->desc
.picType
;
581 /************************************************************************
582 * OLEPictureImpl_get_Width
584 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
585 OLE_XSIZE_HIMETRIC
*pwidth
)
587 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
588 TRACE("(%p)->(%p): width is %d\n", This
, pwidth
, This
->himetricWidth
);
589 *pwidth
= This
->himetricWidth
;
593 /************************************************************************
594 * OLEPictureImpl_get_Height
596 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
597 OLE_YSIZE_HIMETRIC
*pheight
)
599 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
600 TRACE("(%p)->(%p): height is %d\n", This
, pheight
, This
->himetricHeight
);
601 *pheight
= This
->himetricHeight
;
605 static void render_masked_bitmap(OLEPictureImpl
*This
, HDC hdc
,
606 LONG x
, LONG y
, LONG cx
, LONG cy
, OLE_XPOS_HIMETRIC xSrc
, OLE_YPOS_HIMETRIC ySrc
,
607 OLE_XSIZE_HIMETRIC cxSrc
, OLE_YSIZE_HIMETRIC cySrc
, HBITMAP hbmMask
, HBITMAP hbmXor
)
611 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
612 * NB y-axis gets flipped
615 hdcBmp
= CreateCompatibleDC(0);
616 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
617 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
618 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
619 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
620 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
624 SetBkColor(hdc
, RGB(255, 255, 255));
625 SetTextColor(hdc
, RGB(0, 0, 0));
627 SelectObject(hdcBmp
, hbmMask
);
628 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
632 SelectObject(hdcBmp
, hbmXor
);
633 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
635 else StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
- This
->himetricHeight
,
636 cxSrc
, cySrc
, SRCPAINT
);
640 SelectObject(hdcBmp
, hbmXor
);
641 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
647 /************************************************************************
648 * OLEPictureImpl_Render
650 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
651 LONG x
, LONG y
, LONG cx
, LONG cy
,
652 OLE_XPOS_HIMETRIC xSrc
,
653 OLE_YPOS_HIMETRIC ySrc
,
654 OLE_XSIZE_HIMETRIC cxSrc
,
655 OLE_YSIZE_HIMETRIC cySrc
,
658 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
659 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
660 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
662 TRACE("prcWBounds %s\n", wine_dbgstr_rect(prcWBounds
));
664 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
665 return CTL_E_INVALIDPROPERTYVALUE
;
669 * While the documentation suggests this to be here (or after rendering?)
670 * it does cause an endless recursion in my sample app. -MM 20010804
671 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
674 switch(This
->desc
.picType
) {
675 case PICTYPE_UNINITIALIZED
:
681 HBITMAP hbmMask
, hbmXor
;
685 hbmMask
= This
->hbmMask
;
686 hbmXor
= This
->hbmXor
;
691 hbmXor
= This
->desc
.u
.bmp
.hbitmap
;
694 render_masked_bitmap(This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, hbmMask
, hbmXor
);
702 if (!GetIconInfo(This
->desc
.u
.icon
.hicon
, &info
))
705 render_masked_bitmap(This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, info
.hbmMask
, info
.hbmColor
);
707 DeleteObject(info
.hbmMask
);
708 if (info
.hbmColor
) DeleteObject(info
.hbmColor
);
712 case PICTYPE_METAFILE
:
714 POINT prevOrg
, prevWndOrg
;
715 SIZE prevExt
, prevWndExt
;
718 /* Render the WMF to the appropriate location by setting the
719 appropriate ratio between "device units" and "logical units" */
720 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
721 /* For the "source rectangle" the y-axis must be inverted */
722 SetWindowOrgEx(hdc
, xSrc
, This
->himetricHeight
-ySrc
, &prevWndOrg
);
723 SetWindowExtEx(hdc
, cxSrc
, -cySrc
, &prevWndExt
);
724 /* For the "destination rectangle" no inversion is necessary */
725 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
726 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
728 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
729 ERR("PlayMetaFile failed!\n");
731 /* We're done, restore the DC to the previous settings for converting
732 logical units to device units */
733 SetWindowExtEx(hdc
, prevWndExt
.cx
, prevWndExt
.cy
, NULL
);
734 SetWindowOrgEx(hdc
, prevWndOrg
.x
, prevWndOrg
.y
, NULL
);
735 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
736 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
737 SetMapMode(hdc
, oldmode
);
741 case PICTYPE_ENHMETAFILE
:
743 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
744 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
749 FIXME("type %d not implemented\n", This
->desc
.picType
);
755 /************************************************************************
756 * OLEPictureImpl_set_hPal
758 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
761 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
763 TRACE("(%p)->(%08x)\n", This
, hpal
);
765 if (This
->desc
.picType
== PICTYPE_BITMAP
)
767 This
->desc
.u
.bmp
.hpal
= ULongToHandle(hpal
);
768 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
775 /************************************************************************
776 * OLEPictureImpl_get_CurDC
778 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
781 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
782 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
783 if (phdc
) *phdc
= This
->hDCCur
;
787 /************************************************************************
788 * OLEPictureImpl_SelectPicture
790 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
793 OLE_HANDLE
*phbmpOut
)
795 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
796 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
797 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
799 *phdcOut
= This
->hDCCur
;
800 if (This
->hDCCur
) SelectObject(This
->hDCCur
,This
->stock_bitmap
);
801 if (hdcIn
) SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
802 This
->hDCCur
= hdcIn
;
804 *phbmpOut
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
807 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
812 /************************************************************************
813 * OLEPictureImpl_get_KeepOriginalFormat
815 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
818 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
819 TRACE("(%p)->(%p)\n", This
, pfKeep
);
822 *pfKeep
= This
->keepOrigFormat
;
826 /************************************************************************
827 * OLEPictureImpl_put_KeepOriginalFormat
829 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
832 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
833 TRACE("(%p)->(%d)\n", This
, keep
);
834 This
->keepOrigFormat
= keep
;
835 /* FIXME: what DISPID notification here? */
839 /************************************************************************
840 * OLEPictureImpl_PictureChanged
842 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
844 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
845 TRACE("(%p)->()\n", This
);
846 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
847 This
->bIsDirty
= TRUE
;
851 /************************************************************************
852 * OLEPictureImpl_SaveAsFile
854 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
859 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
860 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
861 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
864 /************************************************************************
865 * OLEPictureImpl_get_Attributes
867 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
870 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
871 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
877 switch (This
->desc
.picType
) {
878 case PICTYPE_UNINITIALIZED
:
879 case PICTYPE_NONE
: break;
880 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
881 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
882 case PICTYPE_ENHMETAFILE
: /* fall through */
883 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
884 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
890 /************************************************************************
891 * IConnectionPointContainer
893 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
894 IConnectionPointContainer
* iface
,
898 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
900 return IPicture_QueryInterface(&This
->IPicture_iface
,riid
,ppvoid
);
903 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
904 IConnectionPointContainer
* iface
)
906 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
908 return IPicture_AddRef(&This
->IPicture_iface
);
911 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
912 IConnectionPointContainer
* iface
)
914 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
916 return IPicture_Release(&This
->IPicture_iface
);
919 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
920 IConnectionPointContainer
* iface
,
921 IEnumConnectionPoints
** ppEnum
)
923 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
925 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
929 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
930 IConnectionPointContainer
* iface
,
932 IConnectionPoint
**ppCP
)
934 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
935 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
939 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
940 return IConnectionPoint_QueryInterface(This
->pCP
, &IID_IConnectionPoint
, (void**)ppCP
);
941 FIXME("no connection point for %s\n",debugstr_guid(riid
));
942 return CONNECT_E_NOCONNECTION
;
946 /************************************************************************
950 /************************************************************************
951 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
953 * See Windows documentation for more details on IUnknown methods.
955 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
956 IPersistStream
* iface
,
960 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
962 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
965 /************************************************************************
966 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
968 * See Windows documentation for more details on IUnknown methods.
970 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
971 IPersistStream
* iface
)
973 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
975 return IPicture_AddRef(&This
->IPicture_iface
);
978 /************************************************************************
979 * OLEPictureImpl_IPersistStream_Release (IUnknown)
981 * See Windows documentation for more details on IUnknown methods.
983 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
984 IPersistStream
* iface
)
986 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
988 return IPicture_Release(&This
->IPicture_iface
);
991 /************************************************************************
992 * OLEPictureImpl_IPersistStream_GetClassID
994 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
995 IPersistStream
* iface
,CLSID
* pClassID
)
997 TRACE("(%p)\n", pClassID
);
998 *pClassID
= CLSID_StdPicture
;
1002 /************************************************************************
1003 * OLEPictureImpl_IPersistStream_IsDirty
1005 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
1006 IPersistStream
* iface
)
1008 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1009 FIXME("(%p),stub!\n",This
);
1013 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1015 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1016 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1019 /* Does not matter whether this is a coreheader or not, we only use
1020 * components which are in both
1023 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1027 xbuf
+bfh
->bfOffBits
,
1031 ReleaseDC(0, hdcref
);
1032 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1034 This
->desc
.picType
= PICTYPE_BITMAP
;
1035 OLEPictureImpl_SetBitmap(This
);
1039 static HRESULT
OLEPictureImpl_LoadWICSource(OLEPictureImpl
*This
, IWICBitmapSource
*src
)
1042 BITMAPINFOHEADER bih
;
1045 UINT stride
, buffersize
;
1048 IWICBitmapSource
*real_source
;
1050 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1051 BOOL has_alpha
=FALSE
;
1053 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
, src
, &real_source
);
1054 if (FAILED(hr
)) return hr
;
1056 hr
= IWICBitmapSource_GetSize(real_source
, &width
, &height
);
1057 if (FAILED(hr
)) goto end
;
1059 bih
.biSize
= sizeof(bih
);
1060 bih
.biWidth
= width
;
1061 bih
.biHeight
= -height
;
1063 bih
.biBitCount
= 32;
1064 bih
.biCompression
= BI_RGB
;
1065 bih
.biSizeImage
= 0;
1066 bih
.biXPelsPerMeter
= 4085; /* olepicture ignores the stored resolution */
1067 bih
.biYPelsPerMeter
= 4085;
1069 bih
.biClrImportant
= 0;
1072 buffersize
= stride
* height
;
1074 bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
1085 hr
= IWICBitmapSource_CopyPixels(real_source
, &rc
, stride
, buffersize
, bits
);
1090 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1098 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1101 ReleaseDC(0, hdcref
);
1105 This
->desc
.picType
= PICTYPE_BITMAP
;
1106 OLEPictureImpl_SetBitmap(This
);
1108 /* set transparent pixels to black, all others to white */
1109 for(y
= 0; y
< height
; y
++){
1110 for(x
= 0; x
< width
; x
++){
1111 DWORD
*pixel
= (DWORD
*)(bits
+ stride
*y
+ 4*x
);
1112 if((*pixel
& 0x80000000) == 0)
1124 HDC hdcBmp
, hdcXor
, hdcMask
;
1125 HBITMAP hbmoldBmp
, hbmoldXor
, hbmoldMask
;
1127 This
->hbmXor
= CreateDIBitmap(
1136 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1137 hdcBmp
= CreateCompatibleDC(NULL
);
1138 hdcXor
= CreateCompatibleDC(NULL
);
1139 hdcMask
= CreateCompatibleDC(NULL
);
1141 hbmoldBmp
= SelectObject(hdcBmp
,This
->desc
.u
.bmp
.hbitmap
);
1142 hbmoldXor
= SelectObject(hdcXor
,This
->hbmXor
);
1143 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1145 SetBkColor(hdcXor
,black
);
1146 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1147 BitBlt(hdcXor
,0,0,width
,height
,hdcBmp
,0,0,SRCAND
);
1149 SelectObject(hdcBmp
,hbmoldBmp
);
1150 SelectObject(hdcXor
,hbmoldXor
);
1151 SelectObject(hdcMask
,hbmoldMask
);
1158 ReleaseDC(0, hdcref
);
1161 HeapFree(GetProcessHeap(), 0, bits
);
1162 IWICBitmapSource_Release(real_source
);
1166 static HRESULT
OLEPictureImpl_LoadWICDecoder(OLEPictureImpl
*This
, REFCLSID decoder_clsid
, BYTE
*xbuf
, ULONG xread
)
1169 IWICImagingFactory
*factory
;
1170 IWICBitmapDecoder
*decoder
;
1171 IWICBitmapFrameDecode
*framedecode
;
1175 initresult
= CoInitialize(NULL
);
1177 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
1178 &IID_IWICImagingFactory
, (void**)&factory
);
1179 if (SUCCEEDED(hr
)) /* created factory */
1181 hr
= IWICImagingFactory_CreateStream(factory
, &stream
);
1182 IWICImagingFactory_Release(factory
);
1185 if (SUCCEEDED(hr
)) /* created stream */
1187 hr
= IWICStream_InitializeFromMemory(stream
, xbuf
, xread
);
1189 if (SUCCEEDED(hr
)) /* initialized stream */
1191 hr
= CoCreateInstance(decoder_clsid
, NULL
, CLSCTX_INPROC_SERVER
,
1192 &IID_IWICBitmapDecoder
, (void**)&decoder
);
1193 if (SUCCEEDED(hr
)) /* created decoder */
1195 hr
= IWICBitmapDecoder_Initialize(decoder
, (IStream
*)stream
, WICDecodeMetadataCacheOnLoad
);
1197 if (SUCCEEDED(hr
)) /* initialized decoder */
1198 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
1200 IWICBitmapDecoder_Release(decoder
);
1204 IWICStream_Release(stream
);
1207 if (SUCCEEDED(hr
)) /* got framedecode */
1209 hr
= OLEPictureImpl_LoadWICSource(This
, (IWICBitmapSource
*)framedecode
);
1210 IWICBitmapFrameDecode_Release(framedecode
);
1213 if (SUCCEEDED(initresult
)) CoUninitialize();
1217 /*****************************************************
1218 * start of Icon-specific code
1221 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1224 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1228 TRACE("(this %p, xbuf %p, xread %u)\n", This
, xbuf
, xread
);
1231 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1232 FIXME("icon.idType=%d\n",cifd->idType);
1233 FIXME("icon.idCount=%d\n",cifd->idCount);
1235 for (i=0;i<cifd->idCount;i++) {
1236 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1237 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1238 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1239 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1240 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1241 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1242 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1243 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1247 /* Need at least one icon to do something. */
1250 ERR("Invalid icon count of zero.\n");
1254 /* If we have more than one icon, try to find the best.
1255 * this currently means '32 pixel wide'.
1257 if (cifd
->idCount
!=1) {
1258 for (i
=0;i
<cifd
->idCount
;i
++) {
1259 if (cifd
->idEntries
[i
].bWidth
== 32)
1262 if (i
==cifd
->idCount
) i
=0;
1264 if (xread
< cifd
->idEntries
[i
].dwDIBOffset
+ cifd
->idEntries
[i
].dwDIBSize
)
1266 ERR("Icon data address %u is over %u bytes available.\n",
1267 cifd
->idEntries
[i
].dwDIBOffset
+ cifd
->idEntries
[i
].dwDIBSize
, xread
);
1270 if (cifd
->idType
== 2)
1272 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, cifd
->idEntries
[i
].dwDIBSize
+ 4);
1273 memcpy(buf
, &cifd
->idEntries
[i
].xHotspot
, 4);
1274 memcpy(buf
+ 4, xbuf
+cifd
->idEntries
[i
].dwDIBOffset
, cifd
->idEntries
[i
].dwDIBSize
);
1275 hicon
= CreateIconFromResourceEx(
1277 cifd
->idEntries
[i
].dwDIBSize
+ 4,
1278 FALSE
, /* is cursor */
1280 cifd
->idEntries
[i
].bWidth
,
1281 cifd
->idEntries
[i
].bHeight
,
1284 HeapFree(GetProcessHeap(), 0, buf
);
1288 hicon
= CreateIconFromResourceEx(
1289 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1290 cifd
->idEntries
[i
].dwDIBSize
,
1293 cifd
->idEntries
[i
].bWidth
,
1294 cifd
->idEntries
[i
].bHeight
,
1299 ERR("CreateIcon failed.\n");
1302 This
->desc
.picType
= PICTYPE_ICON
;
1303 This
->desc
.u
.icon
.hicon
= hicon
;
1304 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1305 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1306 hdcRef
= CreateCompatibleDC(0);
1307 This
->himetricWidth
= xpixels_to_himetric(cifd
->idEntries
[i
].bWidth
, hdcRef
);
1308 This
->himetricHeight
= ypixels_to_himetric(cifd
->idEntries
[i
].bHeight
, hdcRef
);
1314 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1315 const BYTE
*data
, ULONG size
)
1320 hemf
= SetEnhMetaFileBits(size
, data
);
1321 if (!hemf
) return E_FAIL
;
1323 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1325 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1326 This
->desc
.u
.emf
.hemf
= hemf
;
1328 This
->origWidth
= 0;
1329 This
->origHeight
= 0;
1330 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1331 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1336 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1337 const BYTE
*data
, ULONG size
)
1339 const APM_HEADER
*header
= (const APM_HEADER
*)data
;
1342 if (size
< sizeof(APM_HEADER
))
1344 if (header
->key
!= 0x9ac6cdd7)
1347 /* SetMetaFileBitsEx performs data check on its own */
1348 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1349 if (!hmf
) return E_FAIL
;
1351 This
->desc
.picType
= PICTYPE_METAFILE
;
1352 This
->desc
.u
.wmf
.hmeta
= hmf
;
1353 This
->desc
.u
.wmf
.xExt
= 0;
1354 This
->desc
.u
.wmf
.yExt
= 0;
1356 This
->origWidth
= 0;
1357 This
->origHeight
= 0;
1358 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1359 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1363 /************************************************************************
1364 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1366 * Loads the binary data from the IStream. Starts at current position.
1367 * There appears to be an 2 DWORD header:
1371 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
1373 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
, IStream
*pStm
) {
1376 BOOL statfailed
= FALSE
;
1377 ULONG xread
, toread
;
1383 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1385 TRACE("(%p,%p)\n",This
,pStm
);
1387 /****************************************************************************************
1388 * Part 1: Load the data
1390 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1391 * out whether we do.
1393 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1394 * compound file. This may explain most, if not all, of the cases of "no
1395 * header", and the header validation should take this into account.
1396 * At least in Visual Basic 6, resource streams, valid headers are
1397 * header[0] == "lt\0\0",
1398 * header[1] == length_of_stream.
1400 * Also handle streams where we do not have a working "Stat" method by
1401 * reading all data until the end of the stream.
1403 hr
= IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1405 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr
);
1407 /* we will read at least 8 byte ... just right below */
1408 statstg
.cbSize
.QuadPart
= 8;
1413 headerisdata
= FALSE
;
1415 hr
= IStream_Read(pStm
, header
, 8, &xread
);
1416 if (hr
!= S_OK
|| xread
!=8) {
1417 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr
,xread
);
1418 return (hr
?hr
:E_FAIL
);
1420 headerread
+= xread
;
1423 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1424 if (toread
!= 0 && toread
!= header
[1])
1425 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1430 statstg
.cbSize
.QuadPart
= header
[1] + 8;
1433 if (toread
== 0) break;
1435 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1436 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1437 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1438 (header
[0] == EMR_HEADER
) || /* EMF header */
1439 (header
[0] == 0x10000) || /* icon: idReserved 0, idType 1 */
1440 (header
[0] == 0x20000) || /* cursor: idReserved 0, idType 2 */
1441 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1443 ) {/* Found start of bitmap data */
1444 headerisdata
= TRUE
;
1446 toread
= statstg
.cbSize
.QuadPart
-8;
1450 FIXME("Unknown stream header magic: %08x\n", header
[0]);
1454 } while (!headerisdata
);
1456 if (statfailed
) { /* we don't know the size ... read all we get */
1457 unsigned int sizeinc
= 4096;
1458 unsigned int origsize
= sizeinc
;
1461 TRACE("Reading all data from stream.\n");
1462 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1464 memcpy (xbuf
, header
, 8);
1466 while (xread
< origsize
) {
1467 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1469 if (hr
!= S_OK
|| !nread
)
1472 if (!nread
|| hr
!= S_OK
) /* done, or error */
1474 if (xread
== origsize
) {
1475 origsize
+= sizeinc
;
1476 sizeinc
= 2*sizeinc
; /* exponential increase */
1477 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1481 TRACE("hr in no-stat loader case is %08x\n", hr
);
1482 TRACE("loaded %d bytes.\n", xread
);
1483 This
->datalen
= xread
;
1486 This
->datalen
= toread
+(headerisdata
?8:0);
1487 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1489 return E_OUTOFMEMORY
;
1492 memcpy (xbuf
, header
, 8);
1494 while (xread
< This
->datalen
) {
1496 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1498 if (hr
!= S_OK
|| !nread
)
1501 if (xread
!= This
->datalen
)
1502 ERR("Could only read %d of %d bytes out of stream?\n",xread
,This
->datalen
);
1504 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1505 This
->desc
.picType
= PICTYPE_NONE
;
1510 /****************************************************************************************
1511 * Part 2: Process the loaded data
1514 magic
= xbuf
[0] + (xbuf
[1]<<8);
1515 This
->loadtime_format
= magic
;
1518 case BITMAP_FORMAT_GIF
: /* GIF */
1519 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICGifDecoder
, xbuf
, xread
);
1521 case BITMAP_FORMAT_JPEG
: /* JPEG */
1522 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICJpegDecoder
, xbuf
, xread
);
1524 case BITMAP_FORMAT_BMP
: /* Bitmap */
1525 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1527 case BITMAP_FORMAT_PNG
: /* PNG */
1528 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICPngDecoder
, xbuf
, xread
);
1530 case BITMAP_FORMAT_APM
: /* APM */
1531 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1533 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1534 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1541 /* let's see if it's a EMF */
1542 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1543 if (hr
== S_OK
) break;
1545 FIXME("Unknown magic %04x, %d read bytes:\n",magic
,xread
);
1547 for (i
=0;i
<xread
+8;i
++) {
1548 if (i
<8) MESSAGE("%02x ",((unsigned char*)header
)[i
]);
1549 else MESSAGE("%02x ",xbuf
[i
-8]);
1550 if (i
% 10 == 9) MESSAGE("\n");
1556 This
->bIsDirty
= FALSE
;
1558 /* FIXME: this notify is not really documented */
1560 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1564 static BOOL
serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1566 BOOL success
= FALSE
;
1568 BITMAPINFO
* pInfoBitmap
;
1569 int iNumPaletteEntries
;
1570 unsigned char * pPixelData
;
1571 BITMAPFILEHEADER
* pFileHeader
;
1572 BITMAPINFO
* pInfoHeader
;
1574 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1575 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1577 /* Find out bitmap size and padded length */
1579 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1580 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1582 /* Fetch bitmap palette & pixel data */
1584 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1585 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1587 /* Calculate the total length required for the BMP data */
1588 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1589 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1590 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1592 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1593 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1595 iNumPaletteEntries
= 0;
1598 sizeof(BITMAPFILEHEADER
) +
1599 sizeof(BITMAPINFOHEADER
) +
1600 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1601 pInfoBitmap
->bmiHeader
.biSizeImage
;
1602 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1604 /* Fill the BITMAPFILEHEADER */
1605 pFileHeader
= *ppBuffer
;
1606 pFileHeader
->bfType
= BITMAP_FORMAT_BMP
;
1607 pFileHeader
->bfSize
= *pLength
;
1608 pFileHeader
->bfOffBits
=
1609 sizeof(BITMAPFILEHEADER
) +
1610 sizeof(BITMAPINFOHEADER
) +
1611 iNumPaletteEntries
* sizeof(RGBQUAD
);
1613 /* Fill the BITMAPINFOHEADER and the palette data */
1614 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1615 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1617 (unsigned char *)(*ppBuffer
) +
1618 sizeof(BITMAPFILEHEADER
) +
1619 sizeof(BITMAPINFOHEADER
) +
1620 iNumPaletteEntries
* sizeof(RGBQUAD
),
1621 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1624 HeapFree(GetProcessHeap(), 0, pPixelData
);
1625 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1629 static BOOL
serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1632 BOOL success
= FALSE
;
1634 *ppBuffer
= NULL
; *pLength
= 0;
1635 if (GetIconInfo(hIcon
, &infoIcon
)) {
1637 BITMAPINFO
* pInfoBitmap
;
1638 unsigned char * pIconData
= NULL
;
1639 unsigned int iDataSize
= 0;
1641 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1643 /* Find out icon size */
1645 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1646 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1648 /* Auxiliary pointers */
1649 CURSORICONFILEDIR
* pIconDir
;
1650 CURSORICONFILEDIRENTRY
* pIconEntry
;
1651 BITMAPINFOHEADER
* pIconBitmapHeader
;
1652 unsigned int iOffsetPalette
;
1653 unsigned int iOffsetColorData
;
1654 unsigned int iOffsetMaskData
;
1656 unsigned int iLengthScanLineMask
;
1657 unsigned int iNumEntriesPalette
;
1659 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1661 FIXME("DEBUG: bitmap size is %d x %d\n",
1662 pInfoBitmap->bmiHeader.biWidth,
1663 pInfoBitmap->bmiHeader.biHeight);
1664 FIXME("DEBUG: bitmap bpp is %d\n",
1665 pInfoBitmap->bmiHeader.biBitCount);
1666 FIXME("DEBUG: bitmap nplanes is %d\n",
1667 pInfoBitmap->bmiHeader.biPlanes);
1668 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1669 pInfoBitmap->bmiHeader.biSizeImage);
1671 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1672 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1673 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1675 /* Fill out the CURSORICONFILEDIR */
1676 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1677 pIconDir
->idType
= 1;
1678 pIconDir
->idCount
= 1;
1679 pIconDir
->idReserved
= 0;
1681 /* Fill out the CURSORICONFILEDIRENTRY */
1682 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1683 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1684 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1685 pIconEntry
->bColorCount
=
1686 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1687 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1689 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1690 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1691 pIconEntry
->dwDIBSize
= 0;
1692 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1694 /* Fill out the BITMAPINFOHEADER */
1695 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1696 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
1698 /* Find out whether a palette exists for the bitmap */
1699 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1700 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1701 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1702 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1703 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1704 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1705 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1706 iNumEntriesPalette
= 3;
1707 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1708 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1710 iNumEntriesPalette
= 0;
1713 /* Add bitmap size and header size to icon data size. */
1714 iOffsetPalette
= iDataSize
;
1715 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1716 iOffsetColorData
= iDataSize
;
1717 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1718 iOffsetMaskData
= iDataSize
;
1719 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1720 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1721 pIconBitmapHeader
->biHeight
*= 2;
1722 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1723 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1724 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1725 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1727 /* Get the actual bitmap data from the icon bitmap */
1728 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1729 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1730 if (iNumEntriesPalette
> 0) {
1731 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1732 iNumEntriesPalette
* sizeof(RGBQUAD
));
1735 /* Reset all values so that GetDIBits call succeeds */
1736 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1737 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1738 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1740 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1741 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1742 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1744 printf("ERROR: unable to get bitmap mask (error %u)\n",
1749 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1750 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1752 /* Write out everything produced so far to the stream */
1753 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1757 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1762 Remarks (from MSDN entry on GetIconInfo):
1764 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1765 members of ICONINFO. The calling application must manage
1766 these bitmaps and delete them when they are no longer
1769 if (hDC
) ReleaseDC(0, hDC
);
1770 DeleteObject(infoIcon
.hbmMask
);
1771 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1772 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1774 printf("ERROR: Unable to get icon information (error %u)\n",
1780 static HRESULT WINAPI
OLEPictureImpl_Save(
1781 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1783 HRESULT hResult
= E_NOTIMPL
;
1785 unsigned int iDataSize
;
1788 BOOL serializeResult
= FALSE
;
1789 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1791 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
1793 switch (This
->desc
.picType
) {
1795 header
[0] = 0x0000746c;
1797 hResult
= IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1801 if (This
->bIsDirty
|| !This
->data
) {
1802 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1803 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
1807 HeapFree(GetProcessHeap(), 0, This
->data
);
1808 This
->data
= pIconData
;
1809 This
->datalen
= iDataSize
;
1812 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1813 header
[1] = This
->datalen
;
1814 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1815 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1818 case PICTYPE_BITMAP
:
1819 if (This
->bIsDirty
|| !This
->data
) {
1820 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
1821 case BITMAP_FORMAT_BMP
:
1822 serializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1824 case BITMAP_FORMAT_JPEG
:
1825 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1827 case BITMAP_FORMAT_GIF
:
1828 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1830 case BITMAP_FORMAT_PNG
:
1831 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
1834 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1838 if (!serializeResult
)
1844 HeapFree(GetProcessHeap(), 0, This
->data
);
1845 This
->data
= pIconData
;
1846 This
->datalen
= iDataSize
;
1849 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1850 header
[1] = This
->datalen
;
1851 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1852 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1855 case PICTYPE_METAFILE
:
1856 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1858 case PICTYPE_ENHMETAFILE
:
1859 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1862 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1865 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1869 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1870 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1872 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1873 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1878 /************************************************************************
1882 /************************************************************************
1883 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1885 * See Windows documentation for more details on IUnknown methods.
1887 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1892 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1894 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
1897 /************************************************************************
1898 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1900 * See Windows documentation for more details on IUnknown methods.
1902 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1905 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1907 return IPicture_AddRef(&This
->IPicture_iface
);
1910 /************************************************************************
1911 * OLEPictureImpl_IDispatch_Release (IUnknown)
1913 * See Windows documentation for more details on IUnknown methods.
1915 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1918 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1920 return IPicture_Release(&This
->IPicture_iface
);
1923 /************************************************************************
1924 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1926 * See Windows documentation for more details on IDispatch methods.
1928 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1930 unsigned int* pctinfo
)
1932 TRACE("(%p)\n", pctinfo
);
1939 /************************************************************************
1940 * OLEPictureImpl_GetTypeInfo (IDispatch)
1942 * See Windows documentation for more details on IDispatch methods.
1944 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1948 ITypeInfo
** ppTInfo
)
1950 static const WCHAR stdole2tlb
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1954 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
1959 hres
= LoadTypeLib(stdole2tlb
, &tl
);
1962 ERR("Could not load stdole2.tlb\n");
1966 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
1968 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres
);
1973 /************************************************************************
1974 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1976 * See Windows documentation for more details on IDispatch methods.
1978 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1981 LPOLESTR
* rgszNames
,
1989 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
1990 rgszNames
, cNames
, (int)lcid
, rgDispId
);
1994 return E_INVALIDARG
;
1998 /* retrieve type information */
1999 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
2003 ERR("GetTypeInfo failed.\n");
2007 /* convert names to DISPIDs */
2008 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
2009 ITypeInfo_Release(pTInfo
);
2015 /************************************************************************
2016 * OLEPictureImpl_Invoke (IDispatch)
2018 * See Windows documentation for more details on IDispatch methods.
2020 static HRESULT WINAPI
OLEPictureImpl_Invoke(
2022 DISPID dispIdMember
,
2026 DISPPARAMS
* pDispParams
,
2027 VARIANT
* pVarResult
,
2028 EXCEPINFO
* pExepInfo
,
2031 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2034 /* validate parameters */
2036 if (!IsEqualIID(riid
, &IID_NULL
))
2038 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2039 return DISP_E_UNKNOWNNAME
;
2044 ERR("null pDispParams not allowed\n");
2045 return DISP_E_PARAMNOTOPTIONAL
;
2048 if (wFlags
& DISPATCH_PROPERTYGET
)
2050 if (pDispParams
->cArgs
!= 0)
2052 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2053 return DISP_E_BADPARAMCOUNT
;
2057 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2058 return DISP_E_PARAMNOTOPTIONAL
;
2061 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2063 if (pDispParams
->cArgs
!= 1)
2065 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2066 return DISP_E_BADPARAMCOUNT
;
2070 switch (dispIdMember
)
2072 case DISPID_PICT_HANDLE
:
2073 if (wFlags
& DISPATCH_PROPERTYGET
)
2075 TRACE("DISPID_PICT_HANDLE\n");
2076 V_VT(pVarResult
) = VT_I4
;
2077 return IPicture_get_Handle(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2080 case DISPID_PICT_HPAL
:
2081 if (wFlags
& DISPATCH_PROPERTYGET
)
2083 TRACE("DISPID_PICT_HPAL\n");
2084 V_VT(pVarResult
) = VT_I4
;
2085 return IPicture_get_hPal(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2087 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2091 TRACE("DISPID_PICT_HPAL\n");
2093 VariantInit(&vararg
);
2094 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2098 hr
= IPicture_set_hPal(&This
->IPicture_iface
, V_I4(&vararg
));
2100 VariantClear(&vararg
);
2104 case DISPID_PICT_TYPE
:
2105 if (wFlags
& DISPATCH_PROPERTYGET
)
2107 TRACE("DISPID_PICT_TYPE\n");
2108 V_VT(pVarResult
) = VT_I2
;
2109 return OLEPictureImpl_get_Type(&This
->IPicture_iface
, &V_I2(pVarResult
));
2112 case DISPID_PICT_WIDTH
:
2113 if (wFlags
& DISPATCH_PROPERTYGET
)
2115 TRACE("DISPID_PICT_WIDTH\n");
2116 V_VT(pVarResult
) = VT_I4
;
2117 return IPicture_get_Width(&This
->IPicture_iface
, &V_I4(pVarResult
));
2120 case DISPID_PICT_HEIGHT
:
2121 if (wFlags
& DISPATCH_PROPERTYGET
)
2123 TRACE("DISPID_PICT_HEIGHT\n");
2124 V_VT(pVarResult
) = VT_I4
;
2125 return IPicture_get_Height(&This
->IPicture_iface
, &V_I4(pVarResult
));
2128 case DISPID_PICT_RENDER
:
2129 if (wFlags
& DISPATCH_METHOD
)
2131 VARIANTARG
*args
= pDispParams
->rgvarg
;
2134 TRACE("DISPID_PICT_RENDER\n");
2136 if (pDispParams
->cArgs
!= 10)
2137 return DISP_E_BADPARAMCOUNT
;
2139 /* All parameters are supposed to be VT_I4 (on 64 bits too). */
2140 for (i
= 0; i
< pDispParams
->cArgs
; i
++)
2141 if (V_VT(&args
[i
]) != VT_I4
)
2143 ERR("DISPID_PICT_RENDER: wrong argument type %d:%d\n", i
, V_VT(&args
[i
]));
2144 return DISP_E_TYPEMISMATCH
;
2147 /* FIXME: rectangle pointer argument handling seems broken on 64 bits,
2148 currently Render() doesn't use it at all so for now NULL is passed. */
2149 return IPicture_Render(&This
->IPicture_iface
,
2150 LongToHandle(V_I4(&args
[9])),
2164 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember
, wFlags
);
2165 return DISP_E_MEMBERNOTFOUND
;
2169 static const IPictureVtbl OLEPictureImpl_VTable
=
2171 OLEPictureImpl_QueryInterface
,
2172 OLEPictureImpl_AddRef
,
2173 OLEPictureImpl_Release
,
2174 OLEPictureImpl_get_Handle
,
2175 OLEPictureImpl_get_hPal
,
2176 OLEPictureImpl_get_Type
,
2177 OLEPictureImpl_get_Width
,
2178 OLEPictureImpl_get_Height
,
2179 OLEPictureImpl_Render
,
2180 OLEPictureImpl_set_hPal
,
2181 OLEPictureImpl_get_CurDC
,
2182 OLEPictureImpl_SelectPicture
,
2183 OLEPictureImpl_get_KeepOriginalFormat
,
2184 OLEPictureImpl_put_KeepOriginalFormat
,
2185 OLEPictureImpl_PictureChanged
,
2186 OLEPictureImpl_SaveAsFile
,
2187 OLEPictureImpl_get_Attributes
2190 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2192 OLEPictureImpl_IDispatch_QueryInterface
,
2193 OLEPictureImpl_IDispatch_AddRef
,
2194 OLEPictureImpl_IDispatch_Release
,
2195 OLEPictureImpl_GetTypeInfoCount
,
2196 OLEPictureImpl_GetTypeInfo
,
2197 OLEPictureImpl_GetIDsOfNames
,
2198 OLEPictureImpl_Invoke
2201 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2203 OLEPictureImpl_IPersistStream_QueryInterface
,
2204 OLEPictureImpl_IPersistStream_AddRef
,
2205 OLEPictureImpl_IPersistStream_Release
,
2206 OLEPictureImpl_GetClassID
,
2207 OLEPictureImpl_IsDirty
,
2208 OLEPictureImpl_Load
,
2209 OLEPictureImpl_Save
,
2210 OLEPictureImpl_GetSizeMax
2213 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2215 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2216 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2217 OLEPictureImpl_IConnectionPointContainer_Release
,
2218 OLEPictureImpl_EnumConnectionPoints
,
2219 OLEPictureImpl_FindConnectionPoint
2222 /***********************************************************************
2223 * OleCreatePictureIndirect (OLEAUT32.419)
2225 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2226 BOOL Own
, void **ppvObj
)
2228 OLEPictureImpl
* newPict
;
2231 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), Own
, ppvObj
);
2235 hr
= OLEPictureImpl_Construct(lpPictDesc
, Own
, &newPict
);
2236 if (hr
!= S_OK
) return hr
;
2239 * Make sure it supports the interface required by the caller.
2241 hr
= IPicture_QueryInterface(&newPict
->IPicture_iface
, riid
, ppvObj
);
2244 * Release the reference obtained in the constructor. If
2245 * the QueryInterface was unsuccessful, it will free the class.
2247 IPicture_Release(&newPict
->IPicture_iface
);
2253 /***********************************************************************
2254 * OleLoadPicture (OLEAUT32.418)
2256 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2257 REFIID riid
, LPVOID
*ppvObj
)
2263 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2264 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2266 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2269 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2271 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2272 IPicture_Release(newpic
);
2276 hr
= IPersistStream_Load(ps
,lpstream
);
2277 IPersistStream_Release(ps
);
2280 ERR("IPersistStream_Load failed\n");
2281 IPicture_Release(newpic
);
2285 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2287 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2288 IPicture_Release(newpic
);
2292 /***********************************************************************
2293 * OleLoadPictureEx (OLEAUT32.401)
2295 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2296 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2302 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2303 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2305 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2308 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2310 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2311 IPicture_Release(newpic
);
2315 hr
= IPersistStream_Load(ps
,lpstream
);
2316 IPersistStream_Release(ps
);
2319 ERR("IPersistStream_Load failed\n");
2320 IPicture_Release(newpic
);
2324 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2326 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2327 IPicture_Release(newpic
);
2331 /***********************************************************************
2332 * OleLoadPictureFile (OLEAUT32.422)
2334 HRESULT WINAPI
OleLoadPictureFile(VARIANT file
, LPDISPATCH
*picture
)
2336 FIXME("(%s %p): stub\n", wine_dbgstr_variant(&file
), picture
);
2340 /***********************************************************************
2341 * OleSavePictureFile (OLEAUT32.423)
2343 HRESULT WINAPI
OleSavePictureFile(IDispatch
*picture
, BSTR filename
)
2345 FIXME("(%p %s): stub\n", picture
, debugstr_w(filename
));
2346 return CTL_E_FILENOTFOUND
;
2349 /***********************************************************************
2350 * OleLoadPicturePath (OLEAUT32.424)
2352 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2353 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2356 static const WCHAR file
[] = { 'f','i','l','e',':',0 };
2360 HGLOBAL hGlobal
= NULL
;
2364 IPersistStream
*pStream
;
2367 WCHAR
*file_candidate
;
2368 WCHAR path_buf
[MAX_PATH
];
2370 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2371 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2372 debugstr_guid(riid
), ppvRet
);
2374 if (!szURLorPath
|| !ppvRet
)
2375 return E_INVALIDARG
;
2379 /* Convert file URLs to DOS paths. */
2380 if (wcsncmp(szURLorPath
, file
, 5) == 0) {
2382 hRes
= CoInternetParseUrl(szURLorPath
, PARSE_PATH_FROM_URL
, 0, path_buf
,
2383 ARRAY_SIZE(path_buf
), &size
, 0);
2387 file_candidate
= path_buf
;
2390 file_candidate
= szURLorPath
;
2392 /* Handle candidate DOS paths separately. */
2393 if (file_candidate
[1] == ':') {
2394 hFile
= CreateFileW(file_candidate
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2396 if (hFile
== INVALID_HANDLE_VALUE
)
2397 return INET_E_RESOURCE_NOT_FOUND
;
2399 dwFileSize
= GetFileSize(hFile
, NULL
);
2400 if (dwFileSize
!= INVALID_FILE_SIZE
)
2402 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2405 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
) && dwBytesRead
== dwFileSize
;
2408 GlobalFree(hGlobal
);
2416 return INET_E_RESOURCE_NOT_FOUND
;
2418 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2421 GlobalFree(hGlobal
);
2428 hRes
= CreateBindCtx(0, &pbc
);
2429 if (SUCCEEDED(hRes
))
2431 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2432 if (SUCCEEDED(hRes
))
2434 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2435 IMoniker_Release(pmnk
);
2437 IBindCtx_Release(pbc
);
2443 init_res
= CoInitialize(NULL
);
2445 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2446 &IID_IPicture
, (LPVOID
*)&ipicture
);
2447 if (SUCCEEDED(hRes
)) {
2448 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2450 if (SUCCEEDED(hRes
)) {
2451 hRes
= IPersistStream_Load(pStream
, stream
);
2453 if (SUCCEEDED(hRes
)) {
2454 hRes
= IPicture_QueryInterface(ipicture
, riid
, ppvRet
);
2457 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid
));
2459 IPersistStream_Release(pStream
);
2461 IPicture_Release(ipicture
);
2464 IStream_Release(stream
);
2466 if (SUCCEEDED(init_res
))
2472 /*******************************************************************************
2473 * StdPic ClassFactory
2477 /* IUnknown fields */
2478 IClassFactory IClassFactory_iface
;
2480 } IClassFactoryImpl
;
2482 static inline IClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
2484 return CONTAINING_RECORD(iface
, IClassFactoryImpl
, IClassFactory_iface
);
2487 static HRESULT WINAPI
2488 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2489 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2491 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2492 return E_NOINTERFACE
;
2496 SPCF_AddRef(LPCLASSFACTORY iface
) {
2497 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2498 return InterlockedIncrement(&This
->ref
);
2501 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2502 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2503 /* static class, won't be freed */
2504 return InterlockedDecrement(&This
->ref
);
2507 static HRESULT WINAPI
SPCF_CreateInstance(
2508 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2510 /* Creates an uninitialized picture */
2511 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2515 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2516 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2517 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2521 static const IClassFactoryVtbl SPCF_Vtbl
= {
2522 SPCF_QueryInterface
,
2525 SPCF_CreateInstance
,
2528 static IClassFactoryImpl STDPIC_CF
= {{&SPCF_Vtbl
}, 1 };
2530 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= &STDPIC_CF
; }