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 static const CHAR winetest0
[] = "winetest0";
33 static const CHAR winetest1
[] = "winetest1";
34 static const CHAR testfilename
[] = "wine_avifil32_test.avi";
36 /* ########################### */
38 static const DWORD deffh
[] = /* file_header */
40 FOURCC_RIFF
, 0x34c6 /* length */, formtypeAVI
,
41 FOURCC_LIST
, 0x1ac /* length */,
42 listtypeAVIHEADER
, ckidAVIMAINHDR
, sizeof(MainAVIHeader
),
45 static const MainAVIHeader defmah
=
47 0x00008256, /* dwMicroSecPerFrame */
48 0x000080e8, /* dwMaxBytesPerSec */
49 0x00000000, /* dwPaddingGranularity */
50 0x00000910, /* dwFlags */
51 1, /* dwTotalFrames */
52 0, /* dwInitialFrames */
54 0x00100000, /* dwSuggestedBufferSize*/
57 { 0, 0, 0, 0 } /* dwReserved[4] */
60 static const AVIStreamHeader defash0
=
62 streamtypeVIDEO
, /* fccType */
63 0x30323449, /* fccHandler */
64 0x00000000, /* dwFlags */
67 0, /* dwInitialFrames */
68 0x000003e9, /* dwScale */
69 0x00007530, /* dwRate */
72 0x00100000, /* dwSuggestedBufferSize*/
73 0xffffffff, /* dwQuality */
75 { 0, 0, 0, 0 } /* short left right top bottom */
78 static const AVIStreamHeader defash1
=
81 streamtypeAUDIO
, /* fccType */
86 0, /* dwInitialFrames */
88 0x00002b11, /* dwRate */
90 0x00000665, /* dwLength */
91 0x00003000, /* dwSuggestedBufferSize*/
92 0xffffffff, /* dwQuality */
94 { 0, 0, 0, 0 } /* short left right top bottom */
97 static const PCMWAVEFORMAT defpcmwf
=
102 11025, /* nSamplesPerSec */
103 22050, /* nAvgBytesPerSec */
106 8, /* wBitsPerSample */
109 typedef struct common_avi_headers
{
110 DWORD fh
[sizeof(deffh
)];
112 AVIStreamHeader ash0
;
113 AVIStreamHeader ash1
;
115 } COMMON_AVI_HEADERS
;
117 /* Extra data needed to get the VFW API to load the file */
119 /* MainAVIHeader mah */
120 static const DWORD streamlist
[] =
122 FOURCC_LIST
, 0xd4 /* length */,
123 listtypeSTREAMHEADER
, ckidSTREAMHEADER
, 0x38 /* length */,
125 /* AVIStreamHeader ash0 */
126 static const DWORD videostreamformat
[] =
128 ckidSTREAMFORMAT
, 0x28 /* length */,
129 0x00000028, 0x00000008, 0x00000006, 0x00180001,
130 0x30323449, 0x00000090, 0x00000000, 0x00000000,
131 0x00000000, 0x00000000,
133 static const DWORD padding1
[] =
135 ckidAVIPADDING
, 0xc /* length */,
136 0x00000004, 0x00000000, 0x63643030
138 static const DWORD videopropheader
[] =
140 0x70727076, 0x44 /* length */,
141 0x00000000, 0x00000000,
142 0x0000001e, 0x00000008, 0x00000006, 0x00100009,
143 0x00000008, 0x00000006, 0x00000001, 0x00000006,
144 0x00000008, 0x00000006, 0x00000008, 0x00000000,
145 0x00000000, 0x00000000, 0x00000000,
146 FOURCC_LIST
, 0x70 /* length */,
147 listtypeSTREAMHEADER
, ckidSTREAMHEADER
, 0x38 /* length */,
149 /* AVIStreamHeader ash1 */
150 static const DWORD audiostreamformat_pre
[] =
152 ckidSTREAMFORMAT
, sizeof(PCMWAVEFORMAT
) /* length */,
154 /* PCMWAVEFORMAT pcmwf */
155 static DWORD data
[] =
157 ckidAVIPADDING
, 0xc /* length */,
158 0x00000004, 0x00000000, 0x62773130,
159 ckidAVIPADDING
, 0xc /* length */,
160 0x6c6d646f, 0x686c6d64, 0x000000f8,
161 FOURCC_LIST
, 0x18 /* length */,
163 0x54465349, 0xc /* length */,
164 0x6676614c, 0x332e3235, 0x00302e37,
165 ckidAVIPADDING
, 0x4 /* length */,
167 FOURCC_LIST
, 0xd1b /* length */, listtypeAVIMOVIE
,
171 /* ########################### */
173 static void test_AVISaveOptions(void)
175 AVICOMPRESSOPTIONS options
[2];
176 LPAVICOMPRESSOPTIONS poptions
[2];
177 PAVISTREAM streams
[2] = {NULL
, NULL
};
182 poptions
[0] = &options
[0];
183 poptions
[1] = &options
[1];
184 ZeroMemory(options
, sizeof(options
));
186 SetLastError(0xdeadbeef);
187 hres
= CreateEditableStream(&streams
[0], NULL
);
188 ok(hres
== AVIERR_OK
, "0: got 0x%x and %p (expected AVIERR_OK)\n", hres
, streams
[0]);
190 SetLastError(0xdeadbeef);
191 hres
= CreateEditableStream(&streams
[1], NULL
);
192 ok(hres
== AVIERR_OK
, "1: got 0x%x and %p (expected AVIERR_OK)\n", hres
, streams
[1]);
194 SetLastError(0xdeadbeef);
195 hres
= EditStreamSetNameA(streams
[0], winetest0
);
196 ok(hres
== AVIERR_OK
, "0: got 0x%x (expected AVIERR_OK)\n", hres
);
198 SetLastError(0xdeadbeef);
199 hres
= EditStreamSetNameA(streams
[1], winetest1
);
200 ok(hres
== AVIERR_OK
, "1: got 0x%x (expected AVIERR_OK)\n", hres
);
202 if (winetest_interactive
) {
203 SetLastError(0xdeadbeef);
204 res
= AVISaveOptions(0, ICMF_CHOOSE_DATARATE
|ICMF_CHOOSE_KEYFRAME
| ICMF_CHOOSE_ALLCOMPRESSORS
,
205 2, streams
, poptions
);
206 trace("got %u with 0x%x/%u\n", res
, GetLastError(), GetLastError());
209 SetLastError(0xdeadbeef);
210 lres
= AVISaveOptionsFree(2, poptions
);
211 ok(lres
== AVIERR_OK
, "got 0x%x with 0x%x/%u\n", lres
, GetLastError(), GetLastError());
213 SetLastError(0xdeadbeef);
214 res
= AVIStreamRelease(streams
[0]);
215 ok(res
== 0, "0: got refcount %u (expected 0)\n", res
);
217 SetLastError(0xdeadbeef);
218 res
= AVIStreamRelease(streams
[1]);
219 ok(res
== 0, "1: got refcount %u (expected 0)\n", res
);
223 /* ########################### */
225 static void test_EditStreamSetInfo(void)
227 PAVISTREAM stream
= NULL
;
229 AVISTREAMINFO info
, info2
;
231 hres
= CreateEditableStream(&stream
, NULL
);
232 ok(hres
== AVIERR_OK
, "got 0x%08X, expected AVIERR_OK\n", hres
);
234 /* Size parameter is somehow checked (notice the crash with size=-1 below) */
235 hres
= EditStreamSetInfo(stream
, NULL
, 0);
236 ok( hres
== AVIERR_BADSIZE
, "got 0x%08X, expected AVIERR_BADSIZE\n", hres
);
238 hres
= EditStreamSetInfo(stream
, NULL
, sizeof(AVISTREAMINFO
)-1 );
239 ok( hres
== AVIERR_BADSIZE
, "got 0x%08X, expected AVIERR_BADSIZE\n", hres
);
243 /* Crashing - first parameter not checked */
244 EditStreamSetInfo(NULL
, &info
, sizeof(AVISTREAMINFO
) );
246 /* Crashing - second parameter not checked */
247 EditStreamSetInfo(stream
, NULL
, sizeof(AVISTREAMINFO
) );
249 EditStreamSetInfo(stream
, NULL
, -1);
252 hres
= AVIStreamInfo(stream
, &info
, sizeof(AVISTREAMINFO
) );
253 ok( hres
== 0, "got 0x%08X, expected 0\n", hres
);
255 /* Does the function check what's it's updating ? */
257 #define IS_INFO_UPDATED(m) do { \
258 hres = EditStreamSetInfo(stream, &info, sizeof(AVISTREAMINFO) ); \
259 ok( hres == 0, "got 0x%08X, expected 0\n", hres); \
260 hres = AVIStreamInfo(stream, &info2, sizeof(AVISTREAMINFO) ); \
261 ok( hres == 0, "got 0x%08X, expected 0\n", hres); \
262 ok( info2.m == info.m, "EditStreamSetInfo did not update "#m" parameter\n" ); \
266 IS_INFO_UPDATED(dwStart
);
268 IS_INFO_UPDATED(dwStart
);
271 IS_INFO_UPDATED(wPriority
);
273 IS_INFO_UPDATED(wPriority
);
276 IS_INFO_UPDATED(wLanguage
);
278 IS_INFO_UPDATED(wLanguage
);
281 IS_INFO_UPDATED(dwScale
);
283 IS_INFO_UPDATED(dwScale
);
286 IS_INFO_UPDATED(dwRate
);
288 IS_INFO_UPDATED(dwRate
);
291 IS_INFO_UPDATED(dwQuality
);
293 IS_INFO_UPDATED(dwQuality
);
295 IS_INFO_UPDATED(dwQuality
);
296 info
.dwQuality
= ICQUALITY_HIGH
+1;
297 IS_INFO_UPDATED(dwQuality
);
299 info
.rcFrame
.left
= 0;
300 IS_INFO_UPDATED(rcFrame
.left
);
301 info
.rcFrame
.top
= 0;
302 IS_INFO_UPDATED(rcFrame
.top
);
303 info
.rcFrame
.right
= 0;
304 IS_INFO_UPDATED(rcFrame
.right
);
305 info
.rcFrame
.bottom
= 0;
306 IS_INFO_UPDATED(rcFrame
.bottom
);
308 info
.rcFrame
.left
= -1;
309 IS_INFO_UPDATED(rcFrame
.left
);
310 info
.rcFrame
.top
= -1;
311 IS_INFO_UPDATED(rcFrame
.top
);
312 info
.rcFrame
.right
= -1;
313 IS_INFO_UPDATED(rcFrame
.right
);
314 info
.rcFrame
.bottom
= -1;
315 IS_INFO_UPDATED(rcFrame
.bottom
);
316 AVIStreamRelease(stream
);
317 #undef IS_INFO_UPDATED
321 static void init_test_struct(COMMON_AVI_HEADERS
*cah
)
323 memcpy(cah
->fh
, deffh
, sizeof(deffh
));
327 cah
->pcmwf
= defpcmwf
;
330 static void create_avi_file(const COMMON_AVI_HEADERS
*cah
, char *filename
)
335 hFile
= CreateFile(filename
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
337 ok(hFile
!= INVALID_HANDLE_VALUE
, "Couldn't create file\n");
339 WriteFile(hFile
, &cah
->fh
, sizeof(deffh
), &written
, NULL
);
340 WriteFile(hFile
, &cah
->mah
, sizeof(MainAVIHeader
), &written
, NULL
);
341 WriteFile(hFile
, streamlist
, sizeof(streamlist
), &written
, NULL
);
342 WriteFile(hFile
, &cah
->ash0
, 0x38, &written
, NULL
);
343 WriteFile(hFile
, videostreamformat
, sizeof(videostreamformat
), &written
, NULL
);
344 WriteFile(hFile
, padding1
, sizeof(padding1
), &written
, NULL
);
345 WriteFile(hFile
, videopropheader
, sizeof(videopropheader
), &written
, NULL
);
346 WriteFile(hFile
, &cah
->ash1
, 0x38, &written
, NULL
);
347 WriteFile(hFile
, audiostreamformat_pre
, sizeof(audiostreamformat_pre
), &written
, NULL
);
348 WriteFile(hFile
, &cah
->pcmwf
, sizeof(PCMWAVEFORMAT
), &written
, NULL
);
349 WriteFile(hFile
, data
, sizeof(data
), &written
, NULL
);
354 static void test_default_data(void)
356 COMMON_AVI_HEADERS cah
;
357 char filename
[MAX_PATH
];
367 GetTempPath(MAX_PATH
, filename
);
368 strcpy(filename
+strlen(filename
), testfilename
);
370 init_test_struct(&cah
);
371 create_avi_file(&cah
, filename
);
373 res
= AVIFileOpen(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
374 ok(res
!= AVIERR_BADFORMAT
, "Unable to open file: error1=%u\n", AVIERR_BADFORMAT
);
375 ok(res
!= AVIERR_MEMORY
, "Unable to open file: error2=%u\n", AVIERR_MEMORY
);
376 ok(res
!= AVIERR_FILEREAD
, "Unable to open file: error3=%u\n", AVIERR_FILEREAD
);
377 ok(res
!= AVIERR_FILEOPEN
, "Unable to open file: error4=%u\n", AVIERR_FILEOPEN
);
378 ok(res
!= REGDB_E_CLASSNOTREG
, "Unable to open file: error5=%u\n", REGDB_E_CLASSNOTREG
);
379 ok(res
== 0, "Unable to open file: error=%u\n", res
);
381 res
= AVIFileGetStream(pFile
, &pStream0
, 0, 0);
382 ok(res
== 0, "Unable to open video stream: error=%u\n", res
);
384 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
385 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
387 res
= AVIStreamInfo(pStream0
, &asi0
, sizeof(AVISTREAMINFO
));
388 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
390 res
= AVIStreamInfo(pStream1
, &asi1
, sizeof(AVISTREAMINFO
));
391 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
393 res
= AVIStreamReadFormat(pStream0
, AVIStreamStart(pStream1
), NULL
, &lSize
);
394 ok(res
== 0, "Unable to read format size: error=%u\n", res
);
396 res
= AVIStreamReadFormat(pStream1
, AVIStreamStart(pStream1
), &wfx
, &lSize
);
397 ok(res
== 0, "Unable to read format: error=%u\n", res
);
399 ok(asi0
.fccType
== streamtypeVIDEO
, "got 0x%x (expected streamtypeVIDEO)\n", asi0
.fccType
);
400 ok(asi0
.fccHandler
== 0x30323449, "got 0x%x (expected 0x30323449)\n", asi0
.fccHandler
);
401 ok(asi0
.dwFlags
== 0, "got %u (expected 0)\n", asi0
.dwFlags
);
402 ok(asi0
.wPriority
== 0, "got %u (expected 0)\n", asi0
.wPriority
);
403 ok(asi0
.wLanguage
== 0, "got %u (expected 0)\n", asi0
.wLanguage
);
404 ok(asi0
.dwScale
== 1001, "got %u (expected 1001)\n", asi0
.dwScale
);
405 ok(asi0
.dwRate
== 30000, "got %u (expected 30000)\n", asi0
.dwRate
);
406 ok(asi0
.dwStart
== 0, "got %u (expected 0)\n", asi0
.dwStart
);
407 ok(asi0
.dwLength
== 1, "got %u (expected 1)\n", asi0
.dwLength
);
408 ok(asi0
.dwInitialFrames
== 0, "got %u (expected 0)\n", asi0
.dwInitialFrames
);
409 ok(asi0
.dwSuggestedBufferSize
== 0, "got %u (expected 0)\n", asi0
.dwSuggestedBufferSize
);
410 ok(asi0
.dwQuality
== 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi0
.dwQuality
);
411 ok(asi0
.dwSampleSize
== 0, "got %u (expected 0)\n", asi0
.dwSampleSize
);
412 ok(asi0
.rcFrame
.left
== 0, "got %u (expected 0)\n", asi0
.rcFrame
.left
);
413 ok(asi0
.rcFrame
.top
== 0, "got %u (expected 0)\n", asi0
.rcFrame
.top
);
414 ok(asi0
.rcFrame
.right
== 8, "got %u (expected 8)\n", asi0
.rcFrame
.right
); /* these are based on the values in the mah and not */
415 ok(asi0
.rcFrame
.bottom
== 6, "got %u (expected 6)\n", asi0
.rcFrame
.bottom
);/* on the ones in the ash which are 0 here */
416 ok(asi0
.dwEditCount
== 0, "got %u (expected 0)\n", asi0
.dwEditCount
);
417 ok(asi0
.dwFormatChangeCount
== 0, "got %u (expected 0)\n", asi0
.dwFormatChangeCount
);
419 ok(asi1
.fccType
== streamtypeAUDIO
, "got 0x%x (expected streamtypeVIDEO)\n", asi1
.fccType
);
420 ok(asi1
.fccHandler
== 0x1, "got 0x%x (expected 0x1)\n", asi1
.fccHandler
);
421 ok(asi1
.dwFlags
== 0, "got %u (expected 0)\n", asi1
.dwFlags
);
422 ok(asi1
.wPriority
== 0, "got %u (expected 0)\n", asi1
.wPriority
);
423 ok(asi1
.wLanguage
== 0, "got %u (expected 0)\n", asi1
.wLanguage
);
424 ok(asi1
.dwScale
== 1, "got %u (expected 1)\n", asi1
.dwScale
);
425 ok(asi1
.dwRate
== 11025, "got %u (expected 11025)\n", asi1
.dwRate
);
426 ok(asi1
.dwStart
== 0, "got %u (expected 0)\n", asi1
.dwStart
);
427 ok(asi1
.dwLength
== 1637, "got %u (expected 1637)\n", asi1
.dwLength
);
428 ok(asi1
.dwInitialFrames
== 0, "got %u (expected 0)\n", asi1
.dwInitialFrames
);
429 ok(asi1
.dwSuggestedBufferSize
== 0, "got %u (expected 0)\n", asi1
.dwSuggestedBufferSize
);
430 ok(asi1
.dwQuality
== 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi1
.dwQuality
);
431 ok(asi1
.dwSampleSize
== 2, "got %u (expected 2)\n", asi1
.dwSampleSize
);
432 ok(asi1
.rcFrame
.left
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.left
);
433 ok(asi1
.rcFrame
.top
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.top
);
434 ok(asi1
.rcFrame
.right
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.right
);
435 ok(asi1
.rcFrame
.bottom
== 0, "got %u (expected 0)\n", asi1
.rcFrame
.bottom
);
436 ok(asi1
.dwEditCount
== 0, "got %u (expected 0)\n", asi1
.dwEditCount
);
437 ok(asi1
.dwFormatChangeCount
== 0, "got %u (expected 0)\n", asi1
.dwFormatChangeCount
);
439 ok(wfx
.wFormatTag
== 1, "got %u (expected 1)\n",wfx
.wFormatTag
);
440 ok(wfx
.nChannels
== 2, "got %u (expected 2)\n",wfx
.nChannels
);
441 ok(wfx
.wFormatTag
== 1, "got %u (expected 1)\n",wfx
.wFormatTag
);
442 ok(wfx
.nSamplesPerSec
== 11025, "got %u (expected 11025)\n",wfx
.nSamplesPerSec
);
443 ok(wfx
.nAvgBytesPerSec
== 22050, "got %u (expected 22050)\n",wfx
.nAvgBytesPerSec
);
444 ok(wfx
.nBlockAlign
== 2, "got %u (expected 2)\n",wfx
.nBlockAlign
);
446 AVIStreamRelease(pStream0
);
447 AVIStreamRelease(pStream1
);
448 AVIFileRelease(pFile
);
449 ok(DeleteFile(filename
) !=0, "Deleting file %s failed\n", filename
);
452 static void test_amh_corruption(void)
454 COMMON_AVI_HEADERS cah
;
455 char filename
[MAX_PATH
];
459 GetTempPath(MAX_PATH
, filename
);
460 strcpy(filename
+strlen(filename
), testfilename
);
462 /* Make sure only AVI files with the proper headers will be loaded */
463 init_test_struct(&cah
);
464 cah
.fh
[3] = mmioFOURCC('A', 'V', 'i', ' ');
466 create_avi_file(&cah
, filename
);
467 res
= AVIFileOpen(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
468 ok(res
!= 0, "Able to open file: error=%u\n", res
);
470 ok(DeleteFile(filename
) !=0, "Deleting file %s failed\n", filename
);
473 static void test_ash1_corruption(void)
475 COMMON_AVI_HEADERS cah
;
476 char filename
[MAX_PATH
];
482 GetTempPath(MAX_PATH
, filename
);
483 strcpy(filename
+strlen(filename
), testfilename
);
485 /* Corrupt the sample size in the audio stream header */
486 init_test_struct(&cah
);
487 cah
.ash1
.dwSampleSize
= 0xdeadbeef;
489 create_avi_file(&cah
, filename
);
491 res
= AVIFileOpen(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
492 ok(res
== 0, "Unable to open file: error=%u\n", res
);
494 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
495 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
497 res
= AVIStreamInfo(pStream1
, &asi1
, sizeof(AVISTREAMINFO
));
498 ok(res
== 0, "Unable to read stream info: error=%u\n", res
);
500 /* The result will still be 2, because the value is dynamically replaced with the nBlockAlign
501 value from the stream format header. The next test will prove this */
502 ok(asi1
.dwSampleSize
== 2, "got %u (expected 2)\n", asi1
.dwSampleSize
);
504 AVIStreamRelease(pStream1
);
505 AVIFileRelease(pFile
);
506 ok(DeleteFile(filename
) !=0, "Deleting file %s failed\n", filename
);
509 static void test_ash1_corruption2(void)
511 COMMON_AVI_HEADERS cah
;
512 char filename
[MAX_PATH
];
518 GetTempPath(MAX_PATH
, filename
);
519 strcpy(filename
+strlen(filename
), testfilename
);
521 /* Corrupt the block alignment in the audio format header */
522 init_test_struct(&cah
);
523 cah
.pcmwf
.wf
.nBlockAlign
= 0xdead;
525 create_avi_file(&cah
, filename
);
527 res
= AVIFileOpen(&pFile
, filename
, OF_SHARE_DENY_WRITE
, 0L);
528 ok(res
== 0, "Unable to open file: error=%u\n", res
);
530 res
= AVIFileGetStream(pFile
, &pStream1
, 0, 1);
531 ok(res
== 0, "Unable to open audio stream: error=%u\n", res
);
533 ok(AVIStreamInfo(pStream1
, &asi1
, sizeof(AVISTREAMINFO
)) == 0, "Unable to read stream info\n");
535 /* The result will also be the corrupt value, as explained above. */
536 ok(asi1
.dwSampleSize
== 0xdead, "got 0x%x (expected 0xdead)\n", asi1
.dwSampleSize
);
538 AVIStreamRelease(pStream1
);
539 AVIFileRelease(pFile
);
540 ok(DeleteFile(filename
) !=0, "Deleting file %s failed\n", filename
);
543 /* Outer IUnknown for COM aggregation tests */
545 IUnknown IUnknown_iface
;
550 static inline struct unk_impl
*impl_from_IUnknown(IUnknown
*iface
)
552 return CONTAINING_RECORD(iface
, struct unk_impl
, IUnknown_iface
);
555 static HRESULT WINAPI
unk_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
557 struct unk_impl
*This
= impl_from_IUnknown(iface
);
558 LONG ref
= This
->ref
;
561 if (IsEqualGUID(riid
, &IID_IUnknown
))
564 IUnknown_AddRef(iface
);
568 hr
= IUnknown_QueryInterface(This
->inner_unk
, riid
, ppv
);
571 trace("Working around COM aggregation ref counting bug\n");
572 ok(ref
== This
->ref
, "Outer ref count expected %d got %d\n", ref
, This
->ref
);
573 IUnknown_AddRef((IUnknown
*)*ppv
);
574 ref
= IUnknown_Release(This
->inner_unk
);
575 ok(ref
== 1, "Inner ref count expected 1 got %d\n", ref
);
581 static ULONG WINAPI
unk_AddRef(IUnknown
*iface
)
583 struct unk_impl
*This
= impl_from_IUnknown(iface
);
585 return InterlockedIncrement(&This
->ref
);
588 static ULONG WINAPI
unk_Release(IUnknown
*iface
)
590 struct unk_impl
*This
= impl_from_IUnknown(iface
);
592 return InterlockedDecrement(&This
->ref
);
595 static const IUnknownVtbl unk_vtbl
=
602 static void test_COM(void)
604 struct unk_impl unk_obj
= {{&unk_vtbl
}, 19, NULL
};
605 IAVIFile
*avif
= NULL
;
611 /* COM aggregation */
612 hr
= CoCreateInstance(&CLSID_AVIFile
, &unk_obj
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
613 &IID_IUnknown
, (void**)&unk_obj
.inner_unk
);
614 ok(hr
== S_OK
, "COM aggregation failed: %08x, expected S_OK\n", hr
);
615 hr
= IUnknown_QueryInterface(&unk_obj
.IUnknown_iface
, &IID_IAVIFile
, (void**)&avif
);
616 ok(hr
== S_OK
, "QueryInterface for IID_IAVIFile failed: %08x\n", hr
);
617 refcount
= IAVIFile_AddRef(avif
);
618 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
619 refcount
= IAVIFile_Release(avif
);
620 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
621 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
622 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
623 refcount
= IPersistFile_Release(pf
);
624 ok(refcount
== unk_obj
.ref
, "AVIFile just pretends to support COM aggregation\n");
625 refcount
= IAVIFile_Release(avif
);
626 ok(refcount
== 19, "Outer ref count should be back at 19 but is %d\n", refcount
);
627 refcount
= IUnknown_Release(unk_obj
.inner_unk
);
628 ok(refcount
== 0, "Inner ref count should be 0 but is %u\n", refcount
);
631 hr
= CoCreateInstance(&CLSID_AVIFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIStream
,
633 ok(hr
== E_NOINTERFACE
, "AVIFile create failed: %08x, expected E_NOINTERFACE\n", hr
);
636 hr
= CoCreateInstance(&CLSID_AVIFile
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IAVIFile
, (void**)&avif
);
637 ok(hr
== S_OK
, "AVIFile create failed: %08x, expected S_OK\n", hr
);
638 refcount
= IAVIFile_AddRef(avif
);
639 ok(refcount
== 2, "refcount == %u, expected 2\n", refcount
);
640 hr
= IAVIFile_QueryInterface(avif
, &IID_IUnknown
, (void**)&unk
);
641 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %08x\n", hr
);
642 refcount
= IUnknown_AddRef(unk
);
643 ok(refcount
== 4, "refcount == %u, expected 4\n", refcount
);
644 hr
= IAVIFile_QueryInterface(avif
, &IID_IPersistFile
, (void**)&pf
);
645 ok(hr
== S_OK
, "QueryInterface for IID_IPersistFile failed: %08x\n", hr
);
646 refcount
= IPersistFile_AddRef(pf
);
647 ok(refcount
== 6, "refcount == %u, expected 6\n", refcount
);
649 while (IAVIFile_Release(avif
));
656 test_EditStreamSetInfo();
657 test_AVISaveOptions();
659 test_amh_corruption();
660 test_ash1_corruption();
661 test_ash1_corruption2();