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
52 #define NONAMELESSUNION
53 #define NONAMELESSSTRUCT
65 #include "wine/debug.h"
66 #include "wine/unicode.h"
68 #include "wine/wingdi16.h"
71 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
73 #define UINT8 JPEG_UINT8
74 #define UINT16 JPEG_UINT16
76 #define boolean jpeg_boolean
80 #ifndef SONAME_LIBJPEG
81 #define SONAME_LIBJPEG "libjpeg" SONAME_EXT
87 WINE_DEFAULT_DEBUG_CHANNEL(ole);
100 } CURSORICONFILEDIRENTRY;
107 CURSORICONFILEDIRENTRY idEntries[1];
112 /*************************************************************************
113 * Declaration of implementation class
116 typedef struct OLEPictureImpl {
119 * IPicture handles IUnknown
122 const IPictureVtbl *lpVtbl;
123 const IDispatchVtbl *lpvtblIDispatch;
124 const IPersistStreamVtbl *lpvtblIPersistStream;
125 const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
127 /* Object reference count */
130 /* We own the object and must destroy it ourselves */
133 /* Picture description */
136 /* These are the pixel size of a bitmap */
140 /* And these are the size of the picture converted into HIMETRIC units */
141 OLE_XSIZE_HIMETRIC himetricWidth;
142 OLE_YSIZE_HIMETRIC himetricHeight;
144 IConnectionPoint *pCP;
149 /* Bitmap transparency mask */
157 BOOL bIsDirty; /* Set to TRUE if picture has changed */
158 unsigned int loadtime_magic; /* If a length header was found, saves value */
159 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
163 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
166 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
168 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
171 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
173 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
176 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
178 return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
182 * Predeclare VTables. They get initialized at the end.
184 static const IPictureVtbl OLEPictureImpl_VTable;
185 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
186 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
187 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
189 /***********************************************************************
190 * Implementation of the OLEPictureImpl class.
193 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
197 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
198 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
199 ERR("GetObject fails\n");
202 This->origWidth = bm.bmWidth;
203 This->origHeight = bm.bmHeight;
204 /* The width and height are stored in HIMETRIC units (0.01 mm),
205 so we take our pixel width divide by pixels per inch and
206 multiply by 25.4 * 100 */
207 /* Should we use GetBitmapDimension if available? */
208 hdcRef = CreateCompatibleDC(0);
209 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
210 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
214 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
218 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
219 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
223 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
224 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
225 ERR("GetObject fails on icon bitmap\n");
229 This->origWidth = bm.bmWidth;
230 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
231 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
233 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
234 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
235 ReleaseDC(0, hdcRef);
237 DeleteObject(infoIcon.hbmMask);
238 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
240 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
244 /************************************************************************
245 * OLEPictureImpl_Construct
247 * This method will construct a new instance of the OLEPictureImpl
250 * The caller of this method must release the object when it's
253 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
255 OLEPictureImpl* newObject = 0;
258 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
261 * Allocate space for the object.
263 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
269 * Initialize the virtual function table.
271 newObject->lpVtbl = &OLEPictureImpl_VTable;
272 newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
273 newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
274 newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
276 newObject->pCP = NULL;
277 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
280 HeapFree(GetProcessHeap(), 0, newObject);
285 * Start with one reference count. The caller of this function
286 * must release the interface pointer when it is done.
289 newObject->hDCCur = 0;
291 newObject->fOwn = fOwn;
293 /* dunno about original value */
294 newObject->keepOrigFormat = TRUE;
296 newObject->hbmMask = NULL;
297 newObject->hbmXor = NULL;
298 newObject->loadtime_magic = 0xdeadbeef;
299 newObject->loadtime_format = 0;
300 newObject->bIsDirty = FALSE;
303 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
305 switch(pictDesc->picType) {
307 OLEPictureImpl_SetBitmap(newObject);
310 case PICTYPE_METAFILE:
311 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
312 newObject->himetricWidth = pictDesc->u.wmf.xExt;
313 newObject->himetricHeight = pictDesc->u.wmf.yExt;
317 /* not sure what to do here */
318 newObject->himetricWidth = newObject->himetricHeight = 0;
322 OLEPictureImpl_SetIcon(newObject);
324 case PICTYPE_ENHMETAFILE:
326 FIXME("Unsupported type %d\n", pictDesc->picType);
327 newObject->himetricWidth = newObject->himetricHeight = 0;
331 newObject->desc.picType = PICTYPE_UNINITIALIZED;
334 TRACE("returning %p\n", newObject);
338 /************************************************************************
339 * OLEPictureImpl_Destroy
341 * This method is called by the Release method when the reference
342 * count goes down to 0. It will free all resources used by
344 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
346 TRACE("(%p)\n", Obj);
349 IConnectionPoint_Release(Obj->pCP);
351 if(Obj->fOwn) { /* We need to destroy the picture */
352 switch(Obj->desc.picType) {
354 DeleteObject(Obj->desc.u.bmp.hbitmap);
355 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
356 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
358 case PICTYPE_METAFILE:
359 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
362 DestroyIcon(Obj->desc.u.icon.hicon);
364 case PICTYPE_ENHMETAFILE:
365 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
368 case PICTYPE_UNINITIALIZED:
372 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
376 HeapFree(GetProcessHeap(), 0, Obj->data);
377 HeapFree(GetProcessHeap(), 0, Obj);
381 /************************************************************************
382 * OLEPictureImpl_AddRef (IUnknown)
384 * See Windows documentation for more details on IUnknown methods.
386 static ULONG WINAPI OLEPictureImpl_AddRef(
389 OLEPictureImpl *This = (OLEPictureImpl *)iface;
390 ULONG refCount = InterlockedIncrement(&This->ref);
392 TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
397 /************************************************************************
398 * OLEPictureImpl_Release (IUnknown)
400 * See Windows documentation for more details on IUnknown methods.
402 static ULONG WINAPI OLEPictureImpl_Release(
405 OLEPictureImpl *This = (OLEPictureImpl *)iface;
406 ULONG refCount = InterlockedDecrement(&This->ref);
408 TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
411 * If the reference count goes down to 0, perform suicide.
413 if (!refCount) OLEPictureImpl_Destroy(This);
418 /************************************************************************
419 * OLEPictureImpl_QueryInterface (IUnknown)
421 * See Windows documentation for more details on IUnknown methods.
423 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
428 OLEPictureImpl *This = (OLEPictureImpl *)iface;
429 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
432 * Perform a sanity check on the parameters.
434 if ( (This==0) || (ppvObject==0) )
438 * Initialize the return parameter.
443 * Compare the riid with the interface IDs implemented by this object.
445 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
446 *ppvObject = (IPicture*)This;
447 else if (IsEqualIID(&IID_IDispatch, riid))
448 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
449 else if (IsEqualIID(&IID_IPictureDisp, riid))
450 *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
451 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
452 *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
453 else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
454 *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
457 * Check that we obtained an interface.
461 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
462 return E_NOINTERFACE;
466 * Query Interface always increases the reference count by one when it is
469 OLEPictureImpl_AddRef((IPicture*)This);
474 /***********************************************************************
475 * OLEPicture_SendNotify (internal)
477 * Sends notification messages of changed properties to any interested
480 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
482 IEnumConnections *pEnum;
485 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
487 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
488 IPropertyNotifySink *sink;
490 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
491 IPropertyNotifySink_OnChanged(sink, dispID);
492 IPropertyNotifySink_Release(sink);
493 IUnknown_Release(CD.pUnk);
495 IEnumConnections_Release(pEnum);
499 /************************************************************************
500 * OLEPictureImpl_get_Handle
502 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
505 OLEPictureImpl *This = (OLEPictureImpl *)iface;
506 TRACE("(%p)->(%p)\n", This, phandle);
507 switch(This->desc.picType) {
509 case PICTYPE_UNINITIALIZED:
513 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
515 case PICTYPE_METAFILE:
516 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
519 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
521 case PICTYPE_ENHMETAFILE:
522 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
525 FIXME("Unimplemented type %d\n", This->desc.picType);
528 TRACE("returning handle %08x\n", *phandle);
532 /************************************************************************
533 * OLEPictureImpl_get_hPal
535 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
538 OLEPictureImpl *This = (OLEPictureImpl *)iface;
540 TRACE("(%p)->(%p)\n", This, phandle);
545 switch (This->desc.picType) {
546 case PICTYPE_UNINITIALIZED:
552 *phandle = (OLE_HANDLE)This->desc.u.bmp.hpal;
556 case PICTYPE_METAFILE:
557 case PICTYPE_ENHMETAFILE:
559 FIXME("unimplemented for type %d. Returning 0 palette.\n",
565 TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
569 /************************************************************************
570 * OLEPictureImpl_get_Type
572 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
575 OLEPictureImpl *This = (OLEPictureImpl *)iface;
576 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
577 *ptype = This->desc.picType;
581 /************************************************************************
582 * OLEPictureImpl_get_Width
584 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
585 OLE_XSIZE_HIMETRIC *pwidth)
587 OLEPictureImpl *This = (OLEPictureImpl *)iface;
588 TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
589 *pwidth = This->himetricWidth;
593 /************************************************************************
594 * OLEPictureImpl_get_Height
596 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
597 OLE_YSIZE_HIMETRIC *pheight)
599 OLEPictureImpl *This = (OLEPictureImpl *)iface;
600 TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
601 *pheight = This->himetricHeight;
605 /************************************************************************
606 * OLEPictureImpl_Render
608 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
609 LONG x, LONG y, LONG cx, LONG cy,
610 OLE_XPOS_HIMETRIC xSrc,
611 OLE_YPOS_HIMETRIC ySrc,
612 OLE_XSIZE_HIMETRIC cxSrc,
613 OLE_YSIZE_HIMETRIC cySrc,
616 OLEPictureImpl *This = (OLEPictureImpl *)iface;
617 TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
618 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
620 TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
621 prcWBounds->right, prcWBounds->bottom);
624 * While the documentation suggests this to be here (or after rendering?)
625 * it does cause an endless recursion in my sample app. -MM 20010804
626 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
629 switch(This->desc.picType) {
635 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
636 NB y-axis gets flipped */
638 hdcBmp = CreateCompatibleDC(0);
639 SetMapMode(hdcBmp, MM_ANISOTROPIC);
640 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
641 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
642 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
643 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
646 HDC hdcMask = CreateCompatibleDC(0);
647 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
649 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
651 SetMapMode(hdcMask, MM_ANISOTROPIC);
652 SetWindowOrgEx(hdcMask, 0, 0, NULL);
653 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
654 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
655 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
657 SetBkColor(hdc, RGB(255, 255, 255));
658 SetTextColor(hdc, RGB(0, 0, 0));
659 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
660 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
662 SelectObject(hdcMask, hOldbm);
665 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
666 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
669 SelectObject(hdcBmp, hbmpOld);
674 FIXME("Not quite correct implementation of rendering icons...\n");
675 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
678 case PICTYPE_METAFILE:
679 PlayMetaFile(hdc, This->desc.u.wmf.hmeta);
682 case PICTYPE_ENHMETAFILE:
684 RECT rc = { x, y, cx, cy };
685 PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
690 FIXME("type %d not implemented\n", This->desc.picType);
696 /************************************************************************
697 * OLEPictureImpl_set_hPal
699 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
702 OLEPictureImpl *This = (OLEPictureImpl *)iface;
703 FIXME("(%p)->(%08x): stub\n", This, hpal);
704 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
708 /************************************************************************
709 * OLEPictureImpl_get_CurDC
711 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
714 OLEPictureImpl *This = (OLEPictureImpl *)iface;
715 TRACE("(%p), returning %p\n", This, This->hDCCur);
716 if (phdc) *phdc = This->hDCCur;
720 /************************************************************************
721 * OLEPictureImpl_SelectPicture
723 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
726 OLE_HANDLE *phbmpOut)
728 OLEPictureImpl *This = (OLEPictureImpl *)iface;
729 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
730 if (This->desc.picType == PICTYPE_BITMAP) {
731 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
734 *phdcOut = This->hDCCur;
735 This->hDCCur = hdcIn;
737 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
740 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
745 /************************************************************************
746 * OLEPictureImpl_get_KeepOriginalFormat
748 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
751 OLEPictureImpl *This = (OLEPictureImpl *)iface;
752 TRACE("(%p)->(%p)\n", This, pfKeep);
755 *pfKeep = This->keepOrigFormat;
759 /************************************************************************
760 * OLEPictureImpl_put_KeepOriginalFormat
762 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
765 OLEPictureImpl *This = (OLEPictureImpl *)iface;
766 TRACE("(%p)->(%d)\n", This, keep);
767 This->keepOrigFormat = keep;
768 /* FIXME: what DISPID notification here? */
772 /************************************************************************
773 * OLEPictureImpl_PictureChanged
775 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
777 OLEPictureImpl *This = (OLEPictureImpl *)iface;
778 TRACE("(%p)->()\n", This);
779 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
780 This->bIsDirty = TRUE;
784 /************************************************************************
785 * OLEPictureImpl_SaveAsFile
787 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
792 OLEPictureImpl *This = (OLEPictureImpl *)iface;
793 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
794 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
797 /************************************************************************
798 * OLEPictureImpl_get_Attributes
800 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
803 OLEPictureImpl *This = (OLEPictureImpl *)iface;
804 TRACE("(%p)->(%p).\n", This, pdwAttr);
806 switch (This->desc.picType) {
807 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
808 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
809 case PICTYPE_ENHMETAFILE: /* fall through */
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 */
1002 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
1003 struct gifdata *gd = (struct gifdata*)gif->UserData;
1005 if (len+gd->curoff > gd->len) {
1006 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
1007 len = gd->len - gd->curoff;
1009 memcpy(data, gd->data+gd->curoff, len);
1015 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1026 int transparent = -1;
1033 gif = DGifOpen((void*)&gd, _gif_inputfunc);
1034 ret = DGifSlurp(gif);
1035 if (ret == GIF_ERROR) {
1036 FIXME("Failed reading GIF using libgif.\n");
1039 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1040 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1041 TRACE("imgcnt %d\n", gif->ImageCount);
1042 if (gif->ImageCount<1) {
1043 FIXME("GIF stream does not have images inside?\n");
1046 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1047 gif->Image.Width, gif->Image.Height,
1048 gif->Image.Left, gif->Image.Top,
1049 gif->Image.Interlace
1052 padding = (gif->SWidth+3) & ~3;
1053 si = gif->SavedImages+0;
1054 gid = &(si->ImageDesc);
1056 if (!cm) cm = gif->SColorMap;
1057 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
1058 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1060 /* look for the transparent color extension */
1061 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1062 eb = si->ExtensionBlocks + i;
1063 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1064 if ((eb->Bytes[0] & 1) == 1) {
1065 transparent = (unsigned char)eb->Bytes[3];
1070 for (i = 0; i < cm->ColorCount; i++) {
1071 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1072 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1073 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1074 if (i == transparent) {
1075 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1076 bmi->bmiColors[i].rgbGreen,
1077 bmi->bmiColors[i].rgbBlue);
1081 /* Map to in picture coordinates */
1082 for (i = 0, j = 0; i < gid->Height; i++) {
1083 if (gif->Image.Interlace) {
1085 bytes + (gid->Top + j) * padding + gid->Left,
1086 si->RasterBits + i * gid->Width,
1089 /* Lower bits of interlaced counter encode current interlace */
1090 if (j & 1) j += 2; /* Currently filling odd rows */
1091 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1092 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1094 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1095 /* End of current interlace, go to next interlace */
1096 if (j & 2) j = 1; /* Next iteration fills odd rows */
1097 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1098 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1102 bytes + (gid->Top + i) * padding + gid->Left,
1103 si->RasterBits + i * gid->Width,
1108 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1109 bmi->bmiHeader.biWidth = gif->SWidth;
1110 bmi->bmiHeader.biHeight = -gif->SHeight;
1111 bmi->bmiHeader.biPlanes = 1;
1112 bmi->bmiHeader.biBitCount = 8;
1113 bmi->bmiHeader.biCompression = BI_RGB;
1114 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1115 bmi->bmiHeader.biXPelsPerMeter = 0;
1116 bmi->bmiHeader.biYPelsPerMeter = 0;
1117 bmi->bmiHeader.biClrUsed = cm->ColorCount;
1118 bmi->bmiHeader.biClrImportant = 0;
1121 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1130 if (transparent > -1) {
1131 /* Create the Mask */
1132 HDC hdc = CreateCompatibleDC(0);
1133 HDC hdcMask = CreateCompatibleDC(0);
1135 HBITMAP hOldbitmapmask;
1137 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1140 This->hbmXor = CreateDIBitmap(
1149 bmi->bmiColors[0].rgbRed = 0;
1150 bmi->bmiColors[0].rgbGreen = 0;
1151 bmi->bmiColors[0].rgbBlue = 0;
1152 bmi->bmiColors[1].rgbRed = 255;
1153 bmi->bmiColors[1].rgbGreen = 255;
1154 bmi->bmiColors[1].rgbBlue = 255;
1156 bmi->bmiHeader.biBitCount = 1;
1157 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1158 bmi->bmiHeader.biClrUsed = 2;
1160 for (i = 0; i < gif->SHeight; i++) {
1161 unsigned char * colorPointer = bytes + padding * i;
1162 unsigned char * monoPointer = bytes + monopadding * i;
1163 for (j = 0; j < gif->SWidth; j++) {
1164 unsigned char pixel = colorPointer[j];
1165 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1166 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1170 hTempMask = CreateDIBitmap(
1180 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1181 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1182 hOldbitmap = SelectObject(hdc, hTempMask);
1183 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1185 SetBkColor(hdc, RGB(255, 255, 255));
1186 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1188 /* We no longer need the original bitmap, so we apply the first
1189 transformation with the mask to speed up the rendering */
1190 SelectObject(hdc, This->hbmXor);
1191 SetBkColor(hdc, RGB(0,0,0));
1192 SetTextColor(hdc, RGB(255,255,255));
1193 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1194 hdcMask, 0, 0, SRCAND);
1196 SelectObject(hdc, hOldbitmap);
1197 SelectObject(hdcMask, hOldbitmapmask);
1200 DeleteObject(hTempMask);
1204 This->desc.picType = PICTYPE_BITMAP;
1205 OLEPictureImpl_SetBitmap(This);
1207 HeapFree(GetProcessHeap(),0,bytes);
1211 static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1213 #ifdef HAVE_JPEGLIB_H
1214 struct jpeg_decompress_struct jd;
1215 struct jpeg_error_mgr jerr;
1218 JSAMPROW samprow,oldsamprow;
1219 BITMAPINFOHEADER bmi;
1222 struct jpeg_source_mgr xjsm;
1226 if(!libjpeg_handle) {
1227 if(!load_libjpeg()) {
1228 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1233 /* This is basically so we can use in-memory data for jpeg decompression.
1234 * We need to have all the functions.
1236 xjsm.next_input_byte = xbuf;
1237 xjsm.bytes_in_buffer = xread;
1238 xjsm.init_source = _jpeg_init_source;
1239 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1240 xjsm.skip_input_data = _jpeg_skip_input_data;
1241 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1242 xjsm.term_source = _jpeg_term_source;
1244 jd.err = pjpeg_std_error(&jerr);
1245 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1246 * jpeg_create_decompress(&jd); */
1247 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1249 ret=pjpeg_read_header(&jd,TRUE);
1250 jd.out_color_space = JCS_RGB;
1251 pjpeg_start_decompress(&jd);
1252 if (ret != JPEG_HEADER_OK) {
1253 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1254 HeapFree(GetProcessHeap(),0,xbuf);
1258 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1259 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1260 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1263 oldsamprow = samprow;
1264 while ( jd.output_scanline<jd.output_height ) {
1265 x = pjpeg_read_scanlines(&jd,&samprow,1);
1267 FIXME("failed to read current scanline?\n");
1270 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1271 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1272 *(bits++) = *(samprow+2);
1273 *(bits++) = *(samprow+1);
1274 *(bits++) = *(samprow);
1276 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1277 samprow = oldsamprow;
1281 bmi.biSize = sizeof(bmi);
1282 bmi.biWidth = jd.output_width;
1283 bmi.biHeight = -jd.output_height;
1285 bmi.biBitCount = jd.output_components<<3;
1286 bmi.biCompression = BI_RGB;
1287 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1288 bmi.biXPelsPerMeter = 0;
1289 bmi.biYPelsPerMeter = 0;
1291 bmi.biClrImportant = 0;
1293 HeapFree(GetProcessHeap(),0,samprow);
1294 pjpeg_finish_decompress(&jd);
1295 pjpeg_destroy_decompress(&jd);
1297 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1306 This->desc.picType = PICTYPE_BITMAP;
1307 OLEPictureImpl_SetBitmap(This);
1308 HeapFree(GetProcessHeap(),0,bits);
1311 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1316 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1318 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1319 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1322 /* Does not matter whether this is a coreheader or not, we only use
1323 * components which are in both
1326 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1330 xbuf+bfh->bfOffBits,
1335 This->desc.picType = PICTYPE_BITMAP;
1336 OLEPictureImpl_SetBitmap(This);
1340 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1343 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1348 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1349 FIXME("icon.idType=%d\n",cifd->idType);
1350 FIXME("icon.idCount=%d\n",cifd->idCount);
1352 for (i=0;i<cifd->idCount;i++) {
1353 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1354 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1355 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1356 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1357 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1358 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1359 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1360 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1364 /* If we have more than one icon, try to find the best.
1365 * this currently means '32 pixel wide'.
1367 if (cifd->idCount!=1) {
1368 for (i=0;i<cifd->idCount;i++) {
1369 if (cifd->idEntries[i].bWidth == 32)
1372 if (i==cifd->idCount) i=0;
1375 hicon = CreateIconFromResourceEx(
1376 xbuf+cifd->idEntries[i].dwDIBOffset,
1377 cifd->idEntries[i].dwDIBSize,
1380 cifd->idEntries[i].bWidth,
1381 cifd->idEntries[i].bHeight,
1385 FIXME("CreateIcon failed.\n");
1388 This->desc.picType = PICTYPE_ICON;
1389 This->desc.u.icon.hicon = hicon;
1390 This->origWidth = cifd->idEntries[i].bWidth;
1391 This->origHeight = cifd->idEntries[i].bHeight;
1392 hdcRef = CreateCompatibleDC(0);
1393 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1394 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1400 static HRESULT OLEPictureImpl_LoadMetafile(OLEPictureImpl *This,
1401 const BYTE *data, ULONG size)
1406 /* SetMetaFileBitsEx performs data check on its own */
1407 hmf = SetMetaFileBitsEx(size, data);
1410 This->desc.picType = PICTYPE_METAFILE;
1411 This->desc.u.wmf.hmeta = hmf;
1412 This->desc.u.wmf.xExt = 0;
1413 This->desc.u.wmf.yExt = 0;
1415 This->origWidth = 0;
1416 This->origHeight = 0;
1417 This->himetricWidth = 0;
1418 This->himetricHeight = 0;
1423 hemf = SetEnhMetaFileBits(size, data);
1424 if (!hemf) return E_FAIL;
1426 This->desc.picType = PICTYPE_ENHMETAFILE;
1427 This->desc.u.emf.hemf = hemf;
1429 This->origWidth = 0;
1430 This->origHeight = 0;
1431 This->himetricWidth = 0;
1432 This->himetricHeight = 0;
1437 /************************************************************************
1438 * OLEPictureImpl_IPersistStream_Load (IUnknown)
1440 * Loads the binary data from the IStream. Starts at current position.
1441 * There appears to be an 2 DWORD header:
1445 * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1447 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1448 HRESULT hr = E_FAIL;
1449 BOOL headerisdata = FALSE;
1450 BOOL statfailed = FALSE;
1451 ULONG xread, toread;
1457 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1459 TRACE("(%p,%p)\n",This,pStm);
1461 /****************************************************************************************
1462 * Part 1: Load the data
1464 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1465 * out whether we do.
1467 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1468 * compound file. This may explain most, if not all, of the cases of "no
1469 * header", and the header validation should take this into account.
1470 * At least in Visual Basic 6, resource streams, valid headers are
1471 * header[0] == "lt\0\0",
1472 * header[1] == length_of_stream.
1474 * Also handle streams where we do not have a working "Stat" method by
1475 * reading all data until the end of the stream.
1477 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1479 TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1481 /* we will read at least 8 byte ... just right below */
1482 statstg.cbSize.QuadPart = 8;
1487 headerisdata = FALSE;
1489 hr=IStream_Read(pStm,header,8,&xread);
1490 if (hr || xread!=8) {
1491 FIXME("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1494 headerread += xread;
1497 if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1498 if (toread != 0 && toread != header[1])
1499 FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1502 if (toread == 0) break;
1504 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1505 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1506 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1507 (header[1] > statstg.cbSize.QuadPart)|| /* invalid size */
1509 ) {/* Found start of bitmap data */
1510 headerisdata = TRUE;
1512 toread = statstg.cbSize.QuadPart-8;
1516 FIXME("Unknown stream header magic: %08x\n", header[0]);
1520 } while (!headerisdata);
1522 if (statfailed) { /* we don't know the size ... read all we get */
1524 int origsize = sizeinc;
1527 TRACE("Reading all data from stream.\n");
1528 xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1530 memcpy (xbuf, &header, 8);
1532 while (xread < origsize) {
1533 hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1538 if (!nread || hr) /* done, or error */
1540 if (xread == origsize) {
1541 origsize += sizeinc;
1542 sizeinc = 2*sizeinc; /* exponential increase */
1543 xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1547 TRACE("hr in no-stat loader case is %08x\n", hr);
1548 TRACE("loaded %d bytes.\n", xread);
1549 This->datalen = xread;
1552 This->datalen = toread+(headerisdata?8:0);
1553 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1556 memcpy (xbuf, &header, 8);
1558 while (xread < This->datalen) {
1560 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1565 if (xread != This->datalen)
1566 FIXME("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1568 if (This->datalen == 0) { /* Marks the "NONE" picture */
1569 This->desc.picType = PICTYPE_NONE;
1574 /****************************************************************************************
1575 * Part 2: Process the loaded data
1578 magic = xbuf[0] + (xbuf[1]<<8);
1580 case 0x4947: /* GIF */
1581 hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
1583 case 0xd8ff: /* JPEG */
1584 hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
1586 case 0x4d42: /* Bitmap */
1587 hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1589 case 0x0000: { /* ICON , first word is dwReserved */
1590 hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1597 /* let's see if it's a metafile */
1598 hr = OLEPictureImpl_LoadMetafile(This, xbuf, xread);
1599 if (hr == S_OK) break;
1601 FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1603 for (i=0;i<xread+8;i++) {
1604 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1605 else MESSAGE("%02x ",xbuf[i-8]);
1606 if (i % 10 == 9) MESSAGE("\n");
1612 This->bIsDirty = FALSE;
1614 /* FIXME: this notify is not really documented */
1616 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1620 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1624 BITMAPINFO * pInfoBitmap;
1625 int iNumPaletteEntries;
1626 unsigned char * pPixelData;
1627 BITMAPFILEHEADER * pFileHeader;
1628 BITMAPINFO * pInfoHeader;
1630 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1631 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1633 /* Find out bitmap size and padded length */
1635 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1636 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1638 /* Fetch bitmap palette & pixel data */
1640 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1641 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1643 /* Calculate the total length required for the BMP data */
1644 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1645 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1646 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1648 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1649 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1651 iNumPaletteEntries = 0;
1654 sizeof(BITMAPFILEHEADER) +
1655 sizeof(BITMAPINFOHEADER) +
1656 iNumPaletteEntries * sizeof(RGBQUAD) +
1657 pInfoBitmap->bmiHeader.biSizeImage;
1658 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1660 /* Fill the BITMAPFILEHEADER */
1661 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1662 pFileHeader->bfType = 0x4d42;
1663 pFileHeader->bfSize = *pLength;
1664 pFileHeader->bfOffBits =
1665 sizeof(BITMAPFILEHEADER) +
1666 sizeof(BITMAPINFOHEADER) +
1667 iNumPaletteEntries * sizeof(RGBQUAD);
1669 /* Fill the BITMAPINFOHEADER and the palette data */
1670 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1671 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1673 (unsigned char *)(*ppBuffer) +
1674 sizeof(BITMAPFILEHEADER) +
1675 sizeof(BITMAPINFOHEADER) +
1676 iNumPaletteEntries * sizeof(RGBQUAD),
1677 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1680 HeapFree(GetProcessHeap(), 0, pPixelData);
1681 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1685 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1690 *ppBuffer = NULL; *pLength = 0;
1691 if (GetIconInfo(hIcon, &infoIcon)) {
1693 BITMAPINFO * pInfoBitmap;
1694 unsigned char * pIconData = NULL;
1695 unsigned int iDataSize = 0;
1697 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1699 /* Find out icon size */
1701 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1702 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1704 /* Auxiliary pointers */
1705 CURSORICONFILEDIR * pIconDir;
1706 CURSORICONFILEDIRENTRY * pIconEntry;
1707 BITMAPINFOHEADER * pIconBitmapHeader;
1708 unsigned int iOffsetPalette;
1709 unsigned int iOffsetColorData;
1710 unsigned int iOffsetMaskData;
1712 unsigned int iLengthScanLineColor;
1713 unsigned int iLengthScanLineMask;
1714 unsigned int iNumEntriesPalette;
1716 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1717 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1719 FIXME("DEBUG: bitmap size is %d x %d\n",
1720 pInfoBitmap->bmiHeader.biWidth,
1721 pInfoBitmap->bmiHeader.biHeight);
1722 FIXME("DEBUG: bitmap bpp is %d\n",
1723 pInfoBitmap->bmiHeader.biBitCount);
1724 FIXME("DEBUG: bitmap nplanes is %d\n",
1725 pInfoBitmap->bmiHeader.biPlanes);
1726 FIXME("DEBUG: bitmap biSizeImage is %u\n",
1727 pInfoBitmap->bmiHeader.biSizeImage);
1729 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1730 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1731 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1733 /* Fill out the CURSORICONFILEDIR */
1734 pIconDir = (CURSORICONFILEDIR *)pIconData;
1735 pIconDir->idType = 1;
1736 pIconDir->idCount = 1;
1738 /* Fill out the CURSORICONFILEDIRENTRY */
1739 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1740 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1741 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1742 pIconEntry->bColorCount =
1743 (pInfoBitmap->bmiHeader.biBitCount < 8)
1744 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1746 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1747 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1748 pIconEntry->dwDIBSize = 0;
1749 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1751 /* Fill out the BITMAPINFOHEADER */
1752 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1753 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1755 /* Find out whether a palette exists for the bitmap */
1756 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1757 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1758 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1759 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1760 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1761 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1762 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1763 iNumEntriesPalette = 3;
1764 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1765 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1767 iNumEntriesPalette = 0;
1770 /* Add bitmap size and header size to icon data size. */
1771 iOffsetPalette = iDataSize;
1772 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1773 iOffsetColorData = iDataSize;
1774 iDataSize += pIconBitmapHeader->biSizeImage;
1775 iOffsetMaskData = iDataSize;
1776 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1777 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1778 pIconBitmapHeader->biHeight *= 2;
1779 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1780 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1781 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1782 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1784 /* Get the actual bitmap data from the icon bitmap */
1785 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1786 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1787 if (iNumEntriesPalette > 0) {
1788 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1789 iNumEntriesPalette * sizeof(RGBQUAD));
1792 /* Reset all values so that GetDIBits call succeeds */
1793 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1794 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1795 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1797 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1798 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1799 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1801 printf("ERROR: unable to get bitmap mask (error %u)\n",
1806 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1807 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1809 /* Write out everything produced so far to the stream */
1810 *ppBuffer = pIconData; *pLength = iDataSize;
1814 printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1819 Remarks (from MSDN entry on GetIconInfo):
1821 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1822 members of ICONINFO. The calling application must manage
1823 these bitmaps and delete them when they are no longer
1826 if (hDC) ReleaseDC(0, hDC);
1827 DeleteObject(infoIcon.hbmMask);
1828 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1829 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1831 printf("ERROR: Unable to get icon information (error %u)\n",
1837 static HRESULT WINAPI OLEPictureImpl_Save(
1838 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1840 HRESULT hResult = E_NOTIMPL;
1842 unsigned int iDataSize;
1844 int iSerializeResult = 0;
1845 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1847 TRACE("%p %p %d\n", This, pStm, fClearDirty);
1849 switch (This->desc.picType) {
1851 if (This->bIsDirty || !This->data) {
1852 if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1853 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1857 HeapFree(GetProcessHeap(), 0, This->data);
1858 This->data = pIconData;
1859 This->datalen = iDataSize;
1861 if (This->loadtime_magic != 0xdeadbeef) {
1864 header[0] = This->loadtime_magic;
1865 header[1] = This->datalen;
1866 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1868 IStream_Write(pStm, This->data, This->datalen, &dummy);
1872 case PICTYPE_BITMAP:
1873 if (This->bIsDirty) {
1874 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1876 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1879 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1882 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1885 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1888 if (iSerializeResult) {
1890 if (This->loadtime_magic != 0xdeadbeef) {
1895 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1896 header[1] = iDataSize;
1897 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1899 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1901 HeapFree(GetProcessHeap(), 0, This->data);
1902 This->data = pIconData;
1903 This->datalen = iDataSize;
1908 if (This->loadtime_magic != 0xdeadbeef) {
1913 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1914 header[1] = This->datalen;
1915 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1917 IStream_Write(pStm, This->data, This->datalen, &dummy);
1921 case PICTYPE_METAFILE:
1922 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1924 case PICTYPE_ENHMETAFILE:
1925 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1928 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1931 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1935 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1936 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1938 OLEPictureImpl *This = impl_from_IPersistStream(iface);
1939 FIXME("(%p,%p),stub!\n",This,pcbSize);
1944 /************************************************************************
1948 /************************************************************************
1949 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1951 * See Windows documentation for more details on IUnknown methods.
1953 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1958 OLEPictureImpl *This = impl_from_IDispatch(iface);
1960 return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1963 /************************************************************************
1964 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1966 * See Windows documentation for more details on IUnknown methods.
1968 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1971 OLEPictureImpl *This = impl_from_IDispatch(iface);
1973 return IPicture_AddRef((IPicture *)This);
1976 /************************************************************************
1977 * OLEPictureImpl_IDispatch_Release (IUnknown)
1979 * See Windows documentation for more details on IUnknown methods.
1981 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1984 OLEPictureImpl *This = impl_from_IDispatch(iface);
1986 return IPicture_Release((IPicture *)This);
1989 /************************************************************************
1990 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1992 * See Windows documentation for more details on IDispatch methods.
1994 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1996 unsigned int* pctinfo)
1998 TRACE("(%p)\n", pctinfo);
2005 /************************************************************************
2006 * OLEPictureImpl_GetTypeInfo (IDispatch)
2008 * See Windows documentation for more details on IDispatch methods.
2010 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
2014 ITypeInfo** ppTInfo)
2016 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
2020 TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
2025 hres = LoadTypeLib(stdole2tlb, &tl);
2028 ERR("Could not load stdole2.tlb\n");
2032 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
2034 ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
2039 /************************************************************************
2040 * OLEPictureImpl_GetIDsOfNames (IDispatch)
2042 * See Windows documentation for more details on IDispatch methods.
2044 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2047 LPOLESTR* rgszNames,
2057 /************************************************************************
2058 * OLEPictureImpl_Invoke (IDispatch)
2060 * See Windows documentation for more details on IDispatch methods.
2062 static HRESULT WINAPI OLEPictureImpl_Invoke(
2064 DISPID dispIdMember,
2068 DISPPARAMS* pDispParams,
2069 VARIANT* pVarResult,
2070 EXCEPINFO* pExepInfo,
2073 OLEPictureImpl *This = impl_from_IDispatch(iface);
2075 /* validate parameters */
2077 if (!IsEqualIID(riid, &IID_NULL))
2079 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2080 return DISP_E_UNKNOWNNAME;
2085 ERR("null pDispParams not allowed\n");
2086 return DISP_E_PARAMNOTOPTIONAL;
2089 if (wFlags & DISPATCH_PROPERTYGET)
2091 if (pDispParams->cArgs != 0)
2093 ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2094 return DISP_E_BADPARAMCOUNT;
2098 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2099 return DISP_E_PARAMNOTOPTIONAL;
2102 else if (wFlags & DISPATCH_PROPERTYPUT)
2104 if (pDispParams->cArgs != 1)
2106 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2107 return DISP_E_BADPARAMCOUNT;
2111 switch (dispIdMember)
2113 case DISPID_PICT_HANDLE:
2114 if (wFlags & DISPATCH_PROPERTYGET)
2116 TRACE("DISPID_PICT_HANDLE\n");
2117 V_VT(pVarResult) = VT_I4;
2118 return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2121 case DISPID_PICT_HPAL:
2122 if (wFlags & DISPATCH_PROPERTYGET)
2124 TRACE("DISPID_PICT_HPAL\n");
2125 V_VT(pVarResult) = VT_I4;
2126 return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2128 else if (wFlags & DISPATCH_PROPERTYPUT)
2132 TRACE("DISPID_PICT_HPAL\n");
2134 VariantInit(&vararg);
2135 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2139 hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2141 VariantClear(&vararg);
2145 case DISPID_PICT_TYPE:
2146 if (wFlags & DISPATCH_PROPERTYGET)
2148 TRACE("DISPID_PICT_TYPE\n");
2149 V_VT(pVarResult) = VT_I2;
2150 return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2153 case DISPID_PICT_WIDTH:
2154 if (wFlags & DISPATCH_PROPERTYGET)
2156 TRACE("DISPID_PICT_WIDTH\n");
2157 V_VT(pVarResult) = VT_I4;
2158 return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2161 case DISPID_PICT_HEIGHT:
2162 if (wFlags & DISPATCH_PROPERTYGET)
2164 TRACE("DISPID_PICT_HEIGHT\n");
2165 V_VT(pVarResult) = VT_I4;
2166 return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2171 ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2172 return DISP_E_MEMBERNOTFOUND;
2176 static const IPictureVtbl OLEPictureImpl_VTable =
2178 OLEPictureImpl_QueryInterface,
2179 OLEPictureImpl_AddRef,
2180 OLEPictureImpl_Release,
2181 OLEPictureImpl_get_Handle,
2182 OLEPictureImpl_get_hPal,
2183 OLEPictureImpl_get_Type,
2184 OLEPictureImpl_get_Width,
2185 OLEPictureImpl_get_Height,
2186 OLEPictureImpl_Render,
2187 OLEPictureImpl_set_hPal,
2188 OLEPictureImpl_get_CurDC,
2189 OLEPictureImpl_SelectPicture,
2190 OLEPictureImpl_get_KeepOriginalFormat,
2191 OLEPictureImpl_put_KeepOriginalFormat,
2192 OLEPictureImpl_PictureChanged,
2193 OLEPictureImpl_SaveAsFile,
2194 OLEPictureImpl_get_Attributes
2197 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2199 OLEPictureImpl_IDispatch_QueryInterface,
2200 OLEPictureImpl_IDispatch_AddRef,
2201 OLEPictureImpl_IDispatch_Release,
2202 OLEPictureImpl_GetTypeInfoCount,
2203 OLEPictureImpl_GetTypeInfo,
2204 OLEPictureImpl_GetIDsOfNames,
2205 OLEPictureImpl_Invoke
2208 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2210 OLEPictureImpl_IPersistStream_QueryInterface,
2211 OLEPictureImpl_IPersistStream_AddRef,
2212 OLEPictureImpl_IPersistStream_Release,
2213 OLEPictureImpl_GetClassID,
2214 OLEPictureImpl_IsDirty,
2215 OLEPictureImpl_Load,
2216 OLEPictureImpl_Save,
2217 OLEPictureImpl_GetSizeMax
2220 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2222 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2223 OLEPictureImpl_IConnectionPointContainer_AddRef,
2224 OLEPictureImpl_IConnectionPointContainer_Release,
2225 OLEPictureImpl_EnumConnectionPoints,
2226 OLEPictureImpl_FindConnectionPoint
2229 /***********************************************************************
2230 * OleCreatePictureIndirect (OLEAUT32.419)
2232 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2233 BOOL fOwn, LPVOID *ppvObj )
2235 OLEPictureImpl* newPict = NULL;
2238 TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2249 * Try to construct a new instance of the class.
2251 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2253 if (newPict == NULL)
2254 return E_OUTOFMEMORY;
2257 * Make sure it supports the interface required by the caller.
2259 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2262 * Release the reference obtained in the constructor. If
2263 * the QueryInterface was unsuccessful, it will free the class.
2265 IPicture_Release((IPicture*)newPict);
2271 /***********************************************************************
2272 * OleLoadPicture (OLEAUT32.418)
2274 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2275 REFIID riid, LPVOID *ppvObj )
2281 TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2282 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2284 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2287 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2289 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2290 IPicture_Release(newpic);
2294 IPersistStream_Load(ps,lpstream);
2295 IPersistStream_Release(ps);
2296 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2298 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2299 IPicture_Release(newpic);
2303 /***********************************************************************
2304 * OleLoadPictureEx (OLEAUT32.401)
2306 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2307 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2313 FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2314 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2316 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2319 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2321 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2322 IPicture_Release(newpic);
2326 IPersistStream_Load(ps,lpstream);
2327 IPersistStream_Release(ps);
2328 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2330 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2331 IPicture_Release(newpic);
2335 /***********************************************************************
2336 * OleLoadPicturePath (OLEAUT32.424)
2338 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2339 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2342 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2346 HGLOBAL hGlobal = NULL;
2347 DWORD dwBytesRead = 0;
2350 IPersistStream *pStream;
2353 TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2354 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2355 debugstr_guid(riid), ppvRet);
2357 if (!ppvRet) return E_POINTER;
2359 if (strncmpW(szURLorPath, file, 7) == 0) {
2362 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2364 if (hFile == INVALID_HANDLE_VALUE)
2365 return E_UNEXPECTED;
2367 dwFileSize = GetFileSize(hFile, NULL);
2368 if (dwFileSize != INVALID_FILE_SIZE )
2370 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2373 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2376 GlobalFree(hGlobal);
2384 return E_UNEXPECTED;
2386 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2389 GlobalFree(hGlobal);
2396 hRes = CreateBindCtx(0, &pbc);
2397 if (SUCCEEDED(hRes))
2399 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2400 if (SUCCEEDED(hRes))
2402 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2403 IMoniker_Release(pmnk);
2405 IBindCtx_Release(pbc);
2411 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2412 &IID_IPicture, (LPVOID*)&ipicture);
2414 IStream_Release(stream);
2418 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2420 IStream_Release(stream);
2421 IPicture_Release(ipicture);
2425 hRes = IPersistStream_Load(pStream, stream);
2426 IPersistStream_Release(pStream);
2427 IStream_Release(stream);
2430 IPicture_Release(ipicture);
2434 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2436 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2438 IPicture_Release(ipicture);
2442 /*******************************************************************************
2443 * StdPic ClassFactory
2447 /* IUnknown fields */
2448 const IClassFactoryVtbl *lpVtbl;
2450 } IClassFactoryImpl;
2452 static HRESULT WINAPI
2453 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2454 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2456 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2457 return E_NOINTERFACE;
2461 SPCF_AddRef(LPCLASSFACTORY iface) {
2462 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2463 return InterlockedIncrement(&This->ref);
2466 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2467 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2468 /* static class, won't be freed */
2469 return InterlockedDecrement(&This->ref);
2472 static HRESULT WINAPI SPCF_CreateInstance(
2473 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2475 /* Creates an uninitialized picture */
2476 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2480 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2481 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2482 FIXME("(%p)->(%d),stub!\n",This,dolock);
2486 static const IClassFactoryVtbl SPCF_Vtbl = {
2487 SPCF_QueryInterface,
2490 SPCF_CreateInstance,
2493 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2495 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }