[MSVFW32_WINETEST] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / modules / rostests / winetests / msvfw32 / msvfw.c
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
28 static inline int get_stride(int width, int depth)
29 {
30 return ((depth * width + 31) >> 3) & ~3;
31 }
32
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
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
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
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
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
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
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
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
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
799 START_TEST(msvfw)
800 {
801 test_OpenCase();
802 test_Locate();
803 test_ICSeqCompress();
804 test_ICInfo();
805 test_ICGetDisplayFormat();
806 }