64c9804544de847fa7d22c8313ff7d8dae975292
[reactos.git] / rostests / winetests / avifil32 / api.c
1 /*
2 * Unit test suite for AVI Functions
3 *
4 * Copyright 2008 Detlef Riekenberg
5 *
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.
10 *
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.
15 *
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
19 *
20 */
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 #define COBJMACROS
27 #define CONST_VTABLE
28
29 #include <wine/test.h>
30 #include <initguid.h>
31 #include <wingdi.h>
32 #include <vfw.h>
33
34 /* ########################### */
35
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";
40
41 /* ########################### */
42
43 static const DWORD deffh[] = /* file_header */
44 {
45 FOURCC_RIFF, 0x34c6 /* length */, formtypeAVI,
46 FOURCC_LIST, 0x1ac /* length */,
47 listtypeAVIHEADER, ckidAVIMAINHDR, sizeof(MainAVIHeader),
48 };
49
50 static const MainAVIHeader defmah =
51 {
52 0x00008256, /* dwMicroSecPerFrame */
53 0x000080e8, /* dwMaxBytesPerSec */
54 0x00000000, /* dwPaddingGranularity */
55 0x00000910, /* dwFlags */
56 1, /* dwTotalFrames */
57 0, /* dwInitialFrames */
58 2, /* dwStreams */
59 0x00100000, /* dwSuggestedBufferSize*/
60 8, /* dwWidth */
61 6, /* dwHeight */
62 { 0, 0, 0, 0 } /* dwReserved[4] */
63 };
64
65 static const AVIStreamHeader defash0 =
66 {
67 streamtypeVIDEO, /* fccType */
68 0x30323449, /* fccHandler */
69 0x00000000, /* dwFlags */
70 0, /* wPriority */
71 0, /* wLanguage */
72 0, /* dwInitialFrames */
73 0x000003e9, /* dwScale */
74 0x00007530, /* dwRate */
75 0, /* dwStart */
76 1, /* dwLength */
77 0x00100000, /* dwSuggestedBufferSize*/
78 0xffffffff, /* dwQuality */
79 0, /* dwSampleSize */
80 { 0, 0, 0, 0 } /* short left right top bottom */
81 };
82
83 static const AVIStreamHeader defash1 =
84 {
85 /* AVIStreamHeader */
86 streamtypeAUDIO, /* fccType */
87 1, /* fccHandler */
88 0, /* dwFlags */
89 0, /* wPriority */
90 0, /* wLanguage */
91 0, /* dwInitialFrames */
92 1, /* dwScale */
93 0x00002b11, /* dwRate */
94 0, /* dwStart */
95 0x00000665, /* dwLength */
96 0x00003000, /* dwSuggestedBufferSize*/
97 0xffffffff, /* dwQuality */
98 2, /* dwSampleSize */
99 { 0, 0, 0, 0 } /* short left right top bottom */
100 };
101
102 static const PCMWAVEFORMAT defpcmwf =
103 {
104 {
105 1, /* wFormatTag */
106 2, /* nChannels */
107 11025, /* nSamplesPerSec */
108 22050, /* nAvgBytesPerSec */
109 2, /* nBlockAlign */
110 },
111 8, /* wBitsPerSample */
112 };
113
114 typedef struct common_avi_headers {
115 DWORD fh[sizeof(deffh)];
116 MainAVIHeader mah;
117 AVIStreamHeader ash0;
118 AVIStreamHeader ash1;
119 PCMWAVEFORMAT pcmwf;
120 } COMMON_AVI_HEADERS;
121
122 /* Extra data needed to get the VFW API to load the file */
123 /* DWORD deffh */
124 /* MainAVIHeader mah */
125 static const DWORD streamlist[] =
126 {
127 FOURCC_LIST, 0xd4 /* length */,
128 listtypeSTREAMHEADER, ckidSTREAMHEADER, 0x38 /* length */,
129 };
130 /* AVIStreamHeader ash0 */
131 static const DWORD videostreamformat[] =
132 {
133 ckidSTREAMFORMAT, 0x28 /* length */,
134 0x00000028, 0x00000008, 0x00000006, 0x00180001,
135 0x30323449, 0x00000090, 0x00000000, 0x00000000,
136 0x00000000, 0x00000000,
137 };
138 static const DWORD padding1[] =
139 {
140 ckidAVIPADDING, 0xc /* length */,
141 0x00000004, 0x00000000, 0x63643030
142 };
143 static const DWORD videopropheader[] =
144 {
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 */,
153 };
154 /* AVIStreamHeader ash1 */
155 static const DWORD audiostreamformat_pre[] =
156 {
157 ckidSTREAMFORMAT, sizeof(PCMWAVEFORMAT) /* length */,
158 };
159 /* PCMWAVEFORMAT pcmwf */
160 static DWORD data[] =
161 {
162 ckidAVIPADDING, 0xc /* length */,
163 0x00000004, 0x00000000, 0x62773130,
164 ckidAVIPADDING, 0xc /* length */,
165 0x6c6d646f, 0x686c6d64, 0x000000f8,
166 FOURCC_LIST, 0x18 /* length */,
167 0x4f464e49,
168 0x54465349, 0xc /* length */,
169 0x6676614c, 0x332e3235, 0x00302e37,
170 ckidAVIPADDING, 0x4 /* length */,
171 0,
172 FOURCC_LIST, 0xd1b /* length */, listtypeAVIMOVIE,
173 0, 0
174 };
175
176 /* ########################### */
177
178 static void test_AVISaveOptions(void)
179 {
180 AVICOMPRESSOPTIONS options[2];
181 LPAVICOMPRESSOPTIONS poptions[2];
182 PAVISTREAM streams[2] = {NULL, NULL};
183 HRESULT hres;
184 DWORD res;
185 LONG lres;
186
187 poptions[0] = &options[0];
188 poptions[1] = &options[1];
189 ZeroMemory(options, sizeof(options));
190
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]);
194
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]);
198
199 SetLastError(0xdeadbeef);
200 hres = EditStreamSetNameA(streams[0], winetest0);
201 ok(hres == AVIERR_OK, "0: got 0x%x (expected AVIERR_OK)\n", hres);
202
203 SetLastError(0xdeadbeef);
204 hres = EditStreamSetNameA(streams[1], winetest1);
205 ok(hres == AVIERR_OK, "1: got 0x%x (expected AVIERR_OK)\n", hres);
206
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());
212 }
213
214 SetLastError(0xdeadbeef);
215 lres = AVISaveOptionsFree(2, poptions);
216 ok(lres == AVIERR_OK, "got 0x%x with 0x%x/%u\n", lres, GetLastError(), GetLastError());
217
218 SetLastError(0xdeadbeef);
219 res = AVIStreamRelease(streams[0]);
220 ok(res == 0, "0: got refcount %u (expected 0)\n", res);
221
222 SetLastError(0xdeadbeef);
223 res = AVIStreamRelease(streams[1]);
224 ok(res == 0, "1: got refcount %u (expected 0)\n", res);
225
226 }
227
228 /* ########################### */
229
230 static void test_EditStreamSetInfo(void)
231 {
232 PAVISTREAM stream = NULL;
233 HRESULT hres;
234 AVISTREAMINFOA info, info2;
235
236 hres = CreateEditableStream(&stream, NULL);
237 ok(hres == AVIERR_OK, "got 0x%08X, expected AVIERR_OK\n", hres);
238
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);
242
243 hres = EditStreamSetInfoA(stream, NULL, sizeof(AVISTREAMINFOA)-1 );
244 ok( hres == AVIERR_BADSIZE, "got 0x%08X, expected AVIERR_BADSIZE\n", hres);
245
246 if(0)
247 {
248 /* Crashing - first parameter not checked */
249 EditStreamSetInfoA(NULL, &info, sizeof(info) );
250
251 /* Crashing - second parameter not checked */
252 EditStreamSetInfoA(stream, NULL, sizeof(AVISTREAMINFOA) );
253
254 EditStreamSetInfoA(stream, NULL, -1);
255 }
256
257 hres = AVIStreamInfoA(stream, &info, sizeof(info) );
258 ok( hres == 0, "got 0x%08X, expected 0\n", hres);
259
260 /* Does the function check what's it's updating ? */
261
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" ); \
268 } while(0)
269
270 info.dwStart++;
271 IS_INFO_UPDATED(dwStart);
272 info.dwStart = 0;
273 IS_INFO_UPDATED(dwStart);
274
275 info.wPriority++;
276 IS_INFO_UPDATED(wPriority);
277 info.wPriority = 0;
278 IS_INFO_UPDATED(wPriority);
279
280 info.wLanguage++;
281 IS_INFO_UPDATED(wLanguage);
282 info.wLanguage = 0;
283 IS_INFO_UPDATED(wLanguage);
284
285 info.dwScale++;
286 IS_INFO_UPDATED(dwScale);
287 info.dwScale = 0;
288 IS_INFO_UPDATED(dwScale);
289
290 info.dwRate++;
291 IS_INFO_UPDATED(dwRate);
292 info.dwRate = 0;
293 IS_INFO_UPDATED(dwRate);
294
295 info.dwQuality++;
296 IS_INFO_UPDATED(dwQuality);
297 info.dwQuality = 0;
298 IS_INFO_UPDATED(dwQuality);
299 info.dwQuality = -2;
300 IS_INFO_UPDATED(dwQuality);
301 info.dwQuality = ICQUALITY_HIGH+1;
302 IS_INFO_UPDATED(dwQuality);
303
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);
312
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
323 }
324
325
326 static void init_test_struct(COMMON_AVI_HEADERS *cah)
327 {
328 memcpy(cah->fh, deffh, sizeof(deffh));
329 cah->mah = defmah;
330 cah->ash0 = defash0;
331 cah->ash1 = defash1;
332 cah->pcmwf = defpcmwf;
333 }
334
335 static void create_avi_file(const COMMON_AVI_HEADERS *cah, char *filename)
336 {
337 HANDLE hFile;
338 DWORD written;
339
340 hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
341
342 ok(hFile != INVALID_HANDLE_VALUE, "Couldn't create file\n");
343
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);
355
356 CloseHandle(hFile);
357 }
358
359 static void test_default_data(void)
360 {
361 COMMON_AVI_HEADERS cah;
362 char filename[MAX_PATH];
363 PAVIFILE pFile;
364 int res;
365 LONG lSize;
366 PAVISTREAM pStream0;
367 PAVISTREAM pStream1;
368 AVISTREAMINFOA asi0, asi1;
369 WAVEFORMATEX wfx;
370
371 GetTempPathA(MAX_PATH, filename);
372 strcpy(filename+strlen(filename), testfilename);
373
374 init_test_struct(&cah);
375 create_avi_file(&cah, filename);
376
377 res = AVIFileOpenA(&pFile, filename, OF_SHARE_DENY_WRITE, 0L);
378 ok(res == 0, "Unable to open file: error=%u\n", res);
379
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");
384
385 res = AVIFileGetStream(pFile, &pStream0, 0, 0);
386 ok(res == 0, "Unable to open video stream: error=%u\n", res);
387
388 res = AVIFileGetStream(pFile, &pStream1, 0, 1);
389 ok(res == 0, "Unable to open audio stream: error=%u\n", res);
390
391 res = AVIStreamInfoA(pStream0, &asi0, sizeof(asi0));
392 ok(res == 0, "Unable to read stream info: error=%u\n", res);
393
394 res = AVIStreamInfoA(pStream1, &asi1, sizeof(asi1));
395 ok(res == 0, "Unable to read stream info: error=%u\n", res);
396
397 res = AVIStreamReadFormat(pStream0, AVIStreamStart(pStream1), NULL, &lSize);
398 ok(res == 0, "Unable to read format size: error=%u\n", res);
399
400 res = AVIStreamReadFormat(pStream1, AVIStreamStart(pStream1), &wfx, &lSize);
401 ok(res == 0, "Unable to read format: error=%u\n", res);
402
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);
422
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);
442
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);
449
450 AVIStreamRelease(pStream0);
451 AVIStreamRelease(pStream1);
452 AVIFileRelease(pFile);
453 ok(DeleteFileA(filename) !=0, "Deleting file %s failed\n", filename);
454 }
455
456 static void test_amh_corruption(void)
457 {
458 COMMON_AVI_HEADERS cah;
459 char filename[MAX_PATH];
460 PAVIFILE pFile;
461 int res;
462
463 GetTempPathA(MAX_PATH, filename);
464 strcpy(filename+strlen(filename), testfilename);
465
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', ' ');
469
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);
473
474 ok(DeleteFileA(filename) !=0, "Deleting file %s failed\n", filename);
475 }
476
477 static void test_ash1_corruption(void)
478 {
479 COMMON_AVI_HEADERS cah;
480 char filename[MAX_PATH];
481 PAVIFILE pFile;
482 int res;
483 PAVISTREAM pStream1;
484 AVISTREAMINFOA asi1;
485
486 GetTempPathA(MAX_PATH, filename);
487 strcpy(filename+strlen(filename), testfilename);
488
489 /* Corrupt the sample size in the audio stream header */
490 init_test_struct(&cah);
491 cah.ash1.dwSampleSize = 0xdeadbeef;
492
493 create_avi_file(&cah, filename);
494
495 res = AVIFileOpenA(&pFile, filename, OF_SHARE_DENY_WRITE, 0L);
496 ok(res == 0, "Unable to open file: error=%u\n", res);
497
498 res = AVIFileGetStream(pFile, &pStream1, 0, 1);
499 ok(res == 0, "Unable to open audio stream: error=%u\n", res);
500
501 res = AVIStreamInfoA(pStream1, &asi1, sizeof(asi1));
502 ok(res == 0, "Unable to read stream info: error=%u\n", res);
503
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);
507
508 AVIStreamRelease(pStream1);
509 AVIFileRelease(pFile);
510 ok(DeleteFileA(filename) !=0, "Deleting file %s failed\n", filename);
511 }
512
513 static void test_ash1_corruption2(void)
514 {
515 COMMON_AVI_HEADERS cah;
516 char filename[MAX_PATH];
517 PAVIFILE pFile;
518 int res;
519 PAVISTREAM pStream1;
520 AVISTREAMINFOA asi1;
521
522 GetTempPathA(MAX_PATH, filename);
523 strcpy(filename+strlen(filename), testfilename);
524
525 /* Corrupt the block alignment in the audio format header */
526 init_test_struct(&cah);
527 cah.pcmwf.wf.nBlockAlign = 0xdead;
528
529 create_avi_file(&cah, filename);
530
531 res = AVIFileOpenA(&pFile, filename, OF_SHARE_DENY_WRITE, 0L);
532 ok(res == 0, "Unable to open file: error=%u\n", res);
533
534 res = AVIFileGetStream(pFile, &pStream1, 0, 1);
535 ok(res == 0, "Unable to open audio stream: error=%u\n", res);
536
537 ok(AVIStreamInfoA(pStream1, &asi1, sizeof(asi1)) == 0, "Unable to read stream info\n");
538
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);
541
542 AVIStreamRelease(pStream1);
543 AVIFileRelease(pFile);
544 ok(DeleteFileA(filename) !=0, "Deleting file %s failed\n", filename);
545 }
546
547 /* Outer IUnknown for COM aggregation tests */
548 struct unk_impl {
549 IUnknown IUnknown_iface;
550 LONG ref;
551 IUnknown *inner_unk;
552 };
553
554 static inline struct unk_impl *impl_from_IUnknown(IUnknown *iface)
555 {
556 return CONTAINING_RECORD(iface, struct unk_impl, IUnknown_iface);
557 }
558
559 static HRESULT WINAPI unk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
560 {
561 struct unk_impl *This = impl_from_IUnknown(iface);
562 LONG ref = This->ref;
563 HRESULT hr;
564
565 if (IsEqualGUID(riid, &IID_IUnknown))
566 {
567 *ppv = iface;
568 IUnknown_AddRef(iface);
569 return S_OK;
570 }
571
572 hr = IUnknown_QueryInterface(This->inner_unk, riid, ppv);
573 if (hr == S_OK)
574 {
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);
580 }
581
582 return hr;
583 }
584
585 static ULONG WINAPI unk_AddRef(IUnknown *iface)
586 {
587 struct unk_impl *This = impl_from_IUnknown(iface);
588
589 return InterlockedIncrement(&This->ref);
590 }
591
592 static ULONG WINAPI unk_Release(IUnknown *iface)
593 {
594 struct unk_impl *This = impl_from_IUnknown(iface);
595
596 return InterlockedDecrement(&This->ref);
597 }
598
599 static const IUnknownVtbl unk_vtbl =
600 {
601 unk_QueryInterface,
602 unk_AddRef,
603 unk_Release
604 };
605
606 static void test_COM(void)
607 {
608 struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL};
609 IAVIFile *avif = NULL;
610 IPersistFile *pf;
611 IUnknown *unk;
612 LONG refcount;
613 HRESULT hr;
614
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);
633
634 /* Invalid RIID */
635 hr = CoCreateInstance(&CLSID_AVIFile, NULL, CLSCTX_INPROC_SERVER, &IID_IAVIStream,
636 (void**)&avif);
637 ok(hr == E_NOINTERFACE, "AVIFile create failed: %08x, expected E_NOINTERFACE\n", hr);
638
639 /* Same refcount */
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);
652
653 while (IAVIFile_Release(avif));
654 }
655
656 static void test_COM_wavfile(void)
657 {
658 struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL};
659 IAVIFile *avif = NULL;
660 IPersistFile *pf;
661 IAVIStream *avis;
662 IUnknown *unk;
663 ULONG refcount;
664 HRESULT hr;
665
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);
684
685 /* Invalid RIID */
686 hr = CoCreateInstance(&CLSID_WAVFile, NULL, CLSCTX_INPROC_SERVER, &IID_IAVIStreaming,
687 (void**)&avif);
688 ok(hr == E_NOINTERFACE, "WAVFile create failed: %08x, expected E_NOINTERFACE\n", hr);
689
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);
695
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);
701
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);
707
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);
713
714 while (IAVIFile_Release(avif));
715 }
716
717 static void test_COM_editstream(void)
718 {
719 IAVIEditStream *edit;
720 IAVIStream *stream;
721 IUnknown *unk;
722 ULONG refcount;
723 HRESULT hr;
724
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);
730
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);
736
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);
742
743 while (IAVIEditStream_Release(edit));
744 }
745
746 START_TEST(api)
747 {
748
749 AVIFileInit();
750 test_EditStreamSetInfo();
751 test_AVISaveOptions();
752 test_default_data();
753 test_amh_corruption();
754 test_ash1_corruption();
755 test_ash1_corruption2();
756 test_COM();
757 test_COM_wavfile();
758 test_COM_editstream();
759 AVIFileExit();
760
761 }