dinput8: DirectInput8Create rewrite.
[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_LIB_H
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_LIB_H */
1044
1045
1046 static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
1047 {
1048 #ifdef HAVE_GIF_LIB_H
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   FIXME("():Stub\n");
1996
1997   return E_NOTIMPL;
1998 }
1999
2000 /************************************************************************
2001  * OLEPictureImpl_GetTypeInfo (IDispatch)
2002  *
2003  * See Windows documentation for more details on IDispatch methods.
2004  */
2005 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
2006   IDispatch*  iface,
2007   UINT      iTInfo,
2008   LCID        lcid,
2009   ITypeInfo** ppTInfo)
2010 {
2011   FIXME("():Stub\n");
2012
2013   return E_NOTIMPL;
2014 }
2015
2016 /************************************************************************
2017  * OLEPictureImpl_GetIDsOfNames (IDispatch)
2018  *
2019  * See Windows documentation for more details on IDispatch methods.
2020  */
2021 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
2022   IDispatch*  iface,
2023   REFIID      riid,
2024   LPOLESTR* rgszNames,
2025   UINT      cNames,
2026   LCID        lcid,
2027   DISPID*     rgDispId)
2028 {
2029   FIXME("():Stub\n");
2030
2031   return E_NOTIMPL;
2032 }
2033
2034 /************************************************************************
2035  * OLEPictureImpl_Invoke (IDispatch)
2036  *
2037  * See Windows documentation for more details on IDispatch methods.
2038  */
2039 static HRESULT WINAPI OLEPictureImpl_Invoke(
2040   IDispatch*  iface,
2041   DISPID      dispIdMember,
2042   REFIID      riid,
2043   LCID        lcid,
2044   WORD        wFlags,
2045   DISPPARAMS* pDispParams,
2046   VARIANT*    pVarResult,
2047   EXCEPINFO*  pExepInfo,
2048   UINT*     puArgErr)
2049 {
2050   OLEPictureImpl *This = impl_from_IDispatch(iface);
2051   if (dispIdMember == DISPID_PICT_TYPE)
2052   {
2053     TRACE("DISPID_PICT_TYPE\n");
2054     if (!(wFlags & INVOKE_PROPERTYGET))
2055         return DISP_E_PARAMNOTFOUND;
2056     if (pDispParams->cArgs != 0)
2057         return DISP_E_BADPARAMCOUNT;
2058     if (pVarResult)
2059     {
2060         VariantInit(pVarResult);
2061         V_VT(pVarResult) = VT_I2;
2062         return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
2063     }
2064     return S_OK;
2065   }
2066   else
2067   {
2068     FIXME("(dispid: %ld):Stub\n",dispIdMember);
2069
2070     VariantInit(pVarResult);
2071     V_VT(pVarResult) = VT_BOOL;
2072     V_BOOL(pVarResult) = FALSE;
2073     return S_OK;
2074   }
2075 }
2076
2077
2078 static const IPictureVtbl OLEPictureImpl_VTable =
2079 {
2080   OLEPictureImpl_QueryInterface,
2081   OLEPictureImpl_AddRef,
2082   OLEPictureImpl_Release,
2083   OLEPictureImpl_get_Handle,
2084   OLEPictureImpl_get_hPal,
2085   OLEPictureImpl_get_Type,
2086   OLEPictureImpl_get_Width,
2087   OLEPictureImpl_get_Height,
2088   OLEPictureImpl_Render,
2089   OLEPictureImpl_set_hPal,
2090   OLEPictureImpl_get_CurDC,
2091   OLEPictureImpl_SelectPicture,
2092   OLEPictureImpl_get_KeepOriginalFormat,
2093   OLEPictureImpl_put_KeepOriginalFormat,
2094   OLEPictureImpl_PictureChanged,
2095   OLEPictureImpl_SaveAsFile,
2096   OLEPictureImpl_get_Attributes
2097 };
2098
2099 static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
2100 {
2101   OLEPictureImpl_IDispatch_QueryInterface,
2102   OLEPictureImpl_IDispatch_AddRef,
2103   OLEPictureImpl_IDispatch_Release,
2104   OLEPictureImpl_GetTypeInfoCount,
2105   OLEPictureImpl_GetTypeInfo,
2106   OLEPictureImpl_GetIDsOfNames,
2107   OLEPictureImpl_Invoke
2108 };
2109
2110 static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
2111 {
2112   OLEPictureImpl_IPersistStream_QueryInterface,
2113   OLEPictureImpl_IPersistStream_AddRef,
2114   OLEPictureImpl_IPersistStream_Release,
2115   OLEPictureImpl_GetClassID,
2116   OLEPictureImpl_IsDirty,
2117   OLEPictureImpl_Load,
2118   OLEPictureImpl_Save,
2119   OLEPictureImpl_GetSizeMax
2120 };
2121
2122 static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
2123 {
2124   OLEPictureImpl_IConnectionPointContainer_QueryInterface,
2125   OLEPictureImpl_IConnectionPointContainer_AddRef,
2126   OLEPictureImpl_IConnectionPointContainer_Release,
2127   OLEPictureImpl_EnumConnectionPoints,
2128   OLEPictureImpl_FindConnectionPoint
2129 };
2130
2131 /***********************************************************************
2132  * OleCreatePictureIndirect (OLEAUT32.419)
2133  */
2134 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
2135                             BOOL fOwn, LPVOID *ppvObj )
2136 {
2137   OLEPictureImpl* newPict = NULL;
2138   HRESULT      hr         = S_OK;
2139
2140   TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
2141
2142   /*
2143    * Sanity check
2144    */
2145   if (ppvObj==0)
2146     return E_POINTER;
2147
2148   *ppvObj = NULL;
2149
2150   /*
2151    * Try to construct a new instance of the class.
2152    */
2153   newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
2154
2155   if (newPict == NULL)
2156     return E_OUTOFMEMORY;
2157
2158   /*
2159    * Make sure it supports the interface required by the caller.
2160    */
2161   hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
2162
2163   /*
2164    * Release the reference obtained in the constructor. If
2165    * the QueryInterface was unsuccessful, it will free the class.
2166    */
2167   IPicture_Release((IPicture*)newPict);
2168
2169   return hr;
2170 }
2171
2172
2173 /***********************************************************************
2174  * OleLoadPicture (OLEAUT32.418)
2175  */
2176 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2177                             REFIID riid, LPVOID *ppvObj )
2178 {
2179   LPPERSISTSTREAM ps;
2180   IPicture      *newpic;
2181   HRESULT hr;
2182
2183   TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
2184         lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
2185
2186   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2187   if (hr)
2188     return hr;
2189   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2190   if (hr) {
2191       FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2192       IPicture_Release(newpic);
2193       *ppvObj = NULL;
2194       return hr;
2195   }
2196   IPersistStream_Load(ps,lpstream);
2197   IPersistStream_Release(ps);
2198   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2199   if (hr)
2200       FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2201   IPicture_Release(newpic);
2202   return hr;
2203 }
2204
2205 /***********************************************************************
2206  * OleLoadPictureEx (OLEAUT32.401)
2207  */
2208 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
2209                             REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
2210 {
2211   LPPERSISTSTREAM ps;
2212   IPicture      *newpic;
2213   HRESULT hr;
2214
2215   FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
2216         lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
2217
2218   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
2219   if (hr)
2220     return hr;
2221   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
2222   if (hr) {
2223       FIXME("Could not get IPersistStream iface from Ole Picture?\n");
2224       IPicture_Release(newpic);
2225       *ppvObj = NULL;
2226       return hr;
2227   }
2228   IPersistStream_Load(ps,lpstream);
2229   IPersistStream_Release(ps);
2230   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
2231   if (hr)
2232       FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2233   IPicture_Release(newpic);
2234   return hr;
2235 }
2236
2237 /***********************************************************************
2238  * OleLoadPicturePath (OLEAUT32.424)
2239  */
2240 HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
2241                 DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
2242                 LPVOID *ppvRet )
2243 {
2244   static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
2245   IPicture *ipicture;
2246   HANDLE hFile;
2247   DWORD dwFileSize;
2248   HGLOBAL hGlobal = NULL;
2249   DWORD dwBytesRead = 0;
2250   IStream *stream;
2251   BOOL bRead;
2252   IPersistStream *pStream;
2253   HRESULT hRes;
2254
2255   TRACE("(%s,%p,%ld,%08lx,%s,%p): stub\n",
2256         debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
2257         debugstr_guid(riid), ppvRet);
2258
2259   if (!ppvRet) return E_POINTER;
2260
2261   if (strncmpW(szURLorPath, file, 7) == 0) {        
2262       szURLorPath += 7;
2263   
2264       hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
2265                                    0, NULL);
2266       if (hFile == INVALID_HANDLE_VALUE)
2267           return E_UNEXPECTED;
2268
2269       dwFileSize = GetFileSize(hFile, NULL);
2270       if (dwFileSize != INVALID_FILE_SIZE )
2271       {
2272           hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
2273           if ( hGlobal)
2274           {
2275               bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
2276               if (!bRead)
2277               {
2278                   GlobalFree(hGlobal);
2279                   hGlobal = 0;
2280               }
2281           }
2282       }
2283       CloseHandle(hFile);
2284       
2285       if (!hGlobal)
2286           return E_UNEXPECTED;
2287
2288       hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
2289       if (FAILED(hRes)) 
2290       {
2291           GlobalFree(hGlobal);
2292           return hRes;
2293       }
2294   } else {
2295       IMoniker *pmnk;
2296       IBindCtx *pbc;
2297
2298       hRes = CreateBindCtx(0, &pbc);
2299       if (SUCCEEDED(hRes)) 
2300       {
2301           hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
2302           if (SUCCEEDED(hRes))
2303           {              
2304               hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
2305               IMoniker_Release(pmnk);
2306           }
2307           IBindCtx_Release(pbc);
2308       }
2309       if (FAILED(hRes))
2310           return hRes;
2311   }
2312
2313   hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER, 
2314                    &IID_IPicture, (LPVOID*)&ipicture);
2315   if (hRes != S_OK) {
2316       IStream_Release(stream);
2317       return hRes;
2318   }
2319   
2320   hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
2321   if (hRes) {
2322       IStream_Release(stream);
2323       IPicture_Release(ipicture);
2324       return hRes;
2325   }
2326
2327   hRes = IPersistStream_Load(pStream, stream); 
2328   IPersistStream_Release(pStream);
2329   IStream_Release(stream);
2330
2331   if (hRes) {
2332       IPicture_Release(ipicture);
2333       return hRes;
2334   }
2335
2336   hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
2337   if (hRes)
2338       FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
2339   
2340   IPicture_Release(ipicture);
2341   return hRes;
2342 }
2343
2344 /*******************************************************************************
2345  * StdPic ClassFactory
2346  */
2347 typedef struct
2348 {
2349     /* IUnknown fields */
2350     const IClassFactoryVtbl    *lpVtbl;
2351     LONG                        ref;
2352 } IClassFactoryImpl;
2353
2354 static HRESULT WINAPI
2355 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2356         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2357
2358         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2359         return E_NOINTERFACE;
2360 }
2361
2362 static ULONG WINAPI
2363 SPCF_AddRef(LPCLASSFACTORY iface) {
2364         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2365         return InterlockedIncrement(&This->ref);
2366 }
2367
2368 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
2369         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2370         /* static class, won't be  freed */
2371         return InterlockedDecrement(&This->ref);
2372 }
2373
2374 static HRESULT WINAPI SPCF_CreateInstance(
2375         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2376 ) {
2377     /* Creates an uninitialized picture */
2378     return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
2379
2380 }
2381
2382 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2383         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2384         FIXME("(%p)->(%d),stub!\n",This,dolock);
2385         return S_OK;
2386 }
2387
2388 static const IClassFactoryVtbl SPCF_Vtbl = {
2389         SPCF_QueryInterface,
2390         SPCF_AddRef,
2391         SPCF_Release,
2392         SPCF_CreateInstance,
2393         SPCF_LockServer
2394 };
2395 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
2396
2397 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }