4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
8 * Copyright 2008 Kirill K. Smirnov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well..
27 * Lots of methods are just stubs.
30 * NOTES (or things that msdn doesn't tell you)
32 * The width and height properties are returned in HIMETRIC units (0.01mm)
33 * IPicture::Render also uses these to select a region of the src picture.
34 * A bitmap's size is converted into these units by using the screen resolution
35 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
40 #include "wine/port.h"
50 #define NONAMELESSUNION
51 #define NONAMELESSSTRUCT
64 #include "wine/debug.h"
65 #include "wine/unicode.h"
66 #include "wine/library.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(ole);
72 /* Header for Aldus Placable Metafiles - a standard metafile follows */
73 typedef struct _APM_HEADER
95 } CURSORICONFILEDIRENTRY;
102 CURSORICONFILEDIRENTRY idEntries[1];
107 /*************************************************************************
108 * Declaration of implementation class
111 typedef struct OLEPictureImpl {
114 * IPicture handles IUnknown
117 const IPictureVtbl *lpVtbl;
118 const IDispatchVtbl *lpvtblIDispatch;
119 const IPersistStreamVtbl *lpvtblIPersistStream;
120 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
122 /* Object reference count */
125 /* We own the object and must destroy it ourselves */
128 /* Picture description */
131 /* These are the pixel size of a bitmap */
135 /* And these are the size of the picture converted into HIMETRIC units */
136 OLE_XSIZE_HIMETRIC himetricWidth;
137 OLE_YSIZE_HIMETRIC himetricHeight;
139 IConnectionPoint *pCP;
144 /* Bitmap transparency mask */
152 BOOL bIsDirty; /* Set to TRUE if picture has changed */
153 unsigned int loadtime_magic; /* If a length header was found, saves value */
154 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
158 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
161 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
163 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
166 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
168 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
171 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
173 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
177 * Predeclare VTables. They get initialized at the end.
179 static const IPictureVtbl OLEPictureImpl_VTable;
180 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
181 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
182 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
184 /* pixels to HIMETRIC units conversion */
185 static inline OLE_XSIZE_HIMETRIC xpixels_to_himetric(INT pixels, HDC hdc)
187 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
190 static inline OLE_YSIZE_HIMETRIC ypixels_to_himetric(INT pixels, HDC hdc)
192 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
195 /***********************************************************************
196 * Implementation of the OLEPictureImpl class.
199 static void OLEPictureImpl_SetBitmap(OLEPictureImpl *This)
204 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
205 if(GetObjectW(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
206 ERR("GetObject fails\n");
209 This->origWidth = bm.bmWidth;
210 This->origHeight = bm.bmHeight;
212 /* The width and height are stored in HIMETRIC units (0.01 mm),
213 so we take our pixel width divide by pixels per inch and
214 multiply by 25.4 * 100 */
215 /* Should we use GetBitmapDimension if available? */
216 hdcRef = CreateCompatibleDC(0);
218 This->himetricWidth = xpixels_to_himetric(bm.bmWidth, hdcRef);
219 This->himetricHeight = xpixels_to_himetric(bm.bmHeight, hdcRef);
224 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
228 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
229 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
233 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
234 if(GetObjectW(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
235 ERR("GetObject fails on icon bitmap\n");
239 This->origWidth = bm.bmWidth;
240 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
241 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
244 This->himetricWidth = xpixels_to_himetric(This->origWidth, hdcRef);
245 This->himetricHeight = ypixels_to_himetric(This->origHeight, hdcRef);
247 ReleaseDC(0, hdcRef);
249 DeleteObject(infoIcon.hbmMask);
250 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
252 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
256 /************************************************************************
257 * OLEPictureImpl_Construct
259 * This method will construct a new instance of the OLEPictureImpl
262 * The caller of this method must release the object when it's
265 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
267 OLEPictureImpl* newObject = 0;
270 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
273 * Allocate space for the object.
275 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
281 * Initialize the virtual function table.
283 newObject->lpVtbl = &OLEPictureImpl_VTable;
284 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
285 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
286 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
288 newObject->pCP = NULL;
289 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
292 HeapFree(GetProcessHeap(), 0, newObject);
297 * Start with one reference count. The caller of this function
298 * must release the interface pointer when it is done.
301 newObject->hDCCur = 0;
303 newObject->fOwn = fOwn;
305 /* dunno about original value */
306 newObject->keepOrigFormat = TRUE;
308 newObject->hbmMask = NULL;
309 newObject->hbmXor = NULL;
310 newObject->loadtime_magic = 0xdeadbeef;
311 newObject->loadtime_format = 0;
312 newObject->bIsDirty = FALSE;
315 newObject->desc = *pictDesc;
317 switch(pictDesc->picType) {
319 OLEPictureImpl_SetBitmap(newObject);
322 case PICTYPE_METAFILE:
323 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
324 newObject->himetricWidth = pictDesc->u.wmf.xExt;
325 newObject->himetricHeight = pictDesc->u.wmf.yExt;
329 /* not sure what to do here */
330 newObject->himetricWidth = newObject->himetricHeight = 0;
334 OLEPictureImpl_SetIcon(newObject);
336 case PICTYPE_ENHMETAFILE:
338 FIXME("Unsupported type %d\n", pictDesc->picType);
339 newObject->himetricWidth = newObject->himetricHeight = 0;
343 newObject->desc.picType = PICTYPE_UNINITIALIZED;
346 TRACE("returning %p\n", newObject);
350 /************************************************************************
351 * OLEPictureImpl_Destroy
353 * This method is called by the Release method when the reference
354 * count goes down to 0. It will free all resources used by
356 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
358 TRACE("(%p)\n", Obj);
361 IConnectionPoint_Release(Obj->pCP);
363 if(Obj->fOwn) { /* We need to destroy the picture */
364 switch(Obj->desc.picType) {
366 DeleteObject(Obj->desc.u.bmp.hbitmap);
367 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
368 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
370 case PICTYPE_METAFILE:
371 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
374 DestroyIcon(Obj->desc.u.icon.hicon);
376 case PICTYPE_ENHMETAFILE:
377 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
380 case PICTYPE_UNINITIALIZED:
384 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
388 HeapFree(GetProcessHeap(), 0, Obj->data);
389 HeapFree(GetProcessHeap(), 0, Obj);
393 /************************************************************************
394 * OLEPictureImpl_AddRef (IUnknown)
396 * See Windows documentation for more details on IUnknown methods.
398 static ULONG WINAPI OLEPictureImpl_AddRef(
401 OLEPictureImpl *This = (OLEPictureImpl *)iface;
402 ULONG refCount = InterlockedIncrement(&This->ref);
404 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
409 /************************************************************************
410 * OLEPictureImpl_Release (IUnknown)
412 * See Windows documentation for more details on IUnknown methods.
414 static ULONG WINAPI OLEPictureImpl_Release(
417 OLEPictureImpl *This = (OLEPictureImpl *)iface;
418 ULONG refCount = InterlockedDecrement(&This->ref);
420 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
423 * If the reference count goes down to 0, perform suicide.
425 if (!refCount) OLEPictureImpl_Destroy(This);
430 /************************************************************************
431 * OLEPictureImpl_QueryInterface (IUnknown)
433 * See Windows documentation for more details on IUnknown methods.
435 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
440 OLEPictureImpl *This = (OLEPictureImpl *)iface;
441 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
444 * Perform a sanity check on the parameters.
446 if ( (This==0) || (ppvObject==0) )
450 * Initialize the return parameter.
455 * Compare the riid with the interface IDs implemented by this object.
457 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
459 else if (IsEqualIID(&IID_IDispatch, riid))
460 *ppvObject = &This->lpvtblIDispatch;
461 else if (IsEqualIID(&IID_IPictureDisp, riid))
462 *ppvObject = &This->lpvtblIDispatch;
463 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
464 *ppvObject = &This->lpvtblIPersistStream;
465 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
466 *ppvObject = &This->lpvtblIConnectionPointContainer;
469 * Check that we obtained an interface.
473 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
474 return E_NOINTERFACE;
478 * Query Interface always increases the reference count by one when it is
481 OLEPictureImpl_AddRef((IPicture*)This);
486 /***********************************************************************
487 * OLEPicture_SendNotify (internal)
489 * Sends notification messages of changed properties to any interested
492 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
494 IEnumConnections *pEnum;
497 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
499 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
500 IPropertyNotifySink *sink;
502 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
503 IPropertyNotifySink_OnChanged(sink, dispID);
504 IPropertyNotifySink_Release(sink);
505 IUnknown_Release(CD.pUnk);
507 IEnumConnections_Release(pEnum);
510 /************************************************************************
511 * OLEPictureImpl_get_Handle
513 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
516 OLEPictureImpl *This = (OLEPictureImpl *)iface;
517 TRACE("(%p)->(%p)\n", This, phandle);
522 switch(This->desc.picType) {
524 case PICTYPE_UNINITIALIZED:
528 *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
530 case PICTYPE_METAFILE:
531 *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
534 *phandle = HandleToUlong(This->desc.u.icon.hicon);
536 case PICTYPE_ENHMETAFILE:
537 *phandle = HandleToUlong(This->desc.u.emf.hemf);
540 FIXME("Unimplemented type %d\n", This->desc.picType);
543 TRACE("returning handle %08x\n", *phandle);
547 /************************************************************************
548 * OLEPictureImpl_get_hPal
550 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
553 OLEPictureImpl *This = (OLEPictureImpl *)iface;
555 TRACE("(%p)->(%p)\n", This, phandle);
560 switch (This->desc.picType) {
561 case (UINT)PICTYPE_UNINITIALIZED:
567 *phandle = HandleToUlong(This->desc.u.bmp.hpal);
570 case PICTYPE_METAFILE:
574 case PICTYPE_ENHMETAFILE:
576 FIXME("unimplemented for type %d. Returning 0 palette.\n",
582 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
586 /************************************************************************
587 * OLEPictureImpl_get_Type
589 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
592 OLEPictureImpl *This = (OLEPictureImpl *)iface;
593 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
598 *ptype = This->desc.picType;
602 /************************************************************************
603 * OLEPictureImpl_get_Width
605 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
606 OLE_XSIZE_HIMETRIC *pwidth)
608 OLEPictureImpl *This = (OLEPictureImpl *)iface;
609 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
610 *pwidth = This->himetricWidth;
614 /************************************************************************
615 * OLEPictureImpl_get_Height
617 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
618 OLE_YSIZE_HIMETRIC *pheight)
620 OLEPictureImpl *This = (OLEPictureImpl *)iface;
621 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
622 *pheight = This->himetricHeight;
626 /************************************************************************
627 * OLEPictureImpl_Render
629 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
630 LONG x, LONG y, LONG cx, LONG cy,
631 OLE_XPOS_HIMETRIC xSrc,
632 OLE_YPOS_HIMETRIC ySrc,
633 OLE_XSIZE_HIMETRIC cxSrc,
634 OLE_YSIZE_HIMETRIC cySrc,
637 OLEPictureImpl *This = (OLEPictureImpl *)iface;
638 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
639 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
641 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
642 prcWBounds->right, prcWBounds->bottom);
644 if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
645 return CTL_E_INVALIDPROPERTYVALUE;
649 * While the documentation suggests this to be here (or after rendering?)
650 * it does cause an endless recursion in my sample app. -MM 20010804
651 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
654 switch(This->desc.picType) {
655 case PICTYPE_UNINITIALIZED:
664 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
665 NB y-axis gets flipped */
667 hdcBmp = CreateCompatibleDC(0);
668 SetMapMode(hdcBmp, MM_ANISOTROPIC);
669 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
670 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
671 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
672 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
675 HDC hdcMask = CreateCompatibleDC(0);
676 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
678 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
680 SetMapMode(hdcMask, MM_ANISOTROPIC);
681 SetWindowOrgEx(hdcMask, 0, 0, NULL);
682 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
683 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
684 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
686 SetBkColor(hdc, RGB(255, 255, 255));
687 SetTextColor(hdc, RGB(0, 0, 0));
688 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
689 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
691 SelectObject(hdcMask, hOldbm);
694 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
695 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
698 SelectObject(hdcBmp, hbmpOld);
703 FIXME("Not quite correct implementation of rendering icons...\n");
704 DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL);
707 case PICTYPE_METAFILE:
709 POINT prevOrg, prevWndOrg;
710 SIZE prevExt, prevWndExt;
713 /* Render the WMF to the appropriate location by setting the
714 appropriate ratio between "device units" and "logical units" */
715 oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
716 /* For the "source rectangle" the y-axis must be inverted */
717 SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
718 SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
719 /* For the "destination rectangle" no inversion is necessary */
720 SetViewportOrgEx(hdc, x, y, &prevOrg);
721 SetViewportExtEx(hdc, cx, cy, &prevExt);
723 if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
724 ERR("PlayMetaFile failed!\n");
726 /* We're done, restore the DC to the previous settings for converting
727 logical units to device units */
728 SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
729 SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
730 SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
731 SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
732 SetMapMode(hdc, oldmode);
736 case PICTYPE_ENHMETAFILE:
738 RECT rc = { x, y, x + cx, y + cy };
739 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
744 FIXME("type %d not implemented\n", This->desc.picType);
750 /************************************************************************
751 * OLEPictureImpl_set_hPal
753 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
756 OLEPictureImpl *This = (OLEPictureImpl *)iface;
757 FIXME("(%p)->(%08x): stub\n", This, hpal);
758 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
762 /************************************************************************
763 * OLEPictureImpl_get_CurDC
765 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
768 OLEPictureImpl *This = (OLEPictureImpl *)iface;
769 TRACE("(%p), returning %p\n", This, This->hDCCur);
770 if (phdc) *phdc = This->hDCCur;
774 /************************************************************************
775 * OLEPictureImpl_SelectPicture
777 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
780 OLE_HANDLE *phbmpOut)
782 OLEPictureImpl *This = (OLEPictureImpl *)iface;
783 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
784 if (This->desc.picType == PICTYPE_BITMAP) {
785 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
788 *phdcOut = This->hDCCur;
789 This->hDCCur = hdcIn;
791 *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
794 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
799 /************************************************************************
800 * OLEPictureImpl_get_KeepOriginalFormat
802 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
805 OLEPictureImpl *This = (OLEPictureImpl *)iface;
806 TRACE("(%p)->(%p)\n", This, pfKeep);
809 *pfKeep = This->keepOrigFormat;
813 /************************************************************************
814 * OLEPictureImpl_put_KeepOriginalFormat
816 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
819 OLEPictureImpl *This = (OLEPictureImpl *)iface;
820 TRACE("(%p)->(%d)\n", This, keep);
821 This->keepOrigFormat = keep;
822 /* FIXME: what DISPID notification here? */
826 /************************************************************************
827 * OLEPictureImpl_PictureChanged
829 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
831 OLEPictureImpl *This = (OLEPictureImpl *)iface;
832 TRACE("(%p)->()\n", This);
833 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
834 This->bIsDirty = TRUE;
838 /************************************************************************
839 * OLEPictureImpl_SaveAsFile
841 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
846 OLEPictureImpl *This = (OLEPictureImpl *)iface;
847 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
848 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
851 /************************************************************************
852 * OLEPictureImpl_get_Attributes
854 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
857 OLEPictureImpl *This = (OLEPictureImpl *)iface;
858 TRACE("(%p)->(%p).\n", This, pdwAttr);
864 switch (This->desc.picType) {
865 case PICTYPE_UNINITIALIZED:
866 case PICTYPE_NONE: break;
867 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
868 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
869 case PICTYPE_ENHMETAFILE: /* fall through */
870 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
871 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
877 /************************************************************************
878 * IConnectionPointContainer
880 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
881 IConnectionPointContainer* iface,
885 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
887 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
890 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
891 IConnectionPointContainer* iface)
893 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
895 return IPicture_AddRef((IPicture *)This);
898 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
899 IConnectionPointContainer* iface)
901 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
903 return IPicture_Release((IPicture *)This);
906 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
907 IConnectionPointContainer* iface,
908 IEnumConnectionPoints** ppEnum)
910 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
912 FIXME("(%p,%p), stub!\n",This,ppEnum);
916 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
917 IConnectionPointContainer* iface,
919 IConnectionPoint **ppCP)
921 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
922 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
926 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
927 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
928 FIXME("no connection point for %s\n",debugstr_guid(riid));
929 return CONNECT_E_NOCONNECTION;
933 /************************************************************************
937 /************************************************************************
938 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
940 * See Windows documentation for more details on IUnknown methods.
942 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
943 IPersistStream* iface,
947 OLEPictureImpl *This = impl_from_IPersistStream(iface);
949 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
952 /************************************************************************
953 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
955 * See Windows documentation for more details on IUnknown methods.
957 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
958 IPersistStream* iface)
960 OLEPictureImpl *This = impl_from_IPersistStream(iface);
962 return IPicture_AddRef((IPicture *)This);
965 /************************************************************************
966 * OLEPictureImpl_IPersistStream_Release (IUnknown)
968 * See Windows documentation for more details on IUnknown methods.
970 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
971 IPersistStream* iface)
973 OLEPictureImpl *This = impl_from_IPersistStream(iface);
975 return IPicture_Release((IPicture *)This);
978 /************************************************************************
979 * OLEPictureImpl_IPersistStream_GetClassID
981 static HRESULT WINAPI OLEPictureImpl_GetClassID(
982 IPersistStream* iface,CLSID* pClassID)
984 TRACE("(%p)\n", pClassID);
985 *pClassID = CLSID_StdPicture;
989 /************************************************************************
990 * OLEPictureImpl_IPersistStream_IsDirty
992 static HRESULT WINAPI OLEPictureImpl_IsDirty(
993 IPersistStream* iface)
995 OLEPictureImpl *This = impl_from_IPersistStream(iface);
996 FIXME("(%p),stub!\n",This);
1000 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1002 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1003 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1006 /* Does not matter whether this is a coreheader or not, we only use
1007 * components which are in both
1010 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1014 xbuf+bfh->bfOffBits,
1018 ReleaseDC(0, hdcref);
1019 if (This->desc.u.bmp.hbitmap == 0)
1021 This->desc.picType = PICTYPE_BITMAP;
1022 OLEPictureImpl_SetBitmap(This);
1026 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
1029 BITMAPINFOHEADER bih;
1032 UINT stride, buffersize;
1035 IWICBitmapSource *real_source;
1037 COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
1038 BOOL has_alpha=FALSE;
1040 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
1041 if (FAILED(hr)) return hr;
1043 hr = IWICBitmapSource_GetSize(real_source, &width, &height);
1044 if (FAILED(hr)) goto end;
1046 bih.biSize = sizeof(bih);
1047 bih.biWidth = width;
1048 bih.biHeight = -height;
1050 bih.biBitCount = 32;
1051 bih.biCompression = BI_RGB;
1052 bih.biSizeImage = 0;
1053 bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
1054 bih.biYPelsPerMeter = 4085;
1056 bih.biClrImportant = 0;
1059 buffersize = stride * height;
1061 bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
1072 hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
1077 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1085 if (This->desc.u.bmp.hbitmap == 0)
1088 ReleaseDC(0, hdcref);
1092 This->desc.picType = PICTYPE_BITMAP;
1093 OLEPictureImpl_SetBitmap(This);
1095 /* set transparent pixels to black, all others to white */
1096 for(y = 0; y < height; y++){
1097 for(x = 0; x < width; x++){
1098 DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
1099 if((*pixel & 0x80000000) == 0)
1111 HDC hdcBmp, hdcXor, hdcMask;
1112 HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
1114 This->hbmXor = CreateDIBitmap(
1123 This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
1124 hdcBmp = CreateCompatibleDC(NULL);
1125 hdcXor = CreateCompatibleDC(NULL);
1126 hdcMask = CreateCompatibleDC(NULL);
1128 hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
1129 hbmoldXor = SelectObject(hdcXor,This->hbmXor);
1130 hbmoldMask = SelectObject(hdcMask,This->hbmMask);
1132 SetBkColor(hdcXor,black);
1133 BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
1134 BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
1136 SelectObject(hdcBmp,hbmoldBmp);
1137 SelectObject(hdcXor,hbmoldXor);
1138 SelectObject(hdcMask,hbmoldMask);
1145 ReleaseDC(0, hdcref);
1148 HeapFree(GetProcessHeap(), 0, bits);
1149 IWICBitmapSource_Release(real_source);
1153 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
1156 IWICImagingFactory *factory;
1157 IWICBitmapDecoder *decoder;
1158 IWICBitmapFrameDecode *framedecode;
1162 initresult = CoInitialize(NULL);
1164 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1165 &IID_IWICImagingFactory, (void**)&factory);
1166 if (SUCCEEDED(hr)) /* created factory */
1168 hr = IWICImagingFactory_CreateStream(factory, &stream);
1169 IWICImagingFactory_Release(factory);
1172 if (SUCCEEDED(hr)) /* created stream */
1174 hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
1176 if (SUCCEEDED(hr)) /* initialized stream */
1178 hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
1179 &IID_IWICBitmapDecoder, (void**)&decoder);
1180 if (SUCCEEDED(hr)) /* created decoder */
1182 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
1184 if (SUCCEEDED(hr)) /* initialized decoder */
1185 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
1187 IWICBitmapDecoder_Release(decoder);
1191 IWICStream_Release(stream);
1194 if (SUCCEEDED(hr)) /* got framedecode */
1196 hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
1197 IWICBitmapFrameDecode_Release(framedecode);
1200 if (SUCCEEDED(initresult)) CoUninitialize();
1204 /*****************************************************
1205 * start of Icon-specific code
1208 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1211 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1216 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1217 FIXME("icon.idType=%d\n",cifd->idType);
1218 FIXME("icon.idCount=%d\n",cifd->idCount);
1220 for (i=0;i<cifd->idCount;i++) {
1221 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1222 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1223 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1224 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1225 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1226 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1227 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1228 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1232 /* If we have more than one icon, try to find the best.
1233 * this currently means '32 pixel wide'.
1235 if (cifd->idCount!=1) {
1236 for (i=0;i<cifd->idCount;i++) {
1237 if (cifd->idEntries[i].bWidth == 32)
1240 if (i==cifd->idCount) i=0;
1243 hicon = CreateIconFromResourceEx(
1244 xbuf+cifd->idEntries[i].dwDIBOffset,
1245 cifd->idEntries[i].dwDIBSize,
1248 cifd->idEntries[i].bWidth,
1249 cifd->idEntries[i].bHeight,
1253 ERR("CreateIcon failed.\n");
1256 This->desc.picType = PICTYPE_ICON;
1257 This->desc.u.icon.hicon = hicon;
1258 This->origWidth = cifd->idEntries[i].bWidth;
1259 This->origHeight = cifd->idEntries[i].bHeight;
1260 hdcRef = CreateCompatibleDC(0);
1261 This->himetricWidth = xpixels_to_himetric(cifd->idEntries[i].bWidth, hdcRef);
1262 This->himetricHeight= ypixels_to_himetric(cifd->idEntries[i].bHeight, hdcRef);
1268 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
1269 const BYTE *data, ULONG size)
1274 hemf = SetEnhMetaFileBits(size, data);
1275 if (!hemf) return E_FAIL;
1277 GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
1279 This->desc.picType = PICTYPE_ENHMETAFILE;
1280 This->desc.u.emf.hemf = hemf;
1282 This->origWidth = 0;
1283 This->origHeight = 0;
1284 This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
1285 This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
1290 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
1291 const BYTE *data, ULONG size)
1293 const APM_HEADER *header = (const APM_HEADER *)data;
1296 if (size < sizeof(APM_HEADER))
1298 if (header->key != 0x9ac6cdd7)
1301 /* SetMetaFileBitsEx performs data check on its own */
1302 hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
1303 if (!hmf) return E_FAIL;
1305 This->desc.picType = PICTYPE_METAFILE;
1306 This->desc.u.wmf.hmeta = hmf;
1307 This->desc.u.wmf.xExt = 0;
1308 This->desc.u.wmf.yExt = 0;
1310 This->origWidth = 0;
1311 This->origHeight = 0;
1312 This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
1313 This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
1317 /************************************************************************
1318 * BITMAP FORMAT FLAGS -
1319 * Flags that differentiate between different types of bitmaps.
1322 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
1323 #define BITMAP_FORMAT_JPEG 0xd8ff
1324 #define BITMAP_FORMAT_GIF 0x4947
1325 #define BITMAP_FORMAT_PNG 0x5089
1326 #define BITMAP_FORMAT_APM 0xcdd7
1328 /************************************************************************
1329 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1331 * Loads the binary data from the IStream. Starts at current position.
1332 * There appears to be an 2 DWORD header:
1336 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1338 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1339 HRESULT hr = E_FAIL;
1340 BOOL headerisdata = FALSE;
1341 BOOL statfailed = FALSE;
1342 ULONG xread, toread;
1348 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1350 TRACE("(%p,%p)\n",This,pStm);
1352 /****************************************************************************************
1353 * Part 1: Load the data
1355 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1356 * out whether we do.
1358 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1359 * compound file. This may explain most, if not all, of the cases of "no
1360 * header", and the header validation should take this into account.
1361 * At least in Visual Basic 6, resource streams, valid headers are
1362 * header[0] == "lt\0\0",
1363 * header[1] == length_of_stream.
1365 * Also handle streams where we do not have a working "Stat" method by
1366 * reading all data until the end of the stream.
1368 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1370 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1372 /* we will read at least 8 byte ... just right below */
1373 statstg.cbSize.QuadPart = 8;
1378 headerisdata = FALSE;
1380 hr=IStream_Read(pStm,header,8,&xread);
1381 if (hr || xread!=8) {
1382 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1383 return (hr?hr:E_FAIL);
1385 headerread += xread;
1388 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1389 if (toread != 0 && toread != header[1])
1390 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1393 if (toread == 0) break;
1395 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1396 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1397 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1398 (header[0] == EMR_HEADER) || /* EMF header */
1399 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1401 ) {/* Found start of bitmap data */
1402 headerisdata = TRUE;
1404 toread = statstg.cbSize.QuadPart-8;
1408 FIXME("Unknown stream header magic: %08x\n", header[0]);
1412 } while (!headerisdata);
1414 if (statfailed) { /* we don't know the size ... read all we get */
1416 int origsize = sizeinc;
1419 TRACE("Reading all data from stream.\n");
1420 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1422 memcpy (xbuf, header, 8);
1424 while (xread < origsize) {
1425 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1430 if (!nread || hr) /* done, or error */
1432 if (xread == origsize) {
1433 origsize += sizeinc;
1434 sizeinc = 2*sizeinc; /* exponential increase */
1435 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1439 TRACE("hr in no-stat loader case is %08x\n", hr);
1440 TRACE("loaded %d bytes.\n", xread);
1441 This->datalen = xread;
1444 This->datalen = toread+(headerisdata?8:0);
1445 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1447 return E_OUTOFMEMORY;
1450 memcpy (xbuf, header, 8);
1452 while (xread < This->datalen) {
1454 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1459 if (xread != This->datalen)
1460 ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1462 if (This->datalen == 0) { /* Marks the "NONE" picture */
1463 This->desc.picType = PICTYPE_NONE;
1468 /****************************************************************************************
1469 * Part 2: Process the loaded data
1472 magic = xbuf[0] + (xbuf[1]<<8);
1473 This->loadtime_format = magic;
1476 case BITMAP_FORMAT_GIF: /* GIF */
1477 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
1479 case BITMAP_FORMAT_JPEG: /* JPEG */
1480 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
1482 case BITMAP_FORMAT_BMP: /* Bitmap */
1483 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1485 case BITMAP_FORMAT_PNG: /* PNG */
1486 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
1488 case BITMAP_FORMAT_APM: /* APM */
1489 hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
1491 case 0x0000: { /* ICON , first word is dwReserved */
1492 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1499 /* let's see if it's a EMF */
1500 hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
1501 if (hr == S_OK) break;
1503 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1505 for (i=0;i<xread+8;i++) {
1506 if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
1507 else MESSAGE("%02x ",xbuf[i-8]);
1508 if (i % 10 == 9) MESSAGE("\n");
1514 This->bIsDirty = FALSE;
1516 /* FIXME: this notify is not really documented */
1518 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1522 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1526 BITMAPINFO * pInfoBitmap;
1527 int iNumPaletteEntries;
1528 unsigned char * pPixelData;
1529 BITMAPFILEHEADER * pFileHeader;
1530 BITMAPINFO * pInfoHeader;
1532 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1533 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1535 /* Find out bitmap size and padded length */
1537 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1538 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1540 /* Fetch bitmap palette & pixel data */
1542 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1543 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1545 /* Calculate the total length required for the BMP data */
1546 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1547 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1548 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1550 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1551 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1553 iNumPaletteEntries = 0;
1556 sizeof(BITMAPFILEHEADER) +
1557 sizeof(BITMAPINFOHEADER) +
1558 iNumPaletteEntries * sizeof(RGBQUAD) +
1559 pInfoBitmap->bmiHeader.biSizeImage;
1560 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1562 /* Fill the BITMAPFILEHEADER */
1563 pFileHeader = *ppBuffer;
1564 pFileHeader->bfType = BITMAP_FORMAT_BMP;
1565 pFileHeader->bfSize = *pLength;
1566 pFileHeader->bfOffBits =
1567 sizeof(BITMAPFILEHEADER) +
1568 sizeof(BITMAPINFOHEADER) +
1569 iNumPaletteEntries * sizeof(RGBQUAD);
1571 /* Fill the BITMAPINFOHEADER and the palette data */
1572 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1573 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1575 (unsigned char *)(*ppBuffer) +
1576 sizeof(BITMAPFILEHEADER) +
1577 sizeof(BITMAPINFOHEADER) +
1578 iNumPaletteEntries * sizeof(RGBQUAD),
1579 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1582 HeapFree(GetProcessHeap(), 0, pPixelData);
1583 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1587 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1592 *ppBuffer = NULL; *pLength = 0;
1593 if (GetIconInfo(hIcon, &infoIcon)) {
1595 BITMAPINFO * pInfoBitmap;
1596 unsigned char * pIconData = NULL;
1597 unsigned int iDataSize = 0;
1599 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1601 /* Find out icon size */
1603 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1604 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1606 /* Auxiliary pointers */
1607 CURSORICONFILEDIR * pIconDir;
1608 CURSORICONFILEDIRENTRY * pIconEntry;
1609 BITMAPINFOHEADER * pIconBitmapHeader;
1610 unsigned int iOffsetPalette;
1611 unsigned int iOffsetColorData;
1612 unsigned int iOffsetMaskData;
1614 unsigned int iLengthScanLineMask;
1615 unsigned int iNumEntriesPalette;
1617 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1619 FIXME("DEBUG: bitmap size is %d x %d\n",
1620 pInfoBitmap->bmiHeader.biWidth,
1621 pInfoBitmap->bmiHeader.biHeight);
1622 FIXME("DEBUG: bitmap bpp is %d\n",
1623 pInfoBitmap->bmiHeader.biBitCount);
1624 FIXME("DEBUG: bitmap nplanes is %d\n",
1625 pInfoBitmap->bmiHeader.biPlanes);
1626 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1627 pInfoBitmap->bmiHeader.biSizeImage);
1629 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1630 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1631 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1633 /* Fill out the CURSORICONFILEDIR */
1634 pIconDir = (CURSORICONFILEDIR *)pIconData;
1635 pIconDir->idType = 1;
1636 pIconDir->idCount = 1;
1638 /* Fill out the CURSORICONFILEDIRENTRY */
1639 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1640 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1641 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1642 pIconEntry->bColorCount =
1643 (pInfoBitmap->bmiHeader.biBitCount < 8)
1644 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1646 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1647 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1648 pIconEntry->dwDIBSize = 0;
1649 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1651 /* Fill out the BITMAPINFOHEADER */
1652 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1653 *pIconBitmapHeader = pInfoBitmap->bmiHeader;
1655 /* Find out whether a palette exists for the bitmap */
1656 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1657 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1658 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1659 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1660 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1661 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1662 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1663 iNumEntriesPalette = 3;
1664 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1665 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1667 iNumEntriesPalette = 0;
1670 /* Add bitmap size and header size to icon data size. */
1671 iOffsetPalette = iDataSize;
1672 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1673 iOffsetColorData = iDataSize;
1674 iDataSize += pIconBitmapHeader->biSizeImage;
1675 iOffsetMaskData = iDataSize;
1676 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1677 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1678 pIconBitmapHeader->biHeight *= 2;
1679 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1680 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1681 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1682 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1684 /* Get the actual bitmap data from the icon bitmap */
1685 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1686 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1687 if (iNumEntriesPalette > 0) {
1688 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1689 iNumEntriesPalette * sizeof(RGBQUAD));
1692 /* Reset all values so that GetDIBits call succeeds */
1693 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1694 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1695 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1697 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1698 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1699 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1701 printf("ERROR: unable to get bitmap mask (error %u)\n",
1706 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1707 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1709 /* Write out everything produced so far to the stream */
1710 *ppBuffer = pIconData; *pLength = iDataSize;
1714 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1719 Remarks (from MSDN entry on GetIconInfo):
1721 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1722 members of ICONINFO. The calling application must manage
1723 these bitmaps and delete them when they are no longer
1726 if (hDC) ReleaseDC(0, hDC);
1727 DeleteObject(infoIcon.hbmMask);
1728 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1729 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1731 printf("ERROR: Unable to get icon information (error %u)\n",
1737 static HRESULT WINAPI OLEPictureImpl_Save(
1738 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1740 HRESULT hResult = E_NOTIMPL;
1742 unsigned int iDataSize;
1744 int iSerializeResult = 0;
1745 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1747 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1749 switch (This->desc.picType) {
1751 if (This->bIsDirty || !This->data) {
1752 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1753 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1757 HeapFree(GetProcessHeap(), 0, This->data);
1758 This->data = pIconData;
1759 This->datalen = iDataSize;
1761 if (This->loadtime_magic != 0xdeadbeef) {
1764 header[0] = This->loadtime_magic;
1765 header[1] = This->datalen;
1766 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1768 IStream_Write(pStm, This->data, This->datalen, &dummy);
1772 case PICTYPE_BITMAP:
1773 if (This->bIsDirty) {
1774 switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
1775 case BITMAP_FORMAT_BMP:
1776 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1778 case BITMAP_FORMAT_JPEG:
1779 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1781 case BITMAP_FORMAT_GIF:
1782 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1784 case BITMAP_FORMAT_PNG:
1785 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
1788 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1791 if (iSerializeResult) {
1793 if (This->loadtime_magic != 0xdeadbeef) {
1798 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1799 header[1] = iDataSize;
1800 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1802 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1804 HeapFree(GetProcessHeap(), 0, This->data);
1805 This->data = pIconData;
1806 This->datalen = iDataSize;
1811 if (This->loadtime_magic != 0xdeadbeef) {
1816 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1817 header[1] = This->datalen;
1818 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1820 IStream_Write(pStm, This->data, This->datalen, &dummy);
1824 case PICTYPE_METAFILE:
1825 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1827 case PICTYPE_ENHMETAFILE:
1828 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1831 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1834 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1838 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1839 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1841 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1842 FIXME("(%p,%p),stub!\n",This,pcbSize);
1847 /************************************************************************
1851 /************************************************************************
1852 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1854 * See Windows documentation for more details on IUnknown methods.
1856 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1861 OLEPictureImpl *This = impl_from_IDispatch(iface);
1863 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1866 /************************************************************************
1867 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1869 * See Windows documentation for more details on IUnknown methods.
1871 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1874 OLEPictureImpl *This = impl_from_IDispatch(iface);
1876 return IPicture_AddRef((IPicture *)This);
1879 /************************************************************************
1880 * OLEPictureImpl_IDispatch_Release (IUnknown)
1882 * See Windows documentation for more details on IUnknown methods.
1884 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1887 OLEPictureImpl *This = impl_from_IDispatch(iface);
1889 return IPicture_Release((IPicture *)This);
1892 /************************************************************************
1893 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1895 * See Windows documentation for more details on IDispatch methods.
1897 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1899 unsigned int* pctinfo)
1901 TRACE("(%p)\n", pctinfo);
1908 /************************************************************************
1909 * OLEPictureImpl_GetTypeInfo (IDispatch)
1911 * See Windows documentation for more details on IDispatch methods.
1913 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1917 ITypeInfo** ppTInfo)
1919 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1923 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1928 hres = LoadTypeLib(stdole2tlb, &tl);
1931 ERR("Could not load stdole2.tlb\n");
1935 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1937 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1942 /************************************************************************
1943 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1945 * See Windows documentation for more details on IDispatch methods.
1947 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1950 LPOLESTR* rgszNames,
1958 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
1959 rgszNames, cNames, (int)lcid, rgDispId);
1963 return E_INVALIDARG;
1967 /* retrieve type information */
1968 hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1972 ERR("GetTypeInfo failed.\n");
1976 /* convert names to DISPIDs */
1977 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1978 ITypeInfo_Release(pTInfo);
1984 /************************************************************************
1985 * OLEPictureImpl_Invoke (IDispatch)
1987 * See Windows documentation for more details on IDispatch methods.
1989 static HRESULT WINAPI OLEPictureImpl_Invoke(
1991 DISPID dispIdMember,
1995 DISPPARAMS* pDispParams,
1996 VARIANT* pVarResult,
1997 EXCEPINFO* pExepInfo,
2000 OLEPictureImpl *This = impl_from_IDispatch(iface);
2002 /* validate parameters */
2004 if (!IsEqualIID(riid, &IID_NULL))
2006 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2007 return DISP_E_UNKNOWNNAME;
2012 ERR("null pDispParams not allowed\n");
2013 return DISP_E_PARAMNOTOPTIONAL;
2016 if (wFlags & DISPATCH_PROPERTYGET)
2018 if (pDispParams->cArgs != 0)
2020 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2021 return DISP_E_BADPARAMCOUNT;
2025 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2026 return DISP_E_PARAMNOTOPTIONAL;
2029 else if (wFlags & DISPATCH_PROPERTYPUT)
2031 if (pDispParams->cArgs != 1)
2033 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2034 return DISP_E_BADPARAMCOUNT;
2038 switch (dispIdMember)
2040 case DISPID_PICT_HANDLE:
2041 if (wFlags & DISPATCH_PROPERTYGET)
2043 TRACE("DISPID_PICT_HANDLE\n");
2044 V_VT(pVarResult) = VT_I4;
2045 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2048 case DISPID_PICT_HPAL:
2049 if (wFlags & DISPATCH_PROPERTYGET)
2051 TRACE("DISPID_PICT_HPAL\n");
2052 V_VT(pVarResult) = VT_I4;
2053 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2055 else if (wFlags & DISPATCH_PROPERTYPUT)
2059 TRACE("DISPID_PICT_HPAL\n");
2061 VariantInit(&vararg);
2062 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2066 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2068 VariantClear(&vararg);
2072 case DISPID_PICT_TYPE:
2073 if (wFlags & DISPATCH_PROPERTYGET)
2075 TRACE("DISPID_PICT_TYPE\n");
2076 V_VT(pVarResult) = VT_I2;
2077 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2080 case DISPID_PICT_WIDTH:
2081 if (wFlags & DISPATCH_PROPERTYGET)
2083 TRACE("DISPID_PICT_WIDTH\n");
2084 V_VT(pVarResult) = VT_I4;
2085 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2088 case DISPID_PICT_HEIGHT:
2089 if (wFlags & DISPATCH_PROPERTYGET)
2091 TRACE("DISPID_PICT_HEIGHT\n");
2092 V_VT(pVarResult) = VT_I4;
2093 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2098 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2099 return DISP_E_MEMBERNOTFOUND;
2103 static const IPictureVtbl OLEPictureImpl_VTable =
2105 OLEPictureImpl_QueryInterface,
2106 OLEPictureImpl_AddRef,
2107 OLEPictureImpl_Release,
2108 OLEPictureImpl_get_Handle,
2109 OLEPictureImpl_get_hPal,
2110 OLEPictureImpl_get_Type,
2111 OLEPictureImpl_get_Width,
2112 OLEPictureImpl_get_Height,
2113 OLEPictureImpl_Render,
2114 OLEPictureImpl_set_hPal,
2115 OLEPictureImpl_get_CurDC,
2116 OLEPictureImpl_SelectPicture,
2117 OLEPictureImpl_get_KeepOriginalFormat,
2118 OLEPictureImpl_put_KeepOriginalFormat,
2119 OLEPictureImpl_PictureChanged,
2120 OLEPictureImpl_SaveAsFile,
2121 OLEPictureImpl_get_Attributes
2124 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2126 OLEPictureImpl_IDispatch_QueryInterface,
2127 OLEPictureImpl_IDispatch_AddRef,
2128 OLEPictureImpl_IDispatch_Release,
2129 OLEPictureImpl_GetTypeInfoCount,
2130 OLEPictureImpl_GetTypeInfo,
2131 OLEPictureImpl_GetIDsOfNames,
2132 OLEPictureImpl_Invoke
2135 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2137 OLEPictureImpl_IPersistStream_QueryInterface,
2138 OLEPictureImpl_IPersistStream_AddRef,
2139 OLEPictureImpl_IPersistStream_Release,
2140 OLEPictureImpl_GetClassID,
2141 OLEPictureImpl_IsDirty,
2142 OLEPictureImpl_Load,
2143 OLEPictureImpl_Save,
2144 OLEPictureImpl_GetSizeMax
2147 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2149 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2150 OLEPictureImpl_IConnectionPointContainer_AddRef,
2151 OLEPictureImpl_IConnectionPointContainer_Release,
2152 OLEPictureImpl_EnumConnectionPoints,
2153 OLEPictureImpl_FindConnectionPoint
2156 /***********************************************************************
2157 * OleCreatePictureIndirect (OLEAUT32.419)
2159 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2160 BOOL fOwn, LPVOID *ppvObj )
2162 OLEPictureImpl* newPict = NULL;
2165 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2176 * Try to construct a new instance of the class.
2178 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2180 if (newPict == NULL)
2181 return E_OUTOFMEMORY;
2184 * Make sure it supports the interface required by the caller.
2186 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2189 * Release the reference obtained in the constructor. If
2190 * the QueryInterface was unsuccessful, it will free the class.
2192 IPicture_Release((IPicture*)newPict);
2198 /***********************************************************************
2199 * OleLoadPicture (OLEAUT32.418)
2201 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2202 REFIID riid, LPVOID *ppvObj )
2208 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2209 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2211 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2214 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2216 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2217 IPicture_Release(newpic);
2221 hr = IPersistStream_Load(ps,lpstream);
2222 IPersistStream_Release(ps);
2225 ERR("IPersistStream_Load failed\n");
2226 IPicture_Release(newpic);
2230 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2232 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2233 IPicture_Release(newpic);
2237 /***********************************************************************
2238 * OleLoadPictureEx (OLEAUT32.401)
2240 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2241 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2247 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2248 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2250 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2253 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2255 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2256 IPicture_Release(newpic);
2260 hr = IPersistStream_Load(ps,lpstream);
2261 IPersistStream_Release(ps);
2264 ERR("IPersistStream_Load failed\n");
2265 IPicture_Release(newpic);
2269 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2271 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2272 IPicture_Release(newpic);
2276 /***********************************************************************
2277 * OleLoadPicturePath (OLEAUT32.424)
2279 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2280 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2283 static const WCHAR file[] = { 'f','i','l','e',':',0 };
2287 HGLOBAL hGlobal = NULL;
2288 DWORD dwBytesRead = 0;
2291 IPersistStream *pStream;
2294 WCHAR *file_candidate;
2295 WCHAR path_buf[MAX_PATH];
2297 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2298 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2299 debugstr_guid(riid), ppvRet);
2301 if (!szURLorPath || !ppvRet)
2302 return E_INVALIDARG;
2306 /* Convert file URLs to DOS paths. */
2307 if (strncmpW(szURLorPath, file, 5) == 0) {
2309 hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
2310 sizeof(path_buf)/sizeof(WCHAR), &size, 0);
2314 file_candidate = path_buf;
2317 file_candidate = szURLorPath;
2319 /* Handle candidate DOS paths separately. */
2320 if (file_candidate[1] == ':') {
2321 hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2323 if (hFile == INVALID_HANDLE_VALUE)
2324 return E_UNEXPECTED;
2326 dwFileSize = GetFileSize(hFile, NULL);
2327 if (dwFileSize != INVALID_FILE_SIZE )
2329 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2332 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2335 GlobalFree(hGlobal);
2343 return E_UNEXPECTED;
2345 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2348 GlobalFree(hGlobal);
2355 hRes = CreateBindCtx(0, &pbc);
2356 if (SUCCEEDED(hRes))
2358 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2359 if (SUCCEEDED(hRes))
2361 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2362 IMoniker_Release(pmnk);
2364 IBindCtx_Release(pbc);
2370 init_res = CoInitialize(NULL);
2372 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2373 &IID_IPicture, (LPVOID*)&ipicture);
2374 if (SUCCEEDED(hRes)) {
2375 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2377 if (SUCCEEDED(hRes)) {
2378 hRes = IPersistStream_Load(pStream, stream);
2380 if (SUCCEEDED(hRes)) {
2381 hRes = IPicture_QueryInterface(ipicture, riid, ppvRet);
2384 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid));
2386 IPersistStream_Release(pStream);
2388 IPicture_Release(ipicture);
2391 IStream_Release(stream);
2393 if (SUCCEEDED(init_res))
2399 /*******************************************************************************
2400 * StdPic ClassFactory
2404 /* IUnknown fields */
2405 const IClassFactoryVtbl *lpVtbl;
2407 } IClassFactoryImpl;
2409 static HRESULT WINAPI
2410 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2411 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2413 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2414 return E_NOINTERFACE;
2418 SPCF_AddRef(LPCLASSFACTORY iface) {
2419 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2420 return InterlockedIncrement(&This->ref);
2423 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2424 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2425 /* static class, won't be freed */
2426 return InterlockedDecrement(&This->ref);
2429 static HRESULT WINAPI SPCF_CreateInstance(
2430 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2432 /* Creates an uninitialized picture */
2433 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2437 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2438 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2439 FIXME("(%p)->(%d),stub!\n",This,dolock);
2443 static const IClassFactoryVtbl SPCF_Vtbl = {
2444 SPCF_QueryInterface,
2447 SPCF_CreateInstance,
2450 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2452 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }