1 /*
2  * Unit tests for video playback
3  *
4  * Copyright 2008,2010 Jörg Höhle
5  * Copyright 2008 Austin English
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #define WIN32_LEAN_AND_MEAN
23 #include <windows.h>
24 #include <vfw.h>
25 
26 #include "wine/test.h"
27 
get_stride(int width,int depth)28 static inline int get_stride(int width, int depth)
29 {
30     return ((depth * width + 31) >> 3) & ~3;
31 }
32 
test_OpenCase(void)33 static void test_OpenCase(void)
34 {
35     HIC h;
36     ICINFO info;
37     /* Check if default handler works */
38     h = ICOpen(mmioFOURCC('v','i','d','c'),0,ICMODE_DECOMPRESS);
39     ok(0!=h,"ICOpen(vidc.0) failed\n");
40     if (h) {
41         info.dwSize = sizeof(info);
42         info.szName[0] = 0;
43         ICGetInfo(h, &info, sizeof(info));
44         trace("The default decompressor is %s\n", wine_dbgstr_w(info.szName));
45         ok(ICClose(h)==ICERR_OK,"ICClose failed\n");
46     }
47     h = ICOpen(mmioFOURCC('v','i','d','c'),0,ICMODE_COMPRESS);
48     ok(0!=h || broken(h == 0),"ICOpen(vidc.0) failed\n");  /* Not present in Win8 */
49     if (h) {
50         info.dwSize = sizeof(info);
51         info.szName[0] = 0;
52         ICGetInfo(h, &info, sizeof(info));
53         trace("The default compressor is %s\n", wine_dbgstr_w(info.szName));
54         ok(ICClose(h)==ICERR_OK,"ICClose failed\n");
55     }
56 
57     /* Open a compressor with combinations of lowercase
58      * and uppercase compressortype and handler.
59      */
60     h = ICOpen(mmioFOURCC('v','i','d','c'),mmioFOURCC('m','s','v','c'),ICMODE_DECOMPRESS);
61     ok(0!=h,"ICOpen(vidc.msvc) failed\n");
62     if (h) {
63         ok(ICClose(h)==ICERR_OK,"ICClose failed\n");
64     }
65     h = ICOpen(mmioFOURCC('v','i','d','c'),mmioFOURCC('M','S','V','C'),ICMODE_DECOMPRESS);
66     ok(0!=h,"ICOpen(vidc.MSVC) failed\n");
67     if (h) {
68         ok(ICClose(h)==ICERR_OK,"ICClose failed\n");
69     }
70     h = ICOpen(mmioFOURCC('V','I','D','C'),mmioFOURCC('m','s','v','c'),ICMODE_DECOMPRESS);
71     ok(0!=h,"ICOpen(VIDC.msvc) failed\n");
72     if (h) {
73         ok(ICClose(h)==ICERR_OK,"ICClose failed\n");
74     }
75     h = ICOpen(mmioFOURCC('V','I','D','C'),mmioFOURCC('M','S','V','C'),ICMODE_DECOMPRESS);
76     ok(0!=h,"ICOpen(VIDC.MSVC) failed\n");
77     if (h) {
78         ok(ICClose(h)==ICERR_OK,"ICClose failed\n");
79     }
80     h = ICOpen(mmioFOURCC('v','i','d','c'),mmioFOURCC('m','S','v','C'),ICMODE_DECOMPRESS);
81     ok(0!=h,"ICOpen(vidc.mSvC) failed\n");
82     if (h) {
83         ok(ICClose(h)==ICERR_OK,"ICClose failed\n");
84     }
85     h = ICOpen(mmioFOURCC('v','I','d','C'),mmioFOURCC('m','s','v','c'),ICMODE_DECOMPRESS);
86     ok(0!=h,"ICOpen(vIdC.msvc) failed\n");
87     if (h) {
88         ok(ICClose(h)==ICERR_OK,"ICClose failed\n");
89     }
90 }
91 
test_Locate(void)92 static void test_Locate(void)
93 {
94     static BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RLE8, 0,100000,100000, 0,0};
95     static BITMAPINFOHEADER bo = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RGB, 0,100000,100000, 0,0};
96     BITMAPINFOHEADER tmp = {sizeof(BITMAPINFOHEADER)};
97     HIC h;
98     DWORD err;
99 
100     /* Oddly, MSDN documents that ICLocate takes BITMAPINFOHEADER
101      * pointers, while ICDecompressQuery takes the larger
102      * BITMAPINFO.  Probably it's all the same as long as the
103      * variable length color quads are present when they are
104      * needed. */
105 
106     h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
107     ok(h != 0, "RLE8->RGB failed\n");
108     if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
109 
110     bo.biHeight = - bo.biHeight;
111     h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
112     ok(h == 0, "RLE8->RGB height<0 succeeded\n");
113     if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
114     bo.biHeight = - bo.biHeight;
115 
116     bi.biCompression = mmioFOURCC('c','v','i','d'); /* Cinepak */
117     h = ICOpen(ICTYPE_VIDEO, mmioFOURCC('c','v','i','d'), ICMODE_DECOMPRESS);
118     if (h == 0) win_skip("Cinepak/ICCVID codec not found\n");
119     else {
120         bo.biBitCount = bi.biBitCount = 32;
121         err = ICDecompressQuery(h, &bi, &bo);
122         ok(err == ICERR_OK, "Query cvid->RGB32: %d\n", err);
123 
124         err = ICDecompressQuery(h, &bi, NULL);
125         ok(err == ICERR_OK, "Query cvid 32: %d\n", err);
126 
127         bo.biHeight = -bo.biHeight;
128         err = ICDecompressQuery(h, &bi, &bo);
129         ok(err == ICERR_OK, "Query cvid->RGB32 height<0: %d\n", err);
130         bo.biHeight = -bo.biHeight;
131 
132         bi.biWidth = 17;
133 
134         bi.biBitCount = 8;
135         err = ICDecompressGetFormat(h, &bi, &tmp);
136         ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
137         ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
138         ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
139            get_stride(17, 24) * 8, tmp.biSizeImage);
140 
141         bi.biBitCount = 15;
142         err = ICDecompressGetFormat(h, &bi, &tmp);
143         ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
144         ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
145         ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
146            get_stride(17, 24) * 8, tmp.biSizeImage);
147 
148         bi.biBitCount = 16;
149         err = ICDecompressGetFormat(h, &bi, &tmp);
150         ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
151         ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
152         ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
153            get_stride(17, 24) * 8, tmp.biSizeImage);
154 
155         bi.biBitCount = 24;
156         err = ICDecompressGetFormat(h, &bi, &tmp);
157         ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
158         ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
159         ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
160            get_stride(17, 24) * 8, tmp.biSizeImage);
161 
162         bi.biBitCount = 32;
163         err = ICDecompressGetFormat(h, &bi, &tmp);
164         ok(err == ICERR_OK, "Query cvid output format: %d\n", err);
165         ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount);
166         ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n",
167            get_stride(17, 24) * 8, tmp.biSizeImage);
168 
169         bi.biWidth = 32;
170 
171         ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
172 
173         bo.biBitCount = bi.biBitCount = 8;
174         h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
175         todo_wine ok(h != 0, "cvid->RGB8 failed\n");
176         if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
177         bo.biHeight = - bo.biHeight;
178         h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
179         todo_wine ok(h != 0, "cvid->RGB8 height<0 failed\n");
180         if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
181         bo.biHeight = - bo.biHeight;
182 
183         bo.biBitCount = bi.biBitCount = 16;
184         h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
185         ok(h != 0, "cvid->RGB16 failed\n");
186         if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
187         bo.biHeight = - bo.biHeight;
188         h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
189         ok(h != 0, "cvid->RGB16 height<0 failed\n");
190         if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
191         bo.biHeight = - bo.biHeight;
192 
193         bo.biBitCount = bi.biBitCount = 32;
194         h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
195         ok(h != 0, "cvid->RGB32 failed\n");
196         if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
197         bo.biHeight = - bo.biHeight;
198         h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
199         ok(h != 0, "cvid->RGB32 height<0 failed\n");
200         if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
201         bo.biHeight = - bo.biHeight;
202 
203         bi.biCompression = mmioFOURCC('C','V','I','D');
204         /* Unlike ICOpen, upper case fails with ICLocate. */
205         h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
206         ok(h == 0, "CVID->RGB32 upper case succeeded\n");
207         if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
208     }
209 
210     bi.biCompression = mmioFOURCC('M','S','V','C'); /* MS Video 1 */
211 
212     bo.biBitCount = bi.biBitCount = 16;
213     h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
214     ok(h != 0, "MSVC->RGB16 failed\n");
215     if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
216 
217     bo.biHeight = - bo.biHeight;
218     h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
219     todo_wine ok(h != 0, "MSVC->RGB16 height<0 failed\n");
220     if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
221     bo.biHeight = - bo.biHeight;
222 
223     bo.biHeight--;
224     h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
225     ok(h == 0, "MSVC->RGB16 height too small succeeded\n");
226     if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
227     bo.biHeight++;
228 
229     /* ICLocate wants upper case MSVC */
230     bi.biCompression = mmioFOURCC('m','s','v','c');
231     h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
232     ok(h == 0, "msvc->RGB16 succeeded\n");
233     if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
234 
235     bi.biCompression = mmioFOURCC('M','S','V','C');
236     h = ICOpen(ICTYPE_VIDEO, mmioFOURCC('M','S','V','C'), ICMODE_DECOMPRESS);
237     ok(h != 0, "No MSVC codec installed!?\n");
238     if (h != 0) {
239         err = ICDecompressQuery(h, &bi, &bo);
240         ok(err == ICERR_OK, "Query MSVC->RGB16: %d\n", err);
241 
242         err = ICDecompressQuery(h, &bi, NULL);
243         ok(err == ICERR_OK, "Query MSVC 16: %d\n", err);
244 
245         bo.biHeight = -bo.biHeight;
246         err = ICDecompressQuery(h, &bi, &bo);
247         todo_wine ok(err == ICERR_OK, "Query MSVC->RGB16 height<0: %d\n", err);
248         bo.biHeight = -bo.biHeight;
249 
250         bo.biBitCount = 24;
251         err = ICDecompressQuery(h, &bi, &bo);
252         ok(err == ICERR_OK, "Query MSVC 16->24: %d\n", err);
253         bo.biBitCount = 16;
254 
255         bi.biWidth = 553;
256 
257         bi.biBitCount = 8;
258         err = ICDecompressGetFormat(h, &bi, &tmp);
259         ok(err == ICERR_OK, "Query MSVC output format: %d\n", err);
260         ok(tmp.biBitCount == 8, "Expected 8 bit, got %d bit\n", tmp.biBitCount);
261         ok(tmp.biWidth == 552, "Expected width 552, got %d\n", tmp.biWidth);
262         ok(tmp.biSizeImage == get_stride(552, 8) * 8, "Expected size %d, got %d\n",
263            get_stride(552, 8) * 8, tmp.biSizeImage);
264 
265         bi.biBitCount = 15;
266         err = ICDecompressGetFormat(h, &bi, &tmp);
267         ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err);
268 
269         bi.biBitCount = 16;
270         err = ICDecompressGetFormat(h, &bi, &tmp);
271         ok(err == ICERR_OK, "Query MSVC output format: %d\n", err);
272         ok(tmp.biBitCount == 16, "Expected 16 bit, got %d bit\n", tmp.biBitCount);
273         ok(tmp.biWidth == 552, "Expected width 552, got %d\n", tmp.biWidth);
274         ok(tmp.biSizeImage == get_stride(552, 16) * 8, "Expected size %d, got %d\n",
275            get_stride(552, 16) * 8, tmp.biSizeImage);
276 
277         bi.biBitCount = 24;
278         err = ICDecompressGetFormat(h, &bi, &tmp);
279         ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err);
280 
281         bi.biBitCount = 32;
282         err = ICDecompressGetFormat(h, &bi, &tmp);
283         ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err);
284 
285         bi.biHeight = 17;
286         bi.biBitCount = 8;
287         err = ICDecompressGetFormat(h, &bi, &tmp);
288         ok(err == ICERR_OK, "Query MSVC output format: %d\n", err);
289         ok(tmp.biHeight == 16, "Expected height 16, got %d\n", tmp.biHeight);
290         bi.biHeight = 8;
291 
292         bi.biWidth = 32;
293 
294         bi.biCompression = mmioFOURCC('m','s','v','c');
295         err = ICDecompressQuery(h, &bi, &bo);
296         ok(err == ICERR_BADFORMAT, "Query msvc->RGB16: %d\n", err);
297 
298         ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
299     }
300 
301     bi.biCompression = BI_RGB;
302     bo.biBitCount = bi.biBitCount = 8;
303     h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
304     ok(h != 0, "RGB8->RGB identity failed\n");
305     if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
306 
307     bi.biCompression = BI_RLE8;
308     h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS);
309     ok(h != 0, "RLE8->RGB again failed\n");
310     if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n");
311 }
312 
test_ICSeqCompress(void)313 static void test_ICSeqCompress(void)
314 {
315     /* The purpose of this test is to validate sequential frame compressing
316      * functions. The MRLE codec will be used because Wine supports it and
317      * it is present in any Windows.
318      */
319     HIC h;
320     DWORD err, vidc = mmioFOURCC('v','i','d','c'), mrle = mmioFOURCC('m', 'r', 'l', 'e');
321     DWORD i;
322     LONG frame_len;
323     BOOL key_frame, ret;
324     char *frame;
325     COMPVARS pc;
326     struct { BITMAPINFOHEADER header; RGBQUAD map[256]; }
327     input_header = { {sizeof(BITMAPINFOHEADER), 32, 1, 1, 8, 0, 32*8, 0, 0, 256, 256},
328                      {{255,0,0}, {0,255,0}, {0,0,255}, {255,255,255}}};
329     PBITMAPINFO bitmap = (PBITMAPINFO) &input_header;
330     static BYTE input[32] = {1,2,3,3,3,3,2,3,1};
331     static const BYTE output_kf[] = {1,1,1,2,4,3,0,3,2,3,1,0,23,0,0,0,0,1}, /* key frame*/
332                       output_nkf[] = {0,0,0,1}; /* non key frame */
333 
334     h = ICOpen(vidc, mrle, ICMODE_COMPRESS);
335     ok(h != NULL, "Expected non-NULL\n");
336 
337     pc.cbSize = sizeof(pc);
338     pc.dwFlags    = ICMF_COMPVARS_VALID;
339     pc.fccType    = vidc;
340     pc.fccHandler = mrle;
341     pc.hic        = h;
342     pc.lpbiIn     = NULL;
343     pc.lpbiOut    = NULL;
344     pc.lpBitsOut  = pc.lpBitsPrev = pc.lpState = NULL;
345     pc.lQ         = ICQUALITY_DEFAULT;
346     pc.lKey       = 1;
347     pc.lDataRate  = 300;
348     pc.lpState    = NULL;
349     pc.cbState    = 0;
350 
351     ret = ICSeqCompressFrameStart(&pc, bitmap);
352     ok(ret == TRUE, "Expected TRUE\n");
353     /* Check that reserved pointers were allocated */
354     ok(pc.lpbiIn != NULL, "Expected non-NULL\n");
355     ok(pc.lpbiOut != NULL, "Expected non-NULL\n");
356 
357     for(i = 0; i < 9; i++)
358     {
359         frame_len = 0;
360         frame = ICSeqCompressFrame(&pc, 0, input, &key_frame, &frame_len);
361         ok(frame != NULL, "Frame[%d]: Expected non-NULL\n", i);
362         if (frame_len == sizeof(output_nkf))
363             ok(!memcmp(output_nkf, frame, frame_len), "Frame[%d]: Contents do not match\n", i);
364         else if (frame_len == sizeof(output_kf))
365             ok(!memcmp(output_kf, frame, frame_len), "Frame[%d]: Contents do not match\n", i);
366         else
367             ok(0, "Unknown frame size of %d byten\n", frame_len);
368     }
369 
370     ICSeqCompressFrameEnd(&pc);
371     ICCompressorFree(&pc);
372     /* ICCompressorFree already closed the HIC */
373     err = ICClose(h);
374     ok(err == ICERR_BADHANDLE, "Expected -8, got %d\n", err);
375 }
376 
377 static ICINFO enum_info;
378 
enum_driver_proc(DWORD_PTR id,HDRVR driver,UINT msg,LPARAM lparam1,LPARAM lparam2)379 static LRESULT CALLBACK enum_driver_proc(DWORD_PTR id, HDRVR driver, UINT msg,
380         LPARAM lparam1, LPARAM lparam2)
381 {
382     ICINFO *info = (ICINFO *)lparam1;
383 
384     ok(!id, "Got unexpected id %#lx.\n", id);
385     ok(msg == ICM_GETINFO, "Got unexpected message %#x.\n", msg);
386     ok(info == &enum_info, "Expected lparam1 %p, got %p.\n", &enum_info, info);
387     ok(lparam2 == sizeof(ICINFO), "Got lparam2 %ld.\n", lparam2);
388 
389     ok(!info->fccType, "Got unexpected type %#x.\n", info->fccType);
390     ok(!info->fccHandler, "Got unexpected handler %#x.\n", info->fccHandler);
391     ok(!info->dwFlags, "Got unexpected flags %#x.\n", info->dwFlags);
392     ok(!info->dwVersion, "Got unexpected version %#x.\n", info->dwVersion);
393     ok(info->dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info->dwVersionICM);
394     ok(!info->szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info->szName));
395     ok(!info->szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info->szDescription));
396     ok(!info->szDriver[0], "Got unexpected driver %s.\n", wine_dbgstr_w(info->szDriver));
397 
398     info->dwVersion = 0xdeadbeef;
399     return sizeof(ICINFO);
400 }
401 
test_ICInfo(void)402 static void test_ICInfo(void)
403 {
404     static const WCHAR bogusW[] = {'b','o','g','u','s',0};
405     static const DWORD test_type = mmioFOURCC('w','i','n','e');
406     static const DWORD test_handler = mmioFOURCC('t','e','s','t');
407     DWORD i = 0, found = 0;
408     char buffer[MAX_PATH];
409     ICINFO info, info2;
410     unsigned char *fcc;
411     DWORD size;
412     BOOL ret;
413     HKEY key;
414     LONG res;
415 
416     for (;;)
417     {
418         memset(&info, 0x55, sizeof(info));
419         info.dwSize = sizeof(info);
420         if (!ICInfo(0, i++, &info))
421             break;
422         trace("Codec name: %s, fccHandler: 0x%08x\n", wine_dbgstr_w(info.szName), info.fccHandler);
423         ok(info.fccType, "Expected nonzero type.\n");
424         ok(info.fccHandler, "Expected nonzero handler.\n");
425         ok(!info.dwFlags, "Got unexpected flags %#x.\n", info.dwFlags);
426         ok(!info.dwVersion, "Got unexpected version %#x.\n", info.dwVersion);
427         ok(info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info.dwVersionICM);
428         ok(!info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szName));
429         ok(!info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szDescription));
430 
431         ok(ICInfo(info.fccType, info.fccHandler, &info2),
432            "ICInfo failed on fcc 0x%08x\n", info.fccHandler);
433 
434         fcc = (unsigned char *)&info.fccHandler;
435         if (!isalpha(fcc[0])) continue;
436 
437         found++;
438         /* Test getting info with a different case - bug 41602 */
439         fcc[0] ^= 0x20;
440         ok(ICInfo(info.fccType, info.fccHandler, &info2),
441            "ICInfo failed on fcc 0x%08x\n", info.fccHandler);
442     }
443     ok(found != 0, "expected at least one codec\n");
444 
445     memset(&info, 0x55, sizeof(info));
446     info.dwSize = sizeof(info);
447     ok(!ICInfo(ICTYPE_VIDEO, mmioFOURCC('f','a','k','e'), &info), "expected failure\n");
448     ok(info.fccType == ICTYPE_VIDEO, "got 0x%08x\n", info.fccType);
449     ok(info.fccHandler == mmioFOURCC('f','a','k','e'), "got 0x%08x\n", info.fccHandler);
450     ok(!info.dwFlags, "Got unexpected flags %#x.\n", info.dwFlags);
451     ok(!info.dwVersion, "Got unexpected version %#x.\n", info.dwVersion);
452     ok(info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info.dwVersionICM);
453     ok(!info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szName));
454     ok(!info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szDescription));
455     ok(!info.szDriver[0], "Got unexpected driver %s.\n", wine_dbgstr_w(info.szDriver));
456 
457     if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT"
458             "\\CurrentVersion\\Drivers32", 0, KEY_ALL_ACCESS, &key))
459     {
460         ret = ICInstall(test_type, test_handler, (LPARAM)"bogus", NULL, ICINSTALL_DRIVER);
461         ok(ret, "Failed to install driver.\n");
462 
463         size = sizeof(buffer);
464         res = RegQueryValueExA(key, "wine.test", NULL, NULL, (BYTE *)buffer, &size);
465         ok(!res, "Failed to query value, error %d.\n", res);
466         ok(!strcmp(buffer, "bogus"), "Got unexpected value \"%s\".\n", buffer);
467 
468         memset(&info, 0x55, sizeof(info));
469         info.dwSize = sizeof(info);
470         ok(ICInfo(test_type, test_handler, &info), "Expected success.\n");
471         ok(info.fccType == test_type, "Got unexpected type %#x.\n", info.fccType);
472         ok(info.fccHandler == test_handler, "Got unexpected handler %#x.\n", info.fccHandler);
473         ok(!info.dwFlags, "Got unexpected flags %#x.\n", info.dwFlags);
474         ok(!info.dwVersion, "Got unexpected version %#x.\n", info.dwVersion);
475         ok(info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info.dwVersionICM);
476         ok(!info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szName));
477         ok(!info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szDescription));
478         ok(!lstrcmpW(info.szDriver, bogusW), "Got unexpected driver %s.\n", wine_dbgstr_w(info.szDriver));
479 
480         /* Drivers installed after msvfw32 is loaded are not enumerated. */
481 todo_wine
482         ok(!ICInfo(test_type, 0, &info), "Expected failure.\n");
483 
484         ret = ICRemove(test_type, test_handler, 0);
485         ok(ret, "Failed to remove driver.\n");
486 
487         res = RegDeleteValueA(key, "wine.test");
488         ok(res == ERROR_FILE_NOT_FOUND, "Got error %u.\n", res);
489         RegCloseKey(key);
490     }
491     else
492         win_skip("Not enough permissions to register codec drivers.\n");
493 
494     if (WritePrivateProfileStringA("drivers32", "wine.test", "bogus", "system.ini"))
495     {
496         memset(&info, 0x55, sizeof(info));
497         info.dwSize = sizeof(info);
498         ok(ICInfo(test_type, test_handler, &info), "Expected success.\n");
499         ok(info.fccType == test_type, "Got unexpected type %#x.\n", info.fccType);
500         ok(info.fccHandler == test_handler, "Got unexpected handler %#x.\n", info.fccHandler);
501         ok(!info.dwFlags, "Got unexpected flags %#x.\n", info.dwFlags);
502         ok(!info.dwVersion, "Got unexpected version %#x.\n", info.dwVersion);
503         ok(info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info.dwVersionICM);
504         ok(!info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szName));
505         ok(!info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szDescription));
506         ok(!lstrcmpW(info.szDriver, bogusW), "Got unexpected driver %s.\n", wine_dbgstr_w(info.szDriver));
507 
508         /* Drivers installed after msvfw32 is loaded are not enumerated. */
509 todo_wine
510         ok(!ICInfo(test_type, 0, &info), "Expected failure.\n");
511 
512         ret = WritePrivateProfileStringA("drivers32", "wine.test", NULL, "system.ini");
513         ok(ret, "Failed to remove INI entry.\n");
514     }
515 
516     ret = ICInstall(test_type, test_handler, (LPARAM)enum_driver_proc, NULL, ICINSTALL_FUNCTION);
517     ok(ret, "Failed to install driver.\n");
518 
519     memset(&enum_info, 0x55, sizeof(enum_info));
520     enum_info.dwSize = sizeof(enum_info);
521     ok(ICInfo(test_type, test_handler, &enum_info), "Expected success.\n");
522     ok(!enum_info.fccType, "Got unexpected type %#x.\n", enum_info.fccType);
523     ok(!enum_info.fccHandler, "Got unexpected handler %#x.\n", enum_info.fccHandler);
524     ok(!enum_info.dwFlags, "Got unexpected flags %#x.\n", enum_info.dwFlags);
525     ok(enum_info.dwVersion == 0xdeadbeef, "Got unexpected version %#x.\n", enum_info.dwVersion);
526     ok(enum_info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", enum_info.dwVersionICM);
527     ok(!enum_info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(enum_info.szName));
528     ok(!enum_info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(enum_info.szDescription));
529     ok(!enum_info.szDriver[0], "Got unexpected driver %s.\n", wine_dbgstr_w(enum_info.szDriver));
530 
531     /* Functions installed after msvfw32 is loaded are enumerated. */
532     memset(&enum_info, 0x55, sizeof(enum_info));
533     enum_info.dwSize = sizeof(enum_info);
534     ok(ICInfo(test_type, 0, &enum_info), "Expected success.\n");
535     ok(!enum_info.fccType, "Got unexpected type %#x.\n", enum_info.fccType);
536     ok(!enum_info.fccHandler, "Got unexpected handler %#x.\n", enum_info.fccHandler);
537     ok(!enum_info.dwFlags, "Got unexpected flags %#x.\n", enum_info.dwFlags);
538     ok(enum_info.dwVersion == 0xdeadbeef, "Got unexpected version %#x.\n", enum_info.dwVersion);
539     ok(enum_info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", enum_info.dwVersionICM);
540     ok(!enum_info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(enum_info.szName));
541     ok(!enum_info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(enum_info.szDescription));
542     ok(!enum_info.szDriver[0], "Got unexpected driver %s.\n", wine_dbgstr_w(enum_info.szDriver));
543 
544     ret = ICRemove(test_type, test_handler, 0);
545     ok(ret, "Failed to remove driver.\n");
546 }
547 
548 static int get_display_format_test;
549 
get_size_image(LONG width,LONG height,WORD depth)550 static DWORD get_size_image(LONG width, LONG height, WORD depth)
551 {
552     DWORD ret = width * depth;
553     ret = (ret + 7) / 8;    /* divide by byte size, rounding up */
554     ret = (ret + 3) & ~3;   /* align to 4 bytes */
555     ret *= abs(height);
556     return ret;
557 }
558 
559 static const RGBQUAD color_yellow = {0x00, 0xff, 0xff, 0x00};
560 
561 static BITMAPINFOHEADER gdf_in, *gdf_out;
562 
gdf_driver_proc(DWORD_PTR id,HDRVR driver,UINT msg,LPARAM lparam1,LPARAM lparam2)563 static LRESULT CALLBACK gdf_driver_proc(DWORD_PTR id, HDRVR driver, UINT msg,
564     LPARAM lparam1, LPARAM lparam2)
565 {
566     LRESULT ret = 0;
567 
568     if (winetest_debug > 1)
569         trace("(%#lx, %p, %#x, %#lx, %#lx)\n", id, driver, msg, lparam1, lparam2);
570 
571     switch(msg)
572     {
573     case DRV_LOAD:
574     case DRV_OPEN:
575     case DRV_CLOSE:
576     case DRV_FREE:
577         return 1;
578     case ICM_DECOMPRESS_QUERY:
579     {
580         BITMAPINFOHEADER *out = (BITMAPINFOHEADER *)lparam2;
581         DWORD expected_size;
582 
583         ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1);
584 
585         if (!out)
586             return ICERR_OK;
587 
588         ok(out == gdf_out, "got output %p\n", out);
589 
590         ok(out->biSize == sizeof(*out), "got size %d\n", out->biSize);
591         expected_size = get_size_image(out->biWidth, out->biHeight, out->biBitCount);
592         ok(out->biSizeImage == expected_size, "expected image size %d, got %d\n",
593             expected_size, out->biSizeImage);
594 
595         ok(out->biPlanes == 0xcccc, "got planes %d\n", out->biPlanes);
596         ok(out->biXPelsPerMeter == 0xcccccccc && out->biYPelsPerMeter == 0xcccccccc,
597             "got resolution %dx%d\n", out->biXPelsPerMeter, out->biYPelsPerMeter);
598         ok(out->biClrUsed == 0xcccccccc, "got biClrUsed %u\n", out->biClrUsed);
599         ok(out->biClrImportant == 0xcccccccc, "got biClrImportant %u\n", out->biClrImportant);
600 
601         switch (get_display_format_test)
602         {
603             case 0:
604                 return ICERR_OK;
605             case 1:
606                 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 16)
607                     return ICERR_OK;
608                 break;
609             case 2:
610                 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_BITFIELDS && out->biBitCount == 16)
611                     return ICERR_OK;
612                 break;
613             case 3:
614                 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 24)
615                     return ICERR_OK;
616                 break;
617             case 4:
618                 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 32)
619                     return ICERR_OK;
620                 break;
621             case 5:
622                 if (out->biWidth == 10 && out->biHeight == 20 && out->biCompression == BI_RGB && out->biBitCount == 32)
623                     return ICERR_OK;
624                 break;
625             case 6:
626                 break;
627         }
628 
629         return ICERR_BADFORMAT;
630     }
631     case ICM_DECOMPRESS_GET_FORMAT:
632     {
633         BITMAPINFOHEADER *out = (BITMAPINFOHEADER *)lparam2;
634 
635         ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1);
636         if (out)
637         {
638             ok(out == gdf_out, "got output %p\n", out);
639 
640             memset(out, 0x55, sizeof(*out));
641             out->biWidth = 50;
642             out->biHeight = 60;
643             out->biBitCount = 0xdead;
644             out->biCompression = 0xbeef;
645             out->biSizeImage = 0;
646 
647             return ICERR_OK;
648         }
649     }
650     case ICM_DECOMPRESS_GET_PALETTE:
651     {
652         BITMAPINFO *out = (BITMAPINFO *)lparam2;
653 
654         ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1);
655         if (out)
656         {
657             ok(out == (BITMAPINFO *)gdf_out, "got output %p\n", out);
658 
659             out->bmiHeader.biClrUsed = 1;
660             out->bmiColors[0] = color_yellow;
661 
662             return 0xdeadbeef;
663         }
664     }
665     }
666 
667     return ret;
668 }
669 
check_bitmap_header_(int line,BITMAPINFOHEADER * header,LONG width,LONG height,WORD depth,DWORD compression)670 static void check_bitmap_header_(int line, BITMAPINFOHEADER *header, LONG width, LONG height, WORD depth, DWORD compression)
671 {
672     ok_(__FILE__, line)(header->biWidth == width, "expected %d, got %d\n", width, header->biWidth);
673     ok_(__FILE__, line)(header->biHeight == height, "expected %d, got %d\n", height, header->biHeight);
674     ok_(__FILE__, line)(header->biBitCount == depth, "expected %d, got %d\n", depth, header->biBitCount);
675     ok_(__FILE__, line)(header->biCompression == compression, "expected %#x, got %#x\n", compression, header->biCompression);
676 }
677 #define check_bitmap_header(a,b,c,d,e) check_bitmap_header_(__LINE__,a,b,c,d,e)
678 
test_ICGetDisplayFormat(void)679 static void test_ICGetDisplayFormat(void)
680 {
681     static const DWORD testcc = mmioFOURCC('t','e','s','t');
682 #ifdef __REACTOS__
683     char outbuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
684 #else
685     char outbuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
686 #endif
687     BITMAPINFO *out_bmi;
688     LRESULT lres;
689     BOOL ret;
690     HIC hic;
691 
692     memset(&gdf_in, 0xcc, sizeof(gdf_in));
693     gdf_in.biSize = sizeof(gdf_in);
694     gdf_in.biWidth = 10;
695     gdf_in.biHeight = 20;
696     gdf_in.biBitCount = 1;
697     gdf_in.biCompression = testcc;
698 
699     ret = ICInstall(ICTYPE_VIDEO, testcc, (LPARAM)gdf_driver_proc, NULL, ICINSTALL_FUNCTION);
700     ok(ret, "ICInstall failed\n");
701 
702     hic = ICOpen(ICTYPE_VIDEO, testcc, ICMODE_DECOMPRESS);
703     ok(ret, "ICOpen failed\n");
704 
705     memset(outbuf, 0, sizeof(outbuf));
706     gdf_out = (BITMAPINFOHEADER *)outbuf;
707 
708     /* ICGetDisplayFormat tries several default formats; make sure those work */
709     get_display_format_test = 0;
710     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
711     ok(hic != NULL, "ICGetDisplayFormat failed\n");
712     check_bitmap_header(gdf_out, 30, 40, 1, BI_RGB);
713 
714     get_display_format_test = 1;
715     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
716     ok(hic != NULL, "ICGetDisplayFormat failed\n");
717     check_bitmap_header(gdf_out, 30, 40, 16, BI_RGB);
718 
719     get_display_format_test = 2;
720     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
721     ok(hic != NULL, "ICGetDisplayFormat failed\n");
722     check_bitmap_header(gdf_out, 30, 40, 16, BI_BITFIELDS);
723 
724     get_display_format_test = 3;
725     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
726     ok(hic != NULL, "ICGetDisplayFormat failed\n");
727     check_bitmap_header(gdf_out, 30, 40, 24, BI_RGB);
728 
729     get_display_format_test = 4;
730     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
731     ok(hic != NULL, "ICGetDisplayFormat failed\n");
732     check_bitmap_header(gdf_out, 30, 40, 32, BI_RGB);
733 
734     get_display_format_test = 5;
735     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
736     ok(hic != NULL, "ICGetDisplayFormat failed\n");
737     check_bitmap_header(gdf_out, 10, 20, 32, BI_RGB);
738 
739     /* if every default format is rejected, the output of
740      * ICM_DECOMPRESS_GET_FORMAT is returned */
741     get_display_format_test = 6;
742     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
743     ok(hic != NULL, "ICGetDisplayFormat failed\n");
744     check_bitmap_header(gdf_out, 50, 60, 0xdead, 0xbeef);
745 
746     /* given bpp is treated as a lower bound */
747     get_display_format_test = 1;
748     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 24, 30, 40);
749     ok(hic != NULL, "ICGetDisplayFormat failed\n");
750     check_bitmap_header(gdf_out, 50, 60, 0xdead, 0xbeef);
751 
752     get_display_format_test = 3;
753     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 24, 30, 40);
754     ok(hic != NULL, "ICGetDisplayFormat failed\n");
755     check_bitmap_header(gdf_out, 30, 40, 24, BI_RGB);
756 
757     get_display_format_test = 0;
758 
759     /* width or height <= 0 causes the input width and height to be supplied */
760     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 0, 40);
761     ok(hic != NULL, "ICGetDisplayFormat failed\n");
762     check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB);
763 
764     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 0);
765     ok(hic != NULL, "ICGetDisplayFormat failed\n");
766     check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB);
767 
768     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, -10, 40);
769     ok(hic != NULL, "ICGetDisplayFormat failed\n");
770     check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB);
771 
772     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, -10);
773     ok(hic != NULL, "ICGetDisplayFormat failed\n");
774     check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB);
775 
776     /* zero bpp causes 32 bpp to be supplied */
777     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 0, 30, 40);
778     ok(hic != NULL, "ICGetDisplayFormat failed\n");
779     ok(gdf_out->biBitCount == 32 || gdf_out->biBitCount == 24,
780         "got %d\n", gdf_out->biBitCount);
781     ok(gdf_out->biCompression == BI_RGB, "got %#x\n", gdf_out->biCompression);
782 
783     /* specifying 8 bpp yields a request for palette colours */
784     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 8, 30, 40);
785     ok(hic != NULL, "ICGetDisplayFormat failed\n");
786     check_bitmap_header(gdf_out, 30, 40, 8, BI_RGB);
787     ok(gdf_out->biClrUsed == 1, "got biClrUsed %u\n", gdf_out->biClrUsed);
788     out_bmi = (BITMAPINFO *)gdf_out;
789     ok(!memcmp(&out_bmi->bmiColors[0], &color_yellow, sizeof(color_yellow)),
790         "got wrong colour\n");
791 
792     lres = ICClose(hic);
793     ok(lres == ICERR_OK, "got %ld\n", lres);
794 
795     ret = ICRemove(ICTYPE_VIDEO, testcc, 0);
796     ok(ret, "ICRemove failed\n");
797 }
798 
START_TEST(msvfw)799 START_TEST(msvfw)
800 {
801     test_OpenCase();
802     test_Locate();
803     test_ICSeqCompress();
804     test_ICInfo();
805     test_ICGetDisplayFormat();
806 }
807