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 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
52 #define UINT8 JPEG_UINT8
53 #define UINT16 JPEG_UINT16
54 #define boolean jpeg_boolean
65 /* Must be before wine includes, the header has things conflicting with
69 #define NONAMELESSUNION
70 #define NONAMELESSSTRUCT
82 #include "wine/debug.h"
83 #include "wine/unicode.h"
85 #include "wine/wingdi16.h"
89 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
93 /* Header for Aldus Placable Metafiles - a standard metafile follows */
94 typedef struct _APM_HEADER
116 } CURSORICONFILEDIRENTRY
;
123 CURSORICONFILEDIRENTRY idEntries
[1];
128 /*************************************************************************
129 * Declaration of implementation class
132 typedef struct OLEPictureImpl
{
135 * IPicture handles IUnknown
138 const IPictureVtbl
*lpVtbl
;
139 const IDispatchVtbl
*lpvtblIDispatch
;
140 const IPersistStreamVtbl
*lpvtblIPersistStream
;
141 const IConnectionPointContainerVtbl
*lpvtblIConnectionPointContainer
;
143 /* Object reference count */
146 /* We own the object and must destroy it ourselves */
149 /* Picture description */
152 /* These are the pixel size of a bitmap */
156 /* And these are the size of the picture converted into HIMETRIC units */
157 OLE_XSIZE_HIMETRIC himetricWidth
;
158 OLE_YSIZE_HIMETRIC himetricHeight
;
160 IConnectionPoint
*pCP
;
165 /* Bitmap transparency mask */
173 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
174 unsigned int loadtime_magic
; /* If a length header was found, saves value */
175 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
179 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
182 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
184 return (OLEPictureImpl
*)((char*)iface
- FIELD_OFFSET(OLEPictureImpl
, lpvtblIDispatch
));
187 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
189 return (OLEPictureImpl
*)((char*)iface
- FIELD_OFFSET(OLEPictureImpl
, lpvtblIPersistStream
));
192 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
194 return (OLEPictureImpl
*)((char*)iface
- FIELD_OFFSET(OLEPictureImpl
, lpvtblIConnectionPointContainer
));
198 * Predeclare VTables. They get initialized at the end.
200 static const IPictureVtbl OLEPictureImpl_VTable
;
201 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
202 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
203 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
205 /***********************************************************************
206 * Implementation of the OLEPictureImpl class.
209 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
) {
213 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
214 if(GetObjectA(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
215 ERR("GetObject fails\n");
218 This
->origWidth
= bm
.bmWidth
;
219 This
->origHeight
= bm
.bmHeight
;
220 /* The width and height are stored in HIMETRIC units (0.01 mm),
221 so we take our pixel width divide by pixels per inch and
222 multiply by 25.4 * 100 */
223 /* Should we use GetBitmapDimension if available? */
224 hdcRef
= CreateCompatibleDC(0);
225 This
->himetricWidth
=(bm
.bmWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
226 This
->himetricHeight
=(bm
.bmHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
230 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
234 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
235 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
239 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
240 if(GetObjectA(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
241 ERR("GetObject fails on icon bitmap\n");
245 This
->origWidth
= bm
.bmWidth
;
246 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
247 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
249 This
->himetricWidth
= (This
->origWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
250 This
->himetricHeight
= (This
->origHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
251 ReleaseDC(0, hdcRef
);
253 DeleteObject(infoIcon
.hbmMask
);
254 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
256 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
260 /************************************************************************
261 * OLEPictureImpl_Construct
263 * This method will construct a new instance of the OLEPictureImpl
266 * The caller of this method must release the object when it's
269 static OLEPictureImpl
* OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
)
271 OLEPictureImpl
* newObject
= 0;
274 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
277 * Allocate space for the object.
279 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
285 * Initialize the virtual function table.
287 newObject
->lpVtbl
= &OLEPictureImpl_VTable
;
288 newObject
->lpvtblIDispatch
= &OLEPictureImpl_IDispatch_VTable
;
289 newObject
->lpvtblIPersistStream
= &OLEPictureImpl_IPersistStream_VTable
;
290 newObject
->lpvtblIConnectionPointContainer
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
292 newObject
->pCP
= NULL
;
293 CreateConnectionPoint((IUnknown
*)newObject
,&IID_IPropertyNotifySink
,&newObject
->pCP
);
296 HeapFree(GetProcessHeap(), 0, newObject
);
301 * Start with one reference count. The caller of this function
302 * must release the interface pointer when it is done.
305 newObject
->hDCCur
= 0;
307 newObject
->fOwn
= fOwn
;
309 /* dunno about original value */
310 newObject
->keepOrigFormat
= TRUE
;
312 newObject
->hbmMask
= NULL
;
313 newObject
->hbmXor
= NULL
;
314 newObject
->loadtime_magic
= 0xdeadbeef;
315 newObject
->loadtime_format
= 0;
316 newObject
->bIsDirty
= FALSE
;
319 newObject
->desc
= *pictDesc
;
321 switch(pictDesc
->picType
) {
323 OLEPictureImpl_SetBitmap(newObject
);
326 case PICTYPE_METAFILE
:
327 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
328 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
329 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
333 /* not sure what to do here */
334 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
338 OLEPictureImpl_SetIcon(newObject
);
340 case PICTYPE_ENHMETAFILE
:
342 FIXME("Unsupported type %d\n", pictDesc
->picType
);
343 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
347 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
350 TRACE("returning %p\n", newObject
);
354 /************************************************************************
355 * OLEPictureImpl_Destroy
357 * This method is called by the Release method when the reference
358 * count goes down to 0. It will free all resources used by
360 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
362 TRACE("(%p)\n", Obj
);
365 IConnectionPoint_Release(Obj
->pCP
);
367 if(Obj
->fOwn
) { /* We need to destroy the picture */
368 switch(Obj
->desc
.picType
) {
370 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
371 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
372 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
374 case PICTYPE_METAFILE
:
375 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
378 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
380 case PICTYPE_ENHMETAFILE
:
381 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
384 case PICTYPE_UNINITIALIZED
:
388 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
392 HeapFree(GetProcessHeap(), 0, Obj
->data
);
393 HeapFree(GetProcessHeap(), 0, Obj
);
397 /************************************************************************
398 * OLEPictureImpl_AddRef (IUnknown)
400 * See Windows documentation for more details on IUnknown methods.
402 static ULONG WINAPI
OLEPictureImpl_AddRef(
405 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
406 ULONG refCount
= InterlockedIncrement(&This
->ref
);
408 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
413 /************************************************************************
414 * OLEPictureImpl_Release (IUnknown)
416 * See Windows documentation for more details on IUnknown methods.
418 static ULONG WINAPI
OLEPictureImpl_Release(
421 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
422 ULONG refCount
= InterlockedDecrement(&This
->ref
);
424 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
427 * If the reference count goes down to 0, perform suicide.
429 if (!refCount
) OLEPictureImpl_Destroy(This
);
434 /************************************************************************
435 * OLEPictureImpl_QueryInterface (IUnknown)
437 * See Windows documentation for more details on IUnknown methods.
439 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
444 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
445 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
448 * Perform a sanity check on the parameters.
450 if ( (This
==0) || (ppvObject
==0) )
454 * Initialize the return parameter.
459 * Compare the riid with the interface IDs implemented by this object.
461 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
462 *ppvObject
= (IPicture
*)This
;
463 else if (IsEqualIID(&IID_IDispatch
, riid
))
464 *ppvObject
= (IDispatch
*)&(This
->lpvtblIDispatch
);
465 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
466 *ppvObject
= (IDispatch
*)&(This
->lpvtblIDispatch
);
467 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
468 *ppvObject
= (IPersistStream
*)&(This
->lpvtblIPersistStream
);
469 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
470 *ppvObject
= (IConnectionPointContainer
*)&(This
->lpvtblIConnectionPointContainer
);
473 * Check that we obtained an interface.
477 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
478 return E_NOINTERFACE
;
482 * Query Interface always increases the reference count by one when it is
485 OLEPictureImpl_AddRef((IPicture
*)This
);
490 /***********************************************************************
491 * OLEPicture_SendNotify (internal)
493 * Sends notification messages of changed properties to any interested
496 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
498 IEnumConnections
*pEnum
;
501 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
))
503 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
504 IPropertyNotifySink
*sink
;
506 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
507 IPropertyNotifySink_OnChanged(sink
, dispID
);
508 IPropertyNotifySink_Release(sink
);
509 IUnknown_Release(CD
.pUnk
);
511 IEnumConnections_Release(pEnum
);
514 /************************************************************************
515 * OLEPictureImpl_get_Handle
517 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
520 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
521 TRACE("(%p)->(%p)\n", This
, phandle
);
522 switch(This
->desc
.picType
) {
524 case PICTYPE_UNINITIALIZED
:
528 *phandle
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
530 case PICTYPE_METAFILE
:
531 *phandle
= (OLE_HANDLE
)This
->desc
.u
.wmf
.hmeta
;
534 *phandle
= (OLE_HANDLE
)This
->desc
.u
.icon
.hicon
;
536 case PICTYPE_ENHMETAFILE
:
537 *phandle
= (OLE_HANDLE
)This
->desc
.u
.emf
.hemf
;
540 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
543 TRACE("returning handle %08x\n", *phandle
);
547 /************************************************************************
548 * OLEPictureImpl_get_hPal
550 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
553 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
555 TRACE("(%p)->(%p)\n", This
, phandle
);
560 switch (This
->desc
.picType
) {
561 case (UINT
)PICTYPE_UNINITIALIZED
:
567 *phandle
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hpal
;
570 case PICTYPE_METAFILE
:
574 case PICTYPE_ENHMETAFILE
:
576 FIXME("unimplemented for type %d. Returning 0 palette.\n",
582 TRACE("returning 0x%08x, palette handle %08x\n", hres
, *phandle
);
586 /************************************************************************
587 * OLEPictureImpl_get_Type
589 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
592 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
593 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
594 *ptype
= This
->desc
.picType
;
598 /************************************************************************
599 * OLEPictureImpl_get_Width
601 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
602 OLE_XSIZE_HIMETRIC
*pwidth
)
604 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
605 TRACE("(%p)->(%p): width is %d\n", This
, pwidth
, This
->himetricWidth
);
606 *pwidth
= This
->himetricWidth
;
610 /************************************************************************
611 * OLEPictureImpl_get_Height
613 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
614 OLE_YSIZE_HIMETRIC
*pheight
)
616 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
617 TRACE("(%p)->(%p): height is %d\n", This
, pheight
, This
->himetricHeight
);
618 *pheight
= This
->himetricHeight
;
622 /************************************************************************
623 * OLEPictureImpl_Render
625 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
626 LONG x
, LONG y
, LONG cx
, LONG cy
,
627 OLE_XPOS_HIMETRIC xSrc
,
628 OLE_YPOS_HIMETRIC ySrc
,
629 OLE_XSIZE_HIMETRIC cxSrc
,
630 OLE_YSIZE_HIMETRIC cySrc
,
633 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
634 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
635 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
637 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds
->left
, prcWBounds
->top
,
638 prcWBounds
->right
, prcWBounds
->bottom
);
640 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
641 return CTL_E_INVALIDPROPERTYVALUE
;
645 * While the documentation suggests this to be here (or after rendering?)
646 * it does cause an endless recursion in my sample app. -MM 20010804
647 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
650 switch(This
->desc
.picType
) {
651 case PICTYPE_UNINITIALIZED
:
660 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
661 NB y-axis gets flipped */
663 hdcBmp
= CreateCompatibleDC(0);
664 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
665 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
666 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
667 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
668 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
671 HDC hdcMask
= CreateCompatibleDC(0);
672 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
674 hbmpOld
= SelectObject(hdcBmp
, This
->hbmXor
);
676 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
677 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
678 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
679 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
680 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
682 SetBkColor(hdc
, RGB(255, 255, 255));
683 SetTextColor(hdc
, RGB(0, 0, 0));
684 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
685 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
687 SelectObject(hdcMask
, hOldbm
);
690 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
691 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
694 SelectObject(hdcBmp
, hbmpOld
);
699 FIXME("Not quite correct implementation of rendering icons...\n");
700 DrawIcon(hdc
,x
,y
,This
->desc
.u
.icon
.hicon
);
703 case PICTYPE_METAFILE
:
709 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
710 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
711 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
713 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
714 ERR("PlayMetaFile failed!\n");
716 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
717 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
718 SetMapMode(hdc
, oldmode
);
722 case PICTYPE_ENHMETAFILE
:
724 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
725 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
730 FIXME("type %d not implemented\n", This
->desc
.picType
);
736 /************************************************************************
737 * OLEPictureImpl_set_hPal
739 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
742 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
743 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
744 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
748 /************************************************************************
749 * OLEPictureImpl_get_CurDC
751 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
754 OLEPictureImpl
*This
= (OLEPictureImpl
*)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
= (OLEPictureImpl
*)iface
;
769 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
770 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
771 SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
774 *phdcOut
= This
->hDCCur
;
775 This
->hDCCur
= hdcIn
;
777 *phbmpOut
= (OLE_HANDLE
)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
= (OLEPictureImpl
*)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
= (OLEPictureImpl
*)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
= (OLEPictureImpl
*)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
= (OLEPictureImpl
*)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
= (OLEPictureImpl
*)iface
;
844 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
846 switch (This
->desc
.picType
) {
847 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
848 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
849 case PICTYPE_ENHMETAFILE
: /* fall through */
850 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
851 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
857 /************************************************************************
858 * IConnectionPointContainer
860 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
861 IConnectionPointContainer
* iface
,
865 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
867 return IPicture_QueryInterface((IPicture
*)This
,riid
,ppvoid
);
870 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
871 IConnectionPointContainer
* iface
)
873 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
875 return IPicture_AddRef((IPicture
*)This
);
878 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
879 IConnectionPointContainer
* iface
)
881 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
883 return IPicture_Release((IPicture
*)This
);
886 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
887 IConnectionPointContainer
* iface
,
888 IEnumConnectionPoints
** ppEnum
)
890 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
892 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
896 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
897 IConnectionPointContainer
* iface
,
899 IConnectionPoint
**ppCP
)
901 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
902 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
906 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
907 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
908 FIXME("no connection point for %s\n",debugstr_guid(riid
));
909 return CONNECT_E_NOCONNECTION
;
913 /************************************************************************
917 /************************************************************************
918 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
920 * See Windows documentation for more details on IUnknown methods.
922 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
923 IPersistStream
* iface
,
927 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
929 return IPicture_QueryInterface((IPicture
*)This
, riid
, ppvoid
);
932 /************************************************************************
933 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
935 * See Windows documentation for more details on IUnknown methods.
937 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
938 IPersistStream
* iface
)
940 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
942 return IPicture_AddRef((IPicture
*)This
);
945 /************************************************************************
946 * OLEPictureImpl_IPersistStream_Release (IUnknown)
948 * See Windows documentation for more details on IUnknown methods.
950 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
951 IPersistStream
* iface
)
953 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
955 return IPicture_Release((IPicture
*)This
);
958 /************************************************************************
959 * OLEPictureImpl_IPersistStream_GetClassID
961 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
962 IPersistStream
* iface
,CLSID
* pClassID
)
964 TRACE("(%p)\n", pClassID
);
965 *pClassID
= CLSID_StdPicture
;
969 /************************************************************************
970 * OLEPictureImpl_IPersistStream_IsDirty
972 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
973 IPersistStream
* iface
)
975 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
976 FIXME("(%p),stub!\n",This
);
980 #ifdef SONAME_LIBJPEG
982 static void *libjpeg_handle
;
983 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
984 MAKE_FUNCPTR(jpeg_std_error
);
985 MAKE_FUNCPTR(jpeg_CreateDecompress
);
986 MAKE_FUNCPTR(jpeg_read_header
);
987 MAKE_FUNCPTR(jpeg_start_decompress
);
988 MAKE_FUNCPTR(jpeg_read_scanlines
);
989 MAKE_FUNCPTR(jpeg_finish_decompress
);
990 MAKE_FUNCPTR(jpeg_destroy_decompress
);
993 static void *load_libjpeg(void)
995 if((libjpeg_handle
= wine_dlopen(SONAME_LIBJPEG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
997 #define LOAD_FUNCPTR(f) \
998 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
999 libjpeg_handle = NULL; \
1003 LOAD_FUNCPTR(jpeg_std_error
);
1004 LOAD_FUNCPTR(jpeg_CreateDecompress
);
1005 LOAD_FUNCPTR(jpeg_read_header
);
1006 LOAD_FUNCPTR(jpeg_start_decompress
);
1007 LOAD_FUNCPTR(jpeg_read_scanlines
);
1008 LOAD_FUNCPTR(jpeg_finish_decompress
);
1009 LOAD_FUNCPTR(jpeg_destroy_decompress
);
1012 return libjpeg_handle
;
1015 /* for the jpeg decompressor source manager. */
1016 static void _jpeg_init_source(j_decompress_ptr cinfo
) { }
1018 static jpeg_boolean
_jpeg_fill_input_buffer(j_decompress_ptr cinfo
) {
1019 ERR("(), should not get here.\n");
1023 static void _jpeg_skip_input_data(j_decompress_ptr cinfo
,long num_bytes
) {
1024 TRACE("Skipping %ld bytes...\n", num_bytes
);
1025 cinfo
->src
->next_input_byte
+= num_bytes
;
1026 cinfo
->src
->bytes_in_buffer
-= num_bytes
;
1029 static jpeg_boolean
_jpeg_resync_to_restart(j_decompress_ptr cinfo
, int desired
) {
1030 ERR("(desired=%d), should not get here.\n",desired
);
1033 static void _jpeg_term_source(j_decompress_ptr cinfo
) { }
1034 #endif /* SONAME_LIBJPEG */
1037 unsigned char *data
;
1038 unsigned int curoff
;
1042 static int _gif_inputfunc(GifFileType
*gif
, GifByteType
*data
, int len
) {
1043 struct gifdata
*gd
= (struct gifdata
*)gif
->UserData
;
1045 if (len
+gd
->curoff
> gd
->len
) {
1046 ERR("Trying to read %d bytes, but only %d available.\n",len
, gd
->len
-gd
->curoff
);
1047 len
= gd
->len
- gd
->curoff
;
1049 memcpy(data
, gd
->data
+gd
->curoff
, len
);
1055 static HRESULT
OLEPictureImpl_LoadGif(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1066 int transparent
= -1;
1073 gif
= DGifOpen((void*)&gd
, _gif_inputfunc
);
1074 ret
= DGifSlurp(gif
);
1075 if (ret
== GIF_ERROR
) {
1076 ERR("Failed reading GIF using libgif.\n");
1079 TRACE("screen height %d, width %d\n", gif
->SWidth
, gif
->SHeight
);
1080 TRACE("color res %d, backgcolor %d\n", gif
->SColorResolution
, gif
->SBackGroundColor
);
1081 TRACE("imgcnt %d\n", gif
->ImageCount
);
1082 if (gif
->ImageCount
<1) {
1083 ERR("GIF stream does not have images inside?\n");
1086 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1087 gif
->Image
.Width
, gif
->Image
.Height
,
1088 gif
->Image
.Left
, gif
->Image
.Top
,
1089 gif
->Image
.Interlace
1092 padding
= (gif
->SWidth
+3) & ~3;
1093 si
= gif
->SavedImages
+0;
1094 gid
= &(si
->ImageDesc
);
1096 if (!cm
) cm
= gif
->SColorMap
;
1097 bmi
= HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER
)+(cm
->ColorCount
)*sizeof(RGBQUAD
));
1098 bytes
= HeapAlloc(GetProcessHeap(),0,padding
*gif
->SHeight
);
1100 /* look for the transparent color extension */
1101 for (i
= 0; i
< si
->ExtensionBlockCount
; ++i
) {
1102 eb
= si
->ExtensionBlocks
+ i
;
1103 if (eb
->Function
== 0xF9 && eb
->ByteCount
== 4) {
1104 if ((eb
->Bytes
[0] & 1) == 1) {
1105 transparent
= (unsigned char)eb
->Bytes
[3];
1110 for (i
= 0; i
< cm
->ColorCount
; i
++) {
1111 bmi
->bmiColors
[i
].rgbRed
= cm
->Colors
[i
].Red
;
1112 bmi
->bmiColors
[i
].rgbGreen
= cm
->Colors
[i
].Green
;
1113 bmi
->bmiColors
[i
].rgbBlue
= cm
->Colors
[i
].Blue
;
1114 if (i
== transparent
) {
1115 This
->rgbTrans
= RGB(bmi
->bmiColors
[i
].rgbRed
,
1116 bmi
->bmiColors
[i
].rgbGreen
,
1117 bmi
->bmiColors
[i
].rgbBlue
);
1121 /* Map to in picture coordinates */
1122 for (i
= 0, j
= 0; i
< gid
->Height
; i
++) {
1123 if (gif
->Image
.Interlace
) {
1125 bytes
+ (gid
->Top
+ j
) * padding
+ gid
->Left
,
1126 si
->RasterBits
+ i
* gid
->Width
,
1129 /* Lower bits of interlaced counter encode current interlace */
1130 if (j
& 1) j
+= 2; /* Currently filling odd rows */
1131 else if (j
& 2) j
+= 4; /* Currently filling even rows not multiples of 4 */
1132 else j
+= 8; /* Currently filling every 8th row or 4th row in-between */
1134 if (j
>= gid
->Height
&& i
< gid
->Height
&& (j
& 1) == 0) {
1135 /* End of current interlace, go to next interlace */
1136 if (j
& 2) j
= 1; /* Next iteration fills odd rows */
1137 else if (j
& 4) j
= 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1138 else j
= 4; /* Next iteration fills rows in-between rows mod 6 */
1142 bytes
+ (gid
->Top
+ i
) * padding
+ gid
->Left
,
1143 si
->RasterBits
+ i
* gid
->Width
,
1148 bmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1149 bmi
->bmiHeader
.biWidth
= gif
->SWidth
;
1150 bmi
->bmiHeader
.biHeight
= -gif
->SHeight
;
1151 bmi
->bmiHeader
.biPlanes
= 1;
1152 bmi
->bmiHeader
.biBitCount
= 8;
1153 bmi
->bmiHeader
.biCompression
= BI_RGB
;
1154 bmi
->bmiHeader
.biSizeImage
= padding
*gif
->SHeight
;
1155 bmi
->bmiHeader
.biXPelsPerMeter
= 0;
1156 bmi
->bmiHeader
.biYPelsPerMeter
= 0;
1157 bmi
->bmiHeader
.biClrUsed
= cm
->ColorCount
;
1158 bmi
->bmiHeader
.biClrImportant
= 0;
1161 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1170 if (transparent
> -1) {
1171 /* Create the Mask */
1172 HDC hdc
= CreateCompatibleDC(0);
1173 HDC hdcMask
= CreateCompatibleDC(0);
1175 HBITMAP hOldbitmapmask
;
1177 unsigned int monopadding
= (((unsigned)(gif
->SWidth
+ 31)) >> 5) << 2;
1180 This
->hbmXor
= CreateDIBitmap(
1189 bmi
->bmiColors
[0].rgbRed
= 0;
1190 bmi
->bmiColors
[0].rgbGreen
= 0;
1191 bmi
->bmiColors
[0].rgbBlue
= 0;
1192 bmi
->bmiColors
[1].rgbRed
= 255;
1193 bmi
->bmiColors
[1].rgbGreen
= 255;
1194 bmi
->bmiColors
[1].rgbBlue
= 255;
1196 bmi
->bmiHeader
.biBitCount
= 1;
1197 bmi
->bmiHeader
.biSizeImage
= monopadding
*gif
->SHeight
;
1198 bmi
->bmiHeader
.biClrUsed
= 2;
1200 for (i
= 0; i
< gif
->SHeight
; i
++) {
1201 unsigned char * colorPointer
= bytes
+ padding
* i
;
1202 unsigned char * monoPointer
= bytes
+ monopadding
* i
;
1203 for (j
= 0; j
< gif
->SWidth
; j
++) {
1204 unsigned char pixel
= colorPointer
[j
];
1205 if ((j
& 7) == 0) monoPointer
[j
>> 3] = 0;
1206 if (pixel
== (transparent
& 0x000000FFU
)) monoPointer
[j
>> 3] |= 1 << (7 - (j
& 7));
1210 hTempMask
= CreateDIBitmap(
1220 bmi
->bmiHeader
.biHeight
= -bmi
->bmiHeader
.biHeight
;
1221 This
->hbmMask
= CreateBitmap(bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, 1, 1, NULL
);
1222 hOldbitmap
= SelectObject(hdc
, hTempMask
);
1223 hOldbitmapmask
= SelectObject(hdcMask
, This
->hbmMask
);
1225 SetBkColor(hdc
, RGB(255, 255, 255));
1226 BitBlt(hdcMask
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, hdc
, 0, 0, SRCCOPY
);
1228 /* We no longer need the original bitmap, so we apply the first
1229 transformation with the mask to speed up the rendering */
1230 SelectObject(hdc
, This
->hbmXor
);
1231 SetBkColor(hdc
, RGB(0,0,0));
1232 SetTextColor(hdc
, RGB(255,255,255));
1233 BitBlt(hdc
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
,
1234 hdcMask
, 0, 0, SRCAND
);
1236 SelectObject(hdc
, hOldbitmap
);
1237 SelectObject(hdcMask
, hOldbitmapmask
);
1240 DeleteObject(hTempMask
);
1244 This
->desc
.picType
= PICTYPE_BITMAP
;
1245 OLEPictureImpl_SetBitmap(This
);
1247 HeapFree(GetProcessHeap(),0,bmi
);
1248 HeapFree(GetProcessHeap(),0,bytes
);
1252 static HRESULT
OLEPictureImpl_LoadJpeg(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1254 #ifdef SONAME_LIBJPEG
1255 struct jpeg_decompress_struct jd
;
1256 struct jpeg_error_mgr jerr
;
1259 JSAMPROW samprow
,oldsamprow
;
1260 BITMAPINFOHEADER bmi
;
1263 struct jpeg_source_mgr xjsm
;
1267 if(!libjpeg_handle
) {
1268 if(!load_libjpeg()) {
1269 ERR("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG
);
1274 /* This is basically so we can use in-memory data for jpeg decompression.
1275 * We need to have all the functions.
1277 xjsm
.next_input_byte
= xbuf
;
1278 xjsm
.bytes_in_buffer
= xread
;
1279 xjsm
.init_source
= _jpeg_init_source
;
1280 xjsm
.fill_input_buffer
= _jpeg_fill_input_buffer
;
1281 xjsm
.skip_input_data
= _jpeg_skip_input_data
;
1282 xjsm
.resync_to_restart
= _jpeg_resync_to_restart
;
1283 xjsm
.term_source
= _jpeg_term_source
;
1285 jd
.err
= pjpeg_std_error(&jerr
);
1286 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1287 * jpeg_create_decompress(&jd); */
1288 pjpeg_CreateDecompress(&jd
, JPEG_LIB_VERSION
, sizeof(struct jpeg_decompress_struct
));
1290 ret
=pjpeg_read_header(&jd
,TRUE
);
1291 jd
.out_color_space
= JCS_RGB
;
1292 pjpeg_start_decompress(&jd
);
1293 if (ret
!= JPEG_HEADER_OK
) {
1294 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret
);
1295 HeapFree(GetProcessHeap(),0,xbuf
);
1299 bits
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1300 (jd
.output_height
+1) * ((jd
.output_width
*jd
.output_components
+ 3) & ~3) );
1301 samprow
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,jd
.output_width
*jd
.output_components
);
1304 oldsamprow
= samprow
;
1305 while ( jd
.output_scanline
<jd
.output_height
) {
1306 x
= pjpeg_read_scanlines(&jd
,&samprow
,1);
1308 ERR("failed to read current scanline?\n");
1311 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1312 for(i
=0;i
<jd
.output_width
;i
++,samprow
+=jd
.output_components
) {
1313 *(bits
++) = *(samprow
+2);
1314 *(bits
++) = *(samprow
+1);
1315 *(bits
++) = *(samprow
);
1317 bits
= (LPBYTE
)(((UINT_PTR
)bits
+ 3) & ~3);
1318 samprow
= oldsamprow
;
1322 bmi
.biSize
= sizeof(bmi
);
1323 bmi
.biWidth
= jd
.output_width
;
1324 bmi
.biHeight
= -jd
.output_height
;
1326 bmi
.biBitCount
= jd
.output_components
<<3;
1327 bmi
.biCompression
= BI_RGB
;
1328 bmi
.biSizeImage
= jd
.output_height
*jd
.output_width
*jd
.output_components
;
1329 bmi
.biXPelsPerMeter
= 0;
1330 bmi
.biYPelsPerMeter
= 0;
1332 bmi
.biClrImportant
= 0;
1334 HeapFree(GetProcessHeap(),0,samprow
);
1335 pjpeg_finish_decompress(&jd
);
1336 pjpeg_destroy_decompress(&jd
);
1338 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1347 This
->desc
.picType
= PICTYPE_BITMAP
;
1348 OLEPictureImpl_SetBitmap(This
);
1349 HeapFree(GetProcessHeap(),0,bits
);
1352 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1357 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1359 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1360 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1363 /* Does not matter whether this is a coreheader or not, we only use
1364 * components which are in both
1367 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1371 xbuf
+bfh
->bfOffBits
,
1376 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1378 This
->desc
.picType
= PICTYPE_BITMAP
;
1379 OLEPictureImpl_SetBitmap(This
);
1383 /*****************************************************
1384 * start of PNG-specific code
1385 * currently only supports colortype PNG_COLOR_TYPE_RGB
1387 #ifdef SONAME_LIBPNG
1394 static void png_stream_read_data(png_structp png_ptr
, png_bytep data
,
1397 png_io
* io_ptr
= png_ptr
->io_ptr
;
1399 if(length
+ io_ptr
->position
> io_ptr
->size
){
1400 length
= io_ptr
->size
- io_ptr
->position
;
1403 memcpy(data
, io_ptr
->buff
+ io_ptr
->position
, length
);
1405 io_ptr
->position
+= length
;
1408 static void *libpng_handle
;
1409 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
1410 MAKE_FUNCPTR(png_create_read_struct
);
1411 MAKE_FUNCPTR(png_create_info_struct
);
1412 MAKE_FUNCPTR(png_set_read_fn
);
1413 MAKE_FUNCPTR(png_read_info
);
1414 MAKE_FUNCPTR(png_read_image
);
1415 MAKE_FUNCPTR(png_get_rowbytes
);
1416 MAKE_FUNCPTR(png_set_bgr
);
1417 MAKE_FUNCPTR(png_destroy_read_struct
);
1418 MAKE_FUNCPTR(png_set_palette_to_rgb
);
1419 MAKE_FUNCPTR(png_read_update_info
);
1420 MAKE_FUNCPTR(png_get_tRNS
);
1421 MAKE_FUNCPTR(png_get_PLTE
);
1422 MAKE_FUNCPTR(png_set_expand
);
1425 static void *load_libpng(void)
1427 if((libpng_handle
= wine_dlopen(SONAME_LIBPNG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
1429 #define LOAD_FUNCPTR(f) \
1430 if((p##f = wine_dlsym(libpng_handle, #f, NULL, 0)) == NULL) { \
1431 libpng_handle = NULL; \
1434 LOAD_FUNCPTR(png_create_read_struct
);
1435 LOAD_FUNCPTR(png_create_info_struct
);
1436 LOAD_FUNCPTR(png_set_read_fn
);
1437 LOAD_FUNCPTR(png_read_info
);
1438 LOAD_FUNCPTR(png_read_image
);
1439 LOAD_FUNCPTR(png_get_rowbytes
);
1440 LOAD_FUNCPTR(png_set_bgr
);
1441 LOAD_FUNCPTR(png_destroy_read_struct
);
1442 LOAD_FUNCPTR(png_set_palette_to_rgb
);
1443 LOAD_FUNCPTR(png_read_update_info
);
1444 LOAD_FUNCPTR(png_get_tRNS
);
1445 LOAD_FUNCPTR(png_get_PLTE
);
1446 LOAD_FUNCPTR(png_set_expand
);
1450 return libpng_handle
;
1452 #endif /* SONAME_LIBPNG */
1454 static HRESULT
OLEPictureImpl_LoadPNG(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1456 #ifdef SONAME_LIBPNG
1458 png_structp png_ptr
= NULL
;
1459 png_infop info_ptr
= NULL
;
1460 INT row
, rowsize
, height
, width
, num_trans
, i
, j
;
1461 png_bytep
* row_pointers
= NULL
;
1462 png_bytep pngdata
= NULL
;
1463 BITMAPINFOHEADER bmi
;
1464 HDC hdcref
= NULL
, hdcXor
, hdcMask
;
1468 png_color_16p trans_values
;
1469 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1470 HBITMAP hbmoldXor
, hbmoldMask
, temp
;
1472 if(!libpng_handle
) {
1473 if(!load_libpng()) {
1474 ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG
);
1483 png_ptr
= ppng_create_read_struct(PNG_LIBPNG_VER_STRING
,
1486 if(setjmp(png_jmpbuf(png_ptr
))){
1487 TRACE("Error in libpng\n");
1492 info_ptr
= ppng_create_info_struct(png_ptr
);
1493 ppng_set_read_fn(png_ptr
, &io
, png_stream_read_data
);
1494 ppng_read_info(png_ptr
, info_ptr
);
1496 if(!(png_ptr
->color_type
== PNG_COLOR_TYPE_RGB
||
1497 png_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
||
1498 png_ptr
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)){
1499 FIXME("Unsupported .PNG type: %d\n", png_ptr
->color_type
);
1504 transparency
= (ppng_get_tRNS(png_ptr
, info_ptr
, &trans
, &num_trans
, &trans_values
)
1507 /* sets format from anything to RGBA */
1508 ppng_set_expand(png_ptr
);
1509 /* sets format to BGRA */
1510 ppng_set_bgr(png_ptr
);
1512 ppng_read_update_info(png_ptr
, info_ptr
);
1514 rowsize
= ppng_get_rowbytes(png_ptr
, info_ptr
);
1515 /* align rowsize to 4-byte boundary */
1516 rowsize
= (rowsize
+ 3) & ~3;
1517 height
= info_ptr
->height
;
1518 width
= info_ptr
->width
;
1520 pngdata
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, height
* rowsize
);
1521 row_pointers
= HeapAlloc(GetProcessHeap(), 0, height
* (sizeof(VOID
*)));
1523 if(!pngdata
|| !row_pointers
){
1528 for (row
= 0; row
< height
; row
++){
1529 row_pointers
[row
] = pngdata
+ row
* rowsize
;
1532 ppng_read_image(png_ptr
, row_pointers
);
1534 bmi
.biSize
= sizeof(bmi
);
1535 bmi
.biWidth
= width
;
1536 bmi
.biHeight
= -height
;
1538 bmi
.biBitCount
= info_ptr
->channels
* 8;
1539 bmi
.biCompression
= BI_RGB
;
1540 bmi
.biSizeImage
= height
* rowsize
;
1541 bmi
.biXPelsPerMeter
= 0;
1542 bmi
.biYPelsPerMeter
= 0;
1544 bmi
.biClrImportant
= 0;
1547 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1556 /* only fully-transparent alpha is handled */
1557 if((info_ptr
->channels
!= 4) || !transparency
){
1558 ReleaseDC(0, hdcref
);
1562 This
->hbmXor
= CreateDIBitmap(
1571 /* set transparent pixels to black, all others to white */
1572 for(i
= 0; i
< height
; i
++){
1573 for(j
= 3; j
< rowsize
; j
+= 4){
1574 if(row_pointers
[i
][j
] == 0)
1575 *((DWORD
*)(&row_pointers
[i
][j
- 3])) = black
;
1577 *((DWORD
*)(&row_pointers
[i
][j
- 3])) = white
;
1581 temp
= CreateDIBitmap(
1590 ReleaseDC(0, hdcref
);
1592 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1593 hdcXor
= CreateCompatibleDC(NULL
);
1594 hdcMask
= CreateCompatibleDC(NULL
);
1596 hbmoldXor
= SelectObject(hdcXor
,temp
);
1597 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1598 SetBkColor(hdcXor
,black
);
1599 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1601 SelectObject(hdcXor
,This
->hbmXor
);
1604 SetTextColor(hdcXor
,white
);
1605 SetBkColor(hdcXor
,black
);
1606 BitBlt(hdcXor
,0,0,width
,height
,hdcMask
,0,0,SRCAND
);
1608 SelectObject(hdcXor
,hbmoldXor
);
1609 SelectObject(hdcMask
,hbmoldMask
);
1615 This
->desc
.picType
= PICTYPE_BITMAP
;
1616 OLEPictureImpl_SetBitmap(This
);
1621 ppng_destroy_read_struct(&png_ptr
, info_ptr
? &info_ptr
: NULL
, NULL
);
1622 HeapFree(GetProcessHeap(), 0, row_pointers
);
1623 HeapFree(GetProcessHeap(), 0, pngdata
);
1625 #else /* SONAME_LIBPNG */
1626 ERR("Trying to load PNG picture, but PNG supported not compiled in.\n");
1631 /*****************************************************
1632 * start of Icon-specific code
1635 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1638 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1643 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1644 FIXME("icon.idType=%d\n",cifd->idType);
1645 FIXME("icon.idCount=%d\n",cifd->idCount);
1647 for (i=0;i<cifd->idCount;i++) {
1648 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1649 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1650 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1651 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1652 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1653 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1654 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1655 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1659 /* If we have more than one icon, try to find the best.
1660 * this currently means '32 pixel wide'.
1662 if (cifd
->idCount
!=1) {
1663 for (i
=0;i
<cifd
->idCount
;i
++) {
1664 if (cifd
->idEntries
[i
].bWidth
== 32)
1667 if (i
==cifd
->idCount
) i
=0;
1670 hicon
= CreateIconFromResourceEx(
1671 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1672 cifd
->idEntries
[i
].dwDIBSize
,
1675 cifd
->idEntries
[i
].bWidth
,
1676 cifd
->idEntries
[i
].bHeight
,
1680 ERR("CreateIcon failed.\n");
1683 This
->desc
.picType
= PICTYPE_ICON
;
1684 This
->desc
.u
.icon
.hicon
= hicon
;
1685 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1686 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1687 hdcRef
= CreateCompatibleDC(0);
1688 This
->himetricWidth
=(cifd
->idEntries
[i
].bWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
1689 This
->himetricHeight
=(cifd
->idEntries
[i
].bHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
1695 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1696 const BYTE
*data
, ULONG size
)
1701 hemf
= SetEnhMetaFileBits(size
, data
);
1702 if (!hemf
) return E_FAIL
;
1704 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1706 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1707 This
->desc
.u
.emf
.hemf
= hemf
;
1709 This
->origWidth
= 0;
1710 This
->origHeight
= 0;
1711 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1712 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1717 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1718 const BYTE
*data
, ULONG size
)
1720 APM_HEADER
*header
= (APM_HEADER
*)data
;
1723 if (size
< sizeof(APM_HEADER
))
1725 if (header
->key
!= 0x9ac6cdd7)
1728 /* SetMetaFileBitsEx performs data check on its own */
1729 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1730 if (!hmf
) return E_FAIL
;
1732 This
->desc
.picType
= PICTYPE_METAFILE
;
1733 This
->desc
.u
.wmf
.hmeta
= hmf
;
1734 This
->desc
.u
.wmf
.xExt
= 0;
1735 This
->desc
.u
.wmf
.yExt
= 0;
1737 This
->origWidth
= 0;
1738 This
->origHeight
= 0;
1739 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1740 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1744 /************************************************************************
1745 * BITMAP FORMAT FLAGS -
1746 * Flags that differentiate between different types of bitmaps.
1749 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
1750 #define BITMAP_FORMAT_JPEG 0xd8ff
1751 #define BITMAP_FORMAT_GIF 0x4947
1752 #define BITMAP_FORMAT_PNG 0x5089
1753 #define BITMAP_FORMAT_APM 0xcdd7
1755 /************************************************************************
1756 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1758 * Loads the binary data from the IStream. Starts at current position.
1759 * There appears to be an 2 DWORD header:
1763 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1765 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
,IStream
*pStm
) {
1766 HRESULT hr
= E_FAIL
;
1767 BOOL headerisdata
= FALSE
;
1768 BOOL statfailed
= FALSE
;
1769 ULONG xread
, toread
;
1775 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1777 TRACE("(%p,%p)\n",This
,pStm
);
1779 /****************************************************************************************
1780 * Part 1: Load the data
1782 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1783 * out whether we do.
1785 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1786 * compound file. This may explain most, if not all, of the cases of "no
1787 * header", and the header validation should take this into account.
1788 * At least in Visual Basic 6, resource streams, valid headers are
1789 * header[0] == "lt\0\0",
1790 * header[1] == length_of_stream.
1792 * Also handle streams where we do not have a working "Stat" method by
1793 * reading all data until the end of the stream.
1795 hr
=IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1797 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr
);
1799 /* we will read at least 8 byte ... just right below */
1800 statstg
.cbSize
.QuadPart
= 8;
1805 headerisdata
= FALSE
;
1807 hr
=IStream_Read(pStm
,header
,8,&xread
);
1808 if (hr
|| xread
!=8) {
1809 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr
,xread
);
1810 return (hr
?hr
:E_FAIL
);
1812 headerread
+= xread
;
1815 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1816 if (toread
!= 0 && toread
!= header
[1])
1817 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1820 if (toread
== 0) break;
1822 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1823 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1824 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1825 (header
[0] == EMR_HEADER
) || /* EMF header */
1826 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1828 ) {/* Found start of bitmap data */
1829 headerisdata
= TRUE
;
1831 toread
= statstg
.cbSize
.QuadPart
-8;
1835 FIXME("Unknown stream header magic: %08x\n", header
[0]);
1839 } while (!headerisdata
);
1841 if (statfailed
) { /* we don't know the size ... read all we get */
1843 int origsize
= sizeinc
;
1846 TRACE("Reading all data from stream.\n");
1847 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1849 memcpy (xbuf
, header
, 8);
1851 while (xread
< origsize
) {
1852 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1857 if (!nread
|| hr
) /* done, or error */
1859 if (xread
== origsize
) {
1860 origsize
+= sizeinc
;
1861 sizeinc
= 2*sizeinc
; /* exponential increase */
1862 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1866 TRACE("hr in no-stat loader case is %08x\n", hr
);
1867 TRACE("loaded %d bytes.\n", xread
);
1868 This
->datalen
= xread
;
1871 This
->datalen
= toread
+(headerisdata
?8:0);
1872 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1874 return E_OUTOFMEMORY
;
1877 memcpy (xbuf
, header
, 8);
1879 while (xread
< This
->datalen
) {
1881 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1886 if (xread
!= This
->datalen
)
1887 ERR("Could only read %d of %d bytes out of stream?\n",xread
,This
->datalen
);
1889 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1890 This
->desc
.picType
= PICTYPE_NONE
;
1895 /****************************************************************************************
1896 * Part 2: Process the loaded data
1899 magic
= xbuf
[0] + (xbuf
[1]<<8);
1900 This
->loadtime_format
= magic
;
1903 case BITMAP_FORMAT_GIF
: /* GIF */
1904 hr
= OLEPictureImpl_LoadGif(This
, xbuf
, xread
);
1906 case BITMAP_FORMAT_JPEG
: /* JPEG */
1907 hr
= OLEPictureImpl_LoadJpeg(This
, xbuf
, xread
);
1909 case BITMAP_FORMAT_BMP
: /* Bitmap */
1910 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1912 case BITMAP_FORMAT_PNG
: /* PNG */
1913 hr
= OLEPictureImpl_LoadPNG(This
, xbuf
, xread
);
1915 case BITMAP_FORMAT_APM
: /* APM */
1916 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1918 case 0x0000: { /* ICON , first word is dwReserved */
1919 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1926 /* let's see if it's a EMF */
1927 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1928 if (hr
== S_OK
) break;
1930 FIXME("Unknown magic %04x, %d read bytes:\n",magic
,xread
);
1932 for (i
=0;i
<xread
+8;i
++) {
1933 if (i
<8) MESSAGE("%02x ",((unsigned char*)header
)[i
]);
1934 else MESSAGE("%02x ",xbuf
[i
-8]);
1935 if (i
% 10 == 9) MESSAGE("\n");
1941 This
->bIsDirty
= FALSE
;
1943 /* FIXME: this notify is not really documented */
1945 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1949 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1953 BITMAPINFO
* pInfoBitmap
;
1954 int iNumPaletteEntries
;
1955 unsigned char * pPixelData
;
1956 BITMAPFILEHEADER
* pFileHeader
;
1957 BITMAPINFO
* pInfoHeader
;
1959 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1960 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1962 /* Find out bitmap size and padded length */
1964 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1965 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1967 /* Fetch bitmap palette & pixel data */
1969 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1970 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1972 /* Calculate the total length required for the BMP data */
1973 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1974 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1975 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1977 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1978 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1980 iNumPaletteEntries
= 0;
1983 sizeof(BITMAPFILEHEADER
) +
1984 sizeof(BITMAPINFOHEADER
) +
1985 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1986 pInfoBitmap
->bmiHeader
.biSizeImage
;
1987 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1989 /* Fill the BITMAPFILEHEADER */
1990 pFileHeader
= (BITMAPFILEHEADER
*)(*ppBuffer
);
1991 pFileHeader
->bfType
= BITMAP_FORMAT_BMP
;
1992 pFileHeader
->bfSize
= *pLength
;
1993 pFileHeader
->bfOffBits
=
1994 sizeof(BITMAPFILEHEADER
) +
1995 sizeof(BITMAPINFOHEADER
) +
1996 iNumPaletteEntries
* sizeof(RGBQUAD
);
1998 /* Fill the BITMAPINFOHEADER and the palette data */
1999 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
2000 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
2002 (unsigned char *)(*ppBuffer
) +
2003 sizeof(BITMAPFILEHEADER
) +
2004 sizeof(BITMAPINFOHEADER
) +
2005 iNumPaletteEntries
* sizeof(RGBQUAD
),
2006 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
2009 HeapFree(GetProcessHeap(), 0, pPixelData
);
2010 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
2014 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
2019 *ppBuffer
= NULL
; *pLength
= 0;
2020 if (GetIconInfo(hIcon
, &infoIcon
)) {
2022 BITMAPINFO
* pInfoBitmap
;
2023 unsigned char * pIconData
= NULL
;
2024 unsigned int iDataSize
= 0;
2026 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
2028 /* Find out icon size */
2030 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
2031 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
2033 /* Auxiliary pointers */
2034 CURSORICONFILEDIR
* pIconDir
;
2035 CURSORICONFILEDIRENTRY
* pIconEntry
;
2036 BITMAPINFOHEADER
* pIconBitmapHeader
;
2037 unsigned int iOffsetPalette
;
2038 unsigned int iOffsetColorData
;
2039 unsigned int iOffsetMaskData
;
2041 unsigned int iLengthScanLineColor
;
2042 unsigned int iLengthScanLineMask
;
2043 unsigned int iNumEntriesPalette
;
2045 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
2046 iLengthScanLineColor
= ((pInfoBitmap
->bmiHeader
.biWidth
* pInfoBitmap
->bmiHeader
.biBitCount
+ 31) >> 5) << 2;
2048 FIXME("DEBUG: bitmap size is %d x %d\n",
2049 pInfoBitmap->bmiHeader.biWidth,
2050 pInfoBitmap->bmiHeader.biHeight);
2051 FIXME("DEBUG: bitmap bpp is %d\n",
2052 pInfoBitmap->bmiHeader.biBitCount);
2053 FIXME("DEBUG: bitmap nplanes is %d\n",
2054 pInfoBitmap->bmiHeader.biPlanes);
2055 FIXME("DEBUG: bitmap biSizeImage is %u\n",
2056 pInfoBitmap->bmiHeader.biSizeImage);
2058 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
2059 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
2060 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
2062 /* Fill out the CURSORICONFILEDIR */
2063 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
2064 pIconDir
->idType
= 1;
2065 pIconDir
->idCount
= 1;
2067 /* Fill out the CURSORICONFILEDIRENTRY */
2068 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
2069 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
2070 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
2071 pIconEntry
->bColorCount
=
2072 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
2073 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
2075 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
2076 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
2077 pIconEntry
->dwDIBSize
= 0;
2078 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
2080 /* Fill out the BITMAPINFOHEADER */
2081 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2082 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
2084 /* Find out whether a palette exists for the bitmap */
2085 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
2086 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
2087 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
2088 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
2089 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
2090 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
2091 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
2092 iNumEntriesPalette
= 3;
2093 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
2094 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
2096 iNumEntriesPalette
= 0;
2099 /* Add bitmap size and header size to icon data size. */
2100 iOffsetPalette
= iDataSize
;
2101 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
2102 iOffsetColorData
= iDataSize
;
2103 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
2104 iOffsetMaskData
= iDataSize
;
2105 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
2106 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
2107 pIconBitmapHeader
->biHeight
*= 2;
2108 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
2109 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
2110 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2111 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2113 /* Get the actual bitmap data from the icon bitmap */
2114 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
2115 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
2116 if (iNumEntriesPalette
> 0) {
2117 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
2118 iNumEntriesPalette
* sizeof(RGBQUAD
));
2121 /* Reset all values so that GetDIBits call succeeds */
2122 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
2123 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
2124 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
2126 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
2127 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
2128 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
2130 printf("ERROR: unable to get bitmap mask (error %u)\n",
2135 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
2136 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
2138 /* Write out everything produced so far to the stream */
2139 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
2143 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
2148 Remarks (from MSDN entry on GetIconInfo):
2150 GetIconInfo creates bitmaps for the hbmMask and hbmColor
2151 members of ICONINFO. The calling application must manage
2152 these bitmaps and delete them when they are no longer
2155 if (hDC
) ReleaseDC(0, hDC
);
2156 DeleteObject(infoIcon
.hbmMask
);
2157 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
2158 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
2160 printf("ERROR: Unable to get icon information (error %u)\n",
2166 static HRESULT WINAPI
OLEPictureImpl_Save(
2167 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
2169 HRESULT hResult
= E_NOTIMPL
;
2171 unsigned int iDataSize
;
2173 int iSerializeResult
= 0;
2174 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
2176 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
2178 switch (This
->desc
.picType
) {
2180 if (This
->bIsDirty
|| !This
->data
) {
2181 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
2182 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
2186 HeapFree(GetProcessHeap(), 0, This
->data
);
2187 This
->data
= pIconData
;
2188 This
->datalen
= iDataSize
;
2190 if (This
->loadtime_magic
!= 0xdeadbeef) {
2193 header
[0] = This
->loadtime_magic
;
2194 header
[1] = This
->datalen
;
2195 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2197 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
2201 case PICTYPE_BITMAP
:
2202 if (This
->bIsDirty
) {
2203 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
2204 case BITMAP_FORMAT_BMP
:
2205 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
2207 case BITMAP_FORMAT_JPEG
:
2208 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
2210 case BITMAP_FORMAT_GIF
:
2211 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
2213 case BITMAP_FORMAT_PNG
:
2214 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
2217 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
2220 if (iSerializeResult
) {
2222 if (This->loadtime_magic != 0xdeadbeef) {
2227 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
2228 header
[1] = iDataSize
;
2229 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2231 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
2233 HeapFree(GetProcessHeap(), 0, This
->data
);
2234 This
->data
= pIconData
;
2235 This
->datalen
= iDataSize
;
2240 if (This->loadtime_magic != 0xdeadbeef) {
2245 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
2246 header
[1] = This
->datalen
;
2247 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2249 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
2253 case PICTYPE_METAFILE
:
2254 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
2256 case PICTYPE_ENHMETAFILE
:
2257 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
2260 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
2263 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
2267 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
2268 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
2270 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
2271 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
2276 /************************************************************************
2280 /************************************************************************
2281 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
2283 * See Windows documentation for more details on IUnknown methods.
2285 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
2290 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2292 return IPicture_QueryInterface((IPicture
*)This
, riid
, ppvoid
);
2295 /************************************************************************
2296 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
2298 * See Windows documentation for more details on IUnknown methods.
2300 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
2303 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2305 return IPicture_AddRef((IPicture
*)This
);
2308 /************************************************************************
2309 * OLEPictureImpl_IDispatch_Release (IUnknown)
2311 * See Windows documentation for more details on IUnknown methods.
2313 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
2316 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2318 return IPicture_Release((IPicture
*)This
);
2321 /************************************************************************
2322 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
2324 * See Windows documentation for more details on IDispatch methods.
2326 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
2328 unsigned int* pctinfo
)
2330 TRACE("(%p)\n", pctinfo
);
2337 /************************************************************************
2338 * OLEPictureImpl_GetTypeInfo (IDispatch)
2340 * See Windows documentation for more details on IDispatch methods.
2342 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
2346 ITypeInfo
** ppTInfo
)
2348 static const WCHAR stdole2tlb
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
2352 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
2357 hres
= LoadTypeLib(stdole2tlb
, &tl
);
2360 ERR("Could not load stdole2.tlb\n");
2364 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
2366 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres
);
2371 /************************************************************************
2372 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2374 * See Windows documentation for more details on IDispatch methods.
2376 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
2379 LPOLESTR
* rgszNames
,
2387 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
2388 rgszNames
, cNames
, (int)lcid
, rgDispId
);
2392 return E_INVALIDARG
;
2396 /* retrieve type information */
2397 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
2401 ERR("GetTypeInfo failed.\n");
2405 /* convert names to DISPIDs */
2406 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
2407 ITypeInfo_Release(pTInfo
);
2413 /************************************************************************
2414 * OLEPictureImpl_Invoke (IDispatch)
2416 * See Windows documentation for more details on IDispatch methods.
2418 static HRESULT WINAPI
OLEPictureImpl_Invoke(
2420 DISPID dispIdMember
,
2424 DISPPARAMS
* pDispParams
,
2425 VARIANT
* pVarResult
,
2426 EXCEPINFO
* pExepInfo
,
2429 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2431 /* validate parameters */
2433 if (!IsEqualIID(riid
, &IID_NULL
))
2435 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2436 return DISP_E_UNKNOWNNAME
;
2441 ERR("null pDispParams not allowed\n");
2442 return DISP_E_PARAMNOTOPTIONAL
;
2445 if (wFlags
& DISPATCH_PROPERTYGET
)
2447 if (pDispParams
->cArgs
!= 0)
2449 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2450 return DISP_E_BADPARAMCOUNT
;
2454 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2455 return DISP_E_PARAMNOTOPTIONAL
;
2458 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2460 if (pDispParams
->cArgs
!= 1)
2462 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2463 return DISP_E_BADPARAMCOUNT
;
2467 switch (dispIdMember
)
2469 case DISPID_PICT_HANDLE
:
2470 if (wFlags
& DISPATCH_PROPERTYGET
)
2472 TRACE("DISPID_PICT_HANDLE\n");
2473 V_VT(pVarResult
) = VT_I4
;
2474 return IPicture_get_Handle((IPicture
*)&This
->lpVtbl
, &V_UINT(pVarResult
));
2477 case DISPID_PICT_HPAL
:
2478 if (wFlags
& DISPATCH_PROPERTYGET
)
2480 TRACE("DISPID_PICT_HPAL\n");
2481 V_VT(pVarResult
) = VT_I4
;
2482 return IPicture_get_hPal((IPicture
*)&This
->lpVtbl
, &V_UINT(pVarResult
));
2484 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2488 TRACE("DISPID_PICT_HPAL\n");
2490 VariantInit(&vararg
);
2491 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2495 hr
= IPicture_set_hPal((IPicture
*)&This
->lpVtbl
, V_I4(&vararg
));
2497 VariantClear(&vararg
);
2501 case DISPID_PICT_TYPE
:
2502 if (wFlags
& DISPATCH_PROPERTYGET
)
2504 TRACE("DISPID_PICT_TYPE\n");
2505 V_VT(pVarResult
) = VT_I2
;
2506 return OLEPictureImpl_get_Type((IPicture
*)&This
->lpVtbl
, &V_I2(pVarResult
));
2509 case DISPID_PICT_WIDTH
:
2510 if (wFlags
& DISPATCH_PROPERTYGET
)
2512 TRACE("DISPID_PICT_WIDTH\n");
2513 V_VT(pVarResult
) = VT_I4
;
2514 return IPicture_get_Width((IPicture
*)&This
->lpVtbl
, &V_I4(pVarResult
));
2517 case DISPID_PICT_HEIGHT
:
2518 if (wFlags
& DISPATCH_PROPERTYGET
)
2520 TRACE("DISPID_PICT_HEIGHT\n");
2521 V_VT(pVarResult
) = VT_I4
;
2522 return IPicture_get_Height((IPicture
*)&This
->lpVtbl
, &V_I4(pVarResult
));
2527 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember
, wFlags
);
2528 return DISP_E_MEMBERNOTFOUND
;
2532 static const IPictureVtbl OLEPictureImpl_VTable
=
2534 OLEPictureImpl_QueryInterface
,
2535 OLEPictureImpl_AddRef
,
2536 OLEPictureImpl_Release
,
2537 OLEPictureImpl_get_Handle
,
2538 OLEPictureImpl_get_hPal
,
2539 OLEPictureImpl_get_Type
,
2540 OLEPictureImpl_get_Width
,
2541 OLEPictureImpl_get_Height
,
2542 OLEPictureImpl_Render
,
2543 OLEPictureImpl_set_hPal
,
2544 OLEPictureImpl_get_CurDC
,
2545 OLEPictureImpl_SelectPicture
,
2546 OLEPictureImpl_get_KeepOriginalFormat
,
2547 OLEPictureImpl_put_KeepOriginalFormat
,
2548 OLEPictureImpl_PictureChanged
,
2549 OLEPictureImpl_SaveAsFile
,
2550 OLEPictureImpl_get_Attributes
2553 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2555 OLEPictureImpl_IDispatch_QueryInterface
,
2556 OLEPictureImpl_IDispatch_AddRef
,
2557 OLEPictureImpl_IDispatch_Release
,
2558 OLEPictureImpl_GetTypeInfoCount
,
2559 OLEPictureImpl_GetTypeInfo
,
2560 OLEPictureImpl_GetIDsOfNames
,
2561 OLEPictureImpl_Invoke
2564 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2566 OLEPictureImpl_IPersistStream_QueryInterface
,
2567 OLEPictureImpl_IPersistStream_AddRef
,
2568 OLEPictureImpl_IPersistStream_Release
,
2569 OLEPictureImpl_GetClassID
,
2570 OLEPictureImpl_IsDirty
,
2571 OLEPictureImpl_Load
,
2572 OLEPictureImpl_Save
,
2573 OLEPictureImpl_GetSizeMax
2576 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2578 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2579 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2580 OLEPictureImpl_IConnectionPointContainer_Release
,
2581 OLEPictureImpl_EnumConnectionPoints
,
2582 OLEPictureImpl_FindConnectionPoint
2585 /***********************************************************************
2586 * OleCreatePictureIndirect (OLEAUT32.419)
2588 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2589 BOOL fOwn
, LPVOID
*ppvObj
)
2591 OLEPictureImpl
* newPict
= NULL
;
2594 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), fOwn
, ppvObj
);
2605 * Try to construct a new instance of the class.
2607 newPict
= OLEPictureImpl_Construct(lpPictDesc
, fOwn
);
2609 if (newPict
== NULL
)
2610 return E_OUTOFMEMORY
;
2613 * Make sure it supports the interface required by the caller.
2615 hr
= IPicture_QueryInterface((IPicture
*)newPict
, riid
, ppvObj
);
2618 * Release the reference obtained in the constructor. If
2619 * the QueryInterface was unsuccessful, it will free the class.
2621 IPicture_Release((IPicture
*)newPict
);
2627 /***********************************************************************
2628 * OleLoadPicture (OLEAUT32.418)
2630 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2631 REFIID riid
, LPVOID
*ppvObj
)
2637 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2638 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2640 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2643 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2645 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2646 IPicture_Release(newpic
);
2650 hr
= IPersistStream_Load(ps
,lpstream
);
2651 IPersistStream_Release(ps
);
2654 ERR("IPersistStream_Load failed\n");
2655 IPicture_Release(newpic
);
2659 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2661 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2662 IPicture_Release(newpic
);
2666 /***********************************************************************
2667 * OleLoadPictureEx (OLEAUT32.401)
2669 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2670 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2676 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2677 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2679 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2682 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2684 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2685 IPicture_Release(newpic
);
2689 hr
= IPersistStream_Load(ps
,lpstream
);
2690 IPersistStream_Release(ps
);
2693 ERR("IPersistStream_Load failed\n");
2694 IPicture_Release(newpic
);
2698 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2700 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2701 IPicture_Release(newpic
);
2705 /***********************************************************************
2706 * OleLoadPicturePath (OLEAUT32.424)
2708 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2709 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2712 static const WCHAR file
[] = { 'f','i','l','e',':','/','/',0 };
2716 HGLOBAL hGlobal
= NULL
;
2717 DWORD dwBytesRead
= 0;
2720 IPersistStream
*pStream
;
2723 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2724 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2725 debugstr_guid(riid
), ppvRet
);
2727 if (!ppvRet
) return E_POINTER
;
2729 if (strncmpW(szURLorPath
, file
, 7) == 0) {
2732 hFile
= CreateFileW(szURLorPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2734 if (hFile
== INVALID_HANDLE_VALUE
)
2735 return E_UNEXPECTED
;
2737 dwFileSize
= GetFileSize(hFile
, NULL
);
2738 if (dwFileSize
!= INVALID_FILE_SIZE
)
2740 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2743 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
);
2746 GlobalFree(hGlobal
);
2754 return E_UNEXPECTED
;
2756 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2759 GlobalFree(hGlobal
);
2766 hRes
= CreateBindCtx(0, &pbc
);
2767 if (SUCCEEDED(hRes
))
2769 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2770 if (SUCCEEDED(hRes
))
2772 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2773 IMoniker_Release(pmnk
);
2775 IBindCtx_Release(pbc
);
2781 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2782 &IID_IPicture
, (LPVOID
*)&ipicture
);
2784 IStream_Release(stream
);
2788 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2790 IStream_Release(stream
);
2791 IPicture_Release(ipicture
);
2795 hRes
= IPersistStream_Load(pStream
, stream
);
2796 IPersistStream_Release(pStream
);
2797 IStream_Release(stream
);
2800 IPicture_Release(ipicture
);
2804 hRes
= IPicture_QueryInterface(ipicture
,riid
,ppvRet
);
2806 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2808 IPicture_Release(ipicture
);
2812 /*******************************************************************************
2813 * StdPic ClassFactory
2817 /* IUnknown fields */
2818 const IClassFactoryVtbl
*lpVtbl
;
2820 } IClassFactoryImpl
;
2822 static HRESULT WINAPI
2823 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2824 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2826 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2827 return E_NOINTERFACE
;
2831 SPCF_AddRef(LPCLASSFACTORY iface
) {
2832 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2833 return InterlockedIncrement(&This
->ref
);
2836 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2837 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2838 /* static class, won't be freed */
2839 return InterlockedDecrement(&This
->ref
);
2842 static HRESULT WINAPI
SPCF_CreateInstance(
2843 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2845 /* Creates an uninitialized picture */
2846 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2850 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2851 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2852 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2856 static const IClassFactoryVtbl SPCF_Vtbl
= {
2857 SPCF_QueryInterface
,
2860 SPCF_CreateInstance
,
2863 static IClassFactoryImpl STDPIC_CF
= {&SPCF_Vtbl
, 1 };
2865 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= (LPVOID
)&STDPIC_CF
; }