diff --git a/dlls/windowscodecs/icoformat.c b/dlls/windowscodecs/icoformat.c index e26de5fe34..6f9113729a 100644 --- a/dlls/windowscodecs/icoformat.c +++ b/dlls/windowscodecs/icoformat.c @@ -63,6 +63,133 @@ typedef struct { ICONHEADER header; } IcoDecoder; +typedef struct { + const IWICBitmapFrameDecodeVtbl *lpVtbl; + LONG ref; + ICONDIRENTRY entry; + IcoDecoder *parent; +} 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); + } + + return ref; +} + +static HRESULT WINAPI IcoFrameDecode_GetSize(IWICBitmapFrameDecode *iface, + UINT *puiWidth, UINT *puiHeight) +{ + FIXME("(%p,%p,%p): stub\n", iface, puiWidth, puiHeight); + return E_NOTIMPL; +} + +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 HRESULT WINAPI IcoFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, + const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) +{ + FIXME("(%p,%p,%u,%u,%p): stub\n", iface, prc, cbStride, cbBufferSize, pbBuffer); + return E_NOTIMPL; +} + +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) { @@ -198,15 +325,57 @@ static HRESULT WINAPI IcoDecoder_GetThumbnail(IWICBitmapDecoder *iface, static HRESULT WINAPI IcoDecoder_GetFrameCount(IWICBitmapDecoder *iface, UINT *pCount) { - FIXME("(%p,%p): stub\n", iface, pCount); - return E_NOTIMPL; + 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) { - FIXME("(%p,%u,%p): stub\n", iface, index, ppIBitmapFrame); - return E_NOTIMPL; + 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; + + /* 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 = {