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