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