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
31 #include "wincodecs_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
60 const IWICBitmapDecoderVtbl
*lpVtbl
;
68 const IWICBitmapFrameDecodeVtbl
*lpVtbl
;
75 static HRESULT WINAPI
IcoFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
78 IcoFrameDecode
*This
= (IcoFrameDecode
*)iface
;
79 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
81 if (!ppv
) return E_INVALIDARG
;
83 if (IsEqualIID(&IID_IUnknown
, iid
) ||
84 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
85 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
))
95 IUnknown_AddRef((IUnknown
*)*ppv
);
99 static ULONG WINAPI
IcoFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
101 IcoFrameDecode
*This
= (IcoFrameDecode
*)iface
;
102 ULONG ref
= InterlockedIncrement(&This
->ref
);
104 TRACE("(%p) refcount=%u\n", iface
, ref
);
109 static ULONG WINAPI
IcoFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
111 IcoFrameDecode
*This
= (IcoFrameDecode
*)iface
;
112 ULONG ref
= InterlockedDecrement(&This
->ref
);
114 TRACE("(%p) refcount=%u\n", iface
, ref
);
118 IUnknown_Release((IUnknown
*)This
->parent
);
119 HeapFree(GetProcessHeap(), 0, This
->bits
);
120 HeapFree(GetProcessHeap(), 0, This
);
126 static HRESULT WINAPI
IcoFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
,
127 UINT
*puiWidth
, UINT
*puiHeight
)
129 IcoFrameDecode
*This
= (IcoFrameDecode
*)iface
;
131 *puiWidth
= This
->entry
.bWidth
? This
->entry
.bWidth
: 256;
132 *puiHeight
= This
->entry
.bHeight
? This
->entry
.bHeight
: 256;
134 TRACE("(%p) -> (%i,%i)\n", iface
, *puiWidth
, *puiHeight
);
139 static HRESULT WINAPI
IcoFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
140 WICPixelFormatGUID
*pPixelFormat
)
142 memcpy(pPixelFormat
, &GUID_WICPixelFormat32bppBGRA
, sizeof(GUID
));
146 static HRESULT WINAPI
IcoFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
,
147 double *pDpiX
, double *pDpiY
)
149 FIXME("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
153 static HRESULT WINAPI
IcoFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
,
154 IWICPalette
*pIPalette
)
156 TRACE("(%p,%p)\n", iface
, pIPalette
);
157 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
160 static inline void pixel_set_trans(DWORD
* pixel
, BOOL transparent
)
162 if (transparent
) *pixel
= 0;
163 else *pixel
|= 0xff000000;
166 static HRESULT
IcoFrameDecode_ReadPixels(IcoFrameDecode
*This
)
168 BITMAPINFOHEADER bih
;
174 BYTE
*tempdata
= NULL
;
180 width
= This
->entry
.bWidth
? This
->entry
.bWidth
: 256;
181 height
= This
->entry
.bHeight
? This
->entry
.bHeight
: 256;
183 /* read the BITMAPINFOHEADER */
184 seek
.QuadPart
= This
->entry
.dwDIBOffset
;
185 hr
= IStream_Seek(This
->parent
->stream
, seek
, STREAM_SEEK_SET
, NULL
);
186 if (FAILED(hr
)) goto fail
;
188 hr
= IStream_Read(This
->parent
->stream
, &bih
, sizeof(BITMAPINFOHEADER
), &bytesread
);
189 if (FAILED(hr
) || bytesread
!= sizeof(BITMAPINFOHEADER
)) goto fail
;
191 if (This
->entry
.wBitCount
<= 8)
193 /* read the palette */
194 colorcount
= This
->entry
.bColorCount
? This
->entry
.bColorCount
: 256;
196 hr
= IStream_Read(This
->parent
->stream
, colors
, sizeof(RGBQUAD
)*colorcount
, &bytesread
);
197 if (FAILED(hr
) || bytesread
!= sizeof(RGBQUAD
)*colorcount
) goto fail
;
200 bitsStride
= width
* 4;
201 bitsSize
= bitsStride
* height
;
203 /* read the XOR data */
204 switch (This
->entry
.wBitCount
)
208 UINT xorBytesPerRow
= (width
+31)/32*4;
209 UINT xorBytes
= xorBytesPerRow
* height
;
215 tempdata
= HeapAlloc(GetProcessHeap(), 0, xorBytes
);
222 hr
= IStream_Read(This
->parent
->stream
, tempdata
, xorBytes
, &bytesread
);
223 if (FAILED(hr
) || bytesread
!= xorBytes
) goto fail
;
225 if (bih
.biHeight
> 0) /* bottom-up DIB */
227 xorStride
= -xorBytesPerRow
;
228 xorRow
= tempdata
+ (height
-1)*xorBytesPerRow
;
230 else /* top-down DIB */
232 xorStride
= xorBytesPerRow
;
236 bits
= HeapAlloc(GetProcessHeap(), 0, bitsSize
);
238 /* palette-map the 1-bit data */
240 for (y
=0; y
<height
; y
++) {
241 BYTE
*xorByte
=xorRow
;
242 DWORD
*bitsPixel
=(DWORD
*)bitsRow
;
243 for (x
=0; x
<width
; x
+=8) {
246 *bitsPixel
++ = colors
[xorVal
>>7];
247 if (x
+1 < width
) *bitsPixel
++ = colors
[xorVal
>>6&1];
248 if (x
+2 < width
) *bitsPixel
++ = colors
[xorVal
>>5&1];
249 if (x
+3 < width
) *bitsPixel
++ = colors
[xorVal
>>4&1];
250 if (x
+4 < width
) *bitsPixel
++ = colors
[xorVal
>>3&1];
251 if (x
+5 < width
) *bitsPixel
++ = colors
[xorVal
>>2&1];
252 if (x
+6 < width
) *bitsPixel
++ = colors
[xorVal
>>1&1];
253 if (x
+7 < width
) *bitsPixel
++ = colors
[xorVal
&1];
256 bitsRow
+= bitsStride
;
259 HeapFree(GetProcessHeap(), 0, tempdata
);
264 UINT xorBytesPerRow
= (width
+7)/8*4;
265 UINT xorBytes
= xorBytesPerRow
* height
;
271 tempdata
= HeapAlloc(GetProcessHeap(), 0, xorBytes
);
278 hr
= IStream_Read(This
->parent
->stream
, tempdata
, xorBytes
, &bytesread
);
279 if (FAILED(hr
) || bytesread
!= xorBytes
) goto fail
;
281 if (bih
.biHeight
> 0) /* bottom-up DIB */
283 xorStride
= -xorBytesPerRow
;
284 xorRow
= tempdata
+ (height
-1)*xorBytesPerRow
;
286 else /* top-down DIB */
288 xorStride
= xorBytesPerRow
;
292 bits
= HeapAlloc(GetProcessHeap(), 0, bitsSize
);
294 /* palette-map the 4-bit data */
296 for (y
=0; y
<height
; y
++) {
297 BYTE
*xorByte
=xorRow
;
298 DWORD
*bitsPixel
=(DWORD
*)bitsRow
;
299 for (x
=0; x
<width
; x
+=2) {
302 *bitsPixel
++ = colors
[xorVal
>>4];
303 if (x
+1 < width
) *bitsPixel
++ = colors
[xorVal
&0xf];
306 bitsRow
+= bitsStride
;
309 HeapFree(GetProcessHeap(), 0, tempdata
);
314 UINT xorBytesPerRow
= (width
+3)/4*4;
315 UINT xorBytes
= xorBytesPerRow
* height
;
321 tempdata
= HeapAlloc(GetProcessHeap(), 0, xorBytes
);
328 hr
= IStream_Read(This
->parent
->stream
, tempdata
, xorBytes
, &bytesread
);
329 if (FAILED(hr
) || bytesread
!= xorBytes
) goto fail
;
331 if (bih
.biHeight
> 0) /* bottom-up DIB */
333 xorStride
= -xorBytesPerRow
;
334 xorRow
= tempdata
+ (height
-1)*xorBytesPerRow
;
336 else /* top-down DIB */
338 xorStride
= xorBytesPerRow
;
342 bits
= HeapAlloc(GetProcessHeap(), 0, bitsSize
);
344 /* palette-map the 8-bit data */
346 for (y
=0; y
<height
; y
++) {
347 BYTE
*xorByte
=xorRow
;
348 DWORD
*bitsPixel
=(DWORD
*)bitsRow
;
349 for (x
=0; x
<width
; x
++)
350 *bitsPixel
++ = colors
[*xorByte
++];
352 bitsRow
+= bitsStride
;
355 HeapFree(GetProcessHeap(), 0, tempdata
);
360 UINT xorBytesPerRow
= (width
*3+3)/4*4;
361 UINT xorBytes
= xorBytesPerRow
* height
;
367 tempdata
= HeapAlloc(GetProcessHeap(), 0, xorBytes
);
374 hr
= IStream_Read(This
->parent
->stream
, tempdata
, xorBytes
, &bytesread
);
375 if (FAILED(hr
) || bytesread
!= xorBytes
) goto fail
;
377 if (bih
.biHeight
> 0) /* bottom-up DIB */
379 xorStride
= -xorBytesPerRow
;
380 xorRow
= tempdata
+ (height
-1)*xorBytesPerRow
;
382 else /* top-down DIB */
384 xorStride
= xorBytesPerRow
;
388 bits
= HeapAlloc(GetProcessHeap(), 0, bitsSize
);
392 for (y
=0; y
<height
; y
++) {
393 BYTE
*xorByte
=xorRow
;
394 BYTE
*bitsByte
=bitsRow
;
395 for (x
=0; x
<width
; x
++)
397 *bitsByte
++ = *xorByte
++; /* blue */
398 *bitsByte
++ = *xorByte
++; /* green */
399 *bitsByte
++ = *xorByte
++; /* red */
400 bitsByte
++; /* alpha */
403 bitsRow
+= bitsStride
;
406 HeapFree(GetProcessHeap(), 0, tempdata
);
411 UINT xorBytesPerRow
= width
*4;
412 UINT xorBytes
= xorBytesPerRow
* height
;
414 bits
= HeapAlloc(GetProcessHeap(), 0, xorBytes
);
421 if (bih
.biHeight
> 0) /* bottom-up DIB */
423 /* read the rows backwards so we get a top-down DIB */
425 BYTE
*xorRow
= bits
+ xorBytesPerRow
* (height
-1);
427 for (i
=0; i
<height
; i
++)
429 hr
= IStream_Read(This
->parent
->stream
, xorRow
, xorBytesPerRow
, &bytesread
);
430 if (FAILED(hr
) || bytesread
!= xorBytesPerRow
) goto fail
;
431 xorRow
-= xorBytesPerRow
;
434 else /* top-down DIB */
436 hr
= IStream_Read(This
->parent
->stream
, bits
, xorBytes
, &bytesread
);
437 if (FAILED(hr
) || bytesread
!= xorBytes
) goto fail
;
442 FIXME("unsupported bitcount: %u\n", This
->entry
.wBitCount
);
446 if (This
->entry
.wBitCount
< 32)
448 /* set alpha data based on the AND mask */
449 UINT andBytesPerRow
= (width
+31)/32*4;
450 UINT andBytes
= andBytesPerRow
* height
;
456 tempdata
= HeapAlloc(GetProcessHeap(), 0, andBytes
);
463 hr
= IStream_Read(This
->parent
->stream
, tempdata
, andBytes
, &bytesread
);
464 if (FAILED(hr
) || bytesread
!= andBytes
) goto fail
;
466 if (bih
.biHeight
> 0) /* bottom-up DIB */
468 andStride
= -andBytesPerRow
;
469 andRow
= tempdata
+ (height
-1)*andBytesPerRow
;
471 else /* top-down DIB */
473 andStride
= andBytesPerRow
;
478 for (y
=0; y
<height
; y
++) {
479 BYTE
*andByte
=andRow
;
480 DWORD
*bitsPixel
=(DWORD
*)bitsRow
;
481 for (x
=0; x
<width
; x
+=8) {
482 BYTE andVal
=*andByte
++;
483 pixel_set_trans(bitsPixel
++, andVal
>>7&1);
484 if (x
+1 < width
) pixel_set_trans(bitsPixel
++, andVal
>>6&1);
485 if (x
+2 < width
) pixel_set_trans(bitsPixel
++, andVal
>>5&1);
486 if (x
+3 < width
) pixel_set_trans(bitsPixel
++, andVal
>>4&1);
487 if (x
+4 < width
) pixel_set_trans(bitsPixel
++, andVal
>>3&1);
488 if (x
+5 < width
) pixel_set_trans(bitsPixel
++, andVal
>>2&1);
489 if (x
+6 < width
) pixel_set_trans(bitsPixel
++, andVal
>>1&1);
490 if (x
+7 < width
) pixel_set_trans(bitsPixel
++, andVal
&1);
493 bitsRow
+= bitsStride
;
496 HeapFree(GetProcessHeap(), 0, tempdata
);
504 HeapFree(GetProcessHeap(), 0, tempdata
);
505 HeapFree(GetProcessHeap(), 0, bits
);
506 if (SUCCEEDED(hr
)) hr
= E_FAIL
;
507 TRACE("<-- %x\n", hr
);
511 static HRESULT WINAPI
IcoFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
,
512 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
514 IcoFrameDecode
*This
= (IcoFrameDecode
*)iface
;
516 UINT width
, height
, stride
;
517 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
521 hr
= IcoFrameDecode_ReadPixels(This
);
522 if (FAILED(hr
)) return hr
;
525 width
= This
->entry
.bWidth
? This
->entry
.bWidth
: 256;
526 height
= This
->entry
.bHeight
? This
->entry
.bHeight
: 256;
529 return copy_pixels(32, This
->bits
, width
, height
, stride
,
530 prc
, cbStride
, cbBufferSize
, pbBuffer
);
533 static HRESULT WINAPI
IcoFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
534 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
536 TRACE("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
537 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
540 static HRESULT WINAPI
IcoFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
,
541 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
543 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
544 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
547 static HRESULT WINAPI
IcoFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
,
548 IWICBitmapSource
**ppIThumbnail
)
550 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
551 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
554 static const IWICBitmapFrameDecodeVtbl IcoFrameDecode_Vtbl
= {
555 IcoFrameDecode_QueryInterface
,
556 IcoFrameDecode_AddRef
,
557 IcoFrameDecode_Release
,
558 IcoFrameDecode_GetSize
,
559 IcoFrameDecode_GetPixelFormat
,
560 IcoFrameDecode_GetResolution
,
561 IcoFrameDecode_CopyPalette
,
562 IcoFrameDecode_CopyPixels
,
563 IcoFrameDecode_GetMetadataQueryReader
,
564 IcoFrameDecode_GetColorContexts
,
565 IcoFrameDecode_GetThumbnail
568 static HRESULT WINAPI
IcoDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
571 IcoDecoder
*This
= (IcoDecoder
*)iface
;
572 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
574 if (!ppv
) return E_INVALIDARG
;
576 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICBitmapDecoder
, iid
))
583 return E_NOINTERFACE
;
586 IUnknown_AddRef((IUnknown
*)*ppv
);
590 static ULONG WINAPI
IcoDecoder_AddRef(IWICBitmapDecoder
*iface
)
592 IcoDecoder
*This
= (IcoDecoder
*)iface
;
593 ULONG ref
= InterlockedIncrement(&This
->ref
);
595 TRACE("(%p) refcount=%u\n", iface
, ref
);
600 static ULONG WINAPI
IcoDecoder_Release(IWICBitmapDecoder
*iface
)
602 IcoDecoder
*This
= (IcoDecoder
*)iface
;
603 ULONG ref
= InterlockedDecrement(&This
->ref
);
605 TRACE("(%p) refcount=%u\n", iface
, ref
);
609 if (This
->stream
) IStream_Release(This
->stream
);
610 HeapFree(GetProcessHeap(), 0, This
);
616 static HRESULT WINAPI
IcoDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
617 DWORD
*pdwCapability
)
619 FIXME("(%p,%p,%p): stub\n", iface
, pIStream
, pdwCapability
);
623 static HRESULT WINAPI
IcoDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
624 WICDecodeOptions cacheOptions
)
626 IcoDecoder
*This
= (IcoDecoder
*)iface
;
630 TRACE("(%p,%p,%x)\n", iface
, pIStream
, cacheOptions
);
632 if (This
->initialized
) return WINCODEC_ERR_WRONGSTATE
;
635 hr
= IStream_Seek(pIStream
, seek
, STREAM_SEEK_SET
, NULL
);
636 if (FAILED(hr
)) return hr
;
638 hr
= IStream_Read(pIStream
, &This
->header
, sizeof(ICONHEADER
), &bytesread
);
639 if (FAILED(hr
)) return hr
;
640 if (bytesread
!= sizeof(ICONHEADER
) ||
641 This
->header
.idReserved
!= 0 ||
642 This
->header
.idType
!= 1) return E_FAIL
;
644 This
->initialized
= TRUE
;
645 This
->stream
= pIStream
;
646 IStream_AddRef(pIStream
);
651 static HRESULT WINAPI
IcoDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
652 GUID
*pguidContainerFormat
)
654 FIXME("(%p,%p): stub\n", iface
, pguidContainerFormat
);
658 static HRESULT WINAPI
IcoDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
659 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
661 FIXME("(%p,%p): stub\n", iface
, ppIDecoderInfo
);
665 static HRESULT WINAPI
IcoDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
666 IWICPalette
*pIPalette
)
668 TRACE("(%p,%p)\n", iface
, pIPalette
);
669 return WINCODEC_ERR_PALETTEUNAVAILABLE
;
672 static HRESULT WINAPI
IcoDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
673 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
675 TRACE("(%p,%p)\n", iface
, ppIMetadataQueryReader
);
676 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
679 static HRESULT WINAPI
IcoDecoder_GetPreview(IWICBitmapDecoder
*iface
,
680 IWICBitmapSource
**ppIBitmapSource
)
682 TRACE("(%p,%p)\n", iface
, ppIBitmapSource
);
683 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
686 static HRESULT WINAPI
IcoDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
687 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
689 TRACE("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
690 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
693 static HRESULT WINAPI
IcoDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
694 IWICBitmapSource
**ppIThumbnail
)
696 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
697 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
700 static HRESULT WINAPI
IcoDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
703 IcoDecoder
*This
= (IcoDecoder
*)iface
;
704 TRACE("(%p,%p)\n", iface
, pCount
);
706 if (!This
->initialized
) return WINCODEC_ERR_NOTINITIALIZED
;
708 *pCount
= This
->header
.idCount
;
709 TRACE("<-- %u\n", *pCount
);
714 static HRESULT WINAPI
IcoDecoder_GetFrame(IWICBitmapDecoder
*iface
,
715 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
717 IcoDecoder
*This
= (IcoDecoder
*)iface
;
718 IcoFrameDecode
*result
;
722 TRACE("(%p,%u,%p)\n", iface
, index
, ppIBitmapFrame
);
724 if (!This
->initialized
) return WINCODEC_ERR_NOTINITIALIZED
;
726 if (This
->header
.idCount
< index
) return E_INVALIDARG
;
728 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(IcoFrameDecode
));
729 if (!result
) return E_OUTOFMEMORY
;
731 result
->lpVtbl
= &IcoFrameDecode_Vtbl
;
733 result
->parent
= This
;
736 /* read the icon entry */
737 seek
.QuadPart
= sizeof(ICONHEADER
) + sizeof(ICONDIRENTRY
) * index
;
738 hr
= IStream_Seek(This
->stream
, seek
, STREAM_SEEK_SET
, 0);
739 if (FAILED(hr
)) goto fail
;
741 hr
= IStream_Read(This
->stream
, &result
->entry
, sizeof(ICONDIRENTRY
), &bytesread
);
742 if (FAILED(hr
) || bytesread
!= sizeof(ICONDIRENTRY
)) goto fail
;
744 IWICBitmapDecoder_AddRef(iface
);
746 *ppIBitmapFrame
= (IWICBitmapFrameDecode
*)result
;
751 HeapFree(GetProcessHeap(), 0, result
);
752 if (SUCCEEDED(hr
)) hr
= E_FAIL
;
753 TRACE("<-- %x\n", hr
);
757 static const IWICBitmapDecoderVtbl IcoDecoder_Vtbl
= {
758 IcoDecoder_QueryInterface
,
761 IcoDecoder_QueryCapability
,
762 IcoDecoder_Initialize
,
763 IcoDecoder_GetContainerFormat
,
764 IcoDecoder_GetDecoderInfo
,
765 IcoDecoder_CopyPalette
,
766 IcoDecoder_GetMetadataQueryReader
,
767 IcoDecoder_GetPreview
,
768 IcoDecoder_GetColorContexts
,
769 IcoDecoder_GetThumbnail
,
770 IcoDecoder_GetFrameCount
,
774 HRESULT
IcoDecoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
779 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
783 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
785 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IcoDecoder
));
786 if (!This
) return E_OUTOFMEMORY
;
788 This
->lpVtbl
= &IcoDecoder_Vtbl
;
791 This
->initialized
= FALSE
;
793 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
794 IUnknown_Release((IUnknown
*)This
);