wordpad: Update Portuguese translation.
[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     DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL);
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     const APM_HEADER *header = (const 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 iLengthScanLineMask;
1598                         unsigned int iNumEntriesPalette;
1599
1600                         iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1601 /*
1602                         FIXME("DEBUG: bitmap size is %d x %d\n",
1603                                 pInfoBitmap->bmiHeader.biWidth,
1604                                 pInfoBitmap->bmiHeader.biHeight);
1605                         FIXME("DEBUG: bitmap bpp is %d\n",
1606                                 pInfoBitmap->bmiHeader.biBitCount);
1607                         FIXME("DEBUG: bitmap nplanes is %d\n",
1608                                 pInfoBitmap->bmiHeader.biPlanes);
1609                         FIXME("DEBUG: bitmap biSizeImage is %u\n",
1610                                 pInfoBitmap->bmiHeader.biSizeImage);
1611 */
1612                         /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1613                         iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1614                         pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1615
1616                         /* Fill out the CURSORICONFILEDIR */
1617                         pIconDir = (CURSORICONFILEDIR *)pIconData;
1618                         pIconDir->idType = 1;
1619                         pIconDir->idCount = 1;
1620
1621                         /* Fill out the CURSORICONFILEDIRENTRY */
1622                         pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1623                         pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1624                         pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1625                         pIconEntry->bColorCount =
1626                                 (pInfoBitmap->bmiHeader.biBitCount < 8)
1627                                 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1628                                 : 0;
1629                         pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1630                         pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1631                         pIconEntry->dwDIBSize = 0;
1632                         pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1633
1634                         /* Fill out the BITMAPINFOHEADER */
1635                         pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1636                         *pIconBitmapHeader = pInfoBitmap->bmiHeader;
1637
1638                         /*      Find out whether a palette exists for the bitmap */
1639                         if (    (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1640                                 ||      (pInfoBitmap->bmiHeader.biBitCount == 24)
1641                                 ||      (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1642                                 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1643                                 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; 
1644                         } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1645                                 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1646                                 iNumEntriesPalette = 3;
1647                         } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1648                                 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1649                         } else {
1650                                 iNumEntriesPalette = 0;
1651                         }
1652
1653                         /*  Add bitmap size and header size to icon data size. */
1654                         iOffsetPalette = iDataSize;
1655                         iDataSize += iNumEntriesPalette * sizeof(DWORD);
1656                         iOffsetColorData = iDataSize;
1657                         iDataSize += pIconBitmapHeader->biSizeImage;
1658                         iOffsetMaskData = iDataSize;
1659                         iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1660                         pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1661                         pIconBitmapHeader->biHeight *= 2;
1662                         pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1663                         pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1664                         pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1665                         pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1666
1667                         /* Get the actual bitmap data from the icon bitmap */
1668                         GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1669                                 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1670                         if (iNumEntriesPalette > 0) {
1671                                 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1672                                         iNumEntriesPalette * sizeof(RGBQUAD));
1673                         }
1674
1675                         /* Reset all values so that GetDIBits call succeeds */
1676                         memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1677                         memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1678                         pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1679 /*
1680             if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1681                                 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1682                                         pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1683
1684                 printf("ERROR: unable to get bitmap mask (error %u)\n",
1685                                         GetLastError());
1686
1687                         }
1688 */
1689             GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1690             GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1691
1692                         /* Write out everything produced so far to the stream */
1693                         *ppBuffer = pIconData; *pLength = iDataSize;
1694                         iSuccess = 1;
1695                 } else {
1696 /*
1697                         printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1698                                 GetLastError());
1699 */
1700                 }
1701                 /*
1702                         Remarks (from MSDN entry on GetIconInfo):
1703
1704                         GetIconInfo creates bitmaps for the hbmMask and hbmColor
1705                         members of ICONINFO. The calling application must manage
1706                         these bitmaps and delete them when they are no longer
1707                         necessary.
1708                  */
1709                 if (hDC) ReleaseDC(0, hDC);
1710                 DeleteObject(infoIcon.hbmMask);
1711                 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1712                 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1713         } else {
1714                 printf("ERROR: Unable to get icon information (error %u)\n",
1715                         GetLastError());
1716         }
1717         return iSuccess;
1718 }
1719
1720 static HRESULT WINAPI OLEPictureImpl_Save(
1721   IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1722 {
1723     HRESULT hResult = E_NOTIMPL;
1724     void * pIconData;
1725     unsigned int iDataSize;
1726     ULONG dummy;
1727     int iSerializeResult = 0;
1728     OLEPictureImpl *This = impl_from_IPersistStream(iface);
1729
1730     TRACE("%p %p %d\n", This, pStm, fClearDirty);
1731
1732     switch (This->desc.picType) {
1733     case PICTYPE_ICON:
1734         if (This->bIsDirty || !This->data) {
1735             if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1736                 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1737                 hResult = E_FAIL;
1738                 break;
1739             }
1740             HeapFree(GetProcessHeap(), 0, This->data);
1741             This->data = pIconData;
1742             This->datalen = iDataSize;
1743         }
1744         if (This->loadtime_magic != 0xdeadbeef) {
1745             DWORD header[2];
1746
1747             header[0] = This->loadtime_magic;
1748             header[1] = This->datalen;
1749             IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1750         }
1751         IStream_Write(pStm, This->data, This->datalen, &dummy);
1752
1753         hResult = S_OK;
1754         break;
1755     case PICTYPE_BITMAP:
1756         if (This->bIsDirty) {
1757             switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
1758             case BITMAP_FORMAT_BMP:
1759                 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1760                 break;
1761             case BITMAP_FORMAT_JPEG:
1762                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1763                 break;
1764             case BITMAP_FORMAT_GIF:
1765                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1766                 break;
1767             case BITMAP_FORMAT_PNG:
1768                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
1769                 break;
1770             default:
1771                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1772                 break;
1773             }
1774             if (iSerializeResult) {
1775                 /*
1776                 if (This->loadtime_magic != 0xdeadbeef) {
1777                 */
1778                 if (1) {
1779                     DWORD header[2];
1780
1781                     header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1782                     header[1] = iDataSize;
1783                     IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1784                 }
1785                 IStream_Write(pStm, pIconData, iDataSize, &dummy);
1786
1787                 HeapFree(GetProcessHeap(), 0, This->data);
1788                 This->data = pIconData;
1789                 This->datalen = iDataSize;
1790                 hResult = S_OK;
1791             }
1792         } else {
1793             /*
1794             if (This->loadtime_magic != 0xdeadbeef) {
1795             */
1796             if (1) {
1797                 DWORD header[2];
1798
1799                 header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1800                 header[1] = This->datalen;
1801                 IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1802             }
1803             IStream_Write(pStm, This->data, This->datalen, &dummy);
1804             hResult = S_OK;
1805         }
1806         break;
1807     case PICTYPE_METAFILE:
1808         FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1809         break;
1810     case PICTYPE_ENHMETAFILE:
1811         FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1812         break;
1813     default:
1814         FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1815         break;
1816     }
1817     if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1818     return hResult;
1819 }
1820
1821 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1822   IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1823 {
1824   OLEPictureImpl *This = impl_from_IPersistStream(iface);
1825   FIXME("(%p,%p),stub!\n",This,pcbSize);
1826   return E_NOTIMPL;
1827 }
1828
1829
1830 /************************************************************************
1831  *    IDispatch
1832  */
1833
1834 /************************************************************************
1835  * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1836  *
1837  * See Windows documentation for more details on IUnknown methods.
1838  */
1839 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1840   IDispatch* iface,
1841   REFIID     riid,
1842   VOID**     ppvoid)
1843 {
1844   OLEPictureImpl *This = impl_from_IDispatch(iface);
1845
1846   return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
1847 }
1848
1849 /************************************************************************
1850  * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1851  *
1852  * See Windows documentation for more details on IUnknown methods.
1853  */
1854 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1855   IDispatch* iface)
1856 {
1857   OLEPictureImpl *This = impl_from_IDispatch(iface);
1858
1859   return IPicture_AddRef((IPicture *)This);
1860 }
1861
1862 /************************************************************************
1863  * OLEPictureImpl_IDispatch_Release (IUnknown)
1864  *
1865  * See Windows documentation for more details on IUnknown methods.
1866  */
1867 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1868   IDispatch* iface)
1869 {
1870   OLEPictureImpl *This = impl_from_IDispatch(iface);
1871
1872   return IPicture_Release((IPicture *)This);
1873 }
1874
1875 /************************************************************************
1876  * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1877  *
1878  * See Windows documentation for more details on IDispatch methods.
1879  */
1880 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1881   IDispatch*    iface,
1882   unsigned int* pctinfo)
1883 {
1884   TRACE("(%p)\n", pctinfo);
1885
1886   *pctinfo = 1;
1887
1888   return S_OK;
1889 }
1890
1891 /************************************************************************
1892  * OLEPictureImpl_GetTypeInfo (IDispatch)
1893  *
1894  * See Windows documentation for more details on IDispatch methods.
1895  */
1896 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1897   IDispatch*  iface,
1898   UINT      iTInfo,
1899   LCID        lcid,
1900   ITypeInfo** ppTInfo)
1901 {
1902   static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1903   ITypeLib *tl;
1904   HRESULT hres;
1905
1906   TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1907
1908   if (iTInfo != 0)
1909     return E_FAIL;
1910
1911   hres = LoadTypeLib(stdole2tlb, &tl);
1912   if (FAILED(hres))
1913   {
1914     ERR("Could not load stdole2.tlb\n");
1915     return hres;
1916   }
1917
1918   hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1919   if (FAILED(hres))
1920     ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1921
1922   return hres;
1923 }
1924
1925 /************************************************************************
1926  * OLEPictureImpl_GetIDsOfNames (IDispatch)
1927  *
1928  * See Windows documentation for more details on IDispatch methods.
1929  */
1930 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1931   IDispatch*  iface,
1932   REFIID      riid,
1933   LPOLESTR* rgszNames,
1934   UINT      cNames,
1935   LCID        lcid,
1936   DISPID*     rgDispId)
1937 {
1938   ITypeInfo * pTInfo;
1939   HRESULT hres;
1940
1941   TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
1942         rgszNames, cNames, (int)lcid, rgDispId);
1943
1944   if (cNames == 0)
1945   {
1946     return E_INVALIDARG;
1947   }
1948   else
1949   {
1950     /* retrieve type information */
1951     hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1952
1953     if (FAILED(hres))
1954     {
1955       ERR("GetTypeInfo failed.\n");
1956       return hres;
1957     }
1958
1959     /* convert names to DISPIDs */
1960     hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1961     ITypeInfo_Release(pTInfo);
1962
1963     return hres;
1964   }
1965 }
1966
1967 /************************************************************************
1968  * OLEPictureImpl_Invoke (IDispatch)
1969  *
1970  * See Windows documentation for more details on IDispatch methods.
1971  */
1972 static HRESULT WINAPI OLEPictureImpl_Invoke(
1973   IDispatch*  iface,
1974   DISPID      dispIdMember,
1975   REFIID      riid,
1976   LCID        lcid,
1977   WORD        wFlags,
1978   DISPPARAMS* pDispParams,
1979   VARIANT*    pVarResult,
1980   EXCEPINFO*  pExepInfo,
1981   UINT*     puArgErr)
1982 {
1983   OLEPictureImpl *This = impl_from_IDispatch(iface);
1984
1985   /* validate parameters */
1986
1987   if (!IsEqualIID(riid, &IID_NULL))
1988   {
1989     ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1990     return DISP_E_UNKNOWNNAME;
1991   }
1992
1993   if (!pDispParams)
1994   {
1995     ERR("null pDispParams not allowed\n");
1996     return DISP_E_PARAMNOTOPTIONAL;
1997   }
1998
1999   if (wFlags & DISPATCH_PROPERTYGET)
2000   {
2001     if (pDispParams->cArgs != 0)
2002     {
2003       ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2004       return DISP_E_BADPARAMCOUNT;
2005     }
2006     if (!pVarResult)
2007     {
2008       ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2009       return DISP_E_PARAMNOTOPTIONAL;
2010     }
2011   }
2012   else if (wFlags & DISPATCH_PROPERTYPUT)
2013   {
2014     if (pDispParams->cArgs != 1)
2015     {
2016       ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2017       return DISP_E_BADPARAMCOUNT;
2018     }
2019   }
2020
2021   switch (dispIdMember)
2022   {
2023   case DISPID_PICT_HANDLE:
2024     if (wFlags & DISPATCH_PROPERTYGET)
2025     {
2026       TRACE("DISPID_PICT_HANDLE\n");
2027       V_VT(pVarResult) = VT_I4;
2028       return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2029     }
2030     break;
2031   case DISPID_PICT_HPAL:
2032     if (wFlags & DISPATCH_PROPERTYGET)
2033     {
2034       TRACE("DISPID_PICT_HPAL\n");
2035       V_VT(pVarResult) = VT_I4;
2036       return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
2037     }
2038     else if (wFlags & DISPATCH_PROPERTYPUT)
2039     {
2040       VARIANTARG vararg;
2041       HRESULT hr;
2042       TRACE("DISPID_PICT_HPAL\n");
2043
2044       VariantInit(&vararg);
2045       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2046       if (FAILED(hr))
2047         return hr;
2048
2049       hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
2050
2051       VariantClear(&vararg);
2052       return hr;
2053     }
2054     break;
2055   case DISPID_PICT_TYPE:
2056     if (wFlags & DISPATCH_PROPERTYGET)
2057     {
2058       TRACE("DISPID_PICT_TYPE\n");
2059       V_VT(pVarResult) = VT_I2;
2060       return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2061     }
2062     break;
2063   case DISPID_PICT_WIDTH:
2064     if (wFlags & DISPATCH_PROPERTYGET)
2065     {
2066       TRACE("DISPID_PICT_WIDTH\n");
2067       V_VT(pVarResult) = VT_I4;
2068       return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2069     }
2070     break;
2071   case DISPID_PICT_HEIGHT:
2072     if (wFlags & DISPATCH_PROPERTYGET)
2073     {
2074       TRACE("DISPID_PICT_HEIGHT\n");
2075       V_VT(pVarResult) = VT_I4;
2076       return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
2077     }
2078     break;
2079   }
2080
2081   ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2082   return DISP_E_MEMBERNOTFOUND;
2083 }
2084
2085
2086 static const IPictureVtbl OLEPictureImpl_VTable =
2087 {
2088   OLEPictureImpl_QueryInterface,
2089   OLEPictureImpl_AddRef,
2090   OLEPictureImpl_Release,
2091   OLEPictureImpl_get_Handle,
2092   OLEPictureImpl_get_hPal,
2093   OLEPictureImpl_get_Type,
2094   OLEPictureImpl_get_Width,
2095   OLEPictureImpl_get_Height,
2096   OLEPictureImpl_Render,
2097   OLEPictureImpl_set_hPal,
2098   OLEPictureImpl_get_CurDC,
2099   OLEPictureImpl_SelectPicture,
2100   OLEPictureImpl_get_KeepOriginalFormat,
2101   OLEPictureImpl_put_KeepOriginalFormat,
2102   OLEPictureImpl_PictureChanged,
2103   OLEPictureImpl_SaveAsFile,
2104   OLEPictureImpl_get_Attributes
2105 };
2106
2107 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2108 {
2109   OLEPictureImpl_IDispatch_QueryInterface,
2110   OLEPictureImpl_IDispatch_AddRef,
2111   OLEPictureImpl_IDispatch_Release,
2112   OLEPictureImpl_GetTypeInfoCount,
2113   OLEPictureImpl_GetTypeInfo,
2114   OLEPictureImpl_GetIDsOfNames,
2115   OLEPictureImpl_Invoke
2116 };
2117
2118 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2119 {
2120   OLEPictureImpl_IPersistStream_QueryInterface,
2121   OLEPictureImpl_IPersistStream_AddRef,
2122   OLEPictureImpl_IPersistStream_Release,
2123   OLEPictureImpl_GetClassID,
2124   OLEPictureImpl_IsDirty,
2125   OLEPictureImpl_Load,
2126   OLEPictureImpl_Save,
2127   OLEPictureImpl_GetSizeMax
2128 };
2129
2130 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2131 {
2132   OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2133   OLEPictureImpl_IConnectionPointContainer_AddRef,
2134   OLEPictureImpl_IConnectionPointContainer_Release,
2135   OLEPictureImpl_EnumConnectionPoints,
2136   OLEPictureImpl_FindConnectionPoint
2137 };
2138
2139 /***********************************************************************
2140  * OleCreatePictureIndirect (OLEAUT32.419)
2141  */
2142 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2143                             BOOL fOwn, LPVOID *ppvObj )
2144 {
2145   OLEPictureImpl* newPict = NULL;
2146   HRESULT      hr         = S_OK;
2147
2148   TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
2149
2150   /*
2151    * Sanity check
2152    */
2153   if (ppvObj==0)
2154     return E_POINTER;
2155
2156   *ppvObj = NULL;
2157
2158   /*
2159    * Try to construct a new instance of the class.
2160    */
2161   newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2162
2163   if (newPict == NULL)
2164     return E_OUTOFMEMORY;
2165
2166   /*
2167    * Make sure it supports the interface required by the caller.
2168    */
2169   hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2170
2171   /*
2172    * Release the reference obtained in the constructor. If
2173    * the QueryInterface was unsuccessful, it will free the class.
2174    */
2175   IPicture_Release((IPicture*)newPict);
2176
2177   return hr;
2178 }
2179
2180
2181 /***********************************************************************
2182  * OleLoadPicture (OLEAUT32.418)
2183  */
2184 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2185                             REFIID riid, LPVOID *ppvObj )
2186 {
2187   LPPERSISTSTREAM ps;
2188   IPicture      *newpic;
2189   HRESULT hr;
2190
2191   TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2192         lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2193
2194   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2195   if (hr)
2196     return hr;
2197   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2198   if (hr) {
2199       ERR("Could not get IPersistStream iface from Ole Picture?\n");
2200       IPicture_Release(newpic);
2201       *ppvObj = NULL;
2202       return hr;
2203   }
2204   hr = IPersistStream_Load(ps,lpstream);
2205   IPersistStream_Release(ps);
2206   if (FAILED(hr))
2207   {
2208       ERR("IPersistStream_Load failed\n");
2209       IPicture_Release(newpic);
2210       *ppvObj = NULL;
2211       return hr;
2212   }
2213   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2214   if (hr)
2215       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2216   IPicture_Release(newpic);
2217   return hr;
2218 }
2219
2220 /***********************************************************************
2221  * OleLoadPictureEx (OLEAUT32.401)
2222  */
2223 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2224                             REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2225 {
2226   LPPERSISTSTREAM ps;
2227   IPicture      *newpic;
2228   HRESULT hr;
2229
2230   FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2231         lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2232
2233   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2234   if (hr)
2235     return hr;
2236   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2237   if (hr) {
2238       ERR("Could not get IPersistStream iface from Ole Picture?\n");
2239       IPicture_Release(newpic);
2240       *ppvObj = NULL;
2241       return hr;
2242   }
2243   hr = IPersistStream_Load(ps,lpstream);
2244   IPersistStream_Release(ps);
2245   if (FAILED(hr))
2246   {
2247       ERR("IPersistStream_Load failed\n");
2248       IPicture_Release(newpic);
2249       *ppvObj = NULL;
2250       return hr;
2251   }
2252   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2253   if (hr)
2254       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2255   IPicture_Release(newpic);
2256   return hr;
2257 }
2258
2259 /***********************************************************************
2260  * OleLoadPicturePath (OLEAUT32.424)
2261  */
2262 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2263                 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2264                 LPVOID *ppvRet )
2265 {
2266   static const WCHAR file[] = { 'f','i','l','e',':',0 };
2267   IPicture *ipicture;
2268   HANDLE hFile;
2269   DWORD dwFileSize;
2270   HGLOBAL hGlobal = NULL;
2271   DWORD dwBytesRead = 0;
2272   IStream *stream;
2273   BOOL bRead;
2274   IPersistStream *pStream;
2275   HRESULT hRes;
2276   HRESULT init_res;
2277   WCHAR *file_candidate;
2278   WCHAR path_buf[MAX_PATH];
2279
2280   TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2281         debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2282         debugstr_guid(riid), ppvRet);
2283
2284   if (!szURLorPath || !ppvRet)
2285       return E_INVALIDARG;
2286
2287   *ppvRet = NULL;
2288
2289   /* Convert file URLs to DOS paths. */
2290   if (strncmpW(szURLorPath, file, 5) == 0) {
2291       DWORD size;
2292       hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
2293                                 sizeof(path_buf)/sizeof(WCHAR), &size, 0);
2294       if (FAILED(hRes))
2295           return hRes;
2296
2297       file_candidate = path_buf;
2298   }
2299   else
2300       file_candidate = szURLorPath;
2301
2302   /* Handle candidate DOS paths separately. */
2303   if (file_candidate[1] == ':') {
2304       hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2305                           0, NULL);
2306       if (hFile == INVALID_HANDLE_VALUE)
2307           return E_UNEXPECTED;
2308
2309       dwFileSize = GetFileSize(hFile, NULL);
2310       if (dwFileSize != INVALID_FILE_SIZE )
2311       {
2312           hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2313           if ( hGlobal)
2314           {
2315               bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2316               if (!bRead)
2317               {
2318                   GlobalFree(hGlobal);
2319                   hGlobal = 0;
2320               }
2321           }
2322       }
2323       CloseHandle(hFile);
2324       
2325       if (!hGlobal)
2326           return E_UNEXPECTED;
2327
2328       hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2329       if (FAILED(hRes)) 
2330       {
2331           GlobalFree(hGlobal);
2332           return hRes;
2333       }
2334   } else {
2335       IMoniker *pmnk;
2336       IBindCtx *pbc;
2337
2338       hRes = CreateBindCtx(0, &pbc);
2339       if (SUCCEEDED(hRes)) 
2340       {
2341           hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2342           if (SUCCEEDED(hRes))
2343           {              
2344               hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2345               IMoniker_Release(pmnk);
2346           }
2347           IBindCtx_Release(pbc);
2348       }
2349       if (FAILED(hRes))
2350           return hRes;
2351   }
2352
2353   init_res = CoInitialize(NULL);
2354
2355   hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2356                           &IID_IPicture, (LPVOID*)&ipicture);
2357   if (SUCCEEDED(hRes)) {
2358       hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2359
2360       if (SUCCEEDED(hRes)) {
2361           hRes = IPersistStream_Load(pStream, stream);
2362
2363           if (SUCCEEDED(hRes)) {
2364               hRes = IPicture_QueryInterface(ipicture, riid, ppvRet);
2365
2366               if (FAILED(hRes))
2367                   ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid));
2368           }
2369           IPersistStream_Release(pStream);
2370       }
2371       IPicture_Release(ipicture);
2372   }
2373
2374   IStream_Release(stream);
2375
2376   if (SUCCEEDED(init_res))
2377       CoUninitialize();
2378
2379   return hRes;
2380 }
2381
2382 /*******************************************************************************
2383  * StdPic ClassFactory
2384  */
2385 typedef struct
2386 {
2387     /* IUnknown fields */
2388     const IClassFactoryVtbl    *lpVtbl;
2389     LONG                        ref;
2390 } IClassFactoryImpl;
2391
2392 static HRESULT WINAPI
2393 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2394         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2395
2396         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2397         return E_NOINTERFACE;
2398 }
2399
2400 static ULONG WINAPI
2401 SPCF_AddRef(LPCLASSFACTORY iface) {
2402         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2403         return InterlockedIncrement(&This->ref);
2404 }
2405
2406 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2407         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2408         /* static class, won't be  freed */
2409         return InterlockedDecrement(&This->ref);
2410 }
2411
2412 static HRESULT WINAPI SPCF_CreateInstance(
2413         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2414 ) {
2415     /* Creates an uninitialized picture */
2416     return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2417
2418 }
2419
2420 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2421         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2422         FIXME("(%p)->(%d),stub!\n",This,dolock);
2423         return S_OK;
2424 }
2425
2426 static const IClassFactoryVtbl SPCF_Vtbl = {
2427         SPCF_QueryInterface,
2428         SPCF_AddRef,
2429         SPCF_Release,
2430         SPCF_CreateInstance,
2431         SPCF_LockServer
2432 };
2433 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2434
2435 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }