oleaut32: Search inherited interfaces again in ITypeComp::Bind.
[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 /* pixels to HIMETRIC units conversion */
185 static inline OLE_XSIZE_HIMETRIC xpixels_to_himetric(INT pixels, HDC hdc)
186 {
187     return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
188 }
189
190 static inline OLE_YSIZE_HIMETRIC ypixels_to_himetric(INT pixels, HDC hdc)
191 {
192     return MulDiv(pixels, 2540, GetDeviceCaps(hdc, LOGPIXELSY));
193 }
194
195 /***********************************************************************
196  * Implementation of the OLEPictureImpl class.
197  */
198
199 static void OLEPictureImpl_SetBitmap(OLEPictureImpl *This)
200 {
201   BITMAP bm;
202   HDC hdcRef;
203
204   TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
205   if(GetObjectW(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
206     ERR("GetObject fails\n");
207     return;
208   }
209   This->origWidth = bm.bmWidth;
210   This->origHeight = bm.bmHeight;
211
212   /* The width and height are stored in HIMETRIC units (0.01 mm),
213      so we take our pixel width divide by pixels per inch and
214      multiply by 25.4 * 100 */
215   /* Should we use GetBitmapDimension if available? */
216   hdcRef = CreateCompatibleDC(0);
217
218   This->himetricWidth  = xpixels_to_himetric(bm.bmWidth, hdcRef);
219   This->himetricHeight = ypixels_to_himetric(bm.bmHeight, hdcRef);
220
221   DeleteDC(hdcRef);
222 }
223
224 static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
225 {
226     ICONINFO infoIcon;
227
228     TRACE("icon handle %p\n", This->desc.u.icon.hicon);
229     if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
230         HDC hdcRef;
231         BITMAP bm;
232
233         TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
234         if(GetObjectW(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
235             ERR("GetObject fails on icon bitmap\n");
236             return;
237         }
238
239         This->origWidth = bm.bmWidth;
240         This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
241         /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
242         hdcRef = GetDC(0);
243
244         This->himetricWidth  = xpixels_to_himetric(This->origWidth, hdcRef);
245         This->himetricHeight = ypixels_to_himetric(This->origHeight, hdcRef);
246
247         ReleaseDC(0, hdcRef);
248
249         DeleteObject(infoIcon.hbmMask);
250         if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
251     } else {
252         ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
253     }
254 }
255
256 /************************************************************************
257  * OLEPictureImpl_Construct
258  *
259  * This method will construct a new instance of the OLEPictureImpl
260  * class.
261  *
262  * The caller of this method must release the object when it's
263  * done with it.
264  */
265 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
266 {
267   OLEPictureImpl* newObject = 0;
268
269   if (pictDesc)
270       TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
271
272   /*
273    * Allocate space for the object.
274    */
275   newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
276
277   if (newObject==0)
278     return newObject;
279
280   /*
281    * Initialize the virtual function table.
282    */
283   newObject->lpVtbl = &OLEPictureImpl_VTable;
284   newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
285   newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
286   newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
287
288   newObject->pCP = NULL;
289   CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
290   if (!newObject->pCP)
291   {
292     HeapFree(GetProcessHeap(), 0, newObject);
293     return NULL;
294   }
295
296   /*
297    * Start with one reference count. The caller of this function
298    * must release the interface pointer when it is done.
299    */
300   newObject->ref        = 1;
301   newObject->hDCCur     = 0;
302
303   newObject->fOwn       = fOwn;
304
305   /* dunno about original value */
306   newObject->keepOrigFormat = TRUE;
307
308   newObject->hbmMask = NULL;
309   newObject->hbmXor = NULL;
310   newObject->loadtime_magic = 0xdeadbeef;
311   newObject->loadtime_format = 0;
312   newObject->bIsDirty = FALSE;
313
314   if (pictDesc) {
315       newObject->desc = *pictDesc;
316
317       switch(pictDesc->picType) {
318       case PICTYPE_BITMAP:
319         OLEPictureImpl_SetBitmap(newObject);
320         break;
321
322       case PICTYPE_METAFILE:
323         TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
324         newObject->himetricWidth = pictDesc->u.wmf.xExt;
325         newObject->himetricHeight = pictDesc->u.wmf.yExt;
326         break;
327
328       case PICTYPE_NONE:
329         /* not sure what to do here */
330         newObject->himetricWidth = newObject->himetricHeight = 0;
331         break;
332
333       case PICTYPE_ICON:
334         OLEPictureImpl_SetIcon(newObject);
335         break;
336       case PICTYPE_ENHMETAFILE:
337       default:
338         FIXME("Unsupported type %d\n", pictDesc->picType);
339         newObject->himetricWidth = newObject->himetricHeight = 0;
340         break;
341       }
342   } else {
343       newObject->desc.picType = PICTYPE_UNINITIALIZED;
344   }
345
346   TRACE("returning %p\n", newObject);
347   return newObject;
348 }
349
350 /************************************************************************
351  * OLEPictureImpl_Destroy
352  *
353  * This method is called by the Release method when the reference
354  * count goes down to 0. It will free all resources used by
355  * this object.  */
356 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
357 {
358   TRACE("(%p)\n", Obj);
359
360   if (Obj->pCP)
361     IConnectionPoint_Release(Obj->pCP);
362
363   if(Obj->fOwn) { /* We need to destroy the picture */
364     switch(Obj->desc.picType) {
365     case PICTYPE_BITMAP:
366       DeleteObject(Obj->desc.u.bmp.hbitmap);
367       if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
368       if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
369       break;
370     case PICTYPE_METAFILE:
371       DeleteMetaFile(Obj->desc.u.wmf.hmeta);
372       break;
373     case PICTYPE_ICON:
374       DestroyIcon(Obj->desc.u.icon.hicon);
375       break;
376     case PICTYPE_ENHMETAFILE:
377       DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
378       break;
379     case PICTYPE_NONE:
380     case PICTYPE_UNINITIALIZED:
381       /* Nothing to do */
382       break;
383     default:
384       FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
385       break;
386     }
387   }
388   HeapFree(GetProcessHeap(), 0, Obj->data);
389   HeapFree(GetProcessHeap(), 0, Obj);
390 }
391
392
393 /************************************************************************
394  * OLEPictureImpl_AddRef (IUnknown)
395  *
396  * See Windows documentation for more details on IUnknown methods.
397  */
398 static ULONG WINAPI OLEPictureImpl_AddRef(
399   IPicture* iface)
400 {
401   OLEPictureImpl *This = (OLEPictureImpl *)iface;
402   ULONG refCount = InterlockedIncrement(&This->ref);
403
404   TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
405
406   return refCount;
407 }
408
409 /************************************************************************
410  * OLEPictureImpl_Release (IUnknown)
411  *
412  * See Windows documentation for more details on IUnknown methods.
413  */
414 static ULONG WINAPI OLEPictureImpl_Release(
415       IPicture* iface)
416 {
417   OLEPictureImpl *This = (OLEPictureImpl *)iface;
418   ULONG refCount = InterlockedDecrement(&This->ref);
419
420   TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
421
422   /*
423    * If the reference count goes down to 0, perform suicide.
424    */
425   if (!refCount) OLEPictureImpl_Destroy(This);
426
427   return refCount;
428 }
429
430 /************************************************************************
431  * OLEPictureImpl_QueryInterface (IUnknown)
432  *
433  * See Windows documentation for more details on IUnknown methods.
434  */
435 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
436   IPicture*  iface,
437   REFIID  riid,
438   void**  ppvObject)
439 {
440   OLEPictureImpl *This = (OLEPictureImpl *)iface;
441
442   TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
443
444   if (!ppvObject)
445     return E_INVALIDARG;
446
447   *ppvObject = 0;
448
449   if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
450     *ppvObject = This;
451   else if (IsEqualIID(&IID_IDispatch, riid))
452     *ppvObject = &This->lpvtblIDispatch;
453   else if (IsEqualIID(&IID_IPictureDisp, riid))
454     *ppvObject = &This->lpvtblIDispatch;
455   else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
456     *ppvObject = &This->lpvtblIPersistStream;
457   else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
458     *ppvObject = &This->lpvtblIConnectionPointContainer;
459
460   if (!*ppvObject)
461   {
462     FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
463     return E_NOINTERFACE;
464   }
465
466   IPicture_AddRef(iface);
467
468   return S_OK;
469 }
470
471 /***********************************************************************
472  *    OLEPicture_SendNotify (internal)
473  *
474  * Sends notification messages of changed properties to any interested
475  * connections.
476  */
477 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
478 {
479   IEnumConnections *pEnum;
480   CONNECTDATA CD;
481
482   if (IConnectionPoint_EnumConnections(this->pCP, &pEnum) != S_OK)
483       return;
484   while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
485     IPropertyNotifySink *sink;
486
487     IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
488     IPropertyNotifySink_OnChanged(sink, dispID);
489     IPropertyNotifySink_Release(sink);
490     IUnknown_Release(CD.pUnk);
491   }
492   IEnumConnections_Release(pEnum);
493 }
494
495 /************************************************************************
496  * OLEPictureImpl_get_Handle
497  */
498 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
499                                                 OLE_HANDLE *phandle)
500 {
501   OLEPictureImpl *This = (OLEPictureImpl *)iface;
502   TRACE("(%p)->(%p)\n", This, phandle);
503
504   if(!phandle)
505     return E_POINTER;
506
507   switch(This->desc.picType) {
508   case PICTYPE_NONE:
509   case PICTYPE_UNINITIALIZED:
510     *phandle = 0;
511     break;
512   case PICTYPE_BITMAP:
513     *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
514     break;
515   case PICTYPE_METAFILE:
516     *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
517     break;
518   case PICTYPE_ICON:
519     *phandle = HandleToUlong(This->desc.u.icon.hicon);
520     break;
521   case PICTYPE_ENHMETAFILE:
522     *phandle = HandleToUlong(This->desc.u.emf.hemf);
523     break;
524   default:
525     FIXME("Unimplemented type %d\n", This->desc.picType);
526     return E_NOTIMPL;
527   }
528   TRACE("returning handle %08x\n", *phandle);
529   return S_OK;
530 }
531
532 /************************************************************************
533  * OLEPictureImpl_get_hPal
534  */
535 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
536                                               OLE_HANDLE *phandle)
537 {
538   OLEPictureImpl *This = (OLEPictureImpl *)iface;
539   HRESULT hres;
540   TRACE("(%p)->(%p)\n", This, phandle);
541
542   if (!phandle)
543     return E_POINTER;
544
545   switch (This->desc.picType) {
546     case (UINT)PICTYPE_UNINITIALIZED:
547     case PICTYPE_NONE:
548       *phandle = 0;
549       hres = S_FALSE;
550       break;
551     case PICTYPE_BITMAP:
552       *phandle = HandleToUlong(This->desc.u.bmp.hpal);
553       hres = S_OK;
554       break;
555     case PICTYPE_METAFILE:
556       hres = E_FAIL;
557       break;
558     case PICTYPE_ICON:
559     case PICTYPE_ENHMETAFILE:
560     default:
561       FIXME("unimplemented for type %d. Returning 0 palette.\n",
562            This->desc.picType);
563       *phandle = 0;
564       hres = S_OK;
565   }
566
567   TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
568   return hres;
569 }
570
571 /************************************************************************
572  * OLEPictureImpl_get_Type
573  */
574 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
575                                               short *ptype)
576 {
577   OLEPictureImpl *This = (OLEPictureImpl *)iface;
578   TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
579
580   if(!ptype)
581     return E_POINTER;
582
583   *ptype = This->desc.picType;
584   return S_OK;
585 }
586
587 /************************************************************************
588  * OLEPictureImpl_get_Width
589  */
590 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
591                                                OLE_XSIZE_HIMETRIC *pwidth)
592 {
593   OLEPictureImpl *This = (OLEPictureImpl *)iface;
594   TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
595   *pwidth = This->himetricWidth;
596   return S_OK;
597 }
598
599 /************************************************************************
600  * OLEPictureImpl_get_Height
601  */
602 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
603                                                 OLE_YSIZE_HIMETRIC *pheight)
604 {
605   OLEPictureImpl *This = (OLEPictureImpl *)iface;
606   TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
607   *pheight = This->himetricHeight;
608   return S_OK;
609 }
610
611 /************************************************************************
612  * OLEPictureImpl_Render
613  */
614 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
615                                             LONG x, LONG y, LONG cx, LONG cy,
616                                             OLE_XPOS_HIMETRIC xSrc,
617                                             OLE_YPOS_HIMETRIC ySrc,
618                                             OLE_XSIZE_HIMETRIC cxSrc,
619                                             OLE_YSIZE_HIMETRIC cySrc,
620                                             LPCRECT prcWBounds)
621 {
622   OLEPictureImpl *This = (OLEPictureImpl *)iface;
623   TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
624         This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
625   if(prcWBounds)
626     TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
627           prcWBounds->right, prcWBounds->bottom);
628
629   if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
630     return CTL_E_INVALIDPROPERTYVALUE;
631   }
632
633   /*
634    * While the documentation suggests this to be here (or after rendering?)
635    * it does cause an endless recursion in my sample app. -MM 20010804
636   OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
637    */
638
639   switch(This->desc.picType) {
640   case PICTYPE_UNINITIALIZED:
641   case PICTYPE_NONE:
642     /* nothing to do */
643     return S_OK;
644   case PICTYPE_BITMAP:
645     {
646       HBITMAP hbmpOld;
647       HDC hdcBmp;
648
649       /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
650          NB y-axis gets flipped */
651
652       hdcBmp = CreateCompatibleDC(0);
653       SetMapMode(hdcBmp, MM_ANISOTROPIC);
654       SetWindowOrgEx(hdcBmp, 0, 0, NULL);
655       SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
656       SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
657       SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
658
659       if (This->hbmMask) {
660           HDC hdcMask = CreateCompatibleDC(0);
661           HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
662
663           hbmpOld = SelectObject(hdcBmp, This->hbmXor);
664
665           SetMapMode(hdcMask, MM_ANISOTROPIC);
666           SetWindowOrgEx(hdcMask, 0, 0, NULL);
667           SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
668           SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
669           SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
670           
671           SetBkColor(hdc, RGB(255, 255, 255));    
672           SetTextColor(hdc, RGB(0, 0, 0));        
673           StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND); 
674           StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
675
676           SelectObject(hdcMask, hOldbm);
677           DeleteDC(hdcMask);
678       } else {
679           hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
680           StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
681       }
682
683       SelectObject(hdcBmp, hbmpOld);
684       DeleteDC(hdcBmp);
685     }
686     break;
687   case PICTYPE_ICON:
688     FIXME("Not quite correct implementation of rendering icons...\n");
689     DrawIconEx(hdc, x, y, This->desc.u.icon.hicon, cx, cy, 0, NULL, DI_NORMAL);
690     break;
691
692   case PICTYPE_METAFILE:
693   {
694     POINT prevOrg, prevWndOrg;
695     SIZE prevExt, prevWndExt;
696     int oldmode;
697
698     /* Render the WMF to the appropriate location by setting the
699        appropriate ratio between "device units" and "logical units" */
700     oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
701     /* For the "source rectangle" the y-axis must be inverted */
702     SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
703     SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
704     /* For the "destination rectangle" no inversion is necessary */
705     SetViewportOrgEx(hdc, x, y, &prevOrg);
706     SetViewportExtEx(hdc, cx, cy, &prevExt);
707
708     if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
709         ERR("PlayMetaFile failed!\n");
710
711     /* We're done, restore the DC to the previous settings for converting
712        logical units to device units */
713     SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
714     SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
715     SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
716     SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
717     SetMapMode(hdc, oldmode);
718     break;
719   }
720
721   case PICTYPE_ENHMETAFILE:
722   {
723     RECT rc = { x, y, x + cx, y + cy };
724     PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
725     break;
726   }
727
728   default:
729     FIXME("type %d not implemented\n", This->desc.picType);
730     return E_NOTIMPL;
731   }
732   return S_OK;
733 }
734
735 /************************************************************************
736  * OLEPictureImpl_set_hPal
737  */
738 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
739                                               OLE_HANDLE hpal)
740 {
741   OLEPictureImpl *This = (OLEPictureImpl *)iface;
742   FIXME("(%p)->(%08x): stub\n", This, hpal);
743   OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
744   return E_NOTIMPL;
745 }
746
747 /************************************************************************
748  * OLEPictureImpl_get_CurDC
749  */
750 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
751                                                HDC *phdc)
752 {
753   OLEPictureImpl *This = (OLEPictureImpl *)iface;
754   TRACE("(%p), returning %p\n", This, This->hDCCur);
755   if (phdc) *phdc = This->hDCCur;
756   return S_OK;
757 }
758
759 /************************************************************************
760  * OLEPictureImpl_SelectPicture
761  */
762 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
763                                                    HDC hdcIn,
764                                                    HDC *phdcOut,
765                                                    OLE_HANDLE *phbmpOut)
766 {
767   OLEPictureImpl *This = (OLEPictureImpl *)iface;
768   TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
769   if (This->desc.picType == PICTYPE_BITMAP) {
770       SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
771
772       if (phdcOut)
773           *phdcOut = This->hDCCur;
774       This->hDCCur = hdcIn;
775       if (phbmpOut)
776           *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
777       return S_OK;
778   } else {
779       FIXME("Don't know how to select picture type %d\n",This->desc.picType);
780       return E_FAIL;
781   }
782 }
783
784 /************************************************************************
785  * OLEPictureImpl_get_KeepOriginalFormat
786  */
787 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
788                                                             BOOL *pfKeep)
789 {
790   OLEPictureImpl *This = (OLEPictureImpl *)iface;
791   TRACE("(%p)->(%p)\n", This, pfKeep);
792   if (!pfKeep)
793       return E_POINTER;
794   *pfKeep = This->keepOrigFormat;
795   return S_OK;
796 }
797
798 /************************************************************************
799  * OLEPictureImpl_put_KeepOriginalFormat
800  */
801 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
802                                                             BOOL keep)
803 {
804   OLEPictureImpl *This = (OLEPictureImpl *)iface;
805   TRACE("(%p)->(%d)\n", This, keep);
806   This->keepOrigFormat = keep;
807   /* FIXME: what DISPID notification here? */
808   return S_OK;
809 }
810
811 /************************************************************************
812  * OLEPictureImpl_PictureChanged
813  */
814 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
815 {
816   OLEPictureImpl *This = (OLEPictureImpl *)iface;
817   TRACE("(%p)->()\n", This);
818   OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
819   This->bIsDirty = TRUE;
820   return S_OK;
821 }
822
823 /************************************************************************
824  * OLEPictureImpl_SaveAsFile
825  */
826 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
827                                                 IStream *pstream,
828                                                 BOOL SaveMemCopy,
829                                                 LONG *pcbSize)
830 {
831   OLEPictureImpl *This = (OLEPictureImpl *)iface;
832   FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
833   return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
834 }
835
836 /************************************************************************
837  * OLEPictureImpl_get_Attributes
838  */
839 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
840                                                     DWORD *pdwAttr)
841 {
842   OLEPictureImpl *This = (OLEPictureImpl *)iface;
843   TRACE("(%p)->(%p).\n", This, pdwAttr);
844
845   if(!pdwAttr)
846     return E_POINTER;
847
848   *pdwAttr = 0;
849   switch (This->desc.picType) {
850   case PICTYPE_UNINITIALIZED:
851   case PICTYPE_NONE: break;
852   case PICTYPE_BITMAP:  if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break;       /* not 'truly' scalable, see MSDN. */
853   case PICTYPE_ICON: *pdwAttr     = PICTURE_TRANSPARENT;break;
854   case PICTYPE_ENHMETAFILE: /* fall through */
855   case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
856   default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
857   }
858   return S_OK;
859 }
860
861
862 /************************************************************************
863  *    IConnectionPointContainer
864  */
865 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
866   IConnectionPointContainer* iface,
867   REFIID riid,
868   VOID** ppvoid)
869 {
870   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
871
872   return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
873 }
874
875 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
876   IConnectionPointContainer* iface)
877 {
878   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
879
880   return IPicture_AddRef((IPicture *)This);
881 }
882
883 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
884   IConnectionPointContainer* iface)
885 {
886   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
887
888   return IPicture_Release((IPicture *)This);
889 }
890
891 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
892   IConnectionPointContainer* iface,
893   IEnumConnectionPoints** ppEnum)
894 {
895   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
896
897   FIXME("(%p,%p), stub!\n",This,ppEnum);
898   return E_NOTIMPL;
899 }
900
901 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
902   IConnectionPointContainer* iface,
903   REFIID riid,
904   IConnectionPoint **ppCP)
905 {
906   OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
907   TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
908   if (!ppCP)
909       return E_POINTER;
910   *ppCP = NULL;
911   if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
912       return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
913   FIXME("no connection point for %s\n",debugstr_guid(riid));
914   return CONNECT_E_NOCONNECTION;
915 }
916
917
918 /************************************************************************
919  *    IPersistStream
920  */
921
922 /************************************************************************
923  * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
924  *
925  * See Windows documentation for more details on IUnknown methods.
926  */
927 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
928   IPersistStream* iface,
929   REFIID     riid,
930   VOID**     ppvoid)
931 {
932   OLEPictureImpl *This = impl_from_IPersistStream(iface);
933
934   return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
935 }
936
937 /************************************************************************
938  * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
939  *
940  * See Windows documentation for more details on IUnknown methods.
941  */
942 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
943   IPersistStream* iface)
944 {
945   OLEPictureImpl *This = impl_from_IPersistStream(iface);
946
947   return IPicture_AddRef((IPicture *)This);
948 }
949
950 /************************************************************************
951  * OLEPictureImpl_IPersistStream_Release (IUnknown)
952  *
953  * See Windows documentation for more details on IUnknown methods.
954  */
955 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
956   IPersistStream* iface)
957 {
958   OLEPictureImpl *This = impl_from_IPersistStream(iface);
959
960   return IPicture_Release((IPicture *)This);
961 }
962
963 /************************************************************************
964  * OLEPictureImpl_IPersistStream_GetClassID
965  */
966 static HRESULT WINAPI OLEPictureImpl_GetClassID(
967   IPersistStream* iface,CLSID* pClassID)
968 {
969   TRACE("(%p)\n", pClassID);
970   *pClassID = CLSID_StdPicture;
971   return S_OK;
972 }
973
974 /************************************************************************
975  * OLEPictureImpl_IPersistStream_IsDirty
976  */
977 static HRESULT WINAPI OLEPictureImpl_IsDirty(
978   IPersistStream* iface)
979 {
980   OLEPictureImpl *This = impl_from_IPersistStream(iface);
981   FIXME("(%p),stub!\n",This);
982   return E_NOTIMPL;
983 }
984
985 static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
986 {
987     BITMAPFILEHEADER    *bfh = (BITMAPFILEHEADER*)xbuf;
988     BITMAPINFO          *bi = (BITMAPINFO*)(bfh+1);
989     HDC                 hdcref;
990
991     /* Does not matter whether this is a coreheader or not, we only use
992      * components which are in both
993      */
994     hdcref = GetDC(0);
995     This->desc.u.bmp.hbitmap = CreateDIBitmap(
996         hdcref,
997         &(bi->bmiHeader),
998         CBM_INIT,
999         xbuf+bfh->bfOffBits,
1000         bi,
1001        DIB_RGB_COLORS
1002     );
1003     ReleaseDC(0, hdcref);
1004     if (This->desc.u.bmp.hbitmap == 0)
1005         return E_FAIL;
1006     This->desc.picType = PICTYPE_BITMAP;
1007     OLEPictureImpl_SetBitmap(This);
1008     return S_OK;
1009 }
1010
1011 static HRESULT OLEPictureImpl_LoadWICSource(OLEPictureImpl *This, IWICBitmapSource *src)
1012 {
1013     HRESULT hr;
1014     BITMAPINFOHEADER bih;
1015     HDC hdcref;
1016     UINT width, height;
1017     UINT stride, buffersize;
1018     LPBYTE bits=NULL;
1019     WICRect rc;
1020     IWICBitmapSource *real_source;
1021     UINT x, y;
1022     COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
1023     BOOL has_alpha=FALSE;
1024
1025     hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, src, &real_source);
1026     if (FAILED(hr)) return hr;
1027
1028     hr = IWICBitmapSource_GetSize(real_source, &width, &height);
1029     if (FAILED(hr)) goto end;
1030
1031     bih.biSize = sizeof(bih);
1032     bih.biWidth = width;
1033     bih.biHeight = -height;
1034     bih.biPlanes = 1;
1035     bih.biBitCount = 32;
1036     bih.biCompression = BI_RGB;
1037     bih.biSizeImage = 0;
1038     bih.biXPelsPerMeter = 4085; /* olepicture ignores the stored resolution */
1039     bih.biYPelsPerMeter = 4085;
1040     bih.biClrUsed = 0;
1041     bih.biClrImportant = 0;
1042
1043     stride = 4 * width;
1044     buffersize = stride * height;
1045
1046     bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
1047     if (!bits)
1048     {
1049         hr = E_OUTOFMEMORY;
1050         goto end;
1051     }
1052
1053     rc.X = 0;
1054     rc.Y = 0;
1055     rc.Width = width;
1056     rc.Height = height;
1057     hr = IWICBitmapSource_CopyPixels(real_source, &rc, stride, buffersize, bits);
1058     if (FAILED(hr))
1059         goto end;
1060
1061     hdcref = GetDC(0);
1062     This->desc.u.bmp.hbitmap = CreateDIBitmap(
1063         hdcref,
1064         &bih,
1065         CBM_INIT,
1066         bits,
1067         (BITMAPINFO*)&bih,
1068         DIB_RGB_COLORS);
1069
1070     if (This->desc.u.bmp.hbitmap == 0)
1071     {
1072         hr = E_FAIL;
1073         ReleaseDC(0, hdcref);
1074         goto end;
1075     }
1076
1077     This->desc.picType = PICTYPE_BITMAP;
1078     OLEPictureImpl_SetBitmap(This);
1079
1080     /* set transparent pixels to black, all others to white */
1081     for(y = 0; y < height; y++){
1082         for(x = 0; x < width; x++){
1083             DWORD *pixel = (DWORD*)(bits + stride*y + 4*x);
1084             if((*pixel & 0x80000000) == 0)
1085             {
1086                 has_alpha = TRUE;
1087                 *pixel = black;
1088             }
1089             else
1090                 *pixel = white;
1091         }
1092     }
1093
1094     if (has_alpha)
1095     {
1096         HDC hdcBmp, hdcXor, hdcMask;
1097         HBITMAP hbmoldBmp, hbmoldXor, hbmoldMask;
1098
1099         This->hbmXor = CreateDIBitmap(
1100             hdcref,
1101             &bih,
1102             CBM_INIT,
1103             bits,
1104             (BITMAPINFO*)&bih,
1105             DIB_RGB_COLORS
1106         );
1107
1108         This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
1109         hdcBmp = CreateCompatibleDC(NULL);
1110         hdcXor = CreateCompatibleDC(NULL);
1111         hdcMask = CreateCompatibleDC(NULL);
1112
1113         hbmoldBmp = SelectObject(hdcBmp,This->desc.u.bmp.hbitmap);
1114         hbmoldXor = SelectObject(hdcXor,This->hbmXor);
1115         hbmoldMask = SelectObject(hdcMask,This->hbmMask);
1116
1117         SetBkColor(hdcXor,black);
1118         BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
1119         BitBlt(hdcXor,0,0,width,height,hdcBmp,0,0,SRCAND);
1120
1121         SelectObject(hdcBmp,hbmoldBmp);
1122         SelectObject(hdcXor,hbmoldXor);
1123         SelectObject(hdcMask,hbmoldMask);
1124
1125         DeleteDC(hdcBmp);
1126         DeleteDC(hdcXor);
1127         DeleteDC(hdcMask);
1128     }
1129
1130     ReleaseDC(0, hdcref);
1131
1132 end:
1133     HeapFree(GetProcessHeap(), 0, bits);
1134     IWICBitmapSource_Release(real_source);
1135     return hr;
1136 }
1137
1138 static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID decoder_clsid, BYTE *xbuf, ULONG xread)
1139 {
1140     HRESULT hr;
1141     IWICImagingFactory *factory;
1142     IWICBitmapDecoder *decoder;
1143     IWICBitmapFrameDecode *framedecode;
1144     HRESULT initresult;
1145     IWICStream *stream;
1146
1147     initresult = CoInitialize(NULL);
1148
1149     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1150         &IID_IWICImagingFactory, (void**)&factory);
1151     if (SUCCEEDED(hr)) /* created factory */
1152     {
1153         hr = IWICImagingFactory_CreateStream(factory, &stream);
1154         IWICImagingFactory_Release(factory);
1155     }
1156
1157     if (SUCCEEDED(hr)) /* created stream */
1158     {
1159         hr = IWICStream_InitializeFromMemory(stream, xbuf, xread);
1160
1161         if (SUCCEEDED(hr)) /* initialized stream */
1162         {
1163             hr = CoCreateInstance(decoder_clsid, NULL, CLSCTX_INPROC_SERVER,
1164                 &IID_IWICBitmapDecoder, (void**)&decoder);
1165             if (SUCCEEDED(hr)) /* created decoder */
1166             {
1167                 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)stream, WICDecodeMetadataCacheOnLoad);
1168
1169                 if (SUCCEEDED(hr)) /* initialized decoder */
1170                     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode);
1171
1172                 IWICBitmapDecoder_Release(decoder);
1173             }
1174         }
1175
1176         IWICStream_Release(stream);
1177     }
1178
1179     if (SUCCEEDED(hr)) /* got framedecode */
1180     {
1181         hr = OLEPictureImpl_LoadWICSource(This, (IWICBitmapSource*)framedecode);
1182         IWICBitmapFrameDecode_Release(framedecode);
1183     }
1184
1185     if (SUCCEEDED(initresult)) CoUninitialize();
1186     return hr;
1187 }
1188
1189 /*****************************************************
1190 *   start of Icon-specific code
1191 */
1192
1193 static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1194 {
1195     HICON hicon;
1196     CURSORICONFILEDIR   *cifd = (CURSORICONFILEDIR*)xbuf;
1197     HDC hdcRef;
1198     int i;
1199
1200     /*
1201     FIXME("icon.idReserved=%d\n",cifd->idReserved);
1202     FIXME("icon.idType=%d\n",cifd->idType);
1203     FIXME("icon.idCount=%d\n",cifd->idCount);
1204
1205     for (i=0;i<cifd->idCount;i++) {
1206         FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1207         FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1208         FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1209         FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1210         FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1211         FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1212         FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1213         FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1214     }
1215     */
1216     i=0;
1217     /* If we have more than one icon, try to find the best.
1218      * this currently means '32 pixel wide'.
1219      */
1220     if (cifd->idCount!=1) {
1221         for (i=0;i<cifd->idCount;i++) {
1222             if (cifd->idEntries[i].bWidth == 32)
1223                 break;
1224         }
1225         if (i==cifd->idCount) i=0;
1226     }
1227
1228     hicon = CreateIconFromResourceEx(
1229                 xbuf+cifd->idEntries[i].dwDIBOffset,
1230                 cifd->idEntries[i].dwDIBSize,
1231                 TRUE, /* is icon */
1232                 0x00030000,
1233                 cifd->idEntries[i].bWidth,
1234                 cifd->idEntries[i].bHeight,
1235                 0
1236     );
1237     if (!hicon) {
1238         ERR("CreateIcon failed.\n");
1239         return E_FAIL;
1240     } else {
1241         This->desc.picType = PICTYPE_ICON;
1242         This->desc.u.icon.hicon = hicon;
1243         This->origWidth = cifd->idEntries[i].bWidth;
1244         This->origHeight = cifd->idEntries[i].bHeight;
1245         hdcRef = CreateCompatibleDC(0);
1246         This->himetricWidth = xpixels_to_himetric(cifd->idEntries[i].bWidth, hdcRef);
1247         This->himetricHeight= ypixels_to_himetric(cifd->idEntries[i].bHeight, hdcRef);
1248         DeleteDC(hdcRef);
1249         return S_OK;
1250     }
1251 }
1252
1253 static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
1254                                               const BYTE *data, ULONG size)
1255 {
1256     HENHMETAFILE hemf;
1257     ENHMETAHEADER hdr;
1258
1259     hemf = SetEnhMetaFileBits(size, data);
1260     if (!hemf) return E_FAIL;
1261
1262     GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
1263
1264     This->desc.picType = PICTYPE_ENHMETAFILE;
1265     This->desc.u.emf.hemf = hemf;
1266
1267     This->origWidth = 0;
1268     This->origHeight = 0;
1269     This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
1270     This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
1271
1272     return S_OK;
1273 }
1274
1275 static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
1276                                       const BYTE *data, ULONG size)
1277 {
1278     const APM_HEADER *header = (const APM_HEADER *)data;
1279     HMETAFILE hmf;
1280
1281     if (size < sizeof(APM_HEADER))
1282         return E_FAIL;
1283     if (header->key != 0x9ac6cdd7)
1284         return E_FAIL;
1285
1286     /* SetMetaFileBitsEx performs data check on its own */
1287     hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
1288     if (!hmf) return E_FAIL;
1289
1290     This->desc.picType = PICTYPE_METAFILE;
1291     This->desc.u.wmf.hmeta = hmf;
1292     This->desc.u.wmf.xExt = 0;
1293     This->desc.u.wmf.yExt = 0;
1294
1295     This->origWidth = 0;
1296     This->origHeight = 0;
1297     This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
1298     This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
1299     return S_OK;
1300 }
1301
1302 /************************************************************************
1303  * BITMAP FORMAT FLAGS -
1304  *   Flags that differentiate between different types of bitmaps.
1305  */
1306
1307 #define BITMAP_FORMAT_BMP   0x4d42 /* "BM" */
1308 #define BITMAP_FORMAT_JPEG  0xd8ff
1309 #define BITMAP_FORMAT_GIF   0x4947
1310 #define BITMAP_FORMAT_PNG   0x5089
1311 #define BITMAP_FORMAT_APM   0xcdd7
1312
1313 /************************************************************************
1314  * OLEPictureImpl_IPersistStream_Load (IUnknown)
1315  *
1316  * Loads the binary data from the IStream. Starts at current position.
1317  * There appears to be an 2 DWORD header:
1318  *      DWORD magic;
1319  *      DWORD len;
1320  *
1321  * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
1322  */
1323 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface, IStream *pStm) {
1324   HRESULT       hr;
1325   BOOL          headerisdata;
1326   BOOL          statfailed = FALSE;
1327   ULONG         xread, toread;
1328   ULONG         headerread;
1329   BYTE          *xbuf;
1330   DWORD         header[2];
1331   WORD          magic;
1332   STATSTG       statstg;
1333   OLEPictureImpl *This = impl_from_IPersistStream(iface);
1334   
1335   TRACE("(%p,%p)\n",This,pStm);
1336
1337   /****************************************************************************************
1338    * Part 1: Load the data
1339    */
1340   /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
1341    * out whether we do.
1342    *
1343    * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
1344    * compound file. This may explain most, if not all, of the cases of "no
1345    * header", and the header validation should take this into account.
1346    * At least in Visual Basic 6, resource streams, valid headers are
1347    *    header[0] == "lt\0\0",
1348    *    header[1] == length_of_stream.
1349    *
1350    * Also handle streams where we do not have a working "Stat" method by
1351    * reading all data until the end of the stream.
1352    */
1353   hr = IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
1354   if (hr != S_OK) {
1355       TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
1356       statfailed = TRUE;
1357       /* we will read at least 8 byte ... just right below */
1358       statstg.cbSize.QuadPart = 8;
1359   }
1360
1361   toread = 0;
1362   headerread = 0;
1363   headerisdata = FALSE;
1364   do {
1365       hr = IStream_Read(pStm, header, 8, &xread);
1366       if (hr != S_OK || xread!=8) {
1367           ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
1368           return (hr?hr:E_FAIL);
1369       }
1370       headerread += xread;
1371       xread = 0;
1372       
1373       if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
1374           if (toread != 0 && toread != header[1]) 
1375               FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
1376                   toread, header[1]);
1377           toread = header[1];
1378           if (toread == 0) break;
1379       } else {
1380           if (!memcmp(&(header[0]), "GIF8",     4) ||   /* GIF header */
1381               !memcmp(&(header[0]), "BM",       2) ||   /* BMP header */
1382               !memcmp(&(header[0]), "\xff\xd8", 2) ||   /* JPEG header */
1383               (header[0] == EMR_HEADER)            ||   /* EMF header */
1384               (header[1] > statstg.cbSize.QuadPart)||   /* invalid size */
1385               (header[1]==0)
1386           ) {/* Found start of bitmap data */
1387               headerisdata = TRUE;
1388               if (toread == 0) 
1389                   toread = statstg.cbSize.QuadPart-8;
1390               else toread -= 8;
1391               xread = 8;
1392           } else {
1393               FIXME("Unknown stream header magic: %08x\n", header[0]);
1394               toread = header[1];
1395           }
1396       }
1397   } while (!headerisdata);
1398
1399   if (statfailed) { /* we don't know the size ... read all we get */
1400       int sizeinc = 4096;
1401       int origsize = sizeinc;
1402       ULONG nread = 42;
1403
1404       TRACE("Reading all data from stream.\n");
1405       xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1406       if (headerisdata)
1407           memcpy (xbuf, header, 8);
1408       while (1) {
1409           while (xread < origsize) {
1410               hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1411               xread += nread;
1412               if (hr != S_OK || !nread)
1413                   break;
1414           }
1415           if (!nread || hr != S_OK) /* done, or error */
1416               break;
1417           if (xread == origsize) {
1418               origsize += sizeinc;
1419               sizeinc = 2*sizeinc; /* exponential increase */
1420               xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1421           }
1422       }
1423       if (hr != S_OK)
1424           TRACE("hr in no-stat loader case is %08x\n", hr);
1425       TRACE("loaded %d bytes.\n", xread);
1426       This->datalen = xread;
1427       This->data    = xbuf;
1428   } else {
1429       This->datalen = toread+(headerisdata?8:0);
1430       xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1431       if (!xbuf)
1432           return E_OUTOFMEMORY;
1433
1434       if (headerisdata)
1435           memcpy (xbuf, header, 8);
1436
1437       while (xread < This->datalen) {
1438           ULONG nread;
1439           hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1440           xread += nread;
1441           if (hr != S_OK || !nread)
1442               break;
1443       }
1444       if (xread != This->datalen)
1445           ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1446   }
1447   if (This->datalen == 0) { /* Marks the "NONE" picture */
1448       This->desc.picType = PICTYPE_NONE;
1449       return S_OK;
1450   }
1451
1452
1453   /****************************************************************************************
1454    * Part 2: Process the loaded data
1455    */
1456
1457   magic = xbuf[0] + (xbuf[1]<<8);
1458   This->loadtime_format = magic;
1459
1460   switch (magic) {
1461   case BITMAP_FORMAT_GIF: /* GIF */
1462     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
1463     break;
1464   case BITMAP_FORMAT_JPEG: /* JPEG */
1465     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
1466     break;
1467   case BITMAP_FORMAT_BMP: /* Bitmap */
1468     hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1469     break;
1470   case BITMAP_FORMAT_PNG: /* PNG */
1471     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
1472     break;
1473   case BITMAP_FORMAT_APM: /* APM */
1474     hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
1475     break;
1476   case 0x0000: { /* ICON , first word is dwReserved */
1477     hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1478     break;
1479   }
1480   default:
1481   {
1482     unsigned int i;
1483
1484     /* let's see if it's a EMF */
1485     hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
1486     if (hr == S_OK) break;
1487
1488     FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1489     hr=E_FAIL;
1490     for (i=0;i<xread+8;i++) {
1491         if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
1492         else MESSAGE("%02x ",xbuf[i-8]);
1493         if (i % 10 == 9) MESSAGE("\n");
1494     }
1495     MESSAGE("\n");
1496     break;
1497   }
1498   }
1499   This->bIsDirty = FALSE;
1500
1501   /* FIXME: this notify is not really documented */
1502   if (hr==S_OK)
1503       OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1504   return hr;
1505 }
1506
1507 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1508 {
1509     int iSuccess = 0;
1510     HDC hDC;
1511     BITMAPINFO * pInfoBitmap;
1512     int iNumPaletteEntries;
1513     unsigned char * pPixelData;
1514     BITMAPFILEHEADER * pFileHeader;
1515     BITMAPINFO * pInfoHeader;
1516
1517     pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1518         sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1519
1520     /* Find out bitmap size and padded length */
1521     hDC = GetDC(0);
1522     pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1523     GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1524
1525     /* Fetch bitmap palette & pixel data */
1526
1527     pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1528     GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1529
1530     /* Calculate the total length required for the BMP data */
1531     if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1532         iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1533         if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1534     } else {
1535         if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1536             iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1537         else
1538             iNumPaletteEntries = 0;
1539     }
1540     *pLength =
1541         sizeof(BITMAPFILEHEADER) +
1542         sizeof(BITMAPINFOHEADER) +
1543         iNumPaletteEntries * sizeof(RGBQUAD) +
1544         pInfoBitmap->bmiHeader.biSizeImage;
1545     *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1546
1547     /* Fill the BITMAPFILEHEADER */
1548     pFileHeader = *ppBuffer;
1549     pFileHeader->bfType = BITMAP_FORMAT_BMP;
1550     pFileHeader->bfSize = *pLength;
1551     pFileHeader->bfOffBits =
1552         sizeof(BITMAPFILEHEADER) +
1553         sizeof(BITMAPINFOHEADER) +
1554         iNumPaletteEntries * sizeof(RGBQUAD);
1555
1556     /* Fill the BITMAPINFOHEADER and the palette data */
1557     pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1558     memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1559     memcpy(
1560         (unsigned char *)(*ppBuffer) +
1561             sizeof(BITMAPFILEHEADER) +
1562             sizeof(BITMAPINFOHEADER) +
1563             iNumPaletteEntries * sizeof(RGBQUAD),
1564         pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1565     iSuccess = 1;
1566
1567     HeapFree(GetProcessHeap(), 0, pPixelData);
1568     HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1569     return iSuccess;
1570 }
1571
1572 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1573 {
1574         ICONINFO infoIcon;
1575         int iSuccess = 0;
1576
1577         *ppBuffer = NULL; *pLength = 0;
1578         if (GetIconInfo(hIcon, &infoIcon)) {
1579                 HDC hDC;
1580                 BITMAPINFO * pInfoBitmap;
1581                 unsigned char * pIconData = NULL;
1582                 unsigned int iDataSize = 0;
1583
1584         pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1585
1586                 /* Find out icon size */
1587                 hDC = GetDC(0);
1588                 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1589                 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1590                 if (1) {
1591                         /* Auxiliary pointers */
1592                         CURSORICONFILEDIR * pIconDir;
1593                         CURSORICONFILEDIRENTRY * pIconEntry;
1594                         BITMAPINFOHEADER * pIconBitmapHeader;
1595                         unsigned int iOffsetPalette;
1596                         unsigned int iOffsetColorData;
1597                         unsigned int iOffsetMaskData;
1598
1599                         unsigned int iLengthScanLineMask;
1600                         unsigned int iNumEntriesPalette;
1601
1602                         iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 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 Own, void **ppvObj )
2146 {
2147   OLEPictureImpl* newPict;
2148   HRESULT hr;
2149
2150   TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), Own, ppvObj);
2151
2152   *ppvObj = NULL;
2153
2154   newPict = OLEPictureImpl_Construct(lpPictDesc, Own);
2155
2156   if (newPict == NULL)
2157     return E_OUTOFMEMORY;
2158
2159   /*
2160    * Make sure it supports the interface required by the caller.
2161    */
2162   hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2163
2164   /*
2165    * Release the reference obtained in the constructor. If
2166    * the QueryInterface was unsuccessful, it will free the class.
2167    */
2168   IPicture_Release((IPicture*)newPict);
2169
2170   return hr;
2171 }
2172
2173
2174 /***********************************************************************
2175  * OleLoadPicture (OLEAUT32.418)
2176  */
2177 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2178                             REFIID riid, LPVOID *ppvObj )
2179 {
2180   LPPERSISTSTREAM ps;
2181   IPicture      *newpic;
2182   HRESULT hr;
2183
2184   TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2185         lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2186
2187   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2188   if (hr != S_OK)
2189     return hr;
2190   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2191   if (hr != S_OK) {
2192       ERR("Could not get IPersistStream iface from Ole Picture?\n");
2193       IPicture_Release(newpic);
2194       *ppvObj = NULL;
2195       return hr;
2196   }
2197   hr = IPersistStream_Load(ps,lpstream);
2198   IPersistStream_Release(ps);
2199   if (FAILED(hr))
2200   {
2201       ERR("IPersistStream_Load failed\n");
2202       IPicture_Release(newpic);
2203       *ppvObj = NULL;
2204       return hr;
2205   }
2206   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2207   if (hr != S_OK)
2208       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2209   IPicture_Release(newpic);
2210   return hr;
2211 }
2212
2213 /***********************************************************************
2214  * OleLoadPictureEx (OLEAUT32.401)
2215  */
2216 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2217                             REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2218 {
2219   LPPERSISTSTREAM ps;
2220   IPicture      *newpic;
2221   HRESULT hr;
2222
2223   FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2224         lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2225
2226   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2227   if (hr != S_OK)
2228     return hr;
2229   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2230   if (hr != S_OK) {
2231       ERR("Could not get IPersistStream iface from Ole Picture?\n");
2232       IPicture_Release(newpic);
2233       *ppvObj = NULL;
2234       return hr;
2235   }
2236   hr = IPersistStream_Load(ps,lpstream);
2237   IPersistStream_Release(ps);
2238   if (FAILED(hr))
2239   {
2240       ERR("IPersistStream_Load failed\n");
2241       IPicture_Release(newpic);
2242       *ppvObj = NULL;
2243       return hr;
2244   }
2245   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2246   if (hr != S_OK)
2247       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2248   IPicture_Release(newpic);
2249   return hr;
2250 }
2251
2252 /***********************************************************************
2253  * OleLoadPicturePath (OLEAUT32.424)
2254  */
2255 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2256                 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2257                 LPVOID *ppvRet )
2258 {
2259   static const WCHAR file[] = { 'f','i','l','e',':',0 };
2260   IPicture *ipicture;
2261   HANDLE hFile;
2262   DWORD dwFileSize;
2263   HGLOBAL hGlobal = NULL;
2264   DWORD dwBytesRead = 0;
2265   IStream *stream;
2266   BOOL bRead;
2267   IPersistStream *pStream;
2268   HRESULT hRes;
2269   HRESULT init_res;
2270   WCHAR *file_candidate;
2271   WCHAR path_buf[MAX_PATH];
2272
2273   TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2274         debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2275         debugstr_guid(riid), ppvRet);
2276
2277   if (!szURLorPath || !ppvRet)
2278       return E_INVALIDARG;
2279
2280   *ppvRet = NULL;
2281
2282   /* Convert file URLs to DOS paths. */
2283   if (strncmpW(szURLorPath, file, 5) == 0) {
2284       DWORD size;
2285       hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
2286                                 sizeof(path_buf)/sizeof(WCHAR), &size, 0);
2287       if (FAILED(hRes))
2288           return hRes;
2289
2290       file_candidate = path_buf;
2291   }
2292   else
2293       file_candidate = szURLorPath;
2294
2295   /* Handle candidate DOS paths separately. */
2296   if (file_candidate[1] == ':') {
2297       hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2298                           0, NULL);
2299       if (hFile == INVALID_HANDLE_VALUE)
2300           return E_UNEXPECTED;
2301
2302       dwFileSize = GetFileSize(hFile, NULL);
2303       if (dwFileSize != INVALID_FILE_SIZE )
2304       {
2305           hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2306           if ( hGlobal)
2307           {
2308               bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2309               if (!bRead)
2310               {
2311                   GlobalFree(hGlobal);
2312                   hGlobal = 0;
2313               }
2314           }
2315       }
2316       CloseHandle(hFile);
2317       
2318       if (!hGlobal)
2319           return E_UNEXPECTED;
2320
2321       hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2322       if (FAILED(hRes)) 
2323       {
2324           GlobalFree(hGlobal);
2325           return hRes;
2326       }
2327   } else {
2328       IMoniker *pmnk;
2329       IBindCtx *pbc;
2330
2331       hRes = CreateBindCtx(0, &pbc);
2332       if (SUCCEEDED(hRes)) 
2333       {
2334           hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2335           if (SUCCEEDED(hRes))
2336           {              
2337               hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2338               IMoniker_Release(pmnk);
2339           }
2340           IBindCtx_Release(pbc);
2341       }
2342       if (FAILED(hRes))
2343           return hRes;
2344   }
2345
2346   init_res = CoInitialize(NULL);
2347
2348   hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2349                           &IID_IPicture, (LPVOID*)&ipicture);
2350   if (SUCCEEDED(hRes)) {
2351       hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2352
2353       if (SUCCEEDED(hRes)) {
2354           hRes = IPersistStream_Load(pStream, stream);
2355
2356           if (SUCCEEDED(hRes)) {
2357               hRes = IPicture_QueryInterface(ipicture, riid, ppvRet);
2358
2359               if (FAILED(hRes))
2360                   ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid));
2361           }
2362           IPersistStream_Release(pStream);
2363       }
2364       IPicture_Release(ipicture);
2365   }
2366
2367   IStream_Release(stream);
2368
2369   if (SUCCEEDED(init_res))
2370       CoUninitialize();
2371
2372   return hRes;
2373 }
2374
2375 /*******************************************************************************
2376  * StdPic ClassFactory
2377  */
2378 typedef struct
2379 {
2380     /* IUnknown fields */
2381     const IClassFactoryVtbl    *lpVtbl;
2382     LONG                        ref;
2383 } IClassFactoryImpl;
2384
2385 static HRESULT WINAPI
2386 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2387         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2388
2389         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2390         return E_NOINTERFACE;
2391 }
2392
2393 static ULONG WINAPI
2394 SPCF_AddRef(LPCLASSFACTORY iface) {
2395         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2396         return InterlockedIncrement(&This->ref);
2397 }
2398
2399 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2400         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2401         /* static class, won't be  freed */
2402         return InterlockedDecrement(&This->ref);
2403 }
2404
2405 static HRESULT WINAPI SPCF_CreateInstance(
2406         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2407 ) {
2408     /* Creates an uninitialized picture */
2409     return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2410
2411 }
2412
2413 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2414         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2415         FIXME("(%p)->(%d),stub!\n",This,dolock);
2416         return S_OK;
2417 }
2418
2419 static const IClassFactoryVtbl SPCF_Vtbl = {
2420         SPCF_QueryInterface,
2421         SPCF_AddRef,
2422         SPCF_Release,
2423         SPCF_CreateInstance,
2424         SPCF_LockServer
2425 };
2426 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2427
2428 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }