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