diff --git a/reactos/baseaddress.rbuild b/reactos/baseaddress.rbuild
index f36856cde5b..5ec3e97f213 100644
--- a/reactos/baseaddress.rbuild
+++ b/reactos/baseaddress.rbuild
@@ -6,6 +6,7 @@
+
diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff
index 36326cf412d..aa7382a7fb2 100644
--- a/reactos/boot/bootdata/packages/reactos.dff
+++ b/reactos/boot/bootdata/packages/reactos.dff
@@ -439,6 +439,7 @@ dll\win32\usp10\usp10.dll 1
dll\win32\uxtheme\uxtheme.dll 1
dll\win32\vdmdbg\vdmdbg.dll 1
dll\win32\version\version.dll 1
+dll\win32\windowscodecs\windowscodecs.dll 1
dll\win32\winemp3.acm\winemp3.acm 1
dll\win32\winfax\winfax.dll 1
dll\win32\winhttp\winhttp.dll 1
diff --git a/reactos/dll/win32/win32.rbuild b/reactos/dll/win32/win32.rbuild
index c3261d565cf..a1fbe616098 100644
--- a/reactos/dll/win32/win32.rbuild
+++ b/reactos/dll/win32/win32.rbuild
@@ -583,6 +583,9 @@
+
+
+
diff --git a/reactos/dll/win32/windowscodecs/bmpdecode.c b/reactos/dll/win32/windowscodecs/bmpdecode.c
new file mode 100644
index 00000000000..5c805c8c098
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/bmpdecode.c
@@ -0,0 +1,1059 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#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);
+
+typedef struct {
+ DWORD bc2Size;
+ DWORD bc2Width;
+ DWORD bc2Height;
+ WORD bc2Planes;
+ WORD bc2BitCount;
+ DWORD bc2Compression;
+ DWORD bc2SizeImage;
+ DWORD bc2XRes;
+ DWORD bc2YRes;
+ DWORD bc2ClrUsed;
+ DWORD bc2ClrImportant;
+ /* same as BITMAPINFOHEADER until this point */
+ WORD bc2ResUnit;
+ WORD bc2Reserved;
+ WORD bc2Orientation;
+ WORD bc2Halftoning;
+ DWORD bc2HalftoneSize1;
+ DWORD bc2HalftoneSize2;
+ DWORD bc2ColorSpace;
+ DWORD bc2AppData;
+} BITMAPCOREHEADER2;
+
+struct BmpFrameDecode;
+typedef HRESULT (*ReadDataFunc)(struct BmpFrameDecode* This);
+
+typedef struct BmpFrameDecode {
+ const IWICBitmapFrameDecodeVtbl *lpVtbl;
+ LONG ref;
+ IStream *stream;
+ BITMAPFILEHEADER bfh;
+ BITMAPV5HEADER bih;
+ const WICPixelFormatGUID *pixelformat;
+ int bitsperpixel;
+ ReadDataFunc read_data_func;
+ INT stride;
+ BYTE *imagedata;
+ BYTE *imagedatastart;
+} BmpFrameDecode;
+
+static HRESULT WINAPI BmpFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
+ void **ppv)
+{
+ BmpFrameDecode *This = (BmpFrameDecode*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapSource, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI BmpFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
+{
+ BmpFrameDecode *This = (BmpFrameDecode*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI BmpFrameDecode_Release(IWICBitmapFrameDecode *iface)
+{
+ BmpFrameDecode *This = (BmpFrameDecode*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ IStream_Release(This->stream);
+ HeapFree(GetProcessHeap(), 0, This->imagedata);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI BmpFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
+ UINT *puiWidth, UINT *puiHeight)
+{
+ BmpFrameDecode *This = (BmpFrameDecode*)iface;
+ TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
+
+ if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
+ *puiWidth = bch->bcWidth;
+ *puiHeight = bch->bcHeight;
+ }
+ else
+ {
+ *puiWidth = This->bih.bV5Width;
+ *puiHeight = abs(This->bih.bV5Height);
+ }
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ BmpFrameDecode *This = (BmpFrameDecode*)iface;
+ TRACE("(%p,%p)\n", iface, pPixelFormat);
+
+ memcpy(pPixelFormat, This->pixelformat, sizeof(GUID));
+
+ return S_OK;
+}
+
+static HRESULT BmpHeader_GetResolution(BITMAPV5HEADER *bih, double *pDpiX, double *pDpiY)
+{
+ switch (bih->bV5Size)
+ {
+ case sizeof(BITMAPCOREHEADER):
+ *pDpiX = 96.0;
+ *pDpiY = 96.0;
+ return S_OK;
+ case sizeof(BITMAPCOREHEADER2):
+ case sizeof(BITMAPINFOHEADER):
+ case sizeof(BITMAPV4HEADER):
+ case sizeof(BITMAPV5HEADER):
+ *pDpiX = bih->bV5XPelsPerMeter * 0.0254;
+ *pDpiY = bih->bV5YPelsPerMeter * 0.0254;
+ return S_OK;
+ default:
+ return E_FAIL;
+ }
+}
+
+static HRESULT WINAPI BmpFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
+ double *pDpiX, double *pDpiY)
+{
+ BmpFrameDecode *This = (BmpFrameDecode*)iface;
+ TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
+
+ return BmpHeader_GetResolution(&This->bih, pDpiX, pDpiY);
+}
+
+static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
+ IWICPalette *pIPalette)
+{
+ HRESULT hr;
+ BmpFrameDecode *This = (BmpFrameDecode*)iface;
+ int count;
+ WICColor *wiccolors=NULL;
+ RGBTRIPLE *bgrcolors=NULL;
+
+ TRACE("(%p,%p)\n", iface, pIPalette);
+
+ if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
+ if (bch->bcBitCount <= 8)
+ {
+ /* 2**n colors in BGR format after the header */
+ ULONG tablesize, bytesread;
+ LARGE_INTEGER offset;
+ int i;
+
+ count = 1 << bch->bcBitCount;
+ wiccolors = HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor) * count);
+ tablesize = sizeof(RGBTRIPLE) * count;
+ bgrcolors = HeapAlloc(GetProcessHeap(), 0, tablesize);
+ if (!wiccolors || !bgrcolors)
+ {
+ hr = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ offset.QuadPart = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPCOREHEADER);
+ hr = IStream_Seek(This->stream, offset, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto end;
+
+ hr = IStream_Read(This->stream, bgrcolors, tablesize, &bytesread);
+ if (FAILED(hr)) goto end;
+ if (bytesread != tablesize) {
+ hr = E_FAIL;
+ goto end;
+ }
+
+ for (i=0; ibih.bV5BitCount <= 8)
+ {
+ ULONG tablesize, bytesread;
+ LARGE_INTEGER offset;
+ int i;
+
+ if (This->bih.bV5ClrUsed == 0)
+ count = 1 << This->bih.bV5BitCount;
+ else
+ count = This->bih.bV5ClrUsed;
+
+ tablesize = sizeof(WICColor) * count;
+ wiccolors = HeapAlloc(GetProcessHeap(), 0, tablesize);
+ if (!wiccolors) return E_OUTOFMEMORY;
+
+ offset.QuadPart = sizeof(BITMAPFILEHEADER) + This->bih.bV5Size;
+ hr = IStream_Seek(This->stream, offset, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto end;
+
+ hr = IStream_Read(This->stream, wiccolors, tablesize, &bytesread);
+ if (FAILED(hr)) goto end;
+ if (bytesread != tablesize) {
+ hr = E_FAIL;
+ goto end;
+ }
+
+ /* convert from BGR to BGRA by setting alpha to 100% */
+ for (i=0; iimagedata)
+ {
+ hr = This->read_data_func(This);
+ if (FAILED(hr)) return hr;
+ }
+
+ hr = BmpFrameDecode_GetSize(iface, &width, &height);
+ if (FAILED(hr)) return hr;
+
+ return copy_pixels(This->bitsperpixel, This->imagedatastart,
+ width, height, This->stride,
+ prc, cbStride, cbBufferSize, pbBuffer);
+}
+
+static HRESULT WINAPI BmpFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+ TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static HRESULT BmpFrameDecode_ReadUncompressed(BmpFrameDecode* This)
+{
+ UINT bytesperrow;
+ UINT width, height;
+ UINT datasize;
+ int bottomup;
+ HRESULT hr;
+ LARGE_INTEGER offbits;
+ ULONG bytesread;
+
+ if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
+ width = bch->bcWidth;
+ height = bch->bcHeight;
+ bottomup = 1;
+ }
+ else
+ {
+ width = This->bih.bV5Width;
+ height = abs(This->bih.bV5Height);
+ bottomup = (This->bih.bV5Height > 0);
+ }
+
+ /* row sizes in BMP files must be divisible by 4 bytes */
+ bytesperrow = (((width * This->bitsperpixel)+31)/32)*4;
+ datasize = bytesperrow * height;
+
+ This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
+ if (!This->imagedata) return E_OUTOFMEMORY;
+
+ offbits.QuadPart = This->bfh.bfOffBits;
+ hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto fail;
+
+ hr = IStream_Read(This->stream, This->imagedata, datasize, &bytesread);
+ if (FAILED(hr) || bytesread != datasize) goto fail;
+
+ if (bottomup)
+ {
+ This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
+ This->stride = -bytesperrow;
+ }
+ else
+ {
+ This->imagedatastart = This->imagedata;
+ This->stride = bytesperrow;
+ }
+ return S_OK;
+
+fail:
+ HeapFree(GetProcessHeap(), 0, This->imagedata);
+ This->imagedata = NULL;
+ if (SUCCEEDED(hr)) hr = E_FAIL;
+ return hr;
+}
+
+static HRESULT BmpFrameDecode_ReadRLE8(BmpFrameDecode* This)
+{
+ UINT bytesperrow;
+ UINT width, height;
+ BYTE *rledata, *cursor, *rledataend;
+ UINT rlesize, datasize, palettesize;
+ DWORD palette[256];
+ UINT x, y;
+ DWORD *bgrdata;
+ HRESULT hr;
+ LARGE_INTEGER offbits;
+ ULONG bytesread;
+
+ width = This->bih.bV5Width;
+ height = abs(This->bih.bV5Height);
+ bytesperrow = width * 4;
+ datasize = bytesperrow * height;
+ rlesize = This->bih.bV5SizeImage;
+ if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 256)
+ palettesize = 4 * This->bih.bV5ClrUsed;
+ else
+ palettesize = 4 * 256;
+
+ rledata = HeapAlloc(GetProcessHeap(), 0, rlesize);
+ This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
+ if (!This->imagedata || !rledata)
+ {
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ /* read palette */
+ offbits.QuadPart = sizeof(BITMAPFILEHEADER) + This->bih.bV5Size;
+ hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto fail;
+
+ hr = IStream_Read(This->stream, palette, palettesize, &bytesread);
+ if (FAILED(hr) || bytesread != palettesize) goto fail;
+
+ /* read RLE data */
+ offbits.QuadPart = This->bfh.bfOffBits;
+ hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto fail;
+
+ hr = IStream_Read(This->stream, rledata, rlesize, &bytesread);
+ if (FAILED(hr) || bytesread != rlesize) goto fail;
+
+ /* decode RLE */
+ bgrdata = (DWORD*)This->imagedata;
+ x = 0;
+ y = 0;
+ rledataend = rledata + rlesize;
+ cursor = rledata;
+ while (cursor < rledataend && y < height)
+ {
+ BYTE length = *cursor++;
+ if (length == 0)
+ {
+ /* escape code */
+ BYTE escape = *cursor++;
+ switch(escape)
+ {
+ case 0: /* end of line */
+ x = 0;
+ y++;
+ break;
+ case 1: /* end of bitmap */
+ goto end;
+ case 2: /* delta */
+ if (cursor < rledataend)
+ {
+ x += *cursor++;
+ y += *cursor++;
+ }
+ break;
+ default: /* absolute mode */
+ length = escape;
+ while (cursor < rledataend && length-- && x < width)
+ bgrdata[y*width + x++] = palette[*cursor++];
+ if (escape & 1) cursor++; /* skip pad byte */
+ }
+ }
+ else
+ {
+ DWORD color = palette[*cursor++];
+ while (length-- && x < width)
+ bgrdata[y*width + x++] = color;
+ }
+ }
+
+end:
+ HeapFree(GetProcessHeap(), 0, rledata);
+
+ This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
+ This->stride = -bytesperrow;
+
+ return S_OK;
+
+fail:
+ HeapFree(GetProcessHeap(), 0, rledata);
+ HeapFree(GetProcessHeap(), 0, This->imagedata);
+ This->imagedata = NULL;
+ if (SUCCEEDED(hr)) hr = E_FAIL;
+ return hr;
+}
+
+static HRESULT BmpFrameDecode_ReadRLE4(BmpFrameDecode* This)
+{
+ UINT bytesperrow;
+ UINT width, height;
+ BYTE *rledata, *cursor, *rledataend;
+ UINT rlesize, datasize, palettesize;
+ DWORD palette[16];
+ UINT x, y;
+ DWORD *bgrdata;
+ HRESULT hr;
+ LARGE_INTEGER offbits;
+ ULONG bytesread;
+
+ width = This->bih.bV5Width;
+ height = abs(This->bih.bV5Height);
+ bytesperrow = width * 4;
+ datasize = bytesperrow * height;
+ rlesize = This->bih.bV5SizeImage;
+ if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 16)
+ palettesize = 4 * This->bih.bV5ClrUsed;
+ else
+ palettesize = 4 * 16;
+
+ rledata = HeapAlloc(GetProcessHeap(), 0, rlesize);
+ This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
+ if (!This->imagedata || !rledata)
+ {
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ /* read palette */
+ offbits.QuadPart = sizeof(BITMAPFILEHEADER) + This->bih.bV5Size;
+ hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto fail;
+
+ hr = IStream_Read(This->stream, palette, palettesize, &bytesread);
+ if (FAILED(hr) || bytesread != palettesize) goto fail;
+
+ /* read RLE data */
+ offbits.QuadPart = This->bfh.bfOffBits;
+ hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto fail;
+
+ hr = IStream_Read(This->stream, rledata, rlesize, &bytesread);
+ if (FAILED(hr) || bytesread != rlesize) goto fail;
+
+ /* decode RLE */
+ bgrdata = (DWORD*)This->imagedata;
+ x = 0;
+ y = 0;
+ rledataend = rledata + rlesize;
+ cursor = rledata;
+ while (cursor < rledataend && y < height)
+ {
+ BYTE length = *cursor++;
+ if (length == 0)
+ {
+ /* escape code */
+ BYTE escape = *cursor++;
+ switch(escape)
+ {
+ case 0: /* end of line */
+ x = 0;
+ y++;
+ break;
+ case 1: /* end of bitmap */
+ goto end;
+ case 2: /* delta */
+ if (cursor < rledataend)
+ {
+ x += *cursor++;
+ y += *cursor++;
+ }
+ break;
+ default: /* absolute mode */
+ length = escape;
+ while (cursor < rledataend && length-- && x < width)
+ {
+ BYTE colors = *cursor++;
+ bgrdata[y*width + x++] = palette[colors>>4];
+ if (length-- && x < width)
+ bgrdata[y*width + x++] = palette[colors&0xf];
+ else
+ break;
+ }
+ if ((cursor - rledata) & 1) cursor++; /* skip pad byte */
+ }
+ }
+ else
+ {
+ BYTE colors = *cursor++;
+ DWORD color1 = palette[colors>>4];
+ DWORD color2 = palette[colors&0xf];
+ while (length-- && x < width)
+ {
+ bgrdata[y*width + x++] = color1;
+ if (length-- && x < width)
+ bgrdata[y*width + x++] = color2;
+ else
+ break;
+ }
+ }
+ }
+
+end:
+ HeapFree(GetProcessHeap(), 0, rledata);
+
+ This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
+ This->stride = -bytesperrow;
+
+ return S_OK;
+
+fail:
+ HeapFree(GetProcessHeap(), 0, rledata);
+ HeapFree(GetProcessHeap(), 0, This->imagedata);
+ This->imagedata = NULL;
+ if (SUCCEEDED(hr)) hr = E_FAIL;
+ return hr;
+}
+
+static HRESULT BmpFrameDecode_ReadUnsupported(BmpFrameDecode* This)
+{
+ return E_FAIL;
+}
+
+struct bitfields_format {
+ WORD bitcount; /* 0 for end of list */
+ DWORD redmask;
+ DWORD greenmask;
+ DWORD bluemask;
+ DWORD alphamask;
+ const WICPixelFormatGUID *pixelformat;
+ ReadDataFunc read_data_func;
+};
+
+static const struct bitfields_format bitfields_formats[] = {
+ {16,0x7c00,0x3e0,0x1f,0,&GUID_WICPixelFormat16bppBGR555,BmpFrameDecode_ReadUncompressed},
+ {16,0xf800,0x7e0,0x1f,0,&GUID_WICPixelFormat16bppBGR565,BmpFrameDecode_ReadUncompressed},
+ {32,0xff0000,0xff00,0xff,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadUncompressed},
+ {32,0xff0000,0xff00,0xff,0xff000000,&GUID_WICPixelFormat32bppBGRA,BmpFrameDecode_ReadUncompressed},
+ {0}
+};
+
+static const IWICBitmapFrameDecodeVtbl BmpFrameDecode_Vtbl = {
+ BmpFrameDecode_QueryInterface,
+ BmpFrameDecode_AddRef,
+ BmpFrameDecode_Release,
+ BmpFrameDecode_GetSize,
+ BmpFrameDecode_GetPixelFormat,
+ BmpFrameDecode_GetResolution,
+ BmpFrameDecode_CopyPalette,
+ BmpFrameDecode_CopyPixels,
+ BmpFrameDecode_GetMetadataQueryReader,
+ BmpFrameDecode_GetColorContexts,
+ BmpFrameDecode_GetThumbnail
+};
+
+typedef struct {
+ const IWICBitmapDecoderVtbl *lpVtbl;
+ LONG ref;
+ BOOL initialized;
+ IStream *stream;
+ BITMAPFILEHEADER bfh;
+ BITMAPV5HEADER bih;
+ BmpFrameDecode *framedecode;
+ const WICPixelFormatGUID *pixelformat;
+ int bitsperpixel;
+ ReadDataFunc read_data_func;
+} BmpDecoder;
+
+static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream *stream)
+{
+ HRESULT hr;
+ ULONG bytestoread, bytesread;
+ LARGE_INTEGER seek;
+
+ if (This->initialized) return WINCODEC_ERR_WRONGSTATE;
+
+ seek.QuadPart = 0;
+ hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) return hr;
+
+ hr = IStream_Read(stream, &This->bfh, sizeof(BITMAPFILEHEADER), &bytesread);
+ if (FAILED(hr)) return hr;
+ if (bytesread != sizeof(BITMAPFILEHEADER) ||
+ This->bfh.bfType != 0x4d42 /* "BM" */) return E_FAIL;
+
+ hr = IStream_Read(stream, &This->bih.bV5Size, sizeof(DWORD), &bytesread);
+ if (FAILED(hr)) return hr;
+ if (bytesread != sizeof(DWORD) ||
+ (This->bih.bV5Size != sizeof(BITMAPCOREHEADER) &&
+ This->bih.bV5Size != sizeof(BITMAPCOREHEADER2) &&
+ This->bih.bV5Size != sizeof(BITMAPINFOHEADER) &&
+ This->bih.bV5Size != sizeof(BITMAPV4HEADER) &&
+ This->bih.bV5Size != sizeof(BITMAPV5HEADER))) return E_FAIL;
+
+ bytestoread = This->bih.bV5Size-sizeof(DWORD);
+ hr = IStream_Read(stream, &This->bih.bV5Width, bytestoread, &bytesread);
+ if (FAILED(hr)) return hr;
+ if (bytestoread != bytesread) return E_FAIL;
+
+ /* if this is a BITMAPINFOHEADER with BI_BITFIELDS compression, we need to
+ read the extra fields */
+ if (This->bih.bV5Size == sizeof(BITMAPINFOHEADER) &&
+ This->bih.bV5Compression == BI_BITFIELDS)
+ {
+ hr = IStream_Read(stream, &This->bih.bV5RedMask, 12, &bytesread);
+ if (FAILED(hr)) return hr;
+ if (bytesread != 12) return E_FAIL;
+ This->bih.bV5AlphaMask = 0;
+ }
+
+ /* decide what kind of bitmap this is and how/if we can read it */
+ if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER *bch = (BITMAPCOREHEADER*)&This->bih;
+ TRACE("BITMAPCOREHEADER with depth=%i\n", bch->bcBitCount);
+ This->bitsperpixel = bch->bcBitCount;
+ This->read_data_func = BmpFrameDecode_ReadUncompressed;
+ switch(bch->bcBitCount)
+ {
+ case 1:
+ This->pixelformat = &GUID_WICPixelFormat1bppIndexed;
+ break;
+ case 2:
+ This->pixelformat = &GUID_WICPixelFormat2bppIndexed;
+ break;
+ case 4:
+ This->pixelformat = &GUID_WICPixelFormat4bppIndexed;
+ break;
+ case 8:
+ This->pixelformat = &GUID_WICPixelFormat8bppIndexed;
+ break;
+ case 24:
+ This->pixelformat = &GUID_WICPixelFormat24bppBGR;
+ break;
+ default:
+ This->pixelformat = &GUID_WICPixelFormatUndefined;
+ WARN("unsupported bit depth %i for BITMAPCOREHEADER\n", bch->bcBitCount);
+ break;
+ }
+ }
+ else /* struct is compatible with BITMAPINFOHEADER */
+ {
+ TRACE("bitmap header=%i compression=%i depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount);
+ switch(This->bih.bV5Compression)
+ {
+ case BI_RGB:
+ This->bitsperpixel = This->bih.bV5BitCount;
+ This->read_data_func = BmpFrameDecode_ReadUncompressed;
+ switch(This->bih.bV5BitCount)
+ {
+ case 1:
+ This->pixelformat = &GUID_WICPixelFormat1bppIndexed;
+ break;
+ case 2:
+ This->pixelformat = &GUID_WICPixelFormat2bppIndexed;
+ break;
+ case 4:
+ This->pixelformat = &GUID_WICPixelFormat4bppIndexed;
+ break;
+ case 8:
+ This->pixelformat = &GUID_WICPixelFormat8bppIndexed;
+ break;
+ case 16:
+ This->pixelformat = &GUID_WICPixelFormat16bppBGR555;
+ break;
+ case 24:
+ This->pixelformat = &GUID_WICPixelFormat24bppBGR;
+ break;
+ case 32:
+ This->pixelformat = &GUID_WICPixelFormat32bppBGR;
+ break;
+ default:
+ This->pixelformat = &GUID_WICPixelFormatUndefined;
+ FIXME("unsupported bit depth %i for uncompressed RGB\n", This->bih.bV5BitCount);
+ }
+ break;
+ case BI_RLE8:
+ This->bitsperpixel = 32;
+ This->read_data_func = BmpFrameDecode_ReadRLE8;
+ This->pixelformat = &GUID_WICPixelFormat32bppBGR;
+ break;
+ case BI_RLE4:
+ This->bitsperpixel = 32;
+ This->read_data_func = BmpFrameDecode_ReadRLE4;
+ This->pixelformat = &GUID_WICPixelFormat32bppBGR;
+ break;
+ case BI_BITFIELDS:
+ {
+ const struct bitfields_format *format;
+ if (This->bih.bV5Size == sizeof(BITMAPCOREHEADER2))
+ {
+ /* BCH2 doesn't support bitfields; this is Huffman 1D compression */
+ This->bitsperpixel = 0;
+ This->read_data_func = BmpFrameDecode_ReadUnsupported;
+ This->pixelformat = &GUID_WICPixelFormatUndefined;
+ FIXME("Huffman 1D compression is unsupported\n");
+ break;
+ }
+ This->bitsperpixel = This->bih.bV5BitCount;
+ for (format = bitfields_formats; format->bitcount; format++)
+ {
+ if ((format->bitcount == This->bih.bV5BitCount) &&
+ (format->redmask == This->bih.bV5RedMask) &&
+ (format->greenmask == This->bih.bV5GreenMask) &&
+ (format->bluemask == This->bih.bV5BlueMask) &&
+ (format->alphamask == This->bih.bV5AlphaMask))
+ {
+ This->read_data_func = format->read_data_func;
+ This->pixelformat = format->pixelformat;
+ break;
+ }
+ }
+ if (!format->bitcount)
+ {
+ This->read_data_func = BmpFrameDecode_ReadUncompressed;
+ This->pixelformat = &GUID_WICPixelFormatUndefined;
+ FIXME("unsupported bitfields type depth=%i red=%x green=%x blue=%x alpha=%x\n",
+ This->bih.bV5BitCount, This->bih.bV5RedMask, This->bih.bV5GreenMask, This->bih.bV5BlueMask, This->bih.bV5AlphaMask);
+ }
+ break;
+ }
+ default:
+ This->bitsperpixel = 0;
+ This->read_data_func = BmpFrameDecode_ReadUnsupported;
+ This->pixelformat = &GUID_WICPixelFormatUndefined;
+ FIXME("unsupported bitmap type header=%i compression=%i depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount);
+ break;
+ }
+ }
+
+ This->initialized = TRUE;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
+ void **ppv)
+{
+ BmpDecoder *This = (BmpDecoder*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI BmpDecoder_AddRef(IWICBitmapDecoder *iface)
+{
+ BmpDecoder *This = (BmpDecoder*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI BmpDecoder_Release(IWICBitmapDecoder *iface)
+{
+ BmpDecoder *This = (BmpDecoder*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ if (This->stream) IStream_Release(This->stream);
+ if (This->framedecode) IUnknown_Release((IUnknown*)This->framedecode);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI BmpDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
+ DWORD *pdwCapability)
+{
+ HRESULT hr;
+ BmpDecoder *This = (BmpDecoder*)iface;
+
+ hr = BmpDecoder_ReadHeaders(This, pIStream);
+ if (FAILED(hr)) return hr;
+
+ if (This->read_data_func == BmpFrameDecode_ReadUnsupported)
+ *pdwCapability = 0;
+ else
+ *pdwCapability = WICBitmapDecoderCapabilityCanDecodeAllImages;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
+ WICDecodeOptions cacheOptions)
+{
+ HRESULT hr;
+ BmpDecoder *This = (BmpDecoder*)iface;
+
+ hr = BmpDecoder_ReadHeaders(This, pIStream);
+
+ if (SUCCEEDED(hr))
+ {
+ This->stream = pIStream;
+ IStream_AddRef(pIStream);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI BmpDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
+ GUID *pguidContainerFormat)
+{
+ memcpy(pguidContainerFormat, &GUID_ContainerFormatBmp, sizeof(GUID));
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
+ IWICBitmapDecoderInfo **ppIDecoderInfo)
+{
+ HRESULT hr;
+ IWICComponentInfo *compinfo;
+
+ TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
+
+ hr = CreateComponentInfo(&CLSID_WICBmpDecoder, &compinfo);
+ if (FAILED(hr)) return hr;
+
+ hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
+ (void**)ppIDecoderInfo);
+
+ IWICComponentInfo_Release(compinfo);
+
+ return hr;
+}
+
+static HRESULT WINAPI BmpDecoder_CopyPalette(IWICBitmapDecoder *iface,
+ IWICPalette *pIPalette)
+{
+ TRACE("(%p,%p)\n", iface, pIPalette);
+
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
+}
+
+static HRESULT WINAPI BmpDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+ TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpDecoder_GetPreview(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIBitmapSource)
+{
+ TRACE("(%p,%p)\n", iface, ppIBitmapSource);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpDecoder_GetColorContexts(IWICBitmapDecoder *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpDecoder_GetThumbnail(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static HRESULT WINAPI BmpDecoder_GetFrameCount(IWICBitmapDecoder *iface,
+ UINT *pCount)
+{
+ *pCount = 1;
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpDecoder_GetFrame(IWICBitmapDecoder *iface,
+ UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
+{
+ BmpDecoder *This = (BmpDecoder*)iface;
+
+ if (index != 0) return E_INVALIDARG;
+
+ if (!This->stream) return WINCODEC_ERR_WRONGSTATE;
+
+ if (!This->framedecode)
+ {
+ This->framedecode = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameDecode));
+ if (!This->framedecode) return E_OUTOFMEMORY;
+
+ This->framedecode->lpVtbl = &BmpFrameDecode_Vtbl;
+ This->framedecode->ref = 1;
+ This->framedecode->stream = This->stream;
+ IStream_AddRef(This->stream);
+ This->framedecode->bfh = This->bfh;
+ This->framedecode->bih = This->bih;
+ This->framedecode->pixelformat = This->pixelformat;
+ This->framedecode->bitsperpixel = This->bitsperpixel;
+ This->framedecode->read_data_func = This->read_data_func;
+ This->framedecode->imagedata = NULL;
+ }
+
+ *ppIBitmapFrame = (IWICBitmapFrameDecode*)This->framedecode;
+ IWICBitmapFrameDecode_AddRef((IWICBitmapFrameDecode*)This->framedecode);
+
+ return S_OK;
+}
+
+static const IWICBitmapDecoderVtbl BmpDecoder_Vtbl = {
+ BmpDecoder_QueryInterface,
+ BmpDecoder_AddRef,
+ BmpDecoder_Release,
+ BmpDecoder_QueryCapability,
+ BmpDecoder_Initialize,
+ BmpDecoder_GetContainerFormat,
+ BmpDecoder_GetDecoderInfo,
+ BmpDecoder_CopyPalette,
+ BmpDecoder_GetMetadataQueryReader,
+ BmpDecoder_GetPreview,
+ BmpDecoder_GetColorContexts,
+ BmpDecoder_GetThumbnail,
+ BmpDecoder_GetFrameCount,
+ BmpDecoder_GetFrame
+};
+
+HRESULT BmpDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+ BmpDecoder *This;
+ HRESULT ret;
+
+ TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
+
+ *ppv = NULL;
+
+ if (pUnkOuter) return CLASS_E_NOAGGREGATION;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpDecoder));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->lpVtbl = &BmpDecoder_Vtbl;
+ This->ref = 1;
+ This->initialized = FALSE;
+ This->stream = NULL;
+ This->framedecode = NULL;
+
+ ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
+ IUnknown_Release((IUnknown*)This);
+
+ return ret;
+}
diff --git a/reactos/dll/win32/windowscodecs/bmpencode.c b/reactos/dll/win32/windowscodecs/bmpencode.c
new file mode 100644
index 00000000000..a545103ca6c
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/bmpencode.c
@@ -0,0 +1,598 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#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);
+
+struct bmp_pixelformat {
+ const WICPixelFormatGUID *guid;
+ UINT bpp;
+ DWORD compression;
+ DWORD redmask;
+ DWORD greenmask;
+ DWORD bluemask;
+ DWORD alphamask;
+};
+
+static const struct bmp_pixelformat formats[] = {
+ {&GUID_WICPixelFormat24bppBGR, 24, BI_RGB},
+ {NULL}
+};
+
+typedef struct BmpFrameEncode {
+ const IWICBitmapFrameEncodeVtbl *lpVtbl;
+ LONG ref;
+ IStream *stream;
+ BOOL initialized;
+ UINT width, height;
+ BYTE *bits;
+ const struct bmp_pixelformat *format;
+ double xres, yres;
+ UINT lineswritten;
+ UINT stride;
+ BOOL committed;
+} BmpFrameEncode;
+
+static HRESULT WINAPI BmpFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
+ void **ppv)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI BmpFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI BmpFrameEncode_Release(IWICBitmapFrameEncode *iface)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ if (This->stream) IStream_Release(This->stream);
+ HeapFree(GetProcessHeap(), 0, This->bits);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI BmpFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
+ IPropertyBag2 *pIEncoderOptions)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ TRACE("(%p,%p)\n", iface, pIEncoderOptions);
+
+ if (This->initialized) return WINCODEC_ERR_WRONGSTATE;
+
+ This->initialized = TRUE;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
+ UINT uiWidth, UINT uiHeight)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
+
+ if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
+
+ This->width = uiWidth;
+ This->height = uiHeight;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
+ double dpiX, double dpiY)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
+
+ if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
+
+ This->xres = dpiX;
+ This->yres = dpiY;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ int i;
+ TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
+
+ if (!This->initialized || This->bits) return WINCODEC_ERR_WRONGSTATE;
+
+ for (i=0; formats[i].guid; i++)
+ {
+ if (memcmp(formats[i].guid, pPixelFormat, sizeof(GUID)) == 0)
+ break;
+ }
+
+ if (!formats[i].guid) i = 0;
+
+ This->format = &formats[i];
+ memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
+ UINT cCount, IWICColorContext **ppIColorContext)
+{
+ FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
+ IWICPalette *pIPalette)
+{
+ FIXME("(%p,%p): stub\n", iface, pIPalette);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
+ IWICBitmapSource *pIThumbnail)
+{
+ FIXME("(%p,%p): stub\n", iface, pIThumbnail);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT BmpFrameEncode_AllocateBits(BmpFrameEncode *This)
+{
+ if (!This->bits)
+ {
+ if (!This->initialized || !This->width || !This->height || !This->format)
+ return WINCODEC_ERR_WRONGSTATE;
+
+ This->stride = (((This->width * This->format->bpp)+31)/32)*4;
+ This->bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->stride * This->height);
+ if (!This->bits) return E_OUTOFMEMORY;
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
+ UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ HRESULT hr;
+ WICRect rc;
+ TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
+
+ if (!This->initialized || !This->width || !This->height || !This->format)
+ return WINCODEC_ERR_WRONGSTATE;
+
+ hr = BmpFrameEncode_AllocateBits(This);
+ if (FAILED(hr)) return hr;
+
+ rc.X = 0;
+ rc.Y = 0;
+ rc.Width = This->width;
+ rc.Height = lineCount;
+
+ hr = copy_pixels(This->format->bpp, pbPixels, This->width, lineCount, cbStride,
+ &rc, This->stride, This->stride*(This->height-This->lineswritten),
+ This->bits + This->stride*This->lineswritten);
+
+ if (SUCCEEDED(hr))
+ This->lineswritten += lineCount;
+
+ return hr;
+}
+
+static HRESULT WINAPI BmpFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
+ IWICBitmapSource *pIBitmapSource, WICRect *prc)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ HRESULT hr;
+ WICRect rc;
+ WICPixelFormatGUID guid;
+ TRACE("(%p,%p,%p)\n", iface, pIBitmapSource, prc);
+
+ if (!This->initialized || !This->width || !This->height)
+ 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;
+ }
+
+ if (!prc)
+ {
+ 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;
+ }
+
+ 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;
+}
+
+static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface)
+{
+ BmpFrameEncode *This = (BmpFrameEncode*)iface;
+ BITMAPFILEHEADER bfh;
+ BITMAPV5HEADER bih;
+ UINT info_size;
+ LARGE_INTEGER pos;
+ ULONG byteswritten;
+ HRESULT hr;
+
+ TRACE("(%p)\n", iface);
+
+ if (!This->bits || This->committed || This->height != This->lineswritten)
+ return WINCODEC_ERR_WRONGSTATE;
+
+ bfh.bfType = 0x4d42; /* "BM" */
+ bfh.bfReserved1 = 0;
+ bfh.bfReserved2 = 0;
+
+ bih.bV5Size = info_size = sizeof(BITMAPINFOHEADER);
+ bih.bV5Width = This->width;
+ bih.bV5Height = -This->height; /* top-down 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;
+
+ bfh.bfSize = sizeof(BITMAPFILEHEADER) + info_size + bih.bV5SizeImage;
+ bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + info_size;
+
+ pos.QuadPart = 0;
+ hr = IStream_Seek(This->stream, pos, STREAM_SEEK_SET, NULL);\
+ if (FAILED(hr)) return hr;
+
+ hr = IStream_Write(This->stream, &bfh, sizeof(BITMAPFILEHEADER), &byteswritten);
+ if (FAILED(hr)) return hr;
+ if (byteswritten != sizeof(BITMAPFILEHEADER)) return E_FAIL;
+
+ hr = IStream_Write(This->stream, &bih, info_size, &byteswritten);
+ 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;
+
+ This->committed = TRUE;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
+ IWICMetadataQueryWriter **ppIMetadataQueryWriter)
+{
+ FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
+ return E_NOTIMPL;
+}
+
+static const IWICBitmapFrameEncodeVtbl BmpFrameEncode_Vtbl = {
+ BmpFrameEncode_QueryInterface,
+ BmpFrameEncode_AddRef,
+ BmpFrameEncode_Release,
+ BmpFrameEncode_Initialize,
+ BmpFrameEncode_SetSize,
+ BmpFrameEncode_SetResolution,
+ BmpFrameEncode_SetPixelFormat,
+ BmpFrameEncode_SetColorContexts,
+ BmpFrameEncode_SetPalette,
+ BmpFrameEncode_SetThumbnail,
+ BmpFrameEncode_WritePixels,
+ BmpFrameEncode_WriteSource,
+ BmpFrameEncode_Commit,
+ BmpFrameEncode_GetMetadataQueryWriter
+};
+
+typedef struct BmpEncoder {
+ const IWICBitmapEncoderVtbl *lpVtbl;
+ LONG ref;
+ IStream *stream;
+ IWICBitmapFrameEncode *frame;
+} BmpEncoder;
+
+static HRESULT WINAPI BmpEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
+ void **ppv)
+{
+ BmpEncoder *This = (BmpEncoder*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapEncoder, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI BmpEncoder_AddRef(IWICBitmapEncoder *iface)
+{
+ BmpEncoder *This = (BmpEncoder*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI BmpEncoder_Release(IWICBitmapEncoder *iface)
+{
+ BmpEncoder *This = (BmpEncoder*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ if (This->stream) IStream_Release(This->stream);
+ if (This->frame) IWICBitmapFrameEncode_Release(This->frame);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI BmpEncoder_Initialize(IWICBitmapEncoder *iface,
+ IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
+{
+ BmpEncoder *This = (BmpEncoder*)iface;
+
+ TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
+
+ IStream_AddRef(pIStream);
+ This->stream = pIStream;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
+ GUID *pguidContainerFormat)
+{
+ FIXME("(%p,%s): stub\n", iface, debugstr_guid(pguidContainerFormat));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BmpEncoder_GetEncoderInfo(IWICBitmapEncoder *iface,
+ IWICBitmapEncoderInfo **ppIEncoderInfo)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BmpEncoder_SetColorContexts(IWICBitmapEncoder *iface,
+ UINT cCount, IWICColorContext **ppIColorContext)
+{
+ FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BmpEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *pIPalette)
+{
+ TRACE("(%p,%p)\n", iface, pIPalette);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, pIThumbnail);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
+{
+ TRACE("(%p,%p)\n", iface, pIPreview);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
+ IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
+{
+ BmpEncoder *This = (BmpEncoder*)iface;
+ BmpFrameEncode *encode;
+ HRESULT hr;
+
+ TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
+
+ if (This->frame) return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+
+ if (!This->stream) return WINCODEC_ERR_NOTINITIALIZED;
+
+ hr = CreatePropertyBag2(ppIEncoderOptions);
+ if (FAILED(hr)) return hr;
+
+ encode = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameEncode));
+ if (!encode)
+ {
+ IPropertyBag2_Release(*ppIEncoderOptions);
+ *ppIEncoderOptions = NULL;
+ return E_OUTOFMEMORY;
+ }
+ encode->lpVtbl = &BmpFrameEncode_Vtbl;
+ encode->ref = 2;
+ IStream_AddRef(This->stream);
+ encode->stream = This->stream;
+ encode->initialized = FALSE;
+ encode->width = 0;
+ encode->height = 0;
+ encode->bits = NULL;
+ encode->format = NULL;
+ encode->xres = 0.0;
+ encode->yres = 0.0;
+ encode->lineswritten = 0;
+ encode->committed = FALSE;
+
+ *ppIFrameEncode = (IWICBitmapFrameEncode*)encode;
+ This->frame = (IWICBitmapFrameEncode*)encode;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpEncoder_Commit(IWICBitmapEncoder *iface)
+{
+ BmpEncoder *This = (BmpEncoder*)iface;
+ BmpFrameEncode *frame = (BmpFrameEncode*)This->frame;
+ TRACE("(%p)\n", iface);
+
+ if (!frame || !frame->committed) return WINCODEC_ERR_WRONGSTATE;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI BmpEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
+ IWICMetadataQueryWriter **ppIMetadataQueryWriter)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
+ return E_NOTIMPL;
+}
+
+static const IWICBitmapEncoderVtbl BmpEncoder_Vtbl = {
+ BmpEncoder_QueryInterface,
+ BmpEncoder_AddRef,
+ BmpEncoder_Release,
+ BmpEncoder_Initialize,
+ BmpEncoder_GetContainerFormat,
+ BmpEncoder_GetEncoderInfo,
+ BmpEncoder_SetColorContexts,
+ BmpEncoder_SetPalette,
+ BmpEncoder_SetThumbnail,
+ BmpEncoder_SetPreview,
+ BmpEncoder_CreateNewFrame,
+ BmpEncoder_Commit,
+ BmpEncoder_GetMetadataQueryWriter
+};
+
+HRESULT BmpEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+ BmpEncoder *This;
+ HRESULT ret;
+
+ TRACE("(%p,%s,%p)\n", pUnkOuter, 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->ref = 1;
+ This->stream = NULL;
+ This->frame = NULL;
+
+ ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
+ IUnknown_Release((IUnknown*)This);
+
+ return ret;
+}
diff --git a/reactos/dll/win32/windowscodecs/clsfactory.c b/reactos/dll/win32/windowscodecs/clsfactory.c
new file mode 100644
index 00000000000..0ce08b3f22b
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/clsfactory.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "ocidl.h"
+#include "initguid.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+typedef struct {
+ REFCLSID classid;
+ HRESULT (*constructor)(IUnknown*,REFIID,void**);
+} classinfo;
+
+static classinfo wic_classes[] = {
+ {&CLSID_WICImagingFactory, ImagingFactory_CreateInstance},
+ {&CLSID_WICBmpDecoder, BmpDecoder_CreateInstance},
+ {&CLSID_WICBmpEncoder, BmpEncoder_CreateInstance},
+ {&CLSID_WICGifDecoder, GifDecoder_CreateInstance},
+ {&CLSID_WICIcoDecoder, IcoDecoder_CreateInstance},
+ {&CLSID_WICDefaultFormatConverter, FormatConverter_CreateInstance},
+ {0}};
+
+typedef struct {
+ const IClassFactoryVtbl *lpIClassFactoryVtbl;
+ LONG ref;
+ classinfo *info;
+} ClassFactoryImpl;
+
+static HRESULT WINAPI ClassFactoryImpl_QueryInterface(IClassFactory *iface,
+ REFIID iid, void **ppv)
+{
+ ClassFactoryImpl *This = (ClassFactoryImpl*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IClassFactory, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI ClassFactoryImpl_AddRef(IClassFactory *iface)
+{
+ ClassFactoryImpl *This = (ClassFactoryImpl*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI ClassFactoryImpl_Release(IClassFactory *iface)
+{
+ ClassFactoryImpl *This = (ClassFactoryImpl*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ HeapFree(GetProcessHeap(), 0, This);
+
+ return ref;
+}
+
+static HRESULT WINAPI ClassFactoryImpl_CreateInstance(IClassFactory *iface,
+ IUnknown *pUnkOuter, REFIID riid, void **ppv)
+{
+ ClassFactoryImpl *This = (ClassFactoryImpl*)iface;
+
+ return This->info->constructor(pUnkOuter, riid, ppv);
+}
+
+static HRESULT WINAPI ClassFactoryImpl_LockServer(IClassFactory *iface, BOOL lock)
+{
+ TRACE("(%p, %i): stub\n", iface, lock);
+ return E_NOTIMPL;
+}
+
+static const IClassFactoryVtbl ClassFactoryImpl_Vtbl = {
+ ClassFactoryImpl_QueryInterface,
+ ClassFactoryImpl_AddRef,
+ ClassFactoryImpl_Release,
+ ClassFactoryImpl_CreateInstance,
+ ClassFactoryImpl_LockServer
+};
+
+static HRESULT ClassFactoryImpl_Constructor(classinfo *info, REFIID riid, LPVOID *ppv)
+{
+ ClassFactoryImpl *This;
+ HRESULT ret;
+
+ *ppv = NULL;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassFactoryImpl));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->lpIClassFactoryVtbl = &ClassFactoryImpl_Vtbl;
+ This->ref = 1;
+ This->info = info;
+
+ ret = IClassFactory_QueryInterface((IClassFactory*)This, riid, ppv);
+ IClassFactory_Release((IClassFactory*)This);
+
+ return ret;
+}
+
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
+{
+ HRESULT ret;
+ classinfo *info=NULL;
+ int i;
+
+ TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
+
+ if (!rclsid || !iid || !ppv)
+ return E_INVALIDARG;
+
+ *ppv = NULL;
+
+ for (i=0; wic_classes[i].classid; i++)
+ {
+ if (IsEqualCLSID(wic_classes[i].classid, rclsid))
+ {
+ info = &wic_classes[i];
+ break;
+ }
+ }
+
+ if (info)
+ ret = ClassFactoryImpl_Constructor(info, iid, ppv);
+ else
+ ret = CLASS_E_CLASSNOTAVAILABLE;
+
+ TRACE("<-- %08X\n", ret);
+ return ret;
+}
diff --git a/reactos/dll/win32/windowscodecs/converter.c b/reactos/dll/win32/windowscodecs/converter.c
new file mode 100644
index 00000000000..7db56eafd6a
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/converter.c
@@ -0,0 +1,659 @@
+/*
+ * Copyright 2009 Vincent Povirk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+struct FormatConverter;
+
+enum pixelformat {
+ format_1bppIndexed,
+ format_4bppIndexed,
+ format_8bppIndexed,
+ format_16bppBGR555,
+ format_16bppBGR565,
+ format_24bppBGR,
+ format_32bppBGR,
+ format_32bppBGRA
+};
+
+typedef HRESULT (*copyfunc)(struct FormatConverter *This, const WICRect *prc,
+ UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format);
+
+struct pixelformatinfo {
+ enum pixelformat format;
+ const WICPixelFormatGUID *guid;
+ copyfunc copy_function;
+};
+
+typedef struct FormatConverter {
+ const IWICFormatConverterVtbl *lpVtbl;
+ LONG ref;
+ IWICBitmapSource *source;
+ const struct pixelformatinfo *dst_format, *src_format;
+ WICBitmapDitherType dither;
+ double alpha_threshold;
+ WICBitmapPaletteType palette_type;
+} FormatConverter;
+
+static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRect *prc,
+ UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
+{
+ switch (source_format)
+ {
+ case format_1bppIndexed:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+ BYTE *srcdata;
+ UINT srcstride, srcdatasize;
+ const BYTE *srcrow;
+ const BYTE *srcbyte;
+ BYTE *dstrow;
+ DWORD *dstpixel;
+ WICColor colors[2];
+ IWICPalette *palette;
+ UINT actualcolors;
+
+ res = PaletteImpl_Create(&palette);
+ if (FAILED(res)) return res;
+
+ res = IWICBitmapSource_CopyPalette(This->source, palette);
+ if (SUCCEEDED(res))
+ res = IWICPalette_GetColors(palette, 2, colors, &actualcolors);
+
+ IWICPalette_Release(palette);
+
+ if (FAILED(res)) return res;
+
+ srcstride = (prc->Width+7)/8;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
+
+ if (SUCCEEDED(res))
+ {
+ srcrow = srcdata;
+ dstrow = pbBuffer;
+ for (y=0; yHeight; y++) {
+ srcbyte=(const BYTE*)srcrow;
+ dstpixel=(DWORD*)dstrow;
+ for (x=0; xWidth; x+=8) {
+ BYTE srcval;
+ srcval=*srcbyte++;
+ *dstpixel++ = colors[srcval>>7&1];
+ if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>6&1];
+ if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>5&1];
+ if (x+3 < prc->Width) *dstpixel++ = colors[srcval>>4&1];
+ if (x+4 < prc->Width) *dstpixel++ = colors[srcval>>3&1];
+ if (x+5 < prc->Width) *dstpixel++ = colors[srcval>>2&1];
+ if (x+6 < prc->Width) *dstpixel++ = colors[srcval>>1&1];
+ if (x+7 < prc->Width) *dstpixel++ = colors[srcval&1];
+ }
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
+
+ return res;
+ }
+ return S_OK;
+ case format_4bppIndexed:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+ BYTE *srcdata;
+ UINT srcstride, srcdatasize;
+ const BYTE *srcrow;
+ const BYTE *srcbyte;
+ BYTE *dstrow;
+ DWORD *dstpixel;
+ WICColor colors[16];
+ IWICPalette *palette;
+ UINT actualcolors;
+
+ res = PaletteImpl_Create(&palette);
+ if (FAILED(res)) return res;
+
+ res = IWICBitmapSource_CopyPalette(This->source, palette);
+ if (SUCCEEDED(res))
+ res = IWICPalette_GetColors(palette, 16, colors, &actualcolors);
+
+ IWICPalette_Release(palette);
+
+ if (FAILED(res)) return res;
+
+ srcstride = (prc->Width+1)/2;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
+
+ if (SUCCEEDED(res))
+ {
+ srcrow = srcdata;
+ dstrow = pbBuffer;
+ for (y=0; yHeight; y++) {
+ srcbyte=(const BYTE*)srcrow;
+ dstpixel=(DWORD*)dstrow;
+ for (x=0; xWidth; x+=2) {
+ BYTE srcval;
+ srcval=*srcbyte++;
+ *dstpixel++ = colors[srcval>>4];
+ if (x+1 < prc->Width) *dstpixel++ = colors[srcval&0xf];
+ }
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
+
+ return res;
+ }
+ return S_OK;
+ case format_8bppIndexed:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+ BYTE *srcdata;
+ UINT srcstride, srcdatasize;
+ const BYTE *srcrow;
+ const BYTE *srcbyte;
+ BYTE *dstrow;
+ DWORD *dstpixel;
+ WICColor colors[256];
+ IWICPalette *palette;
+ UINT actualcolors;
+
+ res = PaletteImpl_Create(&palette);
+ if (FAILED(res)) return res;
+
+ res = IWICBitmapSource_CopyPalette(This->source, palette);
+ if (SUCCEEDED(res))
+ res = IWICPalette_GetColors(palette, 256, colors, &actualcolors);
+
+ IWICPalette_Release(palette);
+
+ if (FAILED(res)) return res;
+
+ srcstride = prc->Width;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
+
+ if (SUCCEEDED(res))
+ {
+ srcrow = srcdata;
+ dstrow = pbBuffer;
+ for (y=0; yHeight; y++) {
+ srcbyte=(const BYTE*)srcrow;
+ dstpixel=(DWORD*)dstrow;
+ for (x=0; xWidth; x++)
+ *dstpixel++ = colors[*srcbyte++];
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
+
+ return res;
+ }
+ return S_OK;
+ case format_16bppBGR555:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+ BYTE *srcdata;
+ UINT srcstride, srcdatasize;
+ const BYTE *srcrow;
+ const WORD *srcpixel;
+ BYTE *dstrow;
+ DWORD *dstpixel;
+
+ srcstride = 2 * prc->Width;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
+
+ if (SUCCEEDED(res))
+ {
+ srcrow = srcdata;
+ dstrow = pbBuffer;
+ for (y=0; yHeight; y++) {
+ srcpixel=(const WORD*)srcrow;
+ dstpixel=(DWORD*)dstrow;
+ for (x=0; xWidth; x++) {
+ WORD srcval;
+ srcval=*srcpixel++;
+ *dstpixel++=0xff000000 | /* constant 255 alpha */
+ ((srcval << 9) & 0xf80000) | /* r */
+ ((srcval << 4) & 0x070000) | /* r - 3 bits */
+ ((srcval << 6) & 0x00f800) | /* g */
+ ((srcval << 1) & 0x000700) | /* g - 3 bits */
+ ((srcval << 3) & 0x0000f8) | /* b */
+ ((srcval >> 2) & 0x000007); /* b - 3 bits */
+ }
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
+
+ return res;
+ }
+ return S_OK;
+ case format_16bppBGR565:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+ BYTE *srcdata;
+ UINT srcstride, srcdatasize;
+ const BYTE *srcrow;
+ const WORD *srcpixel;
+ BYTE *dstrow;
+ DWORD *dstpixel;
+
+ srcstride = 2 * prc->Width;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
+
+ if (SUCCEEDED(res))
+ {
+ srcrow = srcdata;
+ dstrow = pbBuffer;
+ for (y=0; yHeight; y++) {
+ srcpixel=(const WORD*)srcrow;
+ dstpixel=(DWORD*)dstrow;
+ for (x=0; xWidth; x++) {
+ WORD srcval;
+ srcval=*srcpixel++;
+ *dstpixel++=0xff000000 | /* constant 255 alpha */
+ ((srcval << 8) & 0xf80000) | /* r */
+ ((srcval << 3) & 0x070000) | /* r - 3 bits */
+ ((srcval << 5) & 0x00fc00) | /* g */
+ ((srcval >> 1) & 0x000300) | /* g - 2 bits */
+ ((srcval << 3) & 0x0000f8) | /* b */
+ ((srcval >> 2) & 0x000007); /* b - 3 bits */
+ }
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
+
+ return res;
+ }
+ return S_OK;
+ case format_24bppBGR:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+ BYTE *srcdata;
+ UINT srcstride, srcdatasize;
+ const BYTE *srcrow;
+ const BYTE *srcpixel;
+ BYTE *dstrow;
+ BYTE *dstpixel;
+
+ srcstride = 3 * prc->Width;
+ srcdatasize = srcstride * prc->Height;
+
+ srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
+ if (!srcdata) return E_OUTOFMEMORY;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
+
+ if (SUCCEEDED(res))
+ {
+ srcrow = srcdata;
+ dstrow = pbBuffer;
+ for (y=0; yHeight; y++) {
+ srcpixel=srcrow;
+ dstpixel=dstrow;
+ for (x=0; xWidth; x++) {
+ *dstpixel++=*srcpixel++; /* blue */
+ *dstpixel++=*srcpixel++; /* green */
+ *dstpixel++=*srcpixel++; /* red */
+ *dstpixel++=255; /* alpha */
+ }
+ srcrow += srcstride;
+ dstrow += cbStride;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, srcdata);
+
+ return res;
+ }
+ return S_OK;
+ case format_32bppBGR:
+ if (prc)
+ {
+ HRESULT res;
+ UINT x, y;
+
+ res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
+ if (FAILED(res)) return res;
+
+ /* set all alpha values to 255 */
+ for (y=0; yHeight; y++)
+ for (x=0; xWidth; x++)
+ pbBuffer[cbStride*y+4*x+3] = 0xff;
+ }
+ return S_OK;
+ case format_32bppBGRA:
+ if (prc)
+ return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
+ return S_OK;
+ default:
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+ }
+}
+
+static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRect *prc,
+ UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
+{
+ switch (source_format)
+ {
+ case format_32bppBGR:
+ case format_32bppBGRA:
+ if (prc)
+ return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
+ return S_OK;
+ default:
+ return copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
+ }
+}
+
+static const struct pixelformatinfo supported_formats[] = {
+ {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL},
+ {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL},
+ {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, NULL},
+ {format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL},
+ {format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL},
+ {format_24bppBGR, &GUID_WICPixelFormat24bppBGR, NULL},
+ {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR},
+ {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA},
+ {0}
+};
+
+static const struct pixelformatinfo *get_formatinfo(const WICPixelFormatGUID *format)
+{
+ UINT i;
+
+ for (i=0; supported_formats[i].guid; i++)
+ if (IsEqualGUID(supported_formats[i].guid, format)) return &supported_formats[i];
+
+ return NULL;
+}
+
+static HRESULT WINAPI FormatConverter_QueryInterface(IWICFormatConverter *iface, REFIID iid,
+ void **ppv)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapSource, iid) ||
+ IsEqualIID(&IID_IWICFormatConverter, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter *iface)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ if (This->source) IWICBitmapSource_Release(This->source);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI FormatConverter_GetSize(IWICFormatConverter *iface,
+ UINT *puiWidth, UINT *puiHeight)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+
+ TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
+
+ if (This->source)
+ return IWICBitmapSource_GetSize(This->source, puiWidth, puiHeight);
+ else
+ return WINCODEC_ERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI FormatConverter_GetPixelFormat(IWICFormatConverter *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+
+ TRACE("(%p,%p): stub\n", iface, pPixelFormat);
+
+ if (This->source)
+ memcpy(pPixelFormat, This->dst_format->guid, sizeof(GUID));
+ else
+ return WINCODEC_ERR_NOTINITIALIZED;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface,
+ double *pDpiX, double *pDpiY)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+
+ TRACE("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
+
+ if (This->source)
+ return IWICBitmapSource_GetResolution(This->source, pDpiX, pDpiY);
+ else
+ return WINCODEC_ERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface,
+ IWICPalette *pIPalette)
+{
+ FIXME("(%p,%p): stub\n", iface, pIPalette);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
+ const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+ TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
+
+ if (This->source)
+ return This->dst_format->copy_function(This, prc, cbStride, cbBufferSize,
+ pbBuffer, This->src_format->format);
+ else
+ return WINCODEC_ERR_NOTINITIALIZED;
+}
+
+static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
+ IWICBitmapSource *pISource, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
+ IWICPalette *pIPalette, double alphaThresholdPercent, WICBitmapPaletteType paletteTranslate)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+ const struct pixelformatinfo *srcinfo, *dstinfo;
+ static INT fixme=0;
+ GUID srcFormat;
+ HRESULT res;
+
+ TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface, pISource, debugstr_guid(dstFormat),
+ dither, pIPalette, alphaThresholdPercent, paletteTranslate);
+
+ if (pIPalette && !fixme++) FIXME("ignoring palette\n");
+
+ if (This->source) return WINCODEC_ERR_WRONGSTATE;
+
+ res = IWICBitmapSource_GetPixelFormat(pISource, &srcFormat);
+ if (FAILED(res)) return res;
+
+ srcinfo = get_formatinfo(&srcFormat);
+ if (!srcinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+
+ dstinfo = get_formatinfo(dstFormat);
+ if (!dstinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+
+ if (dstinfo->copy_function)
+ {
+ IWICBitmapSource_AddRef(pISource);
+ This->source = pISource;
+ This->src_format = srcinfo;
+ This->dst_format = dstinfo;
+ This->dither = dither;
+ This->alpha_threshold = alphaThresholdPercent;
+ This->palette_type = paletteTranslate;
+ }
+ else
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI FormatConverter_CanConvert(IWICFormatConverter *iface,
+ REFWICPixelFormatGUID srcPixelFormat, REFWICPixelFormatGUID dstPixelFormat,
+ BOOL *pfCanConvert)
+{
+ FormatConverter *This = (FormatConverter*)iface;
+ const struct pixelformatinfo *srcinfo, *dstinfo;
+
+ TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(srcPixelFormat),
+ debugstr_guid(dstPixelFormat), pfCanConvert);
+
+ srcinfo = get_formatinfo(srcPixelFormat);
+ if (!srcinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+
+ dstinfo = get_formatinfo(dstPixelFormat);
+ if (!dstinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
+
+ if (dstinfo->copy_function &&
+ SUCCEEDED(dstinfo->copy_function(This, NULL, 0, 0, NULL, dstinfo->format)))
+ *pfCanConvert = TRUE;
+ else
+ *pfCanConvert = FALSE;
+
+ return S_OK;
+}
+
+static const IWICFormatConverterVtbl FormatConverter_Vtbl = {
+ FormatConverter_QueryInterface,
+ FormatConverter_AddRef,
+ FormatConverter_Release,
+ FormatConverter_GetSize,
+ FormatConverter_GetPixelFormat,
+ FormatConverter_GetResolution,
+ FormatConverter_CopyPalette,
+ FormatConverter_CopyPixels,
+ FormatConverter_Initialize,
+ FormatConverter_CanConvert
+};
+
+HRESULT FormatConverter_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+ FormatConverter *This;
+ HRESULT ret;
+
+ TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
+
+ *ppv = NULL;
+
+ if (pUnkOuter) return CLASS_E_NOAGGREGATION;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->lpVtbl = &FormatConverter_Vtbl;
+ This->ref = 1;
+ This->source = NULL;
+
+ ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
+ IUnknown_Release((IUnknown*)This);
+
+ return ret;
+}
diff --git a/reactos/dll/win32/windowscodecs/gifformat.c b/reactos/dll/win32/windowscodecs/gifformat.c
new file mode 100644
index 00000000000..0597b1afbe3
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/gifformat.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "ungif.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+typedef struct {
+ const IWICBitmapDecoderVtbl *lpVtbl;
+ LONG ref;
+ BOOL initialized;
+ GifFileType *gif;
+} GifDecoder;
+
+typedef struct {
+ const IWICBitmapFrameDecodeVtbl *lpVtbl;
+ LONG ref;
+ SavedImage *frame;
+ GifDecoder *parent;
+} GifFrameDecode;
+
+static HRESULT WINAPI GifFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
+ void **ppv)
+{
+ GifFrameDecode *This = (GifFrameDecode*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapSource, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI GifFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
+{
+ GifFrameDecode *This = (GifFrameDecode*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI GifFrameDecode_Release(IWICBitmapFrameDecode *iface)
+{
+ GifFrameDecode *This = (GifFrameDecode*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ IUnknown_Release((IUnknown*)This->parent);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI GifFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
+ UINT *puiWidth, UINT *puiHeight)
+{
+ GifFrameDecode *This = (GifFrameDecode*)iface;
+ TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
+
+ *puiWidth = This->frame->ImageDesc.Width;
+ *puiHeight = This->frame->ImageDesc.Height;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI GifFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ memcpy(pPixelFormat, &GUID_WICPixelFormat8bppIndexed, sizeof(GUID));
+
+ return S_OK;
+}
+
+static HRESULT WINAPI GifFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
+ double *pDpiX, double *pDpiY)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI GifFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
+ IWICPalette *pIPalette)
+{
+ GifFrameDecode *This = (GifFrameDecode*)iface;
+ WICColor colors[256];
+ ColorMapObject *cm = This->frame->ImageDesc.ColorMap;
+ int i, trans;
+ ExtensionBlock *eb;
+ TRACE("(%p,%p)\n", iface, pIPalette);
+
+ if (!cm) cm = This->parent->gif->SColorMap;
+
+ if (cm->ColorCount > 256)
+ {
+ ERR("GIF contains %i colors???\n", cm->ColorCount);
+ return E_FAIL;
+ }
+
+ for (i = 0; i < cm->ColorCount; i++) {
+ colors[i] = 0xff000000| /* alpha */
+ cm->Colors[i].Red << 16|
+ cm->Colors[i].Green << 8|
+ cm->Colors[i].Blue;
+ }
+
+ /* look for the transparent color extension */
+ for (i = 0; i < This->frame->ExtensionBlockCount; ++i) {
+ eb = This->frame->ExtensionBlocks + i;
+ if (eb->Function == 0xF9 && eb->ByteCount == 4) {
+ if ((eb->Bytes[0] & 1) == 1) {
+ trans = (unsigned char)eb->Bytes[3];
+ colors[trans] &= 0xffffff; /* set alpha to 0 */
+ break;
+ }
+ }
+ }
+
+ IWICPalette_InitializeCustom(pIPalette, colors, cm->ColorCount);
+
+ return S_OK;
+}
+
+static HRESULT copy_interlaced_pixels(const BYTE *srcbuffer,
+ UINT srcwidth, UINT srcheight, INT srcstride, const WICRect *rc,
+ UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
+{
+ UINT row_offset; /* number of bytes into the source rows where the data starts */
+ const BYTE *src;
+ BYTE *dst;
+ UINT y;
+
+ if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
+ return E_INVALIDARG;
+
+ if (dststride < rc->Width)
+ return E_INVALIDARG;
+
+ if ((dststride * rc->Height) > dstbuffersize)
+ return E_INVALIDARG;
+
+ row_offset = rc->X;
+
+ dst = dstbuffer;
+ for (y=rc->Y; y-rc->Y < rc->Height; y++)
+ {
+ if (y%8 == 0)
+ src = srcbuffer + srcstride * (y/8);
+ else if (y%4 == 0)
+ src = srcbuffer + srcstride * ((srcheight+7)/8 + y/8);
+ else if (y%2 == 0)
+ src = srcbuffer + srcstride * ((srcheight+3)/4 + y/4);
+ else /* y%2 == 1 */
+ src = srcbuffer + srcstride * ((srcheight+1)/2 + y/2);
+ src += row_offset;
+ memcpy(dst, src, rc->Width);
+ dst += dststride;
+ }
+ return S_OK;
+}
+
+static HRESULT WINAPI GifFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
+ const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
+{
+ GifFrameDecode *This = (GifFrameDecode*)iface;
+ TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
+
+ if (This->frame->ImageDesc.Interlace)
+ {
+ return copy_interlaced_pixels(This->frame->RasterBits, This->frame->ImageDesc.Width,
+ This->frame->ImageDesc.Height, This->frame->ImageDesc.Width,
+ prc, cbStride, cbBufferSize, pbBuffer);
+ }
+ else
+ {
+ return copy_pixels(8, This->frame->RasterBits, This->frame->ImageDesc.Width,
+ This->frame->ImageDesc.Height, This->frame->ImageDesc.Width,
+ prc, cbStride, cbBufferSize, pbBuffer);
+ }
+}
+
+static HRESULT WINAPI GifFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+ TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI GifFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI GifFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static const IWICBitmapFrameDecodeVtbl GifFrameDecode_Vtbl = {
+ GifFrameDecode_QueryInterface,
+ GifFrameDecode_AddRef,
+ GifFrameDecode_Release,
+ GifFrameDecode_GetSize,
+ GifFrameDecode_GetPixelFormat,
+ GifFrameDecode_GetResolution,
+ GifFrameDecode_CopyPalette,
+ GifFrameDecode_CopyPixels,
+ GifFrameDecode_GetMetadataQueryReader,
+ GifFrameDecode_GetColorContexts,
+ GifFrameDecode_GetThumbnail
+};
+
+static HRESULT WINAPI GifDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
+ void **ppv)
+{
+ GifDecoder *This = (GifDecoder*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI GifDecoder_AddRef(IWICBitmapDecoder *iface)
+{
+ GifDecoder *This = (GifDecoder*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI GifDecoder_Release(IWICBitmapDecoder *iface)
+{
+ GifDecoder *This = (GifDecoder*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ DGifCloseFile(This->gif);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI GifDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
+ DWORD *pdwCapability)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
+ return E_NOTIMPL;
+}
+
+static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
+ IStream *stream = gif->UserData;
+ ULONG bytesread;
+ HRESULT hr;
+
+ if (!stream)
+ {
+ ERR("attempting to read file after initialization\n");
+ return 0;
+ }
+
+ hr = IStream_Read(stream, data, len, &bytesread);
+ if (hr != S_OK) bytesread = 0;
+ return bytesread;
+}
+
+static HRESULT WINAPI GifDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
+ WICDecodeOptions cacheOptions)
+{
+ GifDecoder *This = (GifDecoder*)iface;
+ LARGE_INTEGER seek;
+ int ret;
+
+ TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
+
+ if (This->initialized || This->gif)
+ {
+ WARN("already initialized\n");
+ return WINCODEC_ERR_WRONGSTATE;
+ }
+
+ /* seek to start of stream */
+ seek.QuadPart = 0;
+ IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
+
+ /* read all data from the stream */
+ This->gif = DGifOpen((void*)pIStream, _gif_inputfunc);
+ if (!This->gif) return E_FAIL;
+
+ ret = DGifSlurp(This->gif);
+ if (ret == GIF_ERROR) return E_FAIL;
+
+ /* make sure we don't use the stream after this method returns */
+ This->gif->UserData = NULL;
+
+ This->initialized = TRUE;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI GifDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
+ GUID *pguidContainerFormat)
+{
+ memcpy(pguidContainerFormat, &GUID_ContainerFormatGif, sizeof(GUID));
+ return S_OK;
+}
+
+static HRESULT WINAPI GifDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
+ IWICBitmapDecoderInfo **ppIDecoderInfo)
+{
+ HRESULT hr;
+ IWICComponentInfo *compinfo;
+
+ TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
+
+ hr = CreateComponentInfo(&CLSID_WICGifDecoder, &compinfo);
+ if (FAILED(hr)) return hr;
+
+ hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
+ (void**)ppIDecoderInfo);
+
+ IWICComponentInfo_Release(compinfo);
+
+ return hr;
+}
+
+static HRESULT WINAPI GifDecoder_CopyPalette(IWICBitmapDecoder *iface,
+ IWICPalette *pIPalette)
+{
+ TRACE("(%p,%p)\n", iface, pIPalette);
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
+}
+
+static HRESULT WINAPI GifDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+ TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI GifDecoder_GetPreview(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIBitmapSource)
+{
+ TRACE("(%p,%p)\n", iface, ppIBitmapSource);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI GifDecoder_GetColorContexts(IWICBitmapDecoder *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI GifDecoder_GetThumbnail(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static HRESULT WINAPI GifDecoder_GetFrameCount(IWICBitmapDecoder *iface,
+ UINT *pCount)
+{
+ GifDecoder *This = (GifDecoder*)iface;
+ TRACE("(%p,%p)\n", iface, pCount);
+
+ if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
+
+ *pCount = This->gif->ImageCount;
+
+ TRACE("<- %u\n", *pCount);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI GifDecoder_GetFrame(IWICBitmapDecoder *iface,
+ UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
+{
+ GifDecoder *This = (GifDecoder*)iface;
+ GifFrameDecode *result;
+ TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
+
+ if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
+
+ if (index >= This->gif->ImageCount) return E_INVALIDARG;
+
+ result = HeapAlloc(GetProcessHeap(), 0, sizeof(GifFrameDecode));
+ if (!result) return E_OUTOFMEMORY;
+
+ result->lpVtbl = &GifFrameDecode_Vtbl;
+ result->ref = 1;
+ result->frame = &This->gif->SavedImages[index];
+ IWICBitmapDecoder_AddRef(iface);
+ result->parent = This;
+
+ *ppIBitmapFrame = (IWICBitmapFrameDecode*)result;
+
+ return S_OK;
+}
+
+static const IWICBitmapDecoderVtbl GifDecoder_Vtbl = {
+ GifDecoder_QueryInterface,
+ GifDecoder_AddRef,
+ GifDecoder_Release,
+ GifDecoder_QueryCapability,
+ GifDecoder_Initialize,
+ GifDecoder_GetContainerFormat,
+ GifDecoder_GetDecoderInfo,
+ GifDecoder_CopyPalette,
+ GifDecoder_GetMetadataQueryReader,
+ GifDecoder_GetPreview,
+ GifDecoder_GetColorContexts,
+ GifDecoder_GetThumbnail,
+ GifDecoder_GetFrameCount,
+ GifDecoder_GetFrame
+};
+
+HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+ GifDecoder *This;
+ HRESULT ret;
+
+ TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
+
+ *ppv = NULL;
+
+ if (pUnkOuter) return CLASS_E_NOAGGREGATION;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(GifDecoder));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->lpVtbl = &GifDecoder_Vtbl;
+ This->ref = 1;
+ This->initialized = FALSE;
+ This->gif = NULL;
+
+ ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
+ IUnknown_Release((IUnknown*)This);
+
+ return ret;
+}
diff --git a/reactos/dll/win32/windowscodecs/icoformat.c b/reactos/dll/win32/windowscodecs/icoformat.c
new file mode 100644
index 00000000000..ab30ab0a8af
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/icoformat.c
@@ -0,0 +1,797 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+#include "pshpack1.h"
+
+typedef struct {
+ BYTE bWidth;
+ BYTE bHeight;
+ BYTE bColorCount;
+ BYTE bReserved;
+ WORD wPlanes;
+ WORD wBitCount;
+ DWORD dwDIBSize;
+ DWORD dwDIBOffset;
+} ICONDIRENTRY;
+
+typedef struct
+{
+ WORD idReserved;
+ WORD idType;
+ WORD idCount;
+} ICONHEADER;
+
+#include "poppack.h"
+
+typedef struct {
+ const IWICBitmapDecoderVtbl *lpVtbl;
+ LONG ref;
+ BOOL initialized;
+ IStream *stream;
+ ICONHEADER header;
+} IcoDecoder;
+
+typedef struct {
+ const IWICBitmapFrameDecodeVtbl *lpVtbl;
+ LONG ref;
+ ICONDIRENTRY entry;
+ IcoDecoder *parent;
+ BYTE *bits;
+} IcoFrameDecode;
+
+static HRESULT WINAPI IcoFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
+ void **ppv)
+{
+ IcoFrameDecode *This = (IcoFrameDecode*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICBitmapSource, iid) ||
+ IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI IcoFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
+{
+ IcoFrameDecode *This = (IcoFrameDecode*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI IcoFrameDecode_Release(IWICBitmapFrameDecode *iface)
+{
+ IcoFrameDecode *This = (IcoFrameDecode*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ IUnknown_Release((IUnknown*)This->parent);
+ HeapFree(GetProcessHeap(), 0, This->bits);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI IcoFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
+ UINT *puiWidth, UINT *puiHeight)
+{
+ IcoFrameDecode *This = (IcoFrameDecode*)iface;
+
+ *puiWidth = This->entry.bWidth ? This->entry.bWidth : 256;
+ *puiHeight = This->entry.bHeight ? This->entry.bHeight : 256;
+
+ TRACE("(%p) -> (%i,%i)\n", iface, *puiWidth, *puiHeight);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI IcoFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
+ WICPixelFormatGUID *pPixelFormat)
+{
+ memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
+ return S_OK;
+}
+
+static HRESULT WINAPI IcoFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
+ double *pDpiX, double *pDpiY)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IcoFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
+ IWICPalette *pIPalette)
+{
+ TRACE("(%p,%p)\n", iface, pIPalette);
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
+}
+
+static inline void pixel_set_trans(DWORD* pixel, BOOL transparent)
+{
+ if (transparent) *pixel = 0;
+ else *pixel |= 0xff000000;
+}
+
+static HRESULT IcoFrameDecode_ReadPixels(IcoFrameDecode *This)
+{
+ BITMAPINFOHEADER bih;
+ DWORD colors[256];
+ UINT colorcount=0;
+ LARGE_INTEGER seek;
+ ULONG bytesread;
+ HRESULT hr;
+ BYTE *tempdata = NULL;
+ BYTE *bits = NULL;
+ UINT bitsStride;
+ UINT bitsSize;
+ UINT width, height;
+
+ width = This->entry.bWidth ? This->entry.bWidth : 256;
+ height = This->entry.bHeight ? This->entry.bHeight : 256;
+
+ /* read the BITMAPINFOHEADER */
+ seek.QuadPart = This->entry.dwDIBOffset;
+ hr = IStream_Seek(This->parent->stream, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto fail;
+
+ hr = IStream_Read(This->parent->stream, &bih, sizeof(BITMAPINFOHEADER), &bytesread);
+ if (FAILED(hr) || bytesread != sizeof(BITMAPINFOHEADER)) goto fail;
+
+ if (This->entry.wBitCount <= 8)
+ {
+ /* read the palette */
+ colorcount = This->entry.bColorCount ? This->entry.bColorCount : 256;
+
+ hr = IStream_Read(This->parent->stream, colors, sizeof(RGBQUAD)*colorcount, &bytesread);
+ if (FAILED(hr) || bytesread != sizeof(RGBQUAD)*colorcount) goto fail;
+ }
+
+ bitsStride = width * 4;
+ bitsSize = bitsStride * height;
+
+ /* read the XOR data */
+ switch (This->entry.wBitCount)
+ {
+ case 1:
+ {
+ UINT xorBytesPerRow = (width+31)/32*4;
+ UINT xorBytes = xorBytesPerRow * height;
+ INT xorStride;
+ BYTE *xorRow;
+ BYTE *bitsRow;
+ UINT x, y;
+
+ tempdata = HeapAlloc(GetProcessHeap(), 0, xorBytes);
+ if (!tempdata)
+ {
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ hr = IStream_Read(This->parent->stream, tempdata, xorBytes, &bytesread);
+ if (FAILED(hr) || bytesread != xorBytes) goto fail;
+
+ if (bih.biHeight > 0) /* bottom-up DIB */
+ {
+ xorStride = -xorBytesPerRow;
+ xorRow = tempdata + (height-1)*xorBytesPerRow;
+ }
+ else /* top-down DIB */
+ {
+ xorStride = xorBytesPerRow;
+ xorRow = tempdata;
+ }
+
+ bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
+
+ /* palette-map the 1-bit data */
+ bitsRow = bits;
+ for (y=0; y>7];
+ if (x+1 < width) *bitsPixel++ = colors[xorVal>>6&1];
+ if (x+2 < width) *bitsPixel++ = colors[xorVal>>5&1];
+ if (x+3 < width) *bitsPixel++ = colors[xorVal>>4&1];
+ if (x+4 < width) *bitsPixel++ = colors[xorVal>>3&1];
+ if (x+5 < width) *bitsPixel++ = colors[xorVal>>2&1];
+ if (x+6 < width) *bitsPixel++ = colors[xorVal>>1&1];
+ if (x+7 < width) *bitsPixel++ = colors[xorVal&1];
+ }
+ xorRow += xorStride;
+ bitsRow += bitsStride;
+ }
+
+ HeapFree(GetProcessHeap(), 0, tempdata);
+ break;
+ }
+ case 4:
+ {
+ UINT xorBytesPerRow = (width+7)/8*4;
+ UINT xorBytes = xorBytesPerRow * height;
+ INT xorStride;
+ BYTE *xorRow;
+ BYTE *bitsRow;
+ UINT x, y;
+
+ tempdata = HeapAlloc(GetProcessHeap(), 0, xorBytes);
+ if (!tempdata)
+ {
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ hr = IStream_Read(This->parent->stream, tempdata, xorBytes, &bytesread);
+ if (FAILED(hr) || bytesread != xorBytes) goto fail;
+
+ if (bih.biHeight > 0) /* bottom-up DIB */
+ {
+ xorStride = -xorBytesPerRow;
+ xorRow = tempdata + (height-1)*xorBytesPerRow;
+ }
+ else /* top-down DIB */
+ {
+ xorStride = xorBytesPerRow;
+ xorRow = tempdata;
+ }
+
+ bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
+
+ /* palette-map the 4-bit data */
+ bitsRow = bits;
+ for (y=0; y>4];
+ if (x+1 < width) *bitsPixel++ = colors[xorVal&0xf];
+ }
+ xorRow += xorStride;
+ bitsRow += bitsStride;
+ }
+
+ HeapFree(GetProcessHeap(), 0, tempdata);
+ break;
+ }
+ case 8:
+ {
+ UINT xorBytesPerRow = (width+3)/4*4;
+ UINT xorBytes = xorBytesPerRow * height;
+ INT xorStride;
+ BYTE *xorRow;
+ BYTE *bitsRow;
+ UINT x, y;
+
+ tempdata = HeapAlloc(GetProcessHeap(), 0, xorBytes);
+ if (!tempdata)
+ {
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ hr = IStream_Read(This->parent->stream, tempdata, xorBytes, &bytesread);
+ if (FAILED(hr) || bytesread != xorBytes) goto fail;
+
+ if (bih.biHeight > 0) /* bottom-up DIB */
+ {
+ xorStride = -xorBytesPerRow;
+ xorRow = tempdata + (height-1)*xorBytesPerRow;
+ }
+ else /* top-down DIB */
+ {
+ xorStride = xorBytesPerRow;
+ xorRow = tempdata;
+ }
+
+ bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
+
+ /* palette-map the 8-bit data */
+ bitsRow = bits;
+ for (y=0; yparent->stream, tempdata, xorBytes, &bytesread);
+ if (FAILED(hr) || bytesread != xorBytes) goto fail;
+
+ if (bih.biHeight > 0) /* bottom-up DIB */
+ {
+ xorStride = -xorBytesPerRow;
+ xorRow = tempdata + (height-1)*xorBytesPerRow;
+ }
+ else /* top-down DIB */
+ {
+ xorStride = xorBytesPerRow;
+ xorRow = tempdata;
+ }
+
+ bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
+
+ /* copy BGR->BGRA */
+ bitsRow = bits;
+ for (y=0; y 0) /* bottom-up DIB */
+ {
+ /* read the rows backwards so we get a top-down DIB */
+ UINT i;
+ BYTE *xorRow = bits + xorBytesPerRow * (height-1);
+
+ for (i=0; iparent->stream, xorRow, xorBytesPerRow, &bytesread);
+ if (FAILED(hr) || bytesread != xorBytesPerRow) goto fail;
+ xorRow -= xorBytesPerRow;
+ }
+ }
+ else /* top-down DIB */
+ {
+ hr = IStream_Read(This->parent->stream, bits, xorBytes, &bytesread);
+ if (FAILED(hr) || bytesread != xorBytes) goto fail;
+ }
+ break;
+ }
+ default:
+ FIXME("unsupported bitcount: %u\n", This->entry.wBitCount);
+ goto fail;
+ }
+
+ if (This->entry.wBitCount < 32)
+ {
+ /* set alpha data based on the AND mask */
+ UINT andBytesPerRow = (width+31)/32*4;
+ UINT andBytes = andBytesPerRow * height;
+ INT andStride;
+ BYTE *andRow;
+ BYTE *bitsRow;
+ UINT x, y;
+
+ tempdata = HeapAlloc(GetProcessHeap(), 0, andBytes);
+ if (!tempdata)
+ {
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ hr = IStream_Read(This->parent->stream, tempdata, andBytes, &bytesread);
+ if (FAILED(hr) || bytesread != andBytes) goto fail;
+
+ if (bih.biHeight > 0) /* bottom-up DIB */
+ {
+ andStride = -andBytesPerRow;
+ andRow = tempdata + (height-1)*andBytesPerRow;
+ }
+ else /* top-down DIB */
+ {
+ andStride = andBytesPerRow;
+ andRow = tempdata;
+ }
+
+ bitsRow = bits;
+ for (y=0; y>7&1);
+ if (x+1 < width) pixel_set_trans(bitsPixel++, andVal>>6&1);
+ if (x+2 < width) pixel_set_trans(bitsPixel++, andVal>>5&1);
+ if (x+3 < width) pixel_set_trans(bitsPixel++, andVal>>4&1);
+ if (x+4 < width) pixel_set_trans(bitsPixel++, andVal>>3&1);
+ if (x+5 < width) pixel_set_trans(bitsPixel++, andVal>>2&1);
+ if (x+6 < width) pixel_set_trans(bitsPixel++, andVal>>1&1);
+ if (x+7 < width) pixel_set_trans(bitsPixel++, andVal&1);
+ }
+ andRow += andStride;
+ bitsRow += bitsStride;
+ }
+
+ HeapFree(GetProcessHeap(), 0, tempdata);
+ }
+
+ This->bits = bits;
+
+ return S_OK;
+
+fail:
+ HeapFree(GetProcessHeap(), 0, tempdata);
+ HeapFree(GetProcessHeap(), 0, bits);
+ if (SUCCEEDED(hr)) hr = E_FAIL;
+ TRACE("<-- %x\n", hr);
+ return hr;
+}
+
+static HRESULT WINAPI IcoFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
+ const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
+{
+ IcoFrameDecode *This = (IcoFrameDecode*)iface;
+ HRESULT hr;
+ UINT width, height, stride;
+ TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
+
+ if (!This->bits)
+ {
+ hr = IcoFrameDecode_ReadPixels(This);
+ if (FAILED(hr)) return hr;
+ }
+
+ width = This->entry.bWidth ? This->entry.bWidth : 256;
+ height = This->entry.bHeight ? This->entry.bHeight : 256;
+ stride = width * 4;
+
+ return copy_pixels(32, This->bits, width, height, stride,
+ prc, cbStride, cbBufferSize, pbBuffer);
+}
+
+static HRESULT WINAPI IcoFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+ TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI IcoFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI IcoFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static const IWICBitmapFrameDecodeVtbl IcoFrameDecode_Vtbl = {
+ IcoFrameDecode_QueryInterface,
+ IcoFrameDecode_AddRef,
+ IcoFrameDecode_Release,
+ IcoFrameDecode_GetSize,
+ IcoFrameDecode_GetPixelFormat,
+ IcoFrameDecode_GetResolution,
+ IcoFrameDecode_CopyPalette,
+ IcoFrameDecode_CopyPixels,
+ IcoFrameDecode_GetMetadataQueryReader,
+ IcoFrameDecode_GetColorContexts,
+ IcoFrameDecode_GetThumbnail
+};
+
+static HRESULT WINAPI IcoDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
+ void **ppv)
+{
+ IcoDecoder *This = (IcoDecoder*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI IcoDecoder_AddRef(IWICBitmapDecoder *iface)
+{
+ IcoDecoder *This = (IcoDecoder*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI IcoDecoder_Release(IWICBitmapDecoder *iface)
+{
+ IcoDecoder *This = (IcoDecoder*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ if (This->stream) IStream_Release(This->stream);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI IcoDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
+ DWORD *pdwCapability)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IcoDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
+ WICDecodeOptions cacheOptions)
+{
+ IcoDecoder *This = (IcoDecoder*)iface;
+ LARGE_INTEGER seek;
+ HRESULT hr;
+ ULONG bytesread;
+ TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
+
+ if (This->initialized) return WINCODEC_ERR_WRONGSTATE;
+
+ seek.QuadPart = 0;
+ hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) return hr;
+
+ hr = IStream_Read(pIStream, &This->header, sizeof(ICONHEADER), &bytesread);
+ if (FAILED(hr)) return hr;
+ if (bytesread != sizeof(ICONHEADER) ||
+ This->header.idReserved != 0 ||
+ This->header.idType != 1) return E_FAIL;
+
+ This->initialized = TRUE;
+ This->stream = pIStream;
+ IStream_AddRef(pIStream);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI IcoDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
+ GUID *pguidContainerFormat)
+{
+ FIXME("(%p,%p): stub\n", iface, pguidContainerFormat);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IcoDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
+ IWICBitmapDecoderInfo **ppIDecoderInfo)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIDecoderInfo);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IcoDecoder_CopyPalette(IWICBitmapDecoder *iface,
+ IWICPalette *pIPalette)
+{
+ TRACE("(%p,%p)\n", iface, pIPalette);
+ return WINCODEC_ERR_PALETTEUNAVAILABLE;
+}
+
+static HRESULT WINAPI IcoDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
+ IWICMetadataQueryReader **ppIMetadataQueryReader)
+{
+ TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI IcoDecoder_GetPreview(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIBitmapSource)
+{
+ TRACE("(%p,%p)\n", iface, ppIBitmapSource);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI IcoDecoder_GetColorContexts(IWICBitmapDecoder *iface,
+ UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
+{
+ TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
+ return WINCODEC_ERR_UNSUPPORTEDOPERATION;
+}
+
+static HRESULT WINAPI IcoDecoder_GetThumbnail(IWICBitmapDecoder *iface,
+ IWICBitmapSource **ppIThumbnail)
+{
+ TRACE("(%p,%p)\n", iface, ppIThumbnail);
+ return WINCODEC_ERR_CODECNOTHUMBNAIL;
+}
+
+static HRESULT WINAPI IcoDecoder_GetFrameCount(IWICBitmapDecoder *iface,
+ UINT *pCount)
+{
+ IcoDecoder *This = (IcoDecoder*)iface;
+ TRACE("(%p,%p)\n", iface, pCount);
+
+ if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
+
+ *pCount = This->header.idCount;
+ TRACE("<-- %u\n", *pCount);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI IcoDecoder_GetFrame(IWICBitmapDecoder *iface,
+ UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
+{
+ IcoDecoder *This = (IcoDecoder*)iface;
+ IcoFrameDecode *result;
+ LARGE_INTEGER seek;
+ HRESULT hr;
+ ULONG bytesread;
+ TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
+
+ if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
+
+ if (This->header.idCount < index) return E_INVALIDARG;
+
+ result = HeapAlloc(GetProcessHeap(), 0, sizeof(IcoFrameDecode));
+ if (!result) return E_OUTOFMEMORY;
+
+ result->lpVtbl = &IcoFrameDecode_Vtbl;
+ result->ref = 1;
+ result->parent = This;
+ result->bits = NULL;
+
+ /* read the icon entry */
+ seek.QuadPart = sizeof(ICONHEADER) + sizeof(ICONDIRENTRY) * index;
+ hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, 0);
+ if (FAILED(hr)) goto fail;
+
+ hr = IStream_Read(This->stream, &result->entry, sizeof(ICONDIRENTRY), &bytesread);
+ if (FAILED(hr) || bytesread != sizeof(ICONDIRENTRY)) goto fail;
+
+ IWICBitmapDecoder_AddRef(iface);
+
+ *ppIBitmapFrame = (IWICBitmapFrameDecode*)result;
+
+ return S_OK;
+
+fail:
+ HeapFree(GetProcessHeap(), 0, result);
+ if (SUCCEEDED(hr)) hr = E_FAIL;
+ TRACE("<-- %x\n", hr);
+ return hr;
+}
+
+static const IWICBitmapDecoderVtbl IcoDecoder_Vtbl = {
+ IcoDecoder_QueryInterface,
+ IcoDecoder_AddRef,
+ IcoDecoder_Release,
+ IcoDecoder_QueryCapability,
+ IcoDecoder_Initialize,
+ IcoDecoder_GetContainerFormat,
+ IcoDecoder_GetDecoderInfo,
+ IcoDecoder_CopyPalette,
+ IcoDecoder_GetMetadataQueryReader,
+ IcoDecoder_GetPreview,
+ IcoDecoder_GetColorContexts,
+ IcoDecoder_GetThumbnail,
+ IcoDecoder_GetFrameCount,
+ IcoDecoder_GetFrame
+};
+
+HRESULT IcoDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+ IcoDecoder *This;
+ HRESULT ret;
+
+ TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
+
+ *ppv = NULL;
+
+ if (pUnkOuter) return CLASS_E_NOAGGREGATION;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(IcoDecoder));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->lpVtbl = &IcoDecoder_Vtbl;
+ This->ref = 1;
+ This->stream = NULL;
+ This->initialized = FALSE;
+
+ ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
+ IUnknown_Release((IUnknown*)This);
+
+ return ret;
+}
diff --git a/reactos/dll/win32/windowscodecs/imgfactory.c b/reactos/dll/win32/windowscodecs/imgfactory.c
new file mode 100644
index 00000000000..a98aeb81295
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/imgfactory.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+typedef struct {
+ const IWICImagingFactoryVtbl *lpIWICImagingFactoryVtbl;
+ LONG ref;
+} ImagingFactory;
+
+static HRESULT WINAPI ImagingFactory_QueryInterface(IWICImagingFactory *iface, REFIID iid,
+ void **ppv)
+{
+ ImagingFactory *This = (ImagingFactory*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICImagingFactory, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI ImagingFactory_AddRef(IWICImagingFactory *iface)
+{
+ ImagingFactory *This = (ImagingFactory*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI ImagingFactory_Release(IWICImagingFactory *iface)
+{
+ ImagingFactory *This = (ImagingFactory*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ HeapFree(GetProcessHeap(), 0, This);
+
+ return ref;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateDecoderFromFilename(
+ IWICImagingFactory *iface, LPCWSTR wzFilename, const GUID *pguidVendor,
+ DWORD dwDesiredAccess, WICDecodeOptions metadataOptions,
+ IWICBitmapDecoder **ppIDecoder)
+{
+ FIXME("(%p,%s,%s,%u,%u,%p): stub\n", iface, debugstr_w(wzFilename),
+ debugstr_guid(pguidVendor), dwDesiredAccess, metadataOptions, ppIDecoder);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateDecoderFromStream(
+ IWICImagingFactory *iface, IStream *pIStream, const GUID *pguidVendor,
+ WICDecodeOptions metadataOptions, IWICBitmapDecoder **ppIDecoder)
+{
+ static int fixme=0;
+ IEnumUnknown *enumdecoders;
+ IUnknown *unkdecoderinfo;
+ IWICBitmapDecoderInfo *decoderinfo;
+ IWICBitmapDecoder *decoder=NULL;
+ HRESULT res=S_OK;
+ ULONG num_fetched;
+ BOOL matches;
+
+ TRACE("(%p,%p,%s,%u,%p)\n", iface, pIStream, debugstr_guid(pguidVendor),
+ metadataOptions, ppIDecoder);
+
+ if (pguidVendor && !fixme++)
+ FIXME("ignoring vendor GUID\n");
+
+ res = CreateComponentEnumerator(WICDecoder, WICComponentEnumerateDefault, &enumdecoders);
+ if (FAILED(res)) return res;
+
+ while (!decoder)
+ {
+ res = IEnumUnknown_Next(enumdecoders, 1, &unkdecoderinfo, &num_fetched);
+
+ if (res == S_OK)
+ {
+ res = IUnknown_QueryInterface(unkdecoderinfo, &IID_IWICBitmapDecoderInfo, (void**)&decoderinfo);
+
+ if (SUCCEEDED(res))
+ {
+ res = IWICBitmapDecoderInfo_MatchesPattern(decoderinfo, pIStream, &matches);
+
+ if (SUCCEEDED(res) && matches)
+ {
+ res = IWICBitmapDecoderInfo_CreateInstance(decoderinfo, &decoder);
+
+ /* FIXME: should use QueryCapability to choose a decoder */
+
+ if (SUCCEEDED(res))
+ {
+ res = IWICBitmapDecoder_Initialize(decoder, pIStream, metadataOptions);
+
+ if (FAILED(res))
+ {
+ IWICBitmapDecoder_Release(decoder);
+ decoder = NULL;
+ }
+ }
+ }
+
+ IWICBitmapDecoderInfo_Release(decoderinfo);
+ }
+
+ IUnknown_Release(unkdecoderinfo);
+ }
+ else
+ break;
+ }
+
+ IEnumUnknown_Release(enumdecoders);
+
+ if (decoder)
+ {
+ *ppIDecoder = decoder;
+ return S_OK;
+ }
+ else
+ {
+ if (WARN_ON(wincodecs))
+ {
+ LARGE_INTEGER seek;
+ BYTE data[4];
+ ULONG bytesread;
+
+ WARN("failed to load from a stream\n");
+
+ seek.QuadPart = 0;
+ res = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
+ if (SUCCEEDED(res))
+ res = IStream_Read(pIStream, data, 4, &bytesread);
+ if (SUCCEEDED(res))
+ WARN("first %i bytes of stream=%x %x %x %x\n", bytesread, data[0], data[1], data[2], data[3]);
+ }
+ *ppIDecoder = NULL;
+ return WINCODEC_ERR_COMPONENTNOTFOUND;
+ }
+}
+
+static HRESULT WINAPI ImagingFactory_CreateDecoderFromFileHandle(
+ IWICImagingFactory *iface, ULONG_PTR hFile, const GUID *pguidVendor,
+ WICDecodeOptions metadataOptions, IWICBitmapDecoder **ppIDecoder)
+{
+ FIXME("(%p,%lx,%s,%u,%p): stub\n", iface, hFile, debugstr_guid(pguidVendor),
+ metadataOptions, ppIDecoder);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateComponentInfo(IWICImagingFactory *iface,
+ REFCLSID clsidComponent, IWICComponentInfo **ppIInfo)
+{
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(clsidComponent), ppIInfo);
+ return CreateComponentInfo(clsidComponent, ppIInfo);
+}
+
+static HRESULT WINAPI ImagingFactory_CreateDecoder(IWICImagingFactory *iface,
+ REFGUID guidContainerFormat, const GUID *pguidVendor,
+ IWICBitmapDecoder **ppIDecoder)
+{
+ FIXME("(%p,%s,%s,%p): stub\n", iface, debugstr_guid(guidContainerFormat),
+ debugstr_guid(pguidVendor), ppIDecoder);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateEncoder(IWICImagingFactory *iface,
+ REFGUID guidContainerFormat, const GUID *pguidVendor,
+ IWICBitmapEncoder **ppIEncoder)
+{
+ FIXME("(%p,%s,%s,%p): stub\n", iface, debugstr_guid(guidContainerFormat),
+ debugstr_guid(pguidVendor), ppIEncoder);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreatePalette(IWICImagingFactory *iface,
+ IWICPalette **ppIPalette)
+{
+ TRACE("(%p,%p)\n", iface, ppIPalette);
+ return PaletteImpl_Create(ppIPalette);
+}
+
+static HRESULT WINAPI ImagingFactory_CreateFormatConverter(IWICImagingFactory *iface,
+ IWICFormatConverter **ppIFormatConverter)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIFormatConverter);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmapScaler(IWICImagingFactory *iface,
+ IWICBitmapScaler **ppIBitmapScaler)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIBitmapScaler);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmapClipper(IWICImagingFactory *iface,
+ IWICBitmapClipper **ppIBitmapClipper)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIBitmapClipper);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmapFlipRotator(IWICImagingFactory *iface,
+ IWICBitmapFlipRotator **ppIBitmapFlipRotator)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIBitmapFlipRotator);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateStream(IWICImagingFactory *iface,
+ IWICStream **ppIWICStream)
+{
+ TRACE("(%p,%p)\n", iface, ppIWICStream);
+ return StreamImpl_Create(ppIWICStream);
+}
+
+static HRESULT WINAPI ImagingFactory_CreateColorContext(IWICImagingFactory *iface,
+ IWICColorContext **ppIColorContext)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIColorContext);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateColorTransformer(IWICImagingFactory *iface,
+ IWICColorTransform **ppIColorTransform)
+{
+ FIXME("(%p,%p): stub\n", iface, ppIColorTransform);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmap(IWICImagingFactory *iface,
+ UINT uiWidth, UINT uiHeight, REFWICPixelFormatGUID pixelFormat,
+ WICBitmapCreateCacheOption option, IWICBitmap **ppIBitmap)
+{
+ FIXME("(%p,%u,%u,%s,%u,%p): stub\n", iface, uiWidth, uiHeight,
+ debugstr_guid(pixelFormat), option, ppIBitmap);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmapFromSource(IWICImagingFactory *iface,
+ IWICBitmapSource *piBitmapSource, WICBitmapCreateCacheOption option,
+ IWICBitmap **ppIBitmap)
+{
+ FIXME("(%p,%p,%u,%p): stub\n", iface, piBitmapSource, option, ppIBitmap);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmapFromSourceRect(IWICImagingFactory *iface,
+ IWICBitmapSource *piBitmapSource, UINT x, UINT y, UINT width, UINT height,
+ IWICBitmap **ppIBitmap)
+{
+ FIXME("(%p,%p,%u,%u,%u,%u,%p): stub\n", iface, piBitmapSource, x, y, width,
+ height, ppIBitmap);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmapFromMemory(IWICImagingFactory *iface,
+ UINT uiWidth, UINT uiHeight, REFWICPixelFormatGUID pixelFormat, UINT cbStride,
+ UINT cbBufferSize, BYTE *pbBuffer, IWICBitmap **ppIBitmap)
+{
+ FIXME("(%p,%u,%u,%s,%u,%u,%p,%p): stub\n", iface, uiWidth, uiHeight,
+ debugstr_guid(pixelFormat), cbStride, cbBufferSize, pbBuffer, ppIBitmap);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmapFromHBITMAP(IWICImagingFactory *iface,
+ HBITMAP hBitmap, HPALETTE hPalette, WICBitmapAlphaChannelOption options,
+ IWICBitmap **ppIBitmap)
+{
+ FIXME("(%p,%p,%p,%u,%p): stub\n", iface, hBitmap, hPalette, options, ppIBitmap);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateBitmapFromHICON(IWICImagingFactory *iface,
+ HICON hIcon, IWICBitmap **ppIBitmap)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, hIcon, ppIBitmap);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateComponentEnumerator(IWICImagingFactory *iface,
+ DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
+{
+ TRACE("(%p,%u,%u,%p)\n", iface, componentTypes, options, ppIEnumUnknown);
+ return CreateComponentEnumerator(componentTypes, options, ppIEnumUnknown);
+}
+
+static HRESULT WINAPI ImagingFactory_CreateFastMetadataEncoderFromDecoder(
+ IWICImagingFactory *iface, IWICBitmapDecoder *pIDecoder,
+ IWICFastMetadataEncoder **ppIFastEncoder)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, pIDecoder, ppIFastEncoder);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateFastMetadataEncoderFromFrameDecode(
+ IWICImagingFactory *iface, IWICBitmapFrameDecode *pIFrameDecoder,
+ IWICFastMetadataEncoder **ppIFastEncoder)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, pIFrameDecoder, ppIFastEncoder);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateQueryWriter(IWICImagingFactory *iface,
+ REFGUID guidMetadataFormat, const GUID *pguidVendor,
+ IWICMetadataQueryWriter **ppIQueryWriter)
+{
+ FIXME("(%p,%s,%s,%p): stub\n", iface, debugstr_guid(guidMetadataFormat),
+ debugstr_guid(pguidVendor), ppIQueryWriter);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImagingFactory_CreateQueryWriterFromReader(IWICImagingFactory *iface,
+ IWICMetadataQueryReader *pIQueryReader, const GUID *pguidVendor,
+ IWICMetadataQueryWriter **ppIQueryWriter)
+{
+ FIXME("(%p,%p,%s,%p): stub\n", iface, pIQueryReader, debugstr_guid(pguidVendor),
+ ppIQueryWriter);
+ return E_NOTIMPL;
+}
+
+static const IWICImagingFactoryVtbl ImagingFactory_Vtbl = {
+ ImagingFactory_QueryInterface,
+ ImagingFactory_AddRef,
+ ImagingFactory_Release,
+ ImagingFactory_CreateDecoderFromFilename,
+ ImagingFactory_CreateDecoderFromStream,
+ ImagingFactory_CreateDecoderFromFileHandle,
+ ImagingFactory_CreateComponentInfo,
+ ImagingFactory_CreateDecoder,
+ ImagingFactory_CreateEncoder,
+ ImagingFactory_CreatePalette,
+ ImagingFactory_CreateFormatConverter,
+ ImagingFactory_CreateBitmapScaler,
+ ImagingFactory_CreateBitmapClipper,
+ ImagingFactory_CreateBitmapFlipRotator,
+ ImagingFactory_CreateStream,
+ ImagingFactory_CreateColorContext,
+ ImagingFactory_CreateColorTransformer,
+ ImagingFactory_CreateBitmap,
+ ImagingFactory_CreateBitmapFromSource,
+ ImagingFactory_CreateBitmapFromSourceRect,
+ ImagingFactory_CreateBitmapFromMemory,
+ ImagingFactory_CreateBitmapFromHBITMAP,
+ ImagingFactory_CreateBitmapFromHICON,
+ ImagingFactory_CreateComponentEnumerator,
+ ImagingFactory_CreateFastMetadataEncoderFromDecoder,
+ ImagingFactory_CreateFastMetadataEncoderFromFrameDecode,
+ ImagingFactory_CreateQueryWriter,
+ ImagingFactory_CreateQueryWriterFromReader
+};
+
+HRESULT ImagingFactory_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
+{
+ ImagingFactory *This;
+ HRESULT ret;
+
+ TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
+
+ *ppv = NULL;
+
+ if (pUnkOuter) return CLASS_E_NOAGGREGATION;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(ImagingFactory));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->lpIWICImagingFactoryVtbl = &ImagingFactory_Vtbl;
+ This->ref = 1;
+
+ ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
+ IUnknown_Release((IUnknown*)This);
+
+ return ret;
+}
diff --git a/reactos/dll/win32/windowscodecs/info.c b/reactos/dll/win32/windowscodecs/info.c
new file mode 100644
index 00000000000..a89759bd2a9
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/info.c
@@ -0,0 +1,1070 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/list.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
+
+typedef struct {
+ const IWICBitmapDecoderInfoVtbl *lpIWICBitmapDecoderInfoVtbl;
+ LONG ref;
+ HKEY classkey;
+ CLSID clsid;
+} BitmapDecoderInfo;
+
+static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid,
+ void **ppv)
+{
+ BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICComponentInfo, iid) ||
+ IsEqualIID(&IID_IWICBitmapCodecInfo, iid) ||
+ IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface)
+{
+ BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI BitmapDecoderInfo_Release(IWICBitmapDecoderInfo *iface)
+{
+ BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ RegCloseKey(This->classkey);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetComponentType(IWICBitmapDecoderInfo *iface,
+ WICComponentType *pType)
+{
+ TRACE("(%p,%p)\n", iface, pType);
+ *pType = WICDecoder;
+ return S_OK;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, CLSID *pclsid)
+{
+ FIXME("(%p,%p): stub\n", iface, pclsid);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetSigningStatus(IWICBitmapDecoderInfo *iface, DWORD *pStatus)
+{
+ FIXME("(%p,%p): stub\n", iface, pStatus);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetAuthor(IWICBitmapDecoderInfo *iface, UINT cchAuthor,
+ WCHAR *wzAuthor, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchAuthor, wzAuthor, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetVendorGUID(IWICBitmapDecoderInfo *iface, GUID *pguidVendor)
+{
+ FIXME("(%p,%p): stub\n", iface, pguidVendor);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetVersion(IWICBitmapDecoderInfo *iface, UINT cchVersion,
+ WCHAR *wzVersion, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchVersion, wzVersion, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetSpecVersion(IWICBitmapDecoderInfo *iface, UINT cchSpecVersion,
+ WCHAR *wzSpecVersion, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetFriendlyName(IWICBitmapDecoderInfo *iface, UINT cchFriendlyName,
+ WCHAR *wzFriendlyName, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetContainerFormat(IWICBitmapDecoderInfo *iface,
+ GUID *pguidContainerFormat)
+{
+ FIXME("(%p,%p): stub\n", iface, pguidContainerFormat);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetPixelFormats(IWICBitmapDecoderInfo *iface,
+ UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetColorManagementVersion(IWICBitmapDecoderInfo *iface,
+ UINT cchColorManagementVersion, WCHAR *wzColorManagementVersion, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchColorManagementVersion, wzColorManagementVersion, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetDeviceManufacturer(IWICBitmapDecoderInfo *iface,
+ UINT cchDeviceManufacturer, WCHAR *wzDeviceManufacturer, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceManufacturer, wzDeviceManufacturer, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetDeviceModels(IWICBitmapDecoderInfo *iface,
+ UINT cchDeviceModels, WCHAR *wzDeviceModels, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchDeviceModels, wzDeviceModels, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetMimeTypes(IWICBitmapDecoderInfo *iface,
+ UINT cchMimeTypes, WCHAR *wzMimeTypes, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchMimeTypes, wzMimeTypes, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetFileExtensions(IWICBitmapDecoderInfo *iface,
+ UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchFileExtensions, wzFileExtensions, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_DoesSupportAnimation(IWICBitmapDecoderInfo *iface,
+ BOOL *pfSupportAnimation)
+{
+ FIXME("(%p,%p): stub\n", iface, pfSupportAnimation);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_DoesSupportChromaKey(IWICBitmapDecoderInfo *iface,
+ BOOL *pfSupportChromaKey)
+{
+ FIXME("(%p,%p): stub\n", iface, pfSupportChromaKey);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_DoesSupportLossless(IWICBitmapDecoderInfo *iface,
+ BOOL *pfSupportLossless)
+{
+ FIXME("(%p,%p): stub\n", iface, pfSupportLossless);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_DoesSupportMultiframe(IWICBitmapDecoderInfo *iface,
+ BOOL *pfSupportMultiframe)
+{
+ FIXME("(%p,%p): stub\n", iface, pfSupportMultiframe);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_MatchesMimeType(IWICBitmapDecoderInfo *iface,
+ LPCWSTR wzMimeType, BOOL *pfMatches)
+{
+ FIXME("(%p,%s,%p): stub\n", iface, debugstr_w(wzMimeType), pfMatches);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_GetPatterns(IWICBitmapDecoderInfo *iface,
+ UINT cbSizePatterns, WICBitmapPattern *pPatterns, UINT *pcPatterns, UINT *pcbPatternsActual)
+{
+ BitmapDecoderInfo *This = (BitmapDecoderInfo*)iface;
+ UINT pattern_count=0, patterns_size=0;
+ WCHAR subkeyname[11];
+ LONG res;
+ HKEY patternskey, patternkey;
+ static const WCHAR uintformatW[] = {'%','u',0};
+ static const WCHAR patternsW[] = {'P','a','t','t','e','r','n','s',0};
+ static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0};
+ static const WCHAR lengthW[] = {'L','e','n','g','t','h',0};
+ static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0};
+ static const WCHAR maskW[] = {'M','a','s','k',0};
+ static const WCHAR endofstreamW[] = {'E','n','d','O','f','S','t','r','e','a','m',0};
+ HRESULT hr=S_OK;
+ UINT i;
+ BYTE *bPatterns=(BYTE*)pPatterns;
+ DWORD length, valuesize;
+
+ TRACE("(%p,%i,%p,%p,%p)\n", iface, cbSizePatterns, pPatterns, pcPatterns, pcbPatternsActual);
+
+ res = RegOpenKeyExW(This->classkey, patternsW, 0, KEY_READ, &patternskey);
+ if (res != ERROR_SUCCESS) return HRESULT_FROM_WIN32(res);
+
+ res = RegQueryInfoKeyW(patternskey, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (res == ERROR_SUCCESS)
+ {
+ patterns_size = pattern_count * sizeof(WICBitmapPattern);
+
+ for (i=0; i= patterns_size) && (res == ERROR_SUCCESS))
+ {
+ pPatterns[i].Length = length;
+
+ pPatterns[i].EndOfStream = 0;
+ valuesize = sizeof(BOOL);
+ RegGetValueW(patternkey, NULL, endofstreamW, RRF_RT_DWORD, NULL,
+ &pPatterns[i].EndOfStream, &valuesize);
+
+ pPatterns[i].Position.QuadPart = 0;
+ valuesize = sizeof(ULARGE_INTEGER);
+ res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL,
+ &pPatterns[i].Position, &valuesize);
+
+ if (res == ERROR_SUCCESS)
+ {
+ pPatterns[i].Pattern = bPatterns+patterns_size-length*2;
+ valuesize = length;
+ res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL,
+ pPatterns[i].Pattern, &valuesize);
+ }
+
+ if (res == ERROR_SUCCESS)
+ {
+ pPatterns[i].Mask = bPatterns+patterns_size-length;
+ valuesize = length;
+ res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL,
+ pPatterns[i].Mask, &valuesize);
+ }
+ }
+
+ RegCloseKey(patternkey);
+ }
+ if (res != ERROR_SUCCESS)
+ {
+ hr = HRESULT_FROM_WIN32(res);
+ break;
+ }
+ }
+ }
+ else hr = HRESULT_FROM_WIN32(res);
+
+ RegCloseKey(patternskey);
+
+ if (hr == S_OK)
+ {
+ *pcPatterns = pattern_count;
+ *pcbPatternsActual = patterns_size;
+ if (pPatterns && cbSizePatterns < patterns_size)
+ hr = WINCODEC_ERR_INSUFFICIENTBUFFER;
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface,
+ IStream *pIStream, BOOL *pfMatches)
+{
+ WICBitmapPattern *patterns;
+ UINT pattern_count=0, patterns_size=0;
+ HRESULT hr;
+ int i, pos;
+ BYTE *data=NULL;
+ ULONG datasize=0;
+ ULONG bytesread;
+ LARGE_INTEGER seekpos;
+
+ TRACE("(%p,%p,%p)\n", iface, pIStream, pfMatches);
+
+ hr = BitmapDecoderInfo_GetPatterns(iface, 0, NULL, &pattern_count, &patterns_size);
+ if (FAILED(hr)) return hr;
+
+ patterns = HeapAlloc(GetProcessHeap(), 0, patterns_size);
+ if (!patterns) return E_OUTOFMEMORY;
+
+ hr = BitmapDecoderInfo_GetPatterns(iface, patterns_size, patterns, &pattern_count, &patterns_size);
+ if (FAILED(hr)) goto end;
+
+ for (i=0; iclsid, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder);
+}
+
+static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = {
+ BitmapDecoderInfo_QueryInterface,
+ BitmapDecoderInfo_AddRef,
+ BitmapDecoderInfo_Release,
+ BitmapDecoderInfo_GetComponentType,
+ BitmapDecoderInfo_GetCLSID,
+ BitmapDecoderInfo_GetSigningStatus,
+ BitmapDecoderInfo_GetAuthor,
+ BitmapDecoderInfo_GetVendorGUID,
+ BitmapDecoderInfo_GetVersion,
+ BitmapDecoderInfo_GetSpecVersion,
+ BitmapDecoderInfo_GetFriendlyName,
+ BitmapDecoderInfo_GetContainerFormat,
+ BitmapDecoderInfo_GetPixelFormats,
+ BitmapDecoderInfo_GetColorManagementVersion,
+ BitmapDecoderInfo_GetDeviceManufacturer,
+ BitmapDecoderInfo_GetDeviceModels,
+ BitmapDecoderInfo_GetMimeTypes,
+ BitmapDecoderInfo_GetFileExtensions,
+ BitmapDecoderInfo_DoesSupportAnimation,
+ BitmapDecoderInfo_DoesSupportChromaKey,
+ BitmapDecoderInfo_DoesSupportLossless,
+ BitmapDecoderInfo_DoesSupportMultiframe,
+ BitmapDecoderInfo_MatchesMimeType,
+ BitmapDecoderInfo_GetPatterns,
+ BitmapDecoderInfo_MatchesPattern,
+ BitmapDecoderInfo_CreateInstance
+};
+
+static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
+{
+ BitmapDecoderInfo *This;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapDecoderInfo));
+ if (!This)
+ {
+ RegCloseKey(classkey);
+ return E_OUTOFMEMORY;
+ }
+
+ This->lpIWICBitmapDecoderInfoVtbl = &BitmapDecoderInfo_Vtbl;
+ This->ref = 1;
+ This->classkey = classkey;
+ memcpy(&This->clsid, clsid, sizeof(CLSID));
+
+ *ppIInfo = (IWICComponentInfo*)This;
+ return S_OK;
+}
+
+typedef struct {
+ const IWICFormatConverterInfoVtbl *lpIWICFormatConverterInfoVtbl;
+ LONG ref;
+ HKEY classkey;
+ CLSID clsid;
+} FormatConverterInfo;
+
+static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid,
+ void **ppv)
+{
+ FormatConverterInfo *This = (FormatConverterInfo*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IWICComponentInfo, iid) ||
+ IsEqualIID(&IID_IWICFormatConverterInfo ,iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface)
+{
+ FormatConverterInfo *This = (FormatConverterInfo*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI FormatConverterInfo_Release(IWICFormatConverterInfo *iface)
+{
+ FormatConverterInfo *This = (FormatConverterInfo*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ RegCloseKey(This->classkey);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetComponentType(IWICFormatConverterInfo *iface,
+ WICComponentType *pType)
+{
+ TRACE("(%p,%p)\n", iface, pType);
+ *pType = WICPixelFormatConverter;
+ return S_OK;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *iface, CLSID *pclsid)
+{
+ FIXME("(%p,%p): stub\n", iface, pclsid);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetSigningStatus(IWICFormatConverterInfo *iface, DWORD *pStatus)
+{
+ FIXME("(%p,%p): stub\n", iface, pStatus);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetAuthor(IWICFormatConverterInfo *iface, UINT cchAuthor,
+ WCHAR *wzAuthor, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchAuthor, wzAuthor, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetVendorGUID(IWICFormatConverterInfo *iface, GUID *pguidVendor)
+{
+ FIXME("(%p,%p): stub\n", iface, pguidVendor);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetVersion(IWICFormatConverterInfo *iface, UINT cchVersion,
+ WCHAR *wzVersion, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchVersion, wzVersion, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetSpecVersion(IWICFormatConverterInfo *iface, UINT cchSpecVersion,
+ WCHAR *wzSpecVersion, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchSpecVersion, wzSpecVersion, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetFriendlyName(IWICFormatConverterInfo *iface, UINT cchFriendlyName,
+ WCHAR *wzFriendlyName, UINT *pcchActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cchFriendlyName, wzFriendlyName, pcchActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverterInfo_GetPixelFormats(IWICFormatConverterInfo *iface,
+ UINT cFormats, GUID *pguidPixelFormats, UINT *pcActual)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cFormats, pguidPixelFormats, pcActual);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo *iface,
+ IWICFormatConverter **ppIFormatConverter)
+{
+ FormatConverterInfo *This = (FormatConverterInfo*)iface;
+
+ TRACE("(%p,%p)\n", iface, ppIFormatConverter);
+
+ return CoCreateInstance(&This->clsid, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IWICFormatConverter, (void**)ppIFormatConverter);
+}
+
+static BOOL ConverterSupportsFormat(IWICFormatConverterInfo *iface, const WCHAR *formatguid)
+{
+ LONG res;
+ FormatConverterInfo *This = (FormatConverterInfo*)iface;
+ HKEY formats_key, guid_key;
+
+ /* Avoid testing using IWICFormatConverter_GetPixelFormats because that
+ would be O(n). A registry test should do better. */
+
+ res = RegOpenKeyExW(This->classkey, pixelformats_keyname, 0, KEY_READ, &formats_key);
+ if (res != ERROR_SUCCESS) return FALSE;
+
+ res = RegOpenKeyExW(formats_key, formatguid, 0, KEY_READ, &guid_key);
+ if (res == ERROR_SUCCESS) RegCloseKey(guid_key);
+
+ RegCloseKey(formats_key);
+
+ return (res == ERROR_SUCCESS);
+}
+
+static const IWICFormatConverterInfoVtbl FormatConverterInfo_Vtbl = {
+ FormatConverterInfo_QueryInterface,
+ FormatConverterInfo_AddRef,
+ FormatConverterInfo_Release,
+ FormatConverterInfo_GetComponentType,
+ FormatConverterInfo_GetCLSID,
+ FormatConverterInfo_GetSigningStatus,
+ FormatConverterInfo_GetAuthor,
+ FormatConverterInfo_GetVendorGUID,
+ FormatConverterInfo_GetVersion,
+ FormatConverterInfo_GetSpecVersion,
+ FormatConverterInfo_GetFriendlyName,
+ FormatConverterInfo_GetPixelFormats,
+ FormatConverterInfo_CreateInstance
+};
+
+static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo)
+{
+ FormatConverterInfo *This;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverterInfo));
+ if (!This)
+ {
+ RegCloseKey(classkey);
+ return E_OUTOFMEMORY;
+ }
+
+ This->lpIWICFormatConverterInfoVtbl = &FormatConverterInfo_Vtbl;
+ This->ref = 1;
+ This->classkey = classkey;
+ memcpy(&This->clsid, clsid, sizeof(CLSID));
+
+ *ppIInfo = (IWICComponentInfo*)This;
+ return S_OK;
+}
+
+static WCHAR const clsid_keyname[] = {'C','L','S','I','D',0};
+static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
+
+struct category {
+ WICComponentType type;
+ const GUID *catid;
+ HRESULT (*constructor)(HKEY,REFCLSID,IWICComponentInfo**);
+};
+
+static const struct category categories[] = {
+ {WICDecoder, &CATID_WICBitmapDecoders, BitmapDecoderInfo_Constructor},
+ {WICPixelFormatConverter, &CATID_WICFormatConverters, FormatConverterInfo_Constructor},
+ {0}
+};
+
+HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo)
+{
+ HKEY clsidkey;
+ HKEY classkey;
+ HKEY catidkey;
+ HKEY instancekey;
+ WCHAR guidstring[39];
+ LONG res;
+ const struct category *category;
+ int found=0;
+ HRESULT hr;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
+ if (res != ERROR_SUCCESS)
+ return HRESULT_FROM_WIN32(res);
+
+ for (category=categories; category->type; category++)
+ {
+ StringFromGUID2(category->catid, guidstring, 39);
+ res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
+ if (res == ERROR_SUCCESS)
+ {
+ StringFromGUID2(clsid, guidstring, 39);
+ res = RegOpenKeyExW(instancekey, guidstring, 0, KEY_READ, &classkey);
+ if (res == ERROR_SUCCESS)
+ {
+ RegCloseKey(classkey);
+ found = 1;
+ }
+ RegCloseKey(instancekey);
+ }
+ RegCloseKey(catidkey);
+ }
+ if (found) break;
+ }
+
+ if (found)
+ {
+ res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey);
+ if (res == ERROR_SUCCESS)
+ hr = category->constructor(classkey, clsid, ppIInfo);
+ else
+ hr = HRESULT_FROM_WIN32(res);
+ }
+ else
+ hr = E_FAIL;
+
+ RegCloseKey(clsidkey);
+
+ return hr;
+}
+
+typedef struct {
+ const IEnumUnknownVtbl *IEnumUnknown_Vtbl;
+ LONG ref;
+ struct list objects;
+ struct list *cursor;
+} ComponentEnum;
+
+typedef struct {
+ struct list entry;
+ IUnknown *unk;
+} ComponentEnumItem;
+
+static const IEnumUnknownVtbl ComponentEnumVtbl;
+
+static HRESULT WINAPI ComponentEnum_QueryInterface(IEnumUnknown *iface, REFIID iid,
+ void **ppv)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IEnumUnknown, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI ComponentEnum_AddRef(IEnumUnknown *iface)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI ComponentEnum_Release(IEnumUnknown *iface)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+ ComponentEnumItem *cursor, *cursor2;
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->objects, ComponentEnumItem, entry)
+ {
+ IUnknown_Release(cursor->unk);
+ list_remove(&cursor->entry);
+ HeapFree(GetProcessHeap(), 0, cursor);
+ }
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI ComponentEnum_Next(IEnumUnknown *iface, ULONG celt,
+ IUnknown **rgelt, ULONG *pceltFetched)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ int num_fetched=0;
+ ComponentEnumItem *item;
+
+ TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
+
+ while (num_fetchedcursor)
+ {
+ *pceltFetched = num_fetched;
+ return S_FALSE;
+ }
+ item = LIST_ENTRY(This->cursor, ComponentEnumItem, entry);
+ IUnknown_AddRef(item->unk);
+ rgelt[num_fetched] = item->unk;
+ num_fetched++;
+ This->cursor = list_next(&This->objects, This->cursor);
+ }
+ *pceltFetched = num_fetched;
+ return S_OK;
+}
+
+static HRESULT WINAPI ComponentEnum_Skip(IEnumUnknown *iface, ULONG celt)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ int i;
+
+ TRACE("(%p,%u)\n", iface, celt);
+
+ for (i=0; icursor)
+ return S_FALSE;
+ This->cursor = list_next(&This->objects, This->cursor);
+ }
+ return S_OK;
+}
+
+static HRESULT WINAPI ComponentEnum_Reset(IEnumUnknown *iface)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+
+ TRACE("(%p)\n", iface);
+
+ This->cursor = list_head(&This->objects);
+ return S_OK;
+}
+
+static HRESULT WINAPI ComponentEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
+{
+ ComponentEnum *This = (ComponentEnum*)iface;
+ ComponentEnum *new_enum;
+ ComponentEnumItem *old_item, *new_item;
+ HRESULT ret=S_OK;
+
+ new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
+ if (!new_enum)
+ {
+ *ppenum = NULL;
+ return E_OUTOFMEMORY;
+ }
+
+ new_enum->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
+ new_enum->ref = 1;
+ new_enum->cursor = NULL;
+
+ list_init(&new_enum->objects);
+ LIST_FOR_EACH_ENTRY(old_item, &This->objects, ComponentEnumItem, entry)
+ {
+ new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
+ if (!new_item)
+ {
+ ret = E_OUTOFMEMORY;
+ break;
+ }
+ new_item->unk = old_item->unk;
+ list_add_tail(&new_enum->objects, &new_item->entry);
+ IUnknown_AddRef(new_item->unk);
+ if (&old_item->entry == This->cursor) new_enum->cursor = &new_item->entry;
+ }
+
+ if (FAILED(ret))
+ {
+ IUnknown_Release((IUnknown*)new_enum);
+ *ppenum = NULL;
+ }
+ else
+ *ppenum = (IEnumUnknown*)new_enum;
+
+ return ret;
+}
+
+static const IEnumUnknownVtbl ComponentEnumVtbl = {
+ ComponentEnum_QueryInterface,
+ ComponentEnum_AddRef,
+ ComponentEnum_Release,
+ ComponentEnum_Next,
+ ComponentEnum_Skip,
+ ComponentEnum_Reset,
+ ComponentEnum_Clone
+};
+
+HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown)
+{
+ ComponentEnum *This;
+ ComponentEnumItem *item;
+ const struct category *category;
+ HKEY clsidkey, catidkey, instancekey;
+ WCHAR guidstring[39];
+ LONG res;
+ int i;
+ HRESULT hr=S_OK;
+ CLSID clsid;
+
+ if (options) FIXME("ignoring flags %x\n", options);
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey);
+ if (res != ERROR_SUCCESS)
+ return HRESULT_FROM_WIN32(res);
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnum));
+ if (!This)
+ {
+ RegCloseKey(clsidkey);
+ return E_OUTOFMEMORY;
+ }
+
+ This->IEnumUnknown_Vtbl = &ComponentEnumVtbl;
+ This->ref = 1;
+ list_init(&This->objects);
+
+ for (category=categories; category->type && hr == S_OK; category++)
+ {
+ if ((category->type & componentTypes) == 0) continue;
+ StringFromGUID2(category->catid, guidstring, 39);
+ res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &catidkey);
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegOpenKeyExW(catidkey, instance_keyname, 0, KEY_READ, &instancekey);
+ if (res == ERROR_SUCCESS)
+ {
+ i=0;
+ for (;;i++)
+ {
+ DWORD guidstring_size = 39;
+ res = RegEnumKeyExW(instancekey, i, guidstring, &guidstring_size, NULL, NULL, NULL, NULL);
+ if (res != ERROR_SUCCESS) break;
+
+ item = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentEnumItem));
+ if (!item) { hr = E_OUTOFMEMORY; break; }
+
+ hr = CLSIDFromString(guidstring, &clsid);
+ if (SUCCEEDED(hr))
+ {
+ hr = CreateComponentInfo(&clsid, (IWICComponentInfo**)&item->unk);
+ if (SUCCEEDED(hr))
+ list_add_tail(&This->objects, &item->entry);
+ }
+
+ if (!SUCCEEDED(hr))
+ {
+ HeapFree(GetProcessHeap(), 0, item);
+ hr = S_OK;
+ }
+ }
+ RegCloseKey(instancekey);
+ }
+ RegCloseKey(catidkey);
+ }
+ if (res != ERROR_SUCCESS && res != ERROR_NO_MORE_ITEMS)
+ hr = HRESULT_FROM_WIN32(res);
+ }
+ RegCloseKey(clsidkey);
+
+ if (SUCCEEDED(hr))
+ {
+ IEnumUnknown_Reset((IEnumUnknown*)This);
+ *ppIEnumUnknown = (IEnumUnknown*)This;
+ }
+ else
+ {
+ *ppIEnumUnknown = NULL;
+ IUnknown_Release((IUnknown*)This);
+ }
+
+ return hr;
+}
+
+HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
+{
+ HRESULT res;
+ IEnumUnknown *enumconverters;
+ IUnknown *unkconverterinfo;
+ IWICFormatConverterInfo *converterinfo=NULL;
+ IWICFormatConverter *converter=NULL;
+ GUID srcFormat;
+ WCHAR srcformatstr[39], dstformatstr[39];
+ BOOL canconvert;
+ ULONG num_fetched;
+
+ res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat);
+ if (FAILED(res)) return res;
+
+ if (IsEqualGUID(&srcFormat, dstFormat))
+ {
+ IWICBitmapSource_AddRef(pISrc);
+ *ppIDst = pISrc;
+ return S_OK;
+ }
+
+ StringFromGUID2(&srcFormat, srcformatstr, 39);
+ StringFromGUID2(dstFormat, dstformatstr, 39);
+
+ res = CreateComponentEnumerator(WICPixelFormatConverter, 0, &enumconverters);
+ if (FAILED(res)) return res;
+
+ while (!converter)
+ {
+ res = IEnumUnknown_Next(enumconverters, 1, &unkconverterinfo, &num_fetched);
+
+ if (res == S_OK)
+ {
+ res = IUnknown_QueryInterface(unkconverterinfo, &IID_IWICFormatConverterInfo, (void**)&converterinfo);
+
+ if (SUCCEEDED(res))
+ {
+ canconvert = ConverterSupportsFormat(converterinfo, srcformatstr);
+
+ if (canconvert)
+ canconvert = ConverterSupportsFormat(converterinfo, dstformatstr);
+
+ if (canconvert)
+ {
+ res = IWICFormatConverterInfo_CreateInstance(converterinfo, &converter);
+
+ if (SUCCEEDED(res))
+ res = IWICFormatConverter_CanConvert(converter, &srcFormat, dstFormat, &canconvert);
+
+ if (SUCCEEDED(res) && canconvert)
+ res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone,
+ NULL, 0.0, WICBitmapPaletteTypeCustom);
+
+ if (FAILED(res) || !canconvert)
+ {
+ if (converter)
+ {
+ IWICFormatConverter_Release(converter);
+ converter = NULL;
+ }
+ res = S_OK;
+ }
+ }
+
+ IWICFormatConverterInfo_Release(converterinfo);
+ }
+
+ IUnknown_Release(unkconverterinfo);
+ }
+ else
+ break;
+ }
+
+ IEnumUnknown_Release(enumconverters);
+
+ if (converter)
+ {
+ *ppIDst = (IWICBitmapSource*)converter;
+ return S_OK;
+ }
+ else
+ {
+ *ppIDst = NULL;
+ return WINCODEC_ERR_COMPONENTNOTFOUND;
+ }
+}
diff --git a/reactos/dll/win32/windowscodecs/main.c b/reactos/dll/win32/windowscodecs/main.c
new file mode 100644
index 00000000000..7ec5d410e71
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/main.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#include "config.h"
+
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+
+ switch (fdwReason)
+ {
+ case DLL_WINE_PREATTACH:
+ return FALSE; /* prefer native version */
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstDLL);
+ break;
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
+ UINT srcwidth, UINT srcheight, INT srcstride,
+ const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer)
+{
+ UINT bytesperrow;
+ UINT row_offset; /* number of bits into the source rows where the data starts */
+
+ if (rc->X < 0 || rc->Y < 0 || rc->X+rc->Width > srcwidth || rc->Y+rc->Height > srcheight)
+ return E_INVALIDARG;
+
+ bytesperrow = ((bpp * rc->Width)+7)/8;
+
+ if (dststride < bytesperrow)
+ return E_INVALIDARG;
+
+ if ((dststride * rc->Height) > dstbuffersize)
+ return E_INVALIDARG;
+
+ row_offset = rc->X * bpp;
+
+ if (row_offset % 8 == 0)
+ {
+ /* everything lines up on a byte boundary */
+ UINT row;
+ const BYTE *src;
+ BYTE *dst;
+
+ src = srcbuffer + (row_offset / 8) + srcstride * rc->Y;
+ dst = dstbuffer;
+ for (row=0; row < rc->Height; row++)
+ {
+ memcpy(dst, src, bytesperrow);
+ src += srcstride;
+ dst += dststride;
+ }
+ return S_OK;
+ }
+ else
+ {
+ /* we have to do a weird bitwise copy. eww. */
+ FIXME("cannot reliably copy bitmap data if bpp < 8\n");
+ return E_FAIL;
+ }
+}
diff --git a/reactos/dll/win32/windowscodecs/palette.c b/reactos/dll/win32/windowscodecs/palette.c
new file mode 100644
index 00000000000..842d3b51c30
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/palette.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+typedef struct {
+ const IWICPaletteVtbl *lpIWICPaletteVtbl;
+ LONG ref;
+ UINT count;
+ WICColor *colors;
+ WICBitmapPaletteType type;
+} PaletteImpl;
+
+static HRESULT WINAPI PaletteImpl_QueryInterface(IWICPalette *iface, REFIID iid,
+ void **ppv)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICPalette, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI PaletteImpl_AddRef(IWICPalette *iface)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI PaletteImpl_Release(IWICPalette *iface)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, This->colors);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI PaletteImpl_InitializePredefined(IWICPalette *iface,
+ WICBitmapPaletteType ePaletteType, BOOL fAddTransparentColor)
+{
+ FIXME("(%p,%u,%i): stub\n", iface, ePaletteType, fAddTransparentColor);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PaletteImpl_InitializeCustom(IWICPalette *iface,
+ WICColor *pColors, UINT colorCount)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+ WICColor *new_colors;
+
+ TRACE("(%p,%p,%u)\n", iface, pColors, colorCount);
+
+ if (colorCount == 0)
+ {
+ new_colors = NULL;
+ }
+ else
+ {
+ if (!pColors) return E_INVALIDARG;
+ new_colors = HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor) * colorCount);
+ if (!new_colors) return E_OUTOFMEMORY;
+ memcpy(new_colors, pColors, sizeof(WICColor) * colorCount);
+ }
+
+ HeapFree(GetProcessHeap(), 0, This->colors);
+ This->colors = new_colors;
+ This->count = colorCount;
+ This->type = WICBitmapPaletteTypeCustom;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI PaletteImpl_InitializeFromBitmap(IWICPalette *iface,
+ IWICBitmapSource *pISurface, UINT colorCount, BOOL fAddTransparentColor)
+{
+ FIXME("(%p,%p,%u,%i): stub\n", iface, pISurface, colorCount, fAddTransparentColor);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PaletteImpl_InitializeFromPalette(IWICPalette *iface,
+ IWICPalette *pIPalette)
+{
+ FIXME("(%p,%p): stub\n", iface, pIPalette);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PaletteImpl_GetType(IWICPalette *iface,
+ WICBitmapPaletteType *pePaletteType)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+
+ TRACE("(%p,%p)\n", iface, pePaletteType);
+
+ if (!pePaletteType) return E_INVALIDARG;
+
+ *pePaletteType = This->type;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI PaletteImpl_GetColorCount(IWICPalette *iface, UINT *pcCount)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+
+ TRACE("(%p,%p)\n", iface, pcCount);
+
+ if (!pcCount) return E_INVALIDARG;
+
+ *pcCount = This->count;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI PaletteImpl_GetColors(IWICPalette *iface, UINT colorCount,
+ WICColor *pColors, UINT *pcActualColors)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+
+ TRACE("(%p,%i,%p,%p)\n", iface, colorCount, pColors, pcActualColors);
+
+ if (!pColors || !pcActualColors) return E_INVALIDARG;
+
+ if (This->count < colorCount) colorCount = This->count;
+
+ memcpy(pColors, This->colors, sizeof(WICColor) * colorCount);
+
+ *pcActualColors = colorCount;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI PaletteImpl_IsBlackWhite(IWICPalette *iface, BOOL *pfIsBlackWhite)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+
+ TRACE("(%p,%p)\n", iface, pfIsBlackWhite);
+
+ if (!pfIsBlackWhite) return E_INVALIDARG;
+
+ if (This->type == WICBitmapPaletteTypeFixedBW)
+ *pfIsBlackWhite = TRUE;
+ else
+ *pfIsBlackWhite = FALSE;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI PaletteImpl_IsGrayscale(IWICPalette *iface, BOOL *pfIsGrayscale)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+
+ TRACE("(%p,%p)\n", iface, pfIsGrayscale);
+
+ if (!pfIsGrayscale) return E_INVALIDARG;
+
+ switch(This->type)
+ {
+ case WICBitmapPaletteTypeFixedBW:
+ case WICBitmapPaletteTypeFixedGray4:
+ case WICBitmapPaletteTypeFixedGray16:
+ case WICBitmapPaletteTypeFixedGray256:
+ *pfIsGrayscale = TRUE;
+ break;
+ default:
+ *pfIsGrayscale = FALSE;
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI PaletteImpl_HasAlpha(IWICPalette *iface, BOOL *pfHasAlpha)
+{
+ PaletteImpl *This = (PaletteImpl*)iface;
+ int i;
+
+ TRACE("(%p,%p)\n", iface, pfHasAlpha);
+
+ if (!pfHasAlpha) return E_INVALIDARG;
+
+ *pfHasAlpha = FALSE;
+
+ for (i=0; icount; i++)
+ if ((This->colors[i]&0xff000000) != 0xff000000)
+ {
+ *pfHasAlpha = TRUE;
+ break;
+ }
+
+ return S_OK;
+}
+
+static const IWICPaletteVtbl PaletteImpl_Vtbl = {
+ PaletteImpl_QueryInterface,
+ PaletteImpl_AddRef,
+ PaletteImpl_Release,
+ PaletteImpl_InitializePredefined,
+ PaletteImpl_InitializeCustom,
+ PaletteImpl_InitializeFromBitmap,
+ PaletteImpl_InitializeFromPalette,
+ PaletteImpl_GetType,
+ PaletteImpl_GetColorCount,
+ PaletteImpl_GetColors,
+ PaletteImpl_IsBlackWhite,
+ PaletteImpl_IsGrayscale,
+ PaletteImpl_HasAlpha
+};
+
+HRESULT PaletteImpl_Create(IWICPalette **palette)
+{
+ PaletteImpl *This;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(PaletteImpl));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->lpIWICPaletteVtbl = &PaletteImpl_Vtbl;
+ This->ref = 1;
+ This->count = 0;
+ This->colors = NULL;
+ This->type = WICBitmapPaletteTypeCustom;
+
+ *palette = (IWICPalette*)This;
+
+ return S_OK;
+}
diff --git a/reactos/dll/win32/windowscodecs/propertybag.c b/reactos/dll/win32/windowscodecs/propertybag.c
new file mode 100644
index 00000000000..ca40b3b65ba
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/propertybag.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "objbase.h"
+#include "wincodec.h"
+
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+typedef struct PropertyBag {
+ const IPropertyBag2Vtbl *lpVtbl;
+ LONG ref;
+} PropertyBag;
+
+static HRESULT WINAPI PropertyBag_QueryInterface(IPropertyBag2 *iface, REFIID iid,
+ void **ppv)
+{
+ PropertyBag *This = (PropertyBag*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) ||
+ IsEqualIID(&IID_IPropertyBag2, iid))
+ {
+ *ppv = This;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI PropertyBag_AddRef(IPropertyBag2 *iface)
+{
+ PropertyBag *This = (PropertyBag*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI PropertyBag_Release(IPropertyBag2 *iface)
+{
+ PropertyBag *This = (PropertyBag*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI PropertyBag_Read(IPropertyBag2 *iface, ULONG cProperties,
+ PROPBAG2 *pPropBag, IErrorLog *pErrLog, VARIANT *pvarValue, HRESULT *phrError)
+{
+ FIXME("(%p,%u,%p,%p,%p,%p): stub\n", iface, cProperties, pPropBag, pErrLog, pvarValue, phrError);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PropertyBag_Write(IPropertyBag2 *iface, ULONG cProperties,
+ PROPBAG2 *pPropBag, VARIANT *pvarValue)
+{
+ FIXME("(%p,%u,%p,%p): stub\n", iface, cProperties, pPropBag, pvarValue);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PropertyBag_CountProperties(IPropertyBag2 *iface, ULONG *pcProperties)
+{
+ FIXME("(%p,%p): stub\n", iface, pcProperties);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PropertyBag_GetPropertyInfo(IPropertyBag2 *iface, ULONG iProperty,
+ ULONG cProperties, PROPBAG2 *pPropBag, ULONG *pcProperties)
+{
+ FIXME("(%p,%u,%u,%p,%p): stub\n", iface, iProperty, cProperties, pPropBag, pcProperties);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PropertyBag_LoadObject(IPropertyBag2 *iface, LPCOLESTR pstrName,
+ DWORD dwHint, IUnknown *pUnkObject, IErrorLog *pErrLog)
+{
+ FIXME("(%p,%s,%u,%p,%p): stub\n", iface, debugstr_w(pstrName), dwHint, pUnkObject, pErrLog);
+ return E_NOTIMPL;
+}
+
+static const IPropertyBag2Vtbl PropertyBag_Vtbl = {
+ PropertyBag_QueryInterface,
+ PropertyBag_AddRef,
+ PropertyBag_Release,
+ PropertyBag_Read,
+ PropertyBag_Write,
+ PropertyBag_CountProperties,
+ PropertyBag_GetPropertyInfo,
+ PropertyBag_LoadObject
+};
+
+extern HRESULT CreatePropertyBag2(IPropertyBag2 **ppPropertyBag2)
+{
+ PropertyBag *This;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(PropertyBag));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->lpVtbl = &PropertyBag_Vtbl;
+ This->ref = 1;
+
+ *ppPropertyBag2 = (IPropertyBag2*)This;
+
+ return S_OK;
+}
diff --git a/reactos/dll/win32/windowscodecs/regsvr.c b/reactos/dll/win32/windowscodecs/regsvr.c
new file mode 100644
index 00000000000..b931b19edc4
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/regsvr.c
@@ -0,0 +1,899 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#define COBJMACROS
+#include
+#include
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "winerror.h"
+
+#include "objbase.h"
+#include "ocidl.h"
+#include "wincodec.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+/***********************************************************************
+ * interface for self-registering
+ */
+struct regsvr_coclass
+{
+ CLSID const *clsid; /* NULL for end of list */
+ LPCSTR name; /* can be NULL to omit */
+ LPCSTR ips; /* can be NULL to omit */
+ LPCSTR ips32; /* can be NULL to omit */
+ LPCSTR ips32_tmodel; /* can be NULL to omit */
+ LPCSTR progid; /* can be NULL to omit */
+ LPCSTR viprogid; /* can be NULL to omit */
+ LPCSTR progid_extra; /* can be NULL to omit */
+};
+
+static HRESULT register_coclasses(struct regsvr_coclass const *list);
+static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
+
+struct decoder_pattern
+{
+ DWORD length; /* 0 for end of list */
+ DWORD position;
+ const BYTE *pattern;
+ const BYTE *mask;
+ DWORD endofstream;
+};
+
+struct regsvr_decoder
+{
+ CLSID const *clsid; /* NULL for end of list */
+ LPCSTR author;
+ LPCSTR friendlyname;
+ LPCSTR version;
+ GUID const *vendor;
+ LPCSTR mimetypes;
+ LPCSTR extensions;
+ GUID const * const *formats;
+ const struct decoder_pattern *patterns;
+};
+
+static HRESULT register_decoders(struct regsvr_decoder const *list);
+static HRESULT unregister_decoders(struct regsvr_decoder const *list);
+
+struct regsvr_converter
+{
+ CLSID const *clsid; /* NULL for end of list */
+ LPCSTR author;
+ LPCSTR friendlyname;
+ LPCSTR version;
+ GUID const *vendor;
+ GUID const * const *formats;
+};
+
+static HRESULT register_converters(struct regsvr_converter const *list);
+static HRESULT unregister_converters(struct regsvr_converter const *list);
+
+/***********************************************************************
+ * static string constants
+ */
+static WCHAR const clsid_keyname[6] = {
+ 'C', 'L', 'S', 'I', 'D', 0 };
+static WCHAR const curver_keyname[7] = {
+ 'C', 'u', 'r', 'V', 'e', 'r', 0 };
+static WCHAR const ips_keyname[13] = {
+ 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
+ 0 };
+static WCHAR const ips32_keyname[15] = {
+ 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
+ '3', '2', 0 };
+static WCHAR const progid_keyname[7] = {
+ 'P', 'r', 'o', 'g', 'I', 'D', 0 };
+static WCHAR const viprogid_keyname[25] = {
+ 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
+ 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
+ 0 };
+static char const tmodel_valuename[] = "ThreadingModel";
+static char const author_valuename[] = "Author";
+static char const friendlyname_valuename[] = "FriendlyName";
+static WCHAR const vendor_valuename[] = {'V','e','n','d','o','r',0};
+static char const version_valuename[] = "Version";
+static char const mimetypes_valuename[] = "MimeTypes";
+static char const extensions_valuename[] = "FileExtensions";
+static WCHAR const formats_keyname[] = {'F','o','r','m','a','t','s',0};
+static WCHAR const patterns_keyname[] = {'P','a','t','t','e','r','n','s',0};
+static WCHAR const instance_keyname[] = {'I','n','s','t','a','n','c','e',0};
+static WCHAR const clsid_valuename[] = {'C','L','S','I','D',0};
+static char const length_valuename[] = "Length";
+static char const position_valuename[] = "Position";
+static char const pattern_valuename[] = "Pattern";
+static char const mask_valuename[] = "Mask";
+static char const endofstream_valuename[] = "EndOfStream";
+static WCHAR const pixelformats_keyname[] = {'P','i','x','e','l','F','o','r','m','a','t','s',0};
+
+/***********************************************************************
+ * static helper functions
+ */
+static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
+ WCHAR const *value);
+static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
+ char const *value);
+static LONG register_progid(WCHAR const *clsid,
+ char const *progid, char const *curver_progid,
+ char const *name, char const *extra);
+
+/***********************************************************************
+ * register_coclasses
+ */
+static HRESULT register_coclasses(struct regsvr_coclass const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+
+ res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ WCHAR buf[39];
+ HKEY clsid_key;
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ if (list->name) {
+ res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)(list->name),
+ strlen(list->name) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->ips) {
+ res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->ips32) {
+ HKEY ips32_key;
+
+ res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL,
+ &ips32_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)list->ips32,
+ lstrlenA(list->ips32) + 1);
+ if (res == ERROR_SUCCESS && list->ips32_tmodel)
+ res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
+ (CONST BYTE*)list->ips32_tmodel,
+ strlen(list->ips32_tmodel) + 1);
+ RegCloseKey(ips32_key);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->progid) {
+ res = register_key_defvalueA(clsid_key, progid_keyname,
+ list->progid);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = register_progid(buf, list->progid, NULL,
+ list->name, list->progid_extra);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->viprogid) {
+ res = register_key_defvalueA(clsid_key, viprogid_keyname,
+ list->viprogid);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ res = register_progid(buf, list->viprogid, list->progid,
+ list->name, list->progid_extra);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ error_close_clsid_key:
+ RegCloseKey(clsid_key);
+ }
+
+error_close_coclass_key:
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * unregister_coclasses
+ */
+static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
+ KEY_READ | KEY_WRITE, &coclass_key);
+ if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ WCHAR buf[39];
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegDeleteTreeW(coclass_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ if (list->progid) {
+ res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+
+ if (list->viprogid) {
+ res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+ }
+
+error_close_coclass_key:
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * register_decoders
+ */
+static HRESULT register_decoders(struct regsvr_decoder const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+ WCHAR buf[39];
+ HKEY decoders_key;
+ HKEY instance_key;
+
+ res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
+ if (res == ERROR_SUCCESS) {
+ StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+ if (res != ERROR_SUCCESS)
+ RegCloseKey(coclass_key);
+ }
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ HKEY clsid_key;
+ HKEY instance_clsid_key;
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
+ if (res == ERROR_SUCCESS) {
+ res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
+ (CONST BYTE*)(buf), 78);
+ RegCloseKey(instance_clsid_key);
+ }
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ if (list->author) {
+ res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
+ (CONST BYTE*)(list->author),
+ strlen(list->author) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->friendlyname) {
+ res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
+ (CONST BYTE*)(list->friendlyname),
+ strlen(list->friendlyname) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->vendor) {
+ StringFromGUID2(list->vendor, buf, 39);
+ res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
+ (CONST BYTE*)(buf), 78);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->version) {
+ res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
+ (CONST BYTE*)(list->version),
+ strlen(list->version) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->mimetypes) {
+ res = RegSetValueExA(clsid_key, mimetypes_valuename, 0, REG_SZ,
+ (CONST BYTE*)(list->mimetypes),
+ strlen(list->mimetypes) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->extensions) {
+ res = RegSetValueExA(clsid_key, extensions_valuename, 0, REG_SZ,
+ (CONST BYTE*)(list->extensions),
+ strlen(list->extensions) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->formats) {
+ HKEY formats_key;
+ GUID const * const *format;
+
+ res = RegCreateKeyExW(clsid_key, formats_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ for (format=list->formats; *format; ++format)
+ {
+ HKEY format_key;
+ StringFromGUID2(*format, buf, 39);
+ res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
+ if (res != ERROR_SUCCESS) break;
+ RegCloseKey(format_key);
+ }
+ RegCloseKey(formats_key);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->patterns) {
+ HKEY patterns_key;
+ int i;
+
+ res = RegCreateKeyExW(clsid_key, patterns_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &patterns_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ for (i=0; list->patterns[i].length; i++)
+ {
+ HKEY pattern_key;
+ static const WCHAR int_format[] = {'%','i',0};
+ snprintfW(buf, 39, int_format, i);
+ res = RegCreateKeyExW(patterns_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &pattern_key, NULL);
+ if (res != ERROR_SUCCESS) break;
+ res = RegSetValueExA(pattern_key, length_valuename, 0, REG_DWORD,
+ (CONST BYTE*)(&list->patterns[i].length), 4);
+ if (res == ERROR_SUCCESS)
+ res = RegSetValueExA(pattern_key, position_valuename, 0, REG_DWORD,
+ (CONST BYTE*)(&list->patterns[i].position), 4);
+ if (res == ERROR_SUCCESS)
+ res = RegSetValueExA(pattern_key, pattern_valuename, 0, REG_BINARY,
+ list->patterns[i].pattern,
+ list->patterns[i].length);
+ if (res == ERROR_SUCCESS)
+ res = RegSetValueExA(pattern_key, mask_valuename, 0, REG_BINARY,
+ list->patterns[i].mask,
+ list->patterns[i].length);
+ if (res == ERROR_SUCCESS)
+ res = RegSetValueExA(pattern_key, endofstream_valuename, 0, REG_DWORD,
+ (CONST BYTE*)&(list->patterns[i].endofstream), 4);
+ RegCloseKey(pattern_key);
+ }
+ RegCloseKey(patterns_key);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ error_close_clsid_key:
+ RegCloseKey(clsid_key);
+ }
+
+error_close_coclass_key:
+ RegCloseKey(instance_key);
+ RegCloseKey(decoders_key);
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * unregister_decoders
+ */
+static HRESULT unregister_decoders(struct regsvr_decoder const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+ WCHAR buf[39];
+ HKEY decoders_key;
+ HKEY instance_key;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
+ KEY_READ | KEY_WRITE, &coclass_key);
+ if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+
+ if (res == ERROR_SUCCESS) {
+ StringFromGUID2(&CATID_WICBitmapDecoders, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &decoders_key, NULL);
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegCreateKeyExW(decoders_key, instance_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+ if (res != ERROR_SUCCESS)
+ RegCloseKey(coclass_key);
+ }
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ StringFromGUID2(list->clsid, buf, 39);
+
+ res = RegDeleteTreeW(coclass_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ res = RegDeleteTreeW(instance_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+
+error_close_coclass_key:
+ RegCloseKey(instance_key);
+ RegCloseKey(decoders_key);
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * register_converters
+ */
+static HRESULT register_converters(struct regsvr_converter const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+ WCHAR buf[39];
+ HKEY converters_key;
+ HKEY instance_key;
+
+ res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
+ if (res == ERROR_SUCCESS) {
+ StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+ if (res != ERROR_SUCCESS)
+ RegCloseKey(coclass_key);
+ }
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ HKEY clsid_key;
+ HKEY instance_clsid_key;
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ StringFromGUID2(list->clsid, buf, 39);
+ res = RegCreateKeyExW(instance_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &instance_clsid_key, NULL);
+ if (res == ERROR_SUCCESS) {
+ res = RegSetValueExW(instance_clsid_key, clsid_valuename, 0, REG_SZ,
+ (CONST BYTE*)(buf), 78);
+ RegCloseKey(instance_clsid_key);
+ }
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+
+ if (list->author) {
+ res = RegSetValueExA(clsid_key, author_valuename, 0, REG_SZ,
+ (CONST BYTE*)(list->author),
+ strlen(list->author) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->friendlyname) {
+ res = RegSetValueExA(clsid_key, friendlyname_valuename, 0, REG_SZ,
+ (CONST BYTE*)(list->friendlyname),
+ strlen(list->friendlyname) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->vendor) {
+ StringFromGUID2(list->vendor, buf, 39);
+ res = RegSetValueExW(clsid_key, vendor_valuename, 0, REG_SZ,
+ (CONST BYTE*)(buf), 78);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->version) {
+ res = RegSetValueExA(clsid_key, version_valuename, 0, REG_SZ,
+ (CONST BYTE*)(list->version),
+ strlen(list->version) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ if (list->formats) {
+ HKEY formats_key;
+ GUID const * const *format;
+
+ res = RegCreateKeyExW(clsid_key, pixelformats_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &formats_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ for (format=list->formats; *format; ++format)
+ {
+ HKEY format_key;
+ StringFromGUID2(*format, buf, 39);
+ res = RegCreateKeyExW(formats_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &format_key, NULL);
+ if (res != ERROR_SUCCESS) break;
+ RegCloseKey(format_key);
+ }
+ RegCloseKey(formats_key);
+ if (res != ERROR_SUCCESS) goto error_close_clsid_key;
+ }
+
+ error_close_clsid_key:
+ RegCloseKey(clsid_key);
+ }
+
+error_close_coclass_key:
+ RegCloseKey(instance_key);
+ RegCloseKey(converters_key);
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * unregister_converters
+ */
+static HRESULT unregister_converters(struct regsvr_converter const *list)
+{
+ LONG res = ERROR_SUCCESS;
+ HKEY coclass_key;
+ WCHAR buf[39];
+ HKEY converters_key;
+ HKEY instance_key;
+
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
+ KEY_READ | KEY_WRITE, &coclass_key);
+ if (res == ERROR_FILE_NOT_FOUND) return S_OK;
+
+ if (res == ERROR_SUCCESS) {
+ StringFromGUID2(&CATID_WICFormatConverters, buf, 39);
+ res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &converters_key, NULL);
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegCreateKeyExW(converters_key, instance_keyname, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &instance_key, NULL);
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+ if (res != ERROR_SUCCESS)
+ RegCloseKey(coclass_key);
+ }
+ if (res != ERROR_SUCCESS) goto error_return;
+
+ for (; res == ERROR_SUCCESS && list->clsid; ++list) {
+ StringFromGUID2(list->clsid, buf, 39);
+
+ res = RegDeleteTreeW(coclass_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+
+ res = RegDeleteTreeW(instance_key, buf);
+ if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
+ if (res != ERROR_SUCCESS) goto error_close_coclass_key;
+ }
+
+error_close_coclass_key:
+ RegCloseKey(instance_key);
+ RegCloseKey(converters_key);
+ RegCloseKey(coclass_key);
+error_return:
+ return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
+}
+
+/***********************************************************************
+ * register_key_defvalueW
+ */
+static LONG register_key_defvalueW(
+ HKEY base,
+ WCHAR const *name,
+ WCHAR const *value)
+{
+ LONG res;
+ HKEY key;
+
+ res = RegCreateKeyExW(base, name, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) return res;
+ res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
+ (lstrlenW(value) + 1) * sizeof(WCHAR));
+ RegCloseKey(key);
+ return res;
+}
+
+/***********************************************************************
+ * register_key_defvalueA
+ */
+static LONG register_key_defvalueA(
+ HKEY base,
+ WCHAR const *name,
+ char const *value)
+{
+ LONG res;
+ HKEY key;
+
+ res = RegCreateKeyExW(base, name, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) return res;
+ res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
+ lstrlenA(value) + 1);
+ RegCloseKey(key);
+ return res;
+}
+
+/***********************************************************************
+ * register_progid
+ */
+static LONG register_progid(
+ WCHAR const *clsid,
+ char const *progid,
+ char const *curver_progid,
+ char const *name,
+ char const *extra)
+{
+ LONG res;
+ HKEY progid_key;
+
+ res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
+ NULL, 0, KEY_READ | KEY_WRITE, NULL,
+ &progid_key, NULL);
+ if (res != ERROR_SUCCESS) return res;
+
+ if (name) {
+ res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
+ (CONST BYTE*)name, strlen(name) + 1);
+ if (res != ERROR_SUCCESS) goto error_close_progid_key;
+ }
+
+ if (clsid) {
+ res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
+ if (res != ERROR_SUCCESS) goto error_close_progid_key;
+ }
+
+ if (curver_progid) {
+ res = register_key_defvalueA(progid_key, curver_keyname,
+ curver_progid);
+ if (res != ERROR_SUCCESS) goto error_close_progid_key;
+ }
+
+ if (extra) {
+ HKEY extra_key;
+
+ res = RegCreateKeyExA(progid_key, extra, 0,
+ NULL, 0, KEY_READ | KEY_WRITE, NULL,
+ &extra_key, NULL);
+ if (res == ERROR_SUCCESS)
+ RegCloseKey(extra_key);
+ }
+
+error_close_progid_key:
+ RegCloseKey(progid_key);
+ return res;
+}
+
+/***********************************************************************
+ * coclass list
+ */
+static struct regsvr_coclass const coclass_list[] = {
+ { &CLSID_WICImagingFactory,
+ "WIC Imaging Factory",
+ NULL,
+ "windowscodecs.dll",
+ "Apartment"
+ },
+ { &CLSID_WICBmpDecoder,
+ "WIC BMP Decoder",
+ NULL,
+ "windowscodecs.dll",
+ "Apartment"
+ },
+ { &CLSID_WICBmpEncoder,
+ "WIC BMP Encoder",
+ NULL,
+ "windowscodecs.dll",
+ "Apartment"
+ },
+ { &CLSID_WICGifDecoder,
+ "WIC GIF Decoder",
+ NULL,
+ "windowscodecs.dll",
+ "Apartment"
+ },
+ { &CLSID_WICIcoDecoder,
+ "WIC ICO Decoder",
+ NULL,
+ "windowscodecs.dll",
+ "Apartment"
+ },
+ { &CLSID_WICDefaultFormatConverter,
+ "WIC Default Format Converter",
+ NULL,
+ "windowscodecs.dll",
+ "Apartment"
+ },
+ { NULL } /* list terminator */
+};
+
+/***********************************************************************
+ * decoder list
+ */
+static const BYTE mask_all[] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+static const BYTE bmp_magic[] = {0x42,0x4d};
+
+static GUID const * const bmp_formats[] = {
+ &GUID_WICPixelFormat1bppIndexed,
+ &GUID_WICPixelFormat2bppIndexed,
+ &GUID_WICPixelFormat4bppIndexed,
+ &GUID_WICPixelFormat8bppIndexed,
+ &GUID_WICPixelFormat16bppBGR555,
+ &GUID_WICPixelFormat16bppBGR565,
+ &GUID_WICPixelFormat24bppBGR,
+ &GUID_WICPixelFormat32bppBGR,
+ &GUID_WICPixelFormat32bppBGRA,
+ NULL
+};
+
+static struct decoder_pattern const bmp_patterns[] = {
+ {2,0,bmp_magic,mask_all,0},
+ {0}
+};
+
+static const BYTE gif87a_magic[6] = "GIF87a";
+static const BYTE gif89a_magic[6] = "GIF89a";
+
+static GUID const * const gif_formats[] = {
+ &GUID_WICPixelFormat8bppIndexed,
+ NULL
+};
+
+static struct decoder_pattern const gif_patterns[] = {
+ {6,0,gif87a_magic,mask_all,0},
+ {6,0,gif89a_magic,mask_all,0},
+ {0}
+};
+
+static const BYTE ico_magic[] = {00,00,01,00};
+
+static GUID const * const ico_formats[] = {
+ &GUID_WICPixelFormat32bppBGRA,
+ NULL
+};
+
+static struct decoder_pattern const ico_patterns[] = {
+ {4,0,ico_magic,mask_all,0},
+ {0}
+};
+
+static struct regsvr_decoder const decoder_list[] = {
+ { &CLSID_WICBmpDecoder,
+ "The Wine Project",
+ "BMP Decoder",
+ "1.0.0.0",
+ &GUID_VendorMicrosoft,
+ "image/bmp",
+ ".bmp,.dib,.rle",
+ bmp_formats,
+ bmp_patterns
+ },
+ { &CLSID_WICGifDecoder,
+ "The Wine Project",
+ "GIF Decoder",
+ "1.0.0.0",
+ &GUID_VendorMicrosoft,
+ "image/gif",
+ ".gif",
+ gif_formats,
+ gif_patterns
+ },
+ { &CLSID_WICIcoDecoder,
+ "The Wine Project",
+ "ICO Decoder",
+ "1.0.0.0",
+ &GUID_VendorMicrosoft,
+ "image/vnd.microsoft.icon",
+ ".ico",
+ ico_formats,
+ ico_patterns
+ },
+ { NULL } /* list terminator */
+};
+
+static GUID const * const converter_formats[] = {
+ &GUID_WICPixelFormat1bppIndexed,
+ &GUID_WICPixelFormat4bppIndexed,
+ &GUID_WICPixelFormat8bppIndexed,
+ &GUID_WICPixelFormat16bppBGR555,
+ &GUID_WICPixelFormat16bppBGR565,
+ &GUID_WICPixelFormat24bppBGR,
+ &GUID_WICPixelFormat32bppBGR,
+ &GUID_WICPixelFormat32bppBGRA,
+ NULL
+};
+
+static struct regsvr_converter const converter_list[] = {
+ { &CLSID_WICDefaultFormatConverter,
+ "The Wine Project",
+ "Default Pixel Format Converter",
+ "1.0.0.0",
+ &GUID_VendorMicrosoft,
+ converter_formats
+ },
+ { NULL } /* list terminator */
+};
+
+HRESULT WINAPI DllRegisterServer(void)
+{
+ HRESULT hr;
+
+ TRACE("\n");
+
+ hr = register_coclasses(coclass_list);
+ if (SUCCEEDED(hr))
+ register_decoders(decoder_list);
+ if (SUCCEEDED(hr))
+ register_converters(converter_list);
+ return hr;
+}
+
+HRESULT WINAPI DllUnregisterServer(void)
+{
+ HRESULT hr;
+
+ TRACE("\n");
+
+ hr = unregister_coclasses(coclass_list);
+ if (SUCCEEDED(hr))
+ unregister_decoders(decoder_list);
+ if (SUCCEEDED(hr))
+ unregister_converters(converter_list);
+ return hr;
+}
diff --git a/reactos/dll/win32/windowscodecs/stream.c b/reactos/dll/win32/windowscodecs/stream.c
new file mode 100644
index 00000000000..ba1b2a6498a
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/stream.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright 2009 Tony Wasserka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wine/debug.h"
+
+#define COBJMACROS
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "objbase.h"
+#include "wincodec.h"
+#include "wincodecs_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+/******************************************
+ * StreamOnMemory implementation
+ *
+ * Used by IWICStream_InitializeFromMemory
+ *
+ */
+typedef struct StreamOnMemory {
+ const IStreamVtbl *lpVtbl;
+ LONG ref;
+
+ BYTE *pbMemory;
+ DWORD dwMemsize;
+ DWORD dwCurPos;
+} StreamOnMemory;
+
+static HRESULT WINAPI StreamOnMemory_QueryInterface(IStream *iface,
+ REFIID iid, void **ppv)
+{
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
+ IsEqualIID(&IID_ISequentialStream, iid))
+ {
+ *ppv = iface;
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+static ULONG WINAPI StreamOnMemory_AddRef(IStream *iface)
+{
+ StreamOnMemory *This = (StreamOnMemory*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI StreamOnMemory_Release(IStream *iface)
+{
+ StreamOnMemory *This = (StreamOnMemory*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0) {
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
+ void *pv, ULONG cb, ULONG *pcbRead)
+{
+ StreamOnMemory *This = (StreamOnMemory*)iface;
+ ULONG uBytesRead;
+ TRACE("(%p)\n", This);
+
+ if (!pv) return E_INVALIDARG;
+
+ uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
+ memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead);
+ This->dwCurPos += uBytesRead;
+ if (pcbRead) *pcbRead = uBytesRead;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
+ void const *pv, ULONG cb, ULONG *pcbWritten)
+{
+ StreamOnMemory *This = (StreamOnMemory*)iface;
+ TRACE("(%p)\n", This);
+
+ if (!pv) return E_INVALIDARG;
+
+ if (cb > This->dwMemsize - This->dwCurPos) return STG_E_MEDIUMFULL;
+ if (cb) {
+ memcpy(This->pbMemory + This->dwCurPos, pv, cb);
+ This->dwCurPos += cb;
+ }
+ if (pcbWritten) *pcbWritten = cb;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI StreamOnMemory_Seek(IStream *iface,
+ LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
+{
+ StreamOnMemory *This = (StreamOnMemory*)iface;
+ LARGE_INTEGER NewPosition;
+ TRACE("(%p)\n", This);
+
+ if (dlibMove.QuadPart > 0xFFFFFFFF) return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
+
+ if (dwOrigin == STREAM_SEEK_SET) NewPosition.QuadPart = dlibMove.QuadPart;
+ else if (dwOrigin == STREAM_SEEK_CUR) NewPosition.QuadPart = This->dwCurPos + dlibMove.QuadPart;
+ else if (dwOrigin == STREAM_SEEK_END) NewPosition.QuadPart = This->dwMemsize + dlibMove.QuadPart;
+ else return E_INVALIDARG;
+
+ if (NewPosition.QuadPart > This->dwMemsize) return E_INVALIDARG;
+ if (NewPosition.QuadPart < 0) return E_INVALIDARG;
+ This->dwCurPos = NewPosition.LowPart;
+
+ if(plibNewPosition) plibNewPosition->QuadPart = This->dwCurPos;
+ return S_OK;
+}
+
+/* SetSize isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnMemory_SetSize(IStream *iface,
+ ULARGE_INTEGER libNewSize)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* CopyTo isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnMemory_CopyTo(IStream *iface,
+ IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* Commit isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnMemory_Commit(IStream *iface,
+ DWORD grfCommitFlags)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* Revert isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnMemory_Revert(IStream *iface)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* LockRegion isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnMemory_LockRegion(IStream *iface,
+ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+/* UnlockRegion isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnMemory_UnlockRegion(IStream *iface,
+ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI StreamOnMemory_Stat(IStream *iface,
+ STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ StreamOnMemory *This = (StreamOnMemory*)iface;
+ TRACE("(%p)\n", This);
+
+ if (!pstatstg) return E_INVALIDARG;
+
+ ZeroMemory(pstatstg, sizeof(STATSTG));
+ pstatstg->type = STGTY_STREAM;
+ pstatstg->cbSize.QuadPart = This->dwMemsize;
+
+ return S_OK;
+}
+
+/* Clone isn't implemented in the native windowscodecs DLL either */
+static HRESULT WINAPI StreamOnMemory_Clone(IStream *iface,
+ IStream **ppstm)
+{
+ TRACE("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+
+const IStreamVtbl StreamOnMemory_Vtbl =
+{
+ /*** IUnknown methods ***/
+ StreamOnMemory_QueryInterface,
+ StreamOnMemory_AddRef,
+ StreamOnMemory_Release,
+ /*** ISequentialStream methods ***/
+ StreamOnMemory_Read,
+ StreamOnMemory_Write,
+ /*** IStream methods ***/
+ StreamOnMemory_Seek,
+ StreamOnMemory_SetSize,
+ StreamOnMemory_CopyTo,
+ StreamOnMemory_Commit,
+ StreamOnMemory_Revert,
+ StreamOnMemory_LockRegion,
+ StreamOnMemory_UnlockRegion,
+ StreamOnMemory_Stat,
+ StreamOnMemory_Clone,
+};
+
+/******************************************
+ * IWICStream implementation
+ *
+ */
+typedef struct IWICStreamImpl
+{
+ const IWICStreamVtbl *lpVtbl;
+ LONG ref;
+
+ IStream *pStream;
+} IWICStreamImpl;
+
+static HRESULT WINAPI IWICStreamImpl_QueryInterface(IWICStream *iface,
+ REFIID iid, void **ppv)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
+
+ if (!ppv) return E_INVALIDARG;
+
+ if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IStream, iid) ||
+ IsEqualIID(&IID_ISequentialStream, iid) || IsEqualIID(&IID_IWICStream, iid))
+ {
+ *ppv = This;
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+static ULONG WINAPI IWICStreamImpl_AddRef(IWICStream *iface)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI IWICStreamImpl_Release(IWICStream *iface)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0) {
+ if (This->pStream) IStream_Release(This->pStream);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI IWICStreamImpl_Read(IWICStream *iface,
+ void *pv, ULONG cb, ULONG *pcbRead)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_Read(This->pStream, pv, cb, pcbRead);
+}
+
+static HRESULT WINAPI IWICStreamImpl_Write(IWICStream *iface,
+ void const *pv, ULONG cb, ULONG *pcbWritten)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_Write(This->pStream, pv, cb, pcbWritten);
+}
+
+static HRESULT WINAPI IWICStreamImpl_Seek(IWICStream *iface,
+ LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_Seek(This->pStream, dlibMove, dwOrigin, plibNewPosition);
+}
+
+static HRESULT WINAPI IWICStreamImpl_SetSize(IWICStream *iface,
+ ULARGE_INTEGER libNewSize)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_SetSize(This->pStream, libNewSize);
+}
+
+static HRESULT WINAPI IWICStreamImpl_CopyTo(IWICStream *iface,
+ IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_CopyTo(This->pStream, pstm, cb, pcbRead, pcbWritten);
+}
+
+static HRESULT WINAPI IWICStreamImpl_Commit(IWICStream *iface,
+ DWORD grfCommitFlags)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_Commit(This->pStream, grfCommitFlags);
+}
+
+static HRESULT WINAPI IWICStreamImpl_Revert(IWICStream *iface)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_Revert(This->pStream);
+}
+
+static HRESULT WINAPI IWICStreamImpl_LockRegion(IWICStream *iface,
+ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_LockRegion(This->pStream, libOffset, cb, dwLockType);
+}
+
+static HRESULT WINAPI IWICStreamImpl_UnlockRegion(IWICStream *iface,
+ ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_UnlockRegion(This->pStream, libOffset, cb, dwLockType);
+}
+
+static HRESULT WINAPI IWICStreamImpl_Stat(IWICStream *iface,
+ STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_Stat(This->pStream, pstatstg, grfStatFlag);
+}
+
+static HRESULT WINAPI IWICStreamImpl_Clone(IWICStream *iface,
+ IStream **ppstm)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ TRACE("(%p): relay\n", This);
+
+ if (!This->pStream) return WINCODEC_ERR_NOTINITIALIZED;
+ return IStream_Clone(This->pStream, ppstm);
+}
+
+static HRESULT WINAPI IWICStreamImpl_InitializeFromIStream(IWICStream *iface,
+ IStream *pIStream)
+{
+ FIXME("(%p): stub\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IWICStreamImpl_InitializeFromFilename(IWICStream *iface,
+ LPCWSTR wzFileName, DWORD dwDesiredAccess)
+{
+ FIXME("(%p): stub\n", iface);
+ return E_NOTIMPL;
+}
+
+/******************************************
+ * IWICStream_InitializeFromMemory
+ *
+ * Initializes the internal IStream object to retrieve its data from a memory chunk.
+ *
+ * PARAMS
+ * pbBuffer [I] pointer to the memory chunk
+ * cbBufferSize [I] number of bytes to use from the memory chunk
+ *
+ * RETURNS
+ * SUCCESS: S_OK
+ * FAILURE: E_INVALIDARG, if pbBuffer is NULL
+ * E_OUTOFMEMORY, if we run out of memory
+ * WINCODEC_ERR_WRONGSTATE, if the IStream object has already been initialized before
+ *
+ */
+static HRESULT WINAPI IWICStreamImpl_InitializeFromMemory(IWICStream *iface,
+ BYTE *pbBuffer, DWORD cbBufferSize)
+{
+ IWICStreamImpl *This = (IWICStreamImpl*)iface;
+ StreamOnMemory *pObject;
+ TRACE("(%p,%p)\n", iface, pbBuffer);
+
+ if (!pbBuffer) return E_INVALIDARG;
+ if (This->pStream) return WINCODEC_ERR_WRONGSTATE;
+
+ pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(StreamOnMemory));
+ if (!pObject) return E_OUTOFMEMORY;
+
+ pObject->lpVtbl = &StreamOnMemory_Vtbl;
+ pObject->ref = 1;
+ pObject->pbMemory = pbBuffer;
+ pObject->dwMemsize = cbBufferSize;
+ pObject->dwCurPos = 0;
+
+ This->pStream = (IStream*)pObject;
+ return S_OK;
+}
+
+static HRESULT WINAPI IWICStreamImpl_InitializeFromIStreamRegion(IWICStream *iface,
+ IStream *pIStream, ULARGE_INTEGER ulOffset, ULARGE_INTEGER ulMaxSize)
+{
+ FIXME("(%p): stub\n", iface);
+ return E_NOTIMPL;
+}
+
+
+const IWICStreamVtbl WICStream_Vtbl =
+{
+ /*** IUnknown methods ***/
+ IWICStreamImpl_QueryInterface,
+ IWICStreamImpl_AddRef,
+ IWICStreamImpl_Release,
+ /*** ISequentialStream methods ***/
+ IWICStreamImpl_Read,
+ IWICStreamImpl_Write,
+ /*** IStream methods ***/
+ IWICStreamImpl_Seek,
+ IWICStreamImpl_SetSize,
+ IWICStreamImpl_CopyTo,
+ IWICStreamImpl_Commit,
+ IWICStreamImpl_Revert,
+ IWICStreamImpl_LockRegion,
+ IWICStreamImpl_UnlockRegion,
+ IWICStreamImpl_Stat,
+ IWICStreamImpl_Clone,
+ /*** IWICStream methods ***/
+ IWICStreamImpl_InitializeFromIStream,
+ IWICStreamImpl_InitializeFromFilename,
+ IWICStreamImpl_InitializeFromMemory,
+ IWICStreamImpl_InitializeFromIStreamRegion,
+};
+
+HRESULT StreamImpl_Create(IWICStream **stream)
+{
+ IWICStreamImpl *pObject;
+
+ if( !stream ) return E_INVALIDARG;
+
+ pObject = HeapAlloc(GetProcessHeap(), 0, sizeof(IWICStreamImpl));
+ if( !pObject ) {
+ *stream = NULL;
+ return E_OUTOFMEMORY;
+ }
+
+ pObject->lpVtbl = &WICStream_Vtbl;
+ pObject->ref = 1;
+ pObject->pStream = NULL;
+
+ *stream = (IWICStream*)pObject;
+
+ return S_OK;
+}
diff --git a/reactos/dll/win32/windowscodecs/ungif.c b/reactos/dll/win32/windowscodecs/ungif.c
new file mode 100644
index 00000000000..c24f387df67
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/ungif.c
@@ -0,0 +1,999 @@
+/*
+ * Gif extracting routines - derived from libungif
+ *
+ * Portions Copyright 2006 Mike McCormack
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/*
+ * Original copyright notice:
+ *
+ * The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+
+/******************************************************************************
+ * "Gif-Lib" - Yet another gif library.
+ *
+ * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990
+ ******************************************************************************
+ * The kernel of the GIF Decoding process can be found here.
+ ******************************************************************************
+ * History:
+ * 16 Jun 89 - Version 1.0 by Gershon Elber.
+ * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names).
+ *****************************************************************************/
+
+#include
+#include
+#include "ungif.h"
+
+#include
+#include "windef.h"
+#include "winbase.h"
+
+static void *ungif_alloc( size_t sz )
+{
+ return HeapAlloc( GetProcessHeap(), 0, sz );
+}
+
+static void *ungif_calloc( size_t num, size_t sz )
+{
+ return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, num*sz );
+}
+
+static void *ungif_realloc( void *ptr, size_t sz )
+{
+ return HeapReAlloc( GetProcessHeap(), 0, ptr, sz );
+}
+
+static void ungif_free( void *ptr )
+{
+ HeapFree( GetProcessHeap(), 0, ptr );
+}
+
+#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
+#define LZ_BITS 12
+
+#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
+
+typedef struct GifFilePrivateType {
+ GifWord BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */
+ ClearCode, /* The CLEAR LZ code. */
+ EOFCode, /* The EOF LZ code. */
+ RunningCode, /* The next code algorithm can generate. */
+ RunningBits, /* The number of bits required to represent RunningCode. */
+ MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
+ LastCode, /* The code before the current code. */
+ CrntCode, /* Current algorithm code. */
+ StackPtr, /* For character stack (see below). */
+ CrntShiftState; /* Number of bits in CrntShiftDWord. */
+ unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */
+ unsigned long PixelCount; /* Number of pixels in image. */
+ InputFunc Read; /* function to read gif input (TVT) */
+ GifByteType Buf[256]; /* Compressed input is buffered here. */
+ GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
+ GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */
+ GifPrefixType Prefix[LZ_MAX_CODE + 1];
+} GifFilePrivateType;
+
+/* avoid extra function call in case we use fread (TVT) */
+#define READ(_gif,_buf,_len) \
+ ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len)
+
+static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
+static int DGifSetupDecompress(GifFileType *GifFile);
+static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen);
+static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code, int ClearCode);
+static int DGifDecompressInput(GifFileType *GifFile, int *Code);
+static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
+ GifByteType *NextByte);
+
+static int DGifGetExtensionNext(GifFileType * GifFile, GifByteType ** GifExtension);
+static int DGifGetCodeNext(GifFileType * GifFile, GifByteType ** GifCodeBlock);
+
+/******************************************************************************
+ * Miscellaneous utility functions
+ *****************************************************************************/
+
+/* return smallest bitfield size n will fit in */
+static int
+BitSize(int n) {
+
+ register int i;
+
+ for (i = 1; i <= 8; i++)
+ if ((1 << i) >= n)
+ break;
+ return (i);
+}
+
+/******************************************************************************
+ * Color map object functions
+ *****************************************************************************/
+
+/*
+ * Allocate a color map of given size; initialize with contents of
+ * ColorMap if that pointer is non-NULL.
+ */
+static ColorMapObject *
+MakeMapObject(int ColorCount,
+ const GifColorType * ColorMap) {
+
+ ColorMapObject *Object;
+
+ /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to
+ * make the user know that or should we automatically round up instead? */
+ if (ColorCount != (1 << BitSize(ColorCount))) {
+ return NULL;
+ }
+
+ Object = ungif_alloc(sizeof(ColorMapObject));
+ if (Object == NULL) {
+ return NULL;
+ }
+
+ Object->Colors = ungif_calloc(ColorCount, sizeof(GifColorType));
+ if (Object->Colors == NULL) {
+ return NULL;
+ }
+
+ Object->ColorCount = ColorCount;
+ Object->BitsPerPixel = BitSize(ColorCount);
+
+ if (ColorMap) {
+ memcpy(Object->Colors, ColorMap, ColorCount * sizeof(GifColorType));
+ }
+
+ return (Object);
+}
+
+/*
+ * Free a color map object
+ */
+static void
+FreeMapObject(ColorMapObject * Object) {
+
+ if (Object != NULL) {
+ ungif_free(Object->Colors);
+ ungif_free(Object);
+ /*** FIXME:
+ * When we are willing to break API we need to make this function
+ * FreeMapObject(ColorMapObject **Object)
+ * and do this assignment to NULL here:
+ * *Object = NULL;
+ */
+ }
+}
+
+static int
+AddExtensionBlock(SavedImage * New,
+ int Len,
+ const unsigned char ExtData[]) {
+
+ ExtensionBlock *ep;
+
+ if (New->ExtensionBlocks == NULL)
+ New->ExtensionBlocks = ungif_alloc(sizeof(ExtensionBlock));
+ else
+ New->ExtensionBlocks = ungif_realloc(New->ExtensionBlocks,
+ sizeof(ExtensionBlock) *
+ (New->ExtensionBlockCount + 1));
+
+ if (New->ExtensionBlocks == NULL)
+ return (GIF_ERROR);
+
+ ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
+
+ ep->ByteCount=Len;
+ ep->Bytes = ungif_alloc(ep->ByteCount);
+ if (ep->Bytes == NULL)
+ return (GIF_ERROR);
+
+ if (ExtData) {
+ memcpy(ep->Bytes, ExtData, Len);
+ ep->Function = New->Function;
+ }
+
+ return (GIF_OK);
+}
+
+static void
+FreeExtension(SavedImage * Image)
+{
+ ExtensionBlock *ep;
+
+ if ((Image == NULL) || (Image->ExtensionBlocks == NULL)) {
+ return;
+ }
+ for (ep = Image->ExtensionBlocks;
+ ep < (Image->ExtensionBlocks + Image->ExtensionBlockCount); ep++)
+ ungif_free(ep->Bytes);
+ ungif_free(Image->ExtensionBlocks);
+ Image->ExtensionBlocks = NULL;
+}
+
+/******************************************************************************
+ * Image block allocation functions
+******************************************************************************/
+
+static void
+FreeSavedImages(GifFileType * GifFile) {
+
+ SavedImage *sp;
+
+ if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
+ return;
+ }
+ for (sp = GifFile->SavedImages;
+ sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
+ if (sp->ImageDesc.ColorMap) {
+ FreeMapObject(sp->ImageDesc.ColorMap);
+ sp->ImageDesc.ColorMap = NULL;
+ }
+
+ ungif_free(sp->RasterBits);
+
+ if (sp->ExtensionBlocks)
+ FreeExtension(sp);
+ }
+ ungif_free(GifFile->SavedImages);
+ GifFile->SavedImages=NULL;
+}
+
+/******************************************************************************
+ * This routine should be called before any other DGif calls. Note that
+ * this routine is called automatically from DGif file open routines.
+ *****************************************************************************/
+static int
+DGifGetScreenDesc(GifFileType * GifFile) {
+
+ int i, BitsPerPixel;
+ GifByteType Buf[3];
+
+ /* Put the screen descriptor into the file: */
+ if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
+ DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
+ return GIF_ERROR;
+
+ if (READ(GifFile, Buf, 3) != 3) {
+ return GIF_ERROR;
+ }
+ GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
+ BitsPerPixel = (Buf[0] & 0x07) + 1;
+ GifFile->SBackGroundColor = Buf[1];
+ if (Buf[0] & 0x80) { /* Do we have global color map? */
+
+ GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
+ if (GifFile->SColorMap == NULL) {
+ return GIF_ERROR;
+ }
+
+ /* Get the global color map: */
+ for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
+ if (READ(GifFile, Buf, 3) != 3) {
+ FreeMapObject(GifFile->SColorMap);
+ GifFile->SColorMap = NULL;
+ return GIF_ERROR;
+ }
+ GifFile->SColorMap->Colors[i].Red = Buf[0];
+ GifFile->SColorMap->Colors[i].Green = Buf[1];
+ GifFile->SColorMap->Colors[i].Blue = Buf[2];
+ }
+ } else {
+ GifFile->SColorMap = NULL;
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * This routine should be called before any attempt to read an image.
+ *****************************************************************************/
+static int
+DGifGetRecordType(GifFileType * GifFile,
+ GifRecordType * Type) {
+
+ GifByteType Buf;
+
+ if (READ(GifFile, &Buf, 1) != 1) {
+ return GIF_ERROR;
+ }
+
+ switch (Buf) {
+ case ',':
+ *Type = IMAGE_DESC_RECORD_TYPE;
+ break;
+ case '!':
+ *Type = EXTENSION_RECORD_TYPE;
+ break;
+ case ';':
+ *Type = TERMINATE_RECORD_TYPE;
+ break;
+ default:
+ *Type = UNDEFINED_RECORD_TYPE;
+ return GIF_ERROR;
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * This routine should be called before any attempt to read an image.
+ * Note it is assumed the Image desc. header (',') has been read.
+ *****************************************************************************/
+static int
+DGifGetImageDesc(GifFileType * GifFile) {
+
+ int i, BitsPerPixel;
+ GifByteType Buf[3];
+ GifFilePrivateType *Private = GifFile->Private;
+ SavedImage *sp;
+
+ if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
+ DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
+ DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
+ DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
+ return GIF_ERROR;
+ if (READ(GifFile, Buf, 1) != 1) {
+ return GIF_ERROR;
+ }
+ BitsPerPixel = (Buf[0] & 0x07) + 1;
+ GifFile->Image.Interlace = (Buf[0] & 0x40);
+ if (Buf[0] & 0x80) { /* Does this image have local color map? */
+
+ /*** FIXME: Why do we check both of these in order to do this?
+ * Why do we have both Image and SavedImages? */
+ if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL)
+ FreeMapObject(GifFile->Image.ColorMap);
+
+ GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
+ if (GifFile->Image.ColorMap == NULL) {
+ return GIF_ERROR;
+ }
+
+ /* Get the image local color map: */
+ for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
+ if (READ(GifFile, Buf, 3) != 3) {
+ FreeMapObject(GifFile->Image.ColorMap);
+ GifFile->Image.ColorMap = NULL;
+ return GIF_ERROR;
+ }
+ GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
+ GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
+ GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
+ }
+ } else if (GifFile->Image.ColorMap) {
+ FreeMapObject(GifFile->Image.ColorMap);
+ GifFile->Image.ColorMap = NULL;
+ }
+
+ if (GifFile->SavedImages) {
+ if ((GifFile->SavedImages = ungif_realloc(GifFile->SavedImages,
+ sizeof(SavedImage) *
+ (GifFile->ImageCount + 1))) == NULL) {
+ return GIF_ERROR;
+ }
+ } else {
+ if ((GifFile->SavedImages = ungif_alloc(sizeof(SavedImage))) == NULL) {
+ return GIF_ERROR;
+ }
+ }
+
+ sp = &GifFile->SavedImages[GifFile->ImageCount];
+ sp->ImageDesc = GifFile->Image;
+ if (GifFile->Image.ColorMap != NULL) {
+ sp->ImageDesc.ColorMap = MakeMapObject(
+ GifFile->Image.ColorMap->ColorCount,
+ GifFile->Image.ColorMap->Colors);
+ if (sp->ImageDesc.ColorMap == NULL) {
+ return GIF_ERROR;
+ }
+ }
+ sp->RasterBits = NULL;
+ sp->ExtensionBlockCount = 0;
+ sp->ExtensionBlocks = NULL;
+
+ GifFile->ImageCount++;
+
+ Private->PixelCount = (long)GifFile->Image.Width *
+ (long)GifFile->Image.Height;
+
+ DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * Get one full scanned line (Line) of length LineLen from GIF file.
+ *****************************************************************************/
+static int
+DGifGetLine(GifFileType * GifFile,
+ GifPixelType * Line,
+ int LineLen) {
+
+ GifByteType *Dummy;
+ GifFilePrivateType *Private = GifFile->Private;
+
+ if (!LineLen)
+ LineLen = GifFile->Image.Width;
+
+ if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
+ return GIF_ERROR;
+ }
+
+ if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
+ if (Private->PixelCount == 0) {
+ /* We probably would not be called any more, so lets clean
+ * everything before we return: need to flush out all rest of
+ * image until empty block (size 0) detected. We use GetCodeNext. */
+ do
+ if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
+ return GIF_ERROR;
+ while (Dummy != NULL) ;
+ }
+ return GIF_OK;
+ } else
+ return GIF_ERROR;
+}
+
+/******************************************************************************
+ * Get an extension block (see GIF manual) from gif file. This routine only
+ * returns the first data block, and DGifGetExtensionNext should be called
+ * after this one until NULL extension is returned.
+ * The Extension should NOT be freed by the user (not dynamically allocated).
+ * Note it is assumed the Extension desc. header ('!') has been read.
+ *****************************************************************************/
+static int
+DGifGetExtension(GifFileType * GifFile,
+ int *ExtCode,
+ GifByteType ** Extension) {
+
+ GifByteType Buf;
+
+ if (READ(GifFile, &Buf, 1) != 1) {
+ return GIF_ERROR;
+ }
+ *ExtCode = Buf;
+
+ return DGifGetExtensionNext(GifFile, Extension);
+}
+
+/******************************************************************************
+ * Get a following extension block (see GIF manual) from gif file. This
+ * routine should be called until NULL Extension is returned.
+ * The Extension should NOT be freed by the user (not dynamically allocated).
+ *****************************************************************************/
+static int
+DGifGetExtensionNext(GifFileType * GifFile,
+ GifByteType ** Extension) {
+
+ GifByteType Buf;
+ GifFilePrivateType *Private = GifFile->Private;
+
+ if (READ(GifFile, &Buf, 1) != 1) {
+ return GIF_ERROR;
+ }
+ if (Buf > 0) {
+ *Extension = Private->Buf; /* Use private unused buffer. */
+ (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
+ if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
+ return GIF_ERROR;
+ }
+ } else
+ *Extension = NULL;
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * Get 2 bytes (word) from the given file:
+ *****************************************************************************/
+static int
+DGifGetWord(GifFileType * GifFile,
+ GifWord *Word) {
+
+ unsigned char c[2];
+
+ if (READ(GifFile, c, 2) != 2) {
+ return GIF_ERROR;
+ }
+
+ *Word = (((unsigned int)c[1]) << 8) + c[0];
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * Continue to get the image code in compressed form. This routine should be
+ * called until NULL block is returned.
+ * The block should NOT be freed by the user (not dynamically allocated).
+ *****************************************************************************/
+static int
+DGifGetCodeNext(GifFileType * GifFile,
+ GifByteType ** CodeBlock) {
+
+ GifByteType Buf;
+ GifFilePrivateType *Private = GifFile->Private;
+
+ if (READ(GifFile, &Buf, 1) != 1) {
+ return GIF_ERROR;
+ }
+
+ if (Buf > 0) {
+ *CodeBlock = Private->Buf; /* Use private unused buffer. */
+ (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
+ if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
+ return GIF_ERROR;
+ }
+ } else {
+ *CodeBlock = NULL;
+ Private->Buf[0] = 0; /* Make sure the buffer is empty! */
+ Private->PixelCount = 0; /* And local info. indicate image read. */
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * Setup the LZ decompression for this image:
+ *****************************************************************************/
+static int
+DGifSetupDecompress(GifFileType * GifFile) {
+
+ int i, BitsPerPixel;
+ GifByteType CodeSize;
+ GifPrefixType *Prefix;
+ GifFilePrivateType *Private = GifFile->Private;
+
+ READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
+ BitsPerPixel = CodeSize;
+
+ Private->Buf[0] = 0; /* Input Buffer empty. */
+ Private->BitsPerPixel = BitsPerPixel;
+ Private->ClearCode = (1 << BitsPerPixel);
+ Private->EOFCode = Private->ClearCode + 1;
+ Private->RunningCode = Private->EOFCode + 1;
+ Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
+ Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
+ Private->StackPtr = 0; /* No pixels on the pixel stack. */
+ Private->LastCode = NO_SUCH_CODE;
+ Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
+ Private->CrntShiftDWord = 0;
+
+ Prefix = Private->Prefix;
+ for (i = 0; i <= LZ_MAX_CODE; i++)
+ Prefix[i] = NO_SUCH_CODE;
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * The LZ decompression routine:
+ * This version decompress the given gif file into Line of length LineLen.
+ * This routine can be called few times (one per scan line, for example), in
+ * order the complete the whole image.
+ *****************************************************************************/
+static int
+DGifDecompressLine(GifFileType * GifFile,
+ GifPixelType * Line,
+ int LineLen) {
+
+ int i = 0;
+ int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
+ GifByteType *Stack, *Suffix;
+ GifPrefixType *Prefix;
+ GifFilePrivateType *Private = GifFile->Private;
+
+ StackPtr = Private->StackPtr;
+ Prefix = Private->Prefix;
+ Suffix = Private->Suffix;
+ Stack = Private->Stack;
+ EOFCode = Private->EOFCode;
+ ClearCode = Private->ClearCode;
+ LastCode = Private->LastCode;
+
+ if (StackPtr != 0) {
+ /* Let pop the stack off before continuing to read the gif file: */
+ while (StackPtr != 0 && i < LineLen)
+ Line[i++] = Stack[--StackPtr];
+ }
+
+ while (i < LineLen) { /* Decode LineLen items. */
+ if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
+ return GIF_ERROR;
+
+ if (CrntCode == EOFCode) {
+ /* Note, however, that usually we will not be here as we will stop
+ * decoding as soon as we got all the pixel, or EOF code will
+ * not be read at all, and DGifGetLine/Pixel clean everything. */
+ if (i != LineLen - 1 || Private->PixelCount != 0) {
+ return GIF_ERROR;
+ }
+ i++;
+ } else if (CrntCode == ClearCode) {
+ /* We need to start over again: */
+ for (j = 0; j <= LZ_MAX_CODE; j++)
+ Prefix[j] = NO_SUCH_CODE;
+ Private->RunningCode = Private->EOFCode + 1;
+ Private->RunningBits = Private->BitsPerPixel + 1;
+ Private->MaxCode1 = 1 << Private->RunningBits;
+ LastCode = Private->LastCode = NO_SUCH_CODE;
+ } else {
+ /* It's a regular code - if in pixel range simply add it to output
+ * stream, otherwise trace to codes linked list until the prefix
+ * is in pixel range: */
+ if (CrntCode < ClearCode) {
+ /* This is simple - its pixel scalar, so add it to output: */
+ Line[i++] = CrntCode;
+ } else {
+ /* It's a code to be traced: trace the linked list
+ * until the prefix is a pixel, while pushing the suffix
+ * pixels on our stack. If we done, pop the stack in reverse
+ * order (that's what stack is good for!) for output. */
+ if (Prefix[CrntCode] == NO_SUCH_CODE) {
+ /* Only allowed if CrntCode is exactly the running code:
+ * In that case CrntCode = XXXCode, CrntCode or the
+ * prefix code is last code and the suffix char is
+ * exactly the prefix of last code! */
+ if (CrntCode == Private->RunningCode - 2) {
+ CrntPrefix = LastCode;
+ Suffix[Private->RunningCode - 2] =
+ Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
+ LastCode,
+ ClearCode);
+ } else {
+ return GIF_ERROR;
+ }
+ } else
+ CrntPrefix = CrntCode;
+
+ /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
+ * during the trace. As we might loop forever, in case of
+ * defective image, we count the number of loops we trace
+ * and stop if we got LZ_MAX_CODE. Obviously we cannot
+ * loop more than that. */
+ j = 0;
+ while (j++ <= LZ_MAX_CODE &&
+ CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
+ Stack[StackPtr++] = Suffix[CrntPrefix];
+ CrntPrefix = Prefix[CrntPrefix];
+ }
+ if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
+ return GIF_ERROR;
+ }
+ /* Push the last character on stack: */
+ Stack[StackPtr++] = CrntPrefix;
+
+ /* Now lets pop all the stack into output: */
+ while (StackPtr != 0 && i < LineLen)
+ Line[i++] = Stack[--StackPtr];
+ }
+ if (LastCode != NO_SUCH_CODE) {
+ Prefix[Private->RunningCode - 2] = LastCode;
+
+ if (CrntCode == Private->RunningCode - 2) {
+ /* Only allowed if CrntCode is exactly the running code:
+ * In that case CrntCode = XXXCode, CrntCode or the
+ * prefix code is last code and the suffix char is
+ * exactly the prefix of last code! */
+ Suffix[Private->RunningCode - 2] =
+ DGifGetPrefixChar(Prefix, LastCode, ClearCode);
+ } else {
+ Suffix[Private->RunningCode - 2] =
+ DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
+ }
+ }
+ LastCode = CrntCode;
+ }
+ }
+
+ Private->LastCode = LastCode;
+ Private->StackPtr = StackPtr;
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * Routine to trace the Prefixes linked list until we get a prefix which is
+ * not code, but a pixel value (less than ClearCode). Returns that pixel value.
+ * If image is defective, we might loop here forever, so we limit the loops to
+ * the maximum possible if image O.k. - LZ_MAX_CODE times.
+ *****************************************************************************/
+static int
+DGifGetPrefixChar(const GifPrefixType *Prefix,
+ int Code,
+ int ClearCode) {
+
+ int i = 0;
+
+ while (Code > ClearCode && i++ <= LZ_MAX_CODE)
+ Code = Prefix[Code];
+ return Code;
+}
+
+/******************************************************************************
+ * The LZ decompression input routine:
+ * This routine is responsible for the decompression of the bit stream from
+ * 8 bits (bytes) packets, into the real codes.
+ * Returns GIF_OK if read successfully.
+ *****************************************************************************/
+static int
+DGifDecompressInput(GifFileType * GifFile,
+ int *Code) {
+
+ GifFilePrivateType *Private = GifFile->Private;
+
+ GifByteType NextByte;
+ static const unsigned short CodeMasks[] = {
+ 0x0000, 0x0001, 0x0003, 0x0007,
+ 0x000f, 0x001f, 0x003f, 0x007f,
+ 0x00ff, 0x01ff, 0x03ff, 0x07ff,
+ 0x0fff
+ };
+ /* The image can't contain more than LZ_BITS per code. */
+ if (Private->RunningBits > LZ_BITS) {
+ return GIF_ERROR;
+ }
+
+ while (Private->CrntShiftState < Private->RunningBits) {
+ /* Needs to get more bytes from input stream for next code: */
+ if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
+ return GIF_ERROR;
+ }
+ Private->CrntShiftDWord |=
+ ((unsigned long)NextByte) << Private->CrntShiftState;
+ Private->CrntShiftState += 8;
+ }
+ *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
+
+ Private->CrntShiftDWord >>= Private->RunningBits;
+ Private->CrntShiftState -= Private->RunningBits;
+
+ /* If code cannot fit into RunningBits bits, must raise its size. Note
+ * however that codes above 4095 are used for special signaling.
+ * If we're using LZ_BITS bits already and we're at the max code, just
+ * keep using the table as it is, don't increment Private->RunningCode.
+ */
+ if (Private->RunningCode < LZ_MAX_CODE + 2 &&
+ ++Private->RunningCode > Private->MaxCode1 &&
+ Private->RunningBits < LZ_BITS) {
+ Private->MaxCode1 <<= 1;
+ Private->RunningBits++;
+ }
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * This routines read one gif data block at a time and buffers it internally
+ * so that the decompression routine could access it.
+ * The routine returns the next byte from its internal buffer (or read next
+ * block in if buffer empty) and returns GIF_OK if successful.
+ *****************************************************************************/
+static int
+DGifBufferedInput(GifFileType * GifFile,
+ GifByteType * Buf,
+ GifByteType * NextByte) {
+
+ if (Buf[0] == 0) {
+ /* Needs to read the next buffer - this one is empty: */
+ if (READ(GifFile, Buf, 1) != 1) {
+ return GIF_ERROR;
+ }
+ /* There shouldn't be any empty data blocks here as the LZW spec
+ * says the LZW termination code should come first. Therefore we
+ * shouldn't be inside this routine at that point.
+ */
+ if (Buf[0] == 0) {
+ return GIF_ERROR;
+ }
+ if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
+ return GIF_ERROR;
+ }
+ *NextByte = Buf[1];
+ Buf[1] = 2; /* We use now the second place as last char read! */
+ Buf[0]--;
+ } else {
+ *NextByte = Buf[Buf[1]++];
+ Buf[0]--;
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+ * This routine reads an entire GIF into core, hanging all its state info off
+ * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle()
+ * first to initialize I/O. Its inverse is EGifSpew().
+ ******************************************************************************/
+int
+DGifSlurp(GifFileType * GifFile) {
+
+ int ImageSize;
+ GifRecordType RecordType;
+ SavedImage *sp;
+ GifByteType *ExtData;
+ SavedImage temp_save;
+
+ temp_save.ExtensionBlocks = NULL;
+ temp_save.ExtensionBlockCount = 0;
+
+ do {
+ if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
+ return (GIF_ERROR);
+
+ switch (RecordType) {
+ case IMAGE_DESC_RECORD_TYPE:
+ if (DGifGetImageDesc(GifFile) == GIF_ERROR)
+ return (GIF_ERROR);
+
+ sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
+ ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
+
+ sp->RasterBits = ungif_alloc(ImageSize * sizeof(GifPixelType));
+ if (sp->RasterBits == NULL) {
+ return GIF_ERROR;
+ }
+ if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) ==
+ GIF_ERROR)
+ return (GIF_ERROR);
+ if (temp_save.ExtensionBlocks) {
+ sp->ExtensionBlocks = temp_save.ExtensionBlocks;
+ sp->ExtensionBlockCount = temp_save.ExtensionBlockCount;
+
+ temp_save.ExtensionBlocks = NULL;
+ temp_save.ExtensionBlockCount = 0;
+
+ /* FIXME: The following is wrong. It is left in only for
+ * backwards compatibility. Someday it should go away. Use
+ * the sp->ExtensionBlocks->Function variable instead. */
+ sp->Function = sp->ExtensionBlocks[0].Function;
+ }
+ break;
+
+ case EXTENSION_RECORD_TYPE:
+ if (DGifGetExtension(GifFile, &temp_save.Function, &ExtData) ==
+ GIF_ERROR)
+ return (GIF_ERROR);
+ while (ExtData != NULL) {
+
+ /* Create an extension block with our data */
+ if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1])
+ == GIF_ERROR)
+ return (GIF_ERROR);
+
+ if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
+ return (GIF_ERROR);
+ temp_save.Function = 0;
+ }
+ break;
+
+ case TERMINATE_RECORD_TYPE:
+ break;
+
+ default: /* Should be trapped by DGifGetRecordType */
+ break;
+ }
+ } while (RecordType != TERMINATE_RECORD_TYPE);
+
+ /* Just in case the Gif has an extension block without an associated
+ * image... (Should we save this into a savefile structure with no image
+ * instead? Have to check if the present writing code can handle that as
+ * well.... */
+ if (temp_save.ExtensionBlocks)
+ FreeExtension(&temp_save);
+
+ return (GIF_OK);
+}
+
+/******************************************************************************
+ * GifFileType constructor with user supplied input function (TVT)
+ *****************************************************************************/
+GifFileType *
+DGifOpen(void *userData,
+ InputFunc readFunc) {
+
+ unsigned char Buf[GIF_STAMP_LEN + 1];
+ GifFileType *GifFile;
+ GifFilePrivateType *Private;
+
+ GifFile = ungif_alloc(sizeof(GifFileType));
+ if (GifFile == NULL) {
+ return NULL;
+ }
+
+ memset(GifFile, '\0', sizeof(GifFileType));
+
+ Private = ungif_alloc(sizeof(GifFilePrivateType));
+ if (!Private) {
+ ungif_free(GifFile);
+ return NULL;
+ }
+
+ GifFile->Private = (void*)Private;
+
+ Private->Read = readFunc; /* TVT */
+ GifFile->UserData = userData; /* TVT */
+
+ /* Lets see if this is a GIF file: */
+ if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
+ ungif_free(Private);
+ ungif_free(GifFile);
+ return NULL;
+ }
+
+ /* The GIF Version number is ignored at this time. Maybe we should do
+ * something more useful with it. */
+ Buf[GIF_STAMP_LEN] = 0;
+ if (memcmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
+ ungif_free(Private);
+ ungif_free(GifFile);
+ return NULL;
+ }
+
+ if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
+ ungif_free(Private);
+ ungif_free(GifFile);
+ return NULL;
+ }
+
+ return GifFile;
+}
+
+/******************************************************************************
+ * This routine should be called last, to close the GIF file.
+ *****************************************************************************/
+int
+DGifCloseFile(GifFileType * GifFile) {
+
+ GifFilePrivateType *Private;
+
+ if (GifFile == NULL)
+ return GIF_ERROR;
+
+ Private = GifFile->Private;
+
+ if (GifFile->Image.ColorMap) {
+ FreeMapObject(GifFile->Image.ColorMap);
+ GifFile->Image.ColorMap = NULL;
+ }
+
+ if (GifFile->SColorMap) {
+ FreeMapObject(GifFile->SColorMap);
+ GifFile->SColorMap = NULL;
+ }
+
+ ungif_free(Private);
+ Private = NULL;
+
+ if (GifFile->SavedImages) {
+ FreeSavedImages(GifFile);
+ GifFile->SavedImages = NULL;
+ }
+
+ ungif_free(GifFile);
+
+ return GIF_OK;
+}
diff --git a/reactos/dll/win32/windowscodecs/ungif.h b/reactos/dll/win32/windowscodecs/ungif.h
new file mode 100644
index 00000000000..e71dad8b3aa
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/ungif.h
@@ -0,0 +1,169 @@
+/*
+ * Gif extracting routines - derived from libungif
+ *
+ * Portions Copyright 2006 Mike McCormack
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/*
+ * Original copyright notice:
+ *
+ * The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ */
+
+/******************************************************************************
+ * In order to make life a little bit easier when using the GIF file format,
+ * this library was written, and which does all the dirty work...
+ *
+ * Written by Gershon Elber, Jun. 1989
+ * Hacks by Eric S. Raymond, Sep. 1992
+ ******************************************************************************
+ * History:
+ * 14 Jun 89 - Version 1.0 by Gershon Elber.
+ * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names)
+ * 15 Sep 90 - Version 2.0 by Eric S. Raymond (Changes to support GIF slurp)
+ * 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support)
+ * 17 Dec 98 - Version 4.0 by Toshio Kuratomi (Fix extension writing code)
+ *****************************************************************************/
+
+#ifndef _UNGIF_H_
+#define _UNGIF_H_ 1
+
+#define GIF_ERROR 0
+#define GIF_OK 1
+
+#ifndef TRUE
+#define TRUE 1
+#endif /* TRUE */
+#ifndef FALSE
+#define FALSE 0
+#endif /* FALSE */
+
+#ifndef NULL
+#define NULL 0
+#endif /* NULL */
+
+#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */
+#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
+#define GIF_VERSION_POS 3 /* Version first character in stamp. */
+#define GIF87_STAMP "GIF87a" /* First chars in file - GIF stamp. */
+#define GIF89_STAMP "GIF89a" /* First chars in file - GIF stamp. */
+
+#define GIF_FILE_BUFFER_SIZE 16384 /* Files uses bigger buffers than usual. */
+
+typedef int GifBooleanType;
+typedef unsigned char GifPixelType;
+typedef unsigned char *GifRowType;
+typedef unsigned char GifByteType;
+typedef unsigned int GifPrefixType;
+typedef int GifWord;
+
+typedef struct GifColorType {
+ GifByteType Red, Green, Blue;
+} GifColorType;
+
+typedef struct ColorMapObject {
+ int ColorCount;
+ int BitsPerPixel;
+ GifColorType *Colors;
+} ColorMapObject;
+
+typedef struct GifImageDesc {
+ GifWord Left, Top, Width, Height, /* Current image dimensions. */
+ Interlace; /* Sequential/Interlaced lines. */
+ ColorMapObject *ColorMap; /* The local color map */
+} GifImageDesc;
+
+typedef struct GifFileType {
+ GifWord SWidth, SHeight, /* Screen dimensions. */
+ SColorResolution, /* How many colors can we generate? */
+ SBackGroundColor; /* I hope you understand this one... */
+ ColorMapObject *SColorMap; /* NULL if not exists. */
+ int ImageCount; /* Number of current image */
+ GifImageDesc Image; /* Block describing current image */
+ struct SavedImage *SavedImages; /* Use this to accumulate file state */
+ void *UserData; /* hook to attach user data (TVT) */
+ void *Private; /* Don't mess with this! */
+} GifFileType;
+
+typedef enum {
+ UNDEFINED_RECORD_TYPE,
+ SCREEN_DESC_RECORD_TYPE,
+ IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */
+ EXTENSION_RECORD_TYPE, /* Begin with '!' */
+ TERMINATE_RECORD_TYPE /* Begin with ';' */
+} GifRecordType;
+
+/* func type to read gif data from arbitrary sources (TVT) */
+typedef int (*InputFunc) (GifFileType *, GifByteType *, int);
+
+/* GIF89 extension function codes */
+
+#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */
+#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control */
+#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */
+#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */
+
+/* public interface to ungif.c */
+int DGifSlurp(GifFileType * GifFile);
+GifFileType *DGifOpen(void *userPtr, InputFunc readFunc);
+int DGifCloseFile(GifFileType * GifFile);
+
+#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */
+#define D_GIF_ERR_READ_FAILED 102
+#define D_GIF_ERR_NOT_GIF_FILE 103
+#define D_GIF_ERR_NO_SCRN_DSCR 104
+#define D_GIF_ERR_NO_IMAG_DSCR 105
+#define D_GIF_ERR_NO_COLOR_MAP 106
+#define D_GIF_ERR_WRONG_RECORD 107
+#define D_GIF_ERR_DATA_TOO_BIG 108
+#define D_GIF_ERR_NOT_ENOUGH_MEM 109
+#define D_GIF_ERR_CLOSE_FAILED 110
+#define D_GIF_ERR_NOT_READABLE 111
+#define D_GIF_ERR_IMAGE_DEFECT 112
+#define D_GIF_ERR_EOF_TOO_SOON 113
+
+/******************************************************************************
+ * Support for the in-core structures allocation (slurp mode).
+ *****************************************************************************/
+
+/* This is the in-core version of an extension record */
+typedef struct {
+ int ByteCount;
+ char *Bytes;
+ int Function; /* Holds the type of the Extension block. */
+} ExtensionBlock;
+
+/* This holds an image header, its unpacked raster bits, and extensions */
+typedef struct SavedImage {
+ GifImageDesc ImageDesc;
+ unsigned char *RasterBits;
+ int Function; /* DEPRECATED: Use ExtensionBlocks[x].Function instead */
+ int ExtensionBlockCount;
+ ExtensionBlock *ExtensionBlocks;
+} SavedImage;
+
+#endif /* _UNGIF_H_ */
diff --git a/reactos/dll/win32/windowscodecs/version.rc b/reactos/dll/win32/windowscodecs/version.rc
new file mode 100644
index 00000000000..40378d3b28e
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/version.rc
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 Louis Lenders
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define WINE_FILEDESCRIPTION_STR "Wine Windows Codecs Library"
+#define WINE_FILENAME_STR "windowscodecs.dll"
+#define WINE_FILEVERSION 6,0,6001,170099
+#define WINE_FILEVERSION_STR "6.0.6001.17009"
+#define WINE_PRODUCTVERSION 6,0,6001,170099
+#define WINE_PRODUCTVERSION_STR "6.0.6001.17009"
+
+#include "wine/wine_common_ver.rc"
diff --git a/reactos/dll/win32/windowscodecs/wincodecs_private.h b/reactos/dll/win32/windowscodecs/wincodecs_private.h
new file mode 100644
index 00000000000..d4441d0db6f
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/wincodecs_private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef WINCODECS_PRIVATE_H
+#define WINCODECS_PRIVATE_H
+
+extern HRESULT FormatConverter_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv);
+extern HRESULT ImagingFactory_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv);
+extern HRESULT BmpDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv);
+extern HRESULT BmpEncoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv);
+extern HRESULT GifDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv);
+extern HRESULT IcoDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv);
+
+extern HRESULT PaletteImpl_Create(IWICPalette **palette);
+extern HRESULT StreamImpl_Create(IWICStream **stream);
+
+extern HRESULT copy_pixels(UINT bpp, const BYTE *srcbuffer,
+ UINT srcwidth, UINT srcheight, INT srcstride,
+ const WICRect *rc, UINT dststride, UINT dstbuffersize, BYTE *dstbuffer);
+
+extern HRESULT CreatePropertyBag2(IPropertyBag2 **ppPropertyBag2);
+
+extern HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo);
+extern HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown);
+
+#endif /* WINCODECS_PRIVATE_H */
diff --git a/reactos/dll/win32/windowscodecs/windowscodecs.rbuild b/reactos/dll/win32/windowscodecs/windowscodecs.rbuild
new file mode 100644
index 00000000000..2f0c8725aa2
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/windowscodecs.rbuild
@@ -0,0 +1,32 @@
+
+
+
+ .
+ include/reactos/wine
+
+
+ 0x600
+
+ wine
+ uuid
+ ole32
+ advapi32
+ kernel32
+
+ bmpdecode.c
+ bmpencode.c
+ clsfactory.c
+ converter.c
+ gifformat.c
+ icoformat.c
+ imgfactory.c
+ info.c
+ main.c
+ palette.c
+ propertybag.c
+ regsvr.c
+ stream.c
+ ungif.c
+
+ version.rc
+
diff --git a/reactos/dll/win32/windowscodecs/windowscodecs.spec b/reactos/dll/win32/windowscodecs/windowscodecs.spec
new file mode 100644
index 00000000000..d0b6a7e58ca
--- /dev/null
+++ b/reactos/dll/win32/windowscodecs/windowscodecs.spec
@@ -0,0 +1,116 @@
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
+@ stub IEnumString_Next_WIC_Proxy
+@ stub IEnumString_Reset_WIC_Proxy
+@ stub IPropertyBag2_Write_Proxy
+@ stub IWICBitmapClipper_Initialize_Proxy
+@ stub IWICBitmapCodecInfo_DoesSupportAnimation_Proxy
+@ stub IWICBitmapCodecInfo_DoesSupportLossless_Proxy
+@ stub IWICBitmapCodecInfo_DoesSupportMultiframe_Proxy
+@ stub IWICBitmapCodecInfo_GetContainerFormat_Proxy
+@ stub IWICBitmapCodecInfo_GetDeviceManufacturer_Proxy
+@ stub IWICBitmapCodecInfo_GetDeviceModels_Proxy
+@ stub IWICBitmapCodecInfo_GetFileExtensions_Proxy
+@ stub IWICBitmapCodecInfo_GetMimeTypes_Proxy
+@ stub IWICBitmapDecoder_CopyPalette_Proxy
+@ stub IWICBitmapDecoder_GetColorContexts_Proxy
+@ stub IWICBitmapDecoder_GetDecoderInfo_Proxy
+@ stub IWICBitmapDecoder_GetFrameCount_Proxy
+@ stub IWICBitmapDecoder_GetFrame_Proxy
+@ stub IWICBitmapDecoder_GetMetadataQueryReader_Proxy
+@ stub IWICBitmapDecoder_GetPreview_Proxy
+@ stub IWICBitmapDecoder_GetThumbnail_Proxy
+@ stub IWICBitmapEncoder_Commit_Proxy
+@ stub IWICBitmapEncoder_CreateNewFrame_Proxy
+@ stub IWICBitmapEncoder_GetEncoderInfo_Proxy
+@ stub IWICBitmapEncoder_GetMetadataQueryWriter_Proxy
+@ stub IWICBitmapEncoder_Initialize_Proxy
+@ stub IWICBitmapEncoder_SetPalette_Proxy
+@ stub IWICBitmapEncoder_SetThumbnail_Proxy
+@ stub IWICBitmapFlipRotator_Initialize_Proxy
+@ stub IWICBitmapFrameDecode_GetColorContexts_Proxy
+@ stub IWICBitmapFrameDecode_GetMetadataQueryReader_Proxy
+@ stub IWICBitmapFrameDecode_GetThumbnail_Proxy
+@ stub IWICBitmapFrameEncode_Commit_Proxy
+@ stub IWICBitmapFrameEncode_GetMetadataQueryWriter_Proxy
+@ stub IWICBitmapFrameEncode_Initialize_Proxy
+@ stub IWICBitmapFrameEncode_SetColorContexts_Proxy
+@ stub IWICBitmapFrameEncode_SetResolution_Proxy
+@ stub IWICBitmapFrameEncode_SetSize_Proxy
+@ stub IWICBitmapFrameEncode_SetThumbnail_Proxy
+@ stub IWICBitmapFrameEncode_WriteSource_Proxy
+@ stub IWICBitmapLock_GetDataPointer_STA_Proxy
+@ stub IWICBitmapLock_GetStride_Proxy
+@ stub IWICBitmapScaler_Initialize_Proxy
+@ stub IWICBitmapSource_CopyPalette_Proxy
+@ stub IWICBitmapSource_CopyPixels_Proxy
+@ stub IWICBitmapSource_GetPixelFormat_Proxy
+@ stub IWICBitmapSource_GetResolution_Proxy
+@ stub IWICBitmapSource_GetSize_Proxy
+@ stub IWICBitmap_Lock_Proxy
+@ stub IWICBitmap_SetPalette_Proxy
+@ stub IWICBitmap_SetResolution_Proxy
+@ stub IWICColorContext_InitializeFromMemory_Proxy
+@ stub IWICComponentFactory_CreateMetadataWriterFromReader_Proxy
+@ stub IWICComponentFactory_CreateQueryWriterFromBlockWriter_Proxy
+@ stub IWICComponentInfo_GetAuthor_Proxy
+@ stub IWICComponentInfo_GetCLSID_Proxy
+@ stub IWICComponentInfo_GetFriendlyName_Proxy
+@ stub IWICComponentInfo_GetSpecVersion_Proxy
+@ stub IWICComponentInfo_GetVersion_Proxy
+@ stub IWICFastMetadataEncoder_Commit_Proxy
+@ stub IWICFastMetadataEncoder_GetMetadataQueryWriter_Proxy
+@ stub IWICFormatConverter_Initialize_Proxy
+@ stub IWICImagingFactory_CreateBitmapClipper_Proxy
+@ stub IWICImagingFactory_CreateBitmapFlipRotator_Proxy
+@ stub IWICImagingFactory_CreateBitmapFromHBITMAP_Proxy
+@ stub IWICImagingFactory_CreateBitmapFromHICON_Proxy
+@ stub IWICImagingFactory_CreateBitmapFromMemory_Proxy
+@ stub IWICImagingFactory_CreateBitmapFromSource_Proxy
+@ stub IWICImagingFactory_CreateBitmapScaler_Proxy
+@ stub IWICImagingFactory_CreateBitmap_Proxy
+@ stub IWICImagingFactory_CreateComponentInfo_Proxy
+@ stub IWICImagingFactory_CreateDecoderFromFileHandle_Proxy
+@ stub IWICImagingFactory_CreateDecoderFromFilename_Proxy
+@ stub IWICImagingFactory_CreateDecoderFromStream_Proxy
+@ stub IWICImagingFactory_CreateEncoder_Proxy
+@ stub IWICImagingFactory_CreateFastMetadataEncoderFromDecoder_Proxy
+@ stub IWICImagingFactory_CreateFastMetadataEncoderFromFrameDecode_Proxy
+@ stub IWICImagingFactory_CreateFormatConverter_Proxy
+@ stub IWICImagingFactory_CreatePalette_Proxy
+@ stub IWICImagingFactory_CreateQueryWriterFromReader_Proxy
+@ stub IWICImagingFactory_CreateQueryWriter_Proxy
+@ stub IWICImagingFactory_CreateStream_Proxy
+@ stub IWICMetadataBlockReader_GetCount_Proxy
+@ stub IWICMetadataBlockReader_GetReaderByIndex_Proxy
+@ stub IWICMetadataQueryReader_GetContainerFormat_Proxy
+@ stub IWICMetadataQueryReader_GetEnumerator_Proxy
+@ stub IWICMetadataQueryReader_GetLocation_Proxy
+@ stub IWICMetadataQueryReader_GetMetadataByName_Proxy
+@ stub IWICMetadataQueryWriter_RemoveMetadataByName_Proxy
+@ stub IWICMetadataQueryWriter_SetMetadataByName_Proxy
+@ stub IWICPalette_GetColorCount_Proxy
+@ stub IWICPalette_GetColors_Proxy
+@ stub IWICPalette_GetType_Proxy
+@ stub IWICPalette_HasAlpha_Proxy
+@ stub IWICPalette_InitializeCustom_Proxy
+@ stub IWICPalette_InitializeFromBitmap_Proxy
+@ stub IWICPalette_InitializeFromPalette_Proxy
+@ stub IWICPalette_InitializePredefined_Proxy
+@ stub IWICPixelFormatInfo_GetBitsPerPixel_Proxy
+@ stub IWICPixelFormatInfo_GetChannelCount_Proxy
+@ stub IWICPixelFormatInfo_GetChannelMask_Proxy
+@ stub IWICStream_InitializeFromIStream_Proxy
+@ stub IWICStream_InitializeFromMemory_Proxy
+@ stdcall WICConvertBitmapSource(ptr ptr ptr)
+@ stub WICCreateBitmapFromSection
+@ stub WICCreateColorContext_Proxy
+@ stub WICCreateImagingFactory_Proxy
+@ stub WICGetMetadataContentSize
+@ stub WICMapGuidToShortName
+@ stub WICMapSchemaToName
+@ stub WICMapShortNameToGuid
+@ stub WICMatchMetadataContent
+@ stub WICSerializeMetadataContent
+@ stub WICSetEncoderFormat_Proxy
diff --git a/reactos/include/psdk/psdk.rbuild b/reactos/include/psdk/psdk.rbuild
index 283aeaba9f0..ad9c497ede3 100644
--- a/reactos/include/psdk/psdk.rbuild
+++ b/reactos/include/psdk/psdk.rbuild
@@ -52,6 +52,7 @@
unknwn.idl
urlhist.idl
urlmon.idl
+ wincodec.idl
mimeole.idl
mscoree.idl
mshtmhst.idl
diff --git a/reactos/include/psdk/wincodec.idl b/reactos/include/psdk/wincodec.idl
new file mode 100644
index 00000000000..80601c1847f
--- /dev/null
+++ b/reactos/include/psdk/wincodec.idl
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2009 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+import "wtypes.idl";
+import "propidl.idl";
+import "objidl.idl";
+import "ocidl.idl";
+
+#define CODEC_FORCE_DWORD 0x7fffffff
+
+typedef enum WICDecodeOptions {
+ WICDecodeMetadataCacheOnDemand = 0x00000000,
+ WICDecodeMetadataCacheOnLoad = 0x00000001,
+ WICMETADATACACHEOPTION_FORCE_DWORD = CODEC_FORCE_DWORD
+} WICDecodeOptions;
+
+typedef enum WICBitmapCreateCacheOption {
+ WICBitmapNoCache = 0x00000000,
+ WICBitmapCacheOnDemand = 0x00000001,
+ WICBitmapCacheOnLoad = 0x00000002,
+ WICBITMAPCREATECACHEOPTION_FORCE_DWORD = CODEC_FORCE_DWORD
+} WICBitmapCreateCacheOption;
+
+typedef enum WICBitmapAlphaChannelOption {
+ WICBitmapUseAlpha = 0x00000000,
+ WICBitmapUsePremultipliedAlpha = 0x00000001,
+ WICBitmapIgnoreAlpha = 0x00000002,
+ WICBITMAPALPHACHANNELOPTIONS_FORCE_DWORD = CODEC_FORCE_DWORD
+} WICBitmapAlphaChannelOption;
+
+typedef enum WICBitmapDecoderCapabilities {
+ WICBitmapDecoderCapabilitySameEncoder = 0x00000001,
+ WICBitmapDecoderCapabilityCanDecodeAllImages = 0x00000002,
+ WICBitmapDecoderCapabilityCanDecodeSomeImages = 0x00000004,
+ WICBitmapDecoderCapabilityCanEnumerateMetadata = 0x00000008,
+ WICBitmapDecoderCapabilityCanDecodeThumbnail = 0x00000010,
+} WICBitmapDecoderCapabilities;
+
+typedef enum WICBitmapDitherType {
+ WICBitmapDitherTypeNone = 0x00000000,
+ WICBitmapDitherTypeSolid = 0x00000000,
+ WICBitmapDitherTypeOrdered4x4 = 0x00000001,
+ WICBitmapDitherTypeOrdered8x8 = 0x00000002,
+ WICBitmapDitherTypeOrdered16x16 = 0x00000003,
+ WICBitmapDitherTypeSpiral4x4 = 0x00000004,
+ WICBitmapDitherTypeSpiral8x8 = 0x00000005,
+ WICBitmapDitherTypeDualSpiral4x4 = 0x00000006,
+ WICBitmapDitherTypeDualSpiral8x8 = 0x00000007,
+ WICBitmapDitherTypeErrorDiffusion = 0x00000008,
+ WICBITMAPDITHERTYPE_FORCE_DWORD = CODEC_FORCE_DWORD
+} WICBitmapDitherType;
+
+typedef enum WICBitmapEncoderCacheOption {
+ WICBitmapEncoderCacheInMemory = 0x00000000,
+ WICBitmapEncoderCacheTempFile = 0x00000001,
+ WICBitmapEncoderNoCache = 0x00000002,
+ WICBITMAPENCODERCACHEOPTION_FORCE_DWORD = CODEC_FORCE_DWORD
+} WICBitmapEncoderCacheOption;
+
+typedef enum WICBitmapPaletteType {
+ WICBitmapPaletteTypeCustom = 0x00000000,
+ WICBitmapPaletteTypeMedianCut = 0x00000001,
+ WICBitmapPaletteTypeFixedBW = 0x00000002,
+ WICBitmapPaletteTypeFixedHalftone8 = 0x00000003,
+ WICBitmapPaletteTypeFixedHalftone27 = 0x00000004,
+ WICBitmapPaletteTypeFixedHalftone64 = 0x00000005,
+ WICBitmapPaletteTypeFixedHalftone125 = 0x00000006,
+ WICBitmapPaletteTypeFixedHalftone216 = 0x00000007,
+ WICBitmapPaletteTypeFixedWebPalette = WICBitmapPaletteTypeFixedHalftone216,
+ WICBitmapPaletteTypeFixedHalftone252 = 0x00000008,
+ WICBitmapPaletteTypeFixedHalftone256 = 0x00000009,
+ WICBitmapPaletteTypeFixedGray4 = 0x0000000A,
+ WICBitmapPaletteTypeFixedGray16 = 0x0000000B,
+ WICBitmapPaletteTypeFixedGray256 = 0x0000000C,
+ WICBITMAPPALETTETYPE_FORCE_DWORD = CODEC_FORCE_DWORD
+} WICBitmapPaletteType;
+
+typedef enum WICComponentType {
+ WICDecoder = 0x00000001,
+ WICEncoder = 0x00000002,
+ WICPixelFormatConverter = 0x00000004,
+ WICMetadataReader = 0x00000008,
+ WICMetadataWriter = 0x00000010,
+ WICPixelFormat = 0x00000020,
+ WICCOMPONENTTYPE_FORCE_DWORD = CODEC_FORCE_DWORD
+} WICComponentType;
+
+typedef enum WICComponentSigning {
+ WICComponentSigned = 0x00000001,
+ WICComponentUnsigned = 0x00000002,
+ WICComponentSafe = 0x00000004,
+ WICComponentDisabled = 0x80000000
+} WICComponentSigning;
+
+typedef enum WICComponentEnumerateOptions {
+ WICComponentEnumerateDefault = 0x00000000,
+ WICComponentEnumerateRefresh = 0x00000001,
+ WICComponentEnumerateBuiltInOnly = 0x20000000,
+ WICComponentEnumerateUnsigned = 0x40000000,
+ WICComponentEnumerateDisabled = 0x80000000
+} WICComponentEnumerateOptions;
+
+typedef GUID WICPixelFormatGUID;
+typedef REFGUID REFWICPixelFormatGUID;
+
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormatDontCare, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x00);")
+cpp_quote("#define GUID_WICPixelFormatUndefined GUID_WICPixelFormatDontCare")
+
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat1bppIndexed, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x01);")
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat2bppIndexed, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x02);")
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat4bppIndexed, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x03);")
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat8bppIndexed, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x04);")
+
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat16bppBGR555, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x09);")
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat16bppBGR565, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0a);")
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat24bppBGR, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0c);")
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat32bppBGR, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0e);")
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat32bppBGRA, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0f);")
+cpp_quote("DEFINE_GUID(GUID_WICPixelFormat32bppPBGRA, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x10);")
+
+typedef struct WICRect {
+ INT X;
+ INT Y;
+ INT Width;
+ INT Height;
+} WICRect;
+
+typedef struct WICBitmapPattern {
+ ULARGE_INTEGER Position;
+ ULONG Length;
+ BYTE *Pattern;
+ BYTE *Mask;
+ BOOL EndOfStream;
+} WICBitmapPattern;
+
+typedef UINT32 WICColor;
+
+cpp_quote("#define WINCODEC_ERR_WRONGSTATE 0x88982f04")
+cpp_quote("#define WINCODEC_ERR_NOTINITIALIZED 0x88982f0c")
+cpp_quote("#define WINCODEC_ERR_CODECNOTHUMBNAIL 0x88982f44")
+cpp_quote("#define WINCODEC_ERR_PALETTEUNAVAILABLE 0x88982f45")
+cpp_quote("#define WINCODEC_ERR_COMPONENTNOTFOUND 0x88982f50")
+cpp_quote("#define WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT 0x88982f80")
+cpp_quote("#define WINCODEC_ERR_UNSUPPORTEDOPERATION 0x88982f81")
+cpp_quote("#define WINCODEC_ERR_INSUFFICIENTBUFFER 0x88982f8c")
+
+interface IWICBitmap;
+interface IWICPalette;
+interface IWICBitmapScaler;
+interface IWICBitmapClipper;
+interface IWICBitmapFlipRotator;
+interface IWICColorContext;
+interface IWICColorTransform;
+interface IWICFastMetadataEncoder;
+interface IWICMetadataQueryReader;
+interface IWICMetadataQueryWriter;
+
+[
+ object,
+ uuid(00000120-a8f2-4877-ba0a-fd2b6645fb94)
+]
+interface IWICBitmapSource : IUnknown
+{
+ HRESULT GetSize(
+ [out] UINT *puiWidth,
+ [out] UINT *puiHeight);
+
+ HRESULT GetPixelFormat(
+ [out] WICPixelFormatGUID *pPixelFormat);
+
+ HRESULT GetResolution(
+ [out] double *pDpiX,
+ [out] double *pDpiY);
+
+ HRESULT CopyPalette(
+ [in] IWICPalette *pIPalette);
+
+ HRESULT CopyPixels(
+ [in] const WICRect *prc,
+ [in] UINT cbStride,
+ [in] UINT cbBufferSize,
+ [out, size_is(cbBufferSize)] BYTE *pbBuffer);
+}
+
+[
+ object,
+ uuid(00000040-a8f2-4877-ba0a-fd2b6645fb94)
+]
+interface IWICPalette : IUnknown
+{
+ HRESULT InitializePredefined(
+ [in] WICBitmapPaletteType ePaletteType,
+ [in] BOOL fAddTransparentColor);
+
+ HRESULT InitializeCustom(
+ [in, size_is(colorCount)] WICColor *pColors,
+ [in] UINT colorCount);
+
+ HRESULT InitializeFromBitmap(
+ [in] IWICBitmapSource *pISurface,
+ [in] UINT colorCount,
+ [in] BOOL fAddTransparentColor);
+
+ HRESULT InitializeFromPalette(
+ [in] IWICPalette *pIPalette);
+
+ HRESULT GetType(
+ [out] WICBitmapPaletteType *pePaletteType);
+
+ HRESULT GetColorCount(
+ [out] UINT *pcCount);
+
+ HRESULT GetColors(
+ [in] UINT colorCount,
+ [out, size_is(colorCount)] WICColor *pColors,
+ [out] UINT *pcActualColors);
+
+ HRESULT IsBlackWhite(
+ [out] BOOL *pfIsBlackWhite);
+
+ HRESULT IsGrayscale(
+ [out] BOOL *pfIsGrayscale);
+
+ HRESULT HasAlpha(
+ [out] BOOL *pfHasAlpha);
+}
+
+[
+ object,
+ uuid(23bc3f0a-698b-4357-886b-f24d50671334)
+]
+interface IWICComponentInfo : IUnknown
+{
+ HRESULT GetComponentType(
+ [out] WICComponentType *pType);
+
+ HRESULT GetCLSID(
+ [out] CLSID *pclsid);
+
+ HRESULT GetSigningStatus(
+ [out] DWORD *pStatus);
+
+ HRESULT GetAuthor(
+ [in] UINT cchAuthor,
+ [in, out, unique, size_is(cchAuthor)] WCHAR *wzAuthor,
+ [out] UINT *pcchActual);
+
+ HRESULT GetVendorGUID(
+ [out] GUID *pguidVendor);
+
+ HRESULT GetVersion(
+ [in] UINT cchVersion,
+ [in, out, unique, size_is(cchVersion)] WCHAR *wzVersion,
+ [out] UINT *pcchActual);
+
+ HRESULT GetSpecVersion(
+ [in] UINT cchSpecVersion,
+ [in, out, unique, size_is(cchSpecVersion)] WCHAR *wzSpecVersion,
+ [out] UINT *pcchActual);
+
+ HRESULT GetFriendlyName(
+ [in] UINT cchFriendlyName,
+ [in, out, unique, size_is(cchFriendlyName)] WCHAR *wzFriendlyName,
+ [out] UINT *pcchActual);
+}
+
+[
+ object,
+ uuid(3b16811b-6a43-4ec9-a813-3d930c13b940)
+]
+interface IWICBitmapFrameDecode : IWICBitmapSource
+{
+ HRESULT GetMetadataQueryReader(
+ [out] IWICMetadataQueryReader **ppIMetadataQueryReader);
+
+ HRESULT GetColorContexts(
+ [in] UINT cCount,
+ [in, out, unique, size_is(cCount)] IWICColorContext **ppIColorContexts,
+ [out] UINT *pcActualCount);
+
+ HRESULT GetThumbnail(
+ [out] IWICBitmapSource **ppIThumbnail);
+}
+
+[
+ object,
+ uuid(e87a44c4-b76e-4c47-8b09-298eb12a2714)
+]
+interface IWICBitmapCodecInfo : IWICComponentInfo
+{
+ HRESULT GetContainerFormat(
+ [out] GUID *pguidContainerFormat);
+
+ HRESULT GetPixelFormats(
+ [in] UINT cFormats,
+ [in, out, unique, size_is(cFormats)] GUID *pguidPixelFormats,
+ [out] UINT *pcActual);
+
+ HRESULT GetColorManagementVersion(
+ [in] UINT cchColorManagementVersion,
+ [in, out, unique, size_is(cchColorManagementVersion)] WCHAR *wzColorManagementVersion,
+ [out] UINT *pcchActual);
+
+ HRESULT GetDeviceManufacturer(
+ [in] UINT cchDeviceManufacturer,
+ [in, out, unique, size_is(cchDeviceManufacturer)] WCHAR *wzDeviceManufacturer,
+ [out] UINT *pcchActual);
+
+ HRESULT GetDeviceModels(
+ [in] UINT cchDeviceModels,
+ [in, out, unique, size_is(cchDeviceModels)] WCHAR *wzDeviceModels,
+ [out] UINT *pcchActual);
+
+ HRESULT GetMimeTypes(
+ [in] UINT cchMimeTypes,
+ [in, out, unique, size_is(cchMimeTypes)] WCHAR *wzMimeTypes,
+ [out] UINT *pcchActual);
+
+ HRESULT GetFileExtensions(
+ [in] UINT cchFileExtensions,
+ [in, out, unique, size_is(cchFileExtensions)] WCHAR *wzFileExtensions,
+ [out] UINT *pcchActual);
+
+ HRESULT DoesSupportAnimation(
+ [out] BOOL *pfSupportAnimation);
+
+ HRESULT DoesSupportChromaKey(
+ [out] BOOL *pfSupportChromaKey);
+
+ HRESULT DoesSupportLossless(
+ [out] BOOL *pfSupportLossless);
+
+ HRESULT DoesSupportMultiframe(
+ [out] BOOL *pfSupportMultiframe);
+
+ HRESULT MatchesMimeType(
+ [in] LPCWSTR wzMimeType,
+ [out] BOOL *pfMatches);
+}
+
+interface IWICBitmapDecoder;
+
+[
+ object,
+ uuid(d8cd007f-d08f-4191-9bfc-236ea7f0e4b5)
+]
+interface IWICBitmapDecoderInfo : IWICBitmapCodecInfo
+{
+ [local]
+ HRESULT GetPatterns(
+ [in] UINT cbSizePatterns,
+ [in, out, unique] WICBitmapPattern *pPatterns,
+ [in, out, unique] UINT *pcPatterns,
+ [in, out, unique] UINT *pcbPatternsActual);
+
+ HRESULT MatchesPattern(
+ [in] IStream *pIStream,
+ [out] BOOL *pfMatches);
+
+ HRESULT CreateInstance(
+ [out] IWICBitmapDecoder **ppIBitmapDecoder);
+}
+
+[
+ object,
+ uuid(9edde9e7-8dee-47ea-99df-e6faf2ed44bf)
+]
+interface IWICBitmapDecoder : IUnknown
+{
+ HRESULT QueryCapability(
+ [in] IStream *pIStream,
+ [out] DWORD *pdwCapability);
+
+ HRESULT Initialize(
+ [in] IStream *pIStream,
+ [in] WICDecodeOptions cacheOptions);
+
+ HRESULT GetContainerFormat(
+ [out] GUID *pguidContainerFormat);
+
+ HRESULT GetDecoderInfo(
+ [out] IWICBitmapDecoderInfo **ppIDecoderInfo);
+
+ HRESULT CopyPalette(
+ [in] IWICPalette *pIPalette);
+
+ HRESULT GetMetadataQueryReader(
+ [out] IWICMetadataQueryReader **ppIMetadataQueryReader);
+
+ HRESULT GetPreview(
+ [out] IWICBitmapSource **ppIBitmapSource);
+
+ HRESULT GetColorContexts(
+ [in] UINT cCount,
+ [in, out, unique, size_is(cCount)] IWICColorContext **ppIColorContexts,
+ [out] UINT *pcActualCount);
+
+ HRESULT GetThumbnail(
+ [out] IWICBitmapSource **ppIThumbnail);
+
+ HRESULT GetFrameCount(
+ [out] UINT *pCount);
+
+ HRESULT GetFrame(
+ [in] UINT index,
+ [out] IWICBitmapFrameDecode **ppIBitmapFrame);
+}
+
+[
+ object,
+ uuid(00000105-a8f2-4877-ba0a-fd2b6645fb94)
+]
+interface IWICBitmapFrameEncode : IUnknown
+{
+ HRESULT Initialize(
+ [in, unique] IPropertyBag2 *pIEncoderOptions);
+
+ HRESULT SetSize(
+ [in] UINT uiWidth,
+ [in] UINT uiHeight);
+
+ HRESULT SetResolution(
+ [in] double dpiX,
+ [in] double dpiY);
+
+ HRESULT SetPixelFormat(
+ [in, out] WICPixelFormatGUID *pPixelFormat);
+
+ HRESULT SetColorContexts(
+ [in] UINT cCount,
+ [in, size_is(cCount)] IWICColorContext **ppIColorContext);
+
+ HRESULT SetPalette(
+ [in] IWICPalette *pIPalette);
+
+ HRESULT SetThumbnail(
+ [in] IWICBitmapSource *pIThumbnail);
+
+ HRESULT WritePixels(
+ [in] UINT lineCount,
+ [in] UINT cbStride,
+ [in] UINT cbBufferSize,
+ [in, size_is(cbBufferSize)] BYTE *pbPixels);
+
+ HRESULT WriteSource(
+ [in] IWICBitmapSource *pIBitmapSource,
+ [in, unique] WICRect *prc);
+
+ HRESULT Commit();
+
+ HRESULT GetMetadataQueryWriter(
+ IWICMetadataQueryWriter **ppIMetadataQueryWriter);
+}
+
+interface IWICBitmapEncoder;
+
+[
+ object,
+ uuid(94c9b4ee-a09f-4f92-8a1e-4a9bce7e76fb)
+]
+interface IWICBitmapEncoderInfo : IWICBitmapCodecInfo
+{
+ HRESULT CreateInstance(
+ [out] IWICBitmapEncoder **ppIBitmapEncoder);
+}
+
+[
+ object,
+ uuid(00000103-a8f2-4877-ba0a-fd2b6645fb94)
+]
+interface IWICBitmapEncoder : IUnknown
+{
+ HRESULT Initialize(
+ [in] IStream *pIStream,
+ [in] WICBitmapEncoderCacheOption cacheOption);
+
+ HRESULT GetContainerFormat(
+ [out] GUID *pguidContainerFormat);
+
+ HRESULT GetEncoderInfo(
+ [out] IWICBitmapEncoderInfo **ppIEncoderInfo);
+
+ HRESULT SetColorContexts(
+ [in] UINT cCount,
+ [in, size_is(cCount)] IWICColorContext **ppIColorContext);
+
+ HRESULT SetPalette(
+ [in] IWICPalette *pIPalette);
+
+ HRESULT SetThumbnail(
+ [in] IWICBitmapSource *pIThumbnail);
+
+ HRESULT SetPreview(
+ [in] IWICBitmapSource *pIPreview);
+
+ HRESULT CreateNewFrame(
+ [out] IWICBitmapFrameEncode **ppIFrameEncode,
+ [in, out, unique] IPropertyBag2 **ppIEncoderOptions);
+
+ HRESULT Commit();
+
+ HRESULT GetMetadataQueryWriter(
+ [out] IWICMetadataQueryWriter **ppIMetadataQueryWriter);
+}
+
+[
+ object,
+ uuid(00000301-a8f2-4877-ba0a-fd2b6645fb94)
+]
+interface IWICFormatConverter : IWICBitmapSource
+{
+ HRESULT Initialize(
+ [in] IWICBitmapSource *pISource,
+ [in] REFWICPixelFormatGUID dstFormat,
+ [in] WICBitmapDitherType dither,
+ [in] IWICPalette *pIPalette,
+ [in] double alphaThresholdPercent,
+ [in] WICBitmapPaletteType paletteTranslate);
+
+ HRESULT CanConvert(
+ [in] REFWICPixelFormatGUID srcPixelFormat,
+ [in] REFWICPixelFormatGUID dstPixelFormat,
+ [out] BOOL *pfCanConvert);
+}
+
+[
+ object,
+ uuid(9f34fb65-13f4-4f15-bc57-3726b5e53d9f)
+]
+interface IWICFormatConverterInfo : IWICComponentInfo
+{
+ HRESULT GetPixelFormats(
+ [in] UINT cFormats,
+ [in, out, size_is(cFormats)] WICPixelFormatGUID *pPixelFormatGUIDs,
+ [out] UINT *pcActual);
+
+ HRESULT CreateInstance(
+ [out] IWICFormatConverter **ppIConverter);
+}
+
+[
+ object,
+ uuid(135ff860-22b7-4ddf-b0f6-218f4f299a43)
+]
+interface IWICStream : IStream
+{
+ HRESULT InitializeFromIStream(
+ [in] IStream *pIStream);
+
+ HRESULT InitializeFromFilename(
+ [in] LPCWSTR wzFileName,
+ [in] DWORD dwAccessMode);
+
+ HRESULT InitializeFromMemory(
+ [in, size_is(cbBufferSize)] BYTE *pbBuffer,
+ [in] DWORD cbBufferSize);
+
+ HRESULT InitializeFromIStreamRegion(
+ [in] IStream *pIStream,
+ [in] ULARGE_INTEGER ulOffset,
+ [in] ULARGE_INTEGER ulMaxSize);
+}
+
+cpp_quote("DEFINE_GUID(CLSID_WICImagingFactory, 0xcacaf262,0x9370,0x4615,0xa1,0x3b,0x9f,0x55,0x39,0xda,0x4c,0x0a);")
+
+[
+ object,
+ uuid(ec5ec8a9-c395-4314-9c77-54d7a935ff70)
+]
+interface IWICImagingFactory : IUnknown
+{
+ HRESULT CreateDecoderFromFilename(
+ [in] LPCWSTR wzFilename,
+ [in, unique] const GUID *pguidVendor,
+ [in] DWORD dwDesiredAccess,
+ [in] WICDecodeOptions metadataOptions,
+ [out, retval] IWICBitmapDecoder **ppIDecoder);
+
+ HRESULT CreateDecoderFromStream(
+ [in] IStream *pIStream,
+ [in, unique] const GUID *pguidVendor,
+ [in] WICDecodeOptions metadataOptions,
+ [out, retval] IWICBitmapDecoder **ppIDecoder);
+
+ HRESULT CreateDecoderFromFileHandle(
+ [in] ULONG_PTR hFile,
+ [in, unique] const GUID *pguidVendor,
+ [in] WICDecodeOptions metadataOptions,
+ [out, retval] IWICBitmapDecoder **ppIDecoder);
+
+ HRESULT CreateComponentInfo(
+ [in] REFCLSID clsidComponent,
+ [out] IWICComponentInfo **ppIInfo);
+
+ HRESULT CreateDecoder(
+ [in] REFGUID guidContainerFormat,
+ [in, unique] const GUID *pguidVendor,
+ [out, retval] IWICBitmapDecoder **ppIDecoder);
+
+ HRESULT CreateEncoder(
+ [in] REFGUID guidContainerFormat,
+ [in, unique] const GUID *pguidVendor,
+ [out, retval] IWICBitmapEncoder **ppIEncoder);
+
+ HRESULT CreatePalette(
+ [out] IWICPalette **ppIPalette);
+
+ HRESULT CreateFormatConverter(
+ [out] IWICFormatConverter **ppIFormatConverter);
+
+ HRESULT CreateBitmapScaler(
+ [out] IWICBitmapScaler **ppIBitmapScaler);
+
+ HRESULT CreateBitmapClipper(
+ [out] IWICBitmapClipper **ppIBitmapClipper);
+
+ HRESULT CreateBitmapFlipRotator(
+ [out] IWICBitmapFlipRotator **ppIBitmapFlipRotator);
+
+ HRESULT CreateStream(
+ [out] IWICStream **ppIWICStream);
+
+ HRESULT CreateColorContext(
+ [out] IWICColorContext **ppIWICColorContext);
+
+ HRESULT CreateColorTransformer(
+ [out] IWICColorTransform **ppIWICColorTransform);
+
+ HRESULT CreateBitmap(
+ [in] UINT uiWidth,
+ [in] UINT uiHeight,
+ [in] REFWICPixelFormatGUID pixelFormat,
+ [in] WICBitmapCreateCacheOption option,
+ [out] IWICBitmap **ppIBitmap);
+
+ HRESULT CreateBitmapFromSource(
+ [in] IWICBitmapSource *piBitmapSource,
+ [in] WICBitmapCreateCacheOption option,
+ [out] IWICBitmap **ppIBitmap);
+
+ HRESULT CreateBitmapFromSourceRect(
+ [in] IWICBitmapSource *piBitmapSource,
+ [in] UINT x,
+ [in] UINT y,
+ [in] UINT width,
+ [in] UINT height,
+ [out] IWICBitmap **ppIBitmap);
+
+ HRESULT CreateBitmapFromMemory(
+ [in] UINT uiWidth,
+ [in] UINT uiHeight,
+ [in] REFWICPixelFormatGUID pixelFormat,
+ [in] UINT cbStride,
+ [in] UINT cbBufferSize,
+ [in, size_is(cbBufferSize)] BYTE *pbBuffer,
+ [out] IWICBitmap **ppIBitmap);
+
+ HRESULT CreateBitmapFromHBITMAP(
+ [in] HBITMAP hBitmap,
+ [in, unique] HPALETTE hPalette,
+ [in] WICBitmapAlphaChannelOption options,
+ [out] IWICBitmap **ppIBitmap);
+
+ HRESULT CreateBitmapFromHICON(
+ [in] HICON hIcon,
+ [out] IWICBitmap **ppIBitmap);
+
+ HRESULT CreateComponentEnumerator(
+ [in] DWORD componentTypes,
+ [in] DWORD options,
+ [out] IEnumUnknown **ppIEnumUnknown);
+
+ HRESULT CreateFastMetadataEncoderFromDecoder(
+ [in] IWICBitmapDecoder *pIDecoder,
+ [out] IWICFastMetadataEncoder **ppIFastEncoder);
+
+ HRESULT CreateFastMetadataEncoderFromFrameDecode(
+ [in] IWICBitmapFrameDecode *pIFrameDecoder,
+ [out] IWICFastMetadataEncoder **ppIFastEncoder);
+
+ HRESULT CreateQueryWriter(
+ [in] REFGUID guidMetadataFormat,
+ [in, unique] const GUID *pguidVendor,
+ [out] IWICMetadataQueryWriter **ppIQueryWriter);
+
+ HRESULT CreateQueryWriterFromReader(
+ [in] IWICMetadataQueryReader *pIQueryReader,
+ [in, unique] const GUID *pguidVendor,
+ [out] IWICMetadataQueryWriter **ppIQueryWriter);
+}
+
+cpp_quote("HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst);")
+
+cpp_quote("DEFINE_GUID(CLSID_WICBmpDecoder, 0x6b462062,0x7cbf,0x400d,0x9f,0xdb,0x81,0x3d,0xd1,0x0f,0x27,0x78);")
+cpp_quote("DEFINE_GUID(CLSID_WICPngDecoder, 0x389ea17b,0x5078,0x4cde,0xb6,0xef,0x25,0xc1,0x51,0x75,0xc7,0x51);")
+cpp_quote("DEFINE_GUID(CLSID_WICIcoDecoder, 0xc61bfcdf,0x2e0f,0x4aad,0xa8,0xd7,0xe0,0x6b,0xaf,0xeb,0xcd,0xfe);")
+cpp_quote("DEFINE_GUID(CLSID_WICJpegDecoder, 0x9456a480,0xe88b,0x43ea,0x9e,0x73,0x0b,0x2d,0x9b,0x71,0xb1,0xca);")
+cpp_quote("DEFINE_GUID(CLSID_WICGifDecoder, 0x381dda3c,0x9ce9,0x4834,0xa2,0x3e,0x1f,0x98,0xf8,0xfc,0x52,0xbe);")
+cpp_quote("DEFINE_GUID(CLSID_WICTiffDecoder, 0xb54e85d9,0xfe23,0x499f,0x8b,0x88,0x6a,0xce,0xa7,0x13,0x75,0x2b);")
+cpp_quote("DEFINE_GUID(CLSID_WICWmpDecoder, 0xa26cec36,0x234c,0x4950,0xae,0x16,0xe3,0x4a,0xac,0xe7,0x1d,0x0d);")
+
+cpp_quote("DEFINE_GUID(CLSID_WICBmpEncoder, 0x69be8bb4,0xd66d,0x47c8,0x86,0x5a,0xed,0x15,0x89,0x43,0x37,0x82);")
+cpp_quote("DEFINE_GUID(CLSID_WICPngEncoder, 0x27949969,0x876a,0x41d7,0x94,0x47,0x56,0x8f,0x6a,0x35,0xa4,0xdc);")
+cpp_quote("DEFINE_GUID(CLSID_WICJpegEncoder, 0x1a34f5c1,0x4a5a,0x46dc,0xb6,0x44,0x1f,0x45,0x67,0xe7,0xa6,0x76);")
+cpp_quote("DEFINE_GUID(CLSID_WICGifEncoder, 0x114f5598,0x0b22,0x40a0,0x86,0xa1,0xc8,0x3e,0xa4,0x95,0xad,0xbd);")
+cpp_quote("DEFINE_GUID(CLSID_WICTiffEncoder, 0x0131be10,0x2001,0x4c5f,0xa9,0xb0,0xcc,0x88,0xfa,0xb6,0x4c,0xe8);")
+cpp_quote("DEFINE_GUID(CLSID_WICWmpEncoder, 0xac4ce3cb,0xe1c1,0x44cd,0x82,0x15,0x5a,0x16,0x65,0x50,0x9e,0xc2);")
+
+cpp_quote("DEFINE_GUID(CLSID_WICDefaultFormatConverter, 0x1a3f11dc,0xb514,0x4b17,0x8c,0x5f,0x21,0x54,0x51,0x38,0x52,0xf1);")
+
+cpp_quote("DEFINE_GUID(GUID_ContainerFormatBmp, 0x0af1d87e,0xfcfe,0x4188,0xbd,0xeb,0xa7,0x90,0x64,0x71,0xcb,0xe3);")
+cpp_quote("DEFINE_GUID(GUID_ContainerFormatPng, 0x1b7cfaf4,0x713f,0x473c,0xbb,0xcd,0x61,0x37,0x42,0x5f,0xae,0xaf);")
+cpp_quote("DEFINE_GUID(GUID_ContainerFormatIco, 0xa3a860c4,0x338f,0x4c17,0x91,0x9a,0xfb,0xa4,0xb5,0x62,0x8f,0x21);")
+cpp_quote("DEFINE_GUID(GUID_ContainerFormatJpeg, 0x19e4a5aa,0x5662,0x4fc5,0xa0,0xc0,0x17,0x58,0x02,0x8e,0x10,0x57);")
+cpp_quote("DEFINE_GUID(GUID_ContainerFormatTiff, 0x163bcc30,0xe2e9,0x4f0b,0x96,0x1d,0xa3,0xe9,0xfd,0xb7,0x88,0xa3);")
+cpp_quote("DEFINE_GUID(GUID_ContainerFormatGif, 0x1f8a5601,0x7d4d,0x4cbd,0x9c,0x82,0x1b,0xc8,0xd4,0xee,0xb9,0xa5);")
+cpp_quote("DEFINE_GUID(GUID_ContainerFormatWmp, 0x57a37caa,0x367a,0x4540,0x91,0x6b,0xf1,0x83,0xc5,0x09,0x3a,0x4b);")
+
+cpp_quote("DEFINE_GUID(GUID_VendorMicrosoft, 0xf0e749ca,0xedef,0x4589,0xa7,0x3a,0xee,0x0e,0x62,0x6a,0x2a,0x2b);")
+
+cpp_quote("DEFINE_GUID(CATID_WICBitmapDecoders, 0x7ed96837,0x96f0,0x4812,0xb2,0x11,0xf1,0x3c,0x24,0x11,0x7e,0xd3);")
+cpp_quote("DEFINE_GUID(CATID_WICBitmapEncoders, 0xac757296,0x3522,0x4e11,0x98,0x62,0xc1,0x7b,0xe5,0xa1,0x76,0x7e);")
+cpp_quote("DEFINE_GUID(CATID_WICFormatConverters, 0x7835eae8,0xbf14,0x49d1,0x93,0xce,0x53,0x3a,0x40,0x7b,0x22,0x48);")
diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE
index 0f241d7e157..bd4ea29bad4 100644
--- a/reactos/media/doc/README.WINE
+++ b/reactos/media/doc/README.WINE
@@ -163,6 +163,7 @@ reactos/dll/win32/urlmon # Autosync
reactos/dll/win32/usp10 # Autosync
reactos/dll/win32/uxtheme # Autosync
reactos/dll/win32/version # Autosync
+reactos/dll/win32/windowscodecs # Autosync
reactos/dll/win32/winemp3.acm # Autosync
reactos/dll/win32/wininet # Autosync
reactos/dll/win32/winhttp # Autosync