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