[SHELL32] CDrivesFolder: Implement the eject and disconnect menu items. CORE-13841
[reactos.git] / dll / win32 / windowscodecs / bmpencode.c
index b79a19b..5bc043a 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2009 Vincent Povirk for CodeWeavers
+ * Copyright 2016 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-
-#include <stdarg.h>
-
-#define COBJMACROS
-
-#include "windef.h"
-#include "winbase.h"
-#include "winreg.h"
-#include "wingdi.h"
-#include "objbase.h"
-#include "wincodec.h"
-
 #include "wincodecs_private.h"
 
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+#include <wingdi.h>
 
 struct bmp_pixelformat {
     const WICPixelFormatGUID *guid;
     UINT bpp;
+    UINT colors; /* palette size */
     DWORD compression;
     DWORD redmask;
     DWORD greenmask;
@@ -46,19 +33,24 @@ struct bmp_pixelformat {
 };
 
 static const struct bmp_pixelformat formats[] = {
-    {&GUID_WICPixelFormat24bppBGR, 24, BI_RGB},
-    {&GUID_WICPixelFormat16bppBGR555, 16, BI_RGB},
-    {&GUID_WICPixelFormat16bppBGR565, 16, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0},
-    {&GUID_WICPixelFormat32bppBGR, 32, BI_RGB},
+    {&GUID_WICPixelFormat24bppBGR, 24, 0, BI_RGB},
+    {&GUID_WICPixelFormatBlackWhite, 1, 2, BI_RGB},
+    {&GUID_WICPixelFormat1bppIndexed, 1, 2, BI_RGB},
+    {&GUID_WICPixelFormat2bppIndexed, 2, 4, BI_RGB},
+    {&GUID_WICPixelFormat4bppIndexed, 4, 16, BI_RGB},
+    {&GUID_WICPixelFormat8bppIndexed, 8, 256, BI_RGB},
+    {&GUID_WICPixelFormat16bppBGR555, 16, 0, BI_RGB},
+    {&GUID_WICPixelFormat16bppBGR565, 16, 0, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0},
+    {&GUID_WICPixelFormat32bppBGR, 32, 0, BI_RGB},
 #if 0
     /* Windows doesn't seem to support this one. */
-    {&GUID_WICPixelFormat32bppBGRA, 32, BI_BITFIELDS, 0xff0000, 0xff00, 0xff, 0xff000000},
+    {&GUID_WICPixelFormat32bppBGRA, 32, 0, BI_BITFIELDS, 0xff0000, 0xff00, 0xff, 0xff000000},
 #endif
     {NULL}
 };
 
 typedef struct BmpFrameEncode {
-    const IWICBitmapFrameEncodeVtbl *lpVtbl;
+    IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
     LONG ref;
     IStream *stream;
     BOOL initialized;
@@ -68,13 +60,20 @@ typedef struct BmpFrameEncode {
     double xres, yres;
     UINT lineswritten;
     UINT stride;
+    WICColor palette[256];
+    UINT colors;
     BOOL committed;
 } BmpFrameEncode;
 
+static inline BmpFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
+{
+    return CONTAINING_RECORD(iface, BmpFrameEncode, IWICBitmapFrameEncode_iface);
+}
+
 static HRESULT WINAPI BmpFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
     void **ppv)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
 
     if (!ppv) return E_INVALIDARG;
@@ -82,7 +81,7 @@ static HRESULT WINAPI BmpFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface
     if (IsEqualIID(&IID_IUnknown, iid) ||
         IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
     {
-        *ppv = This;
+        *ppv = &This->IWICBitmapFrameEncode_iface;
     }
     else
     {
@@ -96,7 +95,7 @@ static HRESULT WINAPI BmpFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface
 
 static ULONG WINAPI BmpFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     ULONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) refcount=%u\n", iface, ref);
@@ -106,7 +105,7 @@ static ULONG WINAPI BmpFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
 
 static ULONG WINAPI BmpFrameEncode_Release(IWICBitmapFrameEncode *iface)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) refcount=%u\n", iface, ref);
@@ -124,7 +123,7 @@ static ULONG WINAPI BmpFrameEncode_Release(IWICBitmapFrameEncode *iface)
 static HRESULT WINAPI BmpFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
     IPropertyBag2 *pIEncoderOptions)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     TRACE("(%p,%p)\n", iface, pIEncoderOptions);
 
     if (This->initialized) return WINCODEC_ERR_WRONGSTATE;
@@ -137,7 +136,7 @@ static HRESULT WINAPI BmpFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
 static HRESULT WINAPI BmpFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
     UINT uiWidth, UINT uiHeight)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
 
     if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
@@ -151,7 +150,7 @@ static HRESULT WINAPI BmpFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
 static HRESULT WINAPI BmpFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
     double dpiX, double dpiY)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
 
     if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
@@ -165,7 +164,7 @@ static HRESULT WINAPI BmpFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
 static HRESULT WINAPI BmpFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
     WICPixelFormatGUID *pPixelFormat)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     int i;
     TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
 
@@ -173,11 +172,13 @@ static HRESULT WINAPI BmpFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface
 
     for (i=0; formats[i].guid; i++)
     {
-        if (memcmp(formats[i].guid, pPixelFormat, sizeof(GUID)) == 0)
+        if (IsEqualGUID(formats[i].guid, pPixelFormat))
             break;
     }
 
     if (!formats[i].guid) i = 0;
+    else if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormatBlackWhite))
+        i = 2; /* GUID_WICPixelFormat1bppIndexed */
 
     This->format = &formats[i];
     memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
@@ -193,10 +194,26 @@ static HRESULT WINAPI BmpFrameEncode_SetColorContexts(IWICBitmapFrameEncode *ifa
 }
 
 static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
-    IWICPalette *pIPalette)
+    IWICPalette *palette)
 {
-    FIXME("(%p,%p): stub\n", iface, pIPalette);
-    return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
+    HRESULT hr;
+
+    TRACE("(%p,%p)\n", iface, palette);
+
+    if (!palette) return E_INVALIDARG;
+
+    if (!This->initialized)
+        return WINCODEC_ERR_NOTINITIALIZED;
+
+    hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
+    if (hr == S_OK)
+    {
+        UINT i;
+        for (i = 0; i < This->colors; i++)
+            This->palette[i] |= 0xff000000; /* BMP palette has no alpha */
+    }
+    return hr;
 }
 
 static HRESULT WINAPI BmpFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
@@ -224,7 +241,7 @@ static HRESULT BmpFrameEncode_AllocateBits(BmpFrameEncode *This)
 static HRESULT WINAPI BmpFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
     UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     HRESULT hr;
     WICRect rc;
     TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
@@ -253,76 +270,36 @@ static HRESULT WINAPI BmpFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
 static HRESULT WINAPI BmpFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
     IWICBitmapSource *pIBitmapSource, WICRect *prc)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     HRESULT hr;
-    WICRect rc;
-    WICPixelFormatGUID guid;
     TRACE("(%p,%p,%p)\n", iface, pIBitmapSource, prc);
 
-    if (!This->initialized || !This->width || !This->height)
+    if (!This->initialized)
         return WINCODEC_ERR_WRONGSTATE;
 
-    if (!This->format)
-    {
-        hr = IWICBitmapSource_GetPixelFormat(pIBitmapSource, &guid);
-        if (FAILED(hr)) return hr;
-        hr = BmpFrameEncode_SetPixelFormat(iface, &guid);
-        if (FAILED(hr)) return hr;
-    }
-
-    hr = IWICBitmapSource_GetPixelFormat(pIBitmapSource, &guid);
-    if (FAILED(hr)) return hr;
-    if (memcmp(&guid, This->format->guid, sizeof(GUID)) != 0)
-    {
-        /* should use WICConvertBitmapSource to convert, but that's unimplemented */
-        ERR("format %s unsupported\n", debugstr_guid(&guid));
-        return E_FAIL;
-    }
-
-    if (This->xres == 0.0 || This->yres == 0.0)
-    {
-        double xres, yres;
-        hr = IWICBitmapSource_GetResolution(pIBitmapSource, &xres, &yres);
-        if (FAILED(hr)) return hr;
-        hr = BmpFrameEncode_SetResolution(iface, xres, yres);
-        if (FAILED(hr)) return hr;
-    }
+    hr = configure_write_source(iface, pIBitmapSource, prc,
+        This->format ? This->format->guid : NULL, This->width, This->height,
+        This->xres, This->yres);
 
-    if (!prc)
+    if (SUCCEEDED(hr))
     {
-        UINT width, height;
-        hr = IWICBitmapSource_GetSize(pIBitmapSource, &width, &height);
-        if (FAILED(hr)) return hr;
-        rc.X = 0;
-        rc.Y = 0;
-        rc.Width = width;
-        rc.Height = height;
-        prc = &rc;
+        hr = write_source(iface, pIBitmapSource, prc,
+            This->format->guid, This->format->bpp, This->width, This->height);
     }
 
-    if (prc->Width != This->width) return E_INVALIDARG;
-
-    hr = BmpFrameEncode_AllocateBits(This);
-    if (FAILED(hr)) return hr;
-
-    hr = IWICBitmapSource_CopyPixels(pIBitmapSource, prc, This->stride,
-        This->stride*(This->height-This->lineswritten),
-        This->bits + This->stride*This->lineswritten);
-
-    This->lineswritten += rc.Height;
-
-    return S_OK;
+    return hr;
 }
 
 static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
 {
-    BmpFrameEncode *This = (BmpFrameEncode*)iface;
+    BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
     BITMAPFILEHEADER bfh;
     BITMAPV5HEADER bih;
-    UINT info_size;
+    UINT info_size, i;
     LARGE_INTEGER pos;
     ULONG byteswritten;
     HRESULT hr;
+    const BYTE *bits;
 
     TRACE("(%p)\n", iface);
 
@@ -335,15 +312,15 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
 
     bih.bV5Size = info_size = sizeof(BITMAPINFOHEADER);
     bih.bV5Width = This->width;
-    bih.bV5Height = -This->height; /* top-down bitmap */
+    bih.bV5Height = This->height; /* bottom-top bitmap */
     bih.bV5Planes = 1;
     bih.bV5BitCount = This->format->bpp;
     bih.bV5Compression = This->format->compression;
     bih.bV5SizeImage = This->stride*This->height;
     bih.bV5XPelsPerMeter = (This->xres+0.0127) / 0.0254;
     bih.bV5YPelsPerMeter = (This->yres+0.0127) / 0.0254;
-    bih.bV5ClrUsed = 0;
-    bih.bV5ClrImportant = 0;
+    bih.bV5ClrUsed = (This->format->bpp <= 8) ? This->colors : 0;
+    bih.bV5ClrImportant = bih.bV5ClrUsed;
 
     if (This->format->compression == BI_BITFIELDS)
     {
@@ -355,11 +332,12 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
         bih.bV5GreenMask = This->format->greenmask;
         bih.bV5BlueMask = This->format->bluemask;
         bih.bV5AlphaMask = This->format->alphamask;
-        bih.bV5AlphaMask = LCS_DEVICE_RGB;
+        bih.bV5CSType = LCS_DEVICE_RGB;
     }
 
     bfh.bfSize = sizeof(BITMAPFILEHEADER) + info_size + bih.bV5SizeImage;
     bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + info_size;
+    bfh.bfOffBits += bih.bV5ClrUsed * sizeof(WICColor);
 
     pos.QuadPart = 0;
     hr = IStream_Seek(This->stream, pos, STREAM_SEEK_SET, NULL);
@@ -373,9 +351,23 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
     if (FAILED(hr)) return hr;
     if (byteswritten != info_size) return E_FAIL;
 
-    hr = IStream_Write(This->stream, This->bits, bih.bV5SizeImage, &byteswritten);
-    if (FAILED(hr)) return hr;
-    if (byteswritten != bih.bV5SizeImage) return E_FAIL;
+    /* write the palette */
+    if (This->format->colors)
+    {
+        hr = IStream_Write(This->stream, This->palette, This->colors * sizeof(WICColor), &byteswritten);
+        if (FAILED(hr)) return hr;
+        if (byteswritten != This->colors * sizeof(WICColor)) return E_FAIL;
+    }
+
+    /* write the image bits as a bottom-top array */
+    bits = This->bits + bih.bV5SizeImage;
+    for (i = 0; i < This->height; i++)
+    {
+        bits -= This->stride;
+        hr = IStream_Write(This->stream, bits, This->stride, &byteswritten);
+        if (FAILED(hr)) return hr;
+        if (byteswritten != This->stride) return E_FAIL;
+    }
 
     This->committed = TRUE;
 
@@ -407,16 +399,21 @@ static const IWICBitmapFrameEncodeVtbl BmpFrameEncode_Vtbl = {
 };
 
 typedef struct BmpEncoder {
-    const IWICBitmapEncoderVtbl *lpVtbl;
+    IWICBitmapEncoder IWICBitmapEncoder_iface;
     LONG ref;
     IStream *stream;
-    IWICBitmapFrameEncode *frame;
+    BmpFrameEncode *frame;
 } BmpEncoder;
 
+static inline BmpEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
+{
+    return CONTAINING_RECORD(iface, BmpEncoder, IWICBitmapEncoder_iface);
+}
+
 static HRESULT WINAPI BmpEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
     void **ppv)
 {
-    BmpEncoder *This = (BmpEncoder*)iface;
+    BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
 
     if (!ppv) return E_INVALIDARG;
@@ -424,7 +421,7 @@ static HRESULT WINAPI BmpEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID
     if (IsEqualIID(&IID_IUnknown, iid) ||
         IsEqualIID(&IID_IWICBitmapEncoder, iid))
     {
-        *ppv = This;
+        *ppv = &This->IWICBitmapEncoder_iface;
     }
     else
     {
@@ -438,7 +435,7 @@ static HRESULT WINAPI BmpEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID
 
 static ULONG WINAPI BmpEncoder_AddRef(IWICBitmapEncoder *iface)
 {
-    BmpEncoder *This = (BmpEncoder*)iface;
+    BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
     ULONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) refcount=%u\n", iface, ref);
@@ -448,7 +445,7 @@ static ULONG WINAPI BmpEncoder_AddRef(IWICBitmapEncoder *iface)
 
 static ULONG WINAPI BmpEncoder_Release(IWICBitmapEncoder *iface)
 {
-    BmpEncoder *This = (BmpEncoder*)iface;
+    BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) refcount=%u\n", iface, ref);
@@ -456,7 +453,7 @@ static ULONG WINAPI BmpEncoder_Release(IWICBitmapEncoder *iface)
     if (ref == 0)
     {
         if (This->stream) IStream_Release(This->stream);
-        if (This->frame) IWICBitmapFrameEncode_Release(This->frame);
+        if (This->frame) IWICBitmapFrameEncode_Release(&This->frame->IWICBitmapFrameEncode_iface);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -466,7 +463,7 @@ static ULONG WINAPI BmpEncoder_Release(IWICBitmapEncoder *iface)
 static HRESULT WINAPI BmpEncoder_Initialize(IWICBitmapEncoder *iface,
     IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
 {
-    BmpEncoder *This = (BmpEncoder*)iface;
+    BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
 
     TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
 
@@ -479,15 +476,26 @@ static HRESULT WINAPI BmpEncoder_Initialize(IWICBitmapEncoder *iface,
 static HRESULT WINAPI BmpEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
     GUID *pguidContainerFormat)
 {
-    FIXME("(%p,%s): stub\n", iface, debugstr_guid(pguidContainerFormat));
-    return E_NOTIMPL;
+    memcpy(pguidContainerFormat, &GUID_ContainerFormatBmp, sizeof(GUID));
+    return S_OK;
 }
 
-static HRESULT WINAPI BmpEncoder_GetEncoderInfo(IWICBitmapEncoder *iface,
-    IWICBitmapEncoderInfo **ppIEncoderInfo)
+static HRESULT WINAPI BmpEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
 {
-    FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo);
-    return E_NOTIMPL;
+    IWICComponentInfo *comp_info;
+    HRESULT hr;
+
+    TRACE("%p,%p\n", iface, info);
+
+    if (!info) return E_INVALIDARG;
+
+    hr = CreateComponentInfo(&CLSID_WICBmpEncoder, &comp_info);
+    if (hr == S_OK)
+    {
+        hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
+        IWICComponentInfo_Release(comp_info);
+    }
+    return hr;
 }
 
 static HRESULT WINAPI BmpEncoder_SetColorContexts(IWICBitmapEncoder *iface,
@@ -497,10 +505,12 @@ static HRESULT WINAPI BmpEncoder_SetColorContexts(IWICBitmapEncoder *iface,
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI BmpEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette)
+static HRESULT WINAPI BmpEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
 {
-    TRACE("(%p,%p)\n", iface, pIPalette);
-    return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+    BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
+
+    TRACE("(%p,%p)\n", iface, palette);
+    return This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
 }
 
 static HRESULT WINAPI BmpEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
@@ -518,7 +528,7 @@ static HRESULT WINAPI BmpEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmap
 static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
     IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
 {
-    BmpEncoder *This = (BmpEncoder*)iface;
+    BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
     BmpFrameEncode *encode;
     HRESULT hr;
 
@@ -528,7 +538,7 @@ static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
 
     if (!This->stream) return WINCODEC_ERR_NOTINITIALIZED;
 
-    hr = CreatePropertyBag2(ppIEncoderOptions);
+    hr = CreatePropertyBag2(NULL, 0, ppIEncoderOptions);
     if (FAILED(hr)) return hr;
 
     encode = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameEncode));
@@ -538,7 +548,7 @@ static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
         *ppIEncoderOptions = NULL;
         return E_OUTOFMEMORY;
     }
-    encode->lpVtbl = &BmpFrameEncode_Vtbl;
+    encode->IWICBitmapFrameEncode_iface.lpVtbl = &BmpFrameEncode_Vtbl;
     encode->ref = 2;
     IStream_AddRef(This->stream);
     encode->stream = This->stream;
@@ -550,21 +560,21 @@ static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
     encode->xres = 0.0;
     encode->yres = 0.0;
     encode->lineswritten = 0;
+    encode->colors = 0;
     encode->committed = FALSE;
 
-    *ppIFrameEncode = (IWICBitmapFrameEncode*)encode;
-    This->frame = (IWICBitmapFrameEncode*)encode;
+    *ppIFrameEncode = &encode->IWICBitmapFrameEncode_iface;
+    This->frame = encode;
 
     return S_OK;
 }
 
 static HRESULT WINAPI BmpEncoder_Commit(IWICBitmapEncoder *iface)
 {
-    BmpEncoder *This = (BmpEncoder*)iface;
-    BmpFrameEncode *frame = (BmpFrameEncode*)This->frame;
+    BmpEncoder *This = impl_from_IWICBitmapEncoder(iface);
     TRACE("(%p)\n", iface);
 
-    if (!frame || !frame->committed) return WINCODEC_ERR_WRONGSTATE;
+    if (!This->frame || !This->frame->committed) return WINCODEC_ERR_WRONGSTATE;
 
     return S_OK;
 }
@@ -592,27 +602,25 @@ static const IWICBitmapEncoderVtbl BmpEncoder_Vtbl = {
     BmpEncoder_GetMetadataQueryWriter
 };
 
-HRESULT BmpEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+HRESULT BmpEncoder_CreateInstance(REFIID iid, void** ppv)
 {
     BmpEncoder *This;
     HRESULT ret;
 
-    TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
+    TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
 
     *ppv = NULL;
 
-    if (pUnkOuter) return CLASS_E_NOAGGREGATION;
-
     This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpEncoder));
     if (!This) return E_OUTOFMEMORY;
 
-    This->lpVtbl = &BmpEncoder_Vtbl;
+    This->IWICBitmapEncoder_iface.lpVtbl = &BmpEncoder_Vtbl;
     This->ref = 1;
     This->stream = NULL;
     This->frame = NULL;
 
-    ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
-    IUnknown_Release((IUnknown*)This);
+    ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
+    IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
 
     return ret;
 }