ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

icoformat.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2009 Vincent Povirk for CodeWeavers
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include "config.h"
00020 
00021 #include <stdarg.h>
00022 
00023 #define COBJMACROS
00024 
00025 #include "windef.h"
00026 #include "winbase.h"
00027 #include "wingdi.h"
00028 #include "objbase.h"
00029 #include "wincodec.h"
00030 
00031 #include "wincodecs_private.h"
00032 
00033 #include "wine/debug.h"
00034 
00035 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
00036 
00037 #include "pshpack1.h"
00038 
00039 typedef struct {
00040     BYTE bWidth;
00041     BYTE bHeight;
00042     BYTE bColorCount;
00043     BYTE bReserved;
00044     WORD wPlanes;
00045     WORD wBitCount;
00046     DWORD dwDIBSize;
00047     DWORD dwDIBOffset;
00048 } ICONDIRENTRY;
00049 
00050 typedef struct
00051 {
00052     WORD idReserved;
00053     WORD idType;
00054     WORD idCount;
00055 } ICONHEADER;
00056 
00057 #include "poppack.h"
00058 
00059 typedef struct {
00060     const IWICBitmapDecoderVtbl *lpVtbl;
00061     LONG ref;
00062     BOOL initialized;
00063     IStream *stream;
00064     ICONHEADER header;
00065     CRITICAL_SECTION lock; /* must be held when accessing stream */
00066 } IcoDecoder;
00067 
00068 typedef struct {
00069     const IWICBitmapFrameDecodeVtbl *lpVtbl;
00070     LONG ref;
00071     ICONDIRENTRY entry;
00072     IcoDecoder *parent;
00073     BYTE *bits;
00074 } IcoFrameDecode;
00075 
00076 static HRESULT WINAPI IcoFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
00077     void **ppv)
00078 {
00079     IcoFrameDecode *This = (IcoFrameDecode*)iface;
00080     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
00081 
00082     if (!ppv) return E_INVALIDARG;
00083 
00084     if (IsEqualIID(&IID_IUnknown, iid) ||
00085         IsEqualIID(&IID_IWICBitmapSource, iid) ||
00086         IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
00087     {
00088         *ppv = This;
00089     }
00090     else
00091     {
00092         *ppv = NULL;
00093         return E_NOINTERFACE;
00094     }
00095 
00096     IUnknown_AddRef((IUnknown*)*ppv);
00097     return S_OK;
00098 }
00099 
00100 static ULONG WINAPI IcoFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
00101 {
00102     IcoFrameDecode *This = (IcoFrameDecode*)iface;
00103     ULONG ref = InterlockedIncrement(&This->ref);
00104 
00105     TRACE("(%p) refcount=%u\n", iface, ref);
00106 
00107     return ref;
00108 }
00109 
00110 static ULONG WINAPI IcoFrameDecode_Release(IWICBitmapFrameDecode *iface)
00111 {
00112     IcoFrameDecode *This = (IcoFrameDecode*)iface;
00113     ULONG ref = InterlockedDecrement(&This->ref);
00114 
00115     TRACE("(%p) refcount=%u\n", iface, ref);
00116 
00117     if (ref == 0)
00118     {
00119         IUnknown_Release((IUnknown*)This->parent);
00120         HeapFree(GetProcessHeap(), 0, This->bits);
00121         HeapFree(GetProcessHeap(), 0, This);
00122     }
00123 
00124     return ref;
00125 }
00126 
00127 static HRESULT WINAPI IcoFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
00128     UINT *puiWidth, UINT *puiHeight)
00129 {
00130     IcoFrameDecode *This = (IcoFrameDecode*)iface;
00131 
00132     *puiWidth = This->entry.bWidth ? This->entry.bWidth : 256;
00133     *puiHeight = This->entry.bHeight ? This->entry.bHeight : 256;
00134 
00135     TRACE("(%p) -> (%i,%i)\n", iface, *puiWidth, *puiHeight);
00136 
00137     return S_OK;
00138 }
00139 
00140 static HRESULT WINAPI IcoFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
00141     WICPixelFormatGUID *pPixelFormat)
00142 {
00143     memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
00144     return S_OK;
00145 }
00146 
00147 static HRESULT WINAPI IcoFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
00148     double *pDpiX, double *pDpiY)
00149 {
00150     FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
00151     return E_NOTIMPL;
00152 }
00153 
00154 static HRESULT WINAPI IcoFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
00155     IWICPalette *pIPalette)
00156 {
00157     TRACE("(%p,%p)\n", iface, pIPalette);
00158     return WINCODEC_ERR_PALETTEUNAVAILABLE;
00159 }
00160 
00161 static inline void pixel_set_trans(DWORD* pixel, BOOL transparent)
00162 {
00163     if (transparent) *pixel = 0;
00164     else *pixel |= 0xff000000;
00165 }
00166 
00167 static HRESULT IcoFrameDecode_ReadPixels(IcoFrameDecode *This)
00168 {
00169     BITMAPINFOHEADER bih;
00170     DWORD colors[256];
00171     UINT colorcount=0;
00172     LARGE_INTEGER seek;
00173     ULONG bytesread;
00174     HRESULT hr;
00175     BYTE *tempdata = NULL;
00176     BYTE *bits = NULL;
00177     UINT bitsStride;
00178     UINT bitsSize;
00179     UINT width, height;
00180 
00181     width = This->entry.bWidth ? This->entry.bWidth : 256;
00182     height = This->entry.bHeight ? This->entry.bHeight : 256;
00183 
00184     /* read the BITMAPINFOHEADER */
00185     seek.QuadPart = This->entry.dwDIBOffset;
00186     hr = IStream_Seek(This->parent->stream, seek, STREAM_SEEK_SET, NULL);
00187     if (FAILED(hr)) goto fail;
00188 
00189     hr = IStream_Read(This->parent->stream, &bih, sizeof(BITMAPINFOHEADER), &bytesread);
00190     if (FAILED(hr) || bytesread != sizeof(BITMAPINFOHEADER)) goto fail;
00191 
00192     if (bih.biBitCount <= 8)
00193     {
00194         /* read the palette */
00195         colorcount = bih.biClrUsed ? bih.biClrUsed : 1 << bih.biBitCount;
00196 
00197         hr = IStream_Read(This->parent->stream, colors, sizeof(RGBQUAD)*colorcount, &bytesread);
00198         if (FAILED(hr) || bytesread != sizeof(RGBQUAD)*colorcount) goto fail;
00199     }
00200 
00201     bitsStride = width * 4;
00202     bitsSize = bitsStride * height;
00203 
00204     /* read the XOR data */
00205     switch (bih.biBitCount)
00206     {
00207     case 1:
00208     {
00209         UINT xorBytesPerRow = (width+31)/32*4;
00210         UINT xorBytes = xorBytesPerRow * height;
00211         INT xorStride;
00212         BYTE *xorRow;
00213         BYTE *bitsRow;
00214         UINT x, y;
00215 
00216         tempdata = HeapAlloc(GetProcessHeap(), 0, xorBytes);
00217         if (!tempdata)
00218         {
00219             hr = E_OUTOFMEMORY;
00220             goto fail;
00221         }
00222 
00223         hr = IStream_Read(This->parent->stream, tempdata, xorBytes, &bytesread);
00224         if (FAILED(hr) || bytesread != xorBytes) goto fail;
00225 
00226         if (bih.biHeight > 0) /* bottom-up DIB */
00227         {
00228             xorStride = -xorBytesPerRow;
00229             xorRow = tempdata + (height-1)*xorBytesPerRow;
00230         }
00231         else /* top-down DIB */
00232         {
00233             xorStride = xorBytesPerRow;
00234             xorRow = tempdata;
00235         }
00236 
00237         bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
00238 
00239         /* palette-map the 1-bit data */
00240         bitsRow = bits;
00241         for (y=0; y<height; y++) {
00242             BYTE *xorByte=xorRow;
00243             DWORD *bitsPixel=(DWORD*)bitsRow;
00244             for (x=0; x<width; x+=8) {
00245                 BYTE xorVal;
00246                 xorVal=*xorByte++;
00247                 *bitsPixel++ = colors[xorVal>>7];
00248                 if (x+1 < width) *bitsPixel++ = colors[xorVal>>6&1];
00249                 if (x+2 < width) *bitsPixel++ = colors[xorVal>>5&1];
00250                 if (x+3 < width) *bitsPixel++ = colors[xorVal>>4&1];
00251                 if (x+4 < width) *bitsPixel++ = colors[xorVal>>3&1];
00252                 if (x+5 < width) *bitsPixel++ = colors[xorVal>>2&1];
00253                 if (x+6 < width) *bitsPixel++ = colors[xorVal>>1&1];
00254                 if (x+7 < width) *bitsPixel++ = colors[xorVal&1];
00255             }
00256             xorRow += xorStride;
00257             bitsRow += bitsStride;
00258         }
00259 
00260         HeapFree(GetProcessHeap(), 0, tempdata);
00261         break;
00262     }
00263     case 4:
00264     {
00265         UINT xorBytesPerRow = (width+7)/8*4;
00266         UINT xorBytes = xorBytesPerRow * height;
00267         INT xorStride;
00268         BYTE *xorRow;
00269         BYTE *bitsRow;
00270         UINT x, y;
00271 
00272         tempdata = HeapAlloc(GetProcessHeap(), 0, xorBytes);
00273         if (!tempdata)
00274         {
00275             hr = E_OUTOFMEMORY;
00276             goto fail;
00277         }
00278 
00279         hr = IStream_Read(This->parent->stream, tempdata, xorBytes, &bytesread);
00280         if (FAILED(hr) || bytesread != xorBytes) goto fail;
00281 
00282         if (bih.biHeight > 0) /* bottom-up DIB */
00283         {
00284             xorStride = -xorBytesPerRow;
00285             xorRow = tempdata + (height-1)*xorBytesPerRow;
00286         }
00287         else /* top-down DIB */
00288         {
00289             xorStride = xorBytesPerRow;
00290             xorRow = tempdata;
00291         }
00292 
00293         bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
00294 
00295         /* palette-map the 4-bit data */
00296         bitsRow = bits;
00297         for (y=0; y<height; y++) {
00298             BYTE *xorByte=xorRow;
00299             DWORD *bitsPixel=(DWORD*)bitsRow;
00300             for (x=0; x<width; x+=2) {
00301                 BYTE xorVal;
00302                 xorVal=*xorByte++;
00303                 *bitsPixel++ = colors[xorVal>>4];
00304                 if (x+1 < width) *bitsPixel++ = colors[xorVal&0xf];
00305             }
00306             xorRow += xorStride;
00307             bitsRow += bitsStride;
00308         }
00309 
00310         HeapFree(GetProcessHeap(), 0, tempdata);
00311         break;
00312     }
00313     case 8:
00314     {
00315         UINT xorBytesPerRow = (width+3)/4*4;
00316         UINT xorBytes = xorBytesPerRow * height;
00317         INT xorStride;
00318         BYTE *xorRow;
00319         BYTE *bitsRow;
00320         UINT x, y;
00321 
00322         tempdata = HeapAlloc(GetProcessHeap(), 0, xorBytes);
00323         if (!tempdata)
00324         {
00325             hr = E_OUTOFMEMORY;
00326             goto fail;
00327         }
00328 
00329         hr = IStream_Read(This->parent->stream, tempdata, xorBytes, &bytesread);
00330         if (FAILED(hr) || bytesread != xorBytes) goto fail;
00331 
00332         if (bih.biHeight > 0) /* bottom-up DIB */
00333         {
00334             xorStride = -xorBytesPerRow;
00335             xorRow = tempdata + (height-1)*xorBytesPerRow;
00336         }
00337         else /* top-down DIB */
00338         {
00339             xorStride = xorBytesPerRow;
00340             xorRow = tempdata;
00341         }
00342 
00343         bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
00344 
00345         /* palette-map the 8-bit data */
00346         bitsRow = bits;
00347         for (y=0; y<height; y++) {
00348             BYTE *xorByte=xorRow;
00349             DWORD *bitsPixel=(DWORD*)bitsRow;
00350             for (x=0; x<width; x++)
00351                 *bitsPixel++ = colors[*xorByte++];
00352             xorRow += xorStride;
00353             bitsRow += bitsStride;
00354         }
00355 
00356         HeapFree(GetProcessHeap(), 0, tempdata);
00357         break;
00358     }
00359     case 24:
00360     {
00361         UINT xorBytesPerRow = (width*3+3)/4*4;
00362         UINT xorBytes = xorBytesPerRow * height;
00363         INT xorStride;
00364         BYTE *xorRow;
00365         BYTE *bitsRow;
00366         UINT x, y;
00367 
00368         tempdata = HeapAlloc(GetProcessHeap(), 0, xorBytes);
00369         if (!tempdata)
00370         {
00371             hr = E_OUTOFMEMORY;
00372             goto fail;
00373         }
00374 
00375         hr = IStream_Read(This->parent->stream, tempdata, xorBytes, &bytesread);
00376         if (FAILED(hr) || bytesread != xorBytes) goto fail;
00377 
00378         if (bih.biHeight > 0) /* bottom-up DIB */
00379         {
00380             xorStride = -xorBytesPerRow;
00381             xorRow = tempdata + (height-1)*xorBytesPerRow;
00382         }
00383         else /* top-down DIB */
00384         {
00385             xorStride = xorBytesPerRow;
00386             xorRow = tempdata;
00387         }
00388 
00389         bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
00390 
00391         /* copy BGR->BGRA */
00392         bitsRow = bits;
00393         for (y=0; y<height; y++) {
00394             BYTE *xorByte=xorRow;
00395             BYTE *bitsByte=bitsRow;
00396             for (x=0; x<width; x++)
00397             {
00398                 *bitsByte++ = *xorByte++; /* blue */
00399                 *bitsByte++ = *xorByte++; /* green */
00400                 *bitsByte++ = *xorByte++; /* red */
00401                 bitsByte++; /* alpha */
00402             }
00403             xorRow += xorStride;
00404             bitsRow += bitsStride;
00405         }
00406 
00407         HeapFree(GetProcessHeap(), 0, tempdata);
00408         break;
00409     }
00410     case 32:
00411     {
00412         UINT xorBytesPerRow = width*4;
00413         UINT xorBytes = xorBytesPerRow * height;
00414 
00415         bits = HeapAlloc(GetProcessHeap(), 0, xorBytes);
00416         if (!bits)
00417         {
00418             hr = E_OUTOFMEMORY;
00419             goto fail;
00420         }
00421 
00422         if (bih.biHeight > 0) /* bottom-up DIB */
00423         {
00424             /* read the rows backwards so we get a top-down DIB */
00425             UINT i;
00426             BYTE *xorRow = bits + xorBytesPerRow * (height-1);
00427 
00428             for (i=0; i<height; i++)
00429             {
00430                 hr = IStream_Read(This->parent->stream, xorRow, xorBytesPerRow, &bytesread);
00431                 if (FAILED(hr) || bytesread != xorBytesPerRow) goto fail;
00432                 xorRow -= xorBytesPerRow;
00433             }
00434         }
00435         else /* top-down DIB */
00436         {
00437             hr = IStream_Read(This->parent->stream, bits, xorBytes, &bytesread);
00438             if (FAILED(hr) || bytesread != xorBytes) goto fail;
00439         }
00440         break;
00441     }
00442     default:
00443         FIXME("unsupported bitcount: %u\n", bih.biBitCount);
00444         goto fail;
00445     }
00446 
00447     if (bih.biBitCount < 32)
00448     {
00449         /* set alpha data based on the AND mask */
00450         UINT andBytesPerRow = (width+31)/32*4;
00451         UINT andBytes = andBytesPerRow * height;
00452         INT andStride;
00453         BYTE *andRow;
00454         BYTE *bitsRow;
00455         UINT x, y;
00456 
00457         tempdata = HeapAlloc(GetProcessHeap(), 0, andBytes);
00458         if (!tempdata)
00459         {
00460             hr = E_OUTOFMEMORY;
00461             goto fail;
00462         }
00463 
00464         hr = IStream_Read(This->parent->stream, tempdata, andBytes, &bytesread);
00465         if (FAILED(hr) || bytesread != andBytes) goto fail;
00466 
00467         if (bih.biHeight > 0) /* bottom-up DIB */
00468         {
00469             andStride = -andBytesPerRow;
00470             andRow = tempdata + (height-1)*andBytesPerRow;
00471         }
00472         else /* top-down DIB */
00473         {
00474             andStride = andBytesPerRow;
00475             andRow = tempdata;
00476         }
00477 
00478         bitsRow = bits;
00479         for (y=0; y<height; y++) {
00480             BYTE *andByte=andRow;
00481             DWORD *bitsPixel=(DWORD*)bitsRow;
00482             for (x=0; x<width; x+=8) {
00483                 BYTE andVal=*andByte++;
00484                 pixel_set_trans(bitsPixel++, andVal>>7&1);
00485                 if (x+1 < width) pixel_set_trans(bitsPixel++, andVal>>6&1);
00486                 if (x+2 < width) pixel_set_trans(bitsPixel++, andVal>>5&1);
00487                 if (x+3 < width) pixel_set_trans(bitsPixel++, andVal>>4&1);
00488                 if (x+4 < width) pixel_set_trans(bitsPixel++, andVal>>3&1);
00489                 if (x+5 < width) pixel_set_trans(bitsPixel++, andVal>>2&1);
00490                 if (x+6 < width) pixel_set_trans(bitsPixel++, andVal>>1&1);
00491                 if (x+7 < width) pixel_set_trans(bitsPixel++, andVal&1);
00492             }
00493             andRow += andStride;
00494             bitsRow += bitsStride;
00495         }
00496 
00497         HeapFree(GetProcessHeap(), 0, tempdata);
00498     }
00499 
00500     This->bits = bits;
00501 
00502     return S_OK;
00503 
00504 fail:
00505     HeapFree(GetProcessHeap(), 0, tempdata);
00506     HeapFree(GetProcessHeap(), 0, bits);
00507     if (SUCCEEDED(hr)) hr = E_FAIL;
00508     TRACE("<-- %x\n", hr);
00509     return hr;
00510 }
00511 
00512 static HRESULT WINAPI IcoFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
00513     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
00514 {
00515     IcoFrameDecode *This = (IcoFrameDecode*)iface;
00516     HRESULT hr=S_OK;
00517     UINT width, height, stride;
00518     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
00519 
00520     EnterCriticalSection(&This->parent->lock);
00521     if (!This->bits)
00522     {
00523         hr = IcoFrameDecode_ReadPixels(This);
00524     }
00525     LeaveCriticalSection(&This->parent->lock);
00526     if (FAILED(hr)) return hr;
00527 
00528     width = This->entry.bWidth ? This->entry.bWidth : 256;
00529     height = This->entry.bHeight ? This->entry.bHeight : 256;
00530     stride = width * 4;
00531 
00532     return copy_pixels(32, This->bits, width, height, stride,
00533         prc, cbStride, cbBufferSize, pbBuffer);
00534 }
00535 
00536 static HRESULT WINAPI IcoFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
00537     IWICMetadataQueryReader **ppIMetadataQueryReader)
00538 {
00539     TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
00540     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00541 }
00542 
00543 static HRESULT WINAPI IcoFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
00544     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
00545 {
00546     TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
00547     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00548 }
00549 
00550 static HRESULT WINAPI IcoFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
00551     IWICBitmapSource **ppIThumbnail)
00552 {
00553     TRACE("(%p,%p)\n", iface, ppIThumbnail);
00554     return WINCODEC_ERR_CODECNOTHUMBNAIL;
00555 }
00556 
00557 static const IWICBitmapFrameDecodeVtbl IcoFrameDecode_Vtbl = {
00558     IcoFrameDecode_QueryInterface,
00559     IcoFrameDecode_AddRef,
00560     IcoFrameDecode_Release,
00561     IcoFrameDecode_GetSize,
00562     IcoFrameDecode_GetPixelFormat,
00563     IcoFrameDecode_GetResolution,
00564     IcoFrameDecode_CopyPalette,
00565     IcoFrameDecode_CopyPixels,
00566     IcoFrameDecode_GetMetadataQueryReader,
00567     IcoFrameDecode_GetColorContexts,
00568     IcoFrameDecode_GetThumbnail
00569 };
00570 
00571 static HRESULT WINAPI IcoDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
00572     void **ppv)
00573 {
00574     IcoDecoder *This = (IcoDecoder*)iface;
00575     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
00576 
00577     if (!ppv) return E_INVALIDARG;
00578 
00579     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
00580     {
00581         *ppv = This;
00582     }
00583     else
00584     {
00585         *ppv = NULL;
00586         return E_NOINTERFACE;
00587     }
00588 
00589     IUnknown_AddRef((IUnknown*)*ppv);
00590     return S_OK;
00591 }
00592 
00593 static ULONG WINAPI IcoDecoder_AddRef(IWICBitmapDecoder *iface)
00594 {
00595     IcoDecoder *This = (IcoDecoder*)iface;
00596     ULONG ref = InterlockedIncrement(&This->ref);
00597 
00598     TRACE("(%p) refcount=%u\n", iface, ref);
00599 
00600     return ref;
00601 }
00602 
00603 static ULONG WINAPI IcoDecoder_Release(IWICBitmapDecoder *iface)
00604 {
00605     IcoDecoder *This = (IcoDecoder*)iface;
00606     ULONG ref = InterlockedDecrement(&This->ref);
00607 
00608     TRACE("(%p) refcount=%u\n", iface, ref);
00609 
00610     if (ref == 0)
00611     {
00612         This->lock.DebugInfo->Spare[0] = 0;
00613         DeleteCriticalSection(&This->lock);
00614         if (This->stream) IStream_Release(This->stream);
00615         HeapFree(GetProcessHeap(), 0, This);
00616     }
00617 
00618     return ref;
00619 }
00620 
00621 static HRESULT WINAPI IcoDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
00622     DWORD *pdwCapability)
00623 {
00624     FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
00625     return E_NOTIMPL;
00626 }
00627 
00628 static HRESULT WINAPI IcoDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
00629     WICDecodeOptions cacheOptions)
00630 {
00631     IcoDecoder *This = (IcoDecoder*)iface;
00632     LARGE_INTEGER seek;
00633     HRESULT hr;
00634     ULONG bytesread;
00635     TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
00636 
00637     EnterCriticalSection(&This->lock);
00638 
00639     if (This->initialized)
00640     {
00641         hr = WINCODEC_ERR_WRONGSTATE;
00642         goto end;
00643     }
00644 
00645     seek.QuadPart = 0;
00646     hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
00647     if (FAILED(hr)) goto end;
00648 
00649     hr = IStream_Read(pIStream, &This->header, sizeof(ICONHEADER), &bytesread);
00650     if (FAILED(hr)) goto end;
00651     if (bytesread != sizeof(ICONHEADER) ||
00652         This->header.idReserved != 0 ||
00653         This->header.idType != 1)
00654     {
00655         hr = E_FAIL;
00656         goto end;
00657     }
00658 
00659     This->initialized = TRUE;
00660     This->stream = pIStream;
00661     IStream_AddRef(pIStream);
00662 
00663 end:
00664 
00665     LeaveCriticalSection(&This->lock);
00666 
00667     return hr;
00668 }
00669 
00670 static HRESULT WINAPI IcoDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
00671     GUID *pguidContainerFormat)
00672 {
00673     FIXME("(%p,%p): stub\n", iface, pguidContainerFormat);
00674     return E_NOTIMPL;
00675 }
00676 
00677 static HRESULT WINAPI IcoDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
00678     IWICBitmapDecoderInfo **ppIDecoderInfo)
00679 {
00680     FIXME("(%p,%p): stub\n", iface, ppIDecoderInfo);
00681     return E_NOTIMPL;
00682 }
00683 
00684 static HRESULT WINAPI IcoDecoder_CopyPalette(IWICBitmapDecoder *iface,
00685     IWICPalette *pIPalette)
00686 {
00687     TRACE("(%p,%p)\n", iface, pIPalette);
00688     return WINCODEC_ERR_PALETTEUNAVAILABLE;
00689 }
00690 
00691 static HRESULT WINAPI IcoDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
00692     IWICMetadataQueryReader **ppIMetadataQueryReader)
00693 {
00694     TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
00695     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00696 }
00697 
00698 static HRESULT WINAPI IcoDecoder_GetPreview(IWICBitmapDecoder *iface,
00699     IWICBitmapSource **ppIBitmapSource)
00700 {
00701     TRACE("(%p,%p)\n", iface, ppIBitmapSource);
00702     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00703 }
00704 
00705 static HRESULT WINAPI IcoDecoder_GetColorContexts(IWICBitmapDecoder *iface,
00706     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
00707 {
00708     TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
00709     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
00710 }
00711 
00712 static HRESULT WINAPI IcoDecoder_GetThumbnail(IWICBitmapDecoder *iface,
00713     IWICBitmapSource **ppIThumbnail)
00714 {
00715     TRACE("(%p,%p)\n", iface, ppIThumbnail);
00716     return WINCODEC_ERR_CODECNOTHUMBNAIL;
00717 }
00718 
00719 static HRESULT WINAPI IcoDecoder_GetFrameCount(IWICBitmapDecoder *iface,
00720     UINT *pCount)
00721 {
00722     IcoDecoder *This = (IcoDecoder*)iface;
00723     TRACE("(%p,%p)\n", iface, pCount);
00724 
00725     if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;
00726 
00727     *pCount = This->header.idCount;
00728     TRACE("<-- %u\n", *pCount);
00729 
00730     return S_OK;
00731 }
00732 
00733 static HRESULT WINAPI IcoDecoder_GetFrame(IWICBitmapDecoder *iface,
00734     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
00735 {
00736     IcoDecoder *This = (IcoDecoder*)iface;
00737     IcoFrameDecode *result=NULL;
00738     LARGE_INTEGER seek;
00739     HRESULT hr;
00740     ULONG bytesread;
00741     TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
00742 
00743     EnterCriticalSection(&This->lock);
00744 
00745     if (!This->initialized)
00746     {
00747         hr = WINCODEC_ERR_NOTINITIALIZED;
00748         goto fail;
00749     }
00750 
00751     if (This->header.idCount < index)
00752     {
00753         hr = E_INVALIDARG;
00754         goto fail;
00755     }
00756 
00757     result = HeapAlloc(GetProcessHeap(), 0, sizeof(IcoFrameDecode));
00758     if (!result)
00759     {
00760         hr = E_OUTOFMEMORY;
00761         goto fail;
00762     }
00763 
00764     result->lpVtbl = &IcoFrameDecode_Vtbl;
00765     result->ref = 1;
00766     result->parent = This;
00767     result->bits = NULL;
00768 
00769     /* read the icon entry */
00770     seek.QuadPart = sizeof(ICONHEADER) + sizeof(ICONDIRENTRY) * index;
00771     hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, 0);
00772     if (FAILED(hr)) goto fail;
00773 
00774     hr = IStream_Read(This->stream, &result->entry, sizeof(ICONDIRENTRY), &bytesread);
00775     if (FAILED(hr) || bytesread != sizeof(ICONDIRENTRY)) goto fail;
00776 
00777     IWICBitmapDecoder_AddRef(iface);
00778 
00779     *ppIBitmapFrame = (IWICBitmapFrameDecode*)result;
00780 
00781     LeaveCriticalSection(&This->lock);
00782 
00783     return S_OK;
00784 
00785 fail:
00786     LeaveCriticalSection(&This->lock);
00787     HeapFree(GetProcessHeap(), 0, result);
00788     if (SUCCEEDED(hr)) hr = E_FAIL;
00789     TRACE("<-- %x\n", hr);
00790     return hr;
00791 }
00792 
00793 static const IWICBitmapDecoderVtbl IcoDecoder_Vtbl = {
00794     IcoDecoder_QueryInterface,
00795     IcoDecoder_AddRef,
00796     IcoDecoder_Release,
00797     IcoDecoder_QueryCapability,
00798     IcoDecoder_Initialize,
00799     IcoDecoder_GetContainerFormat,
00800     IcoDecoder_GetDecoderInfo,
00801     IcoDecoder_CopyPalette,
00802     IcoDecoder_GetMetadataQueryReader,
00803     IcoDecoder_GetPreview,
00804     IcoDecoder_GetColorContexts,
00805     IcoDecoder_GetThumbnail,
00806     IcoDecoder_GetFrameCount,
00807     IcoDecoder_GetFrame
00808 };
00809 
00810 HRESULT IcoDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
00811 {
00812     IcoDecoder *This;
00813     HRESULT ret;
00814 
00815     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
00816 
00817     *ppv = NULL;
00818 
00819     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
00820 
00821     This = HeapAlloc(GetProcessHeap(), 0, sizeof(IcoDecoder));
00822     if (!This) return E_OUTOFMEMORY;
00823 
00824     This->lpVtbl = &IcoDecoder_Vtbl;
00825     This->ref = 1;
00826     This->stream = NULL;
00827     This->initialized = FALSE;
00828     InitializeCriticalSection(&This->lock);
00829     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IcoDecoder.lock");
00830 
00831     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
00832     IUnknown_Release((IUnknown*)This);
00833 
00834     return ret;
00835 }

Generated on Fri May 25 2012 04:24:55 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.