4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 * Support PICTYPE_BITMAP and PICTYPE_ICON, altough only bitmaps very well..
26 * Lots of methods are just stubs.
29 * NOTES (or things that msdn doesn't tell you)
31 * The width and height properties are returned in HIMETRIC units (0.01mm)
32 * IPicture::Render also uses these to select a region of the src picture.
33 * A bitmap's size is converted into these units by using the screen resolution
34 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
39 #include "wine/port.h"
48 /* Must be before wine includes, the header has things conflicting with
52 #define NONAMELESSUNION
53 #define NONAMELESSSTRUCT
65 #include "wine/debug.h"
66 #include "wine/unicode.h"
68 #include "wine/wingdi16.h"
71 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
73 #define UINT8 JPEG_UINT8
74 #define UINT16 JPEG_UINT16
76 #define boolean jpeg_boolean
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 memcpy(&newObject
->desc
, pictDesc
, sizeof(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
);
515 /************************************************************************
516 * OLEPictureImpl_get_Handle
518 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
521 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
522 TRACE("(%p)->(%p)\n", This
, phandle
);
523 switch(This
->desc
.picType
) {
525 case PICTYPE_UNINITIALIZED
:
529 *phandle
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
531 case PICTYPE_METAFILE
:
532 *phandle
= (OLE_HANDLE
)This
->desc
.u
.wmf
.hmeta
;
535 *phandle
= (OLE_HANDLE
)This
->desc
.u
.icon
.hicon
;
537 case PICTYPE_ENHMETAFILE
:
538 *phandle
= (OLE_HANDLE
)This
->desc
.u
.emf
.hemf
;
541 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
544 TRACE("returning handle %08x\n", *phandle
);
548 /************************************************************************
549 * OLEPictureImpl_get_hPal
551 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
554 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
556 TRACE("(%p)->(%p)\n", This
, phandle
);
561 switch (This
->desc
.picType
) {
562 case (UINT
)PICTYPE_UNINITIALIZED
:
568 *phandle
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hpal
;
571 case PICTYPE_METAFILE
:
575 case PICTYPE_ENHMETAFILE
:
577 FIXME("unimplemented for type %d. Returning 0 palette.\n",
583 TRACE("returning 0x%08x, palette handle %08x\n", hres
, *phandle
);
587 /************************************************************************
588 * OLEPictureImpl_get_Type
590 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
593 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
594 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
595 *ptype
= This
->desc
.picType
;
599 /************************************************************************
600 * OLEPictureImpl_get_Width
602 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
603 OLE_XSIZE_HIMETRIC
*pwidth
)
605 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
606 TRACE("(%p)->(%p): width is %d\n", This
, pwidth
, This
->himetricWidth
);
607 *pwidth
= This
->himetricWidth
;
611 /************************************************************************
612 * OLEPictureImpl_get_Height
614 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
615 OLE_YSIZE_HIMETRIC
*pheight
)
617 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
618 TRACE("(%p)->(%p): height is %d\n", This
, pheight
, This
->himetricHeight
);
619 *pheight
= This
->himetricHeight
;
623 /************************************************************************
624 * OLEPictureImpl_Render
626 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
627 LONG x
, LONG y
, LONG cx
, LONG cy
,
628 OLE_XPOS_HIMETRIC xSrc
,
629 OLE_YPOS_HIMETRIC ySrc
,
630 OLE_XSIZE_HIMETRIC cxSrc
,
631 OLE_YSIZE_HIMETRIC cySrc
,
634 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
635 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
636 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
638 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds
->left
, prcWBounds
->top
,
639 prcWBounds
->right
, prcWBounds
->bottom
);
642 * While the documentation suggests this to be here (or after rendering?)
643 * it does cause an endless recursion in my sample app. -MM 20010804
644 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
647 switch(This
->desc
.picType
) {
653 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
654 NB y-axis gets flipped */
656 hdcBmp
= CreateCompatibleDC(0);
657 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
658 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
659 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
660 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
661 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
664 HDC hdcMask
= CreateCompatibleDC(0);
665 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
667 hbmpOld
= SelectObject(hdcBmp
, This
->hbmXor
);
669 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
670 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
671 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
672 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
673 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
675 SetBkColor(hdc
, RGB(255, 255, 255));
676 SetTextColor(hdc
, RGB(0, 0, 0));
677 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
678 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
680 SelectObject(hdcMask
, hOldbm
);
683 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
684 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
687 SelectObject(hdcBmp
, hbmpOld
);
692 FIXME("Not quite correct implementation of rendering icons...\n");
693 DrawIcon(hdc
,x
,y
,This
->desc
.u
.icon
.hicon
);
696 case PICTYPE_METAFILE
:
702 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
703 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
704 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
706 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
707 ERR("PlayMetaFile failed!\n");
709 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
710 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
711 SetMapMode(hdc
, oldmode
);
715 case PICTYPE_ENHMETAFILE
:
717 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
718 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
723 FIXME("type %d not implemented\n", This
->desc
.picType
);
729 /************************************************************************
730 * OLEPictureImpl_set_hPal
732 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
735 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
736 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
737 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
741 /************************************************************************
742 * OLEPictureImpl_get_CurDC
744 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
747 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
748 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
749 if (phdc
) *phdc
= This
->hDCCur
;
753 /************************************************************************
754 * OLEPictureImpl_SelectPicture
756 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
759 OLE_HANDLE
*phbmpOut
)
761 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
762 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
763 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
764 SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
767 *phdcOut
= This
->hDCCur
;
768 This
->hDCCur
= hdcIn
;
770 *phbmpOut
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
773 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
778 /************************************************************************
779 * OLEPictureImpl_get_KeepOriginalFormat
781 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
784 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
785 TRACE("(%p)->(%p)\n", This
, pfKeep
);
788 *pfKeep
= This
->keepOrigFormat
;
792 /************************************************************************
793 * OLEPictureImpl_put_KeepOriginalFormat
795 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
798 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
799 TRACE("(%p)->(%d)\n", This
, keep
);
800 This
->keepOrigFormat
= keep
;
801 /* FIXME: what DISPID notification here? */
805 /************************************************************************
806 * OLEPictureImpl_PictureChanged
808 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
810 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
811 TRACE("(%p)->()\n", This
);
812 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
813 This
->bIsDirty
= TRUE
;
817 /************************************************************************
818 * OLEPictureImpl_SaveAsFile
820 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
825 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
826 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
827 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
830 /************************************************************************
831 * OLEPictureImpl_get_Attributes
833 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
836 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
837 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
839 switch (This
->desc
.picType
) {
840 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
841 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
842 case PICTYPE_ENHMETAFILE
: /* fall through */
843 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
844 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
850 /************************************************************************
851 * IConnectionPointContainer
853 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
854 IConnectionPointContainer
* iface
,
858 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
860 return IPicture_QueryInterface((IPicture
*)This
,riid
,ppvoid
);
863 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
864 IConnectionPointContainer
* iface
)
866 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
868 return IPicture_AddRef((IPicture
*)This
);
871 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
872 IConnectionPointContainer
* iface
)
874 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
876 return IPicture_Release((IPicture
*)This
);
879 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
880 IConnectionPointContainer
* iface
,
881 IEnumConnectionPoints
** ppEnum
)
883 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
885 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
889 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
890 IConnectionPointContainer
* iface
,
892 IConnectionPoint
**ppCP
)
894 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
895 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
899 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
900 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
901 FIXME("no connection point for %s\n",debugstr_guid(riid
));
902 return CONNECT_E_NOCONNECTION
;
906 /************************************************************************
910 /************************************************************************
911 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
913 * See Windows documentation for more details on IUnknown methods.
915 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
916 IPersistStream
* iface
,
920 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
922 return IPicture_QueryInterface((IPicture
*)This
, riid
, ppvoid
);
925 /************************************************************************
926 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
928 * See Windows documentation for more details on IUnknown methods.
930 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
931 IPersistStream
* iface
)
933 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
935 return IPicture_AddRef((IPicture
*)This
);
938 /************************************************************************
939 * OLEPictureImpl_IPersistStream_Release (IUnknown)
941 * See Windows documentation for more details on IUnknown methods.
943 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
944 IPersistStream
* iface
)
946 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
948 return IPicture_Release((IPicture
*)This
);
951 /************************************************************************
952 * OLEPictureImpl_IPersistStream_GetClassID
954 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
955 IPersistStream
* iface
,CLSID
* pClassID
)
957 TRACE("(%p)\n", pClassID
);
958 memcpy(pClassID
, &CLSID_StdPicture
, sizeof(*pClassID
));
962 /************************************************************************
963 * OLEPictureImpl_IPersistStream_IsDirty
965 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
966 IPersistStream
* iface
)
968 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
969 FIXME("(%p),stub!\n",This
);
973 #ifdef SONAME_LIBJPEG
975 static void *libjpeg_handle
;
976 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
977 MAKE_FUNCPTR(jpeg_std_error
);
978 MAKE_FUNCPTR(jpeg_CreateDecompress
);
979 MAKE_FUNCPTR(jpeg_read_header
);
980 MAKE_FUNCPTR(jpeg_start_decompress
);
981 MAKE_FUNCPTR(jpeg_read_scanlines
);
982 MAKE_FUNCPTR(jpeg_finish_decompress
);
983 MAKE_FUNCPTR(jpeg_destroy_decompress
);
986 static void *load_libjpeg(void)
988 if((libjpeg_handle
= wine_dlopen(SONAME_LIBJPEG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
990 #define LOAD_FUNCPTR(f) \
991 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
992 libjpeg_handle = NULL; \
996 LOAD_FUNCPTR(jpeg_std_error
);
997 LOAD_FUNCPTR(jpeg_CreateDecompress
);
998 LOAD_FUNCPTR(jpeg_read_header
);
999 LOAD_FUNCPTR(jpeg_start_decompress
);
1000 LOAD_FUNCPTR(jpeg_read_scanlines
);
1001 LOAD_FUNCPTR(jpeg_finish_decompress
);
1002 LOAD_FUNCPTR(jpeg_destroy_decompress
);
1005 return libjpeg_handle
;
1008 /* for the jpeg decompressor source manager. */
1009 static void _jpeg_init_source(j_decompress_ptr cinfo
) { }
1011 static boolean
_jpeg_fill_input_buffer(j_decompress_ptr cinfo
) {
1012 ERR("(), should not get here.\n");
1016 static void _jpeg_skip_input_data(j_decompress_ptr cinfo
,long num_bytes
) {
1017 TRACE("Skipping %ld bytes...\n", num_bytes
);
1018 cinfo
->src
->next_input_byte
+= num_bytes
;
1019 cinfo
->src
->bytes_in_buffer
-= num_bytes
;
1022 static boolean
_jpeg_resync_to_restart(j_decompress_ptr cinfo
, int desired
) {
1023 ERR("(desired=%d), should not get here.\n",desired
);
1026 static void _jpeg_term_source(j_decompress_ptr cinfo
) { }
1027 #endif /* SONAME_LIBJPEG */
1030 unsigned char *data
;
1031 unsigned int curoff
;
1035 static int _gif_inputfunc(GifFileType
*gif
, GifByteType
*data
, int len
) {
1036 struct gifdata
*gd
= (struct gifdata
*)gif
->UserData
;
1038 if (len
+gd
->curoff
> gd
->len
) {
1039 FIXME("Trying to read %d bytes, but only %d available.\n",len
, gd
->len
-gd
->curoff
);
1040 len
= gd
->len
- gd
->curoff
;
1042 memcpy(data
, gd
->data
+gd
->curoff
, len
);
1048 static HRESULT
OLEPictureImpl_LoadGif(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1059 int transparent
= -1;
1066 gif
= DGifOpen((void*)&gd
, _gif_inputfunc
);
1067 ret
= DGifSlurp(gif
);
1068 if (ret
== GIF_ERROR
) {
1069 FIXME("Failed reading GIF using libgif.\n");
1072 TRACE("screen height %d, width %d\n", gif
->SWidth
, gif
->SHeight
);
1073 TRACE("color res %d, backgcolor %d\n", gif
->SColorResolution
, gif
->SBackGroundColor
);
1074 TRACE("imgcnt %d\n", gif
->ImageCount
);
1075 if (gif
->ImageCount
<1) {
1076 FIXME("GIF stream does not have images inside?\n");
1079 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1080 gif
->Image
.Width
, gif
->Image
.Height
,
1081 gif
->Image
.Left
, gif
->Image
.Top
,
1082 gif
->Image
.Interlace
1085 padding
= (gif
->SWidth
+3) & ~3;
1086 si
= gif
->SavedImages
+0;
1087 gid
= &(si
->ImageDesc
);
1089 if (!cm
) cm
= gif
->SColorMap
;
1090 bmi
= HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER
)+(cm
->ColorCount
)*sizeof(RGBQUAD
));
1091 bytes
= HeapAlloc(GetProcessHeap(),0,padding
*gif
->SHeight
);
1093 /* look for the transparent color extension */
1094 for (i
= 0; i
< si
->ExtensionBlockCount
; ++i
) {
1095 eb
= si
->ExtensionBlocks
+ i
;
1096 if (eb
->Function
== 0xF9 && eb
->ByteCount
== 4) {
1097 if ((eb
->Bytes
[0] & 1) == 1) {
1098 transparent
= (unsigned char)eb
->Bytes
[3];
1103 for (i
= 0; i
< cm
->ColorCount
; i
++) {
1104 bmi
->bmiColors
[i
].rgbRed
= cm
->Colors
[i
].Red
;
1105 bmi
->bmiColors
[i
].rgbGreen
= cm
->Colors
[i
].Green
;
1106 bmi
->bmiColors
[i
].rgbBlue
= cm
->Colors
[i
].Blue
;
1107 if (i
== transparent
) {
1108 This
->rgbTrans
= RGB(bmi
->bmiColors
[i
].rgbRed
,
1109 bmi
->bmiColors
[i
].rgbGreen
,
1110 bmi
->bmiColors
[i
].rgbBlue
);
1114 /* Map to in picture coordinates */
1115 for (i
= 0, j
= 0; i
< gid
->Height
; i
++) {
1116 if (gif
->Image
.Interlace
) {
1118 bytes
+ (gid
->Top
+ j
) * padding
+ gid
->Left
,
1119 si
->RasterBits
+ i
* gid
->Width
,
1122 /* Lower bits of interlaced counter encode current interlace */
1123 if (j
& 1) j
+= 2; /* Currently filling odd rows */
1124 else if (j
& 2) j
+= 4; /* Currently filling even rows not multiples of 4 */
1125 else j
+= 8; /* Currently filling every 8th row or 4th row in-between */
1127 if (j
>= gid
->Height
&& i
< gid
->Height
&& (j
& 1) == 0) {
1128 /* End of current interlace, go to next interlace */
1129 if (j
& 2) j
= 1; /* Next iteration fills odd rows */
1130 else if (j
& 4) j
= 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1131 else j
= 4; /* Next iteration fills rows in-between rows mod 6 */
1135 bytes
+ (gid
->Top
+ i
) * padding
+ gid
->Left
,
1136 si
->RasterBits
+ i
* gid
->Width
,
1141 bmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1142 bmi
->bmiHeader
.biWidth
= gif
->SWidth
;
1143 bmi
->bmiHeader
.biHeight
= -gif
->SHeight
;
1144 bmi
->bmiHeader
.biPlanes
= 1;
1145 bmi
->bmiHeader
.biBitCount
= 8;
1146 bmi
->bmiHeader
.biCompression
= BI_RGB
;
1147 bmi
->bmiHeader
.biSizeImage
= padding
*gif
->SHeight
;
1148 bmi
->bmiHeader
.biXPelsPerMeter
= 0;
1149 bmi
->bmiHeader
.biYPelsPerMeter
= 0;
1150 bmi
->bmiHeader
.biClrUsed
= cm
->ColorCount
;
1151 bmi
->bmiHeader
.biClrImportant
= 0;
1154 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1163 if (transparent
> -1) {
1164 /* Create the Mask */
1165 HDC hdc
= CreateCompatibleDC(0);
1166 HDC hdcMask
= CreateCompatibleDC(0);
1168 HBITMAP hOldbitmapmask
;
1170 unsigned int monopadding
= (((unsigned)(gif
->SWidth
+ 31)) >> 5) << 2;
1173 This
->hbmXor
= CreateDIBitmap(
1182 bmi
->bmiColors
[0].rgbRed
= 0;
1183 bmi
->bmiColors
[0].rgbGreen
= 0;
1184 bmi
->bmiColors
[0].rgbBlue
= 0;
1185 bmi
->bmiColors
[1].rgbRed
= 255;
1186 bmi
->bmiColors
[1].rgbGreen
= 255;
1187 bmi
->bmiColors
[1].rgbBlue
= 255;
1189 bmi
->bmiHeader
.biBitCount
= 1;
1190 bmi
->bmiHeader
.biSizeImage
= monopadding
*gif
->SHeight
;
1191 bmi
->bmiHeader
.biClrUsed
= 2;
1193 for (i
= 0; i
< gif
->SHeight
; i
++) {
1194 unsigned char * colorPointer
= bytes
+ padding
* i
;
1195 unsigned char * monoPointer
= bytes
+ monopadding
* i
;
1196 for (j
= 0; j
< gif
->SWidth
; j
++) {
1197 unsigned char pixel
= colorPointer
[j
];
1198 if ((j
& 7) == 0) monoPointer
[j
>> 3] = 0;
1199 if (pixel
== (transparent
& 0x000000FFU
)) monoPointer
[j
>> 3] |= 1 << (7 - (j
& 7));
1203 hTempMask
= CreateDIBitmap(
1213 bmi
->bmiHeader
.biHeight
= -bmi
->bmiHeader
.biHeight
;
1214 This
->hbmMask
= CreateBitmap(bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, 1, 1, NULL
);
1215 hOldbitmap
= SelectObject(hdc
, hTempMask
);
1216 hOldbitmapmask
= SelectObject(hdcMask
, This
->hbmMask
);
1218 SetBkColor(hdc
, RGB(255, 255, 255));
1219 BitBlt(hdcMask
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, hdc
, 0, 0, SRCCOPY
);
1221 /* We no longer need the original bitmap, so we apply the first
1222 transformation with the mask to speed up the rendering */
1223 SelectObject(hdc
, This
->hbmXor
);
1224 SetBkColor(hdc
, RGB(0,0,0));
1225 SetTextColor(hdc
, RGB(255,255,255));
1226 BitBlt(hdc
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
,
1227 hdcMask
, 0, 0, SRCAND
);
1229 SelectObject(hdc
, hOldbitmap
);
1230 SelectObject(hdcMask
, hOldbitmapmask
);
1233 DeleteObject(hTempMask
);
1237 This
->desc
.picType
= PICTYPE_BITMAP
;
1238 OLEPictureImpl_SetBitmap(This
);
1240 HeapFree(GetProcessHeap(),0,bmi
);
1241 HeapFree(GetProcessHeap(),0,bytes
);
1245 static HRESULT
OLEPictureImpl_LoadJpeg(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1247 #ifdef SONAME_LIBJPEG
1248 struct jpeg_decompress_struct jd
;
1249 struct jpeg_error_mgr jerr
;
1252 JSAMPROW samprow
,oldsamprow
;
1253 BITMAPINFOHEADER bmi
;
1256 struct jpeg_source_mgr xjsm
;
1260 if(!libjpeg_handle
) {
1261 if(!load_libjpeg()) {
1262 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG
);
1267 /* This is basically so we can use in-memory data for jpeg decompression.
1268 * We need to have all the functions.
1270 xjsm
.next_input_byte
= xbuf
;
1271 xjsm
.bytes_in_buffer
= xread
;
1272 xjsm
.init_source
= _jpeg_init_source
;
1273 xjsm
.fill_input_buffer
= _jpeg_fill_input_buffer
;
1274 xjsm
.skip_input_data
= _jpeg_skip_input_data
;
1275 xjsm
.resync_to_restart
= _jpeg_resync_to_restart
;
1276 xjsm
.term_source
= _jpeg_term_source
;
1278 jd
.err
= pjpeg_std_error(&jerr
);
1279 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1280 * jpeg_create_decompress(&jd); */
1281 pjpeg_CreateDecompress(&jd
, JPEG_LIB_VERSION
, sizeof(struct jpeg_decompress_struct
));
1283 ret
=pjpeg_read_header(&jd
,TRUE
);
1284 jd
.out_color_space
= JCS_RGB
;
1285 pjpeg_start_decompress(&jd
);
1286 if (ret
!= JPEG_HEADER_OK
) {
1287 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret
);
1288 HeapFree(GetProcessHeap(),0,xbuf
);
1292 bits
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1293 (jd
.output_height
+1) * ((jd
.output_width
*jd
.output_components
+ 3) & ~3) );
1294 samprow
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,jd
.output_width
*jd
.output_components
);
1297 oldsamprow
= samprow
;
1298 while ( jd
.output_scanline
<jd
.output_height
) {
1299 x
= pjpeg_read_scanlines(&jd
,&samprow
,1);
1301 FIXME("failed to read current scanline?\n");
1304 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1305 for(i
=0;i
<jd
.output_width
;i
++,samprow
+=jd
.output_components
) {
1306 *(bits
++) = *(samprow
+2);
1307 *(bits
++) = *(samprow
+1);
1308 *(bits
++) = *(samprow
);
1310 bits
= (LPBYTE
)(((UINT_PTR
)bits
+ 3) & ~3);
1311 samprow
= oldsamprow
;
1315 bmi
.biSize
= sizeof(bmi
);
1316 bmi
.biWidth
= jd
.output_width
;
1317 bmi
.biHeight
= -jd
.output_height
;
1319 bmi
.biBitCount
= jd
.output_components
<<3;
1320 bmi
.biCompression
= BI_RGB
;
1321 bmi
.biSizeImage
= jd
.output_height
*jd
.output_width
*jd
.output_components
;
1322 bmi
.biXPelsPerMeter
= 0;
1323 bmi
.biYPelsPerMeter
= 0;
1325 bmi
.biClrImportant
= 0;
1327 HeapFree(GetProcessHeap(),0,samprow
);
1328 pjpeg_finish_decompress(&jd
);
1329 pjpeg_destroy_decompress(&jd
);
1331 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1340 This
->desc
.picType
= PICTYPE_BITMAP
;
1341 OLEPictureImpl_SetBitmap(This
);
1342 HeapFree(GetProcessHeap(),0,bits
);
1345 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1350 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1352 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1353 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1356 /* Does not matter whether this is a coreheader or not, we only use
1357 * components which are in both
1360 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1364 xbuf
+bfh
->bfOffBits
,
1369 This
->desc
.picType
= PICTYPE_BITMAP
;
1370 OLEPictureImpl_SetBitmap(This
);
1374 /*****************************************************
1375 * start of PNG-specific code
1376 * currently only supports colortype PNG_COLOR_TYPE_RGB
1378 #ifdef SONAME_LIBPNG
1385 static void png_stream_read_data(png_structp png_ptr
, png_bytep data
,
1388 png_io
* io_ptr
= png_ptr
->io_ptr
;
1390 if(length
+ io_ptr
->position
> io_ptr
->size
){
1391 length
= io_ptr
->size
- io_ptr
->position
;
1394 memcpy(data
, io_ptr
->buff
+ io_ptr
->position
, length
);
1396 io_ptr
->position
+= length
;
1399 static void *libpng_handle
;
1400 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
1401 MAKE_FUNCPTR(png_create_read_struct
);
1402 MAKE_FUNCPTR(png_create_info_struct
);
1403 MAKE_FUNCPTR(png_set_read_fn
);
1404 MAKE_FUNCPTR(png_read_info
);
1405 MAKE_FUNCPTR(png_read_image
);
1406 MAKE_FUNCPTR(png_get_rowbytes
);
1407 MAKE_FUNCPTR(png_set_bgr
);
1408 MAKE_FUNCPTR(png_destroy_read_struct
);
1409 MAKE_FUNCPTR(png_set_palette_to_rgb
);
1410 MAKE_FUNCPTR(png_read_update_info
);
1411 MAKE_FUNCPTR(png_get_tRNS
);
1412 MAKE_FUNCPTR(png_get_PLTE
);
1413 MAKE_FUNCPTR(png_set_expand
);
1416 static void *load_libpng(void)
1418 if((libpng_handle
= wine_dlopen(SONAME_LIBPNG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
1420 #define LOAD_FUNCPTR(f) \
1421 if((p##f = wine_dlsym(libpng_handle, #f, NULL, 0)) == NULL) { \
1422 libpng_handle = NULL; \
1425 LOAD_FUNCPTR(png_create_read_struct
);
1426 LOAD_FUNCPTR(png_create_info_struct
);
1427 LOAD_FUNCPTR(png_set_read_fn
);
1428 LOAD_FUNCPTR(png_read_info
);
1429 LOAD_FUNCPTR(png_read_image
);
1430 LOAD_FUNCPTR(png_get_rowbytes
);
1431 LOAD_FUNCPTR(png_set_bgr
);
1432 LOAD_FUNCPTR(png_destroy_read_struct
);
1433 LOAD_FUNCPTR(png_set_palette_to_rgb
);
1434 LOAD_FUNCPTR(png_read_update_info
);
1435 LOAD_FUNCPTR(png_get_tRNS
);
1436 LOAD_FUNCPTR(png_get_PLTE
);
1437 LOAD_FUNCPTR(png_set_expand
);
1441 return libpng_handle
;
1443 #endif /* SONAME_LIBPNG */
1445 static HRESULT
OLEPictureImpl_LoadPNG(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1447 #ifdef SONAME_LIBPNG
1449 png_structp png_ptr
= NULL
;
1450 png_infop info_ptr
= NULL
;
1451 INT row
, rowsize
, height
, width
, num_trans
, i
, j
;
1452 png_bytep
* row_pointers
= NULL
;
1453 png_bytep pngdata
= NULL
;
1454 BITMAPINFOHEADER bmi
;
1455 HDC hdcref
= NULL
, hdcXor
, hdcMask
;
1459 png_color_16p trans_values
;
1460 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1461 HBITMAP hbmoldXor
, hbmoldMask
, temp
;
1463 if(!libpng_handle
) {
1464 if(!load_libpng()) {
1465 ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG
);
1474 png_ptr
= ppng_create_read_struct(PNG_LIBPNG_VER_STRING
,
1477 if(setjmp(png_jmpbuf(png_ptr
))){
1478 TRACE("Error in libpng\n");
1483 info_ptr
= ppng_create_info_struct(png_ptr
);
1484 ppng_set_read_fn(png_ptr
, &io
, png_stream_read_data
);
1485 ppng_read_info(png_ptr
, info_ptr
);
1487 if(!(png_ptr
->color_type
== PNG_COLOR_TYPE_RGB
||
1488 png_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
||
1489 png_ptr
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)){
1490 FIXME("Unsupported .PNG type: %d\n", png_ptr
->color_type
);
1495 transparency
= (ppng_get_tRNS(png_ptr
, info_ptr
, &trans
, &num_trans
, &trans_values
)
1498 /* sets format from anything to RGBA */
1499 ppng_set_expand(png_ptr
);
1500 /* sets format to BGRA */
1501 ppng_set_bgr(png_ptr
);
1503 ppng_read_update_info(png_ptr
, info_ptr
);
1505 rowsize
= ppng_get_rowbytes(png_ptr
, info_ptr
);
1506 /* align rowsize to 4-byte boundary */
1507 rowsize
= (rowsize
+ 3) & ~3;
1508 height
= info_ptr
->height
;
1509 width
= info_ptr
->width
;
1511 pngdata
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, height
* rowsize
);
1512 row_pointers
= HeapAlloc(GetProcessHeap(), 0, height
* (sizeof(VOID
*)));
1514 if(!pngdata
|| !row_pointers
){
1519 for (row
= 0; row
< height
; row
++){
1520 row_pointers
[row
] = pngdata
+ row
* rowsize
;
1523 ppng_read_image(png_ptr
, row_pointers
);
1525 bmi
.biSize
= sizeof(bmi
);
1526 bmi
.biWidth
= width
;
1527 bmi
.biHeight
= -height
;
1529 bmi
.biBitCount
= info_ptr
->channels
* 8;
1530 bmi
.biCompression
= BI_RGB
;
1531 bmi
.biSizeImage
= height
* rowsize
;
1532 bmi
.biXPelsPerMeter
= 0;
1533 bmi
.biYPelsPerMeter
= 0;
1535 bmi
.biClrImportant
= 0;
1538 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1547 /* only fully-transparent alpha is handled */
1548 if((info_ptr
->channels
!= 4) || !transparency
){
1549 ReleaseDC(0, hdcref
);
1553 This
->hbmXor
= CreateDIBitmap(
1562 /* set transparent pixels to black, all others to white */
1563 for(i
= 0; i
< height
; i
++){
1564 for(j
= 3; j
< rowsize
; j
+= 4){
1565 if(row_pointers
[i
][j
] == 0)
1566 *((DWORD
*)(&row_pointers
[i
][j
- 3])) = black
;
1568 *((DWORD
*)(&row_pointers
[i
][j
- 3])) = white
;
1572 temp
= CreateDIBitmap(
1581 ReleaseDC(0, hdcref
);
1583 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1584 hdcXor
= CreateCompatibleDC(NULL
);
1585 hdcMask
= CreateCompatibleDC(NULL
);
1587 hbmoldXor
= SelectObject(hdcXor
,temp
);
1588 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1589 SetBkColor(hdcXor
,black
);
1590 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1592 SelectObject(hdcXor
,This
->hbmXor
);
1595 SetTextColor(hdcXor
,white
);
1596 SetBkColor(hdcXor
,black
);
1597 BitBlt(hdcXor
,0,0,width
,height
,hdcMask
,0,0,SRCAND
);
1599 SelectObject(hdcXor
,hbmoldXor
);
1600 SelectObject(hdcMask
,hbmoldMask
);
1606 This
->desc
.picType
= PICTYPE_BITMAP
;
1607 OLEPictureImpl_SetBitmap(This
);
1612 ppng_destroy_read_struct(&png_ptr
,
1613 (info_ptr
? &info_ptr
: (png_infopp
) NULL
),
1615 HeapFree(GetProcessHeap(), 0, row_pointers
);
1616 HeapFree(GetProcessHeap(), 0, pngdata
);
1618 #else /* SONAME_LIBPNG */
1619 ERR("Trying to load PNG picture, but PNG supported not compiled in.\n");
1624 /*****************************************************
1625 * start of Icon-specific code
1628 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1631 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1636 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1637 FIXME("icon.idType=%d\n",cifd->idType);
1638 FIXME("icon.idCount=%d\n",cifd->idCount);
1640 for (i=0;i<cifd->idCount;i++) {
1641 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1642 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1643 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1644 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1645 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1646 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1647 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1648 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1652 /* If we have more than one icon, try to find the best.
1653 * this currently means '32 pixel wide'.
1655 if (cifd
->idCount
!=1) {
1656 for (i
=0;i
<cifd
->idCount
;i
++) {
1657 if (cifd
->idEntries
[i
].bWidth
== 32)
1660 if (i
==cifd
->idCount
) i
=0;
1663 hicon
= CreateIconFromResourceEx(
1664 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1665 cifd
->idEntries
[i
].dwDIBSize
,
1668 cifd
->idEntries
[i
].bWidth
,
1669 cifd
->idEntries
[i
].bHeight
,
1673 FIXME("CreateIcon failed.\n");
1676 This
->desc
.picType
= PICTYPE_ICON
;
1677 This
->desc
.u
.icon
.hicon
= hicon
;
1678 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1679 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1680 hdcRef
= CreateCompatibleDC(0);
1681 This
->himetricWidth
=(cifd
->idEntries
[i
].bWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
1682 This
->himetricHeight
=(cifd
->idEntries
[i
].bHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
1688 static HRESULT
OLEPictureImpl_LoadMetafile(OLEPictureImpl
*This
,
1689 const BYTE
*data
, ULONG size
)
1694 /* SetMetaFileBitsEx performs data check on its own */
1695 hmf
= SetMetaFileBitsEx(size
, data
);
1698 This
->desc
.picType
= PICTYPE_METAFILE
;
1699 This
->desc
.u
.wmf
.hmeta
= hmf
;
1700 This
->desc
.u
.wmf
.xExt
= 0;
1701 This
->desc
.u
.wmf
.yExt
= 0;
1703 This
->origWidth
= 0;
1704 This
->origHeight
= 0;
1705 This
->himetricWidth
= 0;
1706 This
->himetricHeight
= 0;
1711 hemf
= SetEnhMetaFileBits(size
, data
);
1712 if (!hemf
) return E_FAIL
;
1714 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1715 This
->desc
.u
.emf
.hemf
= hemf
;
1717 This
->origWidth
= 0;
1718 This
->origHeight
= 0;
1719 This
->himetricWidth
= 0;
1720 This
->himetricHeight
= 0;
1725 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1726 const BYTE
*data
, ULONG size
)
1728 APM_HEADER
*header
= (APM_HEADER
*)data
;
1731 if (size
< sizeof(APM_HEADER
))
1733 if (header
->key
!= 0x9ac6cdd7)
1736 if ((hr
= OLEPictureImpl_LoadMetafile(This
, data
+ sizeof(APM_HEADER
), size
- sizeof(*header
))) != S_OK
)
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 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1747 * Loads the binary data from the IStream. Starts at current position.
1748 * There appears to be an 2 DWORD header:
1752 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1754 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
,IStream
*pStm
) {
1755 HRESULT hr
= E_FAIL
;
1756 BOOL headerisdata
= FALSE
;
1757 BOOL statfailed
= FALSE
;
1758 ULONG xread
, toread
;
1764 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1766 TRACE("(%p,%p)\n",This
,pStm
);
1768 /****************************************************************************************
1769 * Part 1: Load the data
1771 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1772 * out whether we do.
1774 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1775 * compound file. This may explain most, if not all, of the cases of "no
1776 * header", and the header validation should take this into account.
1777 * At least in Visual Basic 6, resource streams, valid headers are
1778 * header[0] == "lt\0\0",
1779 * header[1] == length_of_stream.
1781 * Also handle streams where we do not have a working "Stat" method by
1782 * reading all data until the end of the stream.
1784 hr
=IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1786 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr
);
1788 /* we will read at least 8 byte ... just right below */
1789 statstg
.cbSize
.QuadPart
= 8;
1794 headerisdata
= FALSE
;
1796 hr
=IStream_Read(pStm
,header
,8,&xread
);
1797 if (hr
|| xread
!=8) {
1798 FIXME("Failure while reading picture header (hr is %x, nread is %d).\n",hr
,xread
);
1801 headerread
+= xread
;
1804 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1805 if (toread
!= 0 && toread
!= header
[1])
1806 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1809 if (toread
== 0) break;
1811 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1812 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1813 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1814 (header
[0] == EMR_HEADER
) || /* EMF header */
1815 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1817 ) {/* Found start of bitmap data */
1818 headerisdata
= TRUE
;
1820 toread
= statstg
.cbSize
.QuadPart
-8;
1824 FIXME("Unknown stream header magic: %08x\n", header
[0]);
1828 } while (!headerisdata
);
1830 if (statfailed
) { /* we don't know the size ... read all we get */
1832 int origsize
= sizeinc
;
1835 TRACE("Reading all data from stream.\n");
1836 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1838 memcpy (xbuf
, &header
, 8);
1840 while (xread
< origsize
) {
1841 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1846 if (!nread
|| hr
) /* done, or error */
1848 if (xread
== origsize
) {
1849 origsize
+= sizeinc
;
1850 sizeinc
= 2*sizeinc
; /* exponential increase */
1851 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1855 TRACE("hr in no-stat loader case is %08x\n", hr
);
1856 TRACE("loaded %d bytes.\n", xread
);
1857 This
->datalen
= xread
;
1860 This
->datalen
= toread
+(headerisdata
?8:0);
1861 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1864 memcpy (xbuf
, &header
, 8);
1866 while (xread
< This
->datalen
) {
1868 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1873 if (xread
!= This
->datalen
)
1874 FIXME("Could only read %d of %d bytes out of stream?\n",xread
,This
->datalen
);
1876 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1877 This
->desc
.picType
= PICTYPE_NONE
;
1882 /****************************************************************************************
1883 * Part 2: Process the loaded data
1886 magic
= xbuf
[0] + (xbuf
[1]<<8);
1887 This
->loadtime_format
= magic
;
1890 case 0x4947: /* GIF */
1891 hr
= OLEPictureImpl_LoadGif(This
, xbuf
, xread
);
1893 case 0xd8ff: /* JPEG */
1894 hr
= OLEPictureImpl_LoadJpeg(This
, xbuf
, xread
);
1896 case 0x4d42: /* Bitmap */
1897 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1899 case 0x5089: /* PNG */
1900 hr
= OLEPictureImpl_LoadPNG(This
, xbuf
, xread
);
1902 case 0xcdd7: /* APM */
1903 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1905 case 0x0000: { /* ICON , first word is dwReserved */
1906 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1913 /* let's see if it's a metafile */
1914 hr
= OLEPictureImpl_LoadMetafile(This
, xbuf
, xread
);
1915 if (hr
== S_OK
) break;
1917 FIXME("Unknown magic %04x, %d read bytes:\n",magic
,xread
);
1919 for (i
=0;i
<xread
+8;i
++) {
1920 if (i
<8) MESSAGE("%02x ",((unsigned char*)&header
)[i
]);
1921 else MESSAGE("%02x ",xbuf
[i
-8]);
1922 if (i
% 10 == 9) MESSAGE("\n");
1928 This
->bIsDirty
= FALSE
;
1930 /* FIXME: this notify is not really documented */
1932 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1936 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1940 BITMAPINFO
* pInfoBitmap
;
1941 int iNumPaletteEntries
;
1942 unsigned char * pPixelData
;
1943 BITMAPFILEHEADER
* pFileHeader
;
1944 BITMAPINFO
* pInfoHeader
;
1946 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1947 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1949 /* Find out bitmap size and padded length */
1951 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1952 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1954 /* Fetch bitmap palette & pixel data */
1956 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1957 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1959 /* Calculate the total length required for the BMP data */
1960 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1961 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1962 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1964 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1965 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1967 iNumPaletteEntries
= 0;
1970 sizeof(BITMAPFILEHEADER
) +
1971 sizeof(BITMAPINFOHEADER
) +
1972 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1973 pInfoBitmap
->bmiHeader
.biSizeImage
;
1974 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1976 /* Fill the BITMAPFILEHEADER */
1977 pFileHeader
= (BITMAPFILEHEADER
*)(*ppBuffer
);
1978 pFileHeader
->bfType
= 0x4d42;
1979 pFileHeader
->bfSize
= *pLength
;
1980 pFileHeader
->bfOffBits
=
1981 sizeof(BITMAPFILEHEADER
) +
1982 sizeof(BITMAPINFOHEADER
) +
1983 iNumPaletteEntries
* sizeof(RGBQUAD
);
1985 /* Fill the BITMAPINFOHEADER and the palette data */
1986 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1987 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1989 (unsigned char *)(*ppBuffer
) +
1990 sizeof(BITMAPFILEHEADER
) +
1991 sizeof(BITMAPINFOHEADER
) +
1992 iNumPaletteEntries
* sizeof(RGBQUAD
),
1993 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1996 HeapFree(GetProcessHeap(), 0, pPixelData
);
1997 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
2001 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
2006 *ppBuffer
= NULL
; *pLength
= 0;
2007 if (GetIconInfo(hIcon
, &infoIcon
)) {
2009 BITMAPINFO
* pInfoBitmap
;
2010 unsigned char * pIconData
= NULL
;
2011 unsigned int iDataSize
= 0;
2013 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
2015 /* Find out icon size */
2017 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
2018 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
2020 /* Auxiliary pointers */
2021 CURSORICONFILEDIR
* pIconDir
;
2022 CURSORICONFILEDIRENTRY
* pIconEntry
;
2023 BITMAPINFOHEADER
* pIconBitmapHeader
;
2024 unsigned int iOffsetPalette
;
2025 unsigned int iOffsetColorData
;
2026 unsigned int iOffsetMaskData
;
2028 unsigned int iLengthScanLineColor
;
2029 unsigned int iLengthScanLineMask
;
2030 unsigned int iNumEntriesPalette
;
2032 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
2033 iLengthScanLineColor
= ((pInfoBitmap
->bmiHeader
.biWidth
* pInfoBitmap
->bmiHeader
.biBitCount
+ 31) >> 5) << 2;
2035 FIXME("DEBUG: bitmap size is %d x %d\n",
2036 pInfoBitmap->bmiHeader.biWidth,
2037 pInfoBitmap->bmiHeader.biHeight);
2038 FIXME("DEBUG: bitmap bpp is %d\n",
2039 pInfoBitmap->bmiHeader.biBitCount);
2040 FIXME("DEBUG: bitmap nplanes is %d\n",
2041 pInfoBitmap->bmiHeader.biPlanes);
2042 FIXME("DEBUG: bitmap biSizeImage is %u\n",
2043 pInfoBitmap->bmiHeader.biSizeImage);
2045 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
2046 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
2047 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
2049 /* Fill out the CURSORICONFILEDIR */
2050 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
2051 pIconDir
->idType
= 1;
2052 pIconDir
->idCount
= 1;
2054 /* Fill out the CURSORICONFILEDIRENTRY */
2055 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
2056 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
2057 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
2058 pIconEntry
->bColorCount
=
2059 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
2060 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
2062 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
2063 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
2064 pIconEntry
->dwDIBSize
= 0;
2065 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
2067 /* Fill out the BITMAPINFOHEADER */
2068 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2069 memcpy(pIconBitmapHeader
, &pInfoBitmap
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
2071 /* Find out whether a palette exists for the bitmap */
2072 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
2073 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
2074 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
2075 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
2076 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
2077 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
2078 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
2079 iNumEntriesPalette
= 3;
2080 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
2081 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
2083 iNumEntriesPalette
= 0;
2086 /* Add bitmap size and header size to icon data size. */
2087 iOffsetPalette
= iDataSize
;
2088 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
2089 iOffsetColorData
= iDataSize
;
2090 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
2091 iOffsetMaskData
= iDataSize
;
2092 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
2093 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
2094 pIconBitmapHeader
->biHeight
*= 2;
2095 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
2096 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
2097 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2098 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2100 /* Get the actual bitmap data from the icon bitmap */
2101 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
2102 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
2103 if (iNumEntriesPalette
> 0) {
2104 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
2105 iNumEntriesPalette
* sizeof(RGBQUAD
));
2108 /* Reset all values so that GetDIBits call succeeds */
2109 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
2110 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
2111 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
2113 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
2114 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
2115 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
2117 printf("ERROR: unable to get bitmap mask (error %u)\n",
2122 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
2123 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
2125 /* Write out everything produced so far to the stream */
2126 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
2130 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
2135 Remarks (from MSDN entry on GetIconInfo):
2137 GetIconInfo creates bitmaps for the hbmMask and hbmColor
2138 members of ICONINFO. The calling application must manage
2139 these bitmaps and delete them when they are no longer
2142 if (hDC
) ReleaseDC(0, hDC
);
2143 DeleteObject(infoIcon
.hbmMask
);
2144 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
2145 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
2147 printf("ERROR: Unable to get icon information (error %u)\n",
2153 static HRESULT WINAPI
OLEPictureImpl_Save(
2154 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
2156 HRESULT hResult
= E_NOTIMPL
;
2158 unsigned int iDataSize
;
2160 int iSerializeResult
= 0;
2161 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
2163 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
2165 switch (This
->desc
.picType
) {
2167 if (This
->bIsDirty
|| !This
->data
) {
2168 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
2169 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
2173 HeapFree(GetProcessHeap(), 0, This
->data
);
2174 This
->data
= pIconData
;
2175 This
->datalen
= iDataSize
;
2177 if (This
->loadtime_magic
!= 0xdeadbeef) {
2180 header
[0] = This
->loadtime_magic
;
2181 header
[1] = This
->datalen
;
2182 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2184 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
2188 case PICTYPE_BITMAP
:
2189 if (This
->bIsDirty
) {
2190 switch (This
->keepOrigFormat
? This
->loadtime_format
: 0x4d42) {
2192 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
2195 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
2198 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
2201 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
2204 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
2207 if (iSerializeResult
) {
2209 if (This->loadtime_magic != 0xdeadbeef) {
2214 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
2215 header
[1] = iDataSize
;
2216 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2218 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
2220 HeapFree(GetProcessHeap(), 0, This
->data
);
2221 This
->data
= pIconData
;
2222 This
->datalen
= iDataSize
;
2227 if (This->loadtime_magic != 0xdeadbeef) {
2232 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
2233 header
[1] = This
->datalen
;
2234 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2236 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
2240 case PICTYPE_METAFILE
:
2241 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
2243 case PICTYPE_ENHMETAFILE
:
2244 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
2247 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
2250 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
2254 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
2255 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
2257 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
2258 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
2263 /************************************************************************
2267 /************************************************************************
2268 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
2270 * See Windows documentation for more details on IUnknown methods.
2272 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
2277 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2279 return IPicture_QueryInterface((IPicture
*)This
, riid
, ppvoid
);
2282 /************************************************************************
2283 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
2285 * See Windows documentation for more details on IUnknown methods.
2287 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
2290 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2292 return IPicture_AddRef((IPicture
*)This
);
2295 /************************************************************************
2296 * OLEPictureImpl_IDispatch_Release (IUnknown)
2298 * See Windows documentation for more details on IUnknown methods.
2300 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
2303 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2305 return IPicture_Release((IPicture
*)This
);
2308 /************************************************************************
2309 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
2311 * See Windows documentation for more details on IDispatch methods.
2313 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
2315 unsigned int* pctinfo
)
2317 TRACE("(%p)\n", pctinfo
);
2324 /************************************************************************
2325 * OLEPictureImpl_GetTypeInfo (IDispatch)
2327 * See Windows documentation for more details on IDispatch methods.
2329 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
2333 ITypeInfo
** ppTInfo
)
2335 static const WCHAR stdole2tlb
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
2339 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
2344 hres
= LoadTypeLib(stdole2tlb
, &tl
);
2347 ERR("Could not load stdole2.tlb\n");
2351 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
2353 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres
);
2358 /************************************************************************
2359 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2361 * See Windows documentation for more details on IDispatch methods.
2363 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
2366 LPOLESTR
* rgszNames
,
2374 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
2375 rgszNames
, cNames
, (int)lcid
, rgDispId
);
2379 return E_INVALIDARG
;
2383 /* retrieve type information */
2384 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
2388 ERR("GetTypeInfo failed.\n");
2392 /* convert names to DISPIDs */
2393 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
2394 ITypeInfo_Release(pTInfo
);
2400 /************************************************************************
2401 * OLEPictureImpl_Invoke (IDispatch)
2403 * See Windows documentation for more details on IDispatch methods.
2405 static HRESULT WINAPI
OLEPictureImpl_Invoke(
2407 DISPID dispIdMember
,
2411 DISPPARAMS
* pDispParams
,
2412 VARIANT
* pVarResult
,
2413 EXCEPINFO
* pExepInfo
,
2416 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2418 /* validate parameters */
2420 if (!IsEqualIID(riid
, &IID_NULL
))
2422 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2423 return DISP_E_UNKNOWNNAME
;
2428 ERR("null pDispParams not allowed\n");
2429 return DISP_E_PARAMNOTOPTIONAL
;
2432 if (wFlags
& DISPATCH_PROPERTYGET
)
2434 if (pDispParams
->cArgs
!= 0)
2436 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2437 return DISP_E_BADPARAMCOUNT
;
2441 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2442 return DISP_E_PARAMNOTOPTIONAL
;
2445 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2447 if (pDispParams
->cArgs
!= 1)
2449 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2450 return DISP_E_BADPARAMCOUNT
;
2454 switch (dispIdMember
)
2456 case DISPID_PICT_HANDLE
:
2457 if (wFlags
& DISPATCH_PROPERTYGET
)
2459 TRACE("DISPID_PICT_HANDLE\n");
2460 V_VT(pVarResult
) = VT_I4
;
2461 return IPicture_get_Handle((IPicture
*)&This
->lpVtbl
, &V_UINT(pVarResult
));
2464 case DISPID_PICT_HPAL
:
2465 if (wFlags
& DISPATCH_PROPERTYGET
)
2467 TRACE("DISPID_PICT_HPAL\n");
2468 V_VT(pVarResult
) = VT_I4
;
2469 return IPicture_get_hPal((IPicture
*)&This
->lpVtbl
, &V_UINT(pVarResult
));
2471 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2475 TRACE("DISPID_PICT_HPAL\n");
2477 VariantInit(&vararg
);
2478 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2482 hr
= IPicture_set_hPal((IPicture
*)&This
->lpVtbl
, V_I4(&vararg
));
2484 VariantClear(&vararg
);
2488 case DISPID_PICT_TYPE
:
2489 if (wFlags
& DISPATCH_PROPERTYGET
)
2491 TRACE("DISPID_PICT_TYPE\n");
2492 V_VT(pVarResult
) = VT_I2
;
2493 return OLEPictureImpl_get_Type((IPicture
*)&This
->lpVtbl
, &V_I2(pVarResult
));
2496 case DISPID_PICT_WIDTH
:
2497 if (wFlags
& DISPATCH_PROPERTYGET
)
2499 TRACE("DISPID_PICT_WIDTH\n");
2500 V_VT(pVarResult
) = VT_I4
;
2501 return IPicture_get_Width((IPicture
*)&This
->lpVtbl
, &V_I4(pVarResult
));
2504 case DISPID_PICT_HEIGHT
:
2505 if (wFlags
& DISPATCH_PROPERTYGET
)
2507 TRACE("DISPID_PICT_HEIGHT\n");
2508 V_VT(pVarResult
) = VT_I4
;
2509 return IPicture_get_Height((IPicture
*)&This
->lpVtbl
, &V_I4(pVarResult
));
2514 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember
, wFlags
);
2515 return DISP_E_MEMBERNOTFOUND
;
2519 static const IPictureVtbl OLEPictureImpl_VTable
=
2521 OLEPictureImpl_QueryInterface
,
2522 OLEPictureImpl_AddRef
,
2523 OLEPictureImpl_Release
,
2524 OLEPictureImpl_get_Handle
,
2525 OLEPictureImpl_get_hPal
,
2526 OLEPictureImpl_get_Type
,
2527 OLEPictureImpl_get_Width
,
2528 OLEPictureImpl_get_Height
,
2529 OLEPictureImpl_Render
,
2530 OLEPictureImpl_set_hPal
,
2531 OLEPictureImpl_get_CurDC
,
2532 OLEPictureImpl_SelectPicture
,
2533 OLEPictureImpl_get_KeepOriginalFormat
,
2534 OLEPictureImpl_put_KeepOriginalFormat
,
2535 OLEPictureImpl_PictureChanged
,
2536 OLEPictureImpl_SaveAsFile
,
2537 OLEPictureImpl_get_Attributes
2540 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2542 OLEPictureImpl_IDispatch_QueryInterface
,
2543 OLEPictureImpl_IDispatch_AddRef
,
2544 OLEPictureImpl_IDispatch_Release
,
2545 OLEPictureImpl_GetTypeInfoCount
,
2546 OLEPictureImpl_GetTypeInfo
,
2547 OLEPictureImpl_GetIDsOfNames
,
2548 OLEPictureImpl_Invoke
2551 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2553 OLEPictureImpl_IPersistStream_QueryInterface
,
2554 OLEPictureImpl_IPersistStream_AddRef
,
2555 OLEPictureImpl_IPersistStream_Release
,
2556 OLEPictureImpl_GetClassID
,
2557 OLEPictureImpl_IsDirty
,
2558 OLEPictureImpl_Load
,
2559 OLEPictureImpl_Save
,
2560 OLEPictureImpl_GetSizeMax
2563 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2565 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2566 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2567 OLEPictureImpl_IConnectionPointContainer_Release
,
2568 OLEPictureImpl_EnumConnectionPoints
,
2569 OLEPictureImpl_FindConnectionPoint
2572 /***********************************************************************
2573 * OleCreatePictureIndirect (OLEAUT32.419)
2575 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2576 BOOL fOwn
, LPVOID
*ppvObj
)
2578 OLEPictureImpl
* newPict
= NULL
;
2581 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), fOwn
, ppvObj
);
2592 * Try to construct a new instance of the class.
2594 newPict
= OLEPictureImpl_Construct(lpPictDesc
, fOwn
);
2596 if (newPict
== NULL
)
2597 return E_OUTOFMEMORY
;
2600 * Make sure it supports the interface required by the caller.
2602 hr
= IPicture_QueryInterface((IPicture
*)newPict
, riid
, ppvObj
);
2605 * Release the reference obtained in the constructor. If
2606 * the QueryInterface was unsuccessful, it will free the class.
2608 IPicture_Release((IPicture
*)newPict
);
2614 /***********************************************************************
2615 * OleLoadPicture (OLEAUT32.418)
2617 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2618 REFIID riid
, LPVOID
*ppvObj
)
2624 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2625 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2627 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2630 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2632 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2633 IPicture_Release(newpic
);
2637 IPersistStream_Load(ps
,lpstream
);
2638 IPersistStream_Release(ps
);
2639 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2641 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2642 IPicture_Release(newpic
);
2646 /***********************************************************************
2647 * OleLoadPictureEx (OLEAUT32.401)
2649 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2650 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2656 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2657 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2659 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2662 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2664 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2665 IPicture_Release(newpic
);
2669 IPersistStream_Load(ps
,lpstream
);
2670 IPersistStream_Release(ps
);
2671 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2673 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2674 IPicture_Release(newpic
);
2678 /***********************************************************************
2679 * OleLoadPicturePath (OLEAUT32.424)
2681 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2682 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2685 static const WCHAR file
[] = { 'f','i','l','e',':','/','/',0 };
2689 HGLOBAL hGlobal
= NULL
;
2690 DWORD dwBytesRead
= 0;
2693 IPersistStream
*pStream
;
2696 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2697 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2698 debugstr_guid(riid
), ppvRet
);
2700 if (!ppvRet
) return E_POINTER
;
2702 if (strncmpW(szURLorPath
, file
, 7) == 0) {
2705 hFile
= CreateFileW(szURLorPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2707 if (hFile
== INVALID_HANDLE_VALUE
)
2708 return E_UNEXPECTED
;
2710 dwFileSize
= GetFileSize(hFile
, NULL
);
2711 if (dwFileSize
!= INVALID_FILE_SIZE
)
2713 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2716 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
);
2719 GlobalFree(hGlobal
);
2727 return E_UNEXPECTED
;
2729 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2732 GlobalFree(hGlobal
);
2739 hRes
= CreateBindCtx(0, &pbc
);
2740 if (SUCCEEDED(hRes
))
2742 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2743 if (SUCCEEDED(hRes
))
2745 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2746 IMoniker_Release(pmnk
);
2748 IBindCtx_Release(pbc
);
2754 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2755 &IID_IPicture
, (LPVOID
*)&ipicture
);
2757 IStream_Release(stream
);
2761 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2763 IStream_Release(stream
);
2764 IPicture_Release(ipicture
);
2768 hRes
= IPersistStream_Load(pStream
, stream
);
2769 IPersistStream_Release(pStream
);
2770 IStream_Release(stream
);
2773 IPicture_Release(ipicture
);
2777 hRes
= IPicture_QueryInterface(ipicture
,riid
,ppvRet
);
2779 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2781 IPicture_Release(ipicture
);
2785 /*******************************************************************************
2786 * StdPic ClassFactory
2790 /* IUnknown fields */
2791 const IClassFactoryVtbl
*lpVtbl
;
2793 } IClassFactoryImpl
;
2795 static HRESULT WINAPI
2796 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2797 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2799 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2800 return E_NOINTERFACE
;
2804 SPCF_AddRef(LPCLASSFACTORY iface
) {
2805 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2806 return InterlockedIncrement(&This
->ref
);
2809 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2810 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2811 /* static class, won't be freed */
2812 return InterlockedDecrement(&This
->ref
);
2815 static HRESULT WINAPI
SPCF_CreateInstance(
2816 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2818 /* Creates an uninitialized picture */
2819 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2823 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2824 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2825 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2829 static const IClassFactoryVtbl SPCF_Vtbl
= {
2830 SPCF_QueryInterface
,
2833 SPCF_CreateInstance
,
2836 static IClassFactoryImpl STDPIC_CF
= {&SPCF_Vtbl
, 1 };
2838 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= (LPVOID
)&STDPIC_CF
; }