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