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