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