Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/avifil32/tests/api.c
4393 views
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 COBJMACROS
23
#define CONST_VTABLE
24
25
#include "wine/test.h"
26
#include "initguid.h"
27
#include "wingdi.h"
28
#include "vfw.h"
29
30
/* ########################### */
31
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";
36
37
/* ########################### */
38
39
static const DWORD deffh[] = /* file_header */
40
{
41
FOURCC_RIFF, 0x34c6 /* length */, formtypeAVI,
42
FOURCC_LIST, 0x1ac /* length */,
43
listtypeAVIHEADER, ckidAVIMAINHDR, sizeof(MainAVIHeader),
44
};
45
46
static const MainAVIHeader defmah =
47
{
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] */
59
};
60
61
static const AVIStreamHeader defash0 =
62
{
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 */
77
};
78
79
static const AVIStreamHeader defash1 =
80
{
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 */
96
};
97
98
static const PCMWAVEFORMAT defpcmwf =
99
{
100
{
101
1, /* wFormatTag */
102
2, /* nChannels */
103
11025, /* nSamplesPerSec */
104
22050, /* nAvgBytesPerSec */
105
2, /* nBlockAlign */
106
},
107
8, /* wBitsPerSample */
108
};
109
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;
117
118
/* Extra data needed to get the VFW API to load the file */
119
/* DWORD deffh */
120
/* MainAVIHeader mah */
121
static const DWORD streamlist[] =
122
{
123
FOURCC_LIST, 0xd4 /* length */,
124
listtypeSTREAMHEADER, ckidSTREAMHEADER, 0x38 /* length */,
125
};
126
/* AVIStreamHeader ash0 */
127
static const DWORD videostreamformat[] =
128
{
129
ckidSTREAMFORMAT, 0x28 /* length */,
130
0x00000028, 0x00000008, 0x00000006, 0x00180001,
131
0x30323449, 0x00000090, 0x00000000, 0x00000000,
132
0x00000000, 0x00000000,
133
};
134
static const DWORD padding1[] =
135
{
136
ckidAVIPADDING, 0xc /* length */,
137
0x00000004, 0x00000000, 0x63643030
138
};
139
static const DWORD videopropheader[] =
140
{
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 */,
149
};
150
/* AVIStreamHeader ash1 */
151
static const DWORD audiostreamformat_pre[] =
152
{
153
ckidSTREAMFORMAT, sizeof(PCMWAVEFORMAT) /* length */,
154
};
155
/* PCMWAVEFORMAT pcmwf */
156
static DWORD data[] =
157
{
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 */,
167
0,
168
FOURCC_LIST, 0xd1b /* length */, listtypeAVIMOVIE,
169
0, 0
170
};
171
172
/* ########################### */
173
174
static void test_AVISaveOptions(void)
175
{
176
AVICOMPRESSOPTIONS options[2];
177
LPAVICOMPRESSOPTIONS poptions[2];
178
PAVISTREAM streams[2] = {NULL, NULL};
179
HRESULT hres;
180
DWORD res;
181
LONG lres;
182
183
poptions[0] = &options[0];
184
poptions[1] = &options[1];
185
ZeroMemory(options, sizeof(options));
186
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]);
190
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]);
194
195
SetLastError(0xdeadbeef);
196
hres = EditStreamSetNameA(streams[0], winetest0);
197
ok(hres == AVIERR_OK, "0: got 0x%lx (expected AVIERR_OK)\n", hres);
198
199
SetLastError(0xdeadbeef);
200
hres = EditStreamSetNameA(streams[1], winetest1);
201
ok(hres == AVIERR_OK, "1: got 0x%lx (expected AVIERR_OK)\n", hres);
202
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());
208
}
209
210
SetLastError(0xdeadbeef);
211
lres = AVISaveOptionsFree(2, poptions);
212
ok(lres == AVIERR_OK, "got 0x%lx with 0x%lx/%lu\n", lres, GetLastError(), GetLastError());
213
214
SetLastError(0xdeadbeef);
215
res = AVIStreamRelease(streams[0]);
216
ok(res == 0, "0: got refcount %lu (expected 0)\n", res);
217
218
SetLastError(0xdeadbeef);
219
res = AVIStreamRelease(streams[1]);
220
ok(res == 0, "1: got refcount %lu (expected 0)\n", res);
221
222
}
223
224
/* ########################### */
225
226
static void test_EditStreamSetInfo(void)
227
{
228
PAVISTREAM stream = NULL;
229
HRESULT hres;
230
AVISTREAMINFOA info, info2;
231
232
hres = CreateEditableStream(&stream, NULL);
233
ok(hres == AVIERR_OK, "got 0x%08lX, expected AVIERR_OK\n", hres);
234
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);
238
239
hres = EditStreamSetInfoA(stream, NULL, sizeof(AVISTREAMINFOA)-1 );
240
ok( hres == AVIERR_BADSIZE, "got 0x%08lX, expected AVIERR_BADSIZE\n", hres);
241
242
if(0)
243
{
244
/* Crashing - first parameter not checked */
245
EditStreamSetInfoA(NULL, &info, sizeof(info) );
246
247
/* Crashing - second parameter not checked */
248
EditStreamSetInfoA(stream, NULL, sizeof(AVISTREAMINFOA) );
249
250
EditStreamSetInfoA(stream, NULL, -1);
251
}
252
253
hres = AVIStreamInfoA(stream, &info, sizeof(info) );
254
ok( hres == 0, "got 0x%08lX, expected 0\n", hres);
255
256
/* Does the function check what's it's updating ? */
257
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)
265
266
info.dwStart++;
267
IS_INFO_UPDATED(dwStart);
268
info.dwStart = 0;
269
IS_INFO_UPDATED(dwStart);
270
271
info.wPriority++;
272
IS_INFO_UPDATED(wPriority);
273
info.wPriority = 0;
274
IS_INFO_UPDATED(wPriority);
275
276
info.wLanguage++;
277
IS_INFO_UPDATED(wLanguage);
278
info.wLanguage = 0;
279
IS_INFO_UPDATED(wLanguage);
280
281
info.dwScale++;
282
IS_INFO_UPDATED(dwScale);
283
info.dwScale = 0;
284
IS_INFO_UPDATED(dwScale);
285
286
info.dwRate++;
287
IS_INFO_UPDATED(dwRate);
288
info.dwRate = 0;
289
IS_INFO_UPDATED(dwRate);
290
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);
299
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);
308
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
319
}
320
321
322
static void init_test_struct(COMMON_AVI_HEADERS *cah)
323
{
324
memcpy(cah->fh, deffh, sizeof(deffh));
325
cah->mah = defmah;
326
cah->ash0 = defash0;
327
cah->ash1 = defash1;
328
cah->pcmwf = defpcmwf;
329
}
330
331
static void create_avi_file(const COMMON_AVI_HEADERS *cah, char *filename)
332
{
333
HANDLE hFile;
334
DWORD written;
335
336
hFile = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
337
338
ok(hFile != INVALID_HANDLE_VALUE, "Couldn't create file\n");
339
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);
351
352
CloseHandle(hFile);
353
}
354
355
static ULONG get_file_refcount(PAVIFILE file)
356
{
357
AVIFileAddRef(file);
358
return AVIFileRelease(file);
359
}
360
361
static void test_default_data(void)
362
{
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;
373
374
GetTempPathA(MAX_PATH, filename);
375
strcpy(filename+strlen(filename), testfilename);
376
377
init_test_struct(&cah);
378
create_avi_file(&cah, filename);
379
380
res = AVIFileOpenA(&pFile, filename, OF_SHARE_DENY_WRITE, 0L);
381
ok(res == 0, "Unable to open file: error=%u\n", res);
382
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");
387
388
res = AVIFileGetStream(pFile, &pStream0, 0, 0);
389
ok(res == 0, "Unable to open video stream: error=%u\n", res);
390
391
res = AVIFileGetStream(pFile, &pStream1, 0, 1);
392
ok(res == 0, "Unable to open audio stream: error=%u\n", res);
393
394
res = AVIStreamInfoA(pStream0, &asi0, sizeof(asi0));
395
ok(res == 0, "Unable to read stream info: error=%u\n", res);
396
397
res = AVIStreamInfoA(pStream1, &asi1, sizeof(asi1));
398
ok(res == 0, "Unable to read stream info: error=%u\n", res);
399
400
res = AVIStreamReadFormat(pStream0, AVIStreamStart(pStream1), NULL, &lSize);
401
ok(res == 0, "Unable to read format size: error=%u\n", res);
402
403
res = AVIStreamReadFormat(pStream1, AVIStreamStart(pStream1), &wfx, &lSize);
404
ok(res == 0, "Unable to read format: error=%u\n", res);
405
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);
425
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);
445
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);
452
453
refcount = get_file_refcount(pFile);
454
ok(refcount == 3, "got %lu (expected 3)\n", refcount);
455
456
AVIStreamRelease(pStream0);
457
458
refcount = get_file_refcount(pFile);
459
ok(refcount == 2, "got %lu (expected 2)\n", refcount);
460
461
AVIStreamAddRef(pStream1);
462
463
refcount = get_file_refcount(pFile);
464
ok(refcount == 2, "got %lu (expected 2)\n", refcount);
465
466
AVIStreamRelease(pStream1);
467
AVIStreamRelease(pStream1);
468
469
refcount = get_file_refcount(pFile);
470
ok(refcount == 1, "got %lu (expected 1)\n", refcount);
471
472
refcount = AVIStreamRelease(pStream1);
473
ok(refcount == (ULONG)-1, "got %lu (expected 4294967295)\n", refcount);
474
475
refcount = get_file_refcount(pFile);
476
ok(refcount == 1, "got %lu (expected 1)\n", refcount);
477
478
refcount = AVIFileRelease(pFile);
479
ok(refcount == 0, "got %lu (expected 0)\n", refcount);
480
481
ok(DeleteFileA(filename) !=0, "Deleting file %s failed\n", filename);
482
}
483
484
static void test_amh_corruption(void)
485
{
486
COMMON_AVI_HEADERS cah;
487
char filename[MAX_PATH];
488
PAVIFILE pFile;
489
int res;
490
491
GetTempPathA(MAX_PATH, filename);
492
strcpy(filename+strlen(filename), testfilename);
493
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', ' ');
497
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);
501
502
ok(DeleteFileA(filename) !=0, "Deleting file %s failed\n", filename);
503
}
504
505
static void test_ash1_corruption(void)
506
{
507
COMMON_AVI_HEADERS cah;
508
char filename[MAX_PATH];
509
PAVIFILE pFile;
510
int res;
511
PAVISTREAM pStream1;
512
AVISTREAMINFOA asi1;
513
514
GetTempPathA(MAX_PATH, filename);
515
strcpy(filename+strlen(filename), testfilename);
516
517
/* Corrupt the sample size in the audio stream header */
518
init_test_struct(&cah);
519
cah.ash1.dwSampleSize = 0xdeadbeef;
520
521
create_avi_file(&cah, filename);
522
523
res = AVIFileOpenA(&pFile, filename, OF_SHARE_DENY_WRITE, 0L);
524
ok(res == 0, "Unable to open file: error=%u\n", res);
525
526
res = AVIFileGetStream(pFile, &pStream1, 0, 1);
527
ok(res == 0, "Unable to open audio stream: error=%u\n", res);
528
529
res = AVIStreamInfoA(pStream1, &asi1, sizeof(asi1));
530
ok(res == 0, "Unable to read stream info: error=%u\n", res);
531
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);
535
536
AVIStreamRelease(pStream1);
537
AVIFileRelease(pFile);
538
ok(DeleteFileA(filename) !=0, "Deleting file %s failed\n", filename);
539
}
540
541
static void test_ash1_corruption2(void)
542
{
543
COMMON_AVI_HEADERS cah;
544
char filename[MAX_PATH];
545
PAVIFILE pFile;
546
int res;
547
PAVISTREAM pStream1;
548
AVISTREAMINFOA asi1;
549
550
GetTempPathA(MAX_PATH, filename);
551
strcpy(filename+strlen(filename), testfilename);
552
553
/* Corrupt the block alignment in the audio format header */
554
init_test_struct(&cah);
555
cah.pcmwf.wf.nBlockAlign = 0xdead;
556
557
create_avi_file(&cah, filename);
558
559
res = AVIFileOpenA(&pFile, filename, OF_SHARE_DENY_WRITE, 0L);
560
ok(res == 0, "Unable to open file: error=%u\n", res);
561
562
res = AVIFileGetStream(pFile, &pStream1, 0, 1);
563
ok(res == 0, "Unable to open audio stream: error=%u\n", res);
564
565
ok(AVIStreamInfoA(pStream1, &asi1, sizeof(asi1)) == 0, "Unable to read stream info\n");
566
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);
569
570
AVIStreamRelease(pStream1);
571
AVIFileRelease(pFile);
572
ok(DeleteFileA(filename) !=0, "Deleting file %s failed\n", filename);
573
}
574
575
/* Outer IUnknown for COM aggregation tests */
576
struct unk_impl {
577
IUnknown IUnknown_iface;
578
LONG ref;
579
IUnknown *inner_unk;
580
};
581
582
static inline struct unk_impl *impl_from_IUnknown(IUnknown *iface)
583
{
584
return CONTAINING_RECORD(iface, struct unk_impl, IUnknown_iface);
585
}
586
587
static HRESULT WINAPI unk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
588
{
589
struct unk_impl *This = impl_from_IUnknown(iface);
590
LONG ref = This->ref;
591
HRESULT hr;
592
593
if (IsEqualGUID(riid, &IID_IUnknown))
594
{
595
*ppv = iface;
596
IUnknown_AddRef(iface);
597
return S_OK;
598
}
599
600
hr = IUnknown_QueryInterface(This->inner_unk, riid, ppv);
601
if (hr == S_OK)
602
{
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);
608
}
609
610
return hr;
611
}
612
613
static ULONG WINAPI unk_AddRef(IUnknown *iface)
614
{
615
struct unk_impl *This = impl_from_IUnknown(iface);
616
617
return InterlockedIncrement(&This->ref);
618
}
619
620
static ULONG WINAPI unk_Release(IUnknown *iface)
621
{
622
struct unk_impl *This = impl_from_IUnknown(iface);
623
624
return InterlockedDecrement(&This->ref);
625
}
626
627
static const IUnknownVtbl unk_vtbl =
628
{
629
unk_QueryInterface,
630
unk_AddRef,
631
unk_Release
632
};
633
634
static void test_COM(void)
635
{
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;
642
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);
661
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);
666
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);
680
681
while (IAVIFile_Release(avif));
682
}
683
684
static void test_COM_wavfile(void)
685
{
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;
693
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);
712
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);
717
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);
723
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);
729
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);
735
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);
741
742
while (IAVIFile_Release(avif));
743
}
744
745
static void test_COM_editstream(void)
746
{
747
IAVIEditStream *edit;
748
IAVIStream *stream;
749
IUnknown *unk;
750
ULONG refcount;
751
HRESULT hr;
752
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);
758
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);
764
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);
770
771
while (IAVIEditStream_Release(edit));
772
}
773
774
static void test_avifile_write(void)
775
{
776
WCHAR fn[MAX_PATH];
777
IPersistFile *persist;
778
PCMWAVEFORMAT afmt;
779
AVISTREAMINFOW si;
780
USHORT buffer[64];
781
PAVIFILE avifile;
782
PAVISTREAM stm;
783
HRESULT hr;
784
BOOL ret;
785
786
GetTempPathW(MAX_PATH, fn);
787
wcscat(fn, L"test.avi");
788
789
hr = CoCreateInstance(&CLSID_AVIFile, NULL, CLSCTX_INPROC, &IID_IAVIFile, (void **)&avifile);
790
ok(hr == S_OK, "got %#lx.\n", hr);
791
hr = IAVIFile_QueryInterface(avifile, &IID_IPersistFile, (void **)&persist);
792
ok(hr == S_OK, "got %#lx.\n", hr);
793
hr = IPersistFile_Load(persist, fn, STGM_CREATE);
794
ok(hr == S_OK, "got %#lx.\n", hr);
795
796
memset(&si, 0, sizeof(si));
797
si.fccType = streamtypeAUDIO;
798
si.dwScale = 1;
799
si.dwRate = 48000;
800
si.dwLength = 4;
801
si.dwQuality = ~0u;
802
si.dwSampleSize = 4;
803
hr = IAVIFile_CreateStream(avifile, &stm, &si);
804
ok(hr == AVIERR_READONLY, "got %#lx.\n", hr);
805
806
IPersistFile_Release(persist);
807
IAVIFile_Release(avifile);
808
809
ret = DeleteFileW(fn);
810
ok(ret, "got error %lu.\n", GetLastError());
811
812
hr = AVIFileOpenW(&avifile, fn, OF_CREATE, NULL);
813
ok(hr == S_OK, "got %#lx.\n", hr);
814
hr = AVIFileCreateStreamW(avifile, &stm, &si);
815
ok(hr == S_OK, "got %#lx.\n", hr);
816
817
memset(&afmt, 0, sizeof(afmt));
818
afmt.wBitsPerSample = 16;
819
afmt.wf.wFormatTag = WAVE_FORMAT_PCM;
820
afmt.wf.nChannels = 2;
821
afmt.wf.nSamplesPerSec = 44800;
822
afmt.wf.nAvgBytesPerSec = afmt.wf.nSamplesPerSec * afmt.wf.nChannels;
823
afmt.wf.nBlockAlign = afmt.wf.nChannels * 2;
824
hr = AVIStreamSetFormat(stm, 0, &afmt, sizeof(afmt));
825
ok(hr == S_OK, "got %#lx.\n", hr);
826
827
memset(buffer, 0xcc, sizeof(buffer));
828
829
hr = IAVIStream_Info(stm, &si, sizeof(si));
830
ok(hr == S_OK, "got %#lx.\n", hr);
831
ok(!si.dwLength, "got %lu.\n", si.dwLength);
832
ok(!si.dwStart, "got %lu.\n", si.dwStart);
833
ok(!si.dwSuggestedBufferSize, "got %lu.\n", si.dwSuggestedBufferSize);
834
hr = AVIStreamWrite(stm, 0, 2, buffer, si.dwSampleSize * 2, 0, NULL, NULL);
835
ok(hr == S_OK, "got %#lx.\n", hr);
836
hr = IAVIStream_Info(stm, &si, sizeof(si));
837
ok(hr == S_OK, "got %#lx.\n", hr);
838
ok(si.dwLength == 2, "got %lu.\n", si.dwLength);
839
ok(!si.dwStart, "got %lu.\n", si.dwStart);
840
ok(si.dwSuggestedBufferSize == 8, "got %lu.\n", si.dwSuggestedBufferSize);
841
hr = AVIStreamWrite(stm, 2, 2, buffer, si.dwSampleSize * 2, 0, NULL, NULL);
842
ok(hr == S_OK, "got %#lx.\n", hr);
843
hr = IAVIStream_Info(stm, &si, sizeof(si));
844
ok(hr == S_OK, "got %#lx.\n", hr);
845
ok(si.dwLength == 4, "got %lu.\n", si.dwLength);
846
ok(!si.dwStart, "got %lu.\n", si.dwStart);
847
ok(si.dwSuggestedBufferSize == 8, "got %lu.\n", si.dwSuggestedBufferSize);
848
849
hr = AVIStreamWrite(stm, 4, 4, buffer, si.dwSampleSize * 4, 0, NULL, NULL);
850
ok(hr == S_OK, "got %#lx.\n", hr);
851
hr = IAVIStream_Info(stm, &si, sizeof(si));
852
ok(hr == S_OK, "got %#lx.\n", hr);
853
ok(si.dwLength == 8, "got %lu.\n", si.dwLength);
854
ok(!si.dwStart, "got %lu.\n", si.dwStart);
855
ok(si.dwSuggestedBufferSize == 16, "got %lu.\n", si.dwSuggestedBufferSize);
856
857
IAVIStream_Release(stm);
858
IAVIFile_Release(avifile);
859
ret = DeleteFileW(fn);
860
ok(ret, "got error %lu.\n", GetLastError());
861
}
862
863
START_TEST(api)
864
{
865
866
AVIFileInit();
867
868
test_EditStreamSetInfo();
869
test_AVISaveOptions();
870
test_default_data();
871
test_amh_corruption();
872
test_ash1_corruption();
873
test_ash1_corruption2();
874
test_COM();
875
test_COM_wavfile();
876
test_COM_editstream();
877
test_avifile_write();
878
AVIFileExit();
879
880
}
881
882