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