winmm: Add a bunch of new mmio tests which discover some bugs in mmio handling.
[wine] / dlls / winmm / tests / mmio.c
1 /*
2  * Unit tests for mmio APIs
3  *
4  * Copyright 2005 Dmitry Timoshkov
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 #include <assert.h>
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "mmsystem.h"
28 #include "vfw.h"
29 #include "wine/test.h"
30
31 static DWORD RIFF_buf[] =
32 {
33     FOURCC_RIFF, 32*sizeof(DWORD), mmioFOURCC('A','V','I',' '),
34     FOURCC_LIST, 29*sizeof(DWORD), listtypeAVIHEADER, ckidAVIMAINHDR,
35     sizeof(MainAVIHeader), 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
36     0xdeadbeef, 0xdeadbeef, 0xdeadbeef,0xdeadbeef,
37     0xdeadbeef, 0xdeadbeef, 0xdeadbeef,0xdeadbeef,
38     0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
39     FOURCC_LIST, 10*sizeof(DWORD),listtypeSTREAMHEADER, ckidSTREAMHEADER,
40     7*sizeof(DWORD), streamtypeVIDEO, 0xdeadbeef, 0xdeadbeef,
41     0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
42     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
43     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
44     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
46 };
47
48 static void expect_buf_offset_dbg(HMMIO hmmio, LONG off, int line)
49 {
50     MMIOINFO mmio;
51     LONG ret;
52
53     memset(&mmio, 0, sizeof(mmio));
54     ret = mmioGetInfo(hmmio, &mmio, 0);
55     ok_(__FILE__, line)(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
56     ok_(__FILE__, line)(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
57     ret = mmioSeek(hmmio, 0, SEEK_CUR);
58     ok_(__FILE__, line)(ret == off, "expected %d, got %d\n", off, ret);
59 }
60
61 #define expect_buf_offset(a1, a2) expect_buf_offset_dbg(a1, a2, __LINE__)
62
63 static void test_mmioDescend(char *fname)
64 {
65     MMRESULT ret;
66     HMMIO hmmio;
67     MMIOINFO mmio;
68     MMCKINFO ckRiff, ckList, ck;
69
70     memset(&mmio, 0, sizeof(mmio));
71     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
72     mmio.cchBuffer = sizeof(RIFF_buf);
73     mmio.pchBuffer = (char *)RIFF_buf;
74     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
75     if (fname && !hmmio)
76     {
77         skip("%s file is missing, skipping the test\n", fname);
78         return;
79     }
80     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
81
82     expect_buf_offset(hmmio, 0);
83
84     /* first normal RIFF AVI parsing */
85     ret = mmioDescend(hmmio, &ckRiff, NULL, 0);
86     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
87     ok(ckRiff.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ckRiff.ckid);
88     ok(ckRiff.fccType == formtypeAVI, "wrong fccType: %04x\n", ckRiff.fccType);
89     ok(ckRiff.dwDataOffset == 8, "expected 8 got %u\n", ckRiff.dwDataOffset);
90     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
91           (LPCSTR)&ckRiff.ckid, ckRiff.cksize, (LPCSTR)&ckRiff.fccType,
92           ckRiff.dwDataOffset, ckRiff.dwFlags);
93
94     expect_buf_offset(hmmio, 12);
95
96     ret = mmioDescend(hmmio, &ckList, &ckRiff, 0);
97     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
98     ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList.ckid);
99     ok(ckList.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ckList.fccType);
100     ok(ckList.dwDataOffset == 20, "expected 20 got %u\n", ckList.dwDataOffset);
101     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
102           (LPCSTR)&ckList.ckid, ckList.cksize, (LPCSTR)&ckList.fccType,
103           ckList.dwDataOffset, ckList.dwFlags);
104
105     expect_buf_offset(hmmio, 24);
106
107     ret = mmioDescend(hmmio, &ck, &ckList, 0);
108     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
109     ok(ck.ckid == ckidAVIMAINHDR, "wrong ckid: %04x\n", ck.ckid);
110     ok(ck.fccType == 0, "wrong fccType: %04x\n", ck.fccType);
111     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
112           (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType,
113           ck.dwDataOffset, ck.dwFlags);
114
115     expect_buf_offset(hmmio, 32);
116
117     /* Skip chunk data */
118     ret = mmioSeek(hmmio, ck.cksize, SEEK_CUR);
119     ok(ret == 0x58, "expected 0x58, got %#x\n", ret);
120
121     ret = mmioDescend(hmmio, &ckList, &ckList, 0);
122     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
123     ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList.ckid);
124     ok(ckList.fccType == listtypeSTREAMHEADER, "wrong fccType: %04x\n", ckList.fccType);
125     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
126           (LPCSTR)&ckList.ckid, ckList.cksize, (LPCSTR)&ckList.fccType,
127           ckList.dwDataOffset, ckList.dwFlags);
128
129     expect_buf_offset(hmmio, 100);
130
131     ret = mmioDescend(hmmio, &ck, &ckList, 0);
132     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
133     ok(ck.ckid == ckidSTREAMHEADER, "wrong ckid: %04x\n", ck.ckid);
134     ok(ck.fccType == 0, "wrong fccType: %04x\n", ck.fccType);
135     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
136           (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType,
137           ck.dwDataOffset, ck.dwFlags);
138
139     expect_buf_offset(hmmio, 108);
140
141     /* test various mmioDescend flags */
142
143     mmioSeek(hmmio, 0, SEEK_SET);
144     memset(&ck, 0x66, sizeof(ck));
145     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF);
146     ok(ret == MMIOERR_CHUNKNOTFOUND ||
147        ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret);
148
149     mmioSeek(hmmio, 0, SEEK_SET);
150     memset(&ck, 0x66, sizeof(ck));
151     ck.ckid = 0;
152     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF);
153     ok(ret == MMIOERR_CHUNKNOTFOUND ||
154        ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret);
155
156     mmioSeek(hmmio, 0, SEEK_SET);
157     memset(&ck, 0x66, sizeof(ck));
158     ck.fccType = 0;
159     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF);
160     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
161     ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid);
162     ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType);
163
164     mmioSeek(hmmio, 0, SEEK_SET);
165     memset(&ck, 0x66, sizeof(ck));
166     ret = mmioDescend(hmmio, &ck, NULL, 0);
167     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
168     ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid);
169     ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType);
170
171     /* do NOT seek, use current file position */
172     memset(&ck, 0x66, sizeof(ck));
173     ck.fccType = 0;
174     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDLIST);
175     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
176     ok(ck.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ck.ckid);
177     ok(ck.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ck.fccType);
178
179     mmioSeek(hmmio, 0, SEEK_SET);
180     memset(&ck, 0x66, sizeof(ck));
181     ck.ckid = 0;
182     ck.fccType = listtypeAVIHEADER;
183     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK);
184     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
185     ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid);
186     ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType);
187
188     /* do NOT seek, use current file position */
189     memset(&ck, 0x66, sizeof(ck));
190     ck.ckid = FOURCC_LIST;
191     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK);
192     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
193     ok(ck.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ck.ckid);
194     ok(ck.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ck.fccType);
195
196     mmioSeek(hmmio, 0, SEEK_SET);
197     memset(&ck, 0x66, sizeof(ck));
198     ck.ckid = FOURCC_RIFF;
199     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK);
200     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
201     ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid);
202     ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType);
203
204     /* do NOT seek, use current file position */
205     memset(&ckList, 0x66, sizeof(ckList));
206     ckList.ckid = 0;
207     ret = mmioDescend(hmmio, &ckList, &ck, MMIO_FINDCHUNK);
208     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
209     ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList.ckid);
210     ok(ckList.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ckList.fccType);
211
212     mmioSeek(hmmio, 0, SEEK_SET);
213     memset(&ck, 0x66, sizeof(ck));
214     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK);
215     ok(ret == MMIOERR_CHUNKNOTFOUND ||
216        ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret);
217     ok(ck.ckid != 0x66666666, "wrong ckid: %04x\n", ck.ckid);
218     ok(ck.fccType != 0x66666666, "wrong fccType: %04x\n", ck.fccType);
219     ok(ck.dwDataOffset != 0x66666666, "wrong dwDataOffset: %04x\n", ck.dwDataOffset);
220
221     mmioSeek(hmmio, 0, SEEK_SET);
222     memset(&ck, 0x66, sizeof(ck));
223     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF);
224     ok(ret == MMIOERR_CHUNKNOTFOUND ||
225        ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret);
226
227     mmioClose(hmmio, 0);
228 }
229
230 static void test_mmioOpen(char *fname)
231 {
232     char buf[MMIO_DEFAULTBUFFER];
233     MMRESULT ret;
234     HMMIO hmmio;
235     MMIOINFO mmio;
236
237     memset(&mmio, 0, sizeof(mmio));
238     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
239     mmio.cchBuffer = sizeof(buf);
240     mmio.pchBuffer = buf;
241     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
242     if (fname && !hmmio)
243     {
244         skip("%s file is missing, skipping the test\n", fname);
245         return;
246     }
247     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
248
249     memset(&mmio, 0, sizeof(mmio));
250     ret = mmioGetInfo(hmmio, &mmio, 0);
251     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
252     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
253     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
254     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
255     ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer);
256     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
257     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
258     if (mmio.fccIOProc == FOURCC_DOS)
259         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
260     else
261         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
262     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
263     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
264     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
265
266     ret = mmioSeek(hmmio, 0, SEEK_CUR);
267     ok(ret == 0, "expected 0, got %d\n", ret);
268
269     mmioClose(hmmio, 0);
270
271     memset(&mmio, 0, sizeof(mmio));
272     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
273     mmio.cchBuffer = 0;
274     mmio.pchBuffer = buf;
275     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
276     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
277
278     memset(&mmio, 0, sizeof(mmio));
279     ret = mmioGetInfo(hmmio, &mmio, 0);
280     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
281     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
282     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
283     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
284     ok(mmio.cchBuffer == 0, "expected 0, got %u\n", mmio.cchBuffer);
285     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
286     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
287     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
288     ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite);
289     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
290     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
291
292     ret = mmioSeek(hmmio, 0, SEEK_CUR);
293     ok(ret == 0, "expected 0, got %d\n", ret);
294
295     mmioClose(hmmio, 0);
296
297     memset(&mmio, 0, sizeof(mmio));
298     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
299     mmio.cchBuffer = 0;
300     mmio.pchBuffer = NULL;
301     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
302     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
303
304     memset(&mmio, 0, sizeof(mmio));
305     ret = mmioGetInfo(hmmio, &mmio, 0);
306     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
307     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
308     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
309     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
310     ok(mmio.cchBuffer == 0, "expected 0, got %u\n", mmio.cchBuffer);
311     ok(mmio.pchBuffer == NULL, "expected NULL\n");
312     ok(mmio.pchNext == NULL, "expected NULL\n");
313     ok(mmio.pchEndRead == NULL, "expected NULL\n");
314     ok(mmio.pchEndWrite == NULL, "expected NULL\n");
315     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
316     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
317
318 #if 0 /* remove once passes under Wine */
319     ret = mmioSeek(hmmio, 0, SEEK_CUR);
320     ok(ret == 0, "expected 0, got %d\n", ret);
321 #endif
322
323     mmioClose(hmmio, 0);
324
325     memset(&mmio, 0, sizeof(mmio));
326     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
327     mmio.cchBuffer = 256;
328     mmio.pchBuffer = NULL;
329     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
330     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
331
332     memset(&mmio, 0, sizeof(mmio));
333     ret = mmioGetInfo(hmmio, &mmio, 0);
334     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
335     ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags);
336     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
337     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
338     ok(mmio.cchBuffer == 256, "expected 256, got %u\n", mmio.cchBuffer);
339     ok(mmio.pchBuffer != NULL, "expected not NULL\n");
340     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
341     if (mmio.fccIOProc == FOURCC_DOS)
342         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
343     else
344         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
345     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
346     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
347     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
348
349 #if 0 /* remove once passes under Wine */
350     ret = mmioSeek(hmmio, 0, SEEK_CUR);
351     ok(ret == 0, "expected 0, got %d\n", ret);
352 #endif
353
354     mmioClose(hmmio, 0);
355
356     memset(&mmio, 0, sizeof(mmio));
357     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
358     mmio.cchBuffer = sizeof(buf);
359     mmio.pchBuffer = buf;
360     hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF);
361     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
362
363     memset(&mmio, 0, sizeof(mmio));
364     ret = mmioGetInfo(hmmio, &mmio, 0);
365     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
366     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
367     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
368     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
369     ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer);
370     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
371     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
372     if (mmio.fccIOProc == FOURCC_DOS)
373         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
374     else
375         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
376     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
377     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
378     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
379
380     ret = mmioSeek(hmmio, 0, SEEK_CUR);
381     ok(ret == 0, "expected 0, got %d\n", ret);
382
383     mmioClose(hmmio, 0);
384
385     memset(&mmio, 0, sizeof(mmio));
386     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
387     mmio.cchBuffer = 0;
388     mmio.pchBuffer = NULL;
389     hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF);
390     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
391
392     memset(&mmio, 0, sizeof(mmio));
393     ret = mmioGetInfo(hmmio, &mmio, 0);
394     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
395     ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags);
396     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
397     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
398     ok(mmio.cchBuffer == MMIO_DEFAULTBUFFER, "expected MMIO_DEFAULTBUFFER, got %u\n", mmio.cchBuffer);
399     ok(mmio.pchBuffer != NULL, "expected not NULL\n");
400     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
401     if (mmio.fccIOProc == FOURCC_DOS)
402         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
403     else
404         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
405     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
406     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
407     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
408
409 #if 0 /* remove once passes under Wine */
410     ret = mmioSeek(hmmio, 0, SEEK_CUR);
411     ok(ret == 0, "expected 0, got %d\n", ret);
412 #endif
413
414     mmioClose(hmmio, 0);
415
416     memset(&mmio, 0, sizeof(mmio));
417     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
418     mmio.cchBuffer = 256;
419     mmio.pchBuffer = NULL;
420     hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF);
421     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
422
423     memset(&mmio, 0, sizeof(mmio));
424     ret = mmioGetInfo(hmmio, &mmio, 0);
425     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
426     ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags);
427     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
428     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
429     ok(mmio.cchBuffer == 256, "expected 256, got %u\n", mmio.cchBuffer);
430     ok(mmio.pchBuffer != NULL, "expected not NULL\n");
431     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
432     if (mmio.fccIOProc == FOURCC_DOS)
433         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
434     else
435         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
436     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
437     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
438     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
439
440 #if 0 /* remove once passes under Wine */
441     ret = mmioSeek(hmmio, 0, SEEK_CUR);
442     ok(ret == 0, "expected 0, got %d\n", ret);
443 #endif
444
445     mmioClose(hmmio, 0);
446
447     memset(&mmio, 0, sizeof(mmio));
448     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
449     mmio.cchBuffer = 0;
450     mmio.pchBuffer = buf;
451     hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF);
452     if (!hmmio && mmio.wErrorRet == ERROR_BAD_FORMAT)
453     {
454         /* Seen on Win9x, WinMe but also XP-SP1 */
455         skip("Some Windows versions don't like a 0 size and a given buffer\n");
456         return;
457     }
458     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
459
460     memset(&mmio, 0, sizeof(mmio));
461     ret = mmioGetInfo(hmmio, &mmio, 0);
462     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
463     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
464     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
465     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
466     ok(mmio.cchBuffer == MMIO_DEFAULTBUFFER, "expected MMIO_DEFAULTBUFFER, got %u\n", mmio.cchBuffer);
467     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
468     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
469     if (mmio.fccIOProc == FOURCC_DOS)
470         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
471     else
472         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
473     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
474     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
475     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
476
477     ret = mmioSeek(hmmio, 0, SEEK_CUR);
478     ok(ret == 0, "expected 0, got %d\n", ret);
479
480     mmioClose(hmmio, 0);
481 }
482
483 static void test_mmioSetBuffer(char *fname)
484 {
485     char buf[256];
486     MMRESULT ret;
487     HMMIO hmmio;
488     MMIOINFO mmio;
489
490     memset(&mmio, 0, sizeof(mmio));
491     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
492     mmio.cchBuffer = sizeof(buf);
493     mmio.pchBuffer = buf;
494     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
495     if (fname && !hmmio)
496     {
497         skip("%s file is missing, skipping the test\n", fname);
498         return;
499     }
500     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
501
502     memset(&mmio, 0, sizeof(mmio));
503     ret = mmioGetInfo(hmmio, &mmio, 0);
504     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
505     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
506     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
507     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
508     ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer);
509     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
510     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
511     if (mmio.fccIOProc == FOURCC_DOS)
512         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
513     else
514         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
515     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
516     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
517     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
518
519     ret = mmioSeek(hmmio, 0, SEEK_CUR);
520     ok(ret == 0, "expected 0, got %d\n", ret);
521
522     ret = mmioSetBuffer(hmmio, NULL, 0, 0);
523     ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret);
524
525     memset(&mmio, 0, sizeof(mmio));
526     ret = mmioGetInfo(hmmio, &mmio, 0);
527     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
528     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
529     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
530     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
531     ok(mmio.cchBuffer == 0, "got not 0\n");
532     ok(mmio.pchBuffer == NULL, "got not NULL buf\n");
533     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
534     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
535     ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite);
536 #if 0 /* remove once passes under Wine */
537     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
538     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
539 #endif
540
541 #if 0 /* remove once passes under Wine */
542     ret = mmioSeek(hmmio, 0, SEEK_CUR);
543     ok(ret == 0, "expected 0, got %d\n", ret);
544 #endif
545
546     ret = mmioSetBuffer(hmmio, NULL, 0, MMIO_ALLOCBUF);
547     ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret);
548
549     memset(&mmio, 0, sizeof(mmio));
550     ret = mmioGetInfo(hmmio, &mmio, 0);
551     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
552     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
553     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
554     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
555     ok(mmio.cchBuffer == 0, "got not 0\n");
556     ok(mmio.pchBuffer == NULL, "got not NULL buf\n");
557     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
558     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
559     ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite);
560 #if 0 /* remove once passes under Wine */
561     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
562     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
563 #endif
564
565 #if 0 /* remove once passes under Wine */
566     ret = mmioSeek(hmmio, 0, SEEK_CUR);
567     ok(ret == 0, "expected 0, got %d\n", ret);
568 #endif
569
570     ret = mmioSetBuffer(hmmio, buf, 0, MMIO_ALLOCBUF);
571     ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret);
572
573     memset(&mmio, 0, sizeof(mmio));
574     ret = mmioGetInfo(hmmio, &mmio, 0);
575     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
576     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
577     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
578     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
579     ok(mmio.cchBuffer == 0, "got not 0\n");
580     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
581     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
582     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
583     ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite);
584 #if 0 /* remove once passes under Wine */
585     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
586     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
587 #endif
588
589 #if 0 /* remove once passes under Wine */
590     ret = mmioSeek(hmmio, 0, SEEK_CUR);
591     ok(ret == 0, "expected 0, got %d\n", ret);
592 #endif
593
594     ret = mmioSetBuffer(hmmio, NULL, 256, MMIO_WRITE|MMIO_ALLOCBUF);
595     ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret);
596
597     memset(&mmio, 0, sizeof(mmio));
598     ret = mmioGetInfo(hmmio, &mmio, 0);
599     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
600     ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags);
601     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
602     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
603     ok(mmio.cchBuffer == 256, "got %u\n", mmio.cchBuffer);
604     ok(mmio.pchBuffer != NULL, "expected not NULL\n");
605     ok(mmio.pchBuffer != buf, "expected != buf\n");
606     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
607     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", buf, mmio.pchEndRead);
608     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
609 #if 0 /* remove once passes under Wine */
610     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
611     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
612 #endif
613
614 #if 0 /* remove once passes under Wine */
615     ret = mmioSeek(hmmio, 0, SEEK_CUR);
616     ok(ret == 0, "expected 0, got %d\n", ret);
617 #endif
618
619     mmioClose(hmmio, 0);
620 }
621
622 START_TEST(mmio)
623 {
624     char fname[] = "msrle.avi";
625
626     test_mmioDescend(NULL);
627     test_mmioDescend(fname);
628     test_mmioOpen(NULL);
629     test_mmioOpen(fname);
630     test_mmioSetBuffer(NULL);
631     test_mmioSetBuffer(fname);
632 }