4 * Implementation of OLE IPicture and related interfaces
6 * Copyright 2000 Huw D M Davies for CodeWeavers.
7 * Copyright 2001 Marcus Meissner
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * Support PICTYPE_BITMAP and PICTYPE_ICON, altough only bitmaps very well..
26 * Lots of methods are just stubs.
29 * NOTES (or things that msdn doesn't tell you)
31 * The width and height properties are returned in HIMETRIC units (0.01mm)
32 * IPicture::Render also uses these to select a region of the src picture.
33 * A bitmap's size is converted into these units by using the screen resolution
34 * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
39 #include "wine/port.h"
48 /* Must be before wine includes, the header has things conflicting with
53 # ifndef SONAME_LIBUNGIF
54 # define SONAME_LIBUNGIF "libungif.so"
56 # ifndef SONAME_LIBGIF
57 # define SONAME_LIBGIF "libgif.so"
62 #define NONAMELESSUNION
63 #define NONAMELESSSTRUCT
75 #include "wine/debug.h"
76 #include "wine/unicode.h"
78 #include "wine/wingdi16.h"
79 #include "cursoricon.h"
82 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
84 #define UINT8 JPEG_UINT8
85 #define UINT16 JPEG_UINT16
89 #ifndef SONAME_LIBJPEG
90 #define SONAME_LIBJPEG "libjpeg.so"
94 WINE_DEFAULT_DEBUG_CHANNEL(ole);
96 /*************************************************************************
97 * Declaration of implementation class
100 typedef struct OLEPictureImpl {
103 * IPicture handles IUnknown
106 const IPictureVtbl *lpvtbl1;
107 const IDispatchVtbl *lpvtbl2;
108 const IPersistStreamVtbl *lpvtbl3;
109 const IConnectionPointContainerVtbl *lpvtbl4;
111 /* Object reference count */
114 /* We own the object and must destroy it ourselves */
117 /* Picture description */
120 /* These are the pixel size of a bitmap */
124 /* And these are the size of the picture converted into HIMETRIC units */
125 OLE_XSIZE_HIMETRIC himetricWidth;
126 OLE_YSIZE_HIMETRIC himetricHeight;
128 IConnectionPoint *pCP;
133 /* Bitmap transparency mask */
141 BOOL bIsDirty; /* Set to TRUE if picture has changed */
142 unsigned int loadtime_magic; /* If a length header was found, saves value */
143 unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
147 * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
149 #define ICOM_THIS_From_IDispatch(impl, name) \
150 impl *This = (impl*)(((char*)name)-sizeof(void*));
151 #define ICOM_THIS_From_IPersistStream(impl, name) \
152 impl *This = (impl*)(((char*)name)-2*sizeof(void*));
153 #define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
154 impl *This = (impl*)(((char*)name)-3*sizeof(void*));
157 * Predeclare VTables. They get initialized at the end.
159 static const IPictureVtbl OLEPictureImpl_VTable;
160 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
161 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
162 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
164 /***********************************************************************
165 * Implementation of the OLEPictureImpl class.
168 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
172 TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
173 if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
174 ERR("GetObject fails\n");
177 This->origWidth = bm.bmWidth;
178 This->origHeight = bm.bmHeight;
179 /* The width and height are stored in HIMETRIC units (0.01 mm),
180 so we take our pixel width divide by pixels per inch and
181 multiply by 25.4 * 100 */
182 /* Should we use GetBitmapDimension if available? */
183 hdcRef = CreateCompatibleDC(0);
184 This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
185 This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
189 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
193 TRACE("icon handle %p\n", This->desc.u.icon.hicon);
194 if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
198 TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
199 if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
200 ERR("GetObject fails on icon bitmap\n");
204 This->origWidth = bm.bmWidth;
205 This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
206 /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
208 This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
209 This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
210 ReleaseDC(0, hdcRef);
212 DeleteObject(infoIcon.hbmMask);
213 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
215 ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
219 /************************************************************************
220 * OLEPictureImpl_Construct
222 * This method will construct a new instance of the OLEPictureImpl
225 * The caller of this method must release the object when it's
228 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
230 OLEPictureImpl* newObject = 0;
233 TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
236 * Allocate space for the object.
238 newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
244 * Initialize the virtual function table.
246 newObject->lpvtbl1 = &OLEPictureImpl_VTable;
247 newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
248 newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
249 newObject->lpvtbl4 = &OLEPictureImpl_IConnectionPointContainer_VTable;
251 CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
254 * Start with one reference count. The caller of this function
255 * must release the interface pointer when it is done.
258 newObject->hDCCur = 0;
260 newObject->fOwn = fOwn;
262 /* dunno about original value */
263 newObject->keepOrigFormat = TRUE;
265 newObject->hbmMask = NULL;
266 newObject->hbmXor = NULL;
267 newObject->loadtime_magic = 0xdeadbeef;
268 newObject->loadtime_format = 0;
269 newObject->bIsDirty = FALSE;
272 if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
273 FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
275 memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
278 switch(pictDesc->picType) {
280 OLEPictureImpl_SetBitmap(newObject);
283 case PICTYPE_METAFILE:
284 TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
285 newObject->himetricWidth = pictDesc->u.wmf.xExt;
286 newObject->himetricHeight = pictDesc->u.wmf.yExt;
290 /* not sure what to do here */
291 newObject->himetricWidth = newObject->himetricHeight = 0;
295 OLEPictureImpl_SetIcon(newObject);
297 case PICTYPE_ENHMETAFILE:
299 FIXME("Unsupported type %d\n", pictDesc->picType);
300 newObject->himetricWidth = newObject->himetricHeight = 0;
304 newObject->desc.picType = PICTYPE_UNINITIALIZED;
307 TRACE("returning %p\n", newObject);
311 /************************************************************************
312 * OLEPictureImpl_Destroy
314 * This method is called by the Release method when the reference
315 * count goes down to 0. It will free all resources used by
317 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
319 TRACE("(%p)\n", Obj);
321 if(Obj->fOwn) { /* We need to destroy the picture */
322 switch(Obj->desc.picType) {
324 DeleteObject(Obj->desc.u.bmp.hbitmap);
325 if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
326 if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
328 case PICTYPE_METAFILE:
329 DeleteMetaFile(Obj->desc.u.wmf.hmeta);
332 DestroyIcon(Obj->desc.u.icon.hicon);
334 case PICTYPE_ENHMETAFILE:
335 DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
341 FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
345 HeapFree(GetProcessHeap(), 0, Obj->data);
346 HeapFree(GetProcessHeap(), 0, Obj);
349 static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
351 /************************************************************************
352 * OLEPictureImpl_QueryInterface (IUnknown)
354 * See Windows documentation for more details on IUnknown methods.
356 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
361 OLEPictureImpl *This = (OLEPictureImpl *)iface;
362 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
365 * Perform a sanity check on the parameters.
367 if ( (This==0) || (ppvObject==0) )
371 * Initialize the return parameter.
376 * Compare the riid with the interface IDs implemented by this object.
378 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
380 *ppvObject = (IPicture*)This;
382 else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
384 *ppvObject = (IPicture*)This;
386 else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
388 *ppvObject = (IDispatch*)&(This->lpvtbl2);
390 else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
392 *ppvObject = (IDispatch*)&(This->lpvtbl2);
394 else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
396 *ppvObject = (IPersistStream*)&(This->lpvtbl3);
398 else if (memcmp(&IID_IConnectionPointContainer, riid, sizeof(IID_IConnectionPointContainer)) == 0)
400 *ppvObject = (IConnectionPointContainer*)&(This->lpvtbl4);
403 * Check that we obtained an interface.
407 FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
408 return E_NOINTERFACE;
412 * Query Interface always increases the reference count by one when it is
415 OLEPictureImpl_AddRef((IPicture*)This);
419 /***********************************************************************
420 * OLEPicture_SendNotify (internal)
422 * Sends notification messages of changed properties to any interested
425 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
427 IEnumConnections *pEnum;
430 if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
432 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
433 IPropertyNotifySink *sink;
435 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
436 IPropertyNotifySink_OnChanged(sink, dispID);
437 IPropertyNotifySink_Release(sink);
438 IUnknown_Release(CD.pUnk);
440 IEnumConnections_Release(pEnum);
444 /************************************************************************
445 * OLEPictureImpl_AddRef (IUnknown)
447 * See Windows documentation for more details on IUnknown methods.
449 static ULONG WINAPI OLEPictureImpl_AddRef(
452 OLEPictureImpl *This = (OLEPictureImpl *)iface;
453 ULONG refCount = InterlockedIncrement(&This->ref);
455 TRACE("(%p)->(ref before=%ld)\n", This, refCount - 1);
460 /************************************************************************
461 * OLEPictureImpl_Release (IUnknown)
463 * See Windows documentation for more details on IUnknown methods.
465 static ULONG WINAPI OLEPictureImpl_Release(
468 OLEPictureImpl *This = (OLEPictureImpl *)iface;
469 ULONG refCount = InterlockedDecrement(&This->ref);
471 TRACE("(%p)->(ref before=%ld)\n", This, refCount + 1);
474 * If the reference count goes down to 0, perform suicide.
476 if (!refCount) OLEPictureImpl_Destroy(This);
482 /************************************************************************
483 * OLEPictureImpl_get_Handle
485 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
488 OLEPictureImpl *This = (OLEPictureImpl *)iface;
489 TRACE("(%p)->(%p)\n", This, phandle);
490 switch(This->desc.picType) {
495 *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
497 case PICTYPE_METAFILE:
498 *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
501 *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
503 case PICTYPE_ENHMETAFILE:
504 *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
507 FIXME("Unimplemented type %d\n", This->desc.picType);
510 TRACE("returning handle %08x\n", *phandle);
514 /************************************************************************
515 * OLEPictureImpl_get_hPal
517 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
520 OLEPictureImpl *This = (OLEPictureImpl *)iface;
521 FIXME("(%p)->(%p): stub, return 0 palette.\n", This, phandle);
527 /************************************************************************
528 * OLEPictureImpl_get_Type
530 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
533 OLEPictureImpl *This = (OLEPictureImpl *)iface;
534 TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
535 *ptype = This->desc.picType;
539 /************************************************************************
540 * OLEPictureImpl_get_Width
542 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
543 OLE_XSIZE_HIMETRIC *pwidth)
545 OLEPictureImpl *This = (OLEPictureImpl *)iface;
546 TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
547 *pwidth = This->himetricWidth;
551 /************************************************************************
552 * OLEPictureImpl_get_Height
554 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
555 OLE_YSIZE_HIMETRIC *pheight)
557 OLEPictureImpl *This = (OLEPictureImpl *)iface;
558 TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
559 *pheight = This->himetricHeight;
563 /************************************************************************
564 * OLEPictureImpl_Render
566 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
567 LONG x, LONG y, LONG cx, LONG cy,
568 OLE_XPOS_HIMETRIC xSrc,
569 OLE_YPOS_HIMETRIC ySrc,
570 OLE_XSIZE_HIMETRIC cxSrc,
571 OLE_YSIZE_HIMETRIC cySrc,
574 OLEPictureImpl *This = (OLEPictureImpl *)iface;
575 TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
576 This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
578 TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
579 prcWBounds->right, prcWBounds->bottom);
582 * While the documentation suggests this to be here (or after rendering?)
583 * it does cause an endless recursion in my sample app. -MM 20010804
584 OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
587 switch(This->desc.picType) {
593 /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
594 NB y-axis gets flipped */
596 hdcBmp = CreateCompatibleDC(0);
597 SetMapMode(hdcBmp, MM_ANISOTROPIC);
598 SetWindowOrgEx(hdcBmp, 0, 0, NULL);
599 SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
600 SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
601 SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
604 HDC hdcMask = CreateCompatibleDC(0);
605 HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
607 hbmpOld = SelectObject(hdcBmp, This->hbmXor);
609 SetMapMode(hdcMask, MM_ANISOTROPIC);
610 SetWindowOrgEx(hdcMask, 0, 0, NULL);
611 SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
612 SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
613 SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
615 SetBkColor(hdc, RGB(255, 255, 255));
616 SetTextColor(hdc, RGB(0, 0, 0));
617 StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND);
618 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
620 SelectObject(hdcMask, hOldbm);
623 hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
624 StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
627 SelectObject(hdcBmp, hbmpOld);
632 FIXME("Not quite correct implementation of rendering icons...\n");
633 DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
636 case PICTYPE_METAFILE:
637 case PICTYPE_ENHMETAFILE:
639 FIXME("type %d not implemented\n", This->desc.picType);
645 /************************************************************************
646 * OLEPictureImpl_set_hPal
648 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
651 OLEPictureImpl *This = (OLEPictureImpl *)iface;
652 FIXME("(%p)->(%08x): stub\n", This, hpal);
653 OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
657 /************************************************************************
658 * OLEPictureImpl_get_CurDC
660 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
663 OLEPictureImpl *This = (OLEPictureImpl *)iface;
664 TRACE("(%p), returning %p\n", This, This->hDCCur);
665 if (phdc) *phdc = This->hDCCur;
669 /************************************************************************
670 * OLEPictureImpl_SelectPicture
672 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
675 OLE_HANDLE *phbmpOut)
677 OLEPictureImpl *This = (OLEPictureImpl *)iface;
678 TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
679 if (This->desc.picType == PICTYPE_BITMAP) {
680 SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
683 *phdcOut = This->hDCCur;
684 This->hDCCur = hdcIn;
686 *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
689 FIXME("Don't know how to select picture type %d\n",This->desc.picType);
694 /************************************************************************
695 * OLEPictureImpl_get_KeepOriginalFormat
697 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
700 OLEPictureImpl *This = (OLEPictureImpl *)iface;
701 TRACE("(%p)->(%p)\n", This, pfKeep);
704 *pfKeep = This->keepOrigFormat;
708 /************************************************************************
709 * OLEPictureImpl_put_KeepOriginalFormat
711 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
714 OLEPictureImpl *This = (OLEPictureImpl *)iface;
715 TRACE("(%p)->(%d)\n", This, keep);
716 This->keepOrigFormat = keep;
717 /* FIXME: what DISPID notification here? */
721 /************************************************************************
722 * OLEPictureImpl_PictureChanged
724 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
726 OLEPictureImpl *This = (OLEPictureImpl *)iface;
727 TRACE("(%p)->()\n", This);
728 OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
729 This->bIsDirty = TRUE;
733 /************************************************************************
734 * OLEPictureImpl_SaveAsFile
736 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
741 OLEPictureImpl *This = (OLEPictureImpl *)iface;
742 FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
743 return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
746 /************************************************************************
747 * OLEPictureImpl_get_Attributes
749 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
752 OLEPictureImpl *This = (OLEPictureImpl *)iface;
753 TRACE("(%p)->(%p).\n", This, pdwAttr);
755 switch (This->desc.picType) {
756 case PICTYPE_BITMAP: if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break; /* not 'truly' scalable, see MSDN. */
757 case PICTYPE_ICON: *pdwAttr = PICTURE_TRANSPARENT;break;
758 case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
759 default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
765 /************************************************************************
766 * IConnectionPointContainer
769 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
770 IConnectionPointContainer* iface,
774 ICOM_THIS_From_IConnectionPointContainer(IPicture,iface);
776 return IPicture_QueryInterface(This,riid,ppvoid);
779 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
780 IConnectionPointContainer* iface)
782 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
784 return IPicture_AddRef(This);
787 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
788 IConnectionPointContainer* iface)
790 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
792 return IPicture_Release(This);
795 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
796 IConnectionPointContainer* iface,
797 IEnumConnectionPoints** ppEnum
799 ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
801 FIXME("(%p,%p), stub!\n",This,ppEnum);
805 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
806 IConnectionPointContainer* iface,
808 IConnectionPoint **ppCP
810 ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl, iface);
811 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
815 if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
816 return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
817 FIXME("tried to find connection point on %s?\n",debugstr_guid(riid));
820 /************************************************************************
823 /************************************************************************
824 * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
826 * See Windows documentation for more details on IUnknown methods.
828 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
829 IPersistStream* iface,
833 ICOM_THIS_From_IPersistStream(IPicture, iface);
835 return IPicture_QueryInterface(This, riid, ppvoid);
838 /************************************************************************
839 * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
841 * See Windows documentation for more details on IUnknown methods.
843 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
844 IPersistStream* iface)
846 ICOM_THIS_From_IPersistStream(IPicture, iface);
848 return IPicture_AddRef(This);
851 /************************************************************************
852 * OLEPictureImpl_IPersistStream_Release (IUnknown)
854 * See Windows documentation for more details on IUnknown methods.
856 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
857 IPersistStream* iface)
859 ICOM_THIS_From_IPersistStream(IPicture, iface);
861 return IPicture_Release(This);
864 /************************************************************************
865 * OLEPictureImpl_IPersistStream_GetClassID
867 static HRESULT WINAPI OLEPictureImpl_GetClassID(
868 IPersistStream* iface,CLSID* pClassID)
870 ICOM_THIS_From_IPersistStream(IPicture, iface);
871 FIXME("(%p),stub!\n",This);
875 /************************************************************************
876 * OLEPictureImpl_IPersistStream_IsDirty
878 static HRESULT WINAPI OLEPictureImpl_IsDirty(
879 IPersistStream* iface)
881 ICOM_THIS_From_IPersistStream(IPicture, iface);
882 FIXME("(%p),stub!\n",This);
886 #ifdef HAVE_JPEGLIB_H
888 static void *libjpeg_handle;
889 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
890 MAKE_FUNCPTR(jpeg_std_error);
891 MAKE_FUNCPTR(jpeg_CreateDecompress);
892 MAKE_FUNCPTR(jpeg_read_header);
893 MAKE_FUNCPTR(jpeg_start_decompress);
894 MAKE_FUNCPTR(jpeg_read_scanlines);
895 MAKE_FUNCPTR(jpeg_finish_decompress);
896 MAKE_FUNCPTR(jpeg_destroy_decompress);
899 static void *load_libjpeg(void)
901 if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) {
903 #define LOAD_FUNCPTR(f) \
904 if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \
905 libjpeg_handle = NULL; \
909 LOAD_FUNCPTR(jpeg_std_error);
910 LOAD_FUNCPTR(jpeg_CreateDecompress);
911 LOAD_FUNCPTR(jpeg_read_header);
912 LOAD_FUNCPTR(jpeg_start_decompress);
913 LOAD_FUNCPTR(jpeg_read_scanlines);
914 LOAD_FUNCPTR(jpeg_finish_decompress);
915 LOAD_FUNCPTR(jpeg_destroy_decompress);
918 return libjpeg_handle;
921 /* for the jpeg decompressor source manager. */
922 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
924 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
925 ERR("(), should not get here.\n");
929 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
930 TRACE("Skipping %ld bytes...\n", num_bytes);
931 cinfo->src->next_input_byte += num_bytes;
932 cinfo->src->bytes_in_buffer -= num_bytes;
935 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
936 ERR("(desired=%d), should not get here.\n",desired);
939 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
940 #endif /* HAVE_JPEGLIB_H */
942 #ifdef HAVE_GIF_LIB_H
944 static void *libungif_handle;
945 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
946 MAKE_FUNCPTR(DGifOpen);
947 MAKE_FUNCPTR(DGifSlurp);
948 MAKE_FUNCPTR(DGifCloseFile);
957 static void *load_libungif(void)
959 if(((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) ||
960 ((libungif_handle = wine_dlopen(SONAME_LIBGIF , RTLD_NOW, NULL, 0)) != NULL)
963 #define LOAD_FUNCPTR(f) \
964 if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
965 libungif_handle = NULL; \
969 LOAD_FUNCPTR(DGifOpen);
970 LOAD_FUNCPTR(DGifSlurp);
971 LOAD_FUNCPTR(DGifCloseFile);
974 return libungif_handle;
977 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
978 struct gifdata *gd = (struct gifdata*)gif->UserData;
980 if (len+gd->curoff > gd->len) {
981 FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
982 len = gd->len - gd->curoff;
984 memcpy(data, gd->data+gd->curoff, len);
989 #endif /* HAVE_GIF_LIB_H */
991 /************************************************************************
992 * OLEPictureImpl_IPersistStream_Load (IUnknown)
994 * Loads the binary data from the IStream. Starts at current position.
995 * There appears to be an 2 DWORD header:
999 * Currently implemented: BITMAP, ICON, JPEG, GIF
1001 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1002 HRESULT hr = E_FAIL;
1003 BOOL headerisdata = FALSE;
1004 ULONG xread, toread;
1009 ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
1011 TRACE("(%p,%p)\n",This,pStm);
1013 /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1014 * out whether we do.
1016 * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1017 * compound file. This may explain most, if not all, of the cases of "no header",
1018 * and the header validation should take this into account. At least in Visual Basic 6,
1019 * resource streams, valid headers are
1020 * header[0] == "lt\0\0",
1021 * header[1] == length_of_stream.
1023 hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1025 FIXME("Stat failed with hres %lx\n",hr);
1026 hr=IStream_Read(pStm,header,8,&xread);
1027 if (hr || xread!=8) {
1028 FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
1032 headerisdata = FALSE;
1034 if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
1037 if (!memcmp(&(header[0]), "GIF8", 4) || /* GIF header */
1038 !memcmp(&(header[0]), "BM", 2) || /* BMP header */
1039 !memcmp(&(header[0]), "\xff\xd8", 2) || /* JPEG header */
1040 (header[1] > statstg.cbSize.QuadPart) || /* invalid size */
1042 ) {/* Incorrect header, assume none. */
1043 headerisdata = TRUE;
1044 toread = statstg.cbSize.QuadPart-8;
1047 FIXME("Unknown stream header magic: %08lx\n", header[0]);
1052 This->datalen = toread+(headerisdata?8:0);
1053 xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1056 memcpy (xbuf, &header, 8);
1058 while (xread < This->datalen) {
1060 hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1065 if (xread != This->datalen)
1066 FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
1068 if (This->datalen == 0) { /* Marks the "NONE" picture */
1069 This->desc.picType = PICTYPE_NONE;
1073 magic = xbuf[0] + (xbuf[1]<<8);
1075 case 0x4947: { /* GIF */
1076 #ifdef HAVE_GIF_LIB_H
1086 int transparent = -1;
1090 if(!libungif_handle) {
1091 if(!load_libungif()) {
1092 FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF);
1100 gif = pDGifOpen((void*)&gd, _gif_inputfunc);
1101 ret = pDGifSlurp(gif);
1102 if (ret == GIF_ERROR) {
1103 FIXME("Failed reading GIF using libgif.\n");
1106 TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
1107 TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
1108 TRACE("imgcnt %d\n", gif->ImageCount);
1109 if (gif->ImageCount<1) {
1110 FIXME("GIF stream does not have images inside?\n");
1113 TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
1114 gif->Image.Width, gif->Image.Height,
1115 gif->Image.Left, gif->Image.Top,
1116 gif->Image.Interlace
1119 padding = (gif->SWidth+3) & ~3;
1120 bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(1<<gif->SColorResolution)*sizeof(RGBQUAD));
1121 bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
1122 si = gif->SavedImages+0;
1123 gid = &(si->ImageDesc);
1125 if (!cm) cm = gif->SColorMap;
1127 /* look for the transparent color extension */
1128 for (i = 0; i < si->ExtensionBlockCount; ++i) {
1129 eb = si->ExtensionBlocks + i;
1130 if (eb->Function == 0xF9 && eb->ByteCount == 4) {
1131 if ((eb->Bytes[0] & 1) == 1) {
1132 transparent = (unsigned char)eb->Bytes[3];
1137 for (i=0;i<(1<<gif->SColorResolution);i++) {
1138 bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
1139 bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
1140 bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
1141 if (i == transparent) {
1142 This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
1143 bmi->bmiColors[i].rgbGreen,
1144 bmi->bmiColors[i].rgbBlue);
1148 /* Map to in picture coordinates */
1149 for (i = 0, j = 0; i < gid->Height; i++) {
1150 if (gif->Image.Interlace) {
1152 bytes + (gid->Top + j) * padding + gid->Left,
1153 si->RasterBits + i * gid->Width,
1156 /* Lower bits of interlaced counter encode current interlace */
1157 if (j & 1) j += 2; /* Currently filling odd rows */
1158 else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
1159 else j += 8; /* Currently filling every 8th row or 4th row in-between */
1161 if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
1162 /* End of current interlace, go to next interlace */
1163 if (j & 2) j = 1; /* Next iteration fills odd rows */
1164 else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */
1165 else j = 4; /* Next iteration fills rows in-between rows mod 6 */
1169 bytes + (gid->Top + i) * padding + gid->Left,
1170 si->RasterBits + i * gid->Width,
1175 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1176 bmi->bmiHeader.biWidth = gif->SWidth;
1177 bmi->bmiHeader.biHeight = -gif->SHeight;
1178 bmi->bmiHeader.biPlanes = 1;
1179 bmi->bmiHeader.biBitCount = 8;
1180 bmi->bmiHeader.biCompression = BI_RGB;
1181 bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
1182 bmi->bmiHeader.biXPelsPerMeter = 0;
1183 bmi->bmiHeader.biYPelsPerMeter = 0;
1184 bmi->bmiHeader.biClrUsed = 1 << gif->SColorResolution;
1185 bmi->bmiHeader.biClrImportant = 0;
1188 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1197 if (transparent > -1) {
1198 /* Create the Mask */
1199 HDC hdc = CreateCompatibleDC(0);
1200 HDC hdcMask = CreateCompatibleDC(0);
1202 HBITMAP hOldbitmapmask;
1204 unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
1207 This->hbmXor = CreateDIBitmap(
1216 bmi->bmiColors[0].rgbRed = 0;
1217 bmi->bmiColors[0].rgbGreen = 0;
1218 bmi->bmiColors[0].rgbBlue = 0;
1219 bmi->bmiColors[1].rgbRed = 255;
1220 bmi->bmiColors[1].rgbGreen = 255;
1221 bmi->bmiColors[1].rgbBlue = 255;
1223 bmi->bmiHeader.biBitCount = 1;
1224 bmi->bmiHeader.biSizeImage = monopadding*gif->SHeight;
1225 bmi->bmiHeader.biClrUsed = 2;
1227 for (i = 0; i < gif->SHeight; i++) {
1228 unsigned char * colorPointer = bytes + padding * i;
1229 unsigned char * monoPointer = bytes + monopadding * i;
1230 for (j = 0; j < gif->SWidth; j++) {
1231 unsigned char pixel = colorPointer[j];
1232 if ((j & 7) == 0) monoPointer[j >> 3] = 0;
1233 if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
1237 hTempMask = CreateDIBitmap(
1247 bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
1248 This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1249 hOldbitmap = SelectObject(hdc, hTempMask);
1250 hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1252 SetBkColor(hdc, RGB(255, 255, 255));
1253 BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1255 /* We no longer need the original bitmap, so we apply the first
1256 transformation with the mask to speed up the rendering */
1257 SelectObject(hdc, This->hbmXor);
1258 SetBkColor(hdc, RGB(0,0,0));
1259 SetTextColor(hdc, RGB(255,255,255));
1260 BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1261 hdcMask, 0, 0, SRCAND);
1263 SelectObject(hdc, hOldbitmap);
1264 SelectObject(hdcMask, hOldbitmapmask);
1267 DeleteObject(hTempMask);
1271 This->desc.picType = PICTYPE_BITMAP;
1272 OLEPictureImpl_SetBitmap(This);
1273 pDGifCloseFile(gif);
1274 HeapFree(GetProcessHeap(),0,bytes);
1277 FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1281 case 0xd8ff: { /* JPEG */
1282 #ifdef HAVE_JPEGLIB_H
1283 struct jpeg_decompress_struct jd;
1284 struct jpeg_error_mgr jerr;
1287 JSAMPROW samprow,oldsamprow;
1288 BITMAPINFOHEADER bmi;
1291 struct jpeg_source_mgr xjsm;
1295 if(!libjpeg_handle) {
1296 if(!load_libjpeg()) {
1297 FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
1302 /* This is basically so we can use in-memory data for jpeg decompression.
1303 * We need to have all the functions.
1305 xjsm.next_input_byte = xbuf;
1306 xjsm.bytes_in_buffer = xread;
1307 xjsm.init_source = _jpeg_init_source;
1308 xjsm.fill_input_buffer = _jpeg_fill_input_buffer;
1309 xjsm.skip_input_data = _jpeg_skip_input_data;
1310 xjsm.resync_to_restart = _jpeg_resync_to_restart;
1311 xjsm.term_source = _jpeg_term_source;
1313 jd.err = pjpeg_std_error(&jerr);
1314 /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
1315 * jpeg_create_decompress(&jd); */
1316 pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
1318 ret=pjpeg_read_header(&jd,TRUE);
1319 jd.out_color_space = JCS_RGB;
1320 pjpeg_start_decompress(&jd);
1321 if (ret != JPEG_HEADER_OK) {
1322 ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1323 HeapFree(GetProcessHeap(),0,xbuf);
1327 bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1328 (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1329 samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1332 oldsamprow = samprow;
1333 while ( jd.output_scanline<jd.output_height ) {
1334 x = pjpeg_read_scanlines(&jd,&samprow,1);
1336 FIXME("failed to read current scanline?\n");
1339 /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1340 for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1341 *(bits++) = *(samprow+2);
1342 *(bits++) = *(samprow+1);
1343 *(bits++) = *(samprow);
1345 bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1346 samprow = oldsamprow;
1350 bmi.biSize = sizeof(bmi);
1351 bmi.biWidth = jd.output_width;
1352 bmi.biHeight = -jd.output_height;
1354 bmi.biBitCount = jd.output_components<<3;
1355 bmi.biCompression = BI_RGB;
1356 bmi.biSizeImage = jd.output_height*jd.output_width*jd.output_components;
1357 bmi.biXPelsPerMeter = 0;
1358 bmi.biYPelsPerMeter = 0;
1360 bmi.biClrImportant = 0;
1362 HeapFree(GetProcessHeap(),0,samprow);
1363 pjpeg_finish_decompress(&jd);
1364 pjpeg_destroy_decompress(&jd);
1366 This->desc.u.bmp.hbitmap=CreateDIBitmap(
1375 This->desc.picType = PICTYPE_BITMAP;
1376 OLEPictureImpl_SetBitmap(This);
1378 HeapFree(GetProcessHeap(),0,bits);
1380 ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1385 case 0x4d42: { /* Bitmap */
1386 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)xbuf;
1387 BITMAPINFO *bi = (BITMAPINFO*)(bfh+1);
1390 /* Does not matter whether this is a coreheader or not, we only use
1391 * components which are in both
1394 This->desc.u.bmp.hbitmap = CreateDIBitmap(
1398 xbuf+bfh->bfOffBits,
1403 This->desc.picType = PICTYPE_BITMAP;
1404 OLEPictureImpl_SetBitmap(This);
1408 case 0x0000: { /* ICON , first word is dwReserved */
1410 CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf;
1415 FIXME("icon.idReserved=%d\n",cifd->idReserved);
1416 FIXME("icon.idType=%d\n",cifd->idType);
1417 FIXME("icon.idCount=%d\n",cifd->idCount);
1419 for (i=0;i<cifd->idCount;i++) {
1420 FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1421 FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1422 FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1423 FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1424 FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1425 FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1426 FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1427 FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1431 /* If we have more than one icon, try to find the best.
1432 * this currently means '32 pixel wide'.
1434 if (cifd->idCount!=1) {
1435 for (i=0;i<cifd->idCount;i++) {
1436 if (cifd->idEntries[i].bWidth == 32)
1439 if (i==cifd->idCount) i=0;
1442 hicon = CreateIconFromResourceEx(
1443 xbuf+cifd->idEntries[i].dwDIBOffset,
1444 cifd->idEntries[i].dwDIBSize,
1447 cifd->idEntries[i].bWidth,
1448 cifd->idEntries[i].bHeight,
1452 FIXME("CreateIcon failed.\n");
1455 This->desc.picType = PICTYPE_ICON;
1456 This->desc.u.icon.hicon = hicon;
1457 This->origWidth = cifd->idEntries[i].bWidth;
1458 This->origHeight = cifd->idEntries[i].bHeight;
1459 hdcRef = CreateCompatibleDC(0);
1460 This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1461 This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1470 FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1472 for (i=0;i<xread+8;i++) {
1473 if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1474 else MESSAGE("%02x ",xbuf[i-8]);
1475 if (i % 10 == 9) MESSAGE("\n");
1481 This->bIsDirty = FALSE;
1483 /* FIXME: this notify is not really documented */
1485 OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1489 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength);
1490 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength);
1491 static HRESULT WINAPI OLEPictureImpl_Save(
1492 IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1494 HRESULT hResult = E_NOTIMPL;
1496 unsigned int iDataSize;
1498 int iSerializeResult = 0;
1500 ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
1502 switch (This->desc.picType) {
1504 if (This->bIsDirty) {
1505 if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1506 if (This->loadtime_magic != 0xdeadbeef) {
1509 header[0] = This->loadtime_magic;
1510 header[1] = iDataSize;
1511 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1513 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1515 HeapFree(GetProcessHeap(), 0, This->data);
1516 This->data = pIconData;
1517 This->datalen = iDataSize;
1520 FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty);
1524 if (This->loadtime_magic != 0xdeadbeef) {
1527 header[0] = This->loadtime_magic;
1528 header[1] = This->datalen;
1529 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1531 IStream_Write(pStm, This->data, This->datalen, &dummy);
1535 case PICTYPE_BITMAP:
1536 if (This->bIsDirty) {
1537 switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) {
1539 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1542 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1545 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1548 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1551 if (iSerializeResult) {
1553 if (This->loadtime_magic != 0xdeadbeef) {
1558 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1559 header[1] = iDataSize;
1560 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1562 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1564 HeapFree(GetProcessHeap(), 0, This->data);
1565 This->data = pIconData;
1566 This->datalen = iDataSize;
1571 if (This->loadtime_magic != 0xdeadbeef) {
1576 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1577 header[1] = This->datalen;
1578 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1580 IStream_Write(pStm, This->data, This->datalen, &dummy);
1584 case PICTYPE_METAFILE:
1585 FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1587 case PICTYPE_ENHMETAFILE:
1588 FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1591 FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1594 if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1598 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1602 BITMAPINFO * pInfoBitmap;
1603 int iNumPaletteEntries;
1604 unsigned char * pPixelData;
1605 BITMAPFILEHEADER * pFileHeader;
1606 BITMAPINFO * pInfoHeader;
1608 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1609 sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1611 /* Find out bitmap size and padded length */
1613 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1614 GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1616 /* Fetch bitmap palette & pixel data */
1618 pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1619 GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1621 /* Calculate the total length required for the BMP data */
1622 if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1623 iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1624 if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1626 if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1627 iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1629 iNumPaletteEntries = 0;
1632 sizeof(BITMAPFILEHEADER) +
1633 sizeof(BITMAPINFOHEADER) +
1634 iNumPaletteEntries * sizeof(RGBQUAD) +
1635 pInfoBitmap->bmiHeader.biSizeImage;
1636 *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1638 /* Fill the BITMAPFILEHEADER */
1639 pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
1640 pFileHeader->bfType = 0x4d42;
1641 pFileHeader->bfSize = *pLength;
1642 pFileHeader->bfOffBits =
1643 sizeof(BITMAPFILEHEADER) +
1644 sizeof(BITMAPINFOHEADER) +
1645 iNumPaletteEntries * sizeof(RGBQUAD);
1647 /* Fill the BITMAPINFOHEADER and the palette data */
1648 pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1649 memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1651 (unsigned char *)(*ppBuffer) +
1652 sizeof(BITMAPFILEHEADER) +
1653 sizeof(BITMAPINFOHEADER) +
1654 iNumPaletteEntries * sizeof(RGBQUAD),
1655 pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1658 HeapFree(GetProcessHeap(), 0, pPixelData);
1659 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1663 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1668 *ppBuffer = NULL; *pLength = 0;
1669 if (GetIconInfo(hIcon, &infoIcon)) {
1671 BITMAPINFO * pInfoBitmap;
1672 unsigned char * pIconData = NULL;
1673 unsigned int iDataSize = 0;
1675 pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1677 /* Find out icon size */
1679 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1680 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1682 /* Auxiliary pointers */
1683 CURSORICONFILEDIR * pIconDir;
1684 CURSORICONFILEDIRENTRY * pIconEntry;
1685 BITMAPINFOHEADER * pIconBitmapHeader;
1686 unsigned int iOffsetPalette;
1687 unsigned int iOffsetColorData;
1688 unsigned int iOffsetMaskData;
1690 unsigned int iLengthScanLineColor;
1691 unsigned int iLengthScanLineMask;
1692 unsigned int iNumEntriesPalette;
1694 iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1695 iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1697 FIXME("DEBUG: bitmap size is %d x %d\n",
1698 pInfoBitmap->bmiHeader.biWidth,
1699 pInfoBitmap->bmiHeader.biHeight);
1700 FIXME("DEBUG: bitmap bpp is %d\n",
1701 pInfoBitmap->bmiHeader.biBitCount);
1702 FIXME("DEBUG: bitmap nplanes is %d\n",
1703 pInfoBitmap->bmiHeader.biPlanes);
1704 FIXME("DEBUG: bitmap biSizeImage is %lu\n",
1705 pInfoBitmap->bmiHeader.biSizeImage);
1707 /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1708 iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1709 pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1711 /* Fill out the CURSORICONFILEDIR */
1712 pIconDir = (CURSORICONFILEDIR *)pIconData;
1713 pIconDir->idType = 1;
1714 pIconDir->idCount = 1;
1716 /* Fill out the CURSORICONFILEDIRENTRY */
1717 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1718 pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1719 pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1720 pIconEntry->bColorCount =
1721 (pInfoBitmap->bmiHeader.biBitCount < 8)
1722 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1724 pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1725 pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1726 pIconEntry->dwDIBSize = 0;
1727 pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1729 /* Fill out the BITMAPINFOHEADER */
1730 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1731 memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER));
1733 /* Find out whether a palette exists for the bitmap */
1734 if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1735 || (pInfoBitmap->bmiHeader.biBitCount == 24)
1736 || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1737 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1738 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256;
1739 } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1740 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1741 iNumEntriesPalette = 3;
1742 } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1743 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1745 iNumEntriesPalette = 0;
1748 /* Add bitmap size and header size to icon data size. */
1749 iOffsetPalette = iDataSize;
1750 iDataSize += iNumEntriesPalette * sizeof(DWORD);
1751 iOffsetColorData = iDataSize;
1752 iDataSize += pIconBitmapHeader->biSizeImage;
1753 iOffsetMaskData = iDataSize;
1754 iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1755 pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1756 pIconBitmapHeader->biHeight *= 2;
1757 pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1758 pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1759 pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1760 pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1762 /* Get the actual bitmap data from the icon bitmap */
1763 GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1764 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1765 if (iNumEntriesPalette > 0) {
1766 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1767 iNumEntriesPalette * sizeof(RGBQUAD));
1770 /* Reset all values so that GetDIBits call succeeds */
1771 memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1772 memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1773 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1775 if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1776 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1777 pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1779 printf("ERROR: unable to get bitmap mask (error %lu)\n",
1784 GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1785 GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1787 /* Write out everything produced so far to the stream */
1788 *ppBuffer = pIconData; *pLength = iDataSize;
1792 printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n",
1797 Remarks (from MSDN entry on GetIconInfo):
1799 GetIconInfo creates bitmaps for the hbmMask and hbmColor
1800 members of ICONINFO. The calling application must manage
1801 these bitmaps and delete them when they are no longer
1804 if (hDC) ReleaseDC(0, hDC);
1805 DeleteObject(infoIcon.hbmMask);
1806 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1807 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1809 printf("ERROR: Unable to get icon information (error %lu)\n",
1815 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1816 IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1818 ICOM_THIS_From_IPersistStream(IPicture, iface);
1819 FIXME("(%p,%p),stub!\n",This,pcbSize);
1823 /************************************************************************
1826 /************************************************************************
1827 * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1829 * See Windows documentation for more details on IUnknown methods.
1831 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1836 ICOM_THIS_From_IDispatch(IPicture, iface);
1838 return IPicture_QueryInterface(This, riid, ppvoid);
1841 /************************************************************************
1842 * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1844 * See Windows documentation for more details on IUnknown methods.
1846 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1849 ICOM_THIS_From_IDispatch(IPicture, iface);
1851 return IPicture_AddRef(This);
1854 /************************************************************************
1855 * OLEPictureImpl_IDispatch_Release (IUnknown)
1857 * See Windows documentation for more details on IUnknown methods.
1859 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1862 ICOM_THIS_From_IDispatch(IPicture, iface);
1864 return IPicture_Release(This);
1867 /************************************************************************
1868 * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1870 * See Windows documentation for more details on IDispatch methods.
1872 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1874 unsigned int* pctinfo)
1881 /************************************************************************
1882 * OLEPictureImpl_GetTypeInfo (IDispatch)
1884 * See Windows documentation for more details on IDispatch methods.
1886 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1890 ITypeInfo** ppTInfo)
1897 /************************************************************************
1898 * OLEPictureImpl_GetIDsOfNames (IDispatch)
1900 * See Windows documentation for more details on IDispatch methods.
1902 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1905 LPOLESTR* rgszNames,
1915 /************************************************************************
1916 * OLEPictureImpl_Invoke (IDispatch)
1918 * See Windows documentation for more details on IDispatch methods.
1920 static HRESULT WINAPI OLEPictureImpl_Invoke(
1922 DISPID dispIdMember,
1926 DISPPARAMS* pDispParams,
1927 VARIANT* pVarResult,
1928 EXCEPINFO* pExepInfo,
1931 FIXME("(dispid: %ld):Stub\n",dispIdMember);
1933 VariantInit(pVarResult);
1934 V_VT(pVarResult) = VT_BOOL;
1935 V_BOOL(pVarResult) = FALSE;
1940 static const IPictureVtbl OLEPictureImpl_VTable =
1942 OLEPictureImpl_QueryInterface,
1943 OLEPictureImpl_AddRef,
1944 OLEPictureImpl_Release,
1945 OLEPictureImpl_get_Handle,
1946 OLEPictureImpl_get_hPal,
1947 OLEPictureImpl_get_Type,
1948 OLEPictureImpl_get_Width,
1949 OLEPictureImpl_get_Height,
1950 OLEPictureImpl_Render,
1951 OLEPictureImpl_set_hPal,
1952 OLEPictureImpl_get_CurDC,
1953 OLEPictureImpl_SelectPicture,
1954 OLEPictureImpl_get_KeepOriginalFormat,
1955 OLEPictureImpl_put_KeepOriginalFormat,
1956 OLEPictureImpl_PictureChanged,
1957 OLEPictureImpl_SaveAsFile,
1958 OLEPictureImpl_get_Attributes
1961 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
1963 OLEPictureImpl_IDispatch_QueryInterface,
1964 OLEPictureImpl_IDispatch_AddRef,
1965 OLEPictureImpl_IDispatch_Release,
1966 OLEPictureImpl_GetTypeInfoCount,
1967 OLEPictureImpl_GetTypeInfo,
1968 OLEPictureImpl_GetIDsOfNames,
1969 OLEPictureImpl_Invoke
1972 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
1974 OLEPictureImpl_IPersistStream_QueryInterface,
1975 OLEPictureImpl_IPersistStream_AddRef,
1976 OLEPictureImpl_IPersistStream_Release,
1977 OLEPictureImpl_GetClassID,
1978 OLEPictureImpl_IsDirty,
1979 OLEPictureImpl_Load,
1980 OLEPictureImpl_Save,
1981 OLEPictureImpl_GetSizeMax
1984 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
1986 OLEPictureImpl_IConnectionPointContainer_QueryInterface,
1987 OLEPictureImpl_IConnectionPointContainer_AddRef,
1988 OLEPictureImpl_IConnectionPointContainer_Release,
1989 OLEPictureImpl_EnumConnectionPoints,
1990 OLEPictureImpl_FindConnectionPoint
1993 /***********************************************************************
1994 * OleCreatePictureIndirect (OLEAUT32.419)
1996 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
1997 BOOL fOwn, LPVOID *ppvObj )
1999 OLEPictureImpl* newPict = NULL;
2002 TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2013 * Try to construct a new instance of the class.
2015 newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2017 if (newPict == NULL)
2018 return E_OUTOFMEMORY;
2021 * Make sure it supports the interface required by the caller.
2023 hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2026 * Release the reference obtained in the constructor. If
2027 * the QueryInterface was unsuccessful, it will free the class.
2029 IPicture_Release((IPicture*)newPict);
2035 /***********************************************************************
2036 * OleLoadPicture (OLEAUT32.418)
2038 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2039 REFIID riid, LPVOID *ppvObj )
2045 TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2046 lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2048 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2051 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2053 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2054 IPicture_Release(newpic);
2058 IPersistStream_Load(ps,lpstream);
2059 IPersistStream_Release(ps);
2060 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2062 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2063 IPicture_Release(newpic);
2067 /***********************************************************************
2068 * OleLoadPictureEx (OLEAUT32.401)
2070 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2071 REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2077 FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2078 lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2080 hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2083 hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2085 FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2086 IPicture_Release(newpic);
2090 IPersistStream_Load(ps,lpstream);
2091 IPersistStream_Release(ps);
2092 hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2094 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2095 IPicture_Release(newpic);
2099 /***********************************************************************
2100 * OleLoadPicturePath (OLEAUT32.424)
2102 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2103 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2106 static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2110 HGLOBAL hGlobal = NULL;
2111 DWORD dwBytesRead = 0;
2114 IPersistStream *pStream;
2117 TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2118 debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2119 debugstr_guid(riid), ppvRet);
2121 if (!ppvRet) return E_POINTER;
2123 if (strncmpW(szURLorPath, file, 7) == 0) {
2126 hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2128 if (hFile == INVALID_HANDLE_VALUE)
2129 return E_UNEXPECTED;
2131 dwFileSize = GetFileSize(hFile, NULL);
2132 if (dwFileSize != INVALID_FILE_SIZE )
2134 hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2137 bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2140 GlobalFree(hGlobal);
2148 return E_UNEXPECTED;
2150 hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2153 GlobalFree(hGlobal);
2160 hRes = CreateBindCtx(0, &pbc);
2161 if (SUCCEEDED(hRes))
2163 hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2164 if (SUCCEEDED(hRes))
2166 hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2167 IMoniker_Release(pmnk);
2169 IBindCtx_Release(pbc);
2175 hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2176 &IID_IPicture, (LPVOID*)&ipicture);
2178 IStream_Release(stream);
2182 hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2184 IStream_Release(stream);
2185 IPicture_Release(ipicture);
2189 hRes = IPersistStream_Load(pStream, stream);
2190 IPersistStream_Release(pStream);
2191 IStream_Release(stream);
2194 IPicture_Release(ipicture);
2198 hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2200 FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2202 IPicture_Release(ipicture);
2206 /*******************************************************************************
2207 * StdPic ClassFactory
2211 /* IUnknown fields */
2212 const IClassFactoryVtbl *lpVtbl;
2214 } IClassFactoryImpl;
2216 static HRESULT WINAPI
2217 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2218 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2220 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2221 return E_NOINTERFACE;
2225 SPCF_AddRef(LPCLASSFACTORY iface) {
2226 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2227 return InterlockedIncrement(&This->ref);
2230 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2231 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2232 /* static class, won't be freed */
2233 return InterlockedDecrement(&This->ref);
2236 static HRESULT WINAPI SPCF_CreateInstance(
2237 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2239 /* Creates an uninitialized picture */
2240 return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2244 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2245 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2246 FIXME("(%p)->(%d),stub!\n",This,dolock);
2250 static const IClassFactoryVtbl SPCF_Vtbl = {
2251 SPCF_QueryInterface,
2254 SPCF_CreateInstance,
2257 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2259 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }