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;
553 TRACE("(%p)->(%p)\n", This, phandle);
558 switch (This->desc.picType) {
559 case PICTYPE_UNINITIALIZED:
565 *phandle = (OLE_HANDLE)This->desc.u.bmp.hpal;
569 case PICTYPE_METAFILE:
570 case PICTYPE_ENHMETAFILE:
572 FIXME("unimplemented for type %d. Returning 0 palette.\n",
578 TRACE("returning 0x%08lx, palette handle %08x\n", hres, *phandle);
582 /************************************************************************
583 * OLEPictureImpl_get_Type
585 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
588 OLEPictureImpl *This = (OLEPictureImpl *)iface;
589 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
590 *ptype = This->desc.picType;
594 /************************************************************************
595 * OLEPictureImpl_get_Width
597 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
598 OLE_XSIZE_HIMETRIC *pwidth)
600 OLEPictureImpl *This = (OLEPictureImpl *)iface;
601 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
602 *pwidth = This->himetricWidth;
606 /************************************************************************
607 * OLEPictureImpl_get_Height
609 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
610 OLE_YSIZE_HIMETRIC *pheight)
612 OLEPictureImpl *This = (OLEPictureImpl *)iface;
613 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
614 *pheight = This->himetricHeight;
618 /************************************************************************
619 * OLEPictureImpl_Render
621 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
622 LONG x, LONG y, LONG cx, LONG cy,
623 OLE_XPOS_HIMETRIC xSrc,
624 OLE_YPOS_HIMETRIC ySrc,
625 OLE_XSIZE_HIMETRIC cxSrc,
626 OLE_YSIZE_HIMETRIC cySrc,
629 OLEPictureImpl *This = (OLEPictureImpl *)iface;
630 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
631 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
633 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
634 prcWBounds->right, prcWBounds->bottom);
637 * While the documentation suggests this to be here (or after rendering?)
638 * it does cause an endless recursion in my sample app. -MM 20010804
639 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
642 switch(This->desc.picType) {
648 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
649 NB y-axis gets flipped */
651 hdcBmp = CreateCompatibleDC(0);
652 SetMapMode(hdcBmp, MM_ANISOTROPIC);
653 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
654 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
655 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
656 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
659 HDC hdcMask = CreateCompatibleDC(0);
660 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
662 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
664 SetMapMode(hdcMask, MM_ANISOTROPIC);
665 SetWindowOrgEx(hdcMask, 0, 0, NULL);
666 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
667 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
668 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
670 SetBkColor(hdc, RGB(255, 255, 255));
671 SetTextColor(hdc, RGB(0, 0, 0));
672 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
673 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
675 SelectObject(hdcMask, hOldbm);
678 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
679 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
682 SelectObject(hdcBmp, hbmpOld);
687 FIXME("Not quite correct implementation of rendering icons...\n");
688 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
691 case PICTYPE_METAFILE:
692 case PICTYPE_ENHMETAFILE:
694 FIXME("type %d not implemented\n", This->desc.picType);
700 /************************************************************************
701 * OLEPictureImpl_set_hPal
703 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
706 OLEPictureImpl *This = (OLEPictureImpl *)iface;
707 FIXME("(%p)->(%08x): stub\n", This, hpal);
708 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
712 /************************************************************************
713 * OLEPictureImpl_get_CurDC
715 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
718 OLEPictureImpl *This = (OLEPictureImpl *)iface;
719 TRACE("(%p), returning %p\n", This, This->hDCCur);
720 if (phdc) *phdc = This->hDCCur;
724 /************************************************************************
725 * OLEPictureImpl_SelectPicture
727 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
730 OLE_HANDLE *phbmpOut)
732 OLEPictureImpl *This = (OLEPictureImpl *)iface;
733 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
734 if (This->desc.picType == PICTYPE_BITMAP) {
735 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
738 *phdcOut = This->hDCCur;
739 This->hDCCur = hdcIn;
741 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
744 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
749 /************************************************************************
750 * OLEPictureImpl_get_KeepOriginalFormat
752 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
755 OLEPictureImpl *This = (OLEPictureImpl *)iface;
756 TRACE("(%p)->(%p)\n", This, pfKeep);
759 *pfKeep = This->keepOrigFormat;
763 /************************************************************************
764 * OLEPictureImpl_put_KeepOriginalFormat
766 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
769 OLEPictureImpl *This = (OLEPictureImpl *)iface;
770 TRACE("(%p)->(%d)\n", This, keep);
771 This->keepOrigFormat = keep;
772 /* FIXME: what DISPID notification here? */
776 /************************************************************************
777 * OLEPictureImpl_PictureChanged
779 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
781 OLEPictureImpl *This = (OLEPictureImpl *)iface;
782 TRACE("(%p)->()\n", This);
783 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
784 This->bIsDirty = TRUE;
788 /************************************************************************
789 * OLEPictureImpl_SaveAsFile
791 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
796 OLEPictureImpl *This = (OLEPictureImpl *)iface;
797 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
798 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
801 /************************************************************************
802 * OLEPictureImpl_get_Attributes
804 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
807 OLEPictureImpl *This = (OLEPictureImpl *)iface;
808 TRACE("(%p)->(%p).\n", This, pdwAttr);
810 switch (This->desc.picType) {
811 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
812 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
813 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
814 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
820 /************************************************************************
821 * IConnectionPointContainer
824 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
825 IConnectionPointContainer* iface,
829 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
831 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
834 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
835 IConnectionPointContainer* iface)
837 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
839 return IPicture_AddRef((IPicture *)This);
842 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
843 IConnectionPointContainer* iface)
845 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
847 return IPicture_Release((IPicture *)This);
850 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
851 IConnectionPointContainer* iface,
852 IEnumConnectionPoints** ppEnum)
854 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
856 FIXME("(%p,%p), stub!\n",This,ppEnum);
860 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
861 IConnectionPointContainer* iface,
863 IConnectionPoint **ppCP)
865 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
866 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
870 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
871 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
872 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid));
875 /************************************************************************
878 /************************************************************************
879 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
881 * See Windows documentation for more details on IUnknown methods.
883 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
884 IPersistStream* iface,
888 OLEPictureImpl *This = impl_from_IPersistStream(iface);
890 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
893 /************************************************************************
894 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
896 * See Windows documentation for more details on IUnknown methods.
898 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
899 IPersistStream* iface)
901 OLEPictureImpl *This = impl_from_IPersistStream(iface);
903 return IPicture_AddRef((IPicture *)This);
906 /************************************************************************
907 * OLEPictureImpl_IPersistStream_Release (IUnknown)
909 * See Windows documentation for more details on IUnknown methods.
911 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
912 IPersistStream* iface)
914 OLEPictureImpl *This = impl_from_IPersistStream(iface);
916 return IPicture_Release((IPicture *)This);
919 /************************************************************************
920 * OLEPictureImpl_IPersistStream_GetClassID
922 static HRESULT WINAPI OLEPictureImpl_GetClassID(
923 IPersistStream* iface,CLSID* pClassID)
925 OLEPictureImpl *This = impl_from_IPersistStream(iface);
926 FIXME("(%p),stub!\n",This);
930 /************************************************************************
931 * OLEPictureImpl_IPersistStream_IsDirty
933 static HRESULT WINAPI OLEPictureImpl_IsDirty(
934 IPersistStream* iface)
936 OLEPictureImpl *This = impl_from_IPersistStream(iface);
937 FIXME("(%p),stub!\n",This);
941 #ifdef HAVE_JPEGLIB_H
943 static void *libjpeg_handle;
944 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
945 MAKE_FUNCPTR(jpeg_std_error);
946 MAKE_FUNCPTR(jpeg_CreateDecompress);
947 MAKE_FUNCPTR(jpeg_read_header);
948 MAKE_FUNCPTR(jpeg_start_decompress);
949 MAKE_FUNCPTR(jpeg_read_scanlines);
950 MAKE_FUNCPTR(jpeg_finish_decompress);
951 MAKE_FUNCPTR(jpeg_destroy_decompress);
954 static void *load_libjpeg(void)
956 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
958 #define LOAD_FUNCPTR(f) \
959 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
960 libjpeg_handle = NULL; \
964 LOAD_FUNCPTR(jpeg_std_error);
965 LOAD_FUNCPTR(jpeg_CreateDecompress);
966 LOAD_FUNCPTR(jpeg_read_header);
967 LOAD_FUNCPTR(jpeg_start_decompress);
968 LOAD_FUNCPTR(jpeg_read_scanlines);
969 LOAD_FUNCPTR(jpeg_finish_decompress);
970 LOAD_FUNCPTR(jpeg_destroy_decompress);
973 return libjpeg_handle;
976 /* for the jpeg decompressor source manager. */
977 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
979 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
980 ERR("(), should not get here.\n");
984 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
985 TRACE("Skipping %ld bytes...\n", num_bytes);
986 cinfo->src->next_input_byte += num_bytes;
987 cinfo->src->bytes_in_buffer -= num_bytes;
990 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
991 ERR("(desired=%d), should not get here.\n",desired);
994 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
995 #endif /* HAVE_JPEGLIB_H */
997 #ifdef HAVE_GIF_LIB_H
999 static void *libungif_handle;
1000 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
1001 MAKE_FUNCPTR(DGifOpen);
1002 MAKE_FUNCPTR(DGifSlurp);
1003 MAKE_FUNCPTR(DGifCloseFile);
1007 unsigned char *data;
1008 unsigned int curoff;
1012 static void *load_libungif(void)
1014 if(((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) ||
1015 ((libungif_handle = wine_dlopen(SONAME_LIBGIF , RTLD_NOW, NULL, 0)) != NULL)
1018 #define LOAD_FUNCPTR(f) \
1019 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
1020 libungif_handle = NULL; \
1024 LOAD_FUNCPTR(DGifOpen);
1025 LOAD_FUNCPTR(DGifSlurp);
1026 LOAD_FUNCPTR(DGifCloseFile);
1029 return libungif_handle;
1032 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
1033 struct gifdata *gd = (struct gifdata*)gif->UserData;
1035 if (len+gd->curoff > gd->len) {
1036 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
1037 len = gd->len - gd->curoff;
1039 memcpy(data, gd->data+gd->curoff, len);
1044 #endif /* HAVE_GIF_LIB_H */
1046 /************************************************************************
1047 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1049 * Loads the binary data from the IStream. Starts at current position.
1050 * There appears to be an 2 DWORD header:
1054 * Currently implemented: BITMAP, ICON, JPEG, GIF
1056 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1057 HRESULT hr = E_FAIL;
1058 BOOL headerisdata = FALSE;
1059 BOOL statfailed = FALSE;
1060 ULONG xread, toread;
1065 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1067 TRACE("(%p,%p)\n",This,pStm);
1069 /****************************************************************************************
1070 * Part 1: Load the data
1072 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1073 * out whether we do.
1075 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1076 * compound file. This may explain most, if not all, of the cases of "no
1077 * header", and the header validation should take this into account.
1078 * At least in Visual Basic 6, resource streams, valid headers are
1079 * header[0] == "lt\0\0",
1080 * header[1] == length_of_stream.
1082 * Also handle streams where we do not have a working "Stat" method by
1083 * reading all data until the end of the stream.
1085 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1087 TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr);
1089 /* we will read at least 8 byte ... just right below */
1090 statstg.cbSize.QuadPart = 8;
1092 hr=IStream_Read(pStm,header,8,&xread);
1093 if (hr || xread!=8) {
1094 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
1098 headerisdata = FALSE;
1100 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1103 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1104 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1105 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1106 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1108 ) {/* Incorrect header, assume none. */
1109 headerisdata = TRUE;
1110 toread = statstg.cbSize.QuadPart-8;
1113 FIXME("Unknown stream header magic: %08lx\n", header[0]);
1118 if (statfailed) { /* we don't know the size ... read all we get */
1120 int origsize = sizeinc;
1123 TRACE("Reading all data from stream.\n");
1124 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1126 memcpy (xbuf, &header, 8);
1128 while (xread < origsize) {
1129 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1134 if (!nread || hr) /* done, or error */
1136 if (xread == origsize) {
1137 origsize += sizeinc;
1138 sizeinc = 2*sizeinc; /* exponential increase */
1139 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1143 TRACE("hr in no-stat loader case is %08lx\n", hr);
1144 TRACE("loaded %ld bytes.\n", xread);
1145 This->datalen = xread;
1148 This->datalen = toread+(headerisdata?8:0);
1149 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1152 memcpy (xbuf, &header, 8);
1154 while (xread < This->datalen) {
1156 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1161 if (xread != This->datalen)
1162 FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
1164 if (This->datalen == 0) { /* Marks the "NONE" picture */
1165 This->desc.picType = PICTYPE_NONE;
1170 /****************************************************************************************
1171 * Part 2: Process the loaded data
1174 magic = xbuf[0] + (xbuf[1]<<8);
1176 case 0x4947: { /* GIF */
1177 #ifdef HAVE_GIF_LIB_H
1187 int transparent = -1;
1191 if(!libungif_handle) {
1192 if(!load_libungif()) {
1193 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF);
1201 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1202 ret = pDGifSlurp(gif);
1203 if (ret == GIF_ERROR) {
1204 FIXME("Failed reading GIF using libgif.\n");
1207 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1208 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1209 TRACE("imgcnt %d\n", gif->ImageCount);
1210 if (gif->ImageCount<1) {
1211 FIXME("GIF stream does not have images inside?\n");
1214 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1215 gif->Image.Width, gif->Image.Height,
1216 gif->Image.Left, gif->Image.Top,
1217 gif->Image.Interlace
1220 padding = (gif->SWidth+3) & ~3;
1221 si = gif->SavedImages+0;
1222 gid = &(si->ImageDesc);
1224 if (!cm) cm = gif->SColorMap;
1225 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1226 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1228 /* look for the transparent color extension */
1229 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1230 eb = si->ExtensionBlocks + i;
1231 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1232 if ((eb->Bytes[0] & 1) == 1) {
1233 transparent = (unsigned char)eb->Bytes[3];
1238 for (i = 0; i < cm->ColorCount; i++) {
1239 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1240 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1241 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1242 if (i == transparent) {
1243 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1244 bmi->bmiColors[i].rgbGreen,
1245 bmi->bmiColors[i].rgbBlue);
1249 /* Map to in picture coordinates */
1250 for (i = 0, j = 0; i < gid->Height; i++) {
1251 if (gif->Image.Interlace) {
1253 bytes + (gid->Top + j) * padding + gid->Left,
1254 si->RasterBits + i * gid->Width,
1257 /* Lower bits of interlaced counter encode current interlace */
1258 if (j & 1) j += 2; /* Currently filling odd rows */
1259 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1260 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1262 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1263 /* End of current interlace, go to next interlace */
1264 if (j & 2) j = 1; /* Next iteration fills odd rows */
1265 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1266 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1270 bytes + (gid->Top + i) * padding + gid->Left,
1271 si->RasterBits + i * gid->Width,
1276 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1277 bmi->bmiHeader.biWidth = gif->SWidth;
1278 bmi->bmiHeader.biHeight = -gif->SHeight;
1279 bmi->bmiHeader.biPlanes = 1;
1280 bmi->bmiHeader.biBitCount = 8;
1281 bmi->bmiHeader.biCompression = BI_RGB;
1282 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1283 bmi->bmiHeader.biXPelsPerMeter = 0;
1284 bmi->bmiHeader.biYPelsPerMeter = 0;
1285 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1286 bmi->bmiHeader.biClrImportant = 0;
1289 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1298 if (transparent > -1) {
1299 /* Create the Mask */
1300 HDC hdc = CreateCompatibleDC(0);
1301 HDC hdcMask = CreateCompatibleDC(0);
1303 HBITMAP hOldbitmapmask;
1305 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1308 This->hbmXor = CreateDIBitmap(
1317 bmi->bmiColors[0].rgbRed = 0;
1318 bmi->bmiColors[0].rgbGreen = 0;
1319 bmi->bmiColors[0].rgbBlue = 0;
1320 bmi->bmiColors[1].rgbRed = 255;
1321 bmi->bmiColors[1].rgbGreen = 255;
1322 bmi->bmiColors[1].rgbBlue = 255;
1324 bmi->bmiHeader.biBitCount = 1;
1325 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1326 bmi->bmiHeader.biClrUsed = 2;
1328 for (i = 0; i < gif->SHeight; i++) {
1329 unsigned char * colorPointer = bytes + padding * i;
1330 unsigned char * monoPointer = bytes + monopadding * i;
1331 for (j = 0; j < gif->SWidth; j++) {
1332 unsigned char pixel = colorPointer[j];
1333 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1334 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1338 hTempMask = CreateDIBitmap(
1348 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1349 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1350 hOldbitmap = SelectObject(hdc, hTempMask);
1351 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1353 SetBkColor(hdc, RGB(255, 255, 255));
1354 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1356 /* We no longer need the original bitmap, so we apply the first
1357 transformation with the mask to speed up the rendering */
1358 SelectObject(hdc, This->hbmXor);
1359 SetBkColor(hdc, RGB(0,0,0));
1360 SetTextColor(hdc, RGB(255,255,255));
1361 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1362 hdcMask, 0, 0, SRCAND);
1364 SelectObject(hdc, hOldbitmap);
1365 SelectObject(hdcMask, hOldbitmapmask);
1368 DeleteObject(hTempMask);
1372 This->desc.picType = PICTYPE_BITMAP;
1373 OLEPictureImpl_SetBitmap(This);
1374 pDGifCloseFile(gif);
1375 HeapFree(GetProcessHeap(),0,bytes);
1378 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1382 case 0xd8ff: { /* JPEG */
1383 #ifdef HAVE_JPEGLIB_H
1384 struct jpeg_decompress_struct jd;
1385 struct jpeg_error_mgr jerr;
1388 JSAMPROW samprow,oldsamprow;
1389 BITMAPINFOHEADER bmi;
1392 struct jpeg_source_mgr xjsm;
1396 if(!libjpeg_handle) {
1397 if(!load_libjpeg()) {
1398 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1403 /* This is basically so we can use in-memory data for jpeg decompression.
1404 * We need to have all the functions.
1406 xjsm.next_input_byte = xbuf;
1407 xjsm.bytes_in_buffer = xread;
1408 xjsm.init_source = _jpeg_init_source;
1409 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1410 xjsm.skip_input_data = _jpeg_skip_input_data;
1411 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1412 xjsm.term_source = _jpeg_term_source;
1414 jd.err = pjpeg_std_error(&jerr);
1415 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1416 * jpeg_create_decompress(&jd); */
1417 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1419 ret=pjpeg_read_header(&jd,TRUE);
1420 jd.out_color_space = JCS_RGB;
1421 pjpeg_start_decompress(&jd);
1422 if (ret != JPEG_HEADER_OK) {
1423 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1424 HeapFree(GetProcessHeap(),0,xbuf);
1428 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1429 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1430 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1433 oldsamprow = samprow;
1434 while ( jd.output_scanline<jd.output_height ) {
1435 x = pjpeg_read_scanlines(&jd,&samprow,1);
1437 FIXME("failed to read current scanline?\n");
1440 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1441 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1442 *(bits++) = *(samprow+2);
1443 *(bits++) = *(samprow+1);
1444 *(bits++) = *(samprow);
1446 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1447 samprow = oldsamprow;
1451 bmi.biSize = sizeof(bmi);
1452 bmi.biWidth = jd.output_width;
1453 bmi.biHeight = -jd.output_height;
1455 bmi.biBitCount = jd.output_components<<3;
1456 bmi.biCompression = BI_RGB;
1457 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1458 bmi.biXPelsPerMeter = 0;
1459 bmi.biYPelsPerMeter = 0;
1461 bmi.biClrImportant = 0;
1463 HeapFree(GetProcessHeap(),0,samprow);
1464 pjpeg_finish_decompress(&jd);
1465 pjpeg_destroy_decompress(&jd);
1467 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1476 This->desc.picType = PICTYPE_BITMAP;
1477 OLEPictureImpl_SetBitmap(This);
1479 HeapFree(GetProcessHeap(),0,bits);
1481 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1486 case 0x4d42: { /* Bitmap */
1487 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1488 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1491 /* Does not matter whether this is a coreheader or not, we only use
1492 * components which are in both
1495 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1499 xbuf+bfh->bfOffBits,
1504 This->desc.picType = PICTYPE_BITMAP;
1505 OLEPictureImpl_SetBitmap(This);
1509 case 0x0000: { /* ICON , first word is dwReserved */
1511 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1516 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1517 FIXME("icon.idType=%d\n",cifd->idType);
1518 FIXME("icon.idCount=%d\n",cifd->idCount);
1520 for (i=0;i<cifd->idCount;i++) {
1521 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1522 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1523 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1524 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1525 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1526 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1527 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1528 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1532 /* If we have more than one icon, try to find the best.
1533 * this currently means '32 pixel wide'.
1535 if (cifd->idCount!=1) {
1536 for (i=0;i<cifd->idCount;i++) {
1537 if (cifd->idEntries[i].bWidth == 32)
1540 if (i==cifd->idCount) i=0;
1543 hicon = CreateIconFromResourceEx(
1544 xbuf+cifd->idEntries[i].dwDIBOffset,
1545 cifd->idEntries[i].dwDIBSize,
1548 cifd->idEntries[i].bWidth,
1549 cifd->idEntries[i].bHeight,
1553 FIXME("CreateIcon failed.\n");
1556 This->desc.picType = PICTYPE_ICON;
1557 This->desc.u.icon.hicon = hicon;
1558 This->origWidth = cifd->idEntries[i].bWidth;
1559 This->origHeight = cifd->idEntries[i].bHeight;
1560 hdcRef = CreateCompatibleDC(0);
1561 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1562 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1571 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1573 for (i=0;i<xread+8;i++) {
1574 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1575 else MESSAGE("%02x ",xbuf[i-8]);
1576 if (i % 10 == 9) MESSAGE("\n");
1582 This->bIsDirty = FALSE;
1584 /* FIXME: this notify is not really documented */
1586 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1590 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength);
1591 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength);
1592 static HRESULT WINAPI OLEPictureImpl_Save(
1593 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1595 HRESULT hResult = E_NOTIMPL;
1597 unsigned int iDataSize;
1599 int iSerializeResult = 0;
1601 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1603 switch (This->desc.picType) {
1605 if (This->bIsDirty) {
1606 if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1607 if (This->loadtime_magic != 0xdeadbeef) {
1610 header[0] = This->loadtime_magic;
1611 header[1] = iDataSize;
1612 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1614 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1616 HeapFree(GetProcessHeap(), 0, This->data);
1617 This->data = pIconData;
1618 This->datalen = iDataSize;
1621 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
1625 if (This->loadtime_magic != 0xdeadbeef) {
1628 header[0] = This->loadtime_magic;
1629 header[1] = This->datalen;
1630 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1632 IStream_Write(pStm, This->data, This->datalen, &dummy);
1636 case PICTYPE_BITMAP:
1637 if (This->bIsDirty) {
1638 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1640 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1643 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1646 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1649 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1652 if (iSerializeResult) {
1654 if (This->loadtime_magic != 0xdeadbeef) {
1659 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1660 header[1] = iDataSize;
1661 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1663 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1665 HeapFree(GetProcessHeap(), 0, This->data);
1666 This->data = pIconData;
1667 This->datalen = iDataSize;
1672 if (This->loadtime_magic != 0xdeadbeef) {
1677 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1678 header[1] = This->datalen;
1679 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1681 IStream_Write(pStm, This->data, This->datalen, &dummy);
1685 case PICTYPE_METAFILE:
1686 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1688 case PICTYPE_ENHMETAFILE:
1689 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1692 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1695 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1699 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1703 BITMAPINFO * pInfoBitmap;
1704 int iNumPaletteEntries;
1705 unsigned char * pPixelData;
1706 BITMAPFILEHEADER * pFileHeader;
1707 BITMAPINFO * pInfoHeader;
1709 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1710 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1712 /* Find out bitmap size and padded length */
1714 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1715 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1717 /* Fetch bitmap palette & pixel data */
1719 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1720 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1722 /* Calculate the total length required for the BMP data */
1723 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1724 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1725 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1727 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1728 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1730 iNumPaletteEntries = 0;
1733 sizeof(BITMAPFILEHEADER) +
1734 sizeof(BITMAPINFOHEADER) +
1735 iNumPaletteEntries * sizeof(RGBQUAD) +
1736 pInfoBitmap->bmiHeader.biSizeImage;
1737 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1739 /* Fill the BITMAPFILEHEADER */
1740 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1741 pFileHeader->bfType = 0x4d42;
1742 pFileHeader->bfSize = *pLength;
1743 pFileHeader->bfOffBits =
1744 sizeof(BITMAPFILEHEADER) +
1745 sizeof(BITMAPINFOHEADER) +
1746 iNumPaletteEntries * sizeof(RGBQUAD);
1748 /* Fill the BITMAPINFOHEADER and the palette data */
1749 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1750 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1752 (unsigned char *)(*ppBuffer) +
1753 sizeof(BITMAPFILEHEADER) +
1754 sizeof(BITMAPINFOHEADER) +
1755 iNumPaletteEntries * sizeof(RGBQUAD),
1756 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1759 HeapFree(GetProcessHeap(), 0, pPixelData);
1760 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1764 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1769 *ppBuffer = NULL; *pLength = 0;
1770 if (GetIconInfo(hIcon, &infoIcon)) {
1772 BITMAPINFO * pInfoBitmap;
1773 unsigned char * pIconData = NULL;
1774 unsigned int iDataSize = 0;
1776 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1778 /* Find out icon size */
1780 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1781 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1783 /* Auxiliary pointers */
1784 CURSORICONFILEDIR * pIconDir;
1785 CURSORICONFILEDIRENTRY * pIconEntry;
1786 BITMAPINFOHEADER * pIconBitmapHeader;
1787 unsigned int iOffsetPalette;
1788 unsigned int iOffsetColorData;
1789 unsigned int iOffsetMaskData;
1791 unsigned int iLengthScanLineColor;
1792 unsigned int iLengthScanLineMask;
1793 unsigned int iNumEntriesPalette;
1795 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1796 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1798 FIXME("DEBUG: bitmap size is %d x %d\n",
1799 pInfoBitmap->bmiHeader.biWidth,
1800 pInfoBitmap->bmiHeader.biHeight);
1801 FIXME("DEBUG: bitmap bpp is %d\n",
1802 pInfoBitmap->bmiHeader.biBitCount);
1803 FIXME("DEBUG: bitmap nplanes is %d\n",
1804 pInfoBitmap->bmiHeader.biPlanes);
1805 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1806 pInfoBitmap->bmiHeader.biSizeImage);
1808 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1809 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1810 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1812 /* Fill out the CURSORICONFILEDIR */
1813 pIconDir = (CURSORICONFILEDIR *)pIconData;
1814 pIconDir->idType = 1;
1815 pIconDir->idCount = 1;
1817 /* Fill out the CURSORICONFILEDIRENTRY */
1818 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1819 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1820 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1821 pIconEntry->bColorCount =
1822 (pInfoBitmap->bmiHeader.biBitCount < 8)
1823 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1825 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1826 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1827 pIconEntry->dwDIBSize = 0;
1828 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1830 /* Fill out the BITMAPINFOHEADER */
1831 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1832 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1834 /* Find out whether a palette exists for the bitmap */
1835 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1836 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1837 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1838 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1839 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1840 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1841 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1842 iNumEntriesPalette = 3;
1843 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1844 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1846 iNumEntriesPalette = 0;
1849 /* Add bitmap size and header size to icon data size. */
1850 iOffsetPalette = iDataSize;
1851 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1852 iOffsetColorData = iDataSize;
1853 iDataSize += pIconBitmapHeader->biSizeImage;
1854 iOffsetMaskData = iDataSize;
1855 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1856 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1857 pIconBitmapHeader->biHeight *= 2;
1858 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1859 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1860 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1861 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1863 /* Get the actual bitmap data from the icon bitmap */
1864 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1865 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1866 if (iNumEntriesPalette > 0) {
1867 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1868 iNumEntriesPalette * sizeof(RGBQUAD));
1871 /* Reset all values so that GetDIBits call succeeds */
1872 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1873 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1874 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1876 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1877 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1878 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1880 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1885 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1886 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1888 /* Write out everything produced so far to the stream */
1889 *ppBuffer = pIconData; *pLength = iDataSize;
1893 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1898 Remarks (from MSDN entry on GetIconInfo):
1900 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1901 members of ICONINFO. The calling application must manage
1902 these bitmaps and delete them when they are no longer
1905 if (hDC) ReleaseDC(0, hDC);
1906 DeleteObject(infoIcon.hbmMask);
1907 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1908 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1910 printf("ERROR: Unable to get icon information (error %lu)\n",
1916 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1917 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1919 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1920 FIXME("(%p,%p),stub!\n",This,pcbSize);
1924 /************************************************************************
1927 /************************************************************************
1928 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1930 * See Windows documentation for more details on IUnknown methods.
1932 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1937 OLEPictureImpl *This = impl_from_IDispatch(iface);
1939 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1942 /************************************************************************
1943 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1945 * See Windows documentation for more details on IUnknown methods.
1947 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1950 OLEPictureImpl *This = impl_from_IDispatch(iface);
1952 return IPicture_AddRef((IPicture *)This);
1955 /************************************************************************
1956 * OLEPictureImpl_IDispatch_Release (IUnknown)
1958 * See Windows documentation for more details on IUnknown methods.
1960 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1963 OLEPictureImpl *This = impl_from_IDispatch(iface);
1965 return IPicture_Release((IPicture *)This);
1968 /************************************************************************
1969 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1971 * See Windows documentation for more details on IDispatch methods.
1973 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1975 unsigned int* pctinfo)
1982 /************************************************************************
1983 * OLEPictureImpl_GetTypeInfo (IDispatch)
1985 * See Windows documentation for more details on IDispatch methods.
1987 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1991 ITypeInfo** ppTInfo)
1998 /************************************************************************
1999 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2001 * See Windows documentation for more details on IDispatch methods.
2003 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2006 LPOLESTR* rgszNames,
2016 /************************************************************************
2017 * OLEPictureImpl_Invoke (IDispatch)
2019 * See Windows documentation for more details on IDispatch methods.
2021 static HRESULT WINAPI OLEPictureImpl_Invoke(
2023 DISPID dispIdMember,
2027 DISPPARAMS* pDispParams,
2028 VARIANT* pVarResult,
2029 EXCEPINFO* pExepInfo,
2032 FIXME("(dispid: %ld):Stub\n",dispIdMember);
2034 VariantInit(pVarResult);
2035 V_VT(pVarResult) = VT_BOOL;
2036 V_BOOL(pVarResult) = FALSE;
2041 static const IPictureVtbl OLEPictureImpl_VTable =
2043 OLEPictureImpl_QueryInterface,
2044 OLEPictureImpl_AddRef,
2045 OLEPictureImpl_Release,
2046 OLEPictureImpl_get_Handle,
2047 OLEPictureImpl_get_hPal,
2048 OLEPictureImpl_get_Type,
2049 OLEPictureImpl_get_Width,
2050 OLEPictureImpl_get_Height,
2051 OLEPictureImpl_Render,
2052 OLEPictureImpl_set_hPal,
2053 OLEPictureImpl_get_CurDC,
2054 OLEPictureImpl_SelectPicture,
2055 OLEPictureImpl_get_KeepOriginalFormat,
2056 OLEPictureImpl_put_KeepOriginalFormat,
2057 OLEPictureImpl_PictureChanged,
2058 OLEPictureImpl_SaveAsFile,
2059 OLEPictureImpl_get_Attributes
2062 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2064 OLEPictureImpl_IDispatch_QueryInterface,
2065 OLEPictureImpl_IDispatch_AddRef,
2066 OLEPictureImpl_IDispatch_Release,
2067 OLEPictureImpl_GetTypeInfoCount,
2068 OLEPictureImpl_GetTypeInfo,
2069 OLEPictureImpl_GetIDsOfNames,
2070 OLEPictureImpl_Invoke
2073 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2075 OLEPictureImpl_IPersistStream_QueryInterface,
2076 OLEPictureImpl_IPersistStream_AddRef,
2077 OLEPictureImpl_IPersistStream_Release,
2078 OLEPictureImpl_GetClassID,
2079 OLEPictureImpl_IsDirty,
2080 OLEPictureImpl_Load,
2081 OLEPictureImpl_Save,
2082 OLEPictureImpl_GetSizeMax
2085 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2087 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2088 OLEPictureImpl_IConnectionPointContainer_AddRef,
2089 OLEPictureImpl_IConnectionPointContainer_Release,
2090 OLEPictureImpl_EnumConnectionPoints,
2091 OLEPictureImpl_FindConnectionPoint
2094 /***********************************************************************
2095 * OleCreatePictureIndirect (OLEAUT32.419)
2097 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2098 BOOL fOwn, LPVOID *ppvObj )
2100 OLEPictureImpl* newPict = NULL;
2103 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2114 * Try to construct a new instance of the class.
2116 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2118 if (newPict == NULL)
2119 return E_OUTOFMEMORY;
2122 * Make sure it supports the interface required by the caller.
2124 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2127 * Release the reference obtained in the constructor. If
2128 * the QueryInterface was unsuccessful, it will free the class.
2130 IPicture_Release((IPicture*)newPict);
2136 /***********************************************************************
2137 * OleLoadPicture (OLEAUT32.418)
2139 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2140 REFIID riid, LPVOID *ppvObj )
2146 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2147 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2149 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2152 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2154 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2155 IPicture_Release(newpic);
2159 IPersistStream_Load(ps,lpstream);
2160 IPersistStream_Release(ps);
2161 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2163 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2164 IPicture_Release(newpic);
2168 /***********************************************************************
2169 * OleLoadPictureEx (OLEAUT32.401)
2171 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2172 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2178 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2179 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2181 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2184 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2186 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2187 IPicture_Release(newpic);
2191 IPersistStream_Load(ps,lpstream);
2192 IPersistStream_Release(ps);
2193 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2195 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2196 IPicture_Release(newpic);
2200 /***********************************************************************
2201 * OleLoadPicturePath (OLEAUT32.424)
2203 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2204 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2207 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2211 HGLOBAL hGlobal = NULL;
2212 DWORD dwBytesRead = 0;
2215 IPersistStream *pStream;
2218 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2219 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2220 debugstr_guid(riid), ppvRet);
2222 if (!ppvRet) return E_POINTER;
2224 if (strncmpW(szURLorPath, file, 7) == 0) {
2227 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2229 if (hFile == INVALID_HANDLE_VALUE)
2230 return E_UNEXPECTED;
2232 dwFileSize = GetFileSize(hFile, NULL);
2233 if (dwFileSize != INVALID_FILE_SIZE )
2235 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2238 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2241 GlobalFree(hGlobal);
2249 return E_UNEXPECTED;
2251 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2254 GlobalFree(hGlobal);
2261 hRes = CreateBindCtx(0, &pbc);
2262 if (SUCCEEDED(hRes))
2264 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2265 if (SUCCEEDED(hRes))
2267 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2268 IMoniker_Release(pmnk);
2270 IBindCtx_Release(pbc);
2276 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2277 &IID_IPicture, (LPVOID*)&ipicture);
2279 IStream_Release(stream);
2283 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2285 IStream_Release(stream);
2286 IPicture_Release(ipicture);
2290 hRes = IPersistStream_Load(pStream, stream);
2291 IPersistStream_Release(pStream);
2292 IStream_Release(stream);
2295 IPicture_Release(ipicture);
2299 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2301 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2303 IPicture_Release(ipicture);
2307 /*******************************************************************************
2308 * StdPic ClassFactory
2312 /* IUnknown fields */
2313 const IClassFactoryVtbl *lpVtbl;
2315 } IClassFactoryImpl;
2317 static HRESULT WINAPI
2318 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2319 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2321 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2322 return E_NOINTERFACE;
2326 SPCF_AddRef(LPCLASSFACTORY iface) {
2327 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2328 return InterlockedIncrement(&This->ref);
2331 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2332 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2333 /* static class, won't be freed */
2334 return InterlockedDecrement(&This->ref);
2337 static HRESULT WINAPI SPCF_CreateInstance(
2338 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2340 /* Creates an uninitialized picture */
2341 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2345 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2346 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2347 FIXME("(%p)->(%d),stub!\n",This,dolock);
2351 static const IClassFactoryVtbl SPCF_Vtbl = {
2352 SPCF_QueryInterface,
2355 SPCF_CreateInstance,
2358 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2360 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }