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
58 #define HAVE_STDLIB_H 1
68 /* Must be before wine includes, the header has things conflicting with
72 #define NONAMELESSUNION
73 #define NONAMELESSSTRUCT
85 #include "wine/debug.h"
86 #include "wine/unicode.h"
87 #include "wine/library.h"
91 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
95 /* Header for Aldus Placable Metafiles - a standard metafile follows */
96 typedef struct _APM_HEADER
118 } CURSORICONFILEDIRENTRY
;
125 CURSORICONFILEDIRENTRY idEntries
[1];
130 /*************************************************************************
131 * Declaration of implementation class
134 typedef struct OLEPictureImpl
{
137 * IPicture handles IUnknown
140 const IPictureVtbl
*lpVtbl
;
141 const IDispatchVtbl
*lpvtblIDispatch
;
142 const IPersistStreamVtbl
*lpvtblIPersistStream
;
143 const IConnectionPointContainerVtbl
*lpvtblIConnectionPointContainer
;
145 /* Object reference count */
148 /* We own the object and must destroy it ourselves */
151 /* Picture description */
154 /* These are the pixel size of a bitmap */
158 /* And these are the size of the picture converted into HIMETRIC units */
159 OLE_XSIZE_HIMETRIC himetricWidth
;
160 OLE_YSIZE_HIMETRIC himetricHeight
;
162 IConnectionPoint
*pCP
;
167 /* Bitmap transparency mask */
175 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
176 unsigned int loadtime_magic
; /* If a length header was found, saves value */
177 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
181 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
184 static inline OLEPictureImpl
*impl_from_IDispatch( IDispatch
*iface
)
186 return (OLEPictureImpl
*)((char*)iface
- FIELD_OFFSET(OLEPictureImpl
, lpvtblIDispatch
));
189 static inline OLEPictureImpl
*impl_from_IPersistStream( IPersistStream
*iface
)
191 return (OLEPictureImpl
*)((char*)iface
- FIELD_OFFSET(OLEPictureImpl
, lpvtblIPersistStream
));
194 static inline OLEPictureImpl
*impl_from_IConnectionPointContainer( IConnectionPointContainer
*iface
)
196 return (OLEPictureImpl
*)((char*)iface
- FIELD_OFFSET(OLEPictureImpl
, lpvtblIConnectionPointContainer
));
200 * Predeclare VTables. They get initialized at the end.
202 static const IPictureVtbl OLEPictureImpl_VTable
;
203 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
204 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
205 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
207 /***********************************************************************
208 * Implementation of the OLEPictureImpl class.
211 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
) {
215 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
216 if(GetObjectA(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
217 ERR("GetObject fails\n");
220 This
->origWidth
= bm
.bmWidth
;
221 This
->origHeight
= bm
.bmHeight
;
222 /* The width and height are stored in HIMETRIC units (0.01 mm),
223 so we take our pixel width divide by pixels per inch and
224 multiply by 25.4 * 100 */
225 /* Should we use GetBitmapDimension if available? */
226 hdcRef
= CreateCompatibleDC(0);
227 This
->himetricWidth
=(bm
.bmWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
228 This
->himetricHeight
=(bm
.bmHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
232 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
236 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
237 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
241 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
242 if(GetObjectA(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
243 ERR("GetObject fails on icon bitmap\n");
247 This
->origWidth
= bm
.bmWidth
;
248 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
249 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
251 This
->himetricWidth
= (This
->origWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
252 This
->himetricHeight
= (This
->origHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
253 ReleaseDC(0, hdcRef
);
255 DeleteObject(infoIcon
.hbmMask
);
256 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
258 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
262 /************************************************************************
263 * OLEPictureImpl_Construct
265 * This method will construct a new instance of the OLEPictureImpl
268 * The caller of this method must release the object when it's
271 static OLEPictureImpl
* OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
)
273 OLEPictureImpl
* newObject
= 0;
276 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
279 * Allocate space for the object.
281 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
287 * Initialize the virtual function table.
289 newObject
->lpVtbl
= &OLEPictureImpl_VTable
;
290 newObject
->lpvtblIDispatch
= &OLEPictureImpl_IDispatch_VTable
;
291 newObject
->lpvtblIPersistStream
= &OLEPictureImpl_IPersistStream_VTable
;
292 newObject
->lpvtblIConnectionPointContainer
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
294 newObject
->pCP
= NULL
;
295 CreateConnectionPoint((IUnknown
*)newObject
,&IID_IPropertyNotifySink
,&newObject
->pCP
);
298 HeapFree(GetProcessHeap(), 0, newObject
);
303 * Start with one reference count. The caller of this function
304 * must release the interface pointer when it is done.
307 newObject
->hDCCur
= 0;
309 newObject
->fOwn
= fOwn
;
311 /* dunno about original value */
312 newObject
->keepOrigFormat
= TRUE
;
314 newObject
->hbmMask
= NULL
;
315 newObject
->hbmXor
= NULL
;
316 newObject
->loadtime_magic
= 0xdeadbeef;
317 newObject
->loadtime_format
= 0;
318 newObject
->bIsDirty
= FALSE
;
321 newObject
->desc
= *pictDesc
;
323 switch(pictDesc
->picType
) {
325 OLEPictureImpl_SetBitmap(newObject
);
328 case PICTYPE_METAFILE
:
329 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
330 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
331 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
335 /* not sure what to do here */
336 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
340 OLEPictureImpl_SetIcon(newObject
);
342 case PICTYPE_ENHMETAFILE
:
344 FIXME("Unsupported type %d\n", pictDesc
->picType
);
345 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
349 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
352 TRACE("returning %p\n", newObject
);
356 /************************************************************************
357 * OLEPictureImpl_Destroy
359 * This method is called by the Release method when the reference
360 * count goes down to 0. It will free all resources used by
362 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
364 TRACE("(%p)\n", Obj
);
367 IConnectionPoint_Release(Obj
->pCP
);
369 if(Obj
->fOwn
) { /* We need to destroy the picture */
370 switch(Obj
->desc
.picType
) {
372 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
373 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
374 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
376 case PICTYPE_METAFILE
:
377 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
380 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
382 case PICTYPE_ENHMETAFILE
:
383 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
386 case PICTYPE_UNINITIALIZED
:
390 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
394 HeapFree(GetProcessHeap(), 0, Obj
->data
);
395 HeapFree(GetProcessHeap(), 0, Obj
);
399 /************************************************************************
400 * OLEPictureImpl_AddRef (IUnknown)
402 * See Windows documentation for more details on IUnknown methods.
404 static ULONG WINAPI
OLEPictureImpl_AddRef(
407 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
408 ULONG refCount
= InterlockedIncrement(&This
->ref
);
410 TRACE("(%p)->(ref before=%d)\n", This
, refCount
- 1);
415 /************************************************************************
416 * OLEPictureImpl_Release (IUnknown)
418 * See Windows documentation for more details on IUnknown methods.
420 static ULONG WINAPI
OLEPictureImpl_Release(
423 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
424 ULONG refCount
= InterlockedDecrement(&This
->ref
);
426 TRACE("(%p)->(ref before=%d)\n", This
, refCount
+ 1);
429 * If the reference count goes down to 0, perform suicide.
431 if (!refCount
) OLEPictureImpl_Destroy(This
);
436 /************************************************************************
437 * OLEPictureImpl_QueryInterface (IUnknown)
439 * See Windows documentation for more details on IUnknown methods.
441 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
446 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
447 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
450 * Perform a sanity check on the parameters.
452 if ( (This
==0) || (ppvObject
==0) )
456 * Initialize the return parameter.
461 * Compare the riid with the interface IDs implemented by this object.
463 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IPicture
, riid
))
465 else if (IsEqualIID(&IID_IDispatch
, riid
))
466 *ppvObject
= &This
->lpvtblIDispatch
;
467 else if (IsEqualIID(&IID_IPictureDisp
, riid
))
468 *ppvObject
= &This
->lpvtblIDispatch
;
469 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistStream
, riid
))
470 *ppvObject
= &This
->lpvtblIPersistStream
;
471 else if (IsEqualIID(&IID_IConnectionPointContainer
, riid
))
472 *ppvObject
= &This
->lpvtblIConnectionPointContainer
;
475 * Check that we obtained an interface.
479 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
480 return E_NOINTERFACE
;
484 * Query Interface always increases the reference count by one when it is
487 OLEPictureImpl_AddRef((IPicture
*)This
);
492 /***********************************************************************
493 * OLEPicture_SendNotify (internal)
495 * Sends notification messages of changed properties to any interested
498 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
500 IEnumConnections
*pEnum
;
503 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
))
505 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
506 IPropertyNotifySink
*sink
;
508 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
509 IPropertyNotifySink_OnChanged(sink
, dispID
);
510 IPropertyNotifySink_Release(sink
);
511 IUnknown_Release(CD
.pUnk
);
513 IEnumConnections_Release(pEnum
);
516 /************************************************************************
517 * OLEPictureImpl_get_Handle
519 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
522 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
523 TRACE("(%p)->(%p)\n", This
, phandle
);
528 switch(This
->desc
.picType
) {
530 case PICTYPE_UNINITIALIZED
:
534 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
536 case PICTYPE_METAFILE
:
537 *phandle
= HandleToUlong(This
->desc
.u
.wmf
.hmeta
);
540 *phandle
= HandleToUlong(This
->desc
.u
.icon
.hicon
);
542 case PICTYPE_ENHMETAFILE
:
543 *phandle
= HandleToUlong(This
->desc
.u
.emf
.hemf
);
546 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
549 TRACE("returning handle %08x\n", *phandle
);
553 /************************************************************************
554 * OLEPictureImpl_get_hPal
556 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
559 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
561 TRACE("(%p)->(%p)\n", This
, phandle
);
566 switch (This
->desc
.picType
) {
567 case (UINT
)PICTYPE_UNINITIALIZED
:
573 *phandle
= HandleToUlong(This
->desc
.u
.bmp
.hpal
);
576 case PICTYPE_METAFILE
:
580 case PICTYPE_ENHMETAFILE
:
582 FIXME("unimplemented for type %d. Returning 0 palette.\n",
588 TRACE("returning 0x%08x, palette handle %08x\n", hres
, *phandle
);
592 /************************************************************************
593 * OLEPictureImpl_get_Type
595 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
598 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
599 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
604 *ptype
= This
->desc
.picType
;
608 /************************************************************************
609 * OLEPictureImpl_get_Width
611 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
612 OLE_XSIZE_HIMETRIC
*pwidth
)
614 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
615 TRACE("(%p)->(%p): width is %d\n", This
, pwidth
, This
->himetricWidth
);
616 *pwidth
= This
->himetricWidth
;
620 /************************************************************************
621 * OLEPictureImpl_get_Height
623 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
624 OLE_YSIZE_HIMETRIC
*pheight
)
626 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
627 TRACE("(%p)->(%p): height is %d\n", This
, pheight
, This
->himetricHeight
);
628 *pheight
= This
->himetricHeight
;
632 /************************************************************************
633 * OLEPictureImpl_Render
635 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
636 LONG x
, LONG y
, LONG cx
, LONG cy
,
637 OLE_XPOS_HIMETRIC xSrc
,
638 OLE_YPOS_HIMETRIC ySrc
,
639 OLE_XSIZE_HIMETRIC cxSrc
,
640 OLE_YSIZE_HIMETRIC cySrc
,
643 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
644 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
645 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
647 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds
->left
, prcWBounds
->top
,
648 prcWBounds
->right
, prcWBounds
->bottom
);
650 if(cx
== 0 || cy
== 0 || cxSrc
== 0 || cySrc
== 0){
651 return CTL_E_INVALIDPROPERTYVALUE
;
655 * While the documentation suggests this to be here (or after rendering?)
656 * it does cause an endless recursion in my sample app. -MM 20010804
657 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
660 switch(This
->desc
.picType
) {
661 case PICTYPE_UNINITIALIZED
:
670 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
671 NB y-axis gets flipped */
673 hdcBmp
= CreateCompatibleDC(0);
674 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
675 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
676 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
677 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
678 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
681 HDC hdcMask
= CreateCompatibleDC(0);
682 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
684 hbmpOld
= SelectObject(hdcBmp
, This
->hbmXor
);
686 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
687 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
688 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
689 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
690 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
692 SetBkColor(hdc
, RGB(255, 255, 255));
693 SetTextColor(hdc
, RGB(0, 0, 0));
694 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
695 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
697 SelectObject(hdcMask
, hOldbm
);
700 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
701 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
704 SelectObject(hdcBmp
, hbmpOld
);
709 FIXME("Not quite correct implementation of rendering icons...\n");
710 DrawIcon(hdc
,x
,y
,This
->desc
.u
.icon
.hicon
);
713 case PICTYPE_METAFILE
:
715 POINT prevOrg
, prevWndOrg
;
716 SIZE prevExt
, prevWndExt
;
719 /* Render the WMF to the appropriate location by setting the
720 appropriate ratio between "device units" and "logical units" */
721 oldmode
= SetMapMode(hdc
, MM_ANISOTROPIC
);
722 /* For the "source rectangle" the y-axis must be inverted */
723 SetWindowOrgEx(hdc
, xSrc
, This
->himetricHeight
-ySrc
, &prevWndOrg
);
724 SetWindowExtEx(hdc
, cxSrc
, -cySrc
, &prevWndExt
);
725 /* For the "destination rectangle" no inversion is necessary */
726 SetViewportOrgEx(hdc
, x
, y
, &prevOrg
);
727 SetViewportExtEx(hdc
, cx
, cy
, &prevExt
);
729 if (!PlayMetaFile(hdc
, This
->desc
.u
.wmf
.hmeta
))
730 ERR("PlayMetaFile failed!\n");
732 /* We're done, restore the DC to the previous settings for converting
733 logical units to device units */
734 SetWindowExtEx(hdc
, prevWndExt
.cx
, prevWndExt
.cy
, NULL
);
735 SetWindowOrgEx(hdc
, prevWndOrg
.x
, prevWndOrg
.y
, NULL
);
736 SetViewportExtEx(hdc
, prevExt
.cx
, prevExt
.cy
, NULL
);
737 SetViewportOrgEx(hdc
, prevOrg
.x
, prevOrg
.y
, NULL
);
738 SetMapMode(hdc
, oldmode
);
742 case PICTYPE_ENHMETAFILE
:
744 RECT rc
= { x
, y
, x
+ cx
, y
+ cy
};
745 PlayEnhMetaFile(hdc
, This
->desc
.u
.emf
.hemf
, &rc
);
750 FIXME("type %d not implemented\n", This
->desc
.picType
);
756 /************************************************************************
757 * OLEPictureImpl_set_hPal
759 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
762 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
763 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
764 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
768 /************************************************************************
769 * OLEPictureImpl_get_CurDC
771 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
774 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
775 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
776 if (phdc
) *phdc
= This
->hDCCur
;
780 /************************************************************************
781 * OLEPictureImpl_SelectPicture
783 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
786 OLE_HANDLE
*phbmpOut
)
788 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
789 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
790 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
791 SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
794 *phdcOut
= This
->hDCCur
;
795 This
->hDCCur
= hdcIn
;
797 *phbmpOut
= HandleToUlong(This
->desc
.u
.bmp
.hbitmap
);
800 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
805 /************************************************************************
806 * OLEPictureImpl_get_KeepOriginalFormat
808 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
811 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
812 TRACE("(%p)->(%p)\n", This
, pfKeep
);
815 *pfKeep
= This
->keepOrigFormat
;
819 /************************************************************************
820 * OLEPictureImpl_put_KeepOriginalFormat
822 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
825 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
826 TRACE("(%p)->(%d)\n", This
, keep
);
827 This
->keepOrigFormat
= keep
;
828 /* FIXME: what DISPID notification here? */
832 /************************************************************************
833 * OLEPictureImpl_PictureChanged
835 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
837 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
838 TRACE("(%p)->()\n", This
);
839 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
840 This
->bIsDirty
= TRUE
;
844 /************************************************************************
845 * OLEPictureImpl_SaveAsFile
847 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
852 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
853 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
854 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
857 /************************************************************************
858 * OLEPictureImpl_get_Attributes
860 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
863 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
864 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
870 switch (This
->desc
.picType
) {
871 case PICTYPE_UNINITIALIZED
:
872 case PICTYPE_NONE
: break;
873 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
874 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
875 case PICTYPE_ENHMETAFILE
: /* fall through */
876 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
877 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
883 /************************************************************************
884 * IConnectionPointContainer
886 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
887 IConnectionPointContainer
* iface
,
891 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
893 return IPicture_QueryInterface((IPicture
*)This
,riid
,ppvoid
);
896 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
897 IConnectionPointContainer
* iface
)
899 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
901 return IPicture_AddRef((IPicture
*)This
);
904 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
905 IConnectionPointContainer
* iface
)
907 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
909 return IPicture_Release((IPicture
*)This
);
912 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
913 IConnectionPointContainer
* iface
,
914 IEnumConnectionPoints
** ppEnum
)
916 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
918 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
922 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
923 IConnectionPointContainer
* iface
,
925 IConnectionPoint
**ppCP
)
927 OLEPictureImpl
*This
= impl_from_IConnectionPointContainer(iface
);
928 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
932 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
933 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
934 FIXME("no connection point for %s\n",debugstr_guid(riid
));
935 return CONNECT_E_NOCONNECTION
;
939 /************************************************************************
943 /************************************************************************
944 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
946 * See Windows documentation for more details on IUnknown methods.
948 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
949 IPersistStream
* iface
,
953 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
955 return IPicture_QueryInterface((IPicture
*)This
, riid
, ppvoid
);
958 /************************************************************************
959 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
961 * See Windows documentation for more details on IUnknown methods.
963 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
964 IPersistStream
* iface
)
966 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
968 return IPicture_AddRef((IPicture
*)This
);
971 /************************************************************************
972 * OLEPictureImpl_IPersistStream_Release (IUnknown)
974 * See Windows documentation for more details on IUnknown methods.
976 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
977 IPersistStream
* iface
)
979 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
981 return IPicture_Release((IPicture
*)This
);
984 /************************************************************************
985 * OLEPictureImpl_IPersistStream_GetClassID
987 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
988 IPersistStream
* iface
,CLSID
* pClassID
)
990 TRACE("(%p)\n", pClassID
);
991 *pClassID
= CLSID_StdPicture
;
995 /************************************************************************
996 * OLEPictureImpl_IPersistStream_IsDirty
998 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
999 IPersistStream
* iface
)
1001 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1002 FIXME("(%p),stub!\n",This
);
1006 #ifdef SONAME_LIBJPEG
1008 static void *libjpeg_handle
;
1009 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
1010 MAKE_FUNCPTR(jpeg_std_error
);
1011 MAKE_FUNCPTR(jpeg_CreateDecompress
);
1012 MAKE_FUNCPTR(jpeg_read_header
);
1013 MAKE_FUNCPTR(jpeg_start_decompress
);
1014 MAKE_FUNCPTR(jpeg_read_scanlines
);
1015 MAKE_FUNCPTR(jpeg_finish_decompress
);
1016 MAKE_FUNCPTR(jpeg_destroy_decompress
);
1019 static void *load_libjpeg(void)
1021 if((libjpeg_handle
= wine_dlopen(SONAME_LIBJPEG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
1023 #define LOAD_FUNCPTR(f) \
1024 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
1025 libjpeg_handle = NULL; \
1029 LOAD_FUNCPTR(jpeg_std_error
);
1030 LOAD_FUNCPTR(jpeg_CreateDecompress
);
1031 LOAD_FUNCPTR(jpeg_read_header
);
1032 LOAD_FUNCPTR(jpeg_start_decompress
);
1033 LOAD_FUNCPTR(jpeg_read_scanlines
);
1034 LOAD_FUNCPTR(jpeg_finish_decompress
);
1035 LOAD_FUNCPTR(jpeg_destroy_decompress
);
1038 return libjpeg_handle
;
1041 /* for the jpeg decompressor source manager. */
1042 static void _jpeg_init_source(j_decompress_ptr cinfo
) { }
1044 static jpeg_boolean
_jpeg_fill_input_buffer(j_decompress_ptr cinfo
) {
1045 ERR("(), should not get here.\n");
1049 static void _jpeg_skip_input_data(j_decompress_ptr cinfo
,long num_bytes
) {
1050 TRACE("Skipping %ld bytes...\n", num_bytes
);
1051 cinfo
->src
->next_input_byte
+= num_bytes
;
1052 cinfo
->src
->bytes_in_buffer
-= num_bytes
;
1055 static jpeg_boolean
_jpeg_resync_to_restart(j_decompress_ptr cinfo
, int desired
) {
1056 ERR("(desired=%d), should not get here.\n",desired
);
1059 static void _jpeg_term_source(j_decompress_ptr cinfo
) { }
1060 #endif /* SONAME_LIBJPEG */
1063 unsigned char *data
;
1064 unsigned int curoff
;
1068 static int _gif_inputfunc(GifFileType
*gif
, GifByteType
*data
, int len
) {
1069 struct gifdata
*gd
= gif
->UserData
;
1071 if (len
+gd
->curoff
> gd
->len
) {
1072 ERR("Trying to read %d bytes, but only %d available.\n",len
, gd
->len
-gd
->curoff
);
1073 len
= gd
->len
- gd
->curoff
;
1075 memcpy(data
, gd
->data
+gd
->curoff
, len
);
1081 static HRESULT
OLEPictureImpl_LoadGif(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1092 int transparent
= -1;
1099 gif
= DGifOpen((void*)&gd
, _gif_inputfunc
);
1100 ret
= DGifSlurp(gif
);
1101 if (ret
== GIF_ERROR
) {
1102 ERR("Failed reading GIF using libgif.\n");
1105 TRACE("screen height %d, width %d\n", gif
->SWidth
, gif
->SHeight
);
1106 TRACE("color res %d, backgcolor %d\n", gif
->SColorResolution
, gif
->SBackGroundColor
);
1107 TRACE("imgcnt %d\n", gif
->ImageCount
);
1108 if (gif
->ImageCount
<1) {
1109 ERR("GIF stream does not have images inside?\n");
1112 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1113 gif
->Image
.Width
, gif
->Image
.Height
,
1114 gif
->Image
.Left
, gif
->Image
.Top
,
1115 gif
->Image
.Interlace
1118 padding
= (gif
->SWidth
+3) & ~3;
1119 si
= gif
->SavedImages
+0;
1120 gid
= &(si
->ImageDesc
);
1122 if (!cm
) cm
= gif
->SColorMap
;
1123 bmi
= HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER
)+(cm
->ColorCount
)*sizeof(RGBQUAD
));
1124 bytes
= HeapAlloc(GetProcessHeap(),0,padding
*gif
->SHeight
);
1126 /* look for the transparent color extension */
1127 for (i
= 0; i
< si
->ExtensionBlockCount
; ++i
) {
1128 eb
= si
->ExtensionBlocks
+ i
;
1129 if (eb
->Function
== 0xF9 && eb
->ByteCount
== 4) {
1130 if ((eb
->Bytes
[0] & 1) == 1) {
1131 transparent
= (unsigned char)eb
->Bytes
[3];
1136 for (i
= 0; i
< cm
->ColorCount
; i
++) {
1137 bmi
->bmiColors
[i
].rgbRed
= cm
->Colors
[i
].Red
;
1138 bmi
->bmiColors
[i
].rgbGreen
= cm
->Colors
[i
].Green
;
1139 bmi
->bmiColors
[i
].rgbBlue
= cm
->Colors
[i
].Blue
;
1140 if (i
== transparent
) {
1141 This
->rgbTrans
= RGB(bmi
->bmiColors
[i
].rgbRed
,
1142 bmi
->bmiColors
[i
].rgbGreen
,
1143 bmi
->bmiColors
[i
].rgbBlue
);
1147 /* Map to in picture coordinates */
1148 for (i
= 0, j
= 0; i
< gid
->Height
; i
++) {
1149 if (gif
->Image
.Interlace
) {
1151 bytes
+ (gid
->Top
+ j
) * padding
+ gid
->Left
,
1152 si
->RasterBits
+ i
* gid
->Width
,
1155 /* Lower bits of interlaced counter encode current interlace */
1156 if (j
& 1) j
+= 2; /* Currently filling odd rows */
1157 else if (j
& 2) j
+= 4; /* Currently filling even rows not multiples of 4 */
1158 else j
+= 8; /* Currently filling every 8th row or 4th row in-between */
1160 if (j
>= gid
->Height
&& i
< gid
->Height
&& (j
& 1) == 0) {
1161 /* End of current interlace, go to next interlace */
1162 if (j
& 2) j
= 1; /* Next iteration fills odd rows */
1163 else if (j
& 4) j
= 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1164 else j
= 4; /* Next iteration fills rows in-between rows mod 6 */
1168 bytes
+ (gid
->Top
+ i
) * padding
+ gid
->Left
,
1169 si
->RasterBits
+ i
* gid
->Width
,
1174 bmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1175 bmi
->bmiHeader
.biWidth
= gif
->SWidth
;
1176 bmi
->bmiHeader
.biHeight
= -gif
->SHeight
;
1177 bmi
->bmiHeader
.biPlanes
= 1;
1178 bmi
->bmiHeader
.biBitCount
= 8;
1179 bmi
->bmiHeader
.biCompression
= BI_RGB
;
1180 bmi
->bmiHeader
.biSizeImage
= padding
*gif
->SHeight
;
1181 bmi
->bmiHeader
.biXPelsPerMeter
= 0;
1182 bmi
->bmiHeader
.biYPelsPerMeter
= 0;
1183 bmi
->bmiHeader
.biClrUsed
= cm
->ColorCount
;
1184 bmi
->bmiHeader
.biClrImportant
= 0;
1187 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1196 if (transparent
> -1) {
1197 /* Create the Mask */
1198 HDC hdc
= CreateCompatibleDC(0);
1199 HDC hdcMask
= CreateCompatibleDC(0);
1201 HBITMAP hOldbitmapmask
;
1203 unsigned int monopadding
= (((unsigned)(gif
->SWidth
+ 31)) >> 5) << 2;
1206 This
->hbmXor
= CreateDIBitmap(
1215 bmi
->bmiColors
[0].rgbRed
= 0;
1216 bmi
->bmiColors
[0].rgbGreen
= 0;
1217 bmi
->bmiColors
[0].rgbBlue
= 0;
1218 bmi
->bmiColors
[1].rgbRed
= 255;
1219 bmi
->bmiColors
[1].rgbGreen
= 255;
1220 bmi
->bmiColors
[1].rgbBlue
= 255;
1222 bmi
->bmiHeader
.biBitCount
= 1;
1223 bmi
->bmiHeader
.biSizeImage
= monopadding
*gif
->SHeight
;
1224 bmi
->bmiHeader
.biClrUsed
= 2;
1226 for (i
= 0; i
< gif
->SHeight
; i
++) {
1227 unsigned char * colorPointer
= bytes
+ padding
* i
;
1228 unsigned char * monoPointer
= bytes
+ monopadding
* i
;
1229 for (j
= 0; j
< gif
->SWidth
; j
++) {
1230 unsigned char pixel
= colorPointer
[j
];
1231 if ((j
& 7) == 0) monoPointer
[j
>> 3] = 0;
1232 if (pixel
== (transparent
& 0x000000FFU
)) monoPointer
[j
>> 3] |= 1 << (7 - (j
& 7));
1235 hTempMask
= CreateDIBitmap(
1244 bmi
->bmiHeader
.biHeight
= -bmi
->bmiHeader
.biHeight
;
1245 This
->hbmMask
= CreateBitmap(bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, 1, 1, NULL
);
1246 hOldbitmap
= SelectObject(hdc
, hTempMask
);
1247 hOldbitmapmask
= SelectObject(hdcMask
, This
->hbmMask
);
1249 SetBkColor(hdc
, RGB(255, 255, 255));
1250 BitBlt(hdcMask
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, hdc
, 0, 0, SRCCOPY
);
1252 /* We no longer need the original bitmap, so we apply the first
1253 transformation with the mask to speed up the rendering */
1254 SelectObject(hdc
, This
->hbmXor
);
1255 SetBkColor(hdc
, RGB(0,0,0));
1256 SetTextColor(hdc
, RGB(255,255,255));
1257 BitBlt(hdc
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
,
1258 hdcMask
, 0, 0, SRCAND
);
1260 SelectObject(hdc
, hOldbitmap
);
1261 SelectObject(hdcMask
, hOldbitmapmask
);
1264 DeleteObject(hTempMask
);
1267 ReleaseDC(0, hdcref
);
1268 This
->desc
.picType
= PICTYPE_BITMAP
;
1269 OLEPictureImpl_SetBitmap(This
);
1271 HeapFree(GetProcessHeap(),0,bmi
);
1272 HeapFree(GetProcessHeap(),0,bytes
);
1276 static HRESULT
OLEPictureImpl_LoadJpeg(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1278 #ifdef SONAME_LIBJPEG
1279 struct jpeg_decompress_struct jd
;
1280 struct jpeg_error_mgr jerr
;
1283 JSAMPROW samprow
,oldsamprow
;
1284 BITMAPINFOHEADER bmi
;
1287 struct jpeg_source_mgr xjsm
;
1291 if(!libjpeg_handle
) {
1292 if(!load_libjpeg()) {
1293 ERR("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG
);
1298 /* This is basically so we can use in-memory data for jpeg decompression.
1299 * We need to have all the functions.
1301 xjsm
.next_input_byte
= xbuf
;
1302 xjsm
.bytes_in_buffer
= xread
;
1303 xjsm
.init_source
= _jpeg_init_source
;
1304 xjsm
.fill_input_buffer
= _jpeg_fill_input_buffer
;
1305 xjsm
.skip_input_data
= _jpeg_skip_input_data
;
1306 xjsm
.resync_to_restart
= _jpeg_resync_to_restart
;
1307 xjsm
.term_source
= _jpeg_term_source
;
1309 jd
.err
= pjpeg_std_error(&jerr
);
1310 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1311 * jpeg_create_decompress(&jd); */
1312 pjpeg_CreateDecompress(&jd
, JPEG_LIB_VERSION
, sizeof(struct jpeg_decompress_struct
));
1314 ret
=pjpeg_read_header(&jd
,TRUE
);
1315 jd
.out_color_space
= JCS_RGB
;
1316 pjpeg_start_decompress(&jd
);
1317 if (ret
!= JPEG_HEADER_OK
) {
1318 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret
);
1319 HeapFree(GetProcessHeap(),0,xbuf
);
1323 bits
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1324 (jd
.output_height
+1) * ((jd
.output_width
*jd
.output_components
+ 3) & ~3) );
1325 samprow
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,jd
.output_width
*jd
.output_components
);
1328 oldsamprow
= samprow
;
1329 while ( jd
.output_scanline
<jd
.output_height
) {
1330 x
= pjpeg_read_scanlines(&jd
,&samprow
,1);
1332 ERR("failed to read current scanline?\n");
1335 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1336 for(i
=0;i
<jd
.output_width
;i
++,samprow
+=jd
.output_components
) {
1337 *(bits
++) = *(samprow
+2);
1338 *(bits
++) = *(samprow
+1);
1339 *(bits
++) = *(samprow
);
1341 bits
= (LPBYTE
)(((UINT_PTR
)bits
+ 3) & ~3);
1342 samprow
= oldsamprow
;
1346 bmi
.biSize
= sizeof(bmi
);
1347 bmi
.biWidth
= jd
.output_width
;
1348 bmi
.biHeight
= -jd
.output_height
;
1350 bmi
.biBitCount
= jd
.output_components
<<3;
1351 bmi
.biCompression
= BI_RGB
;
1352 bmi
.biSizeImage
= jd
.output_height
*jd
.output_width
*jd
.output_components
;
1353 bmi
.biXPelsPerMeter
= 0;
1354 bmi
.biYPelsPerMeter
= 0;
1356 bmi
.biClrImportant
= 0;
1358 HeapFree(GetProcessHeap(),0,samprow
);
1359 pjpeg_finish_decompress(&jd
);
1360 pjpeg_destroy_decompress(&jd
);
1362 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1370 ReleaseDC(0, hdcref
);
1371 This
->desc
.picType
= PICTYPE_BITMAP
;
1372 OLEPictureImpl_SetBitmap(This
);
1373 HeapFree(GetProcessHeap(),0,bits
);
1376 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1381 static HRESULT
OLEPictureImpl_LoadDIB(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1383 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1384 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1387 /* Does not matter whether this is a coreheader or not, we only use
1388 * components which are in both
1391 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1395 xbuf
+bfh
->bfOffBits
,
1399 ReleaseDC(0, hdcref
);
1400 if (This
->desc
.u
.bmp
.hbitmap
== 0)
1402 This
->desc
.picType
= PICTYPE_BITMAP
;
1403 OLEPictureImpl_SetBitmap(This
);
1407 /*****************************************************
1408 * start of PNG-specific code
1409 * currently only supports colortype PNG_COLOR_TYPE_RGB
1411 #ifdef SONAME_LIBPNG
1418 static void png_stream_read_data(png_structp png_ptr
, png_bytep data
,
1421 png_io
* io_ptr
= png_ptr
->io_ptr
;
1423 if(length
+ io_ptr
->position
> io_ptr
->size
){
1424 length
= io_ptr
->size
- io_ptr
->position
;
1427 memcpy(data
, io_ptr
->buff
+ io_ptr
->position
, length
);
1429 io_ptr
->position
+= length
;
1432 static void *libpng_handle
;
1433 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
1434 MAKE_FUNCPTR(png_create_read_struct
);
1435 MAKE_FUNCPTR(png_create_info_struct
);
1436 MAKE_FUNCPTR(png_set_read_fn
);
1437 MAKE_FUNCPTR(png_read_info
);
1438 MAKE_FUNCPTR(png_read_image
);
1439 MAKE_FUNCPTR(png_get_rowbytes
);
1440 MAKE_FUNCPTR(png_set_bgr
);
1441 MAKE_FUNCPTR(png_destroy_read_struct
);
1442 MAKE_FUNCPTR(png_set_palette_to_rgb
);
1443 MAKE_FUNCPTR(png_read_update_info
);
1444 MAKE_FUNCPTR(png_get_tRNS
);
1445 MAKE_FUNCPTR(png_get_PLTE
);
1446 MAKE_FUNCPTR(png_set_expand
);
1449 static void *load_libpng(void)
1451 if((libpng_handle
= wine_dlopen(SONAME_LIBPNG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
1453 #define LOAD_FUNCPTR(f) \
1454 if((p##f = wine_dlsym(libpng_handle, #f, NULL, 0)) == NULL) { \
1455 libpng_handle = NULL; \
1458 LOAD_FUNCPTR(png_create_read_struct
);
1459 LOAD_FUNCPTR(png_create_info_struct
);
1460 LOAD_FUNCPTR(png_set_read_fn
);
1461 LOAD_FUNCPTR(png_read_info
);
1462 LOAD_FUNCPTR(png_read_image
);
1463 LOAD_FUNCPTR(png_get_rowbytes
);
1464 LOAD_FUNCPTR(png_set_bgr
);
1465 LOAD_FUNCPTR(png_destroy_read_struct
);
1466 LOAD_FUNCPTR(png_set_palette_to_rgb
);
1467 LOAD_FUNCPTR(png_read_update_info
);
1468 LOAD_FUNCPTR(png_get_tRNS
);
1469 LOAD_FUNCPTR(png_get_PLTE
);
1470 LOAD_FUNCPTR(png_set_expand
);
1474 return libpng_handle
;
1476 #endif /* SONAME_LIBPNG */
1478 static HRESULT
OLEPictureImpl_LoadPNG(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1480 #ifdef SONAME_LIBPNG
1482 png_structp png_ptr
= NULL
;
1483 png_infop info_ptr
= NULL
;
1484 INT row
, rowsize
, height
, width
, num_trans
, i
, j
;
1485 png_bytep
* row_pointers
= NULL
;
1486 png_bytep pngdata
= NULL
;
1487 BITMAPINFOHEADER bmi
;
1488 HDC hdcref
= NULL
, hdcXor
, hdcMask
;
1492 png_color_16p trans_values
;
1493 COLORREF white
= RGB(255, 255, 255), black
= RGB(0, 0, 0);
1494 HBITMAP hbmoldXor
, hbmoldMask
, temp
;
1496 if(!libpng_handle
) {
1497 if(!load_libpng()) {
1498 ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG
);
1507 png_ptr
= ppng_create_read_struct(PNG_LIBPNG_VER_STRING
,
1510 if(setjmp(png_jmpbuf(png_ptr
))){
1511 TRACE("Error in libpng\n");
1516 info_ptr
= ppng_create_info_struct(png_ptr
);
1517 ppng_set_read_fn(png_ptr
, &io
, png_stream_read_data
);
1518 ppng_read_info(png_ptr
, info_ptr
);
1520 if(!(png_ptr
->color_type
== PNG_COLOR_TYPE_RGB
||
1521 png_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
||
1522 png_ptr
->color_type
== PNG_COLOR_TYPE_RGB_ALPHA
)){
1523 FIXME("Unsupported .PNG type: %d\n", png_ptr
->color_type
);
1528 transparency
= (ppng_get_tRNS(png_ptr
, info_ptr
, &trans
, &num_trans
, &trans_values
)
1531 /* sets format from anything to RGBA */
1532 ppng_set_expand(png_ptr
);
1533 /* sets format to BGRA */
1534 ppng_set_bgr(png_ptr
);
1536 ppng_read_update_info(png_ptr
, info_ptr
);
1538 rowsize
= ppng_get_rowbytes(png_ptr
, info_ptr
);
1539 /* align rowsize to 4-byte boundary */
1540 rowsize
= (rowsize
+ 3) & ~3;
1541 height
= info_ptr
->height
;
1542 width
= info_ptr
->width
;
1544 pngdata
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, height
* rowsize
);
1545 row_pointers
= HeapAlloc(GetProcessHeap(), 0, height
* (sizeof(VOID
*)));
1547 if(!pngdata
|| !row_pointers
){
1552 for (row
= 0; row
< height
; row
++){
1553 row_pointers
[row
] = pngdata
+ row
* rowsize
;
1556 ppng_read_image(png_ptr
, row_pointers
);
1558 bmi
.biSize
= sizeof(bmi
);
1559 bmi
.biWidth
= width
;
1560 bmi
.biHeight
= -height
;
1562 bmi
.biBitCount
= info_ptr
->channels
* 8;
1563 bmi
.biCompression
= BI_RGB
;
1564 bmi
.biSizeImage
= height
* rowsize
;
1565 bmi
.biXPelsPerMeter
= 0;
1566 bmi
.biYPelsPerMeter
= 0;
1568 bmi
.biClrImportant
= 0;
1571 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1580 /* only fully-transparent alpha is handled */
1581 if((info_ptr
->channels
!= 4) || !transparency
){
1582 ReleaseDC(0, hdcref
);
1586 This
->hbmXor
= CreateDIBitmap(
1595 /* set transparent pixels to black, all others to white */
1596 for(i
= 0; i
< height
; i
++){
1597 for(j
= 3; j
< rowsize
; j
+= 4){
1598 if(row_pointers
[i
][j
] == 0)
1599 *((DWORD
*)(&row_pointers
[i
][j
- 3])) = black
;
1601 *((DWORD
*)(&row_pointers
[i
][j
- 3])) = white
;
1605 temp
= CreateDIBitmap(
1614 ReleaseDC(0, hdcref
);
1616 This
->hbmMask
= CreateBitmap(width
,-height
,1,1,NULL
);
1617 hdcXor
= CreateCompatibleDC(NULL
);
1618 hdcMask
= CreateCompatibleDC(NULL
);
1620 hbmoldXor
= SelectObject(hdcXor
,temp
);
1621 hbmoldMask
= SelectObject(hdcMask
,This
->hbmMask
);
1622 SetBkColor(hdcXor
,black
);
1623 BitBlt(hdcMask
,0,0,width
,height
,hdcXor
,0,0,SRCCOPY
);
1625 SelectObject(hdcXor
,This
->hbmXor
);
1628 SetTextColor(hdcXor
,white
);
1629 SetBkColor(hdcXor
,black
);
1630 BitBlt(hdcXor
,0,0,width
,height
,hdcMask
,0,0,SRCAND
);
1632 SelectObject(hdcXor
,hbmoldXor
);
1633 SelectObject(hdcMask
,hbmoldMask
);
1639 This
->desc
.picType
= PICTYPE_BITMAP
;
1640 OLEPictureImpl_SetBitmap(This
);
1645 ppng_destroy_read_struct(&png_ptr
, info_ptr
? &info_ptr
: NULL
, NULL
);
1646 HeapFree(GetProcessHeap(), 0, row_pointers
);
1647 HeapFree(GetProcessHeap(), 0, pngdata
);
1649 #else /* SONAME_LIBPNG */
1650 ERR("Trying to load PNG picture, but PNG supported not compiled in.\n");
1655 /*****************************************************
1656 * start of Icon-specific code
1659 static HRESULT
OLEPictureImpl_LoadIcon(OLEPictureImpl
*This
, BYTE
*xbuf
, ULONG xread
)
1662 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1667 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1668 FIXME("icon.idType=%d\n",cifd->idType);
1669 FIXME("icon.idCount=%d\n",cifd->idCount);
1671 for (i=0;i<cifd->idCount;i++) {
1672 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1673 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1674 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1675 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1676 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1677 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1678 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1679 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1683 /* If we have more than one icon, try to find the best.
1684 * this currently means '32 pixel wide'.
1686 if (cifd
->idCount
!=1) {
1687 for (i
=0;i
<cifd
->idCount
;i
++) {
1688 if (cifd
->idEntries
[i
].bWidth
== 32)
1691 if (i
==cifd
->idCount
) i
=0;
1694 hicon
= CreateIconFromResourceEx(
1695 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1696 cifd
->idEntries
[i
].dwDIBSize
,
1699 cifd
->idEntries
[i
].bWidth
,
1700 cifd
->idEntries
[i
].bHeight
,
1704 ERR("CreateIcon failed.\n");
1707 This
->desc
.picType
= PICTYPE_ICON
;
1708 This
->desc
.u
.icon
.hicon
= hicon
;
1709 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1710 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1711 hdcRef
= CreateCompatibleDC(0);
1712 This
->himetricWidth
=(cifd
->idEntries
[i
].bWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
1713 This
->himetricHeight
=(cifd
->idEntries
[i
].bHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
1719 static HRESULT
OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl
*This
,
1720 const BYTE
*data
, ULONG size
)
1725 hemf
= SetEnhMetaFileBits(size
, data
);
1726 if (!hemf
) return E_FAIL
;
1728 GetEnhMetaFileHeader(hemf
, sizeof(hdr
), &hdr
);
1730 This
->desc
.picType
= PICTYPE_ENHMETAFILE
;
1731 This
->desc
.u
.emf
.hemf
= hemf
;
1733 This
->origWidth
= 0;
1734 This
->origHeight
= 0;
1735 This
->himetricWidth
= hdr
.rclFrame
.right
- hdr
.rclFrame
.left
;
1736 This
->himetricHeight
= hdr
.rclFrame
.bottom
- hdr
.rclFrame
.top
;
1741 static HRESULT
OLEPictureImpl_LoadAPM(OLEPictureImpl
*This
,
1742 const BYTE
*data
, ULONG size
)
1744 APM_HEADER
*header
= (APM_HEADER
*)data
;
1747 if (size
< sizeof(APM_HEADER
))
1749 if (header
->key
!= 0x9ac6cdd7)
1752 /* SetMetaFileBitsEx performs data check on its own */
1753 hmf
= SetMetaFileBitsEx(size
- sizeof(*header
), data
+ sizeof(*header
));
1754 if (!hmf
) return E_FAIL
;
1756 This
->desc
.picType
= PICTYPE_METAFILE
;
1757 This
->desc
.u
.wmf
.hmeta
= hmf
;
1758 This
->desc
.u
.wmf
.xExt
= 0;
1759 This
->desc
.u
.wmf
.yExt
= 0;
1761 This
->origWidth
= 0;
1762 This
->origHeight
= 0;
1763 This
->himetricWidth
= MulDiv((INT
)header
->right
- header
->left
, 2540, header
->inch
);
1764 This
->himetricHeight
= MulDiv((INT
)header
->bottom
- header
->top
, 2540, header
->inch
);
1768 /************************************************************************
1769 * BITMAP FORMAT FLAGS -
1770 * Flags that differentiate between different types of bitmaps.
1773 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
1774 #define BITMAP_FORMAT_JPEG 0xd8ff
1775 #define BITMAP_FORMAT_GIF 0x4947
1776 #define BITMAP_FORMAT_PNG 0x5089
1777 #define BITMAP_FORMAT_APM 0xcdd7
1779 /************************************************************************
1780 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1782 * Loads the binary data from the IStream. Starts at current position.
1783 * There appears to be an 2 DWORD header:
1787 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1789 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
,IStream
*pStm
) {
1790 HRESULT hr
= E_FAIL
;
1791 BOOL headerisdata
= FALSE
;
1792 BOOL statfailed
= FALSE
;
1793 ULONG xread
, toread
;
1799 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
1801 TRACE("(%p,%p)\n",This
,pStm
);
1803 /****************************************************************************************
1804 * Part 1: Load the data
1806 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1807 * out whether we do.
1809 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1810 * compound file. This may explain most, if not all, of the cases of "no
1811 * header", and the header validation should take this into account.
1812 * At least in Visual Basic 6, resource streams, valid headers are
1813 * header[0] == "lt\0\0",
1814 * header[1] == length_of_stream.
1816 * Also handle streams where we do not have a working "Stat" method by
1817 * reading all data until the end of the stream.
1819 hr
=IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1821 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr
);
1823 /* we will read at least 8 byte ... just right below */
1824 statstg
.cbSize
.QuadPart
= 8;
1829 headerisdata
= FALSE
;
1831 hr
=IStream_Read(pStm
,header
,8,&xread
);
1832 if (hr
|| xread
!=8) {
1833 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr
,xread
);
1834 return (hr
?hr
:E_FAIL
);
1836 headerread
+= xread
;
1839 if (!memcmp(&(header
[0]),"lt\0\0", 4) && (statfailed
|| (header
[1] + headerread
<= statstg
.cbSize
.QuadPart
))) {
1840 if (toread
!= 0 && toread
!= header
[1])
1841 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1844 if (toread
== 0) break;
1846 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1847 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1848 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1849 (header
[0] == EMR_HEADER
) || /* EMF header */
1850 (header
[1] > statstg
.cbSize
.QuadPart
)|| /* invalid size */
1852 ) {/* Found start of bitmap data */
1853 headerisdata
= TRUE
;
1855 toread
= statstg
.cbSize
.QuadPart
-8;
1859 FIXME("Unknown stream header magic: %08x\n", header
[0]);
1863 } while (!headerisdata
);
1865 if (statfailed
) { /* we don't know the size ... read all we get */
1867 int origsize
= sizeinc
;
1870 TRACE("Reading all data from stream.\n");
1871 xbuf
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, origsize
);
1873 memcpy (xbuf
, header
, 8);
1875 while (xread
< origsize
) {
1876 hr
= IStream_Read(pStm
,xbuf
+xread
,origsize
-xread
,&nread
);
1881 if (!nread
|| hr
) /* done, or error */
1883 if (xread
== origsize
) {
1884 origsize
+= sizeinc
;
1885 sizeinc
= 2*sizeinc
; /* exponential increase */
1886 xbuf
= HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, xbuf
, origsize
);
1890 TRACE("hr in no-stat loader case is %08x\n", hr
);
1891 TRACE("loaded %d bytes.\n", xread
);
1892 This
->datalen
= xread
;
1895 This
->datalen
= toread
+(headerisdata
?8:0);
1896 xbuf
= This
->data
= HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->datalen
);
1898 return E_OUTOFMEMORY
;
1901 memcpy (xbuf
, header
, 8);
1903 while (xread
< This
->datalen
) {
1905 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1910 if (xread
!= This
->datalen
)
1911 ERR("Could only read %d of %d bytes out of stream?\n",xread
,This
->datalen
);
1913 if (This
->datalen
== 0) { /* Marks the "NONE" picture */
1914 This
->desc
.picType
= PICTYPE_NONE
;
1919 /****************************************************************************************
1920 * Part 2: Process the loaded data
1923 magic
= xbuf
[0] + (xbuf
[1]<<8);
1924 This
->loadtime_format
= magic
;
1927 case BITMAP_FORMAT_GIF
: /* GIF */
1928 hr
= OLEPictureImpl_LoadGif(This
, xbuf
, xread
);
1930 case BITMAP_FORMAT_JPEG
: /* JPEG */
1931 hr
= OLEPictureImpl_LoadJpeg(This
, xbuf
, xread
);
1933 case BITMAP_FORMAT_BMP
: /* Bitmap */
1934 hr
= OLEPictureImpl_LoadDIB(This
, xbuf
, xread
);
1936 case BITMAP_FORMAT_PNG
: /* PNG */
1937 hr
= OLEPictureImpl_LoadPNG(This
, xbuf
, xread
);
1939 case BITMAP_FORMAT_APM
: /* APM */
1940 hr
= OLEPictureImpl_LoadAPM(This
, xbuf
, xread
);
1942 case 0x0000: { /* ICON , first word is dwReserved */
1943 hr
= OLEPictureImpl_LoadIcon(This
, xbuf
, xread
);
1950 /* let's see if it's a EMF */
1951 hr
= OLEPictureImpl_LoadEnhMetafile(This
, xbuf
, xread
);
1952 if (hr
== S_OK
) break;
1954 FIXME("Unknown magic %04x, %d read bytes:\n",magic
,xread
);
1956 for (i
=0;i
<xread
+8;i
++) {
1957 if (i
<8) MESSAGE("%02x ",((unsigned char*)header
)[i
]);
1958 else MESSAGE("%02x ",xbuf
[i
-8]);
1959 if (i
% 10 == 9) MESSAGE("\n");
1965 This
->bIsDirty
= FALSE
;
1967 /* FIXME: this notify is not really documented */
1969 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1973 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1977 BITMAPINFO
* pInfoBitmap
;
1978 int iNumPaletteEntries
;
1979 unsigned char * pPixelData
;
1980 BITMAPFILEHEADER
* pFileHeader
;
1981 BITMAPINFO
* pInfoHeader
;
1983 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1984 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1986 /* Find out bitmap size and padded length */
1988 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1989 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1991 /* Fetch bitmap palette & pixel data */
1993 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1994 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1996 /* Calculate the total length required for the BMP data */
1997 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1998 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1999 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
2001 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
2002 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
2004 iNumPaletteEntries
= 0;
2007 sizeof(BITMAPFILEHEADER
) +
2008 sizeof(BITMAPINFOHEADER
) +
2009 iNumPaletteEntries
* sizeof(RGBQUAD
) +
2010 pInfoBitmap
->bmiHeader
.biSizeImage
;
2011 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
2013 /* Fill the BITMAPFILEHEADER */
2014 pFileHeader
= *ppBuffer
;
2015 pFileHeader
->bfType
= BITMAP_FORMAT_BMP
;
2016 pFileHeader
->bfSize
= *pLength
;
2017 pFileHeader
->bfOffBits
=
2018 sizeof(BITMAPFILEHEADER
) +
2019 sizeof(BITMAPINFOHEADER
) +
2020 iNumPaletteEntries
* sizeof(RGBQUAD
);
2022 /* Fill the BITMAPINFOHEADER and the palette data */
2023 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
2024 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
2026 (unsigned char *)(*ppBuffer
) +
2027 sizeof(BITMAPFILEHEADER
) +
2028 sizeof(BITMAPINFOHEADER
) +
2029 iNumPaletteEntries
* sizeof(RGBQUAD
),
2030 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
2033 HeapFree(GetProcessHeap(), 0, pPixelData
);
2034 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
2038 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
2043 *ppBuffer
= NULL
; *pLength
= 0;
2044 if (GetIconInfo(hIcon
, &infoIcon
)) {
2046 BITMAPINFO
* pInfoBitmap
;
2047 unsigned char * pIconData
= NULL
;
2048 unsigned int iDataSize
= 0;
2050 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
2052 /* Find out icon size */
2054 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
2055 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
2057 /* Auxiliary pointers */
2058 CURSORICONFILEDIR
* pIconDir
;
2059 CURSORICONFILEDIRENTRY
* pIconEntry
;
2060 BITMAPINFOHEADER
* pIconBitmapHeader
;
2061 unsigned int iOffsetPalette
;
2062 unsigned int iOffsetColorData
;
2063 unsigned int iOffsetMaskData
;
2065 unsigned int iLengthScanLineColor
;
2066 unsigned int iLengthScanLineMask
;
2067 unsigned int iNumEntriesPalette
;
2069 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
2070 iLengthScanLineColor
= ((pInfoBitmap
->bmiHeader
.biWidth
* pInfoBitmap
->bmiHeader
.biBitCount
+ 31) >> 5) << 2;
2072 FIXME("DEBUG: bitmap size is %d x %d\n",
2073 pInfoBitmap->bmiHeader.biWidth,
2074 pInfoBitmap->bmiHeader.biHeight);
2075 FIXME("DEBUG: bitmap bpp is %d\n",
2076 pInfoBitmap->bmiHeader.biBitCount);
2077 FIXME("DEBUG: bitmap nplanes is %d\n",
2078 pInfoBitmap->bmiHeader.biPlanes);
2079 FIXME("DEBUG: bitmap biSizeImage is %u\n",
2080 pInfoBitmap->bmiHeader.biSizeImage);
2082 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
2083 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
2084 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
2086 /* Fill out the CURSORICONFILEDIR */
2087 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
2088 pIconDir
->idType
= 1;
2089 pIconDir
->idCount
= 1;
2091 /* Fill out the CURSORICONFILEDIRENTRY */
2092 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
2093 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
2094 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
2095 pIconEntry
->bColorCount
=
2096 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
2097 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
2099 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
2100 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
2101 pIconEntry
->dwDIBSize
= 0;
2102 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
2104 /* Fill out the BITMAPINFOHEADER */
2105 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2106 *pIconBitmapHeader
= pInfoBitmap
->bmiHeader
;
2108 /* Find out whether a palette exists for the bitmap */
2109 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
2110 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
2111 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
2112 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
2113 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
2114 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
2115 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
2116 iNumEntriesPalette
= 3;
2117 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
2118 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
2120 iNumEntriesPalette
= 0;
2123 /* Add bitmap size and header size to icon data size. */
2124 iOffsetPalette
= iDataSize
;
2125 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
2126 iOffsetColorData
= iDataSize
;
2127 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
2128 iOffsetMaskData
= iDataSize
;
2129 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
2130 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
2131 pIconBitmapHeader
->biHeight
*= 2;
2132 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
2133 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
2134 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2135 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
2137 /* Get the actual bitmap data from the icon bitmap */
2138 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
2139 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
2140 if (iNumEntriesPalette
> 0) {
2141 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
2142 iNumEntriesPalette
* sizeof(RGBQUAD
));
2145 /* Reset all values so that GetDIBits call succeeds */
2146 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
2147 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
2148 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
2150 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
2151 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
2152 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
2154 printf("ERROR: unable to get bitmap mask (error %u)\n",
2159 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
2160 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
2162 /* Write out everything produced so far to the stream */
2163 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
2167 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
2172 Remarks (from MSDN entry on GetIconInfo):
2174 GetIconInfo creates bitmaps for the hbmMask and hbmColor
2175 members of ICONINFO. The calling application must manage
2176 these bitmaps and delete them when they are no longer
2179 if (hDC
) ReleaseDC(0, hDC
);
2180 DeleteObject(infoIcon
.hbmMask
);
2181 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
2182 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
2184 printf("ERROR: Unable to get icon information (error %u)\n",
2190 static HRESULT WINAPI
OLEPictureImpl_Save(
2191 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
2193 HRESULT hResult
= E_NOTIMPL
;
2195 unsigned int iDataSize
;
2197 int iSerializeResult
= 0;
2198 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
2200 TRACE("%p %p %d\n", This
, pStm
, fClearDirty
);
2202 switch (This
->desc
.picType
) {
2204 if (This
->bIsDirty
|| !This
->data
) {
2205 if (!serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
2206 ERR("(%p,%p,%d), serializeIcon() failed\n", This
, pStm
, fClearDirty
);
2210 HeapFree(GetProcessHeap(), 0, This
->data
);
2211 This
->data
= pIconData
;
2212 This
->datalen
= iDataSize
;
2214 if (This
->loadtime_magic
!= 0xdeadbeef) {
2217 header
[0] = This
->loadtime_magic
;
2218 header
[1] = This
->datalen
;
2219 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2221 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
2225 case PICTYPE_BITMAP
:
2226 if (This
->bIsDirty
) {
2227 switch (This
->keepOrigFormat
? This
->loadtime_format
: BITMAP_FORMAT_BMP
) {
2228 case BITMAP_FORMAT_BMP
:
2229 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
2231 case BITMAP_FORMAT_JPEG
:
2232 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
2234 case BITMAP_FORMAT_GIF
:
2235 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
2237 case BITMAP_FORMAT_PNG
:
2238 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This
,pStm
,fClearDirty
);
2241 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
2244 if (iSerializeResult
) {
2246 if (This->loadtime_magic != 0xdeadbeef) {
2251 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
2252 header
[1] = iDataSize
;
2253 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2255 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
2257 HeapFree(GetProcessHeap(), 0, This
->data
);
2258 This
->data
= pIconData
;
2259 This
->datalen
= iDataSize
;
2264 if (This->loadtime_magic != 0xdeadbeef) {
2269 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
2270 header
[1] = This
->datalen
;
2271 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
2273 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
2277 case PICTYPE_METAFILE
:
2278 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
2280 case PICTYPE_ENHMETAFILE
:
2281 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
2284 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
2287 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
2291 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
2292 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
2294 OLEPictureImpl
*This
= impl_from_IPersistStream(iface
);
2295 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
2300 /************************************************************************
2304 /************************************************************************
2305 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
2307 * See Windows documentation for more details on IUnknown methods.
2309 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
2314 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2316 return IPicture_QueryInterface((IPicture
*)This
, riid
, ppvoid
);
2319 /************************************************************************
2320 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
2322 * See Windows documentation for more details on IUnknown methods.
2324 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
2327 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2329 return IPicture_AddRef((IPicture
*)This
);
2332 /************************************************************************
2333 * OLEPictureImpl_IDispatch_Release (IUnknown)
2335 * See Windows documentation for more details on IUnknown methods.
2337 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
2340 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2342 return IPicture_Release((IPicture
*)This
);
2345 /************************************************************************
2346 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
2348 * See Windows documentation for more details on IDispatch methods.
2350 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
2352 unsigned int* pctinfo
)
2354 TRACE("(%p)\n", pctinfo
);
2361 /************************************************************************
2362 * OLEPictureImpl_GetTypeInfo (IDispatch)
2364 * See Windows documentation for more details on IDispatch methods.
2366 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
2370 ITypeInfo
** ppTInfo
)
2372 static const WCHAR stdole2tlb
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
2376 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo
, (int)lcid
, ppTInfo
);
2381 hres
= LoadTypeLib(stdole2tlb
, &tl
);
2384 ERR("Could not load stdole2.tlb\n");
2388 hres
= ITypeLib_GetTypeInfoOfGuid(tl
, &IID_IPictureDisp
, ppTInfo
);
2390 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres
);
2395 /************************************************************************
2396 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2398 * See Windows documentation for more details on IDispatch methods.
2400 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
2403 LPOLESTR
* rgszNames
,
2411 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface
, debugstr_guid(riid
),
2412 rgszNames
, cNames
, (int)lcid
, rgDispId
);
2416 return E_INVALIDARG
;
2420 /* retrieve type information */
2421 hres
= OLEPictureImpl_GetTypeInfo(iface
, 0, lcid
, &pTInfo
);
2425 ERR("GetTypeInfo failed.\n");
2429 /* convert names to DISPIDs */
2430 hres
= DispGetIDsOfNames (pTInfo
, rgszNames
, cNames
, rgDispId
);
2431 ITypeInfo_Release(pTInfo
);
2437 /************************************************************************
2438 * OLEPictureImpl_Invoke (IDispatch)
2440 * See Windows documentation for more details on IDispatch methods.
2442 static HRESULT WINAPI
OLEPictureImpl_Invoke(
2444 DISPID dispIdMember
,
2448 DISPPARAMS
* pDispParams
,
2449 VARIANT
* pVarResult
,
2450 EXCEPINFO
* pExepInfo
,
2453 OLEPictureImpl
*This
= impl_from_IDispatch(iface
);
2455 /* validate parameters */
2457 if (!IsEqualIID(riid
, &IID_NULL
))
2459 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid
));
2460 return DISP_E_UNKNOWNNAME
;
2465 ERR("null pDispParams not allowed\n");
2466 return DISP_E_PARAMNOTOPTIONAL
;
2469 if (wFlags
& DISPATCH_PROPERTYGET
)
2471 if (pDispParams
->cArgs
!= 0)
2473 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams
->cArgs
);
2474 return DISP_E_BADPARAMCOUNT
;
2478 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2479 return DISP_E_PARAMNOTOPTIONAL
;
2482 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2484 if (pDispParams
->cArgs
!= 1)
2486 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams
->cArgs
);
2487 return DISP_E_BADPARAMCOUNT
;
2491 switch (dispIdMember
)
2493 case DISPID_PICT_HANDLE
:
2494 if (wFlags
& DISPATCH_PROPERTYGET
)
2496 TRACE("DISPID_PICT_HANDLE\n");
2497 V_VT(pVarResult
) = VT_I4
;
2498 return IPicture_get_Handle((IPicture
*)&This
->lpVtbl
, &V_UINT(pVarResult
));
2501 case DISPID_PICT_HPAL
:
2502 if (wFlags
& DISPATCH_PROPERTYGET
)
2504 TRACE("DISPID_PICT_HPAL\n");
2505 V_VT(pVarResult
) = VT_I4
;
2506 return IPicture_get_hPal((IPicture
*)&This
->lpVtbl
, &V_UINT(pVarResult
));
2508 else if (wFlags
& DISPATCH_PROPERTYPUT
)
2512 TRACE("DISPID_PICT_HPAL\n");
2514 VariantInit(&vararg
);
2515 hr
= VariantChangeTypeEx(&vararg
, &pDispParams
->rgvarg
[0], lcid
, 0, VT_I4
);
2519 hr
= IPicture_set_hPal((IPicture
*)&This
->lpVtbl
, V_I4(&vararg
));
2521 VariantClear(&vararg
);
2525 case DISPID_PICT_TYPE
:
2526 if (wFlags
& DISPATCH_PROPERTYGET
)
2528 TRACE("DISPID_PICT_TYPE\n");
2529 V_VT(pVarResult
) = VT_I2
;
2530 return OLEPictureImpl_get_Type((IPicture
*)&This
->lpVtbl
, &V_I2(pVarResult
));
2533 case DISPID_PICT_WIDTH
:
2534 if (wFlags
& DISPATCH_PROPERTYGET
)
2536 TRACE("DISPID_PICT_WIDTH\n");
2537 V_VT(pVarResult
) = VT_I4
;
2538 return IPicture_get_Width((IPicture
*)&This
->lpVtbl
, &V_I4(pVarResult
));
2541 case DISPID_PICT_HEIGHT
:
2542 if (wFlags
& DISPATCH_PROPERTYGET
)
2544 TRACE("DISPID_PICT_HEIGHT\n");
2545 V_VT(pVarResult
) = VT_I4
;
2546 return IPicture_get_Height((IPicture
*)&This
->lpVtbl
, &V_I4(pVarResult
));
2551 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember
, wFlags
);
2552 return DISP_E_MEMBERNOTFOUND
;
2556 static const IPictureVtbl OLEPictureImpl_VTable
=
2558 OLEPictureImpl_QueryInterface
,
2559 OLEPictureImpl_AddRef
,
2560 OLEPictureImpl_Release
,
2561 OLEPictureImpl_get_Handle
,
2562 OLEPictureImpl_get_hPal
,
2563 OLEPictureImpl_get_Type
,
2564 OLEPictureImpl_get_Width
,
2565 OLEPictureImpl_get_Height
,
2566 OLEPictureImpl_Render
,
2567 OLEPictureImpl_set_hPal
,
2568 OLEPictureImpl_get_CurDC
,
2569 OLEPictureImpl_SelectPicture
,
2570 OLEPictureImpl_get_KeepOriginalFormat
,
2571 OLEPictureImpl_put_KeepOriginalFormat
,
2572 OLEPictureImpl_PictureChanged
,
2573 OLEPictureImpl_SaveAsFile
,
2574 OLEPictureImpl_get_Attributes
2577 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
2579 OLEPictureImpl_IDispatch_QueryInterface
,
2580 OLEPictureImpl_IDispatch_AddRef
,
2581 OLEPictureImpl_IDispatch_Release
,
2582 OLEPictureImpl_GetTypeInfoCount
,
2583 OLEPictureImpl_GetTypeInfo
,
2584 OLEPictureImpl_GetIDsOfNames
,
2585 OLEPictureImpl_Invoke
2588 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
2590 OLEPictureImpl_IPersistStream_QueryInterface
,
2591 OLEPictureImpl_IPersistStream_AddRef
,
2592 OLEPictureImpl_IPersistStream_Release
,
2593 OLEPictureImpl_GetClassID
,
2594 OLEPictureImpl_IsDirty
,
2595 OLEPictureImpl_Load
,
2596 OLEPictureImpl_Save
,
2597 OLEPictureImpl_GetSizeMax
2600 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
2602 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
2603 OLEPictureImpl_IConnectionPointContainer_AddRef
,
2604 OLEPictureImpl_IConnectionPointContainer_Release
,
2605 OLEPictureImpl_EnumConnectionPoints
,
2606 OLEPictureImpl_FindConnectionPoint
2609 /***********************************************************************
2610 * OleCreatePictureIndirect (OLEAUT32.419)
2612 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
2613 BOOL fOwn
, LPVOID
*ppvObj
)
2615 OLEPictureImpl
* newPict
= NULL
;
2618 TRACE("(%p,%s,%d,%p)\n", lpPictDesc
, debugstr_guid(riid
), fOwn
, ppvObj
);
2629 * Try to construct a new instance of the class.
2631 newPict
= OLEPictureImpl_Construct(lpPictDesc
, fOwn
);
2633 if (newPict
== NULL
)
2634 return E_OUTOFMEMORY
;
2637 * Make sure it supports the interface required by the caller.
2639 hr
= IPicture_QueryInterface((IPicture
*)newPict
, riid
, ppvObj
);
2642 * Release the reference obtained in the constructor. If
2643 * the QueryInterface was unsuccessful, it will free the class.
2645 IPicture_Release((IPicture
*)newPict
);
2651 /***********************************************************************
2652 * OleLoadPicture (OLEAUT32.418)
2654 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2655 REFIID riid
, LPVOID
*ppvObj
)
2661 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2662 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2664 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2667 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2669 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2670 IPicture_Release(newpic
);
2674 hr
= IPersistStream_Load(ps
,lpstream
);
2675 IPersistStream_Release(ps
);
2678 ERR("IPersistStream_Load failed\n");
2679 IPicture_Release(newpic
);
2683 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2685 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2686 IPicture_Release(newpic
);
2690 /***********************************************************************
2691 * OleLoadPictureEx (OLEAUT32.401)
2693 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2694 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2700 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2701 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2703 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2706 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2708 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2709 IPicture_Release(newpic
);
2713 hr
= IPersistStream_Load(ps
,lpstream
);
2714 IPersistStream_Release(ps
);
2717 ERR("IPersistStream_Load failed\n");
2718 IPicture_Release(newpic
);
2722 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2724 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2725 IPicture_Release(newpic
);
2729 /***********************************************************************
2730 * OleLoadPicturePath (OLEAUT32.424)
2732 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2733 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2736 static const WCHAR file
[] = { 'f','i','l','e',':','/','/',0 };
2740 HGLOBAL hGlobal
= NULL
;
2741 DWORD dwBytesRead
= 0;
2744 IPersistStream
*pStream
;
2747 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2748 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2749 debugstr_guid(riid
), ppvRet
);
2751 if (!ppvRet
) return E_POINTER
;
2753 if (strncmpW(szURLorPath
, file
, 7) == 0) {
2756 hFile
= CreateFileW(szURLorPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2758 if (hFile
== INVALID_HANDLE_VALUE
)
2759 return E_UNEXPECTED
;
2761 dwFileSize
= GetFileSize(hFile
, NULL
);
2762 if (dwFileSize
!= INVALID_FILE_SIZE
)
2764 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2767 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
);
2770 GlobalFree(hGlobal
);
2778 return E_UNEXPECTED
;
2780 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2783 GlobalFree(hGlobal
);
2790 hRes
= CreateBindCtx(0, &pbc
);
2791 if (SUCCEEDED(hRes
))
2793 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2794 if (SUCCEEDED(hRes
))
2796 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2797 IMoniker_Release(pmnk
);
2799 IBindCtx_Release(pbc
);
2805 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2806 &IID_IPicture
, (LPVOID
*)&ipicture
);
2808 IStream_Release(stream
);
2812 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2814 IStream_Release(stream
);
2815 IPicture_Release(ipicture
);
2819 hRes
= IPersistStream_Load(pStream
, stream
);
2820 IPersistStream_Release(pStream
);
2821 IStream_Release(stream
);
2824 IPicture_Release(ipicture
);
2828 hRes
= IPicture_QueryInterface(ipicture
,riid
,ppvRet
);
2830 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2832 IPicture_Release(ipicture
);
2836 /*******************************************************************************
2837 * StdPic ClassFactory
2841 /* IUnknown fields */
2842 const IClassFactoryVtbl
*lpVtbl
;
2844 } IClassFactoryImpl
;
2846 static HRESULT WINAPI
2847 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2848 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2850 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2851 return E_NOINTERFACE
;
2855 SPCF_AddRef(LPCLASSFACTORY iface
) {
2856 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2857 return InterlockedIncrement(&This
->ref
);
2860 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2861 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2862 /* static class, won't be freed */
2863 return InterlockedDecrement(&This
->ref
);
2866 static HRESULT WINAPI
SPCF_CreateInstance(
2867 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2869 /* Creates an uninitialized picture */
2870 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2874 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2875 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2876 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2880 static const IClassFactoryVtbl SPCF_Vtbl
= {
2881 SPCF_QueryInterface
,
2884 SPCF_CreateInstance
,
2887 static IClassFactoryImpl STDPIC_CF
= {&SPCF_Vtbl
, 1 };
2889 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= &STDPIC_CF
; }