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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
53 # ifndef SONAME_LIBUNGIF
54 # define SONAME_LIBUNGIF "libungif.so"
56 # ifndef SONAME_LIBGIF
57 # define SONAME_LIBGIF "libgif.so"
62 #define NONAMELESSUNION
63 #define NONAMELESSSTRUCT
74 #include "wine/debug.h"
76 #include "wine/wingdi16.h"
77 #include "cursoricon.h"
80 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
82 #define UINT8 JPEG_UINT8
83 #define UINT16 JPEG_UINT16
87 #ifndef SONAME_LIBJPEG
88 #define SONAME_LIBJPEG "libjpeg.so"
92 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
94 /*************************************************************************
95 * Declaration of implementation class
98 typedef struct OLEPictureImpl
{
101 * IPicture handles IUnknown
104 IPictureVtbl
*lpvtbl1
;
105 IDispatchVtbl
*lpvtbl2
;
106 IPersistStreamVtbl
*lpvtbl3
;
107 IConnectionPointContainerVtbl
*lpvtbl4
;
109 /* Object referenece count */
112 /* We own the object and must destroy it ourselves */
115 /* Picture description */
118 /* These are the pixel size of a bitmap */
122 /* And these are the size of the picture converted into HIMETRIC units */
123 OLE_XSIZE_HIMETRIC himetricWidth
;
124 OLE_YSIZE_HIMETRIC himetricHeight
;
126 IConnectionPoint
*pCP
;
131 /* Bitmap transparency mask */
138 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
139 unsigned int loadtime_magic
; /* If a length header was found, saves value */
140 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
144 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
146 #define ICOM_THIS_From_IDispatch(impl, name) \
147 impl *This = (impl*)(((char*)name)-sizeof(void*));
148 #define ICOM_THIS_From_IPersistStream(impl, name) \
149 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
150 #define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
151 impl *This = (impl*)(((char*)name)-3*sizeof(void*));
154 * Predeclare VTables. They get initialized at the end.
156 static IPictureVtbl OLEPictureImpl_VTable
;
157 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
158 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
159 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
161 /***********************************************************************
162 * Implementation of the OLEPictureImpl class.
165 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
) {
169 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
170 if(GetObjectA(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
171 ERR("GetObject fails\n");
174 This
->origWidth
= bm
.bmWidth
;
175 This
->origHeight
= bm
.bmHeight
;
176 /* The width and height are stored in HIMETRIC units (0.01 mm),
177 so we take our pixel width divide by pixels per inch and
178 multiply by 25.4 * 100 */
179 /* Should we use GetBitmapDimension if available? */
180 hdcRef
= CreateCompatibleDC(0);
181 This
->himetricWidth
=(bm
.bmWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
182 This
->himetricHeight
=(bm
.bmHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
186 /************************************************************************
187 * OLEPictureImpl_Construct
189 * This method will construct a new instance of the OLEPictureImpl
192 * The caller of this method must release the object when it's
195 static OLEPictureImpl
* OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
)
197 OLEPictureImpl
* newObject
= 0;
200 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
203 * Allocate space for the object.
205 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
211 * Initialize the virtual function table.
213 newObject
->lpvtbl1
= &OLEPictureImpl_VTable
;
214 newObject
->lpvtbl2
= &OLEPictureImpl_IDispatch_VTable
;
215 newObject
->lpvtbl3
= &OLEPictureImpl_IPersistStream_VTable
;
216 newObject
->lpvtbl4
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
218 CreateConnectionPoint((IUnknown
*)newObject
,&IID_IPropertyNotifySink
,&newObject
->pCP
);
221 * Start with one reference count. The caller of this function
222 * must release the interface pointer when it is done.
225 newObject
->hDCCur
= 0;
227 newObject
->fOwn
= fOwn
;
229 /* dunno about original value */
230 newObject
->keepOrigFormat
= TRUE
;
232 newObject
->hbmMask
= NULL
;
233 newObject
->loadtime_magic
= 0xdeadbeef;
234 newObject
->loadtime_format
= 0;
235 newObject
->bIsDirty
= FALSE
;
238 if(pictDesc
->cbSizeofstruct
!= sizeof(PICTDESC
)) {
239 FIXME("struct size = %d\n", pictDesc
->cbSizeofstruct
);
241 memcpy(&newObject
->desc
, pictDesc
, sizeof(PICTDESC
));
244 switch(pictDesc
->picType
) {
246 OLEPictureImpl_SetBitmap(newObject
);
249 case PICTYPE_METAFILE
:
250 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
251 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
252 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
256 /* not sure what to do here */
257 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
261 case PICTYPE_ENHMETAFILE
:
263 FIXME("Unsupported type %d\n", pictDesc
->picType
);
264 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
268 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
271 TRACE("returning %p\n", newObject
);
275 /************************************************************************
276 * OLEPictureImpl_Destroy
278 * This method is called by the Release method when the reference
279 * count goes down to 0. It will free all resources used by
281 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
283 TRACE("(%p)\n", Obj
);
285 if(Obj
->fOwn
) { /* We need to destroy the picture */
286 switch(Obj
->desc
.picType
) {
288 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
290 case PICTYPE_METAFILE
:
291 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
294 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
296 case PICTYPE_ENHMETAFILE
:
297 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
300 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
304 HeapFree(GetProcessHeap(), 0, Obj
->data
);
305 HeapFree(GetProcessHeap(), 0, Obj
);
308 static ULONG WINAPI
OLEPictureImpl_AddRef(IPicture
* iface
);
310 /************************************************************************
311 * OLEPictureImpl_QueryInterface (IUnknown)
313 * See Windows documentation for more details on IUnknown methods.
315 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
320 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
321 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
324 * Perform a sanity check on the parameters.
326 if ( (This
==0) || (ppvObject
==0) )
330 * Initialize the return parameter.
335 * Compare the riid with the interface IDs implemented by this object.
337 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
339 *ppvObject
= (IPicture
*)This
;
341 else if (memcmp(&IID_IPicture
, riid
, sizeof(IID_IPicture
)) == 0)
343 *ppvObject
= (IPicture
*)This
;
345 else if (memcmp(&IID_IDispatch
, riid
, sizeof(IID_IDispatch
)) == 0)
347 *ppvObject
= (IDispatch
*)&(This
->lpvtbl2
);
349 else if (memcmp(&IID_IPictureDisp
, riid
, sizeof(IID_IPictureDisp
)) == 0)
351 *ppvObject
= (IDispatch
*)&(This
->lpvtbl2
);
353 else if (memcmp(&IID_IPersistStream
, riid
, sizeof(IID_IPersistStream
)) == 0)
355 *ppvObject
= (IPersistStream
*)&(This
->lpvtbl3
);
357 else if (memcmp(&IID_IConnectionPointContainer
, riid
, sizeof(IID_IConnectionPointContainer
)) == 0)
359 *ppvObject
= (IConnectionPointContainer
*)&(This
->lpvtbl4
);
362 * Check that we obtained an interface.
366 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
367 return E_NOINTERFACE
;
371 * Query Interface always increases the reference count by one when it is
374 OLEPictureImpl_AddRef((IPicture
*)This
);
378 /***********************************************************************
379 * OLEPicture_SendNotify (internal)
381 * Sends notification messages of changed properties to any interested
384 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
386 IEnumConnections
*pEnum
;
389 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
))
391 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
392 IPropertyNotifySink
*sink
;
394 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
395 IPropertyNotifySink_OnChanged(sink
, dispID
);
396 IPropertyNotifySink_Release(sink
);
397 IUnknown_Release(CD
.pUnk
);
399 IEnumConnections_Release(pEnum
);
403 /************************************************************************
404 * OLEPictureImpl_AddRef (IUnknown)
406 * See Windows documentation for more details on IUnknown methods.
408 static ULONG WINAPI
OLEPictureImpl_AddRef(
411 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
412 ULONG refCount
= InterlockedIncrement(&This
->ref
);
414 TRACE("(%p)->(ref before=%ld)\n", This
, refCount
- 1);
419 /************************************************************************
420 * OLEPictureImpl_Release (IUnknown)
422 * See Windows documentation for more details on IUnknown methods.
424 static ULONG WINAPI
OLEPictureImpl_Release(
427 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
428 ULONG refCount
= InterlockedDecrement(&This
->ref
);
430 TRACE("(%p)->(ref before=%ld)\n", This
, refCount
+ 1);
433 * If the reference count goes down to 0, perform suicide.
435 if (!refCount
) OLEPictureImpl_Destroy(This
);
441 /************************************************************************
442 * OLEPictureImpl_get_Handle
444 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
447 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
448 TRACE("(%p)->(%p)\n", This
, phandle
);
449 switch(This
->desc
.picType
) {
451 *phandle
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
453 case PICTYPE_METAFILE
:
454 *phandle
= (OLE_HANDLE
)This
->desc
.u
.wmf
.hmeta
;
457 *phandle
= (OLE_HANDLE
)This
->desc
.u
.icon
.hicon
;
459 case PICTYPE_ENHMETAFILE
:
460 *phandle
= (OLE_HANDLE
)This
->desc
.u
.emf
.hemf
;
463 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
466 TRACE("returning handle %08x\n", *phandle
);
470 /************************************************************************
471 * OLEPictureImpl_get_hPal
473 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
476 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
477 FIXME("(%p)->(%p): stub\n", This
, phandle
);
481 /************************************************************************
482 * OLEPictureImpl_get_Type
484 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
487 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
488 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
489 *ptype
= This
->desc
.picType
;
493 /************************************************************************
494 * OLEPictureImpl_get_Width
496 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
497 OLE_XSIZE_HIMETRIC
*pwidth
)
499 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
500 TRACE("(%p)->(%p): width is %ld\n", This
, pwidth
, This
->himetricWidth
);
501 *pwidth
= This
->himetricWidth
;
505 /************************************************************************
506 * OLEPictureImpl_get_Height
508 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
509 OLE_YSIZE_HIMETRIC
*pheight
)
511 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
512 TRACE("(%p)->(%p): height is %ld\n", This
, pheight
, This
->himetricHeight
);
513 *pheight
= This
->himetricHeight
;
517 /************************************************************************
518 * OLEPictureImpl_Render
520 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
521 LONG x
, LONG y
, LONG cx
, LONG cy
,
522 OLE_XPOS_HIMETRIC xSrc
,
523 OLE_YPOS_HIMETRIC ySrc
,
524 OLE_XSIZE_HIMETRIC cxSrc
,
525 OLE_YSIZE_HIMETRIC cySrc
,
528 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
529 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
530 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
532 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds
->left
, prcWBounds
->top
,
533 prcWBounds
->right
, prcWBounds
->bottom
);
536 * While the documentation suggests this to be here (or after rendering?)
537 * it does cause an endless recursion in my sample app. -MM 20010804
538 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
541 switch(This
->desc
.picType
) {
547 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
548 NB y-axis gets flipped */
550 hdcBmp
= CreateCompatibleDC(0);
551 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
552 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
553 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
554 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
555 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
557 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
560 HDC hdcMask
= CreateCompatibleDC(0);
561 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
563 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
564 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
565 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
566 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
567 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
569 SetBkColor(hdc
, RGB(255, 255, 255));
570 SetTextColor(hdc
, RGB(0, 0, 0));
571 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
572 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
574 SelectObject(hdcMask
, hOldbm
);
577 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
579 SelectObject(hdcBmp
, hbmpOld
);
584 FIXME("Not quite correct implementation of rendering icons...\n");
585 DrawIcon(hdc
,x
,y
,This
->desc
.u
.icon
.hicon
);
588 case PICTYPE_METAFILE
:
589 case PICTYPE_ENHMETAFILE
:
591 FIXME("type %d not implemented\n", This
->desc
.picType
);
597 /************************************************************************
598 * OLEPictureImpl_set_hPal
600 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
603 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
604 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
605 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
609 /************************************************************************
610 * OLEPictureImpl_get_CurDC
612 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
615 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
616 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
617 if (phdc
) *phdc
= This
->hDCCur
;
621 /************************************************************************
622 * OLEPictureImpl_SelectPicture
624 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
627 OLE_HANDLE
*phbmpOut
)
629 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
630 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
631 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
632 SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
635 *phdcOut
= This
->hDCCur
;
636 This
->hDCCur
= hdcIn
;
638 *phbmpOut
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
641 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
646 /************************************************************************
647 * OLEPictureImpl_get_KeepOriginalFormat
649 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
652 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
653 TRACE("(%p)->(%p)\n", This
, pfKeep
);
656 *pfKeep
= This
->keepOrigFormat
;
660 /************************************************************************
661 * OLEPictureImpl_put_KeepOriginalFormat
663 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
666 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
667 TRACE("(%p)->(%d)\n", This
, keep
);
668 This
->keepOrigFormat
= keep
;
669 /* FIXME: what DISPID notification here? */
673 /************************************************************************
674 * OLEPictureImpl_PictureChanged
676 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
678 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
679 TRACE("(%p)->()\n", This
);
680 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
681 This
->bIsDirty
= TRUE
;
685 /************************************************************************
686 * OLEPictureImpl_SaveAsFile
688 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
693 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
694 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
695 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
698 /************************************************************************
699 * OLEPictureImpl_get_Attributes
701 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
704 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
705 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
707 switch (This
->desc
.picType
) {
708 case PICTYPE_BITMAP
: break; /* not 'truely' scalable, see MSDN. */
709 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
710 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
711 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
717 /************************************************************************
718 * IConnectionPointContainer
721 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
722 IConnectionPointContainer
* iface
,
726 ICOM_THIS_From_IConnectionPointContainer(IPicture
,iface
);
728 return IPicture_QueryInterface(This
,riid
,ppvoid
);
731 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
732 IConnectionPointContainer
* iface
)
734 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
736 return IPicture_AddRef(This
);
739 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
740 IConnectionPointContainer
* iface
)
742 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
744 return IPicture_Release(This
);
747 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
748 IConnectionPointContainer
* iface
,
749 IEnumConnectionPoints
** ppEnum
751 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
753 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
757 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
758 IConnectionPointContainer
* iface
,
760 IConnectionPoint
**ppCP
762 ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl
, iface
);
763 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
767 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
768 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
769 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid
));
772 /************************************************************************
775 /************************************************************************
776 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
778 * See Windows documentation for more details on IUnknown methods.
780 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
781 IPersistStream
* iface
,
785 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
787 return IPicture_QueryInterface(This
, riid
, ppvoid
);
790 /************************************************************************
791 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
793 * See Windows documentation for more details on IUnknown methods.
795 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
796 IPersistStream
* iface
)
798 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
800 return IPicture_AddRef(This
);
803 /************************************************************************
804 * OLEPictureImpl_IPersistStream_Release (IUnknown)
806 * See Windows documentation for more details on IUnknown methods.
808 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
809 IPersistStream
* iface
)
811 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
813 return IPicture_Release(This
);
816 /************************************************************************
817 * OLEPictureImpl_IPersistStream_GetClassID
819 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
820 IPersistStream
* iface
,CLSID
* pClassID
)
822 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
823 FIXME("(%p),stub!\n",This
);
827 /************************************************************************
828 * OLEPictureImpl_IPersistStream_IsDirty
830 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
831 IPersistStream
* iface
)
833 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
834 FIXME("(%p),stub!\n",This
);
838 #ifdef HAVE_JPEGLIB_H
840 static void *libjpeg_handle
;
841 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
842 MAKE_FUNCPTR(jpeg_std_error
);
843 MAKE_FUNCPTR(jpeg_CreateDecompress
);
844 MAKE_FUNCPTR(jpeg_read_header
);
845 MAKE_FUNCPTR(jpeg_start_decompress
);
846 MAKE_FUNCPTR(jpeg_read_scanlines
);
847 MAKE_FUNCPTR(jpeg_finish_decompress
);
848 MAKE_FUNCPTR(jpeg_destroy_decompress
);
851 static void *load_libjpeg(void)
853 if((libjpeg_handle
= wine_dlopen(SONAME_LIBJPEG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
855 #define LOAD_FUNCPTR(f) \
856 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
857 libjpeg_handle = NULL; \
861 LOAD_FUNCPTR(jpeg_std_error
);
862 LOAD_FUNCPTR(jpeg_CreateDecompress
);
863 LOAD_FUNCPTR(jpeg_read_header
);
864 LOAD_FUNCPTR(jpeg_start_decompress
);
865 LOAD_FUNCPTR(jpeg_read_scanlines
);
866 LOAD_FUNCPTR(jpeg_finish_decompress
);
867 LOAD_FUNCPTR(jpeg_destroy_decompress
);
870 return libjpeg_handle
;
873 /* for the jpeg decompressor source manager. */
874 static void _jpeg_init_source(j_decompress_ptr cinfo
) { }
876 static boolean
_jpeg_fill_input_buffer(j_decompress_ptr cinfo
) {
877 ERR("(), should not get here.\n");
881 static void _jpeg_skip_input_data(j_decompress_ptr cinfo
,long num_bytes
) {
882 TRACE("Skipping %ld bytes...\n", num_bytes
);
883 cinfo
->src
->next_input_byte
+= num_bytes
;
884 cinfo
->src
->bytes_in_buffer
-= num_bytes
;
887 static boolean
_jpeg_resync_to_restart(j_decompress_ptr cinfo
, int desired
) {
888 ERR("(desired=%d), should not get here.\n",desired
);
891 static void _jpeg_term_source(j_decompress_ptr cinfo
) { }
892 #endif /* HAVE_JPEGLIB_H */
894 #ifdef HAVE_GIF_LIB_H
896 static void *libungif_handle
;
897 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
898 MAKE_FUNCPTR(DGifOpen
);
899 MAKE_FUNCPTR(DGifSlurp
);
900 MAKE_FUNCPTR(DGifCloseFile
);
909 static void *load_libungif(void)
911 if(((libungif_handle
= wine_dlopen(SONAME_LIBUNGIF
, RTLD_NOW
, NULL
, 0)) != NULL
) ||
912 ((libungif_handle
= wine_dlopen(SONAME_LIBGIF
, RTLD_NOW
, NULL
, 0)) != NULL
)
915 #define LOAD_FUNCPTR(f) \
916 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
917 libungif_handle = NULL; \
921 LOAD_FUNCPTR(DGifOpen
);
922 LOAD_FUNCPTR(DGifSlurp
);
923 LOAD_FUNCPTR(DGifCloseFile
);
926 return libungif_handle
;
929 static int _gif_inputfunc(GifFileType
*gif
, GifByteType
*data
, int len
) {
930 struct gifdata
*gd
= (struct gifdata
*)gif
->UserData
;
932 if (len
+gd
->curoff
> gd
->len
) {
933 FIXME("Trying to read %d bytes, but only %d available.\n",len
, gd
->len
-gd
->curoff
);
934 len
= gd
->len
- gd
->curoff
;
936 memcpy(data
, gd
->data
+gd
->curoff
, len
);
941 #endif /* HAVE_GIF_LIB_H */
943 /************************************************************************
944 * OLEPictureImpl_IPersistStream_Load (IUnknown)
946 * Loads the binary data from the IStream. Starts at current position.
947 * There appears to be an 2 DWORD header:
951 * Currently implemented: BITMAP, ICON, JPEG, GIF
953 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
,IStream
*pStm
) {
960 ICOM_THIS_From_IPersistStream(OLEPictureImpl
, iface
);
962 TRACE("(%p,%p)\n",This
,pStm
);
964 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
967 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
968 * compound file. This may explain most, if not all, of the cases of "no header",
969 * and the header validation should take this into account. At least in Visual Basic 6,
970 * resource streams, valid headers are
971 * header[0] == "lt\0\0",
972 * header[1] == length_of_stream.
974 hr
=IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
976 FIXME("Stat failed with hres %lx\n",hr
);
977 hr
=IStream_Read(pStm
,header
,8,&xread
);
978 if (hr
|| xread
!=8) {
979 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr
,xread
);
982 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
983 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
984 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
985 header
[1] > statstg
.cbSize
.QuadPart
|| (header
[1]==0)) {/* Incorrect header, assume none. */
987 xbuf
= This
->data
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,statstg
.cbSize
.QuadPart
);
988 memcpy(xbuf
,&header
,8);
989 This
->datalen
= statstg
.cbSize
.QuadPart
;
990 while (xread
< This
->datalen
) {
992 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
997 if (xread
!= This
->datalen
)
998 FIXME("Could only read %ld of %d bytes in no-header case?\n",xread
,This
->datalen
);
1001 xbuf
= This
->data
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,header
[1]);
1002 This
->datalen
= header
[1];
1003 while (xread
< header
[1]) {
1005 hr
= IStream_Read(pStm
,xbuf
+xread
,header
[1]-xread
,&nread
);
1010 if (xread
!= header
[1])
1011 FIXME("Could only read %ld of %ld bytes?\n",xread
,header
[1]);
1013 magic
= xbuf
[0] + (xbuf
[1]<<8);
1015 case 0x4947: { /* GIF */
1016 #ifdef HAVE_GIF_LIB_H
1026 int transparent
= -1;
1030 if(!libungif_handle
) {
1031 if(!load_libungif()) {
1032 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF
, SONAME_LIBGIF
);
1040 gif
= pDGifOpen((void*)&gd
, _gif_inputfunc
);
1041 ret
= pDGifSlurp(gif
);
1042 if (ret
== GIF_ERROR
) {
1043 FIXME("Failed reading GIF using libgif.\n");
1046 TRACE("screen height %d, width %d\n", gif
->SWidth
, gif
->SHeight
);
1047 TRACE("color res %d, backgcolor %d\n", gif
->SColorResolution
, gif
->SBackGroundColor
);
1048 TRACE("imgcnt %d\n", gif
->ImageCount
);
1049 if (gif
->ImageCount
<1) {
1050 FIXME("GIF stream does not have images inside?\n");
1053 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1054 gif
->Image
.Width
, gif
->Image
.Height
,
1055 gif
->Image
.Left
, gif
->Image
.Top
,
1056 gif
->Image
.Interlace
1059 padding
= (gif
->SWidth
+3) & ~3;
1060 bmi
= HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER
)+(1<<gif
->SColorResolution
)*sizeof(RGBQUAD
));
1061 bytes
= HeapAlloc(GetProcessHeap(),0,padding
*gif
->SHeight
);
1062 si
= gif
->SavedImages
+0;
1063 gid
= &(si
->ImageDesc
);
1065 if (!cm
) cm
= gif
->SColorMap
;
1067 /* look for the transparent color extension */
1068 for (i
= 0; i
< si
->ExtensionBlockCount
; ++i
) {
1069 eb
= si
->ExtensionBlocks
+ i
;
1070 if (eb
->Function
== 0xF9 && eb
->ByteCount
== 4) {
1071 if ((eb
->Bytes
[0] & 1) == 1) {
1072 transparent
= eb
->Bytes
[3];
1077 for (i
=0;i
<(1<<gif
->SColorResolution
);i
++) {
1078 bmi
->bmiColors
[i
].rgbRed
= cm
->Colors
[i
].Red
;
1079 bmi
->bmiColors
[i
].rgbGreen
= cm
->Colors
[i
].Green
;
1080 bmi
->bmiColors
[i
].rgbBlue
= cm
->Colors
[i
].Blue
;
1081 if (i
== transparent
) {
1082 This
->rgbTrans
= RGB(bmi
->bmiColors
[i
].rgbRed
,
1083 bmi
->bmiColors
[i
].rgbGreen
,
1084 bmi
->bmiColors
[i
].rgbBlue
);
1088 /* Map to in picture coordinates */
1089 for (i
= 0, j
= 0; i
< gid
->Height
; i
++) {
1090 if (gif
->Image
.Interlace
) {
1092 bytes
+ (gid
->Top
+ j
) * padding
+ gid
->Left
,
1093 si
->RasterBits
+ i
* gid
->Width
,
1096 /* Lower bits of interlaced counter encode current interlace */
1097 if (j
& 1) j
+= 2; /* Currently filling odd rows */
1098 else if (j
& 2) j
+= 4; /* Currently filling even rows not multiples of 4 */
1099 else j
+= 8; /* Currently filling every 8th row or 4th row in-between */
1101 if (j
>= gid
->Height
&& i
< gid
->Height
&& (j
& 1) == 0) {
1102 /* End of current interlace, go to next interlace */
1103 if (j
& 2) j
= 1; /* Next iteration fills odd rows */
1104 else if (j
& 4) j
= 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1105 else j
= 4; /* Next iteration fills rows in-between rows mod 6 */
1109 bytes
+ (gid
->Top
+ i
) * padding
+ gid
->Left
,
1110 si
->RasterBits
+ i
* gid
->Width
,
1115 bmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1116 bmi
->bmiHeader
.biWidth
= gif
->SWidth
;
1117 bmi
->bmiHeader
.biHeight
= -gif
->SHeight
;
1118 bmi
->bmiHeader
.biPlanes
= 1;
1119 bmi
->bmiHeader
.biBitCount
= 8;
1120 bmi
->bmiHeader
.biCompression
= BI_RGB
;
1121 bmi
->bmiHeader
.biSizeImage
= padding
*gif
->SHeight
;
1122 bmi
->bmiHeader
.biXPelsPerMeter
= 0;
1123 bmi
->bmiHeader
.biYPelsPerMeter
= 0;
1124 bmi
->bmiHeader
.biClrUsed
= 1 << gif
->SColorResolution
;
1125 bmi
->bmiHeader
.biClrImportant
= 0;
1128 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1137 if (transparent
> -1) {
1138 /* Create the Mask */
1139 HDC hdc
= CreateCompatibleDC(0);
1140 HDC hdcMask
= CreateCompatibleDC(0);
1142 HBITMAP hOldbitmapmask
;
1144 This
->hbmMask
= CreateBitmap(bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, 1, 1, NULL
);
1146 hOldbitmap
= SelectObject(hdc
,This
->desc
.u
.bmp
.hbitmap
);
1147 hOldbitmapmask
= SelectObject(hdcMask
, This
->hbmMask
);
1148 SetBkColor(hdc
, This
->rgbTrans
);
1149 BitBlt(hdcMask
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, hdc
, 0, 0, SRCCOPY
);
1151 /* We no longer need the original bitmap, so we apply the first
1152 transformation with the mask to speed up the rendering */
1153 SetBkColor(hdc
, RGB(0,0,0));
1154 SetTextColor(hdc
, RGB(255,255,255));
1155 BitBlt(hdc
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
,
1156 hdcMask
, 0, 0, SRCAND
);
1158 SelectObject(hdc
, hOldbitmap
);
1159 SelectObject(hdcMask
, hOldbitmapmask
);
1165 This
->desc
.picType
= PICTYPE_BITMAP
;
1166 OLEPictureImpl_SetBitmap(This
);
1167 pDGifCloseFile(gif
);
1168 HeapFree(GetProcessHeap(),0,bytes
);
1171 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1175 case 0xd8ff: { /* JPEG */
1176 #ifdef HAVE_JPEGLIB_H
1177 struct jpeg_decompress_struct jd
;
1178 struct jpeg_error_mgr jerr
;
1181 JSAMPROW samprow
,oldsamprow
;
1182 BITMAPINFOHEADER bmi
;
1185 struct jpeg_source_mgr xjsm
;
1189 if(!libjpeg_handle
) {
1190 if(!load_libjpeg()) {
1191 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG
);
1196 /* This is basically so we can use in-memory data for jpeg decompression.
1197 * We need to have all the functions.
1199 xjsm
.next_input_byte
= xbuf
;
1200 xjsm
.bytes_in_buffer
= xread
;
1201 xjsm
.init_source
= _jpeg_init_source
;
1202 xjsm
.fill_input_buffer
= _jpeg_fill_input_buffer
;
1203 xjsm
.skip_input_data
= _jpeg_skip_input_data
;
1204 xjsm
.resync_to_restart
= _jpeg_resync_to_restart
;
1205 xjsm
.term_source
= _jpeg_term_source
;
1207 jd
.err
= pjpeg_std_error(&jerr
);
1208 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1209 * jpeg_create_decompress(&jd); */
1210 pjpeg_CreateDecompress(&jd
, JPEG_LIB_VERSION
, (size_t) sizeof(struct jpeg_decompress_struct
));
1212 ret
=pjpeg_read_header(&jd
,TRUE
);
1213 jd
.out_color_space
= JCS_RGB
;
1214 pjpeg_start_decompress(&jd
);
1215 if (ret
!= JPEG_HEADER_OK
) {
1216 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret
);
1217 HeapFree(GetProcessHeap(),0,xbuf
);
1221 bits
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1222 (jd
.output_height
+1) * ((jd
.output_width
*jd
.output_components
+ 3) & ~3) );
1223 samprow
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,jd
.output_width
*jd
.output_components
);
1226 oldsamprow
= samprow
;
1227 while ( jd
.output_scanline
<jd
.output_height
) {
1228 x
= pjpeg_read_scanlines(&jd
,&samprow
,1);
1230 FIXME("failed to read current scanline?\n");
1233 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1234 for(i
=0;i
<jd
.output_width
;i
++,samprow
+=jd
.output_components
) {
1235 *(bits
++) = *(samprow
+2);
1236 *(bits
++) = *(samprow
+1);
1237 *(bits
++) = *(samprow
);
1239 bits
= (LPBYTE
)(((UINT_PTR
)bits
+ 3) & ~3);
1240 samprow
= oldsamprow
;
1244 bmi
.biSize
= sizeof(bmi
);
1245 bmi
.biWidth
= jd
.output_width
;
1246 bmi
.biHeight
= -jd
.output_height
;
1248 bmi
.biBitCount
= jd
.output_components
<<3;
1249 bmi
.biCompression
= BI_RGB
;
1250 bmi
.biSizeImage
= jd
.output_height
*jd
.output_width
*jd
.output_components
;
1251 bmi
.biXPelsPerMeter
= 0;
1252 bmi
.biYPelsPerMeter
= 0;
1254 bmi
.biClrImportant
= 0;
1256 HeapFree(GetProcessHeap(),0,samprow
);
1257 pjpeg_finish_decompress(&jd
);
1258 pjpeg_destroy_decompress(&jd
);
1260 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1269 This
->desc
.picType
= PICTYPE_BITMAP
;
1270 OLEPictureImpl_SetBitmap(This
);
1272 HeapFree(GetProcessHeap(),0,bits
);
1274 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1279 case 0x4d42: { /* Bitmap */
1280 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1281 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1284 /* Does not matter whether this is a coreheader or not, we only use
1285 * components which are in both
1288 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1292 xbuf
+bfh
->bfOffBits
,
1297 This
->desc
.picType
= PICTYPE_BITMAP
;
1298 OLEPictureImpl_SetBitmap(This
);
1302 case 0x0000: { /* ICON , first word is dwReserved */
1304 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1309 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1310 FIXME("icon.idType=%d\n",cifd->idType);
1311 FIXME("icon.idCount=%d\n",cifd->idCount);
1313 for (i=0;i<cifd->idCount;i++) {
1314 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1315 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1316 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1317 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1318 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1319 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1320 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1321 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1325 /* If we have more than one icon, try to find the best.
1326 * this currently means '32 pixel wide'.
1328 if (cifd
->idCount
!=1) {
1329 for (i
=0;i
<cifd
->idCount
;i
++) {
1330 if (cifd
->idEntries
[i
].bWidth
== 32)
1333 if (i
==cifd
->idCount
) i
=0;
1336 hicon
= CreateIconFromResourceEx(
1337 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1338 cifd
->idEntries
[i
].dwDIBSize
,
1341 cifd
->idEntries
[i
].bWidth
,
1342 cifd
->idEntries
[i
].bHeight
,
1346 FIXME("CreateIcon failed.\n");
1349 This
->desc
.picType
= PICTYPE_ICON
;
1350 This
->desc
.u
.icon
.hicon
= hicon
;
1351 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1352 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1353 hdcRef
= CreateCompatibleDC(0);
1354 This
->himetricWidth
=(cifd
->idEntries
[i
].bWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
1355 This
->himetricHeight
=(cifd
->idEntries
[i
].bHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
1364 FIXME("Unknown magic %04x, %ld read bytes:\n",magic
,xread
);
1366 for (i
=0;i
<xread
+8;i
++) {
1367 if (i
<8) MESSAGE("%02x ",((unsigned char*)&header
)[i
]);
1368 else MESSAGE("%02x ",xbuf
[i
-8]);
1369 if (i
% 10 == 9) MESSAGE("\n");
1375 This
->bIsDirty
= FALSE
;
1377 /* FIXME: this notify is not really documented */
1379 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1383 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
);
1384 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
);
1385 static HRESULT WINAPI
OLEPictureImpl_Save(
1386 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1388 HRESULT hResult
= E_NOTIMPL
;
1390 unsigned int iDataSize
;
1392 int iSerializeResult
= 0;
1394 ICOM_THIS_From_IPersistStream(OLEPictureImpl
, iface
);
1396 switch (This
->desc
.picType
) {
1398 if (This
->bIsDirty
) {
1399 if (serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1400 if (This
->loadtime_magic
!= 0xdeadbeef) {
1403 header
[0] = This
->loadtime_magic
;
1404 header
[1] = iDataSize
;
1405 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1407 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
1409 HeapFree(GetProcessHeap(), 0, This
->data
);
1410 This
->data
= pIconData
;
1411 This
->datalen
= iDataSize
;
1414 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This
,pStm
,fClearDirty
);
1418 if (This
->loadtime_magic
!= 0xdeadbeef) {
1421 header
[0] = This
->loadtime_magic
;
1422 header
[1] = This
->datalen
;
1423 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1425 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1429 case PICTYPE_BITMAP
:
1430 if (This
->bIsDirty
) {
1431 switch (This
->keepOrigFormat
? This
->loadtime_format
: 0x4d42) {
1433 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1436 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1439 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1442 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1445 if (iSerializeResult
) {
1447 if (This->loadtime_magic != 0xdeadbeef) {
1452 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1453 header
[1] = iDataSize
;
1454 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1456 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
1458 HeapFree(GetProcessHeap(), 0, This
->data
);
1459 This
->data
= pIconData
;
1460 This
->datalen
= iDataSize
;
1465 if (This->loadtime_magic != 0xdeadbeef) {
1470 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1471 header
[1] = This
->datalen
;
1472 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1474 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1478 case PICTYPE_METAFILE
:
1479 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1481 case PICTYPE_ENHMETAFILE
:
1482 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1485 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1488 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1492 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1496 BITMAPINFO
* pInfoBitmap
;
1497 int iNumPaletteEntries
;
1498 unsigned char * pPixelData
;
1499 BITMAPFILEHEADER
* pFileHeader
;
1500 BITMAPINFO
* pInfoHeader
;
1502 pInfoBitmap
= (BITMAPINFO
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1503 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1505 /* Find out bitmap size and padded length */
1507 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1508 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1510 /* Fetch bitmap palette & pixel data */
1512 pPixelData
= (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1513 pInfoBitmap
->bmiHeader
.biSizeImage
);
1514 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1516 /* Calculate the total length required for the BMP data */
1517 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1518 else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1519 else iNumPaletteEntries
= 0;
1521 sizeof(BITMAPFILEHEADER
) +
1522 sizeof(BITMAPINFOHEADER
) +
1523 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1524 pInfoBitmap
->bmiHeader
.biSizeImage
;
1525 *ppBuffer
= (void *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1527 /* Fill the BITMAPFILEHEADER */
1528 pFileHeader
= (BITMAPFILEHEADER
*)(*ppBuffer
);
1529 pFileHeader
->bfType
= 0x4d42;
1530 pFileHeader
->bfSize
= *pLength
;
1531 pFileHeader
->bfOffBits
=
1532 sizeof(BITMAPFILEHEADER
) +
1533 sizeof(BITMAPINFOHEADER
) +
1534 iNumPaletteEntries
* sizeof(RGBQUAD
);
1536 /* Fill the BITMAPINFOHEADER and the palette data */
1537 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1538 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1540 (unsigned char *)(*ppBuffer
) +
1541 sizeof(BITMAPFILEHEADER
) +
1542 sizeof(BITMAPINFOHEADER
) +
1543 iNumPaletteEntries
* sizeof(RGBQUAD
),
1544 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1547 HeapFree(GetProcessHeap(), 0, pPixelData
);
1548 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1552 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1557 *ppBuffer
= NULL
; *pLength
= 0;
1558 if (GetIconInfo(hIcon
, &infoIcon
)) {
1560 BITMAPINFO
* pInfoBitmap
;
1561 unsigned char * pIconData
= NULL
;
1562 unsigned int iDataSize
= 0;
1564 pInfoBitmap
= (BITMAPINFO
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1566 /* Find out icon size */
1568 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1569 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1571 /* Auxiliary pointers */
1572 CURSORICONFILEDIR
* pIconDir
;
1573 CURSORICONFILEDIRENTRY
* pIconEntry
;
1574 BITMAPINFOHEADER
* pIconBitmapHeader
;
1575 unsigned int iOffsetPalette
;
1576 unsigned int iOffsetColorData
;
1577 unsigned int iOffsetMaskData
;
1579 unsigned int iLengthScanLineColor
;
1580 unsigned int iLengthScanLineMask
;
1581 unsigned int iNumEntriesPalette
;
1583 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1584 iLengthScanLineColor
= ((pInfoBitmap
->bmiHeader
.biWidth
* pInfoBitmap
->bmiHeader
.biBitCount
+ 31) >> 5) << 2;
1586 FIXME("DEBUG: bitmap size is %d x %d\n",
1587 pInfoBitmap->bmiHeader.biWidth,
1588 pInfoBitmap->bmiHeader.biHeight);
1589 FIXME("DEBUG: bitmap bpp is %d\n",
1590 pInfoBitmap->bmiHeader.biBitCount);
1591 FIXME("DEBUG: bitmap nplanes is %d\n",
1592 pInfoBitmap->bmiHeader.biPlanes);
1593 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1594 pInfoBitmap->bmiHeader.biSizeImage);
1596 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1597 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1598 pIconData
= (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1600 /* Fill out the CURSORICONFILEDIR */
1601 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1602 pIconDir
->idType
= 1;
1603 pIconDir
->idCount
= 1;
1605 /* Fill out the CURSORICONFILEDIRENTRY */
1606 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1607 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1608 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1609 pIconEntry
->bColorCount
=
1610 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1611 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1613 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1614 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1615 pIconEntry
->dwDIBSize
= 0;
1616 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1618 /* Fill out the BITMAPINFOHEADER */
1619 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1620 memcpy(pIconBitmapHeader
, &pInfoBitmap
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
1622 /* Find out whether a palette exists for the bitmap */
1623 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1624 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1625 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1626 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1627 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1628 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1629 iNumEntriesPalette
= 3;
1630 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1631 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1633 iNumEntriesPalette
= 0;
1636 /* Add bitmap size and header size to icon data size. */
1637 iOffsetPalette
= iDataSize
;
1638 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1639 iOffsetColorData
= iDataSize
;
1640 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1641 iOffsetMaskData
= iDataSize
;
1642 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1643 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1644 pIconBitmapHeader
->biHeight
*= 2;
1645 pIconData
= (unsigned char *)HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1646 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1647 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1648 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1650 /* Get the actual bitmap data from the icon bitmap */
1651 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1652 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1653 if (iNumEntriesPalette
> 0) {
1654 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1655 iNumEntriesPalette
* sizeof(RGBQUAD
));
1658 /* Reset all values so that GetDIBits call succeeds */
1659 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1660 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1661 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1663 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1664 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1665 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1667 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1672 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1673 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1675 /* Write out everything produced so far to the stream */
1676 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1680 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1685 Remarks (from MSDN entry on GetIconInfo):
1687 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1688 members of ICONINFO. The calling application must manage
1689 these bitmaps and delete them when they are no longer
1692 if (hDC
) ReleaseDC(0, hDC
);
1693 DeleteObject(infoIcon
.hbmMask
);
1694 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1695 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1697 printf("ERROR: Unable to get icon information (error %lu)\n",
1703 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1704 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1706 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
1707 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1711 /************************************************************************
1714 /************************************************************************
1715 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1717 * See Windows documentation for more details on IUnknown methods.
1719 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1724 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1726 return IPicture_QueryInterface(This
, riid
, ppvoid
);
1729 /************************************************************************
1730 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1732 * See Windows documentation for more details on IUnknown methods.
1734 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1737 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1739 return IPicture_AddRef(This
);
1742 /************************************************************************
1743 * OLEPictureImpl_IDispatch_Release (IUnknown)
1745 * See Windows documentation for more details on IUnknown methods.
1747 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1750 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1752 return IPicture_Release(This
);
1755 /************************************************************************
1756 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1758 * See Windows documentation for more details on IDispatch methods.
1760 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1762 unsigned int* pctinfo
)
1769 /************************************************************************
1770 * OLEPictureImpl_GetTypeInfo (IDispatch)
1772 * See Windows documentation for more details on IDispatch methods.
1774 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1778 ITypeInfo
** ppTInfo
)
1785 /************************************************************************
1786 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1788 * See Windows documentation for more details on IDispatch methods.
1790 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1793 LPOLESTR
* rgszNames
,
1803 /************************************************************************
1804 * OLEPictureImpl_Invoke (IDispatch)
1806 * See Windows documentation for more details on IDispatch methods.
1808 static HRESULT WINAPI
OLEPictureImpl_Invoke(
1810 DISPID dispIdMember
,
1814 DISPPARAMS
* pDispParams
,
1815 VARIANT
* pVarResult
,
1816 EXCEPINFO
* pExepInfo
,
1819 FIXME("(dispid: %ld):Stub\n",dispIdMember
);
1821 VariantInit(pVarResult
);
1822 V_VT(pVarResult
) = VT_BOOL
;
1823 V_UNION(pVarResult
,boolVal
) = FALSE
;
1828 static IPictureVtbl OLEPictureImpl_VTable
=
1830 OLEPictureImpl_QueryInterface
,
1831 OLEPictureImpl_AddRef
,
1832 OLEPictureImpl_Release
,
1833 OLEPictureImpl_get_Handle
,
1834 OLEPictureImpl_get_hPal
,
1835 OLEPictureImpl_get_Type
,
1836 OLEPictureImpl_get_Width
,
1837 OLEPictureImpl_get_Height
,
1838 OLEPictureImpl_Render
,
1839 OLEPictureImpl_set_hPal
,
1840 OLEPictureImpl_get_CurDC
,
1841 OLEPictureImpl_SelectPicture
,
1842 OLEPictureImpl_get_KeepOriginalFormat
,
1843 OLEPictureImpl_put_KeepOriginalFormat
,
1844 OLEPictureImpl_PictureChanged
,
1845 OLEPictureImpl_SaveAsFile
,
1846 OLEPictureImpl_get_Attributes
1849 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
1851 OLEPictureImpl_IDispatch_QueryInterface
,
1852 OLEPictureImpl_IDispatch_AddRef
,
1853 OLEPictureImpl_IDispatch_Release
,
1854 OLEPictureImpl_GetTypeInfoCount
,
1855 OLEPictureImpl_GetTypeInfo
,
1856 OLEPictureImpl_GetIDsOfNames
,
1857 OLEPictureImpl_Invoke
1860 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
1862 OLEPictureImpl_IPersistStream_QueryInterface
,
1863 OLEPictureImpl_IPersistStream_AddRef
,
1864 OLEPictureImpl_IPersistStream_Release
,
1865 OLEPictureImpl_GetClassID
,
1866 OLEPictureImpl_IsDirty
,
1867 OLEPictureImpl_Load
,
1868 OLEPictureImpl_Save
,
1869 OLEPictureImpl_GetSizeMax
1872 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
1874 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
1875 OLEPictureImpl_IConnectionPointContainer_AddRef
,
1876 OLEPictureImpl_IConnectionPointContainer_Release
,
1877 OLEPictureImpl_EnumConnectionPoints
,
1878 OLEPictureImpl_FindConnectionPoint
1881 /***********************************************************************
1882 * OleCreatePictureIndirect (OLEAUT32.419)
1884 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
1885 BOOL fOwn
, LPVOID
*ppvObj
)
1887 OLEPictureImpl
* newPict
= NULL
;
1890 TRACE("(%p,%p,%d,%p)\n", lpPictDesc
, riid
, fOwn
, ppvObj
);
1901 * Try to construct a new instance of the class.
1903 newPict
= OLEPictureImpl_Construct(lpPictDesc
, fOwn
);
1905 if (newPict
== NULL
)
1906 return E_OUTOFMEMORY
;
1909 * Make sure it supports the interface required by the caller.
1911 hr
= IPicture_QueryInterface((IPicture
*)newPict
, riid
, ppvObj
);
1914 * Release the reference obtained in the constructor. If
1915 * the QueryInterface was unsuccessful, it will free the class.
1917 IPicture_Release((IPicture
*)newPict
);
1923 /***********************************************************************
1924 * OleLoadPicture (OLEAUT32.418)
1926 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
1927 REFIID riid
, LPVOID
*ppvObj
)
1933 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
1934 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
1936 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
1939 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
1941 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1942 IPicture_Release(newpic
);
1946 IPersistStream_Load(ps
,lpstream
);
1947 IPersistStream_Release(ps
);
1948 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
1950 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
1951 IPicture_Release(newpic
);
1955 /***********************************************************************
1956 * OleLoadPictureEx (OLEAUT32.401)
1958 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
1959 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
1965 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
1966 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
1968 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
1971 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
1973 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1974 IPicture_Release(newpic
);
1978 IPersistStream_Load(ps
,lpstream
);
1979 IPersistStream_Release(ps
);
1980 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
1982 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
1983 IPicture_Release(newpic
);
1987 /*******************************************************************************
1988 * StdPic ClassFactory
1992 /* IUnknown fields */
1993 IClassFactoryVtbl
*lpVtbl
;
1995 } IClassFactoryImpl
;
1997 static HRESULT WINAPI
1998 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
1999 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2001 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2002 return E_NOINTERFACE
;
2006 SPCF_AddRef(LPCLASSFACTORY iface
) {
2007 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2008 return InterlockedIncrement(&This
->ref
);
2011 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2012 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2013 /* static class, won't be freed */
2014 return InterlockedDecrement(&This
->ref
);
2017 static HRESULT WINAPI
SPCF_CreateInstance(
2018 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2022 FIXME("(%p,%p,%s,%p), creating stdpic with PICTYPE_NONE.\n",iface
,pOuter
,debugstr_guid(riid
),ppobj
);
2023 pd
.cbSizeofstruct
= sizeof(pd
);
2024 pd
.picType
= PICTYPE_NONE
;
2025 return OleCreatePictureIndirect(&pd
,riid
,TRUE
,ppobj
);
2029 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2030 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2031 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2035 static IClassFactoryVtbl SPCF_Vtbl
= {
2036 SPCF_QueryInterface
,
2039 SPCF_CreateInstance
,
2042 static IClassFactoryImpl STDPIC_CF
= {&SPCF_Vtbl
, 1 };
2044 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= (LPVOID
)&STDPIC_CF
; }