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
75 #include "wine/debug.h"
76 #include "wine/unicode.h"
78 #include "wine/wingdi16.h"
79 #include "cursoricon.h"
82 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
84 #define UINT8 JPEG_UINT8
85 #define UINT16 JPEG_UINT16
89 #ifndef SONAME_LIBJPEG
90 #define SONAME_LIBJPEG "libjpeg.so"
94 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
96 /*************************************************************************
97 * Declaration of implementation class
100 typedef struct OLEPictureImpl
{
103 * IPicture handles IUnknown
106 IPictureVtbl
*lpvtbl1
;
107 IDispatchVtbl
*lpvtbl2
;
108 IPersistStreamVtbl
*lpvtbl3
;
109 IConnectionPointContainerVtbl
*lpvtbl4
;
111 /* Object reference count */
114 /* We own the object and must destroy it ourselves */
117 /* Picture description */
120 /* These are the pixel size of a bitmap */
124 /* And these are the size of the picture converted into HIMETRIC units */
125 OLE_XSIZE_HIMETRIC himetricWidth
;
126 OLE_YSIZE_HIMETRIC himetricHeight
;
128 IConnectionPoint
*pCP
;
133 /* Bitmap transparency mask */
141 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
142 unsigned int loadtime_magic
; /* If a length header was found, saves value */
143 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
147 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
149 #define ICOM_THIS_From_IDispatch(impl, name) \
150 impl *This = (impl*)(((char*)name)-sizeof(void*));
151 #define ICOM_THIS_From_IPersistStream(impl, name) \
152 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
153 #define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
154 impl *This = (impl*)(((char*)name)-3*sizeof(void*));
157 * Predeclare VTables. They get initialized at the end.
159 static IPictureVtbl OLEPictureImpl_VTable
;
160 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
161 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
162 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
164 /***********************************************************************
165 * Implementation of the OLEPictureImpl class.
168 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
) {
172 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
173 if(GetObjectA(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
174 ERR("GetObject fails\n");
177 This
->origWidth
= bm
.bmWidth
;
178 This
->origHeight
= bm
.bmHeight
;
179 /* The width and height are stored in HIMETRIC units (0.01 mm),
180 so we take our pixel width divide by pixels per inch and
181 multiply by 25.4 * 100 */
182 /* Should we use GetBitmapDimension if available? */
183 hdcRef
= CreateCompatibleDC(0);
184 This
->himetricWidth
=(bm
.bmWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
185 This
->himetricHeight
=(bm
.bmHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
189 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
193 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
194 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
198 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
199 if(GetObjectA(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
200 ERR("GetObject fails on icon bitmap\n");
204 This
->origWidth
= bm
.bmWidth
;
205 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
206 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
208 This
->himetricWidth
= (This
->origWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
209 This
->himetricHeight
= (This
->origHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
210 ReleaseDC(0, hdcRef
);
212 DeleteObject(infoIcon
.hbmMask
);
213 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
215 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
219 /************************************************************************
220 * OLEPictureImpl_Construct
222 * This method will construct a new instance of the OLEPictureImpl
225 * The caller of this method must release the object when it's
228 static OLEPictureImpl
* OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
)
230 OLEPictureImpl
* newObject
= 0;
233 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
236 * Allocate space for the object.
238 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
244 * Initialize the virtual function table.
246 newObject
->lpvtbl1
= &OLEPictureImpl_VTable
;
247 newObject
->lpvtbl2
= &OLEPictureImpl_IDispatch_VTable
;
248 newObject
->lpvtbl3
= &OLEPictureImpl_IPersistStream_VTable
;
249 newObject
->lpvtbl4
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
251 CreateConnectionPoint((IUnknown
*)newObject
,&IID_IPropertyNotifySink
,&newObject
->pCP
);
254 * Start with one reference count. The caller of this function
255 * must release the interface pointer when it is done.
258 newObject
->hDCCur
= 0;
260 newObject
->fOwn
= fOwn
;
262 /* dunno about original value */
263 newObject
->keepOrigFormat
= TRUE
;
265 newObject
->hbmMask
= NULL
;
266 newObject
->hbmXor
= NULL
;
267 newObject
->loadtime_magic
= 0xdeadbeef;
268 newObject
->loadtime_format
= 0;
269 newObject
->bIsDirty
= FALSE
;
272 if(pictDesc
->cbSizeofstruct
!= sizeof(PICTDESC
)) {
273 FIXME("struct size = %d\n", pictDesc
->cbSizeofstruct
);
275 memcpy(&newObject
->desc
, pictDesc
, sizeof(PICTDESC
));
278 switch(pictDesc
->picType
) {
280 OLEPictureImpl_SetBitmap(newObject
);
283 case PICTYPE_METAFILE
:
284 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
285 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
286 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
290 /* not sure what to do here */
291 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
295 OLEPictureImpl_SetIcon(newObject
);
297 case PICTYPE_ENHMETAFILE
:
299 FIXME("Unsupported type %d\n", pictDesc
->picType
);
300 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
304 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
307 TRACE("returning %p\n", newObject
);
311 /************************************************************************
312 * OLEPictureImpl_Destroy
314 * This method is called by the Release method when the reference
315 * count goes down to 0. It will free all resources used by
317 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
319 TRACE("(%p)\n", Obj
);
321 if(Obj
->fOwn
) { /* We need to destroy the picture */
322 switch(Obj
->desc
.picType
) {
324 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
325 if (Obj
->hbmMask
!= NULL
) DeleteObject(Obj
->hbmMask
);
326 if (Obj
->hbmXor
!= NULL
) DeleteObject(Obj
->hbmXor
);
328 case PICTYPE_METAFILE
:
329 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
332 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
334 case PICTYPE_ENHMETAFILE
:
335 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
338 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
342 HeapFree(GetProcessHeap(), 0, Obj
->data
);
343 HeapFree(GetProcessHeap(), 0, Obj
);
346 static ULONG WINAPI
OLEPictureImpl_AddRef(IPicture
* iface
);
348 /************************************************************************
349 * OLEPictureImpl_QueryInterface (IUnknown)
351 * See Windows documentation for more details on IUnknown methods.
353 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
358 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
359 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
362 * Perform a sanity check on the parameters.
364 if ( (This
==0) || (ppvObject
==0) )
368 * Initialize the return parameter.
373 * Compare the riid with the interface IDs implemented by this object.
375 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
377 *ppvObject
= (IPicture
*)This
;
379 else if (memcmp(&IID_IPicture
, riid
, sizeof(IID_IPicture
)) == 0)
381 *ppvObject
= (IPicture
*)This
;
383 else if (memcmp(&IID_IDispatch
, riid
, sizeof(IID_IDispatch
)) == 0)
385 *ppvObject
= (IDispatch
*)&(This
->lpvtbl2
);
387 else if (memcmp(&IID_IPictureDisp
, riid
, sizeof(IID_IPictureDisp
)) == 0)
389 *ppvObject
= (IDispatch
*)&(This
->lpvtbl2
);
391 else if (memcmp(&IID_IPersistStream
, riid
, sizeof(IID_IPersistStream
)) == 0)
393 *ppvObject
= (IPersistStream
*)&(This
->lpvtbl3
);
395 else if (memcmp(&IID_IConnectionPointContainer
, riid
, sizeof(IID_IConnectionPointContainer
)) == 0)
397 *ppvObject
= (IConnectionPointContainer
*)&(This
->lpvtbl4
);
400 * Check that we obtained an interface.
404 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
405 return E_NOINTERFACE
;
409 * Query Interface always increases the reference count by one when it is
412 OLEPictureImpl_AddRef((IPicture
*)This
);
416 /***********************************************************************
417 * OLEPicture_SendNotify (internal)
419 * Sends notification messages of changed properties to any interested
422 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
424 IEnumConnections
*pEnum
;
427 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
))
429 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
430 IPropertyNotifySink
*sink
;
432 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
433 IPropertyNotifySink_OnChanged(sink
, dispID
);
434 IPropertyNotifySink_Release(sink
);
435 IUnknown_Release(CD
.pUnk
);
437 IEnumConnections_Release(pEnum
);
441 /************************************************************************
442 * OLEPictureImpl_AddRef (IUnknown)
444 * See Windows documentation for more details on IUnknown methods.
446 static ULONG WINAPI
OLEPictureImpl_AddRef(
449 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
450 ULONG refCount
= InterlockedIncrement(&This
->ref
);
452 TRACE("(%p)->(ref before=%ld)\n", This
, refCount
- 1);
457 /************************************************************************
458 * OLEPictureImpl_Release (IUnknown)
460 * See Windows documentation for more details on IUnknown methods.
462 static ULONG WINAPI
OLEPictureImpl_Release(
465 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
466 ULONG refCount
= InterlockedDecrement(&This
->ref
);
468 TRACE("(%p)->(ref before=%ld)\n", This
, refCount
+ 1);
471 * If the reference count goes down to 0, perform suicide.
473 if (!refCount
) OLEPictureImpl_Destroy(This
);
479 /************************************************************************
480 * OLEPictureImpl_get_Handle
482 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
485 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
486 TRACE("(%p)->(%p)\n", This
, phandle
);
487 switch(This
->desc
.picType
) {
489 *phandle
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
491 case PICTYPE_METAFILE
:
492 *phandle
= (OLE_HANDLE
)This
->desc
.u
.wmf
.hmeta
;
495 *phandle
= (OLE_HANDLE
)This
->desc
.u
.icon
.hicon
;
497 case PICTYPE_ENHMETAFILE
:
498 *phandle
= (OLE_HANDLE
)This
->desc
.u
.emf
.hemf
;
501 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
504 TRACE("returning handle %08x\n", *phandle
);
508 /************************************************************************
509 * OLEPictureImpl_get_hPal
511 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
514 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
515 FIXME("(%p)->(%p): stub\n", This
, phandle
);
519 /************************************************************************
520 * OLEPictureImpl_get_Type
522 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
525 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
526 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
527 *ptype
= This
->desc
.picType
;
531 /************************************************************************
532 * OLEPictureImpl_get_Width
534 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
535 OLE_XSIZE_HIMETRIC
*pwidth
)
537 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
538 TRACE("(%p)->(%p): width is %ld\n", This
, pwidth
, This
->himetricWidth
);
539 *pwidth
= This
->himetricWidth
;
543 /************************************************************************
544 * OLEPictureImpl_get_Height
546 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
547 OLE_YSIZE_HIMETRIC
*pheight
)
549 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
550 TRACE("(%p)->(%p): height is %ld\n", This
, pheight
, This
->himetricHeight
);
551 *pheight
= This
->himetricHeight
;
555 /************************************************************************
556 * OLEPictureImpl_Render
558 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
559 LONG x
, LONG y
, LONG cx
, LONG cy
,
560 OLE_XPOS_HIMETRIC xSrc
,
561 OLE_YPOS_HIMETRIC ySrc
,
562 OLE_XSIZE_HIMETRIC cxSrc
,
563 OLE_YSIZE_HIMETRIC cySrc
,
566 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
567 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
568 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
570 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds
->left
, prcWBounds
->top
,
571 prcWBounds
->right
, prcWBounds
->bottom
);
574 * While the documentation suggests this to be here (or after rendering?)
575 * it does cause an endless recursion in my sample app. -MM 20010804
576 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
579 switch(This
->desc
.picType
) {
585 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
586 NB y-axis gets flipped */
588 hdcBmp
= CreateCompatibleDC(0);
589 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
590 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
591 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
592 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
593 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
596 HDC hdcMask
= CreateCompatibleDC(0);
597 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
599 hbmpOld
= SelectObject(hdcBmp
, This
->hbmXor
);
601 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
602 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
603 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
604 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
605 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
607 SetBkColor(hdc
, RGB(255, 255, 255));
608 SetTextColor(hdc
, RGB(0, 0, 0));
609 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
610 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
612 SelectObject(hdcMask
, hOldbm
);
615 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
616 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
619 SelectObject(hdcBmp
, hbmpOld
);
624 FIXME("Not quite correct implementation of rendering icons...\n");
625 DrawIcon(hdc
,x
,y
,This
->desc
.u
.icon
.hicon
);
628 case PICTYPE_METAFILE
:
629 case PICTYPE_ENHMETAFILE
:
631 FIXME("type %d not implemented\n", This
->desc
.picType
);
637 /************************************************************************
638 * OLEPictureImpl_set_hPal
640 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
643 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
644 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
645 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
649 /************************************************************************
650 * OLEPictureImpl_get_CurDC
652 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
655 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
656 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
657 if (phdc
) *phdc
= This
->hDCCur
;
661 /************************************************************************
662 * OLEPictureImpl_SelectPicture
664 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
667 OLE_HANDLE
*phbmpOut
)
669 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
670 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
671 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
672 SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
675 *phdcOut
= This
->hDCCur
;
676 This
->hDCCur
= hdcIn
;
678 *phbmpOut
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
681 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
686 /************************************************************************
687 * OLEPictureImpl_get_KeepOriginalFormat
689 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
692 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
693 TRACE("(%p)->(%p)\n", This
, pfKeep
);
696 *pfKeep
= This
->keepOrigFormat
;
700 /************************************************************************
701 * OLEPictureImpl_put_KeepOriginalFormat
703 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
706 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
707 TRACE("(%p)->(%d)\n", This
, keep
);
708 This
->keepOrigFormat
= keep
;
709 /* FIXME: what DISPID notification here? */
713 /************************************************************************
714 * OLEPictureImpl_PictureChanged
716 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
718 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
719 TRACE("(%p)->()\n", This
);
720 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
721 This
->bIsDirty
= TRUE
;
725 /************************************************************************
726 * OLEPictureImpl_SaveAsFile
728 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
733 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
734 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
735 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
738 /************************************************************************
739 * OLEPictureImpl_get_Attributes
741 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
744 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
745 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
747 switch (This
->desc
.picType
) {
748 case PICTYPE_BITMAP
: if (This
->hbmMask
) *pdwAttr
= PICTURE_TRANSPARENT
; break; /* not 'truly' scalable, see MSDN. */
749 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
750 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
751 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
757 /************************************************************************
758 * IConnectionPointContainer
761 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
762 IConnectionPointContainer
* iface
,
766 ICOM_THIS_From_IConnectionPointContainer(IPicture
,iface
);
768 return IPicture_QueryInterface(This
,riid
,ppvoid
);
771 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
772 IConnectionPointContainer
* iface
)
774 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
776 return IPicture_AddRef(This
);
779 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
780 IConnectionPointContainer
* iface
)
782 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
784 return IPicture_Release(This
);
787 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
788 IConnectionPointContainer
* iface
,
789 IEnumConnectionPoints
** ppEnum
791 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
793 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
797 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
798 IConnectionPointContainer
* iface
,
800 IConnectionPoint
**ppCP
802 ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl
, iface
);
803 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
807 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
808 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
809 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid
));
812 /************************************************************************
815 /************************************************************************
816 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
818 * See Windows documentation for more details on IUnknown methods.
820 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
821 IPersistStream
* iface
,
825 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
827 return IPicture_QueryInterface(This
, riid
, ppvoid
);
830 /************************************************************************
831 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
833 * See Windows documentation for more details on IUnknown methods.
835 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
836 IPersistStream
* iface
)
838 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
840 return IPicture_AddRef(This
);
843 /************************************************************************
844 * OLEPictureImpl_IPersistStream_Release (IUnknown)
846 * See Windows documentation for more details on IUnknown methods.
848 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
849 IPersistStream
* iface
)
851 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
853 return IPicture_Release(This
);
856 /************************************************************************
857 * OLEPictureImpl_IPersistStream_GetClassID
859 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
860 IPersistStream
* iface
,CLSID
* pClassID
)
862 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
863 FIXME("(%p),stub!\n",This
);
867 /************************************************************************
868 * OLEPictureImpl_IPersistStream_IsDirty
870 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
871 IPersistStream
* iface
)
873 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
874 FIXME("(%p),stub!\n",This
);
878 #ifdef HAVE_JPEGLIB_H
880 static void *libjpeg_handle
;
881 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
882 MAKE_FUNCPTR(jpeg_std_error
);
883 MAKE_FUNCPTR(jpeg_CreateDecompress
);
884 MAKE_FUNCPTR(jpeg_read_header
);
885 MAKE_FUNCPTR(jpeg_start_decompress
);
886 MAKE_FUNCPTR(jpeg_read_scanlines
);
887 MAKE_FUNCPTR(jpeg_finish_decompress
);
888 MAKE_FUNCPTR(jpeg_destroy_decompress
);
891 static void *load_libjpeg(void)
893 if((libjpeg_handle
= wine_dlopen(SONAME_LIBJPEG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
895 #define LOAD_FUNCPTR(f) \
896 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
897 libjpeg_handle = NULL; \
901 LOAD_FUNCPTR(jpeg_std_error
);
902 LOAD_FUNCPTR(jpeg_CreateDecompress
);
903 LOAD_FUNCPTR(jpeg_read_header
);
904 LOAD_FUNCPTR(jpeg_start_decompress
);
905 LOAD_FUNCPTR(jpeg_read_scanlines
);
906 LOAD_FUNCPTR(jpeg_finish_decompress
);
907 LOAD_FUNCPTR(jpeg_destroy_decompress
);
910 return libjpeg_handle
;
913 /* for the jpeg decompressor source manager. */
914 static void _jpeg_init_source(j_decompress_ptr cinfo
) { }
916 static boolean
_jpeg_fill_input_buffer(j_decompress_ptr cinfo
) {
917 ERR("(), should not get here.\n");
921 static void _jpeg_skip_input_data(j_decompress_ptr cinfo
,long num_bytes
) {
922 TRACE("Skipping %ld bytes...\n", num_bytes
);
923 cinfo
->src
->next_input_byte
+= num_bytes
;
924 cinfo
->src
->bytes_in_buffer
-= num_bytes
;
927 static boolean
_jpeg_resync_to_restart(j_decompress_ptr cinfo
, int desired
) {
928 ERR("(desired=%d), should not get here.\n",desired
);
931 static void _jpeg_term_source(j_decompress_ptr cinfo
) { }
932 #endif /* HAVE_JPEGLIB_H */
934 #ifdef HAVE_GIF_LIB_H
936 static void *libungif_handle
;
937 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
938 MAKE_FUNCPTR(DGifOpen
);
939 MAKE_FUNCPTR(DGifSlurp
);
940 MAKE_FUNCPTR(DGifCloseFile
);
949 static void *load_libungif(void)
951 if(((libungif_handle
= wine_dlopen(SONAME_LIBUNGIF
, RTLD_NOW
, NULL
, 0)) != NULL
) ||
952 ((libungif_handle
= wine_dlopen(SONAME_LIBGIF
, RTLD_NOW
, NULL
, 0)) != NULL
)
955 #define LOAD_FUNCPTR(f) \
956 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
957 libungif_handle = NULL; \
961 LOAD_FUNCPTR(DGifOpen
);
962 LOAD_FUNCPTR(DGifSlurp
);
963 LOAD_FUNCPTR(DGifCloseFile
);
966 return libungif_handle
;
969 static int _gif_inputfunc(GifFileType
*gif
, GifByteType
*data
, int len
) {
970 struct gifdata
*gd
= (struct gifdata
*)gif
->UserData
;
972 if (len
+gd
->curoff
> gd
->len
) {
973 FIXME("Trying to read %d bytes, but only %d available.\n",len
, gd
->len
-gd
->curoff
);
974 len
= gd
->len
- gd
->curoff
;
976 memcpy(data
, gd
->data
+gd
->curoff
, len
);
981 #endif /* HAVE_GIF_LIB_H */
983 /************************************************************************
984 * OLEPictureImpl_IPersistStream_Load (IUnknown)
986 * Loads the binary data from the IStream. Starts at current position.
987 * There appears to be an 2 DWORD header:
991 * Currently implemented: BITMAP, ICON, JPEG, GIF
993 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
,IStream
*pStm
) {
1000 ICOM_THIS_From_IPersistStream(OLEPictureImpl
, iface
);
1002 TRACE("(%p,%p)\n",This
,pStm
);
1004 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1005 * out whether we do.
1007 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1008 * compound file. This may explain most, if not all, of the cases of "no header",
1009 * and the header validation should take this into account. At least in Visual Basic 6,
1010 * resource streams, valid headers are
1011 * header[0] == "lt\0\0",
1012 * header[1] == length_of_stream.
1014 hr
=IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1016 FIXME("Stat failed with hres %lx\n",hr
);
1017 hr
=IStream_Read(pStm
,header
,8,&xread
);
1018 if (hr
|| xread
!=8) {
1019 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr
,xread
);
1022 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1023 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1024 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1025 header
[1] > statstg
.cbSize
.QuadPart
|| (header
[1]==0)) {/* Incorrect header, assume none. */
1027 xbuf
= This
->data
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,statstg
.cbSize
.QuadPart
);
1028 memcpy(xbuf
,&header
,8);
1029 This
->datalen
= statstg
.cbSize
.QuadPart
;
1030 while (xread
< This
->datalen
) {
1032 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1037 if (xread
!= This
->datalen
)
1038 FIXME("Could only read %ld of %d bytes in no-header case?\n",xread
,This
->datalen
);
1041 xbuf
= This
->data
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,header
[1]);
1042 This
->datalen
= header
[1];
1043 while (xread
< header
[1]) {
1045 hr
= IStream_Read(pStm
,xbuf
+xread
,header
[1]-xread
,&nread
);
1050 if (xread
!= header
[1])
1051 FIXME("Could only read %ld of %ld bytes?\n",xread
,header
[1]);
1053 magic
= xbuf
[0] + (xbuf
[1]<<8);
1055 case 0x4947: { /* GIF */
1056 #ifdef HAVE_GIF_LIB_H
1066 int transparent
= -1;
1070 if(!libungif_handle
) {
1071 if(!load_libungif()) {
1072 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF
, SONAME_LIBGIF
);
1080 gif
= pDGifOpen((void*)&gd
, _gif_inputfunc
);
1081 ret
= pDGifSlurp(gif
);
1082 if (ret
== GIF_ERROR
) {
1083 FIXME("Failed reading GIF using libgif.\n");
1086 TRACE("screen height %d, width %d\n", gif
->SWidth
, gif
->SHeight
);
1087 TRACE("color res %d, backgcolor %d\n", gif
->SColorResolution
, gif
->SBackGroundColor
);
1088 TRACE("imgcnt %d\n", gif
->ImageCount
);
1089 if (gif
->ImageCount
<1) {
1090 FIXME("GIF stream does not have images inside?\n");
1093 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1094 gif
->Image
.Width
, gif
->Image
.Height
,
1095 gif
->Image
.Left
, gif
->Image
.Top
,
1096 gif
->Image
.Interlace
1099 padding
= (gif
->SWidth
+3) & ~3;
1100 bmi
= HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER
)+(1<<gif
->SColorResolution
)*sizeof(RGBQUAD
));
1101 bytes
= HeapAlloc(GetProcessHeap(),0,padding
*gif
->SHeight
);
1102 si
= gif
->SavedImages
+0;
1103 gid
= &(si
->ImageDesc
);
1105 if (!cm
) cm
= gif
->SColorMap
;
1107 /* look for the transparent color extension */
1108 for (i
= 0; i
< si
->ExtensionBlockCount
; ++i
) {
1109 eb
= si
->ExtensionBlocks
+ i
;
1110 if (eb
->Function
== 0xF9 && eb
->ByteCount
== 4) {
1111 if ((eb
->Bytes
[0] & 1) == 1) {
1112 transparent
= (unsigned char)eb
->Bytes
[3];
1117 for (i
=0;i
<(1<<gif
->SColorResolution
);i
++) {
1118 bmi
->bmiColors
[i
].rgbRed
= cm
->Colors
[i
].Red
;
1119 bmi
->bmiColors
[i
].rgbGreen
= cm
->Colors
[i
].Green
;
1120 bmi
->bmiColors
[i
].rgbBlue
= cm
->Colors
[i
].Blue
;
1121 if (i
== transparent
) {
1122 This
->rgbTrans
= RGB(bmi
->bmiColors
[i
].rgbRed
,
1123 bmi
->bmiColors
[i
].rgbGreen
,
1124 bmi
->bmiColors
[i
].rgbBlue
);
1128 /* Map to in picture coordinates */
1129 for (i
= 0, j
= 0; i
< gid
->Height
; i
++) {
1130 if (gif
->Image
.Interlace
) {
1132 bytes
+ (gid
->Top
+ j
) * padding
+ gid
->Left
,
1133 si
->RasterBits
+ i
* gid
->Width
,
1136 /* Lower bits of interlaced counter encode current interlace */
1137 if (j
& 1) j
+= 2; /* Currently filling odd rows */
1138 else if (j
& 2) j
+= 4; /* Currently filling even rows not multiples of 4 */
1139 else j
+= 8; /* Currently filling every 8th row or 4th row in-between */
1141 if (j
>= gid
->Height
&& i
< gid
->Height
&& (j
& 1) == 0) {
1142 /* End of current interlace, go to next interlace */
1143 if (j
& 2) j
= 1; /* Next iteration fills odd rows */
1144 else if (j
& 4) j
= 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1145 else j
= 4; /* Next iteration fills rows in-between rows mod 6 */
1149 bytes
+ (gid
->Top
+ i
) * padding
+ gid
->Left
,
1150 si
->RasterBits
+ i
* gid
->Width
,
1155 bmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1156 bmi
->bmiHeader
.biWidth
= gif
->SWidth
;
1157 bmi
->bmiHeader
.biHeight
= -gif
->SHeight
;
1158 bmi
->bmiHeader
.biPlanes
= 1;
1159 bmi
->bmiHeader
.biBitCount
= 8;
1160 bmi
->bmiHeader
.biCompression
= BI_RGB
;
1161 bmi
->bmiHeader
.biSizeImage
= padding
*gif
->SHeight
;
1162 bmi
->bmiHeader
.biXPelsPerMeter
= 0;
1163 bmi
->bmiHeader
.biYPelsPerMeter
= 0;
1164 bmi
->bmiHeader
.biClrUsed
= 1 << gif
->SColorResolution
;
1165 bmi
->bmiHeader
.biClrImportant
= 0;
1168 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1177 if (transparent
> -1) {
1178 /* Create the Mask */
1179 HDC hdc
= CreateCompatibleDC(0);
1180 HDC hdcMask
= CreateCompatibleDC(0);
1182 HBITMAP hOldbitmapmask
;
1184 unsigned int monopadding
= (((unsigned)(gif
->SWidth
+ 31)) >> 5) << 2;
1187 This
->hbmXor
= CreateDIBitmap(
1196 bmi
->bmiColors
[0].rgbRed
= 0;
1197 bmi
->bmiColors
[0].rgbGreen
= 0;
1198 bmi
->bmiColors
[0].rgbBlue
= 0;
1199 bmi
->bmiColors
[1].rgbRed
= 255;
1200 bmi
->bmiColors
[1].rgbGreen
= 255;
1201 bmi
->bmiColors
[1].rgbBlue
= 255;
1203 bmi
->bmiHeader
.biBitCount
= 1;
1204 bmi
->bmiHeader
.biSizeImage
= monopadding
*gif
->SHeight
;
1205 bmi
->bmiHeader
.biClrUsed
= 2;
1207 for (i
= 0; i
< gif
->SHeight
; i
++) {
1208 unsigned char * colorPointer
= bytes
+ padding
* i
;
1209 unsigned char * monoPointer
= bytes
+ monopadding
* i
;
1210 for (j
= 0; j
< gif
->SWidth
; j
++) {
1211 unsigned char pixel
= colorPointer
[j
];
1212 if ((j
& 7) == 0) monoPointer
[j
>> 3] = 0;
1213 if (pixel
== (transparent
& 0x000000FFU
)) monoPointer
[j
>> 3] |= 1 << (7 - (j
& 7));
1217 hTempMask
= CreateDIBitmap(
1227 bmi
->bmiHeader
.biHeight
= -bmi
->bmiHeader
.biHeight
;
1228 This
->hbmMask
= CreateBitmap(bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, 1, 1, NULL
);
1229 hOldbitmap
= SelectObject(hdc
, hTempMask
);
1230 hOldbitmapmask
= SelectObject(hdcMask
, This
->hbmMask
);
1232 SetBkColor(hdc
, RGB(255, 255, 255));
1233 BitBlt(hdcMask
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, hdc
, 0, 0, SRCCOPY
);
1235 /* We no longer need the original bitmap, so we apply the first
1236 transformation with the mask to speed up the rendering */
1237 SelectObject(hdc
, This
->hbmXor
);
1238 SetBkColor(hdc
, RGB(0,0,0));
1239 SetTextColor(hdc
, RGB(255,255,255));
1240 BitBlt(hdc
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
,
1241 hdcMask
, 0, 0, SRCAND
);
1243 SelectObject(hdc
, hOldbitmap
);
1244 SelectObject(hdcMask
, hOldbitmapmask
);
1247 DeleteObject(hTempMask
);
1251 This
->desc
.picType
= PICTYPE_BITMAP
;
1252 OLEPictureImpl_SetBitmap(This
);
1253 pDGifCloseFile(gif
);
1254 HeapFree(GetProcessHeap(),0,bytes
);
1257 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1261 case 0xd8ff: { /* JPEG */
1262 #ifdef HAVE_JPEGLIB_H
1263 struct jpeg_decompress_struct jd
;
1264 struct jpeg_error_mgr jerr
;
1267 JSAMPROW samprow
,oldsamprow
;
1268 BITMAPINFOHEADER bmi
;
1271 struct jpeg_source_mgr xjsm
;
1275 if(!libjpeg_handle
) {
1276 if(!load_libjpeg()) {
1277 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG
);
1282 /* This is basically so we can use in-memory data for jpeg decompression.
1283 * We need to have all the functions.
1285 xjsm
.next_input_byte
= xbuf
;
1286 xjsm
.bytes_in_buffer
= xread
;
1287 xjsm
.init_source
= _jpeg_init_source
;
1288 xjsm
.fill_input_buffer
= _jpeg_fill_input_buffer
;
1289 xjsm
.skip_input_data
= _jpeg_skip_input_data
;
1290 xjsm
.resync_to_restart
= _jpeg_resync_to_restart
;
1291 xjsm
.term_source
= _jpeg_term_source
;
1293 jd
.err
= pjpeg_std_error(&jerr
);
1294 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1295 * jpeg_create_decompress(&jd); */
1296 pjpeg_CreateDecompress(&jd
, JPEG_LIB_VERSION
, (size_t) sizeof(struct jpeg_decompress_struct
));
1298 ret
=pjpeg_read_header(&jd
,TRUE
);
1299 jd
.out_color_space
= JCS_RGB
;
1300 pjpeg_start_decompress(&jd
);
1301 if (ret
!= JPEG_HEADER_OK
) {
1302 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret
);
1303 HeapFree(GetProcessHeap(),0,xbuf
);
1307 bits
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1308 (jd
.output_height
+1) * ((jd
.output_width
*jd
.output_components
+ 3) & ~3) );
1309 samprow
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,jd
.output_width
*jd
.output_components
);
1312 oldsamprow
= samprow
;
1313 while ( jd
.output_scanline
<jd
.output_height
) {
1314 x
= pjpeg_read_scanlines(&jd
,&samprow
,1);
1316 FIXME("failed to read current scanline?\n");
1319 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1320 for(i
=0;i
<jd
.output_width
;i
++,samprow
+=jd
.output_components
) {
1321 *(bits
++) = *(samprow
+2);
1322 *(bits
++) = *(samprow
+1);
1323 *(bits
++) = *(samprow
);
1325 bits
= (LPBYTE
)(((UINT_PTR
)bits
+ 3) & ~3);
1326 samprow
= oldsamprow
;
1330 bmi
.biSize
= sizeof(bmi
);
1331 bmi
.biWidth
= jd
.output_width
;
1332 bmi
.biHeight
= -jd
.output_height
;
1334 bmi
.biBitCount
= jd
.output_components
<<3;
1335 bmi
.biCompression
= BI_RGB
;
1336 bmi
.biSizeImage
= jd
.output_height
*jd
.output_width
*jd
.output_components
;
1337 bmi
.biXPelsPerMeter
= 0;
1338 bmi
.biYPelsPerMeter
= 0;
1340 bmi
.biClrImportant
= 0;
1342 HeapFree(GetProcessHeap(),0,samprow
);
1343 pjpeg_finish_decompress(&jd
);
1344 pjpeg_destroy_decompress(&jd
);
1346 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1355 This
->desc
.picType
= PICTYPE_BITMAP
;
1356 OLEPictureImpl_SetBitmap(This
);
1358 HeapFree(GetProcessHeap(),0,bits
);
1360 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1365 case 0x4d42: { /* Bitmap */
1366 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1367 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1370 /* Does not matter whether this is a coreheader or not, we only use
1371 * components which are in both
1374 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1378 xbuf
+bfh
->bfOffBits
,
1383 This
->desc
.picType
= PICTYPE_BITMAP
;
1384 OLEPictureImpl_SetBitmap(This
);
1388 case 0x0000: { /* ICON , first word is dwReserved */
1390 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1395 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1396 FIXME("icon.idType=%d\n",cifd->idType);
1397 FIXME("icon.idCount=%d\n",cifd->idCount);
1399 for (i=0;i<cifd->idCount;i++) {
1400 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1401 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1402 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1403 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1404 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1405 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1406 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1407 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1411 /* If we have more than one icon, try to find the best.
1412 * this currently means '32 pixel wide'.
1414 if (cifd
->idCount
!=1) {
1415 for (i
=0;i
<cifd
->idCount
;i
++) {
1416 if (cifd
->idEntries
[i
].bWidth
== 32)
1419 if (i
==cifd
->idCount
) i
=0;
1422 hicon
= CreateIconFromResourceEx(
1423 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1424 cifd
->idEntries
[i
].dwDIBSize
,
1427 cifd
->idEntries
[i
].bWidth
,
1428 cifd
->idEntries
[i
].bHeight
,
1432 FIXME("CreateIcon failed.\n");
1435 This
->desc
.picType
= PICTYPE_ICON
;
1436 This
->desc
.u
.icon
.hicon
= hicon
;
1437 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1438 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1439 hdcRef
= CreateCompatibleDC(0);
1440 This
->himetricWidth
=(cifd
->idEntries
[i
].bWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
1441 This
->himetricHeight
=(cifd
->idEntries
[i
].bHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
1450 FIXME("Unknown magic %04x, %ld read bytes:\n",magic
,xread
);
1452 for (i
=0;i
<xread
+8;i
++) {
1453 if (i
<8) MESSAGE("%02x ",((unsigned char*)&header
)[i
]);
1454 else MESSAGE("%02x ",xbuf
[i
-8]);
1455 if (i
% 10 == 9) MESSAGE("\n");
1461 This
->bIsDirty
= FALSE
;
1463 /* FIXME: this notify is not really documented */
1465 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1469 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
);
1470 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
);
1471 static HRESULT WINAPI
OLEPictureImpl_Save(
1472 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1474 HRESULT hResult
= E_NOTIMPL
;
1476 unsigned int iDataSize
;
1478 int iSerializeResult
= 0;
1480 ICOM_THIS_From_IPersistStream(OLEPictureImpl
, iface
);
1482 switch (This
->desc
.picType
) {
1484 if (This
->bIsDirty
) {
1485 if (serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1486 if (This
->loadtime_magic
!= 0xdeadbeef) {
1489 header
[0] = This
->loadtime_magic
;
1490 header
[1] = iDataSize
;
1491 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1493 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
1495 HeapFree(GetProcessHeap(), 0, This
->data
);
1496 This
->data
= pIconData
;
1497 This
->datalen
= iDataSize
;
1500 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This
,pStm
,fClearDirty
);
1504 if (This
->loadtime_magic
!= 0xdeadbeef) {
1507 header
[0] = This
->loadtime_magic
;
1508 header
[1] = This
->datalen
;
1509 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1511 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1515 case PICTYPE_BITMAP
:
1516 if (This
->bIsDirty
) {
1517 switch (This
->keepOrigFormat
? This
->loadtime_format
: 0x4d42) {
1519 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1522 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1525 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1528 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1531 if (iSerializeResult
) {
1533 if (This->loadtime_magic != 0xdeadbeef) {
1538 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1539 header
[1] = iDataSize
;
1540 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1542 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
1544 HeapFree(GetProcessHeap(), 0, This
->data
);
1545 This
->data
= pIconData
;
1546 This
->datalen
= iDataSize
;
1551 if (This->loadtime_magic != 0xdeadbeef) {
1556 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1557 header
[1] = This
->datalen
;
1558 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1560 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1564 case PICTYPE_METAFILE
:
1565 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1567 case PICTYPE_ENHMETAFILE
:
1568 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1571 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1574 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1578 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1582 BITMAPINFO
* pInfoBitmap
;
1583 int iNumPaletteEntries
;
1584 unsigned char * pPixelData
;
1585 BITMAPFILEHEADER
* pFileHeader
;
1586 BITMAPINFO
* pInfoHeader
;
1588 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1589 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1591 /* Find out bitmap size and padded length */
1593 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1594 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1596 /* Fetch bitmap palette & pixel data */
1598 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1599 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1601 /* Calculate the total length required for the BMP data */
1602 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1603 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1604 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1606 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1607 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1609 iNumPaletteEntries
= 0;
1612 sizeof(BITMAPFILEHEADER
) +
1613 sizeof(BITMAPINFOHEADER
) +
1614 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1615 pInfoBitmap
->bmiHeader
.biSizeImage
;
1616 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1618 /* Fill the BITMAPFILEHEADER */
1619 pFileHeader
= (BITMAPFILEHEADER
*)(*ppBuffer
);
1620 pFileHeader
->bfType
= 0x4d42;
1621 pFileHeader
->bfSize
= *pLength
;
1622 pFileHeader
->bfOffBits
=
1623 sizeof(BITMAPFILEHEADER
) +
1624 sizeof(BITMAPINFOHEADER
) +
1625 iNumPaletteEntries
* sizeof(RGBQUAD
);
1627 /* Fill the BITMAPINFOHEADER and the palette data */
1628 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1629 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1631 (unsigned char *)(*ppBuffer
) +
1632 sizeof(BITMAPFILEHEADER
) +
1633 sizeof(BITMAPINFOHEADER
) +
1634 iNumPaletteEntries
* sizeof(RGBQUAD
),
1635 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1638 HeapFree(GetProcessHeap(), 0, pPixelData
);
1639 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1643 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1648 *ppBuffer
= NULL
; *pLength
= 0;
1649 if (GetIconInfo(hIcon
, &infoIcon
)) {
1651 BITMAPINFO
* pInfoBitmap
;
1652 unsigned char * pIconData
= NULL
;
1653 unsigned int iDataSize
= 0;
1655 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1657 /* Find out icon size */
1659 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1660 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1662 /* Auxiliary pointers */
1663 CURSORICONFILEDIR
* pIconDir
;
1664 CURSORICONFILEDIRENTRY
* pIconEntry
;
1665 BITMAPINFOHEADER
* pIconBitmapHeader
;
1666 unsigned int iOffsetPalette
;
1667 unsigned int iOffsetColorData
;
1668 unsigned int iOffsetMaskData
;
1670 unsigned int iLengthScanLineColor
;
1671 unsigned int iLengthScanLineMask
;
1672 unsigned int iNumEntriesPalette
;
1674 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1675 iLengthScanLineColor
= ((pInfoBitmap
->bmiHeader
.biWidth
* pInfoBitmap
->bmiHeader
.biBitCount
+ 31) >> 5) << 2;
1677 FIXME("DEBUG: bitmap size is %d x %d\n",
1678 pInfoBitmap->bmiHeader.biWidth,
1679 pInfoBitmap->bmiHeader.biHeight);
1680 FIXME("DEBUG: bitmap bpp is %d\n",
1681 pInfoBitmap->bmiHeader.biBitCount);
1682 FIXME("DEBUG: bitmap nplanes is %d\n",
1683 pInfoBitmap->bmiHeader.biPlanes);
1684 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1685 pInfoBitmap->bmiHeader.biSizeImage);
1687 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1688 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1689 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1691 /* Fill out the CURSORICONFILEDIR */
1692 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1693 pIconDir
->idType
= 1;
1694 pIconDir
->idCount
= 1;
1696 /* Fill out the CURSORICONFILEDIRENTRY */
1697 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1698 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1699 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1700 pIconEntry
->bColorCount
=
1701 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1702 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1704 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1705 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1706 pIconEntry
->dwDIBSize
= 0;
1707 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1709 /* Fill out the BITMAPINFOHEADER */
1710 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1711 memcpy(pIconBitmapHeader
, &pInfoBitmap
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
1713 /* Find out whether a palette exists for the bitmap */
1714 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1715 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1716 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1717 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1718 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1719 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1720 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1721 iNumEntriesPalette
= 3;
1722 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1723 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1725 iNumEntriesPalette
= 0;
1728 /* Add bitmap size and header size to icon data size. */
1729 iOffsetPalette
= iDataSize
;
1730 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1731 iOffsetColorData
= iDataSize
;
1732 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1733 iOffsetMaskData
= iDataSize
;
1734 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1735 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1736 pIconBitmapHeader
->biHeight
*= 2;
1737 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1738 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1739 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1740 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1742 /* Get the actual bitmap data from the icon bitmap */
1743 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1744 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1745 if (iNumEntriesPalette
> 0) {
1746 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1747 iNumEntriesPalette
* sizeof(RGBQUAD
));
1750 /* Reset all values so that GetDIBits call succeeds */
1751 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1752 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1753 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1755 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1756 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1757 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1759 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1764 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1765 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1767 /* Write out everything produced so far to the stream */
1768 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1772 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1777 Remarks (from MSDN entry on GetIconInfo):
1779 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1780 members of ICONINFO. The calling application must manage
1781 these bitmaps and delete them when they are no longer
1784 if (hDC
) ReleaseDC(0, hDC
);
1785 DeleteObject(infoIcon
.hbmMask
);
1786 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1787 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1789 printf("ERROR: Unable to get icon information (error %lu)\n",
1795 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1796 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1798 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
1799 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1803 /************************************************************************
1806 /************************************************************************
1807 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1809 * See Windows documentation for more details on IUnknown methods.
1811 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1816 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1818 return IPicture_QueryInterface(This
, riid
, ppvoid
);
1821 /************************************************************************
1822 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1824 * See Windows documentation for more details on IUnknown methods.
1826 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1829 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1831 return IPicture_AddRef(This
);
1834 /************************************************************************
1835 * OLEPictureImpl_IDispatch_Release (IUnknown)
1837 * See Windows documentation for more details on IUnknown methods.
1839 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1842 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1844 return IPicture_Release(This
);
1847 /************************************************************************
1848 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1850 * See Windows documentation for more details on IDispatch methods.
1852 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1854 unsigned int* pctinfo
)
1861 /************************************************************************
1862 * OLEPictureImpl_GetTypeInfo (IDispatch)
1864 * See Windows documentation for more details on IDispatch methods.
1866 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1870 ITypeInfo
** ppTInfo
)
1877 /************************************************************************
1878 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1880 * See Windows documentation for more details on IDispatch methods.
1882 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1885 LPOLESTR
* rgszNames
,
1895 /************************************************************************
1896 * OLEPictureImpl_Invoke (IDispatch)
1898 * See Windows documentation for more details on IDispatch methods.
1900 static HRESULT WINAPI
OLEPictureImpl_Invoke(
1902 DISPID dispIdMember
,
1906 DISPPARAMS
* pDispParams
,
1907 VARIANT
* pVarResult
,
1908 EXCEPINFO
* pExepInfo
,
1911 FIXME("(dispid: %ld):Stub\n",dispIdMember
);
1913 VariantInit(pVarResult
);
1914 V_VT(pVarResult
) = VT_BOOL
;
1915 V_BOOL(pVarResult
) = FALSE
;
1920 static IPictureVtbl OLEPictureImpl_VTable
=
1922 OLEPictureImpl_QueryInterface
,
1923 OLEPictureImpl_AddRef
,
1924 OLEPictureImpl_Release
,
1925 OLEPictureImpl_get_Handle
,
1926 OLEPictureImpl_get_hPal
,
1927 OLEPictureImpl_get_Type
,
1928 OLEPictureImpl_get_Width
,
1929 OLEPictureImpl_get_Height
,
1930 OLEPictureImpl_Render
,
1931 OLEPictureImpl_set_hPal
,
1932 OLEPictureImpl_get_CurDC
,
1933 OLEPictureImpl_SelectPicture
,
1934 OLEPictureImpl_get_KeepOriginalFormat
,
1935 OLEPictureImpl_put_KeepOriginalFormat
,
1936 OLEPictureImpl_PictureChanged
,
1937 OLEPictureImpl_SaveAsFile
,
1938 OLEPictureImpl_get_Attributes
1941 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
1943 OLEPictureImpl_IDispatch_QueryInterface
,
1944 OLEPictureImpl_IDispatch_AddRef
,
1945 OLEPictureImpl_IDispatch_Release
,
1946 OLEPictureImpl_GetTypeInfoCount
,
1947 OLEPictureImpl_GetTypeInfo
,
1948 OLEPictureImpl_GetIDsOfNames
,
1949 OLEPictureImpl_Invoke
1952 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
1954 OLEPictureImpl_IPersistStream_QueryInterface
,
1955 OLEPictureImpl_IPersistStream_AddRef
,
1956 OLEPictureImpl_IPersistStream_Release
,
1957 OLEPictureImpl_GetClassID
,
1958 OLEPictureImpl_IsDirty
,
1959 OLEPictureImpl_Load
,
1960 OLEPictureImpl_Save
,
1961 OLEPictureImpl_GetSizeMax
1964 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
1966 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
1967 OLEPictureImpl_IConnectionPointContainer_AddRef
,
1968 OLEPictureImpl_IConnectionPointContainer_Release
,
1969 OLEPictureImpl_EnumConnectionPoints
,
1970 OLEPictureImpl_FindConnectionPoint
1973 /***********************************************************************
1974 * OleCreatePictureIndirect (OLEAUT32.419)
1976 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
1977 BOOL fOwn
, LPVOID
*ppvObj
)
1979 OLEPictureImpl
* newPict
= NULL
;
1982 TRACE("(%p,%p,%d,%p)\n", lpPictDesc
, riid
, fOwn
, ppvObj
);
1993 * Try to construct a new instance of the class.
1995 newPict
= OLEPictureImpl_Construct(lpPictDesc
, fOwn
);
1997 if (newPict
== NULL
)
1998 return E_OUTOFMEMORY
;
2001 * Make sure it supports the interface required by the caller.
2003 hr
= IPicture_QueryInterface((IPicture
*)newPict
, riid
, ppvObj
);
2006 * Release the reference obtained in the constructor. If
2007 * the QueryInterface was unsuccessful, it will free the class.
2009 IPicture_Release((IPicture
*)newPict
);
2015 /***********************************************************************
2016 * OleLoadPicture (OLEAUT32.418)
2018 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2019 REFIID riid
, LPVOID
*ppvObj
)
2025 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2026 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
2028 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2031 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2033 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2034 IPicture_Release(newpic
);
2038 IPersistStream_Load(ps
,lpstream
);
2039 IPersistStream_Release(ps
);
2040 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2042 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2043 IPicture_Release(newpic
);
2047 /***********************************************************************
2048 * OleLoadPictureEx (OLEAUT32.401)
2050 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
2051 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2057 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2058 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2060 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2063 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2065 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2066 IPicture_Release(newpic
);
2070 IPersistStream_Load(ps
,lpstream
);
2071 IPersistStream_Release(ps
);
2072 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2074 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2075 IPicture_Release(newpic
);
2079 /***********************************************************************
2080 * OleLoadPicturePath (OLEAUT32.424)
2082 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2083 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2086 static const WCHAR file
[] = { 'f','i','l','e',':','/','/',0 };
2090 HGLOBAL hGlobal
= NULL
;
2091 DWORD dwBytesRead
= 0;
2094 IPersistStream
*pStream
;
2097 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2098 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2099 debugstr_guid(riid
), ppvRet
);
2101 if (!ppvRet
) return E_POINTER
;
2103 if (strncmpW(szURLorPath
, file
, 7) == 0) {
2106 hFile
= CreateFileW(szURLorPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2108 if (hFile
== INVALID_HANDLE_VALUE
)
2109 return E_UNEXPECTED
;
2111 dwFileSize
= GetFileSize(hFile
, NULL
);
2112 if (dwFileSize
!= INVALID_FILE_SIZE
)
2114 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2117 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
);
2120 GlobalFree(hGlobal
);
2128 return E_UNEXPECTED
;
2130 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2133 GlobalFree(hGlobal
);
2140 hRes
= CreateBindCtx(0, &pbc
);
2141 if (SUCCEEDED(hRes
))
2143 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2144 if (SUCCEEDED(hRes
))
2146 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2147 IMoniker_Release(pmnk
);
2149 IBindCtx_Release(pbc
);
2155 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2156 &IID_IPicture
, (LPVOID
*)&ipicture
);
2158 IStream_Release(stream
);
2162 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2164 IStream_Release(stream
);
2165 IPicture_Release(ipicture
);
2169 hRes
= IPersistStream_Load(pStream
, stream
);
2170 IPersistStream_Release(pStream
);
2171 IStream_Release(stream
);
2174 IPicture_Release(ipicture
);
2178 hRes
= IPicture_QueryInterface(ipicture
,riid
,ppvRet
);
2180 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2182 IPicture_Release(ipicture
);
2186 /*******************************************************************************
2187 * StdPic ClassFactory
2191 /* IUnknown fields */
2192 IClassFactoryVtbl
*lpVtbl
;
2194 } IClassFactoryImpl
;
2196 static HRESULT WINAPI
2197 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2198 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2200 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2201 return E_NOINTERFACE
;
2205 SPCF_AddRef(LPCLASSFACTORY iface
) {
2206 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2207 return InterlockedIncrement(&This
->ref
);
2210 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2211 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2212 /* static class, won't be freed */
2213 return InterlockedDecrement(&This
->ref
);
2216 static HRESULT WINAPI
SPCF_CreateInstance(
2217 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2219 /* Creates an uninitialized picture */
2220 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2224 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2225 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2226 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2230 static IClassFactoryVtbl SPCF_Vtbl
= {
2231 SPCF_QueryInterface
,
2234 SPCF_CreateInstance
,
2237 static IClassFactoryImpl STDPIC_CF
= {&SPCF_Vtbl
, 1 };
2239 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= (LPVOID
)&STDPIC_CF
; }