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