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