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
22 #define WIN32_NO_STATUS
24 #define COM_NO_WINDOWS_H
29 #include <wine/test.h>
34 /* ########################### */
36 DEFINE_AVIGUID(CLSID_WAVFile
, 0x00020003, 0, 0);
37 static const CHAR winetest0
[] = "winetest0";
38 static const CHAR winetest1
[] = "winetest1";
39 static const CHAR testfilename
[] = "wine_avifil32_test.avi";
41 /* ########################### */
43 static const DWORD deffh
[] = /* file_header */
45 FOURCC_RIFF
, 0x34c6 /* length */, formtypeAVI
,
46 FOURCC_LIST
, 0x1ac /* length */,
47 listtypeAVIHEADER
, ckidAVIMAINHDR
, sizeof(MainAVIHeader
),
50 static const MainAVIHeader defmah
=
52 0x00008256, /* dwMicroSecPerFrame */
53 0x000080e8, /* dwMaxBytesPerSec */
54 0x00000000, /* dwPaddingGranularity */
55 0x00000910, /* dwFlags */
56 1, /* dwTotalFrames */
57 0, /* dwInitialFrames */
59 0x00100000, /* dwSuggestedBufferSize*/
62 { 0, 0, 0, 0 } /* dwReserved[4] */
65 static const AVIStreamHeader defash0
=
67 streamtypeVIDEO
, /* fccType */
68 0x30323449, /* fccHandler */
69 0x00000000, /* dwFlags */
72 0, /* dwInitialFrames */
73 0x000003e9, /* dwScale */
74 0x00007530, /* dwRate */
77 0x00100000, /* dwSuggestedBufferSize*/
78 0xffffffff, /* dwQuality */
80 { 0, 0, 0, 0 } /* short left right top bottom */
83 static const AVIStreamHeader defash1
=
86 streamtypeAUDIO
, /* fccType */
91 0, /* dwInitialFrames */
93 0x00002b11, /* dwRate */
95 0x00000665, /* dwLength */
96 0x00003000, /* dwSuggestedBufferSize*/
97 0xffffffff, /* dwQuality */
99 { 0, 0, 0, 0 } /* short left right top bottom */
102 static const PCMWAVEFORMAT defpcmwf
=
107 11025, /* nSamplesPerSec */
108 22050, /* nAvgBytesPerSec */
111 8, /* wBitsPerSample */
114 typedef struct common_avi_headers
{
115 DWORD fh
[sizeof(deffh
)];
117 AVIStreamHeader ash0
;
118 AVIStreamHeader ash1
;
120 } COMMON_AVI_HEADERS
;
122 /* Extra data needed to get the VFW API to load the file */
124 /* MainAVIHeader mah */
125 static const DWORD streamlist
[] =
127 FOURCC_LIST
, 0xd4 /* length */,
128 listtypeSTREAMHEADER
, ckidSTREAMHEADER
, 0x38 /* length */,
130 /* AVIStreamHeader ash0 */
131 static const DWORD videostreamformat
[] =
133 ckidSTREAMFORMAT
, 0x28 /* length */,
134 0x00000028, 0x00000008, 0x00000006, 0x00180001,
135 0x30323449, 0x00000090, 0x00000000, 0x00000000,
136 0x00000000, 0x00000000,
138 static const DWORD padding1
[] =
140 ckidAVIPADDING
, 0xc /* length */,
141 0x00000004, 0x00000000, 0x63643030
143 static const DWORD videopropheader
[] =
145 0x70727076, 0x44 /* length */,
146 0x00000000, 0x00000000,
147 0x0000001e, 0x00000008, 0x00000006, 0x00100009,
148 0x00000008, 0x00000006, 0x00000001, 0x00000006,
149 0x00000008, 0x00000006, 0x00000008, 0x00000000,
150 0x00000000, 0x00000000, 0x00000000,
151 FOURCC_LIST
, 0x70 /* length */,
152 listtypeSTREAMHEADER
, ckidSTREAMHEADER
, 0x38 /* length */,
154 /* AVIStreamHeader ash1 */
155 static const DWORD audiostreamformat_pre
[] =
157 ckidSTREAMFORMAT
, sizeof(PCMWAVEFORMAT
) /* length */,
159 /* PCMWAVEFORMAT pcmwf */
160 static DWORD data
[] =
162 ckidAVIPADDING
, 0xc /* length */,
163 0x00000004, 0x00000000, 0x62773130,
164 ckidAVIPADDING
, 0xc /* length */,
165 0x6c6d646f, 0x686c6d64, 0x000000f8,
166 FOURCC_LIST
, 0x18 /* length */,
168 0x54465349, 0xc /* length */,
169 0x6676614c, 0x332e3235, 0x00302e37,
170 ckidAVIPADDING
, 0x4 /* length */,
172 FOURCC_LIST
, 0xd1b /* length */, listtypeAVIMOVIE
,
176 /* ########################### */
178 static void test_AVISaveOptions(void)
180 AVICOMPRESSOPTIONS options
[2];
181 LPAVICOMPRESSOPTIONS poptions
[2];
182 PAVISTREAM streams
[2] = {NULL
, NULL
};
187 poptions
[0] = &options
[0];
188 poptions
[1] = &options
[1];
189 ZeroMemory(options
, sizeof(options
));
191 SetLastError(0xdeadbeef);
192 hres
= CreateEditableStream(&streams
[0], NULL
);
193 ok(hres
== AVIERR_OK
, "0: got 0x%x and %p (expected AVIERR_OK)\n", hres
, streams
[0]);
195 SetLastError(0xdeadbeef);
196 hres
= CreateEditableStream(&streams
[1], NULL
);
197 ok(hres
== AVIERR_OK
, "1: got 0x%x and %p (expected AVIERR_OK)\n", hres
, streams
[1]);
199 SetLastError(0xdeadbeef);
200 hres
= EditStreamSetNameA(streams
[0], winetest0
);
201 ok(hres
== AVIERR_OK
, "0: got 0x%x (expected AVIERR_OK)\n", hres
);
203 SetLastError(0xdeadbeef);
204 hres
= EditStreamSetNameA(streams
[1], winetest1
);
205 ok(hres
== AVIERR_OK
, "1: got 0x%x (expected AVIERR_OK)\n", hres
);
207 if (winetest_interactive
) {
208 SetLastError(0xdeadbeef);
209 res
= AVISaveOptions(0, ICMF_CHOOSE_DATARATE
|ICMF_CHOOSE_KEYFRAME
| ICMF_CHOOSE_ALLCOMPRESSORS
,
210 2, streams
, poptions
);
211 trace("got %u with 0x%x/%u\n", res
, GetLastError(), GetLastError());
214 SetLastError(0xdeadbeef);
215 lres
= AVISaveOptionsFree(2, poptions
);
216 ok(lres
== AVIERR_OK
, "got 0x%x with 0x%x/%u\n", lres
, GetLastError(), GetLastError());
218 SetLastError(0xdeadbeef);
219 res
= AVIStreamRelease(streams
[0]);
220 ok(res
== 0, "0: got refcount %u (expected 0)\n", res
);
222 SetLastError(0xdeadbeef);
223 res
= AVIStreamRelease(streams
[1]);
224 ok(res
== 0, "1: got refcount %u (expected 0)\n", res
);
228 /* ########################### */
230 static void test_EditStreamSetInfo(void)
232 PAVISTREAM stream
= NULL
;
234 AVISTREAMINFOA info
, info2
;
236 hres
= CreateEditableStream(&stream
, NULL
);
237 ok(hres
== AVIERR_OK
, "got 0x%08X, expected AVIERR_OK\n", hres
);
239 /* Size parameter is somehow checked (notice the crash with size=-1 below) */
240 hres
= EditStreamSetInfoA(stream
, NULL
, 0);
241 ok( hres
== AVIERR_BADSIZE
, "got 0x%08X, expected AVIERR_BADSIZE\n", hres
);
243 hres
= EditStreamSetInfoA(stream
, NULL
, sizeof(AVISTREAMINFOA
)-1 );
244 ok( hres
== AVIERR_BADSIZE
, "got 0x%08X, expected AVIERR_BADSIZE\n", hres
);
248 /* Crashing - first parameter not checked */
249 EditStreamSetInfoA(NULL
, &info
, sizeof(info
) );
251 /* Crashing - second parameter not checked */
252 EditStreamSetInfoA(stream
, NULL
, sizeof(AVISTREAMINFOA
) );
254 EditStreamSetInfoA(stream
, NULL
, -1);
257 hres
= AVIStreamInfoA(stream
, &info
, sizeof(info
) );
258 ok( hres
== 0, "got 0x%08X, expected 0\n", hres
);
260 /* Does the function check what's it's updating ? */
262 #define IS_INFO_UPDATED(m) do { \
263 hres = EditStreamSetInfoA(stream, &info, sizeof(info) ); \
264 ok( hres == 0, "got 0x%08X, expected 0\n", hres); \
265 hres = AVIStreamInfoA(stream, &info2, sizeof(info2) ); \
266 ok( hres == 0, "got 0x%08X, expected 0\n", hres); \
267 ok( info2.m == info.m, "EditStreamSetInfo did not update "#m" parameter\n" ); \
271 IS_INFO_UPDATED(dwStart
);
273 IS_INFO_UPDATED(dwStart
);
276 IS_INFO_UPDATED(wPriority
);
278 IS_INFO_UPDATED(wPriority
);
281 IS_INFO_UPDATED(wLanguage
);
283 IS_INFO_UPDATED(wLanguage
);
286 IS_INFO_UPDATED(dwScale
);
288 IS_INFO_UPDATED(dwScale
);
291 IS_INFO_UPDATED(dwRate
);
293 IS_INFO_UPDATED(dwRate
);
296 IS_INFO_UPDATED(dwQuality
);
298 IS_INFO_UPDATED(dwQuality
);
300 IS_INFO_UPDATED(dwQuality
);
301 info
.dwQuality
= ICQUALITY_HIGH
+1;
302 IS_INFO_UPDATED(dwQuality
);
304 info
.rcFrame
.left
= 0;
305 IS_INFO_UPDATED(rcFrame
.left
);
306 info
.rcFrame
.top
= 0;
307 IS_INFO_UPDATED(rcFrame
.top
);
308 info
.rcFrame
.right
= 0;
309 IS_INFO_UPDATED(rcFrame
.right
);
310 info
.rcFrame
.bottom
= 0;
311 IS_INFO_UPDATED(rcFrame
.bottom
);
313 info
.rcFrame
.left
= -1;
314 IS_INFO_UPDATED(rcFrame
.left
);
315 info
.rcFrame
.top
= -1;
316 IS_INFO_UPDATED(rcFrame
.top
);
317 info
.rcFrame
.right
= -1;
318 IS_INFO_UPDATED(rcFrame
.right
);
319 info
.rcFrame
.bottom
= -1;
320 IS_INFO_UPDATED(rcFrame
.bottom
);
321 AVIStreamRelease(stream
);
322 #undef IS_INFO_UPDATED
326 static void init_test_struct(COMMON_AVI_HEADERS
*cah
)
328 memcpy(cah
->fh
, deffh
, sizeof(deffh
));
332 cah
->pcmwf
= defpcmwf
;
335 static void create_avi_file(const COMMON_AVI_HEADERS
*cah
, char *filename
)
340 hFile
= CreateFileA(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
342 ok(hFile
!= INVALID_HANDLE_VALUE
, "Couldn't create file\n");
344 WriteFile(hFile
, &cah
->fh
, sizeof(deffh
), &written
, NULL
);
345 WriteFile(hFile
, &cah
->mah
, sizeof(MainAVIHeader
), &written
, NULL
);
346 WriteFile(hFile
, streamlist
, sizeof(streamlist
), &written
, NULL
);
347 WriteFile(hFile
, &cah
->ash0
, 0x38, &written
, NULL
);
348 WriteFile(hFile
, videostreamformat
, sizeof(videostreamformat
), &written
, NULL
);
349 WriteFile(hFile
, padding1
, sizeof(padding1
), &written
, NULL
);
350 WriteFile(hFile
, videopropheader
, sizeof(videopropheader
), &written
, NULL
);
351 WriteFile(hFile
, &cah
->ash1
, 0x38, &written
, NULL
);
352 WriteFile(hFile
, audiostreamformat_pre
, sizeof(audiostreamformat_pre
), &written
, NULL
);
353 WriteFile(hFile
, &cah
->pcmwf
, sizeof(PCMWAVEFORMAT
), &written
, NULL
);
354 WriteFile(hFile
, data
, sizeof(data
), &written
, NULL
);
359 static void test_default_data(void)
361 COMMON_AVI_HEADERS cah
;
362 char filename
[MAX_PATH
];
368 AVISTREAMINFOA asi0
, asi1
;
371 GetTempPathA(MAX_PATH
, filename
);
372 strcpy(filename
+strlen(filename
), testfilename
);
374 init_test_struct(&cah
);
375 create_avi_file(&cah
, filename
);
377 res
= AVIFileOpenA(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
378 ok(res
== 0, "Unable to open file: error=%u\n", res
);
380 pStream0
= (void *)0xdeadbeef;
381 res
= AVIFileGetStream(pFile
, &pStream0
, ~0, 0);
382 ok(res
== AVIERR_NODATA
, "expected AVIERR_NODATA, got %#x\n", res
);
383 ok(pStream0
== NULL
, "AVIFileGetStream should set stream to NULL\n");
385 res
= AVIFileGetStream(pFile
, &pStream0
, 0, 0);
386 ok(res
== 0, "Unable to open video stream: error=%u\n", res
);
388 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
389 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
391 res
= AVIStreamInfoA(pStream0
, &asi0
, sizeof(asi0
));
392 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
394 res
= AVIStreamInfoA(pStream1
, &asi1
, sizeof(asi1
));
395 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
397 res
= AVIStreamReadFormat(pStream0
, AVIStreamStart(pStream1
), NULL
, &lSize
);
398 ok(res
== 0, "Unable to read format size: error=%u\n", res
);
400 res
= AVIStreamReadFormat(pStream1
, AVIStreamStart(pStream1
), &wfx
, &lSize
);
401 ok(res
== 0, "Unable to read format: error=%u\n", res
);
403 ok(asi0
.fccType
== streamtypeVIDEO
, "got 0x%x (expected streamtypeVIDEO)\n", asi0
.fccType
);
404 ok(asi0
.fccHandler
== 0x30323449, "got 0x%x (expected 0x30323449)\n", asi0
.fccHandler
);
405 ok(asi0
.dwFlags
== 0, "got %u (expected 0)\n", asi0
.dwFlags
);
406 ok(asi0
.wPriority
== 0, "got %u (expected 0)\n", asi0
.wPriority
);
407 ok(asi0
.wLanguage
== 0, "got %u (expected 0)\n", asi0
.wLanguage
);
408 ok(asi0
.dwScale
== 1001, "got %u (expected 1001)\n", asi0
.dwScale
);
409 ok(asi0
.dwRate
== 30000, "got %u (expected 30000)\n", asi0
.dwRate
);
410 ok(asi0
.dwStart
== 0, "got %u (expected 0)\n", asi0
.dwStart
);
411 ok(asi0
.dwLength
== 1, "got %u (expected 1)\n", asi0
.dwLength
);
412 ok(asi0
.dwInitialFrames
== 0, "got %u (expected 0)\n", asi0
.dwInitialFrames
);
413 ok(asi0
.dwSuggestedBufferSize
== 0, "got %u (expected 0)\n", asi0
.dwSuggestedBufferSize
);
414 ok(asi0
.dwQuality
== 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi0
.dwQuality
);
415 ok(asi0
.dwSampleSize
== 0, "got %u (expected 0)\n", asi0
.dwSampleSize
);
416 ok(asi0
.rcFrame
.left
== 0, "got %u (expected 0)\n", asi0
.rcFrame
.left
);
417 ok(asi0
.rcFrame
.top
== 0, "got %u (expected 0)\n", asi0
.rcFrame
.top
);
418 ok(asi0
.rcFrame
.right
== 8, "got %u (expected 8)\n", asi0
.rcFrame
.right
); /* these are based on the values in the mah and not */
419 ok(asi0
.rcFrame
.bottom
== 6, "got %u (expected 6)\n", asi0
.rcFrame
.bottom
);/* on the ones in the ash which are 0 here */
420 ok(asi0
.dwEditCount
== 0, "got %u (expected 0)\n", asi0
.dwEditCount
);
421 ok(asi0
.dwFormatChangeCount
== 0, "got %u (expected 0)\n", asi0
.dwFormatChangeCount
);
423 ok(asi1
.fccType
== streamtypeAUDIO
, "got 0x%x (expected streamtypeVIDEO)\n", asi1
.fccType
);
424 ok(asi1
.fccHandler
== 0x1, "got 0x%x (expected 0x1)\n", asi1
.fccHandler
);
425 ok(asi1
.dwFlags
== 0, "got %u (expected 0)\n", asi1
.dwFlags
);
426 ok(asi1
.wPriority
== 0, "got %u (expected 0)\n", asi1
.wPriority
);
427 ok(asi1
.wLanguage
== 0, "got %u (expected 0)\n", asi1
.wLanguage
);
428 ok(asi1
.dwScale
== 1, "got %u (expected 1)\n", asi1
.dwScale
);
429 ok(asi1
.dwRate
== 11025, "got %u (expected 11025)\n", asi1
.dwRate
);
430 ok(asi1
.dwStart
== 0, "got %u (expected 0)\n", asi1
.dwStart
);
431 ok(asi1
.dwLength
== 1637, "got %u (expected 1637)\n", asi1
.dwLength
);
432 ok(asi1
.dwInitialFrames
== 0, "got %u (expected 0)\n", asi1
.dwInitialFrames
);
433 ok(asi1
.dwSuggestedBufferSize
== 0, "got %u (expected 0)\n", asi1
.dwSuggestedBufferSize
);
434 ok(asi1
.dwQuality
== 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi1
.dwQuality
);
435 ok(asi1
.dwSampleSize
== 2, "got %u (expected 2)\n", asi1
.dwSampleSize
);
436 ok(asi1
.rcFrame
.left
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.left
);
437 ok(asi1
.rcFrame
.top
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.top
);
438 ok(asi1
.rcFrame
.right
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.right
);
439 ok(asi1
.rcFrame
.bottom
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.bottom
);
440 ok(asi1
.dwEditCount
== 0, "got %u (expected 0)\n", asi1
.dwEditCount
);
441 ok(asi1
.dwFormatChangeCount
== 0, "got %u (expected 0)\n", asi1
.dwFormatChangeCount
);
443 ok(wfx
.wFormatTag
== 1, "got %u (expected 1)\n",wfx
.wFormatTag
);
444 ok(wfx
.nChannels
== 2, "got %u (expected 2)\n",wfx
.nChannels
);
445 ok(wfx
.wFormatTag
== 1, "got %u (expected 1)\n",wfx
.wFormatTag
);
446 ok(wfx
.nSamplesPerSec
== 11025, "got %u (expected 11025)\n",wfx
.nSamplesPerSec
);
447 ok(wfx
.nAvgBytesPerSec
== 22050, "got %u (expected 22050)\n",wfx
.nAvgBytesPerSec
);
448 ok(wfx
.nBlockAlign
== 2, "got %u (expected 2)\n",wfx
.nBlockAlign
);
450 AVIStreamRelease(pStream0
);
451 AVIStreamRelease(pStream1
);
452 AVIFileRelease(pFile
);
453 ok(DeleteFileA(filename
) !=0, "Deleting file %s failed\n", filename
);
456 static void test_amh_corruption(void)
458 COMMON_AVI_HEADERS cah
;
459 char filename
[MAX_PATH
];
463 GetTempPathA(MAX_PATH
, filename
);
464 strcpy(filename
+strlen(filename
), testfilename
);
466 /* Make sure only AVI files with the proper headers will be loaded */
467 init_test_struct(&cah
);
468 cah
.fh
[3] = mmioFOURCC('A', 'V', 'i', ' ');
470 create_avi_file(&cah
, filename
);
471 res
= AVIFileOpenA(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
472 ok(res
!= 0, "Able to open file: error=%u\n", res
);
474 ok(DeleteFileA(filename
) !=0, "Deleting file %s failed\n", filename
);
477 static void test_ash1_corruption(void)
479 COMMON_AVI_HEADERS cah
;
480 char filename
[MAX_PATH
];
486 GetTempPathA(MAX_PATH
, filename
);
487 strcpy(filename
+strlen(filename
), testfilename
);
489 /* Corrupt the sample size in the audio stream header */
490 init_test_struct(&cah
);
491 cah
.ash1
.dwSampleSize
= 0xdeadbeef;
493 create_avi_file(&cah
, filename
);
495 res
= AVIFileOpenA(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
496 ok(res
== 0, "Unable to open file: error=%u\n", res
);
498 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
499 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
501 res
= AVIStreamInfoA(pStream1
, &asi1
, sizeof(asi1
));
502 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
504 /* The result will still be 2, because the value is dynamically replaced with the nBlockAlign
505 value from the stream format header. The next test will prove this */
506 ok(asi1
.dwSampleSize
== 2, "got %u (expected 2)\n", asi1
.dwSampleSize
);
508 AVIStreamRelease(pStream1
);
509 AVIFileRelease(pFile
);
510 ok(DeleteFileA(filename
) !=0, "Deleting file %s failed\n", filename
);
513 static void test_ash1_corruption2(void)
515 COMMON_AVI_HEADERS cah
;
516 char filename
[MAX_PATH
];
522 GetTempPathA(MAX_PATH
, filename
);
523 strcpy(filename
+strlen(filename
), testfilename
);
525 /* Corrupt the block alignment in the audio format header */
526 init_test_struct(&cah
);
527 cah
.pcmwf
.wf
.nBlockAlign
= 0xdead;
529 create_avi_file(&cah
, filename
);
531 res
= AVIFileOpenA(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
532 ok(res
== 0, "Unable to open file: error=%u\n", res
);
534 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
535 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
537 ok(AVIStreamInfoA(pStream1
, &asi1
, sizeof(asi1
)) == 0, "Unable to read stream info\n");
539 /* The result will also be the corrupt value, as explained above. */
540 ok(asi1
.dwSampleSize
== 0xdead, "got 0x%x (expected 0xdead)\n", asi1
.dwSampleSize
);
542 AVIStreamRelease(pStream1
);
543 AVIFileRelease(pFile
);
544 ok(DeleteFileA(filename
) !=0, "Deleting file %s failed\n", filename
);
547 /* Outer IUnknown for COM aggregation tests */
549 IUnknown IUnknown_iface
;
554 static inline struct unk_impl
*impl_from_IUnknown(IUnknown
*iface
)
556 return CONTAINING_RECORD(iface
, struct unk_impl
, IUnknown_iface
);
559 static HRESULT WINAPI
unk_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
561 struct unk_impl
*This
= impl_from_IUnknown(iface
);
562 LONG ref
= This
->ref
;
565 if (IsEqualGUID(riid
, &IID_IUnknown
))
568 IUnknown_AddRef(iface
);
572 hr
= IUnknown_QueryInterface(This
->inner_unk
, riid
, ppv
);
575 trace("Working around COM aggregation ref counting bug\n");
576 ok(ref
== This
->ref
, "Outer ref count expected %d got %d\n", ref
, This
->ref
);
577 IUnknown_AddRef((IUnknown
*)*ppv
);
578 ref
= IUnknown_Release(This
->inner_unk
);
579 ok(ref
== 1, "Inner ref count expected 1 got %d\n", ref
);
585 static ULONG WINAPI
unk_AddRef(IUnknown
*iface
)
587 struct unk_impl
*This
= impl_from_IUnknown(iface
);
589 return InterlockedIncrement(&This
->ref
);
592 static ULONG WINAPI
unk_Release(IUnknown
*iface
)
594 struct unk_impl
*This
= impl_from_IUnknown(iface
);
596 return InterlockedDecrement(&This
->ref
);
599 static const IUnknownVtbl unk_vtbl
=
606 static void test_COM(void)
608 struct unk_impl unk_obj
= {{&unk_vtbl
}, 19, NULL
};
609 IAVIFile
*avif
= NULL
;
615 /* COM aggregation */
616 hr
= CoCreateInstance(&CLSID_AVIFile
, &unk_obj
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
617 &IID_IUnknown
, (void**)&unk_obj
.inner_unk
);
618 ok(hr
== S_OK
, "COM aggregation failed: %08x, expected S_OK\n", hr
);
619 hr
= IUnknown_QueryInterface(&unk_obj
.IUnknown_iface
, &IID_IAVIFile
, (void**)&avif
);
620 ok(hr
== S_OK
, "QueryInterface for IID_IAVIFile failed: %08x\n", hr
);
621 refcount
= IAVIFile_AddRef(avif
);
622 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
623 refcount
= IAVIFile_Release(avif
);
624 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
625 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
626 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
627 refcount
= IPersistFile_Release(pf
);
628 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
629 refcount
= IAVIFile_Release(avif
);
630 ok(refcount
== 19, "Outer ref count should be back at 19 but is %d\n", refcount
);
631 refcount
= IUnknown_Release(unk_obj
.inner_unk
);
632 ok(refcount
== 0, "Inner ref count should be 0 but is %u\n", refcount
);
635 hr
= CoCreateInstance(&CLSID_AVIFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIStream
,
637 ok(hr
== E_NOINTERFACE
, "AVIFile create failed: %08x, expected E_NOINTERFACE\n", hr
);
640 hr
= CoCreateInstance(&CLSID_AVIFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIFile
, (void**)&avif
);
641 ok(hr
== S_OK
, "AVIFile create failed: %08x, expected S_OK\n", hr
);
642 refcount
= IAVIFile_AddRef(avif
);
643 ok(refcount
== 2, "refcount == %u, expected 2\n", refcount
);
644 hr
= IAVIFile_QueryInterface(avif
, &IID_IUnknown
, (void**)&unk
);
645 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %08x\n", hr
);
646 refcount
= IUnknown_AddRef(unk
);
647 ok(refcount
== 4, "refcount == %u, expected 4\n", refcount
);
648 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
649 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
650 refcount
= IPersistFile_AddRef(pf
);
651 ok(refcount
== 6, "refcount == %u, expected 6\n", refcount
);
653 while (IAVIFile_Release(avif
));
656 static void test_COM_wavfile(void)
658 struct unk_impl unk_obj
= {{&unk_vtbl
}, 19, NULL
};
659 IAVIFile
*avif
= NULL
;
666 /* COM aggregation */
667 hr
= CoCreateInstance(&CLSID_WAVFile
, &unk_obj
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
668 &IID_IUnknown
, (void**)&unk_obj
.inner_unk
);
669 ok(hr
== S_OK
, "COM aggregation failed: %08x, expected S_OK\n", hr
);
670 hr
= IUnknown_QueryInterface(&unk_obj
.IUnknown_iface
, &IID_IAVIFile
, (void**)&avif
);
671 ok(hr
== S_OK
, "QueryInterface for IID_IAVIFile failed: %08x\n", hr
);
672 refcount
= IAVIFile_AddRef(avif
);
673 ok(refcount
== unk_obj
.ref
, "WAVFile just pretends to support COM aggregation\n");
674 refcount
= IAVIFile_Release(avif
);
675 ok(refcount
== unk_obj
.ref
, "WAVFile just pretends to support COM aggregation\n");
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_Release(pf
);
679 ok(refcount
== unk_obj
.ref
, "WAVFile just pretends to support COM aggregation\n");
680 refcount
= IAVIFile_Release(avif
);
681 ok(refcount
== 19, "Outer ref count should be back at 19 but is %d\n", refcount
);
682 refcount
= IUnknown_Release(unk_obj
.inner_unk
);
683 ok(refcount
== 0, "Inner ref count should be 0 but is %u\n", refcount
);
686 hr
= CoCreateInstance(&CLSID_WAVFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIStreaming
,
688 ok(hr
== E_NOINTERFACE
, "WAVFile create failed: %08x, expected E_NOINTERFACE\n", hr
);
690 /* Same refcount for all WAVFile interfaces */
691 hr
= CoCreateInstance(&CLSID_WAVFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIFile
, (void**)&avif
);
692 ok(hr
== S_OK
, "WAVFile create failed: %08x, expected S_OK\n", hr
);
693 refcount
= IAVIFile_AddRef(avif
);
694 ok(refcount
== 2, "refcount == %u, expected 2\n", refcount
);
696 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
697 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
698 refcount
= IPersistFile_AddRef(pf
);
699 ok(refcount
== 4, "refcount == %u, expected 4\n", refcount
);
700 refcount
= IPersistFile_Release(pf
);
702 hr
= IAVIFile_QueryInterface(avif
, &IID_IAVIStream
, (void**)&avis
);
703 ok(hr
== S_OK
, "QueryInterface for IID_IAVIStream failed: %08x\n", hr
);
704 refcount
= IAVIStream_AddRef(avis
);
705 ok(refcount
== 5, "refcount == %u, expected 5\n", refcount
);
706 refcount
= IAVIStream_Release(avis
);
708 hr
= IAVIFile_QueryInterface(avif
, &IID_IUnknown
, (void**)&unk
);
709 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %08x\n", hr
);
710 refcount
= IUnknown_AddRef(unk
);
711 ok(refcount
== 6, "refcount == %u, expected 6\n", refcount
);
712 refcount
= IUnknown_Release(unk
);
714 while (IAVIFile_Release(avif
));
717 static void test_COM_editstream(void)
719 IAVIEditStream
*edit
;
725 /* Same refcount for all AVIEditStream interfaces */
726 hr
= CreateEditableStream(&stream
, NULL
);
727 ok(hr
== S_OK
, "AVIEditStream create failed: %08x, expected S_OK\n", hr
);
728 refcount
= IAVIStream_AddRef(stream
);
729 ok(refcount
== 2, "refcount == %u, expected 2\n", refcount
);
731 hr
= IAVIStream_QueryInterface(stream
, &IID_IAVIEditStream
, (void**)&edit
);
732 ok(hr
== S_OK
, "QueryInterface for IID_IAVIEditStream failed: %08x\n", hr
);
733 refcount
= IAVIEditStream_AddRef(edit
);
734 ok(refcount
== 4, "refcount == %u, expected 4\n", refcount
);
735 refcount
= IAVIEditStream_Release(edit
);
737 hr
= IAVIEditStream_QueryInterface(edit
, &IID_IUnknown
, (void**)&unk
);
738 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %08x\n", hr
);
739 refcount
= IUnknown_AddRef(unk
);
740 ok(refcount
== 5, "refcount == %u, expected 5\n", refcount
);
741 IUnknown_Release(unk
);
743 while (IAVIEditStream_Release(edit
));
750 test_EditStreamSetInfo();
751 test_AVISaveOptions();
753 test_amh_corruption();
754 test_ash1_corruption();
755 test_ash1_corruption2();
758 test_COM_editstream();