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 newObject->pCP = NULL;
283 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
286 HeapFree(GetProcessHeap(), 0, newObject);
291 * Start with one reference count. The caller of this function
292 * must release the interface pointer when it is done.
295 newObject->hDCCur = 0;
297 newObject->fOwn = fOwn;
299 /* dunno about original value */
300 newObject->keepOrigFormat = TRUE;
302 newObject->hbmMask = NULL;
303 newObject->hbmXor = NULL;
304 newObject->loadtime_magic = 0xdeadbeef;
305 newObject->loadtime_format = 0;
306 newObject->bIsDirty = FALSE;
309 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
310 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
312 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
315 switch(pictDesc->picType) {
317 OLEPictureImpl_SetBitmap(newObject);
320 case PICTYPE_METAFILE:
321 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
322 newObject->himetricWidth = pictDesc->u.wmf.xExt;
323 newObject->himetricHeight = pictDesc->u.wmf.yExt;
327 /* not sure what to do here */
328 newObject->himetricWidth = newObject->himetricHeight = 0;
332 OLEPictureImpl_SetIcon(newObject);
334 case PICTYPE_ENHMETAFILE:
336 FIXME("Unsupported type %d\n", pictDesc->picType);
337 newObject->himetricWidth = newObject->himetricHeight = 0;
341 newObject->desc.picType = PICTYPE_UNINITIALIZED;
344 TRACE("returning %p\n", newObject);
348 /************************************************************************
349 * OLEPictureImpl_Destroy
351 * This method is called by the Release method when the reference
352 * count goes down to 0. It will free all resources used by
354 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
356 TRACE("(%p)\n", Obj);
359 IConnectionPoint_Release(Obj->pCP);
361 if(Obj->fOwn) { /* We need to destroy the picture */
362 switch(Obj->desc.picType) {
364 DeleteObject(Obj->desc.u.bmp.hbitmap);
365 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
366 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
368 case PICTYPE_METAFILE:
369 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
372 DestroyIcon(Obj->desc.u.icon.hicon);
374 case PICTYPE_ENHMETAFILE:
375 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
381 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
385 HeapFree(GetProcessHeap(), 0, Obj->data);
386 HeapFree(GetProcessHeap(), 0, Obj);
390 /************************************************************************
391 * OLEPictureImpl_AddRef (IUnknown)
393 * See Windows documentation for more details on IUnknown methods.
395 static ULONG WINAPI OLEPictureImpl_AddRef(
398 OLEPictureImpl *This = (OLEPictureImpl *)iface;
399 ULONG refCount = InterlockedIncrement(&This->ref);
401 TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1);
406 /************************************************************************
407 * OLEPictureImpl_Release (IUnknown)
409 * See Windows documentation for more details on IUnknown methods.
411 static ULONG WINAPI OLEPictureImpl_Release(
414 OLEPictureImpl *This = (OLEPictureImpl *)iface;
415 ULONG refCount = InterlockedDecrement(&This->ref);
417 TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1);
420 * If the reference count goes down to 0, perform suicide.
422 if (!refCount) OLEPictureImpl_Destroy(This);
427 /************************************************************************
428 * OLEPictureImpl_QueryInterface (IUnknown)
430 * See Windows documentation for more details on IUnknown methods.
432 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
437 OLEPictureImpl *This = (OLEPictureImpl *)iface;
438 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
441 * Perform a sanity check on the parameters.
443 if ( (This==0) || (ppvObject==0) )
447 * Initialize the return parameter.
452 * Compare the riid with the interface IDs implemented by this object.
454 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
456 *ppvObject = (IPicture*)This;
458 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
460 *ppvObject = (IPicture*)This;
462 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
464 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
466 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
468 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
470 else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
472 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
474 else if (memcmp(&IID_IConnectionPointContainer, riid, sizeof(IID_IConnectionPointContainer)) == 0)
476 *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
479 * Check that we obtained an interface.
483 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
484 return E_NOINTERFACE;
488 * Query Interface always increases the reference count by one when it is
491 OLEPictureImpl_AddRef((IPicture*)This);
496 /***********************************************************************
497 * OLEPicture_SendNotify (internal)
499 * Sends notification messages of changed properties to any interested
502 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
504 IEnumConnections *pEnum;
507 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
509 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
510 IPropertyNotifySink *sink;
512 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
513 IPropertyNotifySink_OnChanged(sink, dispID);
514 IPropertyNotifySink_Release(sink);
515 IUnknown_Release(CD.pUnk);
517 IEnumConnections_Release(pEnum);
521 /************************************************************************
522 * OLEPictureImpl_get_Handle
524 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
527 OLEPictureImpl *This = (OLEPictureImpl *)iface;
528 TRACE("(%p)->(%p)\n", This, phandle);
529 switch(This->desc.picType) {
534 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
536 case PICTYPE_METAFILE:
537 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
540 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
542 case PICTYPE_ENHMETAFILE:
543 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
546 FIXME("Unimplemented type %d\n", This->desc.picType);
549 TRACE("returning handle %08x\n", *phandle);
553 /************************************************************************
554 * OLEPictureImpl_get_hPal
556 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
559 OLEPictureImpl *This = (OLEPictureImpl *)iface;
561 TRACE("(%p)->(%p)\n", This, phandle);
566 switch (This->desc.picType) {
567 case PICTYPE_UNINITIALIZED:
573 *phandle = (OLE_HANDLE)This->desc.u.bmp.hpal;
577 case PICTYPE_METAFILE:
578 case PICTYPE_ENHMETAFILE:
580 FIXME("unimplemented for type %d. Returning 0 palette.\n",
586 TRACE("returning 0x%08lx, palette handle %08x\n", hres, *phandle);
590 /************************************************************************
591 * OLEPictureImpl_get_Type
593 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
596 OLEPictureImpl *This = (OLEPictureImpl *)iface;
597 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
598 *ptype = This->desc.picType;
602 /************************************************************************
603 * OLEPictureImpl_get_Width
605 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
606 OLE_XSIZE_HIMETRIC *pwidth)
608 OLEPictureImpl *This = (OLEPictureImpl *)iface;
609 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
610 *pwidth = This->himetricWidth;
614 /************************************************************************
615 * OLEPictureImpl_get_Height
617 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
618 OLE_YSIZE_HIMETRIC *pheight)
620 OLEPictureImpl *This = (OLEPictureImpl *)iface;
621 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
622 *pheight = This->himetricHeight;
626 /************************************************************************
627 * OLEPictureImpl_Render
629 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
630 LONG x, LONG y, LONG cx, LONG cy,
631 OLE_XPOS_HIMETRIC xSrc,
632 OLE_YPOS_HIMETRIC ySrc,
633 OLE_XSIZE_HIMETRIC cxSrc,
634 OLE_YSIZE_HIMETRIC cySrc,
637 OLEPictureImpl *This = (OLEPictureImpl *)iface;
638 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
639 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
641 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
642 prcWBounds->right, prcWBounds->bottom);
645 * While the documentation suggests this to be here (or after rendering?)
646 * it does cause an endless recursion in my sample app. -MM 20010804
647 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
650 switch(This->desc.picType) {
656 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
657 NB y-axis gets flipped */
659 hdcBmp = CreateCompatibleDC(0);
660 SetMapMode(hdcBmp, MM_ANISOTROPIC);
661 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
662 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
663 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
664 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
667 HDC hdcMask = CreateCompatibleDC(0);
668 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
670 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
672 SetMapMode(hdcMask, MM_ANISOTROPIC);
673 SetWindowOrgEx(hdcMask, 0, 0, NULL);
674 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
675 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
676 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
678 SetBkColor(hdc, RGB(255, 255, 255));
679 SetTextColor(hdc, RGB(0, 0, 0));
680 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
681 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
683 SelectObject(hdcMask, hOldbm);
686 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
687 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
690 SelectObject(hdcBmp, hbmpOld);
695 FIXME("Not quite correct implementation of rendering icons...\n");
696 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
699 case PICTYPE_METAFILE:
700 case PICTYPE_ENHMETAFILE:
702 FIXME("type %d not implemented\n", This->desc.picType);
708 /************************************************************************
709 * OLEPictureImpl_set_hPal
711 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
714 OLEPictureImpl *This = (OLEPictureImpl *)iface;
715 FIXME("(%p)->(%08x): stub\n", This, hpal);
716 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
720 /************************************************************************
721 * OLEPictureImpl_get_CurDC
723 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
726 OLEPictureImpl *This = (OLEPictureImpl *)iface;
727 TRACE("(%p), returning %p\n", This, This->hDCCur);
728 if (phdc) *phdc = This->hDCCur;
732 /************************************************************************
733 * OLEPictureImpl_SelectPicture
735 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
738 OLE_HANDLE *phbmpOut)
740 OLEPictureImpl *This = (OLEPictureImpl *)iface;
741 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
742 if (This->desc.picType == PICTYPE_BITMAP) {
743 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
746 *phdcOut = This->hDCCur;
747 This->hDCCur = hdcIn;
749 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
752 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
757 /************************************************************************
758 * OLEPictureImpl_get_KeepOriginalFormat
760 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
763 OLEPictureImpl *This = (OLEPictureImpl *)iface;
764 TRACE("(%p)->(%p)\n", This, pfKeep);
767 *pfKeep = This->keepOrigFormat;
771 /************************************************************************
772 * OLEPictureImpl_put_KeepOriginalFormat
774 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
777 OLEPictureImpl *This = (OLEPictureImpl *)iface;
778 TRACE("(%p)->(%d)\n", This, keep);
779 This->keepOrigFormat = keep;
780 /* FIXME: what DISPID notification here? */
784 /************************************************************************
785 * OLEPictureImpl_PictureChanged
787 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
789 OLEPictureImpl *This = (OLEPictureImpl *)iface;
790 TRACE("(%p)->()\n", This);
791 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
792 This->bIsDirty = TRUE;
796 /************************************************************************
797 * OLEPictureImpl_SaveAsFile
799 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
804 OLEPictureImpl *This = (OLEPictureImpl *)iface;
805 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
806 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
809 /************************************************************************
810 * OLEPictureImpl_get_Attributes
812 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
815 OLEPictureImpl *This = (OLEPictureImpl *)iface;
816 TRACE("(%p)->(%p).\n", This, pdwAttr);
818 switch (This->desc.picType) {
819 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
820 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
821 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
822 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
828 /************************************************************************
829 * IConnectionPointContainer
831 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
832 IConnectionPointContainer* iface,
836 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
838 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
841 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
842 IConnectionPointContainer* iface)
844 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
846 return IPicture_AddRef((IPicture *)This);
849 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
850 IConnectionPointContainer* iface)
852 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
854 return IPicture_Release((IPicture *)This);
857 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
858 IConnectionPointContainer* iface,
859 IEnumConnectionPoints** ppEnum)
861 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
863 FIXME("(%p,%p), stub!\n",This,ppEnum);
867 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
868 IConnectionPointContainer* iface,
870 IConnectionPoint **ppCP)
872 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
873 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
877 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
878 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
879 FIXME("no connection point for %s\n",debugstr_guid(riid));
880 return CONNECT_E_NOCONNECTION;
884 /************************************************************************
888 /************************************************************************
889 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
891 * See Windows documentation for more details on IUnknown methods.
893 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
894 IPersistStream* iface,
898 OLEPictureImpl *This = impl_from_IPersistStream(iface);
900 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
903 /************************************************************************
904 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
906 * See Windows documentation for more details on IUnknown methods.
908 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
909 IPersistStream* iface)
911 OLEPictureImpl *This = impl_from_IPersistStream(iface);
913 return IPicture_AddRef((IPicture *)This);
916 /************************************************************************
917 * OLEPictureImpl_IPersistStream_Release (IUnknown)
919 * See Windows documentation for more details on IUnknown methods.
921 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
922 IPersistStream* iface)
924 OLEPictureImpl *This = impl_from_IPersistStream(iface);
926 return IPicture_Release((IPicture *)This);
929 /************************************************************************
930 * OLEPictureImpl_IPersistStream_GetClassID
932 static HRESULT WINAPI OLEPictureImpl_GetClassID(
933 IPersistStream* iface,CLSID* pClassID)
935 OLEPictureImpl *This = impl_from_IPersistStream(iface);
936 FIXME("(%p),stub!\n",This);
940 /************************************************************************
941 * OLEPictureImpl_IPersistStream_IsDirty
943 static HRESULT WINAPI OLEPictureImpl_IsDirty(
944 IPersistStream* iface)
946 OLEPictureImpl *This = impl_from_IPersistStream(iface);
947 FIXME("(%p),stub!\n",This);
951 #ifdef HAVE_JPEGLIB_H
953 static void *libjpeg_handle;
954 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
955 MAKE_FUNCPTR(jpeg_std_error);
956 MAKE_FUNCPTR(jpeg_CreateDecompress);
957 MAKE_FUNCPTR(jpeg_read_header);
958 MAKE_FUNCPTR(jpeg_start_decompress);
959 MAKE_FUNCPTR(jpeg_read_scanlines);
960 MAKE_FUNCPTR(jpeg_finish_decompress);
961 MAKE_FUNCPTR(jpeg_destroy_decompress);
964 static void *load_libjpeg(void)
966 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
968 #define LOAD_FUNCPTR(f) \
969 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
970 libjpeg_handle = NULL; \
974 LOAD_FUNCPTR(jpeg_std_error);
975 LOAD_FUNCPTR(jpeg_CreateDecompress);
976 LOAD_FUNCPTR(jpeg_read_header);
977 LOAD_FUNCPTR(jpeg_start_decompress);
978 LOAD_FUNCPTR(jpeg_read_scanlines);
979 LOAD_FUNCPTR(jpeg_finish_decompress);
980 LOAD_FUNCPTR(jpeg_destroy_decompress);
983 return libjpeg_handle;
986 /* for the jpeg decompressor source manager. */
987 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
989 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
990 ERR("(), should not get here.\n");
994 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
995 TRACE("Skipping %ld bytes...\n", num_bytes);
996 cinfo->src->next_input_byte += num_bytes;
997 cinfo->src->bytes_in_buffer -= num_bytes;
1000 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
1001 ERR("(desired=%d), should not get here.\n",desired);
1004 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
1005 #endif /* HAVE_JPEGLIB_H */
1007 #ifdef HAVE_GIF_LIB_H
1009 static void *libungif_handle;
1010 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
1011 MAKE_FUNCPTR(DGifOpen);
1012 MAKE_FUNCPTR(DGifSlurp);
1013 MAKE_FUNCPTR(DGifCloseFile);
1017 unsigned char *data;
1018 unsigned int curoff;
1022 static void *load_libungif(void)
1024 if(((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) ||
1025 ((libungif_handle = wine_dlopen(SONAME_LIBGIF , RTLD_NOW, NULL, 0)) != NULL)
1028 #define LOAD_FUNCPTR(f) \
1029 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
1030 libungif_handle = NULL; \
1034 LOAD_FUNCPTR(DGifOpen);
1035 LOAD_FUNCPTR(DGifSlurp);
1036 LOAD_FUNCPTR(DGifCloseFile);
1039 return libungif_handle;
1042 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
1043 struct gifdata *gd = (struct gifdata*)gif->UserData;
1045 if (len+gd->curoff > gd->len) {
1046 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
1047 len = gd->len - gd->curoff;
1049 memcpy(data, gd->data+gd->curoff, len);
1054 #endif /* HAVE_GIF_LIB_H */
1057 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1059 #ifdef HAVE_GIF_LIB_H
1069 int transparent = -1;
1073 if(!libungif_handle) {
1074 if(!load_libungif()) {
1075 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF);
1083 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1084 ret = pDGifSlurp(gif);
1085 if (ret == GIF_ERROR) {
1086 FIXME("Failed reading GIF using libgif.\n");
1089 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1090 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1091 TRACE("imgcnt %d\n", gif->ImageCount);
1092 if (gif->ImageCount<1) {
1093 FIXME("GIF stream does not have images inside?\n");
1096 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1097 gif->Image.Width, gif->Image.Height,
1098 gif->Image.Left, gif->Image.Top,
1099 gif->Image.Interlace
1102 padding = (gif->SWidth+3) & ~3;
1103 si = gif->SavedImages+0;
1104 gid = &(si->ImageDesc);
1106 if (!cm) cm = gif->SColorMap;
1107 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1108 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1110 /* look for the transparent color extension */
1111 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1112 eb = si->ExtensionBlocks + i;
1113 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1114 if ((eb->Bytes[0] & 1) == 1) {
1115 transparent = (unsigned char)eb->Bytes[3];
1120 for (i = 0; i < cm->ColorCount; i++) {
1121 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1122 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1123 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1124 if (i == transparent) {
1125 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1126 bmi->bmiColors[i].rgbGreen,
1127 bmi->bmiColors[i].rgbBlue);
1131 /* Map to in picture coordinates */
1132 for (i = 0, j = 0; i < gid->Height; i++) {
1133 if (gif->Image.Interlace) {
1135 bytes + (gid->Top + j) * padding + gid->Left,
1136 si->RasterBits + i * gid->Width,
1139 /* Lower bits of interlaced counter encode current interlace */
1140 if (j & 1) j += 2; /* Currently filling odd rows */
1141 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1142 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1144 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1145 /* End of current interlace, go to next interlace */
1146 if (j & 2) j = 1; /* Next iteration fills odd rows */
1147 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1148 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1152 bytes + (gid->Top + i) * padding + gid->Left,
1153 si->RasterBits + i * gid->Width,
1158 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1159 bmi->bmiHeader.biWidth = gif->SWidth;
1160 bmi->bmiHeader.biHeight = -gif->SHeight;
1161 bmi->bmiHeader.biPlanes = 1;
1162 bmi->bmiHeader.biBitCount = 8;
1163 bmi->bmiHeader.biCompression = BI_RGB;
1164 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1165 bmi->bmiHeader.biXPelsPerMeter = 0;
1166 bmi->bmiHeader.biYPelsPerMeter = 0;
1167 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1168 bmi->bmiHeader.biClrImportant = 0;
1171 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1180 if (transparent > -1) {
1181 /* Create the Mask */
1182 HDC hdc = CreateCompatibleDC(0);
1183 HDC hdcMask = CreateCompatibleDC(0);
1185 HBITMAP hOldbitmapmask;
1187 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1190 This->hbmXor = CreateDIBitmap(
1199 bmi->bmiColors[0].rgbRed = 0;
1200 bmi->bmiColors[0].rgbGreen = 0;
1201 bmi->bmiColors[0].rgbBlue = 0;
1202 bmi->bmiColors[1].rgbRed = 255;
1203 bmi->bmiColors[1].rgbGreen = 255;
1204 bmi->bmiColors[1].rgbBlue = 255;
1206 bmi->bmiHeader.biBitCount = 1;
1207 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1208 bmi->bmiHeader.biClrUsed = 2;
1210 for (i = 0; i < gif->SHeight; i++) {
1211 unsigned char * colorPointer = bytes + padding * i;
1212 unsigned char * monoPointer = bytes + monopadding * i;
1213 for (j = 0; j < gif->SWidth; j++) {
1214 unsigned char pixel = colorPointer[j];
1215 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1216 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1220 hTempMask = CreateDIBitmap(
1230 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1231 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1232 hOldbitmap = SelectObject(hdc, hTempMask);
1233 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1235 SetBkColor(hdc, RGB(255, 255, 255));
1236 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1238 /* We no longer need the original bitmap, so we apply the first
1239 transformation with the mask to speed up the rendering */
1240 SelectObject(hdc, This->hbmXor);
1241 SetBkColor(hdc, RGB(0,0,0));
1242 SetTextColor(hdc, RGB(255,255,255));
1243 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1244 hdcMask, 0, 0, SRCAND);
1246 SelectObject(hdc, hOldbitmap);
1247 SelectObject(hdcMask, hOldbitmapmask);
1250 DeleteObject(hTempMask);
1254 This->desc.picType = PICTYPE_BITMAP;
1255 OLEPictureImpl_SetBitmap(This);
1256 pDGifCloseFile(gif);
1257 HeapFree(GetProcessHeap(),0,bytes);
1260 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1265 static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1267 #ifdef HAVE_JPEGLIB_H
1268 struct jpeg_decompress_struct jd;
1269 struct jpeg_error_mgr jerr;
1272 JSAMPROW samprow,oldsamprow;
1273 BITMAPINFOHEADER bmi;
1276 struct jpeg_source_mgr xjsm;
1280 if(!libjpeg_handle) {
1281 if(!load_libjpeg()) {
1282 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1287 /* This is basically so we can use in-memory data for jpeg decompression.
1288 * We need to have all the functions.
1290 xjsm.next_input_byte = xbuf;
1291 xjsm.bytes_in_buffer = xread;
1292 xjsm.init_source = _jpeg_init_source;
1293 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1294 xjsm.skip_input_data = _jpeg_skip_input_data;
1295 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1296 xjsm.term_source = _jpeg_term_source;
1298 jd.err = pjpeg_std_error(&jerr);
1299 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1300 * jpeg_create_decompress(&jd); */
1301 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1303 ret=pjpeg_read_header(&jd,TRUE);
1304 jd.out_color_space = JCS_RGB;
1305 pjpeg_start_decompress(&jd);
1306 if (ret != JPEG_HEADER_OK) {
1307 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1308 HeapFree(GetProcessHeap(),0,xbuf);
1312 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1313 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1314 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1317 oldsamprow = samprow;
1318 while ( jd.output_scanline<jd.output_height ) {
1319 x = pjpeg_read_scanlines(&jd,&samprow,1);
1321 FIXME("failed to read current scanline?\n");
1324 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1325 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1326 *(bits++) = *(samprow+2);
1327 *(bits++) = *(samprow+1);
1328 *(bits++) = *(samprow);
1330 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1331 samprow = oldsamprow;
1335 bmi.biSize = sizeof(bmi);
1336 bmi.biWidth = jd.output_width;
1337 bmi.biHeight = -jd.output_height;
1339 bmi.biBitCount = jd.output_components<<3;
1340 bmi.biCompression = BI_RGB;
1341 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1342 bmi.biXPelsPerMeter = 0;
1343 bmi.biYPelsPerMeter = 0;
1345 bmi.biClrImportant = 0;
1347 HeapFree(GetProcessHeap(),0,samprow);
1348 pjpeg_finish_decompress(&jd);
1349 pjpeg_destroy_decompress(&jd);
1351 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1360 This->desc.picType = PICTYPE_BITMAP;
1361 OLEPictureImpl_SetBitmap(This);
1362 HeapFree(GetProcessHeap(),0,bits);
1365 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1370 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1372 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1373 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1376 /* Does not matter whether this is a coreheader or not, we only use
1377 * components which are in both
1380 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1384 xbuf+bfh->bfOffBits,
1389 This->desc.picType = PICTYPE_BITMAP;
1390 OLEPictureImpl_SetBitmap(This);
1394 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1397 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1402 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1403 FIXME("icon.idType=%d\n",cifd->idType);
1404 FIXME("icon.idCount=%d\n",cifd->idCount);
1406 for (i=0;i<cifd->idCount;i++) {
1407 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1408 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1409 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1410 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1411 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1412 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1413 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1414 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1418 /* If we have more than one icon, try to find the best.
1419 * this currently means '32 pixel wide'.
1421 if (cifd->idCount!=1) {
1422 for (i=0;i<cifd->idCount;i++) {
1423 if (cifd->idEntries[i].bWidth == 32)
1426 if (i==cifd->idCount) i=0;
1429 hicon = CreateIconFromResourceEx(
1430 xbuf+cifd->idEntries[i].dwDIBOffset,
1431 cifd->idEntries[i].dwDIBSize,
1434 cifd->idEntries[i].bWidth,
1435 cifd->idEntries[i].bHeight,
1439 FIXME("CreateIcon failed.\n");
1442 This->desc.picType = PICTYPE_ICON;
1443 This->desc.u.icon.hicon = hicon;
1444 This->origWidth = cifd->idEntries[i].bWidth;
1445 This->origHeight = cifd->idEntries[i].bHeight;
1446 hdcRef = CreateCompatibleDC(0);
1447 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1448 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1454 /************************************************************************
1455 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1457 * Loads the binary data from the IStream. Starts at current position.
1458 * There appears to be an 2 DWORD header:
1462 * Currently implemented: BITMAP, ICON, JPEG, GIF
1464 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1465 HRESULT hr = E_FAIL;
1466 BOOL headerisdata = FALSE;
1467 BOOL statfailed = FALSE;
1468 ULONG xread, toread;
1473 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1475 TRACE("(%p,%p)\n",This,pStm);
1477 /****************************************************************************************
1478 * Part 1: Load the data
1480 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1481 * out whether we do.
1483 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1484 * compound file. This may explain most, if not all, of the cases of "no
1485 * header", and the header validation should take this into account.
1486 * At least in Visual Basic 6, resource streams, valid headers are
1487 * header[0] == "lt\0\0",
1488 * header[1] == length_of_stream.
1490 * Also handle streams where we do not have a working "Stat" method by
1491 * reading all data until the end of the stream.
1493 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1495 TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr);
1497 /* we will read at least 8 byte ... just right below */
1498 statstg.cbSize.QuadPart = 8;
1500 hr=IStream_Read(pStm,header,8,&xread);
1501 if (hr || xread!=8) {
1502 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
1506 headerisdata = FALSE;
1508 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1511 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1512 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1513 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1514 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1516 ) {/* Incorrect header, assume none. */
1517 headerisdata = TRUE;
1518 toread = statstg.cbSize.QuadPart-8;
1521 FIXME("Unknown stream header magic: %08lx\n", header[0]);
1526 if (statfailed) { /* we don't know the size ... read all we get */
1528 int origsize = sizeinc;
1531 TRACE("Reading all data from stream.\n");
1532 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1534 memcpy (xbuf, &header, 8);
1536 while (xread < origsize) {
1537 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1542 if (!nread || hr) /* done, or error */
1544 if (xread == origsize) {
1545 origsize += sizeinc;
1546 sizeinc = 2*sizeinc; /* exponential increase */
1547 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1551 TRACE("hr in no-stat loader case is %08lx\n", hr);
1552 TRACE("loaded %ld bytes.\n", xread);
1553 This->datalen = xread;
1556 This->datalen = toread+(headerisdata?8:0);
1557 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1560 memcpy (xbuf, &header, 8);
1562 while (xread < This->datalen) {
1564 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1569 if (xread != This->datalen)
1570 FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
1572 if (This->datalen == 0) { /* Marks the "NONE" picture */
1573 This->desc.picType = PICTYPE_NONE;
1578 /****************************************************************************************
1579 * Part 2: Process the loaded data
1582 magic = xbuf[0] + (xbuf[1]<<8);
1584 case 0x4947: /* GIF */
1585 hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
1587 case 0xd8ff: /* JPEG */
1588 hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
1590 case 0x4d42: /* Bitmap */
1591 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1593 case 0x0000: { /* ICON , first word is dwReserved */
1594 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1600 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1602 for (i=0;i<xread+8;i++) {
1603 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1604 else MESSAGE("%02x ",xbuf[i-8]);
1605 if (i % 10 == 9) MESSAGE("\n");
1611 This->bIsDirty = FALSE;
1613 /* FIXME: this notify is not really documented */
1615 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1619 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1623 BITMAPINFO * pInfoBitmap;
1624 int iNumPaletteEntries;
1625 unsigned char * pPixelData;
1626 BITMAPFILEHEADER * pFileHeader;
1627 BITMAPINFO * pInfoHeader;
1629 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1630 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1632 /* Find out bitmap size and padded length */
1634 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1635 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1637 /* Fetch bitmap palette & pixel data */
1639 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1640 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1642 /* Calculate the total length required for the BMP data */
1643 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1644 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1645 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1647 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1648 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1650 iNumPaletteEntries = 0;
1653 sizeof(BITMAPFILEHEADER) +
1654 sizeof(BITMAPINFOHEADER) +
1655 iNumPaletteEntries * sizeof(RGBQUAD) +
1656 pInfoBitmap->bmiHeader.biSizeImage;
1657 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1659 /* Fill the BITMAPFILEHEADER */
1660 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1661 pFileHeader->bfType = 0x4d42;
1662 pFileHeader->bfSize = *pLength;
1663 pFileHeader->bfOffBits =
1664 sizeof(BITMAPFILEHEADER) +
1665 sizeof(BITMAPINFOHEADER) +
1666 iNumPaletteEntries * sizeof(RGBQUAD);
1668 /* Fill the BITMAPINFOHEADER and the palette data */
1669 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1670 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1672 (unsigned char *)(*ppBuffer) +
1673 sizeof(BITMAPFILEHEADER) +
1674 sizeof(BITMAPINFOHEADER) +
1675 iNumPaletteEntries * sizeof(RGBQUAD),
1676 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1679 HeapFree(GetProcessHeap(), 0, pPixelData);
1680 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1684 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1689 *ppBuffer = NULL; *pLength = 0;
1690 if (GetIconInfo(hIcon, &infoIcon)) {
1692 BITMAPINFO * pInfoBitmap;
1693 unsigned char * pIconData = NULL;
1694 unsigned int iDataSize = 0;
1696 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1698 /* Find out icon size */
1700 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1701 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1703 /* Auxiliary pointers */
1704 CURSORICONFILEDIR * pIconDir;
1705 CURSORICONFILEDIRENTRY * pIconEntry;
1706 BITMAPINFOHEADER * pIconBitmapHeader;
1707 unsigned int iOffsetPalette;
1708 unsigned int iOffsetColorData;
1709 unsigned int iOffsetMaskData;
1711 unsigned int iLengthScanLineColor;
1712 unsigned int iLengthScanLineMask;
1713 unsigned int iNumEntriesPalette;
1715 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1716 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1718 FIXME("DEBUG: bitmap size is %d x %d\n",
1719 pInfoBitmap->bmiHeader.biWidth,
1720 pInfoBitmap->bmiHeader.biHeight);
1721 FIXME("DEBUG: bitmap bpp is %d\n",
1722 pInfoBitmap->bmiHeader.biBitCount);
1723 FIXME("DEBUG: bitmap nplanes is %d\n",
1724 pInfoBitmap->bmiHeader.biPlanes);
1725 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1726 pInfoBitmap->bmiHeader.biSizeImage);
1728 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1729 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1730 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1732 /* Fill out the CURSORICONFILEDIR */
1733 pIconDir = (CURSORICONFILEDIR *)pIconData;
1734 pIconDir->idType = 1;
1735 pIconDir->idCount = 1;
1737 /* Fill out the CURSORICONFILEDIRENTRY */
1738 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1739 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1740 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1741 pIconEntry->bColorCount =
1742 (pInfoBitmap->bmiHeader.biBitCount < 8)
1743 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1745 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1746 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1747 pIconEntry->dwDIBSize = 0;
1748 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1750 /* Fill out the BITMAPINFOHEADER */
1751 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1752 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1754 /* Find out whether a palette exists for the bitmap */
1755 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1756 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1757 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1758 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1759 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1760 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1761 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1762 iNumEntriesPalette = 3;
1763 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1764 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1766 iNumEntriesPalette = 0;
1769 /* Add bitmap size and header size to icon data size. */
1770 iOffsetPalette = iDataSize;
1771 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1772 iOffsetColorData = iDataSize;
1773 iDataSize += pIconBitmapHeader->biSizeImage;
1774 iOffsetMaskData = iDataSize;
1775 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1776 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1777 pIconBitmapHeader->biHeight *= 2;
1778 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1779 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1780 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1781 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1783 /* Get the actual bitmap data from the icon bitmap */
1784 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1785 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1786 if (iNumEntriesPalette > 0) {
1787 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1788 iNumEntriesPalette * sizeof(RGBQUAD));
1791 /* Reset all values so that GetDIBits call succeeds */
1792 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1793 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1794 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1796 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1797 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1798 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1800 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1805 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1806 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1808 /* Write out everything produced so far to the stream */
1809 *ppBuffer = pIconData; *pLength = iDataSize;
1813 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1818 Remarks (from MSDN entry on GetIconInfo):
1820 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1821 members of ICONINFO. The calling application must manage
1822 these bitmaps and delete them when they are no longer
1825 if (hDC) ReleaseDC(0, hDC);
1826 DeleteObject(infoIcon.hbmMask);
1827 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1828 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1830 printf("ERROR: Unable to get icon information (error %lu)\n",
1836 static HRESULT WINAPI OLEPictureImpl_Save(
1837 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1839 HRESULT hResult = E_NOTIMPL;
1841 unsigned int iDataSize;
1843 int iSerializeResult = 0;
1845 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1847 switch (This->desc.picType) {
1849 if (This->bIsDirty) {
1850 if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1851 if (This->loadtime_magic != 0xdeadbeef) {
1854 header[0] = This->loadtime_magic;
1855 header[1] = iDataSize;
1856 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1858 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1860 HeapFree(GetProcessHeap(), 0, This->data);
1861 This->data = pIconData;
1862 This->datalen = iDataSize;
1865 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
1869 if (This->loadtime_magic != 0xdeadbeef) {
1872 header[0] = This->loadtime_magic;
1873 header[1] = This->datalen;
1874 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1876 IStream_Write(pStm, This->data, This->datalen, &dummy);
1880 case PICTYPE_BITMAP:
1881 if (This->bIsDirty) {
1882 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1884 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1887 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1890 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1893 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1896 if (iSerializeResult) {
1898 if (This->loadtime_magic != 0xdeadbeef) {
1903 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1904 header[1] = iDataSize;
1905 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1907 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1909 HeapFree(GetProcessHeap(), 0, This->data);
1910 This->data = pIconData;
1911 This->datalen = iDataSize;
1916 if (This->loadtime_magic != 0xdeadbeef) {
1921 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1922 header[1] = This->datalen;
1923 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1925 IStream_Write(pStm, This->data, This->datalen, &dummy);
1929 case PICTYPE_METAFILE:
1930 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1932 case PICTYPE_ENHMETAFILE:
1933 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1936 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1939 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1943 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1944 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1946 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1947 FIXME("(%p,%p),stub!\n",This,pcbSize);
1952 /************************************************************************
1956 /************************************************************************
1957 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1959 * See Windows documentation for more details on IUnknown methods.
1961 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1966 OLEPictureImpl *This = impl_from_IDispatch(iface);
1968 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1971 /************************************************************************
1972 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1974 * See Windows documentation for more details on IUnknown methods.
1976 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1979 OLEPictureImpl *This = impl_from_IDispatch(iface);
1981 return IPicture_AddRef((IPicture *)This);
1984 /************************************************************************
1985 * OLEPictureImpl_IDispatch_Release (IUnknown)
1987 * See Windows documentation for more details on IUnknown methods.
1989 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1992 OLEPictureImpl *This = impl_from_IDispatch(iface);
1994 return IPicture_Release((IPicture *)This);
1997 /************************************************************************
1998 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
2000 * See Windows documentation for more details on IDispatch methods.
2002 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
2004 unsigned int* pctinfo)
2011 /************************************************************************
2012 * OLEPictureImpl_GetTypeInfo (IDispatch)
2014 * See Windows documentation for more details on IDispatch methods.
2016 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
2020 ITypeInfo** ppTInfo)
2027 /************************************************************************
2028 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2030 * See Windows documentation for more details on IDispatch methods.
2032 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2035 LPOLESTR* rgszNames,
2045 /************************************************************************
2046 * OLEPictureImpl_Invoke (IDispatch)
2048 * See Windows documentation for more details on IDispatch methods.
2050 static HRESULT WINAPI OLEPictureImpl_Invoke(
2052 DISPID dispIdMember,
2056 DISPPARAMS* pDispParams,
2057 VARIANT* pVarResult,
2058 EXCEPINFO* pExepInfo,
2061 OLEPictureImpl *This = impl_from_IDispatch(iface);
2062 if (dispIdMember == DISPID_PICT_TYPE)
2064 TRACE("DISPID_PICT_TYPE\n");
2065 if (!(wFlags & INVOKE_PROPERTYGET))
2066 return DISP_E_PARAMNOTFOUND;
2067 if (pDispParams->cArgs != 0)
2068 return DISP_E_BADPARAMCOUNT;
2071 VariantInit(pVarResult);
2072 V_VT(pVarResult) = VT_I2;
2073 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2079 FIXME("(dispid: %ld):Stub\n",dispIdMember);
2081 VariantInit(pVarResult);
2082 V_VT(pVarResult) = VT_BOOL;
2083 V_BOOL(pVarResult) = FALSE;
2089 static const IPictureVtbl OLEPictureImpl_VTable =
2091 OLEPictureImpl_QueryInterface,
2092 OLEPictureImpl_AddRef,
2093 OLEPictureImpl_Release,
2094 OLEPictureImpl_get_Handle,
2095 OLEPictureImpl_get_hPal,
2096 OLEPictureImpl_get_Type,
2097 OLEPictureImpl_get_Width,
2098 OLEPictureImpl_get_Height,
2099 OLEPictureImpl_Render,
2100 OLEPictureImpl_set_hPal,
2101 OLEPictureImpl_get_CurDC,
2102 OLEPictureImpl_SelectPicture,
2103 OLEPictureImpl_get_KeepOriginalFormat,
2104 OLEPictureImpl_put_KeepOriginalFormat,
2105 OLEPictureImpl_PictureChanged,
2106 OLEPictureImpl_SaveAsFile,
2107 OLEPictureImpl_get_Attributes
2110 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2112 OLEPictureImpl_IDispatch_QueryInterface,
2113 OLEPictureImpl_IDispatch_AddRef,
2114 OLEPictureImpl_IDispatch_Release,
2115 OLEPictureImpl_GetTypeInfoCount,
2116 OLEPictureImpl_GetTypeInfo,
2117 OLEPictureImpl_GetIDsOfNames,
2118 OLEPictureImpl_Invoke
2121 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2123 OLEPictureImpl_IPersistStream_QueryInterface,
2124 OLEPictureImpl_IPersistStream_AddRef,
2125 OLEPictureImpl_IPersistStream_Release,
2126 OLEPictureImpl_GetClassID,
2127 OLEPictureImpl_IsDirty,
2128 OLEPictureImpl_Load,
2129 OLEPictureImpl_Save,
2130 OLEPictureImpl_GetSizeMax
2133 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2135 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2136 OLEPictureImpl_IConnectionPointContainer_AddRef,
2137 OLEPictureImpl_IConnectionPointContainer_Release,
2138 OLEPictureImpl_EnumConnectionPoints,
2139 OLEPictureImpl_FindConnectionPoint
2142 /***********************************************************************
2143 * OleCreatePictureIndirect (OLEAUT32.419)
2145 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2146 BOOL fOwn, LPVOID *ppvObj )
2148 OLEPictureImpl* newPict = NULL;
2151 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2162 * Try to construct a new instance of the class.
2164 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2166 if (newPict == NULL)
2167 return E_OUTOFMEMORY;
2170 * Make sure it supports the interface required by the caller.
2172 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2175 * Release the reference obtained in the constructor. If
2176 * the QueryInterface was unsuccessful, it will free the class.
2178 IPicture_Release((IPicture*)newPict);
2184 /***********************************************************************
2185 * OleLoadPicture (OLEAUT32.418)
2187 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2188 REFIID riid, LPVOID *ppvObj )
2194 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2195 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2197 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2200 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2202 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2203 IPicture_Release(newpic);
2207 IPersistStream_Load(ps,lpstream);
2208 IPersistStream_Release(ps);
2209 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2211 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2212 IPicture_Release(newpic);
2216 /***********************************************************************
2217 * OleLoadPictureEx (OLEAUT32.401)
2219 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2220 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2226 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2227 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2229 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2232 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2234 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2235 IPicture_Release(newpic);
2239 IPersistStream_Load(ps,lpstream);
2240 IPersistStream_Release(ps);
2241 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2243 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2244 IPicture_Release(newpic);
2248 /***********************************************************************
2249 * OleLoadPicturePath (OLEAUT32.424)
2251 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2252 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2255 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2259 HGLOBAL hGlobal = NULL;
2260 DWORD dwBytesRead = 0;
2263 IPersistStream *pStream;
2266 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2267 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2268 debugstr_guid(riid), ppvRet);
2270 if (!ppvRet) return E_POINTER;
2272 if (strncmpW(szURLorPath, file, 7) == 0) {
2275 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2277 if (hFile == INVALID_HANDLE_VALUE)
2278 return E_UNEXPECTED;
2280 dwFileSize = GetFileSize(hFile, NULL);
2281 if (dwFileSize != INVALID_FILE_SIZE )
2283 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2286 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2289 GlobalFree(hGlobal);
2297 return E_UNEXPECTED;
2299 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2302 GlobalFree(hGlobal);
2309 hRes = CreateBindCtx(0, &pbc);
2310 if (SUCCEEDED(hRes))
2312 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2313 if (SUCCEEDED(hRes))
2315 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2316 IMoniker_Release(pmnk);
2318 IBindCtx_Release(pbc);
2324 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2325 &IID_IPicture, (LPVOID*)&ipicture);
2327 IStream_Release(stream);
2331 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2333 IStream_Release(stream);
2334 IPicture_Release(ipicture);
2338 hRes = IPersistStream_Load(pStream, stream);
2339 IPersistStream_Release(pStream);
2340 IStream_Release(stream);
2343 IPicture_Release(ipicture);
2347 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2349 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2351 IPicture_Release(ipicture);
2355 /*******************************************************************************
2356 * StdPic ClassFactory
2360 /* IUnknown fields */
2361 const IClassFactoryVtbl *lpVtbl;
2363 } IClassFactoryImpl;
2365 static HRESULT WINAPI
2366 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2367 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2369 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2370 return E_NOINTERFACE;
2374 SPCF_AddRef(LPCLASSFACTORY iface) {
2375 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2376 return InterlockedIncrement(&This->ref);
2379 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2380 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2381 /* static class, won't be freed */
2382 return InterlockedDecrement(&This->ref);
2385 static HRESULT WINAPI SPCF_CreateInstance(
2386 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2388 /* Creates an uninitialized picture */
2389 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2393 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2394 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2395 FIXME("(%p)->(%d),stub!\n",This,dolock);
2399 static const IClassFactoryVtbl SPCF_Vtbl = {
2400 SPCF_QueryInterface,
2403 SPCF_CreateInstance,
2406 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2408 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }