4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * Support PICTYPE_BITMAP and PICTYPE_ICON, altough only bitmaps very well..
26 * Lots of methods are just stubs.
29 * NOTES (or things that msdn doesn't tell you)
31 * The width and height properties are returned in HIMETRIC units (0.01mm)
32 * IPicture::Render also uses these to select a region of the src picture.
33 * A bitmap's size is converted into these units by using the screen resolution
34 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
39 #include "wine/port.h"
48 /* Must be before wine includes, the header has things conflicting with
53 # ifndef SONAME_LIBUNGIF
54 # define SONAME_LIBUNGIF "libungif.so"
56 # ifndef SONAME_LIBGIF
57 # define SONAME_LIBGIF "libgif.so"
62 #define NONAMELESSUNION
63 #define NONAMELESSSTRUCT
75 #include "wine/debug.h"
76 #include "wine/unicode.h"
78 #include "wine/wingdi16.h"
81 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
83 #define UINT8 JPEG_UINT8
84 #define UINT16 JPEG_UINT16
88 #ifndef SONAME_LIBJPEG
89 #define SONAME_LIBJPEG "libjpeg.so"
93 WINE_DEFAULT_DEBUG_CHANNEL(ole);
106 } CURSORICONFILEDIRENTRY;
113 CURSORICONFILEDIRENTRY idEntries[1];
118 /*************************************************************************
119 * Declaration of implementation class
122 typedef struct OLEPictureImpl {
125 * IPicture handles IUnknown
128 const IPictureVtbl *lpVtbl;
129 const IDispatchVtbl *lpvtblIDispatch;
130 const IPersistStreamVtbl *lpvtblIPersistStream;
131 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
133 /* Object reference count */
136 /* We own the object and must destroy it ourselves */
139 /* Picture description */
142 /* These are the pixel size of a bitmap */
146 /* And these are the size of the picture converted into HIMETRIC units */
147 OLE_XSIZE_HIMETRIC himetricWidth;
148 OLE_YSIZE_HIMETRIC himetricHeight;
150 IConnectionPoint *pCP;
155 /* Bitmap transparency mask */
163 BOOL bIsDirty; /* Set to TRUE if picture has changed */
164 unsigned int loadtime_magic; /* If a length header was found, saves value */
165 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
169 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
172 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
174 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
177 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
179 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
182 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
184 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
188 * Predeclare VTables. They get initialized at the end.
190 static const IPictureVtbl OLEPictureImpl_VTable;
191 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
192 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
193 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
195 /***********************************************************************
196 * Implementation of the OLEPictureImpl class.
199 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
203 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
204 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
205 ERR("GetObject fails\n");
208 This->origWidth = bm.bmWidth;
209 This->origHeight = bm.bmHeight;
210 /* The width and height are stored in HIMETRIC units (0.01 mm),
211 so we take our pixel width divide by pixels per inch and
212 multiply by 25.4 * 100 */
213 /* Should we use GetBitmapDimension if available? */
214 hdcRef = CreateCompatibleDC(0);
215 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
216 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
220 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
224 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
225 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
229 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
230 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
231 ERR("GetObject fails on icon bitmap\n");
235 This->origWidth = bm.bmWidth;
236 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
237 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
239 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
240 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
241 ReleaseDC(0, hdcRef);
243 DeleteObject(infoIcon.hbmMask);
244 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
246 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
250 /************************************************************************
251 * OLEPictureImpl_Construct
253 * This method will construct a new instance of the OLEPictureImpl
256 * The caller of this method must release the object when it's
259 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
261 OLEPictureImpl* newObject = 0;
264 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
267 * Allocate space for the object.
269 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
275 * Initialize the virtual function table.
277 newObject->lpVtbl = &OLEPictureImpl_VTable;
278 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
279 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
280 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
282 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
285 * Start with one reference count. The caller of this function
286 * must release the interface pointer when it is done.
289 newObject->hDCCur = 0;
291 newObject->fOwn = fOwn;
293 /* dunno about original value */
294 newObject->keepOrigFormat = TRUE;
296 newObject->hbmMask = NULL;
297 newObject->hbmXor = NULL;
298 newObject->loadtime_magic = 0xdeadbeef;
299 newObject->loadtime_format = 0;
300 newObject->bIsDirty = FALSE;
303 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
304 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
306 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
309 switch(pictDesc->picType) {
311 OLEPictureImpl_SetBitmap(newObject);
314 case PICTYPE_METAFILE:
315 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
316 newObject->himetricWidth = pictDesc->u.wmf.xExt;
317 newObject->himetricHeight = pictDesc->u.wmf.yExt;
321 /* not sure what to do here */
322 newObject->himetricWidth = newObject->himetricHeight = 0;
326 OLEPictureImpl_SetIcon(newObject);
328 case PICTYPE_ENHMETAFILE:
330 FIXME("Unsupported type %d\n", pictDesc->picType);
331 newObject->himetricWidth = newObject->himetricHeight = 0;
335 newObject->desc.picType = PICTYPE_UNINITIALIZED;
338 TRACE("returning %p\n", newObject);
342 /************************************************************************
343 * OLEPictureImpl_Destroy
345 * This method is called by the Release method when the reference
346 * count goes down to 0. It will free all resources used by
348 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
350 TRACE("(%p)\n", Obj);
352 if(Obj->fOwn) { /* We need to destroy the picture */
353 switch(Obj->desc.picType) {
355 DeleteObject(Obj->desc.u.bmp.hbitmap);
356 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
357 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
359 case PICTYPE_METAFILE:
360 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
363 DestroyIcon(Obj->desc.u.icon.hicon);
365 case PICTYPE_ENHMETAFILE:
366 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
372 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
376 HeapFree(GetProcessHeap(), 0, Obj->data);
377 HeapFree(GetProcessHeap(), 0, Obj);
380 static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
382 /************************************************************************
383 * OLEPictureImpl_QueryInterface (IUnknown)
385 * See Windows documentation for more details on IUnknown methods.
387 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
392 OLEPictureImpl *This = (OLEPictureImpl *)iface;
393 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
396 * Perform a sanity check on the parameters.
398 if ( (This==0) || (ppvObject==0) )
402 * Initialize the return parameter.
407 * Compare the riid with the interface IDs implemented by this object.
409 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
411 *ppvObject = (IPicture*)This;
413 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
415 *ppvObject = (IPicture*)This;
417 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
419 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
421 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
423 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
425 else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
427 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
429 else if (memcmp(&IID_IConnectionPointContainer, riid, sizeof(IID_IConnectionPointContainer)) == 0)
431 *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
434 * Check that we obtained an interface.
438 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
439 return E_NOINTERFACE;
443 * Query Interface always increases the reference count by one when it is
446 OLEPictureImpl_AddRef((IPicture*)This);
450 /***********************************************************************
451 * OLEPicture_SendNotify (internal)
453 * Sends notification messages of changed properties to any interested
456 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
458 IEnumConnections *pEnum;
461 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
463 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
464 IPropertyNotifySink *sink;
466 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
467 IPropertyNotifySink_OnChanged(sink, dispID);
468 IPropertyNotifySink_Release(sink);
469 IUnknown_Release(CD.pUnk);
471 IEnumConnections_Release(pEnum);
475 /************************************************************************
476 * OLEPictureImpl_AddRef (IUnknown)
478 * See Windows documentation for more details on IUnknown methods.
480 static ULONG WINAPI OLEPictureImpl_AddRef(
483 OLEPictureImpl *This = (OLEPictureImpl *)iface;
484 ULONG refCount = InterlockedIncrement(&This->ref);
486 TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1);
491 /************************************************************************
492 * OLEPictureImpl_Release (IUnknown)
494 * See Windows documentation for more details on IUnknown methods.
496 static ULONG WINAPI OLEPictureImpl_Release(
499 OLEPictureImpl *This = (OLEPictureImpl *)iface;
500 ULONG refCount = InterlockedDecrement(&This->ref);
502 TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1);
505 * If the reference count goes down to 0, perform suicide.
507 if (!refCount) OLEPictureImpl_Destroy(This);
513 /************************************************************************
514 * OLEPictureImpl_get_Handle
516 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
519 OLEPictureImpl *This = (OLEPictureImpl *)iface;
520 TRACE("(%p)->(%p)\n", This, phandle);
521 switch(This->desc.picType) {
526 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
528 case PICTYPE_METAFILE:
529 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
532 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
534 case PICTYPE_ENHMETAFILE:
535 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
538 FIXME("Unimplemented type %d\n", This->desc.picType);
541 TRACE("returning handle %08x\n", *phandle);
545 /************************************************************************
546 * OLEPictureImpl_get_hPal
548 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
551 OLEPictureImpl *This = (OLEPictureImpl *)iface;
552 FIXME("(%p)->(%p): stub, return 0 palette.\n", This, phandle);
558 /************************************************************************
559 * OLEPictureImpl_get_Type
561 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
564 OLEPictureImpl *This = (OLEPictureImpl *)iface;
565 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
566 *ptype = This->desc.picType;
570 /************************************************************************
571 * OLEPictureImpl_get_Width
573 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
574 OLE_XSIZE_HIMETRIC *pwidth)
576 OLEPictureImpl *This = (OLEPictureImpl *)iface;
577 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
578 *pwidth = This->himetricWidth;
582 /************************************************************************
583 * OLEPictureImpl_get_Height
585 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
586 OLE_YSIZE_HIMETRIC *pheight)
588 OLEPictureImpl *This = (OLEPictureImpl *)iface;
589 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
590 *pheight = This->himetricHeight;
594 /************************************************************************
595 * OLEPictureImpl_Render
597 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
598 LONG x, LONG y, LONG cx, LONG cy,
599 OLE_XPOS_HIMETRIC xSrc,
600 OLE_YPOS_HIMETRIC ySrc,
601 OLE_XSIZE_HIMETRIC cxSrc,
602 OLE_YSIZE_HIMETRIC cySrc,
605 OLEPictureImpl *This = (OLEPictureImpl *)iface;
606 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
607 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
609 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
610 prcWBounds->right, prcWBounds->bottom);
613 * While the documentation suggests this to be here (or after rendering?)
614 * it does cause an endless recursion in my sample app. -MM 20010804
615 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
618 switch(This->desc.picType) {
624 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
625 NB y-axis gets flipped */
627 hdcBmp = CreateCompatibleDC(0);
628 SetMapMode(hdcBmp, MM_ANISOTROPIC);
629 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
630 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
631 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
632 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
635 HDC hdcMask = CreateCompatibleDC(0);
636 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
638 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
640 SetMapMode(hdcMask, MM_ANISOTROPIC);
641 SetWindowOrgEx(hdcMask, 0, 0, NULL);
642 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
643 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
644 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
646 SetBkColor(hdc, RGB(255, 255, 255));
647 SetTextColor(hdc, RGB(0, 0, 0));
648 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
649 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
651 SelectObject(hdcMask, hOldbm);
654 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
655 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
658 SelectObject(hdcBmp, hbmpOld);
663 FIXME("Not quite correct implementation of rendering icons...\n");
664 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
667 case PICTYPE_METAFILE:
668 case PICTYPE_ENHMETAFILE:
670 FIXME("type %d not implemented\n", This->desc.picType);
676 /************************************************************************
677 * OLEPictureImpl_set_hPal
679 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
682 OLEPictureImpl *This = (OLEPictureImpl *)iface;
683 FIXME("(%p)->(%08x): stub\n", This, hpal);
684 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
688 /************************************************************************
689 * OLEPictureImpl_get_CurDC
691 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
694 OLEPictureImpl *This = (OLEPictureImpl *)iface;
695 TRACE("(%p), returning %p\n", This, This->hDCCur);
696 if (phdc) *phdc = This->hDCCur;
700 /************************************************************************
701 * OLEPictureImpl_SelectPicture
703 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
706 OLE_HANDLE *phbmpOut)
708 OLEPictureImpl *This = (OLEPictureImpl *)iface;
709 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
710 if (This->desc.picType == PICTYPE_BITMAP) {
711 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
714 *phdcOut = This->hDCCur;
715 This->hDCCur = hdcIn;
717 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
720 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
725 /************************************************************************
726 * OLEPictureImpl_get_KeepOriginalFormat
728 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
731 OLEPictureImpl *This = (OLEPictureImpl *)iface;
732 TRACE("(%p)->(%p)\n", This, pfKeep);
735 *pfKeep = This->keepOrigFormat;
739 /************************************************************************
740 * OLEPictureImpl_put_KeepOriginalFormat
742 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
745 OLEPictureImpl *This = (OLEPictureImpl *)iface;
746 TRACE("(%p)->(%d)\n", This, keep);
747 This->keepOrigFormat = keep;
748 /* FIXME: what DISPID notification here? */
752 /************************************************************************
753 * OLEPictureImpl_PictureChanged
755 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
757 OLEPictureImpl *This = (OLEPictureImpl *)iface;
758 TRACE("(%p)->()\n", This);
759 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
760 This->bIsDirty = TRUE;
764 /************************************************************************
765 * OLEPictureImpl_SaveAsFile
767 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
772 OLEPictureImpl *This = (OLEPictureImpl *)iface;
773 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
774 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
777 /************************************************************************
778 * OLEPictureImpl_get_Attributes
780 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
783 OLEPictureImpl *This = (OLEPictureImpl *)iface;
784 TRACE("(%p)->(%p).\n", This, pdwAttr);
786 switch (This->desc.picType) {
787 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
788 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
789 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
790 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
796 /************************************************************************
797 * IConnectionPointContainer
800 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
801 IConnectionPointContainer* iface,
805 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
807 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
810 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
811 IConnectionPointContainer* iface)
813 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
815 return IPicture_AddRef((IPicture *)This);
818 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
819 IConnectionPointContainer* iface)
821 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
823 return IPicture_Release((IPicture *)This);
826 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
827 IConnectionPointContainer* iface,
828 IEnumConnectionPoints** ppEnum)
830 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
832 FIXME("(%p,%p), stub!\n",This,ppEnum);
836 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
837 IConnectionPointContainer* iface,
839 IConnectionPoint **ppCP)
841 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
842 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
846 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
847 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
848 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid));
851 /************************************************************************
854 /************************************************************************
855 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
857 * See Windows documentation for more details on IUnknown methods.
859 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
860 IPersistStream* iface,
864 OLEPictureImpl *This = impl_from_IPersistStream(iface);
866 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
869 /************************************************************************
870 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
872 * See Windows documentation for more details on IUnknown methods.
874 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
875 IPersistStream* iface)
877 OLEPictureImpl *This = impl_from_IPersistStream(iface);
879 return IPicture_AddRef((IPicture *)This);
882 /************************************************************************
883 * OLEPictureImpl_IPersistStream_Release (IUnknown)
885 * See Windows documentation for more details on IUnknown methods.
887 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
888 IPersistStream* iface)
890 OLEPictureImpl *This = impl_from_IPersistStream(iface);
892 return IPicture_Release((IPicture *)This);
895 /************************************************************************
896 * OLEPictureImpl_IPersistStream_GetClassID
898 static HRESULT WINAPI OLEPictureImpl_GetClassID(
899 IPersistStream* iface,CLSID* pClassID)
901 OLEPictureImpl *This = impl_from_IPersistStream(iface);
902 FIXME("(%p),stub!\n",This);
906 /************************************************************************
907 * OLEPictureImpl_IPersistStream_IsDirty
909 static HRESULT WINAPI OLEPictureImpl_IsDirty(
910 IPersistStream* iface)
912 OLEPictureImpl *This = impl_from_IPersistStream(iface);
913 FIXME("(%p),stub!\n",This);
917 #ifdef HAVE_JPEGLIB_H
919 static void *libjpeg_handle;
920 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
921 MAKE_FUNCPTR(jpeg_std_error);
922 MAKE_FUNCPTR(jpeg_CreateDecompress);
923 MAKE_FUNCPTR(jpeg_read_header);
924 MAKE_FUNCPTR(jpeg_start_decompress);
925 MAKE_FUNCPTR(jpeg_read_scanlines);
926 MAKE_FUNCPTR(jpeg_finish_decompress);
927 MAKE_FUNCPTR(jpeg_destroy_decompress);
930 static void *load_libjpeg(void)
932 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
934 #define LOAD_FUNCPTR(f) \
935 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
936 libjpeg_handle = NULL; \
940 LOAD_FUNCPTR(jpeg_std_error);
941 LOAD_FUNCPTR(jpeg_CreateDecompress);
942 LOAD_FUNCPTR(jpeg_read_header);
943 LOAD_FUNCPTR(jpeg_start_decompress);
944 LOAD_FUNCPTR(jpeg_read_scanlines);
945 LOAD_FUNCPTR(jpeg_finish_decompress);
946 LOAD_FUNCPTR(jpeg_destroy_decompress);
949 return libjpeg_handle;
952 /* for the jpeg decompressor source manager. */
953 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
955 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
956 ERR("(), should not get here.\n");
960 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
961 TRACE("Skipping %ld bytes...\n", num_bytes);
962 cinfo->src->next_input_byte += num_bytes;
963 cinfo->src->bytes_in_buffer -= num_bytes;
966 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
967 ERR("(desired=%d), should not get here.\n",desired);
970 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
971 #endif /* HAVE_JPEGLIB_H */
973 #ifdef HAVE_GIF_LIB_H
975 static void *libungif_handle;
976 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
977 MAKE_FUNCPTR(DGifOpen);
978 MAKE_FUNCPTR(DGifSlurp);
979 MAKE_FUNCPTR(DGifCloseFile);
988 static void *load_libungif(void)
990 if(((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) ||
991 ((libungif_handle = wine_dlopen(SONAME_LIBGIF , RTLD_NOW, NULL, 0)) != NULL)
994 #define LOAD_FUNCPTR(f) \
995 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
996 libungif_handle = NULL; \
1000 LOAD_FUNCPTR(DGifOpen);
1001 LOAD_FUNCPTR(DGifSlurp);
1002 LOAD_FUNCPTR(DGifCloseFile);
1005 return libungif_handle;
1008 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
1009 struct gifdata *gd = (struct gifdata*)gif->UserData;
1011 if (len+gd->curoff > gd->len) {
1012 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
1013 len = gd->len - gd->curoff;
1015 memcpy(data, gd->data+gd->curoff, len);
1020 #endif /* HAVE_GIF_LIB_H */
1022 /************************************************************************
1023 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1025 * Loads the binary data from the IStream. Starts at current position.
1026 * There appears to be an 2 DWORD header:
1030 * Currently implemented: BITMAP, ICON, JPEG, GIF
1032 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1033 HRESULT hr = E_FAIL;
1034 BOOL headerisdata = FALSE;
1035 ULONG xread, toread;
1040 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1042 TRACE("(%p,%p)\n",This,pStm);
1044 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1045 * out whether we do.
1047 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1048 * compound file. This may explain most, if not all, of the cases of "no header",
1049 * and the header validation should take this into account. At least in Visual Basic 6,
1050 * resource streams, valid headers are
1051 * header[0] == "lt\0\0",
1052 * header[1] == length_of_stream.
1054 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1056 FIXME("Stat failed with hres %lx\n",hr);
1057 hr=IStream_Read(pStm,header,8,&xread);
1058 if (hr || xread!=8) {
1059 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
1063 headerisdata = FALSE;
1065 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1068 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1069 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1070 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1071 (header[1] > statstg.cbSize.QuadPart) || /* invalid size */
1073 ) {/* Incorrect header, assume none. */
1074 headerisdata = TRUE;
1075 toread = statstg.cbSize.QuadPart-8;
1078 FIXME("Unknown stream header magic: %08lx\n", header[0]);
1083 This->datalen = toread+(headerisdata?8:0);
1084 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1087 memcpy (xbuf, &header, 8);
1089 while (xread < This->datalen) {
1091 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1096 if (xread != This->datalen)
1097 FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
1099 if (This->datalen == 0) { /* Marks the "NONE" picture */
1100 This->desc.picType = PICTYPE_NONE;
1104 magic = xbuf[0] + (xbuf[1]<<8);
1106 case 0x4947: { /* GIF */
1107 #ifdef HAVE_GIF_LIB_H
1117 int transparent = -1;
1121 if(!libungif_handle) {
1122 if(!load_libungif()) {
1123 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF);
1131 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1132 ret = pDGifSlurp(gif);
1133 if (ret == GIF_ERROR) {
1134 FIXME("Failed reading GIF using libgif.\n");
1137 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1138 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1139 TRACE("imgcnt %d\n", gif->ImageCount);
1140 if (gif->ImageCount<1) {
1141 FIXME("GIF stream does not have images inside?\n");
1144 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1145 gif->Image.Width, gif->Image.Height,
1146 gif->Image.Left, gif->Image.Top,
1147 gif->Image.Interlace
1150 padding = (gif->SWidth+3) & ~3;
1151 si = gif->SavedImages+0;
1152 gid = &(si->ImageDesc);
1154 if (!cm) cm = gif->SColorMap;
1155 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1156 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1158 /* look for the transparent color extension */
1159 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1160 eb = si->ExtensionBlocks + i;
1161 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1162 if ((eb->Bytes[0] & 1) == 1) {
1163 transparent = (unsigned char)eb->Bytes[3];
1168 for (i = 0; i < cm->ColorCount; i++) {
1169 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1170 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1171 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1172 if (i == transparent) {
1173 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1174 bmi->bmiColors[i].rgbGreen,
1175 bmi->bmiColors[i].rgbBlue);
1179 /* Map to in picture coordinates */
1180 for (i = 0, j = 0; i < gid->Height; i++) {
1181 if (gif->Image.Interlace) {
1183 bytes + (gid->Top + j) * padding + gid->Left,
1184 si->RasterBits + i * gid->Width,
1187 /* Lower bits of interlaced counter encode current interlace */
1188 if (j & 1) j += 2; /* Currently filling odd rows */
1189 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1190 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1192 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1193 /* End of current interlace, go to next interlace */
1194 if (j & 2) j = 1; /* Next iteration fills odd rows */
1195 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1196 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1200 bytes + (gid->Top + i) * padding + gid->Left,
1201 si->RasterBits + i * gid->Width,
1206 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1207 bmi->bmiHeader.biWidth = gif->SWidth;
1208 bmi->bmiHeader.biHeight = -gif->SHeight;
1209 bmi->bmiHeader.biPlanes = 1;
1210 bmi->bmiHeader.biBitCount = 8;
1211 bmi->bmiHeader.biCompression = BI_RGB;
1212 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1213 bmi->bmiHeader.biXPelsPerMeter = 0;
1214 bmi->bmiHeader.biYPelsPerMeter = 0;
1215 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1216 bmi->bmiHeader.biClrImportant = 0;
1219 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1228 if (transparent > -1) {
1229 /* Create the Mask */
1230 HDC hdc = CreateCompatibleDC(0);
1231 HDC hdcMask = CreateCompatibleDC(0);
1233 HBITMAP hOldbitmapmask;
1235 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1238 This->hbmXor = CreateDIBitmap(
1247 bmi->bmiColors[0].rgbRed = 0;
1248 bmi->bmiColors[0].rgbGreen = 0;
1249 bmi->bmiColors[0].rgbBlue = 0;
1250 bmi->bmiColors[1].rgbRed = 255;
1251 bmi->bmiColors[1].rgbGreen = 255;
1252 bmi->bmiColors[1].rgbBlue = 255;
1254 bmi->bmiHeader.biBitCount = 1;
1255 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1256 bmi->bmiHeader.biClrUsed = 2;
1258 for (i = 0; i < gif->SHeight; i++) {
1259 unsigned char * colorPointer = bytes + padding * i;
1260 unsigned char * monoPointer = bytes + monopadding * i;
1261 for (j = 0; j < gif->SWidth; j++) {
1262 unsigned char pixel = colorPointer[j];
1263 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1264 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1268 hTempMask = CreateDIBitmap(
1278 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1279 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1280 hOldbitmap = SelectObject(hdc, hTempMask);
1281 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1283 SetBkColor(hdc, RGB(255, 255, 255));
1284 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1286 /* We no longer need the original bitmap, so we apply the first
1287 transformation with the mask to speed up the rendering */
1288 SelectObject(hdc, This->hbmXor);
1289 SetBkColor(hdc, RGB(0,0,0));
1290 SetTextColor(hdc, RGB(255,255,255));
1291 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1292 hdcMask, 0, 0, SRCAND);
1294 SelectObject(hdc, hOldbitmap);
1295 SelectObject(hdcMask, hOldbitmapmask);
1298 DeleteObject(hTempMask);
1302 This->desc.picType = PICTYPE_BITMAP;
1303 OLEPictureImpl_SetBitmap(This);
1304 pDGifCloseFile(gif);
1305 HeapFree(GetProcessHeap(),0,bytes);
1308 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1312 case 0xd8ff: { /* JPEG */
1313 #ifdef HAVE_JPEGLIB_H
1314 struct jpeg_decompress_struct jd;
1315 struct jpeg_error_mgr jerr;
1318 JSAMPROW samprow,oldsamprow;
1319 BITMAPINFOHEADER bmi;
1322 struct jpeg_source_mgr xjsm;
1326 if(!libjpeg_handle) {
1327 if(!load_libjpeg()) {
1328 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1333 /* This is basically so we can use in-memory data for jpeg decompression.
1334 * We need to have all the functions.
1336 xjsm.next_input_byte = xbuf;
1337 xjsm.bytes_in_buffer = xread;
1338 xjsm.init_source = _jpeg_init_source;
1339 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1340 xjsm.skip_input_data = _jpeg_skip_input_data;
1341 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1342 xjsm.term_source = _jpeg_term_source;
1344 jd.err = pjpeg_std_error(&jerr);
1345 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1346 * jpeg_create_decompress(&jd); */
1347 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1349 ret=pjpeg_read_header(&jd,TRUE);
1350 jd.out_color_space = JCS_RGB;
1351 pjpeg_start_decompress(&jd);
1352 if (ret != JPEG_HEADER_OK) {
1353 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1354 HeapFree(GetProcessHeap(),0,xbuf);
1358 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1359 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1360 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1363 oldsamprow = samprow;
1364 while ( jd.output_scanline<jd.output_height ) {
1365 x = pjpeg_read_scanlines(&jd,&samprow,1);
1367 FIXME("failed to read current scanline?\n");
1370 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1371 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1372 *(bits++) = *(samprow+2);
1373 *(bits++) = *(samprow+1);
1374 *(bits++) = *(samprow);
1376 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1377 samprow = oldsamprow;
1381 bmi.biSize = sizeof(bmi);
1382 bmi.biWidth = jd.output_width;
1383 bmi.biHeight = -jd.output_height;
1385 bmi.biBitCount = jd.output_components<<3;
1386 bmi.biCompression = BI_RGB;
1387 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1388 bmi.biXPelsPerMeter = 0;
1389 bmi.biYPelsPerMeter = 0;
1391 bmi.biClrImportant = 0;
1393 HeapFree(GetProcessHeap(),0,samprow);
1394 pjpeg_finish_decompress(&jd);
1395 pjpeg_destroy_decompress(&jd);
1397 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1406 This->desc.picType = PICTYPE_BITMAP;
1407 OLEPictureImpl_SetBitmap(This);
1409 HeapFree(GetProcessHeap(),0,bits);
1411 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1416 case 0x4d42: { /* Bitmap */
1417 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1418 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1421 /* Does not matter whether this is a coreheader or not, we only use
1422 * components which are in both
1425 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1429 xbuf+bfh->bfOffBits,
1434 This->desc.picType = PICTYPE_BITMAP;
1435 OLEPictureImpl_SetBitmap(This);
1439 case 0x0000: { /* ICON , first word is dwReserved */
1441 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1446 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1447 FIXME("icon.idType=%d\n",cifd->idType);
1448 FIXME("icon.idCount=%d\n",cifd->idCount);
1450 for (i=0;i<cifd->idCount;i++) {
1451 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1452 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1453 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1454 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1455 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1456 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1457 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1458 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1462 /* If we have more than one icon, try to find the best.
1463 * this currently means '32 pixel wide'.
1465 if (cifd->idCount!=1) {
1466 for (i=0;i<cifd->idCount;i++) {
1467 if (cifd->idEntries[i].bWidth == 32)
1470 if (i==cifd->idCount) i=0;
1473 hicon = CreateIconFromResourceEx(
1474 xbuf+cifd->idEntries[i].dwDIBOffset,
1475 cifd->idEntries[i].dwDIBSize,
1478 cifd->idEntries[i].bWidth,
1479 cifd->idEntries[i].bHeight,
1483 FIXME("CreateIcon failed.\n");
1486 This->desc.picType = PICTYPE_ICON;
1487 This->desc.u.icon.hicon = hicon;
1488 This->origWidth = cifd->idEntries[i].bWidth;
1489 This->origHeight = cifd->idEntries[i].bHeight;
1490 hdcRef = CreateCompatibleDC(0);
1491 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1492 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1501 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1503 for (i=0;i<xread+8;i++) {
1504 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1505 else MESSAGE("%02x ",xbuf[i-8]);
1506 if (i % 10 == 9) MESSAGE("\n");
1512 This->bIsDirty = FALSE;
1514 /* FIXME: this notify is not really documented */
1516 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1520 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength);
1521 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength);
1522 static HRESULT WINAPI OLEPictureImpl_Save(
1523 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1525 HRESULT hResult = E_NOTIMPL;
1527 unsigned int iDataSize;
1529 int iSerializeResult = 0;
1531 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1533 switch (This->desc.picType) {
1535 if (This->bIsDirty) {
1536 if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1537 if (This->loadtime_magic != 0xdeadbeef) {
1540 header[0] = This->loadtime_magic;
1541 header[1] = iDataSize;
1542 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1544 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1546 HeapFree(GetProcessHeap(), 0, This->data);
1547 This->data = pIconData;
1548 This->datalen = iDataSize;
1551 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
1555 if (This->loadtime_magic != 0xdeadbeef) {
1558 header[0] = This->loadtime_magic;
1559 header[1] = This->datalen;
1560 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1562 IStream_Write(pStm, This->data, This->datalen, &dummy);
1566 case PICTYPE_BITMAP:
1567 if (This->bIsDirty) {
1568 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1570 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1573 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1576 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1579 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1582 if (iSerializeResult) {
1584 if (This->loadtime_magic != 0xdeadbeef) {
1589 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1590 header[1] = iDataSize;
1591 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1593 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1595 HeapFree(GetProcessHeap(), 0, This->data);
1596 This->data = pIconData;
1597 This->datalen = iDataSize;
1602 if (This->loadtime_magic != 0xdeadbeef) {
1607 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1608 header[1] = This->datalen;
1609 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1611 IStream_Write(pStm, This->data, This->datalen, &dummy);
1615 case PICTYPE_METAFILE:
1616 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1618 case PICTYPE_ENHMETAFILE:
1619 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1622 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1625 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1629 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1633 BITMAPINFO * pInfoBitmap;
1634 int iNumPaletteEntries;
1635 unsigned char * pPixelData;
1636 BITMAPFILEHEADER * pFileHeader;
1637 BITMAPINFO * pInfoHeader;
1639 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1640 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1642 /* Find out bitmap size and padded length */
1644 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1645 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1647 /* Fetch bitmap palette & pixel data */
1649 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1650 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1652 /* Calculate the total length required for the BMP data */
1653 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1654 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1655 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1657 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1658 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1660 iNumPaletteEntries = 0;
1663 sizeof(BITMAPFILEHEADER) +
1664 sizeof(BITMAPINFOHEADER) +
1665 iNumPaletteEntries * sizeof(RGBQUAD) +
1666 pInfoBitmap->bmiHeader.biSizeImage;
1667 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1669 /* Fill the BITMAPFILEHEADER */
1670 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1671 pFileHeader->bfType = 0x4d42;
1672 pFileHeader->bfSize = *pLength;
1673 pFileHeader->bfOffBits =
1674 sizeof(BITMAPFILEHEADER) +
1675 sizeof(BITMAPINFOHEADER) +
1676 iNumPaletteEntries * sizeof(RGBQUAD);
1678 /* Fill the BITMAPINFOHEADER and the palette data */
1679 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1680 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1682 (unsigned char *)(*ppBuffer) +
1683 sizeof(BITMAPFILEHEADER) +
1684 sizeof(BITMAPINFOHEADER) +
1685 iNumPaletteEntries * sizeof(RGBQUAD),
1686 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1689 HeapFree(GetProcessHeap(), 0, pPixelData);
1690 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1694 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1699 *ppBuffer = NULL; *pLength = 0;
1700 if (GetIconInfo(hIcon, &infoIcon)) {
1702 BITMAPINFO * pInfoBitmap;
1703 unsigned char * pIconData = NULL;
1704 unsigned int iDataSize = 0;
1706 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1708 /* Find out icon size */
1710 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1711 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1713 /* Auxiliary pointers */
1714 CURSORICONFILEDIR * pIconDir;
1715 CURSORICONFILEDIRENTRY * pIconEntry;
1716 BITMAPINFOHEADER * pIconBitmapHeader;
1717 unsigned int iOffsetPalette;
1718 unsigned int iOffsetColorData;
1719 unsigned int iOffsetMaskData;
1721 unsigned int iLengthScanLineColor;
1722 unsigned int iLengthScanLineMask;
1723 unsigned int iNumEntriesPalette;
1725 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1726 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1728 FIXME("DEBUG: bitmap size is %d x %d\n",
1729 pInfoBitmap->bmiHeader.biWidth,
1730 pInfoBitmap->bmiHeader.biHeight);
1731 FIXME("DEBUG: bitmap bpp is %d\n",
1732 pInfoBitmap->bmiHeader.biBitCount);
1733 FIXME("DEBUG: bitmap nplanes is %d\n",
1734 pInfoBitmap->bmiHeader.biPlanes);
1735 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1736 pInfoBitmap->bmiHeader.biSizeImage);
1738 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1739 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1740 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1742 /* Fill out the CURSORICONFILEDIR */
1743 pIconDir = (CURSORICONFILEDIR *)pIconData;
1744 pIconDir->idType = 1;
1745 pIconDir->idCount = 1;
1747 /* Fill out the CURSORICONFILEDIRENTRY */
1748 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1749 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1750 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1751 pIconEntry->bColorCount =
1752 (pInfoBitmap->bmiHeader.biBitCount < 8)
1753 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1755 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1756 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1757 pIconEntry->dwDIBSize = 0;
1758 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1760 /* Fill out the BITMAPINFOHEADER */
1761 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1762 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1764 /* Find out whether a palette exists for the bitmap */
1765 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1766 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1767 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1768 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1769 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1770 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1771 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1772 iNumEntriesPalette = 3;
1773 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1774 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1776 iNumEntriesPalette = 0;
1779 /* Add bitmap size and header size to icon data size. */
1780 iOffsetPalette = iDataSize;
1781 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1782 iOffsetColorData = iDataSize;
1783 iDataSize += pIconBitmapHeader->biSizeImage;
1784 iOffsetMaskData = iDataSize;
1785 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1786 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1787 pIconBitmapHeader->biHeight *= 2;
1788 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1789 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1790 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1791 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1793 /* Get the actual bitmap data from the icon bitmap */
1794 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1795 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1796 if (iNumEntriesPalette > 0) {
1797 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1798 iNumEntriesPalette * sizeof(RGBQUAD));
1801 /* Reset all values so that GetDIBits call succeeds */
1802 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1803 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1804 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1806 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1807 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1808 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1810 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1815 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1816 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1818 /* Write out everything produced so far to the stream */
1819 *ppBuffer = pIconData; *pLength = iDataSize;
1823 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1828 Remarks (from MSDN entry on GetIconInfo):
1830 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1831 members of ICONINFO. The calling application must manage
1832 these bitmaps and delete them when they are no longer
1835 if (hDC) ReleaseDC(0, hDC);
1836 DeleteObject(infoIcon.hbmMask);
1837 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1838 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1840 printf("ERROR: Unable to get icon information (error %lu)\n",
1846 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1847 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1849 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1850 FIXME("(%p,%p),stub!\n",This,pcbSize);
1854 /************************************************************************
1857 /************************************************************************
1858 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1860 * See Windows documentation for more details on IUnknown methods.
1862 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1867 OLEPictureImpl *This = impl_from_IDispatch(iface);
1869 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1872 /************************************************************************
1873 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1875 * See Windows documentation for more details on IUnknown methods.
1877 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1880 OLEPictureImpl *This = impl_from_IDispatch(iface);
1882 return IPicture_AddRef((IPicture *)This);
1885 /************************************************************************
1886 * OLEPictureImpl_IDispatch_Release (IUnknown)
1888 * See Windows documentation for more details on IUnknown methods.
1890 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1893 OLEPictureImpl *This = impl_from_IDispatch(iface);
1895 return IPicture_Release((IPicture *)This);
1898 /************************************************************************
1899 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1901 * See Windows documentation for more details on IDispatch methods.
1903 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1905 unsigned int* pctinfo)
1912 /************************************************************************
1913 * OLEPictureImpl_GetTypeInfo (IDispatch)
1915 * See Windows documentation for more details on IDispatch methods.
1917 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1921 ITypeInfo** ppTInfo)
1928 /************************************************************************
1929 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1931 * See Windows documentation for more details on IDispatch methods.
1933 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1936 LPOLESTR* rgszNames,
1946 /************************************************************************
1947 * OLEPictureImpl_Invoke (IDispatch)
1949 * See Windows documentation for more details on IDispatch methods.
1951 static HRESULT WINAPI OLEPictureImpl_Invoke(
1953 DISPID dispIdMember,
1957 DISPPARAMS* pDispParams,
1958 VARIANT* pVarResult,
1959 EXCEPINFO* pExepInfo,
1962 FIXME("(dispid: %ld):Stub\n",dispIdMember);
1964 VariantInit(pVarResult);
1965 V_VT(pVarResult) = VT_BOOL;
1966 V_BOOL(pVarResult) = FALSE;
1971 static const IPictureVtbl OLEPictureImpl_VTable =
1973 OLEPictureImpl_QueryInterface,
1974 OLEPictureImpl_AddRef,
1975 OLEPictureImpl_Release,
1976 OLEPictureImpl_get_Handle,
1977 OLEPictureImpl_get_hPal,
1978 OLEPictureImpl_get_Type,
1979 OLEPictureImpl_get_Width,
1980 OLEPictureImpl_get_Height,
1981 OLEPictureImpl_Render,
1982 OLEPictureImpl_set_hPal,
1983 OLEPictureImpl_get_CurDC,
1984 OLEPictureImpl_SelectPicture,
1985 OLEPictureImpl_get_KeepOriginalFormat,
1986 OLEPictureImpl_put_KeepOriginalFormat,
1987 OLEPictureImpl_PictureChanged,
1988 OLEPictureImpl_SaveAsFile,
1989 OLEPictureImpl_get_Attributes
1992 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
1994 OLEPictureImpl_IDispatch_QueryInterface,
1995 OLEPictureImpl_IDispatch_AddRef,
1996 OLEPictureImpl_IDispatch_Release,
1997 OLEPictureImpl_GetTypeInfoCount,
1998 OLEPictureImpl_GetTypeInfo,
1999 OLEPictureImpl_GetIDsOfNames,
2000 OLEPictureImpl_Invoke
2003 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2005 OLEPictureImpl_IPersistStream_QueryInterface,
2006 OLEPictureImpl_IPersistStream_AddRef,
2007 OLEPictureImpl_IPersistStream_Release,
2008 OLEPictureImpl_GetClassID,
2009 OLEPictureImpl_IsDirty,
2010 OLEPictureImpl_Load,
2011 OLEPictureImpl_Save,
2012 OLEPictureImpl_GetSizeMax
2015 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2017 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2018 OLEPictureImpl_IConnectionPointContainer_AddRef,
2019 OLEPictureImpl_IConnectionPointContainer_Release,
2020 OLEPictureImpl_EnumConnectionPoints,
2021 OLEPictureImpl_FindConnectionPoint
2024 /***********************************************************************
2025 * OleCreatePictureIndirect (OLEAUT32.419)
2027 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2028 BOOL fOwn, LPVOID *ppvObj )
2030 OLEPictureImpl* newPict = NULL;
2033 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2044 * Try to construct a new instance of the class.
2046 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2048 if (newPict == NULL)
2049 return E_OUTOFMEMORY;
2052 * Make sure it supports the interface required by the caller.
2054 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2057 * Release the reference obtained in the constructor. If
2058 * the QueryInterface was unsuccessful, it will free the class.
2060 IPicture_Release((IPicture*)newPict);
2066 /***********************************************************************
2067 * OleLoadPicture (OLEAUT32.418)
2069 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2070 REFIID riid, LPVOID *ppvObj )
2076 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2077 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2079 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2082 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2084 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2085 IPicture_Release(newpic);
2089 IPersistStream_Load(ps,lpstream);
2090 IPersistStream_Release(ps);
2091 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2093 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2094 IPicture_Release(newpic);
2098 /***********************************************************************
2099 * OleLoadPictureEx (OLEAUT32.401)
2101 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2102 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2108 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2109 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2111 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2114 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2116 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2117 IPicture_Release(newpic);
2121 IPersistStream_Load(ps,lpstream);
2122 IPersistStream_Release(ps);
2123 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2125 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2126 IPicture_Release(newpic);
2130 /***********************************************************************
2131 * OleLoadPicturePath (OLEAUT32.424)
2133 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2134 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2137 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2141 HGLOBAL hGlobal = NULL;
2142 DWORD dwBytesRead = 0;
2145 IPersistStream *pStream;
2148 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2149 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2150 debugstr_guid(riid), ppvRet);
2152 if (!ppvRet) return E_POINTER;
2154 if (strncmpW(szURLorPath, file, 7) == 0) {
2157 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2159 if (hFile == INVALID_HANDLE_VALUE)
2160 return E_UNEXPECTED;
2162 dwFileSize = GetFileSize(hFile, NULL);
2163 if (dwFileSize != INVALID_FILE_SIZE )
2165 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2168 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2171 GlobalFree(hGlobal);
2179 return E_UNEXPECTED;
2181 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2184 GlobalFree(hGlobal);
2191 hRes = CreateBindCtx(0, &pbc);
2192 if (SUCCEEDED(hRes))
2194 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2195 if (SUCCEEDED(hRes))
2197 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2198 IMoniker_Release(pmnk);
2200 IBindCtx_Release(pbc);
2206 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2207 &IID_IPicture, (LPVOID*)&ipicture);
2209 IStream_Release(stream);
2213 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2215 IStream_Release(stream);
2216 IPicture_Release(ipicture);
2220 hRes = IPersistStream_Load(pStream, stream);
2221 IPersistStream_Release(pStream);
2222 IStream_Release(stream);
2225 IPicture_Release(ipicture);
2229 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2231 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2233 IPicture_Release(ipicture);
2237 /*******************************************************************************
2238 * StdPic ClassFactory
2242 /* IUnknown fields */
2243 const IClassFactoryVtbl *lpVtbl;
2245 } IClassFactoryImpl;
2247 static HRESULT WINAPI
2248 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2249 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2251 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2252 return E_NOINTERFACE;
2256 SPCF_AddRef(LPCLASSFACTORY iface) {
2257 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2258 return InterlockedIncrement(&This->ref);
2261 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2262 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2263 /* static class, won't be freed */
2264 return InterlockedDecrement(&This->ref);
2267 static HRESULT WINAPI SPCF_CreateInstance(
2268 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2270 /* Creates an uninitialized picture */
2271 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2275 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2276 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2277 FIXME("(%p)->(%d),stub!\n",This,dolock);
2281 static const IClassFactoryVtbl SPCF_Vtbl = {
2282 SPCF_QueryInterface,
2285 SPCF_CreateInstance,
2288 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2290 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }