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;
145 /* Bitmap transparency mask */
153 BOOL bIsDirty; /* Set to TRUE if picture has changed */
154 unsigned int loadtime_magic; /* If a length header was found, saves value */
155 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
158 static inline OLEPictureImpl *impl_from_IPicture(IPicture *iface)
160 return CONTAINING_RECORD(iface, OLEPictureImpl, IPicture_iface);
163 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
165 return CONTAINING_RECORD(iface, OLEPictureImpl, IDispatch_iface);
168 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
170 return CONTAINING_RECORD(iface, OLEPictureImpl, IPersistStream_iface);
173 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
175 return CONTAINING_RECORD(iface, OLEPictureImpl, IConnectionPointContainer_iface);
179 * Predeclare VTables. They get initialized at the end.
181 static const IPictureVtbl OLEPictureImpl_VTable;
182 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
183 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
184 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
186 /* pixels to HIMETRIC units conversion */
187 static inline OLE_XSIZE_HIMETRIC xpixels_to_himetric(INT pixels, HDC hdc)
189 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
192 static inline OLE_YSIZE_HIMETRIC ypixels_to_himetric(INT pixels, HDC hdc)
194 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
197 /***********************************************************************
198 * Implementation of the OLEPictureImpl class.
201 static void OLEPictureImpl_SetBitmap(OLEPictureImpl *This)
206 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
207 if(GetObjectW(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
208 ERR("GetObject fails\n");
211 This->origWidth = bm.bmWidth;
212 This->origHeight = bm.bmHeight;
214 /* The width and height are stored in HIMETRIC units (0.01 mm),
215 so we take our pixel width divide by pixels per inch and
216 multiply by 25.4 * 100 */
217 /* Should we use GetBitmapDimension if available? */
218 hdcRef = CreateCompatibleDC(0);
220 This->himetricWidth = xpixels_to_himetric(bm.bmWidth, hdcRef);
221 This->himetricHeight = ypixels_to_himetric(bm.bmHeight, hdcRef);
226 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
230 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
231 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
235 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
236 if(GetObjectW(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
237 ERR("GetObject fails on icon bitmap\n");
241 This->origWidth = bm.bmWidth;
242 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
243 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
246 This->himetricWidth = xpixels_to_himetric(This->origWidth, hdcRef);
247 This->himetricHeight = ypixels_to_himetric(This->origHeight, hdcRef);
249 ReleaseDC(0, hdcRef);
251 DeleteObject(infoIcon.hbmMask);
252 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
254 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
258 /************************************************************************
259 * OLEPictureImpl_Construct
261 * This method will construct a new instance of the OLEPictureImpl
264 * The caller of this method must release the object when it's
267 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
269 OLEPictureImpl* newObject = 0;
272 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
275 * Allocate space for the object.
277 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
283 * Initialize the virtual function table.
285 newObject->IPicture_iface.lpVtbl = &OLEPictureImpl_VTable;
286 newObject->IDispatch_iface.lpVtbl = &OLEPictureImpl_IDispatch_VTable;
287 newObject->IPersistStream_iface.lpVtbl = &OLEPictureImpl_IPersistStream_VTable;
288 newObject->IConnectionPointContainer_iface.lpVtbl = &OLEPictureImpl_IConnectionPointContainer_VTable;
290 newObject->pCP = NULL;
291 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
294 HeapFree(GetProcessHeap(), 0, newObject);
299 * Start with one reference count. The caller of this function
300 * must release the interface pointer when it is done.
303 newObject->hDCCur = 0;
305 newObject->fOwn = fOwn;
307 /* dunno about original value */
308 newObject->keepOrigFormat = TRUE;
310 newObject->hbmMask = NULL;
311 newObject->hbmXor = NULL;
312 newObject->loadtime_magic = 0xdeadbeef;
313 newObject->loadtime_format = 0;
314 newObject->bIsDirty = FALSE;
317 newObject->desc = *pictDesc;
319 switch(pictDesc->picType) {
321 OLEPictureImpl_SetBitmap(newObject);
324 case PICTYPE_METAFILE:
325 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
326 newObject->himetricWidth = pictDesc->u.wmf.xExt;
327 newObject->himetricHeight = pictDesc->u.wmf.yExt;
331 /* not sure what to do here */
332 newObject->himetricWidth = newObject->himetricHeight = 0;
336 OLEPictureImpl_SetIcon(newObject);
338 case PICTYPE_ENHMETAFILE:
340 FIXME("Unsupported type %d\n", pictDesc->picType);
341 newObject->himetricWidth = newObject->himetricHeight = 0;
345 newObject->desc.picType = PICTYPE_UNINITIALIZED;
348 TRACE("returning %p\n", newObject);
352 /************************************************************************
353 * OLEPictureImpl_Destroy
355 * This method is called by the Release method when the reference
356 * count goes down to 0. It will free all resources used by
358 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
360 TRACE("(%p)\n", Obj);
363 IConnectionPoint_Release(Obj->pCP);
365 if(Obj->fOwn) { /* We need to destroy the picture */
366 switch(Obj->desc.picType) {
368 DeleteObject(Obj->desc.u.bmp.hbitmap);
369 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
370 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
372 case PICTYPE_METAFILE:
373 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
376 DestroyIcon(Obj->desc.u.icon.hicon);
378 case PICTYPE_ENHMETAFILE:
379 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
382 case PICTYPE_UNINITIALIZED:
386 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
390 HeapFree(GetProcessHeap(), 0, Obj->data);
391 HeapFree(GetProcessHeap(), 0, Obj);
395 /************************************************************************
396 * OLEPictureImpl_AddRef (IUnknown)
398 * See Windows documentation for more details on IUnknown methods.
400 static ULONG WINAPI OLEPictureImpl_AddRef(
403 OLEPictureImpl *This = impl_from_IPicture(iface);
404 ULONG refCount = InterlockedIncrement(&This->ref);
406 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
411 /************************************************************************
412 * OLEPictureImpl_Release (IUnknown)
414 * See Windows documentation for more details on IUnknown methods.
416 static ULONG WINAPI OLEPictureImpl_Release(
419 OLEPictureImpl *This = impl_from_IPicture(iface);
420 ULONG refCount = InterlockedDecrement(&This->ref);
422 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
425 * If the reference count goes down to 0, perform suicide.
427 if (!refCount) OLEPictureImpl_Destroy(This);
432 /************************************************************************
433 * OLEPictureImpl_QueryInterface (IUnknown)
435 * See Windows documentation for more details on IUnknown methods.
437 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
442 OLEPictureImpl *This = impl_from_IPicture(iface);
444 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
451 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
453 else if (IsEqualIID(&IID_IDispatch, riid))
454 *ppvObject = &This->IDispatch_iface;
455 else if (IsEqualIID(&IID_IPictureDisp, riid))
456 *ppvObject = &This->IDispatch_iface;
457 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
458 *ppvObject = &This->IPersistStream_iface;
459 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
460 *ppvObject = &This->IConnectionPointContainer_iface;
464 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
465 return E_NOINTERFACE;
468 IPicture_AddRef(iface);
473 /***********************************************************************
474 * OLEPicture_SendNotify (internal)
476 * Sends notification messages of changed properties to any interested
479 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
481 IEnumConnections *pEnum;
484 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum) != S_OK)
486 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
487 IPropertyNotifySink *sink;
489 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
490 IPropertyNotifySink_OnChanged(sink, dispID);
491 IPropertyNotifySink_Release(sink);
492 IUnknown_Release(CD.pUnk);
494 IEnumConnections_Release(pEnum);
497 /************************************************************************
498 * OLEPictureImpl_get_Handle
500 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
503 OLEPictureImpl *This = impl_from_IPicture(iface);
504 TRACE("(%p)->(%p)\n", This, phandle);
509 switch(This->desc.picType) {
511 case PICTYPE_UNINITIALIZED:
515 *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
517 case PICTYPE_METAFILE:
518 *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
521 *phandle = HandleToUlong(This->desc.u.icon.hicon);
523 case PICTYPE_ENHMETAFILE:
524 *phandle = HandleToUlong(This->desc.u.emf.hemf);
527 FIXME("Unimplemented type %d\n", This->desc.picType);
530 TRACE("returning handle %08x\n", *phandle);
534 /************************************************************************
535 * OLEPictureImpl_get_hPal
537 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
540 OLEPictureImpl *This = impl_from_IPicture(iface);
542 TRACE("(%p)->(%p)\n", This, phandle);
547 switch (This->desc.picType) {
548 case (UINT)PICTYPE_UNINITIALIZED:
554 *phandle = HandleToUlong(This->desc.u.bmp.hpal);
557 case PICTYPE_METAFILE:
561 case PICTYPE_ENHMETAFILE:
563 FIXME("unimplemented for type %d. Returning 0 palette.\n",
569 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
573 /************************************************************************
574 * OLEPictureImpl_get_Type
576 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
579 OLEPictureImpl *This = impl_from_IPicture(iface);
580 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
585 *ptype = This->desc.picType;
589 /************************************************************************
590 * OLEPictureImpl_get_Width
592 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
593 OLE_XSIZE_HIMETRIC *pwidth)
595 OLEPictureImpl *This = impl_from_IPicture(iface);
596 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
597 *pwidth = This->himetricWidth;
601 /************************************************************************
602 * OLEPictureImpl_get_Height
604 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
605 OLE_YSIZE_HIMETRIC *pheight)
607 OLEPictureImpl *This = impl_from_IPicture(iface);
608 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
609 *pheight = This->himetricHeight;
613 /************************************************************************
614 * OLEPictureImpl_Render
616 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
617 LONG x, LONG y, LONG cx, LONG cy,
618 OLE_XPOS_HIMETRIC xSrc,
619 OLE_YPOS_HIMETRIC ySrc,
620 OLE_XSIZE_HIMETRIC cxSrc,
621 OLE_YSIZE_HIMETRIC cySrc,
624 OLEPictureImpl *This = impl_from_IPicture(iface);
625 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
626 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
628 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
629 prcWBounds->right, prcWBounds->bottom);
631 if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
632 return CTL_E_INVALIDPROPERTYVALUE;
636 * While the documentation suggests this to be here (or after rendering?)
637 * it does cause an endless recursion in my sample app. -MM 20010804
638 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
641 switch(This->desc.picType) {
642 case PICTYPE_UNINITIALIZED:
651 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
652 NB y-axis gets flipped */
654 hdcBmp = CreateCompatibleDC(0);
655 SetMapMode(hdcBmp, MM_ANISOTROPIC);
656 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
657 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
658 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
659 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
662 HDC hdcMask = CreateCompatibleDC(0);
663 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
665 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
667 SetMapMode(hdcMask, MM_ANISOTROPIC);
668 SetWindowOrgEx(hdcMask, 0, 0, NULL);
669 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
670 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
671 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
673 SetBkColor(hdc, RGB(255, 255, 255));
674 SetTextColor(hdc, RGB(0, 0, 0));
675 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
676 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
678 SelectObject(hdcMask, hOldbm);
681 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
682 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
685 SelectObject(hdcBmp, hbmpOld);
690 FIXME("Not quite correct implementation of rendering icons...\n");
691 DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL);
694 case PICTYPE_METAFILE:
696 POINT prevOrg, prevWndOrg;
697 SIZE prevExt, prevWndExt;
700 /* Render the WMF to the appropriate location by setting the
701 appropriate ratio between "device units" and "logical units" */
702 oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
703 /* For the "source rectangle" the y-axis must be inverted */
704 SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
705 SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
706 /* For the "destination rectangle" no inversion is necessary */
707 SetViewportOrgEx(hdc, x, y, &prevOrg);
708 SetViewportExtEx(hdc, cx, cy, &prevExt);
710 if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
711 ERR("PlayMetaFile failed!\n");
713 /* We're done, restore the DC to the previous settings for converting
714 logical units to device units */
715 SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
716 SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
717 SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
718 SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
719 SetMapMode(hdc, oldmode);
723 case PICTYPE_ENHMETAFILE:
725 RECT rc = { x, y, x + cx, y + cy };
726 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
731 FIXME("type %d not implemented\n", This->desc.picType);
737 /************************************************************************
738 * OLEPictureImpl_set_hPal
740 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
743 OLEPictureImpl *This = impl_from_IPicture(iface);
744 FIXME("(%p)->(%08x): stub\n", This, hpal);
745 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
749 /************************************************************************
750 * OLEPictureImpl_get_CurDC
752 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
755 OLEPictureImpl *This = impl_from_IPicture(iface);
756 TRACE("(%p), returning %p\n", This, This->hDCCur);
757 if (phdc) *phdc = This->hDCCur;
761 /************************************************************************
762 * OLEPictureImpl_SelectPicture
764 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
767 OLE_HANDLE *phbmpOut)
769 OLEPictureImpl *This = impl_from_IPicture(iface);
770 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
771 if (This->desc.picType == PICTYPE_BITMAP) {
772 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
775 *phdcOut = This->hDCCur;
776 This->hDCCur = hdcIn;
778 *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
781 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
786 /************************************************************************
787 * OLEPictureImpl_get_KeepOriginalFormat
789 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
792 OLEPictureImpl *This = impl_from_IPicture(iface);
793 TRACE("(%p)->(%p)\n", This, pfKeep);
796 *pfKeep = This->keepOrigFormat;
800 /************************************************************************
801 * OLEPictureImpl_put_KeepOriginalFormat
803 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
806 OLEPictureImpl *This = impl_from_IPicture(iface);
807 TRACE("(%p)->(%d)\n", This, keep);
808 This->keepOrigFormat = keep;
809 /* FIXME: what DISPID notification here? */
813 /************************************************************************
814 * OLEPictureImpl_PictureChanged
816 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
818 OLEPictureImpl *This = impl_from_IPicture(iface);
819 TRACE("(%p)->()\n", This);
820 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
821 This->bIsDirty = TRUE;
825 /************************************************************************
826 * OLEPictureImpl_SaveAsFile
828 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
833 OLEPictureImpl *This = impl_from_IPicture(iface);
834 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
835 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
838 /************************************************************************
839 * OLEPictureImpl_get_Attributes
841 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
844 OLEPictureImpl *This = impl_from_IPicture(iface);
845 TRACE("(%p)->(%p).\n", This, pdwAttr);
851 switch (This->desc.picType) {
852 case PICTYPE_UNINITIALIZED:
853 case PICTYPE_NONE: break;
854 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
855 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
856 case PICTYPE_ENHMETAFILE: /* fall through */
857 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
858 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
864 /************************************************************************
865 * IConnectionPointContainer
867 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
868 IConnectionPointContainer* iface,
872 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
874 return IPicture_QueryInterface(&This->IPicture_iface,riid,ppvoid);
877 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
878 IConnectionPointContainer* iface)
880 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
882 return IPicture_AddRef(&This->IPicture_iface);
885 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
886 IConnectionPointContainer* iface)
888 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
890 return IPicture_Release(&This->IPicture_iface);
893 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
894 IConnectionPointContainer* iface,
895 IEnumConnectionPoints** ppEnum)
897 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
899 FIXME("(%p,%p), stub!\n",This,ppEnum);
903 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
904 IConnectionPointContainer* iface,
906 IConnectionPoint **ppCP)
908 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
909 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
913 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
914 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
915 FIXME("no connection point for %s\n",debugstr_guid(riid));
916 return CONNECT_E_NOCONNECTION;
920 /************************************************************************
924 /************************************************************************
925 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
927 * See Windows documentation for more details on IUnknown methods.
929 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
930 IPersistStream* iface,
934 OLEPictureImpl *This = impl_from_IPersistStream(iface);
936 return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid);
939 /************************************************************************
940 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
942 * See Windows documentation for more details on IUnknown methods.
944 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
945 IPersistStream* iface)
947 OLEPictureImpl *This = impl_from_IPersistStream(iface);
949 return IPicture_AddRef(&This->IPicture_iface);
952 /************************************************************************
953 * OLEPictureImpl_IPersistStream_Release (IUnknown)
955 * See Windows documentation for more details on IUnknown methods.
957 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
958 IPersistStream* iface)
960 OLEPictureImpl *This = impl_from_IPersistStream(iface);
962 return IPicture_Release(&This->IPicture_iface);
965 /************************************************************************
966 * OLEPictureImpl_IPersistStream_GetClassID
968 static HRESULT WINAPI OLEPictureImpl_GetClassID(
969 IPersistStream* iface,CLSID* pClassID)
971 TRACE("(%p)\n", pClassID);
972 *pClassID = CLSID_StdPicture;
976 /************************************************************************
977 * OLEPictureImpl_IPersistStream_IsDirty
979 static HRESULT WINAPI OLEPictureImpl_IsDirty(
980 IPersistStream* iface)
982 OLEPictureImpl *This = impl_from_IPersistStream(iface);
983 FIXME("(%p),stub!\n",This);
987 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
989 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
990 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
993 /* Does not matter whether this is a coreheader or not, we only use
994 * components which are in both
997 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1001 xbuf+bfh->bfOffBits,
1005 ReleaseDC(0, hdcref);
1006 if (This->desc.u.bmp.hbitmap == 0)
1008 This->desc.picType = PICTYPE_BITMAP;
1009 OLEPictureImpl_SetBitmap(This);
1013 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
1016 BITMAPINFOHEADER bih;
1019 UINT stride, buffersize;
1022 IWICBitmapSource *real_source;
1024 COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
1025 BOOL has_alpha=FALSE;
1027 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
1028 if (FAILED(hr)) return hr;
1030 hr = IWICBitmapSource_GetSize(real_source, &width, &height);
1031 if (FAILED(hr)) goto end;
1033 bih.biSize = sizeof(bih);
1034 bih.biWidth = width;
1035 bih.biHeight = -height;
1037 bih.biBitCount = 32;
1038 bih.biCompression = BI_RGB;
1039 bih.biSizeImage = 0;
1040 bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
1041 bih.biYPelsPerMeter = 4085;
1043 bih.biClrImportant = 0;
1046 buffersize = stride * height;
1048 bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
1059 hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
1064 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1072 if (This->desc.u.bmp.hbitmap == 0)
1075 ReleaseDC(0, hdcref);
1079 This->desc.picType = PICTYPE_BITMAP;
1080 OLEPictureImpl_SetBitmap(This);
1082 /* set transparent pixels to black, all others to white */
1083 for(y = 0; y < height; y++){
1084 for(x = 0; x < width; x++){
1085 DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
1086 if((*pixel & 0x80000000) == 0)
1098 HDC hdcBmp, hdcXor, hdcMask;
1099 HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
1101 This->hbmXor = CreateDIBitmap(
1110 This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
1111 hdcBmp = CreateCompatibleDC(NULL);
1112 hdcXor = CreateCompatibleDC(NULL);
1113 hdcMask = CreateCompatibleDC(NULL);
1115 hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
1116 hbmoldXor = SelectObject(hdcXor,This->hbmXor);
1117 hbmoldMask = SelectObject(hdcMask,This->hbmMask);
1119 SetBkColor(hdcXor,black);
1120 BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
1121 BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
1123 SelectObject(hdcBmp,hbmoldBmp);
1124 SelectObject(hdcXor,hbmoldXor);
1125 SelectObject(hdcMask,hbmoldMask);
1132 ReleaseDC(0, hdcref);
1135 HeapFree(GetProcessHeap(), 0, bits);
1136 IWICBitmapSource_Release(real_source);
1140 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
1143 IWICImagingFactory *factory;
1144 IWICBitmapDecoder *decoder;
1145 IWICBitmapFrameDecode *framedecode;
1149 initresult = CoInitialize(NULL);
1151 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1152 &IID_IWICImagingFactory, (void**)&factory);
1153 if (SUCCEEDED(hr)) /* created factory */
1155 hr = IWICImagingFactory_CreateStream(factory, &stream);
1156 IWICImagingFactory_Release(factory);
1159 if (SUCCEEDED(hr)) /* created stream */
1161 hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
1163 if (SUCCEEDED(hr)) /* initialized stream */
1165 hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
1166 &IID_IWICBitmapDecoder, (void**)&decoder);
1167 if (SUCCEEDED(hr)) /* created decoder */
1169 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
1171 if (SUCCEEDED(hr)) /* initialized decoder */
1172 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
1174 IWICBitmapDecoder_Release(decoder);
1178 IWICStream_Release(stream);
1181 if (SUCCEEDED(hr)) /* got framedecode */
1183 hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
1184 IWICBitmapFrameDecode_Release(framedecode);
1187 if (SUCCEEDED(initresult)) CoUninitialize();
1191 /*****************************************************
1192 * start of Icon-specific code
1195 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1198 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1203 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1204 FIXME("icon.idType=%d\n",cifd->idType);
1205 FIXME("icon.idCount=%d\n",cifd->idCount);
1207 for (i=0;i<cifd->idCount;i++) {
1208 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1209 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1210 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1211 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1212 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1213 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1214 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1215 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1219 /* If we have more than one icon, try to find the best.
1220 * this currently means '32 pixel wide'.
1222 if (cifd->idCount!=1) {
1223 for (i=0;i<cifd->idCount;i++) {
1224 if (cifd->idEntries[i].bWidth == 32)
1227 if (i==cifd->idCount) i=0;
1230 hicon = CreateIconFromResourceEx(
1231 xbuf+cifd->idEntries[i].dwDIBOffset,
1232 cifd->idEntries[i].dwDIBSize,
1235 cifd->idEntries[i].bWidth,
1236 cifd->idEntries[i].bHeight,
1240 ERR("CreateIcon failed.\n");
1243 This->desc.picType = PICTYPE_ICON;
1244 This->desc.u.icon.hicon = hicon;
1245 This->origWidth = cifd->idEntries[i].bWidth;
1246 This->origHeight = cifd->idEntries[i].bHeight;
1247 hdcRef = CreateCompatibleDC(0);
1248 This->himetricWidth = xpixels_to_himetric(cifd->idEntries[i].bWidth, hdcRef);
1249 This->himetricHeight= ypixels_to_himetric(cifd->idEntries[i].bHeight, hdcRef);
1255 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
1256 const BYTE *data, ULONG size)
1261 hemf = SetEnhMetaFileBits(size, data);
1262 if (!hemf) return E_FAIL;
1264 GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
1266 This->desc.picType = PICTYPE_ENHMETAFILE;
1267 This->desc.u.emf.hemf = hemf;
1269 This->origWidth = 0;
1270 This->origHeight = 0;
1271 This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
1272 This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
1277 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
1278 const BYTE *data, ULONG size)
1280 const APM_HEADER *header = (const APM_HEADER *)data;
1283 if (size < sizeof(APM_HEADER))
1285 if (header->key != 0x9ac6cdd7)
1288 /* SetMetaFileBitsEx performs data check on its own */
1289 hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
1290 if (!hmf) return E_FAIL;
1292 This->desc.picType = PICTYPE_METAFILE;
1293 This->desc.u.wmf.hmeta = hmf;
1294 This->desc.u.wmf.xExt = 0;
1295 This->desc.u.wmf.yExt = 0;
1297 This->origWidth = 0;
1298 This->origHeight = 0;
1299 This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
1300 This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
1304 /************************************************************************
1305 * BITMAP FORMAT FLAGS -
1306 * Flags that differentiate between different types of bitmaps.
1309 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
1310 #define BITMAP_FORMAT_JPEG 0xd8ff
1311 #define BITMAP_FORMAT_GIF 0x4947
1312 #define BITMAP_FORMAT_PNG 0x5089
1313 #define BITMAP_FORMAT_APM 0xcdd7
1315 /************************************************************************
1316 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1318 * Loads the binary data from the IStream. Starts at current position.
1319 * There appears to be an 2 DWORD header:
1323 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1325 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm) {
1328 BOOL statfailed = FALSE;
1329 ULONG xread, toread;
1335 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1337 TRACE("(%p,%p)\n",This,pStm);
1339 /****************************************************************************************
1340 * Part 1: Load the data
1342 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1343 * out whether we do.
1345 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1346 * compound file. This may explain most, if not all, of the cases of "no
1347 * header", and the header validation should take this into account.
1348 * At least in Visual Basic 6, resource streams, valid headers are
1349 * header[0] == "lt\0\0",
1350 * header[1] == length_of_stream.
1352 * Also handle streams where we do not have a working "Stat" method by
1353 * reading all data until the end of the stream.
1355 hr = IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1357 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1359 /* we will read at least 8 byte ... just right below */
1360 statstg.cbSize.QuadPart = 8;
1365 headerisdata = FALSE;
1367 hr = IStream_Read(pStm, header, 8, &xread);
1368 if (hr != S_OK || xread!=8) {
1369 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1370 return (hr?hr:E_FAIL);
1372 headerread += xread;
1375 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1376 if (toread != 0 && toread != header[1])
1377 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1380 if (toread == 0) break;
1382 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1383 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1384 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1385 (header[0] == EMR_HEADER) || /* EMF header */
1386 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1388 ) {/* Found start of bitmap data */
1389 headerisdata = TRUE;
1391 toread = statstg.cbSize.QuadPart-8;
1395 FIXME("Unknown stream header magic: %08x\n", header[0]);
1399 } while (!headerisdata);
1401 if (statfailed) { /* we don't know the size ... read all we get */
1403 int origsize = sizeinc;
1406 TRACE("Reading all data from stream.\n");
1407 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1409 memcpy (xbuf, header, 8);
1411 while (xread < origsize) {
1412 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1414 if (hr != S_OK || !nread)
1417 if (!nread || hr != S_OK) /* done, or error */
1419 if (xread == origsize) {
1420 origsize += sizeinc;
1421 sizeinc = 2*sizeinc; /* exponential increase */
1422 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1426 TRACE("hr in no-stat loader case is %08x\n", hr);
1427 TRACE("loaded %d bytes.\n", xread);
1428 This->datalen = xread;
1431 This->datalen = toread+(headerisdata?8:0);
1432 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1434 return E_OUTOFMEMORY;
1437 memcpy (xbuf, header, 8);
1439 while (xread < This->datalen) {
1441 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1443 if (hr != S_OK || !nread)
1446 if (xread != This->datalen)
1447 ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1449 if (This->datalen == 0) { /* Marks the "NONE" picture */
1450 This->desc.picType = PICTYPE_NONE;
1455 /****************************************************************************************
1456 * Part 2: Process the loaded data
1459 magic = xbuf[0] + (xbuf[1]<<8);
1460 This->loadtime_format = magic;
1463 case BITMAP_FORMAT_GIF: /* GIF */
1464 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
1466 case BITMAP_FORMAT_JPEG: /* JPEG */
1467 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
1469 case BITMAP_FORMAT_BMP: /* Bitmap */
1470 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1472 case BITMAP_FORMAT_PNG: /* PNG */
1473 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
1475 case BITMAP_FORMAT_APM: /* APM */
1476 hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
1478 case 0x0000: { /* ICON , first word is dwReserved */
1479 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1486 /* let's see if it's a EMF */
1487 hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
1488 if (hr == S_OK) break;
1490 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1492 for (i=0;i<xread+8;i++) {
1493 if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
1494 else MESSAGE("%02x ",xbuf[i-8]);
1495 if (i % 10 == 9) MESSAGE("\n");
1501 This->bIsDirty = FALSE;
1503 /* FIXME: this notify is not really documented */
1505 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1509 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1513 BITMAPINFO * pInfoBitmap;
1514 int iNumPaletteEntries;
1515 unsigned char * pPixelData;
1516 BITMAPFILEHEADER * pFileHeader;
1517 BITMAPINFO * pInfoHeader;
1519 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1520 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1522 /* Find out bitmap size and padded length */
1524 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1525 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1527 /* Fetch bitmap palette & pixel data */
1529 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1530 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1532 /* Calculate the total length required for the BMP data */
1533 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1534 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1535 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1537 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1538 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1540 iNumPaletteEntries = 0;
1543 sizeof(BITMAPFILEHEADER) +
1544 sizeof(BITMAPINFOHEADER) +
1545 iNumPaletteEntries * sizeof(RGBQUAD) +
1546 pInfoBitmap->bmiHeader.biSizeImage;
1547 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1549 /* Fill the BITMAPFILEHEADER */
1550 pFileHeader = *ppBuffer;
1551 pFileHeader->bfType = BITMAP_FORMAT_BMP;
1552 pFileHeader->bfSize = *pLength;
1553 pFileHeader->bfOffBits =
1554 sizeof(BITMAPFILEHEADER) +
1555 sizeof(BITMAPINFOHEADER) +
1556 iNumPaletteEntries * sizeof(RGBQUAD);
1558 /* Fill the BITMAPINFOHEADER and the palette data */
1559 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1560 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1562 (unsigned char *)(*ppBuffer) +
1563 sizeof(BITMAPFILEHEADER) +
1564 sizeof(BITMAPINFOHEADER) +
1565 iNumPaletteEntries * sizeof(RGBQUAD),
1566 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1569 HeapFree(GetProcessHeap(), 0, pPixelData);
1570 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1574 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1579 *ppBuffer = NULL; *pLength = 0;
1580 if (GetIconInfo(hIcon, &infoIcon)) {
1582 BITMAPINFO * pInfoBitmap;
1583 unsigned char * pIconData = NULL;
1584 unsigned int iDataSize = 0;
1586 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1588 /* Find out icon size */
1590 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1591 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1593 /* Auxiliary pointers */
1594 CURSORICONFILEDIR * pIconDir;
1595 CURSORICONFILEDIRENTRY * pIconEntry;
1596 BITMAPINFOHEADER * pIconBitmapHeader;
1597 unsigned int iOffsetPalette;
1598 unsigned int iOffsetColorData;
1599 unsigned int iOffsetMaskData;
1601 unsigned int iLengthScanLineMask;
1602 unsigned int iNumEntriesPalette;
1604 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1606 FIXME("DEBUG: bitmap size is %d x %d\n",
1607 pInfoBitmap->bmiHeader.biWidth,
1608 pInfoBitmap->bmiHeader.biHeight);
1609 FIXME("DEBUG: bitmap bpp is %d\n",
1610 pInfoBitmap->bmiHeader.biBitCount);
1611 FIXME("DEBUG: bitmap nplanes is %d\n",
1612 pInfoBitmap->bmiHeader.biPlanes);
1613 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1614 pInfoBitmap->bmiHeader.biSizeImage);
1616 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1617 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1618 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1620 /* Fill out the CURSORICONFILEDIR */
1621 pIconDir = (CURSORICONFILEDIR *)pIconData;
1622 pIconDir->idType = 1;
1623 pIconDir->idCount = 1;
1625 /* Fill out the CURSORICONFILEDIRENTRY */
1626 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1627 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1628 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1629 pIconEntry->bColorCount =
1630 (pInfoBitmap->bmiHeader.biBitCount < 8)
1631 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1633 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1634 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1635 pIconEntry->dwDIBSize = 0;
1636 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1638 /* Fill out the BITMAPINFOHEADER */
1639 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1640 *pIconBitmapHeader = pInfoBitmap->bmiHeader;
1642 /* Find out whether a palette exists for the bitmap */
1643 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1644 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1645 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1646 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1647 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1648 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1649 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1650 iNumEntriesPalette = 3;
1651 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1652 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1654 iNumEntriesPalette = 0;
1657 /* Add bitmap size and header size to icon data size. */
1658 iOffsetPalette = iDataSize;
1659 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1660 iOffsetColorData = iDataSize;
1661 iDataSize += pIconBitmapHeader->biSizeImage;
1662 iOffsetMaskData = iDataSize;
1663 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1664 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1665 pIconBitmapHeader->biHeight *= 2;
1666 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1667 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1668 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1669 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1671 /* Get the actual bitmap data from the icon bitmap */
1672 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1673 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1674 if (iNumEntriesPalette > 0) {
1675 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1676 iNumEntriesPalette * sizeof(RGBQUAD));
1679 /* Reset all values so that GetDIBits call succeeds */
1680 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1681 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1682 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1684 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1685 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1686 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1688 printf("ERROR: unable to get bitmap mask (error %u)\n",
1693 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1694 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1696 /* Write out everything produced so far to the stream */
1697 *ppBuffer = pIconData; *pLength = iDataSize;
1701 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1706 Remarks (from MSDN entry on GetIconInfo):
1708 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1709 members of ICONINFO. The calling application must manage
1710 these bitmaps and delete them when they are no longer
1713 if (hDC) ReleaseDC(0, hDC);
1714 DeleteObject(infoIcon.hbmMask);
1715 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1716 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1718 printf("ERROR: Unable to get icon information (error %u)\n",
1724 static HRESULT WINAPI OLEPictureImpl_Save(
1725 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1727 HRESULT hResult = E_NOTIMPL;
1729 unsigned int iDataSize;
1731 int iSerializeResult = 0;
1732 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1734 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1736 switch (This->desc.picType) {
1738 if (This->bIsDirty || !This->data) {
1739 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1740 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1744 HeapFree(GetProcessHeap(), 0, This->data);
1745 This->data = pIconData;
1746 This->datalen = iDataSize;
1748 if (This->loadtime_magic != 0xdeadbeef) {
1751 header[0] = This->loadtime_magic;
1752 header[1] = This->datalen;
1753 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1755 IStream_Write(pStm, This->data, This->datalen, &dummy);
1759 case PICTYPE_BITMAP:
1760 if (This->bIsDirty) {
1761 switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
1762 case BITMAP_FORMAT_BMP:
1763 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1765 case BITMAP_FORMAT_JPEG:
1766 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1768 case BITMAP_FORMAT_GIF:
1769 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1771 case BITMAP_FORMAT_PNG:
1772 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
1775 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1778 if (iSerializeResult) {
1780 if (This->loadtime_magic != 0xdeadbeef) {
1785 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1786 header[1] = iDataSize;
1787 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1789 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1791 HeapFree(GetProcessHeap(), 0, This->data);
1792 This->data = pIconData;
1793 This->datalen = iDataSize;
1798 if (This->loadtime_magic != 0xdeadbeef) {
1803 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1804 header[1] = This->datalen;
1805 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1807 IStream_Write(pStm, This->data, This->datalen, &dummy);
1811 case PICTYPE_METAFILE:
1812 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1814 case PICTYPE_ENHMETAFILE:
1815 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1818 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1821 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1825 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1826 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1828 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1829 FIXME("(%p,%p),stub!\n",This,pcbSize);
1834 /************************************************************************
1838 /************************************************************************
1839 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1841 * See Windows documentation for more details on IUnknown methods.
1843 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1848 OLEPictureImpl *This = impl_from_IDispatch(iface);
1850 return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid);
1853 /************************************************************************
1854 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1856 * See Windows documentation for more details on IUnknown methods.
1858 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1861 OLEPictureImpl *This = impl_from_IDispatch(iface);
1863 return IPicture_AddRef(&This->IPicture_iface);
1866 /************************************************************************
1867 * OLEPictureImpl_IDispatch_Release (IUnknown)
1869 * See Windows documentation for more details on IUnknown methods.
1871 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1874 OLEPictureImpl *This = impl_from_IDispatch(iface);
1876 return IPicture_Release(&This->IPicture_iface);
1879 /************************************************************************
1880 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1882 * See Windows documentation for more details on IDispatch methods.
1884 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1886 unsigned int* pctinfo)
1888 TRACE("(%p)\n", pctinfo);
1895 /************************************************************************
1896 * OLEPictureImpl_GetTypeInfo (IDispatch)
1898 * See Windows documentation for more details on IDispatch methods.
1900 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1904 ITypeInfo** ppTInfo)
1906 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1910 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1915 hres = LoadTypeLib(stdole2tlb, &tl);
1918 ERR("Could not load stdole2.tlb\n");
1922 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1924 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1929 /************************************************************************
1930 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1932 * See Windows documentation for more details on IDispatch methods.
1934 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1937 LPOLESTR* rgszNames,
1945 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
1946 rgszNames, cNames, (int)lcid, rgDispId);
1950 return E_INVALIDARG;
1954 /* retrieve type information */
1955 hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1959 ERR("GetTypeInfo failed.\n");
1963 /* convert names to DISPIDs */
1964 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1965 ITypeInfo_Release(pTInfo);
1971 /************************************************************************
1972 * OLEPictureImpl_Invoke (IDispatch)
1974 * See Windows documentation for more details on IDispatch methods.
1976 static HRESULT WINAPI OLEPictureImpl_Invoke(
1978 DISPID dispIdMember,
1982 DISPPARAMS* pDispParams,
1983 VARIANT* pVarResult,
1984 EXCEPINFO* pExepInfo,
1987 OLEPictureImpl *This = impl_from_IDispatch(iface);
1989 /* validate parameters */
1991 if (!IsEqualIID(riid, &IID_NULL))
1993 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1994 return DISP_E_UNKNOWNNAME;
1999 ERR("null pDispParams not allowed\n");
2000 return DISP_E_PARAMNOTOPTIONAL;
2003 if (wFlags & DISPATCH_PROPERTYGET)
2005 if (pDispParams->cArgs != 0)
2007 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2008 return DISP_E_BADPARAMCOUNT;
2012 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2013 return DISP_E_PARAMNOTOPTIONAL;
2016 else if (wFlags & DISPATCH_PROPERTYPUT)
2018 if (pDispParams->cArgs != 1)
2020 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2021 return DISP_E_BADPARAMCOUNT;
2025 switch (dispIdMember)
2027 case DISPID_PICT_HANDLE:
2028 if (wFlags & DISPATCH_PROPERTYGET)
2030 TRACE("DISPID_PICT_HANDLE\n");
2031 V_VT(pVarResult) = VT_I4;
2032 return IPicture_get_Handle(&This->IPicture_iface, &V_UINT(pVarResult));
2035 case DISPID_PICT_HPAL:
2036 if (wFlags & DISPATCH_PROPERTYGET)
2038 TRACE("DISPID_PICT_HPAL\n");
2039 V_VT(pVarResult) = VT_I4;
2040 return IPicture_get_hPal(&This->IPicture_iface, &V_UINT(pVarResult));
2042 else if (wFlags & DISPATCH_PROPERTYPUT)
2046 TRACE("DISPID_PICT_HPAL\n");
2048 VariantInit(&vararg);
2049 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2053 hr = IPicture_set_hPal(&This->IPicture_iface, V_I4(&vararg));
2055 VariantClear(&vararg);
2059 case DISPID_PICT_TYPE:
2060 if (wFlags & DISPATCH_PROPERTYGET)
2062 TRACE("DISPID_PICT_TYPE\n");
2063 V_VT(pVarResult) = VT_I2;
2064 return OLEPictureImpl_get_Type(&This->IPicture_iface, &V_I2(pVarResult));
2067 case DISPID_PICT_WIDTH:
2068 if (wFlags & DISPATCH_PROPERTYGET)
2070 TRACE("DISPID_PICT_WIDTH\n");
2071 V_VT(pVarResult) = VT_I4;
2072 return IPicture_get_Width(&This->IPicture_iface, &V_I4(pVarResult));
2075 case DISPID_PICT_HEIGHT:
2076 if (wFlags & DISPATCH_PROPERTYGET)
2078 TRACE("DISPID_PICT_HEIGHT\n");
2079 V_VT(pVarResult) = VT_I4;
2080 return IPicture_get_Height(&This->IPicture_iface, &V_I4(pVarResult));
2085 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2086 return DISP_E_MEMBERNOTFOUND;
2090 static const IPictureVtbl OLEPictureImpl_VTable =
2092 OLEPictureImpl_QueryInterface,
2093 OLEPictureImpl_AddRef,
2094 OLEPictureImpl_Release,
2095 OLEPictureImpl_get_Handle,
2096 OLEPictureImpl_get_hPal,
2097 OLEPictureImpl_get_Type,
2098 OLEPictureImpl_get_Width,
2099 OLEPictureImpl_get_Height,
2100 OLEPictureImpl_Render,
2101 OLEPictureImpl_set_hPal,
2102 OLEPictureImpl_get_CurDC,
2103 OLEPictureImpl_SelectPicture,
2104 OLEPictureImpl_get_KeepOriginalFormat,
2105 OLEPictureImpl_put_KeepOriginalFormat,
2106 OLEPictureImpl_PictureChanged,
2107 OLEPictureImpl_SaveAsFile,
2108 OLEPictureImpl_get_Attributes
2111 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2113 OLEPictureImpl_IDispatch_QueryInterface,
2114 OLEPictureImpl_IDispatch_AddRef,
2115 OLEPictureImpl_IDispatch_Release,
2116 OLEPictureImpl_GetTypeInfoCount,
2117 OLEPictureImpl_GetTypeInfo,
2118 OLEPictureImpl_GetIDsOfNames,
2119 OLEPictureImpl_Invoke
2122 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2124 OLEPictureImpl_IPersistStream_QueryInterface,
2125 OLEPictureImpl_IPersistStream_AddRef,
2126 OLEPictureImpl_IPersistStream_Release,
2127 OLEPictureImpl_GetClassID,
2128 OLEPictureImpl_IsDirty,
2129 OLEPictureImpl_Load,
2130 OLEPictureImpl_Save,
2131 OLEPictureImpl_GetSizeMax
2134 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2136 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2137 OLEPictureImpl_IConnectionPointContainer_AddRef,
2138 OLEPictureImpl_IConnectionPointContainer_Release,
2139 OLEPictureImpl_EnumConnectionPoints,
2140 OLEPictureImpl_FindConnectionPoint
2143 /***********************************************************************
2144 * OleCreatePictureIndirect (OLEAUT32.419)
2146 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2147 BOOL Own, void **ppvObj )
2149 OLEPictureImpl* newPict;
2152 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), Own, ppvObj);
2156 newPict = OLEPictureImpl_Construct(lpPictDesc, Own);
2158 if (newPict == NULL)
2159 return E_OUTOFMEMORY;
2162 * Make sure it supports the interface required by the caller.
2164 hr = IPicture_QueryInterface(&newPict->IPicture_iface, riid, ppvObj);
2167 * Release the reference obtained in the constructor. If
2168 * the QueryInterface was unsuccessful, it will free the class.
2170 IPicture_Release(&newPict->IPicture_iface);
2176 /***********************************************************************
2177 * OleLoadPicture (OLEAUT32.418)
2179 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2180 REFIID riid, LPVOID *ppvObj )
2186 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2187 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2189 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2192 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2194 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2195 IPicture_Release(newpic);
2199 hr = IPersistStream_Load(ps,lpstream);
2200 IPersistStream_Release(ps);
2203 ERR("IPersistStream_Load failed\n");
2204 IPicture_Release(newpic);
2208 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2210 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2211 IPicture_Release(newpic);
2215 /***********************************************************************
2216 * OleLoadPictureEx (OLEAUT32.401)
2218 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2219 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2225 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2226 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2228 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2231 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2233 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2234 IPicture_Release(newpic);
2238 hr = IPersistStream_Load(ps,lpstream);
2239 IPersistStream_Release(ps);
2242 ERR("IPersistStream_Load failed\n");
2243 IPicture_Release(newpic);
2247 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2249 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2250 IPicture_Release(newpic);
2254 /***********************************************************************
2255 * OleLoadPicturePath (OLEAUT32.424)
2257 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2258 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2261 static const WCHAR file[] = { 'f','i','l','e',':',0 };
2265 HGLOBAL hGlobal = NULL;
2266 DWORD dwBytesRead = 0;
2269 IPersistStream *pStream;
2272 WCHAR *file_candidate;
2273 WCHAR path_buf[MAX_PATH];
2275 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2276 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2277 debugstr_guid(riid), ppvRet);
2279 if (!szURLorPath || !ppvRet)
2280 return E_INVALIDARG;
2284 /* Convert file URLs to DOS paths. */
2285 if (strncmpW(szURLorPath, file, 5) == 0) {
2287 hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
2288 sizeof(path_buf)/sizeof(WCHAR), &size, 0);
2292 file_candidate = path_buf;
2295 file_candidate = szURLorPath;
2297 /* Handle candidate DOS paths separately. */
2298 if (file_candidate[1] == ':') {
2299 hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2301 if (hFile == INVALID_HANDLE_VALUE)
2302 return E_UNEXPECTED;
2304 dwFileSize = GetFileSize(hFile, NULL);
2305 if (dwFileSize != INVALID_FILE_SIZE )
2307 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2310 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2313 GlobalFree(hGlobal);
2321 return E_UNEXPECTED;
2323 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2326 GlobalFree(hGlobal);
2333 hRes = CreateBindCtx(0, &pbc);
2334 if (SUCCEEDED(hRes))
2336 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2337 if (SUCCEEDED(hRes))
2339 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2340 IMoniker_Release(pmnk);
2342 IBindCtx_Release(pbc);
2348 init_res = CoInitialize(NULL);
2350 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2351 &IID_IPicture, (LPVOID*)&ipicture);
2352 if (SUCCEEDED(hRes)) {
2353 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2355 if (SUCCEEDED(hRes)) {
2356 hRes = IPersistStream_Load(pStream, stream);
2358 if (SUCCEEDED(hRes)) {
2359 hRes = IPicture_QueryInterface(ipicture, riid, ppvRet);
2362 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid));
2364 IPersistStream_Release(pStream);
2366 IPicture_Release(ipicture);
2369 IStream_Release(stream);
2371 if (SUCCEEDED(init_res))
2377 /*******************************************************************************
2378 * StdPic ClassFactory
2382 /* IUnknown fields */
2383 IClassFactory IClassFactory_iface;
2385 } IClassFactoryImpl;
2387 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
2389 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
2392 static HRESULT WINAPI
2393 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2394 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2396 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2397 return E_NOINTERFACE;
2401 SPCF_AddRef(LPCLASSFACTORY iface) {
2402 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2403 return InterlockedIncrement(&This->ref);
2406 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2407 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2408 /* static class, won't be freed */
2409 return InterlockedDecrement(&This->ref);
2412 static HRESULT WINAPI SPCF_CreateInstance(
2413 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2415 /* Creates an uninitialized picture */
2416 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2420 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2421 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2422 FIXME("(%p)->(%d),stub!\n",This,dolock);
2426 static const IClassFactoryVtbl SPCF_Vtbl = {
2427 SPCF_QueryInterface,
2430 SPCF_CreateInstance,
2433 static IClassFactoryImpl STDPIC_CF = {{&SPCF_Vtbl}, 1 };
2435 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }