wined3d: Use ARB_internalformat_query2 for the other texture format caps too.
[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[0] == 0x10000)               ||   /* icon: idReserved 0, idType 1 */
1406               (header[0] == 0x20000)               ||   /* cursor: idReserved 0, idType 2 */
1407               (header[1] > statstg.cbSize.QuadPart)||   /* invalid size */
1408               (header[1]==0)
1409           ) {/* Found start of bitmap data */
1410               headerisdata = TRUE;
1411               if (toread == 0) 
1412                   toread = statstg.cbSize.QuadPart-8;
1413               else toread -= 8;
1414               xread = 8;
1415           } else {
1416               FIXME("Unknown stream header magic: %08x\n", header[0]);
1417               toread = header[1];
1418           }
1419       }
1420   } while (!headerisdata);
1421
1422   if (statfailed) { /* we don't know the size ... read all we get */
1423       unsigned int sizeinc = 4096;
1424       unsigned int origsize = sizeinc;
1425       ULONG nread = 42;
1426
1427       TRACE("Reading all data from stream.\n");
1428       xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
1429       if (headerisdata)
1430           memcpy (xbuf, header, 8);
1431       while (1) {
1432           while (xread < origsize) {
1433               hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
1434               xread += nread;
1435               if (hr != S_OK || !nread)
1436                   break;
1437           }
1438           if (!nread || hr != S_OK) /* done, or error */
1439               break;
1440           if (xread == origsize) {
1441               origsize += sizeinc;
1442               sizeinc = 2*sizeinc; /* exponential increase */
1443               xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
1444           }
1445       }
1446       if (hr != S_OK)
1447           TRACE("hr in no-stat loader case is %08x\n", hr);
1448       TRACE("loaded %d bytes.\n", xread);
1449       This->datalen = xread;
1450       This->data    = xbuf;
1451   } else {
1452       This->datalen = toread+(headerisdata?8:0);
1453       xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
1454       if (!xbuf)
1455           return E_OUTOFMEMORY;
1456
1457       if (headerisdata)
1458           memcpy (xbuf, header, 8);
1459
1460       while (xread < This->datalen) {
1461           ULONG nread;
1462           hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
1463           xread += nread;
1464           if (hr != S_OK || !nread)
1465               break;
1466       }
1467       if (xread != This->datalen)
1468           ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
1469   }
1470   if (This->datalen == 0) { /* Marks the "NONE" picture */
1471       This->desc.picType = PICTYPE_NONE;
1472       return S_OK;
1473   }
1474
1475
1476   /****************************************************************************************
1477    * Part 2: Process the loaded data
1478    */
1479
1480   magic = xbuf[0] + (xbuf[1]<<8);
1481   This->loadtime_format = magic;
1482
1483   switch (magic) {
1484   case BITMAP_FORMAT_GIF: /* GIF */
1485     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICGifDecoder, xbuf, xread);
1486     break;
1487   case BITMAP_FORMAT_JPEG: /* JPEG */
1488     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICJpegDecoder, xbuf, xread);
1489     break;
1490   case BITMAP_FORMAT_BMP: /* Bitmap */
1491     hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
1492     break;
1493   case BITMAP_FORMAT_PNG: /* PNG */
1494     hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
1495     break;
1496   case BITMAP_FORMAT_APM: /* APM */
1497     hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
1498     break;
1499   case 0x0000: { /* ICON or CURSOR, first word is dwReserved */
1500     hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
1501     break;
1502   }
1503   default:
1504   {
1505     unsigned int i;
1506
1507     /* let's see if it's a EMF */
1508     hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
1509     if (hr == S_OK) break;
1510
1511     FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
1512     hr=E_FAIL;
1513     for (i=0;i<xread+8;i++) {
1514         if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
1515         else MESSAGE("%02x ",xbuf[i-8]);
1516         if (i % 10 == 9) MESSAGE("\n");
1517     }
1518     MESSAGE("\n");
1519     break;
1520   }
1521   }
1522   This->bIsDirty = FALSE;
1523
1524   /* FIXME: this notify is not really documented */
1525   if (hr==S_OK)
1526       OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1527   return hr;
1528 }
1529
1530 static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
1531 {
1532     int iSuccess = 0;
1533     HDC hDC;
1534     BITMAPINFO * pInfoBitmap;
1535     int iNumPaletteEntries;
1536     unsigned char * pPixelData;
1537     BITMAPFILEHEADER * pFileHeader;
1538     BITMAPINFO * pInfoHeader;
1539
1540     pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1541         sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1542
1543     /* Find out bitmap size and padded length */
1544     hDC = GetDC(0);
1545     pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1546     GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1547
1548     /* Fetch bitmap palette & pixel data */
1549
1550     pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
1551     GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
1552
1553     /* Calculate the total length required for the BMP data */
1554     if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
1555         iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
1556         if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
1557     } else {
1558         if (pInfoBitmap->bmiHeader.biBitCount <= 8)
1559             iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
1560         else
1561             iNumPaletteEntries = 0;
1562     }
1563     *pLength =
1564         sizeof(BITMAPFILEHEADER) +
1565         sizeof(BITMAPINFOHEADER) +
1566         iNumPaletteEntries * sizeof(RGBQUAD) +
1567         pInfoBitmap->bmiHeader.biSizeImage;
1568     *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
1569
1570     /* Fill the BITMAPFILEHEADER */
1571     pFileHeader = *ppBuffer;
1572     pFileHeader->bfType = BITMAP_FORMAT_BMP;
1573     pFileHeader->bfSize = *pLength;
1574     pFileHeader->bfOffBits =
1575         sizeof(BITMAPFILEHEADER) +
1576         sizeof(BITMAPINFOHEADER) +
1577         iNumPaletteEntries * sizeof(RGBQUAD);
1578
1579     /* Fill the BITMAPINFOHEADER and the palette data */
1580     pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
1581     memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
1582     memcpy(
1583         (unsigned char *)(*ppBuffer) +
1584             sizeof(BITMAPFILEHEADER) +
1585             sizeof(BITMAPINFOHEADER) +
1586             iNumPaletteEntries * sizeof(RGBQUAD),
1587         pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
1588     iSuccess = 1;
1589
1590     HeapFree(GetProcessHeap(), 0, pPixelData);
1591     HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1592     return iSuccess;
1593 }
1594
1595 static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
1596 {
1597         ICONINFO infoIcon;
1598         int iSuccess = 0;
1599
1600         *ppBuffer = NULL; *pLength = 0;
1601         if (GetIconInfo(hIcon, &infoIcon)) {
1602                 HDC hDC;
1603                 BITMAPINFO * pInfoBitmap;
1604                 unsigned char * pIconData = NULL;
1605                 unsigned int iDataSize = 0;
1606
1607         pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1608
1609                 /* Find out icon size */
1610                 hDC = GetDC(0);
1611                 pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1612                 GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1613                 if (1) {
1614                         /* Auxiliary pointers */
1615                         CURSORICONFILEDIR * pIconDir;
1616                         CURSORICONFILEDIRENTRY * pIconEntry;
1617                         BITMAPINFOHEADER * pIconBitmapHeader;
1618                         unsigned int iOffsetPalette;
1619                         unsigned int iOffsetColorData;
1620                         unsigned int iOffsetMaskData;
1621
1622                         unsigned int iLengthScanLineMask;
1623                         unsigned int iNumEntriesPalette;
1624
1625                         iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
1626 /*
1627                         FIXME("DEBUG: bitmap size is %d x %d\n",
1628                                 pInfoBitmap->bmiHeader.biWidth,
1629                                 pInfoBitmap->bmiHeader.biHeight);
1630                         FIXME("DEBUG: bitmap bpp is %d\n",
1631                                 pInfoBitmap->bmiHeader.biBitCount);
1632                         FIXME("DEBUG: bitmap nplanes is %d\n",
1633                                 pInfoBitmap->bmiHeader.biPlanes);
1634                         FIXME("DEBUG: bitmap biSizeImage is %u\n",
1635                                 pInfoBitmap->bmiHeader.biSizeImage);
1636 */
1637                         /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
1638                         iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
1639                         pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
1640
1641                         /* Fill out the CURSORICONFILEDIR */
1642                         pIconDir = (CURSORICONFILEDIR *)pIconData;
1643                         pIconDir->idType = 1;
1644                         pIconDir->idCount = 1;
1645                         pIconDir->idReserved = 0;
1646
1647                         /* Fill out the CURSORICONFILEDIRENTRY */
1648                         pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1649                         pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
1650                         pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
1651                         pIconEntry->bColorCount =
1652                                 (pInfoBitmap->bmiHeader.biBitCount < 8)
1653                                 ? 1 << pInfoBitmap->bmiHeader.biBitCount
1654                                 : 0;
1655                         pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
1656                         pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
1657                         pIconEntry->dwDIBSize = 0;
1658                         pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
1659
1660                         /* Fill out the BITMAPINFOHEADER */
1661                         pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1662                         *pIconBitmapHeader = pInfoBitmap->bmiHeader;
1663
1664                         /*      Find out whether a palette exists for the bitmap */
1665                         if (    (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
1666                                 ||      (pInfoBitmap->bmiHeader.biBitCount == 24)
1667                                 ||      (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
1668                                 iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
1669                                 if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; 
1670                         } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
1671                                 && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
1672                                 iNumEntriesPalette = 3;
1673                         } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
1674                                 iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
1675                         } else {
1676                                 iNumEntriesPalette = 0;
1677                         }
1678
1679                         /*  Add bitmap size and header size to icon data size. */
1680                         iOffsetPalette = iDataSize;
1681                         iDataSize += iNumEntriesPalette * sizeof(DWORD);
1682                         iOffsetColorData = iDataSize;
1683                         iDataSize += pIconBitmapHeader->biSizeImage;
1684                         iOffsetMaskData = iDataSize;
1685                         iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1686                         pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
1687                         pIconBitmapHeader->biHeight *= 2;
1688                         pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
1689                         pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
1690                         pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1691                         pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
1692
1693                         /* Get the actual bitmap data from the icon bitmap */
1694                         GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
1695                                 pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
1696                         if (iNumEntriesPalette > 0) {
1697                                 memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
1698                                         iNumEntriesPalette * sizeof(RGBQUAD));
1699                         }
1700
1701                         /* Reset all values so that GetDIBits call succeeds */
1702                         memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
1703                         memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1704                         pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
1705 /*
1706             if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
1707                                 && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
1708                                         pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
1709
1710                 printf("ERROR: unable to get bitmap mask (error %u)\n",
1711                                         GetLastError());
1712
1713                         }
1714 */
1715             GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
1716             GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
1717
1718                         /* Write out everything produced so far to the stream */
1719                         *ppBuffer = pIconData; *pLength = iDataSize;
1720                         iSuccess = 1;
1721                 } else {
1722 /*
1723                         printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
1724                                 GetLastError());
1725 */
1726                 }
1727                 /*
1728                         Remarks (from MSDN entry on GetIconInfo):
1729
1730                         GetIconInfo creates bitmaps for the hbmMask and hbmColor
1731                         members of ICONINFO. The calling application must manage
1732                         these bitmaps and delete them when they are no longer
1733                         necessary.
1734                  */
1735                 if (hDC) ReleaseDC(0, hDC);
1736                 DeleteObject(infoIcon.hbmMask);
1737                 if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
1738                 HeapFree(GetProcessHeap(), 0, pInfoBitmap);
1739         } else {
1740                 printf("ERROR: Unable to get icon information (error %u)\n",
1741                         GetLastError());
1742         }
1743         return iSuccess;
1744 }
1745
1746 static HRESULT WINAPI OLEPictureImpl_Save(
1747   IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1748 {
1749     HRESULT hResult = E_NOTIMPL;
1750     void * pIconData;
1751     unsigned int iDataSize;
1752     DWORD header[2];
1753     ULONG dummy;
1754     int iSerializeResult = 0;
1755     OLEPictureImpl *This = impl_from_IPersistStream(iface);
1756
1757     TRACE("%p %p %d\n", This, pStm, fClearDirty);
1758
1759     switch (This->desc.picType) {
1760     case PICTYPE_NONE:
1761         header[0] = 0x0000746c;
1762         header[1] = 0;
1763         hResult = IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1764         break;
1765
1766     case PICTYPE_ICON:
1767         if (This->bIsDirty || !This->data) {
1768             if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
1769                 ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
1770                 hResult = E_FAIL;
1771                 break;
1772             }
1773             HeapFree(GetProcessHeap(), 0, This->data);
1774             This->data = pIconData;
1775             This->datalen = iDataSize;
1776         }
1777
1778         header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1779         header[1] = This->datalen;
1780         IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1781         IStream_Write(pStm, This->data, This->datalen, &dummy);
1782         hResult = S_OK;
1783         break;
1784     case PICTYPE_BITMAP:
1785         if (This->bIsDirty || !This->data) {
1786             switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
1787             case BITMAP_FORMAT_BMP:
1788                 iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
1789                 break;
1790             case BITMAP_FORMAT_JPEG:
1791                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
1792                 break;
1793             case BITMAP_FORMAT_GIF:
1794                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
1795                 break;
1796             case BITMAP_FORMAT_PNG:
1797                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
1798                 break;
1799             default:
1800                 FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
1801                 break;
1802             }
1803
1804             if (!iSerializeResult)
1805             {
1806                 hResult = E_FAIL;
1807                 break;
1808             }
1809
1810             HeapFree(GetProcessHeap(), 0, This->data);
1811             This->data = pIconData;
1812             This->datalen = iDataSize;
1813         }
1814
1815         header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
1816         header[1] = This->datalen;
1817         IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
1818         IStream_Write(pStm, This->data, This->datalen, &dummy);
1819         hResult = S_OK;
1820         break;
1821     case PICTYPE_METAFILE:
1822         FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
1823         break;
1824     case PICTYPE_ENHMETAFILE:
1825         FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
1826         break;
1827     default:
1828         FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
1829         break;
1830     }
1831     if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
1832     return hResult;
1833 }
1834
1835 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1836   IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1837 {
1838   OLEPictureImpl *This = impl_from_IPersistStream(iface);
1839   FIXME("(%p,%p),stub!\n",This,pcbSize);
1840   return E_NOTIMPL;
1841 }
1842
1843
1844 /************************************************************************
1845  *    IDispatch
1846  */
1847
1848 /************************************************************************
1849  * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1850  *
1851  * See Windows documentation for more details on IUnknown methods.
1852  */
1853 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1854   IDispatch* iface,
1855   REFIID     riid,
1856   VOID**     ppvoid)
1857 {
1858   OLEPictureImpl *This = impl_from_IDispatch(iface);
1859
1860   return IPicture_QueryInterface(&This->IPicture_iface, riid, ppvoid);
1861 }
1862
1863 /************************************************************************
1864  * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1865  *
1866  * See Windows documentation for more details on IUnknown methods.
1867  */
1868 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1869   IDispatch* iface)
1870 {
1871   OLEPictureImpl *This = impl_from_IDispatch(iface);
1872
1873   return IPicture_AddRef(&This->IPicture_iface);
1874 }
1875
1876 /************************************************************************
1877  * OLEPictureImpl_IDispatch_Release (IUnknown)
1878  *
1879  * See Windows documentation for more details on IUnknown methods.
1880  */
1881 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1882   IDispatch* iface)
1883 {
1884   OLEPictureImpl *This = impl_from_IDispatch(iface);
1885
1886   return IPicture_Release(&This->IPicture_iface);
1887 }
1888
1889 /************************************************************************
1890  * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1891  *
1892  * See Windows documentation for more details on IDispatch methods.
1893  */
1894 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1895   IDispatch*    iface,
1896   unsigned int* pctinfo)
1897 {
1898   TRACE("(%p)\n", pctinfo);
1899
1900   *pctinfo = 1;
1901
1902   return S_OK;
1903 }
1904
1905 /************************************************************************
1906  * OLEPictureImpl_GetTypeInfo (IDispatch)
1907  *
1908  * See Windows documentation for more details on IDispatch methods.
1909  */
1910 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1911   IDispatch*  iface,
1912   UINT      iTInfo,
1913   LCID        lcid,
1914   ITypeInfo** ppTInfo)
1915 {
1916   static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1917   ITypeLib *tl;
1918   HRESULT hres;
1919
1920   TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
1921
1922   if (iTInfo != 0)
1923     return E_FAIL;
1924
1925   hres = LoadTypeLib(stdole2tlb, &tl);
1926   if (FAILED(hres))
1927   {
1928     ERR("Could not load stdole2.tlb\n");
1929     return hres;
1930   }
1931
1932   hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
1933   if (FAILED(hres))
1934     ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
1935
1936   return hres;
1937 }
1938
1939 /************************************************************************
1940  * OLEPictureImpl_GetIDsOfNames (IDispatch)
1941  *
1942  * See Windows documentation for more details on IDispatch methods.
1943  */
1944 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1945   IDispatch*  iface,
1946   REFIID      riid,
1947   LPOLESTR* rgszNames,
1948   UINT      cNames,
1949   LCID        lcid,
1950   DISPID*     rgDispId)
1951 {
1952   ITypeInfo * pTInfo;
1953   HRESULT hres;
1954
1955   TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
1956         rgszNames, cNames, (int)lcid, rgDispId);
1957
1958   if (cNames == 0)
1959   {
1960     return E_INVALIDARG;
1961   }
1962   else
1963   {
1964     /* retrieve type information */
1965     hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1966
1967     if (FAILED(hres))
1968     {
1969       ERR("GetTypeInfo failed.\n");
1970       return hres;
1971     }
1972
1973     /* convert names to DISPIDs */
1974     hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1975     ITypeInfo_Release(pTInfo);
1976
1977     return hres;
1978   }
1979 }
1980
1981 /************************************************************************
1982  * OLEPictureImpl_Invoke (IDispatch)
1983  *
1984  * See Windows documentation for more details on IDispatch methods.
1985  */
1986 static HRESULT WINAPI OLEPictureImpl_Invoke(
1987   IDispatch*  iface,
1988   DISPID      dispIdMember,
1989   REFIID      riid,
1990   LCID        lcid,
1991   WORD        wFlags,
1992   DISPPARAMS* pDispParams,
1993   VARIANT*    pVarResult,
1994   EXCEPINFO*  pExepInfo,
1995   UINT*     puArgErr)
1996 {
1997   OLEPictureImpl *This = impl_from_IDispatch(iface);
1998
1999   /* validate parameters */
2000
2001   if (!IsEqualIID(riid, &IID_NULL))
2002   {
2003     ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
2004     return DISP_E_UNKNOWNNAME;
2005   }
2006
2007   if (!pDispParams)
2008   {
2009     ERR("null pDispParams not allowed\n");
2010     return DISP_E_PARAMNOTOPTIONAL;
2011   }
2012
2013   if (wFlags & DISPATCH_PROPERTYGET)
2014   {
2015     if (pDispParams->cArgs != 0)
2016     {
2017       ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
2018       return DISP_E_BADPARAMCOUNT;
2019     }
2020     if (!pVarResult)
2021     {
2022       ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
2023       return DISP_E_PARAMNOTOPTIONAL;
2024     }
2025   }
2026   else if (wFlags & DISPATCH_PROPERTYPUT)
2027   {
2028     if (pDispParams->cArgs != 1)
2029     {
2030       ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
2031       return DISP_E_BADPARAMCOUNT;
2032     }
2033   }
2034
2035   switch (dispIdMember)
2036   {
2037   case DISPID_PICT_HANDLE:
2038     if (wFlags & DISPATCH_PROPERTYGET)
2039     {
2040       TRACE("DISPID_PICT_HANDLE\n");
2041       V_VT(pVarResult) = VT_I4;
2042       return IPicture_get_Handle(&This->IPicture_iface, &V_UINT(pVarResult));
2043     }
2044     break;
2045   case DISPID_PICT_HPAL:
2046     if (wFlags & DISPATCH_PROPERTYGET)
2047     {
2048       TRACE("DISPID_PICT_HPAL\n");
2049       V_VT(pVarResult) = VT_I4;
2050       return IPicture_get_hPal(&This->IPicture_iface, &V_UINT(pVarResult));
2051     }
2052     else if (wFlags & DISPATCH_PROPERTYPUT)
2053     {
2054       VARIANTARG vararg;
2055       HRESULT hr;
2056       TRACE("DISPID_PICT_HPAL\n");
2057
2058       VariantInit(&vararg);
2059       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
2060       if (FAILED(hr))
2061         return hr;
2062
2063       hr = IPicture_set_hPal(&This->IPicture_iface, V_I4(&vararg));
2064
2065       VariantClear(&vararg);
2066       return hr;
2067     }
2068     break;
2069   case DISPID_PICT_TYPE:
2070     if (wFlags & DISPATCH_PROPERTYGET)
2071     {
2072       TRACE("DISPID_PICT_TYPE\n");
2073       V_VT(pVarResult) = VT_I2;
2074       return OLEPictureImpl_get_Type(&This->IPicture_iface, &V_I2(pVarResult));
2075     }
2076     break;
2077   case DISPID_PICT_WIDTH:
2078     if (wFlags & DISPATCH_PROPERTYGET)
2079     {
2080       TRACE("DISPID_PICT_WIDTH\n");
2081       V_VT(pVarResult) = VT_I4;
2082       return IPicture_get_Width(&This->IPicture_iface, &V_I4(pVarResult));
2083     }
2084     break;
2085   case DISPID_PICT_HEIGHT:
2086     if (wFlags & DISPATCH_PROPERTYGET)
2087     {
2088       TRACE("DISPID_PICT_HEIGHT\n");
2089       V_VT(pVarResult) = VT_I4;
2090       return IPicture_get_Height(&This->IPicture_iface, &V_I4(pVarResult));
2091     }
2092     break;
2093   }
2094
2095   ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
2096   return DISP_E_MEMBERNOTFOUND;
2097 }
2098
2099
2100 static const IPictureVtbl OLEPictureImpl_VTable =
2101 {
2102   OLEPictureImpl_QueryInterface,
2103   OLEPictureImpl_AddRef,
2104   OLEPictureImpl_Release,
2105   OLEPictureImpl_get_Handle,
2106   OLEPictureImpl_get_hPal,
2107   OLEPictureImpl_get_Type,
2108   OLEPictureImpl_get_Width,
2109   OLEPictureImpl_get_Height,
2110   OLEPictureImpl_Render,
2111   OLEPictureImpl_set_hPal,
2112   OLEPictureImpl_get_CurDC,
2113   OLEPictureImpl_SelectPicture,
2114   OLEPictureImpl_get_KeepOriginalFormat,
2115   OLEPictureImpl_put_KeepOriginalFormat,
2116   OLEPictureImpl_PictureChanged,
2117   OLEPictureImpl_SaveAsFile,
2118   OLEPictureImpl_get_Attributes
2119 };
2120
2121 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2122 {
2123   OLEPictureImpl_IDispatch_QueryInterface,
2124   OLEPictureImpl_IDispatch_AddRef,
2125   OLEPictureImpl_IDispatch_Release,
2126   OLEPictureImpl_GetTypeInfoCount,
2127   OLEPictureImpl_GetTypeInfo,
2128   OLEPictureImpl_GetIDsOfNames,
2129   OLEPictureImpl_Invoke
2130 };
2131
2132 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2133 {
2134   OLEPictureImpl_IPersistStream_QueryInterface,
2135   OLEPictureImpl_IPersistStream_AddRef,
2136   OLEPictureImpl_IPersistStream_Release,
2137   OLEPictureImpl_GetClassID,
2138   OLEPictureImpl_IsDirty,
2139   OLEPictureImpl_Load,
2140   OLEPictureImpl_Save,
2141   OLEPictureImpl_GetSizeMax
2142 };
2143
2144 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2145 {
2146   OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2147   OLEPictureImpl_IConnectionPointContainer_AddRef,
2148   OLEPictureImpl_IConnectionPointContainer_Release,
2149   OLEPictureImpl_EnumConnectionPoints,
2150   OLEPictureImpl_FindConnectionPoint
2151 };
2152
2153 /***********************************************************************
2154  * OleCreatePictureIndirect (OLEAUT32.419)
2155  */
2156 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2157                             BOOL Own, void **ppvObj )
2158 {
2159   OLEPictureImpl* newPict;
2160   HRESULT hr;
2161
2162   TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), Own, ppvObj);
2163
2164   *ppvObj = NULL;
2165
2166   newPict = OLEPictureImpl_Construct(lpPictDesc, Own);
2167
2168   if (newPict == NULL)
2169     return E_OUTOFMEMORY;
2170
2171   /*
2172    * Make sure it supports the interface required by the caller.
2173    */
2174   hr = IPicture_QueryInterface(&newPict->IPicture_iface, riid, ppvObj);
2175
2176   /*
2177    * Release the reference obtained in the constructor. If
2178    * the QueryInterface was unsuccessful, it will free the class.
2179    */
2180   IPicture_Release(&newPict->IPicture_iface);
2181
2182   return hr;
2183 }
2184
2185
2186 /***********************************************************************
2187  * OleLoadPicture (OLEAUT32.418)
2188  */
2189 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2190                             REFIID riid, LPVOID *ppvObj )
2191 {
2192   LPPERSISTSTREAM ps;
2193   IPicture      *newpic;
2194   HRESULT hr;
2195
2196   TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
2197         lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2198
2199   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2200   if (hr != S_OK)
2201     return hr;
2202   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2203   if (hr != S_OK) {
2204       ERR("Could not get IPersistStream iface from Ole Picture?\n");
2205       IPicture_Release(newpic);
2206       *ppvObj = NULL;
2207       return hr;
2208   }
2209   hr = IPersistStream_Load(ps,lpstream);
2210   IPersistStream_Release(ps);
2211   if (FAILED(hr))
2212   {
2213       ERR("IPersistStream_Load failed\n");
2214       IPicture_Release(newpic);
2215       *ppvObj = NULL;
2216       return hr;
2217   }
2218   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2219   if (hr != S_OK)
2220       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2221   IPicture_Release(newpic);
2222   return hr;
2223 }
2224
2225 /***********************************************************************
2226  * OleLoadPictureEx (OLEAUT32.401)
2227  */
2228 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2229                             REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2230 {
2231   LPPERSISTSTREAM ps;
2232   IPicture      *newpic;
2233   HRESULT hr;
2234
2235   FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
2236         lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2237
2238   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2239   if (hr != S_OK)
2240     return hr;
2241   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2242   if (hr != S_OK) {
2243       ERR("Could not get IPersistStream iface from Ole Picture?\n");
2244       IPicture_Release(newpic);
2245       *ppvObj = NULL;
2246       return hr;
2247   }
2248   hr = IPersistStream_Load(ps,lpstream);
2249   IPersistStream_Release(ps);
2250   if (FAILED(hr))
2251   {
2252       ERR("IPersistStream_Load failed\n");
2253       IPicture_Release(newpic);
2254       *ppvObj = NULL;
2255       return hr;
2256   }
2257   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2258   if (hr != S_OK)
2259       ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2260   IPicture_Release(newpic);
2261   return hr;
2262 }
2263
2264 /***********************************************************************
2265  * OleLoadPicturePath (OLEAUT32.424)
2266  */
2267 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2268                 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2269                 LPVOID *ppvRet )
2270 {
2271   static const WCHAR file[] = { 'f','i','l','e',':',0 };
2272   IPicture *ipicture;
2273   HANDLE hFile;
2274   DWORD dwFileSize;
2275   HGLOBAL hGlobal = NULL;
2276   DWORD dwBytesRead = 0;
2277   IStream *stream;
2278   BOOL bRead;
2279   IPersistStream *pStream;
2280   HRESULT hRes;
2281   HRESULT init_res;
2282   WCHAR *file_candidate;
2283   WCHAR path_buf[MAX_PATH];
2284
2285   TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
2286         debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2287         debugstr_guid(riid), ppvRet);
2288
2289   if (!szURLorPath || !ppvRet)
2290       return E_INVALIDARG;
2291
2292   *ppvRet = NULL;
2293
2294   /* Convert file URLs to DOS paths. */
2295   if (strncmpW(szURLorPath, file, 5) == 0) {
2296       DWORD size;
2297       hRes = CoInternetParseUrl(szURLorPath, PARSE_PATH_FROM_URL, 0, path_buf,
2298                                 sizeof(path_buf)/sizeof(WCHAR), &size, 0);
2299       if (FAILED(hRes))
2300           return hRes;
2301
2302       file_candidate = path_buf;
2303   }
2304   else
2305       file_candidate = szURLorPath;
2306
2307   /* Handle candidate DOS paths separately. */
2308   if (file_candidate[1] == ':') {
2309       hFile = CreateFileW(file_candidate, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2310                           0, NULL);
2311       if (hFile == INVALID_HANDLE_VALUE)
2312           return INET_E_RESOURCE_NOT_FOUND;
2313
2314       dwFileSize = GetFileSize(hFile, NULL);
2315       if (dwFileSize != INVALID_FILE_SIZE )
2316       {
2317           hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2318           if ( hGlobal)
2319           {
2320               bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2321               if (!bRead)
2322               {
2323                   GlobalFree(hGlobal);
2324                   hGlobal = 0;
2325               }
2326           }
2327       }
2328       CloseHandle(hFile);
2329       
2330       if (!hGlobal)
2331           return INET_E_RESOURCE_NOT_FOUND;
2332
2333       hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2334       if (FAILED(hRes)) 
2335       {
2336           GlobalFree(hGlobal);
2337           return hRes;
2338       }
2339   } else {
2340       IMoniker *pmnk;
2341       IBindCtx *pbc;
2342
2343       hRes = CreateBindCtx(0, &pbc);
2344       if (SUCCEEDED(hRes)) 
2345       {
2346           hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2347           if (SUCCEEDED(hRes))
2348           {              
2349               hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2350               IMoniker_Release(pmnk);
2351           }
2352           IBindCtx_Release(pbc);
2353       }
2354       if (FAILED(hRes))
2355           return hRes;
2356   }
2357
2358   init_res = CoInitialize(NULL);
2359
2360   hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER,
2361                           &IID_IPicture, (LPVOID*)&ipicture);
2362   if (SUCCEEDED(hRes)) {
2363       hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2364
2365       if (SUCCEEDED(hRes)) {
2366           hRes = IPersistStream_Load(pStream, stream);
2367
2368           if (SUCCEEDED(hRes)) {
2369               hRes = IPicture_QueryInterface(ipicture, riid, ppvRet);
2370
2371               if (FAILED(hRes))
2372                   ERR("Failed to get interface %s from IPicture.\n", debugstr_guid(riid));
2373           }
2374           IPersistStream_Release(pStream);
2375       }
2376       IPicture_Release(ipicture);
2377   }
2378
2379   IStream_Release(stream);
2380
2381   if (SUCCEEDED(init_res))
2382       CoUninitialize();
2383
2384   return hRes;
2385 }
2386
2387 /*******************************************************************************
2388  * StdPic ClassFactory
2389  */
2390 typedef struct
2391 {
2392     /* IUnknown fields */
2393     IClassFactory IClassFactory_iface;
2394     LONG          ref;
2395 } IClassFactoryImpl;
2396
2397 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
2398 {
2399        return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
2400 }
2401
2402 static HRESULT WINAPI
2403 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2404         IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2405
2406         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2407         return E_NOINTERFACE;
2408 }
2409
2410 static ULONG WINAPI
2411 SPCF_AddRef(LPCLASSFACTORY iface) {
2412         IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2413         return InterlockedIncrement(&This->ref);
2414 }
2415
2416 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2417         IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2418         /* static class, won't be  freed */
2419         return InterlockedDecrement(&This->ref);
2420 }
2421
2422 static HRESULT WINAPI SPCF_CreateInstance(
2423         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2424 ) {
2425     /* Creates an uninitialized picture */
2426     return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2427
2428 }
2429
2430 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2431         IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2432         FIXME("(%p)->(%d),stub!\n",This,dolock);
2433         return S_OK;
2434 }
2435
2436 static const IClassFactoryVtbl SPCF_Vtbl = {
2437         SPCF_QueryInterface,
2438         SPCF_AddRef,
2439         SPCF_Release,
2440         SPCF_CreateInstance,
2441         SPCF_LockServer
2442 };
2443 static IClassFactoryImpl STDPIC_CF = {{&SPCF_Vtbl}, 1 };
2444
2445 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = &STDPIC_CF; }