| /* |
| * 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 <stdarg.h> |
| |
| #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; |
| } |