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
64 #include "wine/debug.h"
65 #include "wine/unicode.h"
66 #include "wine/library.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(olepicture
);
70 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
71 #define BITMAP_FORMAT_JPEG 0xd8ff
72 #define BITMAP_FORMAT_GIF 0x4947
73 #define BITMAP_FORMAT_PNG 0x5089
74 #define BITMAP_FORMAT_APM 0xcdd7
78 /* Header for Aldus Placable Metafiles - a standard metafile follows */
79 typedef struct _APM_HEADER
101 } CURSORICONFILEDIRENTRY
;
108 CURSORICONFILEDIRENTRY idEntries
[1];
113 /*************************************************************************
114 * Declaration of implementation class
117 typedef struct OLEPictureImpl
{
120 * IPicture handles IUnknown
123 IPicture IPicture_iface
;
124 IDispatch IDispatch_iface
;
125 IPersistStream IPersistStream_iface
;
126 IConnectionPointContainer IConnectionPointContainer_iface
;
128 /* Object reference count */
131 /* We own the object and must destroy it ourselves */
134 /* Picture description */
137 /* These are the pixel size of a bitmap */
141 /* And these are the size of the picture converted into HIMETRIC units */
142 OLE_XSIZE_HIMETRIC himetricWidth
;
143 OLE_YSIZE_HIMETRIC himetricHeight
;
145 IConnectionPoint
*pCP
;
149 HBITMAP stock_bitmap
;
151 /* Bitmap transparency mask */
159 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
160 unsigned int loadtime_magic
; /* If a length header was found, saves value */
161 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
164 static inline OLEPictureImpl
*impl_from_IPicture(IPicture
*iface
)
166 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPicture_iface
);
169 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
171 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IDispatch_iface
);
174 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
176 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IPersistStream_iface
);
179 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
181 return CONTAINING_RECORD(iface
, OLEPictureImpl
, IConnectionPointContainer_iface
);
185 * Predeclare VTables. They get initialized at the end.
187 static const IPictureVtbl OLEPictureImpl_VTable
;
188 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
189 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
190 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
192 /* pixels to HIMETRIC units conversion */
193 static inline OLE_XSIZE_HIMETRIC
xpixels_to_himetric(INT pixels
, HDC hdc
)
195 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSX
));
198 static inline OLE_YSIZE_HIMETRIC
ypixels_to_himetric(INT pixels
, HDC hdc
)
200 return MulDiv(pixels
, 2540, GetDeviceCaps(hdc
, LOGPIXELSY
));
203 /***********************************************************************
204 * Implementation of the OLEPictureImpl class.
207 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
)
212 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
213 if(GetObjectW(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
214 ERR("GetObject fails\n");
217 This
->origWidth
= bm
.bmWidth
;
218 This
->origHeight
= bm
.bmHeight
;
220 TRACE("width %d, height %d, bpp %d\n", bm
.bmWidth
, bm
.bmHeight
, bm
.bmBitsPixel
);
222 /* The width and height are stored in HIMETRIC units (0.01 mm),
223 so we take our pixel width divide by pixels per inch and
224 multiply by 25.4 * 100 */
225 /* Should we use GetBitmapDimension if available? */
226 hdcRef
= CreateCompatibleDC(0);
228 This
->himetricWidth
= xpixels_to_himetric(bm
.bmWidth
, hdcRef
);
229 This
->himetricHeight
= ypixels_to_himetric(bm
.bmHeight
, hdcRef
);
230 This
->stock_bitmap
= GetCurrentObject( hdcRef
, OBJ_BITMAP
);
232 This
->loadtime_format
= BITMAP_FORMAT_BMP
;
237 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
241 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
242 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
246 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
247 if(GetObjectW(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
248 ERR("GetObject fails on icon bitmap\n");
252 This
->origWidth
= bm
.bmWidth
;
253 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
254 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
257 This
->himetricWidth
= xpixels_to_himetric(This
->origWidth
, hdcRef
);
258 This
->himetricHeight
= ypixels_to_himetric(This
->origHeight
, hdcRef
);
260 ReleaseDC(0, hdcRef
);
262 DeleteObject(infoIcon
.hbmMask
);
263 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
265 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
269 /************************************************************************
270 * OLEPictureImpl_Construct
272 * This method will construct a new instance of the OLEPictureImpl
275 * The caller of this method must release the object when it's
278 static HRESULT
OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
, OLEPictureImpl
**pict
)
280 OLEPictureImpl
*newObject
;
284 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
287 * Allocate space for the object.
289 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
291 return E_OUTOFMEMORY
;
294 * Initialize the virtual function table.
296 newObject
->IPicture_iface
.lpVtbl
= &OLEPictureImpl_VTable
;
297 newObject
->IDispatch_iface
.lpVtbl
= &OLEPictureImpl_IDispatch_VTable
;
298 newObject
->IPersistStream_iface
.lpVtbl
= &OLEPictureImpl_IPersistStream_VTable
;
299 newObject
->IConnectionPointContainer_iface
.lpVtbl
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
301 newObject
->pCP
= NULL
;
302 hr
= CreateConnectionPoint((IUnknown
*)&newObject
->IPicture_iface
, &IID_IPropertyNotifySink
,
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
);
351 case PICTYPE_ENHMETAFILE
:
352 FIXME("EMF is not supported\n");
353 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
357 WARN("Unsupported type %d\n", pictDesc
->picType
);
358 IPicture_Release(&newObject
->IPicture_iface
);
362 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
365 TRACE("returning %p\n", newObject
);
370 /************************************************************************
371 * OLEPictureImpl_Destroy
373 * This method is called by the Release method when the reference
374 * count goes down to 0. It will free all resources used by
376 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
378 TRACE("(%p)\n", Obj
);
381 IConnectionPoint_Release(Obj
->pCP
);
383 if(Obj
->fOwn
) { /* We need to destroy the picture */
384 switch(Obj
->desc
.picType
) {
386 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
387 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
388 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
390 case PICTYPE_METAFILE
:
391 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
394 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
396 case PICTYPE_ENHMETAFILE
:
397 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
400 case PICTYPE_UNINITIALIZED
:
404 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
408 HeapFree(GetProcessHeap(), 0, Obj
->data
);
409 HeapFree(GetProcessHeap(), 0, Obj
);
413 /************************************************************************
414 * OLEPictureImpl_AddRef (IUnknown)
416 * See Windows documentation for more details on IUnknown methods.
418 static ULONG WINAPI
OLEPictureImpl_AddRef(
421 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
422 ULONG refCount
= InterlockedIncrement(&This
->ref
);
424 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
429 /************************************************************************
430 * OLEPictureImpl_Release (IUnknown)
432 * See Windows documentation for more details on IUnknown methods.
434 static ULONG WINAPI
OLEPictureImpl_Release(
437 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
438 ULONG refCount
= InterlockedDecrement(&This
->ref
);
440 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
443 * If the reference count goes down to 0, perform suicide.
445 if (!refCount
) OLEPictureImpl_Destroy(This
);
450 /************************************************************************
451 * OLEPictureImpl_QueryInterface (IUnknown)
453 * See Windows documentation for more details on IUnknown methods.
455 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
460 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
462 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
469 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
470 *ppvObject
= &This
->IPicture_iface
;
471 else if (IsEqualIID(&IID_IDispatch
, riid
))
472 *ppvObject
= &This
->IDispatch_iface
;
473 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
474 *ppvObject
= &This
->IDispatch_iface
;
475 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
476 *ppvObject
= &This
->IPersistStream_iface
;
477 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
478 *ppvObject
= &This
->IConnectionPointContainer_iface
;
482 FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid
));
483 return E_NOINTERFACE
;
486 IPicture_AddRef(iface
);
491 /***********************************************************************
492 * OLEPicture_SendNotify (internal)
494 * Sends notification messages of changed properties to any interested
497 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
499 IEnumConnections
*pEnum
;
502 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
) != S_OK
)
504 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
505 IPropertyNotifySink
*sink
;
507 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
508 IPropertyNotifySink_OnChanged(sink
, dispID
);
509 IPropertyNotifySink_Release(sink
);
510 IUnknown_Release(CD
.pUnk
);
512 IEnumConnections_Release(pEnum
);
515 /************************************************************************
516 * OLEPictureImpl_get_Handle
518 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
521 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
522 TRACE("(%p)->(%p)\n", This
, phandle
);
527 switch(This
->desc
.picType
) {
529 case PICTYPE_UNINITIALIZED
:
533 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
535 case PICTYPE_METAFILE
:
536 *phandle
= HandleToUlong(This
->desc
.u
.wmf
.hmeta
);
539 *phandle
= HandleToUlong(This
->desc
.u
.icon
.hicon
);
541 case PICTYPE_ENHMETAFILE
:
542 *phandle
= HandleToUlong(This
->desc
.u
.emf
.hemf
);
545 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
548 TRACE("returning handle %08x\n", *phandle
);
552 /************************************************************************
553 * OLEPictureImpl_get_hPal
555 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
558 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
560 TRACE("(%p)->(%p)\n", This
, phandle
);
562 if (!phandle
) return E_POINTER
;
564 if (This
->desc
.picType
== PICTYPE_BITMAP
)
566 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hpal
);
573 /************************************************************************
574 * OLEPictureImpl_get_Type
576 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
579 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
580 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
585 *ptype
= This
->desc
.picType
;
589 /************************************************************************
590 * OLEPictureImpl_get_Width
592 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
593 OLE_XSIZE_HIMETRIC
*pwidth
)
595 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
596 TRACE("(%p)->(%p): width is %d\n", This
, pwidth
, This
->himetricWidth
);
597 *pwidth
= This
->himetricWidth
;
601 /************************************************************************
602 * OLEPictureImpl_get_Height
604 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
605 OLE_YSIZE_HIMETRIC
*pheight
)
607 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
608 TRACE("(%p)->(%p): height is %d\n", This
, pheight
, This
->himetricHeight
);
609 *pheight
= This
->himetricHeight
;
613 static void render_masked_bitmap(OLEPictureImpl
*This
, HDC hdc
,
614 LONG x
, LONG y
, LONG cx
, LONG cy
, OLE_XPOS_HIMETRIC xSrc
, OLE_YPOS_HIMETRIC ySrc
,
615 OLE_XSIZE_HIMETRIC cxSrc
, OLE_YSIZE_HIMETRIC cySrc
, HBITMAP hbmMask
, HBITMAP hbmXor
)
620 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
621 * NB y-axis gets flipped
624 hdcBmp
= CreateCompatibleDC(0);
625 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
626 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
627 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
628 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
629 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
633 HDC hdcMask
= CreateCompatibleDC(0);
634 HBITMAP hOldbm
= SelectObject(hdcMask
, hbmMask
);
636 hbmpOld
= SelectObject(hdcBmp
, hbmXor
);
638 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
639 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
640 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
641 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
642 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
644 SetBkColor(hdc
, RGB(255, 255, 255));
645 SetTextColor(hdc
, RGB(0, 0, 0));
646 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
647 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
649 SelectObject(hdcMask
, hOldbm
);
654 hbmpOld
= SelectObject(hdcBmp
, hbmXor
);
655 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
658 SelectObject(hdcBmp
, hbmpOld
);
662 /************************************************************************
663 * OLEPictureImpl_Render
665 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
666 LONG x
, LONG y
, LONG cx
, LONG cy
,
667 OLE_XPOS_HIMETRIC xSrc
,
668 OLE_YPOS_HIMETRIC ySrc
,
669 OLE_XSIZE_HIMETRIC cxSrc
,
670 OLE_YSIZE_HIMETRIC cySrc
,
673 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
674 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
675 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
677 TRACE("prcWBounds %s\n", wine_dbgstr_rect(prcWBounds
));
679 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
680 return CTL_E_INVALIDPROPERTYVALUE
;
684 * While the documentation suggests this to be here (or after rendering?)
685 * it does cause an endless recursion in my sample app. -MM 20010804
686 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
689 switch(This
->desc
.picType
) {
690 case PICTYPE_UNINITIALIZED
:
696 HBITMAP hbmMask
, hbmXor
;
700 hbmMask
= This
->hbmMask
;
701 hbmXor
= This
->hbmXor
;
706 hbmXor
= This
->desc
.u
.bmp
.hbitmap
;
709 render_masked_bitmap(This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, hbmMask
, hbmXor
);
717 if (!GetIconInfo(This
->desc
.u
.icon
.hicon
, &info
))
720 render_masked_bitmap(This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, info
.hbmMask
, info
.hbmColor
);
722 DeleteObject(info
.hbmMask
);
723 if (info
.hbmColor
) DeleteObject(info
.hbmColor
);
727 case PICTYPE_METAFILE
:
729 POINT prevOrg
, prevWndOrg
;
730 SIZE prevExt
, prevWndExt
;
733 /* Render the WMF to the appropriate location by setting the
734 appropriate ratio between "device units" and "logical units" */
735 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
736 /* For the "source rectangle" the y-axis must be inverted */
737 SetWindowOrgEx(hdc
, xSrc
, This
->himetricHeight
-ySrc
, &prevWndOrg
);
738 SetWindowExtEx(hdc
, cxSrc
, -cySrc
, &prevWndExt
);
739 /* For the "destination rectangle" no inversion is necessary */
740 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
741 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
743 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
744 ERR("PlayMetaFile failed!\n");
746 /* We're done, restore the DC to the previous settings for converting
747 logical units to device units */
748 SetWindowExtEx(hdc
, prevWndExt
.cx
, prevWndExt
.cy
, NULL
);
749 SetWindowOrgEx(hdc
, prevWndOrg
.x
, prevWndOrg
.y
, NULL
);
750 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
751 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
752 SetMapMode(hdc
, oldmode
);
756 case PICTYPE_ENHMETAFILE
:
758 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
759 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
764 FIXME("type %d not implemented\n", This
->desc
.picType
);
770 /************************************************************************
771 * OLEPictureImpl_set_hPal
773 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
776 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
778 TRACE("(%p)->(%08x)\n", This
, hpal
);
780 if (This
->desc
.picType
== PICTYPE_BITMAP
)
782 This
->desc
.u
.bmp
.hpal
= ULongToHandle(hpal
);
783 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
790 /************************************************************************
791 * OLEPictureImpl_get_CurDC
793 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
796 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
797 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
798 if (phdc
) *phdc
= This
->hDCCur
;
802 /************************************************************************
803 * OLEPictureImpl_SelectPicture
805 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
808 OLE_HANDLE
*phbmpOut
)
810 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
811 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
812 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
814 *phdcOut
= This
->hDCCur
;
815 if (This
->hDCCur
) SelectObject(This
->hDCCur
,This
->stock_bitmap
);
816 if (hdcIn
) SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
817 This
->hDCCur
= hdcIn
;
819 *phbmpOut
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
822 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
827 /************************************************************************
828 * OLEPictureImpl_get_KeepOriginalFormat
830 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
833 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
834 TRACE("(%p)->(%p)\n", This
, pfKeep
);
837 *pfKeep
= This
->keepOrigFormat
;
841 /************************************************************************
842 * OLEPictureImpl_put_KeepOriginalFormat
844 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
847 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
848 TRACE("(%p)->(%d)\n", This
, keep
);
849 This
->keepOrigFormat
= keep
;
850 /* FIXME: what DISPID notification here? */
854 /************************************************************************
855 * OLEPictureImpl_PictureChanged
857 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
859 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
860 TRACE("(%p)->()\n", This
);
861 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
862 This
->bIsDirty
= TRUE
;
866 /************************************************************************
867 * OLEPictureImpl_SaveAsFile
869 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
874 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
875 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
876 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
879 /************************************************************************
880 * OLEPictureImpl_get_Attributes
882 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
885 OLEPictureImpl
*This
= impl_from_IPicture(iface
);
886 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
892 switch (This
->desc
.picType
) {
893 case PICTYPE_UNINITIALIZED
:
894 case PICTYPE_NONE
: break;
895 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
896 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
897 case PICTYPE_ENHMETAFILE
: /* fall through */
898 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
899 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
905 /************************************************************************
906 * IConnectionPointContainer
908 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
909 IConnectionPointContainer
* iface
,
913 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
915 return IPicture_QueryInterface(&This
->IPicture_iface
,riid
,ppvoid
);
918 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
919 IConnectionPointContainer
* iface
)
921 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
923 return IPicture_AddRef(&This
->IPicture_iface
);
926 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
927 IConnectionPointContainer
* iface
)
929 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
931 return IPicture_Release(&This
->IPicture_iface
);
934 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
935 IConnectionPointContainer
* iface
,
936 IEnumConnectionPoints
** ppEnum
)
938 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
940 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
944 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
945 IConnectionPointContainer
* iface
,
947 IConnectionPoint
**ppCP
)
949 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
950 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
954 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
955 return IConnectionPoint_QueryInterface(This
->pCP
, &IID_IConnectionPoint
, (void**)ppCP
);
956 FIXME("no connection point for %s\n",debugstr_guid(riid
));
957 return CONNECT_E_NOCONNECTION
;
961 /************************************************************************
965 /************************************************************************
966 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
968 * See Windows documentation for more details on IUnknown methods.
970 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
971 IPersistStream
* iface
,
975 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
977 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
980 /************************************************************************
981 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
983 * See Windows documentation for more details on IUnknown methods.
985 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
986 IPersistStream
* iface
)
988 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
990 return IPicture_AddRef(&This
->IPicture_iface
);
993 /************************************************************************
994 * OLEPictureImpl_IPersistStream_Release (IUnknown)
996 * See Windows documentation for more details on IUnknown methods.
998 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
999 IPersistStream
* iface
)
1001 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1003 return IPicture_Release(&This
->IPicture_iface
);
1006 /************************************************************************
1007 * OLEPictureImpl_IPersistStream_GetClassID
1009 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
1010 IPersistStream
* iface
,CLSID
* pClassID
)
1012 TRACE("(%p)\n", pClassID
);
1013 *pClassID
= CLSID_StdPicture
;
1017 /************************************************************************
1018 * OLEPictureImpl_IPersistStream_IsDirty
1020 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
1021 IPersistStream
* iface
)
1023 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1024 FIXME("(%p),stub!\n",This
);
1028 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1030 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1031 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1034 /* Does not matter whether this is a coreheader or not, we only use
1035 * components which are in both
1038 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1042 xbuf
+bfh
->bfOffBits
,
1046 ReleaseDC(0, hdcref
);
1047 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1049 This
->desc
.picType
= PICTYPE_BITMAP
;
1050 OLEPictureImpl_SetBitmap(This
);
1054 static HRESULT
OLEPictureImpl_LoadWICSource(OLEPictureImpl
*This
, IWICBitmapSource
*src
)
1057 BITMAPINFOHEADER bih
;
1060 UINT stride
, buffersize
;
1063 IWICBitmapSource
*real_source
;
1065 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1066 BOOL has_alpha
=FALSE
;
1068 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
, src
, &real_source
);
1069 if (FAILED(hr
)) return hr
;
1071 hr
= IWICBitmapSource_GetSize(real_source
, &width
, &height
);
1072 if (FAILED(hr
)) goto end
;
1074 bih
.biSize
= sizeof(bih
);
1075 bih
.biWidth
= width
;
1076 bih
.biHeight
= -height
;
1078 bih
.biBitCount
= 32;
1079 bih
.biCompression
= BI_RGB
;
1080 bih
.biSizeImage
= 0;
1081 bih
.biXPelsPerMeter
= 4085; /* olepicture ignores the stored resolution */
1082 bih
.biYPelsPerMeter
= 4085;
1084 bih
.biClrImportant
= 0;
1087 buffersize
= stride
* height
;
1089 bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
1100 hr
= IWICBitmapSource_CopyPixels(real_source
, &rc
, stride
, buffersize
, bits
);
1105 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1113 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1116 ReleaseDC(0, hdcref
);
1120 This
->desc
.picType
= PICTYPE_BITMAP
;
1121 OLEPictureImpl_SetBitmap(This
);
1123 /* set transparent pixels to black, all others to white */
1124 for(y
= 0; y
< height
; y
++){
1125 for(x
= 0; x
< width
; x
++){
1126 DWORD
*pixel
= (DWORD
*)(bits
+ stride
*y
+ 4*x
);
1127 if((*pixel
& 0x80000000) == 0)
1139 HDC hdcBmp
, hdcXor
, hdcMask
;
1140 HBITMAP hbmoldBmp
, hbmoldXor
, hbmoldMask
;
1142 This
->hbmXor
= CreateDIBitmap(
1151 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1152 hdcBmp
= CreateCompatibleDC(NULL
);
1153 hdcXor
= CreateCompatibleDC(NULL
);
1154 hdcMask
= CreateCompatibleDC(NULL
);
1156 hbmoldBmp
= SelectObject(hdcBmp
,This
->desc
.u
.bmp
.hbitmap
);
1157 hbmoldXor
= SelectObject(hdcXor
,This
->hbmXor
);
1158 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1160 SetBkColor(hdcXor
,black
);
1161 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1162 BitBlt(hdcXor
,0,0,width
,height
,hdcBmp
,0,0,SRCAND
);
1164 SelectObject(hdcBmp
,hbmoldBmp
);
1165 SelectObject(hdcXor
,hbmoldXor
);
1166 SelectObject(hdcMask
,hbmoldMask
);
1173 ReleaseDC(0, hdcref
);
1176 HeapFree(GetProcessHeap(), 0, bits
);
1177 IWICBitmapSource_Release(real_source
);
1181 static HRESULT
OLEPictureImpl_LoadWICDecoder(OLEPictureImpl
*This
, REFCLSID decoder_clsid
, BYTE
*xbuf
, ULONG xread
)
1184 IWICImagingFactory
*factory
;
1185 IWICBitmapDecoder
*decoder
;
1186 IWICBitmapFrameDecode
*framedecode
;
1190 initresult
= CoInitialize(NULL
);
1192 hr
= CoCreateInstance(&CLSID_WICImagingFactory
, NULL
, CLSCTX_INPROC_SERVER
,
1193 &IID_IWICImagingFactory
, (void**)&factory
);
1194 if (SUCCEEDED(hr
)) /* created factory */
1196 hr
= IWICImagingFactory_CreateStream(factory
, &stream
);
1197 IWICImagingFactory_Release(factory
);
1200 if (SUCCEEDED(hr
)) /* created stream */
1202 hr
= IWICStream_InitializeFromMemory(stream
, xbuf
, xread
);
1204 if (SUCCEEDED(hr
)) /* initialized stream */
1206 hr
= CoCreateInstance(decoder_clsid
, NULL
, CLSCTX_INPROC_SERVER
,
1207 &IID_IWICBitmapDecoder
, (void**)&decoder
);
1208 if (SUCCEEDED(hr
)) /* created decoder */
1210 hr
= IWICBitmapDecoder_Initialize(decoder
, (IStream
*)stream
, WICDecodeMetadataCacheOnLoad
);
1212 if (SUCCEEDED(hr
)) /* initialized decoder */
1213 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
1215 IWICBitmapDecoder_Release(decoder
);
1219 IWICStream_Release(stream
);
1222 if (SUCCEEDED(hr
)) /* got framedecode */
1224 hr
= OLEPictureImpl_LoadWICSource(This
, (IWICBitmapSource
*)framedecode
);
1225 IWICBitmapFrameDecode_Release(framedecode
);
1228 if (SUCCEEDED(initresult
)) CoUninitialize();
1232 /*****************************************************
1233 * start of Icon-specific code
1236 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1239 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1243 TRACE("(this %p, xbuf %p, xread %u)\n", This
, xbuf
, xread
);
1246 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1247 FIXME("icon.idType=%d\n",cifd->idType);
1248 FIXME("icon.idCount=%d\n",cifd->idCount);
1250 for (i=0;i<cifd->idCount;i++) {
1251 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1252 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1253 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1254 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1255 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1256 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1257 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1258 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1262 /* Need at least one icon to do something. */
1265 ERR("Invalid icon count of zero.\n");
1269 /* If we have more than one icon, try to find the best.
1270 * this currently means '32 pixel wide'.
1272 if (cifd
->idCount
!=1) {
1273 for (i
=0;i
<cifd
->idCount
;i
++) {
1274 if (cifd
->idEntries
[i
].bWidth
== 32)
1277 if (i
==cifd
->idCount
) i
=0;
1279 if (xread
< cifd
->idEntries
[i
].dwDIBOffset
+ cifd
->idEntries
[i
].dwDIBSize
)
1281 ERR("Icon data address %u is over %u bytes available.\n",
1282 cifd
->idEntries
[i
].dwDIBOffset
+ cifd
->idEntries
[i
].dwDIBSize
, xread
);
1285 if (cifd
->idType
== 2)
1287 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, cifd
->idEntries
[i
].dwDIBSize
+ 4);
1288 memcpy(buf
, &cifd
->idEntries
[i
].xHotspot
, 4);
1289 memcpy(buf
+ 4, xbuf
+cifd
->idEntries
[i
].dwDIBOffset
, cifd
->idEntries
[i
].dwDIBSize
);
1290 hicon
= CreateIconFromResourceEx(
1292 cifd
->idEntries
[i
].dwDIBSize
+ 4,
1293 FALSE
, /* is cursor */
1295 cifd
->idEntries
[i
].bWidth
,
1296 cifd
->idEntries
[i
].bHeight
,
1299 HeapFree(GetProcessHeap(), 0, buf
);
1303 hicon
= CreateIconFromResourceEx(
1304 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1305 cifd
->idEntries
[i
].dwDIBSize
,
1308 cifd
->idEntries
[i
].bWidth
,
1309 cifd
->idEntries
[i
].bHeight
,
1314 ERR("CreateIcon failed.\n");
1317 This
->desc
.picType
= PICTYPE_ICON
;
1318 This
->desc
.u
.icon
.hicon
= hicon
;
1319 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1320 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1321 hdcRef
= CreateCompatibleDC(0);
1322 This
->himetricWidth
= xpixels_to_himetric(cifd
->idEntries
[i
].bWidth
, hdcRef
);
1323 This
->himetricHeight
= ypixels_to_himetric(cifd
->idEntries
[i
].bHeight
, hdcRef
);
1329 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1330 const BYTE
*data
, ULONG size
)
1335 hemf
= SetEnhMetaFileBits(size
, data
);
1336 if (!hemf
) return E_FAIL
;
1338 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1340 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1341 This
->desc
.u
.emf
.hemf
= hemf
;
1343 This
->origWidth
= 0;
1344 This
->origHeight
= 0;
1345 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1346 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1351 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1352 const BYTE
*data
, ULONG size
)
1354 const APM_HEADER
*header
= (const APM_HEADER
*)data
;
1357 if (size
< sizeof(APM_HEADER
))
1359 if (header
->key
!= 0x9ac6cdd7)
1362 /* SetMetaFileBitsEx performs data check on its own */
1363 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1364 if (!hmf
) return E_FAIL
;
1366 This
->desc
.picType
= PICTYPE_METAFILE
;
1367 This
->desc
.u
.wmf
.hmeta
= hmf
;
1368 This
->desc
.u
.wmf
.xExt
= 0;
1369 This
->desc
.u
.wmf
.yExt
= 0;
1371 This
->origWidth
= 0;
1372 This
->origHeight
= 0;
1373 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1374 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1378 /************************************************************************
1379 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1381 * Loads the binary data from the IStream. Starts at current position.
1382 * There appears to be an 2 DWORD header:
1386 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
1388 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
, IStream
*pStm
) {
1391 BOOL statfailed
= FALSE
;
1392 ULONG xread
, toread
;
1398 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1400 TRACE("(%p,%p)\n",This
,pStm
);
1402 /****************************************************************************************
1403 * Part 1: Load the data
1405 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1406 * out whether we do.
1408 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1409 * compound file. This may explain most, if not all, of the cases of "no
1410 * header", and the header validation should take this into account.
1411 * At least in Visual Basic 6, resource streams, valid headers are
1412 * header[0] == "lt\0\0",
1413 * header[1] == length_of_stream.
1415 * Also handle streams where we do not have a working "Stat" method by
1416 * reading all data until the end of the stream.
1418 hr
= IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1420 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr
);
1422 /* we will read at least 8 byte ... just right below */
1423 statstg
.cbSize
.QuadPart
= 8;
1428 headerisdata
= FALSE
;
1430 hr
= IStream_Read(pStm
, header
, 8, &xread
);
1431 if (hr
!= S_OK
|| xread
!=8) {
1432 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr
,xread
);
1433 return (hr
?hr
:E_FAIL
);
1435 headerread
+= xread
;
1438 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1439 if (toread
!= 0 && toread
!= header
[1])
1440 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1445 statstg
.cbSize
.QuadPart
= header
[1] + 8;
1448 if (toread
== 0) break;
1450 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1451 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1452 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1453 (header
[0] == EMR_HEADER
) || /* EMF header */
1454 (header
[0] == 0x10000) || /* icon: idReserved 0, idType 1 */
1455 (header
[0] == 0x20000) || /* cursor: idReserved 0, idType 2 */
1456 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1458 ) {/* Found start of bitmap data */
1459 headerisdata
= TRUE
;
1461 toread
= statstg
.cbSize
.QuadPart
-8;
1465 FIXME("Unknown stream header magic: %08x\n", header
[0]);
1469 } while (!headerisdata
);
1471 if (statfailed
) { /* we don't know the size ... read all we get */
1472 unsigned int sizeinc
= 4096;
1473 unsigned int origsize
= sizeinc
;
1476 TRACE("Reading all data from stream.\n");
1477 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1479 memcpy (xbuf
, header
, 8);
1481 while (xread
< origsize
) {
1482 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1484 if (hr
!= S_OK
|| !nread
)
1487 if (!nread
|| hr
!= S_OK
) /* done, or error */
1489 if (xread
== origsize
) {
1490 origsize
+= sizeinc
;
1491 sizeinc
= 2*sizeinc
; /* exponential increase */
1492 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1496 TRACE("hr in no-stat loader case is %08x\n", hr
);
1497 TRACE("loaded %d bytes.\n", xread
);
1498 This
->datalen
= xread
;
1501 This
->datalen
= toread
+(headerisdata
?8:0);
1502 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1504 return E_OUTOFMEMORY
;
1507 memcpy (xbuf
, header
, 8);
1509 while (xread
< This
->datalen
) {
1511 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1513 if (hr
!= S_OK
|| !nread
)
1516 if (xread
!= This
->datalen
)
1517 ERR("Could only read %d of %d bytes out of stream?\n",xread
,This
->datalen
);
1519 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1520 This
->desc
.picType
= PICTYPE_NONE
;
1525 /****************************************************************************************
1526 * Part 2: Process the loaded data
1529 magic
= xbuf
[0] + (xbuf
[1]<<8);
1530 This
->loadtime_format
= magic
;
1533 case BITMAP_FORMAT_GIF
: /* GIF */
1534 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICGifDecoder
, xbuf
, xread
);
1536 case BITMAP_FORMAT_JPEG
: /* JPEG */
1537 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICJpegDecoder
, xbuf
, xread
);
1539 case BITMAP_FORMAT_BMP
: /* Bitmap */
1540 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1542 case BITMAP_FORMAT_PNG
: /* PNG */
1543 hr
= OLEPictureImpl_LoadWICDecoder(This
, &CLSID_WICPngDecoder
, xbuf
, xread
);
1545 case BITMAP_FORMAT_APM
: /* APM */
1546 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1548 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1549 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1556 /* let's see if it's a EMF */
1557 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1558 if (hr
== S_OK
) break;
1560 FIXME("Unknown magic %04x, %d read bytes:\n",magic
,xread
);
1562 for (i
=0;i
<xread
+8;i
++) {
1563 if (i
<8) MESSAGE("%02x ",((unsigned char*)header
)[i
]);
1564 else MESSAGE("%02x ",xbuf
[i
-8]);
1565 if (i
% 10 == 9) MESSAGE("\n");
1571 This
->bIsDirty
= FALSE
;
1573 /* FIXME: this notify is not really documented */
1575 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1579 static BOOL
serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1581 BOOL success
= FALSE
;
1583 BITMAPINFO
* pInfoBitmap
;
1584 int iNumPaletteEntries
;
1585 unsigned char * pPixelData
;
1586 BITMAPFILEHEADER
* pFileHeader
;
1587 BITMAPINFO
* pInfoHeader
;
1589 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1590 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1592 /* Find out bitmap size and padded length */
1594 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1595 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1597 /* Fetch bitmap palette & pixel data */
1599 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1600 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1602 /* Calculate the total length required for the BMP data */
1603 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1604 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1605 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1607 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1608 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1610 iNumPaletteEntries
= 0;
1613 sizeof(BITMAPFILEHEADER
) +
1614 sizeof(BITMAPINFOHEADER
) +
1615 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1616 pInfoBitmap
->bmiHeader
.biSizeImage
;
1617 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1619 /* Fill the BITMAPFILEHEADER */
1620 pFileHeader
= *ppBuffer
;
1621 pFileHeader
->bfType
= BITMAP_FORMAT_BMP
;
1622 pFileHeader
->bfSize
= *pLength
;
1623 pFileHeader
->bfOffBits
=
1624 sizeof(BITMAPFILEHEADER
) +
1625 sizeof(BITMAPINFOHEADER
) +
1626 iNumPaletteEntries
* sizeof(RGBQUAD
);
1628 /* Fill the BITMAPINFOHEADER and the palette data */
1629 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1630 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1632 (unsigned char *)(*ppBuffer
) +
1633 sizeof(BITMAPFILEHEADER
) +
1634 sizeof(BITMAPINFOHEADER
) +
1635 iNumPaletteEntries
* sizeof(RGBQUAD
),
1636 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1639 HeapFree(GetProcessHeap(), 0, pPixelData
);
1640 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1644 static BOOL
serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1647 BOOL success
= FALSE
;
1649 *ppBuffer
= NULL
; *pLength
= 0;
1650 if (GetIconInfo(hIcon
, &infoIcon
)) {
1652 BITMAPINFO
* pInfoBitmap
;
1653 unsigned char * pIconData
= NULL
;
1654 unsigned int iDataSize
= 0;
1656 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1658 /* Find out icon size */
1660 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1661 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1663 /* Auxiliary pointers */
1664 CURSORICONFILEDIR
* pIconDir
;
1665 CURSORICONFILEDIRENTRY
* pIconEntry
;
1666 BITMAPINFOHEADER
* pIconBitmapHeader
;
1667 unsigned int iOffsetPalette
;
1668 unsigned int iOffsetColorData
;
1669 unsigned int iOffsetMaskData
;
1671 unsigned int iLengthScanLineMask
;
1672 unsigned int iNumEntriesPalette
;
1674 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1676 FIXME("DEBUG: bitmap size is %d x %d\n",
1677 pInfoBitmap->bmiHeader.biWidth,
1678 pInfoBitmap->bmiHeader.biHeight);
1679 FIXME("DEBUG: bitmap bpp is %d\n",
1680 pInfoBitmap->bmiHeader.biBitCount);
1681 FIXME("DEBUG: bitmap nplanes is %d\n",
1682 pInfoBitmap->bmiHeader.biPlanes);
1683 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1684 pInfoBitmap->bmiHeader.biSizeImage);
1686 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1687 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1688 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1690 /* Fill out the CURSORICONFILEDIR */
1691 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1692 pIconDir
->idType
= 1;
1693 pIconDir
->idCount
= 1;
1694 pIconDir
->idReserved
= 0;
1696 /* Fill out the CURSORICONFILEDIRENTRY */
1697 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1698 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1699 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1700 pIconEntry
->bColorCount
=
1701 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1702 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1704 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1705 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1706 pIconEntry
->dwDIBSize
= 0;
1707 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1709 /* Fill out the BITMAPINFOHEADER */
1710 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1711 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
1713 /* Find out whether a palette exists for the bitmap */
1714 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1715 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1716 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1717 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1718 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1719 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1720 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1721 iNumEntriesPalette
= 3;
1722 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1723 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1725 iNumEntriesPalette
= 0;
1728 /* Add bitmap size and header size to icon data size. */
1729 iOffsetPalette
= iDataSize
;
1730 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1731 iOffsetColorData
= iDataSize
;
1732 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1733 iOffsetMaskData
= iDataSize
;
1734 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1735 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1736 pIconBitmapHeader
->biHeight
*= 2;
1737 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1738 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1739 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1740 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1742 /* Get the actual bitmap data from the icon bitmap */
1743 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1744 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1745 if (iNumEntriesPalette
> 0) {
1746 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1747 iNumEntriesPalette
* sizeof(RGBQUAD
));
1750 /* Reset all values so that GetDIBits call succeeds */
1751 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1752 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1753 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1755 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1756 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1757 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1759 printf("ERROR: unable to get bitmap mask (error %u)\n",
1764 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1765 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1767 /* Write out everything produced so far to the stream */
1768 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1772 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1777 Remarks (from MSDN entry on GetIconInfo):
1779 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1780 members of ICONINFO. The calling application must manage
1781 these bitmaps and delete them when they are no longer
1784 if (hDC
) ReleaseDC(0, hDC
);
1785 DeleteObject(infoIcon
.hbmMask
);
1786 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1787 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1789 printf("ERROR: Unable to get icon information (error %u)\n",
1795 static HRESULT WINAPI
OLEPictureImpl_Save(
1796 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1798 HRESULT hResult
= E_NOTIMPL
;
1800 unsigned int iDataSize
;
1803 BOOL serializeResult
= FALSE
;
1804 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1806 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
1808 switch (This
->desc
.picType
) {
1810 header
[0] = 0x0000746c;
1812 hResult
= IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1816 if (This
->bIsDirty
|| !This
->data
) {
1817 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1818 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
1822 HeapFree(GetProcessHeap(), 0, This
->data
);
1823 This
->data
= pIconData
;
1824 This
->datalen
= iDataSize
;
1827 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1828 header
[1] = This
->datalen
;
1829 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1830 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1833 case PICTYPE_BITMAP
:
1834 if (This
->bIsDirty
|| !This
->data
) {
1835 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
1836 case BITMAP_FORMAT_BMP
:
1837 serializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1839 case BITMAP_FORMAT_JPEG
:
1840 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1842 case BITMAP_FORMAT_GIF
:
1843 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1845 case BITMAP_FORMAT_PNG
:
1846 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
1849 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1853 if (!serializeResult
)
1859 HeapFree(GetProcessHeap(), 0, This
->data
);
1860 This
->data
= pIconData
;
1861 This
->datalen
= iDataSize
;
1864 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1865 header
[1] = This
->datalen
;
1866 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1867 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1870 case PICTYPE_METAFILE
:
1871 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1873 case PICTYPE_ENHMETAFILE
:
1874 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1877 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1880 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1884 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1885 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1887 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1888 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1893 /************************************************************************
1897 /************************************************************************
1898 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1900 * See Windows documentation for more details on IUnknown methods.
1902 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1907 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1909 return IPicture_QueryInterface(&This
->IPicture_iface
, riid
, ppvoid
);
1912 /************************************************************************
1913 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1915 * See Windows documentation for more details on IUnknown methods.
1917 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1920 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1922 return IPicture_AddRef(&This
->IPicture_iface
);
1925 /************************************************************************
1926 * OLEPictureImpl_IDispatch_Release (IUnknown)
1928 * See Windows documentation for more details on IUnknown methods.
1930 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1933 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
1935 return IPicture_Release(&This
->IPicture_iface
);
1938 /************************************************************************
1939 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1941 * See Windows documentation for more details on IDispatch methods.
1943 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1945 unsigned int* pctinfo
)
1947 TRACE("(%p)\n", pctinfo
);
1954 /************************************************************************
1955 * OLEPictureImpl_GetTypeInfo (IDispatch)
1957 * See Windows documentation for more details on IDispatch methods.
1959 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1963 ITypeInfo
** ppTInfo
)
1965 static const WCHAR stdole2tlb
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1969 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
1974 hres
= LoadTypeLib(stdole2tlb
, &tl
);
1977 ERR("Could not load stdole2.tlb\n");
1981 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
1983 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres
);
1988 /************************************************************************
1989 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1991 * See Windows documentation for more details on IDispatch methods.
1993 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1996 LPOLESTR
* rgszNames
,
2004 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
2005 rgszNames
, cNames
, (int)lcid
, rgDispId
);
2009 return E_INVALIDARG
;
2013 /* retrieve type information */
2014 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
2018 ERR("GetTypeInfo failed.\n");
2022 /* convert names to DISPIDs */
2023 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
2024 ITypeInfo_Release(pTInfo
);
2030 /************************************************************************
2031 * OLEPictureImpl_Invoke (IDispatch)
2033 * See Windows documentation for more details on IDispatch methods.
2035 static HRESULT WINAPI
OLEPictureImpl_Invoke(
2037 DISPID dispIdMember
,
2041 DISPPARAMS
* pDispParams
,
2042 VARIANT
* pVarResult
,
2043 EXCEPINFO
* pExepInfo
,
2046 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2049 /* validate parameters */
2051 if (!IsEqualIID(riid
, &IID_NULL
))
2053 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2054 return DISP_E_UNKNOWNNAME
;
2059 ERR("null pDispParams not allowed\n");
2060 return DISP_E_PARAMNOTOPTIONAL
;
2063 if (wFlags
& DISPATCH_PROPERTYGET
)
2065 if (pDispParams
->cArgs
!= 0)
2067 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2068 return DISP_E_BADPARAMCOUNT
;
2072 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2073 return DISP_E_PARAMNOTOPTIONAL
;
2076 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2078 if (pDispParams
->cArgs
!= 1)
2080 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2081 return DISP_E_BADPARAMCOUNT
;
2085 switch (dispIdMember
)
2087 case DISPID_PICT_HANDLE
:
2088 if (wFlags
& DISPATCH_PROPERTYGET
)
2090 TRACE("DISPID_PICT_HANDLE\n");
2091 V_VT(pVarResult
) = VT_I4
;
2092 return IPicture_get_Handle(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2095 case DISPID_PICT_HPAL
:
2096 if (wFlags
& DISPATCH_PROPERTYGET
)
2098 TRACE("DISPID_PICT_HPAL\n");
2099 V_VT(pVarResult
) = VT_I4
;
2100 return IPicture_get_hPal(&This
->IPicture_iface
, &V_UINT(pVarResult
));
2102 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2106 TRACE("DISPID_PICT_HPAL\n");
2108 VariantInit(&vararg
);
2109 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2113 hr
= IPicture_set_hPal(&This
->IPicture_iface
, V_I4(&vararg
));
2115 VariantClear(&vararg
);
2119 case DISPID_PICT_TYPE
:
2120 if (wFlags
& DISPATCH_PROPERTYGET
)
2122 TRACE("DISPID_PICT_TYPE\n");
2123 V_VT(pVarResult
) = VT_I2
;
2124 return OLEPictureImpl_get_Type(&This
->IPicture_iface
, &V_I2(pVarResult
));
2127 case DISPID_PICT_WIDTH
:
2128 if (wFlags
& DISPATCH_PROPERTYGET
)
2130 TRACE("DISPID_PICT_WIDTH\n");
2131 V_VT(pVarResult
) = VT_I4
;
2132 return IPicture_get_Width(&This
->IPicture_iface
, &V_I4(pVarResult
));
2135 case DISPID_PICT_HEIGHT
:
2136 if (wFlags
& DISPATCH_PROPERTYGET
)
2138 TRACE("DISPID_PICT_HEIGHT\n");
2139 V_VT(pVarResult
) = VT_I4
;
2140 return IPicture_get_Height(&This
->IPicture_iface
, &V_I4(pVarResult
));
2143 case DISPID_PICT_RENDER
:
2144 if (wFlags
& DISPATCH_METHOD
)
2146 VARIANTARG
*args
= pDispParams
->rgvarg
;
2149 TRACE("DISPID_PICT_RENDER\n");
2151 if (pDispParams
->cArgs
!= 10)
2152 return DISP_E_BADPARAMCOUNT
;
2154 /* All parameters are supposed to be VT_I4 (on 64 bits too). */
2155 for (i
= 0; i
< pDispParams
->cArgs
; i
++)
2156 if (V_VT(&args
[i
]) != VT_I4
)
2158 ERR("DISPID_PICT_RENDER: wrong argument type %d:%d\n", i
, V_VT(&args
[i
]));
2159 return DISP_E_TYPEMISMATCH
;
2162 /* FIXME: rectangle pointer argument handling seems broken on 64 bits,
2163 currently Render() doesn't use it at all so for now NULL is passed. */
2164 return IPicture_Render(&This
->IPicture_iface
,
2165 LongToHandle(V_I4(&args
[9])),
2179 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember
, wFlags
);
2180 return DISP_E_MEMBERNOTFOUND
;
2184 static const IPictureVtbl OLEPictureImpl_VTable
=
2186 OLEPictureImpl_QueryInterface
,
2187 OLEPictureImpl_AddRef
,
2188 OLEPictureImpl_Release
,
2189 OLEPictureImpl_get_Handle
,
2190 OLEPictureImpl_get_hPal
,
2191 OLEPictureImpl_get_Type
,
2192 OLEPictureImpl_get_Width
,
2193 OLEPictureImpl_get_Height
,
2194 OLEPictureImpl_Render
,
2195 OLEPictureImpl_set_hPal
,
2196 OLEPictureImpl_get_CurDC
,
2197 OLEPictureImpl_SelectPicture
,
2198 OLEPictureImpl_get_KeepOriginalFormat
,
2199 OLEPictureImpl_put_KeepOriginalFormat
,
2200 OLEPictureImpl_PictureChanged
,
2201 OLEPictureImpl_SaveAsFile
,
2202 OLEPictureImpl_get_Attributes
2205 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2207 OLEPictureImpl_IDispatch_QueryInterface
,
2208 OLEPictureImpl_IDispatch_AddRef
,
2209 OLEPictureImpl_IDispatch_Release
,
2210 OLEPictureImpl_GetTypeInfoCount
,
2211 OLEPictureImpl_GetTypeInfo
,
2212 OLEPictureImpl_GetIDsOfNames
,
2213 OLEPictureImpl_Invoke
2216 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2218 OLEPictureImpl_IPersistStream_QueryInterface
,
2219 OLEPictureImpl_IPersistStream_AddRef
,
2220 OLEPictureImpl_IPersistStream_Release
,
2221 OLEPictureImpl_GetClassID
,
2222 OLEPictureImpl_IsDirty
,
2223 OLEPictureImpl_Load
,
2224 OLEPictureImpl_Save
,
2225 OLEPictureImpl_GetSizeMax
2228 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2230 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2231 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2232 OLEPictureImpl_IConnectionPointContainer_Release
,
2233 OLEPictureImpl_EnumConnectionPoints
,
2234 OLEPictureImpl_FindConnectionPoint
2237 /***********************************************************************
2238 * OleCreatePictureIndirect (OLEAUT32.419)
2240 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2241 BOOL Own
, void **ppvObj
)
2243 OLEPictureImpl
* newPict
;
2246 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), Own
, ppvObj
);
2250 hr
= OLEPictureImpl_Construct(lpPictDesc
, Own
, &newPict
);
2251 if (hr
!= S_OK
) return hr
;
2254 * Make sure it supports the interface required by the caller.
2256 hr
= IPicture_QueryInterface(&newPict
->IPicture_iface
, riid
, ppvObj
);
2259 * Release the reference obtained in the constructor. If
2260 * the QueryInterface was unsuccessful, it will free the class.
2262 IPicture_Release(&newPict
->IPicture_iface
);
2268 /***********************************************************************
2269 * OleLoadPicture (OLEAUT32.418)
2271 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2272 REFIID riid
, LPVOID
*ppvObj
)
2278 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2279 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2281 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2284 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2286 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2287 IPicture_Release(newpic
);
2291 hr
= IPersistStream_Load(ps
,lpstream
);
2292 IPersistStream_Release(ps
);
2295 ERR("IPersistStream_Load failed\n");
2296 IPicture_Release(newpic
);
2300 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2302 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2303 IPicture_Release(newpic
);
2307 /***********************************************************************
2308 * OleLoadPictureEx (OLEAUT32.401)
2310 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2311 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2317 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2318 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2320 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2323 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2325 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2326 IPicture_Release(newpic
);
2330 hr
= IPersistStream_Load(ps
,lpstream
);
2331 IPersistStream_Release(ps
);
2334 ERR("IPersistStream_Load failed\n");
2335 IPicture_Release(newpic
);
2339 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2341 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2342 IPicture_Release(newpic
);
2346 /***********************************************************************
2347 * OleLoadPictureFile (OLEAUT32.422)
2349 HRESULT WINAPI
OleLoadPictureFile(VARIANT file
, LPDISPATCH
*picture
)
2351 FIXME("(%s %p): stub\n", wine_dbgstr_variant(&file
), picture
);
2355 /***********************************************************************
2356 * OleSavePictureFile (OLEAUT32.423)
2358 HRESULT WINAPI
OleSavePictureFile(IDispatch
*picture
, BSTR filename
)
2360 FIXME("(%p %s): stub\n", picture
, debugstr_w(filename
));
2361 return CTL_E_FILENOTFOUND
;
2364 /***********************************************************************
2365 * OleLoadPicturePath (OLEAUT32.424)
2367 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2368 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2371 static const WCHAR file
[] = { 'f','i','l','e',':',0 };
2375 HGLOBAL hGlobal
= NULL
;
2379 IPersistStream
*pStream
;
2382 WCHAR
*file_candidate
;
2383 WCHAR path_buf
[MAX_PATH
];
2385 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2386 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2387 debugstr_guid(riid
), ppvRet
);
2389 if (!szURLorPath
|| !ppvRet
)
2390 return E_INVALIDARG
;
2394 /* Convert file URLs to DOS paths. */
2395 if (strncmpW(szURLorPath
, file
, 5) == 0) {
2397 hRes
= CoInternetParseUrl(szURLorPath
, PARSE_PATH_FROM_URL
, 0, path_buf
,
2398 ARRAY_SIZE(path_buf
), &size
, 0);
2402 file_candidate
= path_buf
;
2405 file_candidate
= szURLorPath
;
2407 /* Handle candidate DOS paths separately. */
2408 if (file_candidate
[1] == ':') {
2409 hFile
= CreateFileW(file_candidate
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2411 if (hFile
== INVALID_HANDLE_VALUE
)
2412 return INET_E_RESOURCE_NOT_FOUND
;
2414 dwFileSize
= GetFileSize(hFile
, NULL
);
2415 if (dwFileSize
!= INVALID_FILE_SIZE
)
2417 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2420 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
) && dwBytesRead
== dwFileSize
;
2423 GlobalFree(hGlobal
);
2431 return INET_E_RESOURCE_NOT_FOUND
;
2433 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2436 GlobalFree(hGlobal
);
2443 hRes
= CreateBindCtx(0, &pbc
);
2444 if (SUCCEEDED(hRes
))
2446 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2447 if (SUCCEEDED(hRes
))
2449 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2450 IMoniker_Release(pmnk
);
2452 IBindCtx_Release(pbc
);
2458 init_res
= CoInitialize(NULL
);
2460 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2461 &IID_IPicture
, (LPVOID
*)&ipicture
);
2462 if (SUCCEEDED(hRes
)) {
2463 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2465 if (SUCCEEDED(hRes
)) {
2466 hRes
= IPersistStream_Load(pStream
, stream
);
2468 if (SUCCEEDED(hRes
)) {
2469 hRes
= IPicture_QueryInterface(ipicture
, riid
, ppvRet
);
2472 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid
));
2474 IPersistStream_Release(pStream
);
2476 IPicture_Release(ipicture
);
2479 IStream_Release(stream
);
2481 if (SUCCEEDED(init_res
))
2487 /*******************************************************************************
2488 * StdPic ClassFactory
2492 /* IUnknown fields */
2493 IClassFactory IClassFactory_iface
;
2495 } IClassFactoryImpl
;
2497 static inline IClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
2499 return CONTAINING_RECORD(iface
, IClassFactoryImpl
, IClassFactory_iface
);
2502 static HRESULT WINAPI
2503 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2504 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2506 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2507 return E_NOINTERFACE
;
2511 SPCF_AddRef(LPCLASSFACTORY iface
) {
2512 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2513 return InterlockedIncrement(&This
->ref
);
2516 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2517 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2518 /* static class, won't be freed */
2519 return InterlockedDecrement(&This
->ref
);
2522 static HRESULT WINAPI
SPCF_CreateInstance(
2523 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2525 /* Creates an uninitialized picture */
2526 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2530 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2531 IClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
2532 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2536 static const IClassFactoryVtbl SPCF_Vtbl
= {
2537 SPCF_QueryInterface
,
2540 SPCF_CreateInstance
,
2543 static IClassFactoryImpl STDPIC_CF
= {{&SPCF_Vtbl
}, 1 };
2545 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= &STDPIC_CF
; }