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 ULONG xread, toread;
1064 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1066 TRACE("(%p,%p)\n",This,pStm);
1068 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1069 * out whether we do.
1071 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1072 * compound file. This may explain most, if not all, of the cases of "no header",
1073 * and the header validation should take this into account. At least in Visual Basic 6,
1074 * resource streams, valid headers are
1075 * header[0] == "lt\0\0",
1076 * header[1] == length_of_stream.
1078 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1080 FIXME("Stat failed with hres %lx\n",hr);
1081 hr=IStream_Read(pStm,header,8,&xread);
1082 if (hr || xread!=8) {
1083 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
1087 headerisdata = FALSE;
1089 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1092 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1093 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1094 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1095 (header[1] > statstg.cbSize.QuadPart) || /* invalid size */
1097 ) {/* Incorrect header, assume none. */
1098 headerisdata = TRUE;
1099 toread = statstg.cbSize.QuadPart-8;
1102 FIXME("Unknown stream header magic: %08lx\n", header[0]);
1107 This->datalen = toread+(headerisdata?8:0);
1108 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1111 memcpy (xbuf, &header, 8);
1113 while (xread < This->datalen) {
1115 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1120 if (xread != This->datalen)
1121 FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
1123 if (This->datalen == 0) { /* Marks the "NONE" picture */
1124 This->desc.picType = PICTYPE_NONE;
1128 magic = xbuf[0] + (xbuf[1]<<8);
1130 case 0x4947: { /* GIF */
1131 #ifdef HAVE_GIF_LIB_H
1141 int transparent = -1;
1145 if(!libungif_handle) {
1146 if(!load_libungif()) {
1147 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF);
1155 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1156 ret = pDGifSlurp(gif);
1157 if (ret == GIF_ERROR) {
1158 FIXME("Failed reading GIF using libgif.\n");
1161 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1162 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1163 TRACE("imgcnt %d\n", gif->ImageCount);
1164 if (gif->ImageCount<1) {
1165 FIXME("GIF stream does not have images inside?\n");
1168 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1169 gif->Image.Width, gif->Image.Height,
1170 gif->Image.Left, gif->Image.Top,
1171 gif->Image.Interlace
1174 padding = (gif->SWidth+3) & ~3;
1175 si = gif->SavedImages+0;
1176 gid = &(si->ImageDesc);
1178 if (!cm) cm = gif->SColorMap;
1179 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1180 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1182 /* look for the transparent color extension */
1183 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1184 eb = si->ExtensionBlocks + i;
1185 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1186 if ((eb->Bytes[0] & 1) == 1) {
1187 transparent = (unsigned char)eb->Bytes[3];
1192 for (i = 0; i < cm->ColorCount; i++) {
1193 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1194 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1195 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1196 if (i == transparent) {
1197 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1198 bmi->bmiColors[i].rgbGreen,
1199 bmi->bmiColors[i].rgbBlue);
1203 /* Map to in picture coordinates */
1204 for (i = 0, j = 0; i < gid->Height; i++) {
1205 if (gif->Image.Interlace) {
1207 bytes + (gid->Top + j) * padding + gid->Left,
1208 si->RasterBits + i * gid->Width,
1211 /* Lower bits of interlaced counter encode current interlace */
1212 if (j & 1) j += 2; /* Currently filling odd rows */
1213 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1214 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1216 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1217 /* End of current interlace, go to next interlace */
1218 if (j & 2) j = 1; /* Next iteration fills odd rows */
1219 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1220 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1224 bytes + (gid->Top + i) * padding + gid->Left,
1225 si->RasterBits + i * gid->Width,
1230 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1231 bmi->bmiHeader.biWidth = gif->SWidth;
1232 bmi->bmiHeader.biHeight = -gif->SHeight;
1233 bmi->bmiHeader.biPlanes = 1;
1234 bmi->bmiHeader.biBitCount = 8;
1235 bmi->bmiHeader.biCompression = BI_RGB;
1236 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1237 bmi->bmiHeader.biXPelsPerMeter = 0;
1238 bmi->bmiHeader.biYPelsPerMeter = 0;
1239 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1240 bmi->bmiHeader.biClrImportant = 0;
1243 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1252 if (transparent > -1) {
1253 /* Create the Mask */
1254 HDC hdc = CreateCompatibleDC(0);
1255 HDC hdcMask = CreateCompatibleDC(0);
1257 HBITMAP hOldbitmapmask;
1259 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1262 This->hbmXor = CreateDIBitmap(
1271 bmi->bmiColors[0].rgbRed = 0;
1272 bmi->bmiColors[0].rgbGreen = 0;
1273 bmi->bmiColors[0].rgbBlue = 0;
1274 bmi->bmiColors[1].rgbRed = 255;
1275 bmi->bmiColors[1].rgbGreen = 255;
1276 bmi->bmiColors[1].rgbBlue = 255;
1278 bmi->bmiHeader.biBitCount = 1;
1279 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1280 bmi->bmiHeader.biClrUsed = 2;
1282 for (i = 0; i < gif->SHeight; i++) {
1283 unsigned char * colorPointer = bytes + padding * i;
1284 unsigned char * monoPointer = bytes + monopadding * i;
1285 for (j = 0; j < gif->SWidth; j++) {
1286 unsigned char pixel = colorPointer[j];
1287 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1288 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1292 hTempMask = CreateDIBitmap(
1302 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1303 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1304 hOldbitmap = SelectObject(hdc, hTempMask);
1305 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1307 SetBkColor(hdc, RGB(255, 255, 255));
1308 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1310 /* We no longer need the original bitmap, so we apply the first
1311 transformation with the mask to speed up the rendering */
1312 SelectObject(hdc, This->hbmXor);
1313 SetBkColor(hdc, RGB(0,0,0));
1314 SetTextColor(hdc, RGB(255,255,255));
1315 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1316 hdcMask, 0, 0, SRCAND);
1318 SelectObject(hdc, hOldbitmap);
1319 SelectObject(hdcMask, hOldbitmapmask);
1322 DeleteObject(hTempMask);
1326 This->desc.picType = PICTYPE_BITMAP;
1327 OLEPictureImpl_SetBitmap(This);
1328 pDGifCloseFile(gif);
1329 HeapFree(GetProcessHeap(),0,bytes);
1332 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1336 case 0xd8ff: { /* JPEG */
1337 #ifdef HAVE_JPEGLIB_H
1338 struct jpeg_decompress_struct jd;
1339 struct jpeg_error_mgr jerr;
1342 JSAMPROW samprow,oldsamprow;
1343 BITMAPINFOHEADER bmi;
1346 struct jpeg_source_mgr xjsm;
1350 if(!libjpeg_handle) {
1351 if(!load_libjpeg()) {
1352 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1357 /* This is basically so we can use in-memory data for jpeg decompression.
1358 * We need to have all the functions.
1360 xjsm.next_input_byte = xbuf;
1361 xjsm.bytes_in_buffer = xread;
1362 xjsm.init_source = _jpeg_init_source;
1363 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1364 xjsm.skip_input_data = _jpeg_skip_input_data;
1365 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1366 xjsm.term_source = _jpeg_term_source;
1368 jd.err = pjpeg_std_error(&jerr);
1369 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1370 * jpeg_create_decompress(&jd); */
1371 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1373 ret=pjpeg_read_header(&jd,TRUE);
1374 jd.out_color_space = JCS_RGB;
1375 pjpeg_start_decompress(&jd);
1376 if (ret != JPEG_HEADER_OK) {
1377 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1378 HeapFree(GetProcessHeap(),0,xbuf);
1382 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1383 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1384 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1387 oldsamprow = samprow;
1388 while ( jd.output_scanline<jd.output_height ) {
1389 x = pjpeg_read_scanlines(&jd,&samprow,1);
1391 FIXME("failed to read current scanline?\n");
1394 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1395 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1396 *(bits++) = *(samprow+2);
1397 *(bits++) = *(samprow+1);
1398 *(bits++) = *(samprow);
1400 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1401 samprow = oldsamprow;
1405 bmi.biSize = sizeof(bmi);
1406 bmi.biWidth = jd.output_width;
1407 bmi.biHeight = -jd.output_height;
1409 bmi.biBitCount = jd.output_components<<3;
1410 bmi.biCompression = BI_RGB;
1411 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1412 bmi.biXPelsPerMeter = 0;
1413 bmi.biYPelsPerMeter = 0;
1415 bmi.biClrImportant = 0;
1417 HeapFree(GetProcessHeap(),0,samprow);
1418 pjpeg_finish_decompress(&jd);
1419 pjpeg_destroy_decompress(&jd);
1421 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1430 This->desc.picType = PICTYPE_BITMAP;
1431 OLEPictureImpl_SetBitmap(This);
1433 HeapFree(GetProcessHeap(),0,bits);
1435 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1440 case 0x4d42: { /* Bitmap */
1441 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1442 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1445 /* Does not matter whether this is a coreheader or not, we only use
1446 * components which are in both
1449 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1453 xbuf+bfh->bfOffBits,
1458 This->desc.picType = PICTYPE_BITMAP;
1459 OLEPictureImpl_SetBitmap(This);
1463 case 0x0000: { /* ICON , first word is dwReserved */
1465 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1470 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1471 FIXME("icon.idType=%d\n",cifd->idType);
1472 FIXME("icon.idCount=%d\n",cifd->idCount);
1474 for (i=0;i<cifd->idCount;i++) {
1475 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1476 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1477 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1478 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1479 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1480 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1481 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1482 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1486 /* If we have more than one icon, try to find the best.
1487 * this currently means '32 pixel wide'.
1489 if (cifd->idCount!=1) {
1490 for (i=0;i<cifd->idCount;i++) {
1491 if (cifd->idEntries[i].bWidth == 32)
1494 if (i==cifd->idCount) i=0;
1497 hicon = CreateIconFromResourceEx(
1498 xbuf+cifd->idEntries[i].dwDIBOffset,
1499 cifd->idEntries[i].dwDIBSize,
1502 cifd->idEntries[i].bWidth,
1503 cifd->idEntries[i].bHeight,
1507 FIXME("CreateIcon failed.\n");
1510 This->desc.picType = PICTYPE_ICON;
1511 This->desc.u.icon.hicon = hicon;
1512 This->origWidth = cifd->idEntries[i].bWidth;
1513 This->origHeight = cifd->idEntries[i].bHeight;
1514 hdcRef = CreateCompatibleDC(0);
1515 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1516 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1525 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1527 for (i=0;i<xread+8;i++) {
1528 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1529 else MESSAGE("%02x ",xbuf[i-8]);
1530 if (i % 10 == 9) MESSAGE("\n");
1536 This->bIsDirty = FALSE;
1538 /* FIXME: this notify is not really documented */
1540 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1544 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength);
1545 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength);
1546 static HRESULT WINAPI OLEPictureImpl_Save(
1547 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1549 HRESULT hResult = E_NOTIMPL;
1551 unsigned int iDataSize;
1553 int iSerializeResult = 0;
1555 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1557 switch (This->desc.picType) {
1559 if (This->bIsDirty) {
1560 if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1561 if (This->loadtime_magic != 0xdeadbeef) {
1564 header[0] = This->loadtime_magic;
1565 header[1] = iDataSize;
1566 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1568 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1570 HeapFree(GetProcessHeap(), 0, This->data);
1571 This->data = pIconData;
1572 This->datalen = iDataSize;
1575 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
1579 if (This->loadtime_magic != 0xdeadbeef) {
1582 header[0] = This->loadtime_magic;
1583 header[1] = This->datalen;
1584 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1586 IStream_Write(pStm, This->data, This->datalen, &dummy);
1590 case PICTYPE_BITMAP:
1591 if (This->bIsDirty) {
1592 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1594 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1597 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1600 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1603 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1606 if (iSerializeResult) {
1608 if (This->loadtime_magic != 0xdeadbeef) {
1613 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1614 header[1] = iDataSize;
1615 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1617 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1619 HeapFree(GetProcessHeap(), 0, This->data);
1620 This->data = pIconData;
1621 This->datalen = iDataSize;
1626 if (This->loadtime_magic != 0xdeadbeef) {
1631 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1632 header[1] = This->datalen;
1633 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1635 IStream_Write(pStm, This->data, This->datalen, &dummy);
1639 case PICTYPE_METAFILE:
1640 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1642 case PICTYPE_ENHMETAFILE:
1643 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1646 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1649 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1653 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1657 BITMAPINFO * pInfoBitmap;
1658 int iNumPaletteEntries;
1659 unsigned char * pPixelData;
1660 BITMAPFILEHEADER * pFileHeader;
1661 BITMAPINFO * pInfoHeader;
1663 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1664 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1666 /* Find out bitmap size and padded length */
1668 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1669 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1671 /* Fetch bitmap palette & pixel data */
1673 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1674 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1676 /* Calculate the total length required for the BMP data */
1677 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1678 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1679 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1681 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1682 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1684 iNumPaletteEntries = 0;
1687 sizeof(BITMAPFILEHEADER) +
1688 sizeof(BITMAPINFOHEADER) +
1689 iNumPaletteEntries * sizeof(RGBQUAD) +
1690 pInfoBitmap->bmiHeader.biSizeImage;
1691 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1693 /* Fill the BITMAPFILEHEADER */
1694 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1695 pFileHeader->bfType = 0x4d42;
1696 pFileHeader->bfSize = *pLength;
1697 pFileHeader->bfOffBits =
1698 sizeof(BITMAPFILEHEADER) +
1699 sizeof(BITMAPINFOHEADER) +
1700 iNumPaletteEntries * sizeof(RGBQUAD);
1702 /* Fill the BITMAPINFOHEADER and the palette data */
1703 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1704 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1706 (unsigned char *)(*ppBuffer) +
1707 sizeof(BITMAPFILEHEADER) +
1708 sizeof(BITMAPINFOHEADER) +
1709 iNumPaletteEntries * sizeof(RGBQUAD),
1710 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1713 HeapFree(GetProcessHeap(), 0, pPixelData);
1714 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1718 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1723 *ppBuffer = NULL; *pLength = 0;
1724 if (GetIconInfo(hIcon, &infoIcon)) {
1726 BITMAPINFO * pInfoBitmap;
1727 unsigned char * pIconData = NULL;
1728 unsigned int iDataSize = 0;
1730 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1732 /* Find out icon size */
1734 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1735 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1737 /* Auxiliary pointers */
1738 CURSORICONFILEDIR * pIconDir;
1739 CURSORICONFILEDIRENTRY * pIconEntry;
1740 BITMAPINFOHEADER * pIconBitmapHeader;
1741 unsigned int iOffsetPalette;
1742 unsigned int iOffsetColorData;
1743 unsigned int iOffsetMaskData;
1745 unsigned int iLengthScanLineColor;
1746 unsigned int iLengthScanLineMask;
1747 unsigned int iNumEntriesPalette;
1749 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1750 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1752 FIXME("DEBUG: bitmap size is %d x %d\n",
1753 pInfoBitmap->bmiHeader.biWidth,
1754 pInfoBitmap->bmiHeader.biHeight);
1755 FIXME("DEBUG: bitmap bpp is %d\n",
1756 pInfoBitmap->bmiHeader.biBitCount);
1757 FIXME("DEBUG: bitmap nplanes is %d\n",
1758 pInfoBitmap->bmiHeader.biPlanes);
1759 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1760 pInfoBitmap->bmiHeader.biSizeImage);
1762 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1763 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1764 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1766 /* Fill out the CURSORICONFILEDIR */
1767 pIconDir = (CURSORICONFILEDIR *)pIconData;
1768 pIconDir->idType = 1;
1769 pIconDir->idCount = 1;
1771 /* Fill out the CURSORICONFILEDIRENTRY */
1772 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1773 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1774 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1775 pIconEntry->bColorCount =
1776 (pInfoBitmap->bmiHeader.biBitCount < 8)
1777 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1779 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1780 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1781 pIconEntry->dwDIBSize = 0;
1782 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1784 /* Fill out the BITMAPINFOHEADER */
1785 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1786 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1788 /* Find out whether a palette exists for the bitmap */
1789 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1790 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1791 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1792 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1793 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1794 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1795 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1796 iNumEntriesPalette = 3;
1797 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1798 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1800 iNumEntriesPalette = 0;
1803 /* Add bitmap size and header size to icon data size. */
1804 iOffsetPalette = iDataSize;
1805 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1806 iOffsetColorData = iDataSize;
1807 iDataSize += pIconBitmapHeader->biSizeImage;
1808 iOffsetMaskData = iDataSize;
1809 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1810 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1811 pIconBitmapHeader->biHeight *= 2;
1812 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1813 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1814 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1815 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1817 /* Get the actual bitmap data from the icon bitmap */
1818 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1819 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1820 if (iNumEntriesPalette > 0) {
1821 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1822 iNumEntriesPalette * sizeof(RGBQUAD));
1825 /* Reset all values so that GetDIBits call succeeds */
1826 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1827 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1828 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1830 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1831 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1832 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1834 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1839 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1840 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1842 /* Write out everything produced so far to the stream */
1843 *ppBuffer = pIconData; *pLength = iDataSize;
1847 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1852 Remarks (from MSDN entry on GetIconInfo):
1854 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1855 members of ICONINFO. The calling application must manage
1856 these bitmaps and delete them when they are no longer
1859 if (hDC) ReleaseDC(0, hDC);
1860 DeleteObject(infoIcon.hbmMask);
1861 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1862 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1864 printf("ERROR: Unable to get icon information (error %lu)\n",
1870 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1871 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1873 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1874 FIXME("(%p,%p),stub!\n",This,pcbSize);
1878 /************************************************************************
1881 /************************************************************************
1882 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1884 * See Windows documentation for more details on IUnknown methods.
1886 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1891 OLEPictureImpl *This = impl_from_IDispatch(iface);
1893 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1896 /************************************************************************
1897 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1899 * See Windows documentation for more details on IUnknown methods.
1901 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1904 OLEPictureImpl *This = impl_from_IDispatch(iface);
1906 return IPicture_AddRef((IPicture *)This);
1909 /************************************************************************
1910 * OLEPictureImpl_IDispatch_Release (IUnknown)
1912 * See Windows documentation for more details on IUnknown methods.
1914 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1917 OLEPictureImpl *This = impl_from_IDispatch(iface);
1919 return IPicture_Release((IPicture *)This);
1922 /************************************************************************
1923 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1925 * See Windows documentation for more details on IDispatch methods.
1927 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1929 unsigned int* pctinfo)
1936 /************************************************************************
1937 * OLEPictureImpl_GetTypeInfo (IDispatch)
1939 * See Windows documentation for more details on IDispatch methods.
1941 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1945 ITypeInfo** ppTInfo)
1952 /************************************************************************
1953 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1955 * See Windows documentation for more details on IDispatch methods.
1957 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1960 LPOLESTR* rgszNames,
1970 /************************************************************************
1971 * OLEPictureImpl_Invoke (IDispatch)
1973 * See Windows documentation for more details on IDispatch methods.
1975 static HRESULT WINAPI OLEPictureImpl_Invoke(
1977 DISPID dispIdMember,
1981 DISPPARAMS* pDispParams,
1982 VARIANT* pVarResult,
1983 EXCEPINFO* pExepInfo,
1986 FIXME("(dispid: %ld):Stub\n",dispIdMember);
1988 VariantInit(pVarResult);
1989 V_VT(pVarResult) = VT_BOOL;
1990 V_BOOL(pVarResult) = FALSE;
1995 static const IPictureVtbl OLEPictureImpl_VTable =
1997 OLEPictureImpl_QueryInterface,
1998 OLEPictureImpl_AddRef,
1999 OLEPictureImpl_Release,
2000 OLEPictureImpl_get_Handle,
2001 OLEPictureImpl_get_hPal,
2002 OLEPictureImpl_get_Type,
2003 OLEPictureImpl_get_Width,
2004 OLEPictureImpl_get_Height,
2005 OLEPictureImpl_Render,
2006 OLEPictureImpl_set_hPal,
2007 OLEPictureImpl_get_CurDC,
2008 OLEPictureImpl_SelectPicture,
2009 OLEPictureImpl_get_KeepOriginalFormat,
2010 OLEPictureImpl_put_KeepOriginalFormat,
2011 OLEPictureImpl_PictureChanged,
2012 OLEPictureImpl_SaveAsFile,
2013 OLEPictureImpl_get_Attributes
2016 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2018 OLEPictureImpl_IDispatch_QueryInterface,
2019 OLEPictureImpl_IDispatch_AddRef,
2020 OLEPictureImpl_IDispatch_Release,
2021 OLEPictureImpl_GetTypeInfoCount,
2022 OLEPictureImpl_GetTypeInfo,
2023 OLEPictureImpl_GetIDsOfNames,
2024 OLEPictureImpl_Invoke
2027 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2029 OLEPictureImpl_IPersistStream_QueryInterface,
2030 OLEPictureImpl_IPersistStream_AddRef,
2031 OLEPictureImpl_IPersistStream_Release,
2032 OLEPictureImpl_GetClassID,
2033 OLEPictureImpl_IsDirty,
2034 OLEPictureImpl_Load,
2035 OLEPictureImpl_Save,
2036 OLEPictureImpl_GetSizeMax
2039 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2041 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2042 OLEPictureImpl_IConnectionPointContainer_AddRef,
2043 OLEPictureImpl_IConnectionPointContainer_Release,
2044 OLEPictureImpl_EnumConnectionPoints,
2045 OLEPictureImpl_FindConnectionPoint
2048 /***********************************************************************
2049 * OleCreatePictureIndirect (OLEAUT32.419)
2051 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2052 BOOL fOwn, LPVOID *ppvObj )
2054 OLEPictureImpl* newPict = NULL;
2057 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2068 * Try to construct a new instance of the class.
2070 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2072 if (newPict == NULL)
2073 return E_OUTOFMEMORY;
2076 * Make sure it supports the interface required by the caller.
2078 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2081 * Release the reference obtained in the constructor. If
2082 * the QueryInterface was unsuccessful, it will free the class.
2084 IPicture_Release((IPicture*)newPict);
2090 /***********************************************************************
2091 * OleLoadPicture (OLEAUT32.418)
2093 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2094 REFIID riid, LPVOID *ppvObj )
2100 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2101 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2103 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2106 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2108 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2109 IPicture_Release(newpic);
2113 IPersistStream_Load(ps,lpstream);
2114 IPersistStream_Release(ps);
2115 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2117 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2118 IPicture_Release(newpic);
2122 /***********************************************************************
2123 * OleLoadPictureEx (OLEAUT32.401)
2125 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2126 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2132 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2133 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2135 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2138 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2140 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2141 IPicture_Release(newpic);
2145 IPersistStream_Load(ps,lpstream);
2146 IPersistStream_Release(ps);
2147 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2149 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2150 IPicture_Release(newpic);
2154 /***********************************************************************
2155 * OleLoadPicturePath (OLEAUT32.424)
2157 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2158 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2161 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2165 HGLOBAL hGlobal = NULL;
2166 DWORD dwBytesRead = 0;
2169 IPersistStream *pStream;
2172 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2173 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2174 debugstr_guid(riid), ppvRet);
2176 if (!ppvRet) return E_POINTER;
2178 if (strncmpW(szURLorPath, file, 7) == 0) {
2181 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2183 if (hFile == INVALID_HANDLE_VALUE)
2184 return E_UNEXPECTED;
2186 dwFileSize = GetFileSize(hFile, NULL);
2187 if (dwFileSize != INVALID_FILE_SIZE )
2189 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2192 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2195 GlobalFree(hGlobal);
2203 return E_UNEXPECTED;
2205 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2208 GlobalFree(hGlobal);
2215 hRes = CreateBindCtx(0, &pbc);
2216 if (SUCCEEDED(hRes))
2218 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2219 if (SUCCEEDED(hRes))
2221 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2222 IMoniker_Release(pmnk);
2224 IBindCtx_Release(pbc);
2230 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2231 &IID_IPicture, (LPVOID*)&ipicture);
2233 IStream_Release(stream);
2237 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2239 IStream_Release(stream);
2240 IPicture_Release(ipicture);
2244 hRes = IPersistStream_Load(pStream, stream);
2245 IPersistStream_Release(pStream);
2246 IStream_Release(stream);
2249 IPicture_Release(ipicture);
2253 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2255 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2257 IPicture_Release(ipicture);
2261 /*******************************************************************************
2262 * StdPic ClassFactory
2266 /* IUnknown fields */
2267 const IClassFactoryVtbl *lpVtbl;
2269 } IClassFactoryImpl;
2271 static HRESULT WINAPI
2272 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2273 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2275 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2276 return E_NOINTERFACE;
2280 SPCF_AddRef(LPCLASSFACTORY iface) {
2281 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2282 return InterlockedIncrement(&This->ref);
2285 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2286 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2287 /* static class, won't be freed */
2288 return InterlockedDecrement(&This->ref);
2291 static HRESULT WINAPI SPCF_CreateInstance(
2292 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2294 /* Creates an uninitialized picture */
2295 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2299 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2300 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2301 FIXME("(%p)->(%d),stub!\n",This,dolock);
2305 static const IClassFactoryVtbl SPCF_Vtbl = {
2306 SPCF_QueryInterface,
2309 SPCF_CreateInstance,
2312 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2314 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }