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).
48 WINE_DEFAULT_DEBUG_CHANNEL(olepicture
);
50 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
51 #define BITMAP_FORMAT_JPEG 0xd8ff
52 #define BITMAP_FORMAT_GIF 0x4947
53 #define BITMAP_FORMAT_PNG 0x5089
54 #define BITMAP_FORMAT_APM 0xcdd7
58 /* Header for Aldus Placable Metafiles - a standard metafile follows */
59 typedef struct _APM_HEADER
81 } CURSORICONFILEDIRENTRY
;
88 CURSORICONFILEDIRENTRY idEntries
[1];
93 /*************************************************************************
94 * Declaration of implementation class
97 typedef struct OLEPictureImpl
{
100 * IPicture handles IUnknown
103 IPicture IPicture_iface
;
104 IDispatch IDispatch_iface
;
105 IPersistStream IPersistStream_iface
;
106 IConnectionPointContainer IConnectionPointContainer_iface
;
108 /* Object reference count */
111 /* We own the object and must destroy it ourselves */
114 /* Picture description */
117 /* These are the pixel size of a bitmap */
121 /* And these are the size of the picture converted into HIMETRIC units */
122 OLE_XSIZE_HIMETRIC himetricWidth
;
123 OLE_YSIZE_HIMETRIC himetricHeight
;
125 IConnectionPoint
*pCP
;
129 HBITMAP stock_bitmap
;
131 /* Bitmap transparency mask */
139 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
140 unsigned int loadtime_magic
; /* If a length header was found, saves value */
141 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
144 static inline OLEPictureImpl
*impl_from_IPicture(IPicture
*iface
)
146 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPicture_iface
);
149 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
151 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IDispatch_iface
);
154 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
156 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPersistStream_iface
);
159 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
161 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IConnectionPointContainer_iface
);
165 * Predeclare VTables. They get initialized at the end.
167 static const IPictureVtbl OLEPictureImpl_VTable
;
168 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
169 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
170 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
172 /* pixels to HIMETRIC units conversion */
173 static inline OLE_XSIZE_HIMETRIC
xpixels_to_himetric(INT pixels
, HDC hdc
)
175 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
178 static inline OLE_YSIZE_HIMETRIC
ypixels_to_himetric(INT pixels
, HDC hdc
)
180 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
183 /***********************************************************************
184 * Implementation of the OLEPictureImpl class.
187 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
)
192 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
193 if(GetObjectW(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
194 ERR("GetObject fails\n");
197 This
->origWidth
= bm
.bmWidth
;
198 This
->origHeight
= bm
.bmHeight
;
200 TRACE("width %d, height %d, bpp %d\n", bm
.bmWidth
, bm
.bmHeight
, bm
.bmBitsPixel
);
202 /* The width and height are stored in HIMETRIC units (0.01 mm),
203 so we take our pixel width divide by pixels per inch and
204 multiply by 25.4 * 100 */
205 /* Should we use GetBitmapDimension if available? */
206 hdcRef
= CreateCompatibleDC(0);
208 This
->himetricWidth
= xpixels_to_himetric(bm
.bmWidth
, hdcRef
);
209 This
->himetricHeight
= ypixels_to_himetric(bm
.bmHeight
, hdcRef
);
210 This
->stock_bitmap
= GetCurrentObject( hdcRef
, OBJ_BITMAP
);
212 This
->loadtime_format
= BITMAP_FORMAT_BMP
;
217 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
221 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
222 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
226 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
227 if(GetObjectW(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
228 ERR("GetObject fails on icon bitmap\n");
232 This
->origWidth
= bm
.bmWidth
;
233 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
234 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
237 This
->himetricWidth
= xpixels_to_himetric(This
->origWidth
, hdcRef
);
238 This
->himetricHeight
= ypixels_to_himetric(This
->origHeight
, hdcRef
);
240 ReleaseDC(0, hdcRef
);
242 DeleteObject(infoIcon
.hbmMask
);
243 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
245 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
249 /************************************************************************
250 * OLEPictureImpl_Construct
252 * This method will construct a new instance of the OLEPictureImpl
255 * The caller of this method must release the object when it's
258 static OLEPictureImpl
* OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
)
260 OLEPictureImpl
* newObject
= 0;
263 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
266 * Allocate space for the object.
268 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
274 * Initialize the virtual function table.
276 newObject
->IPicture_iface
.lpVtbl
= &OLEPictureImpl_VTable
;
277 newObject
->IDispatch_iface
.lpVtbl
= &OLEPictureImpl_IDispatch_VTable
;
278 newObject
->IPersistStream_iface
.lpVtbl
= &OLEPictureImpl_IPersistStream_VTable
;
279 newObject
->IConnectionPointContainer_iface
.lpVtbl
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
281 newObject
->pCP
= NULL
;
282 CreateConnectionPoint((IUnknown
*)newObject
,&IID_IPropertyNotifySink
,&newObject
->pCP
);
285 HeapFree(GetProcessHeap(), 0, newObject
);
290 * Start with one reference count. The caller of this function
291 * must release the interface pointer when it is done.
294 newObject
->hDCCur
= 0;
296 newObject
->fOwn
= fOwn
;
298 /* dunno about original value */
299 newObject
->keepOrigFormat
= TRUE
;
301 newObject
->hbmMask
= NULL
;
302 newObject
->hbmXor
= NULL
;
303 newObject
->loadtime_magic
= 0xdeadbeef;
304 newObject
->loadtime_format
= 0;
305 newObject
->bIsDirty
= FALSE
;
308 newObject
->desc
= *pictDesc
;
310 switch(pictDesc
->picType
) {
312 OLEPictureImpl_SetBitmap(newObject
);
315 case PICTYPE_METAFILE
:
316 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
317 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
318 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
322 /* not sure what to do here */
323 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
327 OLEPictureImpl_SetIcon(newObject
);
329 case PICTYPE_ENHMETAFILE
:
331 FIXME("Unsupported type %d\n", pictDesc
->picType
);
332 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
336 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
339 TRACE("returning %p\n", newObject
);
343 /************************************************************************
344 * OLEPictureImpl_Destroy
346 * This method is called by the Release method when the reference
347 * count goes down to 0. It will free all resources used by
349 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
351 TRACE("(%p)\n", Obj
);
354 IConnectionPoint_Release(Obj
->pCP
);
356 if(Obj
->fOwn
) { /* We need to destroy the picture */
357 switch(Obj
->desc
.picType
) {
359 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
360 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
361 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
363 case PICTYPE_METAFILE
:
364 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
367 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
369 case PICTYPE_ENHMETAFILE
:
370 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
373 case PICTYPE_UNINITIALIZED
:
377 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
381 HeapFree(GetProcessHeap(), 0, Obj
->data
);
382 HeapFree(GetProcessHeap(), 0, Obj
);
386 /************************************************************************
387 * OLEPictureImpl_AddRef (IUnknown)
389 * See Windows documentation for more details on IUnknown methods.
391 static ULONG WINAPI
OLEPictureImpl_AddRef(
394 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
395 ULONG refCount
= InterlockedIncrement(&This
->ref
);
397 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
402 /************************************************************************
403 * OLEPictureImpl_Release (IUnknown)
405 * See Windows documentation for more details on IUnknown methods.
407 static ULONG WINAPI
OLEPictureImpl_Release(
410 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
411 ULONG refCount
= InterlockedDecrement(&This
->ref
);
413 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
416 * If the reference count goes down to 0, perform suicide.
418 if (!refCount
) OLEPictureImpl_Destroy(This
);
423 /************************************************************************
424 * OLEPictureImpl_QueryInterface (IUnknown)
426 * See Windows documentation for more details on IUnknown methods.
428 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
433 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
435 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
442 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
444 else if (IsEqualIID(&IID_IDispatch
, riid
))
445 *ppvObject
= &This
->IDispatch_iface
;
446 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
447 *ppvObject
= &This
->IDispatch_iface
;
448 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
449 *ppvObject
= &This
->IPersistStream_iface
;
450 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
451 *ppvObject
= &This
->IConnectionPointContainer_iface
;
455 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
456 return E_NOINTERFACE
;
459 IPicture_AddRef(iface
);
464 /***********************************************************************
465 * OLEPicture_SendNotify (internal)
467 * Sends notification messages of changed properties to any interested
470 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
472 IEnumConnections
*pEnum
;
475 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
) != S_OK
)
477 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
478 IPropertyNotifySink
*sink
;
480 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
481 IPropertyNotifySink_OnChanged(sink
, dispID
);
482 IPropertyNotifySink_Release(sink
);
483 IUnknown_Release(CD
.pUnk
);
485 IEnumConnections_Release(pEnum
);
488 /************************************************************************
489 * OLEPictureImpl_get_Handle
491 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
494 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
495 TRACE("(%p)->(%p)\n", This
, phandle
);
500 switch(This
->desc
.picType
) {
502 case PICTYPE_UNINITIALIZED
:
506 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
508 case PICTYPE_METAFILE
:
509 *phandle
= HandleToUlong(This
->desc
.u
.wmf
.hmeta
);
512 *phandle
= HandleToUlong(This
->desc
.u
.icon
.hicon
);
514 case PICTYPE_ENHMETAFILE
:
515 *phandle
= HandleToUlong(This
->desc
.u
.emf
.hemf
);
518 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
521 TRACE("returning handle %08x\n", *phandle
);
525 /************************************************************************
526 * OLEPictureImpl_get_hPal
528 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
531 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
533 TRACE("(%p)->(%p)\n", This
, phandle
);
538 switch (This
->desc
.picType
) {
539 case (UINT
)PICTYPE_UNINITIALIZED
:
545 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hpal
);
548 case PICTYPE_METAFILE
:
552 case PICTYPE_ENHMETAFILE
:
554 FIXME("unimplemented for type %d. Returning 0 palette.\n",
560 TRACE("returning 0x%08x, palette handle %08x\n", hres
, *phandle
);
564 /************************************************************************
565 * OLEPictureImpl_get_Type
567 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
570 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
571 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
576 *ptype
= This
->desc
.picType
;
580 /************************************************************************
581 * OLEPictureImpl_get_Width
583 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
584 OLE_XSIZE_HIMETRIC
*pwidth
)
586 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
587 TRACE("(%p)->(%p): width is %d\n", This
, pwidth
, This
->himetricWidth
);
588 *pwidth
= This
->himetricWidth
;
592 /************************************************************************
593 * OLEPictureImpl_get_Height
595 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
596 OLE_YSIZE_HIMETRIC
*pheight
)
598 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
599 TRACE("(%p)->(%p): height is %d\n", This
, pheight
, This
->himetricHeight
);
600 *pheight
= This
->himetricHeight
;
604 /************************************************************************
605 * OLEPictureImpl_Render
607 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
608 LONG x
, LONG y
, LONG cx
, LONG cy
,
609 OLE_XPOS_HIMETRIC xSrc
,
610 OLE_YPOS_HIMETRIC ySrc
,
611 OLE_XSIZE_HIMETRIC cxSrc
,
612 OLE_YSIZE_HIMETRIC cySrc
,
615 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
616 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
617 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
619 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds
->left
, prcWBounds
->top
,
620 prcWBounds
->right
, prcWBounds
->bottom
);
622 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
623 return CTL_E_INVALIDPROPERTYVALUE
;
627 * While the documentation suggests this to be here (or after rendering?)
628 * it does cause an endless recursion in my sample app. -MM 20010804
629 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
632 switch(This
->desc
.picType
) {
633 case PICTYPE_UNINITIALIZED
:
642 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
643 NB y-axis gets flipped */
645 hdcBmp
= CreateCompatibleDC(0);
646 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
647 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
648 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
649 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
650 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
653 HDC hdcMask
= CreateCompatibleDC(0);
654 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
656 hbmpOld
= SelectObject(hdcBmp
, This
->hbmXor
);
658 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
659 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
660 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
661 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
662 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
664 SetBkColor(hdc
, RGB(255, 255, 255));
665 SetTextColor(hdc
, RGB(0, 0, 0));
666 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
667 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
669 SelectObject(hdcMask
, hOldbm
);
672 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
673 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
676 SelectObject(hdcBmp
, hbmpOld
);
681 FIXME("Not quite correct implementation of rendering icons...\n");
682 DrawIconEx(hdc
, x
, y
, This
->desc
.u
.icon
.hicon
, cx
, cy
, 0, NULL
, DI_NORMAL
);
685 case PICTYPE_METAFILE
:
687 POINT prevOrg
, prevWndOrg
;
688 SIZE prevExt
, prevWndExt
;
691 /* Render the WMF to the appropriate location by setting the
692 appropriate ratio between "device units" and "logical units" */
693 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
694 /* For the "source rectangle" the y-axis must be inverted */
695 SetWindowOrgEx(hdc
, xSrc
, This
->himetricHeight
-ySrc
, &prevWndOrg
);
696 SetWindowExtEx(hdc
, cxSrc
, -cySrc
, &prevWndExt
);
697 /* For the "destination rectangle" no inversion is necessary */
698 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
699 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
701 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
702 ERR("PlayMetaFile failed!\n");
704 /* We're done, restore the DC to the previous settings for converting
705 logical units to device units */
706 SetWindowExtEx(hdc
, prevWndExt
.cx
, prevWndExt
.cy
, NULL
);
707 SetWindowOrgEx(hdc
, prevWndOrg
.x
, prevWndOrg
.y
, NULL
);
708 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
709 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
710 SetMapMode(hdc
, oldmode
);
714 case PICTYPE_ENHMETAFILE
:
716 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
717 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
722 FIXME("type %d not implemented\n", This
->desc
.picType
);
728 /************************************************************************
729 * OLEPictureImpl_set_hPal
731 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
734 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
735 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
736 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
740 /************************************************************************
741 * OLEPictureImpl_get_CurDC
743 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
746 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
747 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
748 if (phdc
) *phdc
= This
->hDCCur
;
752 /************************************************************************
753 * OLEPictureImpl_SelectPicture
755 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
758 OLE_HANDLE
*phbmpOut
)
760 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
761 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
762 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
764 *phdcOut
= This
->hDCCur
;
765 if (This
->hDCCur
) SelectObject(This
->hDCCur
,This
->stock_bitmap
);
766 if (hdcIn
) SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
767 This
->hDCCur
= hdcIn
;
769 *phbmpOut
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
772 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
777 /************************************************************************
778 * OLEPictureImpl_get_KeepOriginalFormat
780 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
783 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
784 TRACE("(%p)->(%p)\n", This
, pfKeep
);
787 *pfKeep
= This
->keepOrigFormat
;
791 /************************************************************************
792 * OLEPictureImpl_put_KeepOriginalFormat
794 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
797 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
798 TRACE("(%p)->(%d)\n", This
, keep
);
799 This
->keepOrigFormat
= keep
;
800 /* FIXME: what DISPID notification here? */
804 /************************************************************************
805 * OLEPictureImpl_PictureChanged
807 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
809 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
810 TRACE("(%p)->()\n", This
);
811 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
812 This
->bIsDirty
= TRUE
;
816 /************************************************************************
817 * OLEPictureImpl_SaveAsFile
819 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
824 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
825 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
826 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
829 /************************************************************************
830 * OLEPictureImpl_get_Attributes
832 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
835 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
836 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
842 switch (This
->desc
.picType
) {
843 case PICTYPE_UNINITIALIZED
:
844 case PICTYPE_NONE
: break;
845 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
846 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
847 case PICTYPE_ENHMETAFILE
: /* fall through */
848 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
849 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
855 /************************************************************************
856 * IConnectionPointContainer
858 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
859 IConnectionPointContainer
* iface
,
863 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
865 return IPicture_QueryInterface(&This
->IPicture_iface
,riid
,ppvoid
);
868 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
869 IConnectionPointContainer
* iface
)
871 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
873 return IPicture_AddRef(&This
->IPicture_iface
);
876 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
877 IConnectionPointContainer
* iface
)
879 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
881 return IPicture_Release(&This
->IPicture_iface
);
884 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
885 IConnectionPointContainer
* iface
,
886 IEnumConnectionPoints
** ppEnum
)
888 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
890 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
894 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
895 IConnectionPointContainer
* iface
,
897 IConnectionPoint
**ppCP
)
899 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
900 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
904 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
905 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
906 FIXME("no connection point for %s\n",debugstr_guid(riid
));
907 return CONNECT_E_NOCONNECTION
;
911 /************************************************************************
915 /************************************************************************
916 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
918 * See Windows documentation for more details on IUnknown methods.
920 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
921 IPersistStream
* iface
,
925 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
927 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
930 /************************************************************************
931 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
933 * See Windows documentation for more details on IUnknown methods.
935 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
936 IPersistStream
* iface
)
938 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
940 return IPicture_AddRef(&This
->IPicture_iface
);
943 /************************************************************************
944 * OLEPictureImpl_IPersistStream_Release (IUnknown)
946 * See Windows documentation for more details on IUnknown methods.
948 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
949 IPersistStream
* iface
)
951 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
953 return IPicture_Release(&This
->IPicture_iface
);
956 /************************************************************************
957 * OLEPictureImpl_IPersistStream_GetClassID
959 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
960 IPersistStream
* iface
,CLSID
* pClassID
)
962 TRACE("(%p)\n", pClassID
);
963 *pClassID
= CLSID_StdPicture
;
967 /************************************************************************
968 * OLEPictureImpl_IPersistStream_IsDirty
970 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
971 IPersistStream
* iface
)
973 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
974 FIXME("(%p),stub!\n",This
);
978 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
980 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
981 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
984 /* Does not matter whether this is a coreheader or not, we only use
985 * components which are in both
988 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
996 ReleaseDC(0, hdcref
);
997 if (This
->desc
.u
.bmp
.hbitmap
== 0)
999 This
->desc
.picType
= PICTYPE_BITMAP
;
1000 OLEPictureImpl_SetBitmap(This
);
1004 static HRESULT
OLEPictureImpl_LoadWICSource(OLEPictureImpl
*This
, IWICBitmapSource
*src
)
1007 BITMAPINFOHEADER bih
;
1010 UINT stride
, buffersize
;
1013 IWICBitmapSource
*real_source
;
1015 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1016 BOOL has_alpha
=FALSE
;
1018 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
, src
, &real_source
);
1019 if (FAILED(hr
)) return hr
;
1021 hr
= IWICBitmapSource_GetSize(real_source
, &width
, &height
);
1022 if (FAILED(hr
)) goto end
;
1024 bih
.biSize
= sizeof(bih
);
1025 bih
.biWidth
= width
;
1026 bih
.biHeight
= -height
;
1028 bih
.biBitCount
= 32;
1029 bih
.biCompression
= BI_RGB
;
1030 bih
.biSizeImage
= 0;
1031 bih
.biXPelsPerMeter
= 4085; /* olepicture ignores the stored resolution */
1032 bih
.biYPelsPerMeter
= 4085;
1034 bih
.biClrImportant
= 0;
1037 buffersize
= stride
* height
;
1039 bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
1050 hr
= IWICBitmapSource_CopyPixels(real_source
, &rc
, stride
, buffersize
, bits
);
1055 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1063 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1066 ReleaseDC(0, hdcref
);
1070 This
->desc
.picType
= PICTYPE_BITMAP
;
1071 OLEPictureImpl_SetBitmap(This
);
1073 /* set transparent pixels to black, all others to white */
1074 for(y
= 0; y
< height
; y
++){
1075 for(x
= 0; x
< width
; x
++){
1076 DWORD
*pixel
= (DWORD
*)(bits
+ stride
*y
+ 4*x
);
1077 if((*pixel
& 0x80000000) == 0)
1089 HDC hdcBmp
, hdcXor
, hdcMask
;
1090 HBITMAP hbmoldBmp
, hbmoldXor
, hbmoldMask
;
1092 This
->hbmXor
= CreateDIBitmap(
1101 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1102 hdcBmp
= CreateCompatibleDC(NULL
);
1103 hdcXor
= CreateCompatibleDC(NULL
);
1104 hdcMask
= CreateCompatibleDC(NULL
);
1106 hbmoldBmp
= SelectObject(hdcBmp
,This
->desc
.u
.bmp
.hbitmap
);
1107 hbmoldXor
= SelectObject(hdcXor
,This
->hbmXor
);
1108 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1110 SetBkColor(hdcXor
,black
);
1111 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1112 BitBlt(hdcXor
,0,0,width
,height
,hdcBmp
,0,0,SRCAND
);
1114 SelectObject(hdcBmp
,hbmoldBmp
);
1115 SelectObject(hdcXor
,hbmoldXor
);
1116 SelectObject(hdcMask
,hbmoldMask
);
1123 ReleaseDC(0, hdcref
);
1126 HeapFree(GetProcessHeap(), 0, bits
);
1127 IWICBitmapSource_Release(real_source
);
1131 static HRESULT
OLEPictureImpl_LoadWICDecoder(OLEPictureImpl
*This
, REFCLSID decoder_clsid
, BYTE
*xbuf
, ULONG xread
)
1134 IWICImagingFactory
*factory
;
1135 IWICBitmapDecoder
*decoder
;
1136 IWICBitmapFrameDecode
*framedecode
;
1140 initresult
= CoInitialize(NULL
);
1142 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
1143 &IID_IWICImagingFactory
, (void**)&factory
);
1144 if (SUCCEEDED(hr
)) /* created factory */
1146 hr
= IWICImagingFactory_CreateStream(factory
, &stream
);
1147 IWICImagingFactory_Release(factory
);
1150 if (SUCCEEDED(hr
)) /* created stream */
1152 hr
= IWICStream_InitializeFromMemory(stream
, xbuf
, xread
);
1154 if (SUCCEEDED(hr
)) /* initialized stream */
1156 hr
= CoCreateInstance(decoder_clsid
, NULL
, CLSCTX_INPROC_SERVER
,
1157 &IID_IWICBitmapDecoder
, (void**)&decoder
);
1158 if (SUCCEEDED(hr
)) /* created decoder */
1160 hr
= IWICBitmapDecoder_Initialize(decoder
, (IStream
*)stream
, WICDecodeMetadataCacheOnLoad
);
1162 if (SUCCEEDED(hr
)) /* initialized decoder */
1163 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
1165 IWICBitmapDecoder_Release(decoder
);
1169 IWICStream_Release(stream
);
1172 if (SUCCEEDED(hr
)) /* got framedecode */
1174 hr
= OLEPictureImpl_LoadWICSource(This
, (IWICBitmapSource
*)framedecode
);
1175 IWICBitmapFrameDecode_Release(framedecode
);
1178 if (SUCCEEDED(initresult
)) CoUninitialize();
1182 /*****************************************************
1183 * start of Icon-specific code
1186 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1189 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1194 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1195 FIXME("icon.idType=%d\n",cifd->idType);
1196 FIXME("icon.idCount=%d\n",cifd->idCount);
1198 for (i=0;i<cifd->idCount;i++) {
1199 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1200 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1201 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1202 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1203 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1204 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1205 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1206 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1210 /* If we have more than one icon, try to find the best.
1211 * this currently means '32 pixel wide'.
1213 if (cifd
->idCount
!=1) {
1214 for (i
=0;i
<cifd
->idCount
;i
++) {
1215 if (cifd
->idEntries
[i
].bWidth
== 32)
1218 if (i
==cifd
->idCount
) i
=0;
1220 if (cifd
->idType
== 2)
1222 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, cifd
->idEntries
[i
].dwDIBSize
+ 4);
1223 memcpy(buf
, &cifd
->idEntries
[i
].xHotspot
, 4);
1224 memcpy(buf
+ 4, xbuf
+cifd
->idEntries
[i
].dwDIBOffset
, cifd
->idEntries
[i
].dwDIBSize
);
1225 hicon
= CreateIconFromResourceEx(
1227 cifd
->idEntries
[i
].dwDIBSize
+ 4,
1228 FALSE
, /* is cursor */
1230 cifd
->idEntries
[i
].bWidth
,
1231 cifd
->idEntries
[i
].bHeight
,
1234 HeapFree(GetProcessHeap(), 0, buf
);
1238 hicon
= CreateIconFromResourceEx(
1239 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1240 cifd
->idEntries
[i
].dwDIBSize
,
1243 cifd
->idEntries
[i
].bWidth
,
1244 cifd
->idEntries
[i
].bHeight
,
1249 ERR("CreateIcon failed.\n");
1252 This
->desc
.picType
= PICTYPE_ICON
;
1253 This
->desc
.u
.icon
.hicon
= hicon
;
1254 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1255 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1256 hdcRef
= CreateCompatibleDC(0);
1257 This
->himetricWidth
= xpixels_to_himetric(cifd
->idEntries
[i
].bWidth
, hdcRef
);
1258 This
->himetricHeight
= ypixels_to_himetric(cifd
->idEntries
[i
].bHeight
, hdcRef
);
1264 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1265 const BYTE
*data
, ULONG size
)
1270 hemf
= SetEnhMetaFileBits(size
, data
);
1271 if (!hemf
) return E_FAIL
;
1273 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1275 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1276 This
->desc
.u
.emf
.hemf
= hemf
;
1278 This
->origWidth
= 0;
1279 This
->origHeight
= 0;
1280 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1281 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1286 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1287 const BYTE
*data
, ULONG size
)
1289 const APM_HEADER
*header
= (const APM_HEADER
*)data
;
1292 if (size
< sizeof(APM_HEADER
))
1294 if (header
->key
!= 0x9ac6cdd7)
1297 /* SetMetaFileBitsEx performs data check on its own */
1298 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1299 if (!hmf
) return E_FAIL
;
1301 This
->desc
.picType
= PICTYPE_METAFILE
;
1302 This
->desc
.u
.wmf
.hmeta
= hmf
;
1303 This
->desc
.u
.wmf
.xExt
= 0;
1304 This
->desc
.u
.wmf
.yExt
= 0;
1306 This
->origWidth
= 0;
1307 This
->origHeight
= 0;
1308 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1309 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1313 /************************************************************************
1314 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1316 * Loads the binary data from the IStream. Starts at current position.
1317 * There appears to be an 2 DWORD header:
1321 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
1323 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
, IStream
*pStm
) {
1326 BOOL statfailed
= FALSE
;
1327 ULONG xread
, toread
;
1333 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1335 TRACE("(%p,%p)\n",This
,pStm
);
1337 /****************************************************************************************
1338 * Part 1: Load the data
1340 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1341 * out whether we do.
1343 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1344 * compound file. This may explain most, if not all, of the cases of "no
1345 * header", and the header validation should take this into account.
1346 * At least in Visual Basic 6, resource streams, valid headers are
1347 * header[0] == "lt\0\0",
1348 * header[1] == length_of_stream.
1350 * Also handle streams where we do not have a working "Stat" method by
1351 * reading all data until the end of the stream.
1353 hr
= IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1355 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr
);
1357 /* we will read at least 8 byte ... just right below */
1358 statstg
.cbSize
.QuadPart
= 8;
1363 headerisdata
= FALSE
;
1365 hr
= IStream_Read(pStm
, header
, 8, &xread
);
1366 if (hr
!= S_OK
|| xread
!=8) {
1367 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr
,xread
);
1368 return (hr
?hr
:E_FAIL
);
1370 headerread
+= xread
;
1373 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1374 if (toread
!= 0 && toread
!= header
[1])
1375 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1378 if (toread
== 0) break;
1380 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1381 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1382 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1383 (header
[0] == EMR_HEADER
) || /* EMF header */
1384 (header
[0] == 0x10000) || /* icon: idReserved 0, idType 1 */
1385 (header
[0] == 0x20000) || /* cursor: idReserved 0, idType 2 */
1386 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1388 ) {/* Found start of bitmap data */
1389 headerisdata
= TRUE
;
1391 toread
= statstg
.cbSize
.QuadPart
-8;
1395 FIXME("Unknown stream header magic: %08x\n", header
[0]);
1399 } while (!headerisdata
);
1401 if (statfailed
) { /* we don't know the size ... read all we get */
1402 unsigned int sizeinc
= 4096;
1403 unsigned int origsize
= sizeinc
;
1406 TRACE("Reading all data from stream.\n");
1407 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1409 memcpy (xbuf
, header
, 8);
1411 while (xread
< origsize
) {
1412 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1414 if (hr
!= S_OK
|| !nread
)
1417 if (!nread
|| hr
!= S_OK
) /* done, or error */
1419 if (xread
== origsize
) {
1420 origsize
+= sizeinc
;
1421 sizeinc
= 2*sizeinc
; /* exponential increase */
1422 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1426 TRACE("hr in no-stat loader case is %08x\n", hr
);
1427 TRACE("loaded %d bytes.\n", xread
);
1428 This
->datalen
= xread
;
1431 This
->datalen
= toread
+(headerisdata
?8:0);
1432 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1434 return E_OUTOFMEMORY
;
1437 memcpy (xbuf
, header
, 8);
1439 while (xread
< This
->datalen
) {
1441 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1443 if (hr
!= S_OK
|| !nread
)
1446 if (xread
!= This
->datalen
)
1447 ERR("Could only read %d of %d bytes out of stream?\n",xread
,This
->datalen
);
1449 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1450 This
->desc
.picType
= PICTYPE_NONE
;
1455 /****************************************************************************************
1456 * Part 2: Process the loaded data
1459 magic
= xbuf
[0] + (xbuf
[1]<<8);
1460 This
->loadtime_format
= magic
;
1463 case BITMAP_FORMAT_GIF
: /* GIF */
1464 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICGifDecoder
, xbuf
, xread
);
1466 case BITMAP_FORMAT_JPEG
: /* JPEG */
1467 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICJpegDecoder
, xbuf
, xread
);
1469 case BITMAP_FORMAT_BMP
: /* Bitmap */
1470 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1472 case BITMAP_FORMAT_PNG
: /* PNG */
1473 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICPngDecoder
, xbuf
, xread
);
1475 case BITMAP_FORMAT_APM
: /* APM */
1476 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1478 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1479 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1486 /* let's see if it's a EMF */
1487 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1488 if (hr
== S_OK
) break;
1490 FIXME("Unknown magic %04x, %d read bytes:\n",magic
,xread
);
1492 for (i
=0;i
<xread
+8;i
++) {
1493 if (i
<8) MESSAGE("%02x ",((unsigned char*)header
)[i
]);
1494 else MESSAGE("%02x ",xbuf
[i
-8]);
1495 if (i
% 10 == 9) MESSAGE("\n");
1501 This
->bIsDirty
= FALSE
;
1503 /* FIXME: this notify is not really documented */
1505 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1509 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1513 BITMAPINFO
* pInfoBitmap
;
1514 int iNumPaletteEntries
;
1515 unsigned char * pPixelData
;
1516 BITMAPFILEHEADER
* pFileHeader
;
1517 BITMAPINFO
* pInfoHeader
;
1519 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1520 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1522 /* Find out bitmap size and padded length */
1524 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1525 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1527 /* Fetch bitmap palette & pixel data */
1529 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1530 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1532 /* Calculate the total length required for the BMP data */
1533 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1534 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1535 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1537 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1538 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1540 iNumPaletteEntries
= 0;
1543 sizeof(BITMAPFILEHEADER
) +
1544 sizeof(BITMAPINFOHEADER
) +
1545 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1546 pInfoBitmap
->bmiHeader
.biSizeImage
;
1547 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1549 /* Fill the BITMAPFILEHEADER */
1550 pFileHeader
= *ppBuffer
;
1551 pFileHeader
->bfType
= BITMAP_FORMAT_BMP
;
1552 pFileHeader
->bfSize
= *pLength
;
1553 pFileHeader
->bfOffBits
=
1554 sizeof(BITMAPFILEHEADER
) +
1555 sizeof(BITMAPINFOHEADER
) +
1556 iNumPaletteEntries
* sizeof(RGBQUAD
);
1558 /* Fill the BITMAPINFOHEADER and the palette data */
1559 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1560 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1562 (unsigned char *)(*ppBuffer
) +
1563 sizeof(BITMAPFILEHEADER
) +
1564 sizeof(BITMAPINFOHEADER
) +
1565 iNumPaletteEntries
* sizeof(RGBQUAD
),
1566 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1569 HeapFree(GetProcessHeap(), 0, pPixelData
);
1570 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1574 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1579 *ppBuffer
= NULL
; *pLength
= 0;
1580 if (GetIconInfo(hIcon
, &infoIcon
)) {
1582 BITMAPINFO
* pInfoBitmap
;
1583 unsigned char * pIconData
= NULL
;
1584 unsigned int iDataSize
= 0;
1586 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1588 /* Find out icon size */
1590 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1591 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1593 /* Auxiliary pointers */
1594 CURSORICONFILEDIR
* pIconDir
;
1595 CURSORICONFILEDIRENTRY
* pIconEntry
;
1596 BITMAPINFOHEADER
* pIconBitmapHeader
;
1597 unsigned int iOffsetPalette
;
1598 unsigned int iOffsetColorData
;
1599 unsigned int iOffsetMaskData
;
1601 unsigned int iLengthScanLineMask
;
1602 unsigned int iNumEntriesPalette
;
1604 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1606 FIXME("DEBUG: bitmap size is %d x %d\n",
1607 pInfoBitmap->bmiHeader.biWidth,
1608 pInfoBitmap->bmiHeader.biHeight);
1609 FIXME("DEBUG: bitmap bpp is %d\n",
1610 pInfoBitmap->bmiHeader.biBitCount);
1611 FIXME("DEBUG: bitmap nplanes is %d\n",
1612 pInfoBitmap->bmiHeader.biPlanes);
1613 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1614 pInfoBitmap->bmiHeader.biSizeImage);
1616 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1617 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1618 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1620 /* Fill out the CURSORICONFILEDIR */
1621 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1622 pIconDir
->idType
= 1;
1623 pIconDir
->idCount
= 1;
1624 pIconDir
->idReserved
= 0;
1626 /* Fill out the CURSORICONFILEDIRENTRY */
1627 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1628 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1629 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1630 pIconEntry
->bColorCount
=
1631 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1632 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1634 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1635 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1636 pIconEntry
->dwDIBSize
= 0;
1637 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1639 /* Fill out the BITMAPINFOHEADER */
1640 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1641 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
1643 /* Find out whether a palette exists for the bitmap */
1644 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1645 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1646 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1647 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1648 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1649 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1650 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1651 iNumEntriesPalette
= 3;
1652 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1653 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1655 iNumEntriesPalette
= 0;
1658 /* Add bitmap size and header size to icon data size. */
1659 iOffsetPalette
= iDataSize
;
1660 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1661 iOffsetColorData
= iDataSize
;
1662 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1663 iOffsetMaskData
= iDataSize
;
1664 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1665 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1666 pIconBitmapHeader
->biHeight
*= 2;
1667 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1668 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1669 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1670 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1672 /* Get the actual bitmap data from the icon bitmap */
1673 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1674 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1675 if (iNumEntriesPalette
> 0) {
1676 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1677 iNumEntriesPalette
* sizeof(RGBQUAD
));
1680 /* Reset all values so that GetDIBits call succeeds */
1681 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1682 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1683 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1685 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1686 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1687 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1689 printf("ERROR: unable to get bitmap mask (error %u)\n",
1694 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1695 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1697 /* Write out everything produced so far to the stream */
1698 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1702 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1707 Remarks (from MSDN entry on GetIconInfo):
1709 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1710 members of ICONINFO. The calling application must manage
1711 these bitmaps and delete them when they are no longer
1714 if (hDC
) ReleaseDC(0, hDC
);
1715 DeleteObject(infoIcon
.hbmMask
);
1716 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1717 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1719 printf("ERROR: Unable to get icon information (error %u)\n",
1725 static HRESULT WINAPI
OLEPictureImpl_Save(
1726 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1728 HRESULT hResult
= E_NOTIMPL
;
1730 unsigned int iDataSize
;
1733 int iSerializeResult
= 0;
1734 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1736 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
1738 switch (This
->desc
.picType
) {
1740 header
[0] = 0x0000746c;
1742 hResult
= IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1746 if (This
->bIsDirty
|| !This
->data
) {
1747 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1748 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
1752 HeapFree(GetProcessHeap(), 0, This
->data
);
1753 This
->data
= pIconData
;
1754 This
->datalen
= iDataSize
;
1757 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1758 header
[1] = This
->datalen
;
1759 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1760 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1763 case PICTYPE_BITMAP
:
1764 if (This
->bIsDirty
|| !This
->data
) {
1765 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
1766 case BITMAP_FORMAT_BMP
:
1767 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1769 case BITMAP_FORMAT_JPEG
:
1770 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1772 case BITMAP_FORMAT_GIF
:
1773 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1775 case BITMAP_FORMAT_PNG
:
1776 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
1779 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1783 if (!iSerializeResult
)
1789 HeapFree(GetProcessHeap(), 0, This
->data
);
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_METAFILE
:
1801 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1803 case PICTYPE_ENHMETAFILE
:
1804 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1807 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1810 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1814 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1815 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1817 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1818 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1823 /************************************************************************
1827 /************************************************************************
1828 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1830 * See Windows documentation for more details on IUnknown methods.
1832 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1837 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1839 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
1842 /************************************************************************
1843 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1845 * See Windows documentation for more details on IUnknown methods.
1847 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1850 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1852 return IPicture_AddRef(&This
->IPicture_iface
);
1855 /************************************************************************
1856 * OLEPictureImpl_IDispatch_Release (IUnknown)
1858 * See Windows documentation for more details on IUnknown methods.
1860 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1863 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1865 return IPicture_Release(&This
->IPicture_iface
);
1868 /************************************************************************
1869 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1871 * See Windows documentation for more details on IDispatch methods.
1873 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1875 unsigned int* pctinfo
)
1877 TRACE("(%p)\n", pctinfo
);
1884 /************************************************************************
1885 * OLEPictureImpl_GetTypeInfo (IDispatch)
1887 * See Windows documentation for more details on IDispatch methods.
1889 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1893 ITypeInfo
** ppTInfo
)
1895 static const WCHAR stdole2tlb
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1899 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
1904 hres
= LoadTypeLib(stdole2tlb
, &tl
);
1907 ERR("Could not load stdole2.tlb\n");
1911 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
1913 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres
);
1918 /************************************************************************
1919 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1921 * See Windows documentation for more details on IDispatch methods.
1923 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1926 LPOLESTR
* rgszNames
,
1934 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
1935 rgszNames
, cNames
, (int)lcid
, rgDispId
);
1939 return E_INVALIDARG
;
1943 /* retrieve type information */
1944 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
1948 ERR("GetTypeInfo failed.\n");
1952 /* convert names to DISPIDs */
1953 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
1954 ITypeInfo_Release(pTInfo
);
1960 /************************************************************************
1961 * OLEPictureImpl_Invoke (IDispatch)
1963 * See Windows documentation for more details on IDispatch methods.
1965 static HRESULT WINAPI
OLEPictureImpl_Invoke(
1967 DISPID dispIdMember
,
1971 DISPPARAMS
* pDispParams
,
1972 VARIANT
* pVarResult
,
1973 EXCEPINFO
* pExepInfo
,
1976 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1978 /* validate parameters */
1980 if (!IsEqualIID(riid
, &IID_NULL
))
1982 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
1983 return DISP_E_UNKNOWNNAME
;
1988 ERR("null pDispParams not allowed\n");
1989 return DISP_E_PARAMNOTOPTIONAL
;
1992 if (wFlags
& DISPATCH_PROPERTYGET
)
1994 if (pDispParams
->cArgs
!= 0)
1996 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
1997 return DISP_E_BADPARAMCOUNT
;
2001 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2002 return DISP_E_PARAMNOTOPTIONAL
;
2005 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2007 if (pDispParams
->cArgs
!= 1)
2009 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2010 return DISP_E_BADPARAMCOUNT
;
2014 switch (dispIdMember
)
2016 case DISPID_PICT_HANDLE
:
2017 if (wFlags
& DISPATCH_PROPERTYGET
)
2019 TRACE("DISPID_PICT_HANDLE\n");
2020 V_VT(pVarResult
) = VT_I4
;
2021 return IPicture_get_Handle(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2024 case DISPID_PICT_HPAL
:
2025 if (wFlags
& DISPATCH_PROPERTYGET
)
2027 TRACE("DISPID_PICT_HPAL\n");
2028 V_VT(pVarResult
) = VT_I4
;
2029 return IPicture_get_hPal(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2031 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2035 TRACE("DISPID_PICT_HPAL\n");
2037 VariantInit(&vararg
);
2038 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2042 hr
= IPicture_set_hPal(&This
->IPicture_iface
, V_I4(&vararg
));
2044 VariantClear(&vararg
);
2048 case DISPID_PICT_TYPE
:
2049 if (wFlags
& DISPATCH_PROPERTYGET
)
2051 TRACE("DISPID_PICT_TYPE\n");
2052 V_VT(pVarResult
) = VT_I2
;
2053 return OLEPictureImpl_get_Type(&This
->IPicture_iface
, &V_I2(pVarResult
));
2056 case DISPID_PICT_WIDTH
:
2057 if (wFlags
& DISPATCH_PROPERTYGET
)
2059 TRACE("DISPID_PICT_WIDTH\n");
2060 V_VT(pVarResult
) = VT_I4
;
2061 return IPicture_get_Width(&This
->IPicture_iface
, &V_I4(pVarResult
));
2064 case DISPID_PICT_HEIGHT
:
2065 if (wFlags
& DISPATCH_PROPERTYGET
)
2067 TRACE("DISPID_PICT_HEIGHT\n");
2068 V_VT(pVarResult
) = VT_I4
;
2069 return IPicture_get_Height(&This
->IPicture_iface
, &V_I4(pVarResult
));
2074 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember
, wFlags
);
2075 return DISP_E_MEMBERNOTFOUND
;
2079 static const IPictureVtbl OLEPictureImpl_VTable
=
2081 OLEPictureImpl_QueryInterface
,
2082 OLEPictureImpl_AddRef
,
2083 OLEPictureImpl_Release
,
2084 OLEPictureImpl_get_Handle
,
2085 OLEPictureImpl_get_hPal
,
2086 OLEPictureImpl_get_Type
,
2087 OLEPictureImpl_get_Width
,
2088 OLEPictureImpl_get_Height
,
2089 OLEPictureImpl_Render
,
2090 OLEPictureImpl_set_hPal
,
2091 OLEPictureImpl_get_CurDC
,
2092 OLEPictureImpl_SelectPicture
,
2093 OLEPictureImpl_get_KeepOriginalFormat
,
2094 OLEPictureImpl_put_KeepOriginalFormat
,
2095 OLEPictureImpl_PictureChanged
,
2096 OLEPictureImpl_SaveAsFile
,
2097 OLEPictureImpl_get_Attributes
2100 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2102 OLEPictureImpl_IDispatch_QueryInterface
,
2103 OLEPictureImpl_IDispatch_AddRef
,
2104 OLEPictureImpl_IDispatch_Release
,
2105 OLEPictureImpl_GetTypeInfoCount
,
2106 OLEPictureImpl_GetTypeInfo
,
2107 OLEPictureImpl_GetIDsOfNames
,
2108 OLEPictureImpl_Invoke
2111 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2113 OLEPictureImpl_IPersistStream_QueryInterface
,
2114 OLEPictureImpl_IPersistStream_AddRef
,
2115 OLEPictureImpl_IPersistStream_Release
,
2116 OLEPictureImpl_GetClassID
,
2117 OLEPictureImpl_IsDirty
,
2118 OLEPictureImpl_Load
,
2119 OLEPictureImpl_Save
,
2120 OLEPictureImpl_GetSizeMax
2123 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2125 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2126 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2127 OLEPictureImpl_IConnectionPointContainer_Release
,
2128 OLEPictureImpl_EnumConnectionPoints
,
2129 OLEPictureImpl_FindConnectionPoint
2132 /***********************************************************************
2133 * OleCreatePictureIndirect (OLEAUT32.419)
2135 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2136 BOOL Own
, void **ppvObj
)
2138 OLEPictureImpl
* newPict
;
2141 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), Own
, ppvObj
);
2145 newPict
= OLEPictureImpl_Construct(lpPictDesc
, Own
);
2147 if (newPict
== NULL
)
2148 return E_OUTOFMEMORY
;
2151 * Make sure it supports the interface required by the caller.
2153 hr
= IPicture_QueryInterface(&newPict
->IPicture_iface
, riid
, ppvObj
);
2156 * Release the reference obtained in the constructor. If
2157 * the QueryInterface was unsuccessful, it will free the class.
2159 IPicture_Release(&newPict
->IPicture_iface
);
2165 /***********************************************************************
2166 * OleLoadPicture (OLEAUT32.418)
2168 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2169 REFIID riid
, LPVOID
*ppvObj
)
2175 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2176 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2178 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2181 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2183 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2184 IPicture_Release(newpic
);
2188 hr
= IPersistStream_Load(ps
,lpstream
);
2189 IPersistStream_Release(ps
);
2192 ERR("IPersistStream_Load failed\n");
2193 IPicture_Release(newpic
);
2197 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2199 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2200 IPicture_Release(newpic
);
2204 /***********************************************************************
2205 * OleLoadPictureEx (OLEAUT32.401)
2207 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2208 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2214 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2215 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2217 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2220 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2222 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2223 IPicture_Release(newpic
);
2227 hr
= IPersistStream_Load(ps
,lpstream
);
2228 IPersistStream_Release(ps
);
2231 ERR("IPersistStream_Load failed\n");
2232 IPicture_Release(newpic
);
2236 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2238 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2239 IPicture_Release(newpic
);
2243 /***********************************************************************
2244 * OleLoadPicturePath (OLEAUT32.424)
2246 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2247 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2250 static const WCHAR file
[] = { 'f','i','l','e',':',0 };
2254 HGLOBAL hGlobal
= NULL
;
2255 DWORD dwBytesRead
= 0;
2258 IPersistStream
*pStream
;
2261 WCHAR
*file_candidate
;
2262 WCHAR path_buf
[MAX_PATH
];
2264 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2265 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2266 debugstr_guid(riid
), ppvRet
);
2268 if (!szURLorPath
|| !ppvRet
)
2269 return E_INVALIDARG
;
2273 /* Convert file URLs to DOS paths. */
2274 if (strncmpW(szURLorPath
, file
, 5) == 0) {
2276 hRes
= CoInternetParseUrl(szURLorPath
, PARSE_PATH_FROM_URL
, 0, path_buf
,
2277 sizeof(path_buf
)/sizeof(WCHAR
), &size
, 0);
2281 file_candidate
= path_buf
;
2284 file_candidate
= szURLorPath
;
2286 /* Handle candidate DOS paths separately. */
2287 if (file_candidate
[1] == ':') {
2288 hFile
= CreateFileW(file_candidate
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2290 if (hFile
== INVALID_HANDLE_VALUE
)
2291 return INET_E_RESOURCE_NOT_FOUND
;
2293 dwFileSize
= GetFileSize(hFile
, NULL
);
2294 if (dwFileSize
!= INVALID_FILE_SIZE
)
2296 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2299 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
);
2302 GlobalFree(hGlobal
);
2310 return INET_E_RESOURCE_NOT_FOUND
;
2312 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2315 GlobalFree(hGlobal
);
2322 hRes
= CreateBindCtx(0, &pbc
);
2323 if (SUCCEEDED(hRes
))
2325 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2326 if (SUCCEEDED(hRes
))
2328 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2329 IMoniker_Release(pmnk
);
2331 IBindCtx_Release(pbc
);
2337 init_res
= CoInitialize(NULL
);
2339 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2340 &IID_IPicture
, (LPVOID
*)&ipicture
);
2341 if (SUCCEEDED(hRes
)) {
2342 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2344 if (SUCCEEDED(hRes
)) {
2345 hRes
= IPersistStream_Load(pStream
, stream
);
2347 if (SUCCEEDED(hRes
)) {
2348 hRes
= IPicture_QueryInterface(ipicture
, riid
, ppvRet
);
2351 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid
));
2353 IPersistStream_Release(pStream
);
2355 IPicture_Release(ipicture
);
2358 IStream_Release(stream
);
2360 if (SUCCEEDED(init_res
))
2366 /*******************************************************************************
2367 * StdPic ClassFactory
2371 /* IUnknown fields */
2372 IClassFactory IClassFactory_iface
;
2374 } IClassFactoryImpl
;
2376 static inline IClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
2378 return CONTAINING_RECORD(iface
, IClassFactoryImpl
, IClassFactory_iface
);
2381 static HRESULT WINAPI
2382 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2383 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2385 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2386 return E_NOINTERFACE
;
2390 SPCF_AddRef(LPCLASSFACTORY iface
) {
2391 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2392 return InterlockedIncrement(&This
->ref
);
2395 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2396 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2397 /* static class, won't be freed */
2398 return InterlockedDecrement(&This
->ref
);
2401 static HRESULT WINAPI
SPCF_CreateInstance(
2402 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2404 /* Creates an uninitialized picture */
2405 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2409 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2410 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2411 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2415 static const IClassFactoryVtbl SPCF_Vtbl
= {
2416 SPCF_QueryInterface
,
2419 SPCF_CreateInstance
,
2422 static IClassFactoryImpl STDPIC_CF
= {{&SPCF_Vtbl
}, 1 };
2424 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= &STDPIC_CF
; }