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