Release 1.6-rc2.
[wine/testsucceed.git] / dlls / avifil32 / tests / api.c
blob22c15c59426e2734bfdd3ddffcce28dc7a55fe4d
1 /*
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 COBJMACROS
23 #define CONST_VTABLE
25 #include "wine/test.h"
26 #include "initguid.h"
27 #include "wingdi.h"
28 #include "vfw.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 */
53 2, /* dwStreams */
54 0x00100000, /* dwSuggestedBufferSize*/
55 8, /* dwWidth */
56 6, /* dwHeight */
57 { 0, 0, 0, 0 } /* dwReserved[4] */
60 static const AVIStreamHeader defash0 =
62 streamtypeVIDEO, /* fccType */
63 0x30323449, /* fccHandler */
64 0x00000000, /* dwFlags */
65 0, /* wPriority */
66 0, /* wLanguage */
67 0, /* dwInitialFrames */
68 0x000003e9, /* dwScale */
69 0x00007530, /* dwRate */
70 0, /* dwStart */
71 1, /* dwLength */
72 0x00100000, /* dwSuggestedBufferSize*/
73 0xffffffff, /* dwQuality */
74 0, /* dwSampleSize */
75 { 0, 0, 0, 0 } /* short left right top bottom */
78 static const AVIStreamHeader defash1 =
80 /* AVIStreamHeader */
81 streamtypeAUDIO, /* fccType */
82 1, /* fccHandler */
83 0, /* dwFlags */
84 0, /* wPriority */
85 0, /* wLanguage */
86 0, /* dwInitialFrames */
87 1, /* dwScale */
88 0x00002b11, /* dwRate */
89 0, /* dwStart */
90 0x00000665, /* dwLength */
91 0x00003000, /* dwSuggestedBufferSize*/
92 0xffffffff, /* dwQuality */
93 2, /* dwSampleSize */
94 { 0, 0, 0, 0 } /* short left right top bottom */
97 static const PCMWAVEFORMAT defpcmwf =
100 1, /* wFormatTag */
101 2, /* nChannels */
102 11025, /* nSamplesPerSec */
103 22050, /* nAvgBytesPerSec */
104 2, /* nBlockAlign */
106 8, /* wBitsPerSample */
109 typedef struct common_avi_headers {
110 DWORD fh[sizeof(deffh)];
111 MainAVIHeader mah;
112 AVIStreamHeader ash0;
113 AVIStreamHeader ash1;
114 PCMWAVEFORMAT pcmwf;
115 } COMMON_AVI_HEADERS;
117 /* Extra data needed to get the VFW API to load the file */
118 /* DWORD deffh */
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 */,
162 0x4f464e49,
163 0x54465349, 0xc /* length */,
164 0x6676614c, 0x332e3235, 0x00302e37,
165 ckidAVIPADDING, 0x4 /* length */,
167 FOURCC_LIST, 0xd1b /* length */, listtypeAVIMOVIE,
168 0, 0
171 /* ########################### */
173 static void test_AVISaveOptions(void)
175 AVICOMPRESSOPTIONS options[2];
176 LPAVICOMPRESSOPTIONS poptions[2];
177 PAVISTREAM streams[2] = {NULL, NULL};
178 HRESULT hres;
179 DWORD res;
180 LONG lres;
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;
228 HRESULT hres;
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);
241 if(0)
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" ); \
263 } while(0)
265 info.dwStart++;
266 IS_INFO_UPDATED(dwStart);
267 info.dwStart = 0;
268 IS_INFO_UPDATED(dwStart);
270 info.wPriority++;
271 IS_INFO_UPDATED(wPriority);
272 info.wPriority = 0;
273 IS_INFO_UPDATED(wPriority);
275 info.wLanguage++;
276 IS_INFO_UPDATED(wLanguage);
277 info.wLanguage = 0;
278 IS_INFO_UPDATED(wLanguage);
280 info.dwScale++;
281 IS_INFO_UPDATED(dwScale);
282 info.dwScale = 0;
283 IS_INFO_UPDATED(dwScale);
285 info.dwRate++;
286 IS_INFO_UPDATED(dwRate);
287 info.dwRate = 0;
288 IS_INFO_UPDATED(dwRate);
290 info.dwQuality++;
291 IS_INFO_UPDATED(dwQuality);
292 info.dwQuality = 0;
293 IS_INFO_UPDATED(dwQuality);
294 info.dwQuality = -2;
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));
324 cah->mah = defmah;
325 cah->ash0 = defash0;
326 cah->ash1 = defash1;
327 cah->pcmwf = defpcmwf;
330 static void create_avi_file(const COMMON_AVI_HEADERS *cah, char *filename)
332 HANDLE hFile;
333 DWORD written;
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);
351 CloseHandle(hFile);
354 static void test_default_data(void)
356 COMMON_AVI_HEADERS cah;
357 char filename[MAX_PATH];
358 PAVIFILE pFile;
359 int res;
360 LONG lSize;
361 PAVISTREAM pStream0;
362 PAVISTREAM pStream1;
363 AVISTREAMINFO asi0;
364 AVISTREAMINFO asi1;
365 WAVEFORMATEX wfx;
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];
456 PAVIFILE pFile;
457 int res;
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];
477 PAVIFILE pFile;
478 int res;
479 PAVISTREAM pStream1;
480 AVISTREAMINFO asi1;
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];
513 PAVIFILE pFile;
514 int res;
515 PAVISTREAM pStream1;
516 AVISTREAMINFO asi1;
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 */
544 struct unk_impl {
545 IUnknown IUnknown_iface;
546 LONG ref;
547 IUnknown *inner_unk;
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;
559 HRESULT hr;
561 if (IsEqualGUID(riid, &IID_IUnknown))
563 *ppv = iface;
564 IUnknown_AddRef(iface);
565 return S_OK;
568 hr = IUnknown_QueryInterface(This->inner_unk, riid, ppv);
569 if (hr == S_OK)
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);
578 return hr;
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 =
597 unk_QueryInterface,
598 unk_AddRef,
599 unk_Release
602 static void test_COM(void)
604 struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL};
605 IAVIFile *avif = NULL;
606 IPersistFile *pf;
607 IUnknown *unk;
608 LONG refcount;
609 HRESULT hr;
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);
630 /* Invalid RIID */
631 hr = CoCreateInstance(&CLSID_AVIFile, NULL, CLSCTX_INPROC_SERVER, &IID_IAVIStream,
632 (void**)&avif);
633 ok(hr == E_NOINTERFACE, "AVIFile create failed: %08x, expected E_NOINTERFACE\n", hr);
635 /* Same refcount */
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));
652 START_TEST(api)
655 AVIFileInit();
656 test_EditStreamSetInfo();
657 test_AVISaveOptions();
658 test_default_data();
659 test_amh_corruption();
660 test_ash1_corruption();
661 test_ash1_corruption2();
662 test_COM();
663 AVIFileExit();