avifil32/tests: Test corrupt avi list magic.
[wine] / dlls / avifil32 / tests / 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 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "wingdi.h"
28 #include "vfw.h"
29 #include "wine/test.h"
30
31 /* ########################### */
32
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%x 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%x and %p (expected AVIERR_OK)\n", hres, streams[1]);
194
195     SetLastError(0xdeadbeef);
196     hres = EditStreamSetNameA(streams[0], winetest0);
197     todo_wine ok(hres == AVIERR_OK, "0: got 0x%x (expected AVIERR_OK)\n", hres);
198
199     SetLastError(0xdeadbeef);
200     hres = EditStreamSetNameA(streams[1], winetest1);
201     todo_wine ok(hres == AVIERR_OK, "1: got 0x%x (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 %u with 0x%x/%u\n", res, GetLastError(), GetLastError());
208     }
209
210     SetLastError(0xdeadbeef);
211     lres = AVISaveOptionsFree(2, poptions);
212     ok(lres == AVIERR_OK, "got 0x%x with 0x%x/%u\n", lres, GetLastError(), GetLastError());
213
214     SetLastError(0xdeadbeef);
215     res = AVIStreamRelease(streams[0]);
216     ok(res == 0, "0: got refcount %u (expected 0)\n", res);
217
218     SetLastError(0xdeadbeef);
219     res = AVIStreamRelease(streams[1]);
220     ok(res == 0, "1: got refcount %u (expected 0)\n", res);
221
222 }
223
224 /* ########################### */
225
226 static void init_test_struct(COMMON_AVI_HEADERS *cah)
227 {
228     memcpy(cah->fh, deffh, sizeof(deffh));
229     cah->mah = defmah;
230     cah->ash0 = defash0;
231     cah->ash1 = defash1;
232     cah->pcmwf = defpcmwf;
233 }
234
235 static void create_avi_file(const COMMON_AVI_HEADERS *cah, char *filename)
236 {
237     HANDLE hFile;
238     DWORD written;
239
240     hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
241
242     ok(hFile != INVALID_HANDLE_VALUE, "Couldn't create file\n");
243
244     WriteFile(hFile, &cah->fh, sizeof(deffh), &written, NULL);
245     WriteFile(hFile, &cah->mah, sizeof(MainAVIHeader), &written, NULL);
246     WriteFile(hFile, streamlist, sizeof(streamlist), &written, NULL);
247     WriteFile(hFile, &cah->ash0, 0x38, &written, NULL);
248     WriteFile(hFile, videostreamformat, sizeof(videostreamformat), &written, NULL);
249     WriteFile(hFile, padding1, sizeof(padding1), &written, NULL);
250     WriteFile(hFile, videopropheader, sizeof(videopropheader), &written, NULL);
251     WriteFile(hFile, &cah->ash1, 0x38, &written, NULL);
252     WriteFile(hFile, audiostreamformat_pre, sizeof(audiostreamformat_pre), &written, NULL);
253     WriteFile(hFile, &cah->pcmwf, sizeof(PCMWAVEFORMAT), &written, NULL);
254     WriteFile(hFile, data, sizeof(data), &written, NULL);
255
256     CloseHandle(hFile);
257 }
258
259 static void test_default_data(void)
260 {
261     COMMON_AVI_HEADERS cah;
262     char filename[MAX_PATH];
263     PAVIFILE pFile;
264     int res;
265     LONG lSize;
266     PAVISTREAM pStream0;
267     PAVISTREAM pStream1;
268     AVISTREAMINFO asi0;
269     AVISTREAMINFO asi1;
270     WAVEFORMATEX wfx;
271
272     GetTempPath(MAX_PATH, filename);
273     strcpy(filename+strlen(filename), testfilename);
274
275     init_test_struct(&cah);
276     create_avi_file(&cah, filename);
277
278     res = AVIFileOpen(&pFile, filename, OF_SHARE_DENY_WRITE, 0L);
279     ok(res != AVIERR_BADFORMAT, "Unable to open file: error1=%u\n", AVIERR_BADFORMAT);
280     ok(res != AVIERR_MEMORY, "Unable to open file: error2=%u\n", AVIERR_MEMORY);
281     ok(res != AVIERR_FILEREAD, "Unable to open file: error3=%u\n", AVIERR_FILEREAD);
282     ok(res != AVIERR_FILEOPEN, "Unable to open file: error4=%u\n", AVIERR_FILEOPEN);
283     ok(res != REGDB_E_CLASSNOTREG, "Unable to open file: error5=%u\n", REGDB_E_CLASSNOTREG);
284     ok(res == 0, "Unable to open file: error=%u\n", res);
285
286     res = AVIFileGetStream(pFile, &pStream0, 0, 0);
287     ok(res == 0, "Unable to open video stream: error=%u\n", res);
288
289     res = AVIFileGetStream(pFile, &pStream1, 0, 1);
290     ok(res == 0, "Unable to open audio stream: error=%u\n", res);
291
292     res = AVIStreamInfo(pStream0, &asi0, sizeof(AVISTREAMINFO));
293     ok(res == 0, "Unable to read stream info: error=%u\n", res);
294
295     res = AVIStreamInfo(pStream1, &asi1, sizeof(AVISTREAMINFO));
296     ok(res == 0, "Unable to read stream info: error=%u\n", res);
297
298     res = AVIStreamReadFormat(pStream0, AVIStreamStart(pStream1), NULL, &lSize);
299     ok(res == 0, "Unable to read format size: error=%u\n", res);
300
301     res = AVIStreamReadFormat(pStream1, AVIStreamStart(pStream1), &wfx, &lSize);
302     ok(res == 0, "Unable to read format: error=%u\n", res);
303
304     ok(asi0.fccType == streamtypeVIDEO, "got 0x%x (expected streamtypeVIDEO)\n", asi0.fccType);
305     ok(asi0.fccHandler == 0x30323449, "got 0x%x (expected 0x30323449)\n", asi0.fccHandler);
306     ok(asi0.dwFlags == 0, "got %u (expected 0)\n", asi0.dwFlags);
307     ok(asi0.wPriority == 0, "got %u (expected 0)\n", asi0.wPriority);
308     ok(asi0.wLanguage == 0, "got %u (expected 0)\n", asi0.wLanguage);
309     ok(asi0.dwScale == 1001, "got %u (expected 1001)\n", asi0.dwScale);
310     ok(asi0.dwRate == 30000, "got %u (expected 30000)\n", asi0.dwRate);
311     ok(asi0.dwStart == 0, "got %u (expected 0)\n", asi0.dwStart);
312     ok(asi0.dwLength == 1, "got %u (expected 1)\n", asi0.dwLength);
313     ok(asi0.dwInitialFrames == 0, "got %u (expected 0)\n", asi0.dwInitialFrames);
314     todo_wine { ok(asi0.dwSuggestedBufferSize == 0, "got %u (expected 0)\n", asi0.dwSuggestedBufferSize); }
315     ok(asi0.dwQuality == 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi0.dwQuality);
316     ok(asi0.dwSampleSize == 0, "got %u (expected 0)\n", asi0.dwSampleSize);
317     ok(asi0.rcFrame.left == 0, "got %u (expected 0)\n", asi0.rcFrame.left);
318     ok(asi0.rcFrame.top == 0, "got %u (expected 0)\n", asi0.rcFrame.top);
319     ok(asi0.rcFrame.right == 8, "got %u (expected 8)\n", asi0.rcFrame.right);  /* these are based on the values in the mah and not */
320     ok(asi0.rcFrame.bottom == 6, "got %u (expected 6)\n", asi0.rcFrame.bottom);/* on the ones in the ash which are 0 here */
321     ok(asi0.dwEditCount == 0, "got %u (expected 0)\n", asi0.dwEditCount);
322     ok(asi0.dwFormatChangeCount == 0, "got %u (expected 0)\n)", asi0.dwFormatChangeCount);
323
324     ok(asi1.fccType == streamtypeAUDIO, "got 0x%x (expected streamtypeVIDEO)\n", asi1.fccType);
325     ok(asi1.fccHandler == 0x1, "got 0x%x (expected 0x1)\n", asi1.fccHandler);
326     ok(asi1.dwFlags == 0, "got %u (expected 0)\n", asi1.dwFlags);
327     ok(asi1.wPriority == 0, "got %u (expected 0)\n", asi1.wPriority);
328     ok(asi1.wLanguage == 0, "got %u (expected 0)\n", asi1.wLanguage);
329     ok(asi1.dwScale == 1, "got %u (expected 1)\n", asi1.dwScale);
330     ok(asi1.dwRate == 11025, "got %u (expected 11025)\n", asi1.dwRate);
331     ok(asi1.dwStart == 0, "got %u (expected 0)\n", asi1.dwStart);
332     ok(asi1.dwLength == 1637, "got %u (expected 1637)\n", asi1.dwLength);
333     ok(asi1.dwInitialFrames == 0, "got %u (expected 0)\n", asi1.dwInitialFrames);
334     todo_wine { ok(asi1.dwSuggestedBufferSize == 0, "got %u (expected 0)\n", asi1.dwSuggestedBufferSize); }
335     ok(asi1.dwQuality == 0xffffffff, "got 0x%x (expected 0xffffffff)\n", asi1.dwQuality);
336     ok(asi1.dwSampleSize == 2, "got %u (expected 2)\n", asi1.dwSampleSize);
337     ok(asi1.rcFrame.left == 0, "got %u (expected 0)\n", asi1.rcFrame.left);
338     ok(asi1.rcFrame.top == 0, "got %u (expected 0)\n", asi1.rcFrame.top);
339     ok(asi1.rcFrame.right == 0, "got %u (expected 0)\n", asi1.rcFrame.right);
340     ok(asi1.rcFrame.bottom == 0, "got %u (expected 0)\n", asi1.rcFrame.bottom);
341     ok(asi1.dwEditCount == 0, "got %u (expected 0)\n", asi1.dwEditCount);
342     ok(asi1.dwFormatChangeCount == 0, "got %u (expected 0)\n)", asi1.dwFormatChangeCount);
343
344     ok(wfx.wFormatTag == 1, "got %u (expected 1)\n",wfx.wFormatTag);
345     ok(wfx.nChannels == 2, "got %u (expected 2)\n",wfx.nChannels);
346     ok(wfx.wFormatTag == 1, "got %u (expected 1)\n",wfx.wFormatTag);
347     ok(wfx.nSamplesPerSec == 11025, "got %u (expected 11025)\n",wfx.nSamplesPerSec);
348     ok(wfx.nAvgBytesPerSec == 22050, "got %u (expected 22050)\n",wfx.nAvgBytesPerSec);
349     ok(wfx.nBlockAlign == 2, "got %u (expected 2)\n",wfx.nBlockAlign);
350
351     AVIStreamRelease(pStream0);
352     AVIStreamRelease(pStream1);
353     AVIFileRelease(pFile);
354     ok(DeleteFile(filename) !=0, "Deleting file %s failed", filename);
355 }
356
357 static void test_amh_corruption(void)
358 {
359     COMMON_AVI_HEADERS cah;
360     char filename[MAX_PATH];
361     PAVIFILE pFile;
362     int res;
363
364     GetTempPath(MAX_PATH, filename);
365     strcpy(filename+strlen(filename), testfilename);
366
367     /* Make sure only AVI files with the proper headers will be loaded */
368     init_test_struct(&cah);
369     cah.fh[3] = mmioFOURCC('A', 'V', 'i', ' ');
370
371     create_avi_file(&cah, filename);
372     res = AVIFileOpen(&pFile, filename, OF_SHARE_DENY_WRITE, 0L);
373     ok(res != 0, "Able to open file: error=%u\n", res);
374
375     ok(DeleteFile(filename) !=0, "Deleting file %s failed\n", filename);
376 }
377
378 /* ########################### */
379
380 START_TEST(api)
381 {
382
383     AVIFileInit();
384     test_AVISaveOptions();
385     test_default_data();
386     test_amh_corruption();
387     AVIFileExit();
388
389 }