wineps.drv: BS_DIBPATTERN brushes use a 32-bit handle in 32-bit mode.
[wine] / dlls / oleaut32 / olepicture.c
1 /*
2  * OLE Picture object
3  *
4  * Implementation of OLE IPicture and related interfaces
5  *
6  * Copyright 2000 Huw D M Davies for CodeWeavers.
7  * Copyright 2001 Marcus Meissner
8  * Copyright 2008 Kirill K. Smirnov
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  *
24  * BUGS
25  *
26  * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well..
27  * Lots of methods are just stubs.
28  *
29  *
30  * NOTES (or things that msdn doesn't tell you)
31  *
32  * The width and height properties are returned in HIMETRIC units (0.01mm)
33  * IPicture::Render also uses these to select a region of the src picture.
34  * A bitmap's size is converted into these units by using the screen resolution
35  * thus an 8x8 bitmap on a 96dpi screen has a size of 212x212 (8/96 * 2540).
36  *
37  */
38
39 #include "config.h"
40 #include "wine/port.h"
41
42 #ifdef HAVE_UNISTD_H
43 # include <unistd.h>
44 #endif
45 #include <stdarg.h>
46 #include <stdio.h>
47 #include <string.h>
48
49 #define COBJMACROS
50 #define NONAMELESSUNION
51 #define NONAMELESSSTRUCT
52
53 #include "winerror.h"
54 #include "windef.h"
55 #include "winbase.h"
56 #include "wingdi.h"
57 #include "winuser.h"
58 #include "ole2.h"
59 #include "olectl.h"
60 #include "oleauto.h"
61 #include "connpt.h"
62 #include "urlmon.h"
63 #include "wincodec.h"
64 #include "wine/debug.h"
65 #include "wine/unicode.h"
66 #include "wine/library.h"
67
68 WINE_DEFAULT_DEBUG_CHANNEL(ole);
69
70 #include "pshpack1.h"
71
72 /* Header for Aldus Placable Metafiles - a standard metafile follows */
73 typedef struct _APM_HEADER
74 {
75     DWORD key;
76     WORD handle;
77     SHORT left;
78     SHORT top;
79     SHORT right;
80     SHORT bottom;
81     WORD inch;
82     DWORD reserved;
83     WORD checksum;
84 } APM_HEADER;
85
86 typedef struct {
87     BYTE bWidth;
88     BYTE bHeight;
89     BYTE bColorCount;
90     BYTE bReserved;
91     WORD xHotspot;
92     WORD yHotspot;
93     DWORD dwDIBSize;
94     DWORD dwDIBOffset;
95 } CURSORICONFILEDIRENTRY;
96
97 typedef struct
98 {
99     WORD                idReserved;
100     WORD                idType;
101     WORD                idCount;
102     CURSORICONFILEDIRENTRY  idEntries[1];
103 } CURSORICONFILEDIR;
104
105 #include "poppack.h"
106
107 /*************************************************************************
108  *  Declaration of implementation class
109  */
110
111 typedef struct OLEPictureImpl {
112
113   /*
114    * IPicture handles IUnknown
115    */
116
117     const IPictureVtbl       *lpVtbl;
118     const IDispatchVtbl      *lpvtblIDispatch;
119     const IPersistStreamVtbl *lpvtblIPersistStream;
120     const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
121
122   /* Object reference count */
123     LONG ref;
124
125   /* We own the object and must destroy it ourselves */
126     BOOL fOwn;
127
128   /* Picture description */
129     PICTDESC desc;
130
131   /* These are the pixel size of a bitmap */
132     DWORD origWidth;
133     DWORD origHeight;
134
135   /* And these are the size of the picture converted into HIMETRIC units */
136     OLE_XSIZE_HIMETRIC himetricWidth;
137     OLE_YSIZE_HIMETRIC himetricHeight;
138
139     IConnectionPoint *pCP;
140
141     BOOL keepOrigFormat;
142     HDC hDCCur;
143
144   /* Bitmap transparency mask */
145     HBITMAP hbmMask;
146     HBITMAP hbmXor;
147     COLORREF rgbTrans;
148
149   /* data */
150     void* data;
151     int datalen;
152     BOOL bIsDirty;                  /* Set to TRUE if picture has changed */
153     unsigned int loadtime_magic;    /* If a length header was found, saves value */
154     unsigned int loadtime_format;   /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
155 } OLEPictureImpl;
156
157 /*
158  * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
159  */
160
161 static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
162 {
163     return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
164 }
165
166 static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
167 {
168     return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
169 }
170
171 static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
172 {
173     return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
174 }
175
176 /*
177  * Predeclare VTables.  They get initialized at the end.
178  */
179 static const IPictureVtbl OLEPictureImpl_VTable;
180 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
181 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
182 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
183
184 /***********************************************************************
185  * Implementation of the OLEPictureImpl class.
186  */
187
188 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
189   BITMAP bm;
190   HDC hdcRef;
191
192   TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
193   if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
194     ERR("GetObject fails\n");
195     return;
196   }
197   This->origWidth = bm.bmWidth;
198   This->origHeight = bm.bmHeight;
199   /* The width and height are stored in HIMETRIC units (0.01 mm),
200      so we take our pixel width divide by pixels per inch and
201      multiply by 25.4 * 100 */
202   /* Should we use GetBitmapDimension if available? */
203   hdcRef = CreateCompatibleDC(0);
204   This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
205   This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
206   DeleteDC(hdcRef);
207 }
208
209 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
210 {
211     ICONINFO infoIcon;
212
213     TRACE("icon handle %p\n", This->desc.u.icon.hicon);
214     if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
215         HDC hdcRef;
216         BITMAP bm;
217
218         TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
219         if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
220             ERR("GetObject fails on icon bitmap\n");
221             return;
222         }
223
224         This->origWidth = bm.bmWidth;
225         This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
226         /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
227         hdcRef = GetDC(0);
228         This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
229         This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
230         ReleaseDC(0, hdcRef);
231
232         DeleteObject(infoIcon.hbmMask);
233         if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
234     } else {
235         ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
236     }
237 }
238
239 /************************************************************************
240  * OLEPictureImpl_Construct
241  *
242  * This method will construct a new instance of the OLEPictureImpl
243  * class.
244  *
245  * The caller of this method must release the object when it's
246  * done with it.
247  */
248 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
249 {
250   OLEPictureImpl* newObject = 0;
251
252   if (pictDesc)
253       TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
254
255   /*
256    * Allocate space for the object.
257    */
258   newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
259
260   if (newObject==0)
261     return newObject;
262
263   /*
264    * Initialize the virtual function table.
265    */
266   newObject->lpVtbl = &OLEPictureImpl_VTable;
267   newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
268   newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
269   newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
270
271   newObject->pCP = NULL;
272   CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
273   if (!newObject->pCP)
274   {
275     HeapFree(GetProcessHeap(), 0, newObject);
276     return NULL;
277   }
278
279   /*
280    * Start with one reference count. The caller of this function
281    * must release the interface pointer when it is done.
282    */
283   newObject->ref        = 1;
284   newObject->hDCCur     = 0;
285
286   newObject->fOwn       = fOwn;
287
288   /* dunno about original value */
289   newObject->keepOrigFormat = TRUE;
290
291   newObject->hbmMask = NULL;
292   newObject->hbmXor = NULL;
293   newObject->loadtime_magic = 0xdeadbeef;
294   newObject->loadtime_format = 0;
295   newObject->bIsDirty = FALSE;
296
297   if (pictDesc) {
298       newObject->desc = *pictDesc;
299
300       switch(pictDesc->picType) {
301       case PICTYPE_BITMAP:
302         OLEPictureImpl_SetBitmap(newObject);
303         break;
304
305       case PICTYPE_METAFILE:
306         TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
307         newObject->himetricWidth = pictDesc->u.wmf.xExt;
308         newObject->himetricHeight = pictDesc->u.wmf.yExt;
309         break;
310
311       case PICTYPE_NONE:
312         /* not sure what to do here */
313         newObject->himetricWidth = newObject->himetricHeight = 0;
314         break;
315
316       case PICTYPE_ICON:
317         OLEPictureImpl_SetIcon(newObject);
318         break;
319       case PICTYPE_ENHMETAFILE:
320       default:
321         FIXME("Unsupported type %d\n", pictDesc->picType);
322         newObject->himetricWidth = newObject->himetricHeight = 0;
323         break;
324       }
325   } else {
326       newObject->desc.picType = PICTYPE_UNINITIALIZED;
327   }
328
329   TRACE("returning %p\n", newObject);
330   return newObject;
331 }
332
333 /************************************************************************
334  * OLEPictureImpl_Destroy
335  *
336  * This method is called by the Release method when the reference
337  * count goes down to 0. It will free all resources used by
338  * this object.  */
339 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
340 {
341   TRACE("(%p)\n", Obj);
342
343   if (Obj->pCP)
344     IConnectionPoint_Release(Obj->pCP);
345
346   if(Obj->fOwn) { /* We need to destroy the picture */
347     switch(Obj->desc.picType) {
348     case PICTYPE_BITMAP:
349       DeleteObject(Obj->desc.u.bmp.hbitmap);
350       if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
351       if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
352       break;
353     case PICTYPE_METAFILE:
354       DeleteMetaFile(Obj->desc.u.wmf.hmeta);
355       break;
356     case PICTYPE_ICON:
357       DestroyIcon(Obj->desc.u.icon.hicon);
358       break;
359     case PICTYPE_ENHMETAFILE:
360       DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
361       break;
362     case PICTYPE_NONE:
363     case PICTYPE_UNINITIALIZED:
364       /* Nothing to do */
365       break;
366     default:
367       FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
368       break;
369     }
370   }
371   HeapFree(GetProcessHeap(), 0, Obj->data);
372   HeapFree(GetProcessHeap(), 0, Obj);
373 }
374
375
376 /************************************************************************
377  * OLEPictureImpl_AddRef (IUnknown)
378  *
379  * See Windows documentation for more details on IUnknown methods.
380  */
381 static ULONG WINAPI OLEPictureImpl_AddRef(
382   IPicture* iface)
383 {
384   OLEPictureImpl *This = (OLEPictureImpl *)iface;
385   ULONG refCount = InterlockedIncrement(&This->ref);
386
387   TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
388
389   return refCount;
390 }
391
392 /************************************************************************
393  * OLEPictureImpl_Release (IUnknown)
394  *
395  * See Windows documentation for more details on IUnknown methods.
396  */
397 static ULONG WINAPI OLEPictureImpl_Release(
398       IPicture* iface)
399 {
400   OLEPictureImpl *This = (OLEPictureImpl *)iface;
401   ULONG refCount = InterlockedDecrement(&This->ref);
402
403   TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
404
405   /*
406    * If the reference count goes down to 0, perform suicide.
407    */
408   if (!refCount) OLEPictureImpl_Destroy(This);
409
410   return refCount;
411 }
412
413 /************************************************************************
414  * OLEPictureImpl_QueryInterface (IUnknown)
415  *
416  * See Windows documentation for more details on IUnknown methods.
417  */
418 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
419   IPicture*  iface,
420   REFIID  riid,
421   void**  ppvObject)
422 {
423   OLEPictureImpl *This = (OLEPictureImpl *)iface;
424   TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
425
426   /*
427    * Perform a sanity check on the parameters.
428    */
429   if ( (This==0) || (ppvObject==0) )
430     return E_INVALIDARG;
431
432   /*
433    * Initialize the return parameter.
434    */
435   *ppvObject = 0;
436
437   /*
438    * Compare the riid with the interface IDs implemented by this object.
439    */
440   if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
441     *ppvObject = This;
442   else if (IsEqualIID(&IID_IDispatch, riid))
443     *ppvObject = &This->lpvtblIDispatch;
444   else if (IsEqualIID(&IID_IPictureDisp, riid))
445     *ppvObject = &This->lpvtblIDispatch;
446   else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
447     *ppvObject = &This->lpvtblIPersistStream;
448   else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
449     *ppvObject = &This->lpvtblIConnectionPointContainer;
450
451   /*
452    * Check that we obtained an interface.
453    */
454   if ((*ppvObject)==0)
455   {
456     FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
457     return E_NOINTERFACE;
458   }
459
460   /*
461    * Query Interface always increases the reference count by one when it is
462    * successful
463    */
464   OLEPictureImpl_AddRef((IPicture*)This);
465
466   return S_OK;
467 }
468
469 /***********************************************************************
470  *    OLEPicture_SendNotify (internal)
471  *
472  * Sends notification messages of changed properties to any interested
473  * connections.
474  */
475 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
476 {
477   IEnumConnections *pEnum;
478   CONNECTDATA CD;
479
480   if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
481       return;
482   while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
483     IPropertyNotifySink *sink;
484
485     IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
486     IPropertyNotifySink_OnChanged(sink, dispID);
487     IPropertyNotifySink_Release(sink);
488     IUnknown_Release(CD.pUnk);
489   }
490   IEnumConnections_Release(pEnum);
491 }
492
493 /************************************************************************
494  * OLEPictureImpl_get_Handle
495  */
496 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
497                                                 OLE_HANDLE *phandle)
498 {
499   OLEPictureImpl *This = (OLEPictureImpl *)iface;
500   TRACE("(%p)->(%p)\n", This, phandle);
501
502   if(!phandle)
503     return E_POINTER;
504
505   switch(This->desc.picType) {
506   case PICTYPE_NONE:
507   case PICTYPE_UNINITIALIZED:
508     *phandle = 0;
509     break;
510   case PICTYPE_BITMAP:
511     *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
512     break;
513   case PICTYPE_METAFILE:
514     *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
515     break;
516   case PICTYPE_ICON:
517     *phandle = HandleToUlong(This->desc.u.icon.hicon);
518     break;
519   case PICTYPE_ENHMETAFILE:
520     *phandle = HandleToUlong(This->desc.u.emf.hemf);
521     break;
522   default:
523     FIXME("Unimplemented type %d\n", This->desc.picType);
524     return E_NOTIMPL;
525   }
526   TRACE("returning handle %08x\n", *phandle);
527   return S_OK;
528 }
529
530 /************************************************************************
531  * OLEPictureImpl_get_hPal
532  */
533 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
534                                               OLE_HANDLE *phandle)
535 {
536   OLEPictureImpl *This = (OLEPictureImpl *)iface;
537   HRESULT hres;
538   TRACE("(%p)->(%p)\n", This, phandle);
539
540   if (!phandle)
541     return E_POINTER;
542
543   switch (This->desc.picType) {
544     case (UINT)PICTYPE_UNINITIALIZED:
545     case PICTYPE_NONE:
546       *phandle = 0;
547       hres = S_FALSE;
548       break;
549     case PICTYPE_BITMAP:
550       *phandle = HandleToUlong(This->desc.u.bmp.hpal);
551       hres = S_OK;
552       break;
553     case PICTYPE_METAFILE:
554       hres = E_FAIL;
555       break;
556     case PICTYPE_ICON:
557     case PICTYPE_ENHMETAFILE:
558     default:
559       FIXME("unimplemented for type %d. Returning 0 palette.\n",
560            This->desc.picType);
561       *phandle = 0;
562       hres = S_OK;
563   }
564
565   TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
566   return hres;
567 }
568
569 /************************************************************************
570  * OLEPictureImpl_get_Type
571  */
572 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
573                                               short *ptype)
574 {
575   OLEPictureImpl *This = (OLEPictureImpl *)iface;
576   TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
577
578   if(!ptype)
579     return E_POINTER;
580
581   *ptype = This->desc.picType;
582   return S_OK;
583 }
584
585 /************************************************************************
586  * OLEPictureImpl_get_Width
587  */
588 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
589                                                OLE_XSIZE_HIMETRIC *pwidth)
590 {
591   OLEPictureImpl *This = (OLEPictureImpl *)iface;
592   TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
593   *pwidth = This->himetricWidth;
594   return S_OK;
595 }
596
597 /************************************************************************
598  * OLEPictureImpl_get_Height
599  */
600 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
601                                                 OLE_YSIZE_HIMETRIC *pheight)
602 {
603   OLEPictureImpl *This = (OLEPictureImpl *)iface;
604   TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
605   *pheight = This->himetricHeight;
606   return S_OK;
607 }
608
609 /************************************************************************
610  * OLEPictureImpl_Render
611  */
612 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
613                                             LONG x, LONG y, LONG cx, LONG cy,
614                                             OLE_XPOS_HIMETRIC xSrc,
615                                             OLE_YPOS_HIMETRIC ySrc,
616                                             OLE_XSIZE_HIMETRIC cxSrc,
617                                             OLE_YSIZE_HIMETRIC cySrc,
618                                             LPCRECT prcWBounds)
619 {
620   OLEPictureImpl *This = (OLEPictureImpl *)iface;
621   TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
622         This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
623   if(prcWBounds)
624     TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
625           prcWBounds->right, prcWBounds->bottom);
626
627   if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
628     return CTL_E_INVALIDPROPERTYVALUE;
629   }
630
631   /*
632    * While the documentation suggests this to be here (or after rendering?)
633    * it does cause an endless recursion in my sample app. -MM 20010804
634   OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
635    */
636
637   switch(This->desc.picType) {
638   case PICTYPE_UNINITIALIZED:
639   case PICTYPE_NONE:
640     /* nothing to do */
641     return S_OK;
642   case PICTYPE_BITMAP:
643     {
644       HBITMAP hbmpOld;
645       HDC hdcBmp;
646
647       /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
648          NB y-axis gets flipped */
649
650       hdcBmp = CreateCompatibleDC(0);
651       SetMapMode(hdcBmp, MM_ANISOTROPIC);
652       SetWindowOrgEx(hdcBmp, 0, 0, NULL);
653       SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
654       SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
655       SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
656
657       if (This->hbmMask) {
658           HDC hdcMask = CreateCompatibleDC(0);
659           HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
660
661           hbmpOld = SelectObject(hdcBmp, This->hbmXor);
662
663           SetMapMode(hdcMask, MM_ANISOTROPIC);
664           SetWindowOrgEx(hdcMask, 0, 0, NULL);
665           SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
666           SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
667           SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
668           
669           SetBkColor(hdc, RGB(255, 255, 255));    
670           SetTextColor(hdc, RGB(0, 0, 0));        
671           StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND); 
672           StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
673
674           SelectObject(hdcMask, hOldbm);
675           DeleteDC(hdcMask);
676       } else {
677           hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
678           StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
679       }
680
681       SelectObject(hdcBmp, hbmpOld);
682       DeleteDC(hdcBmp);
683     }
684     break;
685   case PICTYPE_ICON:
686     FIXME("Not quite correct implementation of rendering icons...\n");
687     DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
688     break;
689
690   case PICTYPE_METAFILE:
691   {
692     POINT prevOrg, prevWndOrg;
693     SIZE prevExt, prevWndExt;
694     int oldmode;
695
696     /* Render the WMF to the appropriate location by setting the
697        appropriate ratio between "device units" and "logical units" */
698     oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
699     /* For the "source rectangle" the y-axis must be inverted */
700     SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
701     SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
702     /* For the "destination rectangle" no inversion is necessary */
703     SetViewportOrgEx(hdc, x, y, &prevOrg);
704     SetViewportExtEx(hdc, cx, cy, &prevExt);
705
706     if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
707         ERR("PlayMetaFile failed!\n");
708
709     /* We're done, restore the DC to the previous settings for converting
710        logical units to device units */
711     SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
712     SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
713     SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
714     SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
715     SetMapMode(hdc, oldmode);
716     break;
717   }
718
719   case PICTYPE_ENHMETAFILE:
720   {
721     RECT rc = { x, y, x + cx, y + cy };
722     PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
723     break;
724   }
725
726   default:
727     FIXME("type %d not implemented\n", This->desc.picType);
728     return E_NOTIMPL;
729   }
730   return S_OK;
731 }
732
733 /************************************************************************
734  * OLEPictureImpl_set_hPal
735  */
736 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
737                                               OLE_HANDLE hpal)
738 {
739   OLEPictureImpl *This = (OLEPictureImpl *)iface;
740   FIXME("(%p)->(%08x): stub\n", This, hpal);
741   OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
742   return E_NOTIMPL;
743 }
744
745 /************************************************************************
746  * OLEPictureImpl_get_CurDC
747  */
748 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
749                                                HDC *phdc)
750 {
751   OLEPictureImpl *This = (OLEPictureImpl *)iface;
752   TRACE("(%p), returning %p\n", This, This->hDCCur);
753   if (phdc) *phdc = This->hDCCur;
754   return S_OK;
755 }
756
757 /************************************************************************
758  * OLEPictureImpl_SelectPicture
759  */
760 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
761                                                    HDC hdcIn,
762                                                    HDC *phdcOut,
763                                                    OLE_HANDLE *phbmpOut)
764 {
765   OLEPictureImpl *This = (OLEPictureImpl *)iface;
766   TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
767   if (This->desc.picType == PICTYPE_BITMAP) {
768       SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
769
770       if (phdcOut)
771           *phdcOut = This->hDCCur;
772       This->hDCCur = hdcIn;
773       if (phbmpOut)
774           *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
775       return S_OK;
776   } else {
777       FIXME("Don't know how to select picture type %d\n",This->desc.picType);
778       return E_FAIL;
779   }
780 }
781
782 /************************************************************************
783  * OLEPictureImpl_get_KeepOriginalFormat
784  */
785 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
786                                                             BOOL *pfKeep)
787 {
788   OLEPictureImpl *This = (OLEPictureImpl *)iface;
789   TRACE("(%p)->(%p)\n", This, pfKeep);
790   if (!pfKeep)
791       return E_POINTER;
792   *pfKeep = This->keepOrigFormat;
793   return S_OK;
794 }
795
796 /************************************************************************
797  * OLEPictureImpl_put_KeepOriginalFormat
798  */
799 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
800                                                             BOOL keep)
801 {
802   OLEPictureImpl *This = (OLEPictureImpl *)iface;
803   TRACE("(%p)->(%d)\n", This, keep);
804   This->keepOrigFormat = keep;
805   /* FIXME: what DISPID notification here? */
806   return S_OK;
807 }
808
809 /************************************************************************
810  * OLEPictureImpl_PictureChanged
811  */
812 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
813 {
814   OLEPictureImpl *This = (OLEPictureImpl *)iface;
815   TRACE("(%p)->()\n", This);
816   OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
817   This->bIsDirty = TRUE;
818   return S_OK;
819 }
820
821 /************************************************************************
822  * OLEPictureImpl_SaveAsFile
823  */
824 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
825                                                 IStream *pstream,
826                                                 BOOL SaveMemCopy,
827                                                 LONG *pcbSize)
828 {
829   OLEPictureImpl *This = (OLEPictureImpl *)iface;
830   FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
831   return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
832 }
833
834 /************************************************************************
835  * OLEPictureImpl_get_Attributes
836  */
837 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
838                                                     DWORD *pdwAttr)
839 {
840   OLEPictureImpl *This = (OLEPictureImpl *)iface;
841   TRACE("(%p)->(%p).\n", This, pdwAttr);
842
843   if(!pdwAttr)
844     return E_POINTER;
845
846   *pdwAttr = 0;
847   switch (This->desc.picType) {
848   case PICTYPE_UNINITIALIZED:
849   case PICTYPE_NONE: break;
850   case PICTYPE_BITMAP:  if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break;       /* not 'truly' scalable, see MSDN. */
851   case PICTYPE_ICON: *pdwAttr     = PICTURE_TRANSPARENT;break;
852   case PICTYPE_ENHMETAFILE: /* fall through */
853   case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
854   default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
855   }
856   return S_OK;
857 }
858
859
860 /************************************************************************
861  *    IConnectionPointContainer
862  */
863 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
864   IConnectionPointContainer* iface,
865   REFIID riid,
866   VOID** ppvoid)
867 {
868   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
869
870   return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
871 }
872
873 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
874   IConnectionPointContainer* iface)
875 {
876   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
877
878   return IPicture_AddRef((IPicture *)This);
879 }
880
881 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
882   IConnectionPointContainer* iface)
883 {
884   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
885
886   return IPicture_Release((IPicture *)This);
887 }
888
889 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
890   IConnectionPointContainer* iface,
891   IEnumConnectionPoints** ppEnum)
892 {
893   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
894
895   FIXME("(%p,%p), stub!\n",This,ppEnum);
896   return E_NOTIMPL;
897 }
898
899 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
900   IConnectionPointContainer* iface,
901   REFIID riid,
902   IConnectionPoint **ppCP)
903 {
904   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
905   TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
906   if (!ppCP)
907       return E_POINTER;
908   *ppCP = NULL;
909   if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
910       return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
911   FIXME("no connection point for %s\n",debugstr_guid(riid));
912   return CONNECT_E_NOCONNECTION;
913 }
914
915
916 /************************************************************************
917  *    IPersistStream
918  */
919
920 /************************************************************************
921  * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
922  *
923  * See Windows documentation for more details on IUnknown methods.
924  */
925 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
926   IPersistStream* iface,
927   REFIID     riid,
928   VOID**     ppvoid)
929 {
930   OLEPictureImpl *This = impl_from_IPersistStream(iface);
931
932   return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
933 }
934
935 /************************************************************************
936  * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
937  *
938  * See Windows documentation for more details on IUnknown methods.
939  */
940 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
941   IPersistStream* iface)
942 {
943   OLEPictureImpl *This = impl_from_IPersistStream(iface);
944
945   return IPicture_AddRef((IPicture *)This);
946 }
947
948 /************************************************************************
949  * OLEPictureImpl_IPersistStream_Release (IUnknown)
950  *
951  * See Windows documentation for more details on IUnknown methods.
952  */
953 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
954   IPersistStream* iface)
955 {
956   OLEPictureImpl *This = impl_from_IPersistStream(iface);
957
958   return IPicture_Release((IPicture *)This);
959 }
960
961 /************************************************************************
962  * OLEPictureImpl_IPersistStream_GetClassID
963  */
964 static HRESULT WINAPI OLEPictureImpl_GetClassID(
965   IPersistStream* iface,CLSID* pClassID)
966 {
967   TRACE("(%p)\n", pClassID);
968   *pClassID = CLSID_StdPicture;
969   return S_OK;
970 }
971
972 /************************************************************************
973  * OLEPictureImpl_IPersistStream_IsDirty
974  */
975 static HRESULT WINAPI OLEPictureImpl_IsDirty(
976   IPersistStream* iface)
977 {
978   OLEPictureImpl *This = impl_from_IPersistStream(iface);
979   FIXME("(%p),stub!\n",This);
980   return E_NOTIMPL;
981 }
982
983 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
984 {
985     BITMAPFILEHEADER    *bfh = (BITMAPFILEHEADER*)xbuf;
986     BITMAPINFO          *bi = (BITMAPINFO*)(bfh+1);
987     HDC                 hdcref;
988
989     /* Does not matter whether this is a coreheader or not, we only use
990      * components which are in both
991      */
992     hdcref = GetDC(0);
993     This->desc.u.bmp.hbitmap = CreateDIBitmap(
994         hdcref,
995         &(bi->bmiHeader),
996         CBM_INIT,
997         xbuf+bfh->bfOffBits,
998         bi,
999        DIB_RGB_COLORS
1000     );
1001     ReleaseDC(0, hdcref);
1002     if (This->desc.u.bmp.hbitmap == 0)
1003         return E_FAIL;
1004     This->desc.picType = PICTYPE_BITMAP;
1005     OLEPictureImpl_SetBitmap(This);
1006     return S_OK;
1007 }
1008
1009 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
1010 {
1011     HRESULT hr;
1012     BITMAPINFOHEADER bih;
1013     HDC hdcref;
1014     UINT width, height;
1015     UINT stride, buffersize;
1016     LPBYTE bits=NULL;
1017     WICRect rc;
1018     IWICBitmapSource *real_source;
1019     UINT x, y;
1020     COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
1021     BOOL has_alpha=FALSE;
1022
1023     hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
1024     if (FAILED(hr)) return hr;
1025
1026     hr = IWICBitmapSource_GetSize(real_source, &width, &height);
1027     if (FAILED(hr)) goto end;
1028
1029     bih.biSize = sizeof(bih);
1030     bih.biWidth = width;
1031     bih.biHeight = -height;
1032     bih.biPlanes = 1;
1033     bih.biBitCount = 32;
1034     bih.biCompression = BI_RGB;
1035     bih.biSizeImage = 0;
1036     bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
1037     bih.biYPelsPerMeter = 4085;
1038     bih.biClrUsed = 0;
1039     bih.biClrImportant = 0;
1040
1041     stride = 4 * width;
1042     buffersize = stride * height;
1043
1044     bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
1045     if (!bits)
1046     {
1047         hr = E_OUTOFMEMORY;
1048         goto end;
1049     }
1050
1051     rc.X = 0;
1052     rc.Y = 0;
1053     rc.Width = width;
1054     rc.Height = height;
1055     hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
1056     if (FAILED(hr))
1057         goto end;
1058
1059     hdcref = GetDC(0);
1060     This->desc.u.bmp.hbitmap = CreateDIBitmap(
1061         hdcref,
1062         &bih,
1063         CBM_INIT,
1064         bits,
1065         (BITMAPINFO*)&bih,
1066         DIB_RGB_COLORS);
1067
1068     if (This->desc.u.bmp.hbitmap == 0)
1069     {
1070         hr = E_FAIL;
1071         ReleaseDC(0, hdcref);
1072         goto end;
1073     }
1074
1075     This->desc.picType = PICTYPE_BITMAP;
1076     OLEPictureImpl_SetBitmap(This);
1077
1078     /* set transparent pixels to black, all others to white */
1079     for(y = 0; y < height; y++){
1080         for(x = 0; x < width; x++){
1081             DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
1082             if((*pixel & 0x80000000) == 0)
1083             {
1084                 has_alpha = TRUE;
1085                 *pixel = black;
1086             }
1087             else
1088                 *pixel = white;
1089         }
1090     }
1091
1092     if (has_alpha)
1093     {
1094         HDC hdcBmp, hdcXor, hdcMask;
1095         HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
1096
1097         This->hbmXor = CreateDIBitmap(
1098             hdcref,
1099             &bih,
1100             CBM_INIT,
1101             bits,
1102             (BITMAPINFO*)&bih,
1103             DIB_RGB_COLORS
1104         );
1105
1106         This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
1107         hdcBmp = CreateCompatibleDC(NULL);
1108         hdcXor = CreateCompatibleDC(NULL);
1109         hdcMask = CreateCompatibleDC(NULL);
1110
1111         hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
1112         hbmoldXor = SelectObject(hdcXor,This->hbmXor);
1113         hbmoldMask = SelectObject(hdcMask,This->hbmMask);
1114
1115         SetBkColor(hdcXor,black);
1116         BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
1117         BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
1118
1119         SelectObject(hdcBmp,hbmoldBmp);
1120         SelectObject(hdcXor,hbmoldXor);
1121         SelectObject(hdcMask,hbmoldMask);
1122
1123         DeleteDC(hdcBmp);
1124         DeleteDC(hdcXor);
1125         DeleteDC(hdcMask);
1126     }
1127
1128     ReleaseDC(0, hdcref);
1129
1130 end:
1131     HeapFree(GetProcessHeap(), 0, bits);
1132     IWICBitmapSource_Release(real_source);
1133     return hr;
1134 }
1135
1136 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
1137 {
1138     HRESULT hr;
1139     IWICImagingFactory *factory;
1140     IWICBitmapDecoder *decoder;
1141     IWICBitmapFrameDecode *framedecode;
1142     HRESULT initresult;
1143     IWICStream *stream;
1144
1145     initresult = CoInitialize(NULL);
1146
1147     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1148         &IID_IWICImagingFactory, (void**)&factory);
1149     if (SUCCEEDED(hr)) /* created factory */
1150     {
1151         hr = IWICImagingFactory_CreateStream(factory, &stream);
1152         IWICImagingFactory_Release(factory);
1153     }
1154
1155     if (SUCCEEDED(hr)) /* created stream */
1156     {
1157         hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
1158
1159         if (SUCCEEDED(hr)) /* initialized stream */
1160         {
1161             hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
1162                 &IID_IWICBitmapDecoder, (void**)&decoder);
1163             if (SUCCEEDED(hr)) /* created decoder */
1164             {
1165                 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
1166
1167                 if (SUCCEEDED(hr)) /* initialized decoder */
1168                     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
1169
1170                 IWICBitmapDecoder_Release(decoder);
1171             }
1172         }
1173
1174         IWICStream_Release(stream);
1175     }
1176
1177     if (SUCCEEDED(hr)) /* got framedecode */
1178     {
1179         hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
1180         IWICBitmapFrameDecode_Release(framedecode);
1181     }
1182
1183     if (SUCCEEDED(initresult)) CoUninitialize();
1184     return hr;
1185 }
1186
1187 /*****************************************************
1188 *   start of Icon-specific code
1189 */
1190
1191 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1192 {
1193     HICON hicon;
1194     CURSORICONFILEDIR   *cifd = (CURSORICONFILEDIR*)xbuf;
1195     HDC hdcRef;
1196     int i;
1197
1198     /*
1199     FIXME("icon.idReserved=%d\n",cifd->idReserved);
1200     FIXME("icon.idType=%d\n",cifd->idType);
1201     FIXME("icon.idCount=%d\n",cifd->idCount);
1202
1203     for (i=0;i<cifd->idCount;i++) {
1204         FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1205         FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1206         FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1207         FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1208         FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1209         FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1210         FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1211         FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1212     }
1213     */
1214     i=0;
1215     /* If we have more than one icon, try to find the best.
1216      * this currently means '32 pixel wide'.
1217      */
1218     if (cifd->idCount!=1) {
1219         for (i=0;i<cifd->idCount;i++) {
1220             if (cifd->idEntries[i].bWidth == 32)
1221                 break;
1222         }
1223         if (i==cifd->idCount) i=0;
1224     }
1225
1226     hicon = CreateIconFromResourceEx(
1227                 xbuf+cifd->idEntries[i].dwDIBOffset,
1228                 cifd->idEntries[i].dwDIBSize,
1229                 TRUE, /* is icon */
1230                 0x00030000,
1231                 cifd->idEntries[i].bWidth,
1232                 cifd->idEntries[i].bHeight,
1233                 0
1234     );
1235     if (!hicon) {
1236         ERR("CreateIcon failed.\n");
1237         return E_FAIL;
1238     } else {
1239         This->desc.picType = PICTYPE_ICON;
1240         This->desc.u.icon.hicon = hicon;
1241         This->origWidth = cifd->idEntries[i].bWidth;
1242         This->origHeight = cifd->idEntries[i].bHeight;
1243         hdcRef = CreateCompatibleDC(0);
1244         This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
1245         This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
1246         DeleteDC(hdcRef);
1247         return S_OK;
1248     }
1249 }
1250
1251 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
1252                                               const BYTE *data, ULONG size)
1253 {
1254     HENHMETAFILE hemf;
1255     ENHMETAHEADER hdr;
1256
1257     hemf = SetEnhMetaFileBits(size, data);
1258     if (!hemf) return E_FAIL;
1259
1260     GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
1261
1262     This->desc.picType = PICTYPE_ENHMETAFILE;
1263     This->desc.u.emf.hemf = hemf;
1264
1265     This->origWidth = 0;
1266     This->origHeight = 0;
1267     This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
1268     This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
1269
1270     return S_OK;
1271 }
1272
1273 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
1274                                       const BYTE *data, ULONG size)
1275 {
1276     APM_HEADER *header = (APM_HEADER *)data;
1277     HMETAFILE hmf;
1278
1279     if (size < sizeof(APM_HEADER))
1280         return E_FAIL;
1281     if (header->key != 0x9ac6cdd7)
1282         return E_FAIL;
1283
1284     /* SetMetaFileBitsEx performs data check on its own */
1285     hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
1286     if (!hmf) return E_FAIL;
1287
1288     This->desc.picType = PICTYPE_METAFILE;
1289     This->desc.u.wmf.hmeta = hmf;
1290     This->desc.u.wmf.xExt = 0;
1291     This->desc.u.wmf.yExt = 0;
1292
1293     This->origWidth = 0;
1294     This->origHeight = 0;
1295     This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
1296     This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
1297     return S_OK;
1298 }
1299
1300 /************************************************************************
1301  * BITMAP FORMAT FLAGS -
1302  *   Flags that differentiate between different types of bitmaps.
1303  */
1304
1305 #define BITMAP_FORMAT_BMP   0x4d42 /* "BM" */
1306 #define BITMAP_FORMAT_JPEG  0xd8ff
1307 #define BITMAP_FORMAT_GIF   0x4947
1308 #define BITMAP_FORMAT_PNG   0x5089
1309 #define BITMAP_FORMAT_APM   0xcdd7
1310
1311 /************************************************************************
1312  * OLEPictureImpl_IPersistStream_Load (IUnknown)
1313  *
1314  * Loads the binary data from the IStream. Starts at current position.
1315  * There appears to be an 2 DWORD header:
1316  *      DWORD magic;
1317  *      DWORD len;
1318  *
1319  * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1320  */
1321 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
1322   HRESULT       hr = E_FAIL;
1323   BOOL          headerisdata = FALSE;
1324   BOOL          statfailed = FALSE;
1325   ULONG         xread, toread;
1326   ULONG         headerread;
1327   BYTE          *xbuf;
1328   DWORD         header[2];
1329   WORD          magic;
1330   STATSTG       statstg;
1331   OLEPictureImpl *This = impl_from_IPersistStream(iface);
1332   
1333   TRACE("(%p,%p)\n",This,pStm);
1334
1335   /****************************************************************************************
1336    * Part 1: Load the data
1337    */
1338   /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1339    * out whether we do.
1340    *
1341    * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1342    * compound file. This may explain most, if not all, of the cases of "no
1343    * header", and the header validation should take this into account.
1344    * At least in Visual Basic 6, resource streams, valid headers are
1345    *    header[0] == "lt\0\0",
1346    *    header[1] == length_of_stream.
1347    *
1348    * Also handle streams where we do not have a working "Stat" method by
1349    * reading all data until the end of the stream.
1350    */
1351   hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1352   if (hr) {
1353       TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1354       statfailed = TRUE;
1355       /* we will read at least 8 byte ... just right below */
1356       statstg.cbSize.QuadPart = 8;
1357   }
1358
1359   toread = 0;
1360   headerread = 0;
1361   headerisdata = FALSE;
1362   do {
1363       hr=IStream_Read(pStm,header,8,&xread);
1364       if (hr || xread!=8) {
1365           ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1366           return (hr?hr:E_FAIL);
1367       }
1368       headerread += xread;
1369       xread = 0;
1370       
1371       if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1372           if (toread != 0 && toread != header[1]) 
1373               FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1374                   toread, header[1]);
1375           toread = header[1];
1376           if (toread == 0) break;
1377       } else {
1378           if (!memcmp(&(header[0]), "GIF8",     4) ||   /* GIF header */
1379               !memcmp(&(header[0]), "BM",       2) ||   /* BMP header */
1380               !memcmp(&(header[0]), "\xff\xd8", 2) ||   /* JPEG header */
1381               (header[0] == EMR_HEADER)            ||   /* EMF header */
1382               (header[1] > statstg.cbSize.QuadPart)||   /* invalid size */
1383               (header[1]==0)
1384           ) {/* Found start of bitmap data */
1385               headerisdata = TRUE;
1386               if (toread == 0) 
1387                   toread = statstg.cbSize.QuadPart-8;
1388               else toread -= 8;
1389               xread = 8;
1390           } else {
1391               FIXME("Unknown stream header magic: %08x\n", header[0]);
1392               toread = header[1];
1393           }
1394       }
1395   } while (!headerisdata);
1396
1397   if (statfailed) { /* we don't know the size ... read all we get */
1398       int sizeinc = 4096;
1399       int origsize = sizeinc;
1400       ULONG nread = 42;
1401
1402       TRACE("Reading all data from stream.\n");
1403       xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1404       if (headerisdata)
1405           memcpy (xbuf, header, 8);
1406       while (1) {
1407           while (xread < origsize) {
1408               hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1409               xread+=nread;
1410               if (hr || !nread)
1411                   break;
1412           }
1413           if (!nread || hr) /* done, or error */
1414               break;
1415           if (xread == origsize) {
1416               origsize += sizeinc;
1417               sizeinc = 2*sizeinc; /* exponential increase */
1418               xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1419           }
1420       }
1421       if (hr)
1422           TRACE("hr in no-stat loader case is %08x\n", hr);
1423       TRACE("loaded %d bytes.\n", xread);
1424       This->datalen = xread;
1425       This->data    = xbuf;
1426   } else {
1427       This->datalen = toread+(headerisdata?8:0);
1428       xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1429       if (!xbuf)
1430           return E_OUTOFMEMORY;
1431
1432       if (headerisdata)
1433           memcpy (xbuf, header, 8);
1434
1435       while (xread < This->datalen) {
1436           ULONG nread;
1437           hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1438           xread+=nread;
1439           if (hr || !nread)
1440               break;
1441       }
1442       if (xread != This->datalen)
1443           ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1444   }
1445   if (This->datalen == 0) { /* Marks the "NONE" picture */
1446       This->desc.picType = PICTYPE_NONE;
1447       return S_OK;
1448   }
1449
1450
1451   /****************************************************************************************
1452    * Part 2: Process the loaded data
1453    */
1454
1455   magic = xbuf[0] + (xbuf[1]<<8);
1456   This->loadtime_format = magic;
1457
1458   switch (magic) {
1459   case BITMAP_FORMAT_GIF: /* GIF */
1460     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
1461     break;
1462   case BITMAP_FORMAT_JPEG: /* JPEG */
1463     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
1464     break;
1465   case BITMAP_FORMAT_BMP: /* Bitmap */
1466     hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1467     break;
1468   case BITMAP_FORMAT_PNG: /* PNG */
1469     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
1470     break;
1471   case BITMAP_FORMAT_APM: /* APM */
1472     hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
1473     break;
1474   case 0x0000: { /* ICON , first word is dwReserved */
1475     hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1476     break;
1477   }
1478   default:
1479   {
1480     unsigned int i;
1481
1482     /* let's see if it's a EMF */
1483     hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
1484     if (hr == S_OK) break;
1485
1486     FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1487     hr=E_FAIL;
1488     for (i=0;i<xread+8;i++) {
1489         if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
1490         else MESSAGE("%02x ",xbuf[i-8]);
1491         if (i % 10 == 9) MESSAGE("\n");
1492     }
1493     MESSAGE("\n");
1494     break;
1495   }
1496   }
1497   This->bIsDirty = FALSE;
1498
1499   /* FIXME: this notify is not really documented */
1500   if (hr==S_OK)
1501       OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1502   return hr;
1503 }
1504
1505 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1506 {
1507     int iSuccess = 0;
1508     HDC hDC;
1509     BITMAPINFO * pInfoBitmap;
1510     int iNumPaletteEntries;
1511     unsigned char * pPixelData;
1512     BITMAPFILEHEADER * pFileHeader;
1513     BITMAPINFO * pInfoHeader;
1514
1515     pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1516         sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1517
1518     /* Find out bitmap size and padded length */
1519     hDC = GetDC(0);
1520     pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1521     GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1522
1523     /* Fetch bitmap palette & pixel data */
1524
1525     pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1526     GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1527
1528     /* Calculate the total length required for the BMP data */
1529     if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1530         iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1531         if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1532     } else {
1533         if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1534             iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1535         else
1536             iNumPaletteEntries = 0;
1537     }
1538     *pLength =
1539         sizeof(BITMAPFILEHEADER) +
1540         sizeof(BITMAPINFOHEADER) +
1541         iNumPaletteEntries * sizeof(RGBQUAD) +
1542         pInfoBitmap->bmiHeader.biSizeImage;
1543     *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1544
1545     /* Fill the BITMAPFILEHEADER */
1546     pFileHeader = *ppBuffer;
1547     pFileHeader->bfType = BITMAP_FORMAT_BMP;
1548     pFileHeader->bfSize = *pLength;
1549     pFileHeader->bfOffBits =
1550         sizeof(BITMAPFILEHEADER) +
1551         sizeof(BITMAPINFOHEADER) +
1552         iNumPaletteEntries * sizeof(RGBQUAD);
1553
1554     /* Fill the BITMAPINFOHEADER and the palette data */
1555     pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1556     memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1557     memcpy(
1558         (unsigned char *)(*ppBuffer) +
1559             sizeof(BITMAPFILEHEADER) +
1560             sizeof(BITMAPINFOHEADER) +
1561             iNumPaletteEntries * sizeof(RGBQUAD),
1562         pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1563     iSuccess = 1;
1564
1565     HeapFree(GetProcessHeap(), 0, pPixelData);
1566     HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1567     return iSuccess;
1568 }
1569
1570 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1571 {
1572         ICONINFO infoIcon;
1573         int iSuccess = 0;
1574
1575         *ppBuffer = NULL; *pLength = 0;
1576         if (GetIconInfo(hIcon, &infoIcon)) {
1577                 HDC hDC;
1578                 BITMAPINFO * pInfoBitmap;
1579                 unsigned char * pIconData = NULL;
1580                 unsigned int iDataSize = 0;
1581
1582         pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1583
1584                 /* Find out icon size */
1585                 hDC = GetDC(0);
1586                 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1587                 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1588                 if (1) {
1589                         /* Auxiliary pointers */
1590                         CURSORICONFILEDIR * pIconDir;
1591                         CURSORICONFILEDIRENTRY * pIconEntry;
1592                         BITMAPINFOHEADER * pIconBitmapHeader;
1593                         unsigned int iOffsetPalette;
1594                         unsigned int iOffsetColorData;
1595                         unsigned int iOffsetMaskData;
1596
1597                         unsigned int iLengthScanLineColor;
1598                         unsigned int iLengthScanLineMask;
1599                         unsigned int iNumEntriesPalette;
1600
1601                         iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1602                         iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
1603 /*
1604                         FIXME("DEBUG: bitmap size is %d x %d\n",
1605                                 pInfoBitmap->bmiHeader.biWidth,
1606                                 pInfoBitmap->bmiHeader.biHeight);
1607                         FIXME("DEBUG: bitmap bpp is %d\n",
1608                                 pInfoBitmap->bmiHeader.biBitCount);
1609                         FIXME("DEBUG: bitmap nplanes is %d\n",
1610                                 pInfoBitmap->bmiHeader.biPlanes);
1611                         FIXME("DEBUG: bitmap biSizeImage is %u\n",
1612                                 pInfoBitmap->bmiHeader.biSizeImage);
1613 */
1614                         /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1615                         iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1616                         pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1617
1618                         /* Fill out the CURSORICONFILEDIR */
1619                         pIconDir = (CURSORICONFILEDIR *)pIconData;
1620                         pIconDir->idType = 1;
1621                         pIconDir->idCount = 1;
1622
1623                         /* Fill out the CURSORICONFILEDIRENTRY */
1624                         pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1625                         pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1626                         pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1627                         pIconEntry->bColorCount =
1628                                 (pInfoBitmap->bmiHeader.biBitCount < 8)
1629                                 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1630                                 : 0;
1631                         pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1632                         pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1633                         pIconEntry->dwDIBSize = 0;
1634                         pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1635
1636                         /* Fill out the BITMAPINFOHEADER */
1637                         pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1638                         *pIconBitmapHeader = pInfoBitmap->bmiHeader;
1639
1640                         /*      Find out whether a palette exists for the bitmap */
1641                         if (    (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1642                                 ||      (pInfoBitmap->bmiHeader.biBitCount == 24)
1643                                 ||      (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1644                                 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1645                                 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; 
1646                         } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1647                                 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1648                                 iNumEntriesPalette = 3;
1649                         } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1650                                 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1651                         } else {
1652                                 iNumEntriesPalette = 0;
1653                         }
1654
1655                         /*  Add bitmap size and header size to icon data size. */
1656                         iOffsetPalette = iDataSize;
1657                         iDataSize += iNumEntriesPalette * sizeof(DWORD);
1658                         iOffsetColorData = iDataSize;
1659                         iDataSize += pIconBitmapHeader->biSizeImage;
1660                         iOffsetMaskData = iDataSize;
1661                         iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1662                         pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1663                         pIconBitmapHeader->biHeight *= 2;
1664                         pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1665                         pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1666                         pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1667                         pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1668
1669                         /* Get the actual bitmap data from the icon bitmap */
1670                         GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1671                                 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1672                         if (iNumEntriesPalette > 0) {
1673                                 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1674                                         iNumEntriesPalette * sizeof(RGBQUAD));
1675                         }
1676
1677                         /* Reset all values so that GetDIBits call succeeds */
1678                         memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1679                         memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1680                         pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1681 /*
1682             if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1683                                 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1684                                         pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1685
1686                 printf("ERROR: unable to get bitmap mask (error %u)\n",
1687                                         GetLastError());
1688
1689                         }
1690 */
1691             GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1692             GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1693
1694                         /* Write out everything produced so far to the stream */
1695                         *ppBuffer = pIconData; *pLength = iDataSize;
1696                         iSuccess = 1;
1697                 } else {
1698 /*
1699                         printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1700                                 GetLastError());
1701 */
1702                 }
1703                 /*
1704                         Remarks (from MSDN entry on GetIconInfo):
1705
1706                         GetIconInfo creates bitmaps for the hbmMask and hbmColor
1707                         members of ICONINFO. The calling application must manage
1708                         these bitmaps and delete them when they are no longer
1709                         necessary.
1710                  */
1711                 if (hDC) ReleaseDC(0, hDC);
1712                 DeleteObject(infoIcon.hbmMask);
1713                 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1714                 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1715         } else {
1716                 printf("ERROR: Unable to get icon information (error %u)\n",
1717                         GetLastError());
1718         }
1719         return iSuccess;
1720 }
1721
1722 static HRESULT WINAPI OLEPictureImpl_Save(
1723   IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1724 {
1725     HRESULT hResult = E_NOTIMPL;
1726     void * pIconData;
1727     unsigned int iDataSize;
1728     ULONG dummy;
1729     int iSerializeResult = 0;
1730     OLEPictureImpl *This = impl_from_IPersistStream(iface);
1731
1732     TRACE("%p %p %d\n", This, pStm, fClearDirty);
1733
1734     switch (This->desc.picType) {
1735     case PICTYPE_ICON:
1736         if (This->bIsDirty || !This->data) {
1737             if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1738                 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1739                 hResult = E_FAIL;
1740                 break;
1741             }
1742             HeapFree(GetProcessHeap(), 0, This->data);
1743             This->data = pIconData;
1744             This->datalen = iDataSize;
1745         }
1746         if (This->loadtime_magic != 0xdeadbeef) {
1747             DWORD header[2];
1748
1749             header[0] = This->loadtime_magic;
1750             header[1] = This->datalen;
1751             IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1752         }
1753         IStream_Write(pStm, This->data, This->datalen, &dummy);
1754
1755         hResult = S_OK;
1756         break;
1757     case PICTYPE_BITMAP:
1758         if (This->bIsDirty) {
1759             switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
1760             case BITMAP_FORMAT_BMP:
1761                 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1762                 break;
1763             case BITMAP_FORMAT_JPEG:
1764                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1765                 break;
1766             case BITMAP_FORMAT_GIF:
1767                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1768                 break;
1769             case BITMAP_FORMAT_PNG:
1770                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
1771                 break;
1772             default:
1773                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1774                 break;
1775             }
1776             if (iSerializeResult) {
1777                 /*
1778                 if (This->loadtime_magic != 0xdeadbeef) {
1779                 */
1780                 if (1) {
1781                     DWORD header[2];
1782
1783                     header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1784                     header[1] = iDataSize;
1785                     IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1786                 }
1787                 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1788
1789                 HeapFree(GetProcessHeap(), 0, This->data);
1790                 This->data = pIconData;
1791                 This->datalen = iDataSize;
1792                 hResult = S_OK;
1793             }
1794         } else {
1795             /*
1796             if (This->loadtime_magic != 0xdeadbeef) {
1797             */
1798             if (1) {
1799                 DWORD header[2];
1800
1801                 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1802                 header[1] = This->datalen;
1803                 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1804             }
1805             IStream_Write(pStm, This->data, This->datalen, &dummy);
1806             hResult = S_OK;
1807         }
1808         break;
1809     case PICTYPE_METAFILE:
1810         FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1811         break;
1812     case PICTYPE_ENHMETAFILE:
1813         FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1814         break;
1815     default:
1816         FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1817         break;
1818     }
1819     if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1820     return hResult;
1821 }
1822
1823 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1824   IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1825 {
1826   OLEPictureImpl *This = impl_from_IPersistStream(iface);
1827   FIXME("(%p,%p),stub!\n",This,pcbSize);
1828   return E_NOTIMPL;
1829 }
1830
1831
1832 /************************************************************************
1833  *    IDispatch
1834  */
1835
1836 /************************************************************************
1837  * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1838  *
1839  * See Windows documentation for more details on IUnknown methods.
1840  */
1841 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1842   IDispatch* iface,
1843   REFIID     riid,
1844   VOID**     ppvoid)
1845 {
1846   OLEPictureImpl *This = impl_from_IDispatch(iface);
1847
1848   return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1849 }
1850
1851 /************************************************************************
1852  * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1853  *
1854  * See Windows documentation for more details on IUnknown methods.
1855  */
1856 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1857   IDispatch* iface)
1858 {
1859   OLEPictureImpl *This = impl_from_IDispatch(iface);
1860
1861   return IPicture_AddRef((IPicture *)This);
1862 }
1863
1864 /************************************************************************
1865  * OLEPictureImpl_IDispatch_Release (IUnknown)
1866  *
1867  * See Windows documentation for more details on IUnknown methods.
1868  */
1869 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1870   IDispatch* iface)
1871 {
1872   OLEPictureImpl *This = impl_from_IDispatch(iface);
1873
1874   return IPicture_Release((IPicture *)This);
1875 }
1876
1877 /************************************************************************
1878  * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1879  *
1880  * See Windows documentation for more details on IDispatch methods.
1881  */
1882 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1883   IDispatch*    iface,
1884   unsigned int* pctinfo)
1885 {
1886   TRACE("(%p)\n", pctinfo);
1887
1888   *pctinfo = 1;
1889
1890   return S_OK;
1891 }
1892
1893 /************************************************************************
1894  * OLEPictureImpl_GetTypeInfo (IDispatch)
1895  *
1896  * See Windows documentation for more details on IDispatch methods.
1897  */
1898 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1899   IDispatch*  iface,
1900   UINT      iTInfo,
1901   LCID        lcid,
1902   ITypeInfo** ppTInfo)
1903 {
1904   static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1905   ITypeLib *tl;
1906   HRESULT hres;
1907
1908   TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1909
1910   if (iTInfo != 0)
1911     return E_FAIL;
1912
1913   hres = LoadTypeLib(stdole2tlb, &tl);
1914   if (FAILED(hres))
1915   {
1916     ERR("Could not load stdole2.tlb\n");
1917     return hres;
1918   }
1919
1920   hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1921   if (FAILED(hres))
1922     ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1923
1924   return hres;
1925 }
1926
1927 /************************************************************************
1928  * OLEPictureImpl_GetIDsOfNames (IDispatch)
1929  *
1930  * See Windows documentation for more details on IDispatch methods.
1931  */
1932 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1933   IDispatch*  iface,
1934   REFIID      riid,
1935   LPOLESTR* rgszNames,
1936   UINT      cNames,
1937   LCID        lcid,
1938   DISPID*     rgDispId)
1939 {
1940   ITypeInfo * pTInfo;
1941   HRESULT hres;
1942
1943   TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
1944         rgszNames, cNames, (int)lcid, rgDispId);
1945
1946   if (cNames == 0)
1947   {
1948     return E_INVALIDARG;
1949   }
1950   else
1951   {
1952     /* retrieve type information */
1953     hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1954
1955     if (FAILED(hres))
1956     {
1957       ERR("GetTypeInfo failed.\n");
1958       return hres;
1959     }
1960
1961     /* convert names to DISPIDs */
1962     hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1963     ITypeInfo_Release(pTInfo);
1964
1965     return hres;
1966   }
1967 }
1968
1969 /************************************************************************
1970  * OLEPictureImpl_Invoke (IDispatch)
1971  *
1972  * See Windows documentation for more details on IDispatch methods.
1973  */
1974 static HRESULT WINAPI OLEPictureImpl_Invoke(
1975   IDispatch*  iface,
1976   DISPID      dispIdMember,
1977   REFIID      riid,
1978   LCID        lcid,
1979   WORD        wFlags,
1980   DISPPARAMS* pDispParams,
1981   VARIANT*    pVarResult,
1982   EXCEPINFO*  pExepInfo,
1983   UINT*     puArgErr)
1984 {
1985   OLEPictureImpl *This = impl_from_IDispatch(iface);
1986
1987   /* validate parameters */
1988
1989   if (!IsEqualIID(riid, &IID_NULL))
1990   {
1991     ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1992     return DISP_E_UNKNOWNNAME;
1993   }
1994
1995   if (!pDispParams)
1996   {
1997     ERR("null pDispParams not allowed\n");
1998     return DISP_E_PARAMNOTOPTIONAL;
1999   }
2000
2001   if (wFlags & DISPATCH_PROPERTYGET)
2002   {
2003     if (pDispParams->cArgs != 0)
2004     {
2005       ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2006       return DISP_E_BADPARAMCOUNT;
2007     }
2008     if (!pVarResult)
2009     {
2010       ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2011       return DISP_E_PARAMNOTOPTIONAL;
2012     }
2013   }
2014   else if (wFlags & DISPATCH_PROPERTYPUT)
2015   {
2016     if (pDispParams->cArgs != 1)
2017     {
2018       ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2019       return DISP_E_BADPARAMCOUNT;
2020     }
2021   }
2022
2023   switch (dispIdMember)
2024   {
2025   case DISPID_PICT_HANDLE:
2026     if (wFlags & DISPATCH_PROPERTYGET)
2027     {
2028       TRACE("DISPID_PICT_HANDLE\n");
2029       V_VT(pVarResult) = VT_I4;
2030       return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2031     }
2032     break;
2033   case DISPID_PICT_HPAL:
2034     if (wFlags & DISPATCH_PROPERTYGET)
2035     {
2036       TRACE("DISPID_PICT_HPAL\n");
2037       V_VT(pVarResult) = VT_I4;
2038       return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2039     }
2040     else if (wFlags & DISPATCH_PROPERTYPUT)
2041     {
2042       VARIANTARG vararg;
2043       HRESULT hr;
2044       TRACE("DISPID_PICT_HPAL\n");
2045
2046       VariantInit(&vararg);
2047       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2048       if (FAILED(hr))
2049         return hr;
2050
2051       hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2052
2053       VariantClear(&vararg);
2054       return hr;
2055     }
2056     break;
2057   case DISPID_PICT_TYPE:
2058     if (wFlags & DISPATCH_PROPERTYGET)
2059     {
2060       TRACE("DISPID_PICT_TYPE\n");
2061       V_VT(pVarResult) = VT_I2;
2062       return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2063     }
2064     break;
2065   case DISPID_PICT_WIDTH:
2066     if (wFlags & DISPATCH_PROPERTYGET)
2067     {
2068       TRACE("DISPID_PICT_WIDTH\n");
2069       V_VT(pVarResult) = VT_I4;
2070       return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2071     }
2072     break;
2073   case DISPID_PICT_HEIGHT:
2074     if (wFlags & DISPATCH_PROPERTYGET)
2075     {
2076       TRACE("DISPID_PICT_HEIGHT\n");
2077       V_VT(pVarResult) = VT_I4;
2078       return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2079     }
2080     break;
2081   }
2082
2083   ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2084   return DISP_E_MEMBERNOTFOUND;
2085 }
2086
2087
2088 static const IPictureVtbl OLEPictureImpl_VTable =
2089 {
2090   OLEPictureImpl_QueryInterface,
2091   OLEPictureImpl_AddRef,
2092   OLEPictureImpl_Release,
2093   OLEPictureImpl_get_Handle,
2094   OLEPictureImpl_get_hPal,
2095   OLEPictureImpl_get_Type,
2096   OLEPictureImpl_get_Width,
2097   OLEPictureImpl_get_Height,
2098   OLEPictureImpl_Render,
2099   OLEPictureImpl_set_hPal,
2100   OLEPictureImpl_get_CurDC,
2101   OLEPictureImpl_SelectPicture,
2102   OLEPictureImpl_get_KeepOriginalFormat,
2103   OLEPictureImpl_put_KeepOriginalFormat,
2104   OLEPictureImpl_PictureChanged,
2105   OLEPictureImpl_SaveAsFile,
2106   OLEPictureImpl_get_Attributes
2107 };
2108
2109 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2110 {
2111   OLEPictureImpl_IDispatch_QueryInterface,
2112   OLEPictureImpl_IDispatch_AddRef,
2113   OLEPictureImpl_IDispatch_Release,
2114   OLEPictureImpl_GetTypeInfoCount,
2115   OLEPictureImpl_GetTypeInfo,
2116   OLEPictureImpl_GetIDsOfNames,
2117   OLEPictureImpl_Invoke
2118 };
2119
2120 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2121 {
2122   OLEPictureImpl_IPersistStream_QueryInterface,
2123   OLEPictureImpl_IPersistStream_AddRef,
2124   OLEPictureImpl_IPersistStream_Release,
2125   OLEPictureImpl_GetClassID,
2126   OLEPictureImpl_IsDirty,
2127   OLEPictureImpl_Load,
2128   OLEPictureImpl_Save,
2129   OLEPictureImpl_GetSizeMax
2130 };
2131
2132 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2133 {
2134   OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2135   OLEPictureImpl_IConnectionPointContainer_AddRef,
2136   OLEPictureImpl_IConnectionPointContainer_Release,
2137   OLEPictureImpl_EnumConnectionPoints,
2138   OLEPictureImpl_FindConnectionPoint
2139 };
2140
2141 /***********************************************************************
2142  * OleCreatePictureIndirect (OLEAUT32.419)
2143  */
2144 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2145                             BOOL fOwn, LPVOID *ppvObj )
2146 {
2147   OLEPictureImpl* newPict = NULL;
2148   HRESULT      hr         = S_OK;
2149
2150   TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2151
2152   /*
2153    * Sanity check
2154    */
2155   if (ppvObj==0)
2156     return E_POINTER;
2157
2158   *ppvObj = NULL;
2159
2160   /*
2161    * Try to construct a new instance of the class.
2162    */
2163   newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2164
2165   if (newPict == NULL)
2166     return E_OUTOFMEMORY;
2167
2168   /*
2169    * Make sure it supports the interface required by the caller.
2170    */
2171   hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2172
2173   /*
2174    * Release the reference obtained in the constructor. If
2175    * the QueryInterface was unsuccessful, it will free the class.
2176    */
2177   IPicture_Release((IPicture*)newPict);
2178
2179   return hr;
2180 }
2181
2182
2183 /***********************************************************************
2184  * OleLoadPicture (OLEAUT32.418)
2185  */
2186 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2187                             REFIID riid, LPVOID *ppvObj )
2188 {
2189   LPPERSISTSTREAM ps;
2190   IPicture      *newpic;
2191   HRESULT hr;
2192
2193   TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2194         lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2195
2196   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2197   if (hr)
2198     return hr;
2199   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2200   if (hr) {
2201       ERR("Could not get IPersistStream iface from Ole Picture?\n");
2202       IPicture_Release(newpic);
2203       *ppvObj = NULL;
2204       return hr;
2205   }
2206   hr = IPersistStream_Load(ps,lpstream);
2207   IPersistStream_Release(ps);
2208   if (FAILED(hr))
2209   {
2210       ERR("IPersistStream_Load failed\n");
2211       IPicture_Release(newpic);
2212       *ppvObj = NULL;
2213       return hr;
2214   }
2215   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2216   if (hr)
2217       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2218   IPicture_Release(newpic);
2219   return hr;
2220 }
2221
2222 /***********************************************************************
2223  * OleLoadPictureEx (OLEAUT32.401)
2224  */
2225 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2226                             REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2227 {
2228   LPPERSISTSTREAM ps;
2229   IPicture      *newpic;
2230   HRESULT hr;
2231
2232   FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2233         lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2234
2235   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2236   if (hr)
2237     return hr;
2238   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2239   if (hr) {
2240       ERR("Could not get IPersistStream iface from Ole Picture?\n");
2241       IPicture_Release(newpic);
2242       *ppvObj = NULL;
2243       return hr;
2244   }
2245   hr = IPersistStream_Load(ps,lpstream);
2246   IPersistStream_Release(ps);
2247   if (FAILED(hr))
2248   {
2249       ERR("IPersistStream_Load failed\n");
2250       IPicture_Release(newpic);
2251       *ppvObj = NULL;
2252       return hr;
2253   }
2254   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2255   if (hr)
2256       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2257   IPicture_Release(newpic);
2258   return hr;
2259 }
2260
2261 /***********************************************************************
2262  * OleLoadPicturePath (OLEAUT32.424)
2263  */
2264 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2265                 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2266                 LPVOID *ppvRet )
2267 {
2268   static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2269   IPicture *ipicture;
2270   HANDLE hFile;
2271   DWORD dwFileSize;
2272   HGLOBAL hGlobal = NULL;
2273   DWORD dwBytesRead = 0;
2274   IStream *stream;
2275   BOOL bRead;
2276   IPersistStream *pStream;
2277   HRESULT hRes;
2278
2279   TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2280         debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2281         debugstr_guid(riid), ppvRet);
2282
2283   if (!ppvRet) return E_POINTER;
2284
2285   if (strncmpW(szURLorPath, file, 7) == 0) {        
2286       szURLorPath += 7;
2287   
2288       hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2289                                    0, NULL);
2290       if (hFile == INVALID_HANDLE_VALUE)
2291           return E_UNEXPECTED;
2292
2293       dwFileSize = GetFileSize(hFile, NULL);
2294       if (dwFileSize != INVALID_FILE_SIZE )
2295       {
2296           hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2297           if ( hGlobal)
2298           {
2299               bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2300               if (!bRead)
2301               {
2302                   GlobalFree(hGlobal);
2303                   hGlobal = 0;
2304               }
2305           }
2306       }
2307       CloseHandle(hFile);
2308       
2309       if (!hGlobal)
2310           return E_UNEXPECTED;
2311
2312       hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2313       if (FAILED(hRes)) 
2314       {
2315           GlobalFree(hGlobal);
2316           return hRes;
2317       }
2318   } else {
2319       IMoniker *pmnk;
2320       IBindCtx *pbc;
2321
2322       hRes = CreateBindCtx(0, &pbc);
2323       if (SUCCEEDED(hRes)) 
2324       {
2325           hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2326           if (SUCCEEDED(hRes))
2327           {              
2328               hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2329               IMoniker_Release(pmnk);
2330           }
2331           IBindCtx_Release(pbc);
2332       }
2333       if (FAILED(hRes))
2334           return hRes;
2335   }
2336
2337   hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER, 
2338                    &IID_IPicture, (LPVOID*)&ipicture);
2339   if (hRes != S_OK) {
2340       IStream_Release(stream);
2341       return hRes;
2342   }
2343   
2344   hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2345   if (hRes) {
2346       IStream_Release(stream);
2347       IPicture_Release(ipicture);
2348       return hRes;
2349   }
2350
2351   hRes = IPersistStream_Load(pStream, stream); 
2352   IPersistStream_Release(pStream);
2353   IStream_Release(stream);
2354
2355   if (hRes) {
2356       IPicture_Release(ipicture);
2357       return hRes;
2358   }
2359
2360   hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2361   if (hRes)
2362       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2363   
2364   IPicture_Release(ipicture);
2365   return hRes;
2366 }
2367
2368 /*******************************************************************************
2369  * StdPic ClassFactory
2370  */
2371 typedef struct
2372 {
2373     /* IUnknown fields */
2374     const IClassFactoryVtbl    *lpVtbl;
2375     LONG                        ref;
2376 } IClassFactoryImpl;
2377
2378 static HRESULT WINAPI
2379 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2380         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2381
2382         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2383         return E_NOINTERFACE;
2384 }
2385
2386 static ULONG WINAPI
2387 SPCF_AddRef(LPCLASSFACTORY iface) {
2388         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2389         return InterlockedIncrement(&This->ref);
2390 }
2391
2392 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2393         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2394         /* static class, won't be  freed */
2395         return InterlockedDecrement(&This->ref);
2396 }
2397
2398 static HRESULT WINAPI SPCF_CreateInstance(
2399         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2400 ) {
2401     /* Creates an uninitialized picture */
2402     return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2403
2404 }
2405
2406 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2407         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2408         FIXME("(%p)->(%d),stub!\n",This,dolock);
2409         return S_OK;
2410 }
2411
2412 static const IClassFactoryVtbl SPCF_Vtbl = {
2413         SPCF_QueryInterface,
2414         SPCF_AddRef,
2415         SPCF_Release,
2416         SPCF_CreateInstance,
2417         SPCF_LockServer
2418 };
2419 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2420
2421 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }