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
65 #include "wine/debug.h"
66 #include "wine/unicode.h"
67 #include "wine/library.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(ole);
73 /* Header for Aldus Placable Metafiles - a standard metafile follows */
74 typedef struct _APM_HEADER
96 } CURSORICONFILEDIRENTRY;
103 CURSORICONFILEDIRENTRY idEntries[1];
108 /*************************************************************************
109 * Declaration of implementation class
112 typedef struct OLEPictureImpl {
115 * IPicture handles IUnknown
118 IPicture IPicture_iface;
119 IDispatch IDispatch_iface;
120 IPersistStream IPersistStream_iface;
121 IConnectionPointContainer IConnectionPointContainer_iface;
123 /* Object reference count */
126 /* We own the object and must destroy it ourselves */
129 /* Picture description */
132 /* These are the pixel size of a bitmap */
136 /* And these are the size of the picture converted into HIMETRIC units */
137 OLE_XSIZE_HIMETRIC himetricWidth;
138 OLE_YSIZE_HIMETRIC himetricHeight;
140 IConnectionPoint *pCP;
144 HBITMAP stock_bitmap;
146 /* Bitmap transparency mask */
154 BOOL bIsDirty; /* Set to TRUE if picture has changed */
155 unsigned int loadtime_magic; /* If a length header was found, saves value */
156 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
159 static inline OLEPictureImpl *impl_from_IPicture(IPicture *iface)
161 return CONTAINING_RECORD(iface, OLEPictureImpl, IPicture_iface);
164 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
166 return CONTAINING_RECORD(iface, OLEPictureImpl, IDispatch_iface);
169 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
171 return CONTAINING_RECORD(iface, OLEPictureImpl, IPersistStream_iface);
174 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
176 return CONTAINING_RECORD(iface, OLEPictureImpl, IConnectionPointContainer_iface);
180 * Predeclare VTables. They get initialized at the end.
182 static const IPictureVtbl OLEPictureImpl_VTable;
183 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
184 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
185 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
187 /* pixels to HIMETRIC units conversion */
188 static inline OLE_XSIZE_HIMETRIC xpixels_to_himetric(INT pixels, HDC hdc)
190 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
193 static inline OLE_YSIZE_HIMETRIC ypixels_to_himetric(INT pixels, HDC hdc)
195 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
198 /***********************************************************************
199 * Implementation of the OLEPictureImpl class.
202 static void OLEPictureImpl_SetBitmap(OLEPictureImpl *This)
207 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
208 if(GetObjectW(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
209 ERR("GetObject fails\n");
212 This->origWidth = bm.bmWidth;
213 This->origHeight = bm.bmHeight;
215 /* The width and height are stored in HIMETRIC units (0.01 mm),
216 so we take our pixel width divide by pixels per inch and
217 multiply by 25.4 * 100 */
218 /* Should we use GetBitmapDimension if available? */
219 hdcRef = CreateCompatibleDC(0);
221 This->himetricWidth = xpixels_to_himetric(bm.bmWidth, hdcRef);
222 This->himetricHeight = ypixels_to_himetric(bm.bmHeight, hdcRef);
223 This->stock_bitmap = GetCurrentObject( hdcRef, OBJ_BITMAP );
228 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
232 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
233 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
237 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
238 if(GetObjectW(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
239 ERR("GetObject fails on icon bitmap\n");
243 This->origWidth = bm.bmWidth;
244 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
245 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
248 This->himetricWidth = xpixels_to_himetric(This->origWidth, hdcRef);
249 This->himetricHeight = ypixels_to_himetric(This->origHeight, hdcRef);
251 ReleaseDC(0, hdcRef);
253 DeleteObject(infoIcon.hbmMask);
254 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
256 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
260 /************************************************************************
261 * OLEPictureImpl_Construct
263 * This method will construct a new instance of the OLEPictureImpl
266 * The caller of this method must release the object when it's
269 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
271 OLEPictureImpl* newObject = 0;
274 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
277 * Allocate space for the object.
279 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
285 * Initialize the virtual function table.
287 newObject->IPicture_iface.lpVtbl = &OLEPictureImpl_VTable;
288 newObject->IDispatch_iface.lpVtbl = &OLEPictureImpl_IDispatch_VTable;
289 newObject->IPersistStream_iface.lpVtbl = &OLEPictureImpl_IPersistStream_VTable;
290 newObject->IConnectionPointContainer_iface.lpVtbl = &OLEPictureImpl_IConnectionPointContainer_VTable;
292 newObject->pCP = NULL;
293 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
296 HeapFree(GetProcessHeap(), 0, newObject);
301 * Start with one reference count. The caller of this function
302 * must release the interface pointer when it is done.
305 newObject->hDCCur = 0;
307 newObject->fOwn = fOwn;
309 /* dunno about original value */
310 newObject->keepOrigFormat = TRUE;
312 newObject->hbmMask = NULL;
313 newObject->hbmXor = NULL;
314 newObject->loadtime_magic = 0xdeadbeef;
315 newObject->loadtime_format = 0;
316 newObject->bIsDirty = FALSE;
319 newObject->desc = *pictDesc;
321 switch(pictDesc->picType) {
323 OLEPictureImpl_SetBitmap(newObject);
326 case PICTYPE_METAFILE:
327 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
328 newObject->himetricWidth = pictDesc->u.wmf.xExt;
329 newObject->himetricHeight = pictDesc->u.wmf.yExt;
333 /* not sure what to do here */
334 newObject->himetricWidth = newObject->himetricHeight = 0;
338 OLEPictureImpl_SetIcon(newObject);
340 case PICTYPE_ENHMETAFILE:
342 FIXME("Unsupported type %d\n", pictDesc->picType);
343 newObject->himetricWidth = newObject->himetricHeight = 0;
347 newObject->desc.picType = PICTYPE_UNINITIALIZED;
350 TRACE("returning %p\n", newObject);
354 /************************************************************************
355 * OLEPictureImpl_Destroy
357 * This method is called by the Release method when the reference
358 * count goes down to 0. It will free all resources used by
360 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
362 TRACE("(%p)\n", Obj);
365 IConnectionPoint_Release(Obj->pCP);
367 if(Obj->fOwn) { /* We need to destroy the picture */
368 switch(Obj->desc.picType) {
370 DeleteObject(Obj->desc.u.bmp.hbitmap);
371 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
372 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
374 case PICTYPE_METAFILE:
375 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
378 DestroyIcon(Obj->desc.u.icon.hicon);
380 case PICTYPE_ENHMETAFILE:
381 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
384 case PICTYPE_UNINITIALIZED:
388 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
392 HeapFree(GetProcessHeap(), 0, Obj->data);
393 HeapFree(GetProcessHeap(), 0, Obj);
397 /************************************************************************
398 * OLEPictureImpl_AddRef (IUnknown)
400 * See Windows documentation for more details on IUnknown methods.
402 static ULONG WINAPI OLEPictureImpl_AddRef(
405 OLEPictureImpl *This = impl_from_IPicture(iface);
406 ULONG refCount = InterlockedIncrement(&This->ref);
408 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
413 /************************************************************************
414 * OLEPictureImpl_Release (IUnknown)
416 * See Windows documentation for more details on IUnknown methods.
418 static ULONG WINAPI OLEPictureImpl_Release(
421 OLEPictureImpl *This = impl_from_IPicture(iface);
422 ULONG refCount = InterlockedDecrement(&This->ref);
424 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
427 * If the reference count goes down to 0, perform suicide.
429 if (!refCount) OLEPictureImpl_Destroy(This);
434 /************************************************************************
435 * OLEPictureImpl_QueryInterface (IUnknown)
437 * See Windows documentation for more details on IUnknown methods.
439 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
444 OLEPictureImpl *This = impl_from_IPicture(iface);
446 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
453 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
455 else if (IsEqualIID(&IID_IDispatch, riid))
456 *ppvObject = &This->IDispatch_iface;
457 else if (IsEqualIID(&IID_IPictureDisp, riid))
458 *ppvObject = &This->IDispatch_iface;
459 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
460 *ppvObject = &This->IPersistStream_iface;
461 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
462 *ppvObject = &This->IConnectionPointContainer_iface;
466 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
467 return E_NOINTERFACE;
470 IPicture_AddRef(iface);
475 /***********************************************************************
476 * OLEPicture_SendNotify (internal)
478 * Sends notification messages of changed properties to any interested
481 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
483 IEnumConnections *pEnum;
486 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum) != S_OK)
488 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
489 IPropertyNotifySink *sink;
491 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
492 IPropertyNotifySink_OnChanged(sink, dispID);
493 IPropertyNotifySink_Release(sink);
494 IUnknown_Release(CD.pUnk);
496 IEnumConnections_Release(pEnum);
499 /************************************************************************
500 * OLEPictureImpl_get_Handle
502 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
505 OLEPictureImpl *This = impl_from_IPicture(iface);
506 TRACE("(%p)->(%p)\n", This, phandle);
511 switch(This->desc.picType) {
513 case PICTYPE_UNINITIALIZED:
517 *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
519 case PICTYPE_METAFILE:
520 *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
523 *phandle = HandleToUlong(This->desc.u.icon.hicon);
525 case PICTYPE_ENHMETAFILE:
526 *phandle = HandleToUlong(This->desc.u.emf.hemf);
529 FIXME("Unimplemented type %d\n", This->desc.picType);
532 TRACE("returning handle %08x\n", *phandle);
536 /************************************************************************
537 * OLEPictureImpl_get_hPal
539 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
542 OLEPictureImpl *This = impl_from_IPicture(iface);
544 TRACE("(%p)->(%p)\n", This, phandle);
549 switch (This->desc.picType) {
550 case (UINT)PICTYPE_UNINITIALIZED:
556 *phandle = HandleToUlong(This->desc.u.bmp.hpal);
559 case PICTYPE_METAFILE:
563 case PICTYPE_ENHMETAFILE:
565 FIXME("unimplemented for type %d. Returning 0 palette.\n",
571 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
575 /************************************************************************
576 * OLEPictureImpl_get_Type
578 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
581 OLEPictureImpl *This = impl_from_IPicture(iface);
582 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
587 *ptype = This->desc.picType;
591 /************************************************************************
592 * OLEPictureImpl_get_Width
594 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
595 OLE_XSIZE_HIMETRIC *pwidth)
597 OLEPictureImpl *This = impl_from_IPicture(iface);
598 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
599 *pwidth = This->himetricWidth;
603 /************************************************************************
604 * OLEPictureImpl_get_Height
606 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
607 OLE_YSIZE_HIMETRIC *pheight)
609 OLEPictureImpl *This = impl_from_IPicture(iface);
610 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
611 *pheight = This->himetricHeight;
615 /************************************************************************
616 * OLEPictureImpl_Render
618 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
619 LONG x, LONG y, LONG cx, LONG cy,
620 OLE_XPOS_HIMETRIC xSrc,
621 OLE_YPOS_HIMETRIC ySrc,
622 OLE_XSIZE_HIMETRIC cxSrc,
623 OLE_YSIZE_HIMETRIC cySrc,
626 OLEPictureImpl *This = impl_from_IPicture(iface);
627 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
628 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
630 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
631 prcWBounds->right, prcWBounds->bottom);
633 if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
634 return CTL_E_INVALIDPROPERTYVALUE;
638 * While the documentation suggests this to be here (or after rendering?)
639 * it does cause an endless recursion in my sample app. -MM 20010804
640 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
643 switch(This->desc.picType) {
644 case PICTYPE_UNINITIALIZED:
653 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
654 NB y-axis gets flipped */
656 hdcBmp = CreateCompatibleDC(0);
657 SetMapMode(hdcBmp, MM_ANISOTROPIC);
658 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
659 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
660 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
661 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
664 HDC hdcMask = CreateCompatibleDC(0);
665 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
667 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
669 SetMapMode(hdcMask, MM_ANISOTROPIC);
670 SetWindowOrgEx(hdcMask, 0, 0, NULL);
671 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
672 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
673 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
675 SetBkColor(hdc, RGB(255, 255, 255));
676 SetTextColor(hdc, RGB(0, 0, 0));
677 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
678 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
680 SelectObject(hdcMask, hOldbm);
683 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
684 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
687 SelectObject(hdcBmp, hbmpOld);
692 FIXME("Not quite correct implementation of rendering icons...\n");
693 DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL);
696 case PICTYPE_METAFILE:
698 POINT prevOrg, prevWndOrg;
699 SIZE prevExt, prevWndExt;
702 /* Render the WMF to the appropriate location by setting the
703 appropriate ratio between "device units" and "logical units" */
704 oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
705 /* For the "source rectangle" the y-axis must be inverted */
706 SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
707 SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
708 /* For the "destination rectangle" no inversion is necessary */
709 SetViewportOrgEx(hdc, x, y, &prevOrg);
710 SetViewportExtEx(hdc, cx, cy, &prevExt);
712 if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
713 ERR("PlayMetaFile failed!\n");
715 /* We're done, restore the DC to the previous settings for converting
716 logical units to device units */
717 SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
718 SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
719 SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
720 SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
721 SetMapMode(hdc, oldmode);
725 case PICTYPE_ENHMETAFILE:
727 RECT rc = { x, y, x + cx, y + cy };
728 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
733 FIXME("type %d not implemented\n", This->desc.picType);
739 /************************************************************************
740 * OLEPictureImpl_set_hPal
742 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
745 OLEPictureImpl *This = impl_from_IPicture(iface);
746 FIXME("(%p)->(%08x): stub\n", This, hpal);
747 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
751 /************************************************************************
752 * OLEPictureImpl_get_CurDC
754 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
757 OLEPictureImpl *This = impl_from_IPicture(iface);
758 TRACE("(%p), returning %p\n", This, This->hDCCur);
759 if (phdc) *phdc = This->hDCCur;
763 /************************************************************************
764 * OLEPictureImpl_SelectPicture
766 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
769 OLE_HANDLE *phbmpOut)
771 OLEPictureImpl *This = impl_from_IPicture(iface);
772 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
773 if (This->desc.picType == PICTYPE_BITMAP) {
775 *phdcOut = This->hDCCur;
776 if (This->hDCCur) SelectObject(This->hDCCur,This->stock_bitmap);
777 if (hdcIn) SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
778 This->hDCCur = hdcIn;
780 *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
783 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
788 /************************************************************************
789 * OLEPictureImpl_get_KeepOriginalFormat
791 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
794 OLEPictureImpl *This = impl_from_IPicture(iface);
795 TRACE("(%p)->(%p)\n", This, pfKeep);
798 *pfKeep = This->keepOrigFormat;
802 /************************************************************************
803 * OLEPictureImpl_put_KeepOriginalFormat
805 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
808 OLEPictureImpl *This = impl_from_IPicture(iface);
809 TRACE("(%p)->(%d)\n", This, keep);
810 This->keepOrigFormat = keep;
811 /* FIXME: what DISPID notification here? */
815 /************************************************************************
816 * OLEPictureImpl_PictureChanged
818 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
820 OLEPictureImpl *This = impl_from_IPicture(iface);
821 TRACE("(%p)->()\n", This);
822 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
823 This->bIsDirty = TRUE;
827 /************************************************************************
828 * OLEPictureImpl_SaveAsFile
830 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
835 OLEPictureImpl *This = impl_from_IPicture(iface);
836 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
837 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
840 /************************************************************************
841 * OLEPictureImpl_get_Attributes
843 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
846 OLEPictureImpl *This = impl_from_IPicture(iface);
847 TRACE("(%p)->(%p).\n", This, pdwAttr);
853 switch (This->desc.picType) {
854 case PICTYPE_UNINITIALIZED:
855 case PICTYPE_NONE: break;
856 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
857 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
858 case PICTYPE_ENHMETAFILE: /* fall through */
859 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
860 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
866 /************************************************************************
867 * IConnectionPointContainer
869 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
870 IConnectionPointContainer* iface,
874 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
876 return IPicture_QueryInterface(&This->IPicture_iface,riid,ppvoid);
879 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
880 IConnectionPointContainer* iface)
882 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
884 return IPicture_AddRef(&This->IPicture_iface);
887 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
888 IConnectionPointContainer* iface)
890 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
892 return IPicture_Release(&This->IPicture_iface);
895 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
896 IConnectionPointContainer* iface,
897 IEnumConnectionPoints** ppEnum)
899 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
901 FIXME("(%p,%p), stub!\n",This,ppEnum);
905 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
906 IConnectionPointContainer* iface,
908 IConnectionPoint **ppCP)
910 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
911 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
915 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
916 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
917 FIXME("no connection point for %s\n",debugstr_guid(riid));
918 return CONNECT_E_NOCONNECTION;
922 /************************************************************************
926 /************************************************************************
927 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
929 * See Windows documentation for more details on IUnknown methods.
931 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
932 IPersistStream* iface,
936 OLEPictureImpl *This = impl_from_IPersistStream(iface);
938 return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid);
941 /************************************************************************
942 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
944 * See Windows documentation for more details on IUnknown methods.
946 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
947 IPersistStream* iface)
949 OLEPictureImpl *This = impl_from_IPersistStream(iface);
951 return IPicture_AddRef(&This->IPicture_iface);
954 /************************************************************************
955 * OLEPictureImpl_IPersistStream_Release (IUnknown)
957 * See Windows documentation for more details on IUnknown methods.
959 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
960 IPersistStream* iface)
962 OLEPictureImpl *This = impl_from_IPersistStream(iface);
964 return IPicture_Release(&This->IPicture_iface);
967 /************************************************************************
968 * OLEPictureImpl_IPersistStream_GetClassID
970 static HRESULT WINAPI OLEPictureImpl_GetClassID(
971 IPersistStream* iface,CLSID* pClassID)
973 TRACE("(%p)\n", pClassID);
974 *pClassID = CLSID_StdPicture;
978 /************************************************************************
979 * OLEPictureImpl_IPersistStream_IsDirty
981 static HRESULT WINAPI OLEPictureImpl_IsDirty(
982 IPersistStream* iface)
984 OLEPictureImpl *This = impl_from_IPersistStream(iface);
985 FIXME("(%p),stub!\n",This);
989 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
991 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
992 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
995 /* Does not matter whether this is a coreheader or not, we only use
996 * components which are in both
999 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1003 xbuf+bfh->bfOffBits,
1007 ReleaseDC(0, hdcref);
1008 if (This->desc.u.bmp.hbitmap == 0)
1010 This->desc.picType = PICTYPE_BITMAP;
1011 OLEPictureImpl_SetBitmap(This);
1015 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
1018 BITMAPINFOHEADER bih;
1021 UINT stride, buffersize;
1024 IWICBitmapSource *real_source;
1026 COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
1027 BOOL has_alpha=FALSE;
1029 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
1030 if (FAILED(hr)) return hr;
1032 hr = IWICBitmapSource_GetSize(real_source, &width, &height);
1033 if (FAILED(hr)) goto end;
1035 bih.biSize = sizeof(bih);
1036 bih.biWidth = width;
1037 bih.biHeight = -height;
1039 bih.biBitCount = 32;
1040 bih.biCompression = BI_RGB;
1041 bih.biSizeImage = 0;
1042 bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
1043 bih.biYPelsPerMeter = 4085;
1045 bih.biClrImportant = 0;
1048 buffersize = stride * height;
1050 bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
1061 hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
1066 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1074 if (This->desc.u.bmp.hbitmap == 0)
1077 ReleaseDC(0, hdcref);
1081 This->desc.picType = PICTYPE_BITMAP;
1082 OLEPictureImpl_SetBitmap(This);
1084 /* set transparent pixels to black, all others to white */
1085 for(y = 0; y < height; y++){
1086 for(x = 0; x < width; x++){
1087 DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
1088 if((*pixel & 0x80000000) == 0)
1100 HDC hdcBmp, hdcXor, hdcMask;
1101 HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
1103 This->hbmXor = CreateDIBitmap(
1112 This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
1113 hdcBmp = CreateCompatibleDC(NULL);
1114 hdcXor = CreateCompatibleDC(NULL);
1115 hdcMask = CreateCompatibleDC(NULL);
1117 hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
1118 hbmoldXor = SelectObject(hdcXor,This->hbmXor);
1119 hbmoldMask = SelectObject(hdcMask,This->hbmMask);
1121 SetBkColor(hdcXor,black);
1122 BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
1123 BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
1125 SelectObject(hdcBmp,hbmoldBmp);
1126 SelectObject(hdcXor,hbmoldXor);
1127 SelectObject(hdcMask,hbmoldMask);
1134 ReleaseDC(0, hdcref);
1137 HeapFree(GetProcessHeap(), 0, bits);
1138 IWICBitmapSource_Release(real_source);
1142 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
1145 IWICImagingFactory *factory;
1146 IWICBitmapDecoder *decoder;
1147 IWICBitmapFrameDecode *framedecode;
1151 initresult = CoInitialize(NULL);
1153 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1154 &IID_IWICImagingFactory, (void**)&factory);
1155 if (SUCCEEDED(hr)) /* created factory */
1157 hr = IWICImagingFactory_CreateStream(factory, &stream);
1158 IWICImagingFactory_Release(factory);
1161 if (SUCCEEDED(hr)) /* created stream */
1163 hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
1165 if (SUCCEEDED(hr)) /* initialized stream */
1167 hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
1168 &IID_IWICBitmapDecoder, (void**)&decoder);
1169 if (SUCCEEDED(hr)) /* created decoder */
1171 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
1173 if (SUCCEEDED(hr)) /* initialized decoder */
1174 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
1176 IWICBitmapDecoder_Release(decoder);
1180 IWICStream_Release(stream);
1183 if (SUCCEEDED(hr)) /* got framedecode */
1185 hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
1186 IWICBitmapFrameDecode_Release(framedecode);
1189 if (SUCCEEDED(initresult)) CoUninitialize();
1193 /*****************************************************
1194 * start of Icon-specific code
1197 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1200 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1205 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1206 FIXME("icon.idType=%d\n",cifd->idType);
1207 FIXME("icon.idCount=%d\n",cifd->idCount);
1209 for (i=0;i<cifd->idCount;i++) {
1210 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1211 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1212 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1213 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1214 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1215 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1216 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1217 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1221 /* If we have more than one icon, try to find the best.
1222 * this currently means '32 pixel wide'.
1224 if (cifd->idCount!=1) {
1225 for (i=0;i<cifd->idCount;i++) {
1226 if (cifd->idEntries[i].bWidth == 32)
1229 if (i==cifd->idCount) i=0;
1231 if (cifd->idType == 2)
1233 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, cifd->idEntries[i].dwDIBSize + 4);
1234 memcpy(buf, &cifd->idEntries[i].xHotspot, 4);
1235 memcpy(buf + 4, xbuf+cifd->idEntries[i].dwDIBOffset, cifd->idEntries[i].dwDIBSize);
1236 hicon = CreateIconFromResourceEx(
1238 cifd->idEntries[i].dwDIBSize + 4,
1239 FALSE, /* is cursor */
1241 cifd->idEntries[i].bWidth,
1242 cifd->idEntries[i].bHeight,
1245 HeapFree(GetProcessHeap(), 0, buf);
1249 hicon = CreateIconFromResourceEx(
1250 xbuf+cifd->idEntries[i].dwDIBOffset,
1251 cifd->idEntries[i].dwDIBSize,
1254 cifd->idEntries[i].bWidth,
1255 cifd->idEntries[i].bHeight,
1260 ERR("CreateIcon failed.\n");
1263 This->desc.picType = PICTYPE_ICON;
1264 This->desc.u.icon.hicon = hicon;
1265 This->origWidth = cifd->idEntries[i].bWidth;
1266 This->origHeight = cifd->idEntries[i].bHeight;
1267 hdcRef = CreateCompatibleDC(0);
1268 This->himetricWidth = xpixels_to_himetric(cifd->idEntries[i].bWidth, hdcRef);
1269 This->himetricHeight= ypixels_to_himetric(cifd->idEntries[i].bHeight, hdcRef);
1275 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
1276 const BYTE *data, ULONG size)
1281 hemf = SetEnhMetaFileBits(size, data);
1282 if (!hemf) return E_FAIL;
1284 GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
1286 This->desc.picType = PICTYPE_ENHMETAFILE;
1287 This->desc.u.emf.hemf = hemf;
1289 This->origWidth = 0;
1290 This->origHeight = 0;
1291 This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
1292 This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
1297 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
1298 const BYTE *data, ULONG size)
1300 const APM_HEADER *header = (const APM_HEADER *)data;
1303 if (size < sizeof(APM_HEADER))
1305 if (header->key != 0x9ac6cdd7)
1308 /* SetMetaFileBitsEx performs data check on its own */
1309 hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
1310 if (!hmf) return E_FAIL;
1312 This->desc.picType = PICTYPE_METAFILE;
1313 This->desc.u.wmf.hmeta = hmf;
1314 This->desc.u.wmf.xExt = 0;
1315 This->desc.u.wmf.yExt = 0;
1317 This->origWidth = 0;
1318 This->origHeight = 0;
1319 This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
1320 This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
1324 /************************************************************************
1325 * BITMAP FORMAT FLAGS -
1326 * Flags that differentiate between different types of bitmaps.
1329 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
1330 #define BITMAP_FORMAT_JPEG 0xd8ff
1331 #define BITMAP_FORMAT_GIF 0x4947
1332 #define BITMAP_FORMAT_PNG 0x5089
1333 #define BITMAP_FORMAT_APM 0xcdd7
1335 /************************************************************************
1336 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1338 * Loads the binary data from the IStream. Starts at current position.
1339 * There appears to be an 2 DWORD header:
1343 * Currently implemented: BITMAP, ICON, CURSOR, JPEG, GIF, WMF, EMF
1345 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm) {
1348 BOOL statfailed = FALSE;
1349 ULONG xread, toread;
1355 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1357 TRACE("(%p,%p)\n",This,pStm);
1359 /****************************************************************************************
1360 * Part 1: Load the data
1362 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1363 * out whether we do.
1365 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1366 * compound file. This may explain most, if not all, of the cases of "no
1367 * header", and the header validation should take this into account.
1368 * At least in Visual Basic 6, resource streams, valid headers are
1369 * header[0] == "lt\0\0",
1370 * header[1] == length_of_stream.
1372 * Also handle streams where we do not have a working "Stat" method by
1373 * reading all data until the end of the stream.
1375 hr = IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1377 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1379 /* we will read at least 8 byte ... just right below */
1380 statstg.cbSize.QuadPart = 8;
1385 headerisdata = FALSE;
1387 hr = IStream_Read(pStm, header, 8, &xread);
1388 if (hr != S_OK || xread!=8) {
1389 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1390 return (hr?hr:E_FAIL);
1392 headerread += xread;
1395 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1396 if (toread != 0 && toread != header[1])
1397 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1400 if (toread == 0) break;
1402 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1403 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1404 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1405 (header[0] == EMR_HEADER) || /* EMF header */
1406 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1408 ) {/* Found start of bitmap data */
1409 headerisdata = TRUE;
1411 toread = statstg.cbSize.QuadPart-8;
1415 FIXME("Unknown stream header magic: %08x\n", header[0]);
1419 } while (!headerisdata);
1421 if (statfailed) { /* we don't know the size ... read all we get */
1423 int origsize = sizeinc;
1426 TRACE("Reading all data from stream.\n");
1427 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1429 memcpy (xbuf, header, 8);
1431 while (xread < origsize) {
1432 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1434 if (hr != S_OK || !nread)
1437 if (!nread || hr != S_OK) /* done, or error */
1439 if (xread == origsize) {
1440 origsize += sizeinc;
1441 sizeinc = 2*sizeinc; /* exponential increase */
1442 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1446 TRACE("hr in no-stat loader case is %08x\n", hr);
1447 TRACE("loaded %d bytes.\n", xread);
1448 This->datalen = xread;
1451 This->datalen = toread+(headerisdata?8:0);
1452 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1454 return E_OUTOFMEMORY;
1457 memcpy (xbuf, header, 8);
1459 while (xread < This->datalen) {
1461 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1463 if (hr != S_OK || !nread)
1466 if (xread != This->datalen)
1467 ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1469 if (This->datalen == 0) { /* Marks the "NONE" picture */
1470 This->desc.picType = PICTYPE_NONE;
1475 /****************************************************************************************
1476 * Part 2: Process the loaded data
1479 magic = xbuf[0] + (xbuf[1]<<8);
1480 This->loadtime_format = magic;
1483 case BITMAP_FORMAT_GIF: /* GIF */
1484 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
1486 case BITMAP_FORMAT_JPEG: /* JPEG */
1487 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
1489 case BITMAP_FORMAT_BMP: /* Bitmap */
1490 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1492 case BITMAP_FORMAT_PNG: /* PNG */
1493 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
1495 case BITMAP_FORMAT_APM: /* APM */
1496 hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
1498 case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1499 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1506 /* let's see if it's a EMF */
1507 hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
1508 if (hr == S_OK) break;
1510 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1512 for (i=0;i<xread+8;i++) {
1513 if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
1514 else MESSAGE("%02x ",xbuf[i-8]);
1515 if (i % 10 == 9) MESSAGE("\n");
1521 This->bIsDirty = FALSE;
1523 /* FIXME: this notify is not really documented */
1525 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1529 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1533 BITMAPINFO * pInfoBitmap;
1534 int iNumPaletteEntries;
1535 unsigned char * pPixelData;
1536 BITMAPFILEHEADER * pFileHeader;
1537 BITMAPINFO * pInfoHeader;
1539 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1540 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1542 /* Find out bitmap size and padded length */
1544 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1545 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1547 /* Fetch bitmap palette & pixel data */
1549 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1550 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1552 /* Calculate the total length required for the BMP data */
1553 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1554 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1555 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1557 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1558 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1560 iNumPaletteEntries = 0;
1563 sizeof(BITMAPFILEHEADER) +
1564 sizeof(BITMAPINFOHEADER) +
1565 iNumPaletteEntries * sizeof(RGBQUAD) +
1566 pInfoBitmap->bmiHeader.biSizeImage;
1567 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1569 /* Fill the BITMAPFILEHEADER */
1570 pFileHeader = *ppBuffer;
1571 pFileHeader->bfType = BITMAP_FORMAT_BMP;
1572 pFileHeader->bfSize = *pLength;
1573 pFileHeader->bfOffBits =
1574 sizeof(BITMAPFILEHEADER) +
1575 sizeof(BITMAPINFOHEADER) +
1576 iNumPaletteEntries * sizeof(RGBQUAD);
1578 /* Fill the BITMAPINFOHEADER and the palette data */
1579 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1580 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1582 (unsigned char *)(*ppBuffer) +
1583 sizeof(BITMAPFILEHEADER) +
1584 sizeof(BITMAPINFOHEADER) +
1585 iNumPaletteEntries * sizeof(RGBQUAD),
1586 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1589 HeapFree(GetProcessHeap(), 0, pPixelData);
1590 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1594 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1599 *ppBuffer = NULL; *pLength = 0;
1600 if (GetIconInfo(hIcon, &infoIcon)) {
1602 BITMAPINFO * pInfoBitmap;
1603 unsigned char * pIconData = NULL;
1604 unsigned int iDataSize = 0;
1606 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1608 /* Find out icon size */
1610 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1611 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1613 /* Auxiliary pointers */
1614 CURSORICONFILEDIR * pIconDir;
1615 CURSORICONFILEDIRENTRY * pIconEntry;
1616 BITMAPINFOHEADER * pIconBitmapHeader;
1617 unsigned int iOffsetPalette;
1618 unsigned int iOffsetColorData;
1619 unsigned int iOffsetMaskData;
1621 unsigned int iLengthScanLineMask;
1622 unsigned int iNumEntriesPalette;
1624 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1626 FIXME("DEBUG: bitmap size is %d x %d\n",
1627 pInfoBitmap->bmiHeader.biWidth,
1628 pInfoBitmap->bmiHeader.biHeight);
1629 FIXME("DEBUG: bitmap bpp is %d\n",
1630 pInfoBitmap->bmiHeader.biBitCount);
1631 FIXME("DEBUG: bitmap nplanes is %d\n",
1632 pInfoBitmap->bmiHeader.biPlanes);
1633 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1634 pInfoBitmap->bmiHeader.biSizeImage);
1636 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1637 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1638 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1640 /* Fill out the CURSORICONFILEDIR */
1641 pIconDir = (CURSORICONFILEDIR *)pIconData;
1642 pIconDir->idType = 1;
1643 pIconDir->idCount = 1;
1645 /* Fill out the CURSORICONFILEDIRENTRY */
1646 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1647 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1648 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1649 pIconEntry->bColorCount =
1650 (pInfoBitmap->bmiHeader.biBitCount < 8)
1651 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1653 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1654 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1655 pIconEntry->dwDIBSize = 0;
1656 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1658 /* Fill out the BITMAPINFOHEADER */
1659 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1660 *pIconBitmapHeader = pInfoBitmap->bmiHeader;
1662 /* Find out whether a palette exists for the bitmap */
1663 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1664 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1665 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1666 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1667 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1668 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1669 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1670 iNumEntriesPalette = 3;
1671 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1672 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1674 iNumEntriesPalette = 0;
1677 /* Add bitmap size and header size to icon data size. */
1678 iOffsetPalette = iDataSize;
1679 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1680 iOffsetColorData = iDataSize;
1681 iDataSize += pIconBitmapHeader->biSizeImage;
1682 iOffsetMaskData = iDataSize;
1683 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1684 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1685 pIconBitmapHeader->biHeight *= 2;
1686 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1687 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1688 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1689 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1691 /* Get the actual bitmap data from the icon bitmap */
1692 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1693 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1694 if (iNumEntriesPalette > 0) {
1695 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1696 iNumEntriesPalette * sizeof(RGBQUAD));
1699 /* Reset all values so that GetDIBits call succeeds */
1700 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1701 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1702 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1704 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1705 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1706 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1708 printf("ERROR: unable to get bitmap mask (error %u)\n",
1713 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1714 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1716 /* Write out everything produced so far to the stream */
1717 *ppBuffer = pIconData; *pLength = iDataSize;
1721 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1726 Remarks (from MSDN entry on GetIconInfo):
1728 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1729 members of ICONINFO. The calling application must manage
1730 these bitmaps and delete them when they are no longer
1733 if (hDC) ReleaseDC(0, hDC);
1734 DeleteObject(infoIcon.hbmMask);
1735 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1736 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1738 printf("ERROR: Unable to get icon information (error %u)\n",
1744 static HRESULT WINAPI OLEPictureImpl_Save(
1745 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1747 HRESULT hResult = E_NOTIMPL;
1749 unsigned int iDataSize;
1751 int iSerializeResult = 0;
1752 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1754 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1756 switch (This->desc.picType) {
1758 if (This->bIsDirty || !This->data) {
1759 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1760 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1764 HeapFree(GetProcessHeap(), 0, This->data);
1765 This->data = pIconData;
1766 This->datalen = iDataSize;
1768 if (This->loadtime_magic != 0xdeadbeef) {
1771 header[0] = This->loadtime_magic;
1772 header[1] = This->datalen;
1773 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1775 IStream_Write(pStm, This->data, This->datalen, &dummy);
1779 case PICTYPE_BITMAP:
1780 if (This->bIsDirty) {
1781 switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
1782 case BITMAP_FORMAT_BMP:
1783 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1785 case BITMAP_FORMAT_JPEG:
1786 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1788 case BITMAP_FORMAT_GIF:
1789 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1791 case BITMAP_FORMAT_PNG:
1792 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
1795 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1798 if (iSerializeResult) {
1800 if (This->loadtime_magic != 0xdeadbeef) {
1805 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1806 header[1] = iDataSize;
1807 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1809 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1811 HeapFree(GetProcessHeap(), 0, This->data);
1812 This->data = pIconData;
1813 This->datalen = iDataSize;
1818 if (This->loadtime_magic != 0xdeadbeef) {
1823 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1824 header[1] = This->datalen;
1825 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1827 IStream_Write(pStm, This->data, This->datalen, &dummy);
1831 case PICTYPE_METAFILE:
1832 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1834 case PICTYPE_ENHMETAFILE:
1835 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1838 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1841 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1845 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1846 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1848 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1849 FIXME("(%p,%p),stub!\n",This,pcbSize);
1854 /************************************************************************
1858 /************************************************************************
1859 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1861 * See Windows documentation for more details on IUnknown methods.
1863 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1868 OLEPictureImpl *This = impl_from_IDispatch(iface);
1870 return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid);
1873 /************************************************************************
1874 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1876 * See Windows documentation for more details on IUnknown methods.
1878 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1881 OLEPictureImpl *This = impl_from_IDispatch(iface);
1883 return IPicture_AddRef(&This->IPicture_iface);
1886 /************************************************************************
1887 * OLEPictureImpl_IDispatch_Release (IUnknown)
1889 * See Windows documentation for more details on IUnknown methods.
1891 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1894 OLEPictureImpl *This = impl_from_IDispatch(iface);
1896 return IPicture_Release(&This->IPicture_iface);
1899 /************************************************************************
1900 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1902 * See Windows documentation for more details on IDispatch methods.
1904 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1906 unsigned int* pctinfo)
1908 TRACE("(%p)\n", pctinfo);
1915 /************************************************************************
1916 * OLEPictureImpl_GetTypeInfo (IDispatch)
1918 * See Windows documentation for more details on IDispatch methods.
1920 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1924 ITypeInfo** ppTInfo)
1926 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1930 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1935 hres = LoadTypeLib(stdole2tlb, &tl);
1938 ERR("Could not load stdole2.tlb\n");
1942 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1944 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1949 /************************************************************************
1950 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1952 * See Windows documentation for more details on IDispatch methods.
1954 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1957 LPOLESTR* rgszNames,
1965 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
1966 rgszNames, cNames, (int)lcid, rgDispId);
1970 return E_INVALIDARG;
1974 /* retrieve type information */
1975 hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1979 ERR("GetTypeInfo failed.\n");
1983 /* convert names to DISPIDs */
1984 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1985 ITypeInfo_Release(pTInfo);
1991 /************************************************************************
1992 * OLEPictureImpl_Invoke (IDispatch)
1994 * See Windows documentation for more details on IDispatch methods.
1996 static HRESULT WINAPI OLEPictureImpl_Invoke(
1998 DISPID dispIdMember,
2002 DISPPARAMS* pDispParams,
2003 VARIANT* pVarResult,
2004 EXCEPINFO* pExepInfo,
2007 OLEPictureImpl *This = impl_from_IDispatch(iface);
2009 /* validate parameters */
2011 if (!IsEqualIID(riid, &IID_NULL))
2013 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2014 return DISP_E_UNKNOWNNAME;
2019 ERR("null pDispParams not allowed\n");
2020 return DISP_E_PARAMNOTOPTIONAL;
2023 if (wFlags & DISPATCH_PROPERTYGET)
2025 if (pDispParams->cArgs != 0)
2027 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2028 return DISP_E_BADPARAMCOUNT;
2032 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2033 return DISP_E_PARAMNOTOPTIONAL;
2036 else if (wFlags & DISPATCH_PROPERTYPUT)
2038 if (pDispParams->cArgs != 1)
2040 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2041 return DISP_E_BADPARAMCOUNT;
2045 switch (dispIdMember)
2047 case DISPID_PICT_HANDLE:
2048 if (wFlags & DISPATCH_PROPERTYGET)
2050 TRACE("DISPID_PICT_HANDLE\n");
2051 V_VT(pVarResult) = VT_I4;
2052 return IPicture_get_Handle(&This->IPicture_iface, &V_UINT(pVarResult));
2055 case DISPID_PICT_HPAL:
2056 if (wFlags & DISPATCH_PROPERTYGET)
2058 TRACE("DISPID_PICT_HPAL\n");
2059 V_VT(pVarResult) = VT_I4;
2060 return IPicture_get_hPal(&This->IPicture_iface, &V_UINT(pVarResult));
2062 else if (wFlags & DISPATCH_PROPERTYPUT)
2066 TRACE("DISPID_PICT_HPAL\n");
2068 VariantInit(&vararg);
2069 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2073 hr = IPicture_set_hPal(&This->IPicture_iface, V_I4(&vararg));
2075 VariantClear(&vararg);
2079 case DISPID_PICT_TYPE:
2080 if (wFlags & DISPATCH_PROPERTYGET)
2082 TRACE("DISPID_PICT_TYPE\n");
2083 V_VT(pVarResult) = VT_I2;
2084 return OLEPictureImpl_get_Type(&This->IPicture_iface, &V_I2(pVarResult));
2087 case DISPID_PICT_WIDTH:
2088 if (wFlags & DISPATCH_PROPERTYGET)
2090 TRACE("DISPID_PICT_WIDTH\n");
2091 V_VT(pVarResult) = VT_I4;
2092 return IPicture_get_Width(&This->IPicture_iface, &V_I4(pVarResult));
2095 case DISPID_PICT_HEIGHT:
2096 if (wFlags & DISPATCH_PROPERTYGET)
2098 TRACE("DISPID_PICT_HEIGHT\n");
2099 V_VT(pVarResult) = VT_I4;
2100 return IPicture_get_Height(&This->IPicture_iface, &V_I4(pVarResult));
2105 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2106 return DISP_E_MEMBERNOTFOUND;
2110 static const IPictureVtbl OLEPictureImpl_VTable =
2112 OLEPictureImpl_QueryInterface,
2113 OLEPictureImpl_AddRef,
2114 OLEPictureImpl_Release,
2115 OLEPictureImpl_get_Handle,
2116 OLEPictureImpl_get_hPal,
2117 OLEPictureImpl_get_Type,
2118 OLEPictureImpl_get_Width,
2119 OLEPictureImpl_get_Height,
2120 OLEPictureImpl_Render,
2121 OLEPictureImpl_set_hPal,
2122 OLEPictureImpl_get_CurDC,
2123 OLEPictureImpl_SelectPicture,
2124 OLEPictureImpl_get_KeepOriginalFormat,
2125 OLEPictureImpl_put_KeepOriginalFormat,
2126 OLEPictureImpl_PictureChanged,
2127 OLEPictureImpl_SaveAsFile,
2128 OLEPictureImpl_get_Attributes
2131 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2133 OLEPictureImpl_IDispatch_QueryInterface,
2134 OLEPictureImpl_IDispatch_AddRef,
2135 OLEPictureImpl_IDispatch_Release,
2136 OLEPictureImpl_GetTypeInfoCount,
2137 OLEPictureImpl_GetTypeInfo,
2138 OLEPictureImpl_GetIDsOfNames,
2139 OLEPictureImpl_Invoke
2142 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2144 OLEPictureImpl_IPersistStream_QueryInterface,
2145 OLEPictureImpl_IPersistStream_AddRef,
2146 OLEPictureImpl_IPersistStream_Release,
2147 OLEPictureImpl_GetClassID,
2148 OLEPictureImpl_IsDirty,
2149 OLEPictureImpl_Load,
2150 OLEPictureImpl_Save,
2151 OLEPictureImpl_GetSizeMax
2154 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2156 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2157 OLEPictureImpl_IConnectionPointContainer_AddRef,
2158 OLEPictureImpl_IConnectionPointContainer_Release,
2159 OLEPictureImpl_EnumConnectionPoints,
2160 OLEPictureImpl_FindConnectionPoint
2163 /***********************************************************************
2164 * OleCreatePictureIndirect (OLEAUT32.419)
2166 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2167 BOOL Own, void **ppvObj )
2169 OLEPictureImpl* newPict;
2172 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), Own, ppvObj);
2176 newPict = OLEPictureImpl_Construct(lpPictDesc, Own);
2178 if (newPict == NULL)
2179 return E_OUTOFMEMORY;
2182 * Make sure it supports the interface required by the caller.
2184 hr = IPicture_QueryInterface(&newPict->IPicture_iface, riid, ppvObj);
2187 * Release the reference obtained in the constructor. If
2188 * the QueryInterface was unsuccessful, it will free the class.
2190 IPicture_Release(&newPict->IPicture_iface);
2196 /***********************************************************************
2197 * OleLoadPicture (OLEAUT32.418)
2199 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2200 REFIID riid, LPVOID *ppvObj )
2206 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2207 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2209 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2212 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2214 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2215 IPicture_Release(newpic);
2219 hr = IPersistStream_Load(ps,lpstream);
2220 IPersistStream_Release(ps);
2223 ERR("IPersistStream_Load failed\n");
2224 IPicture_Release(newpic);
2228 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2230 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2231 IPicture_Release(newpic);
2235 /***********************************************************************
2236 * OleLoadPictureEx (OLEAUT32.401)
2238 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2239 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2245 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2246 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2248 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2251 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2253 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2254 IPicture_Release(newpic);
2258 hr = IPersistStream_Load(ps,lpstream);
2259 IPersistStream_Release(ps);
2262 ERR("IPersistStream_Load failed\n");
2263 IPicture_Release(newpic);
2267 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2269 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2270 IPicture_Release(newpic);
2274 /***********************************************************************
2275 * OleLoadPicturePath (OLEAUT32.424)
2277 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2278 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2281 static const WCHAR file[] = { 'f','i','l','e',':',0 };
2285 HGLOBAL hGlobal = NULL;
2286 DWORD dwBytesRead = 0;
2289 IPersistStream *pStream;
2292 WCHAR *file_candidate;
2293 WCHAR path_buf[MAX_PATH];
2295 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2296 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2297 debugstr_guid(riid), ppvRet);
2299 if (!szURLorPath || !ppvRet)
2300 return E_INVALIDARG;
2304 /* Convert file URLs to DOS paths. */
2305 if (strncmpW(szURLorPath, file, 5) == 0) {
2307 hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
2308 sizeof(path_buf)/sizeof(WCHAR), &size, 0);
2312 file_candidate = path_buf;
2315 file_candidate = szURLorPath;
2317 /* Handle candidate DOS paths separately. */
2318 if (file_candidate[1] == ':') {
2319 hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2321 if (hFile == INVALID_HANDLE_VALUE)
2322 return INET_E_RESOURCE_NOT_FOUND;
2324 dwFileSize = GetFileSize(hFile, NULL);
2325 if (dwFileSize != INVALID_FILE_SIZE )
2327 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2330 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2333 GlobalFree(hGlobal);
2341 return INET_E_RESOURCE_NOT_FOUND;
2343 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2346 GlobalFree(hGlobal);
2353 hRes = CreateBindCtx(0, &pbc);
2354 if (SUCCEEDED(hRes))
2356 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2357 if (SUCCEEDED(hRes))
2359 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2360 IMoniker_Release(pmnk);
2362 IBindCtx_Release(pbc);
2368 init_res = CoInitialize(NULL);
2370 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2371 &IID_IPicture, (LPVOID*)&ipicture);
2372 if (SUCCEEDED(hRes)) {
2373 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2375 if (SUCCEEDED(hRes)) {
2376 hRes = IPersistStream_Load(pStream, stream);
2378 if (SUCCEEDED(hRes)) {
2379 hRes = IPicture_QueryInterface(ipicture, riid, ppvRet);
2382 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid));
2384 IPersistStream_Release(pStream);
2386 IPicture_Release(ipicture);
2389 IStream_Release(stream);
2391 if (SUCCEEDED(init_res))
2397 /*******************************************************************************
2398 * StdPic ClassFactory
2402 /* IUnknown fields */
2403 IClassFactory IClassFactory_iface;
2405 } IClassFactoryImpl;
2407 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
2409 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
2412 static HRESULT WINAPI
2413 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2414 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2416 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2417 return E_NOINTERFACE;
2421 SPCF_AddRef(LPCLASSFACTORY iface) {
2422 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2423 return InterlockedIncrement(&This->ref);
2426 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2427 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2428 /* static class, won't be freed */
2429 return InterlockedDecrement(&This->ref);
2432 static HRESULT WINAPI SPCF_CreateInstance(
2433 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2435 /* Creates an uninitialized picture */
2436 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2440 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2441 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2442 FIXME("(%p)->(%d),stub!\n",This,dolock);
2446 static const IClassFactoryVtbl SPCF_Vtbl = {
2447 SPCF_QueryInterface,
2450 SPCF_CreateInstance,
2453 static IClassFactoryImpl STDPIC_CF = {{&SPCF_Vtbl}, 1 };
2455 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }