2 * Unit test suite for AVI Functions
4 * Copyright 2008 Detlef Riekenberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/test.h"
30 /* ########################### */
32 DEFINE_AVIGUID(CLSID_WAVFile
, 0x00020003, 0, 0);
33 static const CHAR winetest0
[] = "winetest0";
34 static const CHAR winetest1
[] = "winetest1";
35 static const CHAR testfilename
[] = "wine_avifil32_test.avi";
37 /* ########################### */
39 static const DWORD deffh
[] = /* file_header */
41 FOURCC_RIFF
, 0x34c6 /* length */, formtypeAVI
,
42 FOURCC_LIST
, 0x1ac /* length */,
43 listtypeAVIHEADER
, ckidAVIMAINHDR
, sizeof(MainAVIHeader
),
46 static const MainAVIHeader defmah
=
48 0x00008256, /* dwMicroSecPerFrame */
49 0x000080e8, /* dwMaxBytesPerSec */
50 0x00000000, /* dwPaddingGranularity */
51 0x00000910, /* dwFlags */
52 1, /* dwTotalFrames */
53 0, /* dwInitialFrames */
55 0x00100000, /* dwSuggestedBufferSize*/
58 { 0, 0, 0, 0 } /* dwReserved[4] */
61 static const AVIStreamHeader defash0
=
63 streamtypeVIDEO
, /* fccType */
64 0x30323449, /* fccHandler */
65 0x00000000, /* dwFlags */
68 0, /* dwInitialFrames */
69 0x000003e9, /* dwScale */
70 0x00007530, /* dwRate */
73 0x00100000, /* dwSuggestedBufferSize*/
74 0xffffffff, /* dwQuality */
76 { 0, 0, 0, 0 } /* short left right top bottom */
79 static const AVIStreamHeader defash1
=
82 streamtypeAUDIO
, /* fccType */
87 0, /* dwInitialFrames */
89 0x00002b11, /* dwRate */
91 0x00000665, /* dwLength */
92 0x00003000, /* dwSuggestedBufferSize*/
93 0xffffffff, /* dwQuality */
95 { 0, 0, 0, 0 } /* short left right top bottom */
98 static const PCMWAVEFORMAT defpcmwf
=
103 11025, /* nSamplesPerSec */
104 22050, /* nAvgBytesPerSec */
107 8, /* wBitsPerSample */
110 typedef struct common_avi_headers
{
111 DWORD fh
[sizeof(deffh
)];
113 AVIStreamHeader ash0
;
114 AVIStreamHeader ash1
;
116 } COMMON_AVI_HEADERS
;
118 /* Extra data needed to get the VFW API to load the file */
120 /* MainAVIHeader mah */
121 static const DWORD streamlist
[] =
123 FOURCC_LIST
, 0xd4 /* length */,
124 listtypeSTREAMHEADER
, ckidSTREAMHEADER
, 0x38 /* length */,
126 /* AVIStreamHeader ash0 */
127 static const DWORD videostreamformat
[] =
129 ckidSTREAMFORMAT
, 0x28 /* length */,
130 0x00000028, 0x00000008, 0x00000006, 0x00180001,
131 0x30323449, 0x00000090, 0x00000000, 0x00000000,
132 0x00000000, 0x00000000,
134 static const DWORD padding1
[] =
136 ckidAVIPADDING
, 0xc /* length */,
137 0x00000004, 0x00000000, 0x63643030
139 static const DWORD videopropheader
[] =
141 0x70727076, 0x44 /* length */,
142 0x00000000, 0x00000000,
143 0x0000001e, 0x00000008, 0x00000006, 0x00100009,
144 0x00000008, 0x00000006, 0x00000001, 0x00000006,
145 0x00000008, 0x00000006, 0x00000008, 0x00000000,
146 0x00000000, 0x00000000, 0x00000000,
147 FOURCC_LIST
, 0x70 /* length */,
148 listtypeSTREAMHEADER
, ckidSTREAMHEADER
, 0x38 /* length */,
150 /* AVIStreamHeader ash1 */
151 static const DWORD audiostreamformat_pre
[] =
153 ckidSTREAMFORMAT
, sizeof(PCMWAVEFORMAT
) /* length */,
155 /* PCMWAVEFORMAT pcmwf */
156 static DWORD data
[] =
158 ckidAVIPADDING
, 0xc /* length */,
159 0x00000004, 0x00000000, 0x62773130,
160 ckidAVIPADDING
, 0xc /* length */,
161 0x6c6d646f, 0x686c6d64, 0x000000f8,
162 FOURCC_LIST
, 0x18 /* length */,
164 0x54465349, 0xc /* length */,
165 0x6676614c, 0x332e3235, 0x00302e37,
166 ckidAVIPADDING
, 0x4 /* length */,
168 FOURCC_LIST
, 0xd1b /* length */, listtypeAVIMOVIE
,
172 /* ########################### */
174 static void test_AVISaveOptions(void)
176 AVICOMPRESSOPTIONS options
[2];
177 LPAVICOMPRESSOPTIONS poptions
[2];
178 PAVISTREAM streams
[2] = {NULL
, NULL
};
183 poptions
[0] = &options
[0];
184 poptions
[1] = &options
[1];
185 ZeroMemory(options
, sizeof(options
));
187 SetLastError(0xdeadbeef);
188 hres
= CreateEditableStream(&streams
[0], NULL
);
189 ok(hres
== AVIERR_OK
, "0: got 0x%x and %p (expected AVIERR_OK)\n", hres
, streams
[0]);
191 SetLastError(0xdeadbeef);
192 hres
= CreateEditableStream(&streams
[1], NULL
);
193 ok(hres
== AVIERR_OK
, "1: got 0x%x and %p (expected AVIERR_OK)\n", hres
, streams
[1]);
195 SetLastError(0xdeadbeef);
196 hres
= EditStreamSetNameA(streams
[0], winetest0
);
197 ok(hres
== AVIERR_OK
, "0: got 0x%x (expected AVIERR_OK)\n", hres
);
199 SetLastError(0xdeadbeef);
200 hres
= EditStreamSetNameA(streams
[1], winetest1
);
201 ok(hres
== AVIERR_OK
, "1: got 0x%x (expected AVIERR_OK)\n", hres
);
203 if (winetest_interactive
) {
204 SetLastError(0xdeadbeef);
205 res
= AVISaveOptions(0, ICMF_CHOOSE_DATARATE
|ICMF_CHOOSE_KEYFRAME
| ICMF_CHOOSE_ALLCOMPRESSORS
,
206 2, streams
, poptions
);
207 trace("got %u with 0x%x/%u\n", res
, GetLastError(), GetLastError());
210 SetLastError(0xdeadbeef);
211 lres
= AVISaveOptionsFree(2, poptions
);
212 ok(lres
== AVIERR_OK
, "got 0x%x with 0x%x/%u\n", lres
, GetLastError(), GetLastError());
214 SetLastError(0xdeadbeef);
215 res
= AVIStreamRelease(streams
[0]);
216 ok(res
== 0, "0: got refcount %u (expected 0)\n", res
);
218 SetLastError(0xdeadbeef);
219 res
= AVIStreamRelease(streams
[1]);
220 ok(res
== 0, "1: got refcount %u (expected 0)\n", res
);
224 /* ########################### */
226 static void test_EditStreamSetInfo(void)
228 PAVISTREAM stream
= NULL
;
230 AVISTREAMINFOA info
, info2
;
232 hres
= CreateEditableStream(&stream
, NULL
);
233 ok(hres
== AVIERR_OK
, "got 0x%08X, expected AVIERR_OK\n", hres
);
235 /* Size parameter is somehow checked (notice the crash with size=-1 below) */
236 hres
= EditStreamSetInfoA(stream
, NULL
, 0);
237 ok( hres
== AVIERR_BADSIZE
, "got 0x%08X, expected AVIERR_BADSIZE\n", hres
);
239 hres
= EditStreamSetInfoA(stream
, NULL
, sizeof(AVISTREAMINFOA
)-1 );
240 ok( hres
== AVIERR_BADSIZE
, "got 0x%08X, expected AVIERR_BADSIZE\n", hres
);
244 /* Crashing - first parameter not checked */
245 EditStreamSetInfoA(NULL
, &info
, sizeof(info
) );
247 /* Crashing - second parameter not checked */
248 EditStreamSetInfoA(stream
, NULL
, sizeof(AVISTREAMINFOA
) );
250 EditStreamSetInfoA(stream
, NULL
, -1);
253 hres
= AVIStreamInfoA(stream
, &info
, sizeof(info
) );
254 ok( hres
== 0, "got 0x%08X, expected 0\n", hres
);
256 /* Does the function check what's it's updating ? */
258 #define IS_INFO_UPDATED(m) do { \
259 hres = EditStreamSetInfoA(stream, &info, sizeof(info) ); \
260 ok( hres == 0, "got 0x%08X, expected 0\n", hres); \
261 hres = AVIStreamInfoA(stream, &info2, sizeof(info2) ); \
262 ok( hres == 0, "got 0x%08X, expected 0\n", hres); \
263 ok( info2.m == info.m, "EditStreamSetInfo did not update "#m" parameter\n" ); \
267 IS_INFO_UPDATED(dwStart
);
269 IS_INFO_UPDATED(dwStart
);
272 IS_INFO_UPDATED(wPriority
);
274 IS_INFO_UPDATED(wPriority
);
277 IS_INFO_UPDATED(wLanguage
);
279 IS_INFO_UPDATED(wLanguage
);
282 IS_INFO_UPDATED(dwScale
);
284 IS_INFO_UPDATED(dwScale
);
287 IS_INFO_UPDATED(dwRate
);
289 IS_INFO_UPDATED(dwRate
);
292 IS_INFO_UPDATED(dwQuality
);
294 IS_INFO_UPDATED(dwQuality
);
296 IS_INFO_UPDATED(dwQuality
);
297 info
.dwQuality
= ICQUALITY_HIGH
+1;
298 IS_INFO_UPDATED(dwQuality
);
300 info
.rcFrame
.left
= 0;
301 IS_INFO_UPDATED(rcFrame
.left
);
302 info
.rcFrame
.top
= 0;
303 IS_INFO_UPDATED(rcFrame
.top
);
304 info
.rcFrame
.right
= 0;
305 IS_INFO_UPDATED(rcFrame
.right
);
306 info
.rcFrame
.bottom
= 0;
307 IS_INFO_UPDATED(rcFrame
.bottom
);
309 info
.rcFrame
.left
= -1;
310 IS_INFO_UPDATED(rcFrame
.left
);
311 info
.rcFrame
.top
= -1;
312 IS_INFO_UPDATED(rcFrame
.top
);
313 info
.rcFrame
.right
= -1;
314 IS_INFO_UPDATED(rcFrame
.right
);
315 info
.rcFrame
.bottom
= -1;
316 IS_INFO_UPDATED(rcFrame
.bottom
);
317 AVIStreamRelease(stream
);
318 #undef IS_INFO_UPDATED
322 static void init_test_struct(COMMON_AVI_HEADERS
*cah
)
324 memcpy(cah
->fh
, deffh
, sizeof(deffh
));
328 cah
->pcmwf
= defpcmwf
;
331 static void create_avi_file(const COMMON_AVI_HEADERS
*cah
, char *filename
)
336 hFile
= CreateFileA(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
338 ok(hFile
!= INVALID_HANDLE_VALUE
, "Couldn't create file\n");
340 WriteFile(hFile
, &cah
->fh
, sizeof(deffh
), &written
, NULL
);
341 WriteFile(hFile
, &cah
->mah
, sizeof(MainAVIHeader
), &written
, NULL
);
342 WriteFile(hFile
, streamlist
, sizeof(streamlist
), &written
, NULL
);
343 WriteFile(hFile
, &cah
->ash0
, 0x38, &written
, NULL
);
344 WriteFile(hFile
, videostreamformat
, sizeof(videostreamformat
), &written
, NULL
);
345 WriteFile(hFile
, padding1
, sizeof(padding1
), &written
, NULL
);
346 WriteFile(hFile
, videopropheader
, sizeof(videopropheader
), &written
, NULL
);
347 WriteFile(hFile
, &cah
->ash1
, 0x38, &written
, NULL
);
348 WriteFile(hFile
, audiostreamformat_pre
, sizeof(audiostreamformat_pre
), &written
, NULL
);
349 WriteFile(hFile
, &cah
->pcmwf
, sizeof(PCMWAVEFORMAT
), &written
, NULL
);
350 WriteFile(hFile
, data
, sizeof(data
), &written
, NULL
);
355 static ULONG
get_file_refcount(PAVIFILE file
)
358 return AVIFileRelease(file
);
361 static void test_default_data(void)
363 COMMON_AVI_HEADERS cah
;
364 char filename
[MAX_PATH
];
370 AVISTREAMINFOA asi0
, asi1
;
374 GetTempPathA(MAX_PATH
, filename
);
375 strcpy(filename
+strlen(filename
), testfilename
);
377 init_test_struct(&cah
);
378 create_avi_file(&cah
, filename
);
380 res
= AVIFileOpenA(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
381 ok(res
== 0, "Unable to open file: error=%u\n", res
);
383 pStream0
= (void *)0xdeadbeef;
384 res
= AVIFileGetStream(pFile
, &pStream0
, ~0U, 0);
385 ok(res
== AVIERR_NODATA
, "expected AVIERR_NODATA, got %u\n", res
);
386 ok(pStream0
== NULL
, "AVIFileGetStream should set stream to NULL\n");
388 res
= AVIFileGetStream(pFile
, &pStream0
, 0, 0);
389 ok(res
== 0, "Unable to open video stream: error=%u\n", res
);
391 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
392 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
394 res
= AVIStreamInfoA(pStream0
, &asi0
, sizeof(asi0
));
395 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
397 res
= AVIStreamInfoA(pStream1
, &asi1
, sizeof(asi1
));
398 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
400 res
= AVIStreamReadFormat(pStream0
, AVIStreamStart(pStream1
), NULL
, &lSize
);
401 ok(res
== 0, "Unable to read format size: error=%u\n", res
);
403 res
= AVIStreamReadFormat(pStream1
, AVIStreamStart(pStream1
), &wfx
, &lSize
);
404 ok(res
== 0, "Unable to read format: error=%u\n", res
);
406 ok(asi0
.fccType
== streamtypeVIDEO
, "got 0x%x (expected streamtypeVIDEO)\n", asi0
.fccType
);
407 ok(asi0
.fccHandler
== 0x30323449, "got 0x%x (expected 0x30323449)\n", asi0
.fccHandler
);
408 ok(asi0
.dwFlags
== 0, "got %u (expected 0)\n", asi0
.dwFlags
);
409 ok(asi0
.wPriority
== 0, "got %u (expected 0)\n", asi0
.wPriority
);
410 ok(asi0
.wLanguage
== 0, "got %u (expected 0)\n", asi0
.wLanguage
);
411 ok(asi0
.dwScale
== 1001, "got %u (expected 1001)\n", asi0
.dwScale
);
412 ok(asi0
.dwRate
== 30000, "got %u (expected 30000)\n", asi0
.dwRate
);
413 ok(asi0
.dwStart
== 0, "got %u (expected 0)\n", asi0
.dwStart
);
414 ok(asi0
.dwLength
== 1, "got %u (expected 1)\n", asi0
.dwLength
);
415 ok(asi0
.dwInitialFrames
== 0, "got %u (expected 0)\n", asi0
.dwInitialFrames
);
416 ok(asi0
.dwSuggestedBufferSize
== 0, "got %u (expected 0)\n", asi0
.dwSuggestedBufferSize
);
417 ok(asi0
.dwQuality
== 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi0
.dwQuality
);
418 ok(asi0
.dwSampleSize
== 0, "got %u (expected 0)\n", asi0
.dwSampleSize
);
419 ok(asi0
.rcFrame
.left
== 0, "got %u (expected 0)\n", asi0
.rcFrame
.left
);
420 ok(asi0
.rcFrame
.top
== 0, "got %u (expected 0)\n", asi0
.rcFrame
.top
);
421 ok(asi0
.rcFrame
.right
== 8, "got %u (expected 8)\n", asi0
.rcFrame
.right
); /* these are based on the values in the mah and not */
422 ok(asi0
.rcFrame
.bottom
== 6, "got %u (expected 6)\n", asi0
.rcFrame
.bottom
);/* on the ones in the ash which are 0 here */
423 ok(asi0
.dwEditCount
== 0, "got %u (expected 0)\n", asi0
.dwEditCount
);
424 ok(asi0
.dwFormatChangeCount
== 0, "got %u (expected 0)\n", asi0
.dwFormatChangeCount
);
426 ok(asi1
.fccType
== streamtypeAUDIO
, "got 0x%x (expected streamtypeVIDEO)\n", asi1
.fccType
);
427 ok(asi1
.fccHandler
== 0x1, "got 0x%x (expected 0x1)\n", asi1
.fccHandler
);
428 ok(asi1
.dwFlags
== 0, "got %u (expected 0)\n", asi1
.dwFlags
);
429 ok(asi1
.wPriority
== 0, "got %u (expected 0)\n", asi1
.wPriority
);
430 ok(asi1
.wLanguage
== 0, "got %u (expected 0)\n", asi1
.wLanguage
);
431 ok(asi1
.dwScale
== 1, "got %u (expected 1)\n", asi1
.dwScale
);
432 ok(asi1
.dwRate
== 11025, "got %u (expected 11025)\n", asi1
.dwRate
);
433 ok(asi1
.dwStart
== 0, "got %u (expected 0)\n", asi1
.dwStart
);
434 ok(asi1
.dwLength
== 1637, "got %u (expected 1637)\n", asi1
.dwLength
);
435 ok(asi1
.dwInitialFrames
== 0, "got %u (expected 0)\n", asi1
.dwInitialFrames
);
436 ok(asi1
.dwSuggestedBufferSize
== 0, "got %u (expected 0)\n", asi1
.dwSuggestedBufferSize
);
437 ok(asi1
.dwQuality
== 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi1
.dwQuality
);
438 ok(asi1
.dwSampleSize
== 2, "got %u (expected 2)\n", asi1
.dwSampleSize
);
439 ok(asi1
.rcFrame
.left
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.left
);
440 ok(asi1
.rcFrame
.top
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.top
);
441 ok(asi1
.rcFrame
.right
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.right
);
442 ok(asi1
.rcFrame
.bottom
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.bottom
);
443 ok(asi1
.dwEditCount
== 0, "got %u (expected 0)\n", asi1
.dwEditCount
);
444 ok(asi1
.dwFormatChangeCount
== 0, "got %u (expected 0)\n", asi1
.dwFormatChangeCount
);
446 ok(wfx
.wFormatTag
== 1, "got %u (expected 1)\n",wfx
.wFormatTag
);
447 ok(wfx
.nChannels
== 2, "got %u (expected 2)\n",wfx
.nChannels
);
448 ok(wfx
.wFormatTag
== 1, "got %u (expected 1)\n",wfx
.wFormatTag
);
449 ok(wfx
.nSamplesPerSec
== 11025, "got %u (expected 11025)\n",wfx
.nSamplesPerSec
);
450 ok(wfx
.nAvgBytesPerSec
== 22050, "got %u (expected 22050)\n",wfx
.nAvgBytesPerSec
);
451 ok(wfx
.nBlockAlign
== 2, "got %u (expected 2)\n",wfx
.nBlockAlign
);
453 refcount
= get_file_refcount(pFile
);
454 ok(refcount
== 3, "got %u (expected 3)\n", refcount
);
456 AVIStreamRelease(pStream0
);
458 refcount
= get_file_refcount(pFile
);
459 ok(refcount
== 2, "got %u (expected 2)\n", refcount
);
461 AVIStreamAddRef(pStream1
);
463 refcount
= get_file_refcount(pFile
);
464 ok(refcount
== 2, "got %u (expected 2)\n", refcount
);
466 AVIStreamRelease(pStream1
);
467 AVIStreamRelease(pStream1
);
469 refcount
= get_file_refcount(pFile
);
470 ok(refcount
== 1, "got %u (expected 1)\n", refcount
);
472 refcount
= AVIStreamRelease(pStream1
);
473 ok(refcount
== (ULONG
)-1, "got %u (expected 4294967295)\n", refcount
);
475 refcount
= get_file_refcount(pFile
);
476 ok(refcount
== 1, "got %u (expected 1)\n", refcount
);
478 refcount
= AVIFileRelease(pFile
);
479 ok(refcount
== 0, "got %u (expected 0)\n", refcount
);
481 ok(DeleteFileA(filename
) !=0, "Deleting file %s failed\n", filename
);
484 static void test_amh_corruption(void)
486 COMMON_AVI_HEADERS cah
;
487 char filename
[MAX_PATH
];
491 GetTempPathA(MAX_PATH
, filename
);
492 strcpy(filename
+strlen(filename
), testfilename
);
494 /* Make sure only AVI files with the proper headers will be loaded */
495 init_test_struct(&cah
);
496 cah
.fh
[3] = mmioFOURCC('A', 'V', 'i', ' ');
498 create_avi_file(&cah
, filename
);
499 res
= AVIFileOpenA(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
500 ok(res
!= 0, "Able to open file: error=%u\n", res
);
502 ok(DeleteFileA(filename
) !=0, "Deleting file %s failed\n", filename
);
505 static void test_ash1_corruption(void)
507 COMMON_AVI_HEADERS cah
;
508 char filename
[MAX_PATH
];
514 GetTempPathA(MAX_PATH
, filename
);
515 strcpy(filename
+strlen(filename
), testfilename
);
517 /* Corrupt the sample size in the audio stream header */
518 init_test_struct(&cah
);
519 cah
.ash1
.dwSampleSize
= 0xdeadbeef;
521 create_avi_file(&cah
, filename
);
523 res
= AVIFileOpenA(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
524 ok(res
== 0, "Unable to open file: error=%u\n", res
);
526 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
527 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
529 res
= AVIStreamInfoA(pStream1
, &asi1
, sizeof(asi1
));
530 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
532 /* The result will still be 2, because the value is dynamically replaced with the nBlockAlign
533 value from the stream format header. The next test will prove this */
534 ok(asi1
.dwSampleSize
== 2, "got %u (expected 2)\n", asi1
.dwSampleSize
);
536 AVIStreamRelease(pStream1
);
537 AVIFileRelease(pFile
);
538 ok(DeleteFileA(filename
) !=0, "Deleting file %s failed\n", filename
);
541 static void test_ash1_corruption2(void)
543 COMMON_AVI_HEADERS cah
;
544 char filename
[MAX_PATH
];
550 GetTempPathA(MAX_PATH
, filename
);
551 strcpy(filename
+strlen(filename
), testfilename
);
553 /* Corrupt the block alignment in the audio format header */
554 init_test_struct(&cah
);
555 cah
.pcmwf
.wf
.nBlockAlign
= 0xdead;
557 create_avi_file(&cah
, filename
);
559 res
= AVIFileOpenA(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
560 ok(res
== 0, "Unable to open file: error=%u\n", res
);
562 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
563 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
565 ok(AVIStreamInfoA(pStream1
, &asi1
, sizeof(asi1
)) == 0, "Unable to read stream info\n");
567 /* The result will also be the corrupt value, as explained above. */
568 ok(asi1
.dwSampleSize
== 0xdead, "got 0x%x (expected 0xdead)\n", asi1
.dwSampleSize
);
570 AVIStreamRelease(pStream1
);
571 AVIFileRelease(pFile
);
572 ok(DeleteFileA(filename
) !=0, "Deleting file %s failed\n", filename
);
575 /* Outer IUnknown for COM aggregation tests */
577 IUnknown IUnknown_iface
;
582 static inline struct unk_impl
*impl_from_IUnknown(IUnknown
*iface
)
584 return CONTAINING_RECORD(iface
, struct unk_impl
, IUnknown_iface
);
587 static HRESULT WINAPI
unk_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
589 struct unk_impl
*This
= impl_from_IUnknown(iface
);
590 LONG ref
= This
->ref
;
593 if (IsEqualGUID(riid
, &IID_IUnknown
))
596 IUnknown_AddRef(iface
);
600 hr
= IUnknown_QueryInterface(This
->inner_unk
, riid
, ppv
);
603 trace("Working around COM aggregation ref counting bug\n");
604 ok(ref
== This
->ref
, "Outer ref count expected %d got %d\n", ref
, This
->ref
);
605 IUnknown_AddRef((IUnknown
*)*ppv
);
606 ref
= IUnknown_Release(This
->inner_unk
);
607 ok(ref
== 1, "Inner ref count expected 1 got %d\n", ref
);
613 static ULONG WINAPI
unk_AddRef(IUnknown
*iface
)
615 struct unk_impl
*This
= impl_from_IUnknown(iface
);
617 return InterlockedIncrement(&This
->ref
);
620 static ULONG WINAPI
unk_Release(IUnknown
*iface
)
622 struct unk_impl
*This
= impl_from_IUnknown(iface
);
624 return InterlockedDecrement(&This
->ref
);
627 static const IUnknownVtbl unk_vtbl
=
634 static void test_COM(void)
636 struct unk_impl unk_obj
= {{&unk_vtbl
}, 19, NULL
};
637 IAVIFile
*avif
= NULL
;
643 /* COM aggregation */
644 hr
= CoCreateInstance(&CLSID_AVIFile
, &unk_obj
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
645 &IID_IUnknown
, (void**)&unk_obj
.inner_unk
);
646 ok(hr
== S_OK
, "COM aggregation failed: %08x, expected S_OK\n", hr
);
647 hr
= IUnknown_QueryInterface(&unk_obj
.IUnknown_iface
, &IID_IAVIFile
, (void**)&avif
);
648 ok(hr
== S_OK
, "QueryInterface for IID_IAVIFile failed: %08x\n", hr
);
649 refcount
= IAVIFile_AddRef(avif
);
650 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
651 refcount
= IAVIFile_Release(avif
);
652 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
653 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
654 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
655 refcount
= IPersistFile_Release(pf
);
656 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
657 refcount
= IAVIFile_Release(avif
);
658 ok(refcount
== 19, "Outer ref count should be back at 19 but is %d\n", refcount
);
659 refcount
= IUnknown_Release(unk_obj
.inner_unk
);
660 ok(refcount
== 0, "Inner ref count should be 0 but is %u\n", refcount
);
663 hr
= CoCreateInstance(&CLSID_AVIFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIStream
,
665 ok(hr
== E_NOINTERFACE
, "AVIFile create failed: %08x, expected E_NOINTERFACE\n", hr
);
668 hr
= CoCreateInstance(&CLSID_AVIFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIFile
, (void**)&avif
);
669 ok(hr
== S_OK
, "AVIFile create failed: %08x, expected S_OK\n", hr
);
670 refcount
= IAVIFile_AddRef(avif
);
671 ok(refcount
== 2, "refcount == %u, expected 2\n", refcount
);
672 hr
= IAVIFile_QueryInterface(avif
, &IID_IUnknown
, (void**)&unk
);
673 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %08x\n", hr
);
674 refcount
= IUnknown_AddRef(unk
);
675 ok(refcount
== 4, "refcount == %u, expected 4\n", refcount
);
676 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
677 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
678 refcount
= IPersistFile_AddRef(pf
);
679 ok(refcount
== 6, "refcount == %u, expected 6\n", refcount
);
681 while (IAVIFile_Release(avif
));
684 static void test_COM_wavfile(void)
686 struct unk_impl unk_obj
= {{&unk_vtbl
}, 19, NULL
};
687 IAVIFile
*avif
= NULL
;
694 /* COM aggregation */
695 hr
= CoCreateInstance(&CLSID_WAVFile
, &unk_obj
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
696 &IID_IUnknown
, (void**)&unk_obj
.inner_unk
);
697 ok(hr
== S_OK
, "COM aggregation failed: %08x, expected S_OK\n", hr
);
698 hr
= IUnknown_QueryInterface(&unk_obj
.IUnknown_iface
, &IID_IAVIFile
, (void**)&avif
);
699 ok(hr
== S_OK
, "QueryInterface for IID_IAVIFile failed: %08x\n", hr
);
700 refcount
= IAVIFile_AddRef(avif
);
701 ok(refcount
== unk_obj
.ref
, "WAVFile just pretends to support COM aggregation\n");
702 refcount
= IAVIFile_Release(avif
);
703 ok(refcount
== unk_obj
.ref
, "WAVFile just pretends to support COM aggregation\n");
704 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
705 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
706 refcount
= IPersistFile_Release(pf
);
707 ok(refcount
== unk_obj
.ref
, "WAVFile just pretends to support COM aggregation\n");
708 refcount
= IAVIFile_Release(avif
);
709 ok(refcount
== 19, "Outer ref count should be back at 19 but is %d\n", refcount
);
710 refcount
= IUnknown_Release(unk_obj
.inner_unk
);
711 ok(refcount
== 0, "Inner ref count should be 0 but is %u\n", refcount
);
714 hr
= CoCreateInstance(&CLSID_WAVFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIStreaming
,
716 ok(hr
== E_NOINTERFACE
, "WAVFile create failed: %08x, expected E_NOINTERFACE\n", hr
);
718 /* Same refcount for all WAVFile interfaces */
719 hr
= CoCreateInstance(&CLSID_WAVFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIFile
, (void**)&avif
);
720 ok(hr
== S_OK
, "WAVFile create failed: %08x, expected S_OK\n", hr
);
721 refcount
= IAVIFile_AddRef(avif
);
722 ok(refcount
== 2, "refcount == %u, expected 2\n", refcount
);
724 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
725 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
726 refcount
= IPersistFile_AddRef(pf
);
727 ok(refcount
== 4, "refcount == %u, expected 4\n", refcount
);
728 refcount
= IPersistFile_Release(pf
);
730 hr
= IAVIFile_QueryInterface(avif
, &IID_IAVIStream
, (void**)&avis
);
731 ok(hr
== S_OK
, "QueryInterface for IID_IAVIStream failed: %08x\n", hr
);
732 refcount
= IAVIStream_AddRef(avis
);
733 ok(refcount
== 5, "refcount == %u, expected 5\n", refcount
);
734 refcount
= IAVIStream_Release(avis
);
736 hr
= IAVIFile_QueryInterface(avif
, &IID_IUnknown
, (void**)&unk
);
737 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %08x\n", hr
);
738 refcount
= IUnknown_AddRef(unk
);
739 ok(refcount
== 6, "refcount == %u, expected 6\n", refcount
);
740 refcount
= IUnknown_Release(unk
);
742 while (IAVIFile_Release(avif
));
745 static void test_COM_editstream(void)
747 IAVIEditStream
*edit
;
753 /* Same refcount for all AVIEditStream interfaces */
754 hr
= CreateEditableStream(&stream
, NULL
);
755 ok(hr
== S_OK
, "AVIEditStream create failed: %08x, expected S_OK\n", hr
);
756 refcount
= IAVIStream_AddRef(stream
);
757 ok(refcount
== 2, "refcount == %u, expected 2\n", refcount
);
759 hr
= IAVIStream_QueryInterface(stream
, &IID_IAVIEditStream
, (void**)&edit
);
760 ok(hr
== S_OK
, "QueryInterface for IID_IAVIEditStream failed: %08x\n", hr
);
761 refcount
= IAVIEditStream_AddRef(edit
);
762 ok(refcount
== 4, "refcount == %u, expected 4\n", refcount
);
763 refcount
= IAVIEditStream_Release(edit
);
765 hr
= IAVIEditStream_QueryInterface(edit
, &IID_IUnknown
, (void**)&unk
);
766 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %08x\n", hr
);
767 refcount
= IUnknown_AddRef(unk
);
768 ok(refcount
== 5, "refcount == %u, expected 5\n", refcount
);
769 IUnknown_Release(unk
);
771 while (IAVIEditStream_Release(edit
));
778 test_EditStreamSetInfo();
779 test_AVISaveOptions();
781 test_amh_corruption();
782 test_ash1_corruption();
783 test_ash1_corruption2();
786 test_COM_editstream();