2 * Copyright 2009 Vincent Povirk for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wincodecs_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
57 IWICBitmapDecoder IWICBitmapDecoder_iface
;
62 CRITICAL_SECTION lock
; /* must be held when accessing stream */
66 IWICBitmapFrameDecode IWICBitmapFrameDecode_iface
;
73 static inline IcoDecoder
*impl_from_IWICBitmapDecoder(IWICBitmapDecoder
*iface
)
75 return CONTAINING_RECORD(iface
, IcoDecoder
, IWICBitmapDecoder_iface
);
78 static inline IcoFrameDecode
*impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode
*iface
)
80 return CONTAINING_RECORD(iface
, IcoFrameDecode
, IWICBitmapFrameDecode_iface
);
83 static HRESULT WINAPI
IcoFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
86 IcoFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
87 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
89 if (!ppv
) return E_INVALIDARG
;
91 if (IsEqualIID(&IID_IUnknown
, iid
) ||
92 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
93 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
))
95 *ppv
= &This
->IWICBitmapFrameDecode_iface
;
100 return E_NOINTERFACE
;
103 IUnknown_AddRef((IUnknown
*)*ppv
);
107 static ULONG WINAPI
IcoFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
109 IcoFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
110 ULONG ref
= InterlockedIncrement(&This
->ref
);
112 TRACE("(%p) refcount=%u\n", iface
, ref
);
117 static ULONG WINAPI
IcoFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
119 IcoFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
120 ULONG ref
= InterlockedDecrement(&This
->ref
);
122 TRACE("(%p) refcount=%u\n", iface
, ref
);
126 HeapFree(GetProcessHeap(), 0, This
->bits
);
127 HeapFree(GetProcessHeap(), 0, This
);
133 static HRESULT WINAPI
IcoFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
,
134 UINT
*puiWidth
, UINT
*puiHeight
)
136 IcoFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
138 *puiWidth
= This
->width
;
139 *puiHeight
= This
->height
;
141 TRACE("(%p) -> (%i,%i)\n", iface
, *puiWidth
, *puiHeight
);
146 static HRESULT WINAPI
IcoFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
147 WICPixelFormatGUID
*pPixelFormat
)
149 memcpy(pPixelFormat
, &GUID_WICPixelFormat32bppBGRA
, sizeof(GUID
));
153 static HRESULT WINAPI
IcoFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
,
154 double *pDpiX
, double *pDpiY
)
156 IcoFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
161 TRACE("(%p) -> (%f,%f)\n", iface
, *pDpiX
, *pDpiY
);
166 static HRESULT WINAPI
IcoFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
,
167 IWICPalette
*pIPalette
)
169 TRACE("(%p,%p)\n", iface
, pIPalette
);
170 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
173 static HRESULT WINAPI
IcoFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
,
174 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
176 IcoFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
177 TRACE("(%p,%s,%u,%u,%p)\n", iface
, debug_wic_rect(prc
), cbStride
, cbBufferSize
, pbBuffer
);
179 return copy_pixels(32, This
->bits
, This
->width
, This
->height
, This
->width
* 4,
180 prc
, cbStride
, cbBufferSize
, pbBuffer
);
183 static HRESULT WINAPI
IcoFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
184 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
186 TRACE("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
187 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
190 static HRESULT WINAPI
IcoFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
,
191 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
193 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
194 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
197 static HRESULT WINAPI
IcoFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
,
198 IWICBitmapSource
**ppIThumbnail
)
200 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
201 return IWICBitmapFrameDecode_QueryInterface(iface
, &IID_IWICBitmapSource
, (void **)ppIThumbnail
);
204 static const IWICBitmapFrameDecodeVtbl IcoFrameDecode_Vtbl
= {
205 IcoFrameDecode_QueryInterface
,
206 IcoFrameDecode_AddRef
,
207 IcoFrameDecode_Release
,
208 IcoFrameDecode_GetSize
,
209 IcoFrameDecode_GetPixelFormat
,
210 IcoFrameDecode_GetResolution
,
211 IcoFrameDecode_CopyPalette
,
212 IcoFrameDecode_CopyPixels
,
213 IcoFrameDecode_GetMetadataQueryReader
,
214 IcoFrameDecode_GetColorContexts
,
215 IcoFrameDecode_GetThumbnail
218 static inline void pixel_set_trans(DWORD
* pixel
, BOOL transparent
)
220 if (transparent
) *pixel
= 0;
221 else *pixel
|= 0xff000000;
224 static HRESULT
ReadIcoDib(IStream
*stream
, IcoFrameDecode
*result
)
227 BmpDecoder
*bmp_decoder
;
228 IWICBitmapDecoder
*decoder
;
229 IWICBitmapFrameDecode
*framedecode
;
230 WICPixelFormatGUID pixelformat
;
231 IWICBitmapSource
*source
;
232 BOOL has_alpha
=FALSE
; /* if TRUE, alpha data might be in the image data */
235 hr
= IcoDibDecoder_CreateInstance(&bmp_decoder
);
238 BmpDecoder_GetWICDecoder(bmp_decoder
, &decoder
);
239 hr
= IWICBitmapDecoder_Initialize(decoder
, stream
, WICDecodeMetadataCacheOnLoad
);
242 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
246 hr
= IWICBitmapFrameDecode_GetSize(framedecode
, &result
->width
, &result
->height
);
250 result
->bits
= HeapAlloc(GetProcessHeap(), 0, result
->width
* result
->height
* 4);
251 if (!result
->bits
) hr
= E_OUTOFMEMORY
;
255 hr
= IWICBitmapFrameDecode_GetPixelFormat(framedecode
, &pixelformat
);
257 if (IsEqualGUID(&pixelformat
, &GUID_WICPixelFormat32bppBGR
) ||
258 IsEqualGUID(&pixelformat
, &GUID_WICPixelFormat32bppBGRA
))
260 source
= (IWICBitmapSource
*)framedecode
;
261 IWICBitmapSource_AddRef(source
);
266 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
,
267 (IWICBitmapSource
*)framedecode
, &source
);
275 rc
.Width
= result
->width
;
276 rc
.Height
= result
->height
;
277 hr
= IWICBitmapSource_CopyPixels(source
, &rc
, result
->width
* 4,
278 result
->width
* result
->height
* 4, result
->bits
);
280 IWICBitmapSource_Release(source
);
284 hr
= IWICBitmapFrameDecode_GetResolution(framedecode
, &result
->dpiX
, &result
->dpiY
);
286 IWICBitmapFrameDecode_Release(framedecode
);
289 if (SUCCEEDED(hr
) && has_alpha
)
291 /* If the alpha channel is fully transparent, we should ignore it. */
292 int nonzero_alpha
= 0;
295 for (i
=0; i
<(result
->height
*result
->width
); i
++)
297 if (result
->bits
[i
*4+3] != 0)
306 for (i
=0; i
<(result
->height
*result
->width
); i
++)
307 result
->bits
[i
*4+3] = 0xff;
313 if (SUCCEEDED(hr
) && !has_alpha
)
315 /* set alpha data based on the AND mask */
316 UINT andBytesPerRow
= (result
->width
+31)/32*4;
317 UINT andBytes
= andBytesPerRow
* result
->height
;
322 UINT bitsStride
= result
->width
* 4;
329 BmpDecoder_FindIconMask(bmp_decoder
, &offset
, &topdown
);
333 seek
.QuadPart
= offset
;
335 hr
= IStream_Seek(stream
, seek
, STREAM_SEEK_SET
, 0);
339 tempdata
= HeapAlloc(GetProcessHeap(), 0, andBytes
);
340 if (!tempdata
) hr
= E_OUTOFMEMORY
;
344 hr
= IStream_Read(stream
, tempdata
, andBytes
, &bytesread
);
346 if (SUCCEEDED(hr
) && bytesread
== andBytes
)
350 andStride
= andBytesPerRow
;
355 andStride
= -andBytesPerRow
;
356 andRow
= tempdata
+ (result
->height
-1)*andBytesPerRow
;
359 bitsRow
= result
->bits
;
360 for (y
=0; y
<result
->height
; y
++) {
361 BYTE
*andByte
=andRow
;
362 DWORD
*bitsPixel
=(DWORD
*)bitsRow
;
363 for (x
=0; x
<result
->width
; x
+=8) {
364 BYTE andVal
=*andByte
++;
365 pixel_set_trans(bitsPixel
++, andVal
>>7&1);
366 if (x
+1 < result
->width
) pixel_set_trans(bitsPixel
++, andVal
>>6&1);
367 if (x
+2 < result
->width
) pixel_set_trans(bitsPixel
++, andVal
>>5&1);
368 if (x
+3 < result
->width
) pixel_set_trans(bitsPixel
++, andVal
>>4&1);
369 if (x
+4 < result
->width
) pixel_set_trans(bitsPixel
++, andVal
>>3&1);
370 if (x
+5 < result
->width
) pixel_set_trans(bitsPixel
++, andVal
>>2&1);
371 if (x
+6 < result
->width
) pixel_set_trans(bitsPixel
++, andVal
>>1&1);
372 if (x
+7 < result
->width
) pixel_set_trans(bitsPixel
++, andVal
&1);
375 bitsRow
+= bitsStride
;
379 HeapFree(GetProcessHeap(), 0, tempdata
);
383 IWICBitmapDecoder_Release(decoder
);
389 static HRESULT
ReadIcoPng(IStream
*stream
, IcoFrameDecode
*result
)
391 IWICBitmapDecoder
*decoder
= NULL
;
392 IWICBitmapFrameDecode
*sourceFrame
= NULL
;
393 IWICBitmapSource
*sourceBitmap
= NULL
;
397 hr
= PngDecoder_CreateInstance(&IID_IWICBitmapDecoder
, (void**)&decoder
);
400 hr
= IWICBitmapDecoder_Initialize(decoder
, stream
, WICDecodeMetadataCacheOnLoad
);
403 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &sourceFrame
);
406 hr
= WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA
, (IWICBitmapSource
*)sourceFrame
, &sourceBitmap
);
409 hr
= IWICBitmapFrameDecode_GetSize(sourceFrame
, &result
->width
, &result
->height
);
412 hr
= IWICBitmapFrameDecode_GetResolution(sourceFrame
, &result
->dpiX
, &result
->dpiY
);
415 result
->bits
= HeapAlloc(GetProcessHeap(), 0, 4 * result
->width
* result
->height
);
416 if (result
->bits
== NULL
)
423 rect
.Width
= result
->width
;
424 rect
.Height
= result
->height
;
425 hr
= IWICBitmapSource_CopyPixels(sourceBitmap
, &rect
, 4*result
->width
,
426 4*result
->width
*result
->height
, result
->bits
);
430 IWICBitmapDecoder_Release(decoder
);
431 if (sourceFrame
!= NULL
)
432 IWICBitmapFrameDecode_Release(sourceFrame
);
433 if (sourceBitmap
!= NULL
)
434 IWICBitmapSource_Release(sourceBitmap
);
438 static HRESULT WINAPI
IcoDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
441 IcoDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
442 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
444 if (!ppv
) return E_INVALIDARG
;
446 if (IsEqualIID(&IID_IUnknown
, iid
) ||
447 IsEqualIID(&IID_IWICBitmapDecoder
, iid
))
449 *ppv
= &This
->IWICBitmapDecoder_iface
;
454 return E_NOINTERFACE
;
457 IUnknown_AddRef((IUnknown
*)*ppv
);
461 static ULONG WINAPI
IcoDecoder_AddRef(IWICBitmapDecoder
*iface
)
463 IcoDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
464 ULONG ref
= InterlockedIncrement(&This
->ref
);
466 TRACE("(%p) refcount=%u\n", iface
, ref
);
471 static ULONG WINAPI
IcoDecoder_Release(IWICBitmapDecoder
*iface
)
473 IcoDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
474 ULONG ref
= InterlockedDecrement(&This
->ref
);
476 TRACE("(%p) refcount=%u\n", iface
, ref
);
480 This
->lock
.DebugInfo
->Spare
[0] = 0;
481 DeleteCriticalSection(&This
->lock
);
482 if (This
->stream
) IStream_Release(This
->stream
);
483 HeapFree(GetProcessHeap(), 0, This
);
489 static HRESULT WINAPI
IcoDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*stream
,
494 TRACE("(%p,%p,%p)\n", iface
, stream
, capability
);
496 if (!stream
|| !capability
) return E_INVALIDARG
;
498 hr
= IWICBitmapDecoder_Initialize(iface
, stream
, WICDecodeMetadataCacheOnDemand
);
499 if (hr
!= S_OK
) return hr
;
501 *capability
= WICBitmapDecoderCapabilityCanDecodeAllImages
;
505 static HRESULT WINAPI
IcoDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
506 WICDecodeOptions cacheOptions
)
508 IcoDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
515 TRACE("(%p,%p,%x)\n", iface
, pIStream
, cacheOptions
);
517 EnterCriticalSection(&This
->lock
);
519 if (This
->initialized
)
521 hr
= WINCODEC_ERR_WRONGSTATE
;
526 hr
= IStream_Seek(pIStream
, seek
, STREAM_SEEK_SET
, NULL
);
527 if (FAILED(hr
)) goto end
;
529 hr
= IStream_Read(pIStream
, &This
->header
, sizeof(ICONHEADER
), &bytesread
);
530 if (FAILED(hr
)) goto end
;
532 if (bytesread
!= sizeof(ICONHEADER
))
534 hr
= WINCODEC_ERR_STREAMREAD
;
538 if (This
->header
.idReserved
!= 0 ||
539 This
->header
.idType
!= 1)
545 hr
= IStream_Stat(pIStream
, &statstg
, STATFLAG_NONAME
);
548 WARN("Stat() failed, hr %#x.\n", hr
);
552 for (i
= 0; i
< This
->header
.idCount
; i
++)
554 ICONDIRENTRY direntry
;
556 hr
= IStream_Read(pIStream
, &direntry
, sizeof(direntry
), &bytesread
);
557 if (FAILED(hr
)) goto end
;
559 if (bytesread
!= sizeof(direntry
) || (direntry
.dwDIBSize
+ direntry
.dwDIBOffset
> statstg
.cbSize
.QuadPart
))
561 hr
= WINCODEC_ERR_BADIMAGE
;
566 This
->initialized
= TRUE
;
567 This
->stream
= pIStream
;
568 IStream_AddRef(pIStream
);
572 LeaveCriticalSection(&This
->lock
);
577 static HRESULT WINAPI
IcoDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
578 GUID
*pguidContainerFormat
)
580 memcpy(pguidContainerFormat
, &GUID_ContainerFormatIco
, sizeof(GUID
));
584 static HRESULT WINAPI
IcoDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
585 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
587 TRACE("(%p,%p)\n", iface
, ppIDecoderInfo
);
589 return get_decoder_info(&CLSID_WICIcoDecoder
, ppIDecoderInfo
);
592 static HRESULT WINAPI
IcoDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
593 IWICPalette
*pIPalette
)
595 TRACE("(%p,%p)\n", iface
, pIPalette
);
596 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
599 static HRESULT WINAPI
IcoDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
600 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
602 TRACE("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
603 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
606 static HRESULT WINAPI
IcoDecoder_GetPreview(IWICBitmapDecoder
*iface
,
607 IWICBitmapSource
**ppIBitmapSource
)
609 TRACE("(%p,%p)\n", iface
, ppIBitmapSource
);
610 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
613 static HRESULT WINAPI
IcoDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
614 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
616 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
617 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
620 static HRESULT WINAPI
IcoDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
621 IWICBitmapSource
**ppIThumbnail
)
623 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
624 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
627 static HRESULT WINAPI
IcoDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
630 IcoDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
632 if (!pCount
) return E_INVALIDARG
;
634 EnterCriticalSection(&This
->lock
);
635 *pCount
= This
->initialized
? This
->header
.idCount
: 0;
636 LeaveCriticalSection(&This
->lock
);
638 TRACE("(%p) <-- %d\n", iface
, *pCount
);
643 static HRESULT WINAPI
IcoDecoder_GetFrame(IWICBitmapDecoder
*iface
,
644 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
646 IcoDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
647 IcoFrameDecode
*result
=NULL
;
649 ULARGE_INTEGER offset
, length
;
653 IWICStream
*substream
=NULL
;
655 TRACE("(%p,%u,%p)\n", iface
, index
, ppIBitmapFrame
);
657 EnterCriticalSection(&This
->lock
);
659 if (!This
->initialized
)
661 hr
= WINCODEC_ERR_FRAMEMISSING
;
665 if (This
->header
.idCount
< index
)
671 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(IcoFrameDecode
));
678 result
->IWICBitmapFrameDecode_iface
.lpVtbl
= &IcoFrameDecode_Vtbl
;
682 /* read the icon entry */
683 seek
.QuadPart
= sizeof(ICONHEADER
) + sizeof(ICONDIRENTRY
) * index
;
684 hr
= IStream_Seek(This
->stream
, seek
, STREAM_SEEK_SET
, 0);
685 if (FAILED(hr
)) goto fail
;
687 hr
= IStream_Read(This
->stream
, &entry
, sizeof(ICONDIRENTRY
), &bytesread
);
688 if (FAILED(hr
) || bytesread
!= sizeof(ICONDIRENTRY
)) goto fail
;
690 /* create a stream object for this icon */
691 hr
= StreamImpl_Create(&substream
);
692 if (FAILED(hr
)) goto fail
;
694 offset
.QuadPart
= entry
.dwDIBOffset
;
695 length
.QuadPart
= entry
.dwDIBSize
;
696 hr
= IWICStream_InitializeFromIStreamRegion(substream
, This
->stream
, offset
, length
);
697 if (FAILED(hr
)) goto fail
;
699 /* read the bitmapinfo size or magic number */
700 hr
= IWICStream_Read(substream
, &magic
, sizeof(magic
), &bytesread
);
701 if (FAILED(hr
) || bytesread
!= sizeof(magic
)) goto fail
;
703 /* forward to the appropriate decoding function based on the magic number */
706 case sizeof(BITMAPCOREHEADER
):
707 case 64: /* sizeof(BITMAPCOREHEADER2) */
708 case sizeof(BITMAPINFOHEADER
):
709 case sizeof(BITMAPV4HEADER
):
710 case sizeof(BITMAPV5HEADER
):
711 hr
= ReadIcoDib((IStream
*)substream
, result
);
714 hr
= ReadIcoPng((IStream
*)substream
, result
);
717 FIXME("Unrecognized ICO frame magic: %x\n", magic
);
721 if (FAILED(hr
)) goto fail
;
723 *ppIBitmapFrame
= &result
->IWICBitmapFrameDecode_iface
;
725 LeaveCriticalSection(&This
->lock
);
727 IWICStream_Release(substream
);
732 LeaveCriticalSection(&This
->lock
);
733 HeapFree(GetProcessHeap(), 0, result
);
734 if (substream
) IWICStream_Release(substream
);
735 if (SUCCEEDED(hr
)) hr
= E_FAIL
;
736 TRACE("<-- %x\n", hr
);
740 static const IWICBitmapDecoderVtbl IcoDecoder_Vtbl
= {
741 IcoDecoder_QueryInterface
,
744 IcoDecoder_QueryCapability
,
745 IcoDecoder_Initialize
,
746 IcoDecoder_GetContainerFormat
,
747 IcoDecoder_GetDecoderInfo
,
748 IcoDecoder_CopyPalette
,
749 IcoDecoder_GetMetadataQueryReader
,
750 IcoDecoder_GetPreview
,
751 IcoDecoder_GetColorContexts
,
752 IcoDecoder_GetThumbnail
,
753 IcoDecoder_GetFrameCount
,
757 HRESULT
IcoDecoder_CreateInstance(REFIID iid
, void** ppv
)
762 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
766 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IcoDecoder
));
767 if (!This
) return E_OUTOFMEMORY
;
769 This
->IWICBitmapDecoder_iface
.lpVtbl
= &IcoDecoder_Vtbl
;
772 This
->initialized
= FALSE
;
773 InitializeCriticalSection(&This
->lock
);
774 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IcoDecoder.lock");
776 ret
= IWICBitmapDecoder_QueryInterface(&This
->IWICBitmapDecoder_iface
, iid
, ppv
);
777 IWICBitmapDecoder_Release(&This
->IWICBitmapDecoder_iface
);