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 const IPictureVtbl *lpVtbl;
119 const IDispatchVtbl *lpvtblIDispatch;
120 const IPersistStreamVtbl *lpvtblIPersistStream;
121 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
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) */
159 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
162 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
164 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
167 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
169 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
172 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
174 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
178 * Predeclare VTables. They get initialized at the end.
180 static const IPictureVtbl OLEPictureImpl_VTable;
181 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
182 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
183 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
185 /* pixels to HIMETRIC units conversion */
186 static inline OLE_XSIZE_HIMETRIC xpixels_to_himetric(INT pixels, HDC hdc)
188 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
191 static inline OLE_YSIZE_HIMETRIC ypixels_to_himetric(INT pixels, HDC hdc)
193 return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
196 /***********************************************************************
197 * Implementation of the OLEPictureImpl class.
200 static void OLEPictureImpl_SetBitmap(OLEPictureImpl *This)
205 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
206 if(GetObjectW(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
207 ERR("GetObject fails\n");
210 This->origWidth = bm.bmWidth;
211 This->origHeight = bm.bmHeight;
213 /* The width and height are stored in HIMETRIC units (0.01 mm),
214 so we take our pixel width divide by pixels per inch and
215 multiply by 25.4 * 100 */
216 /* Should we use GetBitmapDimension if available? */
217 hdcRef = CreateCompatibleDC(0);
219 This->himetricWidth = xpixels_to_himetric(bm.bmWidth, hdcRef);
220 This->himetricHeight = ypixels_to_himetric(bm.bmHeight, hdcRef);
225 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
229 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
230 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
234 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
235 if(GetObjectW(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
236 ERR("GetObject fails on icon bitmap\n");
240 This->origWidth = bm.bmWidth;
241 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
242 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
245 This->himetricWidth = xpixels_to_himetric(This->origWidth, hdcRef);
246 This->himetricHeight = ypixels_to_himetric(This->origHeight, hdcRef);
248 ReleaseDC(0, hdcRef);
250 DeleteObject(infoIcon.hbmMask);
251 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
253 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
257 /************************************************************************
258 * OLEPictureImpl_Construct
260 * This method will construct a new instance of the OLEPictureImpl
263 * The caller of this method must release the object when it's
266 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
268 OLEPictureImpl* newObject = 0;
271 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
274 * Allocate space for the object.
276 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
282 * Initialize the virtual function table.
284 newObject->lpVtbl = &OLEPictureImpl_VTable;
285 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
286 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
287 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
289 newObject->pCP = NULL;
290 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
293 HeapFree(GetProcessHeap(), 0, newObject);
298 * Start with one reference count. The caller of this function
299 * must release the interface pointer when it is done.
302 newObject->hDCCur = 0;
304 newObject->fOwn = fOwn;
306 /* dunno about original value */
307 newObject->keepOrigFormat = TRUE;
309 newObject->hbmMask = NULL;
310 newObject->hbmXor = NULL;
311 newObject->loadtime_magic = 0xdeadbeef;
312 newObject->loadtime_format = 0;
313 newObject->bIsDirty = FALSE;
316 newObject->desc = *pictDesc;
318 switch(pictDesc->picType) {
320 OLEPictureImpl_SetBitmap(newObject);
323 case PICTYPE_METAFILE:
324 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
325 newObject->himetricWidth = pictDesc->u.wmf.xExt;
326 newObject->himetricHeight = pictDesc->u.wmf.yExt;
330 /* not sure what to do here */
331 newObject->himetricWidth = newObject->himetricHeight = 0;
335 OLEPictureImpl_SetIcon(newObject);
337 case PICTYPE_ENHMETAFILE:
339 FIXME("Unsupported type %d\n", pictDesc->picType);
340 newObject->himetricWidth = newObject->himetricHeight = 0;
344 newObject->desc.picType = PICTYPE_UNINITIALIZED;
347 TRACE("returning %p\n", newObject);
351 /************************************************************************
352 * OLEPictureImpl_Destroy
354 * This method is called by the Release method when the reference
355 * count goes down to 0. It will free all resources used by
357 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
359 TRACE("(%p)\n", Obj);
362 IConnectionPoint_Release(Obj->pCP);
364 if(Obj->fOwn) { /* We need to destroy the picture */
365 switch(Obj->desc.picType) {
367 DeleteObject(Obj->desc.u.bmp.hbitmap);
368 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
369 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
371 case PICTYPE_METAFILE:
372 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
375 DestroyIcon(Obj->desc.u.icon.hicon);
377 case PICTYPE_ENHMETAFILE:
378 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
381 case PICTYPE_UNINITIALIZED:
385 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
389 HeapFree(GetProcessHeap(), 0, Obj->data);
390 HeapFree(GetProcessHeap(), 0, Obj);
394 /************************************************************************
395 * OLEPictureImpl_AddRef (IUnknown)
397 * See Windows documentation for more details on IUnknown methods.
399 static ULONG WINAPI OLEPictureImpl_AddRef(
402 OLEPictureImpl *This = (OLEPictureImpl *)iface;
403 ULONG refCount = InterlockedIncrement(&This->ref);
405 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
410 /************************************************************************
411 * OLEPictureImpl_Release (IUnknown)
413 * See Windows documentation for more details on IUnknown methods.
415 static ULONG WINAPI OLEPictureImpl_Release(
418 OLEPictureImpl *This = (OLEPictureImpl *)iface;
419 ULONG refCount = InterlockedDecrement(&This->ref);
421 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
424 * If the reference count goes down to 0, perform suicide.
426 if (!refCount) OLEPictureImpl_Destroy(This);
431 /************************************************************************
432 * OLEPictureImpl_QueryInterface (IUnknown)
434 * See Windows documentation for more details on IUnknown methods.
436 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
441 OLEPictureImpl *This = (OLEPictureImpl *)iface;
443 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
450 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
452 else if (IsEqualIID(&IID_IDispatch, riid))
453 *ppvObject = &This->lpvtblIDispatch;
454 else if (IsEqualIID(&IID_IPictureDisp, riid))
455 *ppvObject = &This->lpvtblIDispatch;
456 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
457 *ppvObject = &This->lpvtblIPersistStream;
458 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
459 *ppvObject = &This->lpvtblIConnectionPointContainer;
463 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
464 return E_NOINTERFACE;
467 IPicture_AddRef(iface);
472 /***********************************************************************
473 * OLEPicture_SendNotify (internal)
475 * Sends notification messages of changed properties to any interested
478 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
480 IEnumConnections *pEnum;
483 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum) != S_OK)
485 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
486 IPropertyNotifySink *sink;
488 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
489 IPropertyNotifySink_OnChanged(sink, dispID);
490 IPropertyNotifySink_Release(sink);
491 IUnknown_Release(CD.pUnk);
493 IEnumConnections_Release(pEnum);
496 /************************************************************************
497 * OLEPictureImpl_get_Handle
499 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
502 OLEPictureImpl *This = (OLEPictureImpl *)iface;
503 TRACE("(%p)->(%p)\n", This, phandle);
508 switch(This->desc.picType) {
510 case PICTYPE_UNINITIALIZED:
514 *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
516 case PICTYPE_METAFILE:
517 *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
520 *phandle = HandleToUlong(This->desc.u.icon.hicon);
522 case PICTYPE_ENHMETAFILE:
523 *phandle = HandleToUlong(This->desc.u.emf.hemf);
526 FIXME("Unimplemented type %d\n", This->desc.picType);
529 TRACE("returning handle %08x\n", *phandle);
533 /************************************************************************
534 * OLEPictureImpl_get_hPal
536 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
539 OLEPictureImpl *This = (OLEPictureImpl *)iface;
541 TRACE("(%p)->(%p)\n", This, phandle);
546 switch (This->desc.picType) {
547 case (UINT)PICTYPE_UNINITIALIZED:
553 *phandle = HandleToUlong(This->desc.u.bmp.hpal);
556 case PICTYPE_METAFILE:
560 case PICTYPE_ENHMETAFILE:
562 FIXME("unimplemented for type %d. Returning 0 palette.\n",
568 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
572 /************************************************************************
573 * OLEPictureImpl_get_Type
575 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
578 OLEPictureImpl *This = (OLEPictureImpl *)iface;
579 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
584 *ptype = This->desc.picType;
588 /************************************************************************
589 * OLEPictureImpl_get_Width
591 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
592 OLE_XSIZE_HIMETRIC *pwidth)
594 OLEPictureImpl *This = (OLEPictureImpl *)iface;
595 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
596 *pwidth = This->himetricWidth;
600 /************************************************************************
601 * OLEPictureImpl_get_Height
603 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
604 OLE_YSIZE_HIMETRIC *pheight)
606 OLEPictureImpl *This = (OLEPictureImpl *)iface;
607 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
608 *pheight = This->himetricHeight;
612 /************************************************************************
613 * OLEPictureImpl_Render
615 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
616 LONG x, LONG y, LONG cx, LONG cy,
617 OLE_XPOS_HIMETRIC xSrc,
618 OLE_YPOS_HIMETRIC ySrc,
619 OLE_XSIZE_HIMETRIC cxSrc,
620 OLE_YSIZE_HIMETRIC cySrc,
623 OLEPictureImpl *This = (OLEPictureImpl *)iface;
624 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
625 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
627 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
628 prcWBounds->right, prcWBounds->bottom);
630 if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
631 return CTL_E_INVALIDPROPERTYVALUE;
635 * While the documentation suggests this to be here (or after rendering?)
636 * it does cause an endless recursion in my sample app. -MM 20010804
637 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
640 switch(This->desc.picType) {
641 case PICTYPE_UNINITIALIZED:
650 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
651 NB y-axis gets flipped */
653 hdcBmp = CreateCompatibleDC(0);
654 SetMapMode(hdcBmp, MM_ANISOTROPIC);
655 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
656 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
657 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
658 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
661 HDC hdcMask = CreateCompatibleDC(0);
662 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
664 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
666 SetMapMode(hdcMask, MM_ANISOTROPIC);
667 SetWindowOrgEx(hdcMask, 0, 0, NULL);
668 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
669 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
670 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
672 SetBkColor(hdc, RGB(255, 255, 255));
673 SetTextColor(hdc, RGB(0, 0, 0));
674 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
675 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
677 SelectObject(hdcMask, hOldbm);
680 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
681 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
684 SelectObject(hdcBmp, hbmpOld);
689 FIXME("Not quite correct implementation of rendering icons...\n");
690 DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL);
693 case PICTYPE_METAFILE:
695 POINT prevOrg, prevWndOrg;
696 SIZE prevExt, prevWndExt;
699 /* Render the WMF to the appropriate location by setting the
700 appropriate ratio between "device units" and "logical units" */
701 oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
702 /* For the "source rectangle" the y-axis must be inverted */
703 SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
704 SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
705 /* For the "destination rectangle" no inversion is necessary */
706 SetViewportOrgEx(hdc, x, y, &prevOrg);
707 SetViewportExtEx(hdc, cx, cy, &prevExt);
709 if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
710 ERR("PlayMetaFile failed!\n");
712 /* We're done, restore the DC to the previous settings for converting
713 logical units to device units */
714 SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
715 SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
716 SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
717 SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
718 SetMapMode(hdc, oldmode);
722 case PICTYPE_ENHMETAFILE:
724 RECT rc = { x, y, x + cx, y + cy };
725 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
730 FIXME("type %d not implemented\n", This->desc.picType);
736 /************************************************************************
737 * OLEPictureImpl_set_hPal
739 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
742 OLEPictureImpl *This = (OLEPictureImpl *)iface;
743 FIXME("(%p)->(%08x): stub\n", This, hpal);
744 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
748 /************************************************************************
749 * OLEPictureImpl_get_CurDC
751 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
754 OLEPictureImpl *This = (OLEPictureImpl *)iface;
755 TRACE("(%p), returning %p\n", This, This->hDCCur);
756 if (phdc) *phdc = This->hDCCur;
760 /************************************************************************
761 * OLEPictureImpl_SelectPicture
763 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
766 OLE_HANDLE *phbmpOut)
768 OLEPictureImpl *This = (OLEPictureImpl *)iface;
769 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
770 if (This->desc.picType == PICTYPE_BITMAP) {
771 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
774 *phdcOut = This->hDCCur;
775 This->hDCCur = hdcIn;
777 *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
780 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
785 /************************************************************************
786 * OLEPictureImpl_get_KeepOriginalFormat
788 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
791 OLEPictureImpl *This = (OLEPictureImpl *)iface;
792 TRACE("(%p)->(%p)\n", This, pfKeep);
795 *pfKeep = This->keepOrigFormat;
799 /************************************************************************
800 * OLEPictureImpl_put_KeepOriginalFormat
802 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
805 OLEPictureImpl *This = (OLEPictureImpl *)iface;
806 TRACE("(%p)->(%d)\n", This, keep);
807 This->keepOrigFormat = keep;
808 /* FIXME: what DISPID notification here? */
812 /************************************************************************
813 * OLEPictureImpl_PictureChanged
815 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
817 OLEPictureImpl *This = (OLEPictureImpl *)iface;
818 TRACE("(%p)->()\n", This);
819 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
820 This->bIsDirty = TRUE;
824 /************************************************************************
825 * OLEPictureImpl_SaveAsFile
827 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
832 OLEPictureImpl *This = (OLEPictureImpl *)iface;
833 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
834 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
837 /************************************************************************
838 * OLEPictureImpl_get_Attributes
840 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
843 OLEPictureImpl *This = (OLEPictureImpl *)iface;
844 TRACE("(%p)->(%p).\n", This, pdwAttr);
850 switch (This->desc.picType) {
851 case PICTYPE_UNINITIALIZED:
852 case PICTYPE_NONE: break;
853 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
854 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
855 case PICTYPE_ENHMETAFILE: /* fall through */
856 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
857 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
863 /************************************************************************
864 * IConnectionPointContainer
866 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
867 IConnectionPointContainer* iface,
871 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
873 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
876 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
877 IConnectionPointContainer* iface)
879 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
881 return IPicture_AddRef((IPicture *)This);
884 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
885 IConnectionPointContainer* iface)
887 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
889 return IPicture_Release((IPicture *)This);
892 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
893 IConnectionPointContainer* iface,
894 IEnumConnectionPoints** ppEnum)
896 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
898 FIXME("(%p,%p), stub!\n",This,ppEnum);
902 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
903 IConnectionPointContainer* iface,
905 IConnectionPoint **ppCP)
907 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
908 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
912 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
913 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
914 FIXME("no connection point for %s\n",debugstr_guid(riid));
915 return CONNECT_E_NOCONNECTION;
919 /************************************************************************
923 /************************************************************************
924 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
926 * See Windows documentation for more details on IUnknown methods.
928 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
929 IPersistStream* iface,
933 OLEPictureImpl *This = impl_from_IPersistStream(iface);
935 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
938 /************************************************************************
939 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
941 * See Windows documentation for more details on IUnknown methods.
943 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
944 IPersistStream* iface)
946 OLEPictureImpl *This = impl_from_IPersistStream(iface);
948 return IPicture_AddRef((IPicture *)This);
951 /************************************************************************
952 * OLEPictureImpl_IPersistStream_Release (IUnknown)
954 * See Windows documentation for more details on IUnknown methods.
956 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
957 IPersistStream* iface)
959 OLEPictureImpl *This = impl_from_IPersistStream(iface);
961 return IPicture_Release((IPicture *)This);
964 /************************************************************************
965 * OLEPictureImpl_IPersistStream_GetClassID
967 static HRESULT WINAPI OLEPictureImpl_GetClassID(
968 IPersistStream* iface,CLSID* pClassID)
970 TRACE("(%p)\n", pClassID);
971 *pClassID = CLSID_StdPicture;
975 /************************************************************************
976 * OLEPictureImpl_IPersistStream_IsDirty
978 static HRESULT WINAPI OLEPictureImpl_IsDirty(
979 IPersistStream* iface)
981 OLEPictureImpl *This = impl_from_IPersistStream(iface);
982 FIXME("(%p),stub!\n",This);
986 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
988 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
989 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
992 /* Does not matter whether this is a coreheader or not, we only use
993 * components which are in both
996 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1000 xbuf+bfh->bfOffBits,
1004 ReleaseDC(0, hdcref);
1005 if (This->desc.u.bmp.hbitmap == 0)
1007 This->desc.picType = PICTYPE_BITMAP;
1008 OLEPictureImpl_SetBitmap(This);
1012 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
1015 BITMAPINFOHEADER bih;
1018 UINT stride, buffersize;
1021 IWICBitmapSource *real_source;
1023 COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
1024 BOOL has_alpha=FALSE;
1026 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
1027 if (FAILED(hr)) return hr;
1029 hr = IWICBitmapSource_GetSize(real_source, &width, &height);
1030 if (FAILED(hr)) goto end;
1032 bih.biSize = sizeof(bih);
1033 bih.biWidth = width;
1034 bih.biHeight = -height;
1036 bih.biBitCount = 32;
1037 bih.biCompression = BI_RGB;
1038 bih.biSizeImage = 0;
1039 bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
1040 bih.biYPelsPerMeter = 4085;
1042 bih.biClrImportant = 0;
1045 buffersize = stride * height;
1047 bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
1058 hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
1063 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1071 if (This->desc.u.bmp.hbitmap == 0)
1074 ReleaseDC(0, hdcref);
1078 This->desc.picType = PICTYPE_BITMAP;
1079 OLEPictureImpl_SetBitmap(This);
1081 /* set transparent pixels to black, all others to white */
1082 for(y = 0; y < height; y++){
1083 for(x = 0; x < width; x++){
1084 DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
1085 if((*pixel & 0x80000000) == 0)
1097 HDC hdcBmp, hdcXor, hdcMask;
1098 HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
1100 This->hbmXor = CreateDIBitmap(
1109 This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
1110 hdcBmp = CreateCompatibleDC(NULL);
1111 hdcXor = CreateCompatibleDC(NULL);
1112 hdcMask = CreateCompatibleDC(NULL);
1114 hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
1115 hbmoldXor = SelectObject(hdcXor,This->hbmXor);
1116 hbmoldMask = SelectObject(hdcMask,This->hbmMask);
1118 SetBkColor(hdcXor,black);
1119 BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
1120 BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
1122 SelectObject(hdcBmp,hbmoldBmp);
1123 SelectObject(hdcXor,hbmoldXor);
1124 SelectObject(hdcMask,hbmoldMask);
1131 ReleaseDC(0, hdcref);
1134 HeapFree(GetProcessHeap(), 0, bits);
1135 IWICBitmapSource_Release(real_source);
1139 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
1142 IWICImagingFactory *factory;
1143 IWICBitmapDecoder *decoder;
1144 IWICBitmapFrameDecode *framedecode;
1148 initresult = CoInitialize(NULL);
1150 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1151 &IID_IWICImagingFactory, (void**)&factory);
1152 if (SUCCEEDED(hr)) /* created factory */
1154 hr = IWICImagingFactory_CreateStream(factory, &stream);
1155 IWICImagingFactory_Release(factory);
1158 if (SUCCEEDED(hr)) /* created stream */
1160 hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
1162 if (SUCCEEDED(hr)) /* initialized stream */
1164 hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
1165 &IID_IWICBitmapDecoder, (void**)&decoder);
1166 if (SUCCEEDED(hr)) /* created decoder */
1168 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
1170 if (SUCCEEDED(hr)) /* initialized decoder */
1171 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
1173 IWICBitmapDecoder_Release(decoder);
1177 IWICStream_Release(stream);
1180 if (SUCCEEDED(hr)) /* got framedecode */
1182 hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
1183 IWICBitmapFrameDecode_Release(framedecode);
1186 if (SUCCEEDED(initresult)) CoUninitialize();
1190 /*****************************************************
1191 * start of Icon-specific code
1194 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1197 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1202 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1203 FIXME("icon.idType=%d\n",cifd->idType);
1204 FIXME("icon.idCount=%d\n",cifd->idCount);
1206 for (i=0;i<cifd->idCount;i++) {
1207 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1208 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1209 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1210 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1211 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1212 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1213 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1214 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1218 /* If we have more than one icon, try to find the best.
1219 * this currently means '32 pixel wide'.
1221 if (cifd->idCount!=1) {
1222 for (i=0;i<cifd->idCount;i++) {
1223 if (cifd->idEntries[i].bWidth == 32)
1226 if (i==cifd->idCount) i=0;
1229 hicon = CreateIconFromResourceEx(
1230 xbuf+cifd->idEntries[i].dwDIBOffset,
1231 cifd->idEntries[i].dwDIBSize,
1234 cifd->idEntries[i].bWidth,
1235 cifd->idEntries[i].bHeight,
1239 ERR("CreateIcon failed.\n");
1242 This->desc.picType = PICTYPE_ICON;
1243 This->desc.u.icon.hicon = hicon;
1244 This->origWidth = cifd->idEntries[i].bWidth;
1245 This->origHeight = cifd->idEntries[i].bHeight;
1246 hdcRef = CreateCompatibleDC(0);
1247 This->himetricWidth = xpixels_to_himetric(cifd->idEntries[i].bWidth, hdcRef);
1248 This->himetricHeight= ypixels_to_himetric(cifd->idEntries[i].bHeight, hdcRef);
1254 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
1255 const BYTE *data, ULONG size)
1260 hemf = SetEnhMetaFileBits(size, data);
1261 if (!hemf) return E_FAIL;
1263 GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
1265 This->desc.picType = PICTYPE_ENHMETAFILE;
1266 This->desc.u.emf.hemf = hemf;
1268 This->origWidth = 0;
1269 This->origHeight = 0;
1270 This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
1271 This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
1276 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
1277 const BYTE *data, ULONG size)
1279 const APM_HEADER *header = (const APM_HEADER *)data;
1282 if (size < sizeof(APM_HEADER))
1284 if (header->key != 0x9ac6cdd7)
1287 /* SetMetaFileBitsEx performs data check on its own */
1288 hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
1289 if (!hmf) return E_FAIL;
1291 This->desc.picType = PICTYPE_METAFILE;
1292 This->desc.u.wmf.hmeta = hmf;
1293 This->desc.u.wmf.xExt = 0;
1294 This->desc.u.wmf.yExt = 0;
1296 This->origWidth = 0;
1297 This->origHeight = 0;
1298 This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
1299 This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
1303 /************************************************************************
1304 * BITMAP FORMAT FLAGS -
1305 * Flags that differentiate between different types of bitmaps.
1308 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
1309 #define BITMAP_FORMAT_JPEG 0xd8ff
1310 #define BITMAP_FORMAT_GIF 0x4947
1311 #define BITMAP_FORMAT_PNG 0x5089
1312 #define BITMAP_FORMAT_APM 0xcdd7
1314 /************************************************************************
1315 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1317 * Loads the binary data from the IStream. Starts at current position.
1318 * There appears to be an 2 DWORD header:
1322 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1324 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm) {
1327 BOOL statfailed = FALSE;
1328 ULONG xread, toread;
1334 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1336 TRACE("(%p,%p)\n",This,pStm);
1338 /****************************************************************************************
1339 * Part 1: Load the data
1341 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1342 * out whether we do.
1344 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1345 * compound file. This may explain most, if not all, of the cases of "no
1346 * header", and the header validation should take this into account.
1347 * At least in Visual Basic 6, resource streams, valid headers are
1348 * header[0] == "lt\0\0",
1349 * header[1] == length_of_stream.
1351 * Also handle streams where we do not have a working "Stat" method by
1352 * reading all data until the end of the stream.
1354 hr = IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1356 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1358 /* we will read at least 8 byte ... just right below */
1359 statstg.cbSize.QuadPart = 8;
1364 headerisdata = FALSE;
1366 hr = IStream_Read(pStm, header, 8, &xread);
1367 if (hr != S_OK || xread!=8) {
1368 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1369 return (hr?hr:E_FAIL);
1371 headerread += xread;
1374 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1375 if (toread != 0 && toread != header[1])
1376 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1379 if (toread == 0) break;
1381 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1382 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1383 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1384 (header[0] == EMR_HEADER) || /* EMF header */
1385 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1387 ) {/* Found start of bitmap data */
1388 headerisdata = TRUE;
1390 toread = statstg.cbSize.QuadPart-8;
1394 FIXME("Unknown stream header magic: %08x\n", header[0]);
1398 } while (!headerisdata);
1400 if (statfailed) { /* we don't know the size ... read all we get */
1402 int origsize = sizeinc;
1405 TRACE("Reading all data from stream.\n");
1406 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1408 memcpy (xbuf, header, 8);
1410 while (xread < origsize) {
1411 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1413 if (hr != S_OK || !nread)
1416 if (!nread || hr != S_OK) /* done, or error */
1418 if (xread == origsize) {
1419 origsize += sizeinc;
1420 sizeinc = 2*sizeinc; /* exponential increase */
1421 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1425 TRACE("hr in no-stat loader case is %08x\n", hr);
1426 TRACE("loaded %d bytes.\n", xread);
1427 This->datalen = xread;
1430 This->datalen = toread+(headerisdata?8:0);
1431 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1433 return E_OUTOFMEMORY;
1436 memcpy (xbuf, header, 8);
1438 while (xread < This->datalen) {
1440 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1442 if (hr != S_OK || !nread)
1445 if (xread != This->datalen)
1446 ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1448 if (This->datalen == 0) { /* Marks the "NONE" picture */
1449 This->desc.picType = PICTYPE_NONE;
1454 /****************************************************************************************
1455 * Part 2: Process the loaded data
1458 magic = xbuf[0] + (xbuf[1]<<8);
1459 This->loadtime_format = magic;
1462 case BITMAP_FORMAT_GIF: /* GIF */
1463 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
1465 case BITMAP_FORMAT_JPEG: /* JPEG */
1466 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
1468 case BITMAP_FORMAT_BMP: /* Bitmap */
1469 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1471 case BITMAP_FORMAT_PNG: /* PNG */
1472 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
1474 case BITMAP_FORMAT_APM: /* APM */
1475 hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
1477 case 0x0000: { /* ICON , first word is dwReserved */
1478 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1485 /* let's see if it's a EMF */
1486 hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
1487 if (hr == S_OK) break;
1489 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1491 for (i=0;i<xread+8;i++) {
1492 if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
1493 else MESSAGE("%02x ",xbuf[i-8]);
1494 if (i % 10 == 9) MESSAGE("\n");
1500 This->bIsDirty = FALSE;
1502 /* FIXME: this notify is not really documented */
1504 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1508 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1512 BITMAPINFO * pInfoBitmap;
1513 int iNumPaletteEntries;
1514 unsigned char * pPixelData;
1515 BITMAPFILEHEADER * pFileHeader;
1516 BITMAPINFO * pInfoHeader;
1518 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1519 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1521 /* Find out bitmap size and padded length */
1523 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1524 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1526 /* Fetch bitmap palette & pixel data */
1528 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1529 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1531 /* Calculate the total length required for the BMP data */
1532 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1533 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1534 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1536 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1537 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1539 iNumPaletteEntries = 0;
1542 sizeof(BITMAPFILEHEADER) +
1543 sizeof(BITMAPINFOHEADER) +
1544 iNumPaletteEntries * sizeof(RGBQUAD) +
1545 pInfoBitmap->bmiHeader.biSizeImage;
1546 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1548 /* Fill the BITMAPFILEHEADER */
1549 pFileHeader = *ppBuffer;
1550 pFileHeader->bfType = BITMAP_FORMAT_BMP;
1551 pFileHeader->bfSize = *pLength;
1552 pFileHeader->bfOffBits =
1553 sizeof(BITMAPFILEHEADER) +
1554 sizeof(BITMAPINFOHEADER) +
1555 iNumPaletteEntries * sizeof(RGBQUAD);
1557 /* Fill the BITMAPINFOHEADER and the palette data */
1558 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1559 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1561 (unsigned char *)(*ppBuffer) +
1562 sizeof(BITMAPFILEHEADER) +
1563 sizeof(BITMAPINFOHEADER) +
1564 iNumPaletteEntries * sizeof(RGBQUAD),
1565 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1568 HeapFree(GetProcessHeap(), 0, pPixelData);
1569 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1573 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1578 *ppBuffer = NULL; *pLength = 0;
1579 if (GetIconInfo(hIcon, &infoIcon)) {
1581 BITMAPINFO * pInfoBitmap;
1582 unsigned char * pIconData = NULL;
1583 unsigned int iDataSize = 0;
1585 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1587 /* Find out icon size */
1589 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1590 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1592 /* Auxiliary pointers */
1593 CURSORICONFILEDIR * pIconDir;
1594 CURSORICONFILEDIRENTRY * pIconEntry;
1595 BITMAPINFOHEADER * pIconBitmapHeader;
1596 unsigned int iOffsetPalette;
1597 unsigned int iOffsetColorData;
1598 unsigned int iOffsetMaskData;
1600 unsigned int iLengthScanLineMask;
1601 unsigned int iNumEntriesPalette;
1603 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1605 FIXME("DEBUG: bitmap size is %d x %d\n",
1606 pInfoBitmap->bmiHeader.biWidth,
1607 pInfoBitmap->bmiHeader.biHeight);
1608 FIXME("DEBUG: bitmap bpp is %d\n",
1609 pInfoBitmap->bmiHeader.biBitCount);
1610 FIXME("DEBUG: bitmap nplanes is %d\n",
1611 pInfoBitmap->bmiHeader.biPlanes);
1612 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1613 pInfoBitmap->bmiHeader.biSizeImage);
1615 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1616 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1617 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1619 /* Fill out the CURSORICONFILEDIR */
1620 pIconDir = (CURSORICONFILEDIR *)pIconData;
1621 pIconDir->idType = 1;
1622 pIconDir->idCount = 1;
1624 /* Fill out the CURSORICONFILEDIRENTRY */
1625 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1626 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1627 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1628 pIconEntry->bColorCount =
1629 (pInfoBitmap->bmiHeader.biBitCount < 8)
1630 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1632 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1633 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1634 pIconEntry->dwDIBSize = 0;
1635 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1637 /* Fill out the BITMAPINFOHEADER */
1638 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1639 *pIconBitmapHeader = pInfoBitmap->bmiHeader;
1641 /* Find out whether a palette exists for the bitmap */
1642 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1643 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1644 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1645 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1646 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1647 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1648 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1649 iNumEntriesPalette = 3;
1650 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1651 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1653 iNumEntriesPalette = 0;
1656 /* Add bitmap size and header size to icon data size. */
1657 iOffsetPalette = iDataSize;
1658 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1659 iOffsetColorData = iDataSize;
1660 iDataSize += pIconBitmapHeader->biSizeImage;
1661 iOffsetMaskData = iDataSize;
1662 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1663 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1664 pIconBitmapHeader->biHeight *= 2;
1665 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1666 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1667 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1668 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1670 /* Get the actual bitmap data from the icon bitmap */
1671 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1672 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1673 if (iNumEntriesPalette > 0) {
1674 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1675 iNumEntriesPalette * sizeof(RGBQUAD));
1678 /* Reset all values so that GetDIBits call succeeds */
1679 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1680 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1681 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1683 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1684 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1685 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1687 printf("ERROR: unable to get bitmap mask (error %u)\n",
1692 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1693 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1695 /* Write out everything produced so far to the stream */
1696 *ppBuffer = pIconData; *pLength = iDataSize;
1700 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1705 Remarks (from MSDN entry on GetIconInfo):
1707 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1708 members of ICONINFO. The calling application must manage
1709 these bitmaps and delete them when they are no longer
1712 if (hDC) ReleaseDC(0, hDC);
1713 DeleteObject(infoIcon.hbmMask);
1714 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1715 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1717 printf("ERROR: Unable to get icon information (error %u)\n",
1723 static HRESULT WINAPI OLEPictureImpl_Save(
1724 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1726 HRESULT hResult = E_NOTIMPL;
1728 unsigned int iDataSize;
1730 int iSerializeResult = 0;
1731 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1733 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1735 switch (This->desc.picType) {
1737 if (This->bIsDirty || !This->data) {
1738 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1739 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1743 HeapFree(GetProcessHeap(), 0, This->data);
1744 This->data = pIconData;
1745 This->datalen = iDataSize;
1747 if (This->loadtime_magic != 0xdeadbeef) {
1750 header[0] = This->loadtime_magic;
1751 header[1] = This->datalen;
1752 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1754 IStream_Write(pStm, This->data, This->datalen, &dummy);
1758 case PICTYPE_BITMAP:
1759 if (This->bIsDirty) {
1760 switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
1761 case BITMAP_FORMAT_BMP:
1762 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1764 case BITMAP_FORMAT_JPEG:
1765 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1767 case BITMAP_FORMAT_GIF:
1768 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1770 case BITMAP_FORMAT_PNG:
1771 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
1774 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1777 if (iSerializeResult) {
1779 if (This->loadtime_magic != 0xdeadbeef) {
1784 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1785 header[1] = iDataSize;
1786 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1788 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1790 HeapFree(GetProcessHeap(), 0, This->data);
1791 This->data = pIconData;
1792 This->datalen = iDataSize;
1797 if (This->loadtime_magic != 0xdeadbeef) {
1802 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1803 header[1] = This->datalen;
1804 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1806 IStream_Write(pStm, This->data, This->datalen, &dummy);
1810 case PICTYPE_METAFILE:
1811 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1813 case PICTYPE_ENHMETAFILE:
1814 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1817 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1820 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1824 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1825 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1827 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1828 FIXME("(%p,%p),stub!\n",This,pcbSize);
1833 /************************************************************************
1837 /************************************************************************
1838 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1840 * See Windows documentation for more details on IUnknown methods.
1842 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1847 OLEPictureImpl *This = impl_from_IDispatch(iface);
1849 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1852 /************************************************************************
1853 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1855 * See Windows documentation for more details on IUnknown methods.
1857 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1860 OLEPictureImpl *This = impl_from_IDispatch(iface);
1862 return IPicture_AddRef((IPicture *)This);
1865 /************************************************************************
1866 * OLEPictureImpl_IDispatch_Release (IUnknown)
1868 * See Windows documentation for more details on IUnknown methods.
1870 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1873 OLEPictureImpl *This = impl_from_IDispatch(iface);
1875 return IPicture_Release((IPicture *)This);
1878 /************************************************************************
1879 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1881 * See Windows documentation for more details on IDispatch methods.
1883 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1885 unsigned int* pctinfo)
1887 TRACE("(%p)\n", pctinfo);
1894 /************************************************************************
1895 * OLEPictureImpl_GetTypeInfo (IDispatch)
1897 * See Windows documentation for more details on IDispatch methods.
1899 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1903 ITypeInfo** ppTInfo)
1905 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1909 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1914 hres = LoadTypeLib(stdole2tlb, &tl);
1917 ERR("Could not load stdole2.tlb\n");
1921 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1923 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1928 /************************************************************************
1929 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1931 * See Windows documentation for more details on IDispatch methods.
1933 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1936 LPOLESTR* rgszNames,
1944 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
1945 rgszNames, cNames, (int)lcid, rgDispId);
1949 return E_INVALIDARG;
1953 /* retrieve type information */
1954 hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1958 ERR("GetTypeInfo failed.\n");
1962 /* convert names to DISPIDs */
1963 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1964 ITypeInfo_Release(pTInfo);
1970 /************************************************************************
1971 * OLEPictureImpl_Invoke (IDispatch)
1973 * See Windows documentation for more details on IDispatch methods.
1975 static HRESULT WINAPI OLEPictureImpl_Invoke(
1977 DISPID dispIdMember,
1981 DISPPARAMS* pDispParams,
1982 VARIANT* pVarResult,
1983 EXCEPINFO* pExepInfo,
1986 OLEPictureImpl *This = impl_from_IDispatch(iface);
1988 /* validate parameters */
1990 if (!IsEqualIID(riid, &IID_NULL))
1992 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1993 return DISP_E_UNKNOWNNAME;
1998 ERR("null pDispParams not allowed\n");
1999 return DISP_E_PARAMNOTOPTIONAL;
2002 if (wFlags & DISPATCH_PROPERTYGET)
2004 if (pDispParams->cArgs != 0)
2006 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2007 return DISP_E_BADPARAMCOUNT;
2011 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2012 return DISP_E_PARAMNOTOPTIONAL;
2015 else if (wFlags & DISPATCH_PROPERTYPUT)
2017 if (pDispParams->cArgs != 1)
2019 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2020 return DISP_E_BADPARAMCOUNT;
2024 switch (dispIdMember)
2026 case DISPID_PICT_HANDLE:
2027 if (wFlags & DISPATCH_PROPERTYGET)
2029 TRACE("DISPID_PICT_HANDLE\n");
2030 V_VT(pVarResult) = VT_I4;
2031 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2034 case DISPID_PICT_HPAL:
2035 if (wFlags & DISPATCH_PROPERTYGET)
2037 TRACE("DISPID_PICT_HPAL\n");
2038 V_VT(pVarResult) = VT_I4;
2039 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2041 else if (wFlags & DISPATCH_PROPERTYPUT)
2045 TRACE("DISPID_PICT_HPAL\n");
2047 VariantInit(&vararg);
2048 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2052 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2054 VariantClear(&vararg);
2058 case DISPID_PICT_TYPE:
2059 if (wFlags & DISPATCH_PROPERTYGET)
2061 TRACE("DISPID_PICT_TYPE\n");
2062 V_VT(pVarResult) = VT_I2;
2063 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2066 case DISPID_PICT_WIDTH:
2067 if (wFlags & DISPATCH_PROPERTYGET)
2069 TRACE("DISPID_PICT_WIDTH\n");
2070 V_VT(pVarResult) = VT_I4;
2071 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2074 case DISPID_PICT_HEIGHT:
2075 if (wFlags & DISPATCH_PROPERTYGET)
2077 TRACE("DISPID_PICT_HEIGHT\n");
2078 V_VT(pVarResult) = VT_I4;
2079 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2084 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2085 return DISP_E_MEMBERNOTFOUND;
2089 static const IPictureVtbl OLEPictureImpl_VTable =
2091 OLEPictureImpl_QueryInterface,
2092 OLEPictureImpl_AddRef,
2093 OLEPictureImpl_Release,
2094 OLEPictureImpl_get_Handle,
2095 OLEPictureImpl_get_hPal,
2096 OLEPictureImpl_get_Type,
2097 OLEPictureImpl_get_Width,
2098 OLEPictureImpl_get_Height,
2099 OLEPictureImpl_Render,
2100 OLEPictureImpl_set_hPal,
2101 OLEPictureImpl_get_CurDC,
2102 OLEPictureImpl_SelectPicture,
2103 OLEPictureImpl_get_KeepOriginalFormat,
2104 OLEPictureImpl_put_KeepOriginalFormat,
2105 OLEPictureImpl_PictureChanged,
2106 OLEPictureImpl_SaveAsFile,
2107 OLEPictureImpl_get_Attributes
2110 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2112 OLEPictureImpl_IDispatch_QueryInterface,
2113 OLEPictureImpl_IDispatch_AddRef,
2114 OLEPictureImpl_IDispatch_Release,
2115 OLEPictureImpl_GetTypeInfoCount,
2116 OLEPictureImpl_GetTypeInfo,
2117 OLEPictureImpl_GetIDsOfNames,
2118 OLEPictureImpl_Invoke
2121 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2123 OLEPictureImpl_IPersistStream_QueryInterface,
2124 OLEPictureImpl_IPersistStream_AddRef,
2125 OLEPictureImpl_IPersistStream_Release,
2126 OLEPictureImpl_GetClassID,
2127 OLEPictureImpl_IsDirty,
2128 OLEPictureImpl_Load,
2129 OLEPictureImpl_Save,
2130 OLEPictureImpl_GetSizeMax
2133 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2135 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2136 OLEPictureImpl_IConnectionPointContainer_AddRef,
2137 OLEPictureImpl_IConnectionPointContainer_Release,
2138 OLEPictureImpl_EnumConnectionPoints,
2139 OLEPictureImpl_FindConnectionPoint
2142 /***********************************************************************
2143 * OleCreatePictureIndirect (OLEAUT32.419)
2145 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2146 BOOL Own, void **ppvObj )
2148 OLEPictureImpl* newPict;
2151 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), Own, ppvObj);
2155 newPict = OLEPictureImpl_Construct(lpPictDesc, Own);
2157 if (newPict == NULL)
2158 return E_OUTOFMEMORY;
2161 * Make sure it supports the interface required by the caller.
2163 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2166 * Release the reference obtained in the constructor. If
2167 * the QueryInterface was unsuccessful, it will free the class.
2169 IPicture_Release((IPicture*)newPict);
2175 /***********************************************************************
2176 * OleLoadPicture (OLEAUT32.418)
2178 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2179 REFIID riid, LPVOID *ppvObj )
2185 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2186 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2188 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2191 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2193 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2194 IPicture_Release(newpic);
2198 hr = IPersistStream_Load(ps,lpstream);
2199 IPersistStream_Release(ps);
2202 ERR("IPersistStream_Load failed\n");
2203 IPicture_Release(newpic);
2207 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2209 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2210 IPicture_Release(newpic);
2214 /***********************************************************************
2215 * OleLoadPictureEx (OLEAUT32.401)
2217 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2218 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2224 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2225 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2227 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2230 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2232 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2233 IPicture_Release(newpic);
2237 hr = IPersistStream_Load(ps,lpstream);
2238 IPersistStream_Release(ps);
2241 ERR("IPersistStream_Load failed\n");
2242 IPicture_Release(newpic);
2246 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2248 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2249 IPicture_Release(newpic);
2253 /***********************************************************************
2254 * OleLoadPicturePath (OLEAUT32.424)
2256 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2257 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2260 static const WCHAR file[] = { 'f','i','l','e',':',0 };
2264 HGLOBAL hGlobal = NULL;
2265 DWORD dwBytesRead = 0;
2268 IPersistStream *pStream;
2271 WCHAR *file_candidate;
2272 WCHAR path_buf[MAX_PATH];
2274 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2275 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2276 debugstr_guid(riid), ppvRet);
2278 if (!szURLorPath || !ppvRet)
2279 return E_INVALIDARG;
2283 /* Convert file URLs to DOS paths. */
2284 if (strncmpW(szURLorPath, file, 5) == 0) {
2286 hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
2287 sizeof(path_buf)/sizeof(WCHAR), &size, 0);
2291 file_candidate = path_buf;
2294 file_candidate = szURLorPath;
2296 /* Handle candidate DOS paths separately. */
2297 if (file_candidate[1] == ':') {
2298 hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2300 if (hFile == INVALID_HANDLE_VALUE)
2301 return E_UNEXPECTED;
2303 dwFileSize = GetFileSize(hFile, NULL);
2304 if (dwFileSize != INVALID_FILE_SIZE )
2306 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2309 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2312 GlobalFree(hGlobal);
2320 return E_UNEXPECTED;
2322 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2325 GlobalFree(hGlobal);
2332 hRes = CreateBindCtx(0, &pbc);
2333 if (SUCCEEDED(hRes))
2335 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2336 if (SUCCEEDED(hRes))
2338 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2339 IMoniker_Release(pmnk);
2341 IBindCtx_Release(pbc);
2347 init_res = CoInitialize(NULL);
2349 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2350 &IID_IPicture, (LPVOID*)&ipicture);
2351 if (SUCCEEDED(hRes)) {
2352 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2354 if (SUCCEEDED(hRes)) {
2355 hRes = IPersistStream_Load(pStream, stream);
2357 if (SUCCEEDED(hRes)) {
2358 hRes = IPicture_QueryInterface(ipicture, riid, ppvRet);
2361 ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid));
2363 IPersistStream_Release(pStream);
2365 IPicture_Release(ipicture);
2368 IStream_Release(stream);
2370 if (SUCCEEDED(init_res))
2376 /*******************************************************************************
2377 * StdPic ClassFactory
2381 /* IUnknown fields */
2382 const IClassFactoryVtbl *lpVtbl;
2384 } IClassFactoryImpl;
2386 static HRESULT WINAPI
2387 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2388 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2390 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2391 return E_NOINTERFACE;
2395 SPCF_AddRef(LPCLASSFACTORY iface) {
2396 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2397 return InterlockedIncrement(&This->ref);
2400 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2401 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2402 /* static class, won't be freed */
2403 return InterlockedDecrement(&This->ref);
2406 static HRESULT WINAPI SPCF_CreateInstance(
2407 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2409 /* Creates an uninitialized picture */
2410 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2414 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2415 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2416 FIXME("(%p)->(%d),stub!\n",This,dolock);
2420 static const IClassFactoryVtbl SPCF_Vtbl = {
2421 SPCF_QueryInterface,
2424 SPCF_CreateInstance,
2427 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2429 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }