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;
1407 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1409 TRACE("(%p,%p)\n",This,pStm);
1411 /****************************************************************************************
1412 * Part 1: Load the data
1414 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1415 * out whether we do.
1417 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1418 * compound file. This may explain most, if not all, of the cases of "no
1419 * header", and the header validation should take this into account.
1420 * At least in Visual Basic 6, resource streams, valid headers are
1421 * header[0] == "lt\0\0",
1422 * header[1] == length_of_stream.
1424 * Also handle streams where we do not have a working "Stat" method by
1425 * reading all data until the end of the stream.
1427 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1429 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1431 /* we will read at least 8 byte ... just right below */
1432 statstg.cbSize.QuadPart = 8;
1434 hr=IStream_Read(pStm,header,8,&xread);
1435 if (hr || xread!=8) {
1436 FIXME("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1440 headerisdata = FALSE;
1442 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1445 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1446 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1447 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1448 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1450 ) {/* Incorrect header, assume none. */
1451 headerisdata = TRUE;
1452 toread = statstg.cbSize.QuadPart-8;
1455 FIXME("Unknown stream header magic: %08x\n", header[0]);
1460 if (statfailed) { /* we don't know the size ... read all we get */
1462 int origsize = sizeinc;
1465 TRACE("Reading all data from stream.\n");
1466 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1468 memcpy (xbuf, &header, 8);
1470 while (xread < origsize) {
1471 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1476 if (!nread || hr) /* done, or error */
1478 if (xread == origsize) {
1479 origsize += sizeinc;
1480 sizeinc = 2*sizeinc; /* exponential increase */
1481 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1485 TRACE("hr in no-stat loader case is %08x\n", hr);
1486 TRACE("loaded %d bytes.\n", xread);
1487 This->datalen = xread;
1490 This->datalen = toread+(headerisdata?8:0);
1491 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1494 memcpy (xbuf, &header, 8);
1496 while (xread < This->datalen) {
1498 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1503 if (xread != This->datalen)
1504 FIXME("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1506 if (This->datalen == 0) { /* Marks the "NONE" picture */
1507 This->desc.picType = PICTYPE_NONE;
1512 /****************************************************************************************
1513 * Part 2: Process the loaded data
1516 magic = xbuf[0] + (xbuf[1]<<8);
1518 case 0x4947: /* GIF */
1519 hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
1521 case 0xd8ff: /* JPEG */
1522 hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
1524 case 0x4d42: /* Bitmap */
1525 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1527 case 0x0000: { /* ICON , first word is dwReserved */
1528 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1534 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1536 for (i=0;i<xread+8;i++) {
1537 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1538 else MESSAGE("%02x ",xbuf[i-8]);
1539 if (i % 10 == 9) MESSAGE("\n");
1545 This->bIsDirty = FALSE;
1547 /* FIXME: this notify is not really documented */
1549 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1553 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1557 BITMAPINFO * pInfoBitmap;
1558 int iNumPaletteEntries;
1559 unsigned char * pPixelData;
1560 BITMAPFILEHEADER * pFileHeader;
1561 BITMAPINFO * pInfoHeader;
1563 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1564 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1566 /* Find out bitmap size and padded length */
1568 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1569 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1571 /* Fetch bitmap palette & pixel data */
1573 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1574 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1576 /* Calculate the total length required for the BMP data */
1577 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1578 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1579 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1581 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1582 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1584 iNumPaletteEntries = 0;
1587 sizeof(BITMAPFILEHEADER) +
1588 sizeof(BITMAPINFOHEADER) +
1589 iNumPaletteEntries * sizeof(RGBQUAD) +
1590 pInfoBitmap->bmiHeader.biSizeImage;
1591 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1593 /* Fill the BITMAPFILEHEADER */
1594 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1595 pFileHeader->bfType = 0x4d42;
1596 pFileHeader->bfSize = *pLength;
1597 pFileHeader->bfOffBits =
1598 sizeof(BITMAPFILEHEADER) +
1599 sizeof(BITMAPINFOHEADER) +
1600 iNumPaletteEntries * sizeof(RGBQUAD);
1602 /* Fill the BITMAPINFOHEADER and the palette data */
1603 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1604 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1606 (unsigned char *)(*ppBuffer) +
1607 sizeof(BITMAPFILEHEADER) +
1608 sizeof(BITMAPINFOHEADER) +
1609 iNumPaletteEntries * sizeof(RGBQUAD),
1610 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1613 HeapFree(GetProcessHeap(), 0, pPixelData);
1614 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1618 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1623 *ppBuffer = NULL; *pLength = 0;
1624 if (GetIconInfo(hIcon, &infoIcon)) {
1626 BITMAPINFO * pInfoBitmap;
1627 unsigned char * pIconData = NULL;
1628 unsigned int iDataSize = 0;
1630 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1632 /* Find out icon size */
1634 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1635 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1637 /* Auxiliary pointers */
1638 CURSORICONFILEDIR * pIconDir;
1639 CURSORICONFILEDIRENTRY * pIconEntry;
1640 BITMAPINFOHEADER * pIconBitmapHeader;
1641 unsigned int iOffsetPalette;
1642 unsigned int iOffsetColorData;
1643 unsigned int iOffsetMaskData;
1645 unsigned int iLengthScanLineColor;
1646 unsigned int iLengthScanLineMask;
1647 unsigned int iNumEntriesPalette;
1649 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1650 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1652 FIXME("DEBUG: bitmap size is %d x %d\n",
1653 pInfoBitmap->bmiHeader.biWidth,
1654 pInfoBitmap->bmiHeader.biHeight);
1655 FIXME("DEBUG: bitmap bpp is %d\n",
1656 pInfoBitmap->bmiHeader.biBitCount);
1657 FIXME("DEBUG: bitmap nplanes is %d\n",
1658 pInfoBitmap->bmiHeader.biPlanes);
1659 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1660 pInfoBitmap->bmiHeader.biSizeImage);
1662 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1663 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1664 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1666 /* Fill out the CURSORICONFILEDIR */
1667 pIconDir = (CURSORICONFILEDIR *)pIconData;
1668 pIconDir->idType = 1;
1669 pIconDir->idCount = 1;
1671 /* Fill out the CURSORICONFILEDIRENTRY */
1672 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1673 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1674 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1675 pIconEntry->bColorCount =
1676 (pInfoBitmap->bmiHeader.biBitCount < 8)
1677 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1679 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1680 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1681 pIconEntry->dwDIBSize = 0;
1682 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1684 /* Fill out the BITMAPINFOHEADER */
1685 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1686 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1688 /* Find out whether a palette exists for the bitmap */
1689 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1690 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1691 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1692 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1693 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1694 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1695 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1696 iNumEntriesPalette = 3;
1697 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1698 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1700 iNumEntriesPalette = 0;
1703 /* Add bitmap size and header size to icon data size. */
1704 iOffsetPalette = iDataSize;
1705 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1706 iOffsetColorData = iDataSize;
1707 iDataSize += pIconBitmapHeader->biSizeImage;
1708 iOffsetMaskData = iDataSize;
1709 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1710 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1711 pIconBitmapHeader->biHeight *= 2;
1712 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1713 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1714 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1715 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1717 /* Get the actual bitmap data from the icon bitmap */
1718 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1719 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1720 if (iNumEntriesPalette > 0) {
1721 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1722 iNumEntriesPalette * sizeof(RGBQUAD));
1725 /* Reset all values so that GetDIBits call succeeds */
1726 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1727 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1728 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1730 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1731 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1732 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1734 printf("ERROR: unable to get bitmap mask (error %u)\n",
1739 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1740 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1742 /* Write out everything produced so far to the stream */
1743 *ppBuffer = pIconData; *pLength = iDataSize;
1747 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1752 Remarks (from MSDN entry on GetIconInfo):
1754 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1755 members of ICONINFO. The calling application must manage
1756 these bitmaps and delete them when they are no longer
1759 if (hDC) ReleaseDC(0, hDC);
1760 DeleteObject(infoIcon.hbmMask);
1761 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1762 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1764 printf("ERROR: Unable to get icon information (error %u)\n",
1770 static HRESULT WINAPI OLEPictureImpl_Save(
1771 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1773 HRESULT hResult = E_NOTIMPL;
1775 unsigned int iDataSize;
1777 int iSerializeResult = 0;
1778 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1780 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1782 switch (This->desc.picType) {
1784 if (This->bIsDirty || !This->data) {
1785 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1786 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1790 HeapFree(GetProcessHeap(), 0, This->data);
1791 This->data = pIconData;
1792 This->datalen = iDataSize;
1794 if (This->loadtime_magic != 0xdeadbeef) {
1797 header[0] = This->loadtime_magic;
1798 header[1] = This->datalen;
1799 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1801 IStream_Write(pStm, This->data, This->datalen, &dummy);
1805 case PICTYPE_BITMAP:
1806 if (This->bIsDirty) {
1807 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1809 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1812 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1815 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1818 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1821 if (iSerializeResult) {
1823 if (This->loadtime_magic != 0xdeadbeef) {
1828 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1829 header[1] = iDataSize;
1830 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1832 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1834 HeapFree(GetProcessHeap(), 0, This->data);
1835 This->data = pIconData;
1836 This->datalen = iDataSize;
1841 if (This->loadtime_magic != 0xdeadbeef) {
1846 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1847 header[1] = This->datalen;
1848 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1850 IStream_Write(pStm, This->data, This->datalen, &dummy);
1854 case PICTYPE_METAFILE:
1855 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1857 case PICTYPE_ENHMETAFILE:
1858 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1861 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1864 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1868 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1869 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1871 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1872 FIXME("(%p,%p),stub!\n",This,pcbSize);
1877 /************************************************************************
1881 /************************************************************************
1882 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1884 * See Windows documentation for more details on IUnknown methods.
1886 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1891 OLEPictureImpl *This = impl_from_IDispatch(iface);
1893 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1896 /************************************************************************
1897 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1899 * See Windows documentation for more details on IUnknown methods.
1901 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1904 OLEPictureImpl *This = impl_from_IDispatch(iface);
1906 return IPicture_AddRef((IPicture *)This);
1909 /************************************************************************
1910 * OLEPictureImpl_IDispatch_Release (IUnknown)
1912 * See Windows documentation for more details on IUnknown methods.
1914 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1917 OLEPictureImpl *This = impl_from_IDispatch(iface);
1919 return IPicture_Release((IPicture *)This);
1922 /************************************************************************
1923 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1925 * See Windows documentation for more details on IDispatch methods.
1927 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1929 unsigned int* pctinfo)
1931 TRACE("(%p)\n", pctinfo);
1938 /************************************************************************
1939 * OLEPictureImpl_GetTypeInfo (IDispatch)
1941 * See Windows documentation for more details on IDispatch methods.
1943 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1947 ITypeInfo** ppTInfo)
1949 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1953 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1958 hres = LoadTypeLib(stdole2tlb, &tl);
1961 ERR("Could not load stdole2.tlb\n");
1965 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1967 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1972 /************************************************************************
1973 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1975 * See Windows documentation for more details on IDispatch methods.
1977 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1980 LPOLESTR* rgszNames,
1990 /************************************************************************
1991 * OLEPictureImpl_Invoke (IDispatch)
1993 * See Windows documentation for more details on IDispatch methods.
1995 static HRESULT WINAPI OLEPictureImpl_Invoke(
1997 DISPID dispIdMember,
2001 DISPPARAMS* pDispParams,
2002 VARIANT* pVarResult,
2003 EXCEPINFO* pExepInfo,
2006 OLEPictureImpl *This = impl_from_IDispatch(iface);
2008 /* validate parameters */
2010 if (!IsEqualIID(riid, &IID_NULL))
2012 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2013 return DISP_E_UNKNOWNNAME;
2018 ERR("null pDispParams not allowed\n");
2019 return DISP_E_PARAMNOTOPTIONAL;
2022 if (wFlags & DISPATCH_PROPERTYGET)
2024 if (pDispParams->cArgs != 0)
2026 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2027 return DISP_E_BADPARAMCOUNT;
2031 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2032 return DISP_E_PARAMNOTOPTIONAL;
2035 else if (wFlags & DISPATCH_PROPERTYPUT)
2037 if (pDispParams->cArgs != 1)
2039 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2040 return DISP_E_BADPARAMCOUNT;
2044 switch (dispIdMember)
2046 case DISPID_PICT_HANDLE:
2047 if (wFlags & DISPATCH_PROPERTYGET)
2049 TRACE("DISPID_PICT_HANDLE\n");
2050 V_VT(pVarResult) = VT_I4;
2051 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2054 case DISPID_PICT_HPAL:
2055 if (wFlags & DISPATCH_PROPERTYGET)
2057 TRACE("DISPID_PICT_HPAL\n");
2058 V_VT(pVarResult) = VT_I4;
2059 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2061 else if (wFlags & DISPATCH_PROPERTYPUT)
2065 TRACE("DISPID_PICT_HPAL\n");
2067 VariantInit(&vararg);
2068 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2072 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2074 VariantClear(&vararg);
2078 case DISPID_PICT_TYPE:
2079 if (wFlags & DISPATCH_PROPERTYGET)
2081 TRACE("DISPID_PICT_TYPE\n");
2082 V_VT(pVarResult) = VT_I2;
2083 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2086 case DISPID_PICT_WIDTH:
2087 if (wFlags & DISPATCH_PROPERTYGET)
2089 TRACE("DISPID_PICT_WIDTH\n");
2090 V_VT(pVarResult) = VT_I4;
2091 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2094 case DISPID_PICT_HEIGHT:
2095 if (wFlags & DISPATCH_PROPERTYGET)
2097 TRACE("DISPID_PICT_HEIGHT\n");
2098 V_VT(pVarResult) = VT_I4;
2099 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2104 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2105 return DISP_E_MEMBERNOTFOUND;
2109 static const IPictureVtbl OLEPictureImpl_VTable =
2111 OLEPictureImpl_QueryInterface,
2112 OLEPictureImpl_AddRef,
2113 OLEPictureImpl_Release,
2114 OLEPictureImpl_get_Handle,
2115 OLEPictureImpl_get_hPal,
2116 OLEPictureImpl_get_Type,
2117 OLEPictureImpl_get_Width,
2118 OLEPictureImpl_get_Height,
2119 OLEPictureImpl_Render,
2120 OLEPictureImpl_set_hPal,
2121 OLEPictureImpl_get_CurDC,
2122 OLEPictureImpl_SelectPicture,
2123 OLEPictureImpl_get_KeepOriginalFormat,
2124 OLEPictureImpl_put_KeepOriginalFormat,
2125 OLEPictureImpl_PictureChanged,
2126 OLEPictureImpl_SaveAsFile,
2127 OLEPictureImpl_get_Attributes
2130 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2132 OLEPictureImpl_IDispatch_QueryInterface,
2133 OLEPictureImpl_IDispatch_AddRef,
2134 OLEPictureImpl_IDispatch_Release,
2135 OLEPictureImpl_GetTypeInfoCount,
2136 OLEPictureImpl_GetTypeInfo,
2137 OLEPictureImpl_GetIDsOfNames,
2138 OLEPictureImpl_Invoke
2141 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2143 OLEPictureImpl_IPersistStream_QueryInterface,
2144 OLEPictureImpl_IPersistStream_AddRef,
2145 OLEPictureImpl_IPersistStream_Release,
2146 OLEPictureImpl_GetClassID,
2147 OLEPictureImpl_IsDirty,
2148 OLEPictureImpl_Load,
2149 OLEPictureImpl_Save,
2150 OLEPictureImpl_GetSizeMax
2153 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2155 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2156 OLEPictureImpl_IConnectionPointContainer_AddRef,
2157 OLEPictureImpl_IConnectionPointContainer_Release,
2158 OLEPictureImpl_EnumConnectionPoints,
2159 OLEPictureImpl_FindConnectionPoint
2162 /***********************************************************************
2163 * OleCreatePictureIndirect (OLEAUT32.419)
2165 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2166 BOOL fOwn, LPVOID *ppvObj )
2168 OLEPictureImpl* newPict = NULL;
2171 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2182 * Try to construct a new instance of the class.
2184 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2186 if (newPict == NULL)
2187 return E_OUTOFMEMORY;
2190 * Make sure it supports the interface required by the caller.
2192 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2195 * Release the reference obtained in the constructor. If
2196 * the QueryInterface was unsuccessful, it will free the class.
2198 IPicture_Release((IPicture*)newPict);
2204 /***********************************************************************
2205 * OleLoadPicture (OLEAUT32.418)
2207 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2208 REFIID riid, LPVOID *ppvObj )
2214 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2215 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2217 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2220 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2222 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2223 IPicture_Release(newpic);
2227 IPersistStream_Load(ps,lpstream);
2228 IPersistStream_Release(ps);
2229 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2231 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2232 IPicture_Release(newpic);
2236 /***********************************************************************
2237 * OleLoadPictureEx (OLEAUT32.401)
2239 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2240 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2246 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2247 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2249 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2252 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2254 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2255 IPicture_Release(newpic);
2259 IPersistStream_Load(ps,lpstream);
2260 IPersistStream_Release(ps);
2261 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2263 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2264 IPicture_Release(newpic);
2268 /***********************************************************************
2269 * OleLoadPicturePath (OLEAUT32.424)
2271 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2272 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2275 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2279 HGLOBAL hGlobal = NULL;
2280 DWORD dwBytesRead = 0;
2283 IPersistStream *pStream;
2286 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2287 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2288 debugstr_guid(riid), ppvRet);
2290 if (!ppvRet) return E_POINTER;
2292 if (strncmpW(szURLorPath, file, 7) == 0) {
2295 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2297 if (hFile == INVALID_HANDLE_VALUE)
2298 return E_UNEXPECTED;
2300 dwFileSize = GetFileSize(hFile, NULL);
2301 if (dwFileSize != INVALID_FILE_SIZE )
2303 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2306 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2309 GlobalFree(hGlobal);
2317 return E_UNEXPECTED;
2319 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2322 GlobalFree(hGlobal);
2329 hRes = CreateBindCtx(0, &pbc);
2330 if (SUCCEEDED(hRes))
2332 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2333 if (SUCCEEDED(hRes))
2335 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2336 IMoniker_Release(pmnk);
2338 IBindCtx_Release(pbc);
2344 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2345 &IID_IPicture, (LPVOID*)&ipicture);
2347 IStream_Release(stream);
2351 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2353 IStream_Release(stream);
2354 IPicture_Release(ipicture);
2358 hRes = IPersistStream_Load(pStream, stream);
2359 IPersistStream_Release(pStream);
2360 IStream_Release(stream);
2363 IPicture_Release(ipicture);
2367 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2369 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2371 IPicture_Release(ipicture);
2375 /*******************************************************************************
2376 * StdPic ClassFactory
2380 /* IUnknown fields */
2381 const IClassFactoryVtbl *lpVtbl;
2383 } IClassFactoryImpl;
2385 static HRESULT WINAPI
2386 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2387 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2389 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2390 return E_NOINTERFACE;
2394 SPCF_AddRef(LPCLASSFACTORY iface) {
2395 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2396 return InterlockedIncrement(&This->ref);
2399 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2400 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2401 /* static class, won't be freed */
2402 return InterlockedDecrement(&This->ref);
2405 static HRESULT WINAPI SPCF_CreateInstance(
2406 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2408 /* Creates an uninitialized picture */
2409 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2413 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2414 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2415 FIXME("(%p)->(%d),stub!\n",This,dolock);
2419 static const IClassFactoryVtbl SPCF_Vtbl = {
2420 SPCF_QueryInterface,
2423 SPCF_CreateInstance,
2426 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2428 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }