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