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