- Fix palette creation.
[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
40 #ifdef HAVE_UNISTD_H
41 # include <unistd.h>
42 #endif
43 #include <stdarg.h>
44 #include <stdio.h>
45 #include <string.h>
46
47 /* Must be before wine includes, the header has things conflicting with
48  * WINE headers.
49  */
50 #ifdef HAVE_GIF_LIB_H
51 # include <gif_lib.h>
52 #endif
53
54 #define NONAMELESSUNION
55 #define NONAMELESSSTRUCT
56 #include "winerror.h"
57 #include "windef.h"
58 #include "winbase.h"
59 #include "wingdi.h"
60 #include "winuser.h"
61 #include "ole2.h"
62 #include "olectl.h"
63 #include "oleauto.h"
64 #include "connpt.h"
65 #include "wine/debug.h"
66
67 #include "wine/wingdi16.h"
68 #include "cursoricon.h"
69
70 #ifdef HAVE_LIBJPEG
71 /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
72 #define XMD_H
73 #define UINT8 JPEG_UINT8
74 #define UINT16 JPEG_UINT16
75 #undef FAR
76 #ifdef HAVE_JPEGLIB_H
77 # include <jpeglib.h>
78 #endif
79 #undef UINT16
80 #endif
81
82 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83
84 /*************************************************************************
85  *  Declaration of implementation class
86  */
87
88 typedef struct OLEPictureImpl {
89
90   /*
91    * IPicture handles IUnknown
92    */
93
94     ICOM_VTABLE(IPicture)       *lpvtbl1;
95     ICOM_VTABLE(IDispatch)      *lpvtbl2;
96     ICOM_VTABLE(IPersistStream) *lpvtbl3;
97     ICOM_VTABLE(IConnectionPointContainer) *lpvtbl4;
98
99   /* Object referenece count */
100     DWORD ref;
101
102   /* We own the object and must destroy it ourselves */
103     BOOL fOwn;
104
105   /* Picture description */
106     PICTDESC desc;
107
108   /* These are the pixel size of a bitmap */
109     DWORD origWidth;
110     DWORD origHeight;
111
112   /* And these are the size of the picture converted into HIMETRIC units */
113     OLE_XSIZE_HIMETRIC himetricWidth;
114     OLE_YSIZE_HIMETRIC himetricHeight;
115
116     IConnectionPoint *pCP;
117
118     BOOL keepOrigFormat;
119     HDC hDCCur;
120
121   /* Bitmap transparency mask */
122     HBITMAP hbmMask;
123     COLORREF rgbTrans;
124
125   /* data */
126     void* data;
127     int datalen;
128 } OLEPictureImpl;
129
130 /*
131  * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
132  */
133 #define ICOM_THIS_From_IDispatch(impl, name) \
134     impl *This = (impl*)(((char*)name)-sizeof(void*));
135 #define ICOM_THIS_From_IPersistStream(impl, name) \
136     impl *This = (impl*)(((char*)name)-2*sizeof(void*));
137 #define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
138     impl *This = (impl*)(((char*)name)-3*sizeof(void*));
139
140 /*
141  * Predeclare VTables.  They get initialized at the end.
142  */
143 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable;
144 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable;
145 static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable;
146 static ICOM_VTABLE(IConnectionPointContainer) OLEPictureImpl_IConnectionPointContainer_VTable;
147
148 /***********************************************************************
149  * Implementation of the OLEPictureImpl class.
150  */
151
152 static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
153   BITMAP bm;
154   HDC hdcRef;
155
156   TRACE("bitmap handle %p\n", This->desc.u.bmp.hbitmap);
157   if(GetObjectA(This->desc.u.bmp.hbitmap, sizeof(bm), &bm) != sizeof(bm)) {
158     ERR("GetObject fails\n");
159     return;
160   }
161   This->origWidth = bm.bmWidth;
162   This->origHeight = bm.bmHeight;
163   /* The width and height are stored in HIMETRIC units (0.01 mm),
164      so we take our pixel width divide by pixels per inch and
165      multiply by 25.4 * 100 */
166   /* Should we use GetBitmapDimension if available? */
167   hdcRef = CreateCompatibleDC(0);
168   This->himetricWidth =(bm.bmWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
169   This->himetricHeight=(bm.bmHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
170   DeleteDC(hdcRef);
171 }
172
173 /************************************************************************
174  * OLEPictureImpl_Construct
175  *
176  * This method will construct a new instance of the OLEPictureImpl
177  * class.
178  *
179  * The caller of this method must release the object when it's
180  * done with it.
181  */
182 static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
183 {
184   OLEPictureImpl* newObject = 0;
185
186   if (pictDesc)
187       TRACE("(%p) type = %d\n", pictDesc, pictDesc->picType);
188
189   /*
190    * Allocate space for the object.
191    */
192   newObject = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OLEPictureImpl));
193
194   if (newObject==0)
195     return newObject;
196
197   /*
198    * Initialize the virtual function table.
199    */
200   newObject->lpvtbl1 = &OLEPictureImpl_VTable;
201   newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
202   newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
203   newObject->lpvtbl4 = &OLEPictureImpl_IConnectionPointContainer_VTable;
204
205   CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
206
207   /*
208    * Start with one reference count. The caller of this function
209    * must release the interface pointer when it is done.
210    */
211   newObject->ref        = 1;
212   newObject->hDCCur     = 0;
213
214   newObject->fOwn       = fOwn;
215
216   /* dunno about original value */
217   newObject->keepOrigFormat = TRUE;
218
219   newObject->hbmMask = NULL;
220
221   if (pictDesc) {
222       if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
223           FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
224       }
225       memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
226
227
228       switch(pictDesc->picType) {
229       case PICTYPE_BITMAP:
230         OLEPictureImpl_SetBitmap(newObject);
231         break;
232
233       case PICTYPE_METAFILE:
234         TRACE("metafile handle %p\n", pictDesc->u.wmf.hmeta);
235         newObject->himetricWidth = pictDesc->u.wmf.xExt;
236         newObject->himetricHeight = pictDesc->u.wmf.yExt;
237         break;
238
239       case PICTYPE_NONE:
240         /* not sure what to do here */
241         newObject->himetricWidth = newObject->himetricHeight = 0;
242         break;
243
244       case PICTYPE_ICON:
245       case PICTYPE_ENHMETAFILE:
246       default:
247         FIXME("Unsupported type %d\n", pictDesc->picType);
248         newObject->himetricWidth = newObject->himetricHeight = 0;
249         break;
250       }
251   } else {
252       newObject->desc.picType = PICTYPE_UNINITIALIZED;
253   }
254
255   TRACE("returning %p\n", newObject);
256   return newObject;
257 }
258
259 /************************************************************************
260  * OLEPictureImpl_Destroy
261  *
262  * This method is called by the Release method when the reference
263  * count goes down to 0. It will free all resources used by
264  * this object.  */
265 static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
266 {
267   TRACE("(%p)\n", Obj);
268
269   if(Obj->fOwn) { /* We need to destroy the picture */
270     switch(Obj->desc.picType) {
271     case PICTYPE_BITMAP:
272       DeleteObject(Obj->desc.u.bmp.hbitmap);
273       break;
274     case PICTYPE_METAFILE:
275       DeleteMetaFile(Obj->desc.u.wmf.hmeta);
276       break;
277     case PICTYPE_ICON:
278       DestroyIcon(Obj->desc.u.icon.hicon);
279       break;
280     case PICTYPE_ENHMETAFILE:
281       DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
282       break;
283     default:
284       FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
285       break;
286     }
287   }
288   if (Obj->data) HeapFree(GetProcessHeap(), 0, Obj->data);
289   HeapFree(GetProcessHeap(), 0, Obj);
290 }
291
292 static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
293
294 /************************************************************************
295  * OLEPictureImpl_QueryInterface (IUnknown)
296  *
297  * See Windows documentation for more details on IUnknown methods.
298  */
299 static HRESULT WINAPI OLEPictureImpl_QueryInterface(
300   IPicture*  iface,
301   REFIID  riid,
302   void**  ppvObject)
303 {
304   ICOM_THIS(OLEPictureImpl, iface);
305   TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
306
307   /*
308    * Perform a sanity check on the parameters.
309    */
310   if ( (This==0) || (ppvObject==0) )
311     return E_INVALIDARG;
312
313   /*
314    * Initialize the return parameter.
315    */
316   *ppvObject = 0;
317
318   /*
319    * Compare the riid with the interface IDs implemented by this object.
320    */
321   if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
322   {
323     *ppvObject = (IPicture*)This;
324   }
325   else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
326   {
327     *ppvObject = (IPicture*)This;
328   }
329   else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
330   {
331     *ppvObject = (IDispatch*)&(This->lpvtbl2);
332   }
333   else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
334   {
335     *ppvObject = (IDispatch*)&(This->lpvtbl2);
336   }
337   else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
338   {
339   *ppvObject = (IPersistStream*)&(This->lpvtbl3);
340   }
341   else if (memcmp(&IID_IConnectionPointContainer, riid, sizeof(IID_IConnectionPointContainer)) == 0)
342   {
343   *ppvObject = (IConnectionPointContainer*)&(This->lpvtbl4);
344   }
345   /*
346    * Check that we obtained an interface.
347    */
348   if ((*ppvObject)==0)
349   {
350     FIXME("() : asking for un supported interface %s\n",debugstr_guid(riid));
351     return E_NOINTERFACE;
352   }
353
354   /*
355    * Query Interface always increases the reference count by one when it is
356    * successful
357    */
358   OLEPictureImpl_AddRef((IPicture*)This);
359
360   return S_OK;
361 }
362 /***********************************************************************
363  *    OLEPicture_SendNotify (internal)
364  *
365  * Sends notification messages of changed properties to any interested
366  * connections.
367  */
368 static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
369 {
370   IEnumConnections *pEnum;
371   CONNECTDATA CD;
372
373   if (IConnectionPoint_EnumConnections(this->pCP, &pEnum))
374       return;
375   while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
376     IPropertyNotifySink *sink;
377
378     IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
379     IPropertyNotifySink_OnChanged(sink, dispID);
380     IPropertyNotifySink_Release(sink);
381     IUnknown_Release(CD.pUnk);
382   }
383   IEnumConnections_Release(pEnum);
384   return;
385 }
386
387 /************************************************************************
388  * OLEPictureImpl_AddRef (IUnknown)
389  *
390  * See Windows documentation for more details on IUnknown methods.
391  */
392 static ULONG WINAPI OLEPictureImpl_AddRef(
393   IPicture* iface)
394 {
395   ICOM_THIS(OLEPictureImpl, iface);
396   TRACE("(%p)->(ref=%ld)\n", This, This->ref);
397   This->ref++;
398
399   return This->ref;
400 }
401
402 /************************************************************************
403  * OLEPictureImpl_Release (IUnknown)
404  *
405  * See Windows documentation for more details on IUnknown methods.
406  */
407 static ULONG WINAPI OLEPictureImpl_Release(
408       IPicture* iface)
409 {
410   ICOM_THIS(OLEPictureImpl, iface);
411   TRACE("(%p)->(ref=%ld)\n", This, This->ref);
412
413   /*
414    * Decrease the reference count on this object.
415    */
416   This->ref--;
417
418   /*
419    * If the reference count goes down to 0, perform suicide.
420    */
421   if (This->ref==0)
422   {
423     OLEPictureImpl_Destroy(This);
424
425     return 0;
426   }
427
428   return This->ref;
429 }
430
431
432 /************************************************************************
433  * OLEPictureImpl_get_Handle
434  */
435 static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
436                                                 OLE_HANDLE *phandle)
437 {
438   ICOM_THIS(OLEPictureImpl, iface);
439   TRACE("(%p)->(%p)\n", This, phandle);
440   switch(This->desc.picType) {
441   case PICTYPE_BITMAP:
442     *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
443     break;
444   case PICTYPE_METAFILE:
445     *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
446     break;
447   case PICTYPE_ICON:
448     *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
449     break;
450   case PICTYPE_ENHMETAFILE:
451     *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
452     break;
453   default:
454     FIXME("Unimplemented type %d\n", This->desc.picType);
455     return E_NOTIMPL;
456   }
457   TRACE("returning handle %08x\n", *phandle);
458   return S_OK;
459 }
460
461 /************************************************************************
462  * OLEPictureImpl_get_hPal
463  */
464 static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
465                                               OLE_HANDLE *phandle)
466 {
467   ICOM_THIS(OLEPictureImpl, iface);
468   FIXME("(%p)->(%p): stub\n", This, phandle);
469   return E_NOTIMPL;
470 }
471
472 /************************************************************************
473  * OLEPictureImpl_get_Type
474  */
475 static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
476                                               short *ptype)
477 {
478   ICOM_THIS(OLEPictureImpl, iface);
479   TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
480   *ptype = This->desc.picType;
481   return S_OK;
482 }
483
484 /************************************************************************
485  * OLEPictureImpl_get_Width
486  */
487 static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
488                                                OLE_XSIZE_HIMETRIC *pwidth)
489 {
490   ICOM_THIS(OLEPictureImpl, iface);
491   TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
492   *pwidth = This->himetricWidth;
493   return S_OK;
494 }
495
496 /************************************************************************
497  * OLEPictureImpl_get_Height
498  */
499 static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
500                                                 OLE_YSIZE_HIMETRIC *pheight)
501 {
502   ICOM_THIS(OLEPictureImpl, iface);
503   TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
504   *pheight = This->himetricHeight;
505   return S_OK;
506 }
507
508 /************************************************************************
509  * OLEPictureImpl_Render
510  */
511 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
512                                             long x, long y, long cx, long cy,
513                                             OLE_XPOS_HIMETRIC xSrc,
514                                             OLE_YPOS_HIMETRIC ySrc,
515                                             OLE_XSIZE_HIMETRIC cxSrc,
516                                             OLE_YSIZE_HIMETRIC cySrc,
517                                             LPCRECT prcWBounds)
518 {
519   ICOM_THIS(OLEPictureImpl, iface);
520   TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
521         This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
522   if(prcWBounds)
523     TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
524           prcWBounds->right, prcWBounds->bottom);
525
526   /*
527    * While the documentation suggests this to be here (or after rendering?)
528    * it does cause an endless recursion in my sample app. -MM 20010804
529   OLEPicture_SendNotify(This,DISPID_PICT_RENDER);
530    */
531
532   switch(This->desc.picType) {
533   case PICTYPE_BITMAP:
534     {
535       HBITMAP hbmpOld;
536       HDC hdcBmp;
537
538       /* Set a mapping mode that maps bitmap pixels into HIMETRIC units.
539          NB y-axis gets flipped */
540
541       hdcBmp = CreateCompatibleDC(0);
542       SetMapMode(hdcBmp, MM_ANISOTROPIC);
543       SetWindowOrgEx(hdcBmp, 0, 0, NULL);
544       SetWindowExtEx(hdcBmp, This->himetricWidth, This->himetricHeight, NULL);
545       SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
546       SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
547
548       hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
549
550       if (This->hbmMask) {
551           HDC hdcMask = CreateCompatibleDC(0);
552           HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
553
554           SetMapMode(hdcMask, MM_ANISOTROPIC);
555           SetWindowOrgEx(hdcMask, 0, 0, NULL);
556           SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
557           SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL);
558           SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL);
559           
560           SetBkColor(hdc, RGB(255, 255, 255));    
561           SetTextColor(hdc, RGB(0, 0, 0));        
562           StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND); 
563           StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT);
564
565           SelectObject(hdcMask, hOldbm);
566           DeleteDC(hdcMask);
567       } else
568           StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
569
570       SelectObject(hdcBmp, hbmpOld);
571       DeleteDC(hdcBmp);
572     }
573     break;
574   case PICTYPE_ICON:
575     FIXME("Not quite correct implementation of rendering icons...\n");
576     DrawIcon(hdc,x,y,This->desc.u.icon.hicon);
577     break;
578
579   case PICTYPE_METAFILE:
580   case PICTYPE_ENHMETAFILE:
581   default:
582     FIXME("type %d not implemented\n", This->desc.picType);
583     return E_NOTIMPL;
584   }
585   return S_OK;
586 }
587
588 /************************************************************************
589  * OLEPictureImpl_set_hPal
590  */
591 static HRESULT WINAPI OLEPictureImpl_set_hPal(IPicture *iface,
592                                               OLE_HANDLE hpal)
593 {
594   ICOM_THIS(OLEPictureImpl, iface);
595   FIXME("(%p)->(%08x): stub\n", This, hpal);
596   OLEPicture_SendNotify(This,DISPID_PICT_HPAL);
597   return E_NOTIMPL;
598 }
599
600 /************************************************************************
601  * OLEPictureImpl_get_CurDC
602  */
603 static HRESULT WINAPI OLEPictureImpl_get_CurDC(IPicture *iface,
604                                                HDC *phdc)
605 {
606   ICOM_THIS(OLEPictureImpl, iface);
607   TRACE("(%p), returning %p\n", This, This->hDCCur);
608   if (phdc) *phdc = This->hDCCur;
609   return S_OK;
610 }
611
612 /************************************************************************
613  * OLEPictureImpl_SelectPicture
614  */
615 static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
616                                                    HDC hdcIn,
617                                                    HDC *phdcOut,
618                                                    OLE_HANDLE *phbmpOut)
619 {
620   ICOM_THIS(OLEPictureImpl, iface);
621   TRACE("(%p)->(%p, %p, %p)\n", This, hdcIn, phdcOut, phbmpOut);
622   if (This->desc.picType == PICTYPE_BITMAP) {
623       SelectObject(hdcIn,This->desc.u.bmp.hbitmap);
624
625       if (phdcOut)
626           *phdcOut = This->hDCCur;
627       This->hDCCur = hdcIn;
628       if (phbmpOut)
629           *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
630       return S_OK;
631   } else {
632       FIXME("Don't know how to select picture type %d\n",This->desc.picType);
633       return E_FAIL;
634   }
635 }
636
637 /************************************************************************
638  * OLEPictureImpl_get_KeepOriginalFormat
639  */
640 static HRESULT WINAPI OLEPictureImpl_get_KeepOriginalFormat(IPicture *iface,
641                                                             BOOL *pfKeep)
642 {
643   ICOM_THIS(OLEPictureImpl, iface);
644   TRACE("(%p)->(%p)\n", This, pfKeep);
645   if (!pfKeep)
646       return E_POINTER;
647   *pfKeep = This->keepOrigFormat;
648   return S_OK;
649 }
650
651 /************************************************************************
652  * OLEPictureImpl_put_KeepOriginalFormat
653  */
654 static HRESULT WINAPI OLEPictureImpl_put_KeepOriginalFormat(IPicture *iface,
655                                                             BOOL keep)
656 {
657   ICOM_THIS(OLEPictureImpl, iface);
658   TRACE("(%p)->(%d)\n", This, keep);
659   This->keepOrigFormat = keep;
660   /* FIXME: what DISPID notification here? */
661   return S_OK;
662 }
663
664 /************************************************************************
665  * OLEPictureImpl_PictureChanged
666  */
667 static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
668 {
669   ICOM_THIS(OLEPictureImpl, iface);
670   TRACE("(%p)->()\n", This);
671   OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
672   return S_OK;
673 }
674
675 /************************************************************************
676  * OLEPictureImpl_SaveAsFile
677  */
678 static HRESULT WINAPI OLEPictureImpl_SaveAsFile(IPicture *iface,
679                                                 IStream *pstream,
680                                                 BOOL SaveMemCopy,
681                                                 LONG *pcbSize)
682 {
683   ICOM_THIS(OLEPictureImpl, iface);
684   FIXME("(%p)->(%p, %d, %p), hacked stub.\n", This, pstream, SaveMemCopy, pcbSize);
685   return IStream_Write(pstream,This->data,This->datalen,(ULONG*)pcbSize);
686 }
687
688 /************************************************************************
689  * OLEPictureImpl_get_Attributes
690  */
691 static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
692                                                     DWORD *pdwAttr)
693 {
694   ICOM_THIS(OLEPictureImpl, iface);
695   TRACE("(%p)->(%p).\n", This, pdwAttr);
696   *pdwAttr = 0;
697   switch (This->desc.picType) {
698   case PICTYPE_BITMAP:  break;  /* not 'truely' scalable, see MSDN. */
699   case PICTYPE_ICON: *pdwAttr     = PICTURE_TRANSPARENT;break;
700   case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
701   default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
702   }
703   return S_OK;
704 }
705
706
707 /************************************************************************
708  *    IConnectionPointContainer
709  */
710
711 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
712   IConnectionPointContainer* iface,
713   REFIID riid,
714   VOID** ppvoid
715 ) {
716   ICOM_THIS_From_IConnectionPointContainer(IPicture,iface);
717
718   return IPicture_QueryInterface(This,riid,ppvoid);
719 }
720
721 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
722   IConnectionPointContainer* iface)
723 {
724   ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
725
726   return IPicture_AddRef(This);
727 }
728
729 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
730   IConnectionPointContainer* iface)
731 {
732   ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
733
734   return IPicture_Release(This);
735 }
736
737 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
738   IConnectionPointContainer* iface,
739   IEnumConnectionPoints** ppEnum
740 ) {
741   ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
742
743   FIXME("(%p,%p), stub!\n",This,ppEnum);
744   return E_NOTIMPL;
745 }
746
747 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
748   IConnectionPointContainer* iface,
749   REFIID riid,
750   IConnectionPoint **ppCP
751 ) {
752   ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl, iface);
753   TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
754   if (!ppCP)
755       return E_POINTER;
756   *ppCP = NULL;
757   if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
758       return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
759   FIXME("tried to find connection point on %s?\n",debugstr_guid(riid));
760   return 0x80040200;
761 }
762 /************************************************************************
763  *    IPersistStream
764  */
765 /************************************************************************
766  * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
767  *
768  * See Windows documentation for more details on IUnknown methods.
769  */
770 static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
771   IPersistStream* iface,
772   REFIID     riid,
773   VOID**     ppvoid)
774 {
775   ICOM_THIS_From_IPersistStream(IPicture, iface);
776
777   return IPicture_QueryInterface(This, riid, ppvoid);
778 }
779
780 /************************************************************************
781  * OLEPictureImpl_IPersistStream_AddRef (IUnknown)
782  *
783  * See Windows documentation for more details on IUnknown methods.
784  */
785 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
786   IPersistStream* iface)
787 {
788   ICOM_THIS_From_IPersistStream(IPicture, iface);
789
790   return IPicture_AddRef(This);
791 }
792
793 /************************************************************************
794  * OLEPictureImpl_IPersistStream_Release (IUnknown)
795  *
796  * See Windows documentation for more details on IUnknown methods.
797  */
798 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
799   IPersistStream* iface)
800 {
801   ICOM_THIS_From_IPersistStream(IPicture, iface);
802
803   return IPicture_Release(This);
804 }
805
806 /************************************************************************
807  * OLEPictureImpl_IPersistStream_GetClassID
808  */
809 static HRESULT WINAPI OLEPictureImpl_GetClassID(
810   IPersistStream* iface,CLSID* pClassID)
811 {
812   ICOM_THIS_From_IPersistStream(IPicture, iface);
813   FIXME("(%p),stub!\n",This);
814   return E_NOTIMPL;
815 }
816
817 /************************************************************************
818  * OLEPictureImpl_IPersistStream_IsDirty
819  */
820 static HRESULT WINAPI OLEPictureImpl_IsDirty(
821   IPersistStream* iface)
822 {
823   ICOM_THIS_From_IPersistStream(IPicture, iface);
824   FIXME("(%p),stub!\n",This);
825   return E_NOTIMPL;
826 }
827
828 #ifdef HAVE_LIBJPEG
829 /* for the jpeg decompressor source manager. */
830 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
831
832 static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
833     ERR("(), should not get here.\n");
834     return FALSE;
835 }
836
837 static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
838     TRACE("Skipping %ld bytes...\n", num_bytes);
839     cinfo->src->next_input_byte += num_bytes;
840     cinfo->src->bytes_in_buffer -= num_bytes;
841 }
842
843 static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
844     ERR("(desired=%d), should not get here.\n",desired);
845     return FALSE;
846 }
847 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
848 #endif /* HAVE_LIBJPEG */
849
850 #ifdef HAVE_LIBGIF
851 struct gifdata {
852     unsigned char *data;
853     unsigned int curoff;
854     unsigned int len;
855 };
856
857 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
858     struct gifdata *gd = (struct gifdata*)gif->UserData;
859
860     if (len+gd->curoff > gd->len) {
861         FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
862         len = gd->len - gd->curoff;
863     }
864     memcpy(data, gd->data+gd->curoff, len);
865     gd->curoff += len;
866     return len;
867 }
868 #endif
869
870 /************************************************************************
871  * OLEPictureImpl_IPersistStream_Load (IUnknown)
872  *
873  * Loads the binary data from the IStream. Starts at current position.
874  * There appears to be an 2 DWORD header:
875  *      DWORD magic;
876  *      DWORD len;
877  *
878  * Currently implemented: BITMAP, ICON, JPEG.
879  */
880 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
881   HRESULT       hr = E_FAIL;
882   ULONG         xread;
883   BYTE          *xbuf;
884   DWORD         header[2];
885   WORD          magic;
886   STATSTG       statstg;
887   ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
888   
889   TRACE("(%p,%p)\n",This,pStm);
890
891   /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
892    * out whether we do.
893    */
894   hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
895   if (hr)
896     FIXME("Stat failed with hres %lx\n",hr);
897   hr=IStream_Read(pStm,header,8,&xread);
898   if (hr || xread!=8) {
899       FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
900       return hr;
901   }
902   if (header[1] > statstg.cbSize.QuadPart || (header[1]==0)) {/* Incorrect header, assume none. */
903     xread = 8;
904     xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,statstg.cbSize.QuadPart);
905     memcpy(xbuf,&header,8);
906     This->datalen = statstg.cbSize.QuadPart;
907     while (xread < This->datalen) {
908       ULONG nread;
909       hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
910       xread+=nread;
911       if (hr || !nread)
912         break;
913     }
914     if (xread != This->datalen)
915       FIXME("Could only read %ld of %d bytes in no-header case?\n",xread,This->datalen);
916   } else {
917     xread = 0;
918     xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
919     This->datalen = header[1];
920     while (xread < header[1]) {
921       ULONG nread;
922       hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
923       xread+=nread;
924       if (hr || !nread)
925         break;
926     }
927     if (xread != header[1])
928       FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
929   }
930   magic = xbuf[0] + (xbuf[1]<<8);
931   switch (magic) {
932   case 0x4947: { /* GIF */
933 #ifdef HAVE_LIBGIF
934     struct gifdata      gd;
935     GifFileType         *gif;
936     BITMAPINFO          *bmi;
937     HDC                 hdcref;
938     LPBYTE              bytes;
939     int                 i,j,ret;
940     GifImageDesc        *gid;
941     SavedImage          *si;
942     ColorMapObject      *cm;
943     int                 transparent = -1;
944     ExtensionBlock      *eb;
945     
946     gd.data   = xbuf;
947     gd.curoff = 0;
948     gd.len    = xread;
949     gif = DGifOpen((void*)&gd, _gif_inputfunc);
950     ret = DGifSlurp(gif);
951     if (ret == GIF_ERROR) {
952       FIXME("Failed reading GIF using libgif.\n");
953       return E_FAIL;
954     }
955     TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
956     TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
957     TRACE("imgcnt %d\n", gif->ImageCount);
958     if (gif->ImageCount<1) {
959       FIXME("GIF stream does not have images inside?\n");
960       return E_FAIL;
961     }
962     TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
963       gif->Image.Width, gif->Image.Height,
964       gif->Image.Left, gif->Image.Top,
965       gif->Image.Interlace
966     );
967     /* */
968     bmi  = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(1<<gif->SColorResolution)*sizeof(RGBQUAD));
969     bytes= HeapAlloc(GetProcessHeap(),0,gif->SWidth*gif->SHeight);
970     si   = gif->SavedImages+0;
971     gid  = &(si->ImageDesc);
972     cm   = gid->ColorMap;
973     if (!cm) cm = gif->SColorMap;
974     
975     /* look for the transparent color extension */
976     for (i = 0; i < si->ExtensionBlockCount; ++i) {
977         eb = si->ExtensionBlocks + i;
978         if (eb->Function == 0xF9 && eb->ByteCount == 4) {
979             if ((eb->Bytes[0] & 1) == 1) {
980                 transparent = eb->Bytes[3];
981             }
982         }
983     }
984
985     for (i=0;i<(1<<gif->SColorResolution);i++) {
986       bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
987       bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
988       bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
989       if (i == transparent) {
990           This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed,
991                                bmi->bmiColors[i].rgbGreen,
992                                bmi->bmiColors[i].rgbBlue);
993       }
994     }
995
996     /* Map to in picture coordinates */
997     for (i=0;i<gid->Height;i++)
998       for (j=0;j<gid->Width;j++)
999         bytes[(gid->Top+(gif->SHeight-i-1))*gif->SWidth+gid->Left+j]=si->RasterBits[i*gid->Width+j];
1000     bmi->bmiHeader.biSize               = sizeof(BITMAPINFOHEADER);
1001     bmi->bmiHeader.biWidth              = gif->SWidth;
1002     bmi->bmiHeader.biHeight             = gif->SHeight;
1003     bmi->bmiHeader.biPlanes             = 1;
1004     bmi->bmiHeader.biBitCount           = 8;
1005     bmi->bmiHeader.biCompression        = BI_RGB;
1006     bmi->bmiHeader.biSizeImage          = gif->SWidth*gif->SHeight;
1007     bmi->bmiHeader.biXPelsPerMeter      = 0;
1008     bmi->bmiHeader.biYPelsPerMeter      = 0;
1009     bmi->bmiHeader.biClrUsed            = 1 << gif->SColorResolution;
1010     bmi->bmiHeader.biClrImportant       = 0;
1011
1012     hdcref = GetDC(0);
1013     This->desc.u.bmp.hbitmap=CreateDIBitmap(
1014             hdcref,
1015             &bmi->bmiHeader,
1016             CBM_INIT,
1017             bytes,
1018             bmi,
1019             DIB_RGB_COLORS
1020     );
1021
1022     if (transparent > -1) {
1023         /* Create the Mask */
1024         HDC hdc = CreateCompatibleDC(0);
1025         HDC hdcMask = CreateCompatibleDC(0);
1026         HBITMAP hOldbitmap; 
1027         HBITMAP hOldbitmapmask;
1028
1029         This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
1030
1031         hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap); 
1032         hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
1033         SetBkColor(hdc, This->rgbTrans);
1034         BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
1035
1036         /* We no longer need the original bitmap, so we apply the first
1037            transformation with the mask to speed up the rendering */
1038         SetBkColor(hdc, RGB(0,0,0));
1039         SetTextColor(hdc, RGB(255,255,255));
1040         BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 
1041                  hdcMask, 0, 0,  SRCAND);
1042
1043         SelectObject(hdc, hOldbitmap);
1044         SelectObject(hdcMask, hOldbitmapmask);
1045         DeleteDC(hdcMask);
1046         DeleteDC(hdc);
1047     }
1048     
1049     DeleteDC(hdcref);
1050     This->desc.picType = PICTYPE_BITMAP;
1051     OLEPictureImpl_SetBitmap(This);
1052     DGifCloseFile(gif);
1053     HeapFree(GetProcessHeap(),0,bytes);
1054     return S_OK;
1055 #else
1056     FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
1057     return E_FAIL;
1058 #endif
1059     break;
1060   }
1061   case 0xd8ff: { /* JPEG */
1062 #ifdef HAVE_LIBJPEG
1063     struct jpeg_decompress_struct       jd;
1064     struct jpeg_error_mgr               jerr;
1065     int                                 ret;
1066     JDIMENSION                          x;
1067     JSAMPROW                            samprow,oldsamprow;
1068     BITMAPINFOHEADER                    bmi;
1069     LPBYTE                              bits;
1070     HDC                                 hdcref;
1071     struct jpeg_source_mgr              xjsm;
1072     LPBYTE                              oldbits;
1073     int i;
1074
1075     /* This is basically so we can use in-memory data for jpeg decompression.
1076      * We need to have all the functions.
1077      */
1078     xjsm.next_input_byte        = xbuf;
1079     xjsm.bytes_in_buffer        = xread;
1080     xjsm.init_source            = _jpeg_init_source;
1081     xjsm.fill_input_buffer      = _jpeg_fill_input_buffer;
1082     xjsm.skip_input_data        = _jpeg_skip_input_data;
1083     xjsm.resync_to_restart      = _jpeg_resync_to_restart;
1084     xjsm.term_source            = _jpeg_term_source;
1085
1086     jd.err = jpeg_std_error(&jerr);
1087     jpeg_create_decompress(&jd);
1088     jd.src = &xjsm;
1089     ret=jpeg_read_header(&jd,TRUE);
1090     jd.out_color_space = JCS_RGB;
1091     jpeg_start_decompress(&jd);
1092     if (ret != JPEG_HEADER_OK) {
1093         ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret);
1094         HeapFree(GetProcessHeap(),0,xbuf);
1095         return E_FAIL;
1096     }
1097
1098     bits = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1099                      (jd.output_height+1) * ((jd.output_width*jd.output_components + 3) & ~3) );
1100     samprow=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,jd.output_width*jd.output_components);
1101
1102     oldbits = bits;
1103     oldsamprow = samprow;
1104     while ( jd.output_scanline<jd.output_height ) {
1105       x = jpeg_read_scanlines(&jd,&samprow,1);
1106       if (x != 1) {
1107         FIXME("failed to read current scanline?\n");
1108         break;
1109       }
1110       /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
1111       for(i=0;i<jd.output_width;i++,samprow+=jd.output_components) {
1112         *(bits++) = *(samprow+2);
1113         *(bits++) = *(samprow+1);
1114         *(bits++) = *(samprow);
1115       }
1116       bits = (LPBYTE)(((UINT_PTR)bits + 3) & ~3);
1117       samprow = oldsamprow;
1118     }
1119     bits = oldbits;
1120
1121     bmi.biSize          = sizeof(bmi);
1122     bmi.biWidth         =  jd.output_width;
1123     bmi.biHeight        = -jd.output_height;
1124     bmi.biPlanes        = 1;
1125     bmi.biBitCount      = jd.output_components<<3;
1126     bmi.biCompression   = BI_RGB;
1127     bmi.biSizeImage     = jd.output_height*jd.output_width*jd.output_components;
1128     bmi.biXPelsPerMeter = 0;
1129     bmi.biYPelsPerMeter = 0;
1130     bmi.biClrUsed       = 0;
1131     bmi.biClrImportant  = 0;
1132
1133     HeapFree(GetProcessHeap(),0,samprow);
1134     jpeg_finish_decompress(&jd);
1135     jpeg_destroy_decompress(&jd);
1136     hdcref = GetDC(0);
1137     This->desc.u.bmp.hbitmap=CreateDIBitmap(
1138             hdcref,
1139             &bmi,
1140             CBM_INIT,
1141             bits,
1142             (BITMAPINFO*)&bmi,
1143             DIB_RGB_COLORS
1144     );
1145     DeleteDC(hdcref);
1146     This->desc.picType = PICTYPE_BITMAP;
1147     OLEPictureImpl_SetBitmap(This);
1148     hr = S_OK;
1149     HeapFree(GetProcessHeap(),0,bits);
1150 #else
1151     ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
1152     hr = E_FAIL;
1153 #endif
1154     break;
1155   }
1156   case 0x4d42: { /* Bitmap */
1157     BITMAPFILEHEADER    *bfh = (BITMAPFILEHEADER*)xbuf;
1158     BITMAPINFO          *bi = (BITMAPINFO*)(bfh+1);
1159     HDC                 hdcref;
1160
1161     /* Does not matter whether this is a coreheader or not, we only use
1162      * components which are in both
1163      */
1164     hdcref = GetDC(0);
1165     This->desc.u.bmp.hbitmap = CreateDIBitmap(
1166         hdcref,
1167         &(bi->bmiHeader),
1168         CBM_INIT,
1169         xbuf+bfh->bfOffBits,
1170         bi,
1171         (bi->bmiHeader.biBitCount<=8)?DIB_PAL_COLORS:DIB_RGB_COLORS
1172     );
1173     DeleteDC(hdcref);
1174     This->desc.picType = PICTYPE_BITMAP;
1175     OLEPictureImpl_SetBitmap(This);
1176     hr = S_OK;
1177     break;
1178   }
1179   case 0x0000: { /* ICON , first word is dwReserved */
1180     HICON hicon;
1181     CURSORICONFILEDIR   *cifd = (CURSORICONFILEDIR*)xbuf;
1182     int i;
1183
1184     /*
1185     FIXME("icon.idReserved=%d\n",cifd->idReserved);
1186     FIXME("icon.idType=%d\n",cifd->idType);
1187     FIXME("icon.idCount=%d\n",cifd->idCount);
1188
1189     for (i=0;i<cifd->idCount;i++) {
1190         FIXME("[%d] width %d\n",i,cifd->idEntries[i].bWidth);
1191         FIXME("[%d] height %d\n",i,cifd->idEntries[i].bHeight);
1192         FIXME("[%d] bColorCount %d\n",i,cifd->idEntries[i].bColorCount);
1193         FIXME("[%d] bReserved %d\n",i,cifd->idEntries[i].bReserved);
1194         FIXME("[%d] xHotspot %d\n",i,cifd->idEntries[i].xHotspot);
1195         FIXME("[%d] yHotspot %d\n",i,cifd->idEntries[i].yHotspot);
1196         FIXME("[%d] dwDIBSize %d\n",i,cifd->idEntries[i].dwDIBSize);
1197         FIXME("[%d] dwDIBOffset %d\n",i,cifd->idEntries[i].dwDIBOffset);
1198     }
1199     */
1200     i=0;
1201     /* If we have more than one icon, try to find the best.
1202      * this currently means '32 pixel wide'.
1203      */
1204     if (cifd->idCount!=1) {
1205         for (i=0;i<cifd->idCount;i++) {
1206             if (cifd->idEntries[i].bWidth == 32)
1207                 break;
1208         }
1209         if (i==cifd->idCount) i=0;
1210     }
1211
1212     hicon = CreateIconFromResourceEx(
1213                 xbuf+cifd->idEntries[i].dwDIBOffset,
1214                 cifd->idEntries[i].dwDIBSize,
1215                 TRUE, /* is icon */
1216                 0x00030000,
1217                 cifd->idEntries[i].bWidth,
1218                 cifd->idEntries[i].bHeight,
1219                 0
1220     );
1221     if (!hicon) {
1222         FIXME("CreateIcon failed.\n");
1223         hr = E_FAIL;
1224     } else {
1225         This->desc.picType = PICTYPE_ICON;
1226         This->desc.u.icon.hicon = hicon;
1227         This->himetricWidth = cifd->idEntries[i].bWidth;
1228         This->himetricHeight = cifd->idEntries[i].bHeight;
1229         hr = S_OK;
1230     }
1231     break;
1232   }
1233   default:
1234   {
1235     int i;
1236     FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
1237     hr=E_FAIL;
1238     for (i=0;i<xread+8;i++) {
1239         if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
1240         else MESSAGE("%02x ",xbuf[i-8]);
1241         if (i % 10 == 9) MESSAGE("\n");
1242     }
1243     MESSAGE("\n");
1244     break;
1245   }
1246   }
1247
1248   /* FIXME: this notify is not really documented */
1249   if (hr==S_OK)
1250       OLEPicture_SendNotify(This,DISPID_PICT_TYPE);
1251   return hr;
1252 }
1253
1254 static HRESULT WINAPI OLEPictureImpl_Save(
1255   IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
1256 {
1257   ICOM_THIS_From_IPersistStream(IPicture, iface);
1258   FIXME("(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
1259   return E_NOTIMPL;
1260 }
1261
1262 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
1263   IPersistStream* iface,ULARGE_INTEGER*pcbSize)
1264 {
1265   ICOM_THIS_From_IPersistStream(IPicture, iface);
1266   FIXME("(%p,%p),stub!\n",This,pcbSize);
1267   return E_NOTIMPL;
1268 }
1269
1270 /************************************************************************
1271  *    IDispatch
1272  */
1273 /************************************************************************
1274  * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
1275  *
1276  * See Windows documentation for more details on IUnknown methods.
1277  */
1278 static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
1279   IDispatch* iface,
1280   REFIID     riid,
1281   VOID**     ppvoid)
1282 {
1283   ICOM_THIS_From_IDispatch(IPicture, iface);
1284
1285   return IPicture_QueryInterface(This, riid, ppvoid);
1286 }
1287
1288 /************************************************************************
1289  * OLEPictureImpl_IDispatch_AddRef (IUnknown)
1290  *
1291  * See Windows documentation for more details on IUnknown methods.
1292  */
1293 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
1294   IDispatch* iface)
1295 {
1296   ICOM_THIS_From_IDispatch(IPicture, iface);
1297
1298   return IPicture_AddRef(This);
1299 }
1300
1301 /************************************************************************
1302  * OLEPictureImpl_IDispatch_Release (IUnknown)
1303  *
1304  * See Windows documentation for more details on IUnknown methods.
1305  */
1306 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
1307   IDispatch* iface)
1308 {
1309   ICOM_THIS_From_IDispatch(IPicture, iface);
1310
1311   return IPicture_Release(This);
1312 }
1313
1314 /************************************************************************
1315  * OLEPictureImpl_GetTypeInfoCount (IDispatch)
1316  *
1317  * See Windows documentation for more details on IDispatch methods.
1318  */
1319 static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
1320   IDispatch*    iface,
1321   unsigned int* pctinfo)
1322 {
1323   FIXME("():Stub\n");
1324
1325   return E_NOTIMPL;
1326 }
1327
1328 /************************************************************************
1329  * OLEPictureImpl_GetTypeInfo (IDispatch)
1330  *
1331  * See Windows documentation for more details on IDispatch methods.
1332  */
1333 static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
1334   IDispatch*  iface,
1335   UINT      iTInfo,
1336   LCID        lcid,
1337   ITypeInfo** ppTInfo)
1338 {
1339   FIXME("():Stub\n");
1340
1341   return E_NOTIMPL;
1342 }
1343
1344 /************************************************************************
1345  * OLEPictureImpl_GetIDsOfNames (IDispatch)
1346  *
1347  * See Windows documentation for more details on IDispatch methods.
1348  */
1349 static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
1350   IDispatch*  iface,
1351   REFIID      riid,
1352   LPOLESTR* rgszNames,
1353   UINT      cNames,
1354   LCID        lcid,
1355   DISPID*     rgDispId)
1356 {
1357   FIXME("():Stub\n");
1358
1359   return E_NOTIMPL;
1360 }
1361
1362 /************************************************************************
1363  * OLEPictureImpl_Invoke (IDispatch)
1364  *
1365  * See Windows documentation for more details on IDispatch methods.
1366  */
1367 static HRESULT WINAPI OLEPictureImpl_Invoke(
1368   IDispatch*  iface,
1369   DISPID      dispIdMember,
1370   REFIID      riid,
1371   LCID        lcid,
1372   WORD        wFlags,
1373   DISPPARAMS* pDispParams,
1374   VARIANT*    pVarResult,
1375   EXCEPINFO*  pExepInfo,
1376   UINT*     puArgErr)
1377 {
1378   FIXME("(dispid: %ld):Stub\n",dispIdMember);
1379
1380   VariantInit(pVarResult);
1381   V_VT(pVarResult) = VT_BOOL;
1382   V_UNION(pVarResult,boolVal) = FALSE;
1383   return S_OK;
1384 }
1385
1386
1387 static ICOM_VTABLE(IPicture) OLEPictureImpl_VTable =
1388 {
1389   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1390   OLEPictureImpl_QueryInterface,
1391   OLEPictureImpl_AddRef,
1392   OLEPictureImpl_Release,
1393   OLEPictureImpl_get_Handle,
1394   OLEPictureImpl_get_hPal,
1395   OLEPictureImpl_get_Type,
1396   OLEPictureImpl_get_Width,
1397   OLEPictureImpl_get_Height,
1398   OLEPictureImpl_Render,
1399   OLEPictureImpl_set_hPal,
1400   OLEPictureImpl_get_CurDC,
1401   OLEPictureImpl_SelectPicture,
1402   OLEPictureImpl_get_KeepOriginalFormat,
1403   OLEPictureImpl_put_KeepOriginalFormat,
1404   OLEPictureImpl_PictureChanged,
1405   OLEPictureImpl_SaveAsFile,
1406   OLEPictureImpl_get_Attributes
1407 };
1408
1409 static ICOM_VTABLE(IDispatch) OLEPictureImpl_IDispatch_VTable =
1410 {
1411   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1412   OLEPictureImpl_IDispatch_QueryInterface,
1413   OLEPictureImpl_IDispatch_AddRef,
1414   OLEPictureImpl_IDispatch_Release,
1415   OLEPictureImpl_GetTypeInfoCount,
1416   OLEPictureImpl_GetTypeInfo,
1417   OLEPictureImpl_GetIDsOfNames,
1418   OLEPictureImpl_Invoke
1419 };
1420
1421 static ICOM_VTABLE(IPersistStream) OLEPictureImpl_IPersistStream_VTable =
1422 {
1423   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1424   OLEPictureImpl_IPersistStream_QueryInterface,
1425   OLEPictureImpl_IPersistStream_AddRef,
1426   OLEPictureImpl_IPersistStream_Release,
1427   OLEPictureImpl_GetClassID,
1428   OLEPictureImpl_IsDirty,
1429   OLEPictureImpl_Load,
1430   OLEPictureImpl_Save,
1431   OLEPictureImpl_GetSizeMax
1432 };
1433
1434 static ICOM_VTABLE(IConnectionPointContainer) OLEPictureImpl_IConnectionPointContainer_VTable =
1435 {
1436   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1437   OLEPictureImpl_IConnectionPointContainer_QueryInterface,
1438   OLEPictureImpl_IConnectionPointContainer_AddRef,
1439   OLEPictureImpl_IConnectionPointContainer_Release,
1440   OLEPictureImpl_EnumConnectionPoints,
1441   OLEPictureImpl_FindConnectionPoint
1442 };
1443
1444 /***********************************************************************
1445  * OleCreatePictureIndirect (OLEAUT32.419)
1446  */
1447 HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
1448                             BOOL fOwn, LPVOID *ppvObj )
1449 {
1450   OLEPictureImpl* newPict = NULL;
1451   HRESULT      hr         = S_OK;
1452
1453   TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
1454
1455   /*
1456    * Sanity check
1457    */
1458   if (ppvObj==0)
1459     return E_POINTER;
1460
1461   *ppvObj = NULL;
1462
1463   /*
1464    * Try to construct a new instance of the class.
1465    */
1466   newPict = OLEPictureImpl_Construct(lpPictDesc, fOwn);
1467
1468   if (newPict == NULL)
1469     return E_OUTOFMEMORY;
1470
1471   /*
1472    * Make sure it supports the interface required by the caller.
1473    */
1474   hr = IPicture_QueryInterface((IPicture*)newPict, riid, ppvObj);
1475
1476   /*
1477    * Release the reference obtained in the constructor. If
1478    * the QueryInterface was unsuccessful, it will free the class.
1479    */
1480   IPicture_Release((IPicture*)newPict);
1481
1482   return hr;
1483 }
1484
1485
1486 /***********************************************************************
1487  * OleLoadPicture (OLEAUT32.418)
1488  */
1489 HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1490                             REFIID riid, LPVOID *ppvObj )
1491 {
1492   LPPERSISTSTREAM ps;
1493   IPicture      *newpic;
1494   HRESULT hr;
1495
1496   TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
1497         lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
1498
1499   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
1500   if (hr)
1501     return hr;
1502   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
1503   if (hr) {
1504       FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1505       IPicture_Release(newpic);
1506       *ppvObj = NULL;
1507       return hr;
1508   }
1509   IPersistStream_Load(ps,lpstream);
1510   IPersistStream_Release(ps);
1511   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
1512   if (hr)
1513       FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
1514   IPicture_Release(newpic);
1515   return hr;
1516 }
1517
1518 /***********************************************************************
1519  * OleLoadPictureEx (OLEAUT32.401)
1520  */
1521 HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
1522                             REFIID riid, DWORD xsiz, DWORD ysiz, DWORD flags, LPVOID *ppvObj )
1523 {
1524   LPPERSISTSTREAM ps;
1525   IPicture      *newpic;
1526   HRESULT hr;
1527
1528   FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
1529         lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
1530
1531   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
1532   if (hr)
1533     return hr;
1534   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
1535   if (hr) {
1536       FIXME("Could not get IPersistStream iface from Ole Picture?\n");
1537       IPicture_Release(newpic);
1538       *ppvObj = NULL;
1539       return hr;
1540   }
1541   IPersistStream_Load(ps,lpstream);
1542   IPersistStream_Release(ps);
1543   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
1544   if (hr)
1545       FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
1546   IPicture_Release(newpic);
1547   return hr;
1548 }
1549
1550 /*******************************************************************************
1551  * StdPic ClassFactory
1552  */
1553 typedef struct
1554 {
1555     /* IUnknown fields */
1556     ICOM_VFIELD(IClassFactory);
1557     DWORD                       ref;
1558 } IClassFactoryImpl;
1559
1560 static HRESULT WINAPI
1561 SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
1562         ICOM_THIS(IClassFactoryImpl,iface);
1563
1564         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1565         return E_NOINTERFACE;
1566 }
1567
1568 static ULONG WINAPI
1569 SPCF_AddRef(LPCLASSFACTORY iface) {
1570         ICOM_THIS(IClassFactoryImpl,iface);
1571         return ++(This->ref);
1572 }
1573
1574 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
1575         ICOM_THIS(IClassFactoryImpl,iface);
1576         /* static class, won't be  freed */
1577         return --(This->ref);
1578 }
1579
1580 static HRESULT WINAPI SPCF_CreateInstance(
1581         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
1582 ) {
1583         PICTDESC        pd;
1584
1585         FIXME("(%p,%p,%s,%p), creating stdpic with PICTYPE_NONE.\n",iface,pOuter,debugstr_guid(riid),ppobj);
1586         pd.cbSizeofstruct = sizeof(pd);
1587         pd.picType = PICTYPE_NONE;
1588         return OleCreatePictureIndirect(&pd,riid,TRUE,ppobj);
1589
1590 }
1591
1592 static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
1593         ICOM_THIS(IClassFactoryImpl,iface);
1594         FIXME("(%p)->(%d),stub!\n",This,dolock);
1595         return S_OK;
1596 }
1597
1598 static ICOM_VTABLE(IClassFactory) SPCF_Vtbl = {
1599         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1600         SPCF_QueryInterface,
1601         SPCF_AddRef,
1602         SPCF_Release,
1603         SPCF_CreateInstance,
1604         SPCF_LockServer
1605 };
1606 static IClassFactoryImpl STDPIC_CF = {&SPCF_Vtbl, 1 };
1607
1608 void _get_STDPIC_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDPIC_CF; }