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