Better error messages.
[wine] / dlls / winmm / mmsystem.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * MMSYTEM functions
5  *
6  * Copyright 1993      Martin Ayotte
7  *           1998-2002 Eric Pouech
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 /*
25  * Eric POUECH :
26  *      99/4    added mmTask and mmThread functions support
27  */
28
29 /* FIXME: I think there are some segmented vs. linear pointer weirdnesses
30  *        and long term pointers to 16 bit space in here
31  */
32
33 #include <string.h>
34
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
37 #include "mmsystem.h"
38 #include "winbase.h"
39 #include "winternl.h"
40 #include "wownt32.h"
41
42 #include "wine/winuser16.h"
43 #include "winemm.h"
44 #include "heap.h"
45
46 #include "wine/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
49
50 static WINE_MMTHREAD*   WINMM_GetmmThread(HANDLE16);
51 static LPWINE_DRIVER    DRIVER_OpenDriver16(LPCSTR, LPCSTR, LPARAM);
52 static LRESULT          DRIVER_CloseDriver16(HDRVR16, LPARAM, LPARAM);
53 static LRESULT          DRIVER_SendMessage16(HDRVR16, UINT, LPARAM, LPARAM);
54 static LRESULT          MMIO_Callback16(SEGPTR, LPMMIOINFO, UINT, LPARAM, LPARAM);
55
56 #define HMODULE_32(h16) ((HMODULE)(ULONG_PTR)(h16))
57 #define HINSTANCE_32(h16) ((HMODULE)(ULONG_PTR)(h16))
58
59 /* ###################################################
60  * #                  LIBRARY                        #
61  * ###################################################
62  */
63
64 /**************************************************************************
65  *                      DllEntryPoint (MMSYSTEM.2046)
66  *
67  * MMSYSTEM DLL entry point
68  *
69  */
70 BOOL WINAPI MMSYSTEM_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
71                              WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
72 {
73     TRACE("%p 0x%lx\n", hinstDLL, fdwReason);
74
75     switch (fdwReason) {
76     case DLL_PROCESS_ATTACH:
77         /* need to load WinMM in order to:
78          * - initiate correctly shared variables (WINMM_Init())
79          */
80         if (!GetModuleHandleA("WINMM.DLL") && !LoadLibraryA("WINMM.DLL"))
81         {
82             ERR("Could not load sibling WinMM.dll\n");
83             return FALSE;
84         }
85         WINMM_IData->hWinMM16Instance = hinstDLL;
86         /* hook in our 16 bit function pointers */
87         pFnGetMMThread16  = WINMM_GetmmThread;
88         pFnOpenDriver16   = DRIVER_OpenDriver16;
89         pFnCloseDriver16  = DRIVER_CloseDriver16;
90         pFnSendMessage16  = DRIVER_SendMessage16;
91         pFnMmioCallback16 = MMIO_Callback16;
92         MMDRV_Init16();
93         break;
94     case DLL_PROCESS_DETACH:
95         WINMM_IData->hWinMM16Instance = 0;
96         pFnGetMMThread16  = NULL;
97         pFnOpenDriver16   = NULL;
98         pFnCloseDriver16  = NULL;
99         pFnSendMessage16  = NULL;
100         pFnMmioCallback16 = NULL;
101         /* FIXME: add equivalent for MMDRV_Init16() */
102         break;
103     case DLL_THREAD_ATTACH:
104     case DLL_THREAD_DETACH:
105         break;
106     }
107     return TRUE;
108 }
109
110 /**************************************************************************
111  *                              MMSYSTEM_WEP                    [MMSYSTEM.1]
112  */
113 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
114                         WORD cbHeapSize, LPSTR lpCmdLine)
115 {
116     FIXME("STUB: Unloading MMSystem DLL ... hInst=%04X \n", hInstance);
117     return TRUE;
118 }
119
120 /* ###################################################
121  * #                  PlaySound                      #
122  * ###################################################
123  */
124
125 /**************************************************************************
126  *                              PlaySound               [MMSYSTEM.3]
127  */
128 BOOL16 WINAPI PlaySound16(LPCSTR pszSound, HMODULE16 hmod, DWORD fdwSound)
129 {
130     BOOL16      retv;
131     DWORD       lc;
132
133     ReleaseThunkLock(&lc);
134     retv = PlaySoundA(pszSound, HMODULE_32(hmod), fdwSound);
135     RestoreThunkLock(lc);
136
137     return retv;
138 }
139
140 /**************************************************************************
141  *                              sndPlaySound            [MMSYSTEM.2]
142  */
143 BOOL16 WINAPI sndPlaySound16(LPCSTR lpszSoundName, UINT16 uFlags)
144 {
145     BOOL16      retv;
146     DWORD       lc;
147
148     ReleaseThunkLock(&lc);
149     retv = sndPlaySoundA(lpszSoundName, uFlags);
150     RestoreThunkLock(lc);
151
152     return retv;
153 }
154
155 /* ###################################################
156  * #                    MISC                         #
157  * ###################################################
158  */
159
160 /**************************************************************************
161  *                              mmsystemGetVersion      [MMSYSTEM.5]
162  *
163  */
164 UINT16 WINAPI mmsystemGetVersion16(void)
165 {
166     return mmsystemGetVersion();
167 }
168
169 /**************************************************************************
170  *                              DriverCallback                  [MMSYSTEM.31]
171  */
172 BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HDRVR16 hDev,
173                                WORD wMsg, DWORD dwUser, DWORD dwParam1,
174                                DWORD dwParam2)
175 {
176     return DriverCallback(dwCallBack, uFlags, HDRVR_32(hDev), wMsg, dwUser, dwParam1, dwParam2);
177 }
178
179 /**************************************************************************
180  *                      OutputDebugStr          [MMSYSTEM.30]
181  */
182 void WINAPI OutputDebugStr16(LPCSTR str)
183 {
184     OutputDebugStringA( str );
185 }
186
187
188 /* ###################################################
189  * #                    MIXER                        #
190  * ###################################################
191  */
192
193 /**************************************************************************
194  *      Mixer devices. New to Win95
195  */
196
197 /**************************************************************************
198  *                              mixerGetNumDevs                 [MMSYSTEM.800]
199  */
200 UINT16 WINAPI mixerGetNumDevs16(void)
201 {
202     return MMDRV_GetNum(MMDRV_MIXER);
203 }
204
205 /**************************************************************************
206  *                              mixerGetDevCaps                 [MMSYSTEM.801]
207  */
208 UINT16 WINAPI mixerGetDevCaps16(UINT16 devid, LPMIXERCAPS16 mixcaps,
209                                 UINT16 size)
210 {
211     MIXERCAPSA  micA;
212     UINT        ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
213
214     if (ret == MMSYSERR_NOERROR) {
215         mixcaps->wMid           = micA.wMid;
216         mixcaps->wPid           = micA.wPid;
217         mixcaps->vDriverVersion = micA.vDriverVersion;
218         strcpy(mixcaps->szPname, micA.szPname);
219         mixcaps->fdwSupport     = micA.fdwSupport;
220         mixcaps->cDestinations  = micA.cDestinations;
221     }
222     return ret;
223 }
224
225 /**************************************************************************
226  *                              mixerOpen                       [MMSYSTEM.802]
227  */
228 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix, UINT16 uDeviceID, DWORD dwCallback,
229                           DWORD dwInstance, DWORD fdwOpen)
230 {
231     HMIXER      hmix;
232     UINT        ret;
233
234     ret = MIXER_Open(&hmix, uDeviceID, dwCallback, dwInstance, fdwOpen, FALSE);
235     if (lphmix) *lphmix = HMIXER_16(hmix);
236     return ret;
237 }
238
239 /**************************************************************************
240  *                              mixerClose                      [MMSYSTEM.803]
241  */
242 UINT16 WINAPI mixerClose16(HMIXER16 hMix)
243 {
244     return mixerClose(HMIXER_32(hMix));
245 }
246
247 /**************************************************************************
248  *                              mixerGetID (MMSYSTEM.806)
249  */
250 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix, LPUINT16 lpid, DWORD fdwID)
251 {
252     UINT        xid;
253     UINT        ret = mixerGetID(HMIXEROBJ_32(hmix), &xid, fdwID);
254
255     if (lpid)
256         *lpid = xid;
257     return ret;
258 }
259
260 /**************************************************************************
261  *                              mixerGetControlDetails  [MMSYSTEM.808]
262  */
263 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix,
264                                        LPMIXERCONTROLDETAILS16 lpmcd,
265                                        DWORD fdwDetails)
266 {
267     DWORD       ret = MMSYSERR_NOTENABLED;
268     SEGPTR      sppaDetails;
269
270     TRACE("(%04x, %p, %08lx)\n", hmix, lpmcd, fdwDetails);
271
272     if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
273         return MMSYSERR_INVALPARAM;
274
275     sppaDetails = (SEGPTR)lpmcd->paDetails;
276     lpmcd->paDetails = MapSL(sppaDetails);
277     ret = mixerGetControlDetailsA(HMIXEROBJ_32(hmix),
278                                  (LPMIXERCONTROLDETAILS)lpmcd, fdwDetails);
279     lpmcd->paDetails = (LPVOID)sppaDetails;
280
281     return ret;
282 }
283
284 /**************************************************************************
285  *                              mixerGetLineControls            [MMSYSTEM.807]
286  */
287 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,
288                                      LPMIXERLINECONTROLS16 lpmlc16,
289                                      DWORD fdwControls)
290 {
291     MIXERLINECONTROLSA  mlcA;
292     DWORD               ret;
293     int                 i;
294     LPMIXERCONTROL16    lpmc16;
295
296     TRACE("(%04x, %p, %08lx)\n", hmix, lpmlc16, fdwControls);
297
298     if (lpmlc16 == NULL || lpmlc16->cbStruct != sizeof(*lpmlc16) ||
299         lpmlc16->cbmxctrl != sizeof(MIXERCONTROL16))
300         return MMSYSERR_INVALPARAM;
301
302     mlcA.cbStruct = sizeof(mlcA);
303     mlcA.dwLineID = lpmlc16->dwLineID;
304     mlcA.u.dwControlID = lpmlc16->u.dwControlID;
305     mlcA.u.dwControlType = lpmlc16->u.dwControlType;
306     mlcA.cControls = lpmlc16->cControls;
307     mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
308     mlcA.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
309                               mlcA.cControls * mlcA.cbmxctrl);
310
311     ret = mixerGetLineControlsA(HMIXEROBJ_32(hmix), &mlcA, fdwControls);
312
313     if (ret == MMSYSERR_NOERROR) {
314         lpmlc16->dwLineID = mlcA.dwLineID;
315         lpmlc16->u.dwControlID = mlcA.u.dwControlID;
316         lpmlc16->u.dwControlType = mlcA.u.dwControlType;
317         lpmlc16->cControls = mlcA.cControls;
318
319         lpmc16 = MapSL(lpmlc16->pamxctrl);
320
321         for (i = 0; i < mlcA.cControls; i++) {
322             lpmc16[i].cbStruct = sizeof(MIXERCONTROL16);
323             lpmc16[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
324             lpmc16[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
325             lpmc16[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
326             lpmc16[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
327             strcpy(lpmc16[i].szShortName, mlcA.pamxctrl[i].szShortName);
328             strcpy(lpmc16[i].szName, mlcA.pamxctrl[i].szName);
329             /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
330             memcpy(&lpmc16[i].Bounds, &mlcA.pamxctrl[i].Bounds,
331                    sizeof(mlcA.pamxctrl[i].Bounds));
332             /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
333             memcpy(&lpmc16[i].Metrics, &mlcA.pamxctrl[i].Metrics,
334                    sizeof(mlcA.pamxctrl[i].Metrics));
335         }
336     }
337
338     HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
339
340     return ret;
341 }
342
343 /**************************************************************************
344  *                              mixerGetLineInfo        [MMSYSTEM.805]
345  */
346 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix, LPMIXERLINE16 lpmli16,
347                                  DWORD fdwInfo)
348 {
349     MIXERLINEA          mliA;
350     UINT                ret;
351
352     TRACE("(%04x, %p, %08lx)\n", hmix, lpmli16, fdwInfo);
353
354     if (lpmli16 == NULL || lpmli16->cbStruct != sizeof(*lpmli16))
355         return MMSYSERR_INVALPARAM;
356
357     mliA.cbStruct = sizeof(mliA);
358     switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) {
359     case MIXER_GETLINEINFOF_COMPONENTTYPE:
360         mliA.dwComponentType = lpmli16->dwComponentType;
361         break;
362     case MIXER_GETLINEINFOF_DESTINATION:
363         mliA.dwDestination = lpmli16->dwDestination;
364         break;
365     case MIXER_GETLINEINFOF_LINEID:
366         mliA.dwLineID = lpmli16->dwLineID;
367         break;
368     case MIXER_GETLINEINFOF_SOURCE:
369         mliA.dwDestination = lpmli16->dwDestination;
370         mliA.dwSource = lpmli16->dwSource;
371         break;
372     case MIXER_GETLINEINFOF_TARGETTYPE:
373         mliA.Target.dwType = lpmli16->Target.dwType;
374         mliA.Target.wMid = lpmli16->Target.wMid;
375         mliA.Target.wPid = lpmli16->Target.wPid;
376         mliA.Target.vDriverVersion = lpmli16->Target.vDriverVersion;
377         strcpy(mliA.Target.szPname, lpmli16->Target.szPname);
378         break;
379     default:
380         FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo);
381     }
382
383     ret = mixerGetLineInfoA(HMIXEROBJ_32(hmix), &mliA, fdwInfo);
384
385     lpmli16->dwDestination      = mliA.dwDestination;
386     lpmli16->dwSource           = mliA.dwSource;
387     lpmli16->dwLineID           = mliA.dwLineID;
388     lpmli16->fdwLine            = mliA.fdwLine;
389     lpmli16->dwUser             = mliA.dwUser;
390     lpmli16->dwComponentType    = mliA.dwComponentType;
391     lpmli16->cChannels          = mliA.cChannels;
392     lpmli16->cConnections       = mliA.cConnections;
393     lpmli16->cControls          = mliA.cControls;
394     strcpy(lpmli16->szShortName, mliA.szShortName);
395     strcpy(lpmli16->szName, mliA.szName);
396     lpmli16->Target.dwType      = mliA.Target.dwType;
397     lpmli16->Target.dwDeviceID  = mliA.Target.dwDeviceID;
398     lpmli16->Target.wMid        = mliA.Target.wMid;
399     lpmli16->Target.wPid        = mliA.Target.wPid;
400     lpmli16->Target.vDriverVersion = mliA.Target.vDriverVersion;
401     strcpy(lpmli16->Target.szPname, mliA.Target.szPname);
402
403     return ret;
404 }
405
406 /**************************************************************************
407  *                              mixerSetControlDetails  [MMSYSTEM.809]
408  */
409 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,
410                                        LPMIXERCONTROLDETAILS16 lpmcd,
411                                        DWORD fdwDetails)
412 {
413     TRACE("(%04x, %p, %08lx)\n", hmix, lpmcd, fdwDetails);
414     return MMSYSERR_NOTENABLED;
415 }
416
417 /**************************************************************************
418  *                              mixerMessage            [MMSYSTEM.804]
419  */
420 DWORD WINAPI mixerMessage16(HMIXER16 hmix, UINT16 uMsg, DWORD dwParam1,
421                              DWORD dwParam2)
422 {
423     return mixerMessage(HMIXER_32(hmix), uMsg, dwParam1, dwParam2);
424 }
425
426 /**************************************************************************
427  *                              auxGetNumDevs           [MMSYSTEM.350]
428  */
429 UINT16 WINAPI auxGetNumDevs16(void)
430 {
431     return MMDRV_GetNum(MMDRV_AUX);
432 }
433
434 /* ###################################################
435  * #                     AUX                         #
436  * ###################################################
437  */
438
439 /**************************************************************************
440  *                              auxGetDevCaps           [MMSYSTEM.351]
441  */
442 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID, LPAUXCAPS16 lpCaps, UINT16 uSize)
443 {
444     LPWINE_MLD          wmld;
445
446     TRACE("(%04X, %p, %d) !\n", uDeviceID, lpCaps, uSize);
447
448     if ((wmld = MMDRV_Get((HANDLE)(ULONG_PTR)uDeviceID, MMDRV_AUX, TRUE)) == NULL)
449         return MMSYSERR_INVALHANDLE;
450     return MMDRV_Message(wmld, AUXDM_GETDEVCAPS, (DWORD)lpCaps, uSize, TRUE);
451 }
452
453 /**************************************************************************
454  *                              auxGetVolume            [MMSYSTEM.352]
455  */
456 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, LPDWORD lpdwVolume)
457 {
458     LPWINE_MLD          wmld;
459
460     TRACE("(%04X, %p) !\n", uDeviceID, lpdwVolume);
461
462     if ((wmld = MMDRV_Get((HANDLE)(ULONG_PTR)uDeviceID, MMDRV_AUX, TRUE)) == NULL)
463         return MMSYSERR_INVALHANDLE;
464     return MMDRV_Message(wmld, AUXDM_GETVOLUME, (DWORD)lpdwVolume, 0L, TRUE);
465 }
466
467 /**************************************************************************
468  *                              auxSetVolume            [MMSYSTEM.353]
469  */
470 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
471 {
472     LPWINE_MLD          wmld;
473
474     TRACE("(%04X, %lu) !\n", uDeviceID, dwVolume);
475
476     if ((wmld = MMDRV_Get((HANDLE)(ULONG_PTR)uDeviceID, MMDRV_AUX, TRUE)) == NULL)
477         return MMSYSERR_INVALHANDLE;
478     return MMDRV_Message(wmld, AUXDM_SETVOLUME, dwVolume, 0L, TRUE);
479 }
480
481 /**************************************************************************
482  *                              auxOutMessage           [MMSYSTEM.354]
483  */
484 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
485 {
486     LPWINE_MLD          wmld;
487
488     TRACE("(%04X, %04X, %08lX, %08lX)\n", uDeviceID, uMessage, dw1, dw2);
489
490     switch (uMessage) {
491     case AUXDM_GETNUMDEVS:
492     case AUXDM_SETVOLUME:
493         /* no argument conversion needed */
494         break;
495     case AUXDM_GETVOLUME:
496         return auxGetVolume16(uDeviceID, MapSL(dw1));
497     case AUXDM_GETDEVCAPS:
498         return auxGetDevCaps16(uDeviceID, MapSL(dw1), dw2);
499     default:
500         TRACE("(%04x, %04x, %08lx, %08lx): unhandled message\n",
501               uDeviceID, uMessage, dw1, dw2);
502         break;
503     }
504     if ((wmld = MMDRV_Get((HANDLE)(ULONG_PTR)uDeviceID, MMDRV_AUX, TRUE)) == NULL)
505         return MMSYSERR_INVALHANDLE;
506
507     return MMDRV_Message(wmld, uMessage, dw1, dw2, TRUE);
508 }
509
510 /* ###################################################
511  * #                     MCI                         #
512  * ###################################################
513  */
514
515 /**************************************************************************
516  *                              mciGetErrorString               [MMSYSTEM.706]
517  */
518 BOOL16 WINAPI mciGetErrorString16(DWORD wError, LPSTR lpstrBuffer, UINT16 uLength)
519 {
520     return mciGetErrorStringA(wError, lpstrBuffer, uLength);
521 }
522
523 /**************************************************************************
524  *                              mciDriverNotify                 [MMSYSTEM.711]
525  */
526 BOOL16 WINAPI mciDriverNotify16(HWND16 hWndCallBack, UINT16 wDevID, UINT16 wStatus)
527 {
528     TRACE("(%04X, %04x, %04X)\n", hWndCallBack, wDevID, wStatus);
529
530     return PostMessageA(HWND_32(hWndCallBack), MM_MCINOTIFY, wStatus, wDevID);
531 }
532
533 /**************************************************************************
534  *                      mciGetDriverData                        [MMSYSTEM.708]
535  */
536 DWORD WINAPI mciGetDriverData16(UINT16 uDeviceID)
537 {
538     return mciGetDriverData(uDeviceID);
539 }
540
541 /**************************************************************************
542  *                      mciSetDriverData                        [MMSYSTEM.707]
543  */
544 BOOL16 WINAPI mciSetDriverData16(UINT16 uDeviceID, DWORD data)
545 {
546     return mciSetDriverData(uDeviceID, data);
547 }
548
549 /**************************************************************************
550  *                              mciSendCommand                  [MMSYSTEM.701]
551  */
552 DWORD WINAPI mciSendCommand16(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
553 {
554     DWORD               dwRet;
555
556     TRACE("(%04X, %s, %08lX, %08lX)\n",
557           wDevID, MCI_MessageToString(wMsg), dwParam1, dwParam2);
558
559     dwRet = MCI_SendCommand(wDevID, wMsg, dwParam1, dwParam2, FALSE);
560     dwRet = MCI_CleanUp(dwRet, wMsg, (DWORD)MapSL(dwParam2));
561     TRACE("=> %ld\n", dwRet);
562     return dwRet;
563 }
564
565 /**************************************************************************
566  *                              mciGetDeviceID                  [MMSYSTEM.703]
567  */
568 UINT16 WINAPI mciGetDeviceID16(LPCSTR lpstrName)
569 {
570     TRACE("(\"%s\")\n", lpstrName);
571
572     return MCI_GetDriverFromString(lpstrName);
573 }
574
575 /**************************************************************************
576  *                              mciSetYieldProc                 [MMSYSTEM.714]
577  */
578 BOOL16 WINAPI mciSetYieldProc16(UINT16 uDeviceID, YIELDPROC16 fpYieldProc, DWORD dwYieldData)
579 {
580     LPWINE_MCIDRIVER    wmd;
581
582     TRACE("(%u, %p, %08lx)\n", uDeviceID, fpYieldProc, dwYieldData);
583
584     if (!(wmd = MCI_GetDriver(uDeviceID))) {
585         WARN("Bad uDeviceID\n");
586         return FALSE;
587     }
588
589     wmd->lpfnYieldProc = (YIELDPROC)fpYieldProc;
590     wmd->dwYieldData   = dwYieldData;
591     wmd->bIs32         = FALSE;
592
593     return TRUE;
594 }
595
596 /**************************************************************************
597  *                              mciGetDeviceIDFromElementID     [MMSYSTEM.715]
598  */
599 UINT16 WINAPI mciGetDeviceIDFromElementID16(DWORD dwElementID, LPCSTR lpstrType)
600 {
601     FIXME("(%lu, %s) stub\n", dwElementID, lpstrType);
602     return 0;
603 }
604
605 /**************************************************************************
606  *                              mciGetYieldProc                 [MMSYSTEM.716]
607  */
608 YIELDPROC16 WINAPI mciGetYieldProc16(UINT16 uDeviceID, DWORD* lpdwYieldData)
609 {
610     LPWINE_MCIDRIVER    wmd;
611
612     TRACE("(%u, %p)\n", uDeviceID, lpdwYieldData);
613
614     if (!(wmd = MCI_GetDriver(uDeviceID))) {
615         WARN("Bad uDeviceID\n");
616         return NULL;
617     }
618     if (!wmd->lpfnYieldProc) {
619         WARN("No proc set\n");
620         return NULL;
621     }
622     if (wmd->bIs32) {
623         WARN("Proc is 32 bit\n");
624         return NULL;
625     }
626     return (YIELDPROC16)wmd->lpfnYieldProc;
627 }
628
629 /**************************************************************************
630  *                              mciGetCreatorTask               [MMSYSTEM.717]
631  */
632 HTASK16 WINAPI mciGetCreatorTask16(UINT16 uDeviceID)
633 {
634     LPWINE_MCIDRIVER wmd;
635     HTASK16 ret = 0;
636
637     if ((wmd = MCI_GetDriver(uDeviceID))) 
638         ret = HTASK_16(wmd->CreatorThread);
639
640     TRACE("(%u) => %04x\n", uDeviceID, ret);
641     return ret;
642 }
643
644 /**************************************************************************
645  *                              mciDriverYield                  [MMSYSTEM.710]
646  */
647 UINT16 WINAPI mciDriverYield16(UINT16 uDeviceID)
648 {
649     LPWINE_MCIDRIVER    wmd;
650     UINT16              ret = 0;
651
652     /*    TRACE("(%04x)\n", uDeviceID); */
653
654     if (!(wmd = MCI_GetDriver(uDeviceID)) || !wmd->lpfnYieldProc || wmd->bIs32) {
655         UserYield16();
656     } else {
657         ret = wmd->lpfnYieldProc(uDeviceID, wmd->dwYieldData);
658     }
659
660     return ret;
661 }
662
663 /* ###################################################
664  * #                     MIDI                        #
665  * ###################################################
666  */
667
668 /**************************************************************************
669  *                              midiOutGetNumDevs       [MMSYSTEM.201]
670  */
671 UINT16 WINAPI midiOutGetNumDevs16(void)
672 {
673     return MMDRV_GetNum(MMDRV_MIDIOUT);
674 }
675
676 /**************************************************************************
677  *                              midiOutGetDevCaps       [MMSYSTEM.202]
678  */
679 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID, LPMIDIOUTCAPS16 lpCaps,
680                                   UINT16 uSize)
681 {
682     MIDIOUTCAPSA        capsA;
683     UINT                dwRet;
684
685     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
686
687     dwRet = midiOutGetDevCapsA(uDeviceID, &capsA, sizeof(capsA));
688     if (dwRet == MMSYSERR_NOERROR) {
689         lpCaps->wMid            = capsA.wMid;
690         lpCaps->wPid            = capsA.wPid;
691         lpCaps->vDriverVersion  = capsA.vDriverVersion;
692         strcpy(lpCaps->szPname, capsA.szPname);
693         lpCaps->wTechnology     = capsA.wTechnology;
694         lpCaps->wVoices         = capsA.wVoices;
695         lpCaps->wNotes          = capsA.wNotes;
696         lpCaps->wChannelMask    = capsA.wChannelMask;
697         lpCaps->dwSupport       = capsA.dwSupport;
698     }
699     return dwRet;
700  }
701
702 /**************************************************************************
703  *                              midiOutGetErrorText     [MMSYSTEM.203]
704  */
705 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
706 {
707     return midiOutGetErrorTextA(uError, lpText, uSize);
708 }
709
710 /**************************************************************************
711  *                              midiOutOpen             [MMSYSTEM.204]
712  */
713 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
714                             DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
715 {
716     HMIDIOUT    hmo;
717     UINT        ret;
718
719     ret = MIDI_OutOpen(&hmo, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
720
721     if (lphMidiOut != NULL) *lphMidiOut = HMIDIOUT_16(hmo);
722     return ret;
723 }
724
725 /**************************************************************************
726  *                              midiOutClose            [MMSYSTEM.205]
727  */
728 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
729 {
730     return midiOutClose(HMIDIOUT_32(hMidiOut));
731 }
732
733 /**************************************************************************
734  *                              midiOutPrepareHeader    [MMSYSTEM.206]
735  */
736 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
737                                      SEGPTR lpsegMidiOutHdr,      /* [???] */
738                                      UINT16 uSize)                /* [in] */
739 {
740     LPWINE_MLD          wmld;
741
742     TRACE("(%04X, %08lx, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
743
744     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
745         return MMSYSERR_INVALHANDLE;
746
747     return MMDRV_Message(wmld, MODM_PREPARE, lpsegMidiOutHdr, uSize, FALSE);
748 }
749
750 /**************************************************************************
751  *                              midiOutUnprepareHeader  [MMSYSTEM.207]
752  */
753 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
754                                        SEGPTR lpsegMidiOutHdr,      /* [???] */
755                                        UINT16 uSize)                /* [in] */
756 {
757     LPWINE_MLD          wmld;
758     LPMIDIHDR16         lpMidiOutHdr = MapSL(lpsegMidiOutHdr);
759
760     TRACE("(%04X, %08lx, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
761
762     if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
763         return MMSYSERR_NOERROR;
764     }
765
766     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
767         return MMSYSERR_INVALHANDLE;
768
769     return MMDRV_Message(wmld, MODM_UNPREPARE, (DWORD)lpsegMidiOutHdr, uSize, FALSE);
770 }
771
772 /**************************************************************************
773  *                              midiOutShortMsg         [MMSYSTEM.208]
774  */
775 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
776 {
777     return midiOutShortMsg(HMIDIOUT_32(hMidiOut), dwMsg);
778 }
779
780 /**************************************************************************
781  *                              midiOutLongMsg          [MMSYSTEM.209]
782  */
783 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut,          /* [in] */
784                                LPMIDIHDR16 lpsegMidiOutHdr,  /* [???] NOTE: SEGPTR */
785                                UINT16 uSize)                 /* [in] */
786 {
787     LPWINE_MLD          wmld;
788
789     TRACE("(%04X, %p, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
790
791     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
792         return MMSYSERR_INVALHANDLE;
793
794     return MMDRV_Message(wmld, MODM_LONGDATA, (DWORD)lpsegMidiOutHdr, uSize, FALSE);
795 }
796
797 /**************************************************************************
798  *                              midiOutReset            [MMSYSTEM.210]
799  */
800 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
801 {
802     return midiOutReset(HMIDIOUT_32(hMidiOut));
803 }
804
805 /**************************************************************************
806  *                              midiOutGetVolume        [MMSYSTEM.211]
807  */
808 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
809 {
810     return midiOutGetVolume(HMIDIOUT_32(uDeviceID), lpdwVolume);
811 }
812
813 /**************************************************************************
814  *                              midiOutSetVolume        [MMSYSTEM.212]
815  */
816 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
817 {
818     return midiOutSetVolume(HMIDIOUT_32(uDeviceID), dwVolume);
819 }
820
821 /**************************************************************************
822  *                              midiOutCachePatches             [MMSYSTEM.213]
823  */
824 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
825                                     WORD* lpwPatchArray, UINT16 uFlags)
826 {
827     return midiOutCachePatches(HMIDIOUT_32(hMidiOut), uBank, lpwPatchArray,
828                                uFlags);
829 }
830
831 /**************************************************************************
832  *                              midiOutCacheDrumPatches [MMSYSTEM.214]
833  */
834 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
835                                         WORD* lpwKeyArray, UINT16 uFlags)
836 {
837     return midiOutCacheDrumPatches(HMIDIOUT_32(hMidiOut), uPatch, lpwKeyArray, uFlags);
838 }
839
840 /**************************************************************************
841  *                              midiOutGetID            [MMSYSTEM.215]
842  */
843 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
844 {
845     LPWINE_MLD          wmld;
846
847     TRACE("(%04X, %p)\n", hMidiOut, lpuDeviceID);
848
849     if (lpuDeviceID == NULL) return MMSYSERR_INVALPARAM;
850     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
851         return MMSYSERR_INVALHANDLE;
852
853     *lpuDeviceID = wmld->uDeviceID;
854     return MMSYSERR_NOERROR;
855 }
856
857 /**************************************************************************
858  *                              midiOutMessage          [MMSYSTEM.216]
859  */
860 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
861                               DWORD dwParam1, DWORD dwParam2)
862 {
863     LPWINE_MLD          wmld;
864
865     TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut, uMessage, dwParam1, dwParam2);
866
867     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
868         return MMSYSERR_INVALHANDLE;
869
870     switch (uMessage) {
871     case MODM_OPEN:
872     case MODM_CLOSE:
873         FIXME("can't handle OPEN or CLOSE message!\n");
874         return MMSYSERR_NOTSUPPORTED;
875
876     case MODM_GETVOLUME:
877         return midiOutGetVolume16(hMidiOut, MapSL(dwParam1));
878     case MODM_LONGDATA:
879         return midiOutLongMsg16(hMidiOut, MapSL(dwParam1), dwParam2);
880     case MODM_PREPARE:
881         /* lpMidiOutHdr is still a segmented pointer for this function */
882         return midiOutPrepareHeader16(hMidiOut, dwParam1, dwParam2);
883     case MODM_UNPREPARE:
884         return midiOutUnprepareHeader16(hMidiOut, dwParam1, dwParam2);
885     }
886     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
887 }
888
889 /**************************************************************************
890  *                              midiInGetNumDevs        [MMSYSTEM.301]
891  */
892 UINT16 WINAPI midiInGetNumDevs16(void)
893 {
894     return MMDRV_GetNum(MMDRV_MIDIIN);
895 }
896
897 /**************************************************************************
898  *                              midiInGetDevCaps        [MMSYSTEM.302]
899  */
900 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID, LPMIDIINCAPS16 lpCaps,
901                                  UINT16 uSize)
902 {
903     MIDIINCAPSA         micA;
904     UINT                ret = midiInGetDevCapsA(uDeviceID, &micA, uSize);
905
906     if (ret == MMSYSERR_NOERROR) {
907         lpCaps->wMid = micA.wMid;
908         lpCaps->wPid = micA.wPid;
909         lpCaps->vDriverVersion = micA.vDriverVersion;
910         strcpy(lpCaps->szPname, micA.szPname);
911         lpCaps->dwSupport = micA.dwSupport;
912     }
913
914     return ret;
915 }
916
917 /**************************************************************************
918  *                              midiInGetErrorText              [MMSYSTEM.303]
919  */
920 UINT16 WINAPI midiInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
921 {
922     return midiInGetErrorTextA(uError, lpText, uSize);
923 }
924
925 /**************************************************************************
926  *                              midiInOpen              [MMSYSTEM.304]
927  */
928 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
929                            DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
930 {
931     HMIDIIN     xhmid;
932     UINT        ret;
933
934     ret = MIDI_InOpen(&xhmid, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
935
936     if (lphMidiIn) *lphMidiIn = HMIDIIN_16(xhmid);
937     return ret;
938 }
939
940 /**************************************************************************
941  *                              midiInClose             [MMSYSTEM.305]
942  */
943 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
944 {
945     return midiInClose(HMIDIIN_32(hMidiIn));
946 }
947
948 /**************************************************************************
949  *                              midiInPrepareHeader     [MMSYSTEM.306]
950  */
951 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
952                                     SEGPTR lpsegMidiInHdr,     /* [???] */
953                                     UINT16 uSize)              /* [in] */
954 {
955     LPWINE_MLD          wmld;
956
957     TRACE("(%04X, %08lx, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
958
959     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
960         return MMSYSERR_INVALHANDLE;
961
962     return MMDRV_Message(wmld, MIDM_PREPARE, (DWORD)lpsegMidiInHdr, uSize, FALSE);
963 }
964
965 /**************************************************************************
966  *                              midiInUnprepareHeader   [MMSYSTEM.307]
967  */
968 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
969                                       SEGPTR lpsegMidiInHdr,     /* [???] */
970                                       UINT16 uSize)              /* [in] */
971 {
972     LPWINE_MLD          wmld;
973     LPMIDIHDR16         lpMidiInHdr = MapSL(lpsegMidiInHdr);
974
975     TRACE("(%04X, %08lx, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
976
977     if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
978         return MMSYSERR_NOERROR;
979     }
980
981     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
982         return MMSYSERR_INVALHANDLE;
983
984     return MMDRV_Message(wmld, MIDM_UNPREPARE, (DWORD)lpsegMidiInHdr, uSize, FALSE);
985 }
986
987 /**************************************************************************
988  *                              midiInAddBuffer         [MMSYSTEM.308]
989  */
990 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn,         /* [in] */
991                                 MIDIHDR16* lpsegMidiInHdr, /* [???] NOTE: SEGPTR */
992                                 UINT16 uSize)              /* [in] */
993 {
994     LPWINE_MLD          wmld;
995
996     TRACE("(%04X, %p, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
997
998     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
999         return MMSYSERR_INVALHANDLE;
1000
1001     return MMDRV_Message(wmld, MIDM_ADDBUFFER, (DWORD)lpsegMidiInHdr, uSize, FALSE);
1002 }
1003
1004 /**************************************************************************
1005  *                              midiInStart                     [MMSYSTEM.309]
1006  */
1007 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
1008 {
1009     return midiInStart(HMIDIIN_32(hMidiIn));
1010 }
1011
1012 /**************************************************************************
1013  *                              midiInStop                      [MMSYSTEM.310]
1014  */
1015 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
1016 {
1017     return midiInStop(HMIDIIN_32(hMidiIn));
1018 }
1019
1020 /**************************************************************************
1021  *                              midiInReset                     [MMSYSTEM.311]
1022  */
1023 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
1024 {
1025     return midiInReset(HMIDIIN_32(hMidiIn));
1026 }
1027
1028 /**************************************************************************
1029  *                              midiInGetID                     [MMSYSTEM.312]
1030  */
1031 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
1032 {
1033     LPWINE_MLD          wmld;
1034
1035     TRACE("(%04X, %p)\n", hMidiIn, lpuDeviceID);
1036
1037     if (lpuDeviceID == NULL) return MMSYSERR_INVALPARAM;
1038
1039     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, TRUE)) == NULL)
1040         return MMSYSERR_INVALHANDLE;
1041
1042     *lpuDeviceID = wmld->uDeviceID;
1043
1044     return MMSYSERR_NOERROR;
1045 }
1046
1047 /**************************************************************************
1048  *                              midiInMessage           [MMSYSTEM.313]
1049  */
1050 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
1051                              DWORD dwParam1, DWORD dwParam2)
1052 {
1053     LPWINE_MLD          wmld;
1054
1055     TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn, uMessage, dwParam1, dwParam2);
1056
1057     switch (uMessage) {
1058     case MIDM_OPEN:
1059     case MIDM_CLOSE:
1060         FIXME("can't handle OPEN or CLOSE message!\n");
1061         return MMSYSERR_NOTSUPPORTED;
1062
1063     case MIDM_GETDEVCAPS:
1064         return midiInGetDevCaps16(hMidiIn, MapSL(dwParam1), dwParam2);
1065     case MIDM_PREPARE:
1066         return midiInPrepareHeader16(hMidiIn, dwParam1, dwParam2);
1067     case MIDM_UNPREPARE:
1068         return midiInUnprepareHeader16(hMidiIn, dwParam1, dwParam2);
1069     case MIDM_ADDBUFFER:
1070         return midiInAddBuffer16(hMidiIn, MapSL(dwParam1), dwParam2);
1071     }
1072
1073     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
1074         return MMSYSERR_INVALHANDLE;
1075
1076     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1077 }
1078
1079 /**************************************************************************
1080  *                              midiStreamClose                 [MMSYSTEM.252]
1081  */
1082 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hMidiStrm)
1083 {
1084     return midiStreamClose(HMIDISTRM_32(hMidiStrm));
1085 }
1086
1087 /**************************************************************************
1088  *                              midiStreamOpen                  [MMSYSTEM.251]
1089  */
1090 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
1091                                    DWORD cMidi, DWORD dwCallback,
1092                                    DWORD dwInstance, DWORD fdwOpen)
1093 {
1094     HMIDISTRM   hMidiStrm32;
1095     MMRESULT    ret;
1096     UINT        devid32;
1097
1098     if (!phMidiStrm || !devid)
1099         return MMSYSERR_INVALPARAM;
1100     devid32 = *devid;
1101     ret = MIDI_StreamOpen(&hMidiStrm32, &devid32, cMidi, dwCallback,
1102                           dwInstance, fdwOpen, FALSE);
1103     *phMidiStrm = HMIDISTRM_16(hMidiStrm32);
1104     *devid = devid32;
1105     return ret;
1106 }
1107
1108 /**************************************************************************
1109  *                              midiStreamOut                   [MMSYSTEM.254]
1110  */
1111 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hMidiStrm, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
1112 {
1113     return midiStreamOut(HMIDISTRM_32(hMidiStrm), (LPMIDIHDR)lpMidiHdr,
1114                          cbMidiHdr);
1115 }
1116
1117 /**************************************************************************
1118  *                              midiStreamPause                 [MMSYSTEM.255]
1119  */
1120 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hMidiStrm)
1121 {
1122     return midiStreamPause(HMIDISTRM_32(hMidiStrm));
1123 }
1124
1125 /**************************************************************************
1126  *                              midiStreamPosition              [MMSYSTEM.253]
1127  */
1128 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hMidiStrm, LPMMTIME16 lpmmt16, UINT16 cbmmt)
1129 {
1130     MMTIME      mmt32;
1131     MMRESULT    ret;
1132
1133     if (!lpmmt16)
1134         return MMSYSERR_INVALPARAM;
1135     MMSYSTEM_MMTIME16to32(&mmt32, lpmmt16);
1136     ret = midiStreamPosition(HMIDISTRM_32(hMidiStrm), &mmt32, sizeof(MMTIME));
1137     MMSYSTEM_MMTIME32to16(lpmmt16, &mmt32);
1138     return ret;
1139 }
1140
1141 /**************************************************************************
1142  *                              midiStreamProperty              [MMSYSTEM.250]
1143  */
1144 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hMidiStrm, LPBYTE lpPropData, DWORD dwProperty)
1145 {
1146     return midiStreamProperty(HMIDISTRM_32(hMidiStrm), lpPropData, dwProperty);
1147 }
1148
1149 /**************************************************************************
1150  *                              midiStreamRestart               [MMSYSTEM.256]
1151  */
1152 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hMidiStrm)
1153 {
1154     return midiStreamRestart(HMIDISTRM_32(hMidiStrm));
1155 }
1156
1157 /**************************************************************************
1158  *                              midiStreamStop                  [MMSYSTEM.257]
1159  */
1160 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hMidiStrm)
1161 {
1162     return midiStreamStop(HMIDISTRM_32(hMidiStrm));
1163 }
1164
1165 /* ###################################################
1166  * #                     WAVE                        #
1167  * ###################################################
1168  */
1169
1170 /**************************************************************************
1171  *                              waveOutGetNumDevs               [MMSYSTEM.401]
1172  */
1173 UINT16 WINAPI waveOutGetNumDevs16(void)
1174 {
1175     return MMDRV_GetNum(MMDRV_WAVEOUT);
1176 }
1177
1178 /**************************************************************************
1179  *                              waveOutGetDevCaps               [MMSYSTEM.402]
1180  */
1181 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID,
1182                                   LPWAVEOUTCAPS16 lpCaps, UINT16 uSize)
1183 {
1184     WAVEOUTCAPSA        wocA;
1185     UINT                ret;
1186
1187     TRACE("(%u %p %u)!\n", uDeviceID, lpCaps, uSize);
1188     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1189
1190     ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA));
1191
1192     if (ret == MMSYSERR_NOERROR) {
1193         lpCaps->wMid = wocA.wMid;
1194         lpCaps->wPid = wocA.wPid;
1195         lpCaps->vDriverVersion = wocA.vDriverVersion;
1196         strcpy(lpCaps->szPname, wocA.szPname);
1197         lpCaps->dwFormats = wocA.dwFormats;
1198         lpCaps->wChannels = wocA.wChannels;
1199         lpCaps->dwSupport = wocA.dwSupport;
1200     }
1201     return ret;
1202 }
1203
1204 /**************************************************************************
1205  *                              waveOutGetErrorText     [MMSYSTEM.403]
1206  */
1207 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1208 {
1209     return waveOutGetErrorTextA(uError, lpText, uSize);
1210 }
1211
1212 /**************************************************************************
1213  *                      waveOutOpen                     [MMSYSTEM.404]
1214  */
1215 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
1216                             const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
1217                             DWORD dwInstance, DWORD dwFlags)
1218 {
1219     HANDLE              hWaveOut;
1220     UINT                ret;
1221
1222     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1223      * call the 32 bit version
1224      * however, we need to promote correctly the wave mapper id
1225      * (0xFFFFFFFF and not 0x0000FFFF)
1226      */
1227     ret = WAVE_Open(&hWaveOut, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1228                     MMDRV_WAVEOUT, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1229
1230     if (lphWaveOut != NULL) *lphWaveOut = HWAVEOUT_16(hWaveOut);
1231     return ret;
1232 }
1233
1234 /**************************************************************************
1235  *                              waveOutClose            [MMSYSTEM.405]
1236  */
1237 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
1238 {
1239     DWORD       level;
1240     UINT16      ret;
1241
1242     ReleaseThunkLock(&level);
1243     ret = waveOutClose(HWAVEOUT_32(hWaveOut));
1244     RestoreThunkLock(level);
1245     return ret;
1246 }
1247
1248 /**************************************************************************
1249  *                              waveOutPrepareHeader    [MMSYSTEM.406]
1250  */
1251 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,      /* [in] */
1252                                      SEGPTR lpsegWaveOutHdr,   /* [???] */
1253                                      UINT16 uSize)             /* [in] */
1254 {
1255     LPWINE_MLD          wmld;
1256     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1257
1258     TRACE("(%04X, %08lx, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1259
1260     if (lpWaveOutHdr == NULL) return MMSYSERR_INVALPARAM;
1261
1262     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1263         return MMSYSERR_INVALHANDLE;
1264
1265     return MMDRV_Message(wmld, WODM_PREPARE, (DWORD)lpsegWaveOutHdr, uSize, FALSE);
1266 }
1267
1268 /**************************************************************************
1269  *                              waveOutUnprepareHeader  [MMSYSTEM.407]
1270  */
1271 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,       /* [in] */
1272                                        SEGPTR lpsegWaveOutHdr,    /* [???] */
1273                                        UINT16 uSize)              /* [in] */
1274 {
1275     LPWINE_MLD          wmld;
1276     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1277
1278     TRACE("(%04X, %08lx, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1279
1280     if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
1281         return MMSYSERR_NOERROR;
1282     }
1283
1284     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1285         return MMSYSERR_INVALHANDLE;
1286
1287     return MMDRV_Message(wmld, WODM_UNPREPARE, (DWORD)lpsegWaveOutHdr, uSize, FALSE);
1288 }
1289
1290 /**************************************************************************
1291  *                              waveOutWrite            [MMSYSTEM.408]
1292  */
1293 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut,       /* [in] */
1294                              LPWAVEHDR lpsegWaveOutHdr, /* [???] NOTE: SEGPTR */
1295                              UINT16 uSize)              /* [in] */
1296 {
1297     LPWINE_MLD          wmld;
1298
1299     TRACE("(%04X, %p, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1300
1301     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1302         return MMSYSERR_INVALHANDLE;
1303
1304     return MMDRV_Message(wmld, WODM_WRITE, (DWORD)lpsegWaveOutHdr, uSize, FALSE);
1305 }
1306
1307 /**************************************************************************
1308  *                              waveOutBreakLoop        [MMSYSTEM.419]
1309  */
1310 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut16)
1311 {
1312     DWORD       level;
1313     UINT16      ret;
1314
1315     ReleaseThunkLock(&level);
1316     ret = waveOutBreakLoop(HWAVEOUT_32(hWaveOut16));
1317     RestoreThunkLock(level);
1318     return ret;
1319 }
1320
1321 /**************************************************************************
1322  *                              waveOutPause            [MMSYSTEM.409]
1323  */
1324 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut16)
1325 {
1326     DWORD       level;
1327     UINT16      ret;
1328
1329     ReleaseThunkLock(&level);
1330     ret = waveOutPause(HWAVEOUT_32(hWaveOut16));
1331     RestoreThunkLock(level);
1332     return ret;
1333 }
1334
1335 /**************************************************************************
1336  *                              waveOutReset            [MMSYSTEM.411]
1337  */
1338 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut16)
1339 {
1340     DWORD       level;
1341     UINT16      ret;
1342
1343     ReleaseThunkLock(&level);
1344     ret = waveOutReset(HWAVEOUT_32(hWaveOut16));
1345     RestoreThunkLock(level);
1346     return ret;
1347 }
1348
1349 /**************************************************************************
1350  *                              waveOutRestart  [MMSYSTEM.410]
1351  */
1352 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut16)
1353 {
1354     DWORD       level;
1355     UINT16      ret;
1356
1357     ReleaseThunkLock(&level);
1358     ret = waveOutRestart(HWAVEOUT_32(hWaveOut16));
1359     RestoreThunkLock(level);
1360     return ret;
1361 }
1362
1363 /**************************************************************************
1364  *                              waveOutGetPosition      [MMSYSTEM.412]
1365  */
1366 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
1367                                    UINT16 uSize)
1368 {
1369     UINT        ret;
1370     MMTIME      mmt;
1371
1372     mmt.wType = lpTime->wType;
1373     ret = waveOutGetPosition(HWAVEOUT_32(hWaveOut), &mmt, sizeof(mmt));
1374     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1375     return ret;
1376 }
1377
1378 /**************************************************************************
1379  *                              waveOutGetPitch         [MMSYSTEM.413]
1380  */
1381 UINT16 WINAPI waveOutGetPitch16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1382 {
1383     return waveOutGetPitch(HWAVEOUT_32(hWaveOut16), lpdw);
1384 }
1385
1386 /**************************************************************************
1387  *                              waveOutSetPitch         [MMSYSTEM.414]
1388  */
1389 UINT16 WINAPI waveOutSetPitch16(HWAVEOUT16 hWaveOut16, DWORD dw)
1390 {
1391     return waveOutSetPitch(HWAVEOUT_32(hWaveOut16), dw);
1392 }
1393
1394 /**************************************************************************
1395  *                              waveOutGetPlaybackRate  [MMSYSTEM.417]
1396  */
1397 UINT16 WINAPI waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1398 {
1399     return waveOutGetPlaybackRate(HWAVEOUT_32(hWaveOut16), lpdw);
1400 }
1401
1402 /**************************************************************************
1403  *                              waveOutSetPlaybackRate  [MMSYSTEM.418]
1404  */
1405 UINT16 WINAPI waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16, DWORD dw)
1406 {
1407     return waveOutSetPlaybackRate(HWAVEOUT_32(hWaveOut16), dw);
1408 }
1409
1410 /**************************************************************************
1411  *                              waveOutGetVolume        [MMSYSTEM.415]
1412  */
1413 UINT16 WINAPI waveOutGetVolume16(UINT16 devid, LPDWORD lpdw)
1414 {
1415     return waveOutGetVolume(HWAVEOUT_32(devid), lpdw);
1416 }
1417
1418 /**************************************************************************
1419  *                              waveOutSetVolume        [MMSYSTEM.416]
1420  */
1421 UINT16 WINAPI waveOutSetVolume16(UINT16 devid, DWORD dw)
1422 {
1423     return waveOutSetVolume(HWAVEOUT_32(devid), dw);
1424 }
1425
1426 /**************************************************************************
1427  *                              waveOutGetID            [MMSYSTEM.420]
1428  */
1429 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
1430 {
1431     LPWINE_MLD          wmld;
1432
1433     TRACE("(%04X, %p);\n", hWaveOut, lpuDeviceID);
1434
1435     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
1436
1437     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1438         return MMSYSERR_INVALHANDLE;
1439
1440     *lpuDeviceID = wmld->uDeviceID;
1441     return 0;
1442 }
1443
1444 /**************************************************************************
1445  *                              waveOutMessage          [MMSYSTEM.421]
1446  */
1447 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
1448                               DWORD dwParam1, DWORD dwParam2)
1449 {
1450     LPWINE_MLD          wmld;
1451
1452     TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut, uMessage, dwParam1, dwParam2);
1453
1454     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL) {
1455         if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, TRUE)) != NULL) {
1456             return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1457         }
1458         return MMSYSERR_INVALHANDLE;
1459     }
1460
1461     /* from M$ KB */
1462     if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1463         return MMSYSERR_INVALPARAM;
1464
1465     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1466 }
1467
1468 /**************************************************************************
1469  *                              waveInGetNumDevs                [MMSYSTEM.501]
1470  */
1471 UINT16 WINAPI waveInGetNumDevs16(void)
1472 {
1473     return MMDRV_GetNum(MMDRV_WAVEIN);
1474 }
1475
1476 /**************************************************************************
1477  *                              waveInGetDevCaps                [MMSYSTEM.502]
1478  */
1479 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps,
1480                                  UINT16 uSize)
1481 {
1482     WAVEINCAPSA wicA;
1483     UINT        ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA));
1484
1485     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1486
1487     if (ret == MMSYSERR_NOERROR) {
1488         lpCaps->wMid = wicA.wMid;
1489         lpCaps->wPid = wicA.wPid;
1490         lpCaps->vDriverVersion = wicA.vDriverVersion;
1491         strcpy(lpCaps->szPname, wicA.szPname);
1492         lpCaps->dwFormats = wicA.dwFormats;
1493         lpCaps->wChannels = wicA.wChannels;
1494     }
1495     return ret;
1496 }
1497
1498 /**************************************************************************
1499  *                              waveInGetErrorText      [MMSYSTEM.503]
1500  */
1501 UINT16 WINAPI waveInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1502 {
1503     return waveInGetErrorTextA(uError, lpText, uSize);
1504 }
1505
1506 /**************************************************************************
1507  *                              waveInOpen                      [MMSYSTEM.504]
1508  */
1509 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
1510                            const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
1511                            DWORD dwInstance, DWORD dwFlags)
1512 {
1513     HANDLE              hWaveIn;
1514     UINT                ret;
1515
1516     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1517      * call the 32 bit version
1518      * however, we need to promote correctly the wave mapper id
1519      * (0xFFFFFFFF and not 0x0000FFFF)
1520      */
1521     ret = WAVE_Open(&hWaveIn, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1522                     MMDRV_WAVEIN, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1523
1524     if (lphWaveIn != NULL) *lphWaveIn = HWAVEIN_16(hWaveIn);
1525     return ret;
1526 }
1527
1528 /**************************************************************************
1529  *                              waveInClose                     [MMSYSTEM.505]
1530  */
1531 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
1532 {
1533     DWORD       level;
1534     UINT16      ret;
1535
1536     ReleaseThunkLock(&level);
1537     ret = waveInClose(HWAVEIN_32(hWaveIn));
1538     RestoreThunkLock(level);
1539     return ret;
1540 }
1541
1542 /**************************************************************************
1543  *                              waveInPrepareHeader             [MMSYSTEM.506]
1544  */
1545 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1546                                     SEGPTR lpsegWaveInHdr,   /* [???] */
1547                                     UINT16 uSize)            /* [in] */
1548 {
1549     LPWINE_MLD          wmld;
1550     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1551     UINT16              ret;
1552
1553     TRACE("(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
1554
1555     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
1556     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1557         return MMSYSERR_INVALHANDLE;
1558
1559     lpWaveInHdr->dwBytesRecorded = 0;
1560
1561     ret = MMDRV_Message(wmld, WIDM_PREPARE, (DWORD)lpsegWaveInHdr, uSize, FALSE);
1562     return ret;
1563 }
1564
1565 /**************************************************************************
1566  *                              waveInUnprepareHeader   [MMSYSTEM.507]
1567  */
1568 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1569                                       SEGPTR lpsegWaveInHdr,   /* [???] */
1570                                       UINT16 uSize)            /* [in] */
1571 {
1572     LPWINE_MLD          wmld;
1573     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1574
1575     TRACE("(%04X, %08lx, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1576
1577     if (lpWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1578
1579     if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED)) {
1580         return MMSYSERR_NOERROR;
1581     }
1582
1583     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1584         return MMSYSERR_INVALHANDLE;
1585
1586     return MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD)lpsegWaveInHdr, uSize, FALSE);
1587 }
1588
1589 /**************************************************************************
1590  *                              waveInAddBuffer         [MMSYSTEM.508]
1591  */
1592 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,       /* [in] */
1593                                 WAVEHDR* lpsegWaveInHdr, /* [???] NOTE: SEGPTR */
1594                                 UINT16 uSize)            /* [in] */
1595 {
1596     LPWINE_MLD          wmld;
1597
1598     TRACE("(%04X, %p, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1599
1600     if (lpsegWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1601     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1602         return MMSYSERR_INVALHANDLE;
1603
1604     return MMDRV_Message(wmld, WIDM_ADDBUFFER, (DWORD)lpsegWaveInHdr, uSize, FALSE);
1605 }
1606
1607 /**************************************************************************
1608  *                              waveInReset             [MMSYSTEM.511]
1609  */
1610 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn16)
1611 {
1612     DWORD       level;
1613     UINT16      ret;
1614
1615     ReleaseThunkLock(&level);
1616     ret = waveInReset(HWAVEIN_32(hWaveIn16));
1617     RestoreThunkLock(level);
1618     return ret;
1619 }
1620
1621 /**************************************************************************
1622  *                              waveInStart             [MMSYSTEM.509]
1623  */
1624 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn16)
1625 {
1626     DWORD       level;
1627     UINT16      ret;
1628
1629     ReleaseThunkLock(&level);
1630     ret = waveInStart(HWAVEIN_32(hWaveIn16));
1631     RestoreThunkLock(level);
1632     return ret;
1633 }
1634
1635 /**************************************************************************
1636  *                              waveInStop              [MMSYSTEM.510]
1637  */
1638 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn16)
1639 {
1640     DWORD       level;
1641     UINT16      ret;
1642
1643     ReleaseThunkLock(&level);
1644     ret = waveInStop(HWAVEIN_32(hWaveIn16));
1645     RestoreThunkLock(level);
1646     return ret;
1647 }
1648
1649 /**************************************************************************
1650  *                              waveInGetPosition       [MMSYSTEM.512]
1651  */
1652 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
1653                                   UINT16 uSize)
1654 {
1655     UINT        ret;
1656     MMTIME      mmt;
1657
1658     mmt.wType = lpTime->wType;
1659     ret = waveInGetPosition(HWAVEIN_32(hWaveIn), &mmt, sizeof(mmt));
1660     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1661     return ret;
1662 }
1663
1664 /**************************************************************************
1665  *                              waveInGetID                     [MMSYSTEM.513]
1666  */
1667 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
1668 {
1669     LPWINE_MLD          wmld;
1670
1671     TRACE("(%04X, %p);\n", hWaveIn, lpuDeviceID);
1672
1673     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
1674
1675     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1676         return MMSYSERR_INVALHANDLE;
1677
1678     *lpuDeviceID = wmld->uDeviceID;
1679     return MMSYSERR_NOERROR;
1680 }
1681
1682 /**************************************************************************
1683  *                              waveInMessage           [MMSYSTEM.514]
1684  */
1685 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
1686                              DWORD dwParam1, DWORD dwParam2)
1687 {
1688     LPWINE_MLD          wmld;
1689
1690     TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn, uMessage, dwParam1, dwParam2);
1691
1692     /* from M$ KB */
1693     if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1694         return MMSYSERR_INVALPARAM;
1695
1696     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1697         return MMSYSERR_INVALHANDLE;
1698
1699     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
1700 }
1701
1702 /* ###################################################
1703  * #                     TASK                        #
1704  * ###################################################
1705  */
1706
1707 /*#define USE_MM_TSK_WINE*/
1708
1709 /**************************************************************************
1710  *                              mmTaskCreate            [MMSYSTEM.900]
1711  *
1712  * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
1713  * called upon creation with dwPmt as parameter.
1714  */
1715 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
1716 {
1717     HINSTANCE16         ret;
1718     HINSTANCE16         handle;
1719     char cmdline[16];
1720     DWORD showCmd = 0x40002;
1721     LOADPARAMS16 lp;
1722
1723     TRACE("(%08lx, %p, %08lx);\n", spProc, lphMmTask, dwPmt);
1724     /* This to work requires NE modules to be started with a binary command line
1725      * which is not currently the case. A patch exists but has never been committed.
1726      * A workaround would be to integrate code for mmtask.tsk into Wine, but
1727      * this requires tremendous work (starting with patching tools/build to
1728      * create NE executables (and not only DLLs) for builtins modules.
1729      * EP 99/04/25
1730      */
1731     FIXME("This is currently broken. It will fail\n");
1732
1733     cmdline[0] = 0x0d;
1734     *(LPDWORD)(cmdline + 1) = (DWORD)spProc;
1735     *(LPDWORD)(cmdline + 5) = dwPmt;
1736     *(LPDWORD)(cmdline + 9) = 0;
1737
1738     lp.hEnvironment = 0;
1739     lp.cmdLine = MapLS(cmdline);
1740     lp.showCmd = MapLS(&showCmd);
1741     lp.reserved = 0;
1742
1743 #ifndef USE_MM_TSK_WINE
1744     handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
1745 #else
1746     handle = LoadModule16("mmtask.tsk", &lp);
1747 #endif
1748     if (handle < 32) {
1749         ret = (handle) ? 1 : 2;
1750         handle = 0;
1751     } else {
1752         ret = 0;
1753     }
1754     if (lphMmTask)
1755         *lphMmTask = handle;
1756
1757     UnMapLS( lp.cmdLine );
1758     UnMapLS( lp.showCmd );
1759     TRACE("=> 0x%04x/%d\n", handle, ret);
1760     return ret;
1761 }
1762
1763 #ifdef USE_MM_TSK_WINE
1764 /* C equivalent to mmtask.tsk binary content */
1765 void    mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
1766 {
1767     int len = cmdLine[0x80];
1768
1769     if (len / 2 == 6) {
1770         void    (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
1771         DWORD   dwPmt  = *((DWORD*)(cmdLine + 5));
1772
1773 #if 0
1774         InitTask16(); /* FIXME: pmts / from context ? */
1775         InitApp(di);
1776 #endif
1777         if (SetMessageQueue16(0x40)) {
1778             WaitEvent16(0);
1779             if (HIWORD(fpProc)) {
1780                 OldYield16();
1781 /* EPP          StackEnter16(); */
1782                 (fpProc)(dwPmt);
1783             }
1784         }
1785     }
1786     OldYield16();
1787     OldYield16();
1788     OldYield16();
1789     ExitProcess(0);
1790 }
1791 #endif
1792
1793 /**************************************************************************
1794  *                              mmTaskBlock             [MMSYSTEM.902]
1795  */
1796 void    WINAPI  mmTaskBlock16(HINSTANCE16 WINE_UNUSED hInst)
1797 {
1798     MSG         msg;
1799
1800     do {
1801         GetMessageA(&msg, 0, 0, 0);
1802         if (msg.hwnd) {
1803             TranslateMessage(&msg);
1804             DispatchMessageA(&msg);
1805         }
1806     } while (msg.message < 0x3A0);
1807 }
1808
1809 /**************************************************************************
1810  *                              mmTaskSignal            [MMSYSTEM.903]
1811  */
1812 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
1813 {
1814     TRACE("(%04x);\n", ht);
1815     return PostThreadMessageW( HTASK_32(ht), WM_USER, 0, 0 );
1816 }
1817
1818 /**************************************************************************
1819  *                              mmGetCurrentTask        [MMSYSTEM.904]
1820  */
1821 HTASK16 WINAPI mmGetCurrentTask16(void)
1822 {
1823     return GetCurrentTask();
1824 }
1825
1826 /**************************************************************************
1827  *                              mmTaskYield             [MMSYSTEM.905]
1828  */
1829 void    WINAPI  mmTaskYield16(void)
1830 {
1831     MSG         msg;
1832
1833     if (PeekMessageA(&msg, 0, 0, 0, 0)) {
1834         K32WOWYield16();
1835     }
1836 }
1837
1838 extern DWORD    WINAPI  GetProcessFlags(DWORD);
1839
1840 /******************************************************************
1841  *              WINMM_GetmmThread
1842  *
1843  *
1844  */
1845 static  WINE_MMTHREAD*  WINMM_GetmmThread(HANDLE16 h)
1846 {
1847     return (WINE_MMTHREAD*)MapSL( MAKESEGPTR(h, 0) );
1848 }
1849
1850 void WINAPI WINE_mmThreadEntryPoint(DWORD);
1851
1852 /**************************************************************************
1853  *                              mmThreadCreate          [MMSYSTEM.1120]
1854  *
1855  * undocumented
1856  * Creates a MM thread, calling fpThreadAddr(dwPmt).
1857  * dwFlags:
1858  *      bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
1859  *      bit.1 set means to open a VxD for this thread (unsupported)
1860  */
1861 LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD dwPmt, DWORD dwFlags)
1862 {
1863     HANDLE16            hndl;
1864     LRESULT             ret;
1865
1866     TRACE("(%p, %p, %08lx, %08lx)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
1867
1868     hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
1869
1870     if (hndl == 0) {
1871         ret = 2;
1872     } else {
1873         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1874
1875 #if 0
1876         /* force mmtask routines even if mmthread is required */
1877         /* this will work only if the patch about binary cmd line and NE tasks
1878          * is committed
1879          */
1880         dwFlags |= 1;
1881 #endif
1882
1883         lpMMThd->dwSignature    = WINE_MMTHREAD_CREATED;
1884         lpMMThd->dwCounter      = 0;
1885         lpMMThd->hThread        = 0;
1886         lpMMThd->dwThreadID     = 0;
1887         lpMMThd->fpThread       = fpThreadAddr;
1888         lpMMThd->dwThreadPmt    = dwPmt;
1889         lpMMThd->dwSignalCount  = 0;
1890         lpMMThd->hEvent         = 0;
1891         lpMMThd->hVxD           = 0;
1892         lpMMThd->dwStatus       = 0;
1893         lpMMThd->dwFlags        = dwFlags;
1894         lpMMThd->hTask          = 0;
1895
1896         if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
1897             lpMMThd->hEvent = CreateEventA(0, 0, 1, 0);
1898
1899             TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
1900             if (lpMMThd->dwFlags & 2) {
1901                 /* as long as we don't support MM VxD in wine, we don't need
1902                  * to care about this flag
1903                  */
1904                 /* FIXME("Don't know how to properly open VxD handles\n"); */
1905                 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
1906             }
1907
1908             lpMMThd->hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)WINE_mmThreadEntryPoint,
1909                                             (LPVOID)(DWORD)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
1910             if (lpMMThd->hThread == 0) {
1911                 WARN("Couldn't create thread\n");
1912                 /* clean-up(VxDhandle...); devicedirectio... */
1913                 if (lpMMThd->hEvent != 0)
1914                     CloseHandle(lpMMThd->hEvent);
1915                 ret = 2;
1916             } else {
1917                 TRACE("Got a nice thread hndl=%p id=0x%08lx\n", lpMMThd->hThread, lpMMThd->dwThreadID);
1918                 ret = 0;
1919             }
1920         } else {
1921             /* get WINE_mmThreadEntryPoint()
1922              * 2047 is its ordinal in mmsystem.spec
1923              */
1924             FARPROC16   fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
1925
1926             TRACE("farproc seg=0x%08lx lin=%p\n", (DWORD)fp, MapSL((SEGPTR)fp));
1927
1928             ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
1929         }
1930
1931         if (ret == 0) {
1932             if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
1933                 WARN("Couldn't resume thread\n");
1934
1935             while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
1936                 UserYield16();
1937             }
1938         }
1939     }
1940
1941     if (ret != 0) {
1942         GlobalFree16(hndl);
1943         hndl = 0;
1944     }
1945
1946     if (lpHndl)
1947         *lpHndl = hndl;
1948
1949     TRACE("ok => %ld\n", ret);
1950     return ret;
1951 }
1952
1953 /**************************************************************************
1954  *                              mmThreadSignal          [MMSYSTEM.1121]
1955  */
1956 void WINAPI mmThreadSignal16(HANDLE16 hndl)
1957 {
1958     TRACE("(%04x)!\n", hndl);
1959
1960     if (hndl) {
1961         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1962
1963         lpMMThd->dwCounter++;
1964         if (lpMMThd->hThread != 0) {
1965             InterlockedIncrement(&lpMMThd->dwSignalCount);
1966             SetEvent(lpMMThd->hEvent);
1967         } else {
1968             mmTaskSignal16(lpMMThd->hTask);
1969         }
1970         lpMMThd->dwCounter--;
1971     }
1972 }
1973
1974 static  void    MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
1975 {
1976     MSG         msg;
1977     DWORD       ret;
1978
1979     if (lpMMThd->dwThreadID != GetCurrentThreadId())
1980         ERR("Not called by thread itself\n");
1981
1982     for (;;) {
1983         ResetEvent(lpMMThd->hEvent);
1984         if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
1985             break;
1986         InterlockedIncrement(&lpMMThd->dwSignalCount);
1987
1988         TRACE("S1\n");
1989
1990         ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
1991         switch (ret) {
1992         case WAIT_OBJECT_0:     /* Event */
1993             TRACE("S2.1\n");
1994             break;
1995         case WAIT_OBJECT_0 + 1: /* Msg */
1996             TRACE("S2.2\n");
1997             if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
1998                 TranslateMessage(&msg);
1999                 DispatchMessageA(&msg);
2000             }
2001             break;
2002         default:
2003             WARN("S2.x unsupported ret val 0x%08lx\n", ret);
2004         }
2005         TRACE("S3\n");
2006     }
2007 }
2008
2009 /**************************************************************************
2010  *                              mmThreadBlock           [MMSYSTEM.1122]
2011  */
2012 void    WINAPI mmThreadBlock16(HANDLE16 hndl)
2013 {
2014     TRACE("(%04x)!\n", hndl);
2015
2016     if (hndl) {
2017         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2018
2019         if (lpMMThd->hThread != 0) {
2020             DWORD       lc;
2021
2022             ReleaseThunkLock(&lc);
2023             MMSYSTEM_ThreadBlock(lpMMThd);
2024             RestoreThunkLock(lc);
2025         } else {
2026             mmTaskBlock16(lpMMThd->hTask);
2027         }
2028     }
2029     TRACE("done\n");
2030 }
2031
2032 /**************************************************************************
2033  *                              mmThreadIsCurrent       [MMSYSTEM.1123]
2034  */
2035 BOOL16  WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
2036 {
2037     BOOL16              ret = FALSE;
2038
2039     TRACE("(%04x)!\n", hndl);
2040
2041     if (hndl && mmThreadIsValid16(hndl)) {
2042         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2043         ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
2044     }
2045     TRACE("=> %d\n", ret);
2046     return ret;
2047 }
2048
2049 /**************************************************************************
2050  *                              mmThreadIsValid         [MMSYSTEM.1124]
2051  */
2052 BOOL16  WINAPI  mmThreadIsValid16(HANDLE16 hndl)
2053 {
2054     BOOL16              ret = FALSE;
2055
2056     TRACE("(%04x)!\n", hndl);
2057
2058     if (hndl) {
2059         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2060
2061         if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
2062             lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
2063             IsTask16(lpMMThd->hTask)) {
2064             lpMMThd->dwCounter++;
2065             if (lpMMThd->hThread != 0) {
2066                 DWORD   dwThreadRet;
2067                 if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
2068                     dwThreadRet == STATUS_PENDING) {
2069                     ret = TRUE;
2070                 }
2071             } else {
2072                 ret = TRUE;
2073             }
2074             lpMMThd->dwCounter--;
2075         }
2076     }
2077     TRACE("=> %d\n", ret);
2078     return ret;
2079 }
2080
2081 /**************************************************************************
2082  *                              mmThreadGetTask         [MMSYSTEM.1125]
2083  */
2084 HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
2085 {
2086     HANDLE16    ret = 0;
2087
2088     TRACE("(%04x)\n", hndl);
2089
2090     if (mmThreadIsValid16(hndl)) {
2091         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2092         ret = lpMMThd->hTask;
2093     }
2094     return ret;
2095 }
2096
2097 /**************************************************************************
2098  *                              __wine_mmThreadEntryPoint (MMSYSTEM.2047)
2099  */
2100 void WINAPI WINE_mmThreadEntryPoint(DWORD _pmt)
2101 {
2102     HANDLE16            hndl = (HANDLE16)_pmt;
2103     WINE_MMTHREAD*      lpMMThd = WINMM_GetmmThread(hndl);
2104
2105     TRACE("(%04x %p)\n", hndl, lpMMThd);
2106
2107     lpMMThd->hTask = LOWORD(GetCurrentTask());
2108     TRACE("[10-%p] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
2109     lpMMThd->dwStatus = 0x10;
2110     MMSYSTEM_ThreadBlock(lpMMThd);
2111     TRACE("[20-%p]\n", lpMMThd->hThread);
2112     lpMMThd->dwStatus = 0x20;
2113     if (lpMMThd->fpThread) {
2114         WOWCallback16((DWORD)lpMMThd->fpThread, lpMMThd->dwThreadPmt);
2115     }
2116     lpMMThd->dwStatus = 0x30;
2117     TRACE("[30-%p]\n", lpMMThd->hThread);
2118     while (lpMMThd->dwCounter) {
2119         Sleep(1);
2120         /* K32WOWYield16();*/
2121     }
2122     TRACE("[XX-%p]\n", lpMMThd->hThread);
2123     /* paranoia */
2124     lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
2125     /* close lpMMThread->hVxD directIO */
2126     if (lpMMThd->hEvent)
2127         CloseHandle(lpMMThd->hEvent);
2128     GlobalFree16(hndl);
2129     TRACE("done\n");
2130 }
2131
2132 typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
2133
2134 /**************************************************************************
2135  *                      mmShowMMCPLPropertySheet        [MMSYSTEM.1150]
2136  */
2137 BOOL16  WINAPI  mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
2138                                            LPCSTR lpStrTab, LPCSTR lpStrTitle)
2139 {
2140     HANDLE      hndl;
2141     BOOL16      ret = FALSE;
2142
2143     TRACE("(%p \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2144
2145     hndl = LoadLibraryA("MMSYS.CPL");
2146     if (hndl != 0) {
2147         MMCPLCALLBACK   fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
2148         if (fp != NULL) {
2149             DWORD       lc;
2150             ReleaseThunkLock(&lc);
2151             ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2152             RestoreThunkLock(lc);
2153         }
2154         FreeLibrary(hndl);
2155     }
2156
2157     return ret;
2158 }
2159
2160 /**************************************************************************
2161  *                      StackEnter              [MMSYSTEM.32]
2162  */
2163 void WINAPI StackEnter16(void)
2164 {
2165 #ifdef __i386__
2166     /* mmsystem.dll from Win 95 does only this: so does Wine */
2167     __asm__("stc");
2168 #endif
2169 }
2170
2171 /**************************************************************************
2172  *                      StackLeave              [MMSYSTEM.33]
2173  */
2174 void WINAPI StackLeave16(void)
2175 {
2176 #ifdef __i386__
2177     /* mmsystem.dll from Win 95 does only this: so does Wine */
2178     __asm__("stc");
2179 #endif
2180 }
2181
2182 /**************************************************************************
2183  *                      WMMMidiRunOnce          [MMSYSTEM.8]
2184  */
2185 void WINAPI WMMMidiRunOnce16(void)
2186 {
2187     FIXME("(), stub!\n");
2188 }
2189
2190 /* ###################################################
2191  * #                    DRIVER                       #
2192  * ###################################################
2193  */
2194
2195 /**************************************************************************
2196  *                              DRIVER_MapMsg32To16             [internal]
2197  *
2198  * Map a 32 bit driver message to a 16 bit driver message.
2199  */
2200 static WINMM_MapType DRIVER_MapMsg32To16(WORD wMsg, DWORD* lParam1, DWORD* lParam2)
2201 {
2202     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
2203
2204     switch (wMsg) {
2205     case DRV_LOAD:
2206     case DRV_ENABLE:
2207     case DRV_DISABLE:
2208     case DRV_FREE:
2209     case DRV_QUERYCONFIGURE:
2210     case DRV_REMOVE:
2211     case DRV_EXITSESSION:
2212     case DRV_EXITAPPLICATION:
2213     case DRV_POWER:
2214     case DRV_CLOSE:     /* should be 0/0 */
2215     case DRV_OPEN:      /* pass through */
2216         /* lParam1 and lParam2 are not used */
2217         ret = WINMM_MAP_OK;
2218         break;
2219     case DRV_CONFIGURE:
2220     case DRV_INSTALL:
2221         /* lParam1 is a handle to a window (conf) or to a driver (inst) or not used,
2222          * lParam2 is a pointer to DRVCONFIGINFO
2223          */
2224         if (*lParam2) {
2225             LPDRVCONFIGINFO16 dci16 = HeapAlloc( GetProcessHeap(), 0, sizeof(*dci16) );
2226             LPDRVCONFIGINFO     dci32 = (LPDRVCONFIGINFO)(*lParam2);
2227
2228             if (dci16) {
2229                 LPSTR str1;
2230
2231                 dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
2232
2233                 if ((str1 = HEAP_strdupWtoA(GetProcessHeap(), 0, dci32->lpszDCISectionName)) != NULL)
2234                 {
2235                     dci16->lpszDCISectionName = MapLS( str1 );
2236                 } else {
2237                     return WINMM_MAP_NOMEM;
2238                 }
2239                 if ((str1 = HEAP_strdupWtoA(GetProcessHeap(), 0, dci32->lpszDCIAliasName)) != NULL)
2240                 {
2241                     dci16->lpszDCIAliasName = MapLS( str1 );
2242                 } else {
2243                     return WINMM_MAP_NOMEM;
2244                 }
2245             } else {
2246                 return WINMM_MAP_NOMEM;
2247             }
2248             *lParam2 = MapLS( dci16 );
2249             ret = WINMM_MAP_OKMEM;
2250         } else {
2251             ret = WINMM_MAP_OK;
2252         }
2253         break;
2254     default:
2255         if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2256            FIXME("Unknown message 0x%04x\n", wMsg);
2257         }
2258         ret = WINMM_MAP_OK;
2259     }
2260     return ret;
2261 }
2262
2263 /**************************************************************************
2264  *                              DRIVER_UnMapMsg32To16           [internal]
2265  *
2266  * UnMap a 32 bit driver message to a 16 bit driver message.
2267  */
2268 static WINMM_MapType DRIVER_UnMapMsg32To16(WORD wMsg, DWORD lParam1, DWORD lParam2)
2269 {
2270     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
2271
2272     switch (wMsg) {
2273     case DRV_LOAD:
2274     case DRV_ENABLE:
2275     case DRV_DISABLE:
2276     case DRV_FREE:
2277     case DRV_QUERYCONFIGURE:
2278     case DRV_REMOVE:
2279     case DRV_EXITSESSION:
2280     case DRV_EXITAPPLICATION:
2281     case DRV_POWER:
2282     case DRV_OPEN:
2283     case DRV_CLOSE:
2284         /* lParam1 and lParam2 are not used */
2285         break;
2286     case DRV_CONFIGURE:
2287     case DRV_INSTALL:
2288         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
2289         if (lParam2) {
2290             LPDRVCONFIGINFO16   dci16 = MapSL(lParam2);
2291             HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCISectionName) );
2292             HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCIAliasName) );
2293             UnMapLS( lParam2 );
2294             UnMapLS( dci16->lpszDCISectionName );
2295             UnMapLS( dci16->lpszDCIAliasName );
2296             HeapFree( GetProcessHeap(), 0, dci16 );
2297         }
2298         ret = WINMM_MAP_OK;
2299         break;
2300     default:
2301         if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2302             FIXME("Unknown message 0x%04x\n", wMsg);
2303         }
2304         ret = WINMM_MAP_OK;
2305     }
2306     return ret;
2307 }
2308
2309 /**************************************************************************
2310  *                              DRIVER_TryOpenDriver16          [internal]
2311  *
2312  * Tries to load a 16 bit driver whose DLL's (module) name is lpFileName.
2313  */
2314 static  LPWINE_DRIVER   DRIVER_OpenDriver16(LPCSTR fn, LPCSTR sn, LPARAM lParam2)
2315 {
2316     LPWINE_DRIVER       lpDrv = NULL;
2317     LPCSTR              cause = 0;
2318
2319     TRACE("(%s, %08lX);\n", debugstr_a(sn), lParam2);
2320
2321     lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
2322     if (lpDrv == NULL) {cause = "OOM"; goto exit;}
2323
2324     /* FIXME: shall we do some black magic here on sn ?
2325      *  drivers32 => drivers
2326      *  mci32 => mci
2327      * ...
2328      */
2329     lpDrv->d.d16.hDriver16 = OpenDriver16(fn, sn, lParam2);
2330     if (lpDrv->d.d16.hDriver16 == 0) {cause = "Not a 16 bit driver"; goto exit;}
2331     lpDrv->dwFlags = WINE_GDF_16BIT;
2332
2333     TRACE("=> %p\n", lpDrv);
2334     return lpDrv;
2335  exit:
2336     HeapFree(GetProcessHeap(), 0, lpDrv);
2337     TRACE("Unable to load 16 bit module %s: %s\n", debugstr_a(fn), cause);
2338     return NULL;
2339 }
2340
2341 /******************************************************************
2342  *              DRIVER_SendMessage16
2343  *
2344  *
2345  */
2346 static LRESULT  DRIVER_SendMessage16(HDRVR16 hDrv16, UINT msg, 
2347                                      LPARAM lParam1, LPARAM lParam2)
2348 {
2349     LRESULT             ret = 0;
2350     WINMM_MapType       map;
2351
2352     TRACE("Before sdm16 call hDrv=%04x wMsg=%04x p1=%08lx p2=%08lx\n",
2353           hDrv16, msg, lParam1, lParam2);
2354
2355     switch (map = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2)) {
2356     case WINMM_MAP_OKMEM:
2357     case WINMM_MAP_OK:
2358         ret = SendDriverMessage16(hDrv16, msg, lParam1, lParam2);
2359         if (map == WINMM_MAP_OKMEM)
2360             DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
2361     default:
2362         break;
2363     }
2364     return ret;
2365 }
2366
2367 /******************************************************************
2368  *              DRIVER_CloseDriver16
2369  *
2370  *
2371  */
2372 static LRESULT DRIVER_CloseDriver16(HDRVR16 hDrv16, LPARAM lParam1, LPARAM lParam2)
2373 {
2374     return CloseDriver16(hDrv16, lParam1, lParam2);
2375 }
2376
2377 /**************************************************************************
2378  *                              DrvOpen                 [MMSYSTEM.1100]
2379  */
2380 HDRVR16 WINAPI DrvOpen16(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
2381 {
2382     return OpenDriver16(lpDriverName, lpSectionName, lParam);
2383 }
2384
2385 /**************************************************************************
2386  *                              DrvClose                [MMSYSTEM.1101]
2387  */
2388 LRESULT WINAPI DrvClose16(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
2389 {
2390     return CloseDriver16(hDrv, lParam1, lParam2);
2391 }
2392
2393 /**************************************************************************
2394  *                              DrvSendMessage          [MMSYSTEM.1102]
2395  */
2396 LRESULT WINAPI DrvSendMessage16(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
2397                                 LPARAM lParam2)
2398 {
2399     return SendDriverMessage16(hDrv, msg, lParam1, lParam2);
2400 }
2401
2402 /**************************************************************************
2403  *                              DrvGetModuleHandle      [MMSYSTEM.1103]
2404  */
2405 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
2406 {
2407     return GetDriverModuleHandle16(hDrv);
2408 }
2409
2410 /**************************************************************************
2411  *                              DrvDefDriverProc        [MMSYSTEM.1104]
2412  */
2413 LRESULT WINAPI DrvDefDriverProc16(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
2414                                   DWORD dwParam1, DWORD dwParam2)
2415 {
2416     return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
2417 }
2418
2419 /**************************************************************************
2420  *                              DriverProc                      [MMSYSTEM.6]
2421  */
2422 LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
2423                             DWORD dwParam1, DWORD dwParam2)
2424 {
2425     TRACE("dwDevID=%08lx hDrv=%04x wMsg=%04x dwParam1=%08lx dwParam2=%08lx\n",
2426           dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2427
2428     return DrvDefDriverProc16(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2429 }
2430
2431 /* ###################################################
2432  * #                     TIME                        #
2433  * ###################################################
2434  */
2435
2436 /******************************************************************
2437  *              MMSYSTEM_MMTIME32to16
2438  *
2439  *
2440  */
2441 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16, const MMTIME* mmt32)
2442 {
2443     mmt16->wType = mmt32->wType;
2444     /* layout of rest is the same for 32/16,
2445      * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2446      */
2447     memcpy(&(mmt16->u), &(mmt32->u), sizeof(mmt16->u));
2448 }
2449
2450 /******************************************************************
2451  *              MMSYSTEM_MMTIME16to32
2452  *
2453  *
2454  */
2455 void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32, const MMTIME16* mmt16)
2456 {
2457     mmt32->wType = mmt16->wType;
2458     /* layout of rest is the same for 32/16,
2459      * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2460      */
2461     memcpy(&(mmt32->u), &(mmt16->u), sizeof(mmt16->u));
2462 }
2463
2464 /**************************************************************************
2465  *                              timeGetSystemTime       [MMSYSTEM.601]
2466  */
2467 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
2468 {
2469     TRACE("(%p, %u);\n", lpTime, wSize);
2470
2471     if (wSize >= sizeof(*lpTime)) {
2472         lpTime->wType = TIME_MS;
2473         TIME_MMTimeStart();
2474         lpTime->u.ms = WINMM_IData->mmSysTimeMS;
2475
2476         TRACE("=> %lu\n", lpTime->u.ms);
2477     }
2478
2479     return 0;
2480 }
2481
2482 /**************************************************************************
2483  *                              timeSetEvent            [MMSYSTEM.602]
2484  */
2485 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol, LPTIMECALLBACK16 lpFunc,
2486                                  DWORD dwUser, UINT16 wFlags)
2487 {
2488     if (wFlags & WINE_TIMER_IS32)
2489         WARN("Unknown windows flag... wine internally used.. ooch\n");
2490
2491     return TIME_SetEventInternal(wDelay, wResol, (FARPROC16)lpFunc,
2492                                  dwUser, wFlags & ~WINE_TIMER_IS32);
2493 }
2494
2495 /**************************************************************************
2496  *                              timeKillEvent           [MMSYSTEM.603]
2497  */
2498 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
2499 {
2500     return timeKillEvent(wID);
2501 }
2502
2503 /**************************************************************************
2504  *                              timeGetDevCaps          [MMSYSTEM.604]
2505  */
2506 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
2507 {
2508     TIMECAPS    caps;
2509     MMRESULT    ret;
2510
2511     TRACE("(%p, %u) !\n", lpCaps, wSize);
2512
2513     ret = timeGetDevCaps(&caps, sizeof(caps));
2514     lpCaps->wPeriodMin = caps.wPeriodMin;
2515     lpCaps->wPeriodMax = caps.wPeriodMax;
2516     return 0;
2517 }
2518
2519 /**************************************************************************
2520  *                              timeBeginPeriod [MMSYSTEM.605]
2521  */
2522 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
2523 {
2524     TRACE("(%u) !\n", wPeriod);
2525
2526     return timeBeginPeriod(wPeriod);
2527 }
2528
2529 /**************************************************************************
2530  *                              timeEndPeriod           [MMSYSTEM.606]
2531  */
2532 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
2533 {
2534     TRACE("(%u) !\n", wPeriod);
2535
2536     return timeEndPeriod(wPeriod);
2537 }
2538
2539 /**************************************************************************
2540  *                              mciSendString                   [MMSYSTEM.702]
2541  */
2542 DWORD WINAPI mciSendString16(LPCSTR lpstrCommand, LPSTR lpstrRet,
2543                              UINT16 uRetLen, HWND16 hwndCallback)
2544 {
2545     return mciSendStringA(lpstrCommand, lpstrRet, uRetLen, HWND_32(hwndCallback));
2546 }
2547
2548 /**************************************************************************
2549  *                      mciLoadCommandResource                  [MMSYSTEM.705]
2550  */
2551 UINT16 WINAPI mciLoadCommandResource16(HINSTANCE16 hInst, LPCSTR resname, UINT16 type)
2552 {
2553     UNICODE_STRING ptr;
2554     UINT          ret;
2555     RtlCreateUnicodeStringFromAsciiz(&ptr, resname);
2556     ret = mciLoadCommandResource(HINSTANCE_32(hInst), ptr.Buffer, type);
2557     RtlFreeUnicodeString(&ptr);
2558     return ret;
2559 }
2560
2561 /**************************************************************************
2562  *                      mciFreeCommandResource                  [MMSYSTEM.713]
2563  */
2564 BOOL16 WINAPI mciFreeCommandResource16(UINT16 uTable)
2565 {
2566     TRACE("(%04x)!\n", uTable);
2567
2568     return mciFreeCommandResource(uTable);
2569 }
2570
2571 /* ###################################################
2572  * #                     MMIO                        #
2573  * ###################################################
2574  */
2575
2576 /****************************************************************
2577  *                      MMIO_Map32To16                  [INTERNAL]
2578  */
2579 static LRESULT  MMIO_Map32To16(DWORD wMsg, LPARAM* lp1, LPARAM* lp2)
2580 {
2581     switch (wMsg) {
2582     case MMIOM_CLOSE:
2583     case MMIOM_SEEK:
2584         /* nothing to do */
2585         break;
2586     case MMIOM_OPEN:
2587     case MMIOM_READ:
2588     case MMIOM_WRITE:
2589     case MMIOM_WRITEFLUSH:
2590         *lp1 = MapLS( (void *)*lp1 );
2591         break;
2592     case MMIOM_RENAME:
2593         *lp1 = MapLS( (void *)*lp1 );
2594         *lp2 = MapLS( (void *)*lp2 );
2595         break;
2596     default:
2597         if (wMsg < MMIOM_USER)
2598             TRACE("Not a mappable message (%ld)\n", wMsg);
2599     }
2600     return MMSYSERR_NOERROR;
2601 }
2602
2603 /****************************************************************
2604  *              MMIO_UnMap32To16                        [INTERNAL]
2605  */
2606 static LRESULT  MMIO_UnMap32To16(DWORD wMsg, LPARAM lParam1, LPARAM lParam2,
2607                                  LPARAM lp1, LPARAM lp2)
2608 {
2609     switch (wMsg) {
2610     case MMIOM_CLOSE:
2611     case MMIOM_SEEK:
2612         /* nothing to do */
2613         break;
2614     case MMIOM_OPEN:
2615     case MMIOM_READ:
2616     case MMIOM_WRITE:
2617     case MMIOM_WRITEFLUSH:
2618         UnMapLS( lp1 );
2619         break;
2620     case MMIOM_RENAME:
2621         UnMapLS( lp1 );
2622         UnMapLS( lp2 );
2623         break;
2624     default:
2625         if (wMsg < MMIOM_USER)
2626             TRACE("Not a mappable message (%ld)\n", wMsg);
2627     }
2628     return MMSYSERR_NOERROR;
2629 }
2630
2631 /******************************************************************
2632  *              MMIO_Callback16
2633  *
2634  *
2635  */
2636 static LRESULT MMIO_Callback16(SEGPTR cb16, LPMMIOINFO lpmmioinfo, UINT uMessage,
2637                                LPARAM lParam1, LPARAM lParam2)
2638 {
2639     LRESULT             result;
2640     MMIOINFO16          mmioInfo16;
2641     SEGPTR              segmmioInfo16;
2642     LPARAM              lp1 = lParam1, lp2 = lParam2;
2643     WORD args[7];
2644
2645     memset(&mmioInfo16, 0, sizeof(MMIOINFO16));
2646     mmioInfo16.lDiskOffset = lpmmioinfo->lDiskOffset;
2647     mmioInfo16.adwInfo[0]  = lpmmioinfo->adwInfo[0];
2648     mmioInfo16.adwInfo[1]  = lpmmioinfo->adwInfo[1];
2649     mmioInfo16.adwInfo[2]  = lpmmioinfo->adwInfo[2];
2650     mmioInfo16.adwInfo[3]  = lpmmioinfo->adwInfo[3];
2651     /* map (lParam1, lParam2) into (lp1, lp2) 32=>16 */
2652     if ((result = MMIO_Map32To16(uMessage, &lp1, &lp2)) != MMSYSERR_NOERROR)
2653         return result;
2654
2655     segmmioInfo16 = MapLS(&mmioInfo16);
2656     args[6] = HIWORD(segmmioInfo16);
2657     args[5] = LOWORD(segmmioInfo16);
2658     args[4] = uMessage;
2659     args[3] = HIWORD(lp1);
2660     args[2] = LOWORD(lp1);
2661     args[1] = HIWORD(lp2);
2662     args[0] = LOWORD(lp2);
2663     WOWCallback16Ex( cb16, WCB16_PASCAL, sizeof(args), args, &result );
2664     UnMapLS(segmmioInfo16);
2665     MMIO_UnMap32To16(uMessage, lParam1, lParam2, lp1, lp2);
2666
2667     lpmmioinfo->lDiskOffset = mmioInfo16.lDiskOffset;
2668     lpmmioinfo->adwInfo[0]  = mmioInfo16.adwInfo[0];
2669     lpmmioinfo->adwInfo[1]  = mmioInfo16.adwInfo[1];
2670     lpmmioinfo->adwInfo[2]  = mmioInfo16.adwInfo[2];
2671     lpmmioinfo->adwInfo[3]  = mmioInfo16.adwInfo[3];
2672
2673     return result;
2674 }
2675
2676 /******************************************************************
2677  *             MMIO_ResetSegmentedData
2678  *
2679  */
2680 static LRESULT     MMIO_SetSegmentedBuffer(HMMIO hmmio, SEGPTR ptr)
2681 {
2682     LPWINE_MMIO         wm;
2683
2684     if ((wm = MMIO_Get(hmmio)) == NULL)
2685         return MMSYSERR_INVALHANDLE;
2686     wm->segBuffer16 = ptr;
2687     return MMSYSERR_NOERROR;
2688 }
2689
2690 /**************************************************************************
2691  *                              mmioOpen                [MMSYSTEM.1210]
2692  */
2693 HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16* lpmmioinfo16,
2694                           DWORD dwOpenFlags)
2695 {
2696     HMMIO       ret;
2697
2698     if (lpmmioinfo16) {
2699         MMIOINFO        mmioinfo;
2700
2701         memset(&mmioinfo, 0, sizeof(mmioinfo));
2702
2703         mmioinfo.dwFlags     = lpmmioinfo16->dwFlags;
2704         mmioinfo.fccIOProc   = lpmmioinfo16->fccIOProc;
2705         mmioinfo.pIOProc     = (LPMMIOPROC)lpmmioinfo16->pIOProc;
2706         mmioinfo.cchBuffer   = lpmmioinfo16->cchBuffer;
2707         mmioinfo.pchBuffer   = MapSL((DWORD)lpmmioinfo16->pchBuffer);
2708         mmioinfo.adwInfo[0]  = lpmmioinfo16->adwInfo[0];
2709         /* if we don't have a file name, it's likely a passed open file descriptor */
2710         if (!szFileName) 
2711             mmioinfo.adwInfo[0] = (DWORD)DosFileHandleToWin32Handle(mmioinfo.adwInfo[0]);
2712         mmioinfo.adwInfo[1]  = lpmmioinfo16->adwInfo[1];
2713         mmioinfo.adwInfo[2]  = lpmmioinfo16->adwInfo[2];
2714         mmioinfo.adwInfo[3]  = lpmmioinfo16->adwInfo[3];
2715
2716         ret = MMIO_Open(szFileName, &mmioinfo, dwOpenFlags, MMIO_PROC_16);
2717         MMIO_SetSegmentedBuffer(mmioinfo.hmmio, (SEGPTR)lpmmioinfo16->pchBuffer);
2718
2719         lpmmioinfo16->wErrorRet = mmioinfo.wErrorRet;
2720         lpmmioinfo16->hmmio     = HMMIO_16(mmioinfo.hmmio);
2721     } else {
2722         ret = MMIO_Open(szFileName, NULL, dwOpenFlags, MMIO_PROC_32A);
2723     }
2724     return HMMIO_16(ret);
2725 }
2726
2727 /**************************************************************************
2728  *                              mmioClose               [MMSYSTEM.1211]
2729  */
2730 MMRESULT16 WINAPI mmioClose16(HMMIO16 hmmio, UINT16 uFlags)
2731 {
2732     return mmioClose(HMMIO_32(hmmio), uFlags);
2733 }
2734
2735 /**************************************************************************
2736  *                              mmioRead                [MMSYSTEM.1212]
2737  */
2738 LONG WINAPI mmioRead16(HMMIO16 hmmio, HPSTR pch, LONG cch)
2739 {
2740     return mmioRead(HMMIO_32(hmmio), pch, cch);
2741 }
2742
2743 /**************************************************************************
2744  *                              mmioWrite               [MMSYSTEM.1213]
2745  */
2746 LONG WINAPI mmioWrite16(HMMIO16 hmmio, HPCSTR pch, LONG cch)
2747 {
2748     return mmioWrite(HMMIO_32(hmmio),pch,cch);
2749 }
2750
2751 /**************************************************************************
2752  *                              mmioSeek                [MMSYSTEM.1214]
2753  */
2754 LONG WINAPI mmioSeek16(HMMIO16 hmmio, LONG lOffset, INT16 iOrigin)
2755 {
2756     return mmioSeek(HMMIO_32(hmmio), lOffset, iOrigin);
2757 }
2758
2759 /**************************************************************************
2760  *                              mmioGetInfo             [MMSYSTEM.1215]
2761  */
2762 MMRESULT16 WINAPI mmioGetInfo16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags)
2763 {
2764     MMIOINFO            mmioinfo;
2765     MMRESULT            ret;
2766     LPWINE_MMIO         wm;
2767
2768     TRACE("(0x%04x,%p,0x%08x)\n", hmmio, lpmmioinfo, uFlags);
2769
2770     if ((wm = MMIO_Get(HMMIO_32(hmmio))) == NULL)
2771         return MMSYSERR_INVALHANDLE;
2772
2773     ret = mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, uFlags);
2774     if (ret != MMSYSERR_NOERROR) return ret;
2775
2776     lpmmioinfo->dwFlags     = mmioinfo.dwFlags;
2777     lpmmioinfo->fccIOProc   = mmioinfo.fccIOProc;
2778     lpmmioinfo->pIOProc     = (wm->ioProc->type == MMIO_PROC_16) ?
2779         (LPMMIOPROC16)wm->ioProc->pIOProc : NULL;
2780     lpmmioinfo->wErrorRet   = mmioinfo.wErrorRet;
2781     lpmmioinfo->hTask       = HTASK_16(mmioinfo.hTask);
2782     lpmmioinfo->cchBuffer   = mmioinfo.cchBuffer;
2783     lpmmioinfo->pchBuffer   = (void*)wm->segBuffer16;
2784     lpmmioinfo->pchNext     = (void*)(wm->segBuffer16 + (mmioinfo.pchNext - mmioinfo.pchBuffer));
2785     lpmmioinfo->pchEndRead  = (void*)(wm->segBuffer16 + (mmioinfo.pchEndRead - mmioinfo.pchBuffer));
2786     lpmmioinfo->pchEndWrite = (void*)(wm->segBuffer16 + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer));
2787     lpmmioinfo->lBufOffset  = mmioinfo.lBufOffset;
2788     lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset;
2789     lpmmioinfo->adwInfo[0]  = mmioinfo.adwInfo[0];
2790     lpmmioinfo->adwInfo[1]  = mmioinfo.adwInfo[1];
2791     lpmmioinfo->adwInfo[2]  = mmioinfo.adwInfo[2];
2792     lpmmioinfo->adwInfo[3]  = mmioinfo.adwInfo[3];
2793     lpmmioinfo->dwReserved1 = 0;
2794     lpmmioinfo->dwReserved2 = 0;
2795     lpmmioinfo->hmmio = HMMIO_16(mmioinfo.hmmio);
2796
2797     return MMSYSERR_NOERROR;
2798 }
2799
2800 /**************************************************************************
2801  *                              mmioSetInfo             [MMSYSTEM.1216]
2802  */
2803 MMRESULT16 WINAPI mmioSetInfo16(HMMIO16 hmmio, const MMIOINFO16* lpmmioinfo, UINT16 uFlags)
2804 {
2805     MMIOINFO            mmioinfo;
2806     MMRESULT            ret;
2807
2808     TRACE("(0x%04x,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
2809
2810     ret = mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, 0);
2811     if (ret != MMSYSERR_NOERROR) return ret;
2812
2813     /* check if seg and lin buffers are the same */
2814     if (mmioinfo.cchBuffer != lpmmioinfo->cchBuffer  ||
2815         mmioinfo.pchBuffer != MapSL((DWORD)lpmmioinfo->pchBuffer)) 
2816         return MMSYSERR_INVALPARAM;
2817
2818     /* check pointers coherence */
2819     if (lpmmioinfo->pchNext < lpmmioinfo->pchBuffer ||
2820         lpmmioinfo->pchNext > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer ||
2821         lpmmioinfo->pchEndRead < lpmmioinfo->pchBuffer ||
2822         lpmmioinfo->pchEndRead > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer ||
2823         lpmmioinfo->pchEndWrite < lpmmioinfo->pchBuffer ||
2824         lpmmioinfo->pchEndWrite > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer)
2825         return MMSYSERR_INVALPARAM;
2826
2827     mmioinfo.pchNext     = mmioinfo.pchBuffer + (lpmmioinfo->pchNext     - lpmmioinfo->pchBuffer);
2828     mmioinfo.pchEndRead  = mmioinfo.pchBuffer + (lpmmioinfo->pchEndRead  - lpmmioinfo->pchBuffer);
2829     mmioinfo.pchEndWrite = mmioinfo.pchBuffer + (lpmmioinfo->pchEndWrite - lpmmioinfo->pchBuffer);
2830
2831     return mmioSetInfo(HMMIO_32(hmmio), &mmioinfo, uFlags);
2832 }
2833
2834 /**************************************************************************
2835  *                              mmioSetBuffer           [MMSYSTEM.1217]
2836  */
2837 MMRESULT16 WINAPI mmioSetBuffer16(HMMIO16 hmmio, LPSTR pchBuffer,
2838                                   LONG cchBuffer, UINT16 uFlags)
2839 {
2840     MMRESULT    ret = mmioSetBuffer(HMMIO_32(hmmio), MapSL((DWORD)pchBuffer), 
2841                                     cchBuffer, uFlags);
2842
2843     if (ret == MMSYSERR_NOERROR)
2844         MMIO_SetSegmentedBuffer(HMMIO_32(hmmio), (DWORD)pchBuffer);
2845     return ret;
2846 }
2847
2848 /**************************************************************************
2849  *                              mmioFlush               [MMSYSTEM.1218]
2850  */
2851 MMRESULT16 WINAPI mmioFlush16(HMMIO16 hmmio, UINT16 uFlags)
2852 {
2853     return mmioFlush(HMMIO_32(hmmio), uFlags);
2854 }
2855
2856 /***********************************************************************
2857  *                              mmioAdvance             [MMSYSTEM.1219]
2858  */
2859 MMRESULT16 WINAPI mmioAdvance16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags)
2860 {
2861     MMIOINFO    mmioinfo;
2862     LRESULT     ret;
2863
2864     /* WARNING: this heavily relies on mmioAdvance implementation (for choosing which
2865      * fields to init
2866      */
2867     if (lpmmioinfo)
2868     {
2869         mmioinfo.pchBuffer = MapSL((DWORD)lpmmioinfo->pchBuffer);
2870         mmioinfo.pchNext = MapSL((DWORD)lpmmioinfo->pchNext);
2871         mmioinfo.dwFlags = lpmmioinfo->dwFlags;
2872         mmioinfo.lBufOffset = lpmmioinfo->lBufOffset;
2873         ret = mmioAdvance(HMMIO_32(hmmio), &mmioinfo, uFlags);
2874     }
2875     else
2876         ret = mmioAdvance(HMMIO_32(hmmio), NULL, uFlags);
2877         
2878     if (ret != MMSYSERR_NOERROR) return ret;
2879
2880     if (lpmmioinfo)
2881     {
2882         lpmmioinfo->dwFlags = mmioinfo.dwFlags;
2883         lpmmioinfo->pchNext     = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchNext - mmioinfo.pchBuffer));
2884         lpmmioinfo->pchEndRead  = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndRead - mmioinfo.pchBuffer));
2885         lpmmioinfo->pchEndWrite = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer));
2886         lpmmioinfo->lBufOffset  = mmioinfo.lBufOffset;
2887         lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset;
2888     }
2889
2890     return MMSYSERR_NOERROR;
2891 }
2892
2893 /**************************************************************************
2894  *                              mmioStringToFOURCC      [MMSYSTEM.1220]
2895  */
2896 FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
2897 {
2898     return mmioStringToFOURCCA(sz, uFlags);
2899 }
2900
2901 /**************************************************************************
2902  *              mmioInstallIOProc    [MMSYSTEM.1221]
2903  */
2904 LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc, LPMMIOPROC16 pIOProc,
2905                                         DWORD dwFlags)
2906 {
2907     return (LPMMIOPROC16)MMIO_InstallIOProc(fccIOProc, (LPMMIOPROC)pIOProc,
2908                                             dwFlags, MMIO_PROC_16);
2909 }
2910
2911 /**************************************************************************
2912  *                              mmioSendMessage [MMSYSTEM.1222]
2913  */
2914 LRESULT WINAPI mmioSendMessage16(HMMIO16 hmmio, UINT16 uMessage,
2915                                  LPARAM lParam1, LPARAM lParam2)
2916 {
2917     return MMIO_SendMessage(HMMIO_32(hmmio), uMessage, 
2918                             lParam1, lParam2, MMIO_PROC_16);
2919 }
2920
2921 /**************************************************************************
2922  *                              mmioDescend             [MMSYSTEM.1223]
2923  */
2924 MMRESULT16 WINAPI mmioDescend16(HMMIO16 hmmio, LPMMCKINFO lpck,
2925                                 const MMCKINFO* lpckParent, UINT16 uFlags)
2926 {
2927     return mmioDescend(HMMIO_32(hmmio), lpck, lpckParent, uFlags);
2928 }
2929
2930 /**************************************************************************
2931  *                              mmioAscend              [MMSYSTEM.1224]
2932  */
2933 MMRESULT16 WINAPI mmioAscend16(HMMIO16 hmmio, MMCKINFO* lpck, UINT16 uFlags)
2934 {
2935     return mmioAscend(HMMIO_32(hmmio),lpck,uFlags);
2936 }
2937
2938 /**************************************************************************
2939  *                              mmioCreateChunk         [MMSYSTEM.1225]
2940  */
2941 MMRESULT16 WINAPI mmioCreateChunk16(HMMIO16 hmmio, MMCKINFO* lpck, UINT16 uFlags)
2942 {
2943     return mmioCreateChunk(HMMIO_32(hmmio), lpck, uFlags);
2944 }
2945
2946 /**************************************************************************
2947  *                              mmioRename              [MMSYSTEM.1226]
2948  */
2949 MMRESULT16 WINAPI mmioRename16(LPCSTR szFileName, LPCSTR szNewFileName,
2950                                MMIOINFO16* lpmmioinfo, DWORD dwRenameFlags)
2951 {
2952     BOOL        inst = FALSE;
2953     MMRESULT    ret;
2954     MMIOINFO    mmioinfo;
2955
2956     if (lpmmioinfo != NULL && lpmmioinfo->pIOProc != NULL && 
2957         lpmmioinfo->fccIOProc == 0) {
2958         FIXME("Can't handle this case yet\n");
2959         return MMSYSERR_ERROR;
2960     }
2961      
2962     /* this is a bit hacky, but it'll work if we get a fourCC code or nothing.
2963      * but a non installed ioproc without a fourcc won't do
2964      */
2965     if (lpmmioinfo && lpmmioinfo->fccIOProc && lpmmioinfo->pIOProc) {
2966         MMIO_InstallIOProc(lpmmioinfo->fccIOProc, (LPMMIOPROC)lpmmioinfo->pIOProc,
2967                            MMIO_INSTALLPROC, MMIO_PROC_16);
2968         inst = TRUE;
2969     }
2970     memset(&mmioinfo, 0, sizeof(mmioinfo));
2971     mmioinfo.fccIOProc = lpmmioinfo->fccIOProc;
2972     ret = mmioRenameA(szFileName, szNewFileName, &mmioinfo, dwRenameFlags);
2973     if (inst) {
2974         MMIO_InstallIOProc(lpmmioinfo->fccIOProc, NULL,
2975                            MMIO_REMOVEPROC, MMIO_PROC_16);
2976     }
2977     return ret;
2978 }
2979
2980 /* ###################################################
2981  * #                     JOYSTICK                    #
2982  * ###################################################
2983  */
2984
2985 /**************************************************************************
2986  *                              joyGetNumDevs           [MMSYSTEM.101]
2987  */
2988 UINT16 WINAPI joyGetNumDevs16(void)
2989 {
2990     return joyGetNumDevs();
2991 }
2992
2993 /**************************************************************************
2994  *                              joyGetDevCaps           [MMSYSTEM.102]
2995  */
2996 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
2997 {
2998     JOYCAPSA    jca;
2999     MMRESULT    ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
3000
3001     if (ret != JOYERR_NOERROR) return ret;
3002     lpCaps->wMid = jca.wMid;
3003     lpCaps->wPid = jca.wPid;
3004     strcpy(lpCaps->szPname, jca.szPname);
3005     lpCaps->wXmin = jca.wXmin;
3006     lpCaps->wXmax = jca.wXmax;
3007     lpCaps->wYmin = jca.wYmin;
3008     lpCaps->wYmax = jca.wYmax;
3009     lpCaps->wZmin = jca.wZmin;
3010     lpCaps->wZmax = jca.wZmax;
3011     lpCaps->wNumButtons = jca.wNumButtons;
3012     lpCaps->wPeriodMin = jca.wPeriodMin;
3013     lpCaps->wPeriodMax = jca.wPeriodMax;
3014
3015     if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
3016         lpCaps->wRmin = jca.wRmin;
3017         lpCaps->wRmax = jca.wRmax;
3018         lpCaps->wUmin = jca.wUmin;
3019         lpCaps->wUmax = jca.wUmax;
3020         lpCaps->wVmin = jca.wVmin;
3021         lpCaps->wVmax = jca.wVmax;
3022         lpCaps->wCaps = jca.wCaps;
3023         lpCaps->wMaxAxes = jca.wMaxAxes;
3024         lpCaps->wNumAxes = jca.wNumAxes;
3025         lpCaps->wMaxButtons = jca.wMaxButtons;
3026         strcpy(lpCaps->szRegKey, jca.szRegKey);
3027         strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
3028     }
3029
3030     return ret;
3031 }
3032
3033 /**************************************************************************
3034  *                              joyGetPosEx           [MMSYSTEM.110]
3035  */
3036 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
3037 {
3038     return joyGetPosEx(wID, lpInfo);
3039 }
3040
3041 /**************************************************************************
3042  *                              joyGetPos               [MMSYSTEM.103]
3043  */
3044 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
3045 {
3046     JOYINFO     ji;
3047     MMRESULT    ret;
3048
3049     TRACE("(%d, %p);\n", wID, lpInfo);
3050
3051     if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
3052         lpInfo->wXpos = ji.wXpos;
3053         lpInfo->wYpos = ji.wYpos;
3054         lpInfo->wZpos = ji.wZpos;
3055         lpInfo->wButtons = ji.wButtons;
3056     }
3057     return ret;
3058 }
3059
3060 /**************************************************************************
3061  *                              joyGetThreshold         [MMSYSTEM.104]
3062  */
3063 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
3064 {
3065     UINT        t;
3066     MMRESULT    ret;
3067
3068     ret = joyGetThreshold(wID, &t);
3069     if (ret == JOYERR_NOERROR)
3070         *lpThreshold = t;
3071     return ret;
3072 }
3073
3074 /**************************************************************************
3075  *                              joyReleaseCapture       [MMSYSTEM.105]
3076  */
3077 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
3078 {
3079     return joyReleaseCapture(wID);
3080 }
3081
3082 /**************************************************************************
3083  *                              joySetCapture           [MMSYSTEM.106]
3084  */
3085 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
3086 {
3087     return joySetCapture16(hWnd, wID, wPeriod, bChanged);
3088 }
3089
3090 /**************************************************************************
3091  *                              joySetThreshold         [MMSYSTEM.107]
3092  */
3093 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
3094 {
3095     return joySetThreshold16(wID,wThreshold);
3096 }
3097
3098 /**************************************************************************
3099  *                              joySetCalibration       [MMSYSTEM.109]
3100  */
3101 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
3102 {
3103     FIXME("(%04X): stub.\n", wID);
3104     return JOYERR_NOCANDO;
3105 }