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