mshtml/tests: Add a trailing '\n' to ok() calls.
[wine] / dlls / mmsystem.dll16 / mmio16.c
1 /*
2  * MMSYSTEM mmio* functions
3  *
4  * Copyright 1993               Martin Ayotte
5  *           1998-2003,2009     Eric Pouech
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <string.h>
24
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "mmsystem.h"
30 #include "winternl.h"
31 #include "wownt32.h"
32 #include "winnls.h"
33
34 #include "wine/winuser16.h"
35 #include "winemm16.h"
36
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
40
41 /* ###################################################
42  * #                     MMIO                        #
43  * ###################################################
44  */
45 #include <pshpack1.h>
46 #define MMIO_MAX_THUNKS      32
47
48 static struct mmio_thunk
49 {
50     BYTE        popl_eax;       /* popl  %eax (return address) */
51     BYTE        pushl_func;     /* pushl $pfn16 (16bit callback function) */
52     LPMMIOPROC16 pfn16;
53     BYTE        pushl_eax;      /* pushl %eax */
54     BYTE        jmp;            /* ljmp MMIO_Callback1632 */
55     DWORD       callback;
56     HMMIO       hMmio;          /* Handle to 32bit mmio object */
57     SEGPTR      segbuffer;      /* actual segmented ptr to buffer */
58 } *MMIO_Thunks;
59
60 #include <poppack.h>
61
62 static CRITICAL_SECTION mmio_cs;
63 static CRITICAL_SECTION_DEBUG mmio_critsect_debug =
64 {
65     0, 0, &mmio_cs,
66     { &mmio_critsect_debug.ProcessLocksList, &mmio_critsect_debug.ProcessLocksList },
67       0, 0, { (DWORD_PTR)(__FILE__ ": mmsystem_mmio_cs") }
68 };
69 static CRITICAL_SECTION mmio_cs = { &mmio_critsect_debug, -1, 0, 0, 0, 0 };
70
71 /****************************************************************
72  *                      MMIO_Map32To16                  [INTERNAL]
73  */
74 static LRESULT  MMIO_Map32To16(DWORD wMsg, LPARAM* lp1, LPARAM* lp2)
75 {
76     switch (wMsg) {
77     case MMIOM_CLOSE:
78     case MMIOM_SEEK:
79         /* nothing to do */
80         break;
81     case MMIOM_OPEN:
82     case MMIOM_READ:
83     case MMIOM_WRITE:
84     case MMIOM_WRITEFLUSH:
85         *lp1 = MapLS( (void *)*lp1 );
86         break;
87     case MMIOM_RENAME:
88         *lp1 = MapLS( (void *)*lp1 );
89         *lp2 = MapLS( (void *)*lp2 );
90         break;
91     default:
92         if (wMsg < MMIOM_USER)
93             TRACE("Not a mappable message (%d)\n", wMsg);
94     }
95     return MMSYSERR_NOERROR;
96 }
97
98 /****************************************************************
99  *              MMIO_UnMap32To16                        [INTERNAL]
100  */
101 static LRESULT  MMIO_UnMap32To16(DWORD wMsg, LPARAM lParam1, LPARAM lParam2,
102                                  LPARAM lp1, LPARAM lp2)
103 {
104     switch (wMsg) {
105     case MMIOM_CLOSE:
106     case MMIOM_SEEK:
107         /* nothing to do */
108         break;
109     case MMIOM_OPEN:
110     case MMIOM_READ:
111     case MMIOM_WRITE:
112     case MMIOM_WRITEFLUSH:
113         UnMapLS( lp1 );
114         break;
115     case MMIOM_RENAME:
116         UnMapLS( lp1 );
117         UnMapLS( lp2 );
118         break;
119     default:
120         if (wMsg < MMIOM_USER)
121             TRACE("Not a mappable message (%d)\n", wMsg);
122     }
123     return MMSYSERR_NOERROR;
124 }
125
126 /******************************************************************
127  *              MMIO_Callback3216
128  *
129  *
130  */
131 static LRESULT MMIO_Callback3216(SEGPTR cb16, LPMMIOINFO lpmmioinfo, UINT uMessage,
132                                  LPARAM lParam1, LPARAM lParam2)
133 {
134     DWORD               result;
135     MMIOINFO16          mmioInfo16;
136     SEGPTR              segmmioInfo16;
137     LPARAM              lp1 = lParam1, lp2 = lParam2;
138     WORD                args[7];
139
140     if (!cb16) return MMSYSERR_INVALPARAM;
141
142     memset(&mmioInfo16, 0, sizeof(MMIOINFO16));
143     mmioInfo16.lDiskOffset = lpmmioinfo->lDiskOffset;
144     mmioInfo16.adwInfo[0]  = lpmmioinfo->adwInfo[0];
145     mmioInfo16.adwInfo[1]  = lpmmioinfo->adwInfo[1];
146     mmioInfo16.adwInfo[2]  = lpmmioinfo->adwInfo[2];
147     /* map (lParam1, lParam2) into (lp1, lp2) 32=>16 */
148     if ((result = MMIO_Map32To16(uMessage, &lp1, &lp2)) != MMSYSERR_NOERROR)
149         return result;
150
151     segmmioInfo16 = MapLS(&mmioInfo16);
152     args[6] = HIWORD(segmmioInfo16);
153     args[5] = LOWORD(segmmioInfo16);
154     args[4] = uMessage;
155     args[3] = HIWORD(lp1);
156     args[2] = LOWORD(lp1);
157     args[1] = HIWORD(lp2);
158     args[0] = LOWORD(lp2);
159     WOWCallback16Ex( cb16, WCB16_PASCAL, sizeof(args), args, &result );
160     UnMapLS(segmmioInfo16);
161     MMIO_UnMap32To16(uMessage, lParam1, lParam2, lp1, lp2);
162
163     lpmmioinfo->lDiskOffset = mmioInfo16.lDiskOffset;
164     lpmmioinfo->adwInfo[0]  = mmioInfo16.adwInfo[0];
165     lpmmioinfo->adwInfo[1]  = mmioInfo16.adwInfo[1];
166     lpmmioinfo->adwInfo[2]  = mmioInfo16.adwInfo[2];
167
168     return result;
169 }
170
171 /******************************************************************
172  *              MMIO_AddThunk
173  *
174  */
175 static struct mmio_thunk*       MMIO_AddThunk(LPMMIOPROC16 pfn16, HPSTR segbuf)
176 {
177     struct mmio_thunk* thunk;
178
179     if (!MMIO_Thunks)
180     {
181         MMIO_Thunks = VirtualAlloc(NULL, MMIO_MAX_THUNKS * sizeof(*MMIO_Thunks), MEM_COMMIT,
182                                    PAGE_EXECUTE_READWRITE);
183         if (!MMIO_Thunks) return NULL;
184         for (thunk = MMIO_Thunks; thunk < &MMIO_Thunks[MMIO_MAX_THUNKS]; thunk++)
185         {
186             thunk->popl_eax     = 0x58;   /* popl  %eax */
187             thunk->pushl_func   = 0x68;   /* pushl $pfn16 */
188             thunk->pfn16        = 0;
189             thunk->pushl_eax    = 0x50;   /* pushl %eax */
190             thunk->jmp          = 0xe9;   /* jmp MMIO_Callback3216 */
191             thunk->callback     = (char *)MMIO_Callback3216 - (char *)(&thunk->callback + 1);
192             thunk->hMmio        = NULL;
193             thunk->segbuffer    = 0;
194         }
195     }
196     for (thunk = MMIO_Thunks; thunk < &MMIO_Thunks[MMIO_MAX_THUNKS]; thunk++)
197     {
198         if (thunk->pfn16 == 0 && thunk->hMmio == NULL)
199         {
200             thunk->pfn16 = pfn16;
201             thunk->hMmio = NULL;
202             thunk->segbuffer = (SEGPTR)segbuf;
203             return thunk;
204         }
205     }
206     FIXME("Out of mmio-thunks. Bump MMIO_MAX_THUNKS\n");
207     return NULL;
208 }
209
210 /******************************************************************
211  *              MMIO_HasThunk
212  *
213  */
214 static struct mmio_thunk*    MMIO_HasThunk(HMMIO hmmio)
215 {
216     struct mmio_thunk* thunk;
217
218     if (!MMIO_Thunks) return NULL;
219     for (thunk = MMIO_Thunks; thunk < &MMIO_Thunks[MMIO_MAX_THUNKS]; thunk++)
220     {
221         if (thunk->hMmio == hmmio) return thunk;
222     }
223     return NULL;
224 }
225
226 /******************************************************************
227  *             MMIO_SetSegmentedBuffer
228  *
229  */
230 static void     MMIO_SetSegmentedBuffer(struct mmio_thunk* thunk, SEGPTR ptr, BOOL release)
231 {
232     if (release) UnMapLS(thunk->segbuffer);
233     thunk->segbuffer = ptr;
234 }
235
236 /**************************************************************************
237  *                              mmioOpen                [MMSYSTEM.1210]
238  */
239 HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16* lpmmioinfo16,
240                           DWORD dwOpenFlags)
241 {
242     HMMIO       ret;
243
244     if (lpmmioinfo16) {
245         MMIOINFO                mmioinfo;
246         struct mmio_thunk*      thunk = NULL;
247
248         memset(&mmioinfo, 0, sizeof(mmioinfo));
249
250         EnterCriticalSection(&mmio_cs);
251         if (lpmmioinfo16->pIOProc && !(thunk = MMIO_AddThunk(lpmmioinfo16->pIOProc, lpmmioinfo16->pchBuffer)))
252         {
253             LeaveCriticalSection(&mmio_cs);
254             return 0;
255         }
256
257         mmioinfo.dwFlags     = lpmmioinfo16->dwFlags;
258         mmioinfo.fccIOProc   = lpmmioinfo16->fccIOProc;
259         mmioinfo.pIOProc     = (LPMMIOPROC)thunk;
260         mmioinfo.cchBuffer   = lpmmioinfo16->cchBuffer;
261         mmioinfo.pchBuffer   = MapSL((DWORD)lpmmioinfo16->pchBuffer);
262         mmioinfo.adwInfo[0]  = lpmmioinfo16->adwInfo[0];
263         /* if we don't have a file name, it's likely a passed open file descriptor */
264         if (!szFileName)
265             mmioinfo.adwInfo[0] = (DWORD)DosFileHandleToWin32Handle(mmioinfo.adwInfo[0]);
266         mmioinfo.adwInfo[1]  = lpmmioinfo16->adwInfo[1];
267         mmioinfo.adwInfo[2]  = lpmmioinfo16->adwInfo[2];
268
269         ret = mmioOpenA(szFileName, &mmioinfo, dwOpenFlags);
270         if (thunk)
271         {
272             if (!ret || (dwOpenFlags & (MMIO_PARSE|MMIO_EXIST)))
273             {
274                 thunk->pfn16 = NULL;
275                 thunk->hMmio = NULL;
276             }
277             else thunk->hMmio = ret;
278         }
279         LeaveCriticalSection(&mmio_cs);
280
281         lpmmioinfo16->wErrorRet = mmioinfo.wErrorRet;
282         lpmmioinfo16->hmmio     = HMMIO_16(mmioinfo.hmmio);
283     } else {
284         ret = mmioOpenA(szFileName, NULL, dwOpenFlags);
285     }
286     return HMMIO_16(ret);
287 }
288
289 /**************************************************************************
290  *                              mmioClose               [MMSYSTEM.1211]
291  */
292 MMRESULT16 WINAPI mmioClose16(HMMIO16 hmmio, UINT16 uFlags)
293 {
294     MMRESULT ret;
295
296     EnterCriticalSection(&mmio_cs);
297     ret = mmioClose(HMMIO_32(hmmio), uFlags);
298     if (ret == MMSYSERR_NOERROR)
299     {
300         struct mmio_thunk* thunk;
301
302         if ((thunk = MMIO_HasThunk(HMMIO_32(hmmio))))
303         {
304             MMIO_SetSegmentedBuffer(thunk, 0, TRUE);
305             thunk->pfn16 = NULL;
306             thunk->hMmio = NULL;
307         }
308     }
309     LeaveCriticalSection(&mmio_cs);
310     return ret;
311 }
312
313 /**************************************************************************
314  *                              mmioRead                [MMSYSTEM.1212]
315  */
316 LONG WINAPI mmioRead16(HMMIO16 hmmio, HPSTR pch, LONG cch)
317 {
318     return mmioRead(HMMIO_32(hmmio), pch, cch);
319 }
320
321 /**************************************************************************
322  *                              mmioWrite               [MMSYSTEM.1213]
323  */
324 LONG WINAPI mmioWrite16(HMMIO16 hmmio, HPCSTR pch, LONG cch)
325 {
326     return mmioWrite(HMMIO_32(hmmio),pch,cch);
327 }
328
329 /**************************************************************************
330  *                              mmioSeek                [MMSYSTEM.1214]
331  */
332 LONG WINAPI mmioSeek16(HMMIO16 hmmio, LONG lOffset, INT16 iOrigin)
333 {
334     return mmioSeek(HMMIO_32(hmmio), lOffset, iOrigin);
335 }
336
337 /**************************************************************************
338  *                              mmioGetInfo             [MMSYSTEM.1215]
339  */
340 MMRESULT16 WINAPI mmioGetInfo16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags)
341 {
342     MMIOINFO            mmioinfo;
343     MMRESULT            ret;
344     struct mmio_thunk*  thunk;
345
346     TRACE("(0x%04x,%p,0x%08x)\n", hmmio, lpmmioinfo, uFlags);
347
348     EnterCriticalSection(&mmio_cs);
349     if ((thunk = MMIO_HasThunk(HMMIO_32(hmmio))) == NULL)
350     {
351         LeaveCriticalSection(&mmio_cs);
352         return MMSYSERR_INVALHANDLE;
353     }
354
355     ret = mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, uFlags);
356     if (ret != MMSYSERR_NOERROR)
357     {
358         LeaveCriticalSection(&mmio_cs);
359         return ret;
360     }
361
362     lpmmioinfo->dwFlags     = mmioinfo.dwFlags;
363     lpmmioinfo->fccIOProc   = mmioinfo.fccIOProc;
364     lpmmioinfo->pIOProc     = thunk->pfn16;
365     lpmmioinfo->wErrorRet   = mmioinfo.wErrorRet;
366     lpmmioinfo->hTask       = HTASK_16(mmioinfo.hTask);
367     lpmmioinfo->cchBuffer   = mmioinfo.cchBuffer;
368     lpmmioinfo->pchBuffer   = (void*)thunk->segbuffer;
369     lpmmioinfo->pchNext     = (void*)(thunk->segbuffer + (mmioinfo.pchNext - mmioinfo.pchBuffer));
370     lpmmioinfo->pchEndRead  = (void*)(thunk->segbuffer + (mmioinfo.pchEndRead - mmioinfo.pchBuffer));
371     lpmmioinfo->pchEndWrite = (void*)(thunk->segbuffer + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer));
372     lpmmioinfo->lBufOffset  = mmioinfo.lBufOffset;
373     lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset;
374     lpmmioinfo->adwInfo[0]  = mmioinfo.adwInfo[0];
375     lpmmioinfo->adwInfo[1]  = mmioinfo.adwInfo[1];
376     lpmmioinfo->adwInfo[2]  = mmioinfo.adwInfo[2];
377     lpmmioinfo->dwReserved1 = 0;
378     lpmmioinfo->dwReserved2 = 0;
379     lpmmioinfo->hmmio = HMMIO_16(mmioinfo.hmmio);
380     LeaveCriticalSection(&mmio_cs);
381
382     return MMSYSERR_NOERROR;
383 }
384
385 /**************************************************************************
386  *                              mmioSetInfo             [MMSYSTEM.1216]
387  */
388 MMRESULT16 WINAPI mmioSetInfo16(HMMIO16 hmmio, const MMIOINFO16* lpmmioinfo, UINT16 uFlags)
389 {
390     MMIOINFO            mmioinfo;
391     MMRESULT            ret;
392
393     TRACE("(0x%04x,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
394
395     ret = mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, 0);
396     if (ret != MMSYSERR_NOERROR) return ret;
397
398     /* check if seg and lin buffers are the same */
399     if (mmioinfo.cchBuffer != lpmmioinfo->cchBuffer  ||
400         mmioinfo.pchBuffer != MapSL((DWORD)lpmmioinfo->pchBuffer))
401         return MMSYSERR_INVALPARAM;
402
403     /* check pointers coherence */
404     if (lpmmioinfo->pchNext < lpmmioinfo->pchBuffer ||
405         lpmmioinfo->pchNext > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer ||
406         lpmmioinfo->pchEndRead < lpmmioinfo->pchBuffer ||
407         lpmmioinfo->pchEndRead > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer ||
408         lpmmioinfo->pchEndWrite < lpmmioinfo->pchBuffer ||
409         lpmmioinfo->pchEndWrite > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer)
410         return MMSYSERR_INVALPARAM;
411
412     mmioinfo.pchNext     = mmioinfo.pchBuffer + (lpmmioinfo->pchNext     - lpmmioinfo->pchBuffer);
413     mmioinfo.pchEndRead  = mmioinfo.pchBuffer + (lpmmioinfo->pchEndRead  - lpmmioinfo->pchBuffer);
414     mmioinfo.pchEndWrite = mmioinfo.pchBuffer + (lpmmioinfo->pchEndWrite - lpmmioinfo->pchBuffer);
415
416     return mmioSetInfo(HMMIO_32(hmmio), &mmioinfo, uFlags);
417 }
418
419 /**************************************************************************
420  *                              mmioSetBuffer           [MMSYSTEM.1217]
421  */
422 MMRESULT16 WINAPI mmioSetBuffer16(HMMIO16 hmmio, LPSTR pchBuffer,
423                                   LONG cchBuffer, UINT16 uFlags)
424 {
425     MMRESULT    ret = mmioSetBuffer(HMMIO_32(hmmio), MapSL((DWORD)pchBuffer),
426                                     cchBuffer, uFlags);
427
428     if (ret == MMSYSERR_NOERROR)
429     {
430         struct mmio_thunk* thunk;
431
432         if ((thunk = MMIO_HasThunk(HMMIO_32(hmmio))) == NULL)
433         {
434             FIXME("really ?\n");
435             return MMSYSERR_INVALHANDLE;
436         }
437         MMIO_SetSegmentedBuffer(thunk, (DWORD)pchBuffer, TRUE);
438     }
439     else
440         UnMapLS((DWORD)pchBuffer);
441     return ret;
442 }
443
444 /**************************************************************************
445  *                              mmioFlush               [MMSYSTEM.1218]
446  */
447 MMRESULT16 WINAPI mmioFlush16(HMMIO16 hmmio, UINT16 uFlags)
448 {
449     return mmioFlush(HMMIO_32(hmmio), uFlags);
450 }
451
452 /***********************************************************************
453  *                              mmioAdvance             [MMSYSTEM.1219]
454  */
455 MMRESULT16 WINAPI mmioAdvance16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags)
456 {
457     MMIOINFO    mmioinfo;
458     LRESULT     ret;
459
460     /* WARNING: this heavily relies on mmioAdvance implementation (for choosing which
461      * fields to init
462      */
463     if (lpmmioinfo)
464     {
465         mmioinfo.pchBuffer = MapSL((DWORD)lpmmioinfo->pchBuffer);
466         mmioinfo.pchNext = MapSL((DWORD)lpmmioinfo->pchNext);
467         mmioinfo.dwFlags = lpmmioinfo->dwFlags;
468         mmioinfo.lBufOffset = lpmmioinfo->lBufOffset;
469         ret = mmioAdvance(HMMIO_32(hmmio), &mmioinfo, uFlags);
470     }
471     else
472         ret = mmioAdvance(HMMIO_32(hmmio), NULL, uFlags);
473
474     if (ret != MMSYSERR_NOERROR) return ret;
475
476     if (lpmmioinfo)
477     {
478         lpmmioinfo->dwFlags = mmioinfo.dwFlags;
479         lpmmioinfo->pchNext     = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchNext - mmioinfo.pchBuffer));
480         lpmmioinfo->pchEndRead  = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndRead - mmioinfo.pchBuffer));
481         lpmmioinfo->pchEndWrite = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer));
482         lpmmioinfo->lBufOffset  = mmioinfo.lBufOffset;
483         lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset;
484     }
485
486     return MMSYSERR_NOERROR;
487 }
488
489 /**************************************************************************
490  *                              mmioStringToFOURCC      [MMSYSTEM.1220]
491  */
492 FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
493 {
494     return mmioStringToFOURCCA(sz, uFlags);
495 }
496
497 /**************************************************************************
498  *              mmioInstallIOProc    [MMSYSTEM.1221]
499  */
500 LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc, LPMMIOPROC16 pIOProc,
501                                         DWORD dwFlags)
502 {
503     struct mmio_thunk*  thunk = NULL;
504     LPMMIOPROC pIOProc32;
505
506     EnterCriticalSection(&mmio_cs);
507
508     switch (dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
509     case MMIO_INSTALLPROC:
510         if (!(thunk = MMIO_AddThunk(pIOProc, NULL)))
511         {
512             LeaveCriticalSection(&mmio_cs);
513             return NULL;
514         }
515         if (!mmioInstallIOProcA(fccIOProc, (LPMMIOPROC)thunk, dwFlags))
516         {
517             thunk->pfn16 = NULL;
518             pIOProc = NULL;
519         }
520         break;
521     case MMIO_REMOVEPROC:
522         if (MMIO_Thunks)
523         {
524             for (thunk = MMIO_Thunks; thunk < &MMIO_Thunks[MMIO_MAX_THUNKS]; thunk++)
525             {
526                 if (thunk->pfn16 == pIOProc && thunk->segbuffer == 0)
527                 {
528                     if (mmioInstallIOProcA(fccIOProc, (LPMMIOPROC)thunk, dwFlags))
529                         thunk->pfn16 = NULL;
530                     else
531                         pIOProc = NULL;
532                     break;
533                 }
534             }
535         }
536         if (!thunk) pIOProc = NULL;
537         break;
538     case MMIO_FINDPROC:
539         if ((pIOProc32 = mmioInstallIOProcA(fccIOProc, NULL, dwFlags)) && MMIO_Thunks)
540         {
541             for (thunk = MMIO_Thunks; thunk < &MMIO_Thunks[MMIO_MAX_THUNKS]; thunk++)
542             {
543                 if ((LPMMIOPROC)thunk == pIOProc32)
544                 {
545                     pIOProc = thunk->pfn16;
546                     break;
547                 }
548             }
549         }
550         break;
551     default:
552         WINE_FIXME("Unsupported flags %08x\n", dwFlags);
553         pIOProc = NULL;
554     }
555     LeaveCriticalSection(&mmio_cs);
556
557     return pIOProc;
558 }
559
560 /**************************************************************************
561  *                              mmioSendMessage [MMSYSTEM.1222]
562  */
563 LRESULT WINAPI mmioSendMessage16(HMMIO16 hmmio, UINT16 uMessage,
564                                  LPARAM lParam1, LPARAM lParam2)
565 {
566     struct mmio_thunk*  thunk;
567
568     if ((thunk = MMIO_HasThunk(HMMIO_32(hmmio))))
569     {
570         MMIOINFO        mmioinfo;
571         if (mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, 0) == MMSYSERR_NOERROR)
572         {
573             return MMIO_Callback3216((SEGPTR)thunk->pfn16, &mmioinfo, uMessage, lParam1, lParam2);
574         }
575         return MMSYSERR_INVALHANDLE;
576     }
577     else
578     {
579         /* FIXME: we need to map lParam1 and lParam2 to 32bit entities */
580         return mmioSendMessage(HMMIO_32(hmmio), uMessage, lParam1, lParam2);
581     }
582 }
583
584 /**************************************************************************
585  *                              mmioDescend             [MMSYSTEM.1223]
586  */
587 MMRESULT16 WINAPI mmioDescend16(HMMIO16 hmmio, LPMMCKINFO lpck,
588                                 const MMCKINFO* lpckParent, UINT16 uFlags)
589 {
590     return mmioDescend(HMMIO_32(hmmio), lpck, lpckParent, uFlags);
591 }
592
593 /**************************************************************************
594  *                              mmioAscend              [MMSYSTEM.1224]
595  */
596 MMRESULT16 WINAPI mmioAscend16(HMMIO16 hmmio, MMCKINFO* lpck, UINT16 uFlags)
597 {
598     return mmioAscend(HMMIO_32(hmmio),lpck,uFlags);
599 }
600
601 /**************************************************************************
602  *                              mmioCreateChunk         [MMSYSTEM.1225]
603  */
604 MMRESULT16 WINAPI mmioCreateChunk16(HMMIO16 hmmio, MMCKINFO* lpck, UINT16 uFlags)
605 {
606     return mmioCreateChunk(HMMIO_32(hmmio), lpck, uFlags);
607 }
608
609 /**************************************************************************
610  *                              mmioRename              [MMSYSTEM.1226]
611  */
612 MMRESULT16 WINAPI mmioRename16(LPCSTR szFileName, LPCSTR szNewFileName,
613                                MMIOINFO16* lpmmioinfo, DWORD dwRenameFlags)
614 {
615     BOOL        inst = FALSE;
616     MMRESULT    ret;
617     MMIOINFO    mmioinfo;
618
619     if (lpmmioinfo != NULL && lpmmioinfo->pIOProc != NULL &&
620         lpmmioinfo->fccIOProc == 0) {
621         FIXME("Can't handle this case yet\n");
622         return MMSYSERR_ERROR;
623     }
624
625     /* this is a bit hacky, but it'll work if we get a fourCC code or nothing.
626      * but a non installed ioproc without a fourcc won't do
627      */
628     if (lpmmioinfo && lpmmioinfo->fccIOProc && lpmmioinfo->pIOProc) {
629         mmioInstallIOProc16(lpmmioinfo->fccIOProc, lpmmioinfo->pIOProc,
630                            MMIO_INSTALLPROC);
631         inst = TRUE;
632     }
633     memset(&mmioinfo, 0, sizeof(mmioinfo));
634     mmioinfo.fccIOProc = lpmmioinfo->fccIOProc;
635     ret = mmioRenameA(szFileName, szNewFileName, &mmioinfo, dwRenameFlags);
636     if (inst) {
637         mmioInstallIOProc16(lpmmioinfo->fccIOProc, NULL, MMIO_REMOVEPROC);
638     }
639     return ret;
640 }