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).
39 #define WIN32_NO_STATUS
43 //#include "wine/port.h"
53 #define NONAMELESSUNION
54 #define NONAMELESSSTRUCT
56 //#include "winerror.h"
60 //#include "winuser.h"
63 //#include "oleauto.h"
68 #include <wine/debug.h>
69 #include <wine/unicode.h>
70 //#include "wine/library.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(olepicture
);
74 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
75 #define BITMAP_FORMAT_JPEG 0xd8ff
76 #define BITMAP_FORMAT_GIF 0x4947
77 #define BITMAP_FORMAT_PNG 0x5089
78 #define BITMAP_FORMAT_APM 0xcdd7
82 /* Header for Aldus Placable Metafiles - a standard metafile follows */
83 typedef struct _APM_HEADER
105 } CURSORICONFILEDIRENTRY
;
112 CURSORICONFILEDIRENTRY idEntries
[1];
117 /*************************************************************************
118 * Declaration of implementation class
121 typedef struct OLEPictureImpl
{
124 * IPicture handles IUnknown
127 IPicture IPicture_iface
;
128 IDispatch IDispatch_iface
;
129 IPersistStream IPersistStream_iface
;
130 IConnectionPointContainer IConnectionPointContainer_iface
;
132 /* Object reference count */
135 /* We own the object and must destroy it ourselves */
138 /* Picture description */
141 /* These are the pixel size of a bitmap */
145 /* And these are the size of the picture converted into HIMETRIC units */
146 OLE_XSIZE_HIMETRIC himetricWidth
;
147 OLE_YSIZE_HIMETRIC himetricHeight
;
149 IConnectionPoint
*pCP
;
153 HBITMAP stock_bitmap
;
155 /* Bitmap transparency mask */
163 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
164 unsigned int loadtime_magic
; /* If a length header was found, saves value */
165 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
168 static inline OLEPictureImpl
*impl_from_IPicture(IPicture
*iface
)
170 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPicture_iface
);
173 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
175 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IDispatch_iface
);
178 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
180 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPersistStream_iface
);
183 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
185 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IConnectionPointContainer_iface
);
189 * Predeclare VTables. They get initialized at the end.
191 static const IPictureVtbl OLEPictureImpl_VTable
;
192 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
193 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
194 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
196 /* pixels to HIMETRIC units conversion */
197 static inline OLE_XSIZE_HIMETRIC
xpixels_to_himetric(INT pixels
, HDC hdc
)
199 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
202 static inline OLE_YSIZE_HIMETRIC
ypixels_to_himetric(INT pixels
, HDC hdc
)
204 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
207 /***********************************************************************
208 * Implementation of the OLEPictureImpl class.
211 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
)
216 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
217 if(GetObjectW(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
218 ERR("GetObject fails\n");
221 This
->origWidth
= bm
.bmWidth
;
222 This
->origHeight
= bm
.bmHeight
;
224 TRACE("width %d, height %d, bpp %d\n", bm
.bmWidth
, bm
.bmHeight
, bm
.bmBitsPixel
);
226 /* The width and height are stored in HIMETRIC units (0.01 mm),
227 so we take our pixel width divide by pixels per inch and
228 multiply by 25.4 * 100 */
229 /* Should we use GetBitmapDimension if available? */
230 hdcRef
= CreateCompatibleDC(0);
232 This
->himetricWidth
= xpixels_to_himetric(bm
.bmWidth
, hdcRef
);
233 This
->himetricHeight
= ypixels_to_himetric(bm
.bmHeight
, hdcRef
);
234 This
->stock_bitmap
= GetCurrentObject( hdcRef
, OBJ_BITMAP
);
236 This
->loadtime_format
= BITMAP_FORMAT_BMP
;
241 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
245 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
246 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
250 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
251 if(GetObjectW(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
252 ERR("GetObject fails on icon bitmap\n");
256 This
->origWidth
= bm
.bmWidth
;
257 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
258 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
261 This
->himetricWidth
= xpixels_to_himetric(This
->origWidth
, hdcRef
);
262 This
->himetricHeight
= ypixels_to_himetric(This
->origHeight
, hdcRef
);
264 ReleaseDC(0, hdcRef
);
266 DeleteObject(infoIcon
.hbmMask
);
267 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
269 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
273 /************************************************************************
274 * OLEPictureImpl_Construct
276 * This method will construct a new instance of the OLEPictureImpl
279 * The caller of this method must release the object when it's
282 static OLEPictureImpl
* OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
)
284 OLEPictureImpl
* newObject
= 0;
287 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
290 * Allocate space for the object.
292 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
298 * Initialize the virtual function table.
300 newObject
->IPicture_iface
.lpVtbl
= &OLEPictureImpl_VTable
;
301 newObject
->IDispatch_iface
.lpVtbl
= &OLEPictureImpl_IDispatch_VTable
;
302 newObject
->IPersistStream_iface
.lpVtbl
= &OLEPictureImpl_IPersistStream_VTable
;
303 newObject
->IConnectionPointContainer_iface
.lpVtbl
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
305 newObject
->pCP
= NULL
;
306 CreateConnectionPoint((IUnknown
*)newObject
,&IID_IPropertyNotifySink
,&newObject
->pCP
);
309 HeapFree(GetProcessHeap(), 0, newObject
);
314 * Start with one reference count. The caller of this function
315 * must release the interface pointer when it is done.
318 newObject
->hDCCur
= 0;
320 newObject
->fOwn
= fOwn
;
322 /* dunno about original value */
323 newObject
->keepOrigFormat
= TRUE
;
325 newObject
->hbmMask
= NULL
;
326 newObject
->hbmXor
= NULL
;
327 newObject
->loadtime_magic
= 0xdeadbeef;
328 newObject
->loadtime_format
= 0;
329 newObject
->bIsDirty
= FALSE
;
332 newObject
->desc
= *pictDesc
;
334 switch(pictDesc
->picType
) {
336 OLEPictureImpl_SetBitmap(newObject
);
339 case PICTYPE_METAFILE
:
340 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
341 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
342 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
346 /* not sure what to do here */
347 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
351 OLEPictureImpl_SetIcon(newObject
);
353 case PICTYPE_ENHMETAFILE
:
355 FIXME("Unsupported type %d\n", pictDesc
->picType
);
356 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
360 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
363 TRACE("returning %p\n", newObject
);
367 /************************************************************************
368 * OLEPictureImpl_Destroy
370 * This method is called by the Release method when the reference
371 * count goes down to 0. It will free all resources used by
373 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
375 TRACE("(%p)\n", Obj
);
378 IConnectionPoint_Release(Obj
->pCP
);
380 if(Obj
->fOwn
) { /* We need to destroy the picture */
381 switch(Obj
->desc
.picType
) {
383 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
384 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
385 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
387 case PICTYPE_METAFILE
:
388 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
391 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
393 case PICTYPE_ENHMETAFILE
:
394 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
397 case PICTYPE_UNINITIALIZED
:
401 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
405 HeapFree(GetProcessHeap(), 0, Obj
->data
);
406 HeapFree(GetProcessHeap(), 0, Obj
);
410 /************************************************************************
411 * OLEPictureImpl_AddRef (IUnknown)
413 * See Windows documentation for more details on IUnknown methods.
415 static ULONG WINAPI
OLEPictureImpl_AddRef(
418 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
419 ULONG refCount
= InterlockedIncrement(&This
->ref
);
421 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
426 /************************************************************************
427 * OLEPictureImpl_Release (IUnknown)
429 * See Windows documentation for more details on IUnknown methods.
431 static ULONG WINAPI
OLEPictureImpl_Release(
434 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
435 ULONG refCount
= InterlockedDecrement(&This
->ref
);
437 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
440 * If the reference count goes down to 0, perform suicide.
442 if (!refCount
) OLEPictureImpl_Destroy(This
);
447 /************************************************************************
448 * OLEPictureImpl_QueryInterface (IUnknown)
450 * See Windows documentation for more details on IUnknown methods.
452 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
457 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
459 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
466 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
468 else if (IsEqualIID(&IID_IDispatch
, riid
))
469 *ppvObject
= &This
->IDispatch_iface
;
470 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
471 *ppvObject
= &This
->IDispatch_iface
;
472 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
473 *ppvObject
= &This
->IPersistStream_iface
;
474 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
475 *ppvObject
= &This
->IConnectionPointContainer_iface
;
479 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
480 return E_NOINTERFACE
;
483 IPicture_AddRef(iface
);
488 /***********************************************************************
489 * OLEPicture_SendNotify (internal)
491 * Sends notification messages of changed properties to any interested
494 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
496 IEnumConnections
*pEnum
;
499 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
) != S_OK
)
501 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
502 IPropertyNotifySink
*sink
;
504 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
505 IPropertyNotifySink_OnChanged(sink
, dispID
);
506 IPropertyNotifySink_Release(sink
);
507 IUnknown_Release(CD
.pUnk
);
509 IEnumConnections_Release(pEnum
);
512 /************************************************************************
513 * OLEPictureImpl_get_Handle
515 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
518 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
519 TRACE("(%p)->(%p)\n", This
, phandle
);
524 switch(This
->desc
.picType
) {
526 case PICTYPE_UNINITIALIZED
:
530 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
532 case PICTYPE_METAFILE
:
533 *phandle
= HandleToUlong(This
->desc
.u
.wmf
.hmeta
);
536 *phandle
= HandleToUlong(This
->desc
.u
.icon
.hicon
);
538 case PICTYPE_ENHMETAFILE
:
539 *phandle
= HandleToUlong(This
->desc
.u
.emf
.hemf
);
542 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
545 TRACE("returning handle %08x\n", *phandle
);
549 /************************************************************************
550 * OLEPictureImpl_get_hPal
552 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
555 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
557 TRACE("(%p)->(%p)\n", This
, phandle
);
562 switch (This
->desc
.picType
) {
563 case (UINT
)PICTYPE_UNINITIALIZED
:
569 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hpal
);
572 case PICTYPE_METAFILE
:
576 case PICTYPE_ENHMETAFILE
:
578 FIXME("unimplemented for type %d. Returning 0 palette.\n",
584 TRACE("returning 0x%08x, palette handle %08x\n", hres
, *phandle
);
588 /************************************************************************
589 * OLEPictureImpl_get_Type
591 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
594 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
595 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
600 *ptype
= This
->desc
.picType
;
604 /************************************************************************
605 * OLEPictureImpl_get_Width
607 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
608 OLE_XSIZE_HIMETRIC
*pwidth
)
610 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
611 TRACE("(%p)->(%p): width is %d\n", This
, pwidth
, This
->himetricWidth
);
612 *pwidth
= This
->himetricWidth
;
616 /************************************************************************
617 * OLEPictureImpl_get_Height
619 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
620 OLE_YSIZE_HIMETRIC
*pheight
)
622 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
623 TRACE("(%p)->(%p): height is %d\n", This
, pheight
, This
->himetricHeight
);
624 *pheight
= This
->himetricHeight
;
628 /************************************************************************
629 * OLEPictureImpl_Render
631 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
632 LONG x
, LONG y
, LONG cx
, LONG cy
,
633 OLE_XPOS_HIMETRIC xSrc
,
634 OLE_YPOS_HIMETRIC ySrc
,
635 OLE_XSIZE_HIMETRIC cxSrc
,
636 OLE_YSIZE_HIMETRIC cySrc
,
639 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
640 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
641 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
643 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds
->left
, prcWBounds
->top
,
644 prcWBounds
->right
, prcWBounds
->bottom
);
646 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
647 return CTL_E_INVALIDPROPERTYVALUE
;
651 * While the documentation suggests this to be here (or after rendering?)
652 * it does cause an endless recursion in my sample app. -MM 20010804
653 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
656 switch(This
->desc
.picType
) {
657 case PICTYPE_UNINITIALIZED
:
666 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
667 NB y-axis gets flipped */
669 hdcBmp
= CreateCompatibleDC(0);
670 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
671 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
672 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
673 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
674 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
677 HDC hdcMask
= CreateCompatibleDC(0);
678 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
680 hbmpOld
= SelectObject(hdcBmp
, This
->hbmXor
);
682 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
683 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
684 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
685 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
686 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
688 SetBkColor(hdc
, RGB(255, 255, 255));
689 SetTextColor(hdc
, RGB(0, 0, 0));
690 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
691 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
693 SelectObject(hdcMask
, hOldbm
);
696 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
697 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
700 SelectObject(hdcBmp
, hbmpOld
);
705 FIXME("Not quite correct implementation of rendering icons...\n");
706 DrawIconEx(hdc
, x
, y
, This
->desc
.u
.icon
.hicon
, cx
, cy
, 0, NULL
, DI_NORMAL
);
709 case PICTYPE_METAFILE
:
711 POINT prevOrg
, prevWndOrg
;
712 SIZE prevExt
, prevWndExt
;
715 /* Render the WMF to the appropriate location by setting the
716 appropriate ratio between "device units" and "logical units" */
717 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
718 /* For the "source rectangle" the y-axis must be inverted */
719 SetWindowOrgEx(hdc
, xSrc
, This
->himetricHeight
-ySrc
, &prevWndOrg
);
720 SetWindowExtEx(hdc
, cxSrc
, -cySrc
, &prevWndExt
);
721 /* For the "destination rectangle" no inversion is necessary */
722 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
723 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
725 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
726 ERR("PlayMetaFile failed!\n");
728 /* We're done, restore the DC to the previous settings for converting
729 logical units to device units */
730 SetWindowExtEx(hdc
, prevWndExt
.cx
, prevWndExt
.cy
, NULL
);
731 SetWindowOrgEx(hdc
, prevWndOrg
.x
, prevWndOrg
.y
, NULL
);
732 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
733 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
734 SetMapMode(hdc
, oldmode
);
738 case PICTYPE_ENHMETAFILE
:
740 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
741 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
746 FIXME("type %d not implemented\n", This
->desc
.picType
);
752 /************************************************************************
753 * OLEPictureImpl_set_hPal
755 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
758 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
759 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
760 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
764 /************************************************************************
765 * OLEPictureImpl_get_CurDC
767 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
770 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
771 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
772 if (phdc
) *phdc
= This
->hDCCur
;
776 /************************************************************************
777 * OLEPictureImpl_SelectPicture
779 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
782 OLE_HANDLE
*phbmpOut
)
784 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
785 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
786 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
788 *phdcOut
= This
->hDCCur
;
789 if (This
->hDCCur
) SelectObject(This
->hDCCur
,This
->stock_bitmap
);
790 if (hdcIn
) SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
791 This
->hDCCur
= hdcIn
;
793 *phbmpOut
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
796 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
801 /************************************************************************
802 * OLEPictureImpl_get_KeepOriginalFormat
804 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
807 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
808 TRACE("(%p)->(%p)\n", This
, pfKeep
);
811 *pfKeep
= This
->keepOrigFormat
;
815 /************************************************************************
816 * OLEPictureImpl_put_KeepOriginalFormat
818 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
821 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
822 TRACE("(%p)->(%d)\n", This
, keep
);
823 This
->keepOrigFormat
= keep
;
824 /* FIXME: what DISPID notification here? */
828 /************************************************************************
829 * OLEPictureImpl_PictureChanged
831 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
833 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
834 TRACE("(%p)->()\n", This
);
835 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
836 This
->bIsDirty
= TRUE
;
840 /************************************************************************
841 * OLEPictureImpl_SaveAsFile
843 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
848 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
849 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
850 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
853 /************************************************************************
854 * OLEPictureImpl_get_Attributes
856 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
859 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
860 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
866 switch (This
->desc
.picType
) {
867 case PICTYPE_UNINITIALIZED
:
868 case PICTYPE_NONE
: break;
869 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
870 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
871 case PICTYPE_ENHMETAFILE
: /* fall through */
872 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
873 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
879 /************************************************************************
880 * IConnectionPointContainer
882 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
883 IConnectionPointContainer
* iface
,
887 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
889 return IPicture_QueryInterface(&This
->IPicture_iface
,riid
,ppvoid
);
892 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
893 IConnectionPointContainer
* iface
)
895 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
897 return IPicture_AddRef(&This
->IPicture_iface
);
900 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
901 IConnectionPointContainer
* iface
)
903 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
905 return IPicture_Release(&This
->IPicture_iface
);
908 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
909 IConnectionPointContainer
* iface
,
910 IEnumConnectionPoints
** ppEnum
)
912 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
914 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
918 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
919 IConnectionPointContainer
* iface
,
921 IConnectionPoint
**ppCP
)
923 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
924 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
928 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
929 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
930 FIXME("no connection point for %s\n",debugstr_guid(riid
));
931 return CONNECT_E_NOCONNECTION
;
935 /************************************************************************
939 /************************************************************************
940 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
942 * See Windows documentation for more details on IUnknown methods.
944 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
945 IPersistStream
* iface
,
949 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
951 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
954 /************************************************************************
955 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
957 * See Windows documentation for more details on IUnknown methods.
959 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
960 IPersistStream
* iface
)
962 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
964 return IPicture_AddRef(&This
->IPicture_iface
);
967 /************************************************************************
968 * OLEPictureImpl_IPersistStream_Release (IUnknown)
970 * See Windows documentation for more details on IUnknown methods.
972 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
973 IPersistStream
* iface
)
975 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
977 return IPicture_Release(&This
->IPicture_iface
);
980 /************************************************************************
981 * OLEPictureImpl_IPersistStream_GetClassID
983 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
984 IPersistStream
* iface
,CLSID
* pClassID
)
986 TRACE("(%p)\n", pClassID
);
987 *pClassID
= CLSID_StdPicture
;
991 /************************************************************************
992 * OLEPictureImpl_IPersistStream_IsDirty
994 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
995 IPersistStream
* iface
)
997 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
998 FIXME("(%p),stub!\n",This
);
1002 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1004 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1005 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1008 /* Does not matter whether this is a coreheader or not, we only use
1009 * components which are in both
1012 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1016 xbuf
+bfh
->bfOffBits
,
1020 ReleaseDC(0, hdcref
);
1021 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1023 This
->desc
.picType
= PICTYPE_BITMAP
;
1024 OLEPictureImpl_SetBitmap(This
);
1028 static HRESULT
OLEPictureImpl_LoadWICSource(OLEPictureImpl
*This
, IWICBitmapSource
*src
)
1031 BITMAPINFOHEADER bih
;
1034 UINT stride
, buffersize
;
1037 IWICBitmapSource
*real_source
;
1039 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1040 BOOL has_alpha
=FALSE
;
1042 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
, src
, &real_source
);
1043 if (FAILED(hr
)) return hr
;
1045 hr
= IWICBitmapSource_GetSize(real_source
, &width
, &height
);
1046 if (FAILED(hr
)) goto end
;
1048 bih
.biSize
= sizeof(bih
);
1049 bih
.biWidth
= width
;
1050 bih
.biHeight
= -height
;
1052 bih
.biBitCount
= 32;
1053 bih
.biCompression
= BI_RGB
;
1054 bih
.biSizeImage
= 0;
1055 bih
.biXPelsPerMeter
= 4085; /* olepicture ignores the stored resolution */
1056 bih
.biYPelsPerMeter
= 4085;
1058 bih
.biClrImportant
= 0;
1061 buffersize
= stride
* height
;
1063 bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
1074 hr
= IWICBitmapSource_CopyPixels(real_source
, &rc
, stride
, buffersize
, bits
);
1079 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1087 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1090 ReleaseDC(0, hdcref
);
1094 This
->desc
.picType
= PICTYPE_BITMAP
;
1095 OLEPictureImpl_SetBitmap(This
);
1097 /* set transparent pixels to black, all others to white */
1098 for(y
= 0; y
< height
; y
++){
1099 for(x
= 0; x
< width
; x
++){
1100 DWORD
*pixel
= (DWORD
*)(bits
+ stride
*y
+ 4*x
);
1101 if((*pixel
& 0x80000000) == 0)
1113 HDC hdcBmp
, hdcXor
, hdcMask
;
1114 HBITMAP hbmoldBmp
, hbmoldXor
, hbmoldMask
;
1116 This
->hbmXor
= CreateDIBitmap(
1125 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1126 hdcBmp
= CreateCompatibleDC(NULL
);
1127 hdcXor
= CreateCompatibleDC(NULL
);
1128 hdcMask
= CreateCompatibleDC(NULL
);
1130 hbmoldBmp
= SelectObject(hdcBmp
,This
->desc
.u
.bmp
.hbitmap
);
1131 hbmoldXor
= SelectObject(hdcXor
,This
->hbmXor
);
1132 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1134 SetBkColor(hdcXor
,black
);
1135 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1136 BitBlt(hdcXor
,0,0,width
,height
,hdcBmp
,0,0,SRCAND
);
1138 SelectObject(hdcBmp
,hbmoldBmp
);
1139 SelectObject(hdcXor
,hbmoldXor
);
1140 SelectObject(hdcMask
,hbmoldMask
);
1147 ReleaseDC(0, hdcref
);
1150 HeapFree(GetProcessHeap(), 0, bits
);
1151 IWICBitmapSource_Release(real_source
);
1155 static HRESULT
OLEPictureImpl_LoadWICDecoder(OLEPictureImpl
*This
, REFCLSID decoder_clsid
, BYTE
*xbuf
, ULONG xread
)
1158 IWICImagingFactory
*factory
;
1159 IWICBitmapDecoder
*decoder
;
1160 IWICBitmapFrameDecode
*framedecode
;
1164 initresult
= CoInitialize(NULL
);
1166 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
1167 &IID_IWICImagingFactory
, (void**)&factory
);
1168 if (SUCCEEDED(hr
)) /* created factory */
1170 hr
= IWICImagingFactory_CreateStream(factory
, &stream
);
1171 IWICImagingFactory_Release(factory
);
1174 if (SUCCEEDED(hr
)) /* created stream */
1176 hr
= IWICStream_InitializeFromMemory(stream
, xbuf
, xread
);
1178 if (SUCCEEDED(hr
)) /* initialized stream */
1180 hr
= CoCreateInstance(decoder_clsid
, NULL
, CLSCTX_INPROC_SERVER
,
1181 &IID_IWICBitmapDecoder
, (void**)&decoder
);
1182 if (SUCCEEDED(hr
)) /* created decoder */
1184 hr
= IWICBitmapDecoder_Initialize(decoder
, (IStream
*)stream
, WICDecodeMetadataCacheOnLoad
);
1186 if (SUCCEEDED(hr
)) /* initialized decoder */
1187 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
1189 IWICBitmapDecoder_Release(decoder
);
1193 IWICStream_Release(stream
);
1196 if (SUCCEEDED(hr
)) /* got framedecode */
1198 hr
= OLEPictureImpl_LoadWICSource(This
, (IWICBitmapSource
*)framedecode
);
1199 IWICBitmapFrameDecode_Release(framedecode
);
1202 if (SUCCEEDED(initresult
)) CoUninitialize();
1206 /*****************************************************
1207 * start of Icon-specific code
1210 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1213 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1218 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1219 FIXME("icon.idType=%d\n",cifd->idType);
1220 FIXME("icon.idCount=%d\n",cifd->idCount);
1222 for (i=0;i<cifd->idCount;i++) {
1223 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1224 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1225 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1226 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1227 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1228 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1229 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1230 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1234 /* If we have more than one icon, try to find the best.
1235 * this currently means '32 pixel wide'.
1237 if (cifd
->idCount
!=1) {
1238 for (i
=0;i
<cifd
->idCount
;i
++) {
1239 if (cifd
->idEntries
[i
].bWidth
== 32)
1242 if (i
==cifd
->idCount
) i
=0;
1244 if (cifd
->idType
== 2)
1246 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, cifd
->idEntries
[i
].dwDIBSize
+ 4);
1247 memcpy(buf
, &cifd
->idEntries
[i
].xHotspot
, 4);
1248 memcpy(buf
+ 4, xbuf
+cifd
->idEntries
[i
].dwDIBOffset
, cifd
->idEntries
[i
].dwDIBSize
);
1249 hicon
= CreateIconFromResourceEx(
1251 cifd
->idEntries
[i
].dwDIBSize
+ 4,
1252 FALSE
, /* is cursor */
1254 cifd
->idEntries
[i
].bWidth
,
1255 cifd
->idEntries
[i
].bHeight
,
1258 HeapFree(GetProcessHeap(), 0, buf
);
1262 hicon
= CreateIconFromResourceEx(
1263 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1264 cifd
->idEntries
[i
].dwDIBSize
,
1267 cifd
->idEntries
[i
].bWidth
,
1268 cifd
->idEntries
[i
].bHeight
,
1273 ERR("CreateIcon failed.\n");
1276 This
->desc
.picType
= PICTYPE_ICON
;
1277 This
->desc
.u
.icon
.hicon
= hicon
;
1278 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1279 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1280 hdcRef
= CreateCompatibleDC(0);
1281 This
->himetricWidth
= xpixels_to_himetric(cifd
->idEntries
[i
].bWidth
, hdcRef
);
1282 This
->himetricHeight
= ypixels_to_himetric(cifd
->idEntries
[i
].bHeight
, hdcRef
);
1288 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1289 const BYTE
*data
, ULONG size
)
1294 hemf
= SetEnhMetaFileBits(size
, data
);
1295 if (!hemf
) return E_FAIL
;
1297 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1299 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1300 This
->desc
.u
.emf
.hemf
= hemf
;
1302 This
->origWidth
= 0;
1303 This
->origHeight
= 0;
1304 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1305 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1310 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1311 const BYTE
*data
, ULONG size
)
1313 const APM_HEADER
*header
= (const APM_HEADER
*)data
;
1316 if (size
< sizeof(APM_HEADER
))
1318 if (header
->key
!= 0x9ac6cdd7)
1321 /* SetMetaFileBitsEx performs data check on its own */
1322 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1323 if (!hmf
) return E_FAIL
;
1325 This
->desc
.picType
= PICTYPE_METAFILE
;
1326 This
->desc
.u
.wmf
.hmeta
= hmf
;
1327 This
->desc
.u
.wmf
.xExt
= 0;
1328 This
->desc
.u
.wmf
.yExt
= 0;
1330 This
->origWidth
= 0;
1331 This
->origHeight
= 0;
1332 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1333 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1337 /************************************************************************
1338 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1340 * Loads the binary data from the IStream. Starts at current position.
1341 * There appears to be an 2 DWORD header:
1345 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
1347 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
, IStream
*pStm
) {
1350 BOOL statfailed
= FALSE
;
1351 ULONG xread
, toread
;
1357 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1359 TRACE("(%p,%p)\n",This
,pStm
);
1361 /****************************************************************************************
1362 * Part 1: Load the data
1364 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1365 * out whether we do.
1367 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1368 * compound file. This may explain most, if not all, of the cases of "no
1369 * header", and the header validation should take this into account.
1370 * At least in Visual Basic 6, resource streams, valid headers are
1371 * header[0] == "lt\0\0",
1372 * header[1] == length_of_stream.
1374 * Also handle streams where we do not have a working "Stat" method by
1375 * reading all data until the end of the stream.
1377 hr
= IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1379 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr
);
1381 /* we will read at least 8 byte ... just right below */
1382 statstg
.cbSize
.QuadPart
= 8;
1387 headerisdata
= FALSE
;
1389 hr
= IStream_Read(pStm
, header
, 8, &xread
);
1390 if (hr
!= S_OK
|| xread
!=8) {
1391 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr
,xread
);
1392 return (hr
?hr
:E_FAIL
);
1394 headerread
+= xread
;
1397 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1398 if (toread
!= 0 && toread
!= header
[1])
1399 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1402 if (toread
== 0) break;
1404 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1405 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1406 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1407 (header
[0] == EMR_HEADER
) || /* EMF header */
1408 (header
[0] == 0x10000) || /* icon: idReserved 0, idType 1 */
1409 (header
[0] == 0x20000) || /* cursor: idReserved 0, idType 2 */
1410 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1412 ) {/* Found start of bitmap data */
1413 headerisdata
= TRUE
;
1415 toread
= statstg
.cbSize
.QuadPart
-8;
1419 FIXME("Unknown stream header magic: %08x\n", header
[0]);
1423 } while (!headerisdata
);
1425 if (statfailed
) { /* we don't know the size ... read all we get */
1426 unsigned int sizeinc
= 4096;
1427 unsigned int origsize
= sizeinc
;
1430 TRACE("Reading all data from stream.\n");
1431 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1433 memcpy (xbuf
, header
, 8);
1435 while (xread
< origsize
) {
1436 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1438 if (hr
!= S_OK
|| !nread
)
1441 if (!nread
|| hr
!= S_OK
) /* done, or error */
1443 if (xread
== origsize
) {
1444 origsize
+= sizeinc
;
1445 sizeinc
= 2*sizeinc
; /* exponential increase */
1446 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1450 TRACE("hr in no-stat loader case is %08x\n", hr
);
1451 TRACE("loaded %d bytes.\n", xread
);
1452 This
->datalen
= xread
;
1455 This
->datalen
= toread
+(headerisdata
?8:0);
1456 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1458 return E_OUTOFMEMORY
;
1461 memcpy (xbuf
, header
, 8);
1463 while (xread
< This
->datalen
) {
1465 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1467 if (hr
!= S_OK
|| !nread
)
1470 if (xread
!= This
->datalen
)
1471 ERR("Could only read %d of %d bytes out of stream?\n",xread
,This
->datalen
);
1473 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1474 This
->desc
.picType
= PICTYPE_NONE
;
1479 /****************************************************************************************
1480 * Part 2: Process the loaded data
1483 magic
= xbuf
[0] + (xbuf
[1]<<8);
1484 This
->loadtime_format
= magic
;
1487 case BITMAP_FORMAT_GIF
: /* GIF */
1488 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICGifDecoder
, xbuf
, xread
);
1490 case BITMAP_FORMAT_JPEG
: /* JPEG */
1491 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICJpegDecoder
, xbuf
, xread
);
1493 case BITMAP_FORMAT_BMP
: /* Bitmap */
1494 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1496 case BITMAP_FORMAT_PNG
: /* PNG */
1497 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICPngDecoder
, xbuf
, xread
);
1499 case BITMAP_FORMAT_APM
: /* APM */
1500 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1502 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1503 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1510 /* let's see if it's a EMF */
1511 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1512 if (hr
== S_OK
) break;
1514 FIXME("Unknown magic %04x, %d read bytes:\n",magic
,xread
);
1516 for (i
=0;i
<xread
+8;i
++) {
1517 if (i
<8) MESSAGE("%02x ",((unsigned char*)header
)[i
]);
1518 else MESSAGE("%02x ",xbuf
[i
-8]);
1519 if (i
% 10 == 9) MESSAGE("\n");
1525 This
->bIsDirty
= FALSE
;
1527 /* FIXME: this notify is not really documented */
1529 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1533 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1537 BITMAPINFO
* pInfoBitmap
;
1538 int iNumPaletteEntries
;
1539 unsigned char * pPixelData
;
1540 BITMAPFILEHEADER
* pFileHeader
;
1541 BITMAPINFO
* pInfoHeader
;
1543 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1544 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1546 /* Find out bitmap size and padded length */
1548 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1549 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1551 /* Fetch bitmap palette & pixel data */
1553 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1554 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1556 /* Calculate the total length required for the BMP data */
1557 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1558 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1559 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1561 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1562 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1564 iNumPaletteEntries
= 0;
1567 sizeof(BITMAPFILEHEADER
) +
1568 sizeof(BITMAPINFOHEADER
) +
1569 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1570 pInfoBitmap
->bmiHeader
.biSizeImage
;
1571 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1573 /* Fill the BITMAPFILEHEADER */
1574 pFileHeader
= *ppBuffer
;
1575 pFileHeader
->bfType
= BITMAP_FORMAT_BMP
;
1576 pFileHeader
->bfSize
= *pLength
;
1577 pFileHeader
->bfOffBits
=
1578 sizeof(BITMAPFILEHEADER
) +
1579 sizeof(BITMAPINFOHEADER
) +
1580 iNumPaletteEntries
* sizeof(RGBQUAD
);
1582 /* Fill the BITMAPINFOHEADER and the palette data */
1583 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1584 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1586 (unsigned char *)(*ppBuffer
) +
1587 sizeof(BITMAPFILEHEADER
) +
1588 sizeof(BITMAPINFOHEADER
) +
1589 iNumPaletteEntries
* sizeof(RGBQUAD
),
1590 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1593 HeapFree(GetProcessHeap(), 0, pPixelData
);
1594 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1598 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1603 *ppBuffer
= NULL
; *pLength
= 0;
1604 if (GetIconInfo(hIcon
, &infoIcon
)) {
1606 BITMAPINFO
* pInfoBitmap
;
1607 unsigned char * pIconData
= NULL
;
1608 unsigned int iDataSize
= 0;
1610 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1612 /* Find out icon size */
1614 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1615 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1617 /* Auxiliary pointers */
1618 CURSORICONFILEDIR
* pIconDir
;
1619 CURSORICONFILEDIRENTRY
* pIconEntry
;
1620 BITMAPINFOHEADER
* pIconBitmapHeader
;
1621 unsigned int iOffsetPalette
;
1622 unsigned int iOffsetColorData
;
1623 unsigned int iOffsetMaskData
;
1625 unsigned int iLengthScanLineMask
;
1626 unsigned int iNumEntriesPalette
;
1628 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1630 FIXME("DEBUG: bitmap size is %d x %d\n",
1631 pInfoBitmap->bmiHeader.biWidth,
1632 pInfoBitmap->bmiHeader.biHeight);
1633 FIXME("DEBUG: bitmap bpp is %d\n",
1634 pInfoBitmap->bmiHeader.biBitCount);
1635 FIXME("DEBUG: bitmap nplanes is %d\n",
1636 pInfoBitmap->bmiHeader.biPlanes);
1637 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1638 pInfoBitmap->bmiHeader.biSizeImage);
1640 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1641 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1642 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1644 /* Fill out the CURSORICONFILEDIR */
1645 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1646 pIconDir
->idType
= 1;
1647 pIconDir
->idCount
= 1;
1648 pIconDir
->idReserved
= 0;
1650 /* Fill out the CURSORICONFILEDIRENTRY */
1651 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1652 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1653 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1654 pIconEntry
->bColorCount
=
1655 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1656 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1658 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1659 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1660 pIconEntry
->dwDIBSize
= 0;
1661 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1663 /* Fill out the BITMAPINFOHEADER */
1664 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1665 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
1667 /* Find out whether a palette exists for the bitmap */
1668 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1669 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1670 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1671 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1672 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1673 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1674 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1675 iNumEntriesPalette
= 3;
1676 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1677 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1679 iNumEntriesPalette
= 0;
1682 /* Add bitmap size and header size to icon data size. */
1683 iOffsetPalette
= iDataSize
;
1684 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1685 iOffsetColorData
= iDataSize
;
1686 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1687 iOffsetMaskData
= iDataSize
;
1688 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1689 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1690 pIconBitmapHeader
->biHeight
*= 2;
1691 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1692 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1693 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1694 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1696 /* Get the actual bitmap data from the icon bitmap */
1697 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1698 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1699 if (iNumEntriesPalette
> 0) {
1700 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1701 iNumEntriesPalette
* sizeof(RGBQUAD
));
1704 /* Reset all values so that GetDIBits call succeeds */
1705 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1706 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1707 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1709 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1710 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1711 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1713 printf("ERROR: unable to get bitmap mask (error %u)\n",
1718 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1719 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1721 /* Write out everything produced so far to the stream */
1722 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1726 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1731 Remarks (from MSDN entry on GetIconInfo):
1733 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1734 members of ICONINFO. The calling application must manage
1735 these bitmaps and delete them when they are no longer
1738 if (hDC
) ReleaseDC(0, hDC
);
1739 DeleteObject(infoIcon
.hbmMask
);
1740 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1741 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1743 printf("ERROR: Unable to get icon information (error %u)\n",
1749 static HRESULT WINAPI
OLEPictureImpl_Save(
1750 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1752 HRESULT hResult
= E_NOTIMPL
;
1754 unsigned int iDataSize
;
1757 int iSerializeResult
= 0;
1758 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1760 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
1762 switch (This
->desc
.picType
) {
1764 header
[0] = 0x0000746c;
1766 hResult
= IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1770 if (This
->bIsDirty
|| !This
->data
) {
1771 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1772 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
1776 HeapFree(GetProcessHeap(), 0, This
->data
);
1777 This
->data
= pIconData
;
1778 This
->datalen
= iDataSize
;
1781 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1782 header
[1] = This
->datalen
;
1783 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1784 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1787 case PICTYPE_BITMAP
:
1788 if (This
->bIsDirty
|| !This
->data
) {
1789 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
1790 case BITMAP_FORMAT_BMP
:
1791 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1793 case BITMAP_FORMAT_JPEG
:
1794 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1796 case BITMAP_FORMAT_GIF
:
1797 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1799 case BITMAP_FORMAT_PNG
:
1800 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
1803 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1807 if (!iSerializeResult
)
1813 HeapFree(GetProcessHeap(), 0, This
->data
);
1814 This
->data
= pIconData
;
1815 This
->datalen
= iDataSize
;
1818 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1819 header
[1] = This
->datalen
;
1820 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1821 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1824 case PICTYPE_METAFILE
:
1825 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1827 case PICTYPE_ENHMETAFILE
:
1828 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1831 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1834 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1838 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1839 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1841 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1842 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1847 /************************************************************************
1851 /************************************************************************
1852 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1854 * See Windows documentation for more details on IUnknown methods.
1856 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1861 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1863 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
1866 /************************************************************************
1867 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1869 * See Windows documentation for more details on IUnknown methods.
1871 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1874 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1876 return IPicture_AddRef(&This
->IPicture_iface
);
1879 /************************************************************************
1880 * OLEPictureImpl_IDispatch_Release (IUnknown)
1882 * See Windows documentation for more details on IUnknown methods.
1884 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1887 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1889 return IPicture_Release(&This
->IPicture_iface
);
1892 /************************************************************************
1893 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1895 * See Windows documentation for more details on IDispatch methods.
1897 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1899 unsigned int* pctinfo
)
1901 TRACE("(%p)\n", pctinfo
);
1908 /************************************************************************
1909 * OLEPictureImpl_GetTypeInfo (IDispatch)
1911 * See Windows documentation for more details on IDispatch methods.
1913 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1917 ITypeInfo
** ppTInfo
)
1919 static const WCHAR stdole2tlb
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1923 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
1928 hres
= LoadTypeLib(stdole2tlb
, &tl
);
1931 ERR("Could not load stdole2.tlb\n");
1935 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
1937 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres
);
1942 /************************************************************************
1943 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1945 * See Windows documentation for more details on IDispatch methods.
1947 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1950 LPOLESTR
* rgszNames
,
1958 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
1959 rgszNames
, cNames
, (int)lcid
, rgDispId
);
1963 return E_INVALIDARG
;
1967 /* retrieve type information */
1968 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
1972 ERR("GetTypeInfo failed.\n");
1976 /* convert names to DISPIDs */
1977 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
1978 ITypeInfo_Release(pTInfo
);
1984 /************************************************************************
1985 * OLEPictureImpl_Invoke (IDispatch)
1987 * See Windows documentation for more details on IDispatch methods.
1989 static HRESULT WINAPI
OLEPictureImpl_Invoke(
1991 DISPID dispIdMember
,
1995 DISPPARAMS
* pDispParams
,
1996 VARIANT
* pVarResult
,
1997 EXCEPINFO
* pExepInfo
,
2000 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2002 /* validate parameters */
2004 if (!IsEqualIID(riid
, &IID_NULL
))
2006 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2007 return DISP_E_UNKNOWNNAME
;
2012 ERR("null pDispParams not allowed\n");
2013 return DISP_E_PARAMNOTOPTIONAL
;
2016 if (wFlags
& DISPATCH_PROPERTYGET
)
2018 if (pDispParams
->cArgs
!= 0)
2020 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2021 return DISP_E_BADPARAMCOUNT
;
2025 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2026 return DISP_E_PARAMNOTOPTIONAL
;
2029 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2031 if (pDispParams
->cArgs
!= 1)
2033 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2034 return DISP_E_BADPARAMCOUNT
;
2038 switch (dispIdMember
)
2040 case DISPID_PICT_HANDLE
:
2041 if (wFlags
& DISPATCH_PROPERTYGET
)
2043 TRACE("DISPID_PICT_HANDLE\n");
2044 V_VT(pVarResult
) = VT_I4
;
2045 return IPicture_get_Handle(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2048 case DISPID_PICT_HPAL
:
2049 if (wFlags
& DISPATCH_PROPERTYGET
)
2051 TRACE("DISPID_PICT_HPAL\n");
2052 V_VT(pVarResult
) = VT_I4
;
2053 return IPicture_get_hPal(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2055 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2059 TRACE("DISPID_PICT_HPAL\n");
2061 VariantInit(&vararg
);
2062 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2066 hr
= IPicture_set_hPal(&This
->IPicture_iface
, V_I4(&vararg
));
2068 VariantClear(&vararg
);
2072 case DISPID_PICT_TYPE
:
2073 if (wFlags
& DISPATCH_PROPERTYGET
)
2075 TRACE("DISPID_PICT_TYPE\n");
2076 V_VT(pVarResult
) = VT_I2
;
2077 return OLEPictureImpl_get_Type(&This
->IPicture_iface
, &V_I2(pVarResult
));
2080 case DISPID_PICT_WIDTH
:
2081 if (wFlags
& DISPATCH_PROPERTYGET
)
2083 TRACE("DISPID_PICT_WIDTH\n");
2084 V_VT(pVarResult
) = VT_I4
;
2085 return IPicture_get_Width(&This
->IPicture_iface
, &V_I4(pVarResult
));
2088 case DISPID_PICT_HEIGHT
:
2089 if (wFlags
& DISPATCH_PROPERTYGET
)
2091 TRACE("DISPID_PICT_HEIGHT\n");
2092 V_VT(pVarResult
) = VT_I4
;
2093 return IPicture_get_Height(&This
->IPicture_iface
, &V_I4(pVarResult
));
2098 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember
, wFlags
);
2099 return DISP_E_MEMBERNOTFOUND
;
2103 static const IPictureVtbl OLEPictureImpl_VTable
=
2105 OLEPictureImpl_QueryInterface
,
2106 OLEPictureImpl_AddRef
,
2107 OLEPictureImpl_Release
,
2108 OLEPictureImpl_get_Handle
,
2109 OLEPictureImpl_get_hPal
,
2110 OLEPictureImpl_get_Type
,
2111 OLEPictureImpl_get_Width
,
2112 OLEPictureImpl_get_Height
,
2113 OLEPictureImpl_Render
,
2114 OLEPictureImpl_set_hPal
,
2115 OLEPictureImpl_get_CurDC
,
2116 OLEPictureImpl_SelectPicture
,
2117 OLEPictureImpl_get_KeepOriginalFormat
,
2118 OLEPictureImpl_put_KeepOriginalFormat
,
2119 OLEPictureImpl_PictureChanged
,
2120 OLEPictureImpl_SaveAsFile
,
2121 OLEPictureImpl_get_Attributes
2124 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2126 OLEPictureImpl_IDispatch_QueryInterface
,
2127 OLEPictureImpl_IDispatch_AddRef
,
2128 OLEPictureImpl_IDispatch_Release
,
2129 OLEPictureImpl_GetTypeInfoCount
,
2130 OLEPictureImpl_GetTypeInfo
,
2131 OLEPictureImpl_GetIDsOfNames
,
2132 OLEPictureImpl_Invoke
2135 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2137 OLEPictureImpl_IPersistStream_QueryInterface
,
2138 OLEPictureImpl_IPersistStream_AddRef
,
2139 OLEPictureImpl_IPersistStream_Release
,
2140 OLEPictureImpl_GetClassID
,
2141 OLEPictureImpl_IsDirty
,
2142 OLEPictureImpl_Load
,
2143 OLEPictureImpl_Save
,
2144 OLEPictureImpl_GetSizeMax
2147 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2149 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2150 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2151 OLEPictureImpl_IConnectionPointContainer_Release
,
2152 OLEPictureImpl_EnumConnectionPoints
,
2153 OLEPictureImpl_FindConnectionPoint
2156 /***********************************************************************
2157 * OleCreatePictureIndirect (OLEAUT32.419)
2159 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2160 BOOL Own
, void **ppvObj
)
2162 OLEPictureImpl
* newPict
;
2165 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), Own
, ppvObj
);
2169 newPict
= OLEPictureImpl_Construct(lpPictDesc
, Own
);
2171 if (newPict
== NULL
)
2172 return E_OUTOFMEMORY
;
2175 * Make sure it supports the interface required by the caller.
2177 hr
= IPicture_QueryInterface(&newPict
->IPicture_iface
, riid
, ppvObj
);
2180 * Release the reference obtained in the constructor. If
2181 * the QueryInterface was unsuccessful, it will free the class.
2183 IPicture_Release(&newPict
->IPicture_iface
);
2189 /***********************************************************************
2190 * OleLoadPicture (OLEAUT32.418)
2192 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2193 REFIID riid
, LPVOID
*ppvObj
)
2199 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2200 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2202 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2205 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2207 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2208 IPicture_Release(newpic
);
2212 hr
= IPersistStream_Load(ps
,lpstream
);
2213 IPersistStream_Release(ps
);
2216 ERR("IPersistStream_Load failed\n");
2217 IPicture_Release(newpic
);
2221 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2223 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2224 IPicture_Release(newpic
);
2228 /***********************************************************************
2229 * OleLoadPictureEx (OLEAUT32.401)
2231 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2232 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2238 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2239 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2241 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2244 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2246 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2247 IPicture_Release(newpic
);
2251 hr
= IPersistStream_Load(ps
,lpstream
);
2252 IPersistStream_Release(ps
);
2255 ERR("IPersistStream_Load failed\n");
2256 IPicture_Release(newpic
);
2260 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2262 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2263 IPicture_Release(newpic
);
2267 /***********************************************************************
2268 * OleLoadPicturePath (OLEAUT32.424)
2270 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2271 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2274 static const WCHAR file
[] = { 'f','i','l','e',':',0 };
2278 HGLOBAL hGlobal
= NULL
;
2279 DWORD dwBytesRead
= 0;
2282 IPersistStream
*pStream
;
2285 WCHAR
*file_candidate
;
2286 WCHAR path_buf
[MAX_PATH
];
2288 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2289 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2290 debugstr_guid(riid
), ppvRet
);
2292 if (!szURLorPath
|| !ppvRet
)
2293 return E_INVALIDARG
;
2297 /* Convert file URLs to DOS paths. */
2298 if (strncmpW(szURLorPath
, file
, 5) == 0) {
2300 hRes
= CoInternetParseUrl(szURLorPath
, PARSE_PATH_FROM_URL
, 0, path_buf
,
2301 sizeof(path_buf
)/sizeof(WCHAR
), &size
, 0);
2305 file_candidate
= path_buf
;
2308 file_candidate
= szURLorPath
;
2310 /* Handle candidate DOS paths separately. */
2311 if (file_candidate
[1] == ':') {
2312 hFile
= CreateFileW(file_candidate
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2314 if (hFile
== INVALID_HANDLE_VALUE
)
2315 return INET_E_RESOURCE_NOT_FOUND
;
2317 dwFileSize
= GetFileSize(hFile
, NULL
);
2318 if (dwFileSize
!= INVALID_FILE_SIZE
)
2320 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2323 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
);
2326 GlobalFree(hGlobal
);
2334 return INET_E_RESOURCE_NOT_FOUND
;
2336 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2339 GlobalFree(hGlobal
);
2346 hRes
= CreateBindCtx(0, &pbc
);
2347 if (SUCCEEDED(hRes
))
2349 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2350 if (SUCCEEDED(hRes
))
2352 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2353 IMoniker_Release(pmnk
);
2355 IBindCtx_Release(pbc
);
2361 init_res
= CoInitialize(NULL
);
2363 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2364 &IID_IPicture
, (LPVOID
*)&ipicture
);
2365 if (SUCCEEDED(hRes
)) {
2366 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2368 if (SUCCEEDED(hRes
)) {
2369 hRes
= IPersistStream_Load(pStream
, stream
);
2371 if (SUCCEEDED(hRes
)) {
2372 hRes
= IPicture_QueryInterface(ipicture
, riid
, ppvRet
);
2375 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid
));
2377 IPersistStream_Release(pStream
);
2379 IPicture_Release(ipicture
);
2382 IStream_Release(stream
);
2384 if (SUCCEEDED(init_res
))
2390 /*******************************************************************************
2391 * StdPic ClassFactory
2395 /* IUnknown fields */
2396 IClassFactory IClassFactory_iface
;
2398 } IClassFactoryImpl
;
2400 static inline IClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
2402 return CONTAINING_RECORD(iface
, IClassFactoryImpl
, IClassFactory_iface
);
2405 static HRESULT WINAPI
2406 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2407 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2409 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2410 return E_NOINTERFACE
;
2414 SPCF_AddRef(LPCLASSFACTORY iface
) {
2415 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2416 return InterlockedIncrement(&This
->ref
);
2419 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2420 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2421 /* static class, won't be freed */
2422 return InterlockedDecrement(&This
->ref
);
2425 static HRESULT WINAPI
SPCF_CreateInstance(
2426 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2428 /* Creates an uninitialized picture */
2429 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2433 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2434 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2435 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2439 static const IClassFactoryVtbl SPCF_Vtbl
= {
2440 SPCF_QueryInterface
,
2443 SPCF_CreateInstance
,
2446 static IClassFactoryImpl STDPIC_CF
= {{&SPCF_Vtbl
}, 1 };
2448 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= &STDPIC_CF
; }