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