msvcrt: Added _snscanf implementation.
[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 (!(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     = lpmmioinfo16->pIOProc ? (LPMMIOPROC)thunk : 0;
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 (!ret || (dwOpenFlags & (MMIO_PARSE|MMIO_EXIST)))
271         {
272             thunk->pfn16 = NULL;
273             thunk->hMmio = NULL;
274         }
275         else thunk->hMmio = ret;
276         if (ret && (dwOpenFlags & MMIO_ALLOCBUF))
277         {
278             MMIOINFO    m;
279             if (lpmmioinfo16->pchBuffer) FIXME("ooch\n");
280             /* FIXME: check whether mmioOpen should set pchBuffer */
281             mmioGetInfo(ret, &m, 0);
282             thunk->segbuffer = MapLS(m.pchBuffer);
283         }
284         LeaveCriticalSection(&mmio_cs);
285
286         lpmmioinfo16->wErrorRet = mmioinfo.wErrorRet;
287         lpmmioinfo16->hmmio     = HMMIO_16(mmioinfo.hmmio);
288     } else {
289         ret = mmioOpenA(szFileName, NULL, dwOpenFlags);
290     }
291     return HMMIO_16(ret);
292 }
293
294 /**************************************************************************
295  *                              mmioClose               [MMSYSTEM.1211]
296  */
297 MMRESULT16 WINAPI mmioClose16(HMMIO16 hmmio, UINT16 uFlags)
298 {
299     MMRESULT ret;
300
301     EnterCriticalSection(&mmio_cs);
302     ret = mmioClose(HMMIO_32(hmmio), uFlags);
303     if (ret == MMSYSERR_NOERROR)
304     {
305         struct mmio_thunk* thunk;
306
307         if ((thunk = MMIO_HasThunk(HMMIO_32(hmmio))))
308         {
309             MMIO_SetSegmentedBuffer(thunk, 0, TRUE);
310             thunk->pfn16 = NULL;
311             thunk->hMmio = NULL;
312         }
313     }
314     LeaveCriticalSection(&mmio_cs);
315     return ret;
316 }
317
318 /**************************************************************************
319  *                              mmioRead                [MMSYSTEM.1212]
320  */
321 LONG WINAPI mmioRead16(HMMIO16 hmmio, HPSTR pch, LONG cch)
322 {
323     return mmioRead(HMMIO_32(hmmio), pch, cch);
324 }
325
326 /**************************************************************************
327  *                              mmioWrite               [MMSYSTEM.1213]
328  */
329 LONG WINAPI mmioWrite16(HMMIO16 hmmio, HPCSTR pch, LONG cch)
330 {
331     return mmioWrite(HMMIO_32(hmmio),pch,cch);
332 }
333
334 /**************************************************************************
335  *                              mmioSeek                [MMSYSTEM.1214]
336  */
337 LONG WINAPI mmioSeek16(HMMIO16 hmmio, LONG lOffset, INT16 iOrigin)
338 {
339     return mmioSeek(HMMIO_32(hmmio), lOffset, iOrigin);
340 }
341
342 /**************************************************************************
343  *                              mmioGetInfo             [MMSYSTEM.1215]
344  */
345 MMRESULT16 WINAPI mmioGetInfo16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags)
346 {
347     MMIOINFO            mmioinfo;
348     MMRESULT            ret;
349     struct mmio_thunk*  thunk;
350
351     TRACE("(0x%04x,%p,0x%08x)\n", hmmio, lpmmioinfo, uFlags);
352
353     EnterCriticalSection(&mmio_cs);
354     if ((thunk = MMIO_HasThunk(HMMIO_32(hmmio))) == NULL)
355     {
356         LeaveCriticalSection(&mmio_cs);
357         return MMSYSERR_INVALHANDLE;
358     }
359
360     ret = mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, uFlags);
361     if (ret != MMSYSERR_NOERROR)
362     {
363         LeaveCriticalSection(&mmio_cs);
364         return ret;
365     }
366
367     lpmmioinfo->dwFlags     = mmioinfo.dwFlags;
368     lpmmioinfo->fccIOProc   = mmioinfo.fccIOProc;
369     lpmmioinfo->pIOProc     = thunk->pfn16;
370     lpmmioinfo->wErrorRet   = mmioinfo.wErrorRet;
371     lpmmioinfo->hTask       = HTASK_16(mmioinfo.hTask);
372     lpmmioinfo->cchBuffer   = mmioinfo.cchBuffer;
373     lpmmioinfo->pchBuffer   = (void*)thunk->segbuffer;
374     lpmmioinfo->pchNext     = (void*)(thunk->segbuffer + (mmioinfo.pchNext - mmioinfo.pchBuffer));
375     lpmmioinfo->pchEndRead  = (void*)(thunk->segbuffer + (mmioinfo.pchEndRead - mmioinfo.pchBuffer));
376     lpmmioinfo->pchEndWrite = (void*)(thunk->segbuffer + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer));
377     lpmmioinfo->lBufOffset  = mmioinfo.lBufOffset;
378     lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset;
379     lpmmioinfo->adwInfo[0]  = mmioinfo.adwInfo[0];
380     lpmmioinfo->adwInfo[1]  = mmioinfo.adwInfo[1];
381     lpmmioinfo->adwInfo[2]  = mmioinfo.adwInfo[2];
382     lpmmioinfo->dwReserved1 = 0;
383     lpmmioinfo->dwReserved2 = 0;
384     lpmmioinfo->hmmio = HMMIO_16(mmioinfo.hmmio);
385     LeaveCriticalSection(&mmio_cs);
386
387     return MMSYSERR_NOERROR;
388 }
389
390 /**************************************************************************
391  *                              mmioSetInfo             [MMSYSTEM.1216]
392  */
393 MMRESULT16 WINAPI mmioSetInfo16(HMMIO16 hmmio, const MMIOINFO16* lpmmioinfo, UINT16 uFlags)
394 {
395     MMIOINFO            mmioinfo;
396     MMRESULT            ret;
397
398     TRACE("(0x%04x,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
399
400     ret = mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, 0);
401     if (ret != MMSYSERR_NOERROR) return ret;
402
403     /* check if seg and lin buffers are the same */
404     if (mmioinfo.cchBuffer != lpmmioinfo->cchBuffer  ||
405         mmioinfo.pchBuffer != MapSL((DWORD)lpmmioinfo->pchBuffer))
406         return MMSYSERR_INVALPARAM;
407
408     /* check pointers coherence */
409     if (lpmmioinfo->pchNext < lpmmioinfo->pchBuffer ||
410         lpmmioinfo->pchNext > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer ||
411         lpmmioinfo->pchEndRead < lpmmioinfo->pchBuffer ||
412         lpmmioinfo->pchEndRead > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer ||
413         lpmmioinfo->pchEndWrite < lpmmioinfo->pchBuffer ||
414         lpmmioinfo->pchEndWrite > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer)
415         return MMSYSERR_INVALPARAM;
416
417     mmioinfo.pchNext     = mmioinfo.pchBuffer + (lpmmioinfo->pchNext     - lpmmioinfo->pchBuffer);
418     mmioinfo.pchEndRead  = mmioinfo.pchBuffer + (lpmmioinfo->pchEndRead  - lpmmioinfo->pchBuffer);
419     mmioinfo.pchEndWrite = mmioinfo.pchBuffer + (lpmmioinfo->pchEndWrite - lpmmioinfo->pchBuffer);
420
421     return mmioSetInfo(HMMIO_32(hmmio), &mmioinfo, uFlags);
422 }
423
424 /**************************************************************************
425  *                              mmioSetBuffer           [MMSYSTEM.1217]
426  */
427 MMRESULT16 WINAPI mmioSetBuffer16(HMMIO16 hmmio, LPSTR pchBuffer,
428                                   LONG cchBuffer, UINT16 uFlags)
429 {
430     MMRESULT    ret = mmioSetBuffer(HMMIO_32(hmmio), MapSL((DWORD)pchBuffer),
431                                     cchBuffer, uFlags);
432
433     if (ret == MMSYSERR_NOERROR)
434     {
435         struct mmio_thunk* thunk;
436
437         if ((thunk = MMIO_HasThunk(HMMIO_32(hmmio))) == NULL)
438         {
439             FIXME("really ?\n");
440             return MMSYSERR_INVALHANDLE;
441         }
442         MMIO_SetSegmentedBuffer(thunk, (DWORD)pchBuffer, TRUE);
443     }
444     else
445         UnMapLS((DWORD)pchBuffer);
446     return ret;
447 }
448
449 /**************************************************************************
450  *                              mmioFlush               [MMSYSTEM.1218]
451  */
452 MMRESULT16 WINAPI mmioFlush16(HMMIO16 hmmio, UINT16 uFlags)
453 {
454     return mmioFlush(HMMIO_32(hmmio), uFlags);
455 }
456
457 /***********************************************************************
458  *                              mmioAdvance             [MMSYSTEM.1219]
459  */
460 MMRESULT16 WINAPI mmioAdvance16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags)
461 {
462     MMIOINFO    mmioinfo;
463     LRESULT     ret;
464
465     /* WARNING: this heavily relies on mmioAdvance implementation (for choosing which
466      * fields to init
467      */
468     if (lpmmioinfo)
469     {
470         mmioinfo.pchBuffer = MapSL((DWORD)lpmmioinfo->pchBuffer);
471         mmioinfo.pchNext = MapSL((DWORD)lpmmioinfo->pchNext);
472         mmioinfo.dwFlags = lpmmioinfo->dwFlags;
473         mmioinfo.lBufOffset = lpmmioinfo->lBufOffset;
474         ret = mmioAdvance(HMMIO_32(hmmio), &mmioinfo, uFlags);
475     }
476     else
477         ret = mmioAdvance(HMMIO_32(hmmio), NULL, uFlags);
478
479     if (ret != MMSYSERR_NOERROR) return ret;
480
481     if (lpmmioinfo)
482     {
483         lpmmioinfo->dwFlags = mmioinfo.dwFlags;
484         lpmmioinfo->pchNext     = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchNext - mmioinfo.pchBuffer));
485         lpmmioinfo->pchEndRead  = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndRead - mmioinfo.pchBuffer));
486         lpmmioinfo->pchEndWrite = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer));
487         lpmmioinfo->lBufOffset  = mmioinfo.lBufOffset;
488         lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset;
489     }
490
491     return MMSYSERR_NOERROR;
492 }
493
494 /**************************************************************************
495  *                              mmioStringToFOURCC      [MMSYSTEM.1220]
496  */
497 FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
498 {
499     return mmioStringToFOURCCA(sz, uFlags);
500 }
501
502 /**************************************************************************
503  *              mmioInstallIOProc    [MMSYSTEM.1221]
504  */
505 LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc, LPMMIOPROC16 pIOProc,
506                                         DWORD dwFlags)
507 {
508     struct mmio_thunk*  thunk = NULL;
509     LPMMIOPROC pIOProc32;
510
511     EnterCriticalSection(&mmio_cs);
512
513     switch (dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
514     case MMIO_INSTALLPROC:
515         if (!(thunk = MMIO_AddThunk(pIOProc, NULL)))
516         {
517             LeaveCriticalSection(&mmio_cs);
518             return NULL;
519         }
520         if (!mmioInstallIOProcA(fccIOProc, (LPMMIOPROC)thunk, dwFlags))
521         {
522             thunk->pfn16 = NULL;
523             pIOProc = NULL;
524         }
525         break;
526     case MMIO_REMOVEPROC:
527         if (MMIO_Thunks)
528         {
529             for (thunk = MMIO_Thunks; thunk < &MMIO_Thunks[MMIO_MAX_THUNKS]; thunk++)
530             {
531                 if (thunk->pfn16 == pIOProc && thunk->segbuffer == 0)
532                 {
533                     if (mmioInstallIOProcA(fccIOProc, (LPMMIOPROC)thunk, dwFlags))
534                         thunk->pfn16 = NULL;
535                     else
536                         pIOProc = NULL;
537                     break;
538                 }
539             }
540         }
541         if (!thunk) pIOProc = NULL;
542         break;
543     case MMIO_FINDPROC:
544         if ((pIOProc32 = mmioInstallIOProcA(fccIOProc, NULL, dwFlags)) && MMIO_Thunks)
545         {
546             for (thunk = MMIO_Thunks; thunk < &MMIO_Thunks[MMIO_MAX_THUNKS]; thunk++)
547             {
548                 if ((LPMMIOPROC)thunk == pIOProc32)
549                 {
550                     pIOProc = thunk->pfn16;
551                     break;
552                 }
553             }
554         }
555         break;
556     default:
557         WINE_FIXME("Unsupported flags %08x\n", dwFlags);
558         pIOProc = NULL;
559     }
560     LeaveCriticalSection(&mmio_cs);
561
562     return pIOProc;
563 }
564
565 /**************************************************************************
566  *                              mmioSendMessage [MMSYSTEM.1222]
567  */
568 LRESULT WINAPI mmioSendMessage16(HMMIO16 hmmio, UINT16 uMessage,
569                                  LPARAM lParam1, LPARAM lParam2)
570 {
571     struct mmio_thunk*  thunk;
572
573     if ((thunk = MMIO_HasThunk(HMMIO_32(hmmio))))
574     {
575         MMIOINFO        mmioinfo;
576         if (mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, 0) == MMSYSERR_NOERROR)
577         {
578             return MMIO_Callback3216((SEGPTR)thunk->pfn16, &mmioinfo, uMessage, lParam1, lParam2);
579         }
580         return MMSYSERR_INVALHANDLE;
581     }
582     else
583     {
584         /* FIXME: we need to map lParam1 and lParam2 to 32bit entities */
585         return mmioSendMessage(HMMIO_32(hmmio), uMessage, lParam1, lParam2);
586     }
587 }
588
589 /**************************************************************************
590  *                              mmioDescend             [MMSYSTEM.1223]
591  */
592 MMRESULT16 WINAPI mmioDescend16(HMMIO16 hmmio, LPMMCKINFO lpck,
593                                 const MMCKINFO* lpckParent, UINT16 uFlags)
594 {
595     return mmioDescend(HMMIO_32(hmmio), lpck, lpckParent, uFlags);
596 }
597
598 /**************************************************************************
599  *                              mmioAscend              [MMSYSTEM.1224]
600  */
601 MMRESULT16 WINAPI mmioAscend16(HMMIO16 hmmio, MMCKINFO* lpck, UINT16 uFlags)
602 {
603     return mmioAscend(HMMIO_32(hmmio),lpck,uFlags);
604 }
605
606 /**************************************************************************
607  *                              mmioCreateChunk         [MMSYSTEM.1225]
608  */
609 MMRESULT16 WINAPI mmioCreateChunk16(HMMIO16 hmmio, MMCKINFO* lpck, UINT16 uFlags)
610 {
611     return mmioCreateChunk(HMMIO_32(hmmio), lpck, uFlags);
612 }
613
614 /**************************************************************************
615  *                              mmioRename              [MMSYSTEM.1226]
616  */
617 MMRESULT16 WINAPI mmioRename16(LPCSTR szFileName, LPCSTR szNewFileName,
618                                MMIOINFO16* lpmmioinfo, DWORD dwRenameFlags)
619 {
620     BOOL        inst = FALSE;
621     MMRESULT    ret;
622     MMIOINFO    mmioinfo;
623
624     if (lpmmioinfo != NULL && lpmmioinfo->pIOProc != NULL &&
625         lpmmioinfo->fccIOProc == 0) {
626         FIXME("Can't handle this case yet\n");
627         return MMSYSERR_ERROR;
628     }
629
630     /* this is a bit hacky, but it'll work if we get a fourCC code or nothing.
631      * but a non installed ioproc without a fourcc won't do
632      */
633     if (lpmmioinfo && lpmmioinfo->fccIOProc && lpmmioinfo->pIOProc) {
634         mmioInstallIOProc16(lpmmioinfo->fccIOProc, lpmmioinfo->pIOProc,
635                            MMIO_INSTALLPROC);
636         inst = TRUE;
637     }
638     memset(&mmioinfo, 0, sizeof(mmioinfo));
639     if (lpmmioinfo)
640         mmioinfo.fccIOProc = lpmmioinfo->fccIOProc;
641     ret = mmioRenameA(szFileName, szNewFileName, &mmioinfo, dwRenameFlags);
642     if (inst) {
643         mmioInstallIOProc16(lpmmioinfo->fccIOProc, NULL, MMIO_REMOVEPROC);
644     }
645     return ret;
646 }