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