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