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