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