1 /* 2 * Copyright 2014 Akihiro Sagawa 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 #define WIN32_LEAN_AND_MEAN 20 21 #include <windows.h> 22 #include <vfw.h> 23 #include <wincrypt.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 #include "wine/test.h" 28 29 #define WIDTH 16 30 #define HEIGHT 12 31 32 static HCRYPTPROV crypt_prov; 33 34 static inline DWORD get_stride(const BITMAPINFO *bmi) 35 { 36 return ((bmi->bmiHeader.biBitCount * bmi->bmiHeader.biWidth + 31) >> 3) & ~3; 37 } 38 39 static inline DWORD get_dib_size(const BITMAPINFO *bmi) 40 { 41 return get_stride(bmi) * abs(bmi->bmiHeader.biHeight); 42 } 43 44 static char *hash_dib(const BITMAPINFO *bmi, const void *bits) 45 { 46 DWORD dib_size = get_dib_size(bmi); 47 HCRYPTHASH hash; 48 char *buf; 49 BYTE hash_buf[20]; 50 DWORD hash_size = sizeof(hash_buf); 51 int i; 52 static const char *hex = "0123456789abcdef"; 53 54 if(!crypt_prov) return NULL; 55 56 if(!CryptCreateHash(crypt_prov, CALG_SHA1, 0, 0, &hash)) return NULL; 57 58 CryptHashData(hash, bits, dib_size, 0); 59 60 CryptGetHashParam(hash, HP_HASHVAL, NULL, &hash_size, 0); 61 if(hash_size != sizeof(hash_buf)) return NULL; 62 63 CryptGetHashParam(hash, HP_HASHVAL, hash_buf, &hash_size, 0); 64 CryptDestroyHash(hash); 65 66 buf = HeapAlloc(GetProcessHeap(), 0, hash_size * 2 + 1); 67 68 for(i = 0; i < hash_size; i++) 69 { 70 buf[i * 2] = hex[hash_buf[i] >> 4]; 71 buf[i * 2 + 1] = hex[hash_buf[i] & 0xf]; 72 } 73 buf[i * 2] = '\0'; 74 75 return buf; 76 } 77 78 static void init_bmi(BITMAPINFO *bmi, LONG width, LONG height, DWORD size) 79 { 80 memset(bmi, 0, sizeof(*bmi)); 81 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 82 bmi->bmiHeader.biWidth = width; 83 bmi->bmiHeader.biHeight = height; 84 bmi->bmiHeader.biPlanes = 1; 85 bmi->bmiHeader.biBitCount = 32; 86 bmi->bmiHeader.biCompression = BI_RGB; 87 bmi->bmiHeader.biSizeImage = size; 88 } 89 90 static void test_DrawDib_sizeimage(void) 91 { 92 const struct { 93 LONG width, height; 94 DWORD size; 95 char hash[41]; 96 } test_data[] = { 97 /* [0] correct size */ 98 { WIDTH, HEIGHT, WIDTH * HEIGHT * sizeof(RGBQUAD), "bc943d5ab024b8b0118d0a80aa283055d39942b8" }, 99 /* [1] zero size */ 100 { WIDTH, HEIGHT, 0, "bc943d5ab024b8b0118d0a80aa283055d39942b8" }, 101 /* error patterns */ 102 { WIDTH, -HEIGHT, 0, "" }, 103 { -WIDTH, HEIGHT, 0, "" }, 104 { -WIDTH, -HEIGHT, 0, "" }, 105 { 0, 0, 0, "" }, 106 { 0, HEIGHT, 0, "" }, 107 { WIDTH, 0, 0, "" }, 108 /* [8] zero size (to compare [9], [10] ) */ 109 { WIDTH, HEIGHT/2, 0, "8b75bf6d54a8645380114fe77505ee0699ffffaa" }, 110 /* [9] insufficient size */ 111 { WIDTH, HEIGHT/2, sizeof(RGBQUAD), "8b75bf6d54a8645380114fe77505ee0699ffffaa" }, 112 /* [10] too much size */ 113 { WIDTH, HEIGHT/2, WIDTH * HEIGHT * sizeof(RGBQUAD), "8b75bf6d54a8645380114fe77505ee0699ffffaa" }, 114 }; 115 HDC hdc; 116 DWORD src_dib_size, dst_dib_size; 117 BOOL r; 118 HBITMAP dib; 119 BITMAPINFO src_info, dst_info; 120 RGBQUAD *src_bits = NULL, *dst_bits; 121 HDRAWDIB hdd; 122 unsigned int i; 123 124 hdc = CreateCompatibleDC(NULL); 125 126 init_bmi(&dst_info, WIDTH, HEIGHT, 0); 127 dib = CreateDIBSection(NULL, &dst_info, DIB_RGB_COLORS, (void **)&dst_bits, NULL, 0); 128 dst_dib_size = get_dib_size(&dst_info); 129 ok(dib != NULL, "CreateDIBSection failed\n"); 130 SelectObject(hdc, dib); 131 132 init_bmi(&src_info, WIDTH, HEIGHT, 0); 133 src_dib_size = get_dib_size(&src_info); 134 src_bits = HeapAlloc(GetProcessHeap(), 0, src_dib_size); 135 ok(src_bits != NULL, "Can't allocate memory\n"); 136 memset(src_bits, 0x88, src_dib_size); 137 138 hdd = DrawDibOpen(); 139 ok(hdd != NULL, "DrawDibOpen failed\n"); 140 141 for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++) { 142 char *hash; 143 memset(dst_bits, 0xff, dst_dib_size); 144 init_bmi(&src_info, test_data[i].width, test_data[i].height, test_data[i].size); 145 r = DrawDibDraw(hdd, hdc, 146 0, 0, -1, -1, &src_info.bmiHeader, src_bits, 147 0, 0, test_data[i].width, test_data[i].height, 0); 148 if (test_data[i].hash[0]) 149 ok(r, "[%u] DrawDibDraw failed, expected success\n", i); 150 else 151 ok(!r, "[%u] DrawDibDraw succeeded, expected failed\n", i); 152 if (!r || !test_data[i].hash[0]) 153 continue; 154 155 hash = hash_dib(&dst_info, dst_bits); 156 if (!hash) { 157 win_skip("This platform doesn't support SHA-1 hash\n"); 158 continue; 159 } 160 ok(strcmp(hash, test_data[i].hash) == 0, 161 "[%u] got %s, expected %s\n", 162 i, hash, test_data[i].hash); 163 HeapFree(GetProcessHeap(), 0, hash); 164 } 165 166 r = DrawDibClose(hdd); 167 ok(r, "DrawDibClose failed\n"); 168 169 HeapFree(GetProcessHeap(), 0, src_bits); 170 171 DeleteDC(hdc); 172 } 173 174 START_TEST(drawdib) 175 { 176 CryptAcquireContextW(&crypt_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 177 test_DrawDib_sizeimage(); 178 CryptReleaseContext(crypt_prov, 0); 179 } 180