4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 * Support PICTYPE_BITMAP and PICTYPE_ICON, altough only bitmaps very well..
26 * Lots of methods are just stubs.
29 * NOTES (or things that msdn doesn't tell you)
31 * The width and height properties are returned in HIMETRIC units (0.01mm)
32 * IPicture::Render also uses these to select a region of the src picture.
33 * A bitmap's size is converted into these units by using the screen resolution
34 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
39 #include "wine/port.h"
48 /* Must be before wine includes, the header has things conflicting with
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"
81 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
83 #define UINT8 JPEG_UINT8
84 #define UINT16 JPEG_UINT16
86 #define boolean jpeg_boolean
90 #ifndef SONAME_LIBJPEG
91 #define SONAME_LIBJPEG "libjpeg.so"
95 WINE_DEFAULT_DEBUG_CHANNEL(ole);
108 } CURSORICONFILEDIRENTRY;
115 CURSORICONFILEDIRENTRY idEntries[1];
120 /*************************************************************************
121 * Declaration of implementation class
124 typedef struct OLEPictureImpl {
127 * IPicture handles IUnknown
130 const IPictureVtbl *lpVtbl;
131 const IDispatchVtbl *lpvtblIDispatch;
132 const IPersistStreamVtbl *lpvtblIPersistStream;
133 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
135 /* Object reference count */
138 /* We own the object and must destroy it ourselves */
141 /* Picture description */
144 /* These are the pixel size of a bitmap */
148 /* And these are the size of the picture converted into HIMETRIC units */
149 OLE_XSIZE_HIMETRIC himetricWidth;
150 OLE_YSIZE_HIMETRIC himetricHeight;
152 IConnectionPoint *pCP;
157 /* Bitmap transparency mask */
165 BOOL bIsDirty; /* Set to TRUE if picture has changed */
166 unsigned int loadtime_magic; /* If a length header was found, saves value */
167 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
171 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
174 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
176 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
179 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
181 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
184 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
186 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
190 * Predeclare VTables. They get initialized at the end.
192 static const IPictureVtbl OLEPictureImpl_VTable;
193 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
194 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
195 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
197 /***********************************************************************
198 * Implementation of the OLEPictureImpl class.
201 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
205 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
206 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
207 ERR("GetObject fails\n");
210 This->origWidth = bm.bmWidth;
211 This->origHeight = bm.bmHeight;
212 /* The width and height are stored in HIMETRIC units (0.01 mm),
213 so we take our pixel width divide by pixels per inch and
214 multiply by 25.4 * 100 */
215 /* Should we use GetBitmapDimension if available? */
216 hdcRef = CreateCompatibleDC(0);
217 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
218 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
222 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
226 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
227 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
231 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
232 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
233 ERR("GetObject fails on icon bitmap\n");
237 This->origWidth = bm.bmWidth;
238 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
239 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
241 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
242 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
243 ReleaseDC(0, hdcRef);
245 DeleteObject(infoIcon.hbmMask);
246 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
248 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
252 /************************************************************************
253 * OLEPictureImpl_Construct
255 * This method will construct a new instance of the OLEPictureImpl
258 * The caller of this method must release the object when it's
261 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
263 OLEPictureImpl* newObject = 0;
266 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
269 * Allocate space for the object.
271 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
277 * Initialize the virtual function table.
279 newObject->lpVtbl = &OLEPictureImpl_VTable;
280 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
281 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
282 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
284 newObject->pCP = NULL;
285 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
288 HeapFree(GetProcessHeap(), 0, newObject);
293 * Start with one reference count. The caller of this function
294 * must release the interface pointer when it is done.
297 newObject->hDCCur = 0;
299 newObject->fOwn = fOwn;
301 /* dunno about original value */
302 newObject->keepOrigFormat = TRUE;
304 newObject->hbmMask = NULL;
305 newObject->hbmXor = NULL;
306 newObject->loadtime_magic = 0xdeadbeef;
307 newObject->loadtime_format = 0;
308 newObject->bIsDirty = FALSE;
311 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
313 switch(pictDesc->picType) {
315 OLEPictureImpl_SetBitmap(newObject);
318 case PICTYPE_METAFILE:
319 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
320 newObject->himetricWidth = pictDesc->u.wmf.xExt;
321 newObject->himetricHeight = pictDesc->u.wmf.yExt;
325 /* not sure what to do here */
326 newObject->himetricWidth = newObject->himetricHeight = 0;
330 OLEPictureImpl_SetIcon(newObject);
332 case PICTYPE_ENHMETAFILE:
334 FIXME("Unsupported type %d\n", pictDesc->picType);
335 newObject->himetricWidth = newObject->himetricHeight = 0;
339 newObject->desc.picType = PICTYPE_UNINITIALIZED;
342 TRACE("returning %p\n", newObject);
346 /************************************************************************
347 * OLEPictureImpl_Destroy
349 * This method is called by the Release method when the reference
350 * count goes down to 0. It will free all resources used by
352 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
354 TRACE("(%p)\n", Obj);
357 IConnectionPoint_Release(Obj->pCP);
359 if(Obj->fOwn) { /* We need to destroy the picture */
360 switch(Obj->desc.picType) {
362 DeleteObject(Obj->desc.u.bmp.hbitmap);
363 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
364 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
366 case PICTYPE_METAFILE:
367 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
370 DestroyIcon(Obj->desc.u.icon.hicon);
372 case PICTYPE_ENHMETAFILE:
373 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
379 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
383 HeapFree(GetProcessHeap(), 0, Obj->data);
384 HeapFree(GetProcessHeap(), 0, Obj);
388 /************************************************************************
389 * OLEPictureImpl_AddRef (IUnknown)
391 * See Windows documentation for more details on IUnknown methods.
393 static ULONG WINAPI OLEPictureImpl_AddRef(
396 OLEPictureImpl *This = (OLEPictureImpl *)iface;
397 ULONG refCount = InterlockedIncrement(&This->ref);
399 TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1);
404 /************************************************************************
405 * OLEPictureImpl_Release (IUnknown)
407 * See Windows documentation for more details on IUnknown methods.
409 static ULONG WINAPI OLEPictureImpl_Release(
412 OLEPictureImpl *This = (OLEPictureImpl *)iface;
413 ULONG refCount = InterlockedDecrement(&This->ref);
415 TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1);
418 * If the reference count goes down to 0, perform suicide.
420 if (!refCount) OLEPictureImpl_Destroy(This);
425 /************************************************************************
426 * OLEPictureImpl_QueryInterface (IUnknown)
428 * See Windows documentation for more details on IUnknown methods.
430 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
435 OLEPictureImpl *This = (OLEPictureImpl *)iface;
436 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
439 * Perform a sanity check on the parameters.
441 if ( (This==0) || (ppvObject==0) )
445 * Initialize the return parameter.
450 * Compare the riid with the interface IDs implemented by this object.
452 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
453 *ppvObject = (IPicture*)This;
454 else if (IsEqualIID(&IID_IDispatch, riid))
455 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
456 else if (IsEqualIID(&IID_IPictureDisp, riid))
457 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
458 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
459 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
460 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
461 *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
464 * Check that we obtained an interface.
468 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
469 return E_NOINTERFACE;
473 * Query Interface always increases the reference count by one when it is
476 OLEPictureImpl_AddRef((IPicture*)This);
481 /***********************************************************************
482 * OLEPicture_SendNotify (internal)
484 * Sends notification messages of changed properties to any interested
487 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
489 IEnumConnections *pEnum;
492 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
494 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
495 IPropertyNotifySink *sink;
497 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
498 IPropertyNotifySink_OnChanged(sink, dispID);
499 IPropertyNotifySink_Release(sink);
500 IUnknown_Release(CD.pUnk);
502 IEnumConnections_Release(pEnum);
506 /************************************************************************
507 * OLEPictureImpl_get_Handle
509 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
512 OLEPictureImpl *This = (OLEPictureImpl *)iface;
513 TRACE("(%p)->(%p)\n", This, phandle);
514 switch(This->desc.picType) {
519 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
521 case PICTYPE_METAFILE:
522 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
525 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
527 case PICTYPE_ENHMETAFILE:
528 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
531 FIXME("Unimplemented type %d\n", This->desc.picType);
534 TRACE("returning handle %08x\n", *phandle);
538 /************************************************************************
539 * OLEPictureImpl_get_hPal
541 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
544 OLEPictureImpl *This = (OLEPictureImpl *)iface;
546 TRACE("(%p)->(%p)\n", This, phandle);
551 switch (This->desc.picType) {
552 case PICTYPE_UNINITIALIZED:
558 *phandle = (OLE_HANDLE)This->desc.u.bmp.hpal;
562 case PICTYPE_METAFILE:
563 case PICTYPE_ENHMETAFILE:
565 FIXME("unimplemented for type %d. Returning 0 palette.\n",
571 TRACE("returning 0x%08lx, palette handle %08x\n", hres, *phandle);
575 /************************************************************************
576 * OLEPictureImpl_get_Type
578 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
581 OLEPictureImpl *This = (OLEPictureImpl *)iface;
582 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
583 *ptype = This->desc.picType;
587 /************************************************************************
588 * OLEPictureImpl_get_Width
590 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
591 OLE_XSIZE_HIMETRIC *pwidth)
593 OLEPictureImpl *This = (OLEPictureImpl *)iface;
594 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
595 *pwidth = This->himetricWidth;
599 /************************************************************************
600 * OLEPictureImpl_get_Height
602 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
603 OLE_YSIZE_HIMETRIC *pheight)
605 OLEPictureImpl *This = (OLEPictureImpl *)iface;
606 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
607 *pheight = This->himetricHeight;
611 /************************************************************************
612 * OLEPictureImpl_Render
614 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
615 LONG x, LONG y, LONG cx, LONG cy,
616 OLE_XPOS_HIMETRIC xSrc,
617 OLE_YPOS_HIMETRIC ySrc,
618 OLE_XSIZE_HIMETRIC cxSrc,
619 OLE_YSIZE_HIMETRIC cySrc,
622 OLEPictureImpl *This = (OLEPictureImpl *)iface;
623 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
624 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
626 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
627 prcWBounds->right, prcWBounds->bottom);
630 * While the documentation suggests this to be here (or after rendering?)
631 * it does cause an endless recursion in my sample app. -MM 20010804
632 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
635 switch(This->desc.picType) {
641 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
642 NB y-axis gets flipped */
644 hdcBmp = CreateCompatibleDC(0);
645 SetMapMode(hdcBmp, MM_ANISOTROPIC);
646 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
647 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
648 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
649 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
652 HDC hdcMask = CreateCompatibleDC(0);
653 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
655 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
657 SetMapMode(hdcMask, MM_ANISOTROPIC);
658 SetWindowOrgEx(hdcMask, 0, 0, NULL);
659 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
660 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
661 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
663 SetBkColor(hdc, RGB(255, 255, 255));
664 SetTextColor(hdc, RGB(0, 0, 0));
665 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
666 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
668 SelectObject(hdcMask, hOldbm);
671 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
672 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
675 SelectObject(hdcBmp, hbmpOld);
680 FIXME("Not quite correct implementation of rendering icons...\n");
681 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
684 case PICTYPE_METAFILE:
685 case PICTYPE_ENHMETAFILE:
687 FIXME("type %d not implemented\n", This->desc.picType);
693 /************************************************************************
694 * OLEPictureImpl_set_hPal
696 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
699 OLEPictureImpl *This = (OLEPictureImpl *)iface;
700 FIXME("(%p)->(%08x): stub\n", This, hpal);
701 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
705 /************************************************************************
706 * OLEPictureImpl_get_CurDC
708 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
711 OLEPictureImpl *This = (OLEPictureImpl *)iface;
712 TRACE("(%p), returning %p\n", This, This->hDCCur);
713 if (phdc) *phdc = This->hDCCur;
717 /************************************************************************
718 * OLEPictureImpl_SelectPicture
720 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
723 OLE_HANDLE *phbmpOut)
725 OLEPictureImpl *This = (OLEPictureImpl *)iface;
726 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
727 if (This->desc.picType == PICTYPE_BITMAP) {
728 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
731 *phdcOut = This->hDCCur;
732 This->hDCCur = hdcIn;
734 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
737 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
742 /************************************************************************
743 * OLEPictureImpl_get_KeepOriginalFormat
745 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
748 OLEPictureImpl *This = (OLEPictureImpl *)iface;
749 TRACE("(%p)->(%p)\n", This, pfKeep);
752 *pfKeep = This->keepOrigFormat;
756 /************************************************************************
757 * OLEPictureImpl_put_KeepOriginalFormat
759 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
762 OLEPictureImpl *This = (OLEPictureImpl *)iface;
763 TRACE("(%p)->(%d)\n", This, keep);
764 This->keepOrigFormat = keep;
765 /* FIXME: what DISPID notification here? */
769 /************************************************************************
770 * OLEPictureImpl_PictureChanged
772 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
774 OLEPictureImpl *This = (OLEPictureImpl *)iface;
775 TRACE("(%p)->()\n", This);
776 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
777 This->bIsDirty = TRUE;
781 /************************************************************************
782 * OLEPictureImpl_SaveAsFile
784 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
789 OLEPictureImpl *This = (OLEPictureImpl *)iface;
790 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
791 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
794 /************************************************************************
795 * OLEPictureImpl_get_Attributes
797 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
800 OLEPictureImpl *This = (OLEPictureImpl *)iface;
801 TRACE("(%p)->(%p).\n", This, pdwAttr);
803 switch (This->desc.picType) {
804 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
805 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
806 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
807 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
813 /************************************************************************
814 * IConnectionPointContainer
816 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
817 IConnectionPointContainer* iface,
821 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
823 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
826 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
827 IConnectionPointContainer* iface)
829 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
831 return IPicture_AddRef((IPicture *)This);
834 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
835 IConnectionPointContainer* iface)
837 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
839 return IPicture_Release((IPicture *)This);
842 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
843 IConnectionPointContainer* iface,
844 IEnumConnectionPoints** ppEnum)
846 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
848 FIXME("(%p,%p), stub!\n",This,ppEnum);
852 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
853 IConnectionPointContainer* iface,
855 IConnectionPoint **ppCP)
857 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
858 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
862 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
863 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
864 FIXME("no connection point for %s\n",debugstr_guid(riid));
865 return CONNECT_E_NOCONNECTION;
869 /************************************************************************
873 /************************************************************************
874 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
876 * See Windows documentation for more details on IUnknown methods.
878 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
879 IPersistStream* iface,
883 OLEPictureImpl *This = impl_from_IPersistStream(iface);
885 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
888 /************************************************************************
889 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
891 * See Windows documentation for more details on IUnknown methods.
893 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
894 IPersistStream* iface)
896 OLEPictureImpl *This = impl_from_IPersistStream(iface);
898 return IPicture_AddRef((IPicture *)This);
901 /************************************************************************
902 * OLEPictureImpl_IPersistStream_Release (IUnknown)
904 * See Windows documentation for more details on IUnknown methods.
906 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
907 IPersistStream* iface)
909 OLEPictureImpl *This = impl_from_IPersistStream(iface);
911 return IPicture_Release((IPicture *)This);
914 /************************************************************************
915 * OLEPictureImpl_IPersistStream_GetClassID
917 static HRESULT WINAPI OLEPictureImpl_GetClassID(
918 IPersistStream* iface,CLSID* pClassID)
920 TRACE("(%p)\n", pClassID);
921 memcpy(pClassID, &CLSID_StdPicture, sizeof(*pClassID));
925 /************************************************************************
926 * OLEPictureImpl_IPersistStream_IsDirty
928 static HRESULT WINAPI OLEPictureImpl_IsDirty(
929 IPersistStream* iface)
931 OLEPictureImpl *This = impl_from_IPersistStream(iface);
932 FIXME("(%p),stub!\n",This);
936 #ifdef HAVE_JPEGLIB_H
938 static void *libjpeg_handle;
939 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
940 MAKE_FUNCPTR(jpeg_std_error);
941 MAKE_FUNCPTR(jpeg_CreateDecompress);
942 MAKE_FUNCPTR(jpeg_read_header);
943 MAKE_FUNCPTR(jpeg_start_decompress);
944 MAKE_FUNCPTR(jpeg_read_scanlines);
945 MAKE_FUNCPTR(jpeg_finish_decompress);
946 MAKE_FUNCPTR(jpeg_destroy_decompress);
949 static void *load_libjpeg(void)
951 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
953 #define LOAD_FUNCPTR(f) \
954 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
955 libjpeg_handle = NULL; \
959 LOAD_FUNCPTR(jpeg_std_error);
960 LOAD_FUNCPTR(jpeg_CreateDecompress);
961 LOAD_FUNCPTR(jpeg_read_header);
962 LOAD_FUNCPTR(jpeg_start_decompress);
963 LOAD_FUNCPTR(jpeg_read_scanlines);
964 LOAD_FUNCPTR(jpeg_finish_decompress);
965 LOAD_FUNCPTR(jpeg_destroy_decompress);
968 return libjpeg_handle;
971 /* for the jpeg decompressor source manager. */
972 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
974 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
975 ERR("(), should not get here.\n");
979 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
980 TRACE("Skipping %ld bytes...\n", num_bytes);
981 cinfo->src->next_input_byte += num_bytes;
982 cinfo->src->bytes_in_buffer -= num_bytes;
985 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
986 ERR("(desired=%d), should not get here.\n",desired);
989 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
990 #endif /* HAVE_JPEGLIB_H */
994 static void *libungif_handle;
995 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
996 MAKE_FUNCPTR(DGifOpen);
997 MAKE_FUNCPTR(DGifSlurp);
998 MAKE_FUNCPTR(DGifCloseFile);
1002 unsigned char *data;
1003 unsigned int curoff;
1007 static void *load_libungif(void)
1009 if(((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) ||
1010 ((libungif_handle = wine_dlopen(SONAME_LIBGIF , RTLD_NOW, NULL, 0)) != NULL)
1013 #define LOAD_FUNCPTR(f) \
1014 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
1015 libungif_handle = NULL; \
1019 LOAD_FUNCPTR(DGifOpen);
1020 LOAD_FUNCPTR(DGifSlurp);
1021 LOAD_FUNCPTR(DGifCloseFile);
1024 return libungif_handle;
1027 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
1028 struct gifdata *gd = (struct gifdata*)gif->UserData;
1030 if (len+gd->curoff > gd->len) {
1031 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
1032 len = gd->len - gd->curoff;
1034 memcpy(data, gd->data+gd->curoff, len);
1039 #endif /* HAVE_GIF */
1042 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1054 int transparent = -1;
1058 if(!libungif_handle) {
1059 if(!load_libungif()) {
1060 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF);
1068 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1069 ret = pDGifSlurp(gif);
1070 if (ret == GIF_ERROR) {
1071 FIXME("Failed reading GIF using libgif.\n");
1074 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1075 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1076 TRACE("imgcnt %d\n", gif->ImageCount);
1077 if (gif->ImageCount<1) {
1078 FIXME("GIF stream does not have images inside?\n");
1081 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1082 gif->Image.Width, gif->Image.Height,
1083 gif->Image.Left, gif->Image.Top,
1084 gif->Image.Interlace
1087 padding = (gif->SWidth+3) & ~3;
1088 si = gif->SavedImages+0;
1089 gid = &(si->ImageDesc);
1091 if (!cm) cm = gif->SColorMap;
1092 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1093 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1095 /* look for the transparent color extension */
1096 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1097 eb = si->ExtensionBlocks + i;
1098 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1099 if ((eb->Bytes[0] & 1) == 1) {
1100 transparent = (unsigned char)eb->Bytes[3];
1105 for (i = 0; i < cm->ColorCount; i++) {
1106 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1107 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1108 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1109 if (i == transparent) {
1110 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1111 bmi->bmiColors[i].rgbGreen,
1112 bmi->bmiColors[i].rgbBlue);
1116 /* Map to in picture coordinates */
1117 for (i = 0, j = 0; i < gid->Height; i++) {
1118 if (gif->Image.Interlace) {
1120 bytes + (gid->Top + j) * padding + gid->Left,
1121 si->RasterBits + i * gid->Width,
1124 /* Lower bits of interlaced counter encode current interlace */
1125 if (j & 1) j += 2; /* Currently filling odd rows */
1126 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1127 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1129 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1130 /* End of current interlace, go to next interlace */
1131 if (j & 2) j = 1; /* Next iteration fills odd rows */
1132 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1133 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1137 bytes + (gid->Top + i) * padding + gid->Left,
1138 si->RasterBits + i * gid->Width,
1143 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1144 bmi->bmiHeader.biWidth = gif->SWidth;
1145 bmi->bmiHeader.biHeight = -gif->SHeight;
1146 bmi->bmiHeader.biPlanes = 1;
1147 bmi->bmiHeader.biBitCount = 8;
1148 bmi->bmiHeader.biCompression = BI_RGB;
1149 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1150 bmi->bmiHeader.biXPelsPerMeter = 0;
1151 bmi->bmiHeader.biYPelsPerMeter = 0;
1152 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1153 bmi->bmiHeader.biClrImportant = 0;
1156 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1165 if (transparent > -1) {
1166 /* Create the Mask */
1167 HDC hdc = CreateCompatibleDC(0);
1168 HDC hdcMask = CreateCompatibleDC(0);
1170 HBITMAP hOldbitmapmask;
1172 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1175 This->hbmXor = CreateDIBitmap(
1184 bmi->bmiColors[0].rgbRed = 0;
1185 bmi->bmiColors[0].rgbGreen = 0;
1186 bmi->bmiColors[0].rgbBlue = 0;
1187 bmi->bmiColors[1].rgbRed = 255;
1188 bmi->bmiColors[1].rgbGreen = 255;
1189 bmi->bmiColors[1].rgbBlue = 255;
1191 bmi->bmiHeader.biBitCount = 1;
1192 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1193 bmi->bmiHeader.biClrUsed = 2;
1195 for (i = 0; i < gif->SHeight; i++) {
1196 unsigned char * colorPointer = bytes + padding * i;
1197 unsigned char * monoPointer = bytes + monopadding * i;
1198 for (j = 0; j < gif->SWidth; j++) {
1199 unsigned char pixel = colorPointer[j];
1200 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1201 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1205 hTempMask = CreateDIBitmap(
1215 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1216 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1217 hOldbitmap = SelectObject(hdc, hTempMask);
1218 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1220 SetBkColor(hdc, RGB(255, 255, 255));
1221 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1223 /* We no longer need the original bitmap, so we apply the first
1224 transformation with the mask to speed up the rendering */
1225 SelectObject(hdc, This->hbmXor);
1226 SetBkColor(hdc, RGB(0,0,0));
1227 SetTextColor(hdc, RGB(255,255,255));
1228 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1229 hdcMask, 0, 0, SRCAND);
1231 SelectObject(hdc, hOldbitmap);
1232 SelectObject(hdcMask, hOldbitmapmask);
1235 DeleteObject(hTempMask);
1239 This->desc.picType = PICTYPE_BITMAP;
1240 OLEPictureImpl_SetBitmap(This);
1241 pDGifCloseFile(gif);
1242 HeapFree(GetProcessHeap(),0,bytes);
1245 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1250 static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1252 #ifdef HAVE_JPEGLIB_H
1253 struct jpeg_decompress_struct jd;
1254 struct jpeg_error_mgr jerr;
1257 JSAMPROW samprow,oldsamprow;
1258 BITMAPINFOHEADER bmi;
1261 struct jpeg_source_mgr xjsm;
1265 if(!libjpeg_handle) {
1266 if(!load_libjpeg()) {
1267 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1272 /* This is basically so we can use in-memory data for jpeg decompression.
1273 * We need to have all the functions.
1275 xjsm.next_input_byte = xbuf;
1276 xjsm.bytes_in_buffer = xread;
1277 xjsm.init_source = _jpeg_init_source;
1278 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1279 xjsm.skip_input_data = _jpeg_skip_input_data;
1280 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1281 xjsm.term_source = _jpeg_term_source;
1283 jd.err = pjpeg_std_error(&jerr);
1284 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1285 * jpeg_create_decompress(&jd); */
1286 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1288 ret=pjpeg_read_header(&jd,TRUE);
1289 jd.out_color_space = JCS_RGB;
1290 pjpeg_start_decompress(&jd);
1291 if (ret != JPEG_HEADER_OK) {
1292 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1293 HeapFree(GetProcessHeap(),0,xbuf);
1297 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1298 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1299 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1302 oldsamprow = samprow;
1303 while ( jd.output_scanline<jd.output_height ) {
1304 x = pjpeg_read_scanlines(&jd,&samprow,1);
1306 FIXME("failed to read current scanline?\n");
1309 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1310 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1311 *(bits++) = *(samprow+2);
1312 *(bits++) = *(samprow+1);
1313 *(bits++) = *(samprow);
1315 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1316 samprow = oldsamprow;
1320 bmi.biSize = sizeof(bmi);
1321 bmi.biWidth = jd.output_width;
1322 bmi.biHeight = -jd.output_height;
1324 bmi.biBitCount = jd.output_components<<3;
1325 bmi.biCompression = BI_RGB;
1326 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1327 bmi.biXPelsPerMeter = 0;
1328 bmi.biYPelsPerMeter = 0;
1330 bmi.biClrImportant = 0;
1332 HeapFree(GetProcessHeap(),0,samprow);
1333 pjpeg_finish_decompress(&jd);
1334 pjpeg_destroy_decompress(&jd);
1336 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1345 This->desc.picType = PICTYPE_BITMAP;
1346 OLEPictureImpl_SetBitmap(This);
1347 HeapFree(GetProcessHeap(),0,bits);
1350 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1355 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1357 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1358 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1361 /* Does not matter whether this is a coreheader or not, we only use
1362 * components which are in both
1365 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1369 xbuf+bfh->bfOffBits,
1374 This->desc.picType = PICTYPE_BITMAP;
1375 OLEPictureImpl_SetBitmap(This);
1379 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1382 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1387 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1388 FIXME("icon.idType=%d\n",cifd->idType);
1389 FIXME("icon.idCount=%d\n",cifd->idCount);
1391 for (i=0;i<cifd->idCount;i++) {
1392 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1393 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1394 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1395 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1396 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1397 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1398 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1399 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1403 /* If we have more than one icon, try to find the best.
1404 * this currently means '32 pixel wide'.
1406 if (cifd->idCount!=1) {
1407 for (i=0;i<cifd->idCount;i++) {
1408 if (cifd->idEntries[i].bWidth == 32)
1411 if (i==cifd->idCount) i=0;
1414 hicon = CreateIconFromResourceEx(
1415 xbuf+cifd->idEntries[i].dwDIBOffset,
1416 cifd->idEntries[i].dwDIBSize,
1419 cifd->idEntries[i].bWidth,
1420 cifd->idEntries[i].bHeight,
1424 FIXME("CreateIcon failed.\n");
1427 This->desc.picType = PICTYPE_ICON;
1428 This->desc.u.icon.hicon = hicon;
1429 This->origWidth = cifd->idEntries[i].bWidth;
1430 This->origHeight = cifd->idEntries[i].bHeight;
1431 hdcRef = CreateCompatibleDC(0);
1432 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1433 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1439 /************************************************************************
1440 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1442 * Loads the binary data from the IStream. Starts at current position.
1443 * There appears to be an 2 DWORD header:
1447 * Currently implemented: BITMAP, ICON, JPEG, GIF
1449 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1450 HRESULT hr = E_FAIL;
1451 BOOL headerisdata = FALSE;
1452 BOOL statfailed = FALSE;
1453 ULONG xread, toread;
1458 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1460 TRACE("(%p,%p)\n",This,pStm);
1462 /****************************************************************************************
1463 * Part 1: Load the data
1465 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1466 * out whether we do.
1468 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1469 * compound file. This may explain most, if not all, of the cases of "no
1470 * header", and the header validation should take this into account.
1471 * At least in Visual Basic 6, resource streams, valid headers are
1472 * header[0] == "lt\0\0",
1473 * header[1] == length_of_stream.
1475 * Also handle streams where we do not have a working "Stat" method by
1476 * reading all data until the end of the stream.
1478 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1480 TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr);
1482 /* we will read at least 8 byte ... just right below */
1483 statstg.cbSize.QuadPart = 8;
1485 hr=IStream_Read(pStm,header,8,&xread);
1486 if (hr || xread!=8) {
1487 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
1491 headerisdata = FALSE;
1493 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1496 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1497 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1498 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1499 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1501 ) {/* Incorrect header, assume none. */
1502 headerisdata = TRUE;
1503 toread = statstg.cbSize.QuadPart-8;
1506 FIXME("Unknown stream header magic: %08lx\n", header[0]);
1511 if (statfailed) { /* we don't know the size ... read all we get */
1513 int origsize = sizeinc;
1516 TRACE("Reading all data from stream.\n");
1517 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1519 memcpy (xbuf, &header, 8);
1521 while (xread < origsize) {
1522 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1527 if (!nread || hr) /* done, or error */
1529 if (xread == origsize) {
1530 origsize += sizeinc;
1531 sizeinc = 2*sizeinc; /* exponential increase */
1532 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1536 TRACE("hr in no-stat loader case is %08lx\n", hr);
1537 TRACE("loaded %ld bytes.\n", xread);
1538 This->datalen = xread;
1541 This->datalen = toread+(headerisdata?8:0);
1542 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1545 memcpy (xbuf, &header, 8);
1547 while (xread < This->datalen) {
1549 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1554 if (xread != This->datalen)
1555 FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
1557 if (This->datalen == 0) { /* Marks the "NONE" picture */
1558 This->desc.picType = PICTYPE_NONE;
1563 /****************************************************************************************
1564 * Part 2: Process the loaded data
1567 magic = xbuf[0] + (xbuf[1]<<8);
1569 case 0x4947: /* GIF */
1570 hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
1572 case 0xd8ff: /* JPEG */
1573 hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
1575 case 0x4d42: /* Bitmap */
1576 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1578 case 0x0000: { /* ICON , first word is dwReserved */
1579 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1585 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1587 for (i=0;i<xread+8;i++) {
1588 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1589 else MESSAGE("%02x ",xbuf[i-8]);
1590 if (i % 10 == 9) MESSAGE("\n");
1596 This->bIsDirty = FALSE;
1598 /* FIXME: this notify is not really documented */
1600 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1604 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1608 BITMAPINFO * pInfoBitmap;
1609 int iNumPaletteEntries;
1610 unsigned char * pPixelData;
1611 BITMAPFILEHEADER * pFileHeader;
1612 BITMAPINFO * pInfoHeader;
1614 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1615 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1617 /* Find out bitmap size and padded length */
1619 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1620 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1622 /* Fetch bitmap palette & pixel data */
1624 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1625 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1627 /* Calculate the total length required for the BMP data */
1628 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1629 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1630 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1632 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1633 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1635 iNumPaletteEntries = 0;
1638 sizeof(BITMAPFILEHEADER) +
1639 sizeof(BITMAPINFOHEADER) +
1640 iNumPaletteEntries * sizeof(RGBQUAD) +
1641 pInfoBitmap->bmiHeader.biSizeImage;
1642 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1644 /* Fill the BITMAPFILEHEADER */
1645 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1646 pFileHeader->bfType = 0x4d42;
1647 pFileHeader->bfSize = *pLength;
1648 pFileHeader->bfOffBits =
1649 sizeof(BITMAPFILEHEADER) +
1650 sizeof(BITMAPINFOHEADER) +
1651 iNumPaletteEntries * sizeof(RGBQUAD);
1653 /* Fill the BITMAPINFOHEADER and the palette data */
1654 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1655 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1657 (unsigned char *)(*ppBuffer) +
1658 sizeof(BITMAPFILEHEADER) +
1659 sizeof(BITMAPINFOHEADER) +
1660 iNumPaletteEntries * sizeof(RGBQUAD),
1661 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1664 HeapFree(GetProcessHeap(), 0, pPixelData);
1665 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1669 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1674 *ppBuffer = NULL; *pLength = 0;
1675 if (GetIconInfo(hIcon, &infoIcon)) {
1677 BITMAPINFO * pInfoBitmap;
1678 unsigned char * pIconData = NULL;
1679 unsigned int iDataSize = 0;
1681 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1683 /* Find out icon size */
1685 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1686 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1688 /* Auxiliary pointers */
1689 CURSORICONFILEDIR * pIconDir;
1690 CURSORICONFILEDIRENTRY * pIconEntry;
1691 BITMAPINFOHEADER * pIconBitmapHeader;
1692 unsigned int iOffsetPalette;
1693 unsigned int iOffsetColorData;
1694 unsigned int iOffsetMaskData;
1696 unsigned int iLengthScanLineColor;
1697 unsigned int iLengthScanLineMask;
1698 unsigned int iNumEntriesPalette;
1700 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1701 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1703 FIXME("DEBUG: bitmap size is %d x %d\n",
1704 pInfoBitmap->bmiHeader.biWidth,
1705 pInfoBitmap->bmiHeader.biHeight);
1706 FIXME("DEBUG: bitmap bpp is %d\n",
1707 pInfoBitmap->bmiHeader.biBitCount);
1708 FIXME("DEBUG: bitmap nplanes is %d\n",
1709 pInfoBitmap->bmiHeader.biPlanes);
1710 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1711 pInfoBitmap->bmiHeader.biSizeImage);
1713 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1714 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1715 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1717 /* Fill out the CURSORICONFILEDIR */
1718 pIconDir = (CURSORICONFILEDIR *)pIconData;
1719 pIconDir->idType = 1;
1720 pIconDir->idCount = 1;
1722 /* Fill out the CURSORICONFILEDIRENTRY */
1723 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1724 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1725 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1726 pIconEntry->bColorCount =
1727 (pInfoBitmap->bmiHeader.biBitCount < 8)
1728 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1730 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1731 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1732 pIconEntry->dwDIBSize = 0;
1733 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1735 /* Fill out the BITMAPINFOHEADER */
1736 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1737 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1739 /* Find out whether a palette exists for the bitmap */
1740 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1741 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1742 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1743 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1744 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1745 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1746 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1747 iNumEntriesPalette = 3;
1748 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1749 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1751 iNumEntriesPalette = 0;
1754 /* Add bitmap size and header size to icon data size. */
1755 iOffsetPalette = iDataSize;
1756 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1757 iOffsetColorData = iDataSize;
1758 iDataSize += pIconBitmapHeader->biSizeImage;
1759 iOffsetMaskData = iDataSize;
1760 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1761 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1762 pIconBitmapHeader->biHeight *= 2;
1763 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1764 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1765 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1766 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1768 /* Get the actual bitmap data from the icon bitmap */
1769 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1770 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1771 if (iNumEntriesPalette > 0) {
1772 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1773 iNumEntriesPalette * sizeof(RGBQUAD));
1776 /* Reset all values so that GetDIBits call succeeds */
1777 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1778 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1779 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1781 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1782 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1783 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1785 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1790 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1791 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1793 /* Write out everything produced so far to the stream */
1794 *ppBuffer = pIconData; *pLength = iDataSize;
1798 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1803 Remarks (from MSDN entry on GetIconInfo):
1805 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1806 members of ICONINFO. The calling application must manage
1807 these bitmaps and delete them when they are no longer
1810 if (hDC) ReleaseDC(0, hDC);
1811 DeleteObject(infoIcon.hbmMask);
1812 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1813 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1815 printf("ERROR: Unable to get icon information (error %lu)\n",
1821 static HRESULT WINAPI OLEPictureImpl_Save(
1822 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1824 HRESULT hResult = E_NOTIMPL;
1826 unsigned int iDataSize;
1828 int iSerializeResult = 0;
1830 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1832 switch (This->desc.picType) {
1834 if (This->bIsDirty) {
1835 if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1836 if (This->loadtime_magic != 0xdeadbeef) {
1839 header[0] = This->loadtime_magic;
1840 header[1] = iDataSize;
1841 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1843 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1845 HeapFree(GetProcessHeap(), 0, This->data);
1846 This->data = pIconData;
1847 This->datalen = iDataSize;
1850 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
1854 if (This->loadtime_magic != 0xdeadbeef) {
1857 header[0] = This->loadtime_magic;
1858 header[1] = This->datalen;
1859 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1861 IStream_Write(pStm, This->data, This->datalen, &dummy);
1865 case PICTYPE_BITMAP:
1866 if (This->bIsDirty) {
1867 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1869 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1872 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1875 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1878 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1881 if (iSerializeResult) {
1883 if (This->loadtime_magic != 0xdeadbeef) {
1888 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1889 header[1] = iDataSize;
1890 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1892 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1894 HeapFree(GetProcessHeap(), 0, This->data);
1895 This->data = pIconData;
1896 This->datalen = iDataSize;
1901 if (This->loadtime_magic != 0xdeadbeef) {
1906 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1907 header[1] = This->datalen;
1908 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1910 IStream_Write(pStm, This->data, This->datalen, &dummy);
1914 case PICTYPE_METAFILE:
1915 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1917 case PICTYPE_ENHMETAFILE:
1918 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1921 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1924 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1928 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1929 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1931 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1932 FIXME("(%p,%p),stub!\n",This,pcbSize);
1937 /************************************************************************
1941 /************************************************************************
1942 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1944 * See Windows documentation for more details on IUnknown methods.
1946 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1951 OLEPictureImpl *This = impl_from_IDispatch(iface);
1953 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1956 /************************************************************************
1957 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1959 * See Windows documentation for more details on IUnknown methods.
1961 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1964 OLEPictureImpl *This = impl_from_IDispatch(iface);
1966 return IPicture_AddRef((IPicture *)This);
1969 /************************************************************************
1970 * OLEPictureImpl_IDispatch_Release (IUnknown)
1972 * See Windows documentation for more details on IUnknown methods.
1974 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1977 OLEPictureImpl *This = impl_from_IDispatch(iface);
1979 return IPicture_Release((IPicture *)This);
1982 /************************************************************************
1983 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1985 * See Windows documentation for more details on IDispatch methods.
1987 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1989 unsigned int* pctinfo)
1991 TRACE("(%p)", pctinfo);
1998 /************************************************************************
1999 * OLEPictureImpl_GetTypeInfo (IDispatch)
2001 * See Windows documentation for more details on IDispatch methods.
2003 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
2007 ITypeInfo** ppTInfo)
2009 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
2013 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
2018 hres = LoadTypeLib(stdole2tlb, &tl);
2021 ERR("Could not load stdole2.tlb\n");
2025 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
2027 ERR("Did not get IPictureDisp typeinfo from typelib, hres %lx\n", hres);
2032 /************************************************************************
2033 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2035 * See Windows documentation for more details on IDispatch methods.
2037 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2040 LPOLESTR* rgszNames,
2050 /************************************************************************
2051 * OLEPictureImpl_Invoke (IDispatch)
2053 * See Windows documentation for more details on IDispatch methods.
2055 static HRESULT WINAPI OLEPictureImpl_Invoke(
2057 DISPID dispIdMember,
2061 DISPPARAMS* pDispParams,
2062 VARIANT* pVarResult,
2063 EXCEPINFO* pExepInfo,
2066 OLEPictureImpl *This = impl_from_IDispatch(iface);
2068 /* validate parameters */
2070 if (!IsEqualIID(riid, &IID_NULL))
2072 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2073 return DISP_E_UNKNOWNNAME;
2078 ERR("null pDispParams not allowed\n");
2079 return DISP_E_PARAMNOTOPTIONAL;
2082 if (wFlags & DISPATCH_PROPERTYGET)
2084 if (pDispParams->cArgs != 0)
2086 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2087 return DISP_E_BADPARAMCOUNT;
2091 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2092 return DISP_E_PARAMNOTOPTIONAL;
2095 else if (wFlags & DISPATCH_PROPERTYPUT)
2097 if (pDispParams->cArgs != 1)
2099 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2100 return DISP_E_BADPARAMCOUNT;
2104 switch (dispIdMember)
2106 case DISPID_PICT_HANDLE:
2107 if (wFlags & DISPATCH_PROPERTYGET)
2109 TRACE("DISPID_PICT_HANDLE\n");
2110 V_VT(pVarResult) = VT_I4;
2111 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2114 case DISPID_PICT_HPAL:
2115 if (wFlags & DISPATCH_PROPERTYGET)
2117 TRACE("DISPID_PICT_HPAL\n");
2118 V_VT(pVarResult) = VT_I4;
2119 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2121 else if (wFlags & DISPATCH_PROPERTYPUT)
2125 TRACE("DISPID_PICT_HPAL\n");
2127 VariantInit(&vararg);
2128 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2132 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2134 VariantClear(&vararg);
2138 case DISPID_PICT_TYPE:
2139 if (wFlags & DISPATCH_PROPERTYGET)
2141 TRACE("DISPID_PICT_TYPE\n");
2142 V_VT(pVarResult) = VT_I2;
2143 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2146 case DISPID_PICT_WIDTH:
2147 if (wFlags & DISPATCH_PROPERTYGET)
2149 TRACE("DISPID_PICT_WIDTH\n");
2150 V_VT(pVarResult) = VT_I4;
2151 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2154 case DISPID_PICT_HEIGHT:
2155 if (wFlags & DISPATCH_PROPERTYGET)
2157 TRACE("DISPID_PICT_HEIGHT\n");
2158 V_VT(pVarResult) = VT_I4;
2159 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2164 ERR("invalid dispid 0x%lx or wFlags 0x%x\n", dispIdMember, wFlags);
2165 return DISP_E_MEMBERNOTFOUND;
2169 static const IPictureVtbl OLEPictureImpl_VTable =
2171 OLEPictureImpl_QueryInterface,
2172 OLEPictureImpl_AddRef,
2173 OLEPictureImpl_Release,
2174 OLEPictureImpl_get_Handle,
2175 OLEPictureImpl_get_hPal,
2176 OLEPictureImpl_get_Type,
2177 OLEPictureImpl_get_Width,
2178 OLEPictureImpl_get_Height,
2179 OLEPictureImpl_Render,
2180 OLEPictureImpl_set_hPal,
2181 OLEPictureImpl_get_CurDC,
2182 OLEPictureImpl_SelectPicture,
2183 OLEPictureImpl_get_KeepOriginalFormat,
2184 OLEPictureImpl_put_KeepOriginalFormat,
2185 OLEPictureImpl_PictureChanged,
2186 OLEPictureImpl_SaveAsFile,
2187 OLEPictureImpl_get_Attributes
2190 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2192 OLEPictureImpl_IDispatch_QueryInterface,
2193 OLEPictureImpl_IDispatch_AddRef,
2194 OLEPictureImpl_IDispatch_Release,
2195 OLEPictureImpl_GetTypeInfoCount,
2196 OLEPictureImpl_GetTypeInfo,
2197 OLEPictureImpl_GetIDsOfNames,
2198 OLEPictureImpl_Invoke
2201 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2203 OLEPictureImpl_IPersistStream_QueryInterface,
2204 OLEPictureImpl_IPersistStream_AddRef,
2205 OLEPictureImpl_IPersistStream_Release,
2206 OLEPictureImpl_GetClassID,
2207 OLEPictureImpl_IsDirty,
2208 OLEPictureImpl_Load,
2209 OLEPictureImpl_Save,
2210 OLEPictureImpl_GetSizeMax
2213 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2215 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2216 OLEPictureImpl_IConnectionPointContainer_AddRef,
2217 OLEPictureImpl_IConnectionPointContainer_Release,
2218 OLEPictureImpl_EnumConnectionPoints,
2219 OLEPictureImpl_FindConnectionPoint
2222 /***********************************************************************
2223 * OleCreatePictureIndirect (OLEAUT32.419)
2225 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2226 BOOL fOwn, LPVOID *ppvObj )
2228 OLEPictureImpl* newPict = NULL;
2231 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2242 * Try to construct a new instance of the class.
2244 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2246 if (newPict == NULL)
2247 return E_OUTOFMEMORY;
2250 * Make sure it supports the interface required by the caller.
2252 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2255 * Release the reference obtained in the constructor. If
2256 * the QueryInterface was unsuccessful, it will free the class.
2258 IPicture_Release((IPicture*)newPict);
2264 /***********************************************************************
2265 * OleLoadPicture (OLEAUT32.418)
2267 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2268 REFIID riid, LPVOID *ppvObj )
2274 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2275 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2277 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2280 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2282 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2283 IPicture_Release(newpic);
2287 IPersistStream_Load(ps,lpstream);
2288 IPersistStream_Release(ps);
2289 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2291 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2292 IPicture_Release(newpic);
2296 /***********************************************************************
2297 * OleLoadPictureEx (OLEAUT32.401)
2299 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2300 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2306 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2307 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2309 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2312 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2314 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2315 IPicture_Release(newpic);
2319 IPersistStream_Load(ps,lpstream);
2320 IPersistStream_Release(ps);
2321 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2323 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2324 IPicture_Release(newpic);
2328 /***********************************************************************
2329 * OleLoadPicturePath (OLEAUT32.424)
2331 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2332 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2335 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2339 HGLOBAL hGlobal = NULL;
2340 DWORD dwBytesRead = 0;
2343 IPersistStream *pStream;
2346 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2347 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2348 debugstr_guid(riid), ppvRet);
2350 if (!ppvRet) return E_POINTER;
2352 if (strncmpW(szURLorPath, file, 7) == 0) {
2355 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2357 if (hFile == INVALID_HANDLE_VALUE)
2358 return E_UNEXPECTED;
2360 dwFileSize = GetFileSize(hFile, NULL);
2361 if (dwFileSize != INVALID_FILE_SIZE )
2363 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2366 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2369 GlobalFree(hGlobal);
2377 return E_UNEXPECTED;
2379 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2382 GlobalFree(hGlobal);
2389 hRes = CreateBindCtx(0, &pbc);
2390 if (SUCCEEDED(hRes))
2392 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2393 if (SUCCEEDED(hRes))
2395 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2396 IMoniker_Release(pmnk);
2398 IBindCtx_Release(pbc);
2404 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2405 &IID_IPicture, (LPVOID*)&ipicture);
2407 IStream_Release(stream);
2411 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2413 IStream_Release(stream);
2414 IPicture_Release(ipicture);
2418 hRes = IPersistStream_Load(pStream, stream);
2419 IPersistStream_Release(pStream);
2420 IStream_Release(stream);
2423 IPicture_Release(ipicture);
2427 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2429 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2431 IPicture_Release(ipicture);
2435 /*******************************************************************************
2436 * StdPic ClassFactory
2440 /* IUnknown fields */
2441 const IClassFactoryVtbl *lpVtbl;
2443 } IClassFactoryImpl;
2445 static HRESULT WINAPI
2446 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2447 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2449 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2450 return E_NOINTERFACE;
2454 SPCF_AddRef(LPCLASSFACTORY iface) {
2455 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2456 return InterlockedIncrement(&This->ref);
2459 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2460 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2461 /* static class, won't be freed */
2462 return InterlockedDecrement(&This->ref);
2465 static HRESULT WINAPI SPCF_CreateInstance(
2466 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2468 /* Creates an uninitialized picture */
2469 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2473 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2474 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2475 FIXME("(%p)->(%d),stub!\n",This,dolock);
2479 static const IClassFactoryVtbl SPCF_Vtbl = {
2480 SPCF_QueryInterface,
2483 SPCF_CreateInstance,
2486 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2488 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }