4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
8 * Copyright 2008 Kirill K. Smirnov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well..
27 * Lots of methods are just stubs.
30 * NOTES (or things that msdn doesn't tell you)
32 * The width and height properties are returned in HIMETRIC units (0.01mm)
33 * IPicture::Render also uses these to select a region of the src picture.
34 * A bitmap's size is converted into these units by using the screen resolution
35 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
44 #define NONAMELESSUNION
58 #include "wine/debug.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(olepicture
);
62 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
63 #define BITMAP_FORMAT_JPEG 0xd8ff
64 #define BITMAP_FORMAT_GIF 0x4947
65 #define BITMAP_FORMAT_PNG 0x5089
66 #define BITMAP_FORMAT_APM 0xcdd7
70 /* Header for Aldus Placable Metafiles - a standard metafile follows */
71 typedef struct _APM_HEADER
93 } CURSORICONFILEDIRENTRY
;
100 CURSORICONFILEDIRENTRY idEntries
[1];
105 /*************************************************************************
106 * Declaration of implementation class
109 typedef struct OLEPictureImpl
{
112 * IPicture handles IUnknown
115 IPicture IPicture_iface
;
116 IDispatch IDispatch_iface
;
117 IPersistStream IPersistStream_iface
;
118 IConnectionPointContainer IConnectionPointContainer_iface
;
120 /* Object reference count */
123 /* We own the object and must destroy it ourselves */
126 /* Picture description */
129 /* These are the pixel size of a bitmap */
133 /* And these are the size of the picture converted into HIMETRIC units */
134 OLE_XSIZE_HIMETRIC himetricWidth
;
135 OLE_YSIZE_HIMETRIC himetricHeight
;
137 IConnectionPoint
*pCP
;
141 HBITMAP stock_bitmap
;
143 /* Bitmap transparency mask */
151 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
152 unsigned int loadtime_magic
; /* If a length header was found, saves value */
153 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
156 static inline OLEPictureImpl
*impl_from_IPicture(IPicture
*iface
)
158 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPicture_iface
);
161 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
163 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IDispatch_iface
);
166 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
168 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPersistStream_iface
);
171 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
173 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IConnectionPointContainer_iface
);
177 * Predeclare VTables. They get initialized at the end.
179 static const IPictureVtbl OLEPictureImpl_VTable
;
180 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
181 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
182 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
184 /* pixels to HIMETRIC units conversion */
185 static inline OLE_XSIZE_HIMETRIC
xpixels_to_himetric(INT pixels
, HDC hdc
)
187 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
190 static inline OLE_YSIZE_HIMETRIC
ypixels_to_himetric(INT pixels
, HDC hdc
)
192 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
195 /***********************************************************************
196 * Implementation of the OLEPictureImpl class.
199 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
)
204 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
205 if(GetObjectW(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
206 ERR("GetObject fails\n");
209 This
->origWidth
= bm
.bmWidth
;
210 This
->origHeight
= bm
.bmHeight
;
212 TRACE("width %d, height %d, bpp %d\n", bm
.bmWidth
, bm
.bmHeight
, bm
.bmBitsPixel
);
214 /* The width and height are stored in HIMETRIC units (0.01 mm),
215 so we take our pixel width divide by pixels per inch and
216 multiply by 25.4 * 100 */
217 /* Should we use GetBitmapDimension if available? */
218 hdcRef
= CreateCompatibleDC(0);
220 This
->himetricWidth
= xpixels_to_himetric(bm
.bmWidth
, hdcRef
);
221 This
->himetricHeight
= ypixels_to_himetric(bm
.bmHeight
, hdcRef
);
222 This
->stock_bitmap
= GetCurrentObject( hdcRef
, OBJ_BITMAP
);
224 This
->loadtime_format
= BITMAP_FORMAT_BMP
;
229 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
233 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
234 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
238 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
239 if(GetObjectW(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
240 ERR("GetObject fails on icon bitmap\n");
244 This
->origWidth
= bm
.bmWidth
;
245 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
246 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
249 This
->himetricWidth
= xpixels_to_himetric(This
->origWidth
, hdcRef
);
250 This
->himetricHeight
= ypixels_to_himetric(This
->origHeight
, hdcRef
);
252 ReleaseDC(0, hdcRef
);
254 DeleteObject(infoIcon
.hbmMask
);
255 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
257 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
261 /************************************************************************
262 * OLEPictureImpl_Construct
264 * This method will construct a new instance of the OLEPictureImpl
267 * The caller of this method must release the object when it's
270 static HRESULT
OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
, OLEPictureImpl
**pict
)
272 OLEPictureImpl
*newObject
;
276 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
279 * Allocate space for the object.
281 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
283 return E_OUTOFMEMORY
;
286 * Initialize the virtual function table.
288 newObject
->IPicture_iface
.lpVtbl
= &OLEPictureImpl_VTable
;
289 newObject
->IDispatch_iface
.lpVtbl
= &OLEPictureImpl_IDispatch_VTable
;
290 newObject
->IPersistStream_iface
.lpVtbl
= &OLEPictureImpl_IPersistStream_VTable
;
291 newObject
->IConnectionPointContainer_iface
.lpVtbl
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
293 newObject
->pCP
= NULL
;
294 hr
= CreateConnectionPoint((IUnknown
*)&newObject
->IPicture_iface
, &IID_IPropertyNotifySink
,
298 HeapFree(GetProcessHeap(), 0, newObject
);
303 * Start with one reference count. The caller of this function
304 * must release the interface pointer when it is done.
307 newObject
->hDCCur
= 0;
309 newObject
->fOwn
= fOwn
;
311 /* dunno about original value */
312 newObject
->keepOrigFormat
= TRUE
;
314 newObject
->hbmMask
= NULL
;
315 newObject
->hbmXor
= NULL
;
316 newObject
->loadtime_magic
= 0xdeadbeef;
317 newObject
->loadtime_format
= 0;
318 newObject
->bIsDirty
= FALSE
;
321 newObject
->desc
= *pictDesc
;
323 switch(pictDesc
->picType
) {
325 OLEPictureImpl_SetBitmap(newObject
);
328 case PICTYPE_METAFILE
:
329 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
330 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
331 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
335 /* not sure what to do here */
336 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
340 OLEPictureImpl_SetIcon(newObject
);
343 case PICTYPE_ENHMETAFILE
:
344 FIXME("EMF is not supported\n");
345 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
349 WARN("Unsupported type %d\n", pictDesc
->picType
);
350 IPicture_Release(&newObject
->IPicture_iface
);
354 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
357 TRACE("returning %p\n", newObject
);
362 /************************************************************************
363 * OLEPictureImpl_Destroy
365 * This method is called by the Release method when the reference
366 * count goes down to 0. It will free all resources used by
368 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
370 TRACE("(%p)\n", Obj
);
373 IConnectionPoint_Release(Obj
->pCP
);
375 if(Obj
->fOwn
) { /* We need to destroy the picture */
376 switch(Obj
->desc
.picType
) {
378 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
379 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
380 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
382 case PICTYPE_METAFILE
:
383 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
386 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
388 case PICTYPE_ENHMETAFILE
:
389 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
392 case PICTYPE_UNINITIALIZED
:
396 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
400 HeapFree(GetProcessHeap(), 0, Obj
->data
);
401 HeapFree(GetProcessHeap(), 0, Obj
);
404 static ULONG WINAPI
OLEPictureImpl_AddRef(
407 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
408 ULONG refCount
= InterlockedIncrement(&This
->ref
);
410 TRACE("%p, refcount %lu.\n", iface
, refCount
);
415 static ULONG WINAPI
OLEPictureImpl_Release(
418 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
419 ULONG refCount
= InterlockedDecrement(&This
->ref
);
421 TRACE("%p, refcount %lu.\n", iface
, refCount
);
423 if (!refCount
) OLEPictureImpl_Destroy(This
);
428 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
433 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
435 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
442 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
443 *ppvObject
= &This
->IPicture_iface
;
444 else if (IsEqualIID(&IID_IDispatch
, riid
))
445 *ppvObject
= &This
->IDispatch_iface
;
446 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
447 *ppvObject
= &This
->IDispatch_iface
;
448 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
449 *ppvObject
= &This
->IPersistStream_iface
;
450 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
451 *ppvObject
= &This
->IConnectionPointContainer_iface
;
455 FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
456 return E_NOINTERFACE
;
459 IPicture_AddRef(iface
);
464 /***********************************************************************
465 * OLEPicture_SendNotify (internal)
467 * Sends notification messages of changed properties to any interested
470 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
472 IEnumConnections
*pEnum
;
475 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
) != S_OK
)
477 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
478 IPropertyNotifySink
*sink
;
480 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
481 IPropertyNotifySink_OnChanged(sink
, dispID
);
482 IPropertyNotifySink_Release(sink
);
483 IUnknown_Release(CD
.pUnk
);
485 IEnumConnections_Release(pEnum
);
488 /************************************************************************
489 * OLEPictureImpl_get_Handle
491 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
494 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
495 TRACE("(%p)->(%p)\n", This
, phandle
);
500 switch(This
->desc
.picType
) {
502 case PICTYPE_UNINITIALIZED
:
506 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
508 case PICTYPE_METAFILE
:
509 *phandle
= HandleToUlong(This
->desc
.u
.wmf
.hmeta
);
512 *phandle
= HandleToUlong(This
->desc
.u
.icon
.hicon
);
514 case PICTYPE_ENHMETAFILE
:
515 *phandle
= HandleToUlong(This
->desc
.u
.emf
.hemf
);
518 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
521 TRACE("returning handle %08x\n", *phandle
);
525 /************************************************************************
526 * OLEPictureImpl_get_hPal
528 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
531 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
533 TRACE("(%p)->(%p)\n", This
, phandle
);
535 if (!phandle
) return E_POINTER
;
537 if (This
->desc
.picType
== PICTYPE_BITMAP
)
539 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hpal
);
546 /************************************************************************
547 * OLEPictureImpl_get_Type
549 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
552 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
553 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
558 *ptype
= This
->desc
.picType
;
562 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
, OLE_XSIZE_HIMETRIC
*pwidth
)
564 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
565 TRACE("%p, %p.\n", iface
, pwidth
);
566 *pwidth
= This
->himetricWidth
;
570 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
, OLE_YSIZE_HIMETRIC
*pheight
)
572 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
573 TRACE("%p, %p.\n", iface
, pheight
);
574 *pheight
= This
->himetricHeight
;
578 static void render_masked_bitmap(OLEPictureImpl
*This
, HDC hdc
,
579 LONG x
, LONG y
, LONG cx
, LONG cy
, OLE_XPOS_HIMETRIC xSrc
, OLE_YPOS_HIMETRIC ySrc
,
580 OLE_XSIZE_HIMETRIC cxSrc
, OLE_YSIZE_HIMETRIC cySrc
, HBITMAP hbmMask
, HBITMAP hbmXor
)
584 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
585 * NB y-axis gets flipped
588 hdcBmp
= CreateCompatibleDC(0);
589 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
590 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
591 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
592 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
593 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
597 SetBkColor(hdc
, RGB(255, 255, 255));
598 SetTextColor(hdc
, RGB(0, 0, 0));
600 SelectObject(hdcBmp
, hbmMask
);
601 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
605 SelectObject(hdcBmp
, hbmXor
);
606 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
608 else StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
- This
->himetricHeight
,
609 cxSrc
, cySrc
, SRCPAINT
);
613 SelectObject(hdcBmp
, hbmXor
);
614 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
620 /************************************************************************
621 * OLEPictureImpl_Render
623 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
624 LONG x
, LONG y
, LONG cx
, LONG cy
,
625 OLE_XPOS_HIMETRIC xSrc
,
626 OLE_YPOS_HIMETRIC ySrc
,
627 OLE_XSIZE_HIMETRIC cxSrc
,
628 OLE_YSIZE_HIMETRIC cySrc
,
631 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
632 TRACE("%p, %p, (%ld,%ld), (%ld,%ld), (%ld,%ld), (%ld,%ld), %p)\n", iface
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
,
633 cxSrc
, cySrc
, prcWBounds
);
635 TRACE("prcWBounds %s\n", wine_dbgstr_rect(prcWBounds
));
637 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
638 return CTL_E_INVALIDPROPERTYVALUE
;
642 * While the documentation suggests this to be here (or after rendering?)
643 * it does cause an endless recursion in my sample app. -MM 20010804
644 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
647 switch(This
->desc
.picType
) {
648 case PICTYPE_UNINITIALIZED
:
654 HBITMAP hbmMask
, hbmXor
;
658 hbmMask
= This
->hbmMask
;
659 hbmXor
= This
->hbmXor
;
664 hbmXor
= This
->desc
.u
.bmp
.hbitmap
;
667 render_masked_bitmap(This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, hbmMask
, hbmXor
);
675 if (!GetIconInfo(This
->desc
.u
.icon
.hicon
, &info
))
678 render_masked_bitmap(This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, info
.hbmMask
, info
.hbmColor
);
680 DeleteObject(info
.hbmMask
);
681 if (info
.hbmColor
) DeleteObject(info
.hbmColor
);
685 case PICTYPE_METAFILE
:
687 POINT prevOrg
, prevWndOrg
;
688 SIZE prevExt
, prevWndExt
;
691 /* Render the WMF to the appropriate location by setting the
692 appropriate ratio between "device units" and "logical units" */
693 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
694 /* For the "source rectangle" the y-axis must be inverted */
695 SetWindowOrgEx(hdc
, xSrc
, This
->himetricHeight
-ySrc
, &prevWndOrg
);
696 SetWindowExtEx(hdc
, cxSrc
, -cySrc
, &prevWndExt
);
697 /* For the "destination rectangle" no inversion is necessary */
698 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
699 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
701 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
702 ERR("PlayMetaFile failed!\n");
704 /* We're done, restore the DC to the previous settings for converting
705 logical units to device units */
706 SetWindowExtEx(hdc
, prevWndExt
.cx
, prevWndExt
.cy
, NULL
);
707 SetWindowOrgEx(hdc
, prevWndOrg
.x
, prevWndOrg
.y
, NULL
);
708 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
709 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
710 SetMapMode(hdc
, oldmode
);
714 case PICTYPE_ENHMETAFILE
:
716 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
717 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
722 FIXME("type %d not implemented\n", This
->desc
.picType
);
728 /************************************************************************
729 * OLEPictureImpl_set_hPal
731 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
734 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
736 TRACE("(%p)->(%08x)\n", This
, hpal
);
738 if (This
->desc
.picType
== PICTYPE_BITMAP
)
740 This
->desc
.u
.bmp
.hpal
= ULongToHandle(hpal
);
741 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
748 /************************************************************************
749 * OLEPictureImpl_get_CurDC
751 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
754 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
755 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
756 if (phdc
) *phdc
= This
->hDCCur
;
760 /************************************************************************
761 * OLEPictureImpl_SelectPicture
763 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
766 OLE_HANDLE
*phbmpOut
)
768 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
769 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
770 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
772 *phdcOut
= This
->hDCCur
;
773 if (This
->hDCCur
) SelectObject(This
->hDCCur
,This
->stock_bitmap
);
774 if (hdcIn
) SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
775 This
->hDCCur
= hdcIn
;
777 *phbmpOut
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
780 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
785 /************************************************************************
786 * OLEPictureImpl_get_KeepOriginalFormat
788 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
791 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
792 TRACE("(%p)->(%p)\n", This
, pfKeep
);
795 *pfKeep
= This
->keepOrigFormat
;
799 /************************************************************************
800 * OLEPictureImpl_put_KeepOriginalFormat
802 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
805 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
806 TRACE("(%p)->(%d)\n", This
, keep
);
807 This
->keepOrigFormat
= keep
;
808 /* FIXME: what DISPID notification here? */
812 /************************************************************************
813 * OLEPictureImpl_PictureChanged
815 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
817 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
818 TRACE("(%p)->()\n", This
);
819 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
820 This
->bIsDirty
= TRUE
;
824 /************************************************************************
825 * OLEPictureImpl_SaveAsFile
827 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
832 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
833 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
834 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
837 /************************************************************************
838 * OLEPictureImpl_get_Attributes
840 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
843 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
844 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
850 switch (This
->desc
.picType
) {
851 case PICTYPE_UNINITIALIZED
:
852 case PICTYPE_NONE
: break;
853 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
854 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
855 case PICTYPE_ENHMETAFILE
: /* fall through */
856 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
857 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
863 /************************************************************************
864 * IConnectionPointContainer
866 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
867 IConnectionPointContainer
* iface
,
871 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
873 return IPicture_QueryInterface(&This
->IPicture_iface
,riid
,ppvoid
);
876 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
877 IConnectionPointContainer
* iface
)
879 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
881 return IPicture_AddRef(&This
->IPicture_iface
);
884 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
885 IConnectionPointContainer
* iface
)
887 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
889 return IPicture_Release(&This
->IPicture_iface
);
892 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
893 IConnectionPointContainer
* iface
,
894 IEnumConnectionPoints
** ppEnum
)
896 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
898 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
902 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
903 IConnectionPointContainer
* iface
,
905 IConnectionPoint
**ppCP
)
907 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
908 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
912 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
913 return IConnectionPoint_QueryInterface(This
->pCP
, &IID_IConnectionPoint
, (void**)ppCP
);
914 FIXME("no connection point for %s\n",debugstr_guid(riid
));
915 return CONNECT_E_NOCONNECTION
;
919 /************************************************************************
923 /************************************************************************
924 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
926 * See Windows documentation for more details on IUnknown methods.
928 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
929 IPersistStream
* iface
,
933 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
935 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
938 /************************************************************************
939 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
941 * See Windows documentation for more details on IUnknown methods.
943 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
944 IPersistStream
* iface
)
946 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
948 return IPicture_AddRef(&This
->IPicture_iface
);
951 /************************************************************************
952 * OLEPictureImpl_IPersistStream_Release (IUnknown)
954 * See Windows documentation for more details on IUnknown methods.
956 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
957 IPersistStream
* iface
)
959 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
961 return IPicture_Release(&This
->IPicture_iface
);
964 /************************************************************************
965 * OLEPictureImpl_IPersistStream_GetClassID
967 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
968 IPersistStream
* iface
,CLSID
* pClassID
)
970 TRACE("(%p)\n", pClassID
);
971 *pClassID
= CLSID_StdPicture
;
975 /************************************************************************
976 * OLEPictureImpl_IPersistStream_IsDirty
978 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
979 IPersistStream
* iface
)
981 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
982 FIXME("(%p),stub!\n",This
);
986 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
988 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
989 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
992 /* Does not matter whether this is a coreheader or not, we only use
993 * components which are in both
996 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1000 xbuf
+bfh
->bfOffBits
,
1004 ReleaseDC(0, hdcref
);
1005 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1007 This
->desc
.picType
= PICTYPE_BITMAP
;
1008 OLEPictureImpl_SetBitmap(This
);
1012 static HRESULT
OLEPictureImpl_LoadWICSource(OLEPictureImpl
*This
, IWICBitmapSource
*src
)
1015 BITMAPINFOHEADER bih
;
1018 UINT stride
, buffersize
;
1021 IWICBitmapSource
*real_source
;
1023 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1024 BOOL has_alpha
=FALSE
;
1026 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
, src
, &real_source
);
1027 if (FAILED(hr
)) return hr
;
1029 hr
= IWICBitmapSource_GetSize(real_source
, &width
, &height
);
1030 if (FAILED(hr
)) goto end
;
1032 bih
.biSize
= sizeof(bih
);
1033 bih
.biWidth
= width
;
1034 bih
.biHeight
= -height
;
1036 bih
.biBitCount
= 32;
1037 bih
.biCompression
= BI_RGB
;
1038 bih
.biSizeImage
= 0;
1039 bih
.biXPelsPerMeter
= 4085; /* olepicture ignores the stored resolution */
1040 bih
.biYPelsPerMeter
= 4085;
1042 bih
.biClrImportant
= 0;
1045 buffersize
= stride
* height
;
1047 bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
1058 hr
= IWICBitmapSource_CopyPixels(real_source
, &rc
, stride
, buffersize
, bits
);
1063 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1071 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1074 ReleaseDC(0, hdcref
);
1078 This
->desc
.picType
= PICTYPE_BITMAP
;
1079 OLEPictureImpl_SetBitmap(This
);
1081 /* set transparent pixels to black, all others to white */
1082 for(y
= 0; y
< height
; y
++){
1083 for(x
= 0; x
< width
; x
++){
1084 DWORD
*pixel
= (DWORD
*)(bits
+ stride
*y
+ 4*x
);
1085 if((*pixel
& 0x80000000) == 0)
1097 HDC hdcBmp
, hdcXor
, hdcMask
;
1098 HBITMAP hbmoldBmp
, hbmoldXor
, hbmoldMask
;
1100 This
->hbmXor
= CreateDIBitmap(
1109 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1110 hdcBmp
= CreateCompatibleDC(NULL
);
1111 hdcXor
= CreateCompatibleDC(NULL
);
1112 hdcMask
= CreateCompatibleDC(NULL
);
1114 hbmoldBmp
= SelectObject(hdcBmp
,This
->desc
.u
.bmp
.hbitmap
);
1115 hbmoldXor
= SelectObject(hdcXor
,This
->hbmXor
);
1116 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1118 SetBkColor(hdcXor
,black
);
1119 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1120 BitBlt(hdcXor
,0,0,width
,height
,hdcBmp
,0,0,SRCAND
);
1122 SelectObject(hdcBmp
,hbmoldBmp
);
1123 SelectObject(hdcXor
,hbmoldXor
);
1124 SelectObject(hdcMask
,hbmoldMask
);
1131 ReleaseDC(0, hdcref
);
1134 HeapFree(GetProcessHeap(), 0, bits
);
1135 IWICBitmapSource_Release(real_source
);
1139 static HRESULT
OLEPictureImpl_LoadWICDecoder(OLEPictureImpl
*This
, REFCLSID decoder_clsid
, BYTE
*xbuf
, ULONG xread
)
1142 IWICImagingFactory
*factory
;
1143 IWICBitmapDecoder
*decoder
;
1144 IWICBitmapFrameDecode
*framedecode
;
1148 initresult
= CoInitialize(NULL
);
1150 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
1151 &IID_IWICImagingFactory
, (void**)&factory
);
1152 if (SUCCEEDED(hr
)) /* created factory */
1154 hr
= IWICImagingFactory_CreateStream(factory
, &stream
);
1155 IWICImagingFactory_Release(factory
);
1158 if (SUCCEEDED(hr
)) /* created stream */
1160 hr
= IWICStream_InitializeFromMemory(stream
, xbuf
, xread
);
1162 if (SUCCEEDED(hr
)) /* initialized stream */
1164 hr
= CoCreateInstance(decoder_clsid
, NULL
, CLSCTX_INPROC_SERVER
,
1165 &IID_IWICBitmapDecoder
, (void**)&decoder
);
1166 if (SUCCEEDED(hr
)) /* created decoder */
1168 hr
= IWICBitmapDecoder_Initialize(decoder
, (IStream
*)stream
, WICDecodeMetadataCacheOnLoad
);
1170 if (SUCCEEDED(hr
)) /* initialized decoder */
1171 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
1173 IWICBitmapDecoder_Release(decoder
);
1177 IWICStream_Release(stream
);
1180 if (SUCCEEDED(hr
)) /* got framedecode */
1182 hr
= OLEPictureImpl_LoadWICSource(This
, (IWICBitmapSource
*)framedecode
);
1183 IWICBitmapFrameDecode_Release(framedecode
);
1186 if (SUCCEEDED(initresult
)) CoUninitialize();
1190 /*****************************************************
1191 * start of Icon-specific code
1194 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1197 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1201 TRACE("(this %p, xbuf %p, xread %lu)\n", This
, xbuf
, xread
);
1204 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1205 FIXME("icon.idType=%d\n",cifd->idType);
1206 FIXME("icon.idCount=%d\n",cifd->idCount);
1208 for (i=0;i<cifd->idCount;i++) {
1209 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1210 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1211 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1212 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1213 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1214 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1215 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1216 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1220 /* Need at least one icon to do something. */
1223 ERR("Invalid icon count of zero.\n");
1227 /* If we have more than one icon, try to find the best.
1228 * this currently means '32 pixel wide'.
1230 if (cifd
->idCount
!=1) {
1231 for (i
=0;i
<cifd
->idCount
;i
++) {
1232 if (cifd
->idEntries
[i
].bWidth
== 32)
1235 if (i
==cifd
->idCount
) i
=0;
1237 if (xread
< cifd
->idEntries
[i
].dwDIBOffset
+ cifd
->idEntries
[i
].dwDIBSize
)
1239 ERR("Icon data address %lu is over %lu bytes available.\n",
1240 cifd
->idEntries
[i
].dwDIBOffset
+ cifd
->idEntries
[i
].dwDIBSize
, xread
);
1243 if (cifd
->idType
== 2)
1245 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, cifd
->idEntries
[i
].dwDIBSize
+ 4);
1246 memcpy(buf
, &cifd
->idEntries
[i
].xHotspot
, 4);
1247 memcpy(buf
+ 4, xbuf
+cifd
->idEntries
[i
].dwDIBOffset
, cifd
->idEntries
[i
].dwDIBSize
);
1248 hicon
= CreateIconFromResourceEx(
1250 cifd
->idEntries
[i
].dwDIBSize
+ 4,
1251 FALSE
, /* is cursor */
1253 cifd
->idEntries
[i
].bWidth
,
1254 cifd
->idEntries
[i
].bHeight
,
1257 HeapFree(GetProcessHeap(), 0, buf
);
1261 hicon
= CreateIconFromResourceEx(
1262 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1263 cifd
->idEntries
[i
].dwDIBSize
,
1266 cifd
->idEntries
[i
].bWidth
,
1267 cifd
->idEntries
[i
].bHeight
,
1272 ERR("CreateIcon failed.\n");
1275 This
->desc
.picType
= PICTYPE_ICON
;
1276 This
->desc
.u
.icon
.hicon
= hicon
;
1277 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1278 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1279 hdcRef
= CreateCompatibleDC(0);
1280 This
->himetricWidth
= xpixels_to_himetric(cifd
->idEntries
[i
].bWidth
, hdcRef
);
1281 This
->himetricHeight
= ypixels_to_himetric(cifd
->idEntries
[i
].bHeight
, hdcRef
);
1287 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1288 const BYTE
*data
, ULONG size
)
1293 hemf
= SetEnhMetaFileBits(size
, data
);
1294 if (!hemf
) return E_FAIL
;
1296 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1298 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1299 This
->desc
.u
.emf
.hemf
= hemf
;
1301 This
->origWidth
= 0;
1302 This
->origHeight
= 0;
1303 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1304 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1309 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1310 const BYTE
*data
, ULONG size
)
1312 const APM_HEADER
*header
= (const APM_HEADER
*)data
;
1315 if (size
< sizeof(APM_HEADER
))
1317 if (header
->key
!= 0x9ac6cdd7)
1320 /* SetMetaFileBitsEx performs data check on its own */
1321 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1322 if (!hmf
) return E_FAIL
;
1324 This
->desc
.picType
= PICTYPE_METAFILE
;
1325 This
->desc
.u
.wmf
.hmeta
= hmf
;
1326 This
->desc
.u
.wmf
.xExt
= 0;
1327 This
->desc
.u
.wmf
.yExt
= 0;
1329 This
->origWidth
= 0;
1330 This
->origHeight
= 0;
1331 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1332 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1336 /************************************************************************
1337 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1339 * Loads the binary data from the IStream. Starts at current position.
1340 * There appears to be an 2 DWORD header:
1344 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
1346 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
, IStream
*pStm
) {
1349 BOOL statfailed
= FALSE
;
1350 ULONG xread
, toread
;
1356 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1358 TRACE("(%p,%p)\n",This
,pStm
);
1360 /****************************************************************************************
1361 * Part 1: Load the data
1363 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1364 * out whether we do.
1366 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1367 * compound file. This may explain most, if not all, of the cases of "no
1368 * header", and the header validation should take this into account.
1369 * At least in Visual Basic 6, resource streams, valid headers are
1370 * header[0] == "lt\0\0",
1371 * header[1] == length_of_stream.
1373 * Also handle streams where we do not have a working "Stat" method by
1374 * reading all data until the end of the stream.
1376 hr
= IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1378 TRACE("stat failed with hres %#lx, proceeding to read all data.\n",hr
);
1380 /* we will read at least 8 byte ... just right below */
1381 statstg
.cbSize
.QuadPart
= 8;
1386 headerisdata
= FALSE
;
1388 hr
= IStream_Read(pStm
, header
, 8, &xread
);
1389 if (hr
!= S_OK
|| xread
!=8) {
1390 ERR("Failure while reading picture header (hr is %#lx, nread is %ld).\n",hr
,xread
);
1391 return (hr
?hr
:E_FAIL
);
1393 headerread
+= xread
;
1396 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1397 if (toread
!= 0 && toread
!= header
[1])
1398 FIXME("varying lengths of image data (prev=%lu curr=%lu), only last one will be used\n",
1403 statstg
.cbSize
.QuadPart
= header
[1] + 8;
1406 if (toread
== 0) break;
1408 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1409 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1410 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1411 (header
[0] == EMR_HEADER
) || /* EMF header */
1412 (header
[0] == 0x10000) || /* icon: idReserved 0, idType 1 */
1413 (header
[0] == 0x20000) || /* cursor: idReserved 0, idType 2 */
1414 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1416 ) {/* Found start of bitmap data */
1417 headerisdata
= TRUE
;
1419 toread
= statstg
.cbSize
.QuadPart
-8;
1423 FIXME("Unknown stream header magic: %#lx.\n", header
[0]);
1427 } while (!headerisdata
);
1429 if (statfailed
) { /* we don't know the size ... read all we get */
1430 unsigned int sizeinc
= 4096;
1431 unsigned int origsize
= sizeinc
;
1434 TRACE("Reading all data from stream.\n");
1435 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1437 memcpy (xbuf
, header
, 8);
1439 while (xread
< origsize
) {
1440 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1442 if (hr
!= S_OK
|| !nread
)
1445 if (!nread
|| hr
!= S_OK
) /* done, or error */
1447 if (xread
== origsize
) {
1448 origsize
+= sizeinc
;
1449 sizeinc
= 2*sizeinc
; /* exponential increase */
1450 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1454 TRACE("hr in no-stat loader case is %#lx.\n", hr
);
1455 TRACE("loaded %ld bytes.\n", xread
);
1456 This
->datalen
= xread
;
1459 This
->datalen
= toread
+(headerisdata
?8:0);
1460 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1462 return E_OUTOFMEMORY
;
1465 memcpy (xbuf
, header
, 8);
1467 while (xread
< This
->datalen
) {
1469 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1471 if (hr
!= S_OK
|| !nread
)
1474 if (xread
!= This
->datalen
)
1475 ERR("Could only read %ld of %d bytes out of stream?\n", xread
, This
->datalen
);
1477 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1478 This
->desc
.picType
= PICTYPE_NONE
;
1483 /****************************************************************************************
1484 * Part 2: Process the loaded data
1487 magic
= xbuf
[0] + (xbuf
[1]<<8);
1488 This
->loadtime_format
= magic
;
1491 case BITMAP_FORMAT_GIF
: /* GIF */
1492 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICGifDecoder
, xbuf
, xread
);
1494 case BITMAP_FORMAT_JPEG
: /* JPEG */
1495 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICJpegDecoder
, xbuf
, xread
);
1497 case BITMAP_FORMAT_BMP
: /* Bitmap */
1498 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1500 case BITMAP_FORMAT_PNG
: /* PNG */
1501 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICPngDecoder
, xbuf
, xread
);
1503 case BITMAP_FORMAT_APM
: /* APM */
1504 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1506 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1507 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1514 /* let's see if it's a EMF */
1515 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1516 if (hr
== S_OK
) break;
1518 FIXME("Unknown magic %04x, %ld read bytes:\n", magic
, xread
);
1520 for (i
=0;i
<xread
+8;i
++) {
1521 if (i
<8) MESSAGE("%02x ",((unsigned char*)header
)[i
]);
1522 else MESSAGE("%02x ",xbuf
[i
-8]);
1523 if (i
% 10 == 9) MESSAGE("\n");
1529 This
->bIsDirty
= FALSE
;
1531 /* FIXME: this notify is not really documented */
1533 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1537 static BOOL
serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1539 BOOL success
= FALSE
;
1541 BITMAPINFO
* pInfoBitmap
;
1542 int iNumPaletteEntries
;
1543 unsigned char * pPixelData
;
1544 BITMAPFILEHEADER
* pFileHeader
;
1545 BITMAPINFO
* pInfoHeader
;
1547 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1548 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1550 /* Find out bitmap size and padded length */
1552 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1553 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1555 /* Fetch bitmap palette & pixel data */
1557 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1558 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1560 /* Calculate the total length required for the BMP data */
1561 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1562 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1563 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1565 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1566 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1568 iNumPaletteEntries
= 0;
1571 sizeof(BITMAPFILEHEADER
) +
1572 sizeof(BITMAPINFOHEADER
) +
1573 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1574 pInfoBitmap
->bmiHeader
.biSizeImage
;
1575 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1577 /* Fill the BITMAPFILEHEADER */
1578 pFileHeader
= *ppBuffer
;
1579 pFileHeader
->bfType
= BITMAP_FORMAT_BMP
;
1580 pFileHeader
->bfSize
= *pLength
;
1581 pFileHeader
->bfOffBits
=
1582 sizeof(BITMAPFILEHEADER
) +
1583 sizeof(BITMAPINFOHEADER
) +
1584 iNumPaletteEntries
* sizeof(RGBQUAD
);
1586 /* Fill the BITMAPINFOHEADER and the palette data */
1587 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1588 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1590 (unsigned char *)(*ppBuffer
) +
1591 sizeof(BITMAPFILEHEADER
) +
1592 sizeof(BITMAPINFOHEADER
) +
1593 iNumPaletteEntries
* sizeof(RGBQUAD
),
1594 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1597 HeapFree(GetProcessHeap(), 0, pPixelData
);
1598 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1602 static BOOL
serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1605 BOOL success
= FALSE
;
1607 *ppBuffer
= NULL
; *pLength
= 0;
1608 if (GetIconInfo(hIcon
, &infoIcon
)) {
1610 BITMAPINFO
* pInfoBitmap
;
1611 unsigned char * pIconData
= NULL
;
1612 unsigned int iDataSize
= 0;
1614 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1616 /* Find out icon size */
1618 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1619 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1621 /* Auxiliary pointers */
1622 CURSORICONFILEDIR
* pIconDir
;
1623 CURSORICONFILEDIRENTRY
* pIconEntry
;
1624 BITMAPINFOHEADER
* pIconBitmapHeader
;
1625 unsigned int iOffsetPalette
;
1626 unsigned int iOffsetColorData
;
1627 unsigned int iOffsetMaskData
;
1629 unsigned int iLengthScanLineMask
;
1630 unsigned int iNumEntriesPalette
;
1632 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1634 FIXME("DEBUG: bitmap size is %d x %d\n",
1635 pInfoBitmap->bmiHeader.biWidth,
1636 pInfoBitmap->bmiHeader.biHeight);
1637 FIXME("DEBUG: bitmap bpp is %d\n",
1638 pInfoBitmap->bmiHeader.biBitCount);
1639 FIXME("DEBUG: bitmap nplanes is %d\n",
1640 pInfoBitmap->bmiHeader.biPlanes);
1641 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1642 pInfoBitmap->bmiHeader.biSizeImage);
1644 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1645 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1646 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1648 /* Fill out the CURSORICONFILEDIR */
1649 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1650 pIconDir
->idType
= 1;
1651 pIconDir
->idCount
= 1;
1652 pIconDir
->idReserved
= 0;
1654 /* Fill out the CURSORICONFILEDIRENTRY */
1655 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1656 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1657 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1658 pIconEntry
->bColorCount
=
1659 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1660 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1662 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1663 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1664 pIconEntry
->dwDIBSize
= 0;
1665 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1667 /* Fill out the BITMAPINFOHEADER */
1668 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1669 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
1671 /* Find out whether a palette exists for the bitmap */
1672 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1673 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1674 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1675 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1676 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1677 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1678 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1679 iNumEntriesPalette
= 3;
1680 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1681 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1683 iNumEntriesPalette
= 0;
1686 /* Add bitmap size and header size to icon data size. */
1687 iOffsetPalette
= iDataSize
;
1688 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1689 iOffsetColorData
= iDataSize
;
1690 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1691 iOffsetMaskData
= iDataSize
;
1692 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1693 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1694 pIconBitmapHeader
->biHeight
*= 2;
1695 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1696 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1697 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1698 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1700 /* Get the actual bitmap data from the icon bitmap */
1701 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1702 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1703 if (iNumEntriesPalette
> 0) {
1704 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1705 iNumEntriesPalette
* sizeof(RGBQUAD
));
1708 /* Reset all values so that GetDIBits call succeeds */
1709 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1710 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1711 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1713 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1714 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1715 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1717 printf("ERROR: unable to get bitmap mask (error %u)\n",
1722 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1723 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1725 /* Write out everything produced so far to the stream */
1726 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1730 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1735 Remarks (from MSDN entry on GetIconInfo):
1737 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1738 members of ICONINFO. The calling application must manage
1739 these bitmaps and delete them when they are no longer
1742 if (hDC
) ReleaseDC(0, hDC
);
1743 DeleteObject(infoIcon
.hbmMask
);
1744 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1745 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1747 ERR("Unable to get icon information (error %lu)\n", GetLastError());
1752 static HRESULT WINAPI
OLEPictureImpl_Save(
1753 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1755 HRESULT hResult
= E_NOTIMPL
;
1757 unsigned int iDataSize
;
1760 BOOL serializeResult
= FALSE
;
1761 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1763 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
1765 switch (This
->desc
.picType
) {
1767 header
[0] = 0x0000746c;
1769 hResult
= IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1773 if (This
->bIsDirty
|| !This
->data
) {
1774 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1775 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
1779 HeapFree(GetProcessHeap(), 0, This
->data
);
1780 This
->data
= pIconData
;
1781 This
->datalen
= iDataSize
;
1784 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1785 header
[1] = This
->datalen
;
1786 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1787 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1790 case PICTYPE_BITMAP
:
1791 if (This
->bIsDirty
|| !This
->data
) {
1792 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
1793 case BITMAP_FORMAT_BMP
:
1794 serializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1796 case BITMAP_FORMAT_JPEG
:
1797 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1799 case BITMAP_FORMAT_GIF
:
1800 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1802 case BITMAP_FORMAT_PNG
:
1803 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
1806 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1810 if (!serializeResult
)
1816 HeapFree(GetProcessHeap(), 0, This
->data
);
1817 This
->data
= pIconData
;
1818 This
->datalen
= iDataSize
;
1821 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1822 header
[1] = This
->datalen
;
1823 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1824 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1827 case PICTYPE_METAFILE
:
1828 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1830 case PICTYPE_ENHMETAFILE
:
1831 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1834 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1837 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1841 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1842 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1844 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1845 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1850 /************************************************************************
1854 /************************************************************************
1855 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1857 * See Windows documentation for more details on IUnknown methods.
1859 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1864 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1866 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
1869 /************************************************************************
1870 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1872 * See Windows documentation for more details on IUnknown methods.
1874 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1877 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1879 return IPicture_AddRef(&This
->IPicture_iface
);
1882 /************************************************************************
1883 * OLEPictureImpl_IDispatch_Release (IUnknown)
1885 * See Windows documentation for more details on IUnknown methods.
1887 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1890 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1892 return IPicture_Release(&This
->IPicture_iface
);
1895 /************************************************************************
1896 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1898 * See Windows documentation for more details on IDispatch methods.
1900 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1902 unsigned int* pctinfo
)
1904 TRACE("(%p)\n", pctinfo
);
1911 /************************************************************************
1912 * OLEPictureImpl_GetTypeInfo (IDispatch)
1914 * See Windows documentation for more details on IDispatch methods.
1916 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1920 ITypeInfo
** ppTInfo
)
1925 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
1930 hres
= LoadTypeLib(L
"stdole2.tlb", &tl
);
1933 ERR("Could not load stdole2.tlb\n");
1937 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
1939 ERR("Did not get IPictureDisp typeinfo from typelib, hres %#lx.\n", hres
);
1944 /************************************************************************
1945 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1947 * See Windows documentation for more details on IDispatch methods.
1949 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1952 LPOLESTR
* rgszNames
,
1960 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
1961 rgszNames
, cNames
, (int)lcid
, rgDispId
);
1965 return E_INVALIDARG
;
1969 /* retrieve type information */
1970 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
1974 ERR("GetTypeInfo failed.\n");
1978 /* convert names to DISPIDs */
1979 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
1980 ITypeInfo_Release(pTInfo
);
1986 /************************************************************************
1987 * OLEPictureImpl_Invoke (IDispatch)
1989 * See Windows documentation for more details on IDispatch methods.
1991 static HRESULT WINAPI
OLEPictureImpl_Invoke(
1993 DISPID dispIdMember
,
1997 DISPPARAMS
* pDispParams
,
1998 VARIANT
* pVarResult
,
1999 EXCEPINFO
* pExepInfo
,
2002 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2005 /* validate parameters */
2007 if (!IsEqualIID(riid
, &IID_NULL
))
2009 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2010 return DISP_E_UNKNOWNNAME
;
2015 ERR("null pDispParams not allowed\n");
2016 return DISP_E_PARAMNOTOPTIONAL
;
2019 if (wFlags
& DISPATCH_PROPERTYGET
)
2021 if (pDispParams
->cArgs
!= 0)
2023 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2024 return DISP_E_BADPARAMCOUNT
;
2028 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2029 return DISP_E_PARAMNOTOPTIONAL
;
2032 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2034 if (pDispParams
->cArgs
!= 1)
2036 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2037 return DISP_E_BADPARAMCOUNT
;
2041 switch (dispIdMember
)
2043 case DISPID_PICT_HANDLE
:
2044 if (wFlags
& DISPATCH_PROPERTYGET
)
2046 TRACE("DISPID_PICT_HANDLE\n");
2047 V_VT(pVarResult
) = VT_I4
;
2048 return IPicture_get_Handle(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2051 case DISPID_PICT_HPAL
:
2052 if (wFlags
& DISPATCH_PROPERTYGET
)
2054 TRACE("DISPID_PICT_HPAL\n");
2055 V_VT(pVarResult
) = VT_I4
;
2056 return IPicture_get_hPal(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2058 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2062 TRACE("DISPID_PICT_HPAL\n");
2064 VariantInit(&vararg
);
2065 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2069 hr
= IPicture_set_hPal(&This
->IPicture_iface
, V_I4(&vararg
));
2071 VariantClear(&vararg
);
2075 case DISPID_PICT_TYPE
:
2076 if (wFlags
& DISPATCH_PROPERTYGET
)
2078 TRACE("DISPID_PICT_TYPE\n");
2079 V_VT(pVarResult
) = VT_I2
;
2080 return OLEPictureImpl_get_Type(&This
->IPicture_iface
, &V_I2(pVarResult
));
2083 case DISPID_PICT_WIDTH
:
2084 if (wFlags
& DISPATCH_PROPERTYGET
)
2086 TRACE("DISPID_PICT_WIDTH\n");
2087 V_VT(pVarResult
) = VT_I4
;
2088 return IPicture_get_Width(&This
->IPicture_iface
, &V_I4(pVarResult
));
2091 case DISPID_PICT_HEIGHT
:
2092 if (wFlags
& DISPATCH_PROPERTYGET
)
2094 TRACE("DISPID_PICT_HEIGHT\n");
2095 V_VT(pVarResult
) = VT_I4
;
2096 return IPicture_get_Height(&This
->IPicture_iface
, &V_I4(pVarResult
));
2099 case DISPID_PICT_RENDER
:
2100 if (wFlags
& DISPATCH_METHOD
)
2102 VARIANTARG
*args
= pDispParams
->rgvarg
;
2105 TRACE("DISPID_PICT_RENDER\n");
2107 if (pDispParams
->cArgs
!= 10)
2108 return DISP_E_BADPARAMCOUNT
;
2110 /* All parameters are supposed to be VT_I4 (on 64 bits too). */
2111 for (i
= 0; i
< pDispParams
->cArgs
; i
++)
2112 if (V_VT(&args
[i
]) != VT_I4
)
2114 ERR("DISPID_PICT_RENDER: wrong argument type %d:%d\n", i
, V_VT(&args
[i
]));
2115 return DISP_E_TYPEMISMATCH
;
2118 /* FIXME: rectangle pointer argument handling seems broken on 64 bits,
2119 currently Render() doesn't use it at all so for now NULL is passed. */
2120 return IPicture_Render(&This
->IPicture_iface
,
2121 LongToHandle(V_I4(&args
[9])),
2135 ERR("invalid dispid %#lx or wFlags 0x%x\n", dispIdMember
, wFlags
);
2136 return DISP_E_MEMBERNOTFOUND
;
2140 static const IPictureVtbl OLEPictureImpl_VTable
=
2142 OLEPictureImpl_QueryInterface
,
2143 OLEPictureImpl_AddRef
,
2144 OLEPictureImpl_Release
,
2145 OLEPictureImpl_get_Handle
,
2146 OLEPictureImpl_get_hPal
,
2147 OLEPictureImpl_get_Type
,
2148 OLEPictureImpl_get_Width
,
2149 OLEPictureImpl_get_Height
,
2150 OLEPictureImpl_Render
,
2151 OLEPictureImpl_set_hPal
,
2152 OLEPictureImpl_get_CurDC
,
2153 OLEPictureImpl_SelectPicture
,
2154 OLEPictureImpl_get_KeepOriginalFormat
,
2155 OLEPictureImpl_put_KeepOriginalFormat
,
2156 OLEPictureImpl_PictureChanged
,
2157 OLEPictureImpl_SaveAsFile
,
2158 OLEPictureImpl_get_Attributes
2161 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2163 OLEPictureImpl_IDispatch_QueryInterface
,
2164 OLEPictureImpl_IDispatch_AddRef
,
2165 OLEPictureImpl_IDispatch_Release
,
2166 OLEPictureImpl_GetTypeInfoCount
,
2167 OLEPictureImpl_GetTypeInfo
,
2168 OLEPictureImpl_GetIDsOfNames
,
2169 OLEPictureImpl_Invoke
2172 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2174 OLEPictureImpl_IPersistStream_QueryInterface
,
2175 OLEPictureImpl_IPersistStream_AddRef
,
2176 OLEPictureImpl_IPersistStream_Release
,
2177 OLEPictureImpl_GetClassID
,
2178 OLEPictureImpl_IsDirty
,
2179 OLEPictureImpl_Load
,
2180 OLEPictureImpl_Save
,
2181 OLEPictureImpl_GetSizeMax
2184 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2186 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2187 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2188 OLEPictureImpl_IConnectionPointContainer_Release
,
2189 OLEPictureImpl_EnumConnectionPoints
,
2190 OLEPictureImpl_FindConnectionPoint
2193 /***********************************************************************
2194 * OleCreatePictureIndirect (OLEAUT32.419)
2196 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2197 BOOL Own
, void **ppvObj
)
2199 OLEPictureImpl
* newPict
;
2202 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), Own
, ppvObj
);
2206 hr
= OLEPictureImpl_Construct(lpPictDesc
, Own
, &newPict
);
2207 if (hr
!= S_OK
) return hr
;
2210 * Make sure it supports the interface required by the caller.
2212 hr
= IPicture_QueryInterface(&newPict
->IPicture_iface
, riid
, ppvObj
);
2215 * Release the reference obtained in the constructor. If
2216 * the QueryInterface was unsuccessful, it will free the class.
2218 IPicture_Release(&newPict
->IPicture_iface
);
2224 /***********************************************************************
2225 * OleLoadPicture (OLEAUT32.418)
2227 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2228 REFIID riid
, LPVOID
*ppvObj
)
2234 TRACE("%p, %ld, %d, %s, %p), partially implemented.\n",
2235 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2237 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2240 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2242 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2243 IPicture_Release(newpic
);
2247 hr
= IPersistStream_Load(ps
,lpstream
);
2248 IPersistStream_Release(ps
);
2251 ERR("IPersistStream_Load failed\n");
2252 IPicture_Release(newpic
);
2256 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2258 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2259 IPicture_Release(newpic
);
2263 /***********************************************************************
2264 * OleLoadPictureEx (OLEAUT32.401)
2266 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2267 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2273 FIXME("%p, %ld, %d, %s, %lu, %lu, %#lx, %p, partially implemented.\n",
2274 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2276 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2279 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2281 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2282 IPicture_Release(newpic
);
2286 hr
= IPersistStream_Load(ps
,lpstream
);
2287 IPersistStream_Release(ps
);
2290 ERR("IPersistStream_Load failed\n");
2291 IPicture_Release(newpic
);
2295 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2297 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2298 IPicture_Release(newpic
);
2302 /***********************************************************************
2303 * OleLoadPictureFile (OLEAUT32.422)
2305 HRESULT WINAPI
OleLoadPictureFile(VARIANT file
, LPDISPATCH
*picture
)
2307 FIXME("(%s %p): stub\n", wine_dbgstr_variant(&file
), picture
);
2311 /***********************************************************************
2312 * OleSavePictureFile (OLEAUT32.423)
2314 HRESULT WINAPI
OleSavePictureFile(IDispatch
*picture
, BSTR filename
)
2316 FIXME("(%p %s): stub\n", picture
, debugstr_w(filename
));
2317 return CTL_E_FILENOTFOUND
;
2320 /***********************************************************************
2321 * OleLoadPicturePath (OLEAUT32.424)
2323 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2324 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2330 HGLOBAL hGlobal
= NULL
;
2334 IPersistStream
*pStream
;
2337 WCHAR
*file_candidate
;
2338 WCHAR path_buf
[MAX_PATH
];
2340 TRACE("%s, %p, %ld, %#lx, %s, %p.\n", debugstr_w(szURLorPath
), punkCaller
, dwReserved
,
2341 clrReserved
, debugstr_guid(riid
), ppvRet
);
2343 if (!szURLorPath
|| !ppvRet
)
2344 return E_INVALIDARG
;
2348 /* Convert file URLs to DOS paths. */
2349 if (wcsncmp(szURLorPath
, L
"file:", 5) == 0) {
2351 hRes
= CoInternetParseUrl(szURLorPath
, PARSE_PATH_FROM_URL
, 0, path_buf
,
2352 ARRAY_SIZE(path_buf
), &size
, 0);
2356 file_candidate
= path_buf
;
2359 file_candidate
= szURLorPath
;
2361 /* Handle candidate DOS paths separately. */
2362 if (file_candidate
[1] == ':') {
2363 hFile
= CreateFileW(file_candidate
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2365 if (hFile
== INVALID_HANDLE_VALUE
)
2366 return INET_E_RESOURCE_NOT_FOUND
;
2368 dwFileSize
= GetFileSize(hFile
, NULL
);
2369 if (dwFileSize
!= INVALID_FILE_SIZE
)
2371 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2374 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
) && dwBytesRead
== dwFileSize
;
2377 GlobalFree(hGlobal
);
2385 return INET_E_RESOURCE_NOT_FOUND
;
2387 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2390 GlobalFree(hGlobal
);
2397 hRes
= CreateBindCtx(0, &pbc
);
2398 if (SUCCEEDED(hRes
))
2400 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2401 if (SUCCEEDED(hRes
))
2403 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2404 IMoniker_Release(pmnk
);
2406 IBindCtx_Release(pbc
);
2412 init_res
= CoInitialize(NULL
);
2414 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2415 &IID_IPicture
, (LPVOID
*)&ipicture
);
2416 if (SUCCEEDED(hRes
)) {
2417 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2419 if (SUCCEEDED(hRes
)) {
2420 hRes
= IPersistStream_Load(pStream
, stream
);
2422 if (SUCCEEDED(hRes
)) {
2423 hRes
= IPicture_QueryInterface(ipicture
, riid
, ppvRet
);
2426 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid
));
2428 IPersistStream_Release(pStream
);
2430 IPicture_Release(ipicture
);
2433 IStream_Release(stream
);
2435 if (SUCCEEDED(init_res
))
2441 /*******************************************************************************
2442 * StdPic ClassFactory
2446 /* IUnknown fields */
2447 IClassFactory IClassFactory_iface
;
2449 } IClassFactoryImpl
;
2451 static inline IClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
2453 return CONTAINING_RECORD(iface
, IClassFactoryImpl
, IClassFactory_iface
);
2456 static HRESULT WINAPI
2457 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2458 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2460 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2461 return E_NOINTERFACE
;
2465 SPCF_AddRef(LPCLASSFACTORY iface
) {
2466 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2467 return InterlockedIncrement(&This
->ref
);
2470 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2471 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2472 /* static class, won't be freed */
2473 return InterlockedDecrement(&This
->ref
);
2476 static HRESULT WINAPI
SPCF_CreateInstance(
2477 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2479 /* Creates an uninitialized picture */
2480 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2484 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2485 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2486 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2490 static const IClassFactoryVtbl SPCF_Vtbl
= {
2491 SPCF_QueryInterface
,
2494 SPCF_CreateInstance
,
2497 static IClassFactoryImpl STDPIC_CF
= {{&SPCF_Vtbl
}, 1 };
2499 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= &STDPIC_CF
; }