dinput/tests: Add EnumObjects callback return value test.
[wine.git] / dlls / avifil32 / tests / api.c
blobf7571f48b6a8bcc36059389e8728eb4275782f0c
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 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 */
54 2, /* dwStreams */
55 0x00100000, /* dwSuggestedBufferSize*/
56 8, /* dwWidth */
57 6, /* dwHeight */
58 { 0, 0, 0, 0 } /* dwReserved[4] */
61 static const AVIStreamHeader defash0 =
63 streamtypeVIDEO, /* fccType */
64 0x30323449, /* fccHandler */
65 0x00000000, /* dwFlags */
66 0, /* wPriority */
67 0, /* wLanguage */
68 0, /* dwInitialFrames */
69 0x000003e9, /* dwScale */
70 0x00007530, /* dwRate */
71 0, /* dwStart */
72 1, /* dwLength */
73 0x00100000, /* dwSuggestedBufferSize*/
74 0xffffffff, /* dwQuality */
75 0, /* dwSampleSize */
76 { 0, 0, 0, 0 } /* short left right top bottom */
79 static const AVIStreamHeader defash1 =
81 /* AVIStreamHeader */
82 streamtypeAUDIO, /* fccType */
83 1, /* fccHandler */
84 0, /* dwFlags */
85 0, /* wPriority */
86 0, /* wLanguage */
87 0, /* dwInitialFrames */
88 1, /* dwScale */
89 0x00002b11, /* dwRate */
90 0, /* dwStart */
91 0x00000665, /* dwLength */
92 0x00003000, /* dwSuggestedBufferSize*/
93 0xffffffff, /* dwQuality */
94 2, /* dwSampleSize */
95 { 0, 0, 0, 0 } /* short left right top bottom */
98 static const PCMWAVEFORMAT defpcmwf =
101 1, /* wFormatTag */
102 2, /* nChannels */
103 11025, /* nSamplesPerSec */
104 22050, /* nAvgBytesPerSec */
105 2, /* nBlockAlign */
107 8, /* wBitsPerSample */
110 typedef struct common_avi_headers {
111 DWORD fh[sizeof(deffh)];
112 MainAVIHeader mah;
113 AVIStreamHeader ash0;
114 AVIStreamHeader ash1;
115 PCMWAVEFORMAT pcmwf;
116 } COMMON_AVI_HEADERS;
118 /* Extra data needed to get the VFW API to load the file */
119 /* DWORD deffh */
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 */,
163 0x4f464e49,
164 0x54465349, 0xc /* length */,
165 0x6676614c, 0x332e3235, 0x00302e37,
166 ckidAVIPADDING, 0x4 /* length */,
168 FOURCC_LIST, 0xd1b /* length */, listtypeAVIMOVIE,
169 0, 0
172 /* ########################### */
174 static void test_AVISaveOptions(void)
176 AVICOMPRESSOPTIONS options[2];
177 LPAVICOMPRESSOPTIONS poptions[2];
178 PAVISTREAM streams[2] = {NULL, NULL};
179 HRESULT hres;
180 DWORD res;
181 LONG lres;
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%lx 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%lx 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%lx (expected AVIERR_OK)\n", hres);
199 SetLastError(0xdeadbeef);
200 hres = EditStreamSetNameA(streams[1], winetest1);
201 ok(hres == AVIERR_OK, "1: got 0x%lx (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 %lu with 0x%lx/%lu\n", res, GetLastError(), GetLastError());
210 SetLastError(0xdeadbeef);
211 lres = AVISaveOptionsFree(2, poptions);
212 ok(lres == AVIERR_OK, "got 0x%lx with 0x%lx/%lu\n", lres, GetLastError(), GetLastError());
214 SetLastError(0xdeadbeef);
215 res = AVIStreamRelease(streams[0]);
216 ok(res == 0, "0: got refcount %lu (expected 0)\n", res);
218 SetLastError(0xdeadbeef);
219 res = AVIStreamRelease(streams[1]);
220 ok(res == 0, "1: got refcount %lu (expected 0)\n", res);
224 /* ########################### */
226 static void test_EditStreamSetInfo(void)
228 PAVISTREAM stream = NULL;
229 HRESULT hres;
230 AVISTREAMINFOA info, info2;
232 hres = CreateEditableStream(&stream, NULL);
233 ok(hres == AVIERR_OK, "got 0x%08lX, 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%08lX, expected AVIERR_BADSIZE\n", hres);
239 hres = EditStreamSetInfoA(stream, NULL, sizeof(AVISTREAMINFOA)-1 );
240 ok( hres == AVIERR_BADSIZE, "got 0x%08lX, expected AVIERR_BADSIZE\n", hres);
242 if(0)
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%08lX, 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%08lX, expected 0\n", hres); \
261 hres = AVIStreamInfoA(stream, &info2, sizeof(info2) ); \
262 ok( hres == 0, "got 0x%08lX, expected 0\n", hres); \
263 ok( info2.m == info.m, "EditStreamSetInfo did not update "#m" parameter\n" ); \
264 } while(0)
266 info.dwStart++;
267 IS_INFO_UPDATED(dwStart);
268 info.dwStart = 0;
269 IS_INFO_UPDATED(dwStart);
271 info.wPriority++;
272 IS_INFO_UPDATED(wPriority);
273 info.wPriority = 0;
274 IS_INFO_UPDATED(wPriority);
276 info.wLanguage++;
277 IS_INFO_UPDATED(wLanguage);
278 info.wLanguage = 0;
279 IS_INFO_UPDATED(wLanguage);
281 info.dwScale++;
282 IS_INFO_UPDATED(dwScale);
283 info.dwScale = 0;
284 IS_INFO_UPDATED(dwScale);
286 info.dwRate++;
287 IS_INFO_UPDATED(dwRate);
288 info.dwRate = 0;
289 IS_INFO_UPDATED(dwRate);
291 info.dwQuality++;
292 IS_INFO_UPDATED(dwQuality);
293 info.dwQuality = 0;
294 IS_INFO_UPDATED(dwQuality);
295 info.dwQuality = -2;
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));
325 cah->mah = defmah;
326 cah->ash0 = defash0;
327 cah->ash1 = defash1;
328 cah->pcmwf = defpcmwf;
331 static void create_avi_file(const COMMON_AVI_HEADERS *cah, char *filename)
333 HANDLE hFile;
334 DWORD written;
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);
352 CloseHandle(hFile);
355 static ULONG get_file_refcount(PAVIFILE file)
357 AVIFileAddRef(file);
358 return AVIFileRelease(file);
361 static void test_default_data(void)
363 COMMON_AVI_HEADERS cah;
364 char filename[MAX_PATH];
365 PAVIFILE pFile;
366 int res;
367 LONG lSize;
368 PAVISTREAM pStream0;
369 PAVISTREAM pStream1;
370 AVISTREAMINFOA asi0, asi1;
371 WAVEFORMATEX wfx;
372 ULONG refcount;
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%lx (expected streamtypeVIDEO)\n", asi0.fccType);
407 ok(asi0.fccHandler == 0x30323449, "got 0x%lx (expected 0x30323449)\n", asi0.fccHandler);
408 ok(asi0.dwFlags == 0, "got %lu (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 %lu (expected 1001)\n", asi0.dwScale);
412 ok(asi0.dwRate == 30000, "got %lu (expected 30000)\n", asi0.dwRate);
413 ok(asi0.dwStart == 0, "got %lu (expected 0)\n", asi0.dwStart);
414 ok(asi0.dwLength == 1, "got %lu (expected 1)\n", asi0.dwLength);
415 ok(asi0.dwInitialFrames == 0, "got %lu (expected 0)\n", asi0.dwInitialFrames);
416 ok(asi0.dwSuggestedBufferSize == 0, "got %lu (expected 0)\n", asi0.dwSuggestedBufferSize);
417 ok(asi0.dwQuality == 0xffffffff, "got 0x%lx (expected 0xffffffff)\n", asi0.dwQuality);
418 ok(asi0.dwSampleSize == 0, "got %lu (expected 0)\n", asi0.dwSampleSize);
419 ok(asi0.rcFrame.left == 0, "got %lu (expected 0)\n", asi0.rcFrame.left);
420 ok(asi0.rcFrame.top == 0, "got %lu (expected 0)\n", asi0.rcFrame.top);
421 ok(asi0.rcFrame.right == 8, "got %lu (expected 8)\n", asi0.rcFrame.right); /* these are based on the values in the mah and not */
422 ok(asi0.rcFrame.bottom == 6, "got %lu (expected 6)\n", asi0.rcFrame.bottom);/* on the ones in the ash which are 0 here */
423 ok(asi0.dwEditCount == 0, "got %lu (expected 0)\n", asi0.dwEditCount);
424 ok(asi0.dwFormatChangeCount == 0, "got %lu (expected 0)\n", asi0.dwFormatChangeCount);
426 ok(asi1.fccType == streamtypeAUDIO, "got 0x%lx (expected streamtypeVIDEO)\n", asi1.fccType);
427 ok(asi1.fccHandler == 0x1, "got 0x%lx (expected 0x1)\n", asi1.fccHandler);
428 ok(asi1.dwFlags == 0, "got %lu (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 %lu (expected 1)\n", asi1.dwScale);
432 ok(asi1.dwRate == 11025, "got %lu (expected 11025)\n", asi1.dwRate);
433 ok(asi1.dwStart == 0, "got %lu (expected 0)\n", asi1.dwStart);
434 ok(asi1.dwLength == 1637, "got %lu (expected 1637)\n", asi1.dwLength);
435 ok(asi1.dwInitialFrames == 0, "got %lu (expected 0)\n", asi1.dwInitialFrames);
436 ok(asi1.dwSuggestedBufferSize == 0, "got %lu (expected 0)\n", asi1.dwSuggestedBufferSize);
437 ok(asi1.dwQuality == 0xffffffff, "got 0x%lx (expected 0xffffffff)\n", asi1.dwQuality);
438 ok(asi1.dwSampleSize == 2, "got %lu (expected 2)\n", asi1.dwSampleSize);
439 ok(asi1.rcFrame.left == 0, "got %lu (expected 0)\n", asi1.rcFrame.left);
440 ok(asi1.rcFrame.top == 0, "got %lu (expected 0)\n", asi1.rcFrame.top);
441 ok(asi1.rcFrame.right == 0, "got %lu (expected 0)\n", asi1.rcFrame.right);
442 ok(asi1.rcFrame.bottom == 0, "got %lu (expected 0)\n", asi1.rcFrame.bottom);
443 ok(asi1.dwEditCount == 0, "got %lu (expected 0)\n", asi1.dwEditCount);
444 ok(asi1.dwFormatChangeCount == 0, "got %lu (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 %lu (expected 11025)\n",wfx.nSamplesPerSec);
450 ok(wfx.nAvgBytesPerSec == 22050, "got %lu (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 %lu (expected 3)\n", refcount);
456 AVIStreamRelease(pStream0);
458 refcount = get_file_refcount(pFile);
459 ok(refcount == 2, "got %lu (expected 2)\n", refcount);
461 AVIStreamAddRef(pStream1);
463 refcount = get_file_refcount(pFile);
464 ok(refcount == 2, "got %lu (expected 2)\n", refcount);
466 AVIStreamRelease(pStream1);
467 AVIStreamRelease(pStream1);
469 refcount = get_file_refcount(pFile);
470 ok(refcount == 1, "got %lu (expected 1)\n", refcount);
472 refcount = AVIStreamRelease(pStream1);
473 ok(refcount == (ULONG)-1, "got %lu (expected 4294967295)\n", refcount);
475 refcount = get_file_refcount(pFile);
476 ok(refcount == 1, "got %lu (expected 1)\n", refcount);
478 refcount = AVIFileRelease(pFile);
479 ok(refcount == 0, "got %lu (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];
488 PAVIFILE pFile;
489 int res;
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];
509 PAVIFILE pFile;
510 int res;
511 PAVISTREAM pStream1;
512 AVISTREAMINFOA asi1;
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 %lu (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];
545 PAVIFILE pFile;
546 int res;
547 PAVISTREAM pStream1;
548 AVISTREAMINFOA asi1;
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%lx (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 */
576 struct unk_impl {
577 IUnknown IUnknown_iface;
578 LONG ref;
579 IUnknown *inner_unk;
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;
591 HRESULT hr;
593 if (IsEqualGUID(riid, &IID_IUnknown))
595 *ppv = iface;
596 IUnknown_AddRef(iface);
597 return S_OK;
600 hr = IUnknown_QueryInterface(This->inner_unk, riid, ppv);
601 if (hr == S_OK)
603 trace("Working around COM aggregation ref counting bug\n");
604 ok(ref == This->ref, "Outer ref count expected %ld got %ld\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 %ld\n", ref);
610 return hr;
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 =
629 unk_QueryInterface,
630 unk_AddRef,
631 unk_Release
634 static void test_COM(void)
636 struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL};
637 IAVIFile *avif = NULL;
638 IPersistFile *pf;
639 IUnknown *unk;
640 LONG refcount;
641 HRESULT hr;
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: %08lx, 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: %08lx\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: %08lx\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 %ld\n", refcount);
659 refcount = IUnknown_Release(unk_obj.inner_unk);
660 ok(refcount == 0, "Inner ref count should be 0 but is %lu\n", refcount);
662 /* Invalid RIID */
663 hr = CoCreateInstance(&CLSID_AVIFile, NULL, CLSCTX_INPROC_SERVER, &IID_IAVIStream,
664 (void**)&avif);
665 ok(hr == E_NOINTERFACE, "AVIFile create failed: %08lx, expected E_NOINTERFACE\n", hr);
667 /* Same refcount */
668 hr = CoCreateInstance(&CLSID_AVIFile, NULL, CLSCTX_INPROC_SERVER, &IID_IAVIFile, (void**)&avif);
669 ok(hr == S_OK, "AVIFile create failed: %08lx, expected S_OK\n", hr);
670 refcount = IAVIFile_AddRef(avif);
671 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
672 hr = IAVIFile_QueryInterface(avif, &IID_IUnknown, (void**)&unk);
673 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08lx\n", hr);
674 refcount = IUnknown_AddRef(unk);
675 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
676 hr = IAVIFile_QueryInterface(avif, &IID_IPersistFile, (void**)&pf);
677 ok(hr == S_OK, "QueryInterface for IID_IPersistFile failed: %08lx\n", hr);
678 refcount = IPersistFile_AddRef(pf);
679 ok(refcount == 6, "refcount == %lu, 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;
688 IPersistFile *pf;
689 IAVIStream *avis;
690 IUnknown *unk;
691 ULONG refcount;
692 HRESULT hr;
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: %08lx, 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: %08lx\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: %08lx\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 %ld\n", refcount);
710 refcount = IUnknown_Release(unk_obj.inner_unk);
711 ok(refcount == 0, "Inner ref count should be 0 but is %lu\n", refcount);
713 /* Invalid RIID */
714 hr = CoCreateInstance(&CLSID_WAVFile, NULL, CLSCTX_INPROC_SERVER, &IID_IAVIStreaming,
715 (void**)&avif);
716 ok(hr == E_NOINTERFACE, "WAVFile create failed: %08lx, 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: %08lx, expected S_OK\n", hr);
721 refcount = IAVIFile_AddRef(avif);
722 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
724 hr = IAVIFile_QueryInterface(avif, &IID_IPersistFile, (void**)&pf);
725 ok(hr == S_OK, "QueryInterface for IID_IPersistFile failed: %08lx\n", hr);
726 refcount = IPersistFile_AddRef(pf);
727 ok(refcount == 4, "refcount == %lu, 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: %08lx\n", hr);
732 refcount = IAVIStream_AddRef(avis);
733 ok(refcount == 5, "refcount == %lu, 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: %08lx\n", hr);
738 refcount = IUnknown_AddRef(unk);
739 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
740 refcount = IUnknown_Release(unk);
742 while (IAVIFile_Release(avif));
745 static void test_COM_editstream(void)
747 IAVIEditStream *edit;
748 IAVIStream *stream;
749 IUnknown *unk;
750 ULONG refcount;
751 HRESULT hr;
753 /* Same refcount for all AVIEditStream interfaces */
754 hr = CreateEditableStream(&stream, NULL);
755 ok(hr == S_OK, "AVIEditStream create failed: %08lx, expected S_OK\n", hr);
756 refcount = IAVIStream_AddRef(stream);
757 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
759 hr = IAVIStream_QueryInterface(stream, &IID_IAVIEditStream, (void**)&edit);
760 ok(hr == S_OK, "QueryInterface for IID_IAVIEditStream failed: %08lx\n", hr);
761 refcount = IAVIEditStream_AddRef(edit);
762 ok(refcount == 4, "refcount == %lu, 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: %08lx\n", hr);
767 refcount = IUnknown_AddRef(unk);
768 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
769 IUnknown_Release(unk);
771 while (IAVIEditStream_Release(edit));
774 START_TEST(api)
777 AVIFileInit();
778 test_EditStreamSetInfo();
779 test_AVISaveOptions();
780 test_default_data();
781 test_amh_corruption();
782 test_ash1_corruption();
783 test_ash1_corruption2();
784 test_COM();
785 test_COM_wavfile();
786 test_COM_editstream();
787 AVIFileExit();