4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
8 * Copyright 2008 Kirill K. Smirnov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well..
27 * Lots of methods are just stubs.
30 * NOTES (or things that msdn doesn't tell you)
32 * The width and height properties are returned in HIMETRIC units (0.01mm)
33 * IPicture::Render also uses these to select a region of the src picture.
34 * A bitmap's size is converted into these units by using the screen resolution
35 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
40 #include "wine/port.h"
50 #define NONAMELESSUNION
51 #define NONAMELESSSTRUCT
64 #include "wine/debug.h"
65 #include "wine/unicode.h"
66 #include "wine/library.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(ole);
72 /* Header for Aldus Placable Metafiles - a standard metafile follows */
73 typedef struct _APM_HEADER
95 } CURSORICONFILEDIRENTRY;
102 CURSORICONFILEDIRENTRY idEntries[1];
107 /*************************************************************************
108 * Declaration of implementation class
111 typedef struct OLEPictureImpl {
114 * IPicture handles IUnknown
117 const IPictureVtbl *lpVtbl;
118 const IDispatchVtbl *lpvtblIDispatch;
119 const IPersistStreamVtbl *lpvtblIPersistStream;
120 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
122 /* Object reference count */
125 /* We own the object and must destroy it ourselves */
128 /* Picture description */
131 /* These are the pixel size of a bitmap */
135 /* And these are the size of the picture converted into HIMETRIC units */
136 OLE_XSIZE_HIMETRIC himetricWidth;
137 OLE_YSIZE_HIMETRIC himetricHeight;
139 IConnectionPoint *pCP;
144 /* Bitmap transparency mask */
152 BOOL bIsDirty; /* Set to TRUE if picture has changed */
153 unsigned int loadtime_magic; /* If a length header was found, saves value */
154 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
158 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
161 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
163 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
166 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
168 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
171 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
173 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
177 * Predeclare VTables. They get initialized at the end.
179 static const IPictureVtbl OLEPictureImpl_VTable;
180 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
181 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
182 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
184 /***********************************************************************
185 * Implementation of the OLEPictureImpl class.
188 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
192 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
193 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
194 ERR("GetObject fails\n");
197 This->origWidth = bm.bmWidth;
198 This->origHeight = bm.bmHeight;
199 /* The width and height are stored in HIMETRIC units (0.01 mm),
200 so we take our pixel width divide by pixels per inch and
201 multiply by 25.4 * 100 */
202 /* Should we use GetBitmapDimension if available? */
203 hdcRef = CreateCompatibleDC(0);
204 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
205 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
209 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
213 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
214 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
218 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
219 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
220 ERR("GetObject fails on icon bitmap\n");
224 This->origWidth = bm.bmWidth;
225 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
226 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
228 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
229 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
230 ReleaseDC(0, hdcRef);
232 DeleteObject(infoIcon.hbmMask);
233 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
235 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
239 /************************************************************************
240 * OLEPictureImpl_Construct
242 * This method will construct a new instance of the OLEPictureImpl
245 * The caller of this method must release the object when it's
248 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
250 OLEPictureImpl* newObject = 0;
253 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
256 * Allocate space for the object.
258 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
264 * Initialize the virtual function table.
266 newObject->lpVtbl = &OLEPictureImpl_VTable;
267 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
268 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
269 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
271 newObject->pCP = NULL;
272 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
275 HeapFree(GetProcessHeap(), 0, newObject);
280 * Start with one reference count. The caller of this function
281 * must release the interface pointer when it is done.
284 newObject->hDCCur = 0;
286 newObject->fOwn = fOwn;
288 /* dunno about original value */
289 newObject->keepOrigFormat = TRUE;
291 newObject->hbmMask = NULL;
292 newObject->hbmXor = NULL;
293 newObject->loadtime_magic = 0xdeadbeef;
294 newObject->loadtime_format = 0;
295 newObject->bIsDirty = FALSE;
298 newObject->desc = *pictDesc;
300 switch(pictDesc->picType) {
302 OLEPictureImpl_SetBitmap(newObject);
305 case PICTYPE_METAFILE:
306 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
307 newObject->himetricWidth = pictDesc->u.wmf.xExt;
308 newObject->himetricHeight = pictDesc->u.wmf.yExt;
312 /* not sure what to do here */
313 newObject->himetricWidth = newObject->himetricHeight = 0;
317 OLEPictureImpl_SetIcon(newObject);
319 case PICTYPE_ENHMETAFILE:
321 FIXME("Unsupported type %d\n", pictDesc->picType);
322 newObject->himetricWidth = newObject->himetricHeight = 0;
326 newObject->desc.picType = PICTYPE_UNINITIALIZED;
329 TRACE("returning %p\n", newObject);
333 /************************************************************************
334 * OLEPictureImpl_Destroy
336 * This method is called by the Release method when the reference
337 * count goes down to 0. It will free all resources used by
339 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
341 TRACE("(%p)\n", Obj);
344 IConnectionPoint_Release(Obj->pCP);
346 if(Obj->fOwn) { /* We need to destroy the picture */
347 switch(Obj->desc.picType) {
349 DeleteObject(Obj->desc.u.bmp.hbitmap);
350 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
351 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
353 case PICTYPE_METAFILE:
354 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
357 DestroyIcon(Obj->desc.u.icon.hicon);
359 case PICTYPE_ENHMETAFILE:
360 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
363 case PICTYPE_UNINITIALIZED:
367 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
371 HeapFree(GetProcessHeap(), 0, Obj->data);
372 HeapFree(GetProcessHeap(), 0, Obj);
376 /************************************************************************
377 * OLEPictureImpl_AddRef (IUnknown)
379 * See Windows documentation for more details on IUnknown methods.
381 static ULONG WINAPI OLEPictureImpl_AddRef(
384 OLEPictureImpl *This = (OLEPictureImpl *)iface;
385 ULONG refCount = InterlockedIncrement(&This->ref);
387 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
392 /************************************************************************
393 * OLEPictureImpl_Release (IUnknown)
395 * See Windows documentation for more details on IUnknown methods.
397 static ULONG WINAPI OLEPictureImpl_Release(
400 OLEPictureImpl *This = (OLEPictureImpl *)iface;
401 ULONG refCount = InterlockedDecrement(&This->ref);
403 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
406 * If the reference count goes down to 0, perform suicide.
408 if (!refCount) OLEPictureImpl_Destroy(This);
413 /************************************************************************
414 * OLEPictureImpl_QueryInterface (IUnknown)
416 * See Windows documentation for more details on IUnknown methods.
418 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
423 OLEPictureImpl *This = (OLEPictureImpl *)iface;
424 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
427 * Perform a sanity check on the parameters.
429 if ( (This==0) || (ppvObject==0) )
433 * Initialize the return parameter.
438 * Compare the riid with the interface IDs implemented by this object.
440 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
442 else if (IsEqualIID(&IID_IDispatch, riid))
443 *ppvObject = &This->lpvtblIDispatch;
444 else if (IsEqualIID(&IID_IPictureDisp, riid))
445 *ppvObject = &This->lpvtblIDispatch;
446 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
447 *ppvObject = &This->lpvtblIPersistStream;
448 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
449 *ppvObject = &This->lpvtblIConnectionPointContainer;
452 * Check that we obtained an interface.
456 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
457 return E_NOINTERFACE;
461 * Query Interface always increases the reference count by one when it is
464 OLEPictureImpl_AddRef((IPicture*)This);
469 /***********************************************************************
470 * OLEPicture_SendNotify (internal)
472 * Sends notification messages of changed properties to any interested
475 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
477 IEnumConnections *pEnum;
480 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
482 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
483 IPropertyNotifySink *sink;
485 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
486 IPropertyNotifySink_OnChanged(sink, dispID);
487 IPropertyNotifySink_Release(sink);
488 IUnknown_Release(CD.pUnk);
490 IEnumConnections_Release(pEnum);
493 /************************************************************************
494 * OLEPictureImpl_get_Handle
496 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
499 OLEPictureImpl *This = (OLEPictureImpl *)iface;
500 TRACE("(%p)->(%p)\n", This, phandle);
505 switch(This->desc.picType) {
507 case PICTYPE_UNINITIALIZED:
511 *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
513 case PICTYPE_METAFILE:
514 *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
517 *phandle = HandleToUlong(This->desc.u.icon.hicon);
519 case PICTYPE_ENHMETAFILE:
520 *phandle = HandleToUlong(This->desc.u.emf.hemf);
523 FIXME("Unimplemented type %d\n", This->desc.picType);
526 TRACE("returning handle %08x\n", *phandle);
530 /************************************************************************
531 * OLEPictureImpl_get_hPal
533 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
536 OLEPictureImpl *This = (OLEPictureImpl *)iface;
538 TRACE("(%p)->(%p)\n", This, phandle);
543 switch (This->desc.picType) {
544 case (UINT)PICTYPE_UNINITIALIZED:
550 *phandle = HandleToUlong(This->desc.u.bmp.hpal);
553 case PICTYPE_METAFILE:
557 case PICTYPE_ENHMETAFILE:
559 FIXME("unimplemented for type %d. Returning 0 palette.\n",
565 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
569 /************************************************************************
570 * OLEPictureImpl_get_Type
572 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
575 OLEPictureImpl *This = (OLEPictureImpl *)iface;
576 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
581 *ptype = This->desc.picType;
585 /************************************************************************
586 * OLEPictureImpl_get_Width
588 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
589 OLE_XSIZE_HIMETRIC *pwidth)
591 OLEPictureImpl *This = (OLEPictureImpl *)iface;
592 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
593 *pwidth = This->himetricWidth;
597 /************************************************************************
598 * OLEPictureImpl_get_Height
600 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
601 OLE_YSIZE_HIMETRIC *pheight)
603 OLEPictureImpl *This = (OLEPictureImpl *)iface;
604 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
605 *pheight = This->himetricHeight;
609 /************************************************************************
610 * OLEPictureImpl_Render
612 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
613 LONG x, LONG y, LONG cx, LONG cy,
614 OLE_XPOS_HIMETRIC xSrc,
615 OLE_YPOS_HIMETRIC ySrc,
616 OLE_XSIZE_HIMETRIC cxSrc,
617 OLE_YSIZE_HIMETRIC cySrc,
620 OLEPictureImpl *This = (OLEPictureImpl *)iface;
621 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
622 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
624 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
625 prcWBounds->right, prcWBounds->bottom);
627 if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
628 return CTL_E_INVALIDPROPERTYVALUE;
632 * While the documentation suggests this to be here (or after rendering?)
633 * it does cause an endless recursion in my sample app. -MM 20010804
634 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
637 switch(This->desc.picType) {
638 case PICTYPE_UNINITIALIZED:
647 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
648 NB y-axis gets flipped */
650 hdcBmp = CreateCompatibleDC(0);
651 SetMapMode(hdcBmp, MM_ANISOTROPIC);
652 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
653 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
654 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
655 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
658 HDC hdcMask = CreateCompatibleDC(0);
659 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
661 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
663 SetMapMode(hdcMask, MM_ANISOTROPIC);
664 SetWindowOrgEx(hdcMask, 0, 0, NULL);
665 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
666 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
667 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
669 SetBkColor(hdc, RGB(255, 255, 255));
670 SetTextColor(hdc, RGB(0, 0, 0));
671 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
672 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
674 SelectObject(hdcMask, hOldbm);
677 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
678 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
681 SelectObject(hdcBmp, hbmpOld);
686 FIXME("Not quite correct implementation of rendering icons...\n");
687 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
690 case PICTYPE_METAFILE:
692 POINT prevOrg, prevWndOrg;
693 SIZE prevExt, prevWndExt;
696 /* Render the WMF to the appropriate location by setting the
697 appropriate ratio between "device units" and "logical units" */
698 oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
699 /* For the "source rectangle" the y-axis must be inverted */
700 SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
701 SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
702 /* For the "destination rectangle" no inversion is necessary */
703 SetViewportOrgEx(hdc, x, y, &prevOrg);
704 SetViewportExtEx(hdc, cx, cy, &prevExt);
706 if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
707 ERR("PlayMetaFile failed!\n");
709 /* We're done, restore the DC to the previous settings for converting
710 logical units to device units */
711 SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
712 SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
713 SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
714 SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
715 SetMapMode(hdc, oldmode);
719 case PICTYPE_ENHMETAFILE:
721 RECT rc = { x, y, x + cx, y + cy };
722 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
727 FIXME("type %d not implemented\n", This->desc.picType);
733 /************************************************************************
734 * OLEPictureImpl_set_hPal
736 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
739 OLEPictureImpl *This = (OLEPictureImpl *)iface;
740 FIXME("(%p)->(%08x): stub\n", This, hpal);
741 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
745 /************************************************************************
746 * OLEPictureImpl_get_CurDC
748 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
751 OLEPictureImpl *This = (OLEPictureImpl *)iface;
752 TRACE("(%p), returning %p\n", This, This->hDCCur);
753 if (phdc) *phdc = This->hDCCur;
757 /************************************************************************
758 * OLEPictureImpl_SelectPicture
760 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
763 OLE_HANDLE *phbmpOut)
765 OLEPictureImpl *This = (OLEPictureImpl *)iface;
766 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
767 if (This->desc.picType == PICTYPE_BITMAP) {
768 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
771 *phdcOut = This->hDCCur;
772 This->hDCCur = hdcIn;
774 *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
777 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
782 /************************************************************************
783 * OLEPictureImpl_get_KeepOriginalFormat
785 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
788 OLEPictureImpl *This = (OLEPictureImpl *)iface;
789 TRACE("(%p)->(%p)\n", This, pfKeep);
792 *pfKeep = This->keepOrigFormat;
796 /************************************************************************
797 * OLEPictureImpl_put_KeepOriginalFormat
799 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
802 OLEPictureImpl *This = (OLEPictureImpl *)iface;
803 TRACE("(%p)->(%d)\n", This, keep);
804 This->keepOrigFormat = keep;
805 /* FIXME: what DISPID notification here? */
809 /************************************************************************
810 * OLEPictureImpl_PictureChanged
812 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
814 OLEPictureImpl *This = (OLEPictureImpl *)iface;
815 TRACE("(%p)->()\n", This);
816 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
817 This->bIsDirty = TRUE;
821 /************************************************************************
822 * OLEPictureImpl_SaveAsFile
824 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
829 OLEPictureImpl *This = (OLEPictureImpl *)iface;
830 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
831 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
834 /************************************************************************
835 * OLEPictureImpl_get_Attributes
837 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
840 OLEPictureImpl *This = (OLEPictureImpl *)iface;
841 TRACE("(%p)->(%p).\n", This, pdwAttr);
847 switch (This->desc.picType) {
848 case PICTYPE_UNINITIALIZED:
849 case PICTYPE_NONE: break;
850 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
851 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
852 case PICTYPE_ENHMETAFILE: /* fall through */
853 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
854 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
860 /************************************************************************
861 * IConnectionPointContainer
863 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
864 IConnectionPointContainer* iface,
868 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
870 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
873 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
874 IConnectionPointContainer* iface)
876 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
878 return IPicture_AddRef((IPicture *)This);
881 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
882 IConnectionPointContainer* iface)
884 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
886 return IPicture_Release((IPicture *)This);
889 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
890 IConnectionPointContainer* iface,
891 IEnumConnectionPoints** ppEnum)
893 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
895 FIXME("(%p,%p), stub!\n",This,ppEnum);
899 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
900 IConnectionPointContainer* iface,
902 IConnectionPoint **ppCP)
904 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
905 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
909 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
910 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
911 FIXME("no connection point for %s\n",debugstr_guid(riid));
912 return CONNECT_E_NOCONNECTION;
916 /************************************************************************
920 /************************************************************************
921 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
923 * See Windows documentation for more details on IUnknown methods.
925 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
926 IPersistStream* iface,
930 OLEPictureImpl *This = impl_from_IPersistStream(iface);
932 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
935 /************************************************************************
936 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
938 * See Windows documentation for more details on IUnknown methods.
940 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
941 IPersistStream* iface)
943 OLEPictureImpl *This = impl_from_IPersistStream(iface);
945 return IPicture_AddRef((IPicture *)This);
948 /************************************************************************
949 * OLEPictureImpl_IPersistStream_Release (IUnknown)
951 * See Windows documentation for more details on IUnknown methods.
953 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
954 IPersistStream* iface)
956 OLEPictureImpl *This = impl_from_IPersistStream(iface);
958 return IPicture_Release((IPicture *)This);
961 /************************************************************************
962 * OLEPictureImpl_IPersistStream_GetClassID
964 static HRESULT WINAPI OLEPictureImpl_GetClassID(
965 IPersistStream* iface,CLSID* pClassID)
967 TRACE("(%p)\n", pClassID);
968 *pClassID = CLSID_StdPicture;
972 /************************************************************************
973 * OLEPictureImpl_IPersistStream_IsDirty
975 static HRESULT WINAPI OLEPictureImpl_IsDirty(
976 IPersistStream* iface)
978 OLEPictureImpl *This = impl_from_IPersistStream(iface);
979 FIXME("(%p),stub!\n",This);
983 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
985 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
986 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
989 /* Does not matter whether this is a coreheader or not, we only use
990 * components which are in both
993 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1001 ReleaseDC(0, hdcref);
1002 if (This->desc.u.bmp.hbitmap == 0)
1004 This->desc.picType = PICTYPE_BITMAP;
1005 OLEPictureImpl_SetBitmap(This);
1009 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
1012 BITMAPINFOHEADER bih;
1015 UINT stride, buffersize;
1018 IWICBitmapSource *real_source;
1020 COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
1021 BOOL has_alpha=FALSE;
1023 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
1024 if (FAILED(hr)) return hr;
1026 hr = IWICBitmapSource_GetSize(real_source, &width, &height);
1027 if (FAILED(hr)) goto end;
1029 bih.biSize = sizeof(bih);
1030 bih.biWidth = width;
1031 bih.biHeight = -height;
1033 bih.biBitCount = 32;
1034 bih.biCompression = BI_RGB;
1035 bih.biSizeImage = 0;
1036 bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
1037 bih.biYPelsPerMeter = 4085;
1039 bih.biClrImportant = 0;
1042 buffersize = stride * height;
1044 bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
1055 hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
1060 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1068 if (This->desc.u.bmp.hbitmap == 0)
1071 ReleaseDC(0, hdcref);
1075 This->desc.picType = PICTYPE_BITMAP;
1076 OLEPictureImpl_SetBitmap(This);
1078 /* set transparent pixels to black, all others to white */
1079 for(y = 0; y < height; y++){
1080 for(x = 0; x < width; x++){
1081 DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
1082 if((*pixel & 0x80000000) == 0)
1094 HDC hdcBmp, hdcXor, hdcMask;
1095 HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
1097 This->hbmXor = CreateDIBitmap(
1106 This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
1107 hdcBmp = CreateCompatibleDC(NULL);
1108 hdcXor = CreateCompatibleDC(NULL);
1109 hdcMask = CreateCompatibleDC(NULL);
1111 hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
1112 hbmoldXor = SelectObject(hdcXor,This->hbmXor);
1113 hbmoldMask = SelectObject(hdcMask,This->hbmMask);
1115 SetBkColor(hdcXor,black);
1116 BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
1117 BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
1119 SelectObject(hdcBmp,hbmoldBmp);
1120 SelectObject(hdcXor,hbmoldXor);
1121 SelectObject(hdcMask,hbmoldMask);
1128 ReleaseDC(0, hdcref);
1131 HeapFree(GetProcessHeap(), 0, bits);
1132 IWICBitmapSource_Release(real_source);
1136 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
1139 IWICImagingFactory *factory;
1140 IWICBitmapDecoder *decoder;
1141 IWICBitmapFrameDecode *framedecode;
1145 initresult = CoInitialize(NULL);
1147 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1148 &IID_IWICImagingFactory, (void**)&factory);
1149 if (SUCCEEDED(hr)) /* created factory */
1151 hr = IWICImagingFactory_CreateStream(factory, &stream);
1152 IWICImagingFactory_Release(factory);
1155 if (SUCCEEDED(hr)) /* created stream */
1157 hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
1159 if (SUCCEEDED(hr)) /* initialized stream */
1161 hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
1162 &IID_IWICBitmapDecoder, (void**)&decoder);
1163 if (SUCCEEDED(hr)) /* created decoder */
1165 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
1167 if (SUCCEEDED(hr)) /* initialized decoder */
1168 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
1170 IWICBitmapDecoder_Release(decoder);
1174 IWICStream_Release(stream);
1177 if (SUCCEEDED(hr)) /* got framedecode */
1179 hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
1180 IWICBitmapFrameDecode_Release(framedecode);
1183 if (SUCCEEDED(initresult)) CoUninitialize();
1187 /*****************************************************
1188 * start of Icon-specific code
1191 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1194 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1199 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1200 FIXME("icon.idType=%d\n",cifd->idType);
1201 FIXME("icon.idCount=%d\n",cifd->idCount);
1203 for (i=0;i<cifd->idCount;i++) {
1204 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1205 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1206 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1207 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1208 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1209 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1210 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1211 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1215 /* If we have more than one icon, try to find the best.
1216 * this currently means '32 pixel wide'.
1218 if (cifd->idCount!=1) {
1219 for (i=0;i<cifd->idCount;i++) {
1220 if (cifd->idEntries[i].bWidth == 32)
1223 if (i==cifd->idCount) i=0;
1226 hicon = CreateIconFromResourceEx(
1227 xbuf+cifd->idEntries[i].dwDIBOffset,
1228 cifd->idEntries[i].dwDIBSize,
1231 cifd->idEntries[i].bWidth,
1232 cifd->idEntries[i].bHeight,
1236 ERR("CreateIcon failed.\n");
1239 This->desc.picType = PICTYPE_ICON;
1240 This->desc.u.icon.hicon = hicon;
1241 This->origWidth = cifd->idEntries[i].bWidth;
1242 This->origHeight = cifd->idEntries[i].bHeight;
1243 hdcRef = CreateCompatibleDC(0);
1244 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1245 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1251 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
1252 const BYTE *data, ULONG size)
1257 hemf = SetEnhMetaFileBits(size, data);
1258 if (!hemf) return E_FAIL;
1260 GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
1262 This->desc.picType = PICTYPE_ENHMETAFILE;
1263 This->desc.u.emf.hemf = hemf;
1265 This->origWidth = 0;
1266 This->origHeight = 0;
1267 This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
1268 This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
1273 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
1274 const BYTE *data, ULONG size)
1276 APM_HEADER *header = (APM_HEADER *)data;
1279 if (size < sizeof(APM_HEADER))
1281 if (header->key != 0x9ac6cdd7)
1284 /* SetMetaFileBitsEx performs data check on its own */
1285 hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
1286 if (!hmf) return E_FAIL;
1288 This->desc.picType = PICTYPE_METAFILE;
1289 This->desc.u.wmf.hmeta = hmf;
1290 This->desc.u.wmf.xExt = 0;
1291 This->desc.u.wmf.yExt = 0;
1293 This->origWidth = 0;
1294 This->origHeight = 0;
1295 This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
1296 This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
1300 /************************************************************************
1301 * BITMAP FORMAT FLAGS -
1302 * Flags that differentiate between different types of bitmaps.
1305 #define BITMAP_FORMAT_BMP 0x4d42 /* "BM" */
1306 #define BITMAP_FORMAT_JPEG 0xd8ff
1307 #define BITMAP_FORMAT_GIF 0x4947
1308 #define BITMAP_FORMAT_PNG 0x5089
1309 #define BITMAP_FORMAT_APM 0xcdd7
1311 /************************************************************************
1312 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1314 * Loads the binary data from the IStream. Starts at current position.
1315 * There appears to be an 2 DWORD header:
1319 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1321 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1322 HRESULT hr = E_FAIL;
1323 BOOL headerisdata = FALSE;
1324 BOOL statfailed = FALSE;
1325 ULONG xread, toread;
1331 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1333 TRACE("(%p,%p)\n",This,pStm);
1335 /****************************************************************************************
1336 * Part 1: Load the data
1338 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1339 * out whether we do.
1341 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1342 * compound file. This may explain most, if not all, of the cases of "no
1343 * header", and the header validation should take this into account.
1344 * At least in Visual Basic 6, resource streams, valid headers are
1345 * header[0] == "lt\0\0",
1346 * header[1] == length_of_stream.
1348 * Also handle streams where we do not have a working "Stat" method by
1349 * reading all data until the end of the stream.
1351 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1353 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1355 /* we will read at least 8 byte ... just right below */
1356 statstg.cbSize.QuadPart = 8;
1361 headerisdata = FALSE;
1363 hr=IStream_Read(pStm,header,8,&xread);
1364 if (hr || xread!=8) {
1365 ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1366 return (hr?hr:E_FAIL);
1368 headerread += xread;
1371 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1372 if (toread != 0 && toread != header[1])
1373 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1376 if (toread == 0) break;
1378 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1379 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1380 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1381 (header[0] == EMR_HEADER) || /* EMF header */
1382 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1384 ) {/* Found start of bitmap data */
1385 headerisdata = TRUE;
1387 toread = statstg.cbSize.QuadPart-8;
1391 FIXME("Unknown stream header magic: %08x\n", header[0]);
1395 } while (!headerisdata);
1397 if (statfailed) { /* we don't know the size ... read all we get */
1399 int origsize = sizeinc;
1402 TRACE("Reading all data from stream.\n");
1403 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1405 memcpy (xbuf, header, 8);
1407 while (xread < origsize) {
1408 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1413 if (!nread || hr) /* done, or error */
1415 if (xread == origsize) {
1416 origsize += sizeinc;
1417 sizeinc = 2*sizeinc; /* exponential increase */
1418 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1422 TRACE("hr in no-stat loader case is %08x\n", hr);
1423 TRACE("loaded %d bytes.\n", xread);
1424 This->datalen = xread;
1427 This->datalen = toread+(headerisdata?8:0);
1428 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1430 return E_OUTOFMEMORY;
1433 memcpy (xbuf, header, 8);
1435 while (xread < This->datalen) {
1437 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1442 if (xread != This->datalen)
1443 ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1445 if (This->datalen == 0) { /* Marks the "NONE" picture */
1446 This->desc.picType = PICTYPE_NONE;
1451 /****************************************************************************************
1452 * Part 2: Process the loaded data
1455 magic = xbuf[0] + (xbuf[1]<<8);
1456 This->loadtime_format = magic;
1459 case BITMAP_FORMAT_GIF: /* GIF */
1460 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
1462 case BITMAP_FORMAT_JPEG: /* JPEG */
1463 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
1465 case BITMAP_FORMAT_BMP: /* Bitmap */
1466 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1468 case BITMAP_FORMAT_PNG: /* PNG */
1469 hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
1471 case BITMAP_FORMAT_APM: /* APM */
1472 hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
1474 case 0x0000: { /* ICON , first word is dwReserved */
1475 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1482 /* let's see if it's a EMF */
1483 hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
1484 if (hr == S_OK) break;
1486 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1488 for (i=0;i<xread+8;i++) {
1489 if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
1490 else MESSAGE("%02x ",xbuf[i-8]);
1491 if (i % 10 == 9) MESSAGE("\n");
1497 This->bIsDirty = FALSE;
1499 /* FIXME: this notify is not really documented */
1501 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1505 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1509 BITMAPINFO * pInfoBitmap;
1510 int iNumPaletteEntries;
1511 unsigned char * pPixelData;
1512 BITMAPFILEHEADER * pFileHeader;
1513 BITMAPINFO * pInfoHeader;
1515 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1516 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1518 /* Find out bitmap size and padded length */
1520 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1521 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1523 /* Fetch bitmap palette & pixel data */
1525 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1526 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1528 /* Calculate the total length required for the BMP data */
1529 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1530 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1531 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1533 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1534 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1536 iNumPaletteEntries = 0;
1539 sizeof(BITMAPFILEHEADER) +
1540 sizeof(BITMAPINFOHEADER) +
1541 iNumPaletteEntries * sizeof(RGBQUAD) +
1542 pInfoBitmap->bmiHeader.biSizeImage;
1543 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1545 /* Fill the BITMAPFILEHEADER */
1546 pFileHeader = *ppBuffer;
1547 pFileHeader->bfType = BITMAP_FORMAT_BMP;
1548 pFileHeader->bfSize = *pLength;
1549 pFileHeader->bfOffBits =
1550 sizeof(BITMAPFILEHEADER) +
1551 sizeof(BITMAPINFOHEADER) +
1552 iNumPaletteEntries * sizeof(RGBQUAD);
1554 /* Fill the BITMAPINFOHEADER and the palette data */
1555 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1556 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1558 (unsigned char *)(*ppBuffer) +
1559 sizeof(BITMAPFILEHEADER) +
1560 sizeof(BITMAPINFOHEADER) +
1561 iNumPaletteEntries * sizeof(RGBQUAD),
1562 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1565 HeapFree(GetProcessHeap(), 0, pPixelData);
1566 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1570 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1575 *ppBuffer = NULL; *pLength = 0;
1576 if (GetIconInfo(hIcon, &infoIcon)) {
1578 BITMAPINFO * pInfoBitmap;
1579 unsigned char * pIconData = NULL;
1580 unsigned int iDataSize = 0;
1582 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1584 /* Find out icon size */
1586 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1587 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1589 /* Auxiliary pointers */
1590 CURSORICONFILEDIR * pIconDir;
1591 CURSORICONFILEDIRENTRY * pIconEntry;
1592 BITMAPINFOHEADER * pIconBitmapHeader;
1593 unsigned int iOffsetPalette;
1594 unsigned int iOffsetColorData;
1595 unsigned int iOffsetMaskData;
1597 unsigned int iLengthScanLineColor;
1598 unsigned int iLengthScanLineMask;
1599 unsigned int iNumEntriesPalette;
1601 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1602 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1604 FIXME("DEBUG: bitmap size is %d x %d\n",
1605 pInfoBitmap->bmiHeader.biWidth,
1606 pInfoBitmap->bmiHeader.biHeight);
1607 FIXME("DEBUG: bitmap bpp is %d\n",
1608 pInfoBitmap->bmiHeader.biBitCount);
1609 FIXME("DEBUG: bitmap nplanes is %d\n",
1610 pInfoBitmap->bmiHeader.biPlanes);
1611 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1612 pInfoBitmap->bmiHeader.biSizeImage);
1614 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1615 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1616 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1618 /* Fill out the CURSORICONFILEDIR */
1619 pIconDir = (CURSORICONFILEDIR *)pIconData;
1620 pIconDir->idType = 1;
1621 pIconDir->idCount = 1;
1623 /* Fill out the CURSORICONFILEDIRENTRY */
1624 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1625 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1626 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1627 pIconEntry->bColorCount =
1628 (pInfoBitmap->bmiHeader.biBitCount < 8)
1629 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1631 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1632 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1633 pIconEntry->dwDIBSize = 0;
1634 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1636 /* Fill out the BITMAPINFOHEADER */
1637 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1638 *pIconBitmapHeader = pInfoBitmap->bmiHeader;
1640 /* Find out whether a palette exists for the bitmap */
1641 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1642 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1643 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1644 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1645 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1646 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1647 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1648 iNumEntriesPalette = 3;
1649 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1650 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1652 iNumEntriesPalette = 0;
1655 /* Add bitmap size and header size to icon data size. */
1656 iOffsetPalette = iDataSize;
1657 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1658 iOffsetColorData = iDataSize;
1659 iDataSize += pIconBitmapHeader->biSizeImage;
1660 iOffsetMaskData = iDataSize;
1661 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1662 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1663 pIconBitmapHeader->biHeight *= 2;
1664 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1665 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1666 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1667 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1669 /* Get the actual bitmap data from the icon bitmap */
1670 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1671 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1672 if (iNumEntriesPalette > 0) {
1673 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1674 iNumEntriesPalette * sizeof(RGBQUAD));
1677 /* Reset all values so that GetDIBits call succeeds */
1678 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1679 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1680 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1682 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1683 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1684 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1686 printf("ERROR: unable to get bitmap mask (error %u)\n",
1691 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1692 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1694 /* Write out everything produced so far to the stream */
1695 *ppBuffer = pIconData; *pLength = iDataSize;
1699 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1704 Remarks (from MSDN entry on GetIconInfo):
1706 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1707 members of ICONINFO. The calling application must manage
1708 these bitmaps and delete them when they are no longer
1711 if (hDC) ReleaseDC(0, hDC);
1712 DeleteObject(infoIcon.hbmMask);
1713 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1714 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1716 printf("ERROR: Unable to get icon information (error %u)\n",
1722 static HRESULT WINAPI OLEPictureImpl_Save(
1723 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1725 HRESULT hResult = E_NOTIMPL;
1727 unsigned int iDataSize;
1729 int iSerializeResult = 0;
1730 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1732 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1734 switch (This->desc.picType) {
1736 if (This->bIsDirty || !This->data) {
1737 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1738 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1742 HeapFree(GetProcessHeap(), 0, This->data);
1743 This->data = pIconData;
1744 This->datalen = iDataSize;
1746 if (This->loadtime_magic != 0xdeadbeef) {
1749 header[0] = This->loadtime_magic;
1750 header[1] = This->datalen;
1751 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1753 IStream_Write(pStm, This->data, This->datalen, &dummy);
1757 case PICTYPE_BITMAP:
1758 if (This->bIsDirty) {
1759 switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
1760 case BITMAP_FORMAT_BMP:
1761 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1763 case BITMAP_FORMAT_JPEG:
1764 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1766 case BITMAP_FORMAT_GIF:
1767 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1769 case BITMAP_FORMAT_PNG:
1770 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
1773 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1776 if (iSerializeResult) {
1778 if (This->loadtime_magic != 0xdeadbeef) {
1783 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1784 header[1] = iDataSize;
1785 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1787 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1789 HeapFree(GetProcessHeap(), 0, This->data);
1790 This->data = pIconData;
1791 This->datalen = iDataSize;
1796 if (This->loadtime_magic != 0xdeadbeef) {
1801 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1802 header[1] = This->datalen;
1803 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1805 IStream_Write(pStm, This->data, This->datalen, &dummy);
1809 case PICTYPE_METAFILE:
1810 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1812 case PICTYPE_ENHMETAFILE:
1813 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1816 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1819 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1823 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1824 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1826 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1827 FIXME("(%p,%p),stub!\n",This,pcbSize);
1832 /************************************************************************
1836 /************************************************************************
1837 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1839 * See Windows documentation for more details on IUnknown methods.
1841 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1846 OLEPictureImpl *This = impl_from_IDispatch(iface);
1848 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1851 /************************************************************************
1852 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1854 * See Windows documentation for more details on IUnknown methods.
1856 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1859 OLEPictureImpl *This = impl_from_IDispatch(iface);
1861 return IPicture_AddRef((IPicture *)This);
1864 /************************************************************************
1865 * OLEPictureImpl_IDispatch_Release (IUnknown)
1867 * See Windows documentation for more details on IUnknown methods.
1869 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1872 OLEPictureImpl *This = impl_from_IDispatch(iface);
1874 return IPicture_Release((IPicture *)This);
1877 /************************************************************************
1878 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1880 * See Windows documentation for more details on IDispatch methods.
1882 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1884 unsigned int* pctinfo)
1886 TRACE("(%p)\n", pctinfo);
1893 /************************************************************************
1894 * OLEPictureImpl_GetTypeInfo (IDispatch)
1896 * See Windows documentation for more details on IDispatch methods.
1898 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1902 ITypeInfo** ppTInfo)
1904 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1908 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1913 hres = LoadTypeLib(stdole2tlb, &tl);
1916 ERR("Could not load stdole2.tlb\n");
1920 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1922 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1927 /************************************************************************
1928 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1930 * See Windows documentation for more details on IDispatch methods.
1932 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1935 LPOLESTR* rgszNames,
1943 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
1944 rgszNames, cNames, (int)lcid, rgDispId);
1948 return E_INVALIDARG;
1952 /* retrieve type information */
1953 hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1957 ERR("GetTypeInfo failed.\n");
1961 /* convert names to DISPIDs */
1962 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1963 ITypeInfo_Release(pTInfo);
1969 /************************************************************************
1970 * OLEPictureImpl_Invoke (IDispatch)
1972 * See Windows documentation for more details on IDispatch methods.
1974 static HRESULT WINAPI OLEPictureImpl_Invoke(
1976 DISPID dispIdMember,
1980 DISPPARAMS* pDispParams,
1981 VARIANT* pVarResult,
1982 EXCEPINFO* pExepInfo,
1985 OLEPictureImpl *This = impl_from_IDispatch(iface);
1987 /* validate parameters */
1989 if (!IsEqualIID(riid, &IID_NULL))
1991 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1992 return DISP_E_UNKNOWNNAME;
1997 ERR("null pDispParams not allowed\n");
1998 return DISP_E_PARAMNOTOPTIONAL;
2001 if (wFlags & DISPATCH_PROPERTYGET)
2003 if (pDispParams->cArgs != 0)
2005 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2006 return DISP_E_BADPARAMCOUNT;
2010 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2011 return DISP_E_PARAMNOTOPTIONAL;
2014 else if (wFlags & DISPATCH_PROPERTYPUT)
2016 if (pDispParams->cArgs != 1)
2018 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2019 return DISP_E_BADPARAMCOUNT;
2023 switch (dispIdMember)
2025 case DISPID_PICT_HANDLE:
2026 if (wFlags & DISPATCH_PROPERTYGET)
2028 TRACE("DISPID_PICT_HANDLE\n");
2029 V_VT(pVarResult) = VT_I4;
2030 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2033 case DISPID_PICT_HPAL:
2034 if (wFlags & DISPATCH_PROPERTYGET)
2036 TRACE("DISPID_PICT_HPAL\n");
2037 V_VT(pVarResult) = VT_I4;
2038 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2040 else if (wFlags & DISPATCH_PROPERTYPUT)
2044 TRACE("DISPID_PICT_HPAL\n");
2046 VariantInit(&vararg);
2047 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2051 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2053 VariantClear(&vararg);
2057 case DISPID_PICT_TYPE:
2058 if (wFlags & DISPATCH_PROPERTYGET)
2060 TRACE("DISPID_PICT_TYPE\n");
2061 V_VT(pVarResult) = VT_I2;
2062 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2065 case DISPID_PICT_WIDTH:
2066 if (wFlags & DISPATCH_PROPERTYGET)
2068 TRACE("DISPID_PICT_WIDTH\n");
2069 V_VT(pVarResult) = VT_I4;
2070 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2073 case DISPID_PICT_HEIGHT:
2074 if (wFlags & DISPATCH_PROPERTYGET)
2076 TRACE("DISPID_PICT_HEIGHT\n");
2077 V_VT(pVarResult) = VT_I4;
2078 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2083 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2084 return DISP_E_MEMBERNOTFOUND;
2088 static const IPictureVtbl OLEPictureImpl_VTable =
2090 OLEPictureImpl_QueryInterface,
2091 OLEPictureImpl_AddRef,
2092 OLEPictureImpl_Release,
2093 OLEPictureImpl_get_Handle,
2094 OLEPictureImpl_get_hPal,
2095 OLEPictureImpl_get_Type,
2096 OLEPictureImpl_get_Width,
2097 OLEPictureImpl_get_Height,
2098 OLEPictureImpl_Render,
2099 OLEPictureImpl_set_hPal,
2100 OLEPictureImpl_get_CurDC,
2101 OLEPictureImpl_SelectPicture,
2102 OLEPictureImpl_get_KeepOriginalFormat,
2103 OLEPictureImpl_put_KeepOriginalFormat,
2104 OLEPictureImpl_PictureChanged,
2105 OLEPictureImpl_SaveAsFile,
2106 OLEPictureImpl_get_Attributes
2109 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2111 OLEPictureImpl_IDispatch_QueryInterface,
2112 OLEPictureImpl_IDispatch_AddRef,
2113 OLEPictureImpl_IDispatch_Release,
2114 OLEPictureImpl_GetTypeInfoCount,
2115 OLEPictureImpl_GetTypeInfo,
2116 OLEPictureImpl_GetIDsOfNames,
2117 OLEPictureImpl_Invoke
2120 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2122 OLEPictureImpl_IPersistStream_QueryInterface,
2123 OLEPictureImpl_IPersistStream_AddRef,
2124 OLEPictureImpl_IPersistStream_Release,
2125 OLEPictureImpl_GetClassID,
2126 OLEPictureImpl_IsDirty,
2127 OLEPictureImpl_Load,
2128 OLEPictureImpl_Save,
2129 OLEPictureImpl_GetSizeMax
2132 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2134 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2135 OLEPictureImpl_IConnectionPointContainer_AddRef,
2136 OLEPictureImpl_IConnectionPointContainer_Release,
2137 OLEPictureImpl_EnumConnectionPoints,
2138 OLEPictureImpl_FindConnectionPoint
2141 /***********************************************************************
2142 * OleCreatePictureIndirect (OLEAUT32.419)
2144 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2145 BOOL fOwn, LPVOID *ppvObj )
2147 OLEPictureImpl* newPict = NULL;
2150 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2161 * Try to construct a new instance of the class.
2163 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2165 if (newPict == NULL)
2166 return E_OUTOFMEMORY;
2169 * Make sure it supports the interface required by the caller.
2171 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2174 * Release the reference obtained in the constructor. If
2175 * the QueryInterface was unsuccessful, it will free the class.
2177 IPicture_Release((IPicture*)newPict);
2183 /***********************************************************************
2184 * OleLoadPicture (OLEAUT32.418)
2186 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2187 REFIID riid, LPVOID *ppvObj )
2193 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2194 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2196 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2199 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2201 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2202 IPicture_Release(newpic);
2206 hr = IPersistStream_Load(ps,lpstream);
2207 IPersistStream_Release(ps);
2210 ERR("IPersistStream_Load failed\n");
2211 IPicture_Release(newpic);
2215 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2217 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2218 IPicture_Release(newpic);
2222 /***********************************************************************
2223 * OleLoadPictureEx (OLEAUT32.401)
2225 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2226 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2232 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2233 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2235 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2238 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2240 ERR("Could not get IPersistStream iface from Ole Picture?\n");
2241 IPicture_Release(newpic);
2245 hr = IPersistStream_Load(ps,lpstream);
2246 IPersistStream_Release(ps);
2249 ERR("IPersistStream_Load failed\n");
2250 IPicture_Release(newpic);
2254 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2256 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2257 IPicture_Release(newpic);
2261 /***********************************************************************
2262 * OleLoadPicturePath (OLEAUT32.424)
2264 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2265 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2268 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2272 HGLOBAL hGlobal = NULL;
2273 DWORD dwBytesRead = 0;
2276 IPersistStream *pStream;
2279 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2280 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2281 debugstr_guid(riid), ppvRet);
2283 if (!ppvRet) return E_POINTER;
2285 if (strncmpW(szURLorPath, file, 7) == 0) {
2288 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2290 if (hFile == INVALID_HANDLE_VALUE)
2291 return E_UNEXPECTED;
2293 dwFileSize = GetFileSize(hFile, NULL);
2294 if (dwFileSize != INVALID_FILE_SIZE )
2296 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2299 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2302 GlobalFree(hGlobal);
2310 return E_UNEXPECTED;
2312 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2315 GlobalFree(hGlobal);
2322 hRes = CreateBindCtx(0, &pbc);
2323 if (SUCCEEDED(hRes))
2325 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2326 if (SUCCEEDED(hRes))
2328 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2329 IMoniker_Release(pmnk);
2331 IBindCtx_Release(pbc);
2337 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2338 &IID_IPicture, (LPVOID*)&ipicture);
2340 IStream_Release(stream);
2344 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2346 IStream_Release(stream);
2347 IPicture_Release(ipicture);
2351 hRes = IPersistStream_Load(pStream, stream);
2352 IPersistStream_Release(pStream);
2353 IStream_Release(stream);
2356 IPicture_Release(ipicture);
2360 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2362 ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2364 IPicture_Release(ipicture);
2368 /*******************************************************************************
2369 * StdPic ClassFactory
2373 /* IUnknown fields */
2374 const IClassFactoryVtbl *lpVtbl;
2376 } IClassFactoryImpl;
2378 static HRESULT WINAPI
2379 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2380 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2382 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2383 return E_NOINTERFACE;
2387 SPCF_AddRef(LPCLASSFACTORY iface) {
2388 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2389 return InterlockedIncrement(&This->ref);
2392 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2393 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2394 /* static class, won't be freed */
2395 return InterlockedDecrement(&This->ref);
2398 static HRESULT WINAPI SPCF_CreateInstance(
2399 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2401 /* Creates an uninitialized picture */
2402 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2406 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2407 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2408 FIXME("(%p)->(%d),stub!\n",This,dolock);
2412 static const IClassFactoryVtbl SPCF_Vtbl = {
2413 SPCF_QueryInterface,
2416 SPCF_CreateInstance,
2419 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2421 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }