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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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
86 #define boolean jpeg_boolean
90 #ifndef SONAME_LIBJPEG
91 #define SONAME_LIBJPEG "libjpeg.so"
95 WINE_DEFAULT_DEBUG_CHANNEL(ole);
108 } CURSORICONFILEDIRENTRY;
115 CURSORICONFILEDIRENTRY idEntries[1];
120 /*************************************************************************
121 * Declaration of implementation class
124 typedef struct OLEPictureImpl {
127 * IPicture handles IUnknown
130 const IPictureVtbl *lpVtbl;
131 const IDispatchVtbl *lpvtblIDispatch;
132 const IPersistStreamVtbl *lpvtblIPersistStream;
133 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
135 /* Object reference count */
138 /* We own the object and must destroy it ourselves */
141 /* Picture description */
144 /* These are the pixel size of a bitmap */
148 /* And these are the size of the picture converted into HIMETRIC units */
149 OLE_XSIZE_HIMETRIC himetricWidth;
150 OLE_YSIZE_HIMETRIC himetricHeight;
152 IConnectionPoint *pCP;
157 /* Bitmap transparency mask */
165 BOOL bIsDirty; /* Set to TRUE if picture has changed */
166 unsigned int loadtime_magic; /* If a length header was found, saves value */
167 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
171 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
174 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
176 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
179 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
181 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
184 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
186 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
190 * Predeclare VTables. They get initialized at the end.
192 static const IPictureVtbl OLEPictureImpl_VTable;
193 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
194 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
195 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
197 /***********************************************************************
198 * Implementation of the OLEPictureImpl class.
201 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
205 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
206 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
207 ERR("GetObject fails\n");
210 This->origWidth = bm.bmWidth;
211 This->origHeight = bm.bmHeight;
212 /* The width and height are stored in HIMETRIC units (0.01 mm),
213 so we take our pixel width divide by pixels per inch and
214 multiply by 25.4 * 100 */
215 /* Should we use GetBitmapDimension if available? */
216 hdcRef = CreateCompatibleDC(0);
217 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
218 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
222 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
226 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
227 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
231 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
232 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
233 ERR("GetObject fails on icon bitmap\n");
237 This->origWidth = bm.bmWidth;
238 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
239 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
241 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
242 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
243 ReleaseDC(0, hdcRef);
245 DeleteObject(infoIcon.hbmMask);
246 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
248 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
252 /************************************************************************
253 * OLEPictureImpl_Construct
255 * This method will construct a new instance of the OLEPictureImpl
258 * The caller of this method must release the object when it's
261 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
263 OLEPictureImpl* newObject = 0;
266 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
269 * Allocate space for the object.
271 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
277 * Initialize the virtual function table.
279 newObject->lpVtbl = &OLEPictureImpl_VTable;
280 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
281 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
282 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
284 newObject->pCP = NULL;
285 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
288 HeapFree(GetProcessHeap(), 0, newObject);
293 * Start with one reference count. The caller of this function
294 * must release the interface pointer when it is done.
297 newObject->hDCCur = 0;
299 newObject->fOwn = fOwn;
301 /* dunno about original value */
302 newObject->keepOrigFormat = TRUE;
304 newObject->hbmMask = NULL;
305 newObject->hbmXor = NULL;
306 newObject->loadtime_magic = 0xdeadbeef;
307 newObject->loadtime_format = 0;
308 newObject->bIsDirty = FALSE;
311 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
312 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
314 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
317 switch(pictDesc->picType) {
319 OLEPictureImpl_SetBitmap(newObject);
322 case PICTYPE_METAFILE:
323 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
324 newObject->himetricWidth = pictDesc->u.wmf.xExt;
325 newObject->himetricHeight = pictDesc->u.wmf.yExt;
329 /* not sure what to do here */
330 newObject->himetricWidth = newObject->himetricHeight = 0;
334 OLEPictureImpl_SetIcon(newObject);
336 case PICTYPE_ENHMETAFILE:
338 FIXME("Unsupported type %d\n", pictDesc->picType);
339 newObject->himetricWidth = newObject->himetricHeight = 0;
343 newObject->desc.picType = PICTYPE_UNINITIALIZED;
346 TRACE("returning %p\n", newObject);
350 /************************************************************************
351 * OLEPictureImpl_Destroy
353 * This method is called by the Release method when the reference
354 * count goes down to 0. It will free all resources used by
356 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
358 TRACE("(%p)\n", Obj);
361 IConnectionPoint_Release(Obj->pCP);
363 if(Obj->fOwn) { /* We need to destroy the picture */
364 switch(Obj->desc.picType) {
366 DeleteObject(Obj->desc.u.bmp.hbitmap);
367 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
368 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
370 case PICTYPE_METAFILE:
371 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
374 DestroyIcon(Obj->desc.u.icon.hicon);
376 case PICTYPE_ENHMETAFILE:
377 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
383 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
387 HeapFree(GetProcessHeap(), 0, Obj->data);
388 HeapFree(GetProcessHeap(), 0, Obj);
392 /************************************************************************
393 * OLEPictureImpl_AddRef (IUnknown)
395 * See Windows documentation for more details on IUnknown methods.
397 static ULONG WINAPI OLEPictureImpl_AddRef(
400 OLEPictureImpl *This = (OLEPictureImpl *)iface;
401 ULONG refCount = InterlockedIncrement(&This->ref);
403 TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1);
408 /************************************************************************
409 * OLEPictureImpl_Release (IUnknown)
411 * See Windows documentation for more details on IUnknown methods.
413 static ULONG WINAPI OLEPictureImpl_Release(
416 OLEPictureImpl *This = (OLEPictureImpl *)iface;
417 ULONG refCount = InterlockedDecrement(&This->ref);
419 TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1);
422 * If the reference count goes down to 0, perform suicide.
424 if (!refCount) OLEPictureImpl_Destroy(This);
429 /************************************************************************
430 * OLEPictureImpl_QueryInterface (IUnknown)
432 * See Windows documentation for more details on IUnknown methods.
434 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
439 OLEPictureImpl *This = (OLEPictureImpl *)iface;
440 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
443 * Perform a sanity check on the parameters.
445 if ( (This==0) || (ppvObject==0) )
449 * Initialize the return parameter.
454 * Compare the riid with the interface IDs implemented by this object.
456 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
457 *ppvObject = (IPicture*)This;
458 else if (IsEqualIID(&IID_IDispatch, riid))
459 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
460 else if (IsEqualIID(&IID_IPictureDisp, riid))
461 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
462 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
463 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
464 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
465 *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
468 * Check that we obtained an interface.
472 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
473 return E_NOINTERFACE;
477 * Query Interface always increases the reference count by one when it is
480 OLEPictureImpl_AddRef((IPicture*)This);
485 /***********************************************************************
486 * OLEPicture_SendNotify (internal)
488 * Sends notification messages of changed properties to any interested
491 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
493 IEnumConnections *pEnum;
496 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
498 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
499 IPropertyNotifySink *sink;
501 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
502 IPropertyNotifySink_OnChanged(sink, dispID);
503 IPropertyNotifySink_Release(sink);
504 IUnknown_Release(CD.pUnk);
506 IEnumConnections_Release(pEnum);
510 /************************************************************************
511 * OLEPictureImpl_get_Handle
513 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
516 OLEPictureImpl *This = (OLEPictureImpl *)iface;
517 TRACE("(%p)->(%p)\n", This, phandle);
518 switch(This->desc.picType) {
523 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
525 case PICTYPE_METAFILE:
526 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
529 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
531 case PICTYPE_ENHMETAFILE:
532 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
535 FIXME("Unimplemented type %d\n", This->desc.picType);
538 TRACE("returning handle %08x\n", *phandle);
542 /************************************************************************
543 * OLEPictureImpl_get_hPal
545 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
548 OLEPictureImpl *This = (OLEPictureImpl *)iface;
550 TRACE("(%p)->(%p)\n", This, phandle);
555 switch (This->desc.picType) {
556 case PICTYPE_UNINITIALIZED:
562 *phandle = (OLE_HANDLE)This->desc.u.bmp.hpal;
566 case PICTYPE_METAFILE:
567 case PICTYPE_ENHMETAFILE:
569 FIXME("unimplemented for type %d. Returning 0 palette.\n",
575 TRACE("returning 0x%08lx, palette handle %08x\n", hres, *phandle);
579 /************************************************************************
580 * OLEPictureImpl_get_Type
582 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
585 OLEPictureImpl *This = (OLEPictureImpl *)iface;
586 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
587 *ptype = This->desc.picType;
591 /************************************************************************
592 * OLEPictureImpl_get_Width
594 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
595 OLE_XSIZE_HIMETRIC *pwidth)
597 OLEPictureImpl *This = (OLEPictureImpl *)iface;
598 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
599 *pwidth = This->himetricWidth;
603 /************************************************************************
604 * OLEPictureImpl_get_Height
606 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
607 OLE_YSIZE_HIMETRIC *pheight)
609 OLEPictureImpl *This = (OLEPictureImpl *)iface;
610 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
611 *pheight = This->himetricHeight;
615 /************************************************************************
616 * OLEPictureImpl_Render
618 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
619 LONG x, LONG y, LONG cx, LONG cy,
620 OLE_XPOS_HIMETRIC xSrc,
621 OLE_YPOS_HIMETRIC ySrc,
622 OLE_XSIZE_HIMETRIC cxSrc,
623 OLE_YSIZE_HIMETRIC cySrc,
626 OLEPictureImpl *This = (OLEPictureImpl *)iface;
627 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
628 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
630 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
631 prcWBounds->right, prcWBounds->bottom);
634 * While the documentation suggests this to be here (or after rendering?)
635 * it does cause an endless recursion in my sample app. -MM 20010804
636 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
639 switch(This->desc.picType) {
645 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
646 NB y-axis gets flipped */
648 hdcBmp = CreateCompatibleDC(0);
649 SetMapMode(hdcBmp, MM_ANISOTROPIC);
650 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
651 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
652 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
653 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
656 HDC hdcMask = CreateCompatibleDC(0);
657 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
659 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
661 SetMapMode(hdcMask, MM_ANISOTROPIC);
662 SetWindowOrgEx(hdcMask, 0, 0, NULL);
663 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
664 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
665 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
667 SetBkColor(hdc, RGB(255, 255, 255));
668 SetTextColor(hdc, RGB(0, 0, 0));
669 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
670 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
672 SelectObject(hdcMask, hOldbm);
675 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
676 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
679 SelectObject(hdcBmp, hbmpOld);
684 FIXME("Not quite correct implementation of rendering icons...\n");
685 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
688 case PICTYPE_METAFILE:
689 case PICTYPE_ENHMETAFILE:
691 FIXME("type %d not implemented\n", This->desc.picType);
697 /************************************************************************
698 * OLEPictureImpl_set_hPal
700 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
703 OLEPictureImpl *This = (OLEPictureImpl *)iface;
704 FIXME("(%p)->(%08x): stub\n", This, hpal);
705 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
709 /************************************************************************
710 * OLEPictureImpl_get_CurDC
712 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
715 OLEPictureImpl *This = (OLEPictureImpl *)iface;
716 TRACE("(%p), returning %p\n", This, This->hDCCur);
717 if (phdc) *phdc = This->hDCCur;
721 /************************************************************************
722 * OLEPictureImpl_SelectPicture
724 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
727 OLE_HANDLE *phbmpOut)
729 OLEPictureImpl *This = (OLEPictureImpl *)iface;
730 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
731 if (This->desc.picType == PICTYPE_BITMAP) {
732 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
735 *phdcOut = This->hDCCur;
736 This->hDCCur = hdcIn;
738 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
741 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
746 /************************************************************************
747 * OLEPictureImpl_get_KeepOriginalFormat
749 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
752 OLEPictureImpl *This = (OLEPictureImpl *)iface;
753 TRACE("(%p)->(%p)\n", This, pfKeep);
756 *pfKeep = This->keepOrigFormat;
760 /************************************************************************
761 * OLEPictureImpl_put_KeepOriginalFormat
763 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
766 OLEPictureImpl *This = (OLEPictureImpl *)iface;
767 TRACE("(%p)->(%d)\n", This, keep);
768 This->keepOrigFormat = keep;
769 /* FIXME: what DISPID notification here? */
773 /************************************************************************
774 * OLEPictureImpl_PictureChanged
776 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
778 OLEPictureImpl *This = (OLEPictureImpl *)iface;
779 TRACE("(%p)->()\n", This);
780 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
781 This->bIsDirty = TRUE;
785 /************************************************************************
786 * OLEPictureImpl_SaveAsFile
788 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
793 OLEPictureImpl *This = (OLEPictureImpl *)iface;
794 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
795 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
798 /************************************************************************
799 * OLEPictureImpl_get_Attributes
801 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
804 OLEPictureImpl *This = (OLEPictureImpl *)iface;
805 TRACE("(%p)->(%p).\n", This, pdwAttr);
807 switch (This->desc.picType) {
808 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
809 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
810 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
811 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
817 /************************************************************************
818 * IConnectionPointContainer
820 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
821 IConnectionPointContainer* iface,
825 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
827 return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
830 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
831 IConnectionPointContainer* iface)
833 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
835 return IPicture_AddRef((IPicture *)This);
838 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
839 IConnectionPointContainer* iface)
841 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
843 return IPicture_Release((IPicture *)This);
846 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
847 IConnectionPointContainer* iface,
848 IEnumConnectionPoints** ppEnum)
850 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
852 FIXME("(%p,%p), stub!\n",This,ppEnum);
856 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
857 IConnectionPointContainer* iface,
859 IConnectionPoint **ppCP)
861 OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
862 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
866 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
867 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
868 FIXME("no connection point for %s\n",debugstr_guid(riid));
869 return CONNECT_E_NOCONNECTION;
873 /************************************************************************
877 /************************************************************************
878 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
880 * See Windows documentation for more details on IUnknown methods.
882 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
883 IPersistStream* iface,
887 OLEPictureImpl *This = impl_from_IPersistStream(iface);
889 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
892 /************************************************************************
893 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
895 * See Windows documentation for more details on IUnknown methods.
897 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
898 IPersistStream* iface)
900 OLEPictureImpl *This = impl_from_IPersistStream(iface);
902 return IPicture_AddRef((IPicture *)This);
905 /************************************************************************
906 * OLEPictureImpl_IPersistStream_Release (IUnknown)
908 * See Windows documentation for more details on IUnknown methods.
910 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
911 IPersistStream* iface)
913 OLEPictureImpl *This = impl_from_IPersistStream(iface);
915 return IPicture_Release((IPicture *)This);
918 /************************************************************************
919 * OLEPictureImpl_IPersistStream_GetClassID
921 static HRESULT WINAPI OLEPictureImpl_GetClassID(
922 IPersistStream* iface,CLSID* pClassID)
924 TRACE("(%p)\n", pClassID);
925 memcpy(pClassID, &CLSID_StdPicture, sizeof(*pClassID));
929 /************************************************************************
930 * OLEPictureImpl_IPersistStream_IsDirty
932 static HRESULT WINAPI OLEPictureImpl_IsDirty(
933 IPersistStream* iface)
935 OLEPictureImpl *This = impl_from_IPersistStream(iface);
936 FIXME("(%p),stub!\n",This);
940 #ifdef HAVE_JPEGLIB_H
942 static void *libjpeg_handle;
943 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
944 MAKE_FUNCPTR(jpeg_std_error);
945 MAKE_FUNCPTR(jpeg_CreateDecompress);
946 MAKE_FUNCPTR(jpeg_read_header);
947 MAKE_FUNCPTR(jpeg_start_decompress);
948 MAKE_FUNCPTR(jpeg_read_scanlines);
949 MAKE_FUNCPTR(jpeg_finish_decompress);
950 MAKE_FUNCPTR(jpeg_destroy_decompress);
953 static void *load_libjpeg(void)
955 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
957 #define LOAD_FUNCPTR(f) \
958 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
959 libjpeg_handle = NULL; \
963 LOAD_FUNCPTR(jpeg_std_error);
964 LOAD_FUNCPTR(jpeg_CreateDecompress);
965 LOAD_FUNCPTR(jpeg_read_header);
966 LOAD_FUNCPTR(jpeg_start_decompress);
967 LOAD_FUNCPTR(jpeg_read_scanlines);
968 LOAD_FUNCPTR(jpeg_finish_decompress);
969 LOAD_FUNCPTR(jpeg_destroy_decompress);
972 return libjpeg_handle;
975 /* for the jpeg decompressor source manager. */
976 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
978 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
979 ERR("(), should not get here.\n");
983 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
984 TRACE("Skipping %ld bytes...\n", num_bytes);
985 cinfo->src->next_input_byte += num_bytes;
986 cinfo->src->bytes_in_buffer -= num_bytes;
989 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
990 ERR("(desired=%d), should not get here.\n",desired);
993 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
994 #endif /* HAVE_JPEGLIB_H */
996 #ifdef HAVE_GIF_LIB_H
998 static void *libungif_handle;
999 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
1000 MAKE_FUNCPTR(DGifOpen);
1001 MAKE_FUNCPTR(DGifSlurp);
1002 MAKE_FUNCPTR(DGifCloseFile);
1006 unsigned char *data;
1007 unsigned int curoff;
1011 static void *load_libungif(void)
1013 if(((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) ||
1014 ((libungif_handle = wine_dlopen(SONAME_LIBGIF , RTLD_NOW, NULL, 0)) != NULL)
1017 #define LOAD_FUNCPTR(f) \
1018 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
1019 libungif_handle = NULL; \
1023 LOAD_FUNCPTR(DGifOpen);
1024 LOAD_FUNCPTR(DGifSlurp);
1025 LOAD_FUNCPTR(DGifCloseFile);
1028 return libungif_handle;
1031 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
1032 struct gifdata *gd = (struct gifdata*)gif->UserData;
1034 if (len+gd->curoff > gd->len) {
1035 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
1036 len = gd->len - gd->curoff;
1038 memcpy(data, gd->data+gd->curoff, len);
1043 #endif /* HAVE_GIF_LIB_H */
1046 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1048 #ifdef HAVE_GIF_LIB_H
1058 int transparent = -1;
1062 if(!libungif_handle) {
1063 if(!load_libungif()) {
1064 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF);
1072 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1073 ret = pDGifSlurp(gif);
1074 if (ret == GIF_ERROR) {
1075 FIXME("Failed reading GIF using libgif.\n");
1078 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1079 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1080 TRACE("imgcnt %d\n", gif->ImageCount);
1081 if (gif->ImageCount<1) {
1082 FIXME("GIF stream does not have images inside?\n");
1085 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1086 gif->Image.Width, gif->Image.Height,
1087 gif->Image.Left, gif->Image.Top,
1088 gif->Image.Interlace
1091 padding = (gif->SWidth+3) & ~3;
1092 si = gif->SavedImages+0;
1093 gid = &(si->ImageDesc);
1095 if (!cm) cm = gif->SColorMap;
1096 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1097 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1099 /* look for the transparent color extension */
1100 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1101 eb = si->ExtensionBlocks + i;
1102 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1103 if ((eb->Bytes[0] & 1) == 1) {
1104 transparent = (unsigned char)eb->Bytes[3];
1109 for (i = 0; i < cm->ColorCount; i++) {
1110 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1111 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1112 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1113 if (i == transparent) {
1114 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1115 bmi->bmiColors[i].rgbGreen,
1116 bmi->bmiColors[i].rgbBlue);
1120 /* Map to in picture coordinates */
1121 for (i = 0, j = 0; i < gid->Height; i++) {
1122 if (gif->Image.Interlace) {
1124 bytes + (gid->Top + j) * padding + gid->Left,
1125 si->RasterBits + i * gid->Width,
1128 /* Lower bits of interlaced counter encode current interlace */
1129 if (j & 1) j += 2; /* Currently filling odd rows */
1130 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1131 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1133 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1134 /* End of current interlace, go to next interlace */
1135 if (j & 2) j = 1; /* Next iteration fills odd rows */
1136 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1137 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1141 bytes + (gid->Top + i) * padding + gid->Left,
1142 si->RasterBits + i * gid->Width,
1147 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1148 bmi->bmiHeader.biWidth = gif->SWidth;
1149 bmi->bmiHeader.biHeight = -gif->SHeight;
1150 bmi->bmiHeader.biPlanes = 1;
1151 bmi->bmiHeader.biBitCount = 8;
1152 bmi->bmiHeader.biCompression = BI_RGB;
1153 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1154 bmi->bmiHeader.biXPelsPerMeter = 0;
1155 bmi->bmiHeader.biYPelsPerMeter = 0;
1156 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1157 bmi->bmiHeader.biClrImportant = 0;
1160 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1169 if (transparent > -1) {
1170 /* Create the Mask */
1171 HDC hdc = CreateCompatibleDC(0);
1172 HDC hdcMask = CreateCompatibleDC(0);
1174 HBITMAP hOldbitmapmask;
1176 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1179 This->hbmXor = CreateDIBitmap(
1188 bmi->bmiColors[0].rgbRed = 0;
1189 bmi->bmiColors[0].rgbGreen = 0;
1190 bmi->bmiColors[0].rgbBlue = 0;
1191 bmi->bmiColors[1].rgbRed = 255;
1192 bmi->bmiColors[1].rgbGreen = 255;
1193 bmi->bmiColors[1].rgbBlue = 255;
1195 bmi->bmiHeader.biBitCount = 1;
1196 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1197 bmi->bmiHeader.biClrUsed = 2;
1199 for (i = 0; i < gif->SHeight; i++) {
1200 unsigned char * colorPointer = bytes + padding * i;
1201 unsigned char * monoPointer = bytes + monopadding * i;
1202 for (j = 0; j < gif->SWidth; j++) {
1203 unsigned char pixel = colorPointer[j];
1204 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1205 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1209 hTempMask = CreateDIBitmap(
1219 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1220 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1221 hOldbitmap = SelectObject(hdc, hTempMask);
1222 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1224 SetBkColor(hdc, RGB(255, 255, 255));
1225 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1227 /* We no longer need the original bitmap, so we apply the first
1228 transformation with the mask to speed up the rendering */
1229 SelectObject(hdc, This->hbmXor);
1230 SetBkColor(hdc, RGB(0,0,0));
1231 SetTextColor(hdc, RGB(255,255,255));
1232 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1233 hdcMask, 0, 0, SRCAND);
1235 SelectObject(hdc, hOldbitmap);
1236 SelectObject(hdcMask, hOldbitmapmask);
1239 DeleteObject(hTempMask);
1243 This->desc.picType = PICTYPE_BITMAP;
1244 OLEPictureImpl_SetBitmap(This);
1245 pDGifCloseFile(gif);
1246 HeapFree(GetProcessHeap(),0,bytes);
1249 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1254 static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1256 #ifdef HAVE_JPEGLIB_H
1257 struct jpeg_decompress_struct jd;
1258 struct jpeg_error_mgr jerr;
1261 JSAMPROW samprow,oldsamprow;
1262 BITMAPINFOHEADER bmi;
1265 struct jpeg_source_mgr xjsm;
1269 if(!libjpeg_handle) {
1270 if(!load_libjpeg()) {
1271 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1276 /* This is basically so we can use in-memory data for jpeg decompression.
1277 * We need to have all the functions.
1279 xjsm.next_input_byte = xbuf;
1280 xjsm.bytes_in_buffer = xread;
1281 xjsm.init_source = _jpeg_init_source;
1282 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1283 xjsm.skip_input_data = _jpeg_skip_input_data;
1284 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1285 xjsm.term_source = _jpeg_term_source;
1287 jd.err = pjpeg_std_error(&jerr);
1288 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1289 * jpeg_create_decompress(&jd); */
1290 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1292 ret=pjpeg_read_header(&jd,TRUE);
1293 jd.out_color_space = JCS_RGB;
1294 pjpeg_start_decompress(&jd);
1295 if (ret != JPEG_HEADER_OK) {
1296 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1297 HeapFree(GetProcessHeap(),0,xbuf);
1301 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1302 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1303 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1306 oldsamprow = samprow;
1307 while ( jd.output_scanline<jd.output_height ) {
1308 x = pjpeg_read_scanlines(&jd,&samprow,1);
1310 FIXME("failed to read current scanline?\n");
1313 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1314 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1315 *(bits++) = *(samprow+2);
1316 *(bits++) = *(samprow+1);
1317 *(bits++) = *(samprow);
1319 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1320 samprow = oldsamprow;
1324 bmi.biSize = sizeof(bmi);
1325 bmi.biWidth = jd.output_width;
1326 bmi.biHeight = -jd.output_height;
1328 bmi.biBitCount = jd.output_components<<3;
1329 bmi.biCompression = BI_RGB;
1330 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1331 bmi.biXPelsPerMeter = 0;
1332 bmi.biYPelsPerMeter = 0;
1334 bmi.biClrImportant = 0;
1336 HeapFree(GetProcessHeap(),0,samprow);
1337 pjpeg_finish_decompress(&jd);
1338 pjpeg_destroy_decompress(&jd);
1340 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1349 This->desc.picType = PICTYPE_BITMAP;
1350 OLEPictureImpl_SetBitmap(This);
1351 HeapFree(GetProcessHeap(),0,bits);
1354 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1359 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1361 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1362 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1365 /* Does not matter whether this is a coreheader or not, we only use
1366 * components which are in both
1369 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1373 xbuf+bfh->bfOffBits,
1378 This->desc.picType = PICTYPE_BITMAP;
1379 OLEPictureImpl_SetBitmap(This);
1383 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1386 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1391 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1392 FIXME("icon.idType=%d\n",cifd->idType);
1393 FIXME("icon.idCount=%d\n",cifd->idCount);
1395 for (i=0;i<cifd->idCount;i++) {
1396 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1397 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1398 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1399 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1400 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1401 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1402 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1403 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1407 /* If we have more than one icon, try to find the best.
1408 * this currently means '32 pixel wide'.
1410 if (cifd->idCount!=1) {
1411 for (i=0;i<cifd->idCount;i++) {
1412 if (cifd->idEntries[i].bWidth == 32)
1415 if (i==cifd->idCount) i=0;
1418 hicon = CreateIconFromResourceEx(
1419 xbuf+cifd->idEntries[i].dwDIBOffset,
1420 cifd->idEntries[i].dwDIBSize,
1423 cifd->idEntries[i].bWidth,
1424 cifd->idEntries[i].bHeight,
1428 FIXME("CreateIcon failed.\n");
1431 This->desc.picType = PICTYPE_ICON;
1432 This->desc.u.icon.hicon = hicon;
1433 This->origWidth = cifd->idEntries[i].bWidth;
1434 This->origHeight = cifd->idEntries[i].bHeight;
1435 hdcRef = CreateCompatibleDC(0);
1436 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1437 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1443 /************************************************************************
1444 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1446 * Loads the binary data from the IStream. Starts at current position.
1447 * There appears to be an 2 DWORD header:
1451 * Currently implemented: BITMAP, ICON, JPEG, GIF
1453 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1454 HRESULT hr = E_FAIL;
1455 BOOL headerisdata = FALSE;
1456 BOOL statfailed = FALSE;
1457 ULONG xread, toread;
1462 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1464 TRACE("(%p,%p)\n",This,pStm);
1466 /****************************************************************************************
1467 * Part 1: Load the data
1469 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1470 * out whether we do.
1472 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1473 * compound file. This may explain most, if not all, of the cases of "no
1474 * header", and the header validation should take this into account.
1475 * At least in Visual Basic 6, resource streams, valid headers are
1476 * header[0] == "lt\0\0",
1477 * header[1] == length_of_stream.
1479 * Also handle streams where we do not have a working "Stat" method by
1480 * reading all data until the end of the stream.
1482 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1484 TRACE("stat failed with hres %lx, proceeding to read all data.\n",hr);
1486 /* we will read at least 8 byte ... just right below */
1487 statstg.cbSize.QuadPart = 8;
1489 hr=IStream_Read(pStm,header,8,&xread);
1490 if (hr || xread!=8) {
1491 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
1495 headerisdata = FALSE;
1497 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1500 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1501 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1502 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1503 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1505 ) {/* Incorrect header, assume none. */
1506 headerisdata = TRUE;
1507 toread = statstg.cbSize.QuadPart-8;
1510 FIXME("Unknown stream header magic: %08lx\n", header[0]);
1515 if (statfailed) { /* we don't know the size ... read all we get */
1517 int origsize = sizeinc;
1520 TRACE("Reading all data from stream.\n");
1521 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1523 memcpy (xbuf, &header, 8);
1525 while (xread < origsize) {
1526 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1531 if (!nread || hr) /* done, or error */
1533 if (xread == origsize) {
1534 origsize += sizeinc;
1535 sizeinc = 2*sizeinc; /* exponential increase */
1536 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1540 TRACE("hr in no-stat loader case is %08lx\n", hr);
1541 TRACE("loaded %ld bytes.\n", xread);
1542 This->datalen = xread;
1545 This->datalen = toread+(headerisdata?8:0);
1546 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1549 memcpy (xbuf, &header, 8);
1551 while (xread < This->datalen) {
1553 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1558 if (xread != This->datalen)
1559 FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
1561 if (This->datalen == 0) { /* Marks the "NONE" picture */
1562 This->desc.picType = PICTYPE_NONE;
1567 /****************************************************************************************
1568 * Part 2: Process the loaded data
1571 magic = xbuf[0] + (xbuf[1]<<8);
1573 case 0x4947: /* GIF */
1574 hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
1576 case 0xd8ff: /* JPEG */
1577 hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
1579 case 0x4d42: /* Bitmap */
1580 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1582 case 0x0000: { /* ICON , first word is dwReserved */
1583 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1589 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1591 for (i=0;i<xread+8;i++) {
1592 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1593 else MESSAGE("%02x ",xbuf[i-8]);
1594 if (i % 10 == 9) MESSAGE("\n");
1600 This->bIsDirty = FALSE;
1602 /* FIXME: this notify is not really documented */
1604 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1608 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1612 BITMAPINFO * pInfoBitmap;
1613 int iNumPaletteEntries;
1614 unsigned char * pPixelData;
1615 BITMAPFILEHEADER * pFileHeader;
1616 BITMAPINFO * pInfoHeader;
1618 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1619 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1621 /* Find out bitmap size and padded length */
1623 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1624 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1626 /* Fetch bitmap palette & pixel data */
1628 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1629 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1631 /* Calculate the total length required for the BMP data */
1632 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1633 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1634 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1636 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1637 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1639 iNumPaletteEntries = 0;
1642 sizeof(BITMAPFILEHEADER) +
1643 sizeof(BITMAPINFOHEADER) +
1644 iNumPaletteEntries * sizeof(RGBQUAD) +
1645 pInfoBitmap->bmiHeader.biSizeImage;
1646 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1648 /* Fill the BITMAPFILEHEADER */
1649 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1650 pFileHeader->bfType = 0x4d42;
1651 pFileHeader->bfSize = *pLength;
1652 pFileHeader->bfOffBits =
1653 sizeof(BITMAPFILEHEADER) +
1654 sizeof(BITMAPINFOHEADER) +
1655 iNumPaletteEntries * sizeof(RGBQUAD);
1657 /* Fill the BITMAPINFOHEADER and the palette data */
1658 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1659 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1661 (unsigned char *)(*ppBuffer) +
1662 sizeof(BITMAPFILEHEADER) +
1663 sizeof(BITMAPINFOHEADER) +
1664 iNumPaletteEntries * sizeof(RGBQUAD),
1665 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1668 HeapFree(GetProcessHeap(), 0, pPixelData);
1669 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1673 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1678 *ppBuffer = NULL; *pLength = 0;
1679 if (GetIconInfo(hIcon, &infoIcon)) {
1681 BITMAPINFO * pInfoBitmap;
1682 unsigned char * pIconData = NULL;
1683 unsigned int iDataSize = 0;
1685 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1687 /* Find out icon size */
1689 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1690 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1692 /* Auxiliary pointers */
1693 CURSORICONFILEDIR * pIconDir;
1694 CURSORICONFILEDIRENTRY * pIconEntry;
1695 BITMAPINFOHEADER * pIconBitmapHeader;
1696 unsigned int iOffsetPalette;
1697 unsigned int iOffsetColorData;
1698 unsigned int iOffsetMaskData;
1700 unsigned int iLengthScanLineColor;
1701 unsigned int iLengthScanLineMask;
1702 unsigned int iNumEntriesPalette;
1704 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1705 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1707 FIXME("DEBUG: bitmap size is %d x %d\n",
1708 pInfoBitmap->bmiHeader.biWidth,
1709 pInfoBitmap->bmiHeader.biHeight);
1710 FIXME("DEBUG: bitmap bpp is %d\n",
1711 pInfoBitmap->bmiHeader.biBitCount);
1712 FIXME("DEBUG: bitmap nplanes is %d\n",
1713 pInfoBitmap->bmiHeader.biPlanes);
1714 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1715 pInfoBitmap->bmiHeader.biSizeImage);
1717 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1718 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1719 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1721 /* Fill out the CURSORICONFILEDIR */
1722 pIconDir = (CURSORICONFILEDIR *)pIconData;
1723 pIconDir->idType = 1;
1724 pIconDir->idCount = 1;
1726 /* Fill out the CURSORICONFILEDIRENTRY */
1727 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1728 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1729 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1730 pIconEntry->bColorCount =
1731 (pInfoBitmap->bmiHeader.biBitCount < 8)
1732 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1734 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1735 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1736 pIconEntry->dwDIBSize = 0;
1737 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1739 /* Fill out the BITMAPINFOHEADER */
1740 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1741 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1743 /* Find out whether a palette exists for the bitmap */
1744 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1745 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1746 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1747 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1748 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1749 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1750 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1751 iNumEntriesPalette = 3;
1752 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1753 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1755 iNumEntriesPalette = 0;
1758 /* Add bitmap size and header size to icon data size. */
1759 iOffsetPalette = iDataSize;
1760 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1761 iOffsetColorData = iDataSize;
1762 iDataSize += pIconBitmapHeader->biSizeImage;
1763 iOffsetMaskData = iDataSize;
1764 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1765 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1766 pIconBitmapHeader->biHeight *= 2;
1767 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1768 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1769 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1770 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1772 /* Get the actual bitmap data from the icon bitmap */
1773 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1774 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1775 if (iNumEntriesPalette > 0) {
1776 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1777 iNumEntriesPalette * sizeof(RGBQUAD));
1780 /* Reset all values so that GetDIBits call succeeds */
1781 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1782 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1783 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1785 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1786 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1787 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1789 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1794 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1795 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1797 /* Write out everything produced so far to the stream */
1798 *ppBuffer = pIconData; *pLength = iDataSize;
1802 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1807 Remarks (from MSDN entry on GetIconInfo):
1809 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1810 members of ICONINFO. The calling application must manage
1811 these bitmaps and delete them when they are no longer
1814 if (hDC) ReleaseDC(0, hDC);
1815 DeleteObject(infoIcon.hbmMask);
1816 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1817 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1819 printf("ERROR: Unable to get icon information (error %lu)\n",
1825 static HRESULT WINAPI OLEPictureImpl_Save(
1826 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1828 HRESULT hResult = E_NOTIMPL;
1830 unsigned int iDataSize;
1832 int iSerializeResult = 0;
1834 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1836 switch (This->desc.picType) {
1838 if (This->bIsDirty) {
1839 if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1840 if (This->loadtime_magic != 0xdeadbeef) {
1843 header[0] = This->loadtime_magic;
1844 header[1] = iDataSize;
1845 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1847 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1849 HeapFree(GetProcessHeap(), 0, This->data);
1850 This->data = pIconData;
1851 This->datalen = iDataSize;
1854 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
1858 if (This->loadtime_magic != 0xdeadbeef) {
1861 header[0] = This->loadtime_magic;
1862 header[1] = This->datalen;
1863 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1865 IStream_Write(pStm, This->data, This->datalen, &dummy);
1869 case PICTYPE_BITMAP:
1870 if (This->bIsDirty) {
1871 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1873 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1876 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1879 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1882 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1885 if (iSerializeResult) {
1887 if (This->loadtime_magic != 0xdeadbeef) {
1892 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1893 header[1] = iDataSize;
1894 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1896 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1898 HeapFree(GetProcessHeap(), 0, This->data);
1899 This->data = pIconData;
1900 This->datalen = iDataSize;
1905 if (This->loadtime_magic != 0xdeadbeef) {
1910 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1911 header[1] = This->datalen;
1912 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1914 IStream_Write(pStm, This->data, This->datalen, &dummy);
1918 case PICTYPE_METAFILE:
1919 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1921 case PICTYPE_ENHMETAFILE:
1922 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1925 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1928 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1932 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1933 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1935 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1936 FIXME("(%p,%p),stub!\n",This,pcbSize);
1941 /************************************************************************
1945 /************************************************************************
1946 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1948 * See Windows documentation for more details on IUnknown methods.
1950 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1955 OLEPictureImpl *This = impl_from_IDispatch(iface);
1957 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1960 /************************************************************************
1961 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1963 * See Windows documentation for more details on IUnknown methods.
1965 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1968 OLEPictureImpl *This = impl_from_IDispatch(iface);
1970 return IPicture_AddRef((IPicture *)This);
1973 /************************************************************************
1974 * OLEPictureImpl_IDispatch_Release (IUnknown)
1976 * See Windows documentation for more details on IUnknown methods.
1978 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1981 OLEPictureImpl *This = impl_from_IDispatch(iface);
1983 return IPicture_Release((IPicture *)This);
1986 /************************************************************************
1987 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1989 * See Windows documentation for more details on IDispatch methods.
1991 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1993 unsigned int* pctinfo)
2000 /************************************************************************
2001 * OLEPictureImpl_GetTypeInfo (IDispatch)
2003 * See Windows documentation for more details on IDispatch methods.
2005 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
2009 ITypeInfo** ppTInfo)
2016 /************************************************************************
2017 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2019 * See Windows documentation for more details on IDispatch methods.
2021 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2024 LPOLESTR* rgszNames,
2034 /************************************************************************
2035 * OLEPictureImpl_Invoke (IDispatch)
2037 * See Windows documentation for more details on IDispatch methods.
2039 static HRESULT WINAPI OLEPictureImpl_Invoke(
2041 DISPID dispIdMember,
2045 DISPPARAMS* pDispParams,
2046 VARIANT* pVarResult,
2047 EXCEPINFO* pExepInfo,
2050 OLEPictureImpl *This = impl_from_IDispatch(iface);
2051 if (dispIdMember == DISPID_PICT_TYPE)
2053 TRACE("DISPID_PICT_TYPE\n");
2054 if (!(wFlags & INVOKE_PROPERTYGET))
2055 return DISP_E_PARAMNOTFOUND;
2056 if (pDispParams->cArgs != 0)
2057 return DISP_E_BADPARAMCOUNT;
2060 VariantInit(pVarResult);
2061 V_VT(pVarResult) = VT_I2;
2062 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2068 FIXME("(dispid: %ld):Stub\n",dispIdMember);
2070 VariantInit(pVarResult);
2071 V_VT(pVarResult) = VT_BOOL;
2072 V_BOOL(pVarResult) = FALSE;
2078 static const IPictureVtbl OLEPictureImpl_VTable =
2080 OLEPictureImpl_QueryInterface,
2081 OLEPictureImpl_AddRef,
2082 OLEPictureImpl_Release,
2083 OLEPictureImpl_get_Handle,
2084 OLEPictureImpl_get_hPal,
2085 OLEPictureImpl_get_Type,
2086 OLEPictureImpl_get_Width,
2087 OLEPictureImpl_get_Height,
2088 OLEPictureImpl_Render,
2089 OLEPictureImpl_set_hPal,
2090 OLEPictureImpl_get_CurDC,
2091 OLEPictureImpl_SelectPicture,
2092 OLEPictureImpl_get_KeepOriginalFormat,
2093 OLEPictureImpl_put_KeepOriginalFormat,
2094 OLEPictureImpl_PictureChanged,
2095 OLEPictureImpl_SaveAsFile,
2096 OLEPictureImpl_get_Attributes
2099 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2101 OLEPictureImpl_IDispatch_QueryInterface,
2102 OLEPictureImpl_IDispatch_AddRef,
2103 OLEPictureImpl_IDispatch_Release,
2104 OLEPictureImpl_GetTypeInfoCount,
2105 OLEPictureImpl_GetTypeInfo,
2106 OLEPictureImpl_GetIDsOfNames,
2107 OLEPictureImpl_Invoke
2110 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2112 OLEPictureImpl_IPersistStream_QueryInterface,
2113 OLEPictureImpl_IPersistStream_AddRef,
2114 OLEPictureImpl_IPersistStream_Release,
2115 OLEPictureImpl_GetClassID,
2116 OLEPictureImpl_IsDirty,
2117 OLEPictureImpl_Load,
2118 OLEPictureImpl_Save,
2119 OLEPictureImpl_GetSizeMax
2122 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2124 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2125 OLEPictureImpl_IConnectionPointContainer_AddRef,
2126 OLEPictureImpl_IConnectionPointContainer_Release,
2127 OLEPictureImpl_EnumConnectionPoints,
2128 OLEPictureImpl_FindConnectionPoint
2131 /***********************************************************************
2132 * OleCreatePictureIndirect (OLEAUT32.419)
2134 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2135 BOOL fOwn, LPVOID *ppvObj )
2137 OLEPictureImpl* newPict = NULL;
2140 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2151 * Try to construct a new instance of the class.
2153 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2155 if (newPict == NULL)
2156 return E_OUTOFMEMORY;
2159 * Make sure it supports the interface required by the caller.
2161 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2164 * Release the reference obtained in the constructor. If
2165 * the QueryInterface was unsuccessful, it will free the class.
2167 IPicture_Release((IPicture*)newPict);
2173 /***********************************************************************
2174 * OleLoadPicture (OLEAUT32.418)
2176 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2177 REFIID riid, LPVOID *ppvObj )
2183 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2184 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2186 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2189 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2191 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2192 IPicture_Release(newpic);
2196 IPersistStream_Load(ps,lpstream);
2197 IPersistStream_Release(ps);
2198 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2200 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2201 IPicture_Release(newpic);
2205 /***********************************************************************
2206 * OleLoadPictureEx (OLEAUT32.401)
2208 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2209 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2215 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2216 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2218 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2221 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2223 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2224 IPicture_Release(newpic);
2228 IPersistStream_Load(ps,lpstream);
2229 IPersistStream_Release(ps);
2230 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2232 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2233 IPicture_Release(newpic);
2237 /***********************************************************************
2238 * OleLoadPicturePath (OLEAUT32.424)
2240 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2241 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2244 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2248 HGLOBAL hGlobal = NULL;
2249 DWORD dwBytesRead = 0;
2252 IPersistStream *pStream;
2255 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2256 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2257 debugstr_guid(riid), ppvRet);
2259 if (!ppvRet) return E_POINTER;
2261 if (strncmpW(szURLorPath, file, 7) == 0) {
2264 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2266 if (hFile == INVALID_HANDLE_VALUE)
2267 return E_UNEXPECTED;
2269 dwFileSize = GetFileSize(hFile, NULL);
2270 if (dwFileSize != INVALID_FILE_SIZE )
2272 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2275 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2278 GlobalFree(hGlobal);
2286 return E_UNEXPECTED;
2288 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2291 GlobalFree(hGlobal);
2298 hRes = CreateBindCtx(0, &pbc);
2299 if (SUCCEEDED(hRes))
2301 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2302 if (SUCCEEDED(hRes))
2304 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2305 IMoniker_Release(pmnk);
2307 IBindCtx_Release(pbc);
2313 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2314 &IID_IPicture, (LPVOID*)&ipicture);
2316 IStream_Release(stream);
2320 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2322 IStream_Release(stream);
2323 IPicture_Release(ipicture);
2327 hRes = IPersistStream_Load(pStream, stream);
2328 IPersistStream_Release(pStream);
2329 IStream_Release(stream);
2332 IPicture_Release(ipicture);
2336 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2338 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2340 IPicture_Release(ipicture);
2344 /*******************************************************************************
2345 * StdPic ClassFactory
2349 /* IUnknown fields */
2350 const IClassFactoryVtbl *lpVtbl;
2352 } IClassFactoryImpl;
2354 static HRESULT WINAPI
2355 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2356 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2358 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2359 return E_NOINTERFACE;
2363 SPCF_AddRef(LPCLASSFACTORY iface) {
2364 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2365 return InterlockedIncrement(&This->ref);
2368 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2369 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2370 /* static class, won't be freed */
2371 return InterlockedDecrement(&This->ref);
2374 static HRESULT WINAPI SPCF_CreateInstance(
2375 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2377 /* Creates an uninitialized picture */
2378 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2382 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2383 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2384 FIXME("(%p)->(%d),stub!\n",This,dolock);
2388 static const IClassFactoryVtbl SPCF_Vtbl = {
2389 SPCF_QueryInterface,
2392 SPCF_CreateInstance,
2395 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2397 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }