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).
40 #include "wine/port.h"
50 #define NONAMELESSUNION
51 #define NONAMELESSSTRUCT
65 #include "wine/debug.h"
66 #include "wine/unicode.h"
67 #include "wine/library.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(olepicture
);
71 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
72 #define BITMAP_FORMAT_JPEG 0xd8ff
73 #define BITMAP_FORMAT_GIF 0x4947
74 #define BITMAP_FORMAT_PNG 0x5089
75 #define BITMAP_FORMAT_APM 0xcdd7
79 /* Header for Aldus Placable Metafiles - a standard metafile follows */
80 typedef struct _APM_HEADER
102 } CURSORICONFILEDIRENTRY
;
109 CURSORICONFILEDIRENTRY idEntries
[1];
114 /*************************************************************************
115 * Declaration of implementation class
118 typedef struct OLEPictureImpl
{
121 * IPicture handles IUnknown
124 IPicture IPicture_iface
;
125 IDispatch IDispatch_iface
;
126 IPersistStream IPersistStream_iface
;
127 IConnectionPointContainer IConnectionPointContainer_iface
;
129 /* Object reference count */
132 /* We own the object and must destroy it ourselves */
135 /* Picture description */
138 /* These are the pixel size of a bitmap */
142 /* And these are the size of the picture converted into HIMETRIC units */
143 OLE_XSIZE_HIMETRIC himetricWidth
;
144 OLE_YSIZE_HIMETRIC himetricHeight
;
146 IConnectionPoint
*pCP
;
150 HBITMAP stock_bitmap
;
152 /* Bitmap transparency mask */
160 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
161 unsigned int loadtime_magic
; /* If a length header was found, saves value */
162 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
165 static inline OLEPictureImpl
*impl_from_IPicture(IPicture
*iface
)
167 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPicture_iface
);
170 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
172 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IDispatch_iface
);
175 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
177 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPersistStream_iface
);
180 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
182 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IConnectionPointContainer_iface
);
186 * Predeclare VTables. They get initialized at the end.
188 static const IPictureVtbl OLEPictureImpl_VTable
;
189 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
190 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
191 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
193 /* pixels to HIMETRIC units conversion */
194 static inline OLE_XSIZE_HIMETRIC
xpixels_to_himetric(INT pixels
, HDC hdc
)
196 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
199 static inline OLE_YSIZE_HIMETRIC
ypixels_to_himetric(INT pixels
, HDC hdc
)
201 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
204 /***********************************************************************
205 * Implementation of the OLEPictureImpl class.
208 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
)
213 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
214 if(GetObjectW(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
215 ERR("GetObject fails\n");
218 This
->origWidth
= bm
.bmWidth
;
219 This
->origHeight
= bm
.bmHeight
;
221 TRACE("width %d, height %d, bpp %d\n", bm
.bmWidth
, bm
.bmHeight
, bm
.bmBitsPixel
);
223 /* The width and height are stored in HIMETRIC units (0.01 mm),
224 so we take our pixel width divide by pixels per inch and
225 multiply by 25.4 * 100 */
226 /* Should we use GetBitmapDimension if available? */
227 hdcRef
= CreateCompatibleDC(0);
229 This
->himetricWidth
= xpixels_to_himetric(bm
.bmWidth
, hdcRef
);
230 This
->himetricHeight
= ypixels_to_himetric(bm
.bmHeight
, hdcRef
);
231 This
->stock_bitmap
= GetCurrentObject( hdcRef
, OBJ_BITMAP
);
233 This
->loadtime_format
= BITMAP_FORMAT_BMP
;
238 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
242 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
243 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
247 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
248 if(GetObjectW(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
249 ERR("GetObject fails on icon bitmap\n");
253 This
->origWidth
= bm
.bmWidth
;
254 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
255 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
258 This
->himetricWidth
= xpixels_to_himetric(This
->origWidth
, hdcRef
);
259 This
->himetricHeight
= ypixels_to_himetric(This
->origHeight
, hdcRef
);
261 ReleaseDC(0, hdcRef
);
263 DeleteObject(infoIcon
.hbmMask
);
264 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
266 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
270 /************************************************************************
271 * OLEPictureImpl_Construct
273 * This method will construct a new instance of the OLEPictureImpl
276 * The caller of this method must release the object when it's
279 static OLEPictureImpl
* OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
)
281 OLEPictureImpl
* newObject
= 0;
284 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
287 * Allocate space for the object.
289 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
295 * Initialize the virtual function table.
297 newObject
->IPicture_iface
.lpVtbl
= &OLEPictureImpl_VTable
;
298 newObject
->IDispatch_iface
.lpVtbl
= &OLEPictureImpl_IDispatch_VTable
;
299 newObject
->IPersistStream_iface
.lpVtbl
= &OLEPictureImpl_IPersistStream_VTable
;
300 newObject
->IConnectionPointContainer_iface
.lpVtbl
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
302 newObject
->pCP
= NULL
;
303 CreateConnectionPoint((IUnknown
*)newObject
,&IID_IPropertyNotifySink
,&newObject
->pCP
);
306 HeapFree(GetProcessHeap(), 0, newObject
);
311 * Start with one reference count. The caller of this function
312 * must release the interface pointer when it is done.
315 newObject
->hDCCur
= 0;
317 newObject
->fOwn
= fOwn
;
319 /* dunno about original value */
320 newObject
->keepOrigFormat
= TRUE
;
322 newObject
->hbmMask
= NULL
;
323 newObject
->hbmXor
= NULL
;
324 newObject
->loadtime_magic
= 0xdeadbeef;
325 newObject
->loadtime_format
= 0;
326 newObject
->bIsDirty
= FALSE
;
329 newObject
->desc
= *pictDesc
;
331 switch(pictDesc
->picType
) {
333 OLEPictureImpl_SetBitmap(newObject
);
336 case PICTYPE_METAFILE
:
337 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
338 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
339 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
343 /* not sure what to do here */
344 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
348 OLEPictureImpl_SetIcon(newObject
);
350 case PICTYPE_ENHMETAFILE
:
352 FIXME("Unsupported type %d\n", pictDesc
->picType
);
353 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
357 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
360 TRACE("returning %p\n", newObject
);
364 /************************************************************************
365 * OLEPictureImpl_Destroy
367 * This method is called by the Release method when the reference
368 * count goes down to 0. It will free all resources used by
370 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
372 TRACE("(%p)\n", Obj
);
375 IConnectionPoint_Release(Obj
->pCP
);
377 if(Obj
->fOwn
) { /* We need to destroy the picture */
378 switch(Obj
->desc
.picType
) {
380 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
381 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
382 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
384 case PICTYPE_METAFILE
:
385 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
388 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
390 case PICTYPE_ENHMETAFILE
:
391 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
394 case PICTYPE_UNINITIALIZED
:
398 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
402 HeapFree(GetProcessHeap(), 0, Obj
->data
);
403 HeapFree(GetProcessHeap(), 0, Obj
);
407 /************************************************************************
408 * OLEPictureImpl_AddRef (IUnknown)
410 * See Windows documentation for more details on IUnknown methods.
412 static ULONG WINAPI
OLEPictureImpl_AddRef(
415 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
416 ULONG refCount
= InterlockedIncrement(&This
->ref
);
418 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
423 /************************************************************************
424 * OLEPictureImpl_Release (IUnknown)
426 * See Windows documentation for more details on IUnknown methods.
428 static ULONG WINAPI
OLEPictureImpl_Release(
431 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
432 ULONG refCount
= InterlockedDecrement(&This
->ref
);
434 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
437 * If the reference count goes down to 0, perform suicide.
439 if (!refCount
) OLEPictureImpl_Destroy(This
);
444 /************************************************************************
445 * OLEPictureImpl_QueryInterface (IUnknown)
447 * See Windows documentation for more details on IUnknown methods.
449 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
454 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
456 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
463 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
465 else if (IsEqualIID(&IID_IDispatch
, riid
))
466 *ppvObject
= &This
->IDispatch_iface
;
467 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
468 *ppvObject
= &This
->IDispatch_iface
;
469 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
470 *ppvObject
= &This
->IPersistStream_iface
;
471 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
472 *ppvObject
= &This
->IConnectionPointContainer_iface
;
476 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
477 return E_NOINTERFACE
;
480 IPicture_AddRef(iface
);
485 /***********************************************************************
486 * OLEPicture_SendNotify (internal)
488 * Sends notification messages of changed properties to any interested
491 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
493 IEnumConnections
*pEnum
;
496 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
) != S_OK
)
498 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
499 IPropertyNotifySink
*sink
;
501 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
502 IPropertyNotifySink_OnChanged(sink
, dispID
);
503 IPropertyNotifySink_Release(sink
);
504 IUnknown_Release(CD
.pUnk
);
506 IEnumConnections_Release(pEnum
);
509 /************************************************************************
510 * OLEPictureImpl_get_Handle
512 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
515 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
516 TRACE("(%p)->(%p)\n", This
, phandle
);
521 switch(This
->desc
.picType
) {
523 case PICTYPE_UNINITIALIZED
:
527 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
529 case PICTYPE_METAFILE
:
530 *phandle
= HandleToUlong(This
->desc
.u
.wmf
.hmeta
);
533 *phandle
= HandleToUlong(This
->desc
.u
.icon
.hicon
);
535 case PICTYPE_ENHMETAFILE
:
536 *phandle
= HandleToUlong(This
->desc
.u
.emf
.hemf
);
539 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
542 TRACE("returning handle %08x\n", *phandle
);
546 /************************************************************************
547 * OLEPictureImpl_get_hPal
549 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
552 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
554 TRACE("(%p)->(%p)\n", This
, phandle
);
559 switch (This
->desc
.picType
) {
560 case (UINT
)PICTYPE_UNINITIALIZED
:
566 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hpal
);
569 case PICTYPE_METAFILE
:
573 case PICTYPE_ENHMETAFILE
:
575 FIXME("unimplemented for type %d. Returning 0 palette.\n",
581 TRACE("returning 0x%08x, palette handle %08x\n", hres
, *phandle
);
585 /************************************************************************
586 * OLEPictureImpl_get_Type
588 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
591 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
592 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
597 *ptype
= This
->desc
.picType
;
601 /************************************************************************
602 * OLEPictureImpl_get_Width
604 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
605 OLE_XSIZE_HIMETRIC
*pwidth
)
607 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
608 TRACE("(%p)->(%p): width is %d\n", This
, pwidth
, This
->himetricWidth
);
609 *pwidth
= This
->himetricWidth
;
613 /************************************************************************
614 * OLEPictureImpl_get_Height
616 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
617 OLE_YSIZE_HIMETRIC
*pheight
)
619 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
620 TRACE("(%p)->(%p): height is %d\n", This
, pheight
, This
->himetricHeight
);
621 *pheight
= This
->himetricHeight
;
625 /************************************************************************
626 * OLEPictureImpl_Render
628 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
629 LONG x
, LONG y
, LONG cx
, LONG cy
,
630 OLE_XPOS_HIMETRIC xSrc
,
631 OLE_YPOS_HIMETRIC ySrc
,
632 OLE_XSIZE_HIMETRIC cxSrc
,
633 OLE_YSIZE_HIMETRIC cySrc
,
636 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
637 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
638 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
640 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds
->left
, prcWBounds
->top
,
641 prcWBounds
->right
, prcWBounds
->bottom
);
643 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
644 return CTL_E_INVALIDPROPERTYVALUE
;
648 * While the documentation suggests this to be here (or after rendering?)
649 * it does cause an endless recursion in my sample app. -MM 20010804
650 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
653 switch(This
->desc
.picType
) {
654 case PICTYPE_UNINITIALIZED
:
663 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
664 NB y-axis gets flipped */
666 hdcBmp
= CreateCompatibleDC(0);
667 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
668 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
669 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
670 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
671 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
674 HDC hdcMask
= CreateCompatibleDC(0);
675 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
677 hbmpOld
= SelectObject(hdcBmp
, This
->hbmXor
);
679 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
680 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
681 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
682 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
683 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
685 SetBkColor(hdc
, RGB(255, 255, 255));
686 SetTextColor(hdc
, RGB(0, 0, 0));
687 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
688 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
690 SelectObject(hdcMask
, hOldbm
);
693 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
694 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
697 SelectObject(hdcBmp
, hbmpOld
);
702 FIXME("Not quite correct implementation of rendering icons...\n");
703 DrawIconEx(hdc
, x
, y
, This
->desc
.u
.icon
.hicon
, cx
, cy
, 0, NULL
, DI_NORMAL
);
706 case PICTYPE_METAFILE
:
708 POINT prevOrg
, prevWndOrg
;
709 SIZE prevExt
, prevWndExt
;
712 /* Render the WMF to the appropriate location by setting the
713 appropriate ratio between "device units" and "logical units" */
714 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
715 /* For the "source rectangle" the y-axis must be inverted */
716 SetWindowOrgEx(hdc
, xSrc
, This
->himetricHeight
-ySrc
, &prevWndOrg
);
717 SetWindowExtEx(hdc
, cxSrc
, -cySrc
, &prevWndExt
);
718 /* For the "destination rectangle" no inversion is necessary */
719 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
720 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
722 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
723 ERR("PlayMetaFile failed!\n");
725 /* We're done, restore the DC to the previous settings for converting
726 logical units to device units */
727 SetWindowExtEx(hdc
, prevWndExt
.cx
, prevWndExt
.cy
, NULL
);
728 SetWindowOrgEx(hdc
, prevWndOrg
.x
, prevWndOrg
.y
, NULL
);
729 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
730 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
731 SetMapMode(hdc
, oldmode
);
735 case PICTYPE_ENHMETAFILE
:
737 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
738 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
743 FIXME("type %d not implemented\n", This
->desc
.picType
);
749 /************************************************************************
750 * OLEPictureImpl_set_hPal
752 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
755 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
756 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
757 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
761 /************************************************************************
762 * OLEPictureImpl_get_CurDC
764 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
767 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
768 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
769 if (phdc
) *phdc
= This
->hDCCur
;
773 /************************************************************************
774 * OLEPictureImpl_SelectPicture
776 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
779 OLE_HANDLE
*phbmpOut
)
781 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
782 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
783 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
785 *phdcOut
= This
->hDCCur
;
786 if (This
->hDCCur
) SelectObject(This
->hDCCur
,This
->stock_bitmap
);
787 if (hdcIn
) SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
788 This
->hDCCur
= hdcIn
;
790 *phbmpOut
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
793 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
798 /************************************************************************
799 * OLEPictureImpl_get_KeepOriginalFormat
801 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
804 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
805 TRACE("(%p)->(%p)\n", This
, pfKeep
);
808 *pfKeep
= This
->keepOrigFormat
;
812 /************************************************************************
813 * OLEPictureImpl_put_KeepOriginalFormat
815 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
818 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
819 TRACE("(%p)->(%d)\n", This
, keep
);
820 This
->keepOrigFormat
= keep
;
821 /* FIXME: what DISPID notification here? */
825 /************************************************************************
826 * OLEPictureImpl_PictureChanged
828 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
830 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
831 TRACE("(%p)->()\n", This
);
832 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
833 This
->bIsDirty
= TRUE
;
837 /************************************************************************
838 * OLEPictureImpl_SaveAsFile
840 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
845 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
846 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
847 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
850 /************************************************************************
851 * OLEPictureImpl_get_Attributes
853 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
856 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
857 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
863 switch (This
->desc
.picType
) {
864 case PICTYPE_UNINITIALIZED
:
865 case PICTYPE_NONE
: break;
866 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
867 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
868 case PICTYPE_ENHMETAFILE
: /* fall through */
869 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
870 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
876 /************************************************************************
877 * IConnectionPointContainer
879 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
880 IConnectionPointContainer
* iface
,
884 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
886 return IPicture_QueryInterface(&This
->IPicture_iface
,riid
,ppvoid
);
889 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
890 IConnectionPointContainer
* iface
)
892 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
894 return IPicture_AddRef(&This
->IPicture_iface
);
897 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
898 IConnectionPointContainer
* iface
)
900 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
902 return IPicture_Release(&This
->IPicture_iface
);
905 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
906 IConnectionPointContainer
* iface
,
907 IEnumConnectionPoints
** ppEnum
)
909 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
911 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
915 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
916 IConnectionPointContainer
* iface
,
918 IConnectionPoint
**ppCP
)
920 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
921 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
925 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
926 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
927 FIXME("no connection point for %s\n",debugstr_guid(riid
));
928 return CONNECT_E_NOCONNECTION
;
932 /************************************************************************
936 /************************************************************************
937 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
939 * See Windows documentation for more details on IUnknown methods.
941 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
942 IPersistStream
* iface
,
946 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
948 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
951 /************************************************************************
952 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
954 * See Windows documentation for more details on IUnknown methods.
956 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
957 IPersistStream
* iface
)
959 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
961 return IPicture_AddRef(&This
->IPicture_iface
);
964 /************************************************************************
965 * OLEPictureImpl_IPersistStream_Release (IUnknown)
967 * See Windows documentation for more details on IUnknown methods.
969 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
970 IPersistStream
* iface
)
972 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
974 return IPicture_Release(&This
->IPicture_iface
);
977 /************************************************************************
978 * OLEPictureImpl_IPersistStream_GetClassID
980 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
981 IPersistStream
* iface
,CLSID
* pClassID
)
983 TRACE("(%p)\n", pClassID
);
984 *pClassID
= CLSID_StdPicture
;
988 /************************************************************************
989 * OLEPictureImpl_IPersistStream_IsDirty
991 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
992 IPersistStream
* iface
)
994 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
995 FIXME("(%p),stub!\n",This
);
999 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1001 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1002 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1005 /* Does not matter whether this is a coreheader or not, we only use
1006 * components which are in both
1009 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1013 xbuf
+bfh
->bfOffBits
,
1017 ReleaseDC(0, hdcref
);
1018 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1020 This
->desc
.picType
= PICTYPE_BITMAP
;
1021 OLEPictureImpl_SetBitmap(This
);
1025 static HRESULT
OLEPictureImpl_LoadWICSource(OLEPictureImpl
*This
, IWICBitmapSource
*src
)
1028 BITMAPINFOHEADER bih
;
1031 UINT stride
, buffersize
;
1034 IWICBitmapSource
*real_source
;
1036 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1037 BOOL has_alpha
=FALSE
;
1039 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
, src
, &real_source
);
1040 if (FAILED(hr
)) return hr
;
1042 hr
= IWICBitmapSource_GetSize(real_source
, &width
, &height
);
1043 if (FAILED(hr
)) goto end
;
1045 bih
.biSize
= sizeof(bih
);
1046 bih
.biWidth
= width
;
1047 bih
.biHeight
= -height
;
1049 bih
.biBitCount
= 32;
1050 bih
.biCompression
= BI_RGB
;
1051 bih
.biSizeImage
= 0;
1052 bih
.biXPelsPerMeter
= 4085; /* olepicture ignores the stored resolution */
1053 bih
.biYPelsPerMeter
= 4085;
1055 bih
.biClrImportant
= 0;
1058 buffersize
= stride
* height
;
1060 bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
1071 hr
= IWICBitmapSource_CopyPixels(real_source
, &rc
, stride
, buffersize
, bits
);
1076 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1084 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1087 ReleaseDC(0, hdcref
);
1091 This
->desc
.picType
= PICTYPE_BITMAP
;
1092 OLEPictureImpl_SetBitmap(This
);
1094 /* set transparent pixels to black, all others to white */
1095 for(y
= 0; y
< height
; y
++){
1096 for(x
= 0; x
< width
; x
++){
1097 DWORD
*pixel
= (DWORD
*)(bits
+ stride
*y
+ 4*x
);
1098 if((*pixel
& 0x80000000) == 0)
1110 HDC hdcBmp
, hdcXor
, hdcMask
;
1111 HBITMAP hbmoldBmp
, hbmoldXor
, hbmoldMask
;
1113 This
->hbmXor
= CreateDIBitmap(
1122 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1123 hdcBmp
= CreateCompatibleDC(NULL
);
1124 hdcXor
= CreateCompatibleDC(NULL
);
1125 hdcMask
= CreateCompatibleDC(NULL
);
1127 hbmoldBmp
= SelectObject(hdcBmp
,This
->desc
.u
.bmp
.hbitmap
);
1128 hbmoldXor
= SelectObject(hdcXor
,This
->hbmXor
);
1129 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1131 SetBkColor(hdcXor
,black
);
1132 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1133 BitBlt(hdcXor
,0,0,width
,height
,hdcBmp
,0,0,SRCAND
);
1135 SelectObject(hdcBmp
,hbmoldBmp
);
1136 SelectObject(hdcXor
,hbmoldXor
);
1137 SelectObject(hdcMask
,hbmoldMask
);
1144 ReleaseDC(0, hdcref
);
1147 HeapFree(GetProcessHeap(), 0, bits
);
1148 IWICBitmapSource_Release(real_source
);
1152 static HRESULT
OLEPictureImpl_LoadWICDecoder(OLEPictureImpl
*This
, REFCLSID decoder_clsid
, BYTE
*xbuf
, ULONG xread
)
1155 IWICImagingFactory
*factory
;
1156 IWICBitmapDecoder
*decoder
;
1157 IWICBitmapFrameDecode
*framedecode
;
1161 initresult
= CoInitialize(NULL
);
1163 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
1164 &IID_IWICImagingFactory
, (void**)&factory
);
1165 if (SUCCEEDED(hr
)) /* created factory */
1167 hr
= IWICImagingFactory_CreateStream(factory
, &stream
);
1168 IWICImagingFactory_Release(factory
);
1171 if (SUCCEEDED(hr
)) /* created stream */
1173 hr
= IWICStream_InitializeFromMemory(stream
, xbuf
, xread
);
1175 if (SUCCEEDED(hr
)) /* initialized stream */
1177 hr
= CoCreateInstance(decoder_clsid
, NULL
, CLSCTX_INPROC_SERVER
,
1178 &IID_IWICBitmapDecoder
, (void**)&decoder
);
1179 if (SUCCEEDED(hr
)) /* created decoder */
1181 hr
= IWICBitmapDecoder_Initialize(decoder
, (IStream
*)stream
, WICDecodeMetadataCacheOnLoad
);
1183 if (SUCCEEDED(hr
)) /* initialized decoder */
1184 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
1186 IWICBitmapDecoder_Release(decoder
);
1190 IWICStream_Release(stream
);
1193 if (SUCCEEDED(hr
)) /* got framedecode */
1195 hr
= OLEPictureImpl_LoadWICSource(This
, (IWICBitmapSource
*)framedecode
);
1196 IWICBitmapFrameDecode_Release(framedecode
);
1199 if (SUCCEEDED(initresult
)) CoUninitialize();
1203 /*****************************************************
1204 * start of Icon-specific code
1207 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1210 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1215 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1216 FIXME("icon.idType=%d\n",cifd->idType);
1217 FIXME("icon.idCount=%d\n",cifd->idCount);
1219 for (i=0;i<cifd->idCount;i++) {
1220 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1221 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1222 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1223 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1224 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1225 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1226 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1227 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1231 /* If we have more than one icon, try to find the best.
1232 * this currently means '32 pixel wide'.
1234 if (cifd
->idCount
!=1) {
1235 for (i
=0;i
<cifd
->idCount
;i
++) {
1236 if (cifd
->idEntries
[i
].bWidth
== 32)
1239 if (i
==cifd
->idCount
) i
=0;
1241 if (cifd
->idType
== 2)
1243 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, cifd
->idEntries
[i
].dwDIBSize
+ 4);
1244 memcpy(buf
, &cifd
->idEntries
[i
].xHotspot
, 4);
1245 memcpy(buf
+ 4, xbuf
+cifd
->idEntries
[i
].dwDIBOffset
, cifd
->idEntries
[i
].dwDIBSize
);
1246 hicon
= CreateIconFromResourceEx(
1248 cifd
->idEntries
[i
].dwDIBSize
+ 4,
1249 FALSE
, /* is cursor */
1251 cifd
->idEntries
[i
].bWidth
,
1252 cifd
->idEntries
[i
].bHeight
,
1255 HeapFree(GetProcessHeap(), 0, buf
);
1259 hicon
= CreateIconFromResourceEx(
1260 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1261 cifd
->idEntries
[i
].dwDIBSize
,
1264 cifd
->idEntries
[i
].bWidth
,
1265 cifd
->idEntries
[i
].bHeight
,
1270 ERR("CreateIcon failed.\n");
1273 This
->desc
.picType
= PICTYPE_ICON
;
1274 This
->desc
.u
.icon
.hicon
= hicon
;
1275 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1276 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1277 hdcRef
= CreateCompatibleDC(0);
1278 This
->himetricWidth
= xpixels_to_himetric(cifd
->idEntries
[i
].bWidth
, hdcRef
);
1279 This
->himetricHeight
= ypixels_to_himetric(cifd
->idEntries
[i
].bHeight
, hdcRef
);
1285 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1286 const BYTE
*data
, ULONG size
)
1291 hemf
= SetEnhMetaFileBits(size
, data
);
1292 if (!hemf
) return E_FAIL
;
1294 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1296 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1297 This
->desc
.u
.emf
.hemf
= hemf
;
1299 This
->origWidth
= 0;
1300 This
->origHeight
= 0;
1301 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1302 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1307 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1308 const BYTE
*data
, ULONG size
)
1310 const APM_HEADER
*header
= (const APM_HEADER
*)data
;
1313 if (size
< sizeof(APM_HEADER
))
1315 if (header
->key
!= 0x9ac6cdd7)
1318 /* SetMetaFileBitsEx performs data check on its own */
1319 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1320 if (!hmf
) return E_FAIL
;
1322 This
->desc
.picType
= PICTYPE_METAFILE
;
1323 This
->desc
.u
.wmf
.hmeta
= hmf
;
1324 This
->desc
.u
.wmf
.xExt
= 0;
1325 This
->desc
.u
.wmf
.yExt
= 0;
1327 This
->origWidth
= 0;
1328 This
->origHeight
= 0;
1329 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1330 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1334 /************************************************************************
1335 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1337 * Loads the binary data from the IStream. Starts at current position.
1338 * There appears to be an 2 DWORD header:
1342 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
1344 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
, IStream
*pStm
) {
1347 BOOL statfailed
= FALSE
;
1348 ULONG xread
, toread
;
1354 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1356 TRACE("(%p,%p)\n",This
,pStm
);
1358 /****************************************************************************************
1359 * Part 1: Load the data
1361 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1362 * out whether we do.
1364 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1365 * compound file. This may explain most, if not all, of the cases of "no
1366 * header", and the header validation should take this into account.
1367 * At least in Visual Basic 6, resource streams, valid headers are
1368 * header[0] == "lt\0\0",
1369 * header[1] == length_of_stream.
1371 * Also handle streams where we do not have a working "Stat" method by
1372 * reading all data until the end of the stream.
1374 hr
= IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1376 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr
);
1378 /* we will read at least 8 byte ... just right below */
1379 statstg
.cbSize
.QuadPart
= 8;
1384 headerisdata
= FALSE
;
1386 hr
= IStream_Read(pStm
, header
, 8, &xread
);
1387 if (hr
!= S_OK
|| xread
!=8) {
1388 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr
,xread
);
1389 return (hr
?hr
:E_FAIL
);
1391 headerread
+= xread
;
1394 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1395 if (toread
!= 0 && toread
!= header
[1])
1396 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1399 if (toread
== 0) break;
1401 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1402 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1403 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1404 (header
[0] == EMR_HEADER
) || /* EMF header */
1405 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1407 ) {/* Found start of bitmap data */
1408 headerisdata
= TRUE
;
1410 toread
= statstg
.cbSize
.QuadPart
-8;
1414 FIXME("Unknown stream header magic: %08x\n", header
[0]);
1418 } while (!headerisdata
);
1420 if (statfailed
) { /* we don't know the size ... read all we get */
1422 int origsize
= sizeinc
;
1425 TRACE("Reading all data from stream.\n");
1426 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1428 memcpy (xbuf
, header
, 8);
1430 while (xread
< origsize
) {
1431 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1433 if (hr
!= S_OK
|| !nread
)
1436 if (!nread
|| hr
!= S_OK
) /* done, or error */
1438 if (xread
== origsize
) {
1439 origsize
+= sizeinc
;
1440 sizeinc
= 2*sizeinc
; /* exponential increase */
1441 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1445 TRACE("hr in no-stat loader case is %08x\n", hr
);
1446 TRACE("loaded %d bytes.\n", xread
);
1447 This
->datalen
= xread
;
1450 This
->datalen
= toread
+(headerisdata
?8:0);
1451 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1453 return E_OUTOFMEMORY
;
1456 memcpy (xbuf
, header
, 8);
1458 while (xread
< This
->datalen
) {
1460 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1462 if (hr
!= S_OK
|| !nread
)
1465 if (xread
!= This
->datalen
)
1466 ERR("Could only read %d of %d bytes out of stream?\n",xread
,This
->datalen
);
1468 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1469 This
->desc
.picType
= PICTYPE_NONE
;
1474 /****************************************************************************************
1475 * Part 2: Process the loaded data
1478 magic
= xbuf
[0] + (xbuf
[1]<<8);
1479 This
->loadtime_format
= magic
;
1482 case BITMAP_FORMAT_GIF
: /* GIF */
1483 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICGifDecoder
, xbuf
, xread
);
1485 case BITMAP_FORMAT_JPEG
: /* JPEG */
1486 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICJpegDecoder
, xbuf
, xread
);
1488 case BITMAP_FORMAT_BMP
: /* Bitmap */
1489 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1491 case BITMAP_FORMAT_PNG
: /* PNG */
1492 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICPngDecoder
, xbuf
, xread
);
1494 case BITMAP_FORMAT_APM
: /* APM */
1495 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1497 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1498 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1505 /* let's see if it's a EMF */
1506 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1507 if (hr
== S_OK
) break;
1509 FIXME("Unknown magic %04x, %d read bytes:\n",magic
,xread
);
1511 for (i
=0;i
<xread
+8;i
++) {
1512 if (i
<8) MESSAGE("%02x ",((unsigned char*)header
)[i
]);
1513 else MESSAGE("%02x ",xbuf
[i
-8]);
1514 if (i
% 10 == 9) MESSAGE("\n");
1520 This
->bIsDirty
= FALSE
;
1522 /* FIXME: this notify is not really documented */
1524 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1528 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1532 BITMAPINFO
* pInfoBitmap
;
1533 int iNumPaletteEntries
;
1534 unsigned char * pPixelData
;
1535 BITMAPFILEHEADER
* pFileHeader
;
1536 BITMAPINFO
* pInfoHeader
;
1538 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1539 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1541 /* Find out bitmap size and padded length */
1543 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1544 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1546 /* Fetch bitmap palette & pixel data */
1548 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1549 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1551 /* Calculate the total length required for the BMP data */
1552 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1553 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1554 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1556 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1557 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1559 iNumPaletteEntries
= 0;
1562 sizeof(BITMAPFILEHEADER
) +
1563 sizeof(BITMAPINFOHEADER
) +
1564 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1565 pInfoBitmap
->bmiHeader
.biSizeImage
;
1566 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1568 /* Fill the BITMAPFILEHEADER */
1569 pFileHeader
= *ppBuffer
;
1570 pFileHeader
->bfType
= BITMAP_FORMAT_BMP
;
1571 pFileHeader
->bfSize
= *pLength
;
1572 pFileHeader
->bfOffBits
=
1573 sizeof(BITMAPFILEHEADER
) +
1574 sizeof(BITMAPINFOHEADER
) +
1575 iNumPaletteEntries
* sizeof(RGBQUAD
);
1577 /* Fill the BITMAPINFOHEADER and the palette data */
1578 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1579 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1581 (unsigned char *)(*ppBuffer
) +
1582 sizeof(BITMAPFILEHEADER
) +
1583 sizeof(BITMAPINFOHEADER
) +
1584 iNumPaletteEntries
* sizeof(RGBQUAD
),
1585 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1588 HeapFree(GetProcessHeap(), 0, pPixelData
);
1589 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1593 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1598 *ppBuffer
= NULL
; *pLength
= 0;
1599 if (GetIconInfo(hIcon
, &infoIcon
)) {
1601 BITMAPINFO
* pInfoBitmap
;
1602 unsigned char * pIconData
= NULL
;
1603 unsigned int iDataSize
= 0;
1605 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1607 /* Find out icon size */
1609 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1610 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1612 /* Auxiliary pointers */
1613 CURSORICONFILEDIR
* pIconDir
;
1614 CURSORICONFILEDIRENTRY
* pIconEntry
;
1615 BITMAPINFOHEADER
* pIconBitmapHeader
;
1616 unsigned int iOffsetPalette
;
1617 unsigned int iOffsetColorData
;
1618 unsigned int iOffsetMaskData
;
1620 unsigned int iLengthScanLineMask
;
1621 unsigned int iNumEntriesPalette
;
1623 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1625 FIXME("DEBUG: bitmap size is %d x %d\n",
1626 pInfoBitmap->bmiHeader.biWidth,
1627 pInfoBitmap->bmiHeader.biHeight);
1628 FIXME("DEBUG: bitmap bpp is %d\n",
1629 pInfoBitmap->bmiHeader.biBitCount);
1630 FIXME("DEBUG: bitmap nplanes is %d\n",
1631 pInfoBitmap->bmiHeader.biPlanes);
1632 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1633 pInfoBitmap->bmiHeader.biSizeImage);
1635 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1636 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1637 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1639 /* Fill out the CURSORICONFILEDIR */
1640 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1641 pIconDir
->idType
= 1;
1642 pIconDir
->idCount
= 1;
1644 /* Fill out the CURSORICONFILEDIRENTRY */
1645 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1646 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1647 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1648 pIconEntry
->bColorCount
=
1649 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1650 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1652 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1653 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1654 pIconEntry
->dwDIBSize
= 0;
1655 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1657 /* Fill out the BITMAPINFOHEADER */
1658 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1659 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
1661 /* Find out whether a palette exists for the bitmap */
1662 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1663 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1664 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1665 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1666 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1667 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1668 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1669 iNumEntriesPalette
= 3;
1670 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1671 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1673 iNumEntriesPalette
= 0;
1676 /* Add bitmap size and header size to icon data size. */
1677 iOffsetPalette
= iDataSize
;
1678 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1679 iOffsetColorData
= iDataSize
;
1680 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1681 iOffsetMaskData
= iDataSize
;
1682 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1683 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1684 pIconBitmapHeader
->biHeight
*= 2;
1685 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1686 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1687 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1688 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1690 /* Get the actual bitmap data from the icon bitmap */
1691 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1692 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1693 if (iNumEntriesPalette
> 0) {
1694 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1695 iNumEntriesPalette
* sizeof(RGBQUAD
));
1698 /* Reset all values so that GetDIBits call succeeds */
1699 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1700 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1701 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1703 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1704 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1705 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1707 printf("ERROR: unable to get bitmap mask (error %u)\n",
1712 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1713 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1715 /* Write out everything produced so far to the stream */
1716 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1720 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1725 Remarks (from MSDN entry on GetIconInfo):
1727 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1728 members of ICONINFO. The calling application must manage
1729 these bitmaps and delete them when they are no longer
1732 if (hDC
) ReleaseDC(0, hDC
);
1733 DeleteObject(infoIcon
.hbmMask
);
1734 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1735 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1737 printf("ERROR: Unable to get icon information (error %u)\n",
1743 static HRESULT WINAPI
OLEPictureImpl_Save(
1744 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1746 HRESULT hResult
= E_NOTIMPL
;
1748 unsigned int iDataSize
;
1750 int iSerializeResult
= 0;
1751 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1753 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
1755 switch (This
->desc
.picType
) {
1757 if (This
->bIsDirty
|| !This
->data
) {
1758 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1759 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
1763 HeapFree(GetProcessHeap(), 0, This
->data
);
1764 This
->data
= pIconData
;
1765 This
->datalen
= iDataSize
;
1767 if (This
->loadtime_magic
!= 0xdeadbeef) {
1770 header
[0] = This
->loadtime_magic
;
1771 header
[1] = This
->datalen
;
1772 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1774 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1778 case PICTYPE_BITMAP
:
1779 if (This
->bIsDirty
) {
1780 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
1781 case BITMAP_FORMAT_BMP
:
1782 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1784 case BITMAP_FORMAT_JPEG
:
1785 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1787 case BITMAP_FORMAT_GIF
:
1788 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1790 case BITMAP_FORMAT_PNG
:
1791 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
1794 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1797 if (iSerializeResult
) {
1799 if (This->loadtime_magic != 0xdeadbeef) {
1804 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1805 header
[1] = iDataSize
;
1806 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1808 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
1810 HeapFree(GetProcessHeap(), 0, This
->data
);
1811 This
->data
= pIconData
;
1812 This
->datalen
= iDataSize
;
1817 if (This->loadtime_magic != 0xdeadbeef) {
1822 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1823 header
[1] = This
->datalen
;
1824 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1826 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1830 case PICTYPE_METAFILE
:
1831 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1833 case PICTYPE_ENHMETAFILE
:
1834 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1837 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1840 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1844 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1845 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1847 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1848 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1853 /************************************************************************
1857 /************************************************************************
1858 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1860 * See Windows documentation for more details on IUnknown methods.
1862 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1867 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1869 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
1872 /************************************************************************
1873 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1875 * See Windows documentation for more details on IUnknown methods.
1877 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1880 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1882 return IPicture_AddRef(&This
->IPicture_iface
);
1885 /************************************************************************
1886 * OLEPictureImpl_IDispatch_Release (IUnknown)
1888 * See Windows documentation for more details on IUnknown methods.
1890 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1893 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1895 return IPicture_Release(&This
->IPicture_iface
);
1898 /************************************************************************
1899 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1901 * See Windows documentation for more details on IDispatch methods.
1903 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1905 unsigned int* pctinfo
)
1907 TRACE("(%p)\n", pctinfo
);
1914 /************************************************************************
1915 * OLEPictureImpl_GetTypeInfo (IDispatch)
1917 * See Windows documentation for more details on IDispatch methods.
1919 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1923 ITypeInfo
** ppTInfo
)
1925 static const WCHAR stdole2tlb
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1929 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
1934 hres
= LoadTypeLib(stdole2tlb
, &tl
);
1937 ERR("Could not load stdole2.tlb\n");
1941 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
1943 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres
);
1948 /************************************************************************
1949 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1951 * See Windows documentation for more details on IDispatch methods.
1953 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1956 LPOLESTR
* rgszNames
,
1964 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
1965 rgszNames
, cNames
, (int)lcid
, rgDispId
);
1969 return E_INVALIDARG
;
1973 /* retrieve type information */
1974 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
1978 ERR("GetTypeInfo failed.\n");
1982 /* convert names to DISPIDs */
1983 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
1984 ITypeInfo_Release(pTInfo
);
1990 /************************************************************************
1991 * OLEPictureImpl_Invoke (IDispatch)
1993 * See Windows documentation for more details on IDispatch methods.
1995 static HRESULT WINAPI
OLEPictureImpl_Invoke(
1997 DISPID dispIdMember
,
2001 DISPPARAMS
* pDispParams
,
2002 VARIANT
* pVarResult
,
2003 EXCEPINFO
* pExepInfo
,
2006 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2008 /* validate parameters */
2010 if (!IsEqualIID(riid
, &IID_NULL
))
2012 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2013 return DISP_E_UNKNOWNNAME
;
2018 ERR("null pDispParams not allowed\n");
2019 return DISP_E_PARAMNOTOPTIONAL
;
2022 if (wFlags
& DISPATCH_PROPERTYGET
)
2024 if (pDispParams
->cArgs
!= 0)
2026 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2027 return DISP_E_BADPARAMCOUNT
;
2031 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2032 return DISP_E_PARAMNOTOPTIONAL
;
2035 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2037 if (pDispParams
->cArgs
!= 1)
2039 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2040 return DISP_E_BADPARAMCOUNT
;
2044 switch (dispIdMember
)
2046 case DISPID_PICT_HANDLE
:
2047 if (wFlags
& DISPATCH_PROPERTYGET
)
2049 TRACE("DISPID_PICT_HANDLE\n");
2050 V_VT(pVarResult
) = VT_I4
;
2051 return IPicture_get_Handle(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2054 case DISPID_PICT_HPAL
:
2055 if (wFlags
& DISPATCH_PROPERTYGET
)
2057 TRACE("DISPID_PICT_HPAL\n");
2058 V_VT(pVarResult
) = VT_I4
;
2059 return IPicture_get_hPal(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2061 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2065 TRACE("DISPID_PICT_HPAL\n");
2067 VariantInit(&vararg
);
2068 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2072 hr
= IPicture_set_hPal(&This
->IPicture_iface
, V_I4(&vararg
));
2074 VariantClear(&vararg
);
2078 case DISPID_PICT_TYPE
:
2079 if (wFlags
& DISPATCH_PROPERTYGET
)
2081 TRACE("DISPID_PICT_TYPE\n");
2082 V_VT(pVarResult
) = VT_I2
;
2083 return OLEPictureImpl_get_Type(&This
->IPicture_iface
, &V_I2(pVarResult
));
2086 case DISPID_PICT_WIDTH
:
2087 if (wFlags
& DISPATCH_PROPERTYGET
)
2089 TRACE("DISPID_PICT_WIDTH\n");
2090 V_VT(pVarResult
) = VT_I4
;
2091 return IPicture_get_Width(&This
->IPicture_iface
, &V_I4(pVarResult
));
2094 case DISPID_PICT_HEIGHT
:
2095 if (wFlags
& DISPATCH_PROPERTYGET
)
2097 TRACE("DISPID_PICT_HEIGHT\n");
2098 V_VT(pVarResult
) = VT_I4
;
2099 return IPicture_get_Height(&This
->IPicture_iface
, &V_I4(pVarResult
));
2104 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember
, wFlags
);
2105 return DISP_E_MEMBERNOTFOUND
;
2109 static const IPictureVtbl OLEPictureImpl_VTable
=
2111 OLEPictureImpl_QueryInterface
,
2112 OLEPictureImpl_AddRef
,
2113 OLEPictureImpl_Release
,
2114 OLEPictureImpl_get_Handle
,
2115 OLEPictureImpl_get_hPal
,
2116 OLEPictureImpl_get_Type
,
2117 OLEPictureImpl_get_Width
,
2118 OLEPictureImpl_get_Height
,
2119 OLEPictureImpl_Render
,
2120 OLEPictureImpl_set_hPal
,
2121 OLEPictureImpl_get_CurDC
,
2122 OLEPictureImpl_SelectPicture
,
2123 OLEPictureImpl_get_KeepOriginalFormat
,
2124 OLEPictureImpl_put_KeepOriginalFormat
,
2125 OLEPictureImpl_PictureChanged
,
2126 OLEPictureImpl_SaveAsFile
,
2127 OLEPictureImpl_get_Attributes
2130 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2132 OLEPictureImpl_IDispatch_QueryInterface
,
2133 OLEPictureImpl_IDispatch_AddRef
,
2134 OLEPictureImpl_IDispatch_Release
,
2135 OLEPictureImpl_GetTypeInfoCount
,
2136 OLEPictureImpl_GetTypeInfo
,
2137 OLEPictureImpl_GetIDsOfNames
,
2138 OLEPictureImpl_Invoke
2141 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2143 OLEPictureImpl_IPersistStream_QueryInterface
,
2144 OLEPictureImpl_IPersistStream_AddRef
,
2145 OLEPictureImpl_IPersistStream_Release
,
2146 OLEPictureImpl_GetClassID
,
2147 OLEPictureImpl_IsDirty
,
2148 OLEPictureImpl_Load
,
2149 OLEPictureImpl_Save
,
2150 OLEPictureImpl_GetSizeMax
2153 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2155 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2156 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2157 OLEPictureImpl_IConnectionPointContainer_Release
,
2158 OLEPictureImpl_EnumConnectionPoints
,
2159 OLEPictureImpl_FindConnectionPoint
2162 /***********************************************************************
2163 * OleCreatePictureIndirect (OLEAUT32.419)
2165 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2166 BOOL Own
, void **ppvObj
)
2168 OLEPictureImpl
* newPict
;
2171 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), Own
, ppvObj
);
2175 newPict
= OLEPictureImpl_Construct(lpPictDesc
, Own
);
2177 if (newPict
== NULL
)
2178 return E_OUTOFMEMORY
;
2181 * Make sure it supports the interface required by the caller.
2183 hr
= IPicture_QueryInterface(&newPict
->IPicture_iface
, riid
, ppvObj
);
2186 * Release the reference obtained in the constructor. If
2187 * the QueryInterface was unsuccessful, it will free the class.
2189 IPicture_Release(&newPict
->IPicture_iface
);
2195 /***********************************************************************
2196 * OleLoadPicture (OLEAUT32.418)
2198 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2199 REFIID riid
, LPVOID
*ppvObj
)
2205 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2206 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2208 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2211 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2213 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2214 IPicture_Release(newpic
);
2218 hr
= IPersistStream_Load(ps
,lpstream
);
2219 IPersistStream_Release(ps
);
2222 ERR("IPersistStream_Load failed\n");
2223 IPicture_Release(newpic
);
2227 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2229 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2230 IPicture_Release(newpic
);
2234 /***********************************************************************
2235 * OleLoadPictureEx (OLEAUT32.401)
2237 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2238 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2244 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2245 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2247 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2250 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2252 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2253 IPicture_Release(newpic
);
2257 hr
= IPersistStream_Load(ps
,lpstream
);
2258 IPersistStream_Release(ps
);
2261 ERR("IPersistStream_Load failed\n");
2262 IPicture_Release(newpic
);
2266 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2268 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2269 IPicture_Release(newpic
);
2273 /***********************************************************************
2274 * OleLoadPicturePath (OLEAUT32.424)
2276 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2277 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2280 static const WCHAR file
[] = { 'f','i','l','e',':',0 };
2284 HGLOBAL hGlobal
= NULL
;
2285 DWORD dwBytesRead
= 0;
2288 IPersistStream
*pStream
;
2291 WCHAR
*file_candidate
;
2292 WCHAR path_buf
[MAX_PATH
];
2294 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2295 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2296 debugstr_guid(riid
), ppvRet
);
2298 if (!szURLorPath
|| !ppvRet
)
2299 return E_INVALIDARG
;
2303 /* Convert file URLs to DOS paths. */
2304 if (strncmpW(szURLorPath
, file
, 5) == 0) {
2306 hRes
= CoInternetParseUrl(szURLorPath
, PARSE_PATH_FROM_URL
, 0, path_buf
,
2307 sizeof(path_buf
)/sizeof(WCHAR
), &size
, 0);
2311 file_candidate
= path_buf
;
2314 file_candidate
= szURLorPath
;
2316 /* Handle candidate DOS paths separately. */
2317 if (file_candidate
[1] == ':') {
2318 hFile
= CreateFileW(file_candidate
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2320 if (hFile
== INVALID_HANDLE_VALUE
)
2321 return INET_E_RESOURCE_NOT_FOUND
;
2323 dwFileSize
= GetFileSize(hFile
, NULL
);
2324 if (dwFileSize
!= INVALID_FILE_SIZE
)
2326 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2329 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
);
2332 GlobalFree(hGlobal
);
2340 return INET_E_RESOURCE_NOT_FOUND
;
2342 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2345 GlobalFree(hGlobal
);
2352 hRes
= CreateBindCtx(0, &pbc
);
2353 if (SUCCEEDED(hRes
))
2355 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2356 if (SUCCEEDED(hRes
))
2358 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2359 IMoniker_Release(pmnk
);
2361 IBindCtx_Release(pbc
);
2367 init_res
= CoInitialize(NULL
);
2369 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2370 &IID_IPicture
, (LPVOID
*)&ipicture
);
2371 if (SUCCEEDED(hRes
)) {
2372 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2374 if (SUCCEEDED(hRes
)) {
2375 hRes
= IPersistStream_Load(pStream
, stream
);
2377 if (SUCCEEDED(hRes
)) {
2378 hRes
= IPicture_QueryInterface(ipicture
, riid
, ppvRet
);
2381 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid
));
2383 IPersistStream_Release(pStream
);
2385 IPicture_Release(ipicture
);
2388 IStream_Release(stream
);
2390 if (SUCCEEDED(init_res
))
2396 /*******************************************************************************
2397 * StdPic ClassFactory
2401 /* IUnknown fields */
2402 IClassFactory IClassFactory_iface
;
2404 } IClassFactoryImpl
;
2406 static inline IClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
2408 return CONTAINING_RECORD(iface
, IClassFactoryImpl
, IClassFactory_iface
);
2411 static HRESULT WINAPI
2412 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2413 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2415 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2416 return E_NOINTERFACE
;
2420 SPCF_AddRef(LPCLASSFACTORY iface
) {
2421 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2422 return InterlockedIncrement(&This
->ref
);
2425 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2426 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2427 /* static class, won't be freed */
2428 return InterlockedDecrement(&This
->ref
);
2431 static HRESULT WINAPI
SPCF_CreateInstance(
2432 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2434 /* Creates an uninitialized picture */
2435 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2439 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2440 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2441 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2445 static const IClassFactoryVtbl SPCF_Vtbl
= {
2446 SPCF_QueryInterface
,
2449 SPCF_CreateInstance
,
2452 static IClassFactoryImpl STDPIC_CF
= {{&SPCF_Vtbl
}, 1 };
2454 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= &STDPIC_CF
; }