d3d10core: Make some device_parent_*() functions static.
[wine] / dlls / oleaut32 / olepicture.c
index b1fa7fe..f05501d 100644 (file)
@@ -5,6 +5,7 @@
  *
  * Copyright 2000 Huw D M Davies for CodeWeavers.
  * Copyright 2001 Marcus Meissner
+ * Copyright 2008 Kirill K. Smirnov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * BUGS
  *
- * Support PICTYPE_BITMAP and PICTYPE_ICON, altough only bitmaps very well..
+ * Support PICTYPE_BITMAP and PICTYPE_ICON, although only bitmaps very well..
  * Lots of methods are just stubs.
  *
  *
 #include <stdio.h>
 #include <string.h>
 
-/* Must be before wine includes, the header has things conflicting with
- * WINE headers.
- */
-#ifdef HAVE_GIF_LIB_H
-# include <gif_lib.h>
-#ifndef SONAME_LIBUNGIF
-#define SONAME_LIBUNGIF "libungif.so"
+#ifdef SONAME_LIBJPEG
+/* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
+#define XMD_H
+#define UINT8 JPEG_UINT8
+#define UINT16 JPEG_UINT16
+#define boolean jpeg_boolean
+# include <jpeglib.h>
+#undef UINT8
+#undef UINT16
+#undef boolean
 #endif
+
+#ifdef HAVE_PNG_H
+#include <png.h>
 #endif
 
+/* Must be before wine includes, the header has things conflicting with
+ * WINE headers.
+ */
+#define COBJMACROS
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
+
 #include "winerror.h"
 #include "windef.h"
 #include "winbase.h"
 #include "olectl.h"
 #include "oleauto.h"
 #include "connpt.h"
+#include "urlmon.h"
 #include "wine/debug.h"
+#include "wine/unicode.h"
 
 #include "wine/wingdi16.h"
-#include "cursoricon.h"
 
-#ifdef HAVE_JPEGLIB_H
-/* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
-#define XMD_H
-#define UINT8 JPEG_UINT8
-#define UINT16 JPEG_UINT16
-#undef FAR
-# include <jpeglib.h>
-#undef UINT16
-#ifndef SONAME_LIBJPEG
-#define SONAME_LIBJPEG "libjpeg.so"
-#endif
-#endif
+#include "ungif.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
+#include "pshpack1.h"
+
+/* Header for Aldus Placable Metafiles - a standard metafile follows */
+typedef struct _APM_HEADER
+{
+    DWORD key;
+    WORD handle;
+    SHORT left;
+    SHORT top;
+    SHORT right;
+    SHORT bottom;
+    WORD inch;
+    DWORD reserved;
+    WORD checksum;
+} APM_HEADER;
+
+typedef struct {
+    BYTE bWidth;
+    BYTE bHeight;
+    BYTE bColorCount;
+    BYTE bReserved;
+    WORD xHotspot;
+    WORD yHotspot;
+    DWORD dwDIBSize;
+    DWORD dwDIBOffset;
+} CURSORICONFILEDIRENTRY;
+
+typedef struct
+{
+    WORD                idReserved;
+    WORD                idType;
+    WORD                idCount;
+    CURSORICONFILEDIRENTRY  idEntries[1];
+} CURSORICONFILEDIR;
+
+#include "poppack.h"
+
 /*************************************************************************
  *  Declaration of implementation class
  */
@@ -96,13 +135,13 @@ typedef struct OLEPictureImpl {
    * IPicture handles IUnknown
    */
 
-    IPictureVtbl       *lpvtbl1;
-    IDispatchVtbl      *lpvtbl2;
-    IPersistStreamVtbl *lpvtbl3;
-    IConnectionPointContainerVtbl *lpvtbl4;
+    const IPictureVtbl       *lpVtbl;
+    const IDispatchVtbl      *lpvtblIDispatch;
+    const IPersistStreamVtbl *lpvtblIPersistStream;
+    const IConnectionPointContainerVtbl *lpvtblIConnectionPointContainer;
 
-  /* Object referenece count */
-    DWORD ref;
+  /* Object reference count */
+    LONG ref;
 
   /* We own the object and must destroy it ourselves */
     BOOL fOwn;
@@ -125,30 +164,43 @@ typedef struct OLEPictureImpl {
 
   /* Bitmap transparency mask */
     HBITMAP hbmMask;
+    HBITMAP hbmXor;
     COLORREF rgbTrans;
 
   /* data */
     void* data;
     int datalen;
+    BOOL bIsDirty;                  /* Set to TRUE if picture has changed */
+    unsigned int loadtime_magic;    /* If a length header was found, saves value */
+    unsigned int loadtime_format;   /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */
 } OLEPictureImpl;
 
 /*
  * Macros to retrieve pointer to IUnknown (IPicture) from the other VTables.
  */
-#define ICOM_THIS_From_IDispatch(impl, name) \
-    impl *This = (impl*)(((char*)name)-sizeof(void*));
-#define ICOM_THIS_From_IPersistStream(impl, name) \
-    impl *This = (impl*)(((char*)name)-2*sizeof(void*));
-#define ICOM_THIS_From_IConnectionPointContainer(impl, name) \
-    impl *This = (impl*)(((char*)name)-3*sizeof(void*));
+
+static inline OLEPictureImpl *impl_from_IDispatch( IDispatch *iface )
+{
+    return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIDispatch));
+}
+
+static inline OLEPictureImpl *impl_from_IPersistStream( IPersistStream *iface )
+{
+    return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIPersistStream));
+}
+
+static inline OLEPictureImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
+{
+    return (OLEPictureImpl *)((char*)iface - FIELD_OFFSET(OLEPictureImpl, lpvtblIConnectionPointContainer));
+}
 
 /*
  * Predeclare VTables.  They get initialized at the end.
  */
-static IPictureVtbl OLEPictureImpl_VTable;
-static IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
-static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
-static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
+static const IPictureVtbl OLEPictureImpl_VTable;
+static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
+static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
+static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
 
 /***********************************************************************
  * Implementation of the OLEPictureImpl class.
@@ -175,6 +227,36 @@ static void OLEPictureImpl_SetBitmap(OLEPictureImpl*This) {
   DeleteDC(hdcRef);
 }
 
+static void OLEPictureImpl_SetIcon(OLEPictureImpl * This)
+{
+    ICONINFO infoIcon;
+
+    TRACE("icon handle %p\n", This->desc.u.icon.hicon);
+    if (GetIconInfo(This->desc.u.icon.hicon, &infoIcon)) {
+        HDC hdcRef;
+        BITMAP bm;
+
+        TRACE("bitmap handle for icon is %p\n", infoIcon.hbmColor);
+        if(GetObjectA(infoIcon.hbmColor ? infoIcon.hbmColor : infoIcon.hbmMask, sizeof(bm), &bm) != sizeof(bm)) {
+            ERR("GetObject fails on icon bitmap\n");
+            return;
+        }
+
+        This->origWidth = bm.bmWidth;
+        This->origHeight = infoIcon.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
+        /* see comment on HIMETRIC on OLEPictureImpl_SetBitmap() */
+        hdcRef = GetDC(0);
+        This->himetricWidth = (This->origWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
+        This->himetricHeight= (This->origHeight *2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
+        ReleaseDC(0, hdcRef);
+
+        DeleteObject(infoIcon.hbmMask);
+        if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
+    } else {
+        ERR("GetIconInfo() fails on icon %p\n", This->desc.u.icon.hicon);
+    }
+}
+
 /************************************************************************
  * OLEPictureImpl_Construct
  *
@@ -202,12 +284,18 @@ static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
   /*
    * Initialize the virtual function table.
    */
-  newObject->lpvtbl1 = &OLEPictureImpl_VTable;
-  newObject->lpvtbl2 = &OLEPictureImpl_IDispatch_VTable;
-  newObject->lpvtbl3 = &OLEPictureImpl_IPersistStream_VTable;
-  newObject->lpvtbl4 = &OLEPictureImpl_IConnectionPointContainer_VTable;
+  newObject->lpVtbl = &OLEPictureImpl_VTable;
+  newObject->lpvtblIDispatch = &OLEPictureImpl_IDispatch_VTable;
+  newObject->lpvtblIPersistStream = &OLEPictureImpl_IPersistStream_VTable;
+  newObject->lpvtblIConnectionPointContainer = &OLEPictureImpl_IConnectionPointContainer_VTable;
 
+  newObject->pCP = NULL;
   CreateConnectionPoint((IUnknown*)newObject,&IID_IPropertyNotifySink,&newObject->pCP);
+  if (!newObject->pCP)
+  {
+    HeapFree(GetProcessHeap(), 0, newObject);
+    return NULL;
+  }
 
   /*
    * Start with one reference count. The caller of this function
@@ -222,13 +310,13 @@ static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
   newObject->keepOrigFormat = TRUE;
 
   newObject->hbmMask = NULL;
+  newObject->hbmXor = NULL;
+  newObject->loadtime_magic = 0xdeadbeef;
+  newObject->loadtime_format = 0;
+  newObject->bIsDirty = FALSE;
 
   if (pictDesc) {
-      if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) {
-         FIXME("struct size = %d\n", pictDesc->cbSizeofstruct);
-      }
-      memcpy(&newObject->desc, pictDesc, sizeof(PICTDESC));
-
+      newObject->desc = *pictDesc;
 
       switch(pictDesc->picType) {
       case PICTYPE_BITMAP:
@@ -247,6 +335,8 @@ static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn)
        break;
 
       case PICTYPE_ICON:
+        OLEPictureImpl_SetIcon(newObject);
+        break;
       case PICTYPE_ENHMETAFILE:
       default:
        FIXME("Unsupported type %d\n", pictDesc->picType);
@@ -271,10 +361,15 @@ static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
 {
   TRACE("(%p)\n", Obj);
 
+  if (Obj->pCP)
+    IConnectionPoint_Release(Obj->pCP);
+
   if(Obj->fOwn) { /* We need to destroy the picture */
     switch(Obj->desc.picType) {
     case PICTYPE_BITMAP:
       DeleteObject(Obj->desc.u.bmp.hbitmap);
+      if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
+      if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
       break;
     case PICTYPE_METAFILE:
       DeleteMetaFile(Obj->desc.u.wmf.hmeta);
@@ -285,16 +380,56 @@ static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
     case PICTYPE_ENHMETAFILE:
       DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
       break;
+    case PICTYPE_NONE:
+    case PICTYPE_UNINITIALIZED:
+      /* Nothing to do */
+      break;
     default:
       FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
       break;
     }
   }
-  if (Obj->data) HeapFree(GetProcessHeap(), 0, Obj->data);
+  HeapFree(GetProcessHeap(), 0, Obj->data);
   HeapFree(GetProcessHeap(), 0, Obj);
 }
 
-static ULONG WINAPI OLEPictureImpl_AddRef(IPicture* iface);
+
+/************************************************************************
+ * OLEPictureImpl_AddRef (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI OLEPictureImpl_AddRef(
+  IPicture* iface)
+{
+  OLEPictureImpl *This = (OLEPictureImpl *)iface;
+  ULONG refCount = InterlockedIncrement(&This->ref);
+
+  TRACE("(%p)->(ref before=%d)\n", This, refCount - 1);
+
+  return refCount;
+}
+
+/************************************************************************
+ * OLEPictureImpl_Release (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI OLEPictureImpl_Release(
+      IPicture* iface)
+{
+  OLEPictureImpl *This = (OLEPictureImpl *)iface;
+  ULONG refCount = InterlockedDecrement(&This->ref);
+
+  TRACE("(%p)->(ref before=%d)\n", This, refCount + 1);
+
+  /*
+   * If the reference count goes down to 0, perform suicide.
+   */
+  if (!refCount) OLEPictureImpl_Destroy(This);
+
+  return refCount;
+}
 
 /************************************************************************
  * OLEPictureImpl_QueryInterface (IUnknown)
@@ -323,30 +458,17 @@ static HRESULT WINAPI OLEPictureImpl_QueryInterface(
   /*
    * Compare the riid with the interface IDs implemented by this object.
    */
-  if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
-  {
-    *ppvObject = (IPicture*)This;
-  }
-  else if (memcmp(&IID_IPicture, riid, sizeof(IID_IPicture)) == 0)
-  {
+  if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPicture, riid))
     *ppvObject = (IPicture*)This;
-  }
-  else if (memcmp(&IID_IDispatch, riid, sizeof(IID_IDispatch)) == 0)
-  {
-    *ppvObject = (IDispatch*)&(This->lpvtbl2);
-  }
-  else if (memcmp(&IID_IPictureDisp, riid, sizeof(IID_IPictureDisp)) == 0)
-  {
-    *ppvObject = (IDispatch*)&(This->lpvtbl2);
-  }
-  else if (memcmp(&IID_IPersistStream, riid, sizeof(IID_IPersistStream)) == 0)
-  {
-  *ppvObject = (IPersistStream*)&(This->lpvtbl3);
-  }
-  else if (memcmp(&IID_IConnectionPointContainer, riid, sizeof(IID_IConnectionPointContainer)) == 0)
-  {
-  *ppvObject = (IConnectionPointContainer*)&(This->lpvtbl4);
-  }
+  else if (IsEqualIID(&IID_IDispatch, riid))
+    *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
+  else if (IsEqualIID(&IID_IPictureDisp, riid))
+    *ppvObject = (IDispatch*)&(This->lpvtblIDispatch);
+  else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid))
+    *ppvObject = (IPersistStream*)&(This->lpvtblIPersistStream);
+  else if (IsEqualIID(&IID_IConnectionPointContainer, riid))
+    *ppvObject = (IConnectionPointContainer*)&(This->lpvtblIConnectionPointContainer);
+
   /*
    * Check that we obtained an interface.
    */
@@ -364,6 +486,7 @@ static HRESULT WINAPI OLEPictureImpl_QueryInterface(
 
   return S_OK;
 }
+
 /***********************************************************************
  *    OLEPicture_SendNotify (internal)
  *
@@ -386,54 +509,8 @@ static void OLEPicture_SendNotify(OLEPictureImpl* this, DISPID dispID)
     IUnknown_Release(CD.pUnk);
   }
   IEnumConnections_Release(pEnum);
-  return;
-}
-
-/************************************************************************
- * OLEPictureImpl_AddRef (IUnknown)
- *
- * See Windows documentation for more details on IUnknown methods.
- */
-static ULONG WINAPI OLEPictureImpl_AddRef(
-  IPicture* iface)
-{
-  OLEPictureImpl *This = (OLEPictureImpl *)iface;
-  TRACE("(%p)->(ref=%ld)\n", This, This->ref);
-  This->ref++;
-
-  return This->ref;
-}
-
-/************************************************************************
- * OLEPictureImpl_Release (IUnknown)
- *
- * See Windows documentation for more details on IUnknown methods.
- */
-static ULONG WINAPI OLEPictureImpl_Release(
-      IPicture* iface)
-{
-  OLEPictureImpl *This = (OLEPictureImpl *)iface;
-  TRACE("(%p)->(ref=%ld)\n", This, This->ref);
-
-  /*
-   * Decrease the reference count on this object.
-   */
-  This->ref--;
-
-  /*
-   * If the reference count goes down to 0, perform suicide.
-   */
-  if (This->ref==0)
-  {
-    OLEPictureImpl_Destroy(This);
-
-    return 0;
-  }
-
-  return This->ref;
 }
 
-
 /************************************************************************
  * OLEPictureImpl_get_Handle
  */
@@ -442,18 +519,26 @@ static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
 {
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
   TRACE("(%p)->(%p)\n", This, phandle);
+
+  if(!phandle)
+    return E_POINTER;
+
   switch(This->desc.picType) {
+  case PICTYPE_NONE:
+  case PICTYPE_UNINITIALIZED:
+    *phandle = 0;
+    break;
   case PICTYPE_BITMAP:
-    *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
+    *phandle = HandleToUlong(This->desc.u.bmp.hbitmap);
     break;
   case PICTYPE_METAFILE:
-    *phandle = (OLE_HANDLE)This->desc.u.wmf.hmeta;
+    *phandle = HandleToUlong(This->desc.u.wmf.hmeta);
     break;
   case PICTYPE_ICON:
-    *phandle = (OLE_HANDLE)This->desc.u.icon.hicon;
+    *phandle = HandleToUlong(This->desc.u.icon.hicon);
     break;
   case PICTYPE_ENHMETAFILE:
-    *phandle = (OLE_HANDLE)This->desc.u.emf.hemf;
+    *phandle = HandleToUlong(This->desc.u.emf.hemf);
     break;
   default:
     FIXME("Unimplemented type %d\n", This->desc.picType);
@@ -470,8 +555,36 @@ static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
                                              OLE_HANDLE *phandle)
 {
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
-  FIXME("(%p)->(%p): stub\n", This, phandle);
-  return E_NOTIMPL;
+  HRESULT hres;
+  TRACE("(%p)->(%p)\n", This, phandle);
+
+  if (!phandle)
+    return E_POINTER;
+
+  switch (This->desc.picType) {
+    case (UINT)PICTYPE_UNINITIALIZED:
+    case PICTYPE_NONE:
+      *phandle = 0;
+      hres = S_FALSE;
+      break;
+    case PICTYPE_BITMAP:
+      *phandle = HandleToUlong(This->desc.u.bmp.hpal);
+      hres = S_OK;
+      break;
+    case PICTYPE_METAFILE:
+      hres = E_FAIL;
+      break;
+    case PICTYPE_ICON:
+    case PICTYPE_ENHMETAFILE:
+    default:
+      FIXME("unimplemented for type %d. Returning 0 palette.\n",
+           This->desc.picType);
+      *phandle = 0;
+      hres = S_OK;
+  }
+
+  TRACE("returning 0x%08x, palette handle %08x\n", hres, *phandle);
+  return hres;
 }
 
 /************************************************************************
@@ -482,6 +595,10 @@ static HRESULT WINAPI OLEPictureImpl_get_Type(IPicture *iface,
 {
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
   TRACE("(%p)->(%p): type is %d\n", This, ptype, This->desc.picType);
+
+  if(!ptype)
+    return E_POINTER;
+
   *ptype = This->desc.picType;
   return S_OK;
 }
@@ -493,7 +610,7 @@ static HRESULT WINAPI OLEPictureImpl_get_Width(IPicture *iface,
                                               OLE_XSIZE_HIMETRIC *pwidth)
 {
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
-  TRACE("(%p)->(%p): width is %ld\n", This, pwidth, This->himetricWidth);
+  TRACE("(%p)->(%p): width is %d\n", This, pwidth, This->himetricWidth);
   *pwidth = This->himetricWidth;
   return S_OK;
 }
@@ -505,7 +622,7 @@ static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
                                                OLE_YSIZE_HIMETRIC *pheight)
 {
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
-  TRACE("(%p)->(%p): height is %ld\n", This, pheight, This->himetricHeight);
+  TRACE("(%p)->(%p): height is %d\n", This, pheight, This->himetricHeight);
   *pheight = This->himetricHeight;
   return S_OK;
 }
@@ -514,7 +631,7 @@ static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface,
  * OLEPictureImpl_Render
  */
 static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
-                                           long x, long y, long cx, long cy,
+                                           LONG x, LONG y, LONG cx, LONG cy,
                                            OLE_XPOS_HIMETRIC xSrc,
                                            OLE_YPOS_HIMETRIC ySrc,
                                            OLE_XSIZE_HIMETRIC cxSrc,
@@ -522,12 +639,16 @@ static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
                                            LPCRECT prcWBounds)
 {
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
-  TRACE("(%p)->(%p, (%ld,%ld), (%ld,%ld) <- (%ld,%ld), (%ld,%ld), %p)\n",
+  TRACE("(%p)->(%p, (%d,%d), (%d,%d) <- (%d,%d), (%d,%d), %p)\n",
        This, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, prcWBounds);
   if(prcWBounds)
-    TRACE("prcWBounds (%ld,%ld) - (%ld,%ld)\n", prcWBounds->left, prcWBounds->top,
+    TRACE("prcWBounds (%d,%d) - (%d,%d)\n", prcWBounds->left, prcWBounds->top,
          prcWBounds->right, prcWBounds->bottom);
 
+  if(cx == 0 || cy == 0 || cxSrc == 0 || cySrc == 0){
+    return CTL_E_INVALIDPROPERTYVALUE;
+  }
+
   /*
    * While the documentation suggests this to be here (or after rendering?)
    * it does cause an endless recursion in my sample app. -MM 20010804
@@ -535,6 +656,10 @@ static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
    */
 
   switch(This->desc.picType) {
+  case PICTYPE_UNINITIALIZED:
+  case PICTYPE_NONE:
+    /* nothing to do */
+    return S_OK;
   case PICTYPE_BITMAP:
     {
       HBITMAP hbmpOld;
@@ -550,12 +675,12 @@ static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
       SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
       SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
 
-      hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
-
       if (This->hbmMask) {
          HDC hdcMask = CreateCompatibleDC(0);
          HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
 
+          hbmpOld = SelectObject(hdcBmp, This->hbmXor);
+
          SetMapMode(hdcMask, MM_ANISOTROPIC);
          SetWindowOrgEx(hdcMask, 0, 0, NULL);
          SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
@@ -569,8 +694,10 @@ static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
 
          SelectObject(hdcMask, hOldbm);
          DeleteDC(hdcMask);
-      } else
+      } else {
+          hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
          StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
+      }
 
       SelectObject(hdcBmp, hbmpOld);
       DeleteDC(hdcBmp);
@@ -582,7 +709,41 @@ static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc,
     break;
 
   case PICTYPE_METAFILE:
+  {
+    POINT prevOrg, prevWndOrg;
+    SIZE prevExt, prevWndExt;
+    int oldmode;
+
+    /* Render the WMF to the appropriate location by setting the
+       appropriate ratio between "device units" and "logical units" */
+    oldmode = SetMapMode(hdc, MM_ANISOTROPIC);
+    /* For the "source rectangle" the y-axis must be inverted */
+    SetWindowOrgEx(hdc, xSrc, This->himetricHeight-ySrc, &prevWndOrg);
+    SetWindowExtEx(hdc, cxSrc, -cySrc, &prevWndExt);
+    /* For the "destination rectangle" no inversion is necessary */
+    SetViewportOrgEx(hdc, x, y, &prevOrg);
+    SetViewportExtEx(hdc, cx, cy, &prevExt);
+
+    if (!PlayMetaFile(hdc, This->desc.u.wmf.hmeta))
+        ERR("PlayMetaFile failed!\n");
+
+    /* We're done, restore the DC to the previous settings for converting
+       logical units to device units */
+    SetWindowExtEx(hdc, prevWndExt.cx, prevWndExt.cy, NULL);
+    SetWindowOrgEx(hdc, prevWndOrg.x, prevWndOrg.y, NULL);
+    SetViewportExtEx(hdc, prevExt.cx, prevExt.cy, NULL);
+    SetViewportOrgEx(hdc, prevOrg.x, prevOrg.y, NULL);
+    SetMapMode(hdc, oldmode);
+    break;
+  }
+
   case PICTYPE_ENHMETAFILE:
+  {
+    RECT rc = { x, y, x + cx, y + cy };
+    PlayEnhMetaFile(hdc, This->desc.u.emf.hemf, &rc);
+    break;
+  }
+
   default:
     FIXME("type %d not implemented\n", This->desc.picType);
     return E_NOTIMPL;
@@ -631,7 +792,7 @@ static HRESULT WINAPI OLEPictureImpl_SelectPicture(IPicture *iface,
          *phdcOut = This->hDCCur;
       This->hDCCur = hdcIn;
       if (phbmpOut)
-         *phbmpOut = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
+         *phbmpOut = HandleToUlong(This->desc.u.bmp.hbitmap);
       return S_OK;
   } else {
       FIXME("Don't know how to select picture type %d\n",This->desc.picType);
@@ -674,6 +835,7 @@ static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface)
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
   TRACE("(%p)->()\n", This);
   OLEPicture_SendNotify(This,DISPID_PICT_HANDLE);
+  This->bIsDirty = TRUE;
   return S_OK;
 }
 
@@ -698,10 +860,17 @@ static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
 {
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
   TRACE("(%p)->(%p).\n", This, pdwAttr);
+
+  if(!pdwAttr)
+    return E_POINTER;
+
   *pdwAttr = 0;
   switch (This->desc.picType) {
-  case PICTYPE_BITMAP:         break;  /* not 'truely' scalable, see MSDN. */
+  case PICTYPE_UNINITIALIZED:
+  case PICTYPE_NONE: break;
+  case PICTYPE_BITMAP:         if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break;       /* not 'truly' scalable, see MSDN. */
   case PICTYPE_ICON: *pdwAttr     = PICTURE_TRANSPARENT;break;
+  case PICTYPE_ENHMETAFILE: /* fall through */
   case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
   default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
   }
@@ -712,38 +881,37 @@ static HRESULT WINAPI OLEPictureImpl_get_Attributes(IPicture *iface,
 /************************************************************************
  *    IConnectionPointContainer
  */
-
 static HRESULT WINAPI OLEPictureImpl_IConnectionPointContainer_QueryInterface(
   IConnectionPointContainer* iface,
   REFIID riid,
-  VOID** ppvoid
-{
-  ICOM_THIS_From_IConnectionPointContainer(IPicture,iface);
+  VOID** ppvoid)
+{
+  OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
 
-  return IPicture_QueryInterface(This,riid,ppvoid);
+  return IPicture_QueryInterface((IPicture *)This,riid,ppvoid);
 }
 
 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_AddRef(
   IConnectionPointContainer* iface)
 {
-  ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
 
-  return IPicture_AddRef(This);
+  return IPicture_AddRef((IPicture *)This);
 }
 
 static ULONG WINAPI OLEPictureImpl_IConnectionPointContainer_Release(
   IConnectionPointContainer* iface)
 {
-  ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
 
-  return IPicture_Release(This);
+  return IPicture_Release((IPicture *)This);
 }
 
 static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
   IConnectionPointContainer* iface,
-  IEnumConnectionPoints** ppEnum
-{
-  ICOM_THIS_From_IConnectionPointContainer(IPicture, iface);
+  IEnumConnectionPoints** ppEnum)
+{
+  OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
 
   FIXME("(%p,%p), stub!\n",This,ppEnum);
   return E_NOTIMPL;
@@ -752,21 +920,24 @@ static HRESULT WINAPI OLEPictureImpl_EnumConnectionPoints(
 static HRESULT WINAPI OLEPictureImpl_FindConnectionPoint(
   IConnectionPointContainer* iface,
   REFIID riid,
-  IConnectionPoint **ppCP
-{
-  ICOM_THIS_From_IConnectionPointContainer(OLEPictureImpl, iface);
+  IConnectionPoint **ppCP)
+{
+  OLEPictureImpl *This = impl_from_IConnectionPointContainer(iface);
   TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppCP);
   if (!ppCP)
       return E_POINTER;
   *ppCP = NULL;
   if (IsEqualGUID(riid,&IID_IPropertyNotifySink))
       return IConnectionPoint_QueryInterface(This->pCP,&IID_IConnectionPoint,(LPVOID)ppCP);
-  FIXME("tried to find connection point on %s?\n",debugstr_guid(riid));
-  return 0x80040200;
+  FIXME("no connection point for %s\n",debugstr_guid(riid));
+  return CONNECT_E_NOCONNECTION;
 }
+
+
 /************************************************************************
  *    IPersistStream
  */
+
 /************************************************************************
  * OLEPictureImpl_IPersistStream_QueryInterface (IUnknown)
  *
@@ -777,9 +948,9 @@ static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
   REFIID     riid,
   VOID**     ppvoid)
 {
-  ICOM_THIS_From_IPersistStream(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IPersistStream(iface);
 
-  return IPicture_QueryInterface(This, riid, ppvoid);
+  return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
 }
 
 /************************************************************************
@@ -790,9 +961,9 @@ static HRESULT WINAPI OLEPictureImpl_IPersistStream_QueryInterface(
 static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
   IPersistStream* iface)
 {
-  ICOM_THIS_From_IPersistStream(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IPersistStream(iface);
 
-  return IPicture_AddRef(This);
+  return IPicture_AddRef((IPicture *)This);
 }
 
 /************************************************************************
@@ -803,9 +974,9 @@ static ULONG WINAPI OLEPictureImpl_IPersistStream_AddRef(
 static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
   IPersistStream* iface)
 {
-  ICOM_THIS_From_IPersistStream(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IPersistStream(iface);
 
-  return IPicture_Release(This);
+  return IPicture_Release((IPicture *)This);
 }
 
 /************************************************************************
@@ -814,9 +985,9 @@ static ULONG WINAPI OLEPictureImpl_IPersistStream_Release(
 static HRESULT WINAPI OLEPictureImpl_GetClassID(
   IPersistStream* iface,CLSID* pClassID)
 {
-  ICOM_THIS_From_IPersistStream(IPicture, iface);
-  FIXME("(%p),stub!\n",This);
-  return E_NOTIMPL;
+  TRACE("(%p)\n", pClassID);
+  *pClassID = CLSID_StdPicture;
+  return S_OK;
 }
 
 /************************************************************************
@@ -825,12 +996,12 @@ static HRESULT WINAPI OLEPictureImpl_GetClassID(
 static HRESULT WINAPI OLEPictureImpl_IsDirty(
   IPersistStream* iface)
 {
-  ICOM_THIS_From_IPersistStream(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IPersistStream(iface);
   FIXME("(%p),stub!\n",This);
   return E_NOTIMPL;
 }
 
-#ifdef HAVE_JPEGLIB_H
+#ifdef SONAME_LIBJPEG
 
 static void *libjpeg_handle;
 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
@@ -868,7 +1039,7 @@ static void *load_libjpeg(void)
 /* for the jpeg decompressor source manager. */
 static void _jpeg_init_source(j_decompress_ptr cinfo) { }
 
-static boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
+static jpeg_boolean _jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
     ERR("(), should not get here.\n");
     return FALSE;
 }
@@ -879,21 +1050,12 @@ static void _jpeg_skip_input_data(j_decompress_ptr cinfo,long num_bytes) {
     cinfo->src->bytes_in_buffer -= num_bytes;
 }
 
-static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
+static jpeg_boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) {
     ERR("(desired=%d), should not get here.\n",desired);
     return FALSE;
 }
 static void _jpeg_term_source(j_decompress_ptr cinfo) { }
-#endif /* HAVE_JPEGLIB_H */
-
-#ifdef HAVE_GIF_LIB_H
-
-static void *libungif_handle;
-#define MAKE_FUNCPTR(f) static typeof(f) * p##f
-MAKE_FUNCPTR(DGifOpen);
-MAKE_FUNCPTR(DGifSlurp);
-MAKE_FUNCPTR(DGifCloseFile);
-#undef MAKE_FUNCPTR
+#endif /* SONAME_LIBJPEG */
 
 struct gifdata {
     unsigned char *data;
@@ -901,29 +1063,11 @@ struct gifdata {
     unsigned int len;
 };
 
-static void *load_libungif(void)
-{
-    if((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) {
-
-#define LOAD_FUNCPTR(f) \
-    if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \
-        libungif_handle = NULL; \
-        return NULL; \
-    }
-
-        LOAD_FUNCPTR(DGifOpen);
-        LOAD_FUNCPTR(DGifSlurp);
-        LOAD_FUNCPTR(DGifCloseFile);
-#undef LOAD_FUNCPTR
-    }
-    return libungif_handle;
-}
-
 static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
     struct gifdata *gd = (struct gifdata*)gif->UserData;
 
     if (len+gd->curoff > gd->len) {
-        FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
+        ERR("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
         len = gd->len - gd->curoff;
     }
     memcpy(data, gd->data+gd->curoff, len);
@@ -931,82 +1075,9 @@ static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
     return len;
 }
 
-#endif  /* HAVE_GIF_LIB_H */
-
-/************************************************************************
- * OLEPictureImpl_IPersistStream_Load (IUnknown)
- *
- * Loads the binary data from the IStream. Starts at current position.
- * There appears to be an 2 DWORD header:
- *     DWORD magic;
- *     DWORD len;
- *
- * Currently implemented: BITMAP, ICON, JPEG, GIF
- */
-static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
-  HRESULT      hr = E_FAIL;
-  ULONG                xread;
-  BYTE                 *xbuf;
-  DWORD                header[2];
-  WORD         magic;
-  STATSTG       statstg;
-  ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
-  
-  TRACE("(%p,%p)\n",This,pStm);
 
-  /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
-   * out whether we do.
-   *
-   * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
-   * compound file. This may explain most, if not all, of the cases of "no header",
-   * and the header validation should take this into account. At least in Visual Basic 6,
-   * resource streams, valid headers are
-   *    header[0] == "lt\0\0",
-   *    header[1] == length_of_stream.
-   */
-  hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
-  if (hr)
-    FIXME("Stat failed with hres %lx\n",hr);
-  hr=IStream_Read(pStm,header,8,&xread);
-  if (hr || xread!=8) {
-      FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
-      return hr;
-  }
-  if (!memcmp(&(header[0]), "GIF8",     4) ||   /* GIF header */
-      !memcmp(&(header[0]), "BM",       2) ||   /* BMP header */
-      !memcmp(&(header[0]), "\xff\xd8", 2) ||   /* JPEG header */
-      header[1] > statstg.cbSize.QuadPart || (header[1]==0)) {/* Incorrect header, assume none. */
-    xread = 8;
-    xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,statstg.cbSize.QuadPart);
-    memcpy(xbuf,&header,8);
-    This->datalen = statstg.cbSize.QuadPart;
-    while (xread < This->datalen) {
-      ULONG nread;
-      hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
-      xread+=nread;
-      if (hr || !nread)
-       break;
-    }
-    if (xread != This->datalen)
-      FIXME("Could only read %ld of %d bytes in no-header case?\n",xread,This->datalen);
-  } else {
-    xread = 0;
-    xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
-    This->datalen = header[1];
-    while (xread < header[1]) {
-      ULONG nread;
-      hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
-      xread+=nread;
-      if (hr || !nread)
-       break;
-    }
-    if (xread != header[1])
-      FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
-  }
-  magic = xbuf[0] + (xbuf[1]<<8);
-  switch (magic) {
-  case 0x4947: { /* GIF */
-#ifdef HAVE_GIF_LIB_H
+static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
+{
     struct gifdata     gd;
     GifFileType        *gif;
     BITMAPINFO         *bmi;
@@ -1020,27 +1091,20 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
     ExtensionBlock      *eb;
     int                 padding;
 
-    if(!libungif_handle) {
-        if(!load_libungif()) {
-            FIXME("Failed reading GIF because unable to find %s\n", SONAME_LIBUNGIF);
-            return E_FAIL;
-        }
-    }
-
     gd.data   = xbuf;
     gd.curoff = 0;
     gd.len    = xread;
-    gif = pDGifOpen((void*)&gd, _gif_inputfunc);
-    ret = pDGifSlurp(gif);
+    gif = DGifOpen((void*)&gd, _gif_inputfunc);
+    ret = DGifSlurp(gif);
     if (ret == GIF_ERROR) {
-      FIXME("Failed reading GIF using libgif.\n");
+      ERR("Failed reading GIF using libgif.\n");
       return E_FAIL;
     }
     TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
     TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
     TRACE("imgcnt %d\n", gif->ImageCount);
     if (gif->ImageCount<1) {
-      FIXME("GIF stream does not have images inside?\n");
+      ERR("GIF stream does not have images inside?\n");
       return E_FAIL;
     }
     TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
@@ -1050,24 +1114,24 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
     );
     /* */
     padding = (gif->SWidth+3) & ~3;
-    bmi  = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(1<<gif->SColorResolution)*sizeof(RGBQUAD));
-    bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
     si   = gif->SavedImages+0;
     gid  = &(si->ImageDesc);
     cm   = gid->ColorMap;
     if (!cm) cm = gif->SColorMap;
+    bmi  = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
+    bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
     
     /* look for the transparent color extension */
     for (i = 0; i < si->ExtensionBlockCount; ++i) {
        eb = si->ExtensionBlocks + i;
        if (eb->Function == 0xF9 && eb->ByteCount == 4) {
            if ((eb->Bytes[0] & 1) == 1) {
-               transparent = eb->Bytes[3];
+               transparent = (unsigned char)eb->Bytes[3];
            }
        }
     }
 
-    for (i=0;i<(1<<gif->SColorResolution);i++) {
+    for (i = 0; i < cm->ColorCount; i++) {
       bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
       bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
       bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
@@ -1078,10 +1142,32 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
       }
     }
 
-    /* Map to in picture coordinates */    
-    for (i=0;i<gid->Height;i++) 
-       for (j=0;j<gid->Width;j++) 
-           bytes[(gid->Top+i)*(padding)+gid->Left+j]=si->RasterBits[i*gid->Width+j];
+    /* Map to in picture coordinates */
+    for (i = 0, j = 0; i < gid->Height; i++) {
+        if (gif->Image.Interlace) {
+            memcpy(
+                bytes + (gid->Top + j) * padding + gid->Left,
+                si->RasterBits + i * gid->Width,
+                gid->Width);
+
+            /* Lower bits of interlaced counter encode current interlace */
+            if (j & 1) j += 2;      /* Currently filling odd rows */
+            else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */
+            else j += 8;            /* Currently filling every 8th row or 4th row in-between */
+
+            if (j >= gid->Height && i < gid->Height && (j & 1) == 0) {
+                /* End of current interlace, go to next interlace */
+                if (j & 2) j = 1;       /* Next iteration fills odd rows */
+                else if (j & 4) j = 2;  /* Next iteration fills even rows not mod 4 and not mod 8 */
+                else j = 4;             /* Next iteration fills rows in-between rows mod 6 */
+            }
+        } else {
+            memcpy(
+                bytes + (gid->Top + i) * padding + gid->Left,
+                si->RasterBits + i * gid->Width,
+                gid->Width);
+        }
+    }
 
     bmi->bmiHeader.biSize              = sizeof(BITMAPINFOHEADER);
     bmi->bmiHeader.biWidth             = gif->SWidth;
@@ -1092,7 +1178,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
     bmi->bmiHeader.biSizeImage         = padding*gif->SHeight;
     bmi->bmiHeader.biXPelsPerMeter     = 0;
     bmi->bmiHeader.biYPelsPerMeter     = 0;
-    bmi->bmiHeader.biClrUsed           = 1 << gif->SColorResolution;
+    bmi->bmiHeader.biClrUsed           = cm->ColorCount;
     bmi->bmiHeader.biClrImportant      = 0;
 
     hdcref = GetDC(0);
@@ -1112,15 +1198,60 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
        HBITMAP hOldbitmap; 
        HBITMAP hOldbitmapmask;
 
-       This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
-
-       hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap); 
+        unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
+        HBITMAP hTempMask;
+
+        This->hbmXor = CreateDIBitmap(
+            hdcref,
+            &bmi->bmiHeader,
+            CBM_INIT,
+            bytes,
+            bmi,
+            DIB_RGB_COLORS
+        );
+
+        bmi->bmiColors[0].rgbRed = 0;
+        bmi->bmiColors[0].rgbGreen = 0;
+        bmi->bmiColors[0].rgbBlue = 0;
+        bmi->bmiColors[1].rgbRed = 255;
+        bmi->bmiColors[1].rgbGreen = 255;
+        bmi->bmiColors[1].rgbBlue = 255;
+
+        bmi->bmiHeader.biBitCount              = 1;
+        bmi->bmiHeader.biSizeImage             = monopadding*gif->SHeight;
+        bmi->bmiHeader.biClrUsed               = 2;
+
+        for (i = 0; i < gif->SHeight; i++) {
+            unsigned char * colorPointer = bytes + padding * i;
+            unsigned char * monoPointer = bytes + monopadding * i;
+            for (j = 0; j < gif->SWidth; j++) {
+                unsigned char pixel = colorPointer[j];
+                if ((j & 7) == 0) monoPointer[j >> 3] = 0;
+                if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
+            }
+        }
+        hdcref = GetDC(0);
+        hTempMask = CreateDIBitmap(
+                hdcref,
+                &bmi->bmiHeader,
+                CBM_INIT,
+                bytes,
+                bmi,
+                DIB_RGB_COLORS
+        );
+        DeleteDC(hdcref);
+
+        bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
+        This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
+       hOldbitmap = SelectObject(hdc, hTempMask);
        hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
-       SetBkColor(hdc, This->rgbTrans);
+
+        SetBkColor(hdc, RGB(255, 255, 255));
        BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
 
        /* We no longer need the original bitmap, so we apply the first
           transformation with the mask to speed up the rendering */
+        SelectObject(hdc, This->hbmXor);
        SetBkColor(hdc, RGB(0,0,0));
        SetTextColor(hdc, RGB(255,255,255));
        BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 
@@ -1130,23 +1261,22 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
        SelectObject(hdcMask, hOldbitmapmask);
        DeleteDC(hdcMask);
        DeleteDC(hdc);
+        DeleteObject(hTempMask);
     }
     
     DeleteDC(hdcref);
     This->desc.picType = PICTYPE_BITMAP;
     OLEPictureImpl_SetBitmap(This);
-    pDGifCloseFile(gif);
+    DGifCloseFile(gif);
+    HeapFree(GetProcessHeap(),0,bmi);
     HeapFree(GetProcessHeap(),0,bytes);
     return S_OK;
-#else
-    FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
-    return E_FAIL;
-#endif
-    break;
-  }
-  case 0xd8ff: { /* JPEG */
-#ifdef HAVE_JPEGLIB_H
-    struct jpeg_decompress_struct      jd;
+}
+
+static HRESULT OLEPictureImpl_LoadJpeg(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
+{
+#ifdef SONAME_LIBJPEG
+    struct jpeg_decompress_struct      jd;
     struct jpeg_error_mgr              jerr;
     int                                        ret;
     JDIMENSION                         x;
@@ -1156,11 +1286,11 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
     HDC                                        hdcref;
     struct jpeg_source_mgr             xjsm;
     LPBYTE                              oldbits;
-    int i;
+    unsigned int i;
 
     if(!libjpeg_handle) {
         if(!load_libjpeg()) {
-            FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
+            ERR("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG);
             return E_FAIL;
         }
     }
@@ -1179,7 +1309,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
     jd.err = pjpeg_std_error(&jerr);
     /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h
      * jpeg_create_decompress(&jd); */
-    pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct));
+    pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, sizeof(struct jpeg_decompress_struct));
     jd.src = &xjsm;
     ret=pjpeg_read_header(&jd,TRUE);
     jd.out_color_space = JCS_RGB;
@@ -1199,7 +1329,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
     while ( jd.output_scanline<jd.output_height ) {
       x = pjpeg_read_scanlines(&jd,&samprow,1);
       if (x != 1) {
-       FIXME("failed to read current scanline?\n");
+       ERR("failed to read current scanline?\n");
        break;
       }
       /* We have to convert from RGB to BGR, see MSDN/ BITMAPINFOHEADER */
@@ -1240,15 +1370,16 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
     DeleteDC(hdcref);
     This->desc.picType = PICTYPE_BITMAP;
     OLEPictureImpl_SetBitmap(This);
-    hr = S_OK;
     HeapFree(GetProcessHeap(),0,bits);
+    return S_OK;
 #else
     ERR("Trying to load JPEG picture, but JPEG supported not compiled in.\n");
-    hr = E_FAIL;
+    return E_FAIL;
 #endif
-    break;
-  }
-  case 0x4d42: { /* Bitmap */
+}
+
+static HRESULT OLEPictureImpl_LoadDIB(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
+{
     BITMAPFILEHEADER   *bfh = (BITMAPFILEHEADER*)xbuf;
     BITMAPINFO         *bi = (BITMAPINFO*)(bfh+1);
     HDC                        hdcref;
@@ -1263,15 +1394,270 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
        CBM_INIT,
        xbuf+bfh->bfOffBits,
        bi,
-       (bi->bmiHeader.biBitCount<=8)?DIB_PAL_COLORS:DIB_RGB_COLORS
+       DIB_RGB_COLORS
     );
     DeleteDC(hdcref);
+    if (This->desc.u.bmp.hbitmap == 0)
+        return E_FAIL;
     This->desc.picType = PICTYPE_BITMAP;
     OLEPictureImpl_SetBitmap(This);
-    hr = S_OK;
-    break;
-  }
-  case 0x0000: { /* ICON , first word is dwReserved */
+    return S_OK;
+}
+
+/*****************************************************
+*   start of PNG-specific code
+*   currently only supports colortype PNG_COLOR_TYPE_RGB
+*/
+#ifdef SONAME_LIBPNG
+typedef struct{
+    ULONG position;
+    ULONG size;
+    BYTE * buff;
+} png_io;
+
+static void png_stream_read_data(png_structp png_ptr, png_bytep data,
+    png_size_t length)
+{
+    png_io * io_ptr = png_ptr->io_ptr;
+
+    if(length + io_ptr->position > io_ptr->size){
+        length = io_ptr->size - io_ptr->position;
+    }
+
+    memcpy(data, io_ptr->buff + io_ptr->position, length);
+
+    io_ptr->position += length;
+}
+
+static void *libpng_handle;
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(png_create_read_struct);
+MAKE_FUNCPTR(png_create_info_struct);
+MAKE_FUNCPTR(png_set_read_fn);
+MAKE_FUNCPTR(png_read_info);
+MAKE_FUNCPTR(png_read_image);
+MAKE_FUNCPTR(png_get_rowbytes);
+MAKE_FUNCPTR(png_set_bgr);
+MAKE_FUNCPTR(png_destroy_read_struct);
+MAKE_FUNCPTR(png_set_palette_to_rgb);
+MAKE_FUNCPTR(png_read_update_info);
+MAKE_FUNCPTR(png_get_tRNS);
+MAKE_FUNCPTR(png_get_PLTE);
+MAKE_FUNCPTR(png_set_expand);
+#undef MAKE_FUNCPTR
+
+static void *load_libpng(void)
+{
+    if((libpng_handle = wine_dlopen(SONAME_LIBPNG, RTLD_NOW, NULL, 0)) != NULL) {
+
+#define LOAD_FUNCPTR(f) \
+    if((p##f = wine_dlsym(libpng_handle, #f, NULL, 0)) == NULL) { \
+        libpng_handle = NULL; \
+        return NULL; \
+    }
+        LOAD_FUNCPTR(png_create_read_struct);
+        LOAD_FUNCPTR(png_create_info_struct);
+        LOAD_FUNCPTR(png_set_read_fn);
+        LOAD_FUNCPTR(png_read_info);
+        LOAD_FUNCPTR(png_read_image);
+        LOAD_FUNCPTR(png_get_rowbytes);
+        LOAD_FUNCPTR(png_set_bgr);
+        LOAD_FUNCPTR(png_destroy_read_struct);
+        LOAD_FUNCPTR(png_set_palette_to_rgb);
+        LOAD_FUNCPTR(png_read_update_info);
+        LOAD_FUNCPTR(png_get_tRNS);
+        LOAD_FUNCPTR(png_get_PLTE);
+        LOAD_FUNCPTR(png_set_expand);
+
+#undef LOAD_FUNCPTR
+    }
+    return libpng_handle;
+}
+#endif /* SONAME_LIBPNG */
+
+static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
+{
+#ifdef SONAME_LIBPNG
+    png_io              io;
+    png_structp         png_ptr = NULL;
+    png_infop           info_ptr = NULL;
+    INT                 row, rowsize, height, width, num_trans, i, j;
+    png_bytep*          row_pointers = NULL;
+    png_bytep           pngdata = NULL;
+    BITMAPINFOHEADER    bmi;
+    HDC                 hdcref = NULL, hdcXor, hdcMask;
+    HRESULT             ret;
+    BOOL                transparency;
+    png_bytep           trans;
+    png_color_16p       trans_values;
+    COLORREF            white = RGB(255, 255, 255), black = RGB(0, 0, 0);
+    HBITMAP             hbmoldXor, hbmoldMask, temp;
+
+    if(!libpng_handle) {
+        if(!load_libpng()) {
+            ERR("Failed reading PNG because unable to find %s\n",SONAME_LIBPNG);
+            return E_FAIL;
+        }
+    }
+
+    io.size     = xread;
+    io.position = 0;
+    io.buff     = xbuf;
+
+    png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING,
+        NULL, NULL, NULL);
+
+    if(setjmp(png_jmpbuf(png_ptr))){
+        TRACE("Error in libpng\n");
+        ret = E_FAIL;
+        goto end;
+    }
+
+    info_ptr = ppng_create_info_struct(png_ptr);
+    ppng_set_read_fn(png_ptr, &io, png_stream_read_data);
+    ppng_read_info(png_ptr, info_ptr);
+
+    if(!(png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
+         png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
+         png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)){
+        FIXME("Unsupported .PNG type: %d\n", png_ptr->color_type);
+        ret = E_FAIL;
+        goto end;
+    }
+
+    transparency = (ppng_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values)
+                       == PNG_INFO_tRNS);
+
+    /* sets format from anything to RGBA */
+    ppng_set_expand(png_ptr);
+    /* sets format to BGRA */
+    ppng_set_bgr(png_ptr);
+
+    ppng_read_update_info(png_ptr, info_ptr);
+
+    rowsize = ppng_get_rowbytes(png_ptr, info_ptr);
+    /* align rowsize to 4-byte boundary */
+    rowsize = (rowsize + 3) & ~3;
+    height = info_ptr->height;
+    width = info_ptr->width;
+
+    pngdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, height * rowsize);
+    row_pointers = HeapAlloc(GetProcessHeap(), 0, height * (sizeof(VOID *)));
+
+    if(!pngdata || !row_pointers){
+        ret = E_FAIL;
+        goto end;
+    }
+
+    for (row = 0; row < height; row++){
+        row_pointers[row] = pngdata + row * rowsize;
+    }
+
+    ppng_read_image(png_ptr, row_pointers);
+
+    bmi.biSize          = sizeof(bmi);
+    bmi.biWidth         = width;
+    bmi.biHeight        = -height;
+    bmi.biPlanes        = 1;
+    bmi.biBitCount      = info_ptr->channels * 8;
+    bmi.biCompression   = BI_RGB;
+    bmi.biSizeImage     = height * rowsize;
+    bmi.biXPelsPerMeter = 0;
+    bmi.biYPelsPerMeter = 0;
+    bmi.biClrUsed       = 0;
+    bmi.biClrImportant  = 0;
+
+    hdcref = GetDC(0);
+    This->desc.u.bmp.hbitmap = CreateDIBitmap(
+        hdcref,
+        &bmi,
+        CBM_INIT,
+        pngdata,
+        (BITMAPINFO*)&bmi,
+        DIB_RGB_COLORS
+    );
+
+    /* only fully-transparent alpha is handled */
+    if((info_ptr->channels != 4) || !transparency){
+        ReleaseDC(0, hdcref);
+        goto succ;
+    }
+
+    This->hbmXor = CreateDIBitmap(
+        hdcref,
+        &bmi,
+        CBM_INIT,
+        pngdata,
+        (BITMAPINFO*)&bmi,
+        DIB_RGB_COLORS
+    );
+
+    /* set transparent pixels to black, all others to white */
+    for(i = 0; i < height; i++){
+        for(j = 3; j < rowsize; j += 4){
+            if(row_pointers[i][j] == 0)
+                *((DWORD*)(&row_pointers[i][j - 3])) = black;
+            else
+                *((DWORD*)(&row_pointers[i][j - 3])) = white;
+        }
+    }
+
+    temp = CreateDIBitmap(
+        hdcref,
+        &bmi,
+        CBM_INIT,
+        pngdata,
+        (BITMAPINFO*)&bmi,
+        DIB_RGB_COLORS
+    );
+
+    ReleaseDC(0, hdcref);
+
+    This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
+    hdcXor = CreateCompatibleDC(NULL);
+    hdcMask = CreateCompatibleDC(NULL);
+
+    hbmoldXor = SelectObject(hdcXor,temp);
+    hbmoldMask = SelectObject(hdcMask,This->hbmMask);
+    SetBkColor(hdcXor,black);
+    BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
+
+    SelectObject(hdcXor,This->hbmXor);
+    DeleteObject(temp);
+
+    SetTextColor(hdcXor,white);
+    SetBkColor(hdcXor,black);
+    BitBlt(hdcXor,0,0,width,height,hdcMask,0,0,SRCAND);
+
+    SelectObject(hdcXor,hbmoldXor);
+    SelectObject(hdcMask,hbmoldMask);
+
+    DeleteDC(hdcXor);
+    DeleteDC(hdcMask);
+
+succ:
+    This->desc.picType = PICTYPE_BITMAP;
+    OLEPictureImpl_SetBitmap(This);
+    ret = S_OK;
+
+end:
+    if(png_ptr)
+        ppng_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : NULL, NULL);
+    HeapFree(GetProcessHeap(), 0, row_pointers);
+    HeapFree(GetProcessHeap(), 0, pngdata);
+    return ret;
+#else /* SONAME_LIBPNG */
+    ERR("Trying to load PNG picture, but PNG supported not compiled in.\n");
+    return E_FAIL;
+#endif
+}
+
+/*****************************************************
+*   start of Icon-specific code
+*/
+
+static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
+{
     HICON hicon;
     CURSORICONFILEDIR  *cifd = (CURSORICONFILEDIR*)xbuf;
     HDC hdcRef;
@@ -1315,8 +1701,8 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
                0
     );
     if (!hicon) {
-       FIXME("CreateIcon failed.\n");
-       hr = E_FAIL;
+       ERR("CreateIcon failed.\n");
+       return E_FAIL;
     } else {
        This->desc.picType = PICTYPE_ICON;
        This->desc.u.icon.hicon = hicon;
@@ -1326,17 +1712,249 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
        This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX);
        This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY);
        DeleteDC(hdcRef);
-       hr = S_OK;
+       return S_OK;
     }
+}
+
+static HRESULT OLEPictureImpl_LoadEnhMetafile(OLEPictureImpl *This,
+                                              const BYTE *data, ULONG size)
+{
+    HENHMETAFILE hemf;
+    ENHMETAHEADER hdr;
+
+    hemf = SetEnhMetaFileBits(size, data);
+    if (!hemf) return E_FAIL;
+
+    GetEnhMetaFileHeader(hemf, sizeof(hdr), &hdr);
+
+    This->desc.picType = PICTYPE_ENHMETAFILE;
+    This->desc.u.emf.hemf = hemf;
+
+    This->origWidth = 0;
+    This->origHeight = 0;
+    This->himetricWidth = hdr.rclFrame.right - hdr.rclFrame.left;
+    This->himetricHeight = hdr.rclFrame.bottom - hdr.rclFrame.top;
+
+    return S_OK;
+}
+
+static HRESULT OLEPictureImpl_LoadAPM(OLEPictureImpl *This,
+                                      const BYTE *data, ULONG size)
+{
+    APM_HEADER *header = (APM_HEADER *)data;
+    HMETAFILE hmf;
+
+    if (size < sizeof(APM_HEADER))
+        return E_FAIL;
+    if (header->key != 0x9ac6cdd7)
+        return E_FAIL;
+
+    /* SetMetaFileBitsEx performs data check on its own */
+    hmf = SetMetaFileBitsEx(size - sizeof(*header), data + sizeof(*header));
+    if (!hmf) return E_FAIL;
+
+    This->desc.picType = PICTYPE_METAFILE;
+    This->desc.u.wmf.hmeta = hmf;
+    This->desc.u.wmf.xExt = 0;
+    This->desc.u.wmf.yExt = 0;
+
+    This->origWidth = 0;
+    This->origHeight = 0;
+    This->himetricWidth = MulDiv((INT)header->right - header->left, 2540, header->inch);
+    This->himetricHeight = MulDiv((INT)header->bottom - header->top, 2540, header->inch);
+    return S_OK;
+}
+
+/************************************************************************
+ * BITMAP FORMAT FLAGS -
+ *   Flags that differentiate between different types of bitmaps.
+ */
+
+#define BITMAP_FORMAT_BMP   0x4d42 /* "BM" */
+#define BITMAP_FORMAT_JPEG  0xd8ff
+#define BITMAP_FORMAT_GIF   0x4947
+#define BITMAP_FORMAT_PNG   0x5089
+#define BITMAP_FORMAT_APM   0xcdd7
+
+/************************************************************************
+ * OLEPictureImpl_IPersistStream_Load (IUnknown)
+ *
+ * Loads the binary data from the IStream. Starts at current position.
+ * There appears to be an 2 DWORD header:
+ *     DWORD magic;
+ *     DWORD len;
+ *
+ * Currently implemented: BITMAP, ICON, JPEG, GIF, WMF, EMF
+ */
+static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
+  HRESULT      hr = E_FAIL;
+  BOOL         headerisdata = FALSE;
+  BOOL         statfailed = FALSE;
+  ULONG                xread, toread;
+  ULONG        headerread;
+  BYTE                 *xbuf;
+  DWORD                header[2];
+  WORD         magic;
+  STATSTG       statstg;
+  OLEPictureImpl *This = impl_from_IPersistStream(iface);
+  
+  TRACE("(%p,%p)\n",This,pStm);
+
+  /****************************************************************************************
+   * Part 1: Load the data
+   */
+  /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
+   * out whether we do.
+   *
+   * UPDATE: the IStream can be mapped to a plain file instead of a stream in a
+   * compound file. This may explain most, if not all, of the cases of "no
+   * header", and the header validation should take this into account.
+   * At least in Visual Basic 6, resource streams, valid headers are
+   *    header[0] == "lt\0\0",
+   *    header[1] == length_of_stream.
+   *
+   * Also handle streams where we do not have a working "Stat" method by
+   * reading all data until the end of the stream.
+   */
+  hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
+  if (hr) {
+      TRACE("stat failed with hres %x, proceeding to read all data.\n",hr);
+      statfailed = TRUE;
+      /* we will read at least 8 byte ... just right below */
+      statstg.cbSize.QuadPart = 8;
+  }
+
+  toread = 0;
+  headerread = 0;
+  headerisdata = FALSE;
+  do {
+      hr=IStream_Read(pStm,header,8,&xread);
+      if (hr || xread!=8) {
+          ERR("Failure while reading picture header (hr is %x, nread is %d).\n",hr,xread);
+          return (hr?hr:E_FAIL);
+      }
+      headerread += xread;
+      xread = 0;
+      
+      if (!memcmp(&(header[0]),"lt\0\0", 4) && (statfailed || (header[1] + headerread <= statstg.cbSize.QuadPart))) {
+          if (toread != 0 && toread != header[1]) 
+              FIXME("varying lengths of image data (prev=%u curr=%u), only last one will be used\n",
+                  toread, header[1]);
+          toread = header[1];
+          if (toread == 0) break;
+      } else {
+          if (!memcmp(&(header[0]), "GIF8",     4) ||   /* GIF header */
+              !memcmp(&(header[0]), "BM",       2) ||   /* BMP header */
+              !memcmp(&(header[0]), "\xff\xd8", 2) ||   /* JPEG header */
+              (header[0] == EMR_HEADER)            ||   /* EMF header */
+              (header[1] > statstg.cbSize.QuadPart)||   /* invalid size */
+              (header[1]==0)
+          ) {/* Found start of bitmap data */
+              headerisdata = TRUE;
+              if (toread == 0) 
+                 toread = statstg.cbSize.QuadPart-8;
+              else toread -= 8;
+              xread = 8;
+          } else {
+              FIXME("Unknown stream header magic: %08x\n", header[0]);
+              toread = header[1];
+          }
+      }
+  } while (!headerisdata);
+
+  if (statfailed) { /* we don't know the size ... read all we get */
+      int sizeinc = 4096;
+      int origsize = sizeinc;
+      ULONG nread = 42;
+
+      TRACE("Reading all data from stream.\n");
+      xbuf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, origsize);
+      if (headerisdata)
+          memcpy (xbuf, header, 8);
+      while (1) {
+          while (xread < origsize) {
+              hr = IStream_Read(pStm,xbuf+xread,origsize-xread,&nread);
+              xread+=nread;
+              if (hr || !nread)
+                  break;
+          }
+          if (!nread || hr) /* done, or error */
+              break;
+          if (xread == origsize) {
+              origsize += sizeinc;
+              sizeinc = 2*sizeinc; /* exponential increase */
+              xbuf = HeapReAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, xbuf, origsize);
+          }
+      }
+      if (hr)
+          TRACE("hr in no-stat loader case is %08x\n", hr);
+      TRACE("loaded %d bytes.\n", xread);
+      This->datalen = xread;
+      This->data    = xbuf;
+  } else {
+      This->datalen = toread+(headerisdata?8:0);
+      xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
+      if (!xbuf)
+          return E_OUTOFMEMORY;
+
+      if (headerisdata)
+          memcpy (xbuf, header, 8);
+
+      while (xread < This->datalen) {
+          ULONG nread;
+          hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
+          xread+=nread;
+          if (hr || !nread)
+              break;
+      }
+      if (xread != This->datalen)
+          ERR("Could only read %d of %d bytes out of stream?\n",xread,This->datalen);
+  }
+  if (This->datalen == 0) { /* Marks the "NONE" picture */
+      This->desc.picType = PICTYPE_NONE;
+      return S_OK;
+  }
+
+
+  /****************************************************************************************
+   * Part 2: Process the loaded data
+   */
+
+  magic = xbuf[0] + (xbuf[1]<<8);
+  This->loadtime_format = magic;
+
+  switch (magic) {
+  case BITMAP_FORMAT_GIF: /* GIF */
+    hr = OLEPictureImpl_LoadGif(This, xbuf, xread);
+    break;
+  case BITMAP_FORMAT_JPEG: /* JPEG */
+    hr = OLEPictureImpl_LoadJpeg(This, xbuf, xread);
+    break;
+  case BITMAP_FORMAT_BMP: /* Bitmap */
+    hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
+    break;
+  case BITMAP_FORMAT_PNG: /* PNG */
+    hr = OLEPictureImpl_LoadPNG(This, xbuf, xread);
+    break;
+  case BITMAP_FORMAT_APM: /* APM */
+    hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
+    break;
+  case 0x0000: { /* ICON , first word is dwReserved */
+    hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
     break;
   }
   default:
   {
-    int i;
-    FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
+    unsigned int i;
+
+    /* let's see if it's a EMF */
+    hr = OLEPictureImpl_LoadEnhMetafile(This, xbuf, xread);
+    if (hr == S_OK) break;
+
+    FIXME("Unknown magic %04x, %d read bytes:\n",magic,xread);
     hr=E_FAIL;
     for (i=0;i<xread+8;i++) {
-       if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
+       if (i<8) MESSAGE("%02x ",((unsigned char*)header)[i]);
        else MESSAGE("%02x ",xbuf[i-8]);
         if (i % 10 == 9) MESSAGE("\n");
     }
@@ -1344,6 +1962,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
     break;
   }
   }
+  This->bIsDirty = FALSE;
 
   /* FIXME: this notify is not really documented */
   if (hr==S_OK)
@@ -1351,25 +1970,337 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
   return hr;
 }
 
+static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength)
+{
+    int iSuccess = 0;
+    HDC hDC;
+    BITMAPINFO * pInfoBitmap;
+    int iNumPaletteEntries;
+    unsigned char * pPixelData;
+    BITMAPFILEHEADER * pFileHeader;
+    BITMAPINFO * pInfoHeader;
+
+    pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+        sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+
+    /* Find out bitmap size and padded length */
+    hDC = GetDC(0);
+    pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
+    GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
+
+    /* Fetch bitmap palette & pixel data */
+
+    pPixelData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pInfoBitmap->bmiHeader.biSizeImage);
+    GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS);
+
+    /* Calculate the total length required for the BMP data */
+    if (pInfoBitmap->bmiHeader.biClrUsed != 0) {
+       iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed;
+       if (iNumPaletteEntries > 256) iNumPaletteEntries = 256;
+    } else {
+       if (pInfoBitmap->bmiHeader.biBitCount <= 8)
+           iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount;
+       else
+           iNumPaletteEntries = 0;
+    }
+    *pLength =
+        sizeof(BITMAPFILEHEADER) +
+        sizeof(BITMAPINFOHEADER) +
+        iNumPaletteEntries * sizeof(RGBQUAD) +
+        pInfoBitmap->bmiHeader.biSizeImage;
+    *ppBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength);
+
+    /* Fill the BITMAPFILEHEADER */
+    pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer);
+    pFileHeader->bfType = BITMAP_FORMAT_BMP;
+    pFileHeader->bfSize = *pLength;
+    pFileHeader->bfOffBits =
+        sizeof(BITMAPFILEHEADER) +
+        sizeof(BITMAPINFOHEADER) +
+        iNumPaletteEntries * sizeof(RGBQUAD);
+
+    /* Fill the BITMAPINFOHEADER and the palette data */
+    pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER));
+    memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD));
+    memcpy(
+        (unsigned char *)(*ppBuffer) +
+            sizeof(BITMAPFILEHEADER) +
+            sizeof(BITMAPINFOHEADER) +
+            iNumPaletteEntries * sizeof(RGBQUAD),
+        pPixelData, pInfoBitmap->bmiHeader.biSizeImage);
+    iSuccess = 1;
+
+    HeapFree(GetProcessHeap(), 0, pPixelData);
+    HeapFree(GetProcessHeap(), 0, pInfoBitmap);
+    return iSuccess;
+}
+
+static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength)
+{
+       ICONINFO infoIcon;
+       int iSuccess = 0;
+
+       *ppBuffer = NULL; *pLength = 0;
+       if (GetIconInfo(hIcon, &infoIcon)) {
+               HDC hDC;
+               BITMAPINFO * pInfoBitmap;
+               unsigned char * pIconData = NULL;
+               unsigned int iDataSize = 0;
+
+        pInfoBitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+
+               /* Find out icon size */
+               hDC = GetDC(0);
+               pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
+               GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
+               if (1) {
+                       /* Auxiliary pointers */
+                       CURSORICONFILEDIR * pIconDir;
+                       CURSORICONFILEDIRENTRY * pIconEntry;
+                       BITMAPINFOHEADER * pIconBitmapHeader;
+                       unsigned int iOffsetPalette;
+                       unsigned int iOffsetColorData;
+                       unsigned int iOffsetMaskData;
+
+                       unsigned int iLengthScanLineColor;
+                       unsigned int iLengthScanLineMask;
+                       unsigned int iNumEntriesPalette;
+
+                       iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2;
+                       iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2;
+/*
+                       FIXME("DEBUG: bitmap size is %d x %d\n",
+                               pInfoBitmap->bmiHeader.biWidth,
+                               pInfoBitmap->bmiHeader.biHeight);
+                       FIXME("DEBUG: bitmap bpp is %d\n",
+                               pInfoBitmap->bmiHeader.biBitCount);
+                       FIXME("DEBUG: bitmap nplanes is %d\n",
+                               pInfoBitmap->bmiHeader.biPlanes);
+                       FIXME("DEBUG: bitmap biSizeImage is %u\n",
+                               pInfoBitmap->bmiHeader.biSizeImage);
+*/
+                       /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */
+                       iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER);
+                       pIconData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize);
+
+                       /* Fill out the CURSORICONFILEDIR */
+                       pIconDir = (CURSORICONFILEDIR *)pIconData;
+                       pIconDir->idType = 1;
+                       pIconDir->idCount = 1;
+
+                       /* Fill out the CURSORICONFILEDIRENTRY */
+                       pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
+                       pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth;
+                       pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight;
+                       pIconEntry->bColorCount =
+                               (pInfoBitmap->bmiHeader.biBitCount < 8)
+                               ? 1 << pInfoBitmap->bmiHeader.biBitCount
+                               : 0;
+                       pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes;
+                       pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount;
+                       pIconEntry->dwDIBSize = 0;
+                       pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY);
+
+                       /* Fill out the BITMAPINFOHEADER */
+                       pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
+                       *pIconBitmapHeader = pInfoBitmap->bmiHeader;
+
+                       /*      Find out whether a palette exists for the bitmap */
+                       if (    (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)
+                               ||      (pInfoBitmap->bmiHeader.biBitCount == 24)
+                               ||      (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) {
+                               iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed;
+                               if (iNumEntriesPalette > 256) iNumEntriesPalette = 256; 
+                       } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32)
+                               && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) {
+                               iNumEntriesPalette = 3;
+                       } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) {
+                               iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount;
+                       } else {
+                               iNumEntriesPalette = 0;
+                       }
+
+                       /*  Add bitmap size and header size to icon data size. */
+                       iOffsetPalette = iDataSize;
+                       iDataSize += iNumEntriesPalette * sizeof(DWORD);
+                       iOffsetColorData = iDataSize;
+                       iDataSize += pIconBitmapHeader->biSizeImage;
+                       iOffsetMaskData = iDataSize;
+                       iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask;
+                       pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask;
+                       pIconBitmapHeader->biHeight *= 2;
+                       pIconData = HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize);
+                       pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD));
+                       pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
+                       pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY));
+
+                       /* Get the actual bitmap data from the icon bitmap */
+                       GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight,
+                               pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS);
+                       if (iNumEntriesPalette > 0) {
+                               memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors,
+                                       iNumEntriesPalette * sizeof(RGBQUAD));
+                       }
+
+                       /* Reset all values so that GetDIBits call succeeds */
+                       memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData);
+                       memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+                       pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader);
+/*
+            if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS)
+                               && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight,
+                                       pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) {
+
+                printf("ERROR: unable to get bitmap mask (error %u)\n",
+                                       GetLastError());
+
+                       }
+*/
+            GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS);
+            GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS);
+
+                       /* Write out everything produced so far to the stream */
+                       *ppBuffer = pIconData; *pLength = iDataSize;
+                       iSuccess = 1;
+               } else {
+/*
+                       printf("ERROR: unable to get bitmap information via GetDIBits() (error %u)\n",
+                               GetLastError());
+*/
+               }
+               /*
+                       Remarks (from MSDN entry on GetIconInfo):
+
+                       GetIconInfo creates bitmaps for the hbmMask and hbmColor
+                       members of ICONINFO. The calling application must manage
+                       these bitmaps and delete them when they are no longer
+                       necessary.
+                */
+               if (hDC) ReleaseDC(0, hDC);
+               DeleteObject(infoIcon.hbmMask);
+               if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor);
+               HeapFree(GetProcessHeap(), 0, pInfoBitmap);
+       } else {
+               printf("ERROR: Unable to get icon information (error %u)\n",
+                       GetLastError());
+       }
+       return iSuccess;
+}
+
 static HRESULT WINAPI OLEPictureImpl_Save(
   IPersistStream* iface,IStream*pStm,BOOL fClearDirty)
 {
-  ICOM_THIS_From_IPersistStream(IPicture, iface);
-  FIXME("(%p,%p,%d),stub!\n",This,pStm,fClearDirty);
-  return E_NOTIMPL;
+    HRESULT hResult = E_NOTIMPL;
+    void * pIconData;
+    unsigned int iDataSize;
+    ULONG dummy;
+    int iSerializeResult = 0;
+    OLEPictureImpl *This = impl_from_IPersistStream(iface);
+
+    TRACE("%p %p %d\n", This, pStm, fClearDirty);
+
+    switch (This->desc.picType) {
+    case PICTYPE_ICON:
+        if (This->bIsDirty || !This->data) {
+            if (!serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) {
+                ERR("(%p,%p,%d), serializeIcon() failed\n", This, pStm, fClearDirty);
+                hResult = E_FAIL;
+                break;
+            }
+            HeapFree(GetProcessHeap(), 0, This->data);
+            This->data = pIconData;
+            This->datalen = iDataSize;
+        }
+        if (This->loadtime_magic != 0xdeadbeef) {
+            DWORD header[2];
+
+            header[0] = This->loadtime_magic;
+            header[1] = This->datalen;
+            IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
+        }
+        IStream_Write(pStm, This->data, This->datalen, &dummy);
+
+        hResult = S_OK;
+        break;
+    case PICTYPE_BITMAP:
+        if (This->bIsDirty) {
+            switch (This->keepOrigFormat ? This->loadtime_format : BITMAP_FORMAT_BMP) {
+            case BITMAP_FORMAT_BMP:
+                iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize);
+                break;
+            case BITMAP_FORMAT_JPEG:
+                FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty);
+                break;
+            case BITMAP_FORMAT_GIF:
+                FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
+                break;
+            case BITMAP_FORMAT_PNG:
+                FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
+                break;
+            default:
+                FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
+                break;
+            }
+            if (iSerializeResult) {
+                /*
+                if (This->loadtime_magic != 0xdeadbeef) {
+                */
+                if (1) {
+                    DWORD header[2];
+
+                    header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
+                    header[1] = iDataSize;
+                    IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
+                }
+                IStream_Write(pStm, pIconData, iDataSize, &dummy);
+
+                HeapFree(GetProcessHeap(), 0, This->data);
+                This->data = pIconData;
+                This->datalen = iDataSize;
+                hResult = S_OK;
+            }
+        } else {
+            /*
+            if (This->loadtime_magic != 0xdeadbeef) {
+            */
+            if (1) {
+                DWORD header[2];
+
+                header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c;
+                header[1] = This->datalen;
+                IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy);
+            }
+            IStream_Write(pStm, This->data, This->datalen, &dummy);
+            hResult = S_OK;
+        }
+        break;
+    case PICTYPE_METAFILE:
+        FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty);
+        break;
+    case PICTYPE_ENHMETAFILE:
+        FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty);
+        break;
+    default:
+        FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty);
+        break;
+    }
+    if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE;
+    return hResult;
 }
 
 static HRESULT WINAPI OLEPictureImpl_GetSizeMax(
   IPersistStream* iface,ULARGE_INTEGER*pcbSize)
 {
-  ICOM_THIS_From_IPersistStream(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IPersistStream(iface);
   FIXME("(%p,%p),stub!\n",This,pcbSize);
   return E_NOTIMPL;
 }
 
+
 /************************************************************************
  *    IDispatch
  */
+
 /************************************************************************
  * OLEPictureImpl_IDispatch_QueryInterface (IUnknown)
  *
@@ -1380,9 +2311,9 @@ static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
   REFIID     riid,
   VOID**     ppvoid)
 {
-  ICOM_THIS_From_IDispatch(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IDispatch(iface);
 
-  return IPicture_QueryInterface(This, riid, ppvoid);
+  return IPicture_QueryInterface((IPicture *)This, riid, ppvoid);
 }
 
 /************************************************************************
@@ -1393,9 +2324,9 @@ static HRESULT WINAPI OLEPictureImpl_IDispatch_QueryInterface(
 static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
   IDispatch* iface)
 {
-  ICOM_THIS_From_IDispatch(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IDispatch(iface);
 
-  return IPicture_AddRef(This);
+  return IPicture_AddRef((IPicture *)This);
 }
 
 /************************************************************************
@@ -1406,9 +2337,9 @@ static ULONG WINAPI OLEPictureImpl_IDispatch_AddRef(
 static ULONG WINAPI OLEPictureImpl_IDispatch_Release(
   IDispatch* iface)
 {
-  ICOM_THIS_From_IDispatch(IPicture, iface);
+  OLEPictureImpl *This = impl_from_IDispatch(iface);
 
-  return IPicture_Release(This);
+  return IPicture_Release((IPicture *)This);
 }
 
 /************************************************************************
@@ -1420,9 +2351,11 @@ static HRESULT WINAPI OLEPictureImpl_GetTypeInfoCount(
   IDispatch*    iface,
   unsigned int* pctinfo)
 {
-  FIXME("():Stub\n");
+  TRACE("(%p)\n", pctinfo);
 
-  return E_NOTIMPL;
+  *pctinfo = 1;
+
+  return S_OK;
 }
 
 /************************************************************************
@@ -1436,9 +2369,27 @@ static HRESULT WINAPI OLEPictureImpl_GetTypeInfo(
   LCID        lcid,
   ITypeInfo** ppTInfo)
 {
-  FIXME("():Stub\n");
+  static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
+  ITypeLib *tl;
+  HRESULT hres;
 
-  return E_NOTIMPL;
+  TRACE("(iTInfo=%d, lcid=%04x, %p)\n", iTInfo, (int)lcid, ppTInfo);
+
+  if (iTInfo != 0)
+    return E_FAIL;
+
+  hres = LoadTypeLib(stdole2tlb, &tl);
+  if (FAILED(hres))
+  {
+    ERR("Could not load stdole2.tlb\n");
+    return hres;
+  }
+
+  hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IPictureDisp, ppTInfo);
+  if (FAILED(hres))
+    ERR("Did not get IPictureDisp typeinfo from typelib, hres %x\n", hres);
+
+  return hres;
 }
 
 /************************************************************************
@@ -1454,9 +2405,33 @@ static HRESULT WINAPI OLEPictureImpl_GetIDsOfNames(
   LCID        lcid,
   DISPID*     rgDispId)
 {
-  FIXME("():Stub\n");
+  ITypeInfo * pTInfo;
+  HRESULT hres;
 
-  return E_NOTIMPL;
+  TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", iface, debugstr_guid(riid),
+        rgszNames, cNames, (int)lcid, rgDispId);
+
+  if (cNames == 0)
+  {
+    return E_INVALIDARG;
+  }
+  else
+  {
+    /* retrieve type information */
+    hres = OLEPictureImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
+
+    if (FAILED(hres))
+    {
+      ERR("GetTypeInfo failed.\n");
+      return hres;
+    }
+
+    /* convert names to DISPIDs */
+    hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
+    ITypeInfo_Release(pTInfo);
+
+    return hres;
+  }
 }
 
 /************************************************************************
@@ -1475,16 +2450,110 @@ static HRESULT WINAPI OLEPictureImpl_Invoke(
   EXCEPINFO*  pExepInfo,
   UINT*     puArgErr)
 {
-  FIXME("(dispid: %ld):Stub\n",dispIdMember);
+  OLEPictureImpl *This = impl_from_IDispatch(iface);
 
-  VariantInit(pVarResult);
-  V_VT(pVarResult) = VT_BOOL;
-  V_UNION(pVarResult,boolVal) = FALSE;
-  return S_OK;
+  /* validate parameters */
+
+  if (!IsEqualIID(riid, &IID_NULL))
+  {
+    ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
+    return DISP_E_UNKNOWNNAME;
+  }
+
+  if (!pDispParams)
+  {
+    ERR("null pDispParams not allowed\n");
+    return DISP_E_PARAMNOTOPTIONAL;
+  }
+
+  if (wFlags & DISPATCH_PROPERTYGET)
+  {
+    if (pDispParams->cArgs != 0)
+    {
+      ERR("param count for DISPATCH_PROPERTYGET was %d instead of 0\n", pDispParams->cArgs);
+      return DISP_E_BADPARAMCOUNT;
+    }
+    if (!pVarResult)
+    {
+      ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
+      return DISP_E_PARAMNOTOPTIONAL;
+    }
+  }
+  else if (wFlags & DISPATCH_PROPERTYPUT)
+  {
+    if (pDispParams->cArgs != 1)
+    {
+      ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
+      return DISP_E_BADPARAMCOUNT;
+    }
+  }
+
+  switch (dispIdMember)
+  {
+  case DISPID_PICT_HANDLE:
+    if (wFlags & DISPATCH_PROPERTYGET)
+    {
+      TRACE("DISPID_PICT_HANDLE\n");
+      V_VT(pVarResult) = VT_I4;
+      return IPicture_get_Handle((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
+    }
+    break;
+  case DISPID_PICT_HPAL:
+    if (wFlags & DISPATCH_PROPERTYGET)
+    {
+      TRACE("DISPID_PICT_HPAL\n");
+      V_VT(pVarResult) = VT_I4;
+      return IPicture_get_hPal((IPicture *)&This->lpVtbl, &V_UINT(pVarResult));
+    }
+    else if (wFlags & DISPATCH_PROPERTYPUT)
+    {
+      VARIANTARG vararg;
+      HRESULT hr;
+      TRACE("DISPID_PICT_HPAL\n");
+
+      VariantInit(&vararg);
+      hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I4);
+      if (FAILED(hr))
+        return hr;
+
+      hr = IPicture_set_hPal((IPicture *)&This->lpVtbl, V_I4(&vararg));
+
+      VariantClear(&vararg);
+      return hr;
+    }
+    break;
+  case DISPID_PICT_TYPE:
+    if (wFlags & DISPATCH_PROPERTYGET)
+    {
+      TRACE("DISPID_PICT_TYPE\n");
+      V_VT(pVarResult) = VT_I2;
+      return OLEPictureImpl_get_Type((IPicture *)&This->lpVtbl, &V_I2(pVarResult));
+    }
+    break;
+  case DISPID_PICT_WIDTH:
+    if (wFlags & DISPATCH_PROPERTYGET)
+    {
+      TRACE("DISPID_PICT_WIDTH\n");
+      V_VT(pVarResult) = VT_I4;
+      return IPicture_get_Width((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
+    }
+    break;
+  case DISPID_PICT_HEIGHT:
+    if (wFlags & DISPATCH_PROPERTYGET)
+    {
+      TRACE("DISPID_PICT_HEIGHT\n");
+      V_VT(pVarResult) = VT_I4;
+      return IPicture_get_Height((IPicture *)&This->lpVtbl, &V_I4(pVarResult));
+    }
+    break;
+  }
+
+  ERR("invalid dispid 0x%x or wFlags 0x%x\n", dispIdMember, wFlags);
+  return DISP_E_MEMBERNOTFOUND;
 }
 
 
-static IPictureVtbl OLEPictureImpl_VTable =
+static const IPictureVtbl OLEPictureImpl_VTable =
 {
   OLEPictureImpl_QueryInterface,
   OLEPictureImpl_AddRef,
@@ -1505,7 +2574,7 @@ static IPictureVtbl OLEPictureImpl_VTable =
   OLEPictureImpl_get_Attributes
 };
 
-static IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
+static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
 {
   OLEPictureImpl_IDispatch_QueryInterface,
   OLEPictureImpl_IDispatch_AddRef,
@@ -1516,7 +2585,7 @@ static IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
   OLEPictureImpl_Invoke
 };
 
-static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
+static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
 {
   OLEPictureImpl_IPersistStream_QueryInterface,
   OLEPictureImpl_IPersistStream_AddRef,
@@ -1528,7 +2597,7 @@ static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
   OLEPictureImpl_GetSizeMax
 };
 
-static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
+static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
 {
   OLEPictureImpl_IConnectionPointContainer_QueryInterface,
   OLEPictureImpl_IConnectionPointContainer_AddRef,
@@ -1546,7 +2615,7 @@ HRESULT WINAPI OleCreatePictureIndirect(LPPICTDESC lpPictDesc, REFIID riid,
   OLEPictureImpl* newPict = NULL;
   HRESULT      hr         = S_OK;
 
-  TRACE("(%p,%p,%d,%p)\n", lpPictDesc, riid, fOwn, ppvObj);
+  TRACE("(%p,%s,%d,%p)\n", lpPictDesc, debugstr_guid(riid), fOwn, ppvObj);
 
   /*
    * Sanity check
@@ -1589,7 +2658,7 @@ HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
   IPicture     *newpic;
   HRESULT hr;
 
-  TRACE("(%p,%ld,%d,%s,%p), partially implemented.\n",
+  TRACE("(%p,%d,%d,%s,%p), partially implemented.\n",
        lpstream, lSize, fRunmode, debugstr_guid(riid), ppvObj);
 
   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
@@ -1597,16 +2666,23 @@ HRESULT WINAPI OleLoadPicture( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
     return hr;
   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
   if (hr) {
-      FIXME("Could not get IPersistStream iface from Ole Picture?\n");
+      ERR("Could not get IPersistStream iface from Ole Picture?\n");
       IPicture_Release(newpic);
       *ppvObj = NULL;
       return hr;
   }
-  IPersistStream_Load(ps,lpstream);
+  hr = IPersistStream_Load(ps,lpstream);
   IPersistStream_Release(ps);
+  if (FAILED(hr))
+  {
+      ERR("IPersistStream_Load failed\n");
+      IPicture_Release(newpic);
+      *ppvObj = NULL;
+      return hr;
+  }
   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
   if (hr)
-      FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
+      ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
   IPicture_Release(newpic);
   return hr;
 }
@@ -1621,7 +2697,7 @@ HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
   IPicture     *newpic;
   HRESULT hr;
 
-  FIXME("(%p,%ld,%d,%s,x=%ld,y=%ld,f=%lx,%p), partially implemented.\n",
+  FIXME("(%p,%d,%d,%s,x=%d,y=%d,f=%x,%p), partially implemented.\n",
        lpstream, lSize, fRunmode, debugstr_guid(riid), xsiz, ysiz, flags, ppvObj);
 
   hr = OleCreatePictureIndirect(NULL,riid,!fRunmode,(LPVOID*)&newpic);
@@ -1629,28 +2705,142 @@ HRESULT WINAPI OleLoadPictureEx( LPSTREAM lpstream, LONG lSize, BOOL fRunmode,
     return hr;
   hr = IPicture_QueryInterface(newpic,&IID_IPersistStream, (LPVOID*)&ps);
   if (hr) {
-      FIXME("Could not get IPersistStream iface from Ole Picture?\n");
+      ERR("Could not get IPersistStream iface from Ole Picture?\n");
       IPicture_Release(newpic);
       *ppvObj = NULL;
       return hr;
   }
-  IPersistStream_Load(ps,lpstream);
+  hr = IPersistStream_Load(ps,lpstream);
   IPersistStream_Release(ps);
+  if (FAILED(hr))
+  {
+      ERR("IPersistStream_Load failed\n");
+      IPicture_Release(newpic);
+      *ppvObj = NULL;
+      return hr;
+  }
   hr = IPicture_QueryInterface(newpic,riid,ppvObj);
   if (hr)
-      FIXME("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
+      ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
   IPicture_Release(newpic);
   return hr;
 }
 
+/***********************************************************************
+ * OleLoadPicturePath (OLEAUT32.424)
+ */
+HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
+               DWORD dwReserved, OLE_COLOR clrReserved, REFIID riid,
+               LPVOID *ppvRet )
+{
+  static const WCHAR file[] = { 'f','i','l','e',':','/','/',0 };
+  IPicture *ipicture;
+  HANDLE hFile;
+  DWORD dwFileSize;
+  HGLOBAL hGlobal = NULL;
+  DWORD dwBytesRead = 0;
+  IStream *stream;
+  BOOL bRead;
+  IPersistStream *pStream;
+  HRESULT hRes;
+
+  TRACE("(%s,%p,%d,%08x,%s,%p): stub\n",
+        debugstr_w(szURLorPath), punkCaller, dwReserved, clrReserved,
+        debugstr_guid(riid), ppvRet);
+
+  if (!ppvRet) return E_POINTER;
+
+  if (strncmpW(szURLorPath, file, 7) == 0) {       
+      szURLorPath += 7;
+  
+      hFile = CreateFileW(szURLorPath, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+                                  0, NULL);
+      if (hFile == INVALID_HANDLE_VALUE)
+         return E_UNEXPECTED;
+
+      dwFileSize = GetFileSize(hFile, NULL);
+      if (dwFileSize != INVALID_FILE_SIZE )
+      {
+         hGlobal = GlobalAlloc(GMEM_FIXED,dwFileSize);
+         if ( hGlobal)
+         {
+             bRead = ReadFile(hFile, hGlobal, dwFileSize, &dwBytesRead, NULL);
+             if (!bRead)
+             {
+                 GlobalFree(hGlobal);
+                 hGlobal = 0;
+             }
+         }
+      }
+      CloseHandle(hFile);
+      
+      if (!hGlobal)
+         return E_UNEXPECTED;
+
+      hRes = CreateStreamOnHGlobal(hGlobal, TRUE, &stream);
+      if (FAILED(hRes)) 
+      {
+         GlobalFree(hGlobal);
+         return hRes;
+      }
+  } else {
+      IMoniker *pmnk;
+      IBindCtx *pbc;
+
+      hRes = CreateBindCtx(0, &pbc);
+      if (SUCCEEDED(hRes)) 
+      {
+         hRes = CreateURLMoniker(NULL, szURLorPath, &pmnk);
+         if (SUCCEEDED(hRes))
+         {              
+             hRes = IMoniker_BindToStorage(pmnk, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
+             IMoniker_Release(pmnk);
+         }
+         IBindCtx_Release(pbc);
+      }
+      if (FAILED(hRes))
+         return hRes;
+  }
+
+  hRes = CoCreateInstance(&CLSID_StdPicture, punkCaller, CLSCTX_INPROC_SERVER, 
+                  &IID_IPicture, (LPVOID*)&ipicture);
+  if (hRes != S_OK) {
+      IStream_Release(stream);
+      return hRes;
+  }
+  
+  hRes = IPicture_QueryInterface(ipicture, &IID_IPersistStream, (LPVOID*)&pStream);
+  if (hRes) {
+      IStream_Release(stream);
+      IPicture_Release(ipicture);
+      return hRes;
+  }
+
+  hRes = IPersistStream_Load(pStream, stream); 
+  IPersistStream_Release(pStream);
+  IStream_Release(stream);
+
+  if (hRes) {
+      IPicture_Release(ipicture);
+      return hRes;
+  }
+
+  hRes = IPicture_QueryInterface(ipicture,riid,ppvRet);
+  if (hRes)
+      ERR("Failed to get interface %s from IPicture.\n",debugstr_guid(riid));
+  
+  IPicture_Release(ipicture);
+  return hRes;
+}
+
 /*******************************************************************************
  * StdPic ClassFactory
  */
 typedef struct
 {
     /* IUnknown fields */
-    IClassFactoryVtbl          *lpVtbl;
-    DWORD                       ref;
+    const IClassFactoryVtbl    *lpVtbl;
+    LONG                        ref;
 } IClassFactoryImpl;
 
 static HRESULT WINAPI
@@ -1664,24 +2854,20 @@ SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
 static ULONG WINAPI
 SPCF_AddRef(LPCLASSFACTORY iface) {
        IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
-       return ++(This->ref);
+       return InterlockedIncrement(&This->ref);
 }
 
 static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) {
        IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
        /* static class, won't be  freed */
-       return --(This->ref);
+       return InterlockedDecrement(&This->ref);
 }
 
 static HRESULT WINAPI SPCF_CreateInstance(
        LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
 ) {
-       PICTDESC        pd;
-
-       FIXME("(%p,%p,%s,%p), creating stdpic with PICTYPE_NONE.\n",iface,pOuter,debugstr_guid(riid),ppobj);
-       pd.cbSizeofstruct = sizeof(pd);
-       pd.picType = PICTYPE_NONE;
-       return OleCreatePictureIndirect(&pd,riid,TRUE,ppobj);
+    /* Creates an uninitialized picture */
+    return OleCreatePictureIndirect(NULL,riid,TRUE,ppobj);
 
 }
 
@@ -1691,7 +2877,7 @@ static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
        return S_OK;
 }
 
-static IClassFactoryVtbl SPCF_Vtbl = {
+static const IClassFactoryVtbl SPCF_Vtbl = {
        SPCF_QueryInterface,
        SPCF_AddRef,
        SPCF_Release,