From 324214f99875727891e3ac3762dd63a5b18df057 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Mon, 4 Jun 2018 03:55:39 +0100 Subject: [PATCH] [WINDOWSCODECS] Sync with Wine Staging 3.9. CORE-14656 --- dll/win32/windowscodecs/bitmap.c | 29 +- dll/win32/windowscodecs/bmpdecode.c | 13 +- dll/win32/windowscodecs/bmpencode.c | 49 +- dll/win32/windowscodecs/converter.c | 43 ++ dll/win32/windowscodecs/gifformat.c | 13 +- dll/win32/windowscodecs/icoformat.c | 13 +- dll/win32/windowscodecs/imgfactory.c | 40 +- dll/win32/windowscodecs/info.c | 817 ++++++++++++-------- dll/win32/windowscodecs/jpegformat.c | 165 ++-- dll/win32/windowscodecs/main.c | 3 + dll/win32/windowscodecs/pngformat.c | 13 +- dll/win32/windowscodecs/precomp.h | 1 + dll/win32/windowscodecs/tgaformat.c | 13 +- dll/win32/windowscodecs/tiffformat.c | 13 +- dll/win32/windowscodecs/wincodecs_private.h | 4 +- media/doc/README.WINE | 2 +- 16 files changed, 679 insertions(+), 552 deletions(-) diff --git a/dll/win32/windowscodecs/bitmap.c b/dll/win32/windowscodecs/bitmap.c index 69ec14fed28..734c211c687 100644 --- a/dll/win32/windowscodecs/bitmap.c +++ b/dll/win32/windowscodecs/bitmap.c @@ -45,7 +45,8 @@ typedef struct BitmapImpl { int palette_set; LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */ BYTE *data; - BOOL is_section; /* TRUE if data is a section created by an application */ + void *view; /* used if data is a section created by an application */ + UINT offset; /* offset into view */ UINT width, height; UINT stride; UINT bpp; @@ -288,8 +289,8 @@ static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface) if (This->palette) IWICPalette_Release(This->palette); This->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->cs); - if (This->is_section) - UnmapViewOfFile(This->data); + if (This->view) + UnmapViewOfFile(This->view); else HeapFree(GetProcessHeap(), 0, This->data); HeapFree(GetProcessHeap(), 0, This); @@ -805,13 +806,13 @@ static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl = IMILUnknown2Impl_unknown3 }; -HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, - UINT stride, UINT datasize, BYTE *data, - REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option, +HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, UINT stride, UINT datasize, void *view, + UINT offset, REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option, IWICBitmap **ppIBitmap) { HRESULT hr; BitmapImpl *This; + BYTE *data; UINT bpp; hr = get_pixelformat_bpp(pixelFormat, &bpp); @@ -826,18 +827,12 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl)); if (!This) return E_OUTOFMEMORY; - if (!data) + if (view) data = (BYTE *)view + offset; + else if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize))) { - data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize); - if (!data) - { - HeapFree(GetProcessHeap(), 0, This); - return E_OUTOFMEMORY; - } - This->is_section = FALSE; + HeapFree(GetProcessHeap(), 0, This); + return E_OUTOFMEMORY; } - else - This->is_section = TRUE; This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl; This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl; @@ -848,6 +843,8 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, This->palette_set = 0; This->lock = 0; This->data = data; + This->view = view; + This->offset = offset; This->width = uiWidth; This->height = uiHeight; This->stride = stride; diff --git a/dll/win32/windowscodecs/bmpdecode.c b/dll/win32/windowscodecs/bmpdecode.c index 47f312ffcf0..1b8e4d1f37d 100644 --- a/dll/win32/windowscodecs/bmpdecode.c +++ b/dll/win32/windowscodecs/bmpdecode.c @@ -1068,20 +1068,9 @@ static HRESULT WINAPI BmpDecoder_GetContainerFormat(IWICBitmapDecoder *iface, 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; + return get_decoder_info(&CLSID_WICBmpDecoder, ppIDecoderInfo); } static HRESULT WINAPI BmpDecoder_CopyPalette(IWICBitmapDecoder *iface, diff --git a/dll/win32/windowscodecs/bmpencode.c b/dll/win32/windowscodecs/bmpencode.c index cb8b4897e49..a81cc532233 100644 --- a/dll/win32/windowscodecs/bmpencode.c +++ b/dll/win32/windowscodecs/bmpencode.c @@ -261,8 +261,10 @@ static HRESULT WINAPI BmpFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels) { BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + UINT dstbuffersize, bytesperrow, row; + BYTE *dst, *src; 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) @@ -271,19 +273,27 @@ static HRESULT WINAPI BmpFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, hr = BmpFrameEncode_AllocateBits(This); if (FAILED(hr)) return hr; - rc.X = 0; - rc.Y = 0; - rc.Width = This->width; - rc.Height = lineCount; + bytesperrow = ((This->format->bpp * This->width) + 7) / 8; - 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 (This->stride < bytesperrow) + return E_INVALIDARG; - if (SUCCEEDED(hr)) - This->lineswritten += lineCount; + dstbuffersize = This->stride * (This->height - This->lineswritten); + if ((This->stride * (lineCount - 1)) + bytesperrow > dstbuffersize) + return E_INVALIDARG; - return hr; + src = pbPixels; + dst = This->bits + This->stride * (This->height - This->lineswritten - 1); + for (row = 0; row < lineCount; row++) + { + memcpy(dst, src, bytesperrow); + src += cbStride; + dst -= This->stride; + } + + This->lineswritten += lineCount; + + return S_OK; } static HRESULT WINAPI BmpFrameEncode_WriteSource(IWICBitmapFrameEncode *iface, @@ -314,11 +324,10 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); BITMAPFILEHEADER bfh; BITMAPV5HEADER bih; - UINT info_size, i; + UINT info_size; LARGE_INTEGER pos; ULONG byteswritten; HRESULT hr; - const BYTE *bits; TRACE("(%p)\n", iface); @@ -331,7 +340,7 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) bih.bV5Size = info_size = sizeof(BITMAPINFOHEADER); bih.bV5Width = This->width; - bih.bV5Height = This->height; /* bottom-top bitmap */ + bih.bV5Height = This->height; bih.bV5Planes = 1; bih.bV5BitCount = This->format->bpp; bih.bV5Compression = This->format->compression; @@ -378,15 +387,9 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) if (byteswritten != This->colors * sizeof(WICColor)) return E_FAIL; } - /* write the image bits as a bottom-top array */ - bits = This->bits + bih.bV5SizeImage; - for (i = 0; i < This->height; i++) - { - bits -= This->stride; - hr = IStream_Write(This->stream, bits, This->stride, &byteswritten); - if (FAILED(hr)) return hr; - if (byteswritten != This->stride) return E_FAIL; - } + 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; diff --git a/dll/win32/windowscodecs/converter.c b/dll/win32/windowscodecs/converter.c index c3bcce89e00..0d3414a1465 100644 --- a/dll/win32/windowscodecs/converter.c +++ b/dll/win32/windowscodecs/converter.c @@ -30,6 +30,7 @@ #include "wincodecs_private.h" +#include "wine/heap.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); @@ -1087,6 +1088,48 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec } return S_OK; + case format_32bppCMYK: + if (prc) + { + BYTE *srcdata; + UINT srcstride, srcdatasize; + + srcstride = 4 * prc->Width; + srcdatasize = srcstride * prc->Height; + + srcdata = heap_alloc(srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); + if (SUCCEEDED(hr)) + { + INT x, y; + BYTE *src = srcdata, *dst = pbBuffer; + + for (y = 0; y < prc->Height; y++) + { + BYTE *cmyk = src; + BYTE *bgr = dst; + + for (x = 0; x < prc->Width; x++) + { + BYTE c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3]; + bgr[0] = (255 - y) * (255 - k) / 255; /* B */ + bgr[1] = (255 - m) * (255 - k) / 255; /* G */ + bgr[2] = (255 - c) * (255 - k) / 255; /* R */ + cmyk += 4; + bgr += 3; + } + src += srcstride; + dst += cbStride; + } + } + + heap_free(srcdata); + return hr; + } + return S_OK; + default: FIXME("Unimplemented conversion path!\n"); return WINCODEC_ERR_UNSUPPORTEDOPERATION; diff --git a/dll/win32/windowscodecs/gifformat.c b/dll/win32/windowscodecs/gifformat.c index e898d9c852d..78ac427d9ac 100644 --- a/dll/win32/windowscodecs/gifformat.c +++ b/dll/win32/windowscodecs/gifformat.c @@ -1176,20 +1176,9 @@ static HRESULT WINAPI GifDecoder_GetContainerFormat(IWICBitmapDecoder *iface, 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; + return get_decoder_info(&CLSID_WICGifDecoder, ppIDecoderInfo); } static HRESULT WINAPI GifDecoder_CopyPalette(IWICBitmapDecoder *iface, IWICPalette *palette) diff --git a/dll/win32/windowscodecs/icoformat.c b/dll/win32/windowscodecs/icoformat.c index 1b1c79291b0..5e38ee0d0fa 100644 --- a/dll/win32/windowscodecs/icoformat.c +++ b/dll/win32/windowscodecs/icoformat.c @@ -556,20 +556,9 @@ static HRESULT WINAPI IcoDecoder_GetContainerFormat(IWICBitmapDecoder *iface, static HRESULT WINAPI IcoDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **ppIDecoderInfo) { - HRESULT hr; - IWICComponentInfo *compinfo; - TRACE("(%p,%p)\n", iface, ppIDecoderInfo); - hr = CreateComponentInfo(&CLSID_WICIcoDecoder, &compinfo); - if (FAILED(hr)) return hr; - - hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo, - (void**)ppIDecoderInfo); - - IWICComponentInfo_Release(compinfo); - - return hr; + return get_decoder_info(&CLSID_WICIcoDecoder, ppIDecoderInfo); } static HRESULT WINAPI IcoDecoder_CopyPalette(IWICBitmapDecoder *iface, diff --git a/dll/win32/windowscodecs/imgfactory.c b/dll/win32/windowscodecs/imgfactory.c index 88ce00e651a..180e745f46b 100644 --- a/dll/win32/windowscodecs/imgfactory.c +++ b/dll/win32/windowscodecs/imgfactory.c @@ -477,7 +477,7 @@ static HRESULT WINAPI ComponentFactory_CreateBitmap(IWICComponentFactory *iface, { TRACE("(%p,%u,%u,%s,%u,%p)\n", iface, uiWidth, uiHeight, debugstr_guid(pixelFormat), option, ppIBitmap); - return BitmapImpl_Create(uiWidth, uiHeight, 0, 0, NULL, pixelFormat, option, ppIBitmap); + return BitmapImpl_Create(uiWidth, uiHeight, 0, 0, NULL, 0, pixelFormat, option, ppIBitmap); } static HRESULT WINAPI ComponentFactory_CreateBitmapFromSource(IWICComponentFactory *iface, @@ -524,7 +524,7 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromSource(IWICComponentFacto } if (SUCCEEDED(hr)) - hr = BitmapImpl_Create(width, height, 0, 0, NULL, &pixelformat, option, &result); + hr = BitmapImpl_Create(width, height, 0, 0, NULL, 0, &pixelformat, option, &result); if (SUCCEEDED(hr)) { @@ -606,7 +606,7 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromMemory(IWICComponentFacto if (!stride || !size || !buffer || !bitmap) return E_INVALIDARG; - hr = BitmapImpl_Create(width, height, stride, size, NULL, format, WICBitmapCacheOnLoad, bitmap); + hr = BitmapImpl_Create(width, height, stride, size, NULL, 0, format, WICBitmapCacheOnLoad, bitmap); if (SUCCEEDED(hr)) { IWICBitmapLock *lock; @@ -738,7 +738,8 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromHBITMAP(IWICComponentFact return E_INVALIDARG; } - hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, &format, WICBitmapCacheOnLoad, bitmap); + hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, 0, &format, + WICBitmapCacheOnLoad, bitmap); if (hr != S_OK) return hr; hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); @@ -822,7 +823,7 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromHICON(IWICComponentFactor stride = width * 4; size = stride * height; - hr = BitmapImpl_Create(width, height, stride, size, NULL, + hr = BitmapImpl_Create(width, height, stride, size, NULL, 0, &GUID_WICPixelFormat32bppBGRA, WICBitmapCacheOnLoad, bitmap); if (hr != S_OK) goto failed; @@ -1209,15 +1210,19 @@ HRESULT WINAPI WICCreateBitmapFromSectionEx(UINT width, UINT height, REFWICPixelFormatGUID format, HANDLE section, UINT stride, UINT offset, WICSectionAccessLevel wicaccess, IWICBitmap **bitmap) { - DWORD access; - void *buffer; + SYSTEM_INFO sysinfo; + UINT bpp, access, size, view_offset, view_size; + void *view; HRESULT hr; - TRACE("%u,%u,%s,%p,%u,%#x,%#x,%p\n", width, height, debugstr_guid(format), - section, stride, offset, wicaccess, bitmap); + TRACE("%u,%u,%s,%p,%u,%u,%#x,%p\n", width, height, debugstr_guid(format), + section, stride, offset, wicaccess, bitmap); if (!width || !height || !section || !bitmap) return E_INVALIDARG; + hr = get_pixelformat_bpp(format, &bpp); + if (FAILED(hr)) return hr; + switch (wicaccess) { case WICSectionAccessLevelReadWrite: @@ -1233,11 +1238,20 @@ HRESULT WINAPI WICCreateBitmapFromSectionEx(UINT width, UINT height, return E_INVALIDARG; } - buffer = MapViewOfFile(section, access, 0, offset, 0); - if (!buffer) return HRESULT_FROM_WIN32(GetLastError()); + if (!stride) stride = (((bpp * width) + 31) / 32) * 4; + size = stride * height; + if (size / height != stride) return E_INVALIDARG; + + GetSystemInfo(&sysinfo); + view_offset = offset - (offset % sysinfo.dwAllocationGranularity); + view_size = size + (offset - view_offset); + + view = MapViewOfFile(section, access, 0, view_offset, view_size); + if (!view) return HRESULT_FROM_WIN32(GetLastError()); - hr = BitmapImpl_Create(width, height, stride, 0, buffer, format, WICBitmapCacheOnLoad, bitmap); - if (FAILED(hr)) UnmapViewOfFile(buffer); + offset -= view_offset; + hr = BitmapImpl_Create(width, height, stride, 0, view, offset, format, WICBitmapCacheOnLoad, bitmap); + if (FAILED(hr)) UnmapViewOfFile(view); return hr; } diff --git a/dll/win32/windowscodecs/info.c b/dll/win32/windowscodecs/info.c index 22a7b83e2c2..33d3c3030dc 100644 --- a/dll/win32/windowscodecs/info.c +++ b/dll/win32/windowscodecs/info.c @@ -33,6 +33,8 @@ #include "wine/debug.h" #include "wine/unicode.h" #include "wine/list.h" +#include "wine/rbtree.h" +#include "wine/heap.h" WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); @@ -56,6 +58,13 @@ static const WCHAR supportspadding_valuename[] = {'S','u','p','p','o','r','t','s static const WCHAR fileextensions_valuename[] = {'F','i','l','e','E','x','t','e','n','s','i','o','n','s',0}; static const WCHAR containers_keyname[] = {'C','o','n','t','a','i','n','e','r','s',0}; +typedef struct { + IWICComponentInfo IWICComponentInfo_iface; + LONG ref; + CLSID clsid; + struct wine_rb_entry entry; +} ComponentInfo; + static HRESULT ComponentInfo_GetStringValue(HKEY classkey, LPCWSTR value, UINT buffer_size, WCHAR *buffer, UINT *actual_size) { @@ -204,15 +213,16 @@ static HRESULT ComponentInfo_GetGuidList(HKEY classkey, LPCWSTR subkeyname, } typedef struct { - IWICBitmapDecoderInfo IWICBitmapDecoderInfo_iface; - LONG ref; + ComponentInfo base; HKEY classkey; - CLSID clsid; + WICBitmapPattern *patterns; + UINT pattern_count; + UINT patterns_size; } BitmapDecoderInfo; static inline BitmapDecoderInfo *impl_from_IWICBitmapDecoderInfo(IWICBitmapDecoderInfo *iface) { - return CONTAINING_RECORD(iface, BitmapDecoderInfo, IWICBitmapDecoderInfo_iface); + return CONTAINING_RECORD(iface, BitmapDecoderInfo, base.IWICComponentInfo_iface); } static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *iface, REFIID iid, @@ -228,7 +238,7 @@ static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *if IsEqualIID(&IID_IWICBitmapCodecInfo, iid) || IsEqualIID(&IID_IWICBitmapDecoderInfo ,iid)) { - *ppv = &This->IWICBitmapDecoderInfo_iface; + *ppv = &This->base.IWICComponentInfo_iface; } else { @@ -243,7 +253,7 @@ static HRESULT WINAPI BitmapDecoderInfo_QueryInterface(IWICBitmapDecoderInfo *if static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface) { BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface); - ULONG ref = InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); @@ -253,13 +263,14 @@ static ULONG WINAPI BitmapDecoderInfo_AddRef(IWICBitmapDecoderInfo *iface) static ULONG WINAPI BitmapDecoderInfo_Release(IWICBitmapDecoderInfo *iface) { BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface); - ULONG ref = InterlockedDecrement(&This->ref); + ULONG ref = InterlockedDecrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); if (ref == 0) { RegCloseKey(This->classkey); + heap_free(This->patterns); HeapFree(GetProcessHeap(), 0, This); } @@ -283,8 +294,7 @@ static HRESULT WINAPI BitmapDecoderInfo_GetCLSID(IWICBitmapDecoderInfo *iface, C if (!pclsid) return E_INVALIDARG; - memcpy(pclsid, &This->clsid, sizeof(CLSID)); - + *pclsid = This->base.clsid; return S_OK; } @@ -445,103 +455,26 @@ static HRESULT WINAPI BitmapDecoderInfo_GetPatterns(IWICBitmapDecoderInfo *iface UINT cbSizePatterns, WICBitmapPattern *pPatterns, UINT *pcPatterns, UINT *pcbPatternsActual) { BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(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); + if (!pcPatterns || !pcbPatternsActual) return E_INVALIDARG; - RegCloseKey(patternskey); - - if (hr == S_OK) + *pcPatterns = This->pattern_count; + *pcbPatternsActual = This->patterns_size; + if (pPatterns) { - *pcPatterns = pattern_count; - *pcbPatternsActual = patterns_size; - if (pPatterns && cbSizePatterns < patterns_size) - hr = WINCODEC_ERR_INSUFFICIENTBUFFER; + if (This->patterns_size && cbSizePatterns < This->patterns_size) + return WINCODEC_ERR_INSUFFICIENTBUFFER; + memcpy(pPatterns, This->patterns, This->patterns_size); } - - return hr; + return S_OK; } static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *iface, IStream *pIStream, BOOL *pfMatches) { - WICBitmapPattern *patterns; - UINT pattern_count=0, patterns_size=0; + BitmapDecoderInfo *This = impl_from_IWICBitmapDecoderInfo(iface); HRESULT hr; UINT i; ULONG pos; @@ -552,22 +485,13 @@ static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *if 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; ipattern_count; i++) { - if (datasize < patterns[i].Length) + if (datasize < This->patterns[i].Length) { HeapFree(GetProcessHeap(), 0, data); - datasize = patterns[i].Length; - data = HeapAlloc(GetProcessHeap(), 0, patterns[i].Length); + datasize = This->patterns[i].Length; + data = HeapAlloc(GetProcessHeap(), 0, This->patterns[i].Length); if (!data) { hr = E_OUTOFMEMORY; @@ -575,25 +499,25 @@ static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *if } } - if (patterns[i].EndOfStream) - seekpos.QuadPart = -patterns[i].Position.QuadPart; + if (This->patterns[i].EndOfStream) + seekpos.QuadPart = -This->patterns[i].Position.QuadPart; else - seekpos.QuadPart = patterns[i].Position.QuadPart; - hr = IStream_Seek(pIStream, seekpos, patterns[i].EndOfStream ? STREAM_SEEK_END : STREAM_SEEK_SET, NULL); + seekpos.QuadPart = This->patterns[i].Position.QuadPart; + hr = IStream_Seek(pIStream, seekpos, This->patterns[i].EndOfStream ? STREAM_SEEK_END : STREAM_SEEK_SET, NULL); if (hr == STG_E_INVALIDFUNCTION) continue; /* before start of stream */ if (FAILED(hr)) break; - hr = IStream_Read(pIStream, data, patterns[i].Length, &bytesread); - if (hr == S_FALSE || (hr == S_OK && bytesread != patterns[i].Length)) /* past end of stream */ + hr = IStream_Read(pIStream, data, This->patterns[i].Length, &bytesread); + if (hr == S_FALSE || (hr == S_OK && bytesread != This->patterns[i].Length)) /* past end of stream */ continue; if (FAILED(hr)) break; - for (pos=0; pospatterns[i].Length; pos++) { - if ((data[pos] & patterns[i].Mask[pos]) != patterns[i].Pattern[pos]) + if ((data[pos] & This->patterns[i].Mask[pos]) != This->patterns[i].Pattern[pos]) break; } - if (pos == patterns[i].Length) /* matches pattern */ + if (pos == This->patterns[i].Length) /* matches pattern */ { hr = S_OK; *pfMatches = TRUE; @@ -601,16 +525,13 @@ static HRESULT WINAPI BitmapDecoderInfo_MatchesPattern(IWICBitmapDecoderInfo *if } } - if (i == pattern_count) /* does not match any pattern */ + if (i == This->pattern_count) /* does not match any pattern */ { hr = S_OK; *pfMatches = FALSE; } -end: - HeapFree(GetProcessHeap(), 0, patterns); HeapFree(GetProcessHeap(), 0, data); - return hr; } @@ -621,7 +542,7 @@ static HRESULT WINAPI BitmapDecoderInfo_CreateInstance(IWICBitmapDecoderInfo *if TRACE("(%p,%p)\n", iface, ppIBitmapDecoder); - return create_instance(&This->clsid, &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder); + return create_instance(&This->base.clsid, &IID_IWICBitmapDecoder, (void**)ppIBitmapDecoder); } static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = { @@ -653,36 +574,146 @@ static const IWICBitmapDecoderInfoVtbl BitmapDecoderInfo_Vtbl = { BitmapDecoderInfo_CreateInstance }; -static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo) +static void read_bitmap_patterns(BitmapDecoderInfo *info) +{ + 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}; + UINT i; + WICBitmapPattern *patterns; + BYTE *patterns_ptr; + DWORD length, valuesize; + + res = RegOpenKeyExW(info->classkey, patternsW, 0, KEY_READ, &patternskey); + if (res != ERROR_SUCCESS) return; + + res = RegQueryInfoKeyW(patternskey, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS) + { + RegCloseKey(patternskey); + return; + } + + patterns_size = pattern_count * sizeof(WICBitmapPattern); + patterns = heap_alloc(patterns_size); + if (!patterns) + { + RegCloseKey(patternskey); + return; + } + + for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++) + { + snprintfW(subkeyname, 11, uintformatW, i); + res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey); + if (res != ERROR_SUCCESS) break; + + valuesize = sizeof(ULONG); + res = RegGetValueW(patternkey, NULL, lengthW, RRF_RT_DWORD, NULL, &length, &valuesize); + if (res == ERROR_SUCCESS) + { + patterns_size += length*2; + patterns[i].Length = length; + + valuesize = sizeof(BOOL); + res = RegGetValueW(patternkey, NULL, endofstreamW, RRF_RT_DWORD, NULL, + &patterns[i].EndOfStream, &valuesize); + if (res) patterns[i].EndOfStream = 0; + + patterns[i].Position.QuadPart = 0; + valuesize = sizeof(ULARGE_INTEGER); + res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL, + &patterns[i].Position, &valuesize); + } + + RegCloseKey(patternkey); + } + + if (res != ERROR_SUCCESS || !(patterns_ptr = heap_realloc(patterns, patterns_size))) + { + heap_free(patterns); + RegCloseKey(patternskey); + return; + } + patterns = (WICBitmapPattern*)patterns_ptr; + patterns_ptr += pattern_count * sizeof(*patterns); + + for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++) + { + snprintfW(subkeyname, 11, uintformatW, i); + res = RegOpenKeyExW(patternskey, subkeyname, 0, KEY_READ, &patternkey); + if (res != ERROR_SUCCESS) break; + + length = patterns[i].Length; + patterns[i].Pattern = patterns_ptr; + valuesize = length; + res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL, + patterns[i].Pattern, &valuesize); + patterns_ptr += length; + + if (res == ERROR_SUCCESS) + { + patterns[i].Mask = patterns_ptr; + valuesize = length; + res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL, + patterns[i].Mask, &valuesize); + patterns_ptr += length; + } + + RegCloseKey(patternkey); + } + + RegCloseKey(patternskey); + + if (res != ERROR_SUCCESS) + { + heap_free(patterns); + return; + } + + info->pattern_count = pattern_count; + info->patterns_size = patterns_size; + info->patterns = patterns; +} + +static HRESULT BitmapDecoderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret) { BitmapDecoderInfo *This; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapDecoderInfo)); + This = heap_alloc_zero(sizeof(BitmapDecoderInfo)); if (!This) { RegCloseKey(classkey); return E_OUTOFMEMORY; } - This->IWICBitmapDecoderInfo_iface.lpVtbl = &BitmapDecoderInfo_Vtbl; - This->ref = 1; + This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&BitmapDecoderInfo_Vtbl; + This->base.ref = 1; This->classkey = classkey; - memcpy(&This->clsid, clsid, sizeof(CLSID)); + This->base.clsid = *clsid; + + read_bitmap_patterns(This); - *ppIInfo = (IWICComponentInfo *)&This->IWICBitmapDecoderInfo_iface; + *ret = &This->base; return S_OK; } typedef struct { - IWICBitmapEncoderInfo IWICBitmapEncoderInfo_iface; - LONG ref; + ComponentInfo base; HKEY classkey; - CLSID clsid; } BitmapEncoderInfo; static inline BitmapEncoderInfo *impl_from_IWICBitmapEncoderInfo(IWICBitmapEncoderInfo *iface) { - return CONTAINING_RECORD(iface, BitmapEncoderInfo, IWICBitmapEncoderInfo_iface); + return CONTAINING_RECORD(iface, BitmapEncoderInfo, base.IWICComponentInfo_iface); } static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *iface, REFIID iid, @@ -698,7 +729,7 @@ static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *if IsEqualIID(&IID_IWICBitmapCodecInfo, iid) || IsEqualIID(&IID_IWICBitmapEncoderInfo ,iid)) { - *ppv = &This->IWICBitmapEncoderInfo_iface; + *ppv = &This->base.IWICComponentInfo_iface; } else { @@ -713,7 +744,7 @@ static HRESULT WINAPI BitmapEncoderInfo_QueryInterface(IWICBitmapEncoderInfo *if static ULONG WINAPI BitmapEncoderInfo_AddRef(IWICBitmapEncoderInfo *iface) { BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface); - ULONG ref = InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); @@ -723,7 +754,7 @@ static ULONG WINAPI BitmapEncoderInfo_AddRef(IWICBitmapEncoderInfo *iface) static ULONG WINAPI BitmapEncoderInfo_Release(IWICBitmapEncoderInfo *iface) { BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface); - ULONG ref = InterlockedDecrement(&This->ref); + ULONG ref = InterlockedDecrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); @@ -753,8 +784,7 @@ static HRESULT WINAPI BitmapEncoderInfo_GetCLSID(IWICBitmapEncoderInfo *iface, C if (!pclsid) return E_INVALIDARG; - memcpy(pclsid, &This->clsid, sizeof(CLSID)); - + *pclsid = This->base.clsid; return S_OK; } @@ -918,7 +948,7 @@ static HRESULT WINAPI BitmapEncoderInfo_CreateInstance(IWICBitmapEncoderInfo *if TRACE("(%p,%p)\n", iface, ppIBitmapEncoder); - return create_instance(&This->clsid, &IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder); + return create_instance(&This->base.clsid, &IID_IWICBitmapEncoder, (void**)ppIBitmapEncoder); } static const IWICBitmapEncoderInfoVtbl BitmapEncoderInfo_Vtbl = { @@ -948,7 +978,7 @@ static const IWICBitmapEncoderInfoVtbl BitmapEncoderInfo_Vtbl = { BitmapEncoderInfo_CreateInstance }; -static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo) +static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret) { BitmapEncoderInfo *This; @@ -959,25 +989,23 @@ static HRESULT BitmapEncoderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWIC return E_OUTOFMEMORY; } - This->IWICBitmapEncoderInfo_iface.lpVtbl = &BitmapEncoderInfo_Vtbl; - This->ref = 1; + This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&BitmapEncoderInfo_Vtbl; + This->base.ref = 1; This->classkey = classkey; - memcpy(&This->clsid, clsid, sizeof(CLSID)); + This->base.clsid = *clsid; - *ppIInfo = (IWICComponentInfo *)&This->IWICBitmapEncoderInfo_iface; + *ret = &This->base; return S_OK; } typedef struct { - IWICFormatConverterInfo IWICFormatConverterInfo_iface; - LONG ref; + ComponentInfo base; HKEY classkey; - CLSID clsid; } FormatConverterInfo; static inline FormatConverterInfo *impl_from_IWICFormatConverterInfo(IWICFormatConverterInfo *iface) { - return CONTAINING_RECORD(iface, FormatConverterInfo, IWICFormatConverterInfo_iface); + return CONTAINING_RECORD(iface, FormatConverterInfo, base.IWICComponentInfo_iface); } static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo *iface, REFIID iid, @@ -992,7 +1020,7 @@ static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo IsEqualIID(&IID_IWICComponentInfo, iid) || IsEqualIID(&IID_IWICFormatConverterInfo ,iid)) { - *ppv = &This->IWICFormatConverterInfo_iface; + *ppv = &This->base.IWICComponentInfo_iface; } else { @@ -1007,7 +1035,7 @@ static HRESULT WINAPI FormatConverterInfo_QueryInterface(IWICFormatConverterInfo static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface) { FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface); - ULONG ref = InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); @@ -1017,7 +1045,7 @@ static ULONG WINAPI FormatConverterInfo_AddRef(IWICFormatConverterInfo *iface) static ULONG WINAPI FormatConverterInfo_Release(IWICFormatConverterInfo *iface) { FormatConverterInfo *This = impl_from_IWICFormatConverterInfo(iface); - ULONG ref = InterlockedDecrement(&This->ref); + ULONG ref = InterlockedDecrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); @@ -1047,8 +1075,7 @@ static HRESULT WINAPI FormatConverterInfo_GetCLSID(IWICFormatConverterInfo *ifac if (!pclsid) return E_INVALIDARG; - memcpy(pclsid, &This->clsid, sizeof(CLSID)); - + *pclsid = This->base.clsid; return S_OK; } @@ -1125,7 +1152,7 @@ static HRESULT WINAPI FormatConverterInfo_CreateInstance(IWICFormatConverterInfo TRACE("(%p,%p)\n", iface, ppIFormatConverter); - return create_instance(&This->clsid, &IID_IWICFormatConverter, + return create_instance(&This->base.clsid, &IID_IWICFormatConverter, (void**)ppIFormatConverter); } @@ -1165,7 +1192,7 @@ static const IWICFormatConverterInfoVtbl FormatConverterInfo_Vtbl = { FormatConverterInfo_CreateInstance }; -static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo) +static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret) { FormatConverterInfo *This; @@ -1176,25 +1203,23 @@ static HRESULT FormatConverterInfo_Constructor(HKEY classkey, REFCLSID clsid, IW return E_OUTOFMEMORY; } - This->IWICFormatConverterInfo_iface.lpVtbl = &FormatConverterInfo_Vtbl; - This->ref = 1; + This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&FormatConverterInfo_Vtbl; + This->base.ref = 1; This->classkey = classkey; - memcpy(&This->clsid, clsid, sizeof(CLSID)); + This->base.clsid = *clsid; - *ppIInfo = (IWICComponentInfo *)&This->IWICFormatConverterInfo_iface; + *ret = &This->base; return S_OK; } typedef struct { - IWICPixelFormatInfo2 IWICPixelFormatInfo2_iface; - LONG ref; + ComponentInfo base; HKEY classkey; - CLSID clsid; } PixelFormatInfo; static inline PixelFormatInfo *impl_from_IWICPixelFormatInfo2(IWICPixelFormatInfo2 *iface) { - return CONTAINING_RECORD(iface, PixelFormatInfo, IWICPixelFormatInfo2_iface); + return CONTAINING_RECORD(iface, PixelFormatInfo, base.IWICComponentInfo_iface); } static HRESULT WINAPI PixelFormatInfo_QueryInterface(IWICPixelFormatInfo2 *iface, REFIID iid, @@ -1210,7 +1235,7 @@ static HRESULT WINAPI PixelFormatInfo_QueryInterface(IWICPixelFormatInfo2 *iface IsEqualIID(&IID_IWICPixelFormatInfo, iid) || IsEqualIID(&IID_IWICPixelFormatInfo2 ,iid)) { - *ppv = &This->IWICPixelFormatInfo2_iface; + *ppv = &This->base.IWICComponentInfo_iface; } else { @@ -1225,7 +1250,7 @@ static HRESULT WINAPI PixelFormatInfo_QueryInterface(IWICPixelFormatInfo2 *iface static ULONG WINAPI PixelFormatInfo_AddRef(IWICPixelFormatInfo2 *iface) { PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface); - ULONG ref = InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); @@ -1235,7 +1260,7 @@ static ULONG WINAPI PixelFormatInfo_AddRef(IWICPixelFormatInfo2 *iface) static ULONG WINAPI PixelFormatInfo_Release(IWICPixelFormatInfo2 *iface) { PixelFormatInfo *This = impl_from_IWICPixelFormatInfo2(iface); - ULONG ref = InterlockedDecrement(&This->ref); + ULONG ref = InterlockedDecrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); @@ -1265,8 +1290,7 @@ static HRESULT WINAPI PixelFormatInfo_GetCLSID(IWICPixelFormatInfo2 *iface, CLSI if (!pclsid) return E_INVALIDARG; - memcpy(pclsid, &This->clsid, sizeof(CLSID)); - + *pclsid = This->base.clsid; return S_OK; } @@ -1345,8 +1369,7 @@ static HRESULT WINAPI PixelFormatInfo_GetFormatGUID(IWICPixelFormatInfo2 *iface, if (!pFormat) return E_INVALIDARG; - *pFormat = This->clsid; - + *pFormat = This->base.clsid; return S_OK; } @@ -1459,7 +1482,7 @@ static const IWICPixelFormatInfo2Vtbl PixelFormatInfo_Vtbl = { PixelFormatInfo_GetNumericRepresentation }; -static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **ppIInfo) +static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **ret) { PixelFormatInfo *This; @@ -1470,26 +1493,45 @@ static HRESULT PixelFormatInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICCo return E_OUTOFMEMORY; } - This->IWICPixelFormatInfo2_iface.lpVtbl = &PixelFormatInfo_Vtbl; - This->ref = 1; + This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&PixelFormatInfo_Vtbl; + This->base.ref = 1; This->classkey = classkey; - memcpy(&This->clsid, clsid, sizeof(CLSID)); + This->base.clsid = *clsid; - *ppIInfo = (IWICComponentInfo *)&This->IWICPixelFormatInfo2_iface; + *ret = &This->base; return S_OK; } +struct metadata_container +{ + WICMetadataPattern *patterns; + UINT pattern_count; + UINT patterns_size; +}; + typedef struct { - IWICMetadataReaderInfo IWICMetadataReaderInfo_iface; - LONG ref; + ComponentInfo base; HKEY classkey; - CLSID clsid; + GUID *container_formats; + struct metadata_container *containers; + UINT container_count; } MetadataReaderInfo; +static struct metadata_container *get_metadata_container(MetadataReaderInfo *info, const GUID *guid) +{ + unsigned i; + + for (i = 0; i < info->container_count; i++) + if (IsEqualGUID(info->container_formats + i, guid)) + return info->containers + i; + + return NULL; +} + static inline MetadataReaderInfo *impl_from_IWICMetadataReaderInfo(IWICMetadataReaderInfo *iface) { - return CONTAINING_RECORD(iface, MetadataReaderInfo, IWICMetadataReaderInfo_iface); + return CONTAINING_RECORD(iface, MetadataReaderInfo, base.IWICComponentInfo_iface); } static HRESULT WINAPI MetadataReaderInfo_QueryInterface(IWICMetadataReaderInfo *iface, @@ -1506,7 +1548,7 @@ static HRESULT WINAPI MetadataReaderInfo_QueryInterface(IWICMetadataReaderInfo * IsEqualIID(&IID_IWICMetadataHandlerInfo, riid) || IsEqualIID(&IID_IWICMetadataReaderInfo, riid)) { - *ppv = &This->IWICMetadataReaderInfo_iface; + *ppv = &This->base.IWICComponentInfo_iface; } else { @@ -1521,7 +1563,7 @@ static HRESULT WINAPI MetadataReaderInfo_QueryInterface(IWICMetadataReaderInfo * static ULONG WINAPI MetadataReaderInfo_AddRef(IWICMetadataReaderInfo *iface) { MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface); - ULONG ref = InterlockedIncrement(&This->ref); + ULONG ref = InterlockedIncrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); return ref; @@ -1530,13 +1572,18 @@ static ULONG WINAPI MetadataReaderInfo_AddRef(IWICMetadataReaderInfo *iface) static ULONG WINAPI MetadataReaderInfo_Release(IWICMetadataReaderInfo *iface) { MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface); - ULONG ref = InterlockedDecrement(&This->ref); + ULONG ref = InterlockedDecrement(&This->base.ref); TRACE("(%p) refcount=%u\n", iface, ref); if (!ref) { + unsigned i; RegCloseKey(This->classkey); + for (i = 0; i < This->container_count; i++) + heap_free(This->containers[i].patterns); + heap_free(This->containers); + heap_free(This->container_formats); HeapFree(GetProcessHeap(), 0, This); } return ref; @@ -1560,7 +1607,7 @@ static HRESULT WINAPI MetadataReaderInfo_GetCLSID(IWICMetadataReaderInfo *iface, TRACE("(%p,%p)\n", iface, clsid); if (!clsid) return E_INVALIDARG; - *clsid = This->clsid; + *clsid = This->base.clsid; return S_OK; } @@ -1637,10 +1684,20 @@ static HRESULT WINAPI MetadataReaderInfo_GetContainerFormats(IWICMetadataReaderI UINT length, GUID *formats, UINT *actual_length) { MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface); + TRACE("(%p,%u,%p,%p)\n", iface, length, formats, actual_length); - return ComponentInfo_GetGuidList(This->classkey, containers_keyname, length, - formats, actual_length); + if (!actual_length) + return E_INVALIDARG; + + *actual_length = This->container_count; + if (formats) + { + if (This->container_count && length < This->container_count) + return WINCODEC_ERR_INSUFFICIENTBUFFER; + memcpy(formats, This->container_formats, This->container_count); + } + return S_OK; } static HRESULT WINAPI MetadataReaderInfo_GetDeviceManufacturer(IWICMetadataReaderInfo *iface, @@ -1681,122 +1738,35 @@ static HRESULT WINAPI MetadataReaderInfo_DoesRequireFixedSize(IWICMetadataReader } static HRESULT WINAPI MetadataReaderInfo_GetPatterns(IWICMetadataReaderInfo *iface, - REFGUID container, UINT length, WICMetadataPattern *patterns, UINT *count, UINT *actual_length) + REFGUID container_guid, UINT length, WICMetadataPattern *patterns, UINT *count, UINT *actual_length) { MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface); - HRESULT hr=S_OK; - LONG res; - UINT pattern_count=0, patterns_size=0; - DWORD valuesize, patternsize; - BYTE *bPatterns=(BYTE*)patterns; - HKEY containers_key, guid_key, pattern_key; - WCHAR subkeyname[11]; - WCHAR guidkeyname[39]; - int i; - static const WCHAR uintformatW[] = {'%','u',0}; - static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0}; - static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0}; - static const WCHAR maskW[] = {'M','a','s','k',0}; - static const WCHAR dataoffsetW[] = {'D','a','t','a','O','f','f','s','e','t',0}; - - TRACE("(%p,%s,%u,%p,%p,%p)\n", iface, debugstr_guid(container), length, patterns, count, actual_length); + struct metadata_container *container; - if (!actual_length || !container) return E_INVALIDARG; - - res = RegOpenKeyExW(This->classkey, containers_keyname, 0, KEY_READ, &containers_key); - if (res == ERROR_SUCCESS) - { - StringFromGUID2(container, guidkeyname, 39); - - res = RegOpenKeyExW(containers_key, guidkeyname, 0, KEY_READ, &guid_key); - if (res == ERROR_FILE_NOT_FOUND) hr = WINCODEC_ERR_COMPONENTNOTFOUND; - else if (res != ERROR_SUCCESS) hr = HRESULT_FROM_WIN32(res); - - RegCloseKey(containers_key); - } - else if (res == ERROR_FILE_NOT_FOUND) hr = WINCODEC_ERR_COMPONENTNOTFOUND; - else hr = HRESULT_FROM_WIN32(res); - - if (SUCCEEDED(hr)) - { - res = RegQueryInfoKeyW(guid_key, NULL, NULL, NULL, &pattern_count, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS) hr = HRESULT_FROM_WIN32(res); - - if (SUCCEEDED(hr)) - { - patterns_size = pattern_count * sizeof(WICMetadataPattern); + TRACE("(%p,%s,%u,%p,%p,%p)\n", iface, debugstr_guid(container_guid), length, patterns, count, actual_length); - for (i=0; i= patterns_size) && (res == ERROR_SUCCESS)) - { - patterns[i].Length = patternsize; - - patterns[i].DataOffset.QuadPart = 0; - valuesize = sizeof(ULARGE_INTEGER); - RegGetValueW(pattern_key, NULL, dataoffsetW, RRF_RT_DWORD|RRF_RT_QWORD, NULL, - &patterns[i].DataOffset, &valuesize); - - patterns[i].Position.QuadPart = 0; - valuesize = sizeof(ULARGE_INTEGER); - res = RegGetValueW(pattern_key, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL, - &patterns[i].Position, &valuesize); - - if (res == ERROR_SUCCESS) - { - patterns[i].Pattern = bPatterns+patterns_size-patternsize*2; - valuesize = patternsize; - res = RegGetValueW(pattern_key, NULL, patternW, RRF_RT_REG_BINARY, NULL, - patterns[i].Pattern, &valuesize); - } - - if (res == ERROR_SUCCESS) - { - patterns[i].Mask = bPatterns+patterns_size-patternsize; - valuesize = patternsize; - res = RegGetValueW(pattern_key, NULL, maskW, RRF_RT_REG_BINARY, NULL, - patterns[i].Mask, &valuesize); - } - } - - RegCloseKey(pattern_key); - } - if (res != ERROR_SUCCESS) - { - hr = HRESULT_FROM_WIN32(res); - break; - } - } - } + if (!actual_length || !container_guid) return E_INVALIDARG; - RegCloseKey(guid_key); - } + if (!(container = get_metadata_container(This, container_guid))) + return WINCODEC_ERR_COMPONENTNOTFOUND; - if (hr == S_OK) + *count = container->pattern_count; + *actual_length = container->patterns_size; + if (patterns) { - *count = pattern_count; - *actual_length = patterns_size; - if (patterns && length < patterns_size) - hr = WINCODEC_ERR_INSUFFICIENTBUFFER; + if (container->patterns_size && length < container->patterns_size) + return WINCODEC_ERR_INSUFFICIENTBUFFER; + memcpy(patterns, container->patterns, container->patterns_size); } - - return hr; + return S_OK; } static HRESULT WINAPI MetadataReaderInfo_MatchesPattern(IWICMetadataReaderInfo *iface, - REFGUID container, IStream *stream, BOOL *matches) + REFGUID container_guid, IStream *stream, BOOL *matches) { + MetadataReaderInfo *This = impl_from_IWICMetadataReaderInfo(iface); + struct metadata_container *container; HRESULT hr; - WICMetadataPattern *patterns; - UINT pattern_count=0, patterns_size=0; ULONG datasize=0; BYTE *data=NULL; ULONG bytesread; @@ -1804,24 +1774,18 @@ static HRESULT WINAPI MetadataReaderInfo_MatchesPattern(IWICMetadataReaderInfo * LARGE_INTEGER seekpos; ULONG pos; - TRACE("(%p,%s,%p,%p)\n", iface, debugstr_guid(container), stream, matches); + TRACE("(%p,%s,%p,%p)\n", iface, debugstr_guid(container_guid), stream, matches); - hr = MetadataReaderInfo_GetPatterns(iface, container, 0, NULL, &pattern_count, &patterns_size); - if (FAILED(hr)) return hr; - - patterns = HeapAlloc(GetProcessHeap(), 0, patterns_size); - if (!patterns) return E_OUTOFMEMORY; - - hr = MetadataReaderInfo_GetPatterns(iface, container, patterns_size, patterns, &pattern_count, &patterns_size); - if (FAILED(hr)) goto end; + if (!(container = get_metadata_container(This, container_guid))) + return WINCODEC_ERR_COMPONENTNOTFOUND; - for (i=0; ipattern_count; i++) { - if (datasize < patterns[i].Length) + if (datasize < container->patterns[i].Length) { HeapFree(GetProcessHeap(), 0, data); - datasize = patterns[i].Length; - data = HeapAlloc(GetProcessHeap(), 0, patterns[i].Length); + datasize = container->patterns[i].Length; + data = HeapAlloc(GetProcessHeap(), 0, container->patterns[i].Length); if (!data) { hr = E_OUTOFMEMORY; @@ -1829,21 +1793,21 @@ static HRESULT WINAPI MetadataReaderInfo_MatchesPattern(IWICMetadataReaderInfo * } } - seekpos.QuadPart = patterns[i].Position.QuadPart; + seekpos.QuadPart = container->patterns[i].Position.QuadPart; hr = IStream_Seek(stream, seekpos, STREAM_SEEK_SET, NULL); if (FAILED(hr)) break; - hr = IStream_Read(stream, data, patterns[i].Length, &bytesread); - if (hr == S_FALSE || (hr == S_OK && bytesread != patterns[i].Length)) /* past end of stream */ + hr = IStream_Read(stream, data, container->patterns[i].Length, &bytesread); + if (hr == S_FALSE || (hr == S_OK && bytesread != container->patterns[i].Length)) /* past end of stream */ continue; if (FAILED(hr)) break; - for (pos=0; pospatterns[i].Length; pos++) { - if ((data[pos] & patterns[i].Mask[pos]) != patterns[i].Pattern[pos]) + if ((data[pos] & container->patterns[i].Mask[pos]) != container->patterns[i].Pattern[pos]) break; } - if (pos == patterns[i].Length) /* matches pattern */ + if (pos == container->patterns[i].Length) /* matches pattern */ { hr = S_OK; *matches = TRUE; @@ -1851,14 +1815,12 @@ static HRESULT WINAPI MetadataReaderInfo_MatchesPattern(IWICMetadataReaderInfo * } } - if (i == pattern_count) /* does not match any pattern */ + if (i == container->pattern_count) /* does not match any pattern */ { hr = S_OK; *matches = FALSE; } -end: - HeapFree(GetProcessHeap(), 0, patterns); HeapFree(GetProcessHeap(), 0, data); return hr; @@ -1871,7 +1833,7 @@ static HRESULT WINAPI MetadataReaderInfo_CreateInstance(IWICMetadataReaderInfo * TRACE("(%p,%p)\n", iface, reader); - return create_instance(&This->clsid, &IID_IWICMetadataReader, (void **)reader); + return create_instance(&This->base.clsid, &IID_IWICMetadataReader, (void **)reader); } static const IWICMetadataReaderInfoVtbl MetadataReaderInfo_Vtbl = { @@ -1898,23 +1860,180 @@ static const IWICMetadataReaderInfoVtbl MetadataReaderInfo_Vtbl = { MetadataReaderInfo_CreateInstance }; -static HRESULT MetadataReaderInfo_Constructor(HKEY classkey, REFCLSID clsid, IWICComponentInfo **info) +static void read_metadata_patterns(MetadataReaderInfo *info, GUID *container_guid, + struct metadata_container *container) +{ + UINT pattern_count=0, patterns_size=0; + WCHAR subkeyname[11], guidkeyname[39]; + LONG res; + HKEY containers_key, guid_key, patternkey; + static const WCHAR uintformatW[] = {'%','u',0}; + static const WCHAR patternW[] = {'P','a','t','t','e','r','n',0}; + static const WCHAR positionW[] = {'P','o','s','i','t','i','o','n',0}; + static const WCHAR maskW[] = {'M','a','s','k',0}; + static const WCHAR dataoffsetW[] = {'D','a','t','a','O','f','f','s','e','t',0}; + UINT i; + WICMetadataPattern *patterns; + BYTE *patterns_ptr; + DWORD length, valuesize; + + res = RegOpenKeyExW(info->classkey, containers_keyname, 0, KEY_READ, &containers_key); + if (res != ERROR_SUCCESS) return; + + StringFromGUID2(container_guid, guidkeyname, 39); + res = RegOpenKeyExW(containers_key, guidkeyname, 0, KEY_READ, &guid_key); + RegCloseKey(containers_key); + if (res != ERROR_SUCCESS) return; + + res = RegQueryInfoKeyW(guid_key, NULL, NULL, NULL, &pattern_count, + NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS) + { + RegCloseKey(guid_key); + return; + } + + patterns_size = pattern_count * sizeof(WICMetadataPattern); + patterns = heap_alloc(patterns_size); + if (!patterns) + { + RegCloseKey(guid_key); + return; + } + + for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++) + { + snprintfW(subkeyname, 11, uintformatW, i); + res = RegOpenKeyExW(guid_key, subkeyname, 0, KEY_READ, &patternkey); + if (res != ERROR_SUCCESS) break; + + res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL, NULL, &length); + if (res == ERROR_SUCCESS) + { + patterns_size += length*2; + patterns[i].Length = length; + + valuesize = sizeof(DWORD64); + res = RegGetValueW(patternkey, NULL, dataoffsetW, RRF_RT_DWORD|RRF_RT_QWORD, NULL, + &patterns[i].DataOffset, &valuesize); + if (res) patterns[i].DataOffset.QuadPart = 0; + + patterns[i].Position.QuadPart = 0; + valuesize = sizeof(DWORD64); + res = RegGetValueW(patternkey, NULL, positionW, RRF_RT_DWORD|RRF_RT_QWORD, NULL, + &patterns[i].Position, &valuesize); + } + + RegCloseKey(patternkey); + } + + if (res != ERROR_SUCCESS || !(patterns_ptr = heap_realloc(patterns, patterns_size))) + { + heap_free(patterns); + RegCloseKey(guid_key); + return; + } + patterns = (WICMetadataPattern*)patterns_ptr; + patterns_ptr += pattern_count * sizeof(*patterns); + + for (i=0; res == ERROR_SUCCESS && i < pattern_count; i++) + { + snprintfW(subkeyname, 11, uintformatW, i); + res = RegOpenKeyExW(guid_key, subkeyname, 0, KEY_READ, &patternkey); + if (res != ERROR_SUCCESS) break; + + length = patterns[i].Length; + patterns[i].Pattern = patterns_ptr; + valuesize = length; + res = RegGetValueW(patternkey, NULL, patternW, RRF_RT_REG_BINARY, NULL, + patterns[i].Pattern, &valuesize); + patterns_ptr += length; + + if (res == ERROR_SUCCESS) + { + patterns[i].Mask = patterns_ptr; + valuesize = length; + res = RegGetValueW(patternkey, NULL, maskW, RRF_RT_REG_BINARY, NULL, + patterns[i].Mask, &valuesize); + patterns_ptr += length; + } + + RegCloseKey(patternkey); + } + + RegCloseKey(guid_key); + + if (res != ERROR_SUCCESS) + { + heap_free(patterns); + return; + } + + container->pattern_count = pattern_count; + container->patterns_size = patterns_size; + container->patterns = patterns; +} + +static BOOL read_metadata_info(MetadataReaderInfo *info) +{ + UINT format_count; + GUID *formats; + HRESULT hr; + + hr = ComponentInfo_GetGuidList(info->classkey, containers_keyname, 0, NULL, &format_count); + if (FAILED(hr)) return TRUE; + + formats = heap_calloc(format_count, sizeof(*formats)); + if (!formats) return FALSE; + + hr = ComponentInfo_GetGuidList(info->classkey, containers_keyname, format_count, formats, + &format_count); + if (FAILED(hr)) + { + heap_free(formats); + return FALSE; + } + + info->container_formats = formats; + info->container_count = format_count; + + if (format_count) + { + unsigned i; + + info->containers = heap_calloc(format_count, sizeof(*info->containers)); + if (!info->containers) return FALSE; + + for (i = 0; i < format_count; i++) + read_metadata_patterns(info, info->container_formats + i, info->containers + i); + } + + return TRUE; +} + +static HRESULT MetadataReaderInfo_Constructor(HKEY classkey, REFCLSID clsid, ComponentInfo **info) { MetadataReaderInfo *This; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + This = heap_alloc_zero(sizeof(*This)); if (!This) { RegCloseKey(classkey); return E_OUTOFMEMORY; } - This->IWICMetadataReaderInfo_iface.lpVtbl = &MetadataReaderInfo_Vtbl; - This->ref = 1; + This->base.IWICComponentInfo_iface.lpVtbl = (const IWICComponentInfoVtbl*)&MetadataReaderInfo_Vtbl; + This->base.ref = 1; This->classkey = classkey; - This->clsid = *clsid; + This->base.clsid = *clsid; + + if (!read_metadata_info(This)) + { + IWICComponentInfo_Release(&This->base.IWICComponentInfo_iface); + return WINCODEC_ERR_COMPONENTNOTFOUND; + } - *info = (IWICComponentInfo *)&This->IWICMetadataReaderInfo_iface; + *info = &This->base; return S_OK; } @@ -1924,7 +2043,7 @@ static const WCHAR instance_keyname[] = {'I','n','s','t','a','n','c','e',0}; struct category { WICComponentType type; const GUID *catid; - HRESULT (*constructor)(HKEY,REFCLSID,IWICComponentInfo**); + HRESULT (*constructor)(HKEY,REFCLSID,ComponentInfo**); }; static const struct category categories[] = { @@ -1936,8 +2055,27 @@ static const struct category categories[] = { {0} }; +static int ComponentInfo_Compare(const void *key, const struct wine_rb_entry *entry) +{ + ComponentInfo *info = WINE_RB_ENTRY_VALUE(entry, ComponentInfo, entry); + return memcmp(key, &info->clsid, sizeof(info->clsid)); +} + +static struct wine_rb_tree component_info_cache = { ComponentInfo_Compare }; + +static CRITICAL_SECTION component_info_cache_cs; +static CRITICAL_SECTION_DEBUG component_info_cache_cs_dbg = +{ + 0, 0, &component_info_cache_cs, + { &component_info_cache_cs_dbg.ProcessLocksList, &component_info_cache_cs_dbg.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": component_info_cache") } +}; +static CRITICAL_SECTION component_info_cache_cs = { &component_info_cache_cs_dbg, -1, 0, 0, 0, 0 }; + HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) { + struct wine_rb_entry *cache_entry; + ComponentInfo *info; HKEY clsidkey; HKEY classkey; HKEY catidkey; @@ -1948,9 +2086,23 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) BOOL found = FALSE; HRESULT hr; + EnterCriticalSection(&component_info_cache_cs); + + cache_entry = wine_rb_get(&component_info_cache, clsid); + if(cache_entry) + { + info = WINE_RB_ENTRY_VALUE(cache_entry, ComponentInfo, entry); + IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface); + LeaveCriticalSection(&component_info_cache_cs); + return S_OK; + } + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, KEY_READ, &clsidkey); if (res != ERROR_SUCCESS) + { + LeaveCriticalSection(&component_info_cache_cs); return HRESULT_FROM_WIN32(res); + } for (category=categories; category->type; category++) { @@ -1979,7 +2131,7 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) { res = RegOpenKeyExW(clsidkey, guidstring, 0, KEY_READ, &classkey); if (res == ERROR_SUCCESS) - hr = category->constructor(classkey, clsid, ppIInfo); + hr = category->constructor(classkey, clsid, &info); else hr = HRESULT_FROM_WIN32(res); } @@ -1991,6 +2143,35 @@ HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) RegCloseKey(clsidkey); + if (SUCCEEDED(hr)) + { + wine_rb_put(&component_info_cache, clsid, &info->entry); + IWICComponentInfo_AddRef(*ppIInfo = &info->IWICComponentInfo_iface); + } + LeaveCriticalSection(&component_info_cache_cs); + return hr; +} + +void ReleaseComponentInfos(void) +{ + ComponentInfo *info, *next_info; + WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(info, next_info, &component_info_cache, ComponentInfo, entry) + IWICComponentInfo_Release(&info->IWICComponentInfo_iface); +} + +HRESULT get_decoder_info(const CLSID *clsid, IWICBitmapDecoderInfo **info) +{ + IWICComponentInfo *compinfo; + HRESULT hr; + + hr = CreateComponentInfo(clsid, &compinfo); + if (FAILED(hr)) return hr; + + hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo, + (void **)info); + + IWICComponentInfo_Release(compinfo); + return hr; } diff --git a/dll/win32/windowscodecs/jpegformat.c b/dll/win32/windowscodecs/jpegformat.c index 0069bdfd899..26dc76c7724 100644 --- a/dll/win32/windowscodecs/jpegformat.c +++ b/dll/win32/windowscodecs/jpegformat.c @@ -50,6 +50,7 @@ #include "wincodecs_private.h" +#include "wine/heap.h" #include "wine/debug.h" #include "wine/library.h" @@ -155,6 +156,7 @@ typedef struct { struct jpeg_error_mgr jerr; struct jpeg_source_mgr source_mgr; BYTE source_buffer[1024]; + UINT bpp, stride; BYTE *image_data; CRITICAL_SECTION lock; } JpegDecoder; @@ -303,6 +305,8 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream * int ret; LARGE_INTEGER seek; jmp_buf jmpbuf; + UINT data_size, i; + TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions); EnterCriticalSection(&This->lock); @@ -381,6 +385,55 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream * return E_FAIL; } + if (This->cinfo.out_color_space == JCS_GRAYSCALE) This->bpp = 8; + else if (This->cinfo.out_color_space == JCS_CMYK) This->bpp = 32; + else This->bpp = 24; + + This->stride = (This->bpp * This->cinfo.output_width + 7) / 8; + data_size = This->stride * This->cinfo.output_height; + + This->image_data = heap_alloc(data_size); + if (!This->image_data) + { + LeaveCriticalSection(&This->lock); + return E_OUTOFMEMORY; + } + + while (This->cinfo.output_scanline < This->cinfo.output_height) + { + UINT first_scanline = This->cinfo.output_scanline; + UINT max_rows; + JSAMPROW out_rows[4]; + JDIMENSION ret; + + max_rows = min(This->cinfo.output_height-first_scanline, 4); + for (i=0; iimage_data + This->stride * (first_scanline+i); + + ret = pjpeg_read_scanlines(&This->cinfo, out_rows, max_rows); + if (ret == 0) + { + ERR("read_scanlines failed\n"); + LeaveCriticalSection(&This->lock); + return E_FAIL; + } + } + + if (This->bpp == 24) + { + /* libjpeg gives us RGB data and we want BGR, so byteswap the data */ + reverse_bgr8(3, This->image_data, + This->cinfo.output_width, This->cinfo.output_height, + This->stride); + } + + if (This->cinfo.out_color_space == JCS_CMYK && This->cinfo.saw_Adobe_marker) + { + /* Adobe JPEG's have inverted CMYK data. */ + for (i=0; iimage_data[i] ^= 0xff; + } + This->initialized = TRUE; LeaveCriticalSection(&This->lock); @@ -398,20 +451,9 @@ static HRESULT WINAPI JpegDecoder_GetContainerFormat(IWICBitmapDecoder *iface, static HRESULT WINAPI JpegDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **ppIDecoderInfo) { - HRESULT hr; - IWICComponentInfo *compinfo; - TRACE("(%p,%p)\n", iface, ppIDecoderInfo); - hr = CreateComponentInfo(&CLSID_WICJpegDecoder, &compinfo); - if (FAILED(hr)) return hr; - - hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo, - (void**)ppIDecoderInfo); - - IWICComponentInfo_Release(compinfo); - - return hr; + return get_decoder_info(&CLSID_WICJpegDecoder, ppIDecoderInfo); } static HRESULT WINAPI JpegDecoder_CopyPalette(IWICBitmapDecoder *iface, @@ -601,104 +643,11 @@ static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) { JpegDecoder *This = impl_from_IWICBitmapFrameDecode(iface); - UINT bpp; - UINT stride; - UINT data_size; - UINT max_row_needed; - jmp_buf jmpbuf; - WICRect rect; - TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer); - - if (!prc) - { - rect.X = 0; - rect.Y = 0; - rect.Width = This->cinfo.output_width; - rect.Height = This->cinfo.output_height; - prc = ▭ - } - else - { - if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->cinfo.output_width || - prc->Y+prc->Height > This->cinfo.output_height) - return E_INVALIDARG; - } - - if (This->cinfo.out_color_space == JCS_GRAYSCALE) bpp = 8; - else if (This->cinfo.out_color_space == JCS_CMYK) bpp = 32; - else bpp = 24; - - stride = bpp * This->cinfo.output_width; - data_size = stride * This->cinfo.output_height; - max_row_needed = prc->Y + prc->Height; - if (max_row_needed > This->cinfo.output_height) return E_INVALIDARG; - - EnterCriticalSection(&This->lock); - - if (!This->image_data) - { - This->image_data = HeapAlloc(GetProcessHeap(), 0, data_size); - if (!This->image_data) - { - LeaveCriticalSection(&This->lock); - return E_OUTOFMEMORY; - } - } - - This->cinfo.client_data = jmpbuf; - - if (setjmp(jmpbuf)) - { - LeaveCriticalSection(&This->lock); - return E_FAIL; - } - - while (max_row_needed > This->cinfo.output_scanline) - { - UINT first_scanline = This->cinfo.output_scanline; - UINT max_rows; - JSAMPROW out_rows[4]; - UINT i; - JDIMENSION ret; - - max_rows = min(This->cinfo.output_height-first_scanline, 4); - for (i=0; iimage_data + stride * (first_scanline+i); - - ret = pjpeg_read_scanlines(&This->cinfo, out_rows, max_rows); - - if (ret == 0) - { - ERR("read_scanlines failed\n"); - LeaveCriticalSection(&This->lock); - return E_FAIL; - } - - if (bpp == 24) - { - /* libjpeg gives us RGB data and we want BGR, so byteswap the data */ - reverse_bgr8(3, This->image_data + stride * first_scanline, - This->cinfo.output_width, This->cinfo.output_scanline - first_scanline, - stride); - } - - if (This->cinfo.out_color_space == JCS_CMYK && This->cinfo.saw_Adobe_marker) - { - DWORD *pDwordData = (DWORD*) (This->image_data + stride * first_scanline); - DWORD *pDwordDataEnd = (DWORD*) (This->image_data + This->cinfo.output_scanline * stride); - - /* Adobe JPEG's have inverted CMYK data. */ - while(pDwordData < pDwordDataEnd) - *pDwordData++ ^= 0xffffffff; - } - - } - - LeaveCriticalSection(&This->lock); + TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer); - return copy_pixels(bpp, This->image_data, - This->cinfo.output_width, This->cinfo.output_height, stride, + return copy_pixels(This->bpp, This->image_data, + This->cinfo.output_width, This->cinfo.output_height, This->stride, prc, cbStride, cbBufferSize, pbBuffer); } diff --git a/dll/win32/windowscodecs/main.c b/dll/win32/windowscodecs/main.c index 3bed56536c2..6f781b812bf 100644 --- a/dll/win32/windowscodecs/main.c +++ b/dll/win32/windowscodecs/main.c @@ -42,6 +42,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); break; + case DLL_PROCESS_DETACH: + ReleaseComponentInfos(); + break; } return WIC_DllMain(hinstDLL, fdwReason, lpvReserved); diff --git a/dll/win32/windowscodecs/pngformat.c b/dll/win32/windowscodecs/pngformat.c index 54be5edb45d..42c905cdaca 100644 --- a/dll/win32/windowscodecs/pngformat.c +++ b/dll/win32/windowscodecs/pngformat.c @@ -829,20 +829,9 @@ static HRESULT WINAPI PngDecoder_GetContainerFormat(IWICBitmapDecoder *iface, static HRESULT WINAPI PngDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **ppIDecoderInfo) { - HRESULT hr; - IWICComponentInfo *compinfo; - TRACE("(%p,%p)\n", iface, ppIDecoderInfo); - hr = CreateComponentInfo(&CLSID_WICPngDecoder, &compinfo); - if (FAILED(hr)) return hr; - - hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo, - (void**)ppIDecoderInfo); - - IWICComponentInfo_Release(compinfo); - - return hr; + return get_decoder_info(&CLSID_WICPngDecoder, ppIDecoderInfo); } static HRESULT WINAPI PngDecoder_CopyPalette(IWICBitmapDecoder *iface, diff --git a/dll/win32/windowscodecs/precomp.h b/dll/win32/windowscodecs/precomp.h index 7f4c241216d..144e085e442 100644 --- a/dll/win32/windowscodecs/precomp.h +++ b/dll/win32/windowscodecs/precomp.h @@ -25,6 +25,7 @@ #include "wincodecs_private.h" #include +#include #include #endif /* !WINCODECS_PRECOMP_H */ diff --git a/dll/win32/windowscodecs/tgaformat.c b/dll/win32/windowscodecs/tgaformat.c index ec7fa23169b..b3d9aeae265 100644 --- a/dll/win32/windowscodecs/tgaformat.c +++ b/dll/win32/windowscodecs/tgaformat.c @@ -360,20 +360,9 @@ static HRESULT WINAPI TgaDecoder_GetContainerFormat(IWICBitmapDecoder *iface, static HRESULT WINAPI TgaDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **ppIDecoderInfo) { - HRESULT hr; - IWICComponentInfo *compinfo; - TRACE("(%p,%p)\n", iface, ppIDecoderInfo); - hr = CreateComponentInfo(&CLSID_WineTgaDecoder, &compinfo); - if (FAILED(hr)) return hr; - - hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo, - (void**)ppIDecoderInfo); - - IWICComponentInfo_Release(compinfo); - - return hr; + return get_decoder_info(&CLSID_WineTgaDecoder, ppIDecoderInfo); } static HRESULT WINAPI TgaDecoder_CopyPalette(IWICBitmapDecoder *iface, diff --git a/dll/win32/windowscodecs/tiffformat.c b/dll/win32/windowscodecs/tiffformat.c index c23594f61f0..d1ee44087ff 100644 --- a/dll/win32/windowscodecs/tiffformat.c +++ b/dll/win32/windowscodecs/tiffformat.c @@ -738,20 +738,9 @@ static HRESULT WINAPI TiffDecoder_GetContainerFormat(IWICBitmapDecoder *iface, static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **ppIDecoderInfo) { - HRESULT hr; - IWICComponentInfo *compinfo; - TRACE("(%p,%p)\n", iface, ppIDecoderInfo); - hr = CreateComponentInfo(&CLSID_WICTiffDecoder, &compinfo); - if (FAILED(hr)) return hr; - - hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo, - (void**)ppIDecoderInfo); - - IWICComponentInfo_Release(compinfo); - - return hr; + return get_decoder_info(&CLSID_WICTiffDecoder, ppIDecoderInfo); } static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface, diff --git a/dll/win32/windowscodecs/wincodecs_private.h b/dll/win32/windowscodecs/wincodecs_private.h index 2f9f6d0b583..264520492ca 100644 --- a/dll/win32/windowscodecs/wincodecs_private.h +++ b/dll/win32/windowscodecs/wincodecs_private.h @@ -155,7 +155,7 @@ extern HRESULT IcnsEncoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDE extern HRESULT TgaDecoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN; extern HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, - UINT stride, UINT datasize, BYTE *bits, + UINT stride, UINT datasize, void *view, UINT offset, REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option, IWICBitmap **ppIBitmap) DECLSPEC_HIDDEN; extern HRESULT BitmapScaler_Create(IWICBitmapScaler **scaler) DECLSPEC_HIDDEN; @@ -188,7 +188,9 @@ extern HRESULT CreatePropertyBag2(const PROPBAG2 *options, UINT count, IPropertyBag2 **property) DECLSPEC_HIDDEN; extern HRESULT CreateComponentInfo(REFCLSID clsid, IWICComponentInfo **ppIInfo) DECLSPEC_HIDDEN; +extern void ReleaseComponentInfos(void) DECLSPEC_HIDDEN; extern HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown) DECLSPEC_HIDDEN; +extern HRESULT get_decoder_info(REFCLSID clsid, IWICBitmapDecoderInfo **info) DECLSPEC_HIDDEN; typedef struct BmpDecoder BmpDecoder; diff --git a/media/doc/README.WINE b/media/doc/README.WINE index b3042fd1fb5..f78e35a3ba5 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -196,7 +196,7 @@ reactos/dll/win32/version # Synced to WineStaging-3.9 reactos/dll/win32/vssapi # Synced to WineStaging-2.9 reactos/dll/win32/wbemdisp # Synced to WineStaging-3.3 reactos/dll/win32/wbemprox # Synced to WineStaging-3.9 -reactos/dll/win32/windowscodecs # Synced to WineStaging-3.3 +reactos/dll/win32/windowscodecs # Synced to WineStaging-3.9 reactos/dll/win32/windowscodecsext # Synced to WineStaging-2.9 reactos/dll/win32/winemp3.acm # Synced to WineStaging-3.3 reactos/dll/win32/wing32 # Synced to WineStaging-3.3 -- 2.17.1