uxtheme: Remove unused variable.
[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 <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "mmsystem.h"
27 #include "vfw.h"
28 #include "wine/test.h"
29
30 static DWORD RIFF_buf[] =
31 {
32     FOURCC_RIFF, 32*sizeof(DWORD), mmioFOURCC('A','V','I',' '),
33     FOURCC_LIST, 29*sizeof(DWORD), listtypeAVIHEADER, ckidAVIMAINHDR,
34     sizeof(MainAVIHeader), 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
35     0xdeadbeef, 0xdeadbeef, 0xdeadbeef,0xdeadbeef,
36     0xdeadbeef, 0xdeadbeef, 0xdeadbeef,0xdeadbeef,
37     0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
38     FOURCC_LIST, 10*sizeof(DWORD),listtypeSTREAMHEADER, ckidSTREAMHEADER,
39     7*sizeof(DWORD), streamtypeVIDEO, 0xdeadbeef, 0xdeadbeef,
40     0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
41     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 };
46
47 static void expect_buf_offset_dbg(HMMIO hmmio, LONG off, int line)
48 {
49     MMIOINFO mmio;
50     LONG ret;
51
52     memset(&mmio, 0, sizeof(mmio));
53     ret = mmioGetInfo(hmmio, &mmio, 0);
54     ok_(__FILE__, line)(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
55     ok_(__FILE__, line)(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
56     ret = mmioSeek(hmmio, 0, SEEK_CUR);
57     ok_(__FILE__, line)(ret == off, "expected %d, got %d\n", off, ret);
58 }
59
60 #define expect_buf_offset(a1, a2) expect_buf_offset_dbg(a1, a2, __LINE__)
61
62 static void test_mmioDescend(char *fname)
63 {
64     MMRESULT ret;
65     HMMIO hmmio;
66     MMIOINFO mmio;
67     MMCKINFO ckRiff, ckList, ck, ckList2;
68
69     memset(&mmio, 0, sizeof(mmio));
70     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
71     mmio.cchBuffer = sizeof(RIFF_buf);
72     mmio.pchBuffer = (char *)RIFF_buf;
73     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
74     if (fname && !hmmio)
75     {
76         trace("No optional %s file. Skipping the test\n", fname);
77         return;
78     }
79     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
80
81     expect_buf_offset(hmmio, 0);
82
83     /* first normal RIFF AVI parsing */
84     ret = mmioDescend(hmmio, &ckRiff, NULL, 0);
85     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
86     ok(ckRiff.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ckRiff.ckid);
87     ok(ckRiff.fccType == formtypeAVI, "wrong fccType: %04x\n", ckRiff.fccType);
88     ok(ckRiff.dwDataOffset == 8, "expected 8 got %u\n", ckRiff.dwDataOffset);
89     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
90           (LPCSTR)&ckRiff.ckid, ckRiff.cksize, (LPCSTR)&ckRiff.fccType,
91           ckRiff.dwDataOffset, ckRiff.dwFlags);
92
93     expect_buf_offset(hmmio, 12);
94
95     ret = mmioDescend(hmmio, &ckList, &ckRiff, 0);
96     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
97     ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList.ckid);
98     ok(ckList.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ckList.fccType);
99     ok(ckList.dwDataOffset == 20, "expected 20 got %u\n", ckList.dwDataOffset);
100     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
101           (LPCSTR)&ckList.ckid, ckList.cksize, (LPCSTR)&ckList.fccType,
102           ckList.dwDataOffset, ckList.dwFlags);
103
104     expect_buf_offset(hmmio, 24);
105
106     ret = mmioDescend(hmmio, &ck, &ckList, 0);
107     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
108     ok(ck.ckid == ckidAVIMAINHDR, "wrong ckid: %04x\n", ck.ckid);
109     ok(ck.fccType == 0, "wrong fccType: %04x\n", ck.fccType);
110     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
111           (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType,
112           ck.dwDataOffset, ck.dwFlags);
113
114     expect_buf_offset(hmmio, 32);
115
116     /* Skip chunk data */
117     ret = mmioSeek(hmmio, ck.cksize, SEEK_CUR);
118     ok(ret == 0x58, "expected 0x58, got %#x\n", ret);
119
120     ret = mmioDescend(hmmio, &ckList2, &ckList, 0);
121     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
122     ok(ckList2.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList2.ckid);
123     ok(ckList2.fccType == listtypeSTREAMHEADER, "wrong fccType: %04x\n", ckList2.fccType);
124     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
125           (LPCSTR)&ckList2.ckid, ckList2.cksize, (LPCSTR)&ckList2.fccType,
126           ckList2.dwDataOffset, ckList2.dwFlags);
127
128     expect_buf_offset(hmmio, 100);
129
130     ret = mmioDescend(hmmio, &ck, &ckList2, 0);
131     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
132     ok(ck.ckid == ckidSTREAMHEADER, "wrong ckid: %04x\n", ck.ckid);
133     ok(ck.fccType == 0, "wrong fccType: %04x\n", ck.fccType);
134     trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n",
135           (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType,
136           ck.dwDataOffset, ck.dwFlags);
137
138     expect_buf_offset(hmmio, 108);
139
140     /* test various mmioDescend flags */
141
142     mmioSeek(hmmio, 0, SEEK_SET);
143     memset(&ck, 0x66, sizeof(ck));
144     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF);
145     ok(ret == MMIOERR_CHUNKNOTFOUND ||
146        ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret);
147
148     mmioSeek(hmmio, 0, SEEK_SET);
149     memset(&ck, 0x66, sizeof(ck));
150     ck.ckid = 0;
151     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF);
152     ok(ret == MMIOERR_CHUNKNOTFOUND ||
153        ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret);
154
155     mmioSeek(hmmio, 0, SEEK_SET);
156     memset(&ck, 0x66, sizeof(ck));
157     ck.fccType = 0;
158     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF);
159     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
160     ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid);
161     ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType);
162
163     mmioSeek(hmmio, 0, SEEK_SET);
164     memset(&ck, 0x66, sizeof(ck));
165     ret = mmioDescend(hmmio, &ck, NULL, 0);
166     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
167     ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid);
168     ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType);
169
170     /* do NOT seek, use current file position */
171     memset(&ck, 0x66, sizeof(ck));
172     ck.fccType = 0;
173     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDLIST);
174     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
175     ok(ck.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ck.ckid);
176     ok(ck.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ck.fccType);
177
178     mmioSeek(hmmio, 0, SEEK_SET);
179     memset(&ck, 0x66, sizeof(ck));
180     ck.ckid = 0;
181     ck.fccType = listtypeAVIHEADER;
182     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK);
183     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
184     ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid);
185     ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType);
186
187     /* do NOT seek, use current file position */
188     memset(&ck, 0x66, sizeof(ck));
189     ck.ckid = FOURCC_LIST;
190     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK);
191     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
192     ok(ck.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ck.ckid);
193     ok(ck.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ck.fccType);
194
195     mmioSeek(hmmio, 0, SEEK_SET);
196     memset(&ck, 0x66, sizeof(ck));
197     ck.ckid = FOURCC_RIFF;
198     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK);
199     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
200     ok(ck.ckid == FOURCC_RIFF, "wrong ckid: %04x\n", ck.ckid);
201     ok(ck.fccType == formtypeAVI, "wrong fccType: %04x\n", ck.fccType);
202
203     /* do NOT seek, use current file position */
204     memset(&ckList, 0x66, sizeof(ckList));
205     ckList.ckid = 0;
206     ret = mmioDescend(hmmio, &ckList, &ck, MMIO_FINDCHUNK);
207     ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret);
208     ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList.ckid);
209     ok(ckList.fccType == listtypeAVIHEADER, "wrong fccType: %04x\n", ckList.fccType);
210
211     mmioSeek(hmmio, 0, SEEK_SET);
212     memset(&ck, 0x66, sizeof(ck));
213     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDCHUNK);
214     ok(ret == MMIOERR_CHUNKNOTFOUND ||
215        ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret);
216     ok(ck.ckid != 0x66666666, "wrong ckid: %04x\n", ck.ckid);
217     ok(ck.fccType != 0x66666666, "wrong fccType: %04x\n", ck.fccType);
218     ok(ck.dwDataOffset != 0x66666666, "wrong dwDataOffset: %04x\n", ck.dwDataOffset);
219
220     mmioSeek(hmmio, 0, SEEK_SET);
221     memset(&ck, 0x66, sizeof(ck));
222     ret = mmioDescend(hmmio, &ck, NULL, MMIO_FINDRIFF);
223     ok(ret == MMIOERR_CHUNKNOTFOUND ||
224        ret == MMIOERR_INVALIDFILE, "mmioDescend returned %u\n", ret);
225
226     mmioClose(hmmio, 0);
227 }
228
229 static void test_mmioOpen(char *fname)
230 {
231     char buf[MMIO_DEFAULTBUFFER];
232     MMRESULT ret;
233     HMMIO hmmio;
234     MMIOINFO mmio;
235
236     memset(&mmio, 0, sizeof(mmio));
237     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
238     mmio.cchBuffer = sizeof(buf);
239     mmio.pchBuffer = buf;
240     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
241     if (fname && !hmmio)
242     {
243         trace("No optional %s file. Skipping the test\n", fname);
244         return;
245     }
246     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
247
248     memset(&mmio, 0, sizeof(mmio));
249     ret = mmioGetInfo(hmmio, &mmio, 0);
250     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
251     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
252     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
253     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
254     ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer);
255     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
256     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
257     if (mmio.fccIOProc == FOURCC_DOS)
258         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
259     else
260         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
261     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
262     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
263     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
264
265     ret = mmioSeek(hmmio, 0, SEEK_CUR);
266     ok(ret == 0, "expected 0, got %d\n", ret);
267
268     mmioClose(hmmio, 0);
269
270     memset(&mmio, 0, sizeof(mmio));
271     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
272     mmio.cchBuffer = 0;
273     mmio.pchBuffer = buf;
274     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
275     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
276
277     memset(&mmio, 0, sizeof(mmio));
278     ret = mmioGetInfo(hmmio, &mmio, 0);
279     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
280     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
281     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
282     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
283     ok(mmio.cchBuffer == 0, "expected 0, got %u\n", mmio.cchBuffer);
284     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
285     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
286     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
287     ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite);
288     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
289     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
290
291     ret = mmioSeek(hmmio, 0, SEEK_CUR);
292     ok(ret == 0, "expected 0, got %d\n", ret);
293
294     mmioClose(hmmio, 0);
295
296     memset(&mmio, 0, sizeof(mmio));
297     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
298     mmio.cchBuffer = 0;
299     mmio.pchBuffer = NULL;
300     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
301     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
302
303     memset(&mmio, 0, sizeof(mmio));
304     ret = mmioGetInfo(hmmio, &mmio, 0);
305     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
306     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
307     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
308     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
309     ok(mmio.cchBuffer == 0, "expected 0, got %u\n", mmio.cchBuffer);
310     ok(mmio.pchBuffer == NULL, "expected NULL\n");
311     ok(mmio.pchNext == NULL, "expected NULL\n");
312     ok(mmio.pchEndRead == NULL, "expected NULL\n");
313     ok(mmio.pchEndWrite == NULL, "expected NULL\n");
314     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
315     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
316
317 #if 0 /* remove once passes under Wine */
318     ret = mmioSeek(hmmio, 0, SEEK_CUR);
319     ok(ret == 0, "expected 0, got %d\n", ret);
320 #endif
321
322     mmioClose(hmmio, 0);
323
324     memset(&mmio, 0, sizeof(mmio));
325     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
326     mmio.cchBuffer = 256;
327     mmio.pchBuffer = NULL;
328     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
329     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
330
331     memset(&mmio, 0, sizeof(mmio));
332     ret = mmioGetInfo(hmmio, &mmio, 0);
333     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
334     ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags);
335     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
336     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
337     ok(mmio.cchBuffer == 256, "expected 256, got %u\n", mmio.cchBuffer);
338     ok(mmio.pchBuffer != NULL, "expected not NULL\n");
339     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
340     if (mmio.fccIOProc == FOURCC_DOS)
341         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
342     else
343         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
344     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
345     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
346     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
347
348 #if 0 /* remove once passes under Wine */
349     ret = mmioSeek(hmmio, 0, SEEK_CUR);
350     ok(ret == 0, "expected 0, got %d\n", ret);
351 #endif
352
353     mmioClose(hmmio, 0);
354
355     memset(&mmio, 0, sizeof(mmio));
356     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
357     mmio.cchBuffer = sizeof(buf);
358     mmio.pchBuffer = buf;
359     hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF);
360     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
361
362     memset(&mmio, 0, sizeof(mmio));
363     ret = mmioGetInfo(hmmio, &mmio, 0);
364     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
365     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
366     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
367     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
368     ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer);
369     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
370     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
371     if (mmio.fccIOProc == FOURCC_DOS)
372         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
373     else
374         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
375     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
376     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
377     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
378
379     ret = mmioSeek(hmmio, 0, SEEK_CUR);
380     ok(ret == 0, "expected 0, got %d\n", ret);
381
382     mmioClose(hmmio, 0);
383
384     memset(&mmio, 0, sizeof(mmio));
385     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
386     mmio.cchBuffer = 0;
387     mmio.pchBuffer = NULL;
388     hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF);
389     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
390
391     memset(&mmio, 0, sizeof(mmio));
392     ret = mmioGetInfo(hmmio, &mmio, 0);
393     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
394     ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags);
395     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
396     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
397     ok(mmio.cchBuffer == MMIO_DEFAULTBUFFER, "expected MMIO_DEFAULTBUFFER, got %u\n", mmio.cchBuffer);
398     ok(mmio.pchBuffer != NULL, "expected not NULL\n");
399     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
400     if (mmio.fccIOProc == FOURCC_DOS)
401         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
402     else
403         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
404     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
405     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
406     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
407
408 #if 0 /* remove once passes under Wine */
409     ret = mmioSeek(hmmio, 0, SEEK_CUR);
410     ok(ret == 0, "expected 0, got %d\n", ret);
411 #endif
412
413     mmioClose(hmmio, 0);
414
415     memset(&mmio, 0, sizeof(mmio));
416     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
417     mmio.cchBuffer = 256;
418     mmio.pchBuffer = NULL;
419     hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF);
420     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
421
422     memset(&mmio, 0, sizeof(mmio));
423     ret = mmioGetInfo(hmmio, &mmio, 0);
424     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
425     ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags);
426     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
427     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
428     ok(mmio.cchBuffer == 256, "expected 256, got %u\n", mmio.cchBuffer);
429     ok(mmio.pchBuffer != NULL, "expected not NULL\n");
430     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
431     if (mmio.fccIOProc == FOURCC_DOS)
432         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
433     else
434         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
435     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
436     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
437     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
438
439 #if 0 /* remove once passes under Wine */
440     ret = mmioSeek(hmmio, 0, SEEK_CUR);
441     ok(ret == 0, "expected 0, got %d\n", ret);
442 #endif
443
444     mmioClose(hmmio, 0);
445
446     memset(&mmio, 0, sizeof(mmio));
447     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
448     mmio.cchBuffer = 0;
449     mmio.pchBuffer = buf;
450     hmmio = mmioOpen(fname, &mmio, MMIO_READ | MMIO_ALLOCBUF);
451     if (!hmmio && mmio.wErrorRet == ERROR_BAD_FORMAT)
452     {
453         /* Seen on Win9x, WinMe but also XP-SP1 */
454         skip("Some Windows versions don't like a 0 size and a given buffer\n");
455         return;
456     }
457     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
458
459     memset(&mmio, 0, sizeof(mmio));
460     ret = mmioGetInfo(hmmio, &mmio, 0);
461     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
462     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
463     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
464     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
465     ok(mmio.cchBuffer == MMIO_DEFAULTBUFFER, "expected MMIO_DEFAULTBUFFER, got %u\n", mmio.cchBuffer);
466     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
467     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
468     if (mmio.fccIOProc == FOURCC_DOS)
469         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
470     else
471         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
472     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
473     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
474     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
475
476     ret = mmioSeek(hmmio, 0, SEEK_CUR);
477     ok(ret == 0, "expected 0, got %d\n", ret);
478
479     mmioClose(hmmio, 0);
480 }
481
482 static void test_mmioSetBuffer(char *fname)
483 {
484     char buf[256];
485     MMRESULT ret;
486     HMMIO hmmio;
487     MMIOINFO mmio;
488
489     memset(&mmio, 0, sizeof(mmio));
490     mmio.fccIOProc = fname ? FOURCC_DOS : FOURCC_MEM;
491     mmio.cchBuffer = sizeof(buf);
492     mmio.pchBuffer = buf;
493     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
494     if (fname && !hmmio)
495     {
496         trace("No optional %s file. Skipping the test\n", fname);
497         return;
498     }
499     ok(hmmio != 0, "mmioOpen error %u\n", mmio.wErrorRet);
500
501     memset(&mmio, 0, sizeof(mmio));
502     ret = mmioGetInfo(hmmio, &mmio, 0);
503     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
504     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
505     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
506     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
507     ok(mmio.cchBuffer == sizeof(buf), "got %u\n", mmio.cchBuffer);
508     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
509     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
510     if (mmio.fccIOProc == FOURCC_DOS)
511         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
512     else
513         ok(mmio.pchEndRead == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndRead);
514     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
515     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
516     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
517
518     ret = mmioSeek(hmmio, 0, SEEK_CUR);
519     ok(ret == 0, "expected 0, got %d\n", ret);
520
521     ret = mmioSetBuffer(hmmio, NULL, 0, 0);
522     ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret);
523
524     memset(&mmio, 0, sizeof(mmio));
525     ret = mmioGetInfo(hmmio, &mmio, 0);
526     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
527     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
528     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
529     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
530     ok(mmio.cchBuffer == 0, "got not 0\n");
531     ok(mmio.pchBuffer == NULL, "got not NULL buf\n");
532     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
533     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
534     ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite);
535 #if 0 /* remove once passes under Wine */
536     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
537     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
538 #endif
539
540 #if 0 /* remove once passes under Wine */
541     ret = mmioSeek(hmmio, 0, SEEK_CUR);
542     ok(ret == 0, "expected 0, got %d\n", ret);
543 #endif
544
545     ret = mmioSetBuffer(hmmio, NULL, 0, MMIO_ALLOCBUF);
546     ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret);
547
548     memset(&mmio, 0, sizeof(mmio));
549     ret = mmioGetInfo(hmmio, &mmio, 0);
550     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
551     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
552     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
553     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
554     ok(mmio.cchBuffer == 0, "got not 0\n");
555     ok(mmio.pchBuffer == NULL, "got not NULL buf\n");
556     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
557     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
558     ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite);
559 #if 0 /* remove once passes under Wine */
560     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
561     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
562 #endif
563
564 #if 0 /* remove once passes under Wine */
565     ret = mmioSeek(hmmio, 0, SEEK_CUR);
566     ok(ret == 0, "expected 0, got %d\n", ret);
567 #endif
568
569     ret = mmioSetBuffer(hmmio, buf, 0, MMIO_ALLOCBUF);
570     ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret);
571
572     memset(&mmio, 0, sizeof(mmio));
573     ret = mmioGetInfo(hmmio, &mmio, 0);
574     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
575     ok(mmio.dwFlags == MMIO_READ, "expected MMIO_READ, got %x\n", mmio.dwFlags);
576     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
577     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
578     ok(mmio.cchBuffer == 0, "got not 0\n");
579     ok(mmio.pchBuffer == buf, "expected %p, got %p\n", buf, mmio.pchBuffer);
580     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
581     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
582     ok(mmio.pchEndWrite == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndWrite);
583 #if 0 /* remove once passes under Wine */
584     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
585     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
586 #endif
587
588 #if 0 /* remove once passes under Wine */
589     ret = mmioSeek(hmmio, 0, SEEK_CUR);
590     ok(ret == 0, "expected 0, got %d\n", ret);
591 #endif
592
593     ret = mmioSetBuffer(hmmio, NULL, 256, MMIO_WRITE|MMIO_ALLOCBUF);
594     ok(ret == MMSYSERR_NOERROR, "mmioSetBuffer error %u\n", ret);
595
596     memset(&mmio, 0, sizeof(mmio));
597     ret = mmioGetInfo(hmmio, &mmio, 0);
598     ok(ret == MMSYSERR_NOERROR, "mmioGetInfo error %u\n", ret);
599     ok(mmio.dwFlags == (MMIO_READ|MMIO_ALLOCBUF), "expected MMIO_READ|MMIO_ALLOCBUF, got %x\n", mmio.dwFlags);
600     ok(mmio.wErrorRet == MMSYSERR_NOERROR, "expected MMSYSERR_NOERROR, got %u\n", mmio.wErrorRet);
601     ok(mmio.fccIOProc == (fname ? FOURCC_DOS : FOURCC_MEM), "got %4.4s\n", (LPCSTR)&mmio.fccIOProc);
602     ok(mmio.cchBuffer == 256, "got %u\n", mmio.cchBuffer);
603     ok(mmio.pchBuffer != NULL, "expected not NULL\n");
604     ok(mmio.pchBuffer != buf, "expected != buf\n");
605     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
606     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", buf, mmio.pchEndRead);
607     ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
608 #if 0 /* remove once passes under Wine */
609     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
610     ok(mmio.lDiskOffset == 0, "expected 0, got %d\n", mmio.lDiskOffset);
611 #endif
612
613 #if 0 /* remove once passes under Wine */
614     ret = mmioSeek(hmmio, 0, SEEK_CUR);
615     ok(ret == 0, "expected 0, got %d\n", ret);
616 #endif
617
618     mmioClose(hmmio, 0);
619 }
620
621 #define FOURCC_XYZ mmioFOURCC('X', 'Y', 'Z', ' ')
622
623 static LRESULT CALLBACK mmio_test_IOProc(LPSTR lpMMIOInfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2)
624 {
625     LPMMIOINFO lpInfo = (LPMMIOINFO) lpMMIOInfo;
626
627     switch (uMessage)
628     {
629     case MMIOM_OPEN:
630         if (lpInfo->fccIOProc == FOURCC_DOS)
631             lpInfo->fccIOProc = mmioFOURCC('F', 'A', 'I', 'L');
632         return MMSYSERR_NOERROR;
633     case MMIOM_CLOSE:
634         return MMSYSERR_NOERROR;
635     default:
636         return 0;
637     }
638 }
639
640 static void test_mmioOpen_fourcc(void)
641 {
642     char fname[] = "file+name.xyz+one.two";
643
644     LPMMIOPROC lpProc;
645     HMMIO hmmio;
646     MMIOINFO mmio;
647
648     lpProc = mmioInstallIOProc(FOURCC_DOS, mmio_test_IOProc, MMIO_INSTALLPROC);
649     ok(lpProc == mmio_test_IOProc, "mmioInstallIOProc error\n");
650
651     lpProc = mmioInstallIOProc(FOURCC_XYZ, mmio_test_IOProc, MMIO_INSTALLPROC);
652     ok(lpProc == mmio_test_IOProc, "mmioInstallIOProc error\n");
653
654     memset(&mmio, 0, sizeof(mmio));
655     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
656     mmioGetInfo(hmmio, &mmio, 0);
657     ok(hmmio != NULL && mmio.fccIOProc == FOURCC_XYZ, "mmioOpen error %u, got %4.4s\n", mmio.wErrorRet, (LPCSTR)&mmio.fccIOProc);
658     mmioClose(hmmio, 0);
659
660     mmioInstallIOProc(FOURCC_XYZ, NULL, MMIO_REMOVEPROC);
661
662     memset(&mmio, 0, sizeof(mmio));
663     hmmio = mmioOpen(fname, &mmio, MMIO_READ);
664     mmioGetInfo(hmmio, &mmio, 0);
665     ok(hmmio == NULL && mmio.wErrorRet == MMIOERR_FILENOTFOUND, "mmioOpen error %u, got %4.4s\n", mmio.wErrorRet, (LPCSTR)&mmio.fccIOProc);
666     mmioClose(hmmio, 0);
667
668     mmioInstallIOProc(FOURCC_DOS, NULL, MMIO_REMOVEPROC);
669 }
670
671 static BOOL create_test_file(char *temp_file)
672 {
673     char temp_path[MAX_PATH];
674     DWORD ret, written;
675     HANDLE h;
676
677     ret = GetTempPath(sizeof(temp_path), temp_path);
678     ok(ret, "Failed to get a temp path, err %d\n", GetLastError());
679     if (!ret)
680         return FALSE;
681
682     ret = GetTempFileName(temp_path, "mmio", 0, temp_file);
683     ok(ret, "Failed to get a temp name, err %d\n", GetLastError());
684     if (!ret)
685         return FALSE;
686
687     h = CreateFileA(temp_file, GENERIC_WRITE, 0, NULL,
688                     CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
689     ok(h != INVALID_HANDLE_VALUE, "Failed to create a file, err %d\n", GetLastError());
690     if (h == INVALID_HANDLE_VALUE) return FALSE;
691
692     ret = WriteFile(h, RIFF_buf, sizeof(RIFF_buf), &written, NULL);
693     ok(ret, "Failed to write a file, err %d\n", GetLastError());
694     CloseHandle(h);
695     if (!ret) DeleteFileA(temp_file);
696     return ret;
697 }
698
699 static void test_mmioSeek(void)
700 {
701     HMMIO hmmio;
702     MMIOINFO mmio;
703     LONG end, pos;
704     const LONG size = sizeof(RIFF_buf), offset = 16;
705     char test_file[MAX_PATH];
706     MMRESULT res;
707
708     /* test memory file */
709     memset(&mmio, 0, sizeof(mmio));
710     mmio.fccIOProc = FOURCC_MEM;
711     mmio.pchBuffer = (char*)&RIFF_buf;
712     mmio.cchBuffer = sizeof(RIFF_buf);
713     hmmio = mmioOpen(NULL, &mmio, MMIO_READ);
714     ok(hmmio != NULL, "mmioOpen error %u\n", mmio.wErrorRet);
715     if (hmmio != NULL) {
716         /* seek to the end */
717         end = mmioSeek(hmmio, 0, SEEK_END);
718         todo_wine ok(end == size, "expected %d, got %d\n", size, end);
719
720         /* seek backward from the end */
721         pos = mmioSeek(hmmio, offset, SEEK_END);
722         ok(pos == size-offset, "expected %d, got %d\n", size-offset, pos);
723
724         mmioClose(hmmio, 0);
725     }
726
727     if (!create_test_file(test_file)) return;
728
729     /* test standard file without buffering */
730     hmmio = NULL;
731     memset(&mmio, 0, sizeof(mmio));
732     mmio.fccIOProc = FOURCC_DOS;
733     mmio.pchBuffer = 0;
734     mmio.cchBuffer = 0;
735     hmmio = mmioOpen(test_file, &mmio, MMIO_READ);
736     ok(hmmio != NULL, "mmioOpen error %u\n", mmio.wErrorRet);
737     if (hmmio != NULL) {
738         /* seek to the end */
739         end = mmioSeek(hmmio, 0, SEEK_END);
740         ok(end == size, "expected %d, got %d\n", size, end);
741
742         /* test MMIOINFO values */
743         res = mmioGetInfo(hmmio, &mmio, 0);
744         ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res);
745         ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
746         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
747         ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
748         todo_wine ok(mmio.lBufOffset == size, "expected %d, got %d\n", size, mmio.lBufOffset);
749         ok(mmio.lDiskOffset == size, "expected %d, got %d\n", size, mmio.lDiskOffset);
750
751         /* seek backward from the end */
752         pos = mmioSeek(hmmio, offset, SEEK_END);
753         ok(pos == size-offset, "expected %d, got %d\n", size-offset, pos);
754
755         mmioClose(hmmio, 0);
756     }
757
758     /* test standard file with buffering */
759     hmmio = NULL;
760     memset(&mmio, 0, sizeof(mmio));
761     mmio.fccIOProc = FOURCC_DOS;
762     mmio.pchBuffer = 0;
763     mmio.cchBuffer = 0;
764     hmmio = mmioOpen(test_file, &mmio, MMIO_READ | MMIO_ALLOCBUF);
765     ok(hmmio != NULL, "mmioOpen error %u\n", mmio.wErrorRet);
766     if (hmmio != NULL) {
767         /* seek to the end */
768         end = mmioSeek(hmmio, 0, SEEK_END);
769         ok(end == size, "expected %d, got %d\n", size, end);
770
771         /* test MMIOINFO values */
772         res = mmioGetInfo(hmmio, &mmio, 0);
773         ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res);
774         ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
775         ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
776         ok(mmio.pchEndWrite == mmio.pchBuffer + mmio.cchBuffer, "expected %p + %d, got %p\n", mmio.pchBuffer, mmio.cchBuffer, mmio.pchEndWrite);
777         ok(mmio.lBufOffset == end, "expected %d, got %d\n", end, mmio.lBufOffset);
778         ok(mmio.lDiskOffset == size, "expected %d, got %d\n", size, mmio.lDiskOffset);
779
780         /* seek backward from the end */
781         pos = mmioSeek(hmmio, offset, SEEK_END);
782         ok(pos == size-offset, "expected %d, got %d\n", size-offset, pos);
783
784         mmioClose(hmmio, 0);
785     }
786
787     DeleteFileA(test_file);
788 }
789
790 static void test_mmio_end_of_file(void)
791 {
792     char test_file[MAX_PATH], buffer[128], data[16];
793     MMIOINFO mmio;
794     HMMIO hmmio;
795     LONG ret;
796     MMRESULT res;
797
798     if (!create_test_file(test_file)) return;
799
800     memset(&mmio, 0, sizeof(mmio));
801     mmio.fccIOProc = FOURCC_DOS;
802     mmio.pchBuffer = buffer;
803     mmio.cchBuffer = sizeof(buffer);
804     hmmio = mmioOpen(test_file, &mmio, MMIO_READ);
805     ok(hmmio != NULL, "mmioOpen error %u\n", mmio.wErrorRet);
806     if (hmmio == NULL) {
807         DeleteFileA(test_file);
808         return;
809     }
810
811     ret = mmioSeek(hmmio, 0, SEEK_END);
812     ok(sizeof(RIFF_buf) == ret, "got %d\n", ret);
813
814     ret = mmioRead(hmmio, data, sizeof(data));
815     ok(ret == 0, "expected %d, got %d\n", 0, ret);
816
817     res = mmioGetInfo(hmmio, &mmio, 0);
818     ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res);
819
820     res = mmioAdvance(hmmio, &mmio, MMIO_READ);
821     ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res);
822     ok(mmio.pchNext == mmio.pchEndRead, "expected %p, got %p\n", mmio.pchEndRead, mmio.pchNext);
823
824     mmioClose(hmmio, 0);
825     DeleteFileA(test_file);
826 }
827
828 static void test_mmio_buffer_pointer(void)
829 {
830     char test_file[MAX_PATH];
831     char buffer[5], data[16];
832     MMIOINFO mmio;
833     HMMIO hmmio;
834     LONG size, pos;
835     MMRESULT res;
836
837     if (!create_test_file(test_file)) return;
838
839     memset(&mmio, 0, sizeof(mmio));
840     mmio.fccIOProc = FOURCC_DOS;
841     mmio.pchBuffer = buffer;
842     mmio.cchBuffer = sizeof(buffer);
843     hmmio = mmioOpen(test_file, &mmio, MMIO_READ);
844     ok(hmmio != NULL, "mmioOpen error %u\n", mmio.wErrorRet);
845     if (hmmio == NULL) {
846         DeleteFileA(test_file);
847         return;
848     }
849
850     /* the buffer is empty */
851     size = mmioRead(hmmio, data, 0);
852     ok(size == 0, "expected 0, got %d\n", size);
853     res = mmioGetInfo(hmmio, &mmio, 0);
854     ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res);
855     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
856
857     /* fill the buffer */
858     size = mmioAdvance(hmmio, &mmio, MMIO_READ);
859     ok(mmio.pchEndRead-mmio.pchBuffer == sizeof(buffer), "got %d\n", (int)(mmio.pchEndRead-mmio.pchBuffer));
860
861     /* seeking to the same buffer chunk, the buffer is kept */
862     size = sizeof(buffer)/2;
863     pos = mmioSeek(hmmio, size, SEEK_SET);
864     ok(pos == size, "failed to seek, expected %d, got %d\n", size, pos);
865     res = mmioGetInfo(hmmio, &mmio, 0);
866     ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res);
867     ok(mmio.lBufOffset == 0, "expected 0, got %d\n", mmio.lBufOffset);
868     ok(mmio.pchNext-mmio.pchBuffer == size, "expected %d, got %d\n", size, (int)(mmio.pchNext-mmio.pchBuffer));
869     ok(mmio.pchEndRead-mmio.pchBuffer == sizeof(buffer), "got %d\n", (int)(mmio.pchEndRead-mmio.pchBuffer));
870
871     /* seeking to another buffer chunk, the buffer is empty */
872     size = sizeof(buffer) * 3 + sizeof(buffer) / 2;
873     pos = mmioSeek(hmmio, size, SEEK_SET);
874     ok(pos == size, "failed to seek, got %d\n", pos);
875     res = mmioGetInfo(hmmio, &mmio, 0);
876     ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res);
877     ok(mmio.lBufOffset == size, "expected %d, got %d\n", size, mmio.lBufOffset);
878     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
879     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
880
881     /* reading a lot (as sizeof(data) > mmio.cchBuffer), the buffer is empty */
882     size = mmioRead(hmmio, data, sizeof(data));
883     ok(size == sizeof(data), "failed to read, got %d\n", size);
884     res = mmioGetInfo(hmmio, &mmio, 0);
885     ok(res == MMSYSERR_NOERROR, "expected 0, got %d\n", res);
886     ok(mmio.lBufOffset == pos+size, "expected %d, got %d\n", pos+size, mmio.lBufOffset);
887     ok(mmio.pchNext == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchNext);
888     ok(mmio.pchEndRead == mmio.pchBuffer, "expected %p, got %p\n", mmio.pchBuffer, mmio.pchEndRead);
889
890     mmioClose(hmmio, 0);
891     DeleteFileA(test_file);
892 }
893
894 START_TEST(mmio)
895 {
896     /* Make it possible to run the tests against a specific AVI file in
897      * addition to the builtin test data. This is mostly meant as a
898      * debugging aid and is not part of the standard tests.
899      */
900     char fname[] = "msrle.avi";
901
902     test_mmioDescend(NULL);
903     test_mmioDescend(fname);
904     test_mmioOpen(NULL);
905     test_mmioOpen(fname);
906     test_mmioSetBuffer(NULL);
907     test_mmioSetBuffer(fname);
908     test_mmioOpen_fourcc();
909     test_mmioSeek();
910     test_mmio_end_of_file();
911     test_mmio_buffer_pointer();
912 }