1 /* 2 * Copyright 2010 Damjan Jovanovic 3 * 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. 8 * 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. 13 * 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 17 */ 18 19 #include <stdarg.h> 20 #include <math.h> 21 22 #define COBJMACROS 23 24 #include "windef.h" 25 #include "objbase.h" 26 #include "wincodec.h" 27 #include "wine/test.h" 28 29 #include "pshpack1.h" 30 31 struct ICONHEADER 32 { 33 WORD idReserved; 34 WORD idType; 35 WORD idCount; 36 }; 37 38 struct ICONDIRENTRY 39 { 40 BYTE bWidth; 41 BYTE bHeight; 42 BYTE bColorCount; 43 BYTE bReserved; 44 WORD wPlanes; 45 WORD wBitCount; 46 DWORD dwDIBSize; 47 DWORD dwDIBOffset; 48 }; 49 50 struct test_ico 51 { 52 struct ICONHEADER header; 53 struct ICONDIRENTRY direntry; 54 BITMAPINFOHEADER bmi; 55 unsigned char data[512]; 56 }; 57 58 static const struct test_ico ico_1 = 59 { 60 /* ICONHEADER */ 61 { 62 0, /* reserved */ 63 1, /* type */ 64 1, /* count */ 65 }, 66 /* ICONDIRENTRY */ 67 { 68 16, /* width */ 69 16, /* height */ 70 2, /* color count */ 71 0, /* reserved */ 72 1, /* planes */ 73 8, /* bitcount*/ 74 40 + 2*4 + 16 * 16 + 16 * 4, /* data size */ 75 22 /* data offset */ 76 }, 77 /* BITMAPINFOHEADER */ 78 { 79 sizeof(BITMAPINFOHEADER), /* header size */ 80 16, /* width */ 81 2*16, /* height (XOR+AND rows) */ 82 1, /* planes */ 83 8, /* bit count */ 84 0, /* compression */ 85 0, /* sizeImage */ 86 0, /* x pels per meter */ 87 0, /* y pels per meter */ 88 2, /* clrUsed */ 89 0, /* clrImportant */ 90 }, 91 { 92 /* palette */ 93 0,0,0,0, 94 0xFF,0xFF,0xFF,0, 95 /* XOR mask */ 96 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 97 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 98 0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 99 0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 100 0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, 101 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0, 102 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0, 103 0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0, 104 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 105 0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 106 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0, 107 0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0, 108 0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0, 109 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 110 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 111 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 112 /* AND mask */ 113 0,0,0,0, 114 0,0,0,0, 115 0,0,0,0, 116 0,0,0,0, 117 0,0,0,0, 118 0,0,0,0, 119 0,0,0,0, 120 0,0,0,0, 121 0,0,0,0, 122 0,0,0,0, 123 0,0,0,0, 124 0,0,0,0, 125 0,0,0,0, 126 0,0,0,0, 127 0,0,0,0, 128 0,0,0,0 129 } 130 }; 131 132 #include "poppack.h" 133 134 #define test_ico_data(a, b, c) test_ico_data_(a, b, c, 0, __LINE__) 135 #define test_ico_data_todo(a, b, c) test_ico_data_(a, b, c, 1, __LINE__) 136 static void test_ico_data_(void *data, DWORD data_size, HRESULT init_hr, int todo, unsigned int line) 137 { 138 IWICBitmapDecoder *decoder; 139 IWICImagingFactory *factory; 140 HRESULT hr; 141 IWICStream *icostream; 142 IWICBitmapFrameDecode *framedecode = NULL; 143 144 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, 145 &IID_IWICImagingFactory, (void**)&factory); 146 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); 147 if (FAILED(hr)) return; 148 149 hr = IWICImagingFactory_CreateStream(factory, &icostream); 150 ok(hr == S_OK, "CreateStream failed, hr=%x\n", hr); 151 if (SUCCEEDED(hr)) 152 { 153 hr = IWICStream_InitializeFromMemory(icostream, data, data_size); 154 ok(hr == S_OK, "InitializeFromMemory failed, hr=%x\n", hr); 155 156 if (SUCCEEDED(hr)) 157 { 158 hr = CoCreateInstance(&CLSID_WICIcoDecoder, NULL, CLSCTX_INPROC_SERVER, 159 &IID_IWICBitmapDecoder, (void**)&decoder); 160 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); 161 } 162 163 if (SUCCEEDED(hr)) 164 { 165 hr = IWICBitmapDecoder_Initialize(decoder, (IStream*)icostream, 166 WICDecodeMetadataCacheOnDemand); 167 todo_wine_if(todo) 168 ok_(__FILE__, line)(hr == init_hr, "Initialize failed, hr=%x\n", hr); 169 170 if (SUCCEEDED(hr)) 171 { 172 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode); 173 ok(hr == S_OK, "GetFrame failed, hr=%x\n", hr); 174 } 175 176 if (SUCCEEDED(hr)) 177 { 178 UINT width, height; 179 IWICBitmapSource *thumbnail; 180 181 width = height = 0; 182 hr = IWICBitmapFrameDecode_GetSize(framedecode, &width, &height); 183 ok(hr == S_OK, "GetFrameSize failed, hr=%x\n", hr); 184 ok(width == 16 && height == 16, "framesize=%ux%u\n", width, height); 185 186 hr = IWICBitmapFrameDecode_GetThumbnail(framedecode, &thumbnail); 187 ok(hr == S_OK, "GetThumbnail failed, hr=%x\n", hr); 188 if (hr == S_OK) 189 { 190 width = height = 0; 191 hr = IWICBitmapSource_GetSize(thumbnail, &width, &height); 192 ok(hr == S_OK, "GetFrameSize failed, hr=%x\n", hr); 193 ok(width == 16 && height == 16, "framesize=%ux%u\n", width, height); 194 IWICBitmapSource_Release(thumbnail); 195 } 196 IWICBitmapFrameDecode_Release(framedecode); 197 } 198 199 IWICBitmapDecoder_Release(decoder); 200 } 201 202 IWICStream_Release(icostream); 203 } 204 205 IWICImagingFactory_Release(factory); 206 } 207 208 static void test_decoder(void) 209 { 210 struct test_ico ico; 211 212 /* Icon size specified in ICONDIRENTRY does not match bitmap header. */ 213 ico = ico_1; 214 ico.direntry.bWidth = 2; 215 ico.direntry.bHeight = 2; 216 test_ico_data(&ico, sizeof(ico), S_OK); 217 218 /* Invalid DIRENTRY data size/offset. */ 219 ico = ico_1; 220 ico.direntry.dwDIBOffset = sizeof(ico); 221 test_ico_data(&ico, sizeof(ico), WINCODEC_ERR_BADIMAGE); 222 223 ico = ico_1; 224 ico.direntry.dwDIBSize = sizeof(ico); 225 test_ico_data(&ico, sizeof(ico), WINCODEC_ERR_BADIMAGE); 226 227 /* Header fields validation. */ 228 ico = ico_1; 229 ico.header.idReserved = 1; 230 test_ico_data_todo(&ico, sizeof(ico), S_OK); 231 ico.header.idReserved = 0; 232 ico.header.idType = 100; 233 test_ico_data_todo(&ico, sizeof(ico), S_OK); 234 235 /* Premature end of data. */ 236 ico = ico_1; 237 test_ico_data(&ico, sizeof(ico.header) - 1, WINCODEC_ERR_STREAMREAD); 238 test_ico_data(&ico, sizeof(ico.header) + sizeof(ico.direntry) - 1, WINCODEC_ERR_BADIMAGE); 239 } 240 241 START_TEST(icoformat) 242 { 243 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 244 245 test_decoder(); 246 247 CoUninitialize(); 248 } 249