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 */
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 */
1046 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
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)
1995 TRACE("(%p)", pctinfo);
2002 /************************************************************************
2003 * OLEPictureImpl_GetTypeInfo (IDispatch)
2005 * See Windows documentation for more details on IDispatch methods.
2007 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
2011 ITypeInfo** ppTInfo)
2013 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
2017 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
2022 hres = LoadTypeLib(stdole2tlb, &tl);
2025 ERR("Could not load stdole2.tlb\n");
2029 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
2031 ERR("Did not get IPictureDisp typeinfo from typelib, hres %lx\n", hres);
2036 /************************************************************************
2037 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2039 * See Windows documentation for more details on IDispatch methods.
2041 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2044 LPOLESTR* rgszNames,
2054 /************************************************************************
2055 * OLEPictureImpl_Invoke (IDispatch)
2057 * See Windows documentation for more details on IDispatch methods.
2059 static HRESULT WINAPI OLEPictureImpl_Invoke(
2061 DISPID dispIdMember,
2065 DISPPARAMS* pDispParams,
2066 VARIANT* pVarResult,
2067 EXCEPINFO* pExepInfo,
2070 OLEPictureImpl *This = impl_from_IDispatch(iface);
2072 /* validate parameters */
2074 if (!IsEqualIID(riid, &IID_NULL))
2076 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2077 return DISP_E_UNKNOWNNAME;
2082 ERR("null pDispParams not allowed\n");
2083 return DISP_E_PARAMNOTOPTIONAL;
2086 if (wFlags & DISPATCH_PROPERTYGET)
2088 if (pDispParams->cArgs != 0)
2090 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2091 return DISP_E_BADPARAMCOUNT;
2095 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2096 return DISP_E_PARAMNOTOPTIONAL;
2099 else if (wFlags & DISPATCH_PROPERTYPUT)
2101 if (pDispParams->cArgs != 1)
2103 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2104 return DISP_E_BADPARAMCOUNT;
2108 switch (dispIdMember)
2110 case DISPID_PICT_HANDLE:
2111 if (wFlags & DISPATCH_PROPERTYGET)
2113 TRACE("DISPID_PICT_HANDLE\n");
2114 V_VT(pVarResult) = VT_I4;
2115 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2118 case DISPID_PICT_HPAL:
2119 if (wFlags & DISPATCH_PROPERTYGET)
2121 TRACE("DISPID_PICT_HPAL\n");
2122 V_VT(pVarResult) = VT_I4;
2123 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2125 else if (wFlags & DISPATCH_PROPERTYPUT)
2129 TRACE("DISPID_PICT_HPAL\n");
2131 VariantInit(&vararg);
2132 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2136 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2138 VariantClear(&vararg);
2142 case DISPID_PICT_TYPE:
2143 if (wFlags & DISPATCH_PROPERTYGET)
2145 TRACE("DISPID_PICT_TYPE\n");
2146 V_VT(pVarResult) = VT_I2;
2147 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2150 case DISPID_PICT_WIDTH:
2151 if (wFlags & DISPATCH_PROPERTYGET)
2153 TRACE("DISPID_PICT_WIDTH\n");
2154 V_VT(pVarResult) = VT_I4;
2155 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2158 case DISPID_PICT_HEIGHT:
2159 if (wFlags & DISPATCH_PROPERTYGET)
2161 TRACE("DISPID_PICT_HEIGHT\n");
2162 V_VT(pVarResult) = VT_I4;
2163 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2168 ERR("invalid dispid 0x%lx or wFlags 0x%x\n", dispIdMember, wFlags);
2169 return DISP_E_MEMBERNOTFOUND;
2173 static const IPictureVtbl OLEPictureImpl_VTable =
2175 OLEPictureImpl_QueryInterface,
2176 OLEPictureImpl_AddRef,
2177 OLEPictureImpl_Release,
2178 OLEPictureImpl_get_Handle,
2179 OLEPictureImpl_get_hPal,
2180 OLEPictureImpl_get_Type,
2181 OLEPictureImpl_get_Width,
2182 OLEPictureImpl_get_Height,
2183 OLEPictureImpl_Render,
2184 OLEPictureImpl_set_hPal,
2185 OLEPictureImpl_get_CurDC,
2186 OLEPictureImpl_SelectPicture,
2187 OLEPictureImpl_get_KeepOriginalFormat,
2188 OLEPictureImpl_put_KeepOriginalFormat,
2189 OLEPictureImpl_PictureChanged,
2190 OLEPictureImpl_SaveAsFile,
2191 OLEPictureImpl_get_Attributes
2194 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2196 OLEPictureImpl_IDispatch_QueryInterface,
2197 OLEPictureImpl_IDispatch_AddRef,
2198 OLEPictureImpl_IDispatch_Release,
2199 OLEPictureImpl_GetTypeInfoCount,
2200 OLEPictureImpl_GetTypeInfo,
2201 OLEPictureImpl_GetIDsOfNames,
2202 OLEPictureImpl_Invoke
2205 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2207 OLEPictureImpl_IPersistStream_QueryInterface,
2208 OLEPictureImpl_IPersistStream_AddRef,
2209 OLEPictureImpl_IPersistStream_Release,
2210 OLEPictureImpl_GetClassID,
2211 OLEPictureImpl_IsDirty,
2212 OLEPictureImpl_Load,
2213 OLEPictureImpl_Save,
2214 OLEPictureImpl_GetSizeMax
2217 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2219 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2220 OLEPictureImpl_IConnectionPointContainer_AddRef,
2221 OLEPictureImpl_IConnectionPointContainer_Release,
2222 OLEPictureImpl_EnumConnectionPoints,
2223 OLEPictureImpl_FindConnectionPoint
2226 /***********************************************************************
2227 * OleCreatePictureIndirect (OLEAUT32.419)
2229 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2230 BOOL fOwn, LPVOID *ppvObj )
2232 OLEPictureImpl* newPict = NULL;
2235 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2246 * Try to construct a new instance of the class.
2248 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2250 if (newPict == NULL)
2251 return E_OUTOFMEMORY;
2254 * Make sure it supports the interface required by the caller.
2256 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2259 * Release the reference obtained in the constructor. If
2260 * the QueryInterface was unsuccessful, it will free the class.
2262 IPicture_Release((IPicture*)newPict);
2268 /***********************************************************************
2269 * OleLoadPicture (OLEAUT32.418)
2271 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2272 REFIID riid, LPVOID *ppvObj )
2278 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2279 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2281 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2284 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2286 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2287 IPicture_Release(newpic);
2291 IPersistStream_Load(ps,lpstream);
2292 IPersistStream_Release(ps);
2293 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2295 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2296 IPicture_Release(newpic);
2300 /***********************************************************************
2301 * OleLoadPictureEx (OLEAUT32.401)
2303 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2304 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2310 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2311 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2313 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2316 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2318 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2319 IPicture_Release(newpic);
2323 IPersistStream_Load(ps,lpstream);
2324 IPersistStream_Release(ps);
2325 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2327 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2328 IPicture_Release(newpic);
2332 /***********************************************************************
2333 * OleLoadPicturePath (OLEAUT32.424)
2335 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2336 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2339 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2343 HGLOBAL hGlobal = NULL;
2344 DWORD dwBytesRead = 0;
2347 IPersistStream *pStream;
2350 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2351 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2352 debugstr_guid(riid), ppvRet);
2354 if (!ppvRet) return E_POINTER;
2356 if (strncmpW(szURLorPath, file, 7) == 0) {
2359 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2361 if (hFile == INVALID_HANDLE_VALUE)
2362 return E_UNEXPECTED;
2364 dwFileSize = GetFileSize(hFile, NULL);
2365 if (dwFileSize != INVALID_FILE_SIZE )
2367 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2370 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2373 GlobalFree(hGlobal);
2381 return E_UNEXPECTED;
2383 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2386 GlobalFree(hGlobal);
2393 hRes = CreateBindCtx(0, &pbc);
2394 if (SUCCEEDED(hRes))
2396 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2397 if (SUCCEEDED(hRes))
2399 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2400 IMoniker_Release(pmnk);
2402 IBindCtx_Release(pbc);
2408 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2409 &IID_IPicture, (LPVOID*)&ipicture);
2411 IStream_Release(stream);
2415 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2417 IStream_Release(stream);
2418 IPicture_Release(ipicture);
2422 hRes = IPersistStream_Load(pStream, stream);
2423 IPersistStream_Release(pStream);
2424 IStream_Release(stream);
2427 IPicture_Release(ipicture);
2431 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2433 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2435 IPicture_Release(ipicture);
2439 /*******************************************************************************
2440 * StdPic ClassFactory
2444 /* IUnknown fields */
2445 const IClassFactoryVtbl *lpVtbl;
2447 } IClassFactoryImpl;
2449 static HRESULT WINAPI
2450 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2451 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2453 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2454 return E_NOINTERFACE;
2458 SPCF_AddRef(LPCLASSFACTORY iface) {
2459 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2460 return InterlockedIncrement(&This->ref);
2463 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2464 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2465 /* static class, won't be freed */
2466 return InterlockedDecrement(&This->ref);
2469 static HRESULT WINAPI SPCF_CreateInstance(
2470 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2472 /* Creates an uninitialized picture */
2473 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2477 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2478 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2479 FIXME("(%p)->(%d),stub!\n",This,dolock);
2483 static const IClassFactoryVtbl SPCF_Vtbl = {
2484 SPCF_QueryInterface,
2487 SPCF_CreateInstance,
2490 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2492 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }