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 (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
455 *ppvObject = (IPicture*)This;
456 else if (IsEqualIID(&IID_IDispatch, riid))
457 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
458 else if (IsEqualIID(&IID_IPictureDisp, riid))
459 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
460 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
461 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
462 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
463 *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
466 * Check that we obtained an interface.
470 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
471 return E_NOINTERFACE;
475 * Query Interface always increases the reference count by one when it is
478 OLEPictureImpl_AddRef((IPicture*)This);
483 /***********************************************************************
484 * OLEPicture_SendNotify (internal)
486 * Sends notification messages of changed properties to any interested
489 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
491 IEnumConnections *pEnum;
494 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
496 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
497 IPropertyNotifySink *sink;
499 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
500 IPropertyNotifySink_OnChanged(sink, dispID);
501 IPropertyNotifySink_Release(sink);
502 IUnknown_Release(CD.pUnk);
504 IEnumConnections_Release(pEnum);
508 /************************************************************************
509 * OLEPictureImpl_get_Handle
511 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
514 OLEPictureImpl *This = (OLEPictureImpl *)iface;
515 TRACE("(%p)->(%p)\n", This, phandle);
516 switch(This->desc.picType) {
521 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
523 case PICTYPE_METAFILE:
524 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
527 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
529 case PICTYPE_ENHMETAFILE:
530 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
533 FIXME("Unimplemented type %d\n", This->desc.picType);
536 TRACE("returning handle %08x\n", *phandle);
540 /************************************************************************
541 * OLEPictureImpl_get_hPal
543 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
546 OLEPictureImpl *This = (OLEPictureImpl *)iface;
548 TRACE("(%p)->(%p)\n", This, phandle);
553 switch (This->desc.picType) {
554 case PICTYPE_UNINITIALIZED:
560 *phandle = (OLE_HANDLE)This->desc.u.bmp.hpal;
564 case PICTYPE_METAFILE:
565 case PICTYPE_ENHMETAFILE:
567 FIXME("unimplemented for type %d. Returning 0 palette.\n",
573 TRACE("returning 0x%08lx, palette handle %08x\n", hres, *phandle);
577 /************************************************************************
578 * OLEPictureImpl_get_Type
580 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
583 OLEPictureImpl *This = (OLEPictureImpl *)iface;
584 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
585 *ptype = This->desc.picType;
589 /************************************************************************
590 * OLEPictureImpl_get_Width
592 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
593 OLE_XSIZE_HIMETRIC *pwidth)
595 OLEPictureImpl *This = (OLEPictureImpl *)iface;
596 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
597 *pwidth = This->himetricWidth;
601 /************************************************************************
602 * OLEPictureImpl_get_Height
604 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
605 OLE_YSIZE_HIMETRIC *pheight)
607 OLEPictureImpl *This = (OLEPictureImpl *)iface;
608 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
609 *pheight = This->himetricHeight;
613 /************************************************************************
614 * OLEPictureImpl_Render
616 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
617 LONG x, LONG y, LONG cx, LONG cy,
618 OLE_XPOS_HIMETRIC xSrc,
619 OLE_YPOS_HIMETRIC ySrc,
620 OLE_XSIZE_HIMETRIC cxSrc,
621 OLE_YSIZE_HIMETRIC cySrc,
624 OLEPictureImpl *This = (OLEPictureImpl *)iface;
625 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
626 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
628 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
629 prcWBounds->right, prcWBounds->bottom);
632 * While the documentation suggests this to be here (or after rendering?)
633 * it does cause an endless recursion in my sample app. -MM 20010804
634 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
637 switch(This->desc.picType) {
643 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
644 NB y-axis gets flipped */
646 hdcBmp = CreateCompatibleDC(0);
647 SetMapMode(hdcBmp, MM_ANISOTROPIC);
648 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
649 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
650 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
651 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
654 HDC hdcMask = CreateCompatibleDC(0);
655 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
657 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
659 SetMapMode(hdcMask, MM_ANISOTROPIC);
660 SetWindowOrgEx(hdcMask, 0, 0, NULL);
661 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
662 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
663 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
665 SetBkColor(hdc, RGB(255, 255, 255));
666 SetTextColor(hdc, RGB(0, 0, 0));
667 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
668 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
670 SelectObject(hdcMask, hOldbm);
673 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
674 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
677 SelectObject(hdcBmp, hbmpOld);
682 FIXME("Not quite correct implementation of rendering icons...\n");
683 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
686 case PICTYPE_METAFILE:
687 case PICTYPE_ENHMETAFILE:
689 FIXME("type %d not implemented\n", This->desc.picType);
695 /************************************************************************
696 * OLEPictureImpl_set_hPal
698 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
701 OLEPictureImpl *This = (OLEPictureImpl *)iface;
702 FIXME("(%p)->(%08x): stub\n", This, hpal);
703 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
707 /************************************************************************
708 * OLEPictureImpl_get_CurDC
710 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
713 OLEPictureImpl *This = (OLEPictureImpl *)iface;
714 TRACE("(%p), returning %p\n", This, This->hDCCur);
715 if (phdc) *phdc = This->hDCCur;
719 /************************************************************************
720 * OLEPictureImpl_SelectPicture
722 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
725 OLE_HANDLE *phbmpOut)
727 OLEPictureImpl *This = (OLEPictureImpl *)iface;
728 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
729 if (This->desc.picType == PICTYPE_BITMAP) {
730 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
733 *phdcOut = This->hDCCur;
734 This->hDCCur = hdcIn;
736 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
739 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
744 /************************************************************************
745 * OLEPictureImpl_get_KeepOriginalFormat
747 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
750 OLEPictureImpl *This = (OLEPictureImpl *)iface;
751 TRACE("(%p)->(%p)\n", This, pfKeep);
754 *pfKeep = This->keepOrigFormat;
758 /************************************************************************
759 * OLEPictureImpl_put_KeepOriginalFormat
761 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
764 OLEPictureImpl *This = (OLEPictureImpl *)iface;
765 TRACE("(%p)->(%d)\n", This, keep);
766 This->keepOrigFormat = keep;
767 /* FIXME: what DISPID notification here? */
771 /************************************************************************
772 * OLEPictureImpl_PictureChanged
774 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
776 OLEPictureImpl *This = (OLEPictureImpl *)iface;
777 TRACE("(%p)->()\n", This);
778 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
779 This->bIsDirty = TRUE;
783 /************************************************************************
784 * OLEPictureImpl_SaveAsFile
786 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
791 OLEPictureImpl *This = (OLEPictureImpl *)iface;
792 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
793 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
796 /************************************************************************
797 * OLEPictureImpl_get_Attributes
799 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
802 OLEPictureImpl *This = (OLEPictureImpl *)iface;
803 TRACE("(%p)->(%p).\n", This, pdwAttr);
805 switch (This->desc.picType) {
806 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
807 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
808 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
809 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
815 /************************************************************************
816 * IConnectionPointContainer
818 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
819 IConnectionPointContainer* iface,
823 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
825 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
828 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
829 IConnectionPointContainer* iface)
831 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
833 return IPicture_AddRef((IPicture *)This);
836 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
837 IConnectionPointContainer* iface)
839 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
841 return IPicture_Release((IPicture *)This);
844 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
845 IConnectionPointContainer* iface,
846 IEnumConnectionPoints** ppEnum)
848 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
850 FIXME("(%p,%p), stub!\n",This,ppEnum);
854 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
855 IConnectionPointContainer* iface,
857 IConnectionPoint **ppCP)
859 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
860 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
864 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
865 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
866 FIXME("no connection point for %s\n",debugstr_guid(riid));
867 return CONNECT_E_NOCONNECTION;
871 /************************************************************************
875 /************************************************************************
876 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
878 * See Windows documentation for more details on IUnknown methods.
880 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
881 IPersistStream* iface,
885 OLEPictureImpl *This = impl_from_IPersistStream(iface);
887 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
890 /************************************************************************
891 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
893 * See Windows documentation for more details on IUnknown methods.
895 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
896 IPersistStream* iface)
898 OLEPictureImpl *This = impl_from_IPersistStream(iface);
900 return IPicture_AddRef((IPicture *)This);
903 /************************************************************************
904 * OLEPictureImpl_IPersistStream_Release (IUnknown)
906 * See Windows documentation for more details on IUnknown methods.
908 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
909 IPersistStream* iface)
911 OLEPictureImpl *This = impl_from_IPersistStream(iface);
913 return IPicture_Release((IPicture *)This);
916 /************************************************************************
917 * OLEPictureImpl_IPersistStream_GetClassID
919 static HRESULT WINAPI OLEPictureImpl_GetClassID(
920 IPersistStream* iface,CLSID* pClassID)
922 OLEPictureImpl *This = impl_from_IPersistStream(iface);
923 FIXME("(%p),stub!\n",This);
927 /************************************************************************
928 * OLEPictureImpl_IPersistStream_IsDirty
930 static HRESULT WINAPI OLEPictureImpl_IsDirty(
931 IPersistStream* iface)
933 OLEPictureImpl *This = impl_from_IPersistStream(iface);
934 FIXME("(%p),stub!\n",This);
938 #ifdef HAVE_JPEGLIB_H
940 static void *libjpeg_handle;
941 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
942 MAKE_FUNCPTR(jpeg_std_error);
943 MAKE_FUNCPTR(jpeg_CreateDecompress);
944 MAKE_FUNCPTR(jpeg_read_header);
945 MAKE_FUNCPTR(jpeg_start_decompress);
946 MAKE_FUNCPTR(jpeg_read_scanlines);
947 MAKE_FUNCPTR(jpeg_finish_decompress);
948 MAKE_FUNCPTR(jpeg_destroy_decompress);
951 static void *load_libjpeg(void)
953 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
955 #define LOAD_FUNCPTR(f) \
956 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
957 libjpeg_handle = NULL; \
961 LOAD_FUNCPTR(jpeg_std_error);
962 LOAD_FUNCPTR(jpeg_CreateDecompress);
963 LOAD_FUNCPTR(jpeg_read_header);
964 LOAD_FUNCPTR(jpeg_start_decompress);
965 LOAD_FUNCPTR(jpeg_read_scanlines);
966 LOAD_FUNCPTR(jpeg_finish_decompress);
967 LOAD_FUNCPTR(jpeg_destroy_decompress);
970 return libjpeg_handle;
973 /* for the jpeg decompressor source manager. */
974 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
976 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
977 ERR("(), should not get here.\n");
981 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
982 TRACE("Skipping %ld bytes...\n", num_bytes);
983 cinfo->src->next_input_byte += num_bytes;
984 cinfo->src->bytes_in_buffer -= num_bytes;
987 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
988 ERR("(desired=%d), should not get here.\n",desired);
991 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
992 #endif /* HAVE_JPEGLIB_H */
994 #ifdef HAVE_GIF_LIB_H
996 static void *libungif_handle;
997 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
998 MAKE_FUNCPTR(DGifOpen);
999 MAKE_FUNCPTR(DGifSlurp);
1000 MAKE_FUNCPTR(DGifCloseFile);
1004 unsigned char *data;
1005 unsigned int curoff;
1009 static void *load_libungif(void)
1011 if(((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) ||
1012 ((libungif_handle = wine_dlopen(SONAME_LIBGIF , RTLD_NOW, NULL, 0)) != NULL)
1015 #define LOAD_FUNCPTR(f) \
1016 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
1017 libungif_handle = NULL; \
1021 LOAD_FUNCPTR(DGifOpen);
1022 LOAD_FUNCPTR(DGifSlurp);
1023 LOAD_FUNCPTR(DGifCloseFile);
1026 return libungif_handle;
1029 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
1030 struct gifdata *gd = (struct gifdata*)gif->UserData;
1032 if (len+gd->curoff > gd->len) {
1033 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
1034 len = gd->len - gd->curoff;
1036 memcpy(data, gd->data+gd->curoff, len);
1041 #endif /* HAVE_GIF_LIB_H */
1044 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1046 #ifdef HAVE_GIF_LIB_H
1056 int transparent = -1;
1060 if(!libungif_handle) {
1061 if(!load_libungif()) {
1062 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF);
1070 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1071 ret = pDGifSlurp(gif);
1072 if (ret == GIF_ERROR) {
1073 FIXME("Failed reading GIF using libgif.\n");
1076 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1077 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1078 TRACE("imgcnt %d\n", gif->ImageCount);
1079 if (gif->ImageCount<1) {
1080 FIXME("GIF stream does not have images inside?\n");
1083 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1084 gif->Image.Width, gif->Image.Height,
1085 gif->Image.Left, gif->Image.Top,
1086 gif->Image.Interlace
1089 padding = (gif->SWidth+3) & ~3;
1090 si = gif->SavedImages+0;
1091 gid = &(si->ImageDesc);
1093 if (!cm) cm = gif->SColorMap;
1094 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1095 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1097 /* look for the transparent color extension */
1098 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1099 eb = si->ExtensionBlocks + i;
1100 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1101 if ((eb->Bytes[0] & 1) == 1) {
1102 transparent = (unsigned char)eb->Bytes[3];
1107 for (i = 0; i < cm->ColorCount; i++) {
1108 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1109 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1110 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1111 if (i == transparent) {
1112 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1113 bmi->bmiColors[i].rgbGreen,
1114 bmi->bmiColors[i].rgbBlue);
1118 /* Map to in picture coordinates */
1119 for (i = 0, j = 0; i < gid->Height; i++) {
1120 if (gif->Image.Interlace) {
1122 bytes + (gid->Top + j) * padding + gid->Left,
1123 si->RasterBits + i * gid->Width,
1126 /* Lower bits of interlaced counter encode current interlace */
1127 if (j & 1) j += 2; /* Currently filling odd rows */
1128 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1129 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1131 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1132 /* End of current interlace, go to next interlace */
1133 if (j & 2) j = 1; /* Next iteration fills odd rows */
1134 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1135 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1139 bytes + (gid->Top + i) * padding + gid->Left,
1140 si->RasterBits + i * gid->Width,
1145 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1146 bmi->bmiHeader.biWidth = gif->SWidth;
1147 bmi->bmiHeader.biHeight = -gif->SHeight;
1148 bmi->bmiHeader.biPlanes = 1;
1149 bmi->bmiHeader.biBitCount = 8;
1150 bmi->bmiHeader.biCompression = BI_RGB;
1151 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1152 bmi->bmiHeader.biXPelsPerMeter = 0;
1153 bmi->bmiHeader.biYPelsPerMeter = 0;
1154 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1155 bmi->bmiHeader.biClrImportant = 0;
1158 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1167 if (transparent > -1) {
1168 /* Create the Mask */
1169 HDC hdc = CreateCompatibleDC(0);
1170 HDC hdcMask = CreateCompatibleDC(0);
1172 HBITMAP hOldbitmapmask;
1174 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1177 This->hbmXor = CreateDIBitmap(
1186 bmi->bmiColors[0].rgbRed = 0;
1187 bmi->bmiColors[0].rgbGreen = 0;
1188 bmi->bmiColors[0].rgbBlue = 0;
1189 bmi->bmiColors[1].rgbRed = 255;
1190 bmi->bmiColors[1].rgbGreen = 255;
1191 bmi->bmiColors[1].rgbBlue = 255;
1193 bmi->bmiHeader.biBitCount = 1;
1194 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1195 bmi->bmiHeader.biClrUsed = 2;
1197 for (i = 0; i < gif->SHeight; i++) {
1198 unsigned char * colorPointer = bytes + padding * i;
1199 unsigned char * monoPointer = bytes + monopadding * i;
1200 for (j = 0; j < gif->SWidth; j++) {
1201 unsigned char pixel = colorPointer[j];
1202 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1203 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1207 hTempMask = CreateDIBitmap(
1217 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1218 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1219 hOldbitmap = SelectObject(hdc, hTempMask);
1220 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1222 SetBkColor(hdc, RGB(255, 255, 255));
1223 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1225 /* We no longer need the original bitmap, so we apply the first
1226 transformation with the mask to speed up the rendering */
1227 SelectObject(hdc, This->hbmXor);
1228 SetBkColor(hdc, RGB(0,0,0));
1229 SetTextColor(hdc, RGB(255,255,255));
1230 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1231 hdcMask, 0, 0, SRCAND);
1233 SelectObject(hdc, hOldbitmap);
1234 SelectObject(hdcMask, hOldbitmapmask);
1237 DeleteObject(hTempMask);
1241 This->desc.picType = PICTYPE_BITMAP;
1242 OLEPictureImpl_SetBitmap(This);
1243 pDGifCloseFile(gif);
1244 HeapFree(GetProcessHeap(),0,bytes);
1247 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1252 static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1254 #ifdef HAVE_JPEGLIB_H
1255 struct jpeg_decompress_struct jd;
1256 struct jpeg_error_mgr jerr;
1259 JSAMPROW samprow,oldsamprow;
1260 BITMAPINFOHEADER bmi;
1263 struct jpeg_source_mgr xjsm;
1267 if(!libjpeg_handle) {
1268 if(!load_libjpeg()) {
1269 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1274 /* This is basically so we can use in-memory data for jpeg decompression.
1275 * We need to have all the functions.
1277 xjsm.next_input_byte = xbuf;
1278 xjsm.bytes_in_buffer = xread;
1279 xjsm.init_source = _jpeg_init_source;
1280 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1281 xjsm.skip_input_data = _jpeg_skip_input_data;
1282 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1283 xjsm.term_source = _jpeg_term_source;
1285 jd.err = pjpeg_std_error(&jerr);
1286 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1287 * jpeg_create_decompress(&jd); */
1288 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1290 ret=pjpeg_read_header(&jd,TRUE);
1291 jd.out_color_space = JCS_RGB;
1292 pjpeg_start_decompress(&jd);
1293 if (ret != JPEG_HEADER_OK) {
1294 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1295 HeapFree(GetProcessHeap(),0,xbuf);
1299 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1300 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1301 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1304 oldsamprow = samprow;
1305 while ( jd.output_scanline<jd.output_height ) {
1306 x = pjpeg_read_scanlines(&jd,&samprow,1);
1308 FIXME("failed to read current scanline?\n");
1311 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1312 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1313 *(bits++) = *(samprow+2);
1314 *(bits++) = *(samprow+1);
1315 *(bits++) = *(samprow);
1317 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1318 samprow = oldsamprow;
1322 bmi.biSize = sizeof(bmi);
1323 bmi.biWidth = jd.output_width;
1324 bmi.biHeight = -jd.output_height;
1326 bmi.biBitCount = jd.output_components<<3;
1327 bmi.biCompression = BI_RGB;
1328 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1329 bmi.biXPelsPerMeter = 0;
1330 bmi.biYPelsPerMeter = 0;
1332 bmi.biClrImportant = 0;
1334 HeapFree(GetProcessHeap(),0,samprow);
1335 pjpeg_finish_decompress(&jd);
1336 pjpeg_destroy_decompress(&jd);
1338 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1347 This->desc.picType = PICTYPE_BITMAP;
1348 OLEPictureImpl_SetBitmap(This);
1349 HeapFree(GetProcessHeap(),0,bits);
1352 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1357 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1359 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1360 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1363 /* Does not matter whether this is a coreheader or not, we only use
1364 * components which are in both
1367 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1371 xbuf+bfh->bfOffBits,
1376 This->desc.picType = PICTYPE_BITMAP;
1377 OLEPictureImpl_SetBitmap(This);
1381 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1384 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1389 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1390 FIXME("icon.idType=%d\n",cifd->idType);
1391 FIXME("icon.idCount=%d\n",cifd->idCount);
1393 for (i=0;i<cifd->idCount;i++) {
1394 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1395 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1396 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1397 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1398 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1399 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1400 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1401 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1405 /* If we have more than one icon, try to find the best.
1406 * this currently means '32 pixel wide'.
1408 if (cifd->idCount!=1) {
1409 for (i=0;i<cifd->idCount;i++) {
1410 if (cifd->idEntries[i].bWidth == 32)
1413 if (i==cifd->idCount) i=0;
1416 hicon = CreateIconFromResourceEx(
1417 xbuf+cifd->idEntries[i].dwDIBOffset,
1418 cifd->idEntries[i].dwDIBSize,
1421 cifd->idEntries[i].bWidth,
1422 cifd->idEntries[i].bHeight,
1426 FIXME("CreateIcon failed.\n");
1429 This->desc.picType = PICTYPE_ICON;
1430 This->desc.u.icon.hicon = hicon;
1431 This->origWidth = cifd->idEntries[i].bWidth;
1432 This->origHeight = cifd->idEntries[i].bHeight;
1433 hdcRef = CreateCompatibleDC(0);
1434 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1435 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1441 /************************************************************************
1442 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1444 * Loads the binary data from the IStream. Starts at current position.
1445 * There appears to be an 2 DWORD header:
1449 * Currently implemented: BITMAP, ICON, JPEG, GIF
1451 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1452 HRESULT hr = E_FAIL;
1453 BOOL headerisdata = FALSE;
1454 BOOL statfailed = FALSE;
1455 ULONG xread, toread;
1460 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1462 TRACE("(%p,%p)\n",This,pStm);
1464 /****************************************************************************************
1465 * Part 1: Load the data
1467 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1468 * out whether we do.
1470 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1471 * compound file. This may explain most, if not all, of the cases of "no
1472 * header", and the header validation should take this into account.
1473 * At least in Visual Basic 6, resource streams, valid headers are
1474 * header[0] == "lt\0\0",
1475 * header[1] == length_of_stream.
1477 * Also handle streams where we do not have a working "Stat" method by
1478 * reading all data until the end of the stream.
1480 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1482 TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr);
1484 /* we will read at least 8 byte ... just right below */
1485 statstg.cbSize.QuadPart = 8;
1487 hr=IStream_Read(pStm,header,8,&xread);
1488 if (hr || xread!=8) {
1489 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
1493 headerisdata = FALSE;
1495 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1498 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1499 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1500 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1501 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1503 ) {/* Incorrect header, assume none. */
1504 headerisdata = TRUE;
1505 toread = statstg.cbSize.QuadPart-8;
1508 FIXME("Unknown stream header magic: %08lx\n", header[0]);
1513 if (statfailed) { /* we don't know the size ... read all we get */
1515 int origsize = sizeinc;
1518 TRACE("Reading all data from stream.\n");
1519 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1521 memcpy (xbuf, &header, 8);
1523 while (xread < origsize) {
1524 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1529 if (!nread || hr) /* done, or error */
1531 if (xread == origsize) {
1532 origsize += sizeinc;
1533 sizeinc = 2*sizeinc; /* exponential increase */
1534 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1538 TRACE("hr in no-stat loader case is %08lx\n", hr);
1539 TRACE("loaded %ld bytes.\n", xread);
1540 This->datalen = xread;
1543 This->datalen = toread+(headerisdata?8:0);
1544 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1547 memcpy (xbuf, &header, 8);
1549 while (xread < This->datalen) {
1551 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1556 if (xread != This->datalen)
1557 FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
1559 if (This->datalen == 0) { /* Marks the "NONE" picture */
1560 This->desc.picType = PICTYPE_NONE;
1565 /****************************************************************************************
1566 * Part 2: Process the loaded data
1569 magic = xbuf[0] + (xbuf[1]<<8);
1571 case 0x4947: /* GIF */
1572 hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
1574 case 0xd8ff: /* JPEG */
1575 hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
1577 case 0x4d42: /* Bitmap */
1578 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1580 case 0x0000: { /* ICON , first word is dwReserved */
1581 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1587 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1589 for (i=0;i<xread+8;i++) {
1590 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1591 else MESSAGE("%02x ",xbuf[i-8]);
1592 if (i % 10 == 9) MESSAGE("\n");
1598 This->bIsDirty = FALSE;
1600 /* FIXME: this notify is not really documented */
1602 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1606 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1610 BITMAPINFO * pInfoBitmap;
1611 int iNumPaletteEntries;
1612 unsigned char * pPixelData;
1613 BITMAPFILEHEADER * pFileHeader;
1614 BITMAPINFO * pInfoHeader;
1616 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1617 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1619 /* Find out bitmap size and padded length */
1621 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1622 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1624 /* Fetch bitmap palette & pixel data */
1626 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1627 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1629 /* Calculate the total length required for the BMP data */
1630 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1631 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1632 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1634 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1635 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1637 iNumPaletteEntries = 0;
1640 sizeof(BITMAPFILEHEADER) +
1641 sizeof(BITMAPINFOHEADER) +
1642 iNumPaletteEntries * sizeof(RGBQUAD) +
1643 pInfoBitmap->bmiHeader.biSizeImage;
1644 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1646 /* Fill the BITMAPFILEHEADER */
1647 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1648 pFileHeader->bfType = 0x4d42;
1649 pFileHeader->bfSize = *pLength;
1650 pFileHeader->bfOffBits =
1651 sizeof(BITMAPFILEHEADER) +
1652 sizeof(BITMAPINFOHEADER) +
1653 iNumPaletteEntries * sizeof(RGBQUAD);
1655 /* Fill the BITMAPINFOHEADER and the palette data */
1656 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1657 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1659 (unsigned char *)(*ppBuffer) +
1660 sizeof(BITMAPFILEHEADER) +
1661 sizeof(BITMAPINFOHEADER) +
1662 iNumPaletteEntries * sizeof(RGBQUAD),
1663 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1666 HeapFree(GetProcessHeap(), 0, pPixelData);
1667 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1671 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1676 *ppBuffer = NULL; *pLength = 0;
1677 if (GetIconInfo(hIcon, &infoIcon)) {
1679 BITMAPINFO * pInfoBitmap;
1680 unsigned char * pIconData = NULL;
1681 unsigned int iDataSize = 0;
1683 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1685 /* Find out icon size */
1687 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1688 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1690 /* Auxiliary pointers */
1691 CURSORICONFILEDIR * pIconDir;
1692 CURSORICONFILEDIRENTRY * pIconEntry;
1693 BITMAPINFOHEADER * pIconBitmapHeader;
1694 unsigned int iOffsetPalette;
1695 unsigned int iOffsetColorData;
1696 unsigned int iOffsetMaskData;
1698 unsigned int iLengthScanLineColor;
1699 unsigned int iLengthScanLineMask;
1700 unsigned int iNumEntriesPalette;
1702 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1703 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1705 FIXME("DEBUG: bitmap size is %d x %d\n",
1706 pInfoBitmap->bmiHeader.biWidth,
1707 pInfoBitmap->bmiHeader.biHeight);
1708 FIXME("DEBUG: bitmap bpp is %d\n",
1709 pInfoBitmap->bmiHeader.biBitCount);
1710 FIXME("DEBUG: bitmap nplanes is %d\n",
1711 pInfoBitmap->bmiHeader.biPlanes);
1712 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1713 pInfoBitmap->bmiHeader.biSizeImage);
1715 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1716 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1717 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1719 /* Fill out the CURSORICONFILEDIR */
1720 pIconDir = (CURSORICONFILEDIR *)pIconData;
1721 pIconDir->idType = 1;
1722 pIconDir->idCount = 1;
1724 /* Fill out the CURSORICONFILEDIRENTRY */
1725 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1726 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1727 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1728 pIconEntry->bColorCount =
1729 (pInfoBitmap->bmiHeader.biBitCount < 8)
1730 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1732 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1733 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1734 pIconEntry->dwDIBSize = 0;
1735 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1737 /* Fill out the BITMAPINFOHEADER */
1738 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1739 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1741 /* Find out whether a palette exists for the bitmap */
1742 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1743 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1744 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1745 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1746 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1747 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1748 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1749 iNumEntriesPalette = 3;
1750 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1751 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1753 iNumEntriesPalette = 0;
1756 /* Add bitmap size and header size to icon data size. */
1757 iOffsetPalette = iDataSize;
1758 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1759 iOffsetColorData = iDataSize;
1760 iDataSize += pIconBitmapHeader->biSizeImage;
1761 iOffsetMaskData = iDataSize;
1762 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1763 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1764 pIconBitmapHeader->biHeight *= 2;
1765 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1766 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1767 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1768 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1770 /* Get the actual bitmap data from the icon bitmap */
1771 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1772 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1773 if (iNumEntriesPalette > 0) {
1774 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1775 iNumEntriesPalette * sizeof(RGBQUAD));
1778 /* Reset all values so that GetDIBits call succeeds */
1779 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1780 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1781 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1783 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1784 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1785 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1787 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1792 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1793 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1795 /* Write out everything produced so far to the stream */
1796 *ppBuffer = pIconData; *pLength = iDataSize;
1800 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1805 Remarks (from MSDN entry on GetIconInfo):
1807 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1808 members of ICONINFO. The calling application must manage
1809 these bitmaps and delete them when they are no longer
1812 if (hDC) ReleaseDC(0, hDC);
1813 DeleteObject(infoIcon.hbmMask);
1814 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1815 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1817 printf("ERROR: Unable to get icon information (error %lu)\n",
1823 static HRESULT WINAPI OLEPictureImpl_Save(
1824 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1826 HRESULT hResult = E_NOTIMPL;
1828 unsigned int iDataSize;
1830 int iSerializeResult = 0;
1832 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1834 switch (This->desc.picType) {
1836 if (This->bIsDirty) {
1837 if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1838 if (This->loadtime_magic != 0xdeadbeef) {
1841 header[0] = This->loadtime_magic;
1842 header[1] = iDataSize;
1843 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1845 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1847 HeapFree(GetProcessHeap(), 0, This->data);
1848 This->data = pIconData;
1849 This->datalen = iDataSize;
1852 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
1856 if (This->loadtime_magic != 0xdeadbeef) {
1859 header[0] = This->loadtime_magic;
1860 header[1] = This->datalen;
1861 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1863 IStream_Write(pStm, This->data, This->datalen, &dummy);
1867 case PICTYPE_BITMAP:
1868 if (This->bIsDirty) {
1869 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1871 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1874 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1877 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1880 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1883 if (iSerializeResult) {
1885 if (This->loadtime_magic != 0xdeadbeef) {
1890 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1891 header[1] = iDataSize;
1892 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1894 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1896 HeapFree(GetProcessHeap(), 0, This->data);
1897 This->data = pIconData;
1898 This->datalen = iDataSize;
1903 if (This->loadtime_magic != 0xdeadbeef) {
1908 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1909 header[1] = This->datalen;
1910 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1912 IStream_Write(pStm, This->data, This->datalen, &dummy);
1916 case PICTYPE_METAFILE:
1917 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1919 case PICTYPE_ENHMETAFILE:
1920 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1923 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1926 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1930 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1931 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1933 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1934 FIXME("(%p,%p),stub!\n",This,pcbSize);
1939 /************************************************************************
1943 /************************************************************************
1944 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1946 * See Windows documentation for more details on IUnknown methods.
1948 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1953 OLEPictureImpl *This = impl_from_IDispatch(iface);
1955 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1958 /************************************************************************
1959 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1961 * See Windows documentation for more details on IUnknown methods.
1963 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1966 OLEPictureImpl *This = impl_from_IDispatch(iface);
1968 return IPicture_AddRef((IPicture *)This);
1971 /************************************************************************
1972 * OLEPictureImpl_IDispatch_Release (IUnknown)
1974 * See Windows documentation for more details on IUnknown methods.
1976 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1979 OLEPictureImpl *This = impl_from_IDispatch(iface);
1981 return IPicture_Release((IPicture *)This);
1984 /************************************************************************
1985 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1987 * See Windows documentation for more details on IDispatch methods.
1989 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1991 unsigned int* pctinfo)
1998 /************************************************************************
1999 * OLEPictureImpl_GetTypeInfo (IDispatch)
2001 * See Windows documentation for more details on IDispatch methods.
2003 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
2007 ITypeInfo** ppTInfo)
2014 /************************************************************************
2015 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2017 * See Windows documentation for more details on IDispatch methods.
2019 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2022 LPOLESTR* rgszNames,
2032 /************************************************************************
2033 * OLEPictureImpl_Invoke (IDispatch)
2035 * See Windows documentation for more details on IDispatch methods.
2037 static HRESULT WINAPI OLEPictureImpl_Invoke(
2039 DISPID dispIdMember,
2043 DISPPARAMS* pDispParams,
2044 VARIANT* pVarResult,
2045 EXCEPINFO* pExepInfo,
2048 OLEPictureImpl *This = impl_from_IDispatch(iface);
2049 if (dispIdMember == DISPID_PICT_TYPE)
2051 TRACE("DISPID_PICT_TYPE\n");
2052 if (!(wFlags & INVOKE_PROPERTYGET))
2053 return DISP_E_PARAMNOTFOUND;
2054 if (pDispParams->cArgs != 0)
2055 return DISP_E_BADPARAMCOUNT;
2058 VariantInit(pVarResult);
2059 V_VT(pVarResult) = VT_I2;
2060 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2066 FIXME("(dispid: %ld):Stub\n",dispIdMember);
2068 VariantInit(pVarResult);
2069 V_VT(pVarResult) = VT_BOOL;
2070 V_BOOL(pVarResult) = FALSE;
2076 static const IPictureVtbl OLEPictureImpl_VTable =
2078 OLEPictureImpl_QueryInterface,
2079 OLEPictureImpl_AddRef,
2080 OLEPictureImpl_Release,
2081 OLEPictureImpl_get_Handle,
2082 OLEPictureImpl_get_hPal,
2083 OLEPictureImpl_get_Type,
2084 OLEPictureImpl_get_Width,
2085 OLEPictureImpl_get_Height,
2086 OLEPictureImpl_Render,
2087 OLEPictureImpl_set_hPal,
2088 OLEPictureImpl_get_CurDC,
2089 OLEPictureImpl_SelectPicture,
2090 OLEPictureImpl_get_KeepOriginalFormat,
2091 OLEPictureImpl_put_KeepOriginalFormat,
2092 OLEPictureImpl_PictureChanged,
2093 OLEPictureImpl_SaveAsFile,
2094 OLEPictureImpl_get_Attributes
2097 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2099 OLEPictureImpl_IDispatch_QueryInterface,
2100 OLEPictureImpl_IDispatch_AddRef,
2101 OLEPictureImpl_IDispatch_Release,
2102 OLEPictureImpl_GetTypeInfoCount,
2103 OLEPictureImpl_GetTypeInfo,
2104 OLEPictureImpl_GetIDsOfNames,
2105 OLEPictureImpl_Invoke
2108 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2110 OLEPictureImpl_IPersistStream_QueryInterface,
2111 OLEPictureImpl_IPersistStream_AddRef,
2112 OLEPictureImpl_IPersistStream_Release,
2113 OLEPictureImpl_GetClassID,
2114 OLEPictureImpl_IsDirty,
2115 OLEPictureImpl_Load,
2116 OLEPictureImpl_Save,
2117 OLEPictureImpl_GetSizeMax
2120 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2122 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2123 OLEPictureImpl_IConnectionPointContainer_AddRef,
2124 OLEPictureImpl_IConnectionPointContainer_Release,
2125 OLEPictureImpl_EnumConnectionPoints,
2126 OLEPictureImpl_FindConnectionPoint
2129 /***********************************************************************
2130 * OleCreatePictureIndirect (OLEAUT32.419)
2132 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2133 BOOL fOwn, LPVOID *ppvObj )
2135 OLEPictureImpl* newPict = NULL;
2138 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2149 * Try to construct a new instance of the class.
2151 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2153 if (newPict == NULL)
2154 return E_OUTOFMEMORY;
2157 * Make sure it supports the interface required by the caller.
2159 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2162 * Release the reference obtained in the constructor. If
2163 * the QueryInterface was unsuccessful, it will free the class.
2165 IPicture_Release((IPicture*)newPict);
2171 /***********************************************************************
2172 * OleLoadPicture (OLEAUT32.418)
2174 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2175 REFIID riid, LPVOID *ppvObj )
2181 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2182 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2184 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2187 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2189 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2190 IPicture_Release(newpic);
2194 IPersistStream_Load(ps,lpstream);
2195 IPersistStream_Release(ps);
2196 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2198 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2199 IPicture_Release(newpic);
2203 /***********************************************************************
2204 * OleLoadPictureEx (OLEAUT32.401)
2206 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2207 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2213 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2214 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2216 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2219 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2221 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2222 IPicture_Release(newpic);
2226 IPersistStream_Load(ps,lpstream);
2227 IPersistStream_Release(ps);
2228 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2230 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2231 IPicture_Release(newpic);
2235 /***********************************************************************
2236 * OleLoadPicturePath (OLEAUT32.424)
2238 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2239 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2242 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2246 HGLOBAL hGlobal = NULL;
2247 DWORD dwBytesRead = 0;
2250 IPersistStream *pStream;
2253 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2254 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2255 debugstr_guid(riid), ppvRet);
2257 if (!ppvRet) return E_POINTER;
2259 if (strncmpW(szURLorPath, file, 7) == 0) {
2262 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2264 if (hFile == INVALID_HANDLE_VALUE)
2265 return E_UNEXPECTED;
2267 dwFileSize = GetFileSize(hFile, NULL);
2268 if (dwFileSize != INVALID_FILE_SIZE )
2270 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2273 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2276 GlobalFree(hGlobal);
2284 return E_UNEXPECTED;
2286 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2289 GlobalFree(hGlobal);
2296 hRes = CreateBindCtx(0, &pbc);
2297 if (SUCCEEDED(hRes))
2299 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2300 if (SUCCEEDED(hRes))
2302 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2303 IMoniker_Release(pmnk);
2305 IBindCtx_Release(pbc);
2311 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2312 &IID_IPicture, (LPVOID*)&ipicture);
2314 IStream_Release(stream);
2318 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2320 IStream_Release(stream);
2321 IPicture_Release(ipicture);
2325 hRes = IPersistStream_Load(pStream, stream);
2326 IPersistStream_Release(pStream);
2327 IStream_Release(stream);
2330 IPicture_Release(ipicture);
2334 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2336 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2338 IPicture_Release(ipicture);
2342 /*******************************************************************************
2343 * StdPic ClassFactory
2347 /* IUnknown fields */
2348 const IClassFactoryVtbl *lpVtbl;
2350 } IClassFactoryImpl;
2352 static HRESULT WINAPI
2353 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2354 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2356 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2357 return E_NOINTERFACE;
2361 SPCF_AddRef(LPCLASSFACTORY iface) {
2362 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2363 return InterlockedIncrement(&This->ref);
2366 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2367 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2368 /* static class, won't be freed */
2369 return InterlockedDecrement(&This->ref);
2372 static HRESULT WINAPI SPCF_CreateInstance(
2373 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2375 /* Creates an uninitialized picture */
2376 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2380 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2381 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2382 FIXME("(%p)->(%d),stub!\n",This,dolock);
2386 static const IClassFactoryVtbl SPCF_Vtbl = {
2387 SPCF_QueryInterface,
2390 SPCF_CreateInstance,
2393 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2395 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }