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 */
140 BOOL bIsDirty
; /* Set to TRUE if picture has changed */
141 unsigned int loadtime_magic
; /* If a length header was found, saves value */
142 unsigned int loadtime_format
; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
146 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
148 #define ICOM_THIS_From_IDispatch(impl, name) \
149 impl *This = (impl*)(((char*)name)-sizeof(void*));
150 #define ICOM_THIS_From_IPersistStream(impl, name) \
151 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
152 #define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
153 impl *This = (impl*)(((char*)name)-3*sizeof(void*));
156 * Predeclare VTables. They get initialized at the end.
158 static IPictureVtbl OLEPictureImpl_VTable
;
159 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable
;
160 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
;
161 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
;
163 /***********************************************************************
164 * Implementation of the OLEPictureImpl class.
167 static void OLEPictureImpl_SetBitmap(OLEPictureImpl
*This
) {
171 TRACE("bitmap handle %p\n", This
->desc
.u
.bmp
.hbitmap
);
172 if(GetObjectA(This
->desc
.u
.bmp
.hbitmap
, sizeof(bm
), &bm
) != sizeof(bm
)) {
173 ERR("GetObject fails\n");
176 This
->origWidth
= bm
.bmWidth
;
177 This
->origHeight
= bm
.bmHeight
;
178 /* The width and height are stored in HIMETRIC units (0.01 mm),
179 so we take our pixel width divide by pixels per inch and
180 multiply by 25.4 * 100 */
181 /* Should we use GetBitmapDimension if available? */
182 hdcRef
= CreateCompatibleDC(0);
183 This
->himetricWidth
=(bm
.bmWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
184 This
->himetricHeight
=(bm
.bmHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
188 static void OLEPictureImpl_SetIcon(OLEPictureImpl
* This
)
192 TRACE("icon handle %p\n", This
->desc
.u
.icon
.hicon
);
193 if (GetIconInfo(This
->desc
.u
.icon
.hicon
, &infoIcon
)) {
197 TRACE("bitmap handle for icon is %p\n", infoIcon
.hbmColor
);
198 if(GetObjectA(infoIcon
.hbmColor
? infoIcon
.hbmColor
: infoIcon
.hbmMask
, sizeof(bm
), &bm
) != sizeof(bm
)) {
199 ERR("GetObject fails on icon bitmap\n");
203 This
->origWidth
= bm
.bmWidth
;
204 This
->origHeight
= infoIcon
.hbmColor
? bm
.bmHeight
: bm
.bmHeight
/ 2;
205 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
207 This
->himetricWidth
= (This
->origWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
208 This
->himetricHeight
= (This
->origHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
209 ReleaseDC(0, hdcRef
);
211 DeleteObject(infoIcon
.hbmMask
);
212 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
214 ERR("GetIconInfo() fails on icon %p\n", This
->desc
.u
.icon
.hicon
);
218 /************************************************************************
219 * OLEPictureImpl_Construct
221 * This method will construct a new instance of the OLEPictureImpl
224 * The caller of this method must release the object when it's
227 static OLEPictureImpl
* OLEPictureImpl_Construct(LPPICTDESC pictDesc
, BOOL fOwn
)
229 OLEPictureImpl
* newObject
= 0;
232 TRACE("(%p) type = %d\n", pictDesc
, pictDesc
->picType
);
235 * Allocate space for the object.
237 newObject
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(OLEPictureImpl
));
243 * Initialize the virtual function table.
245 newObject
->lpvtbl1
= &OLEPictureImpl_VTable
;
246 newObject
->lpvtbl2
= &OLEPictureImpl_IDispatch_VTable
;
247 newObject
->lpvtbl3
= &OLEPictureImpl_IPersistStream_VTable
;
248 newObject
->lpvtbl4
= &OLEPictureImpl_IConnectionPointContainer_VTable
;
250 CreateConnectionPoint((IUnknown
*)newObject
,&IID_IPropertyNotifySink
,&newObject
->pCP
);
253 * Start with one reference count. The caller of this function
254 * must release the interface pointer when it is done.
257 newObject
->hDCCur
= 0;
259 newObject
->fOwn
= fOwn
;
261 /* dunno about original value */
262 newObject
->keepOrigFormat
= TRUE
;
264 newObject
->hbmMask
= NULL
;
265 newObject
->loadtime_magic
= 0xdeadbeef;
266 newObject
->loadtime_format
= 0;
267 newObject
->bIsDirty
= FALSE
;
270 if(pictDesc
->cbSizeofstruct
!= sizeof(PICTDESC
)) {
271 FIXME("struct size = %d\n", pictDesc
->cbSizeofstruct
);
273 memcpy(&newObject
->desc
, pictDesc
, sizeof(PICTDESC
));
276 switch(pictDesc
->picType
) {
278 OLEPictureImpl_SetBitmap(newObject
);
281 case PICTYPE_METAFILE
:
282 TRACE("metafile handle %p\n", pictDesc
->u
.wmf
.hmeta
);
283 newObject
->himetricWidth
= pictDesc
->u
.wmf
.xExt
;
284 newObject
->himetricHeight
= pictDesc
->u
.wmf
.yExt
;
288 /* not sure what to do here */
289 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
293 OLEPictureImpl_SetIcon(newObject
);
295 case PICTYPE_ENHMETAFILE
:
297 FIXME("Unsupported type %d\n", pictDesc
->picType
);
298 newObject
->himetricWidth
= newObject
->himetricHeight
= 0;
302 newObject
->desc
.picType
= PICTYPE_UNINITIALIZED
;
305 TRACE("returning %p\n", newObject
);
309 /************************************************************************
310 * OLEPictureImpl_Destroy
312 * This method is called by the Release method when the reference
313 * count goes down to 0. It will free all resources used by
315 static void OLEPictureImpl_Destroy(OLEPictureImpl
* Obj
)
317 TRACE("(%p)\n", Obj
);
319 if(Obj
->fOwn
) { /* We need to destroy the picture */
320 switch(Obj
->desc
.picType
) {
322 DeleteObject(Obj
->desc
.u
.bmp
.hbitmap
);
324 case PICTYPE_METAFILE
:
325 DeleteMetaFile(Obj
->desc
.u
.wmf
.hmeta
);
328 DestroyIcon(Obj
->desc
.u
.icon
.hicon
);
330 case PICTYPE_ENHMETAFILE
:
331 DeleteEnhMetaFile(Obj
->desc
.u
.emf
.hemf
);
334 FIXME("Unsupported type %d - unable to delete\n", Obj
->desc
.picType
);
338 HeapFree(GetProcessHeap(), 0, Obj
->data
);
339 HeapFree(GetProcessHeap(), 0, Obj
);
342 static ULONG WINAPI
OLEPictureImpl_AddRef(IPicture
* iface
);
344 /************************************************************************
345 * OLEPictureImpl_QueryInterface (IUnknown)
347 * See Windows documentation for more details on IUnknown methods.
349 static HRESULT WINAPI
OLEPictureImpl_QueryInterface(
354 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
355 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
358 * Perform a sanity check on the parameters.
360 if ( (This
==0) || (ppvObject
==0) )
364 * Initialize the return parameter.
369 * Compare the riid with the interface IDs implemented by this object.
371 if (memcmp(&IID_IUnknown
, riid
, sizeof(IID_IUnknown
)) == 0)
373 *ppvObject
= (IPicture
*)This
;
375 else if (memcmp(&IID_IPicture
, riid
, sizeof(IID_IPicture
)) == 0)
377 *ppvObject
= (IPicture
*)This
;
379 else if (memcmp(&IID_IDispatch
, riid
, sizeof(IID_IDispatch
)) == 0)
381 *ppvObject
= (IDispatch
*)&(This
->lpvtbl2
);
383 else if (memcmp(&IID_IPictureDisp
, riid
, sizeof(IID_IPictureDisp
)) == 0)
385 *ppvObject
= (IDispatch
*)&(This
->lpvtbl2
);
387 else if (memcmp(&IID_IPersistStream
, riid
, sizeof(IID_IPersistStream
)) == 0)
389 *ppvObject
= (IPersistStream
*)&(This
->lpvtbl3
);
391 else if (memcmp(&IID_IConnectionPointContainer
, riid
, sizeof(IID_IConnectionPointContainer
)) == 0)
393 *ppvObject
= (IConnectionPointContainer
*)&(This
->lpvtbl4
);
396 * Check that we obtained an interface.
400 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid
));
401 return E_NOINTERFACE
;
405 * Query Interface always increases the reference count by one when it is
408 OLEPictureImpl_AddRef((IPicture
*)This
);
412 /***********************************************************************
413 * OLEPicture_SendNotify (internal)
415 * Sends notification messages of changed properties to any interested
418 static void OLEPicture_SendNotify(OLEPictureImpl
* this, DISPID dispID
)
420 IEnumConnections
*pEnum
;
423 if (IConnectionPoint_EnumConnections(this->pCP
, &pEnum
))
425 while(IEnumConnections_Next(pEnum
, 1, &CD
, NULL
) == S_OK
) {
426 IPropertyNotifySink
*sink
;
428 IUnknown_QueryInterface(CD
.pUnk
, &IID_IPropertyNotifySink
, (LPVOID
)&sink
);
429 IPropertyNotifySink_OnChanged(sink
, dispID
);
430 IPropertyNotifySink_Release(sink
);
431 IUnknown_Release(CD
.pUnk
);
433 IEnumConnections_Release(pEnum
);
437 /************************************************************************
438 * OLEPictureImpl_AddRef (IUnknown)
440 * See Windows documentation for more details on IUnknown methods.
442 static ULONG WINAPI
OLEPictureImpl_AddRef(
445 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
446 ULONG refCount
= InterlockedIncrement(&This
->ref
);
448 TRACE("(%p)->(ref before=%ld)\n", This
, refCount
- 1);
453 /************************************************************************
454 * OLEPictureImpl_Release (IUnknown)
456 * See Windows documentation for more details on IUnknown methods.
458 static ULONG WINAPI
OLEPictureImpl_Release(
461 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
462 ULONG refCount
= InterlockedDecrement(&This
->ref
);
464 TRACE("(%p)->(ref before=%ld)\n", This
, refCount
+ 1);
467 * If the reference count goes down to 0, perform suicide.
469 if (!refCount
) OLEPictureImpl_Destroy(This
);
475 /************************************************************************
476 * OLEPictureImpl_get_Handle
478 static HRESULT WINAPI
OLEPictureImpl_get_Handle(IPicture
*iface
,
481 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
482 TRACE("(%p)->(%p)\n", This
, phandle
);
483 switch(This
->desc
.picType
) {
485 *phandle
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
487 case PICTYPE_METAFILE
:
488 *phandle
= (OLE_HANDLE
)This
->desc
.u
.wmf
.hmeta
;
491 *phandle
= (OLE_HANDLE
)This
->desc
.u
.icon
.hicon
;
493 case PICTYPE_ENHMETAFILE
:
494 *phandle
= (OLE_HANDLE
)This
->desc
.u
.emf
.hemf
;
497 FIXME("Unimplemented type %d\n", This
->desc
.picType
);
500 TRACE("returning handle %08x\n", *phandle
);
504 /************************************************************************
505 * OLEPictureImpl_get_hPal
507 static HRESULT WINAPI
OLEPictureImpl_get_hPal(IPicture
*iface
,
510 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
511 FIXME("(%p)->(%p): stub\n", This
, phandle
);
515 /************************************************************************
516 * OLEPictureImpl_get_Type
518 static HRESULT WINAPI
OLEPictureImpl_get_Type(IPicture
*iface
,
521 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
522 TRACE("(%p)->(%p): type is %d\n", This
, ptype
, This
->desc
.picType
);
523 *ptype
= This
->desc
.picType
;
527 /************************************************************************
528 * OLEPictureImpl_get_Width
530 static HRESULT WINAPI
OLEPictureImpl_get_Width(IPicture
*iface
,
531 OLE_XSIZE_HIMETRIC
*pwidth
)
533 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
534 TRACE("(%p)->(%p): width is %ld\n", This
, pwidth
, This
->himetricWidth
);
535 *pwidth
= This
->himetricWidth
;
539 /************************************************************************
540 * OLEPictureImpl_get_Height
542 static HRESULT WINAPI
OLEPictureImpl_get_Height(IPicture
*iface
,
543 OLE_YSIZE_HIMETRIC
*pheight
)
545 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
546 TRACE("(%p)->(%p): height is %ld\n", This
, pheight
, This
->himetricHeight
);
547 *pheight
= This
->himetricHeight
;
551 /************************************************************************
552 * OLEPictureImpl_Render
554 static HRESULT WINAPI
OLEPictureImpl_Render(IPicture
*iface
, HDC hdc
,
555 LONG x
, LONG y
, LONG cx
, LONG cy
,
556 OLE_XPOS_HIMETRIC xSrc
,
557 OLE_YPOS_HIMETRIC ySrc
,
558 OLE_XSIZE_HIMETRIC cxSrc
,
559 OLE_YSIZE_HIMETRIC cySrc
,
562 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
563 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
564 This
, hdc
, x
, y
, cx
, cy
, xSrc
, ySrc
, cxSrc
, cySrc
, prcWBounds
);
566 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds
->left
, prcWBounds
->top
,
567 prcWBounds
->right
, prcWBounds
->bottom
);
570 * While the documentation suggests this to be here (or after rendering?)
571 * it does cause an endless recursion in my sample app. -MM 20010804
572 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
575 switch(This
->desc
.picType
) {
581 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
582 NB y-axis gets flipped */
584 hdcBmp
= CreateCompatibleDC(0);
585 SetMapMode(hdcBmp
, MM_ANISOTROPIC
);
586 SetWindowOrgEx(hdcBmp
, 0, 0, NULL
);
587 SetWindowExtEx(hdcBmp
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
588 SetViewportOrgEx(hdcBmp
, 0, This
->origHeight
, NULL
);
589 SetViewportExtEx(hdcBmp
, This
->origWidth
, -This
->origHeight
, NULL
);
591 hbmpOld
= SelectObject(hdcBmp
, This
->desc
.u
.bmp
.hbitmap
);
594 HDC hdcMask
= CreateCompatibleDC(0);
595 HBITMAP hOldbm
= SelectObject(hdcMask
, This
->hbmMask
);
597 SetMapMode(hdcMask
, MM_ANISOTROPIC
);
598 SetWindowOrgEx(hdcMask
, 0, 0, NULL
);
599 SetWindowExtEx(hdcMask
, This
->himetricWidth
, This
->himetricHeight
, NULL
);
600 SetViewportOrgEx(hdcMask
, 0, This
->origHeight
, NULL
);
601 SetViewportExtEx(hdcMask
, This
->origWidth
, -This
->origHeight
, NULL
);
603 SetBkColor(hdc
, RGB(255, 255, 255));
604 SetTextColor(hdc
, RGB(0, 0, 0));
605 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcMask
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCAND
);
606 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCPAINT
);
608 SelectObject(hdcMask
, hOldbm
);
611 StretchBlt(hdc
, x
, y
, cx
, cy
, hdcBmp
, xSrc
, ySrc
, cxSrc
, cySrc
, SRCCOPY
);
613 SelectObject(hdcBmp
, hbmpOld
);
618 FIXME("Not quite correct implementation of rendering icons...\n");
619 DrawIcon(hdc
,x
,y
,This
->desc
.u
.icon
.hicon
);
622 case PICTYPE_METAFILE
:
623 case PICTYPE_ENHMETAFILE
:
625 FIXME("type %d not implemented\n", This
->desc
.picType
);
631 /************************************************************************
632 * OLEPictureImpl_set_hPal
634 static HRESULT WINAPI
OLEPictureImpl_set_hPal(IPicture
*iface
,
637 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
638 FIXME("(%p)->(%08x): stub\n", This
, hpal
);
639 OLEPicture_SendNotify(This
,DISPID_PICT_HPAL
);
643 /************************************************************************
644 * OLEPictureImpl_get_CurDC
646 static HRESULT WINAPI
OLEPictureImpl_get_CurDC(IPicture
*iface
,
649 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
650 TRACE("(%p), returning %p\n", This
, This
->hDCCur
);
651 if (phdc
) *phdc
= This
->hDCCur
;
655 /************************************************************************
656 * OLEPictureImpl_SelectPicture
658 static HRESULT WINAPI
OLEPictureImpl_SelectPicture(IPicture
*iface
,
661 OLE_HANDLE
*phbmpOut
)
663 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
664 TRACE("(%p)->(%p, %p, %p)\n", This
, hdcIn
, phdcOut
, phbmpOut
);
665 if (This
->desc
.picType
== PICTYPE_BITMAP
) {
666 SelectObject(hdcIn
,This
->desc
.u
.bmp
.hbitmap
);
669 *phdcOut
= This
->hDCCur
;
670 This
->hDCCur
= hdcIn
;
672 *phbmpOut
= (OLE_HANDLE
)This
->desc
.u
.bmp
.hbitmap
;
675 FIXME("Don't know how to select picture type %d\n",This
->desc
.picType
);
680 /************************************************************************
681 * OLEPictureImpl_get_KeepOriginalFormat
683 static HRESULT WINAPI
OLEPictureImpl_get_KeepOriginalFormat(IPicture
*iface
,
686 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
687 TRACE("(%p)->(%p)\n", This
, pfKeep
);
690 *pfKeep
= This
->keepOrigFormat
;
694 /************************************************************************
695 * OLEPictureImpl_put_KeepOriginalFormat
697 static HRESULT WINAPI
OLEPictureImpl_put_KeepOriginalFormat(IPicture
*iface
,
700 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
701 TRACE("(%p)->(%d)\n", This
, keep
);
702 This
->keepOrigFormat
= keep
;
703 /* FIXME: what DISPID notification here? */
707 /************************************************************************
708 * OLEPictureImpl_PictureChanged
710 static HRESULT WINAPI
OLEPictureImpl_PictureChanged(IPicture
*iface
)
712 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
713 TRACE("(%p)->()\n", This
);
714 OLEPicture_SendNotify(This
,DISPID_PICT_HANDLE
);
715 This
->bIsDirty
= TRUE
;
719 /************************************************************************
720 * OLEPictureImpl_SaveAsFile
722 static HRESULT WINAPI
OLEPictureImpl_SaveAsFile(IPicture
*iface
,
727 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
728 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This
, pstream
, SaveMemCopy
, pcbSize
);
729 return IStream_Write(pstream
,This
->data
,This
->datalen
,(ULONG
*)pcbSize
);
732 /************************************************************************
733 * OLEPictureImpl_get_Attributes
735 static HRESULT WINAPI
OLEPictureImpl_get_Attributes(IPicture
*iface
,
738 OLEPictureImpl
*This
= (OLEPictureImpl
*)iface
;
739 TRACE("(%p)->(%p).\n", This
, pdwAttr
);
741 switch (This
->desc
.picType
) {
742 case PICTYPE_BITMAP
: break; /* not 'truly' scalable, see MSDN. */
743 case PICTYPE_ICON
: *pdwAttr
= PICTURE_TRANSPARENT
;break;
744 case PICTYPE_METAFILE
: *pdwAttr
= PICTURE_TRANSPARENT
|PICTURE_SCALABLE
;break;
745 default:FIXME("Unknown pictype %d\n",This
->desc
.picType
);break;
751 /************************************************************************
752 * IConnectionPointContainer
755 static HRESULT WINAPI
OLEPictureImpl_IConnectionPointContainer_QueryInterface(
756 IConnectionPointContainer
* iface
,
760 ICOM_THIS_From_IConnectionPointContainer(IPicture
,iface
);
762 return IPicture_QueryInterface(This
,riid
,ppvoid
);
765 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_AddRef(
766 IConnectionPointContainer
* iface
)
768 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
770 return IPicture_AddRef(This
);
773 static ULONG WINAPI
OLEPictureImpl_IConnectionPointContainer_Release(
774 IConnectionPointContainer
* iface
)
776 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
778 return IPicture_Release(This
);
781 static HRESULT WINAPI
OLEPictureImpl_EnumConnectionPoints(
782 IConnectionPointContainer
* iface
,
783 IEnumConnectionPoints
** ppEnum
785 ICOM_THIS_From_IConnectionPointContainer(IPicture
, iface
);
787 FIXME("(%p,%p), stub!\n",This
,ppEnum
);
791 static HRESULT WINAPI
OLEPictureImpl_FindConnectionPoint(
792 IConnectionPointContainer
* iface
,
794 IConnectionPoint
**ppCP
796 ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl
, iface
);
797 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppCP
);
801 if (IsEqualGUID(riid
,&IID_IPropertyNotifySink
))
802 return IConnectionPoint_QueryInterface(This
->pCP
,&IID_IConnectionPoint
,(LPVOID
)ppCP
);
803 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid
));
806 /************************************************************************
809 /************************************************************************
810 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
812 * See Windows documentation for more details on IUnknown methods.
814 static HRESULT WINAPI
OLEPictureImpl_IPersistStream_QueryInterface(
815 IPersistStream
* iface
,
819 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
821 return IPicture_QueryInterface(This
, riid
, ppvoid
);
824 /************************************************************************
825 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
827 * See Windows documentation for more details on IUnknown methods.
829 static ULONG WINAPI
OLEPictureImpl_IPersistStream_AddRef(
830 IPersistStream
* iface
)
832 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
834 return IPicture_AddRef(This
);
837 /************************************************************************
838 * OLEPictureImpl_IPersistStream_Release (IUnknown)
840 * See Windows documentation for more details on IUnknown methods.
842 static ULONG WINAPI
OLEPictureImpl_IPersistStream_Release(
843 IPersistStream
* iface
)
845 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
847 return IPicture_Release(This
);
850 /************************************************************************
851 * OLEPictureImpl_IPersistStream_GetClassID
853 static HRESULT WINAPI
OLEPictureImpl_GetClassID(
854 IPersistStream
* iface
,CLSID
* pClassID
)
856 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
857 FIXME("(%p),stub!\n",This
);
861 /************************************************************************
862 * OLEPictureImpl_IPersistStream_IsDirty
864 static HRESULT WINAPI
OLEPictureImpl_IsDirty(
865 IPersistStream
* iface
)
867 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
868 FIXME("(%p),stub!\n",This
);
872 #ifdef HAVE_JPEGLIB_H
874 static void *libjpeg_handle
;
875 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
876 MAKE_FUNCPTR(jpeg_std_error
);
877 MAKE_FUNCPTR(jpeg_CreateDecompress
);
878 MAKE_FUNCPTR(jpeg_read_header
);
879 MAKE_FUNCPTR(jpeg_start_decompress
);
880 MAKE_FUNCPTR(jpeg_read_scanlines
);
881 MAKE_FUNCPTR(jpeg_finish_decompress
);
882 MAKE_FUNCPTR(jpeg_destroy_decompress
);
885 static void *load_libjpeg(void)
887 if((libjpeg_handle
= wine_dlopen(SONAME_LIBJPEG
, RTLD_NOW
, NULL
, 0)) != NULL
) {
889 #define LOAD_FUNCPTR(f) \
890 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
891 libjpeg_handle = NULL; \
895 LOAD_FUNCPTR(jpeg_std_error
);
896 LOAD_FUNCPTR(jpeg_CreateDecompress
);
897 LOAD_FUNCPTR(jpeg_read_header
);
898 LOAD_FUNCPTR(jpeg_start_decompress
);
899 LOAD_FUNCPTR(jpeg_read_scanlines
);
900 LOAD_FUNCPTR(jpeg_finish_decompress
);
901 LOAD_FUNCPTR(jpeg_destroy_decompress
);
904 return libjpeg_handle
;
907 /* for the jpeg decompressor source manager. */
908 static void _jpeg_init_source(j_decompress_ptr cinfo
) { }
910 static boolean
_jpeg_fill_input_buffer(j_decompress_ptr cinfo
) {
911 ERR("(), should not get here.\n");
915 static void _jpeg_skip_input_data(j_decompress_ptr cinfo
,long num_bytes
) {
916 TRACE("Skipping %ld bytes...\n", num_bytes
);
917 cinfo
->src
->next_input_byte
+= num_bytes
;
918 cinfo
->src
->bytes_in_buffer
-= num_bytes
;
921 static boolean
_jpeg_resync_to_restart(j_decompress_ptr cinfo
, int desired
) {
922 ERR("(desired=%d), should not get here.\n",desired
);
925 static void _jpeg_term_source(j_decompress_ptr cinfo
) { }
926 #endif /* HAVE_JPEGLIB_H */
928 #ifdef HAVE_GIF_LIB_H
930 static void *libungif_handle
;
931 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
932 MAKE_FUNCPTR(DGifOpen
);
933 MAKE_FUNCPTR(DGifSlurp
);
934 MAKE_FUNCPTR(DGifCloseFile
);
943 static void *load_libungif(void)
945 if(((libungif_handle
= wine_dlopen(SONAME_LIBUNGIF
, RTLD_NOW
, NULL
, 0)) != NULL
) ||
946 ((libungif_handle
= wine_dlopen(SONAME_LIBGIF
, RTLD_NOW
, NULL
, 0)) != NULL
)
949 #define LOAD_FUNCPTR(f) \
950 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
951 libungif_handle = NULL; \
955 LOAD_FUNCPTR(DGifOpen
);
956 LOAD_FUNCPTR(DGifSlurp
);
957 LOAD_FUNCPTR(DGifCloseFile
);
960 return libungif_handle
;
963 static int _gif_inputfunc(GifFileType
*gif
, GifByteType
*data
, int len
) {
964 struct gifdata
*gd
= (struct gifdata
*)gif
->UserData
;
966 if (len
+gd
->curoff
> gd
->len
) {
967 FIXME("Trying to read %d bytes, but only %d available.\n",len
, gd
->len
-gd
->curoff
);
968 len
= gd
->len
- gd
->curoff
;
970 memcpy(data
, gd
->data
+gd
->curoff
, len
);
975 #endif /* HAVE_GIF_LIB_H */
977 /************************************************************************
978 * OLEPictureImpl_IPersistStream_Load (IUnknown)
980 * Loads the binary data from the IStream. Starts at current position.
981 * There appears to be an 2 DWORD header:
985 * Currently implemented: BITMAP, ICON, JPEG, GIF
987 static HRESULT WINAPI
OLEPictureImpl_Load(IPersistStream
* iface
,IStream
*pStm
) {
994 ICOM_THIS_From_IPersistStream(OLEPictureImpl
, iface
);
996 TRACE("(%p,%p)\n",This
,pStm
);
998 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1001 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1002 * compound file. This may explain most, if not all, of the cases of "no header",
1003 * and the header validation should take this into account. At least in Visual Basic 6,
1004 * resource streams, valid headers are
1005 * header[0] == "lt\0\0",
1006 * header[1] == length_of_stream.
1008 hr
=IStream_Stat(pStm
,&statstg
,STATFLAG_NONAME
);
1010 FIXME("Stat failed with hres %lx\n",hr
);
1011 hr
=IStream_Read(pStm
,header
,8,&xread
);
1012 if (hr
|| xread
!=8) {
1013 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr
,xread
);
1016 if (!memcmp(&(header
[0]), "GIF8", 4) || /* GIF header */
1017 !memcmp(&(header
[0]), "BM", 2) || /* BMP header */
1018 !memcmp(&(header
[0]), "\xff\xd8", 2) || /* JPEG header */
1019 header
[1] > statstg
.cbSize
.QuadPart
|| (header
[1]==0)) {/* Incorrect header, assume none. */
1021 xbuf
= This
->data
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,statstg
.cbSize
.QuadPart
);
1022 memcpy(xbuf
,&header
,8);
1023 This
->datalen
= statstg
.cbSize
.QuadPart
;
1024 while (xread
< This
->datalen
) {
1026 hr
= IStream_Read(pStm
,xbuf
+xread
,This
->datalen
-xread
,&nread
);
1031 if (xread
!= This
->datalen
)
1032 FIXME("Could only read %ld of %d bytes in no-header case?\n",xread
,This
->datalen
);
1035 xbuf
= This
->data
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,header
[1]);
1036 This
->datalen
= header
[1];
1037 while (xread
< header
[1]) {
1039 hr
= IStream_Read(pStm
,xbuf
+xread
,header
[1]-xread
,&nread
);
1044 if (xread
!= header
[1])
1045 FIXME("Could only read %ld of %ld bytes?\n",xread
,header
[1]);
1047 magic
= xbuf
[0] + (xbuf
[1]<<8);
1049 case 0x4947: { /* GIF */
1050 #ifdef HAVE_GIF_LIB_H
1060 int transparent
= -1;
1064 if(!libungif_handle
) {
1065 if(!load_libungif()) {
1066 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF
, SONAME_LIBGIF
);
1074 gif
= pDGifOpen((void*)&gd
, _gif_inputfunc
);
1075 ret
= pDGifSlurp(gif
);
1076 if (ret
== GIF_ERROR
) {
1077 FIXME("Failed reading GIF using libgif.\n");
1080 TRACE("screen height %d, width %d\n", gif
->SWidth
, gif
->SHeight
);
1081 TRACE("color res %d, backgcolor %d\n", gif
->SColorResolution
, gif
->SBackGroundColor
);
1082 TRACE("imgcnt %d\n", gif
->ImageCount
);
1083 if (gif
->ImageCount
<1) {
1084 FIXME("GIF stream does not have images inside?\n");
1087 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1088 gif
->Image
.Width
, gif
->Image
.Height
,
1089 gif
->Image
.Left
, gif
->Image
.Top
,
1090 gif
->Image
.Interlace
1093 padding
= (gif
->SWidth
+3) & ~3;
1094 bmi
= HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER
)+(1<<gif
->SColorResolution
)*sizeof(RGBQUAD
));
1095 bytes
= HeapAlloc(GetProcessHeap(),0,padding
*gif
->SHeight
);
1096 si
= gif
->SavedImages
+0;
1097 gid
= &(si
->ImageDesc
);
1099 if (!cm
) cm
= gif
->SColorMap
;
1101 /* look for the transparent color extension */
1102 for (i
= 0; i
< si
->ExtensionBlockCount
; ++i
) {
1103 eb
= si
->ExtensionBlocks
+ i
;
1104 if (eb
->Function
== 0xF9 && eb
->ByteCount
== 4) {
1105 if ((eb
->Bytes
[0] & 1) == 1) {
1106 transparent
= (unsigned char)eb
->Bytes
[3];
1111 for (i
=0;i
<(1<<gif
->SColorResolution
);i
++) {
1112 bmi
->bmiColors
[i
].rgbRed
= cm
->Colors
[i
].Red
;
1113 bmi
->bmiColors
[i
].rgbGreen
= cm
->Colors
[i
].Green
;
1114 bmi
->bmiColors
[i
].rgbBlue
= cm
->Colors
[i
].Blue
;
1115 if (i
== transparent
) {
1116 This
->rgbTrans
= RGB(bmi
->bmiColors
[i
].rgbRed
,
1117 bmi
->bmiColors
[i
].rgbGreen
,
1118 bmi
->bmiColors
[i
].rgbBlue
);
1122 /* Map to in picture coordinates */
1123 for (i
= 0, j
= 0; i
< gid
->Height
; i
++) {
1124 if (gif
->Image
.Interlace
) {
1126 bytes
+ (gid
->Top
+ j
) * padding
+ gid
->Left
,
1127 si
->RasterBits
+ i
* gid
->Width
,
1130 /* Lower bits of interlaced counter encode current interlace */
1131 if (j
& 1) j
+= 2; /* Currently filling odd rows */
1132 else if (j
& 2) j
+= 4; /* Currently filling even rows not multiples of 4 */
1133 else j
+= 8; /* Currently filling every 8th row or 4th row in-between */
1135 if (j
>= gid
->Height
&& i
< gid
->Height
&& (j
& 1) == 0) {
1136 /* End of current interlace, go to next interlace */
1137 if (j
& 2) j
= 1; /* Next iteration fills odd rows */
1138 else if (j
& 4) j
= 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1139 else j
= 4; /* Next iteration fills rows in-between rows mod 6 */
1143 bytes
+ (gid
->Top
+ i
) * padding
+ gid
->Left
,
1144 si
->RasterBits
+ i
* gid
->Width
,
1149 bmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1150 bmi
->bmiHeader
.biWidth
= gif
->SWidth
;
1151 bmi
->bmiHeader
.biHeight
= -gif
->SHeight
;
1152 bmi
->bmiHeader
.biPlanes
= 1;
1153 bmi
->bmiHeader
.biBitCount
= 8;
1154 bmi
->bmiHeader
.biCompression
= BI_RGB
;
1155 bmi
->bmiHeader
.biSizeImage
= padding
*gif
->SHeight
;
1156 bmi
->bmiHeader
.biXPelsPerMeter
= 0;
1157 bmi
->bmiHeader
.biYPelsPerMeter
= 0;
1158 bmi
->bmiHeader
.biClrUsed
= 1 << gif
->SColorResolution
;
1159 bmi
->bmiHeader
.biClrImportant
= 0;
1162 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1171 if (transparent
> -1) {
1172 /* Create the Mask */
1173 HDC hdc
= CreateCompatibleDC(0);
1174 HDC hdcMask
= CreateCompatibleDC(0);
1176 HBITMAP hOldbitmapmask
;
1178 This
->hbmMask
= CreateBitmap(bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, 1, 1, NULL
);
1180 hOldbitmap
= SelectObject(hdc
,This
->desc
.u
.bmp
.hbitmap
);
1181 hOldbitmapmask
= SelectObject(hdcMask
, This
->hbmMask
);
1182 SetBkColor(hdc
, This
->rgbTrans
);
1183 BitBlt(hdcMask
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
, hdc
, 0, 0, SRCCOPY
);
1185 /* We no longer need the original bitmap, so we apply the first
1186 transformation with the mask to speed up the rendering */
1187 SetBkColor(hdc
, RGB(0,0,0));
1188 SetTextColor(hdc
, RGB(255,255,255));
1189 BitBlt(hdc
, 0, 0, bmi
->bmiHeader
.biWidth
, bmi
->bmiHeader
.biHeight
,
1190 hdcMask
, 0, 0, SRCAND
);
1192 SelectObject(hdc
, hOldbitmap
);
1193 SelectObject(hdcMask
, hOldbitmapmask
);
1199 This
->desc
.picType
= PICTYPE_BITMAP
;
1200 OLEPictureImpl_SetBitmap(This
);
1201 pDGifCloseFile(gif
);
1202 HeapFree(GetProcessHeap(),0,bytes
);
1205 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1209 case 0xd8ff: { /* JPEG */
1210 #ifdef HAVE_JPEGLIB_H
1211 struct jpeg_decompress_struct jd
;
1212 struct jpeg_error_mgr jerr
;
1215 JSAMPROW samprow
,oldsamprow
;
1216 BITMAPINFOHEADER bmi
;
1219 struct jpeg_source_mgr xjsm
;
1223 if(!libjpeg_handle
) {
1224 if(!load_libjpeg()) {
1225 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG
);
1230 /* This is basically so we can use in-memory data for jpeg decompression.
1231 * We need to have all the functions.
1233 xjsm
.next_input_byte
= xbuf
;
1234 xjsm
.bytes_in_buffer
= xread
;
1235 xjsm
.init_source
= _jpeg_init_source
;
1236 xjsm
.fill_input_buffer
= _jpeg_fill_input_buffer
;
1237 xjsm
.skip_input_data
= _jpeg_skip_input_data
;
1238 xjsm
.resync_to_restart
= _jpeg_resync_to_restart
;
1239 xjsm
.term_source
= _jpeg_term_source
;
1241 jd
.err
= pjpeg_std_error(&jerr
);
1242 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1243 * jpeg_create_decompress(&jd); */
1244 pjpeg_CreateDecompress(&jd
, JPEG_LIB_VERSION
, (size_t) sizeof(struct jpeg_decompress_struct
));
1246 ret
=pjpeg_read_header(&jd
,TRUE
);
1247 jd
.out_color_space
= JCS_RGB
;
1248 pjpeg_start_decompress(&jd
);
1249 if (ret
!= JPEG_HEADER_OK
) {
1250 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret
);
1251 HeapFree(GetProcessHeap(),0,xbuf
);
1255 bits
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1256 (jd
.output_height
+1) * ((jd
.output_width
*jd
.output_components
+ 3) & ~3) );
1257 samprow
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,jd
.output_width
*jd
.output_components
);
1260 oldsamprow
= samprow
;
1261 while ( jd
.output_scanline
<jd
.output_height
) {
1262 x
= pjpeg_read_scanlines(&jd
,&samprow
,1);
1264 FIXME("failed to read current scanline?\n");
1267 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1268 for(i
=0;i
<jd
.output_width
;i
++,samprow
+=jd
.output_components
) {
1269 *(bits
++) = *(samprow
+2);
1270 *(bits
++) = *(samprow
+1);
1271 *(bits
++) = *(samprow
);
1273 bits
= (LPBYTE
)(((UINT_PTR
)bits
+ 3) & ~3);
1274 samprow
= oldsamprow
;
1278 bmi
.biSize
= sizeof(bmi
);
1279 bmi
.biWidth
= jd
.output_width
;
1280 bmi
.biHeight
= -jd
.output_height
;
1282 bmi
.biBitCount
= jd
.output_components
<<3;
1283 bmi
.biCompression
= BI_RGB
;
1284 bmi
.biSizeImage
= jd
.output_height
*jd
.output_width
*jd
.output_components
;
1285 bmi
.biXPelsPerMeter
= 0;
1286 bmi
.biYPelsPerMeter
= 0;
1288 bmi
.biClrImportant
= 0;
1290 HeapFree(GetProcessHeap(),0,samprow
);
1291 pjpeg_finish_decompress(&jd
);
1292 pjpeg_destroy_decompress(&jd
);
1294 This
->desc
.u
.bmp
.hbitmap
=CreateDIBitmap(
1303 This
->desc
.picType
= PICTYPE_BITMAP
;
1304 OLEPictureImpl_SetBitmap(This
);
1306 HeapFree(GetProcessHeap(),0,bits
);
1308 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1313 case 0x4d42: { /* Bitmap */
1314 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)xbuf
;
1315 BITMAPINFO
*bi
= (BITMAPINFO
*)(bfh
+1);
1318 /* Does not matter whether this is a coreheader or not, we only use
1319 * components which are in both
1322 This
->desc
.u
.bmp
.hbitmap
= CreateDIBitmap(
1326 xbuf
+bfh
->bfOffBits
,
1331 This
->desc
.picType
= PICTYPE_BITMAP
;
1332 OLEPictureImpl_SetBitmap(This
);
1336 case 0x0000: { /* ICON , first word is dwReserved */
1338 CURSORICONFILEDIR
*cifd
= (CURSORICONFILEDIR
*)xbuf
;
1343 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1344 FIXME("icon.idType=%d\n",cifd->idType);
1345 FIXME("icon.idCount=%d\n",cifd->idCount);
1347 for (i=0;i<cifd->idCount;i++) {
1348 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1349 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1350 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1351 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1352 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1353 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1354 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1355 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1359 /* If we have more than one icon, try to find the best.
1360 * this currently means '32 pixel wide'.
1362 if (cifd
->idCount
!=1) {
1363 for (i
=0;i
<cifd
->idCount
;i
++) {
1364 if (cifd
->idEntries
[i
].bWidth
== 32)
1367 if (i
==cifd
->idCount
) i
=0;
1370 hicon
= CreateIconFromResourceEx(
1371 xbuf
+cifd
->idEntries
[i
].dwDIBOffset
,
1372 cifd
->idEntries
[i
].dwDIBSize
,
1375 cifd
->idEntries
[i
].bWidth
,
1376 cifd
->idEntries
[i
].bHeight
,
1380 FIXME("CreateIcon failed.\n");
1383 This
->desc
.picType
= PICTYPE_ICON
;
1384 This
->desc
.u
.icon
.hicon
= hicon
;
1385 This
->origWidth
= cifd
->idEntries
[i
].bWidth
;
1386 This
->origHeight
= cifd
->idEntries
[i
].bHeight
;
1387 hdcRef
= CreateCompatibleDC(0);
1388 This
->himetricWidth
=(cifd
->idEntries
[i
].bWidth
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSX
);
1389 This
->himetricHeight
=(cifd
->idEntries
[i
].bHeight
*2540)/GetDeviceCaps(hdcRef
, LOGPIXELSY
);
1398 FIXME("Unknown magic %04x, %ld read bytes:\n",magic
,xread
);
1400 for (i
=0;i
<xread
+8;i
++) {
1401 if (i
<8) MESSAGE("%02x ",((unsigned char*)&header
)[i
]);
1402 else MESSAGE("%02x ",xbuf
[i
-8]);
1403 if (i
% 10 == 9) MESSAGE("\n");
1409 This
->bIsDirty
= FALSE
;
1411 /* FIXME: this notify is not really documented */
1413 OLEPicture_SendNotify(This
,DISPID_PICT_TYPE
);
1417 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
);
1418 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
);
1419 static HRESULT WINAPI
OLEPictureImpl_Save(
1420 IPersistStream
* iface
,IStream
*pStm
,BOOL fClearDirty
)
1422 HRESULT hResult
= E_NOTIMPL
;
1424 unsigned int iDataSize
;
1426 int iSerializeResult
= 0;
1428 ICOM_THIS_From_IPersistStream(OLEPictureImpl
, iface
);
1430 switch (This
->desc
.picType
) {
1432 if (This
->bIsDirty
) {
1433 if (serializeIcon(This
->desc
.u
.icon
.hicon
, &pIconData
, &iDataSize
)) {
1434 if (This
->loadtime_magic
!= 0xdeadbeef) {
1437 header
[0] = This
->loadtime_magic
;
1438 header
[1] = iDataSize
;
1439 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1441 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
1443 HeapFree(GetProcessHeap(), 0, This
->data
);
1444 This
->data
= pIconData
;
1445 This
->datalen
= iDataSize
;
1448 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This
,pStm
,fClearDirty
);
1452 if (This
->loadtime_magic
!= 0xdeadbeef) {
1455 header
[0] = This
->loadtime_magic
;
1456 header
[1] = This
->datalen
;
1457 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1459 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1463 case PICTYPE_BITMAP
:
1464 if (This
->bIsDirty
) {
1465 switch (This
->keepOrigFormat
? This
->loadtime_format
: 0x4d42) {
1467 iSerializeResult
= serializeBMP(This
->desc
.u
.bmp
.hbitmap
, &pIconData
, &iDataSize
);
1470 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This
,pStm
,fClearDirty
);
1473 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This
,pStm
,fClearDirty
);
1476 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This
,pStm
,fClearDirty
);
1479 if (iSerializeResult
) {
1481 if (This->loadtime_magic != 0xdeadbeef) {
1486 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1487 header
[1] = iDataSize
;
1488 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1490 IStream_Write(pStm
, pIconData
, iDataSize
, &dummy
);
1492 HeapFree(GetProcessHeap(), 0, This
->data
);
1493 This
->data
= pIconData
;
1494 This
->datalen
= iDataSize
;
1499 if (This->loadtime_magic != 0xdeadbeef) {
1504 header
[0] = (This
->loadtime_magic
!= 0xdeadbeef) ? This
->loadtime_magic
: 0x0000746c;
1505 header
[1] = This
->datalen
;
1506 IStream_Write(pStm
, header
, 2 * sizeof(DWORD
), &dummy
);
1508 IStream_Write(pStm
, This
->data
, This
->datalen
, &dummy
);
1512 case PICTYPE_METAFILE
:
1513 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1515 case PICTYPE_ENHMETAFILE
:
1516 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This
,pStm
,fClearDirty
);
1519 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This
,pStm
,fClearDirty
);
1522 if (hResult
== S_OK
&& fClearDirty
) This
->bIsDirty
= FALSE
;
1526 static int serializeBMP(HBITMAP hBitmap
, void ** ppBuffer
, unsigned int * pLength
)
1530 BITMAPINFO
* pInfoBitmap
;
1531 int iNumPaletteEntries
;
1532 unsigned char * pPixelData
;
1533 BITMAPFILEHEADER
* pFileHeader
;
1534 BITMAPINFO
* pInfoHeader
;
1536 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1537 sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1539 /* Find out bitmap size and padded length */
1541 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1542 GetDIBits(hDC
, hBitmap
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1544 /* Fetch bitmap palette & pixel data */
1546 pPixelData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1547 GetDIBits(hDC
, hBitmap
, 0, pInfoBitmap
->bmiHeader
.biHeight
, pPixelData
, pInfoBitmap
, DIB_RGB_COLORS
);
1549 /* Calculate the total length required for the BMP data */
1550 if (pInfoBitmap
->bmiHeader
.biClrUsed
!= 0) {
1551 iNumPaletteEntries
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1552 if (iNumPaletteEntries
> 256) iNumPaletteEntries
= 256;
1554 if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8)
1555 iNumPaletteEntries
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1557 iNumPaletteEntries
= 0;
1560 sizeof(BITMAPFILEHEADER
) +
1561 sizeof(BITMAPINFOHEADER
) +
1562 iNumPaletteEntries
* sizeof(RGBQUAD
) +
1563 pInfoBitmap
->bmiHeader
.biSizeImage
;
1564 *ppBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, *pLength
);
1566 /* Fill the BITMAPFILEHEADER */
1567 pFileHeader
= (BITMAPFILEHEADER
*)(*ppBuffer
);
1568 pFileHeader
->bfType
= 0x4d42;
1569 pFileHeader
->bfSize
= *pLength
;
1570 pFileHeader
->bfOffBits
=
1571 sizeof(BITMAPFILEHEADER
) +
1572 sizeof(BITMAPINFOHEADER
) +
1573 iNumPaletteEntries
* sizeof(RGBQUAD
);
1575 /* Fill the BITMAPINFOHEADER and the palette data */
1576 pInfoHeader
= (BITMAPINFO
*)((unsigned char *)(*ppBuffer
) + sizeof(BITMAPFILEHEADER
));
1577 memcpy(pInfoHeader
, pInfoBitmap
, sizeof(BITMAPINFOHEADER
) + iNumPaletteEntries
* sizeof(RGBQUAD
));
1579 (unsigned char *)(*ppBuffer
) +
1580 sizeof(BITMAPFILEHEADER
) +
1581 sizeof(BITMAPINFOHEADER
) +
1582 iNumPaletteEntries
* sizeof(RGBQUAD
),
1583 pPixelData
, pInfoBitmap
->bmiHeader
.biSizeImage
);
1586 HeapFree(GetProcessHeap(), 0, pPixelData
);
1587 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1591 static int serializeIcon(HICON hIcon
, void ** ppBuffer
, unsigned int * pLength
)
1596 *ppBuffer
= NULL
; *pLength
= 0;
1597 if (GetIconInfo(hIcon
, &infoIcon
)) {
1599 BITMAPINFO
* pInfoBitmap
;
1600 unsigned char * pIconData
= NULL
;
1601 unsigned int iDataSize
= 0;
1603 pInfoBitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1605 /* Find out icon size */
1607 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1608 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1610 /* Auxiliary pointers */
1611 CURSORICONFILEDIR
* pIconDir
;
1612 CURSORICONFILEDIRENTRY
* pIconEntry
;
1613 BITMAPINFOHEADER
* pIconBitmapHeader
;
1614 unsigned int iOffsetPalette
;
1615 unsigned int iOffsetColorData
;
1616 unsigned int iOffsetMaskData
;
1618 unsigned int iLengthScanLineColor
;
1619 unsigned int iLengthScanLineMask
;
1620 unsigned int iNumEntriesPalette
;
1622 iLengthScanLineMask
= ((pInfoBitmap
->bmiHeader
.biWidth
+ 31) >> 5) << 2;
1623 iLengthScanLineColor
= ((pInfoBitmap
->bmiHeader
.biWidth
* pInfoBitmap
->bmiHeader
.biBitCount
+ 31) >> 5) << 2;
1625 FIXME("DEBUG: bitmap size is %d x %d\n",
1626 pInfoBitmap->bmiHeader.biWidth,
1627 pInfoBitmap->bmiHeader.biHeight);
1628 FIXME("DEBUG: bitmap bpp is %d\n",
1629 pInfoBitmap->bmiHeader.biBitCount);
1630 FIXME("DEBUG: bitmap nplanes is %d\n",
1631 pInfoBitmap->bmiHeader.biPlanes);
1632 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1633 pInfoBitmap->bmiHeader.biSizeImage);
1635 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1636 iDataSize
+= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
) + sizeof(BITMAPINFOHEADER
);
1637 pIconData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, iDataSize
);
1639 /* Fill out the CURSORICONFILEDIR */
1640 pIconDir
= (CURSORICONFILEDIR
*)pIconData
;
1641 pIconDir
->idType
= 1;
1642 pIconDir
->idCount
= 1;
1644 /* Fill out the CURSORICONFILEDIRENTRY */
1645 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1646 pIconEntry
->bWidth
= (unsigned char)pInfoBitmap
->bmiHeader
.biWidth
;
1647 pIconEntry
->bHeight
= (unsigned char)pInfoBitmap
->bmiHeader
.biHeight
;
1648 pIconEntry
->bColorCount
=
1649 (pInfoBitmap
->bmiHeader
.biBitCount
< 8)
1650 ? 1 << pInfoBitmap
->bmiHeader
.biBitCount
1652 pIconEntry
->xHotspot
= pInfoBitmap
->bmiHeader
.biPlanes
;
1653 pIconEntry
->yHotspot
= pInfoBitmap
->bmiHeader
.biBitCount
;
1654 pIconEntry
->dwDIBSize
= 0;
1655 pIconEntry
->dwDIBOffset
= 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
);
1657 /* Fill out the BITMAPINFOHEADER */
1658 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1659 memcpy(pIconBitmapHeader
, &pInfoBitmap
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
1661 /* Find out whether a palette exists for the bitmap */
1662 if ( (pInfoBitmap
->bmiHeader
.biBitCount
== 16 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)
1663 || (pInfoBitmap
->bmiHeader
.biBitCount
== 24)
1664 || (pInfoBitmap
->bmiHeader
.biBitCount
== 32 && pInfoBitmap
->bmiHeader
.biCompression
== BI_RGB
)) {
1665 iNumEntriesPalette
= pInfoBitmap
->bmiHeader
.biClrUsed
;
1666 if (iNumEntriesPalette
> 256) iNumEntriesPalette
= 256;
1667 } else if ((pInfoBitmap
->bmiHeader
.biBitCount
== 16 || pInfoBitmap
->bmiHeader
.biBitCount
== 32)
1668 && pInfoBitmap
->bmiHeader
.biCompression
== BI_BITFIELDS
) {
1669 iNumEntriesPalette
= 3;
1670 } else if (pInfoBitmap
->bmiHeader
.biBitCount
<= 8) {
1671 iNumEntriesPalette
= 1 << pInfoBitmap
->bmiHeader
.biBitCount
;
1673 iNumEntriesPalette
= 0;
1676 /* Add bitmap size and header size to icon data size. */
1677 iOffsetPalette
= iDataSize
;
1678 iDataSize
+= iNumEntriesPalette
* sizeof(DWORD
);
1679 iOffsetColorData
= iDataSize
;
1680 iDataSize
+= pIconBitmapHeader
->biSizeImage
;
1681 iOffsetMaskData
= iDataSize
;
1682 iDataSize
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1683 pIconBitmapHeader
->biSizeImage
+= pIconBitmapHeader
->biHeight
* iLengthScanLineMask
;
1684 pIconBitmapHeader
->biHeight
*= 2;
1685 pIconData
= HeapReAlloc(GetProcessHeap(), 0, pIconData
, iDataSize
);
1686 pIconEntry
= (CURSORICONFILEDIRENTRY
*)(pIconData
+ 3 * sizeof(WORD
));
1687 pIconBitmapHeader
= (BITMAPINFOHEADER
*)(pIconData
+ 3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1688 pIconEntry
->dwDIBSize
= iDataSize
- (3 * sizeof(WORD
) + sizeof(CURSORICONFILEDIRENTRY
));
1690 /* Get the actual bitmap data from the icon bitmap */
1691 GetDIBits(hDC
, infoIcon
.hbmColor
, 0, pInfoBitmap
->bmiHeader
.biHeight
,
1692 pIconData
+ iOffsetColorData
, pInfoBitmap
, DIB_RGB_COLORS
);
1693 if (iNumEntriesPalette
> 0) {
1694 memcpy(pIconData
+ iOffsetPalette
, pInfoBitmap
->bmiColors
,
1695 iNumEntriesPalette
* sizeof(RGBQUAD
));
1698 /* Reset all values so that GetDIBits call succeeds */
1699 memset(pIconData
+ iOffsetMaskData
, 0, iDataSize
- iOffsetMaskData
);
1700 memset(pInfoBitmap
, 0, sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
));
1701 pInfoBitmap
->bmiHeader
.biSize
= sizeof(pInfoBitmap
->bmiHeader
);
1703 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1704 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1705 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1707 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1712 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, 0, NULL
, pInfoBitmap
, DIB_RGB_COLORS
);
1713 GetDIBits(hDC
, infoIcon
.hbmMask
, 0, pIconEntry
->bHeight
, pIconData
+ iOffsetMaskData
, pInfoBitmap
, DIB_RGB_COLORS
);
1715 /* Write out everything produced so far to the stream */
1716 *ppBuffer
= pIconData
; *pLength
= iDataSize
;
1720 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1725 Remarks (from MSDN entry on GetIconInfo):
1727 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1728 members of ICONINFO. The calling application must manage
1729 these bitmaps and delete them when they are no longer
1732 if (hDC
) ReleaseDC(0, hDC
);
1733 DeleteObject(infoIcon
.hbmMask
);
1734 if (infoIcon
.hbmColor
) DeleteObject(infoIcon
.hbmColor
);
1735 HeapFree(GetProcessHeap(), 0, pInfoBitmap
);
1737 printf("ERROR: Unable to get icon information (error %lu)\n",
1743 static HRESULT WINAPI
OLEPictureImpl_GetSizeMax(
1744 IPersistStream
* iface
,ULARGE_INTEGER
*pcbSize
)
1746 ICOM_THIS_From_IPersistStream(IPicture
, iface
);
1747 FIXME("(%p,%p),stub!\n",This
,pcbSize
);
1751 /************************************************************************
1754 /************************************************************************
1755 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1757 * See Windows documentation for more details on IUnknown methods.
1759 static HRESULT WINAPI
OLEPictureImpl_IDispatch_QueryInterface(
1764 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1766 return IPicture_QueryInterface(This
, riid
, ppvoid
);
1769 /************************************************************************
1770 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1772 * See Windows documentation for more details on IUnknown methods.
1774 static ULONG WINAPI
OLEPictureImpl_IDispatch_AddRef(
1777 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1779 return IPicture_AddRef(This
);
1782 /************************************************************************
1783 * OLEPictureImpl_IDispatch_Release (IUnknown)
1785 * See Windows documentation for more details on IUnknown methods.
1787 static ULONG WINAPI
OLEPictureImpl_IDispatch_Release(
1790 ICOM_THIS_From_IDispatch(IPicture
, iface
);
1792 return IPicture_Release(This
);
1795 /************************************************************************
1796 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1798 * See Windows documentation for more details on IDispatch methods.
1800 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfoCount(
1802 unsigned int* pctinfo
)
1809 /************************************************************************
1810 * OLEPictureImpl_GetTypeInfo (IDispatch)
1812 * See Windows documentation for more details on IDispatch methods.
1814 static HRESULT WINAPI
OLEPictureImpl_GetTypeInfo(
1818 ITypeInfo
** ppTInfo
)
1825 /************************************************************************
1826 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1828 * See Windows documentation for more details on IDispatch methods.
1830 static HRESULT WINAPI
OLEPictureImpl_GetIDsOfNames(
1833 LPOLESTR
* rgszNames
,
1843 /************************************************************************
1844 * OLEPictureImpl_Invoke (IDispatch)
1846 * See Windows documentation for more details on IDispatch methods.
1848 static HRESULT WINAPI
OLEPictureImpl_Invoke(
1850 DISPID dispIdMember
,
1854 DISPPARAMS
* pDispParams
,
1855 VARIANT
* pVarResult
,
1856 EXCEPINFO
* pExepInfo
,
1859 FIXME("(dispid: %ld):Stub\n",dispIdMember
);
1861 VariantInit(pVarResult
);
1862 V_VT(pVarResult
) = VT_BOOL
;
1863 V_BOOL(pVarResult
) = FALSE
;
1868 static IPictureVtbl OLEPictureImpl_VTable
=
1870 OLEPictureImpl_QueryInterface
,
1871 OLEPictureImpl_AddRef
,
1872 OLEPictureImpl_Release
,
1873 OLEPictureImpl_get_Handle
,
1874 OLEPictureImpl_get_hPal
,
1875 OLEPictureImpl_get_Type
,
1876 OLEPictureImpl_get_Width
,
1877 OLEPictureImpl_get_Height
,
1878 OLEPictureImpl_Render
,
1879 OLEPictureImpl_set_hPal
,
1880 OLEPictureImpl_get_CurDC
,
1881 OLEPictureImpl_SelectPicture
,
1882 OLEPictureImpl_get_KeepOriginalFormat
,
1883 OLEPictureImpl_put_KeepOriginalFormat
,
1884 OLEPictureImpl_PictureChanged
,
1885 OLEPictureImpl_SaveAsFile
,
1886 OLEPictureImpl_get_Attributes
1889 static IDispatchVtbl OLEPictureImpl_IDispatch_VTable
=
1891 OLEPictureImpl_IDispatch_QueryInterface
,
1892 OLEPictureImpl_IDispatch_AddRef
,
1893 OLEPictureImpl_IDispatch_Release
,
1894 OLEPictureImpl_GetTypeInfoCount
,
1895 OLEPictureImpl_GetTypeInfo
,
1896 OLEPictureImpl_GetIDsOfNames
,
1897 OLEPictureImpl_Invoke
1900 static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable
=
1902 OLEPictureImpl_IPersistStream_QueryInterface
,
1903 OLEPictureImpl_IPersistStream_AddRef
,
1904 OLEPictureImpl_IPersistStream_Release
,
1905 OLEPictureImpl_GetClassID
,
1906 OLEPictureImpl_IsDirty
,
1907 OLEPictureImpl_Load
,
1908 OLEPictureImpl_Save
,
1909 OLEPictureImpl_GetSizeMax
1912 static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable
=
1914 OLEPictureImpl_IConnectionPointContainer_QueryInterface
,
1915 OLEPictureImpl_IConnectionPointContainer_AddRef
,
1916 OLEPictureImpl_IConnectionPointContainer_Release
,
1917 OLEPictureImpl_EnumConnectionPoints
,
1918 OLEPictureImpl_FindConnectionPoint
1921 /***********************************************************************
1922 * OleCreatePictureIndirect (OLEAUT32.419)
1924 HRESULT WINAPI
OleCreatePictureIndirect(LPPICTDESC lpPictDesc
, REFIID riid
,
1925 BOOL fOwn
, LPVOID
*ppvObj
)
1927 OLEPictureImpl
* newPict
= NULL
;
1930 TRACE("(%p,%p,%d,%p)\n", lpPictDesc
, riid
, fOwn
, ppvObj
);
1941 * Try to construct a new instance of the class.
1943 newPict
= OLEPictureImpl_Construct(lpPictDesc
, fOwn
);
1945 if (newPict
== NULL
)
1946 return E_OUTOFMEMORY
;
1949 * Make sure it supports the interface required by the caller.
1951 hr
= IPicture_QueryInterface((IPicture
*)newPict
, riid
, ppvObj
);
1954 * Release the reference obtained in the constructor. If
1955 * the QueryInterface was unsuccessful, it will free the class.
1957 IPicture_Release((IPicture
*)newPict
);
1963 /***********************************************************************
1964 * OleLoadPicture (OLEAUT32.418)
1966 HRESULT WINAPI
OleLoadPicture( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
1967 REFIID riid
, LPVOID
*ppvObj
)
1973 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
1974 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), ppvObj
);
1976 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
1979 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
1981 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1982 IPicture_Release(newpic
);
1986 IPersistStream_Load(ps
,lpstream
);
1987 IPersistStream_Release(ps
);
1988 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
1990 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
1991 IPicture_Release(newpic
);
1995 /***********************************************************************
1996 * OleLoadPictureEx (OLEAUT32.401)
1998 HRESULT WINAPI
OleLoadPictureEx( LPSTREAM lpstream
, LONG lSize
, BOOL fRunmode
,
1999 REFIID riid
, DWORD xsiz
, DWORD ysiz
, DWORD flags
, LPVOID
*ppvObj
)
2005 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2006 lpstream
, lSize
, fRunmode
, debugstr_guid(riid
), xsiz
, ysiz
, flags
, ppvObj
);
2008 hr
= OleCreatePictureIndirect(NULL
,riid
,!fRunmode
,(LPVOID
*)&newpic
);
2011 hr
= IPicture_QueryInterface(newpic
,&IID_IPersistStream
, (LPVOID
*)&ps
);
2013 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2014 IPicture_Release(newpic
);
2018 IPersistStream_Load(ps
,lpstream
);
2019 IPersistStream_Release(ps
);
2020 hr
= IPicture_QueryInterface(newpic
,riid
,ppvObj
);
2022 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2023 IPicture_Release(newpic
);
2027 /***********************************************************************
2028 * OleLoadPicturePath (OLEAUT32.424)
2030 HRESULT WINAPI
OleLoadPicturePath( LPOLESTR szURLorPath
, LPUNKNOWN punkCaller
,
2031 DWORD dwReserved
, OLE_COLOR clrReserved
, REFIID riid
,
2034 static const WCHAR file
[] = { 'f','i','l','e',':','/','/',0 };
2038 HGLOBAL hGlobal
= NULL
;
2039 DWORD dwBytesRead
= 0;
2042 IPersistStream
*pStream
;
2045 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2046 debugstr_w(szURLorPath
), punkCaller
, dwReserved
, clrReserved
,
2047 debugstr_guid(riid
), ppvRet
);
2049 if (!ppvRet
) return E_POINTER
;
2051 if (strncmpW(szURLorPath
, file
, 7) == 0) {
2054 hFile
= CreateFileW(szURLorPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
2056 if (hFile
== INVALID_HANDLE_VALUE
)
2057 return E_UNEXPECTED
;
2059 dwFileSize
= GetFileSize(hFile
, NULL
);
2060 if (dwFileSize
!= INVALID_FILE_SIZE
)
2062 hGlobal
= GlobalAlloc(GMEM_FIXED
,dwFileSize
);
2065 bRead
= ReadFile(hFile
, hGlobal
, dwFileSize
, &dwBytesRead
, NULL
);
2068 GlobalFree(hGlobal
);
2076 return E_UNEXPECTED
;
2078 hRes
= CreateStreamOnHGlobal(hGlobal
, TRUE
, &stream
);
2081 GlobalFree(hGlobal
);
2088 hRes
= CreateBindCtx(0, &pbc
);
2089 if (SUCCEEDED(hRes
))
2091 hRes
= CreateURLMoniker(NULL
, szURLorPath
, &pmnk
);
2092 if (SUCCEEDED(hRes
))
2094 hRes
= IMoniker_BindToStorage(pmnk
, pbc
, NULL
, &IID_IStream
, (LPVOID
*)&stream
);
2095 IMoniker_Release(pmnk
);
2097 IBindCtx_Release(pbc
);
2103 hRes
= CoCreateInstance(&CLSID_StdPicture
, punkCaller
, CLSCTX_INPROC_SERVER
,
2104 &IID_IPicture
, (LPVOID
*)&ipicture
);
2106 IStream_Release(stream
);
2110 hRes
= IPicture_QueryInterface(ipicture
, &IID_IPersistStream
, (LPVOID
*)&pStream
);
2112 IStream_Release(stream
);
2113 IPicture_Release(ipicture
);
2117 hRes
= IPersistStream_Load(pStream
, stream
);
2118 IPersistStream_Release(pStream
);
2119 IStream_Release(stream
);
2122 IPicture_Release(ipicture
);
2126 hRes
= IPicture_QueryInterface(ipicture
,riid
,ppvRet
);
2128 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid
));
2130 IPicture_Release(ipicture
);
2134 /*******************************************************************************
2135 * StdPic ClassFactory
2139 /* IUnknown fields */
2140 IClassFactoryVtbl
*lpVtbl
;
2142 } IClassFactoryImpl
;
2144 static HRESULT WINAPI
2145 SPCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
2146 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2148 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
2149 return E_NOINTERFACE
;
2153 SPCF_AddRef(LPCLASSFACTORY iface
) {
2154 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2155 return InterlockedIncrement(&This
->ref
);
2158 static ULONG WINAPI
SPCF_Release(LPCLASSFACTORY iface
) {
2159 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2160 /* static class, won't be freed */
2161 return InterlockedDecrement(&This
->ref
);
2164 static HRESULT WINAPI
SPCF_CreateInstance(
2165 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
2167 /* Creates an uninitialized picture */
2168 return OleCreatePictureIndirect(NULL
,riid
,TRUE
,ppobj
);
2172 static HRESULT WINAPI
SPCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
2173 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
2174 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
2178 static IClassFactoryVtbl SPCF_Vtbl
= {
2179 SPCF_QueryInterface
,
2182 SPCF_CreateInstance
,
2185 static IClassFactoryImpl STDPIC_CF
= {&SPCF_Vtbl
, 1 };
2187 void _get_STDPIC_CF(LPVOID
*ppv
) { *ppv
= (LPVOID
)&STDPIC_CF
; }