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
52 #define NONAMELESSUNION
53 #define NONAMELESSSTRUCT
65 #include "wine/debug.h"
66 #include "wine/unicode.h"
68 #include "wine/wingdi16.h"
71 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
73 #define UINT8 JPEG_UINT8
74 #define UINT16 JPEG_UINT16
76 #define boolean jpeg_boolean
80 #ifndef SONAME_LIBJPEG
81 #define SONAME_LIBJPEG "libjpeg.so"
87 WINE_DEFAULT_DEBUG_CHANNEL(ole);
100 } CURSORICONFILEDIRENTRY;
107 CURSORICONFILEDIRENTRY idEntries[1];
112 /*************************************************************************
113 * Declaration of implementation class
116 typedef struct OLEPictureImpl {
119 * IPicture handles IUnknown
122 const IPictureVtbl *lpVtbl;
123 const IDispatchVtbl *lpvtblIDispatch;
124 const IPersistStreamVtbl *lpvtblIPersistStream;
125 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
127 /* Object reference count */
130 /* We own the object and must destroy it ourselves */
133 /* Picture description */
136 /* These are the pixel size of a bitmap */
140 /* And these are the size of the picture converted into HIMETRIC units */
141 OLE_XSIZE_HIMETRIC himetricWidth;
142 OLE_YSIZE_HIMETRIC himetricHeight;
144 IConnectionPoint *pCP;
149 /* Bitmap transparency mask */
157 BOOL bIsDirty; /* Set to TRUE if picture has changed */
158 unsigned int loadtime_magic; /* If a length header was found, saves value */
159 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
163 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
166 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
168 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
171 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
173 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
176 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
178 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
182 * Predeclare VTables. They get initialized at the end.
184 static const IPictureVtbl OLEPictureImpl_VTable;
185 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
186 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
187 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
189 /***********************************************************************
190 * Implementation of the OLEPictureImpl class.
193 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
197 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
198 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
199 ERR("GetObject fails\n");
202 This->origWidth = bm.bmWidth;
203 This->origHeight = bm.bmHeight;
204 /* The width and height are stored in HIMETRIC units (0.01 mm),
205 so we take our pixel width divide by pixels per inch and
206 multiply by 25.4 * 100 */
207 /* Should we use GetBitmapDimension if available? */
208 hdcRef = CreateCompatibleDC(0);
209 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
210 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
214 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
218 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
219 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
223 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
224 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
225 ERR("GetObject fails on icon bitmap\n");
229 This->origWidth = bm.bmWidth;
230 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
231 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
233 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
234 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
235 ReleaseDC(0, hdcRef);
237 DeleteObject(infoIcon.hbmMask);
238 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
240 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
244 /************************************************************************
245 * OLEPictureImpl_Construct
247 * This method will construct a new instance of the OLEPictureImpl
250 * The caller of this method must release the object when it's
253 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
255 OLEPictureImpl* newObject = 0;
258 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
261 * Allocate space for the object.
263 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
269 * Initialize the virtual function table.
271 newObject->lpVtbl = &OLEPictureImpl_VTable;
272 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
273 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
274 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
276 newObject->pCP = NULL;
277 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
280 HeapFree(GetProcessHeap(), 0, newObject);
285 * Start with one reference count. The caller of this function
286 * must release the interface pointer when it is done.
289 newObject->hDCCur = 0;
291 newObject->fOwn = fOwn;
293 /* dunno about original value */
294 newObject->keepOrigFormat = TRUE;
296 newObject->hbmMask = NULL;
297 newObject->hbmXor = NULL;
298 newObject->loadtime_magic = 0xdeadbeef;
299 newObject->loadtime_format = 0;
300 newObject->bIsDirty = FALSE;
303 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
305 switch(pictDesc->picType) {
307 OLEPictureImpl_SetBitmap(newObject);
310 case PICTYPE_METAFILE:
311 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
312 newObject->himetricWidth = pictDesc->u.wmf.xExt;
313 newObject->himetricHeight = pictDesc->u.wmf.yExt;
317 /* not sure what to do here */
318 newObject->himetricWidth = newObject->himetricHeight = 0;
322 OLEPictureImpl_SetIcon(newObject);
324 case PICTYPE_ENHMETAFILE:
326 FIXME("Unsupported type %d\n", pictDesc->picType);
327 newObject->himetricWidth = newObject->himetricHeight = 0;
331 newObject->desc.picType = PICTYPE_UNINITIALIZED;
334 TRACE("returning %p\n", newObject);
338 /************************************************************************
339 * OLEPictureImpl_Destroy
341 * This method is called by the Release method when the reference
342 * count goes down to 0. It will free all resources used by
344 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
346 TRACE("(%p)\n", Obj);
349 IConnectionPoint_Release(Obj->pCP);
351 if(Obj->fOwn) { /* We need to destroy the picture */
352 switch(Obj->desc.picType) {
354 DeleteObject(Obj->desc.u.bmp.hbitmap);
355 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
356 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
358 case PICTYPE_METAFILE:
359 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
362 DestroyIcon(Obj->desc.u.icon.hicon);
364 case PICTYPE_ENHMETAFILE:
365 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
371 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
375 HeapFree(GetProcessHeap(), 0, Obj->data);
376 HeapFree(GetProcessHeap(), 0, Obj);
380 /************************************************************************
381 * OLEPictureImpl_AddRef (IUnknown)
383 * See Windows documentation for more details on IUnknown methods.
385 static ULONG WINAPI OLEPictureImpl_AddRef(
388 OLEPictureImpl *This = (OLEPictureImpl *)iface;
389 ULONG refCount = InterlockedIncrement(&This->ref);
391 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
396 /************************************************************************
397 * OLEPictureImpl_Release (IUnknown)
399 * See Windows documentation for more details on IUnknown methods.
401 static ULONG WINAPI OLEPictureImpl_Release(
404 OLEPictureImpl *This = (OLEPictureImpl *)iface;
405 ULONG refCount = InterlockedDecrement(&This->ref);
407 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
410 * If the reference count goes down to 0, perform suicide.
412 if (!refCount) OLEPictureImpl_Destroy(This);
417 /************************************************************************
418 * OLEPictureImpl_QueryInterface (IUnknown)
420 * See Windows documentation for more details on IUnknown methods.
422 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
427 OLEPictureImpl *This = (OLEPictureImpl *)iface;
428 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
431 * Perform a sanity check on the parameters.
433 if ( (This==0) || (ppvObject==0) )
437 * Initialize the return parameter.
442 * Compare the riid with the interface IDs implemented by this object.
444 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
445 *ppvObject = (IPicture*)This;
446 else if (IsEqualIID(&IID_IDispatch, riid))
447 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
448 else if (IsEqualIID(&IID_IPictureDisp, riid))
449 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
450 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
451 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
452 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
453 *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
456 * Check that we obtained an interface.
460 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
461 return E_NOINTERFACE;
465 * Query Interface always increases the reference count by one when it is
468 OLEPictureImpl_AddRef((IPicture*)This);
473 /***********************************************************************
474 * OLEPicture_SendNotify (internal)
476 * Sends notification messages of changed properties to any interested
479 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
481 IEnumConnections *pEnum;
484 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
486 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
487 IPropertyNotifySink *sink;
489 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
490 IPropertyNotifySink_OnChanged(sink, dispID);
491 IPropertyNotifySink_Release(sink);
492 IUnknown_Release(CD.pUnk);
494 IEnumConnections_Release(pEnum);
498 /************************************************************************
499 * OLEPictureImpl_get_Handle
501 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
504 OLEPictureImpl *This = (OLEPictureImpl *)iface;
505 TRACE("(%p)->(%p)\n", This, phandle);
506 switch(This->desc.picType) {
511 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
513 case PICTYPE_METAFILE:
514 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
517 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
519 case PICTYPE_ENHMETAFILE:
520 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
523 FIXME("Unimplemented type %d\n", This->desc.picType);
526 TRACE("returning handle %08x\n", *phandle);
530 /************************************************************************
531 * OLEPictureImpl_get_hPal
533 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
536 OLEPictureImpl *This = (OLEPictureImpl *)iface;
538 TRACE("(%p)->(%p)\n", This, phandle);
543 switch (This->desc.picType) {
544 case PICTYPE_UNINITIALIZED:
550 *phandle = (OLE_HANDLE)This->desc.u.bmp.hpal;
554 case PICTYPE_METAFILE:
555 case PICTYPE_ENHMETAFILE:
557 FIXME("unimplemented for type %d. Returning 0 palette.\n",
563 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
567 /************************************************************************
568 * OLEPictureImpl_get_Type
570 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
573 OLEPictureImpl *This = (OLEPictureImpl *)iface;
574 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
575 *ptype = This->desc.picType;
579 /************************************************************************
580 * OLEPictureImpl_get_Width
582 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
583 OLE_XSIZE_HIMETRIC *pwidth)
585 OLEPictureImpl *This = (OLEPictureImpl *)iface;
586 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
587 *pwidth = This->himetricWidth;
591 /************************************************************************
592 * OLEPictureImpl_get_Height
594 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
595 OLE_YSIZE_HIMETRIC *pheight)
597 OLEPictureImpl *This = (OLEPictureImpl *)iface;
598 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
599 *pheight = This->himetricHeight;
603 /************************************************************************
604 * OLEPictureImpl_Render
606 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
607 LONG x, LONG y, LONG cx, LONG cy,
608 OLE_XPOS_HIMETRIC xSrc,
609 OLE_YPOS_HIMETRIC ySrc,
610 OLE_XSIZE_HIMETRIC cxSrc,
611 OLE_YSIZE_HIMETRIC cySrc,
614 OLEPictureImpl *This = (OLEPictureImpl *)iface;
615 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
616 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
618 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
619 prcWBounds->right, prcWBounds->bottom);
622 * While the documentation suggests this to be here (or after rendering?)
623 * it does cause an endless recursion in my sample app. -MM 20010804
624 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
627 switch(This->desc.picType) {
633 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
634 NB y-axis gets flipped */
636 hdcBmp = CreateCompatibleDC(0);
637 SetMapMode(hdcBmp, MM_ANISOTROPIC);
638 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
639 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
640 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
641 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
644 HDC hdcMask = CreateCompatibleDC(0);
645 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
647 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
649 SetMapMode(hdcMask, MM_ANISOTROPIC);
650 SetWindowOrgEx(hdcMask, 0, 0, NULL);
651 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
652 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
653 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
655 SetBkColor(hdc, RGB(255, 255, 255));
656 SetTextColor(hdc, RGB(0, 0, 0));
657 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
658 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
660 SelectObject(hdcMask, hOldbm);
663 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
664 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
667 SelectObject(hdcBmp, hbmpOld);
672 FIXME("Not quite correct implementation of rendering icons...\n");
673 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
676 case PICTYPE_METAFILE:
677 case PICTYPE_ENHMETAFILE:
679 FIXME("type %d not implemented\n", This->desc.picType);
685 /************************************************************************
686 * OLEPictureImpl_set_hPal
688 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
691 OLEPictureImpl *This = (OLEPictureImpl *)iface;
692 FIXME("(%p)->(%08x): stub\n", This, hpal);
693 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
697 /************************************************************************
698 * OLEPictureImpl_get_CurDC
700 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
703 OLEPictureImpl *This = (OLEPictureImpl *)iface;
704 TRACE("(%p), returning %p\n", This, This->hDCCur);
705 if (phdc) *phdc = This->hDCCur;
709 /************************************************************************
710 * OLEPictureImpl_SelectPicture
712 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
715 OLE_HANDLE *phbmpOut)
717 OLEPictureImpl *This = (OLEPictureImpl *)iface;
718 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
719 if (This->desc.picType == PICTYPE_BITMAP) {
720 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
723 *phdcOut = This->hDCCur;
724 This->hDCCur = hdcIn;
726 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
729 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
734 /************************************************************************
735 * OLEPictureImpl_get_KeepOriginalFormat
737 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
740 OLEPictureImpl *This = (OLEPictureImpl *)iface;
741 TRACE("(%p)->(%p)\n", This, pfKeep);
744 *pfKeep = This->keepOrigFormat;
748 /************************************************************************
749 * OLEPictureImpl_put_KeepOriginalFormat
751 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
754 OLEPictureImpl *This = (OLEPictureImpl *)iface;
755 TRACE("(%p)->(%d)\n", This, keep);
756 This->keepOrigFormat = keep;
757 /* FIXME: what DISPID notification here? */
761 /************************************************************************
762 * OLEPictureImpl_PictureChanged
764 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
766 OLEPictureImpl *This = (OLEPictureImpl *)iface;
767 TRACE("(%p)->()\n", This);
768 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
769 This->bIsDirty = TRUE;
773 /************************************************************************
774 * OLEPictureImpl_SaveAsFile
776 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
781 OLEPictureImpl *This = (OLEPictureImpl *)iface;
782 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
783 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
786 /************************************************************************
787 * OLEPictureImpl_get_Attributes
789 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
792 OLEPictureImpl *This = (OLEPictureImpl *)iface;
793 TRACE("(%p)->(%p).\n", This, pdwAttr);
795 switch (This->desc.picType) {
796 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
797 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
798 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
799 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
805 /************************************************************************
806 * IConnectionPointContainer
808 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
809 IConnectionPointContainer* iface,
813 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
815 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
818 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
819 IConnectionPointContainer* iface)
821 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
823 return IPicture_AddRef((IPicture *)This);
826 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
827 IConnectionPointContainer* iface)
829 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
831 return IPicture_Release((IPicture *)This);
834 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
835 IConnectionPointContainer* iface,
836 IEnumConnectionPoints** ppEnum)
838 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
840 FIXME("(%p,%p), stub!\n",This,ppEnum);
844 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
845 IConnectionPointContainer* iface,
847 IConnectionPoint **ppCP)
849 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
850 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
854 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
855 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
856 FIXME("no connection point for %s\n",debugstr_guid(riid));
857 return CONNECT_E_NOCONNECTION;
861 /************************************************************************
865 /************************************************************************
866 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
868 * See Windows documentation for more details on IUnknown methods.
870 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
871 IPersistStream* iface,
875 OLEPictureImpl *This = impl_from_IPersistStream(iface);
877 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
880 /************************************************************************
881 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
883 * See Windows documentation for more details on IUnknown methods.
885 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
886 IPersistStream* iface)
888 OLEPictureImpl *This = impl_from_IPersistStream(iface);
890 return IPicture_AddRef((IPicture *)This);
893 /************************************************************************
894 * OLEPictureImpl_IPersistStream_Release (IUnknown)
896 * See Windows documentation for more details on IUnknown methods.
898 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
899 IPersistStream* iface)
901 OLEPictureImpl *This = impl_from_IPersistStream(iface);
903 return IPicture_Release((IPicture *)This);
906 /************************************************************************
907 * OLEPictureImpl_IPersistStream_GetClassID
909 static HRESULT WINAPI OLEPictureImpl_GetClassID(
910 IPersistStream* iface,CLSID* pClassID)
912 TRACE("(%p)\n", pClassID);
913 memcpy(pClassID, &CLSID_StdPicture, sizeof(*pClassID));
917 /************************************************************************
918 * OLEPictureImpl_IPersistStream_IsDirty
920 static HRESULT WINAPI OLEPictureImpl_IsDirty(
921 IPersistStream* iface)
923 OLEPictureImpl *This = impl_from_IPersistStream(iface);
924 FIXME("(%p),stub!\n",This);
928 #ifdef HAVE_JPEGLIB_H
930 static void *libjpeg_handle;
931 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
932 MAKE_FUNCPTR(jpeg_std_error);
933 MAKE_FUNCPTR(jpeg_CreateDecompress);
934 MAKE_FUNCPTR(jpeg_read_header);
935 MAKE_FUNCPTR(jpeg_start_decompress);
936 MAKE_FUNCPTR(jpeg_read_scanlines);
937 MAKE_FUNCPTR(jpeg_finish_decompress);
938 MAKE_FUNCPTR(jpeg_destroy_decompress);
941 static void *load_libjpeg(void)
943 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
945 #define LOAD_FUNCPTR(f) \
946 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
947 libjpeg_handle = NULL; \
951 LOAD_FUNCPTR(jpeg_std_error);
952 LOAD_FUNCPTR(jpeg_CreateDecompress);
953 LOAD_FUNCPTR(jpeg_read_header);
954 LOAD_FUNCPTR(jpeg_start_decompress);
955 LOAD_FUNCPTR(jpeg_read_scanlines);
956 LOAD_FUNCPTR(jpeg_finish_decompress);
957 LOAD_FUNCPTR(jpeg_destroy_decompress);
960 return libjpeg_handle;
963 /* for the jpeg decompressor source manager. */
964 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
966 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
967 ERR("(), should not get here.\n");
971 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
972 TRACE("Skipping %ld bytes...\n", num_bytes);
973 cinfo->src->next_input_byte += num_bytes;
974 cinfo->src->bytes_in_buffer -= num_bytes;
977 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
978 ERR("(desired=%d), should not get here.\n",desired);
981 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
982 #endif /* HAVE_JPEGLIB_H */
990 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
991 struct gifdata *gd = (struct gifdata*)gif->UserData;
993 if (len+gd->curoff > gd->len) {
994 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
995 len = gd->len - gd->curoff;
997 memcpy(data, gd->data+gd->curoff, len);
1003 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1014 int transparent = -1;
1021 gif = DGifOpen((void*)&gd, _gif_inputfunc);
1022 ret = DGifSlurp(gif);
1023 if (ret == GIF_ERROR) {
1024 FIXME("Failed reading GIF using libgif.\n");
1027 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1028 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1029 TRACE("imgcnt %d\n", gif->ImageCount);
1030 if (gif->ImageCount<1) {
1031 FIXME("GIF stream does not have images inside?\n");
1034 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1035 gif->Image.Width, gif->Image.Height,
1036 gif->Image.Left, gif->Image.Top,
1037 gif->Image.Interlace
1040 padding = (gif->SWidth+3) & ~3;
1041 si = gif->SavedImages+0;
1042 gid = &(si->ImageDesc);
1044 if (!cm) cm = gif->SColorMap;
1045 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1046 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1048 /* look for the transparent color extension */
1049 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1050 eb = si->ExtensionBlocks + i;
1051 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1052 if ((eb->Bytes[0] & 1) == 1) {
1053 transparent = (unsigned char)eb->Bytes[3];
1058 for (i = 0; i < cm->ColorCount; i++) {
1059 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1060 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1061 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1062 if (i == transparent) {
1063 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1064 bmi->bmiColors[i].rgbGreen,
1065 bmi->bmiColors[i].rgbBlue);
1069 /* Map to in picture coordinates */
1070 for (i = 0, j = 0; i < gid->Height; i++) {
1071 if (gif->Image.Interlace) {
1073 bytes + (gid->Top + j) * padding + gid->Left,
1074 si->RasterBits + i * gid->Width,
1077 /* Lower bits of interlaced counter encode current interlace */
1078 if (j & 1) j += 2; /* Currently filling odd rows */
1079 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1080 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1082 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1083 /* End of current interlace, go to next interlace */
1084 if (j & 2) j = 1; /* Next iteration fills odd rows */
1085 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1086 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1090 bytes + (gid->Top + i) * padding + gid->Left,
1091 si->RasterBits + i * gid->Width,
1096 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1097 bmi->bmiHeader.biWidth = gif->SWidth;
1098 bmi->bmiHeader.biHeight = -gif->SHeight;
1099 bmi->bmiHeader.biPlanes = 1;
1100 bmi->bmiHeader.biBitCount = 8;
1101 bmi->bmiHeader.biCompression = BI_RGB;
1102 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1103 bmi->bmiHeader.biXPelsPerMeter = 0;
1104 bmi->bmiHeader.biYPelsPerMeter = 0;
1105 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1106 bmi->bmiHeader.biClrImportant = 0;
1109 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1118 if (transparent > -1) {
1119 /* Create the Mask */
1120 HDC hdc = CreateCompatibleDC(0);
1121 HDC hdcMask = CreateCompatibleDC(0);
1123 HBITMAP hOldbitmapmask;
1125 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1128 This->hbmXor = CreateDIBitmap(
1137 bmi->bmiColors[0].rgbRed = 0;
1138 bmi->bmiColors[0].rgbGreen = 0;
1139 bmi->bmiColors[0].rgbBlue = 0;
1140 bmi->bmiColors[1].rgbRed = 255;
1141 bmi->bmiColors[1].rgbGreen = 255;
1142 bmi->bmiColors[1].rgbBlue = 255;
1144 bmi->bmiHeader.biBitCount = 1;
1145 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1146 bmi->bmiHeader.biClrUsed = 2;
1148 for (i = 0; i < gif->SHeight; i++) {
1149 unsigned char * colorPointer = bytes + padding * i;
1150 unsigned char * monoPointer = bytes + monopadding * i;
1151 for (j = 0; j < gif->SWidth; j++) {
1152 unsigned char pixel = colorPointer[j];
1153 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1154 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1158 hTempMask = CreateDIBitmap(
1168 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1169 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1170 hOldbitmap = SelectObject(hdc, hTempMask);
1171 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1173 SetBkColor(hdc, RGB(255, 255, 255));
1174 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1176 /* We no longer need the original bitmap, so we apply the first
1177 transformation with the mask to speed up the rendering */
1178 SelectObject(hdc, This->hbmXor);
1179 SetBkColor(hdc, RGB(0,0,0));
1180 SetTextColor(hdc, RGB(255,255,255));
1181 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1182 hdcMask, 0, 0, SRCAND);
1184 SelectObject(hdc, hOldbitmap);
1185 SelectObject(hdcMask, hOldbitmapmask);
1188 DeleteObject(hTempMask);
1192 This->desc.picType = PICTYPE_BITMAP;
1193 OLEPictureImpl_SetBitmap(This);
1195 HeapFree(GetProcessHeap(),0,bytes);
1199 static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1201 #ifdef HAVE_JPEGLIB_H
1202 struct jpeg_decompress_struct jd;
1203 struct jpeg_error_mgr jerr;
1206 JSAMPROW samprow,oldsamprow;
1207 BITMAPINFOHEADER bmi;
1210 struct jpeg_source_mgr xjsm;
1214 if(!libjpeg_handle) {
1215 if(!load_libjpeg()) {
1216 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1221 /* This is basically so we can use in-memory data for jpeg decompression.
1222 * We need to have all the functions.
1224 xjsm.next_input_byte = xbuf;
1225 xjsm.bytes_in_buffer = xread;
1226 xjsm.init_source = _jpeg_init_source;
1227 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1228 xjsm.skip_input_data = _jpeg_skip_input_data;
1229 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1230 xjsm.term_source = _jpeg_term_source;
1232 jd.err = pjpeg_std_error(&jerr);
1233 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1234 * jpeg_create_decompress(&jd); */
1235 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1237 ret=pjpeg_read_header(&jd,TRUE);
1238 jd.out_color_space = JCS_RGB;
1239 pjpeg_start_decompress(&jd);
1240 if (ret != JPEG_HEADER_OK) {
1241 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1242 HeapFree(GetProcessHeap(),0,xbuf);
1246 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1247 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1248 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1251 oldsamprow = samprow;
1252 while ( jd.output_scanline<jd.output_height ) {
1253 x = pjpeg_read_scanlines(&jd,&samprow,1);
1255 FIXME("failed to read current scanline?\n");
1258 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1259 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1260 *(bits++) = *(samprow+2);
1261 *(bits++) = *(samprow+1);
1262 *(bits++) = *(samprow);
1264 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1265 samprow = oldsamprow;
1269 bmi.biSize = sizeof(bmi);
1270 bmi.biWidth = jd.output_width;
1271 bmi.biHeight = -jd.output_height;
1273 bmi.biBitCount = jd.output_components<<3;
1274 bmi.biCompression = BI_RGB;
1275 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1276 bmi.biXPelsPerMeter = 0;
1277 bmi.biYPelsPerMeter = 0;
1279 bmi.biClrImportant = 0;
1281 HeapFree(GetProcessHeap(),0,samprow);
1282 pjpeg_finish_decompress(&jd);
1283 pjpeg_destroy_decompress(&jd);
1285 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1294 This->desc.picType = PICTYPE_BITMAP;
1295 OLEPictureImpl_SetBitmap(This);
1296 HeapFree(GetProcessHeap(),0,bits);
1299 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1304 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1306 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1307 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1310 /* Does not matter whether this is a coreheader or not, we only use
1311 * components which are in both
1314 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1318 xbuf+bfh->bfOffBits,
1323 This->desc.picType = PICTYPE_BITMAP;
1324 OLEPictureImpl_SetBitmap(This);
1328 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1331 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1336 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1337 FIXME("icon.idType=%d\n",cifd->idType);
1338 FIXME("icon.idCount=%d\n",cifd->idCount);
1340 for (i=0;i<cifd->idCount;i++) {
1341 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1342 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1343 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1344 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1345 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1346 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1347 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1348 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1352 /* If we have more than one icon, try to find the best.
1353 * this currently means '32 pixel wide'.
1355 if (cifd->idCount!=1) {
1356 for (i=0;i<cifd->idCount;i++) {
1357 if (cifd->idEntries[i].bWidth == 32)
1360 if (i==cifd->idCount) i=0;
1363 hicon = CreateIconFromResourceEx(
1364 xbuf+cifd->idEntries[i].dwDIBOffset,
1365 cifd->idEntries[i].dwDIBSize,
1368 cifd->idEntries[i].bWidth,
1369 cifd->idEntries[i].bHeight,
1373 FIXME("CreateIcon failed.\n");
1376 This->desc.picType = PICTYPE_ICON;
1377 This->desc.u.icon.hicon = hicon;
1378 This->origWidth = cifd->idEntries[i].bWidth;
1379 This->origHeight = cifd->idEntries[i].bHeight;
1380 hdcRef = CreateCompatibleDC(0);
1381 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1382 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1388 /************************************************************************
1389 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1391 * Loads the binary data from the IStream. Starts at current position.
1392 * There appears to be an 2 DWORD header:
1396 * Currently implemented: BITMAP, ICON, JPEG, GIF
1398 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1399 HRESULT hr = E_FAIL;
1400 BOOL headerisdata = FALSE;
1401 BOOL statfailed = FALSE;
1402 ULONG xread, toread;
1408 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1410 TRACE("(%p,%p)\n",This,pStm);
1412 /****************************************************************************************
1413 * Part 1: Load the data
1415 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1416 * out whether we do.
1418 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1419 * compound file. This may explain most, if not all, of the cases of "no
1420 * header", and the header validation should take this into account.
1421 * At least in Visual Basic 6, resource streams, valid headers are
1422 * header[0] == "lt\0\0",
1423 * header[1] == length_of_stream.
1425 * Also handle streams where we do not have a working "Stat" method by
1426 * reading all data until the end of the stream.
1428 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1430 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1432 /* we will read at least 8 byte ... just right below */
1433 statstg.cbSize.QuadPart = 8;
1438 headerisdata = FALSE;
1440 hr=IStream_Read(pStm,header,8,&xread);
1441 if (hr || xread!=8) {
1442 FIXME("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1445 headerread += xread;
1448 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1449 if (toread != 0 && toread != header[1])
1450 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1453 if (toread == 0) break;
1455 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1456 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1457 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1458 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1460 ) {/* Found start of bitmap data */
1461 headerisdata = TRUE;
1463 toread = statstg.cbSize.QuadPart-8;
1467 FIXME("Unknown stream header magic: %08x\n", header[0]);
1471 } while (!headerisdata);
1473 if (statfailed) { /* we don't know the size ... read all we get */
1475 int origsize = sizeinc;
1478 TRACE("Reading all data from stream.\n");
1479 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1481 memcpy (xbuf, &header, 8);
1483 while (xread < origsize) {
1484 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1489 if (!nread || hr) /* done, or error */
1491 if (xread == origsize) {
1492 origsize += sizeinc;
1493 sizeinc = 2*sizeinc; /* exponential increase */
1494 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1498 TRACE("hr in no-stat loader case is %08x\n", hr);
1499 TRACE("loaded %d bytes.\n", xread);
1500 This->datalen = xread;
1503 This->datalen = toread+(headerisdata?8:0);
1504 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1507 memcpy (xbuf, &header, 8);
1509 while (xread < This->datalen) {
1511 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1516 if (xread != This->datalen)
1517 FIXME("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1519 if (This->datalen == 0) { /* Marks the "NONE" picture */
1520 This->desc.picType = PICTYPE_NONE;
1525 /****************************************************************************************
1526 * Part 2: Process the loaded data
1529 magic = xbuf[0] + (xbuf[1]<<8);
1531 case 0x4947: /* GIF */
1532 hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
1534 case 0xd8ff: /* JPEG */
1535 hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
1537 case 0x4d42: /* Bitmap */
1538 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1540 case 0x0000: { /* ICON , first word is dwReserved */
1541 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1547 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1549 for (i=0;i<xread+8;i++) {
1550 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1551 else MESSAGE("%02x ",xbuf[i-8]);
1552 if (i % 10 == 9) MESSAGE("\n");
1558 This->bIsDirty = FALSE;
1560 /* FIXME: this notify is not really documented */
1562 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1566 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1570 BITMAPINFO * pInfoBitmap;
1571 int iNumPaletteEntries;
1572 unsigned char * pPixelData;
1573 BITMAPFILEHEADER * pFileHeader;
1574 BITMAPINFO * pInfoHeader;
1576 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1577 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1579 /* Find out bitmap size and padded length */
1581 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1582 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1584 /* Fetch bitmap palette & pixel data */
1586 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1587 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1589 /* Calculate the total length required for the BMP data */
1590 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1591 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1592 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1594 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1595 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1597 iNumPaletteEntries = 0;
1600 sizeof(BITMAPFILEHEADER) +
1601 sizeof(BITMAPINFOHEADER) +
1602 iNumPaletteEntries * sizeof(RGBQUAD) +
1603 pInfoBitmap->bmiHeader.biSizeImage;
1604 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1606 /* Fill the BITMAPFILEHEADER */
1607 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1608 pFileHeader->bfType = 0x4d42;
1609 pFileHeader->bfSize = *pLength;
1610 pFileHeader->bfOffBits =
1611 sizeof(BITMAPFILEHEADER) +
1612 sizeof(BITMAPINFOHEADER) +
1613 iNumPaletteEntries * sizeof(RGBQUAD);
1615 /* Fill the BITMAPINFOHEADER and the palette data */
1616 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1617 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1619 (unsigned char *)(*ppBuffer) +
1620 sizeof(BITMAPFILEHEADER) +
1621 sizeof(BITMAPINFOHEADER) +
1622 iNumPaletteEntries * sizeof(RGBQUAD),
1623 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1626 HeapFree(GetProcessHeap(), 0, pPixelData);
1627 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1631 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1636 *ppBuffer = NULL; *pLength = 0;
1637 if (GetIconInfo(hIcon, &infoIcon)) {
1639 BITMAPINFO * pInfoBitmap;
1640 unsigned char * pIconData = NULL;
1641 unsigned int iDataSize = 0;
1643 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1645 /* Find out icon size */
1647 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1648 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1650 /* Auxiliary pointers */
1651 CURSORICONFILEDIR * pIconDir;
1652 CURSORICONFILEDIRENTRY * pIconEntry;
1653 BITMAPINFOHEADER * pIconBitmapHeader;
1654 unsigned int iOffsetPalette;
1655 unsigned int iOffsetColorData;
1656 unsigned int iOffsetMaskData;
1658 unsigned int iLengthScanLineColor;
1659 unsigned int iLengthScanLineMask;
1660 unsigned int iNumEntriesPalette;
1662 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1663 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1665 FIXME("DEBUG: bitmap size is %d x %d\n",
1666 pInfoBitmap->bmiHeader.biWidth,
1667 pInfoBitmap->bmiHeader.biHeight);
1668 FIXME("DEBUG: bitmap bpp is %d\n",
1669 pInfoBitmap->bmiHeader.biBitCount);
1670 FIXME("DEBUG: bitmap nplanes is %d\n",
1671 pInfoBitmap->bmiHeader.biPlanes);
1672 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1673 pInfoBitmap->bmiHeader.biSizeImage);
1675 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1676 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1677 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1679 /* Fill out the CURSORICONFILEDIR */
1680 pIconDir = (CURSORICONFILEDIR *)pIconData;
1681 pIconDir->idType = 1;
1682 pIconDir->idCount = 1;
1684 /* Fill out the CURSORICONFILEDIRENTRY */
1685 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1686 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1687 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1688 pIconEntry->bColorCount =
1689 (pInfoBitmap->bmiHeader.biBitCount < 8)
1690 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1692 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1693 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1694 pIconEntry->dwDIBSize = 0;
1695 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1697 /* Fill out the BITMAPINFOHEADER */
1698 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1699 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1701 /* Find out whether a palette exists for the bitmap */
1702 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1703 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1704 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1705 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1706 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1707 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1708 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1709 iNumEntriesPalette = 3;
1710 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1711 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1713 iNumEntriesPalette = 0;
1716 /* Add bitmap size and header size to icon data size. */
1717 iOffsetPalette = iDataSize;
1718 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1719 iOffsetColorData = iDataSize;
1720 iDataSize += pIconBitmapHeader->biSizeImage;
1721 iOffsetMaskData = iDataSize;
1722 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1723 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1724 pIconBitmapHeader->biHeight *= 2;
1725 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1726 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1727 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1728 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1730 /* Get the actual bitmap data from the icon bitmap */
1731 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1732 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1733 if (iNumEntriesPalette > 0) {
1734 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1735 iNumEntriesPalette * sizeof(RGBQUAD));
1738 /* Reset all values so that GetDIBits call succeeds */
1739 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1740 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1741 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1743 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1744 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1745 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1747 printf("ERROR: unable to get bitmap mask (error %u)\n",
1752 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1753 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1755 /* Write out everything produced so far to the stream */
1756 *ppBuffer = pIconData; *pLength = iDataSize;
1760 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1765 Remarks (from MSDN entry on GetIconInfo):
1767 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1768 members of ICONINFO. The calling application must manage
1769 these bitmaps and delete them when they are no longer
1772 if (hDC) ReleaseDC(0, hDC);
1773 DeleteObject(infoIcon.hbmMask);
1774 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1775 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1777 printf("ERROR: Unable to get icon information (error %u)\n",
1783 static HRESULT WINAPI OLEPictureImpl_Save(
1784 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1786 HRESULT hResult = E_NOTIMPL;
1788 unsigned int iDataSize;
1790 int iSerializeResult = 0;
1791 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1793 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1795 switch (This->desc.picType) {
1797 if (This->bIsDirty || !This->data) {
1798 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1799 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1803 HeapFree(GetProcessHeap(), 0, This->data);
1804 This->data = pIconData;
1805 This->datalen = iDataSize;
1807 if (This->loadtime_magic != 0xdeadbeef) {
1810 header[0] = This->loadtime_magic;
1811 header[1] = This->datalen;
1812 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1814 IStream_Write(pStm, This->data, This->datalen, &dummy);
1818 case PICTYPE_BITMAP:
1819 if (This->bIsDirty) {
1820 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1822 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1825 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1828 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1831 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1834 if (iSerializeResult) {
1836 if (This->loadtime_magic != 0xdeadbeef) {
1841 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1842 header[1] = iDataSize;
1843 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1845 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1847 HeapFree(GetProcessHeap(), 0, This->data);
1848 This->data = pIconData;
1849 This->datalen = iDataSize;
1854 if (This->loadtime_magic != 0xdeadbeef) {
1859 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1860 header[1] = This->datalen;
1861 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1863 IStream_Write(pStm, This->data, This->datalen, &dummy);
1867 case PICTYPE_METAFILE:
1868 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1870 case PICTYPE_ENHMETAFILE:
1871 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1874 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1877 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1881 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1882 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1884 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1885 FIXME("(%p,%p),stub!\n",This,pcbSize);
1890 /************************************************************************
1894 /************************************************************************
1895 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1897 * See Windows documentation for more details on IUnknown methods.
1899 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1904 OLEPictureImpl *This = impl_from_IDispatch(iface);
1906 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1909 /************************************************************************
1910 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1912 * See Windows documentation for more details on IUnknown methods.
1914 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1917 OLEPictureImpl *This = impl_from_IDispatch(iface);
1919 return IPicture_AddRef((IPicture *)This);
1922 /************************************************************************
1923 * OLEPictureImpl_IDispatch_Release (IUnknown)
1925 * See Windows documentation for more details on IUnknown methods.
1927 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1930 OLEPictureImpl *This = impl_from_IDispatch(iface);
1932 return IPicture_Release((IPicture *)This);
1935 /************************************************************************
1936 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1938 * See Windows documentation for more details on IDispatch methods.
1940 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1942 unsigned int* pctinfo)
1944 TRACE("(%p)\n", pctinfo);
1951 /************************************************************************
1952 * OLEPictureImpl_GetTypeInfo (IDispatch)
1954 * See Windows documentation for more details on IDispatch methods.
1956 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1960 ITypeInfo** ppTInfo)
1962 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1966 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1971 hres = LoadTypeLib(stdole2tlb, &tl);
1974 ERR("Could not load stdole2.tlb\n");
1978 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1980 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1985 /************************************************************************
1986 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1988 * See Windows documentation for more details on IDispatch methods.
1990 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1993 LPOLESTR* rgszNames,
2003 /************************************************************************
2004 * OLEPictureImpl_Invoke (IDispatch)
2006 * See Windows documentation for more details on IDispatch methods.
2008 static HRESULT WINAPI OLEPictureImpl_Invoke(
2010 DISPID dispIdMember,
2014 DISPPARAMS* pDispParams,
2015 VARIANT* pVarResult,
2016 EXCEPINFO* pExepInfo,
2019 OLEPictureImpl *This = impl_from_IDispatch(iface);
2021 /* validate parameters */
2023 if (!IsEqualIID(riid, &IID_NULL))
2025 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2026 return DISP_E_UNKNOWNNAME;
2031 ERR("null pDispParams not allowed\n");
2032 return DISP_E_PARAMNOTOPTIONAL;
2035 if (wFlags & DISPATCH_PROPERTYGET)
2037 if (pDispParams->cArgs != 0)
2039 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2040 return DISP_E_BADPARAMCOUNT;
2044 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2045 return DISP_E_PARAMNOTOPTIONAL;
2048 else if (wFlags & DISPATCH_PROPERTYPUT)
2050 if (pDispParams->cArgs != 1)
2052 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2053 return DISP_E_BADPARAMCOUNT;
2057 switch (dispIdMember)
2059 case DISPID_PICT_HANDLE:
2060 if (wFlags & DISPATCH_PROPERTYGET)
2062 TRACE("DISPID_PICT_HANDLE\n");
2063 V_VT(pVarResult) = VT_I4;
2064 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2067 case DISPID_PICT_HPAL:
2068 if (wFlags & DISPATCH_PROPERTYGET)
2070 TRACE("DISPID_PICT_HPAL\n");
2071 V_VT(pVarResult) = VT_I4;
2072 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2074 else if (wFlags & DISPATCH_PROPERTYPUT)
2078 TRACE("DISPID_PICT_HPAL\n");
2080 VariantInit(&vararg);
2081 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2085 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2087 VariantClear(&vararg);
2091 case DISPID_PICT_TYPE:
2092 if (wFlags & DISPATCH_PROPERTYGET)
2094 TRACE("DISPID_PICT_TYPE\n");
2095 V_VT(pVarResult) = VT_I2;
2096 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2099 case DISPID_PICT_WIDTH:
2100 if (wFlags & DISPATCH_PROPERTYGET)
2102 TRACE("DISPID_PICT_WIDTH\n");
2103 V_VT(pVarResult) = VT_I4;
2104 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2107 case DISPID_PICT_HEIGHT:
2108 if (wFlags & DISPATCH_PROPERTYGET)
2110 TRACE("DISPID_PICT_HEIGHT\n");
2111 V_VT(pVarResult) = VT_I4;
2112 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2117 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2118 return DISP_E_MEMBERNOTFOUND;
2122 static const IPictureVtbl OLEPictureImpl_VTable =
2124 OLEPictureImpl_QueryInterface,
2125 OLEPictureImpl_AddRef,
2126 OLEPictureImpl_Release,
2127 OLEPictureImpl_get_Handle,
2128 OLEPictureImpl_get_hPal,
2129 OLEPictureImpl_get_Type,
2130 OLEPictureImpl_get_Width,
2131 OLEPictureImpl_get_Height,
2132 OLEPictureImpl_Render,
2133 OLEPictureImpl_set_hPal,
2134 OLEPictureImpl_get_CurDC,
2135 OLEPictureImpl_SelectPicture,
2136 OLEPictureImpl_get_KeepOriginalFormat,
2137 OLEPictureImpl_put_KeepOriginalFormat,
2138 OLEPictureImpl_PictureChanged,
2139 OLEPictureImpl_SaveAsFile,
2140 OLEPictureImpl_get_Attributes
2143 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2145 OLEPictureImpl_IDispatch_QueryInterface,
2146 OLEPictureImpl_IDispatch_AddRef,
2147 OLEPictureImpl_IDispatch_Release,
2148 OLEPictureImpl_GetTypeInfoCount,
2149 OLEPictureImpl_GetTypeInfo,
2150 OLEPictureImpl_GetIDsOfNames,
2151 OLEPictureImpl_Invoke
2154 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2156 OLEPictureImpl_IPersistStream_QueryInterface,
2157 OLEPictureImpl_IPersistStream_AddRef,
2158 OLEPictureImpl_IPersistStream_Release,
2159 OLEPictureImpl_GetClassID,
2160 OLEPictureImpl_IsDirty,
2161 OLEPictureImpl_Load,
2162 OLEPictureImpl_Save,
2163 OLEPictureImpl_GetSizeMax
2166 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2168 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2169 OLEPictureImpl_IConnectionPointContainer_AddRef,
2170 OLEPictureImpl_IConnectionPointContainer_Release,
2171 OLEPictureImpl_EnumConnectionPoints,
2172 OLEPictureImpl_FindConnectionPoint
2175 /***********************************************************************
2176 * OleCreatePictureIndirect (OLEAUT32.419)
2178 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2179 BOOL fOwn, LPVOID *ppvObj )
2181 OLEPictureImpl* newPict = NULL;
2184 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2195 * Try to construct a new instance of the class.
2197 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2199 if (newPict == NULL)
2200 return E_OUTOFMEMORY;
2203 * Make sure it supports the interface required by the caller.
2205 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2208 * Release the reference obtained in the constructor. If
2209 * the QueryInterface was unsuccessful, it will free the class.
2211 IPicture_Release((IPicture*)newPict);
2217 /***********************************************************************
2218 * OleLoadPicture (OLEAUT32.418)
2220 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2221 REFIID riid, LPVOID *ppvObj )
2227 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2228 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2230 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2233 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2235 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2236 IPicture_Release(newpic);
2240 IPersistStream_Load(ps,lpstream);
2241 IPersistStream_Release(ps);
2242 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2244 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2245 IPicture_Release(newpic);
2249 /***********************************************************************
2250 * OleLoadPictureEx (OLEAUT32.401)
2252 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2253 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2259 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2260 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2262 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2265 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2267 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2268 IPicture_Release(newpic);
2272 IPersistStream_Load(ps,lpstream);
2273 IPersistStream_Release(ps);
2274 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2276 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2277 IPicture_Release(newpic);
2281 /***********************************************************************
2282 * OleLoadPicturePath (OLEAUT32.424)
2284 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2285 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2288 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2292 HGLOBAL hGlobal = NULL;
2293 DWORD dwBytesRead = 0;
2296 IPersistStream *pStream;
2299 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2300 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2301 debugstr_guid(riid), ppvRet);
2303 if (!ppvRet) return E_POINTER;
2305 if (strncmpW(szURLorPath, file, 7) == 0) {
2308 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2310 if (hFile == INVALID_HANDLE_VALUE)
2311 return E_UNEXPECTED;
2313 dwFileSize = GetFileSize(hFile, NULL);
2314 if (dwFileSize != INVALID_FILE_SIZE )
2316 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2319 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2322 GlobalFree(hGlobal);
2330 return E_UNEXPECTED;
2332 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2335 GlobalFree(hGlobal);
2342 hRes = CreateBindCtx(0, &pbc);
2343 if (SUCCEEDED(hRes))
2345 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2346 if (SUCCEEDED(hRes))
2348 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2349 IMoniker_Release(pmnk);
2351 IBindCtx_Release(pbc);
2357 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2358 &IID_IPicture, (LPVOID*)&ipicture);
2360 IStream_Release(stream);
2364 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2366 IStream_Release(stream);
2367 IPicture_Release(ipicture);
2371 hRes = IPersistStream_Load(pStream, stream);
2372 IPersistStream_Release(pStream);
2373 IStream_Release(stream);
2376 IPicture_Release(ipicture);
2380 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2382 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2384 IPicture_Release(ipicture);
2388 /*******************************************************************************
2389 * StdPic ClassFactory
2393 /* IUnknown fields */
2394 const IClassFactoryVtbl *lpVtbl;
2396 } IClassFactoryImpl;
2398 static HRESULT WINAPI
2399 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2400 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2402 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2403 return E_NOINTERFACE;
2407 SPCF_AddRef(LPCLASSFACTORY iface) {
2408 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2409 return InterlockedIncrement(&This->ref);
2412 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2413 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2414 /* static class, won't be freed */
2415 return InterlockedDecrement(&This->ref);
2418 static HRESULT WINAPI SPCF_CreateInstance(
2419 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2421 /* Creates an uninitialized picture */
2422 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2426 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2427 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2428 FIXME("(%p)->(%d),stub!\n",This,dolock);
2432 static const IClassFactoryVtbl SPCF_Vtbl = {
2433 SPCF_QueryInterface,
2436 SPCF_CreateInstance,
2439 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2441 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }