Function parameters don't need WINE_UNUSED.
[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(LPCSTR, LPCSTR, LPARAM);
52 static LRESULT          DRIVER_CloseDriver16(HDRVR16, LPARAM, LPARAM);
53 static LRESULT          DRIVER_SendMessage16(HDRVR16, UINT, LPARAM, LPARAM);
54 static LRESULT          MMIO_Callback16(SEGPTR, LPMMIOINFO, UINT, LPARAM, LPARAM);
55
56 /* ###################################################
57  * #                  LIBRARY                        #
58  * ###################################################
59  */
60
61 /**************************************************************************
62  *                      DllEntryPoint (MMSYSTEM.2046)
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") && !LoadLibraryA("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  *                              MMSYSTEM_WEP                    [MMSYSTEM.1]
113  */
114 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
115                         WORD cbHeapSize, LPSTR lpCmdLine)
116 {
117     FIXME("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     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 MCI_GetDriverFromString(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  */
735 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
736 {
737     return midiOutGetErrorTextA(uError, lpText, uSize);
738 }
739
740 /**************************************************************************
741  *                              midiOutOpen             [MMSYSTEM.204]
742  */
743 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
744                             DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
745 {
746     HMIDIOUT    hmo;
747     UINT        ret;
748
749     ret = MIDI_OutOpen(&hmo, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
750
751     if (lphMidiOut != NULL) *lphMidiOut = HMIDIOUT_16(hmo);
752     return ret;
753 }
754
755 /**************************************************************************
756  *                              midiOutClose            [MMSYSTEM.205]
757  */
758 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
759 {
760     return midiOutClose(HMIDIOUT_32(hMidiOut));
761 }
762
763 /**************************************************************************
764  *                              midiOutPrepareHeader    [MMSYSTEM.206]
765  */
766 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
767                                      SEGPTR lpsegMidiOutHdr,      /* [???] */
768                                      UINT16 uSize)                /* [in] */
769 {
770     LPWINE_MLD          wmld;
771
772     TRACE("(%04X, %08lx, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
773
774     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
775         return MMSYSERR_INVALHANDLE;
776
777     return MMDRV_Message(wmld, MODM_PREPARE, lpsegMidiOutHdr, uSize, FALSE);
778 }
779
780 /**************************************************************************
781  *                              midiOutUnprepareHeader  [MMSYSTEM.207]
782  */
783 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
784                                        SEGPTR lpsegMidiOutHdr,      /* [???] */
785                                        UINT16 uSize)                /* [in] */
786 {
787     LPWINE_MLD          wmld;
788     LPMIDIHDR16         lpMidiOutHdr = MapSL(lpsegMidiOutHdr);
789
790     TRACE("(%04X, %08lx, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
791
792     if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
793         return MMSYSERR_NOERROR;
794     }
795
796     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
797         return MMSYSERR_INVALHANDLE;
798
799     return MMDRV_Message(wmld, MODM_UNPREPARE, lpsegMidiOutHdr, uSize, FALSE);
800 }
801
802 /**************************************************************************
803  *                              midiOutShortMsg         [MMSYSTEM.208]
804  */
805 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
806 {
807     return midiOutShortMsg(HMIDIOUT_32(hMidiOut), dwMsg);
808 }
809
810 /**************************************************************************
811  *                              midiOutLongMsg          [MMSYSTEM.209]
812  */
813 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut,          /* [in] */
814                                LPMIDIHDR16 lpsegMidiOutHdr,  /* [???] NOTE: SEGPTR */
815                                UINT16 uSize)                 /* [in] */
816 {
817     LPWINE_MLD          wmld;
818
819     TRACE("(%04X, %p, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
820
821     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
822         return MMSYSERR_INVALHANDLE;
823
824     return MMDRV_Message(wmld, MODM_LONGDATA, (DWORD_PTR)lpsegMidiOutHdr, uSize, FALSE);
825 }
826
827 /**************************************************************************
828  *                              midiOutReset            [MMSYSTEM.210]
829  */
830 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
831 {
832     return midiOutReset(HMIDIOUT_32(hMidiOut));
833 }
834
835 /**************************************************************************
836  *                              midiOutGetVolume        [MMSYSTEM.211]
837  */
838 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
839 {
840     return midiOutGetVolume(HMIDIOUT_32(uDeviceID), lpdwVolume);
841 }
842
843 /**************************************************************************
844  *                              midiOutSetVolume        [MMSYSTEM.212]
845  */
846 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
847 {
848     return midiOutSetVolume(HMIDIOUT_32(uDeviceID), dwVolume);
849 }
850
851 /**************************************************************************
852  *                              midiOutCachePatches             [MMSYSTEM.213]
853  */
854 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
855                                     WORD* lpwPatchArray, UINT16 uFlags)
856 {
857     return midiOutCachePatches(HMIDIOUT_32(hMidiOut), uBank, lpwPatchArray,
858                                uFlags);
859 }
860
861 /**************************************************************************
862  *                              midiOutCacheDrumPatches [MMSYSTEM.214]
863  */
864 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
865                                         WORD* lpwKeyArray, UINT16 uFlags)
866 {
867     return midiOutCacheDrumPatches(HMIDIOUT_32(hMidiOut), uPatch, lpwKeyArray, uFlags);
868 }
869
870 /**************************************************************************
871  *                              midiOutGetID            [MMSYSTEM.215]
872  */
873 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
874 {
875     LPWINE_MLD          wmld;
876
877     TRACE("(%04X, %p)\n", hMidiOut, lpuDeviceID);
878
879     if (lpuDeviceID == NULL) return MMSYSERR_INVALPARAM;
880     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
881         return MMSYSERR_INVALHANDLE;
882
883     *lpuDeviceID = wmld->uDeviceID;
884     return MMSYSERR_NOERROR;
885 }
886
887 /**************************************************************************
888  *                              midiOutMessage          [MMSYSTEM.216]
889  */
890 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
891                               DWORD dwParam1, DWORD dwParam2)
892 {
893     LPWINE_MLD          wmld;
894
895     TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut, uMessage, dwParam1, dwParam2);
896
897     if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
898         return MMSYSERR_INVALHANDLE;
899
900     switch (uMessage) {
901     case MODM_OPEN:
902     case MODM_CLOSE:
903         FIXME("can't handle OPEN or CLOSE message!\n");
904         return MMSYSERR_NOTSUPPORTED;
905
906     case MODM_GETVOLUME:
907         return midiOutGetVolume16(hMidiOut, MapSL(dwParam1));
908     case MODM_LONGDATA:
909         return midiOutLongMsg16(hMidiOut, MapSL(dwParam1), dwParam2);
910     case MODM_PREPARE:
911         /* lpMidiOutHdr is still a segmented pointer for this function */
912         return midiOutPrepareHeader16(hMidiOut, dwParam1, dwParam2);
913     case MODM_UNPREPARE:
914         return midiOutUnprepareHeader16(hMidiOut, dwParam1, dwParam2);
915     }
916     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
917 }
918
919 /**************************************************************************
920  *                              midiInGetNumDevs        [MMSYSTEM.301]
921  */
922 UINT16 WINAPI midiInGetNumDevs16(void)
923 {
924     return MMDRV_GetNum(MMDRV_MIDIIN);
925 }
926
927 /**************************************************************************
928  *                              midiInGetDevCaps        [MMSYSTEM.302]
929  */
930 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID, LPMIDIINCAPS16 lpCaps,
931                                  UINT16 uSize)
932 {
933     MIDIINCAPSA         micA;
934     UINT                ret;
935
936     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
937
938     ret = midiInGetDevCapsA(uDeviceID, &micA, uSize);
939     if (ret == MMSYSERR_NOERROR) {
940         MIDIINCAPS16 mic16;
941         mic16.wMid           = micA.wMid;
942         mic16.wPid           = micA.wPid;
943         mic16.vDriverVersion = micA.vDriverVersion;
944         strcpy(mic16.szPname, micA.szPname);
945         mic16.dwSupport      = micA.dwSupport;
946         memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
947     }
948     return ret;
949 }
950
951 /**************************************************************************
952  *                              midiInGetErrorText              [MMSYSTEM.303]
953  */
954 UINT16 WINAPI midiInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
955 {
956     return midiInGetErrorTextA(uError, lpText, uSize);
957 }
958
959 /**************************************************************************
960  *                              midiInOpen              [MMSYSTEM.304]
961  */
962 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
963                            DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
964 {
965     HMIDIIN     xhmid;
966     UINT        ret;
967
968     ret = MIDI_InOpen(&xhmid, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
969
970     if (lphMidiIn) *lphMidiIn = HMIDIIN_16(xhmid);
971     return ret;
972 }
973
974 /**************************************************************************
975  *                              midiInClose             [MMSYSTEM.305]
976  */
977 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
978 {
979     return midiInClose(HMIDIIN_32(hMidiIn));
980 }
981
982 /**************************************************************************
983  *                              midiInPrepareHeader     [MMSYSTEM.306]
984  */
985 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
986                                     SEGPTR lpsegMidiInHdr,     /* [???] */
987                                     UINT16 uSize)              /* [in] */
988 {
989     LPWINE_MLD          wmld;
990
991     TRACE("(%04X, %08lx, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
992
993     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
994         return MMSYSERR_INVALHANDLE;
995
996     return MMDRV_Message(wmld, MIDM_PREPARE, lpsegMidiInHdr, uSize, FALSE);
997 }
998
999 /**************************************************************************
1000  *                              midiInUnprepareHeader   [MMSYSTEM.307]
1001  */
1002 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
1003                                       SEGPTR lpsegMidiInHdr,     /* [???] */
1004                                       UINT16 uSize)              /* [in] */
1005 {
1006     LPWINE_MLD          wmld;
1007     LPMIDIHDR16         lpMidiInHdr = MapSL(lpsegMidiInHdr);
1008
1009     TRACE("(%04X, %08lx, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
1010
1011     if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
1012         return MMSYSERR_NOERROR;
1013     }
1014
1015     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
1016         return MMSYSERR_INVALHANDLE;
1017
1018     return MMDRV_Message(wmld, MIDM_UNPREPARE, lpsegMidiInHdr, uSize, FALSE);
1019 }
1020
1021 /**************************************************************************
1022  *                              midiInAddBuffer         [MMSYSTEM.308]
1023  */
1024 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn,         /* [in] */
1025                                 MIDIHDR16* lpsegMidiInHdr, /* [???] NOTE: SEGPTR */
1026                                 UINT16 uSize)              /* [in] */
1027 {
1028     LPWINE_MLD          wmld;
1029
1030     TRACE("(%04X, %p, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
1031
1032     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
1033         return MMSYSERR_INVALHANDLE;
1034
1035     return MMDRV_Message(wmld, MIDM_ADDBUFFER, (DWORD_PTR)lpsegMidiInHdr, uSize, FALSE);
1036 }
1037
1038 /**************************************************************************
1039  *                              midiInStart                     [MMSYSTEM.309]
1040  */
1041 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
1042 {
1043     return midiInStart(HMIDIIN_32(hMidiIn));
1044 }
1045
1046 /**************************************************************************
1047  *                              midiInStop                      [MMSYSTEM.310]
1048  */
1049 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
1050 {
1051     return midiInStop(HMIDIIN_32(hMidiIn));
1052 }
1053
1054 /**************************************************************************
1055  *                              midiInReset                     [MMSYSTEM.311]
1056  */
1057 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
1058 {
1059     return midiInReset(HMIDIIN_32(hMidiIn));
1060 }
1061
1062 /**************************************************************************
1063  *                              midiInGetID                     [MMSYSTEM.312]
1064  */
1065 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
1066 {
1067     LPWINE_MLD          wmld;
1068
1069     TRACE("(%04X, %p)\n", hMidiIn, lpuDeviceID);
1070
1071     if (lpuDeviceID == NULL) return MMSYSERR_INVALPARAM;
1072
1073     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, TRUE)) == NULL)
1074         return MMSYSERR_INVALHANDLE;
1075
1076     *lpuDeviceID = wmld->uDeviceID;
1077
1078     return MMSYSERR_NOERROR;
1079 }
1080
1081 /**************************************************************************
1082  *                              midiInMessage           [MMSYSTEM.313]
1083  */
1084 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
1085                              DWORD dwParam1, DWORD dwParam2)
1086 {
1087     LPWINE_MLD          wmld;
1088
1089     TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn, uMessage, dwParam1, dwParam2);
1090
1091     switch (uMessage) {
1092     case MIDM_OPEN:
1093     case MIDM_CLOSE:
1094         FIXME("can't handle OPEN or CLOSE message!\n");
1095         return MMSYSERR_NOTSUPPORTED;
1096
1097     case MIDM_GETDEVCAPS:
1098         return midiInGetDevCaps16(hMidiIn, MapSL(dwParam1), dwParam2);
1099     case MIDM_PREPARE:
1100         return midiInPrepareHeader16(hMidiIn, dwParam1, dwParam2);
1101     case MIDM_UNPREPARE:
1102         return midiInUnprepareHeader16(hMidiIn, dwParam1, dwParam2);
1103     case MIDM_ADDBUFFER:
1104         return midiInAddBuffer16(hMidiIn, MapSL(dwParam1), dwParam2);
1105     }
1106
1107     if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
1108         return MMSYSERR_INVALHANDLE;
1109
1110     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1111 }
1112
1113 /**************************************************************************
1114  *                              midiStreamClose                 [MMSYSTEM.252]
1115  */
1116 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hMidiStrm)
1117 {
1118     return midiStreamClose(HMIDISTRM_32(hMidiStrm));
1119 }
1120
1121 /**************************************************************************
1122  *                              midiStreamOpen                  [MMSYSTEM.251]
1123  */
1124 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
1125                                    DWORD cMidi, DWORD dwCallback,
1126                                    DWORD dwInstance, DWORD fdwOpen)
1127 {
1128     HMIDISTRM   hMidiStrm32;
1129     MMRESULT    ret;
1130     UINT        devid32;
1131
1132     if (!phMidiStrm || !devid)
1133         return MMSYSERR_INVALPARAM;
1134     devid32 = *devid;
1135     ret = MIDI_StreamOpen(&hMidiStrm32, &devid32, cMidi, dwCallback,
1136                           dwInstance, fdwOpen, FALSE);
1137     *phMidiStrm = HMIDISTRM_16(hMidiStrm32);
1138     *devid = devid32;
1139     return ret;
1140 }
1141
1142 /**************************************************************************
1143  *                              midiStreamOut                   [MMSYSTEM.254]
1144  */
1145 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hMidiStrm, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
1146 {
1147     return midiStreamOut(HMIDISTRM_32(hMidiStrm), (LPMIDIHDR)lpMidiHdr,
1148                          cbMidiHdr);
1149 }
1150
1151 /**************************************************************************
1152  *                              midiStreamPause                 [MMSYSTEM.255]
1153  */
1154 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hMidiStrm)
1155 {
1156     return midiStreamPause(HMIDISTRM_32(hMidiStrm));
1157 }
1158
1159 /**************************************************************************
1160  *                              midiStreamPosition              [MMSYSTEM.253]
1161  */
1162 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hMidiStrm, LPMMTIME16 lpmmt16, UINT16 cbmmt)
1163 {
1164     MMTIME      mmt32;
1165     MMRESULT    ret;
1166
1167     if (!lpmmt16)
1168         return MMSYSERR_INVALPARAM;
1169     MMSYSTEM_MMTIME16to32(&mmt32, lpmmt16);
1170     ret = midiStreamPosition(HMIDISTRM_32(hMidiStrm), &mmt32, sizeof(MMTIME));
1171     MMSYSTEM_MMTIME32to16(lpmmt16, &mmt32);
1172     return ret;
1173 }
1174
1175 /**************************************************************************
1176  *                              midiStreamProperty              [MMSYSTEM.250]
1177  */
1178 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hMidiStrm, LPBYTE lpPropData, DWORD dwProperty)
1179 {
1180     return midiStreamProperty(HMIDISTRM_32(hMidiStrm), lpPropData, dwProperty);
1181 }
1182
1183 /**************************************************************************
1184  *                              midiStreamRestart               [MMSYSTEM.256]
1185  */
1186 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hMidiStrm)
1187 {
1188     return midiStreamRestart(HMIDISTRM_32(hMidiStrm));
1189 }
1190
1191 /**************************************************************************
1192  *                              midiStreamStop                  [MMSYSTEM.257]
1193  */
1194 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hMidiStrm)
1195 {
1196     return midiStreamStop(HMIDISTRM_32(hMidiStrm));
1197 }
1198
1199 /* ###################################################
1200  * #                     WAVE                        #
1201  * ###################################################
1202  */
1203
1204 /**************************************************************************
1205  *                              waveOutGetNumDevs               [MMSYSTEM.401]
1206  */
1207 UINT16 WINAPI waveOutGetNumDevs16(void)
1208 {
1209     return MMDRV_GetNum(MMDRV_WAVEOUT);
1210 }
1211
1212 /**************************************************************************
1213  *                              waveOutGetDevCaps               [MMSYSTEM.402]
1214  */
1215 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID,
1216                                   LPWAVEOUTCAPS16 lpCaps, UINT16 uSize)
1217 {
1218     WAVEOUTCAPSA        wocA;
1219     UINT                ret;
1220     TRACE("(%u %p %u)!\n", uDeviceID, lpCaps, uSize);
1221
1222     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1223
1224     ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA));
1225     if (ret == MMSYSERR_NOERROR) {
1226         WAVEOUTCAPS16 woc16;
1227         woc16.wMid           = wocA.wMid;
1228         woc16.wPid           = wocA.wPid;
1229         woc16.vDriverVersion = wocA.vDriverVersion;
1230         strcpy(woc16.szPname, wocA.szPname);
1231         woc16.dwFormats      = wocA.dwFormats;
1232         woc16.wChannels      = wocA.wChannels;
1233         woc16.dwSupport      = wocA.dwSupport;
1234         memcpy(lpCaps, &woc16, min(uSize, sizeof(woc16)));
1235     }
1236     return ret;
1237 }
1238
1239 /**************************************************************************
1240  *                              waveOutGetErrorText     [MMSYSTEM.403]
1241  */
1242 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1243 {
1244     return waveOutGetErrorTextA(uError, lpText, uSize);
1245 }
1246
1247 /**************************************************************************
1248  *                      waveOutOpen                     [MMSYSTEM.404]
1249  */
1250 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
1251                             const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
1252                             DWORD dwInstance, DWORD dwFlags)
1253 {
1254     HANDLE              hWaveOut;
1255     UINT                ret;
1256
1257     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1258      * call the 32 bit version
1259      * however, we need to promote correctly the wave mapper id
1260      * (0xFFFFFFFF and not 0x0000FFFF)
1261      */
1262     ret = WAVE_Open(&hWaveOut, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1263                     MMDRV_WAVEOUT, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1264
1265     if (lphWaveOut != NULL) *lphWaveOut = HWAVEOUT_16(hWaveOut);
1266     return ret;
1267 }
1268
1269 /**************************************************************************
1270  *                              waveOutClose            [MMSYSTEM.405]
1271  */
1272 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
1273 {
1274     DWORD       level;
1275     UINT16      ret;
1276
1277     ReleaseThunkLock(&level);
1278     ret = waveOutClose(HWAVEOUT_32(hWaveOut));
1279     RestoreThunkLock(level);
1280     return ret;
1281 }
1282
1283 /**************************************************************************
1284  *                              waveOutPrepareHeader    [MMSYSTEM.406]
1285  */
1286 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,      /* [in] */
1287                                      SEGPTR lpsegWaveOutHdr,   /* [???] */
1288                                      UINT16 uSize)             /* [in] */
1289 {
1290     LPWINE_MLD          wmld;
1291     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1292
1293     TRACE("(%04X, %08lx, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1294
1295     if (lpWaveOutHdr == NULL) return MMSYSERR_INVALPARAM;
1296
1297     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1298         return MMSYSERR_INVALHANDLE;
1299
1300     return MMDRV_Message(wmld, WODM_PREPARE, lpsegWaveOutHdr, uSize, FALSE);
1301 }
1302
1303 /**************************************************************************
1304  *                              waveOutUnprepareHeader  [MMSYSTEM.407]
1305  */
1306 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,       /* [in] */
1307                                        SEGPTR lpsegWaveOutHdr,    /* [???] */
1308                                        UINT16 uSize)              /* [in] */
1309 {
1310     LPWINE_MLD          wmld;
1311     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1312
1313     TRACE("(%04X, %08lx, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1314
1315     if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
1316         return MMSYSERR_NOERROR;
1317     }
1318
1319     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1320         return MMSYSERR_INVALHANDLE;
1321
1322     return MMDRV_Message(wmld, WODM_UNPREPARE, lpsegWaveOutHdr, uSize, FALSE);
1323 }
1324
1325 /**************************************************************************
1326  *                              waveOutWrite            [MMSYSTEM.408]
1327  */
1328 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut,       /* [in] */
1329                              LPWAVEHDR lpsegWaveOutHdr, /* [???] NOTE: SEGPTR */
1330                              UINT16 uSize)              /* [in] */
1331 {
1332     LPWINE_MLD          wmld;
1333
1334     TRACE("(%04X, %p, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1335
1336     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1337         return MMSYSERR_INVALHANDLE;
1338
1339     return MMDRV_Message(wmld, WODM_WRITE, (DWORD_PTR)lpsegWaveOutHdr, uSize, FALSE);
1340 }
1341
1342 /**************************************************************************
1343  *                              waveOutBreakLoop        [MMSYSTEM.419]
1344  */
1345 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut16)
1346 {
1347     DWORD       level;
1348     UINT16      ret;
1349
1350     ReleaseThunkLock(&level);
1351     ret = waveOutBreakLoop(HWAVEOUT_32(hWaveOut16));
1352     RestoreThunkLock(level);
1353     return ret;
1354 }
1355
1356 /**************************************************************************
1357  *                              waveOutPause            [MMSYSTEM.409]
1358  */
1359 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut16)
1360 {
1361     DWORD       level;
1362     UINT16      ret;
1363
1364     ReleaseThunkLock(&level);
1365     ret = waveOutPause(HWAVEOUT_32(hWaveOut16));
1366     RestoreThunkLock(level);
1367     return ret;
1368 }
1369
1370 /**************************************************************************
1371  *                              waveOutReset            [MMSYSTEM.411]
1372  */
1373 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut16)
1374 {
1375     DWORD       level;
1376     UINT16      ret;
1377
1378     ReleaseThunkLock(&level);
1379     ret = waveOutReset(HWAVEOUT_32(hWaveOut16));
1380     RestoreThunkLock(level);
1381     return ret;
1382 }
1383
1384 /**************************************************************************
1385  *                              waveOutRestart  [MMSYSTEM.410]
1386  */
1387 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut16)
1388 {
1389     DWORD       level;
1390     UINT16      ret;
1391
1392     ReleaseThunkLock(&level);
1393     ret = waveOutRestart(HWAVEOUT_32(hWaveOut16));
1394     RestoreThunkLock(level);
1395     return ret;
1396 }
1397
1398 /**************************************************************************
1399  *                              waveOutGetPosition      [MMSYSTEM.412]
1400  */
1401 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
1402                                    UINT16 uSize)
1403 {
1404     UINT        ret;
1405     MMTIME      mmt;
1406
1407     mmt.wType = lpTime->wType;
1408     ret = waveOutGetPosition(HWAVEOUT_32(hWaveOut), &mmt, sizeof(mmt));
1409     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1410     return ret;
1411 }
1412
1413 /**************************************************************************
1414  *                              waveOutGetPitch         [MMSYSTEM.413]
1415  */
1416 UINT16 WINAPI waveOutGetPitch16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1417 {
1418     return waveOutGetPitch(HWAVEOUT_32(hWaveOut16), lpdw);
1419 }
1420
1421 /**************************************************************************
1422  *                              waveOutSetPitch         [MMSYSTEM.414]
1423  */
1424 UINT16 WINAPI waveOutSetPitch16(HWAVEOUT16 hWaveOut16, DWORD dw)
1425 {
1426     return waveOutSetPitch(HWAVEOUT_32(hWaveOut16), dw);
1427 }
1428
1429 /**************************************************************************
1430  *                              waveOutGetPlaybackRate  [MMSYSTEM.417]
1431  */
1432 UINT16 WINAPI waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1433 {
1434     return waveOutGetPlaybackRate(HWAVEOUT_32(hWaveOut16), lpdw);
1435 }
1436
1437 /**************************************************************************
1438  *                              waveOutSetPlaybackRate  [MMSYSTEM.418]
1439  */
1440 UINT16 WINAPI waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16, DWORD dw)
1441 {
1442     return waveOutSetPlaybackRate(HWAVEOUT_32(hWaveOut16), dw);
1443 }
1444
1445 /**************************************************************************
1446  *                              waveOutGetVolume        [MMSYSTEM.415]
1447  */
1448 UINT16 WINAPI waveOutGetVolume16(UINT16 devid, LPDWORD lpdw)
1449 {
1450     return waveOutGetVolume(HWAVEOUT_32(devid), lpdw);
1451 }
1452
1453 /**************************************************************************
1454  *                              waveOutSetVolume        [MMSYSTEM.416]
1455  */
1456 UINT16 WINAPI waveOutSetVolume16(UINT16 devid, DWORD dw)
1457 {
1458     return waveOutSetVolume(HWAVEOUT_32(devid), dw);
1459 }
1460
1461 /**************************************************************************
1462  *                              waveOutGetID            [MMSYSTEM.420]
1463  */
1464 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
1465 {
1466     LPWINE_MLD          wmld;
1467
1468     TRACE("(%04X, %p);\n", hWaveOut, lpuDeviceID);
1469
1470     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
1471
1472     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1473         return MMSYSERR_INVALHANDLE;
1474
1475     *lpuDeviceID = wmld->uDeviceID;
1476     return 0;
1477 }
1478
1479 /**************************************************************************
1480  *                              waveOutMessage          [MMSYSTEM.421]
1481  */
1482 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
1483                               DWORD dwParam1, DWORD dwParam2)
1484 {
1485     LPWINE_MLD          wmld;
1486
1487     TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut, uMessage, dwParam1, dwParam2);
1488
1489     if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL) {
1490         if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, TRUE)) != NULL) {
1491             if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1492                 dwParam1 = (DWORD)MapSL(dwParam1);
1493             return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1494         }
1495         return MMSYSERR_INVALHANDLE;
1496     }
1497
1498     /* from M$ KB */
1499     if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1500         return MMSYSERR_INVALPARAM;
1501
1502     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1503 }
1504
1505 /**************************************************************************
1506  *                              waveInGetNumDevs                [MMSYSTEM.501]
1507  */
1508 UINT16 WINAPI waveInGetNumDevs16(void)
1509 {
1510     return MMDRV_GetNum(MMDRV_WAVEIN);
1511 }
1512
1513 /**************************************************************************
1514  *                              waveInGetDevCaps                [MMSYSTEM.502]
1515  */
1516 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps,
1517                                  UINT16 uSize)
1518 {
1519     WAVEINCAPSA wicA;
1520     UINT        ret;
1521
1522     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1523
1524     ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA));
1525     if (ret == MMSYSERR_NOERROR) {
1526         WAVEINCAPS16 wic16;
1527         wic16.wMid           = wicA.wMid;
1528         wic16.wPid           = wicA.wPid;
1529         wic16.vDriverVersion = wicA.vDriverVersion;
1530         strcpy(wic16.szPname, wicA.szPname);
1531         wic16.dwFormats      = wicA.dwFormats;
1532         wic16.wChannels      = wicA.wChannels;
1533         memcpy(lpCaps, &wic16, min(uSize, sizeof(wic16)));
1534     }
1535     return ret;
1536 }
1537
1538 /**************************************************************************
1539  *                              waveInGetErrorText      [MMSYSTEM.503]
1540  */
1541 UINT16 WINAPI waveInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1542 {
1543     return waveInGetErrorTextA(uError, lpText, uSize);
1544 }
1545
1546 /**************************************************************************
1547  *                              waveInOpen                      [MMSYSTEM.504]
1548  */
1549 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
1550                            const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
1551                            DWORD dwInstance, DWORD dwFlags)
1552 {
1553     HANDLE              hWaveIn;
1554     UINT                ret;
1555
1556     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1557      * call the 32 bit version
1558      * however, we need to promote correctly the wave mapper id
1559      * (0xFFFFFFFF and not 0x0000FFFF)
1560      */
1561     ret = WAVE_Open(&hWaveIn, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1562                     MMDRV_WAVEIN, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1563
1564     if (lphWaveIn != NULL) *lphWaveIn = HWAVEIN_16(hWaveIn);
1565     return ret;
1566 }
1567
1568 /**************************************************************************
1569  *                              waveInClose                     [MMSYSTEM.505]
1570  */
1571 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
1572 {
1573     DWORD       level;
1574     UINT16      ret;
1575
1576     ReleaseThunkLock(&level);
1577     ret = waveInClose(HWAVEIN_32(hWaveIn));
1578     RestoreThunkLock(level);
1579     return ret;
1580 }
1581
1582 /**************************************************************************
1583  *                              waveInPrepareHeader             [MMSYSTEM.506]
1584  */
1585 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1586                                     SEGPTR lpsegWaveInHdr,   /* [???] */
1587                                     UINT16 uSize)            /* [in] */
1588 {
1589     LPWINE_MLD          wmld;
1590     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1591     UINT16              ret;
1592
1593     TRACE("(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
1594
1595     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
1596     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1597         return MMSYSERR_INVALHANDLE;
1598
1599     lpWaveInHdr->dwBytesRecorded = 0;
1600
1601     ret = MMDRV_Message(wmld, WIDM_PREPARE, lpsegWaveInHdr, uSize, FALSE);
1602     return ret;
1603 }
1604
1605 /**************************************************************************
1606  *                              waveInUnprepareHeader   [MMSYSTEM.507]
1607  */
1608 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1609                                       SEGPTR lpsegWaveInHdr,   /* [???] */
1610                                       UINT16 uSize)            /* [in] */
1611 {
1612     LPWINE_MLD          wmld;
1613     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1614
1615     TRACE("(%04X, %08lx, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1616
1617     if (lpWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1618
1619     if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED)) {
1620         return MMSYSERR_NOERROR;
1621     }
1622
1623     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1624         return MMSYSERR_INVALHANDLE;
1625
1626     return MMDRV_Message(wmld, WIDM_UNPREPARE, lpsegWaveInHdr, uSize, FALSE);
1627 }
1628
1629 /**************************************************************************
1630  *                              waveInAddBuffer         [MMSYSTEM.508]
1631  */
1632 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,       /* [in] */
1633                                 WAVEHDR* lpsegWaveInHdr, /* [???] NOTE: SEGPTR */
1634                                 UINT16 uSize)            /* [in] */
1635 {
1636     LPWINE_MLD          wmld;
1637
1638     TRACE("(%04X, %p, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1639
1640     if (lpsegWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1641     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1642         return MMSYSERR_INVALHANDLE;
1643
1644     return MMDRV_Message(wmld, WIDM_ADDBUFFER, (DWORD_PTR)lpsegWaveInHdr, uSize, FALSE);
1645 }
1646
1647 /**************************************************************************
1648  *                              waveInReset             [MMSYSTEM.511]
1649  */
1650 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn16)
1651 {
1652     DWORD       level;
1653     UINT16      ret;
1654
1655     ReleaseThunkLock(&level);
1656     ret = waveInReset(HWAVEIN_32(hWaveIn16));
1657     RestoreThunkLock(level);
1658     return ret;
1659 }
1660
1661 /**************************************************************************
1662  *                              waveInStart             [MMSYSTEM.509]
1663  */
1664 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn16)
1665 {
1666     DWORD       level;
1667     UINT16      ret;
1668
1669     ReleaseThunkLock(&level);
1670     ret = waveInStart(HWAVEIN_32(hWaveIn16));
1671     RestoreThunkLock(level);
1672     return ret;
1673 }
1674
1675 /**************************************************************************
1676  *                              waveInStop              [MMSYSTEM.510]
1677  */
1678 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn16)
1679 {
1680     DWORD       level;
1681     UINT16      ret;
1682
1683     ReleaseThunkLock(&level);
1684     ret = waveInStop(HWAVEIN_32(hWaveIn16));
1685     RestoreThunkLock(level);
1686     return ret;
1687 }
1688
1689 /**************************************************************************
1690  *                              waveInGetPosition       [MMSYSTEM.512]
1691  */
1692 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
1693                                   UINT16 uSize)
1694 {
1695     UINT        ret;
1696     MMTIME      mmt;
1697
1698     mmt.wType = lpTime->wType;
1699     ret = waveInGetPosition(HWAVEIN_32(hWaveIn), &mmt, sizeof(mmt));
1700     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1701     return ret;
1702 }
1703
1704 /**************************************************************************
1705  *                              waveInGetID                     [MMSYSTEM.513]
1706  */
1707 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
1708 {
1709     LPWINE_MLD          wmld;
1710
1711     TRACE("(%04X, %p);\n", hWaveIn, lpuDeviceID);
1712
1713     if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
1714
1715     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1716         return MMSYSERR_INVALHANDLE;
1717
1718     *lpuDeviceID = wmld->uDeviceID;
1719     return MMSYSERR_NOERROR;
1720 }
1721
1722 /**************************************************************************
1723  *                              waveInMessage           [MMSYSTEM.514]
1724  */
1725 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
1726                              DWORD dwParam1, DWORD dwParam2)
1727 {
1728     LPWINE_MLD          wmld;
1729
1730     TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn, uMessage, dwParam1, dwParam2);
1731
1732     if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL) {
1733         if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, TRUE)) != NULL) {
1734             if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1735                 dwParam1 = (DWORD)MapSL(dwParam1);
1736             return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1737         }
1738         return MMSYSERR_INVALHANDLE;
1739     }
1740
1741     /* from M$ KB */
1742     if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1743         return MMSYSERR_INVALPARAM;
1744
1745     return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1746 }
1747
1748 /* ###################################################
1749  * #                     TASK                        #
1750  * ###################################################
1751  */
1752
1753 /*#define USE_MM_TSK_WINE*/
1754
1755 /**************************************************************************
1756  *                              mmTaskCreate            [MMSYSTEM.900]
1757  *
1758  * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
1759  * called upon creation with dwPmt as parameter.
1760  */
1761 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
1762 {
1763     HINSTANCE16         ret;
1764     HINSTANCE16         handle;
1765     char cmdline[16];
1766     DWORD showCmd = 0x40002;
1767     LOADPARAMS16 lp;
1768
1769     TRACE("(%08lx, %p, %08lx);\n", spProc, lphMmTask, dwPmt);
1770     /* This to work requires NE modules to be started with a binary command line
1771      * which is not currently the case. A patch exists but has never been committed.
1772      * A workaround would be to integrate code for mmtask.tsk into Wine, but
1773      * this requires tremendous work (starting with patching tools/build to
1774      * create NE executables (and not only DLLs) for builtins modules.
1775      * EP 99/04/25
1776      */
1777     FIXME("This is currently broken. It will fail\n");
1778
1779     cmdline[0] = 0x0d;
1780     *(LPDWORD)(cmdline + 1) = (DWORD)spProc;
1781     *(LPDWORD)(cmdline + 5) = dwPmt;
1782     *(LPDWORD)(cmdline + 9) = 0;
1783
1784     lp.hEnvironment = 0;
1785     lp.cmdLine = MapLS(cmdline);
1786     lp.showCmd = MapLS(&showCmd);
1787     lp.reserved = 0;
1788
1789 #ifndef USE_MM_TSK_WINE
1790     handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
1791 #else
1792     handle = LoadModule16("mmtask.tsk", &lp);
1793 #endif
1794     if (handle < 32) {
1795         ret = (handle) ? 1 : 2;
1796         handle = 0;
1797     } else {
1798         ret = 0;
1799     }
1800     if (lphMmTask)
1801         *lphMmTask = handle;
1802
1803     UnMapLS( lp.cmdLine );
1804     UnMapLS( lp.showCmd );
1805     TRACE("=> 0x%04x/%d\n", handle, ret);
1806     return ret;
1807 }
1808
1809 #ifdef USE_MM_TSK_WINE
1810 /* C equivalent to mmtask.tsk binary content */
1811 void    mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
1812 {
1813     int len = cmdLine[0x80];
1814
1815     if (len / 2 == 6) {
1816         void    (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
1817         DWORD   dwPmt  = *((DWORD*)(cmdLine + 5));
1818
1819 #if 0
1820         InitTask16(); /* FIXME: pmts / from context ? */
1821         InitApp(di);
1822 #endif
1823         if (SetMessageQueue16(0x40)) {
1824             WaitEvent16(0);
1825             if (HIWORD(fpProc)) {
1826                 OldYield16();
1827 /* EPP          StackEnter16(); */
1828                 (fpProc)(dwPmt);
1829             }
1830         }
1831     }
1832     OldYield16();
1833     OldYield16();
1834     OldYield16();
1835     ExitProcess(0);
1836 }
1837 #endif
1838
1839 /**************************************************************************
1840  *                              mmTaskBlock             [MMSYSTEM.902]
1841  */
1842 void WINAPI mmTaskBlock16(HINSTANCE16 hInst)
1843 {
1844     MSG         msg;
1845
1846     do {
1847         GetMessageA(&msg, 0, 0, 0);
1848         if (msg.hwnd) {
1849             TranslateMessage(&msg);
1850             DispatchMessageA(&msg);
1851         }
1852     } while (msg.message < 0x3A0);
1853 }
1854
1855 /**************************************************************************
1856  *                              mmTaskSignal            [MMSYSTEM.903]
1857  */
1858 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
1859 {
1860     TRACE("(%04x);\n", ht);
1861     return PostThreadMessageW( HTASK_32(ht), WM_USER, 0, 0 );
1862 }
1863
1864 /**************************************************************************
1865  *                              mmGetCurrentTask        [MMSYSTEM.904]
1866  */
1867 HTASK16 WINAPI mmGetCurrentTask16(void)
1868 {
1869     return GetCurrentTask();
1870 }
1871
1872 /**************************************************************************
1873  *                              mmTaskYield             [MMSYSTEM.905]
1874  */
1875 void    WINAPI  mmTaskYield16(void)
1876 {
1877     MSG         msg;
1878
1879     if (PeekMessageA(&msg, 0, 0, 0, 0)) {
1880         K32WOWYield16();
1881     }
1882 }
1883
1884 extern DWORD    WINAPI  GetProcessFlags(DWORD);
1885
1886 /******************************************************************
1887  *              WINMM_GetmmThread
1888  *
1889  *
1890  */
1891 static  WINE_MMTHREAD*  WINMM_GetmmThread(HANDLE16 h)
1892 {
1893     return (WINE_MMTHREAD*)MapSL( MAKESEGPTR(h, 0) );
1894 }
1895
1896 void WINAPI WINE_mmThreadEntryPoint(DWORD);
1897
1898 /**************************************************************************
1899  *                              mmThreadCreate          [MMSYSTEM.1120]
1900  *
1901  * undocumented
1902  * Creates a MM thread, calling fpThreadAddr(dwPmt).
1903  * dwFlags:
1904  *      bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
1905  *      bit.1 set means to open a VxD for this thread (unsupported)
1906  */
1907 LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD dwPmt, DWORD dwFlags)
1908 {
1909     HANDLE16            hndl;
1910     LRESULT             ret;
1911
1912     TRACE("(%p, %p, %08lx, %08lx)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
1913
1914     hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
1915
1916     if (hndl == 0) {
1917         ret = 2;
1918     } else {
1919         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1920
1921 #if 0
1922         /* force mmtask routines even if mmthread is required */
1923         /* this will work only if the patch about binary cmd line and NE tasks
1924          * is committed
1925          */
1926         dwFlags |= 1;
1927 #endif
1928
1929         lpMMThd->dwSignature    = WINE_MMTHREAD_CREATED;
1930         lpMMThd->dwCounter      = 0;
1931         lpMMThd->hThread        = 0;
1932         lpMMThd->dwThreadID     = 0;
1933         lpMMThd->fpThread       = (DWORD)fpThreadAddr;
1934         lpMMThd->dwThreadPmt    = dwPmt;
1935         lpMMThd->dwSignalCount  = 0;
1936         lpMMThd->hEvent         = 0;
1937         lpMMThd->hVxD           = 0;
1938         lpMMThd->dwStatus       = 0;
1939         lpMMThd->dwFlags        = dwFlags;
1940         lpMMThd->hTask          = 0;
1941
1942         if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
1943             lpMMThd->hEvent = CreateEventA(0, 0, 1, 0);
1944
1945             TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
1946             if (lpMMThd->dwFlags & 2) {
1947                 /* as long as we don't support MM VxD in wine, we don't need
1948                  * to care about this flag
1949                  */
1950                 /* FIXME("Don't know how to properly open VxD handles\n"); */
1951                 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
1952             }
1953
1954             lpMMThd->hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)WINE_mmThreadEntryPoint,
1955                                             (LPVOID)(DWORD)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
1956             if (lpMMThd->hThread == 0) {
1957                 WARN("Couldn't create thread\n");
1958                 /* clean-up(VxDhandle...); devicedirectio... */
1959                 if (lpMMThd->hEvent != 0)
1960                     CloseHandle(lpMMThd->hEvent);
1961                 ret = 2;
1962             } else {
1963                 TRACE("Got a nice thread hndl=%p id=0x%08lx\n", lpMMThd->hThread, lpMMThd->dwThreadID);
1964                 ret = 0;
1965             }
1966         } else {
1967             /* get WINE_mmThreadEntryPoint()
1968              * 2047 is its ordinal in mmsystem.spec
1969              */
1970             FARPROC16   fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
1971
1972             TRACE("farproc seg=0x%08lx lin=%p\n", (DWORD)fp, MapSL((SEGPTR)fp));
1973
1974             ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
1975         }
1976
1977         if (ret == 0) {
1978             if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
1979                 WARN("Couldn't resume thread\n");
1980
1981             while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
1982                 UserYield16();
1983             }
1984         }
1985     }
1986
1987     if (ret != 0) {
1988         GlobalFree16(hndl);
1989         hndl = 0;
1990     }
1991
1992     if (lpHndl)
1993         *lpHndl = hndl;
1994
1995     TRACE("ok => %ld\n", ret);
1996     return ret;
1997 }
1998
1999 /**************************************************************************
2000  *                              mmThreadSignal          [MMSYSTEM.1121]
2001  */
2002 void WINAPI mmThreadSignal16(HANDLE16 hndl)
2003 {
2004     TRACE("(%04x)!\n", hndl);
2005
2006     if (hndl) {
2007         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2008
2009         lpMMThd->dwCounter++;
2010         if (lpMMThd->hThread != 0) {
2011             InterlockedIncrement(&lpMMThd->dwSignalCount);
2012             SetEvent(lpMMThd->hEvent);
2013         } else {
2014             mmTaskSignal16(lpMMThd->hTask);
2015         }
2016         lpMMThd->dwCounter--;
2017     }
2018 }
2019
2020 static  void    MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
2021 {
2022     MSG         msg;
2023     DWORD       ret;
2024
2025     if (lpMMThd->dwThreadID != GetCurrentThreadId())
2026         ERR("Not called by thread itself\n");
2027
2028     for (;;) {
2029         ResetEvent(lpMMThd->hEvent);
2030         if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
2031             break;
2032         InterlockedIncrement(&lpMMThd->dwSignalCount);
2033
2034         TRACE("S1\n");
2035
2036         ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
2037         switch (ret) {
2038         case WAIT_OBJECT_0:     /* Event */
2039             TRACE("S2.1\n");
2040             break;
2041         case WAIT_OBJECT_0 + 1: /* Msg */
2042             TRACE("S2.2\n");
2043             if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
2044                 TranslateMessage(&msg);
2045                 DispatchMessageA(&msg);
2046             }
2047             break;
2048         default:
2049             WARN("S2.x unsupported ret val 0x%08lx\n", ret);
2050         }
2051         TRACE("S3\n");
2052     }
2053 }
2054
2055 /**************************************************************************
2056  *                              mmThreadBlock           [MMSYSTEM.1122]
2057  */
2058 void    WINAPI mmThreadBlock16(HANDLE16 hndl)
2059 {
2060     TRACE("(%04x)!\n", hndl);
2061
2062     if (hndl) {
2063         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2064
2065         if (lpMMThd->hThread != 0) {
2066             DWORD       lc;
2067
2068             ReleaseThunkLock(&lc);
2069             MMSYSTEM_ThreadBlock(lpMMThd);
2070             RestoreThunkLock(lc);
2071         } else {
2072             mmTaskBlock16(lpMMThd->hTask);
2073         }
2074     }
2075     TRACE("done\n");
2076 }
2077
2078 /**************************************************************************
2079  *                              mmThreadIsCurrent       [MMSYSTEM.1123]
2080  */
2081 BOOL16  WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
2082 {
2083     BOOL16              ret = FALSE;
2084
2085     TRACE("(%04x)!\n", hndl);
2086
2087     if (hndl && mmThreadIsValid16(hndl)) {
2088         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2089         ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
2090     }
2091     TRACE("=> %d\n", ret);
2092     return ret;
2093 }
2094
2095 /**************************************************************************
2096  *                              mmThreadIsValid         [MMSYSTEM.1124]
2097  */
2098 BOOL16  WINAPI  mmThreadIsValid16(HANDLE16 hndl)
2099 {
2100     BOOL16              ret = FALSE;
2101
2102     TRACE("(%04x)!\n", hndl);
2103
2104     if (hndl) {
2105         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2106
2107         if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
2108             lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
2109             IsTask16(lpMMThd->hTask)) {
2110             lpMMThd->dwCounter++;
2111             if (lpMMThd->hThread != 0) {
2112                 DWORD   dwThreadRet;
2113                 if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
2114                     dwThreadRet == STATUS_PENDING) {
2115                     ret = TRUE;
2116                 }
2117             } else {
2118                 ret = TRUE;
2119             }
2120             lpMMThd->dwCounter--;
2121         }
2122     }
2123     TRACE("=> %d\n", ret);
2124     return ret;
2125 }
2126
2127 /**************************************************************************
2128  *                              mmThreadGetTask         [MMSYSTEM.1125]
2129  */
2130 HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
2131 {
2132     HANDLE16    ret = 0;
2133
2134     TRACE("(%04x)\n", hndl);
2135
2136     if (mmThreadIsValid16(hndl)) {
2137         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2138         ret = lpMMThd->hTask;
2139     }
2140     return ret;
2141 }
2142
2143 /**************************************************************************
2144  *                              __wine_mmThreadEntryPoint (MMSYSTEM.2047)
2145  */
2146 void WINAPI WINE_mmThreadEntryPoint(DWORD _pmt)
2147 {
2148     HANDLE16            hndl = (HANDLE16)_pmt;
2149     WINE_MMTHREAD*      lpMMThd = WINMM_GetmmThread(hndl);
2150
2151     TRACE("(%04x %p)\n", hndl, lpMMThd);
2152
2153     lpMMThd->hTask = LOWORD(GetCurrentTask());
2154     TRACE("[10-%p] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
2155     lpMMThd->dwStatus = 0x10;
2156     MMSYSTEM_ThreadBlock(lpMMThd);
2157     TRACE("[20-%p]\n", lpMMThd->hThread);
2158     lpMMThd->dwStatus = 0x20;
2159     if (lpMMThd->fpThread) {
2160         WOWCallback16(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
2161     }
2162     lpMMThd->dwStatus = 0x30;
2163     TRACE("[30-%p]\n", lpMMThd->hThread);
2164     while (lpMMThd->dwCounter) {
2165         Sleep(1);
2166         /* K32WOWYield16();*/
2167     }
2168     TRACE("[XX-%p]\n", lpMMThd->hThread);
2169     /* paranoia */
2170     lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
2171     /* close lpMMThread->hVxD directIO */
2172     if (lpMMThd->hEvent)
2173         CloseHandle(lpMMThd->hEvent);
2174     GlobalFree16(hndl);
2175     TRACE("done\n");
2176 }
2177
2178 typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
2179
2180 /**************************************************************************
2181  *                      mmShowMMCPLPropertySheet        [MMSYSTEM.1150]
2182  */
2183 BOOL16  WINAPI  mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
2184                                            LPCSTR lpStrTab, LPCSTR lpStrTitle)
2185 {
2186     HANDLE      hndl;
2187     BOOL16      ret = FALSE;
2188
2189     TRACE("(%p \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2190
2191     hndl = LoadLibraryA("MMSYS.CPL");
2192     if (hndl != 0) {
2193         MMCPLCALLBACK   fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
2194         if (fp != NULL) {
2195             DWORD       lc;
2196             ReleaseThunkLock(&lc);
2197             ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2198             RestoreThunkLock(lc);
2199         }
2200         FreeLibrary(hndl);
2201     }
2202
2203     return ret;
2204 }
2205
2206 /**************************************************************************
2207  *                      StackEnter              [MMSYSTEM.32]
2208  */
2209 void WINAPI StackEnter16(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  *                      StackLeave              [MMSYSTEM.33]
2219  */
2220 void WINAPI StackLeave16(void)
2221 {
2222 #ifdef __i386__
2223     /* mmsystem.dll from Win 95 does only this: so does Wine */
2224     __asm__("stc");
2225 #endif
2226 }
2227
2228 /**************************************************************************
2229  *                      WMMMidiRunOnce          [MMSYSTEM.8]
2230  */
2231 void WINAPI WMMMidiRunOnce16(void)
2232 {
2233     FIXME("(), stub!\n");
2234 }
2235
2236 /* ###################################################
2237  * #                    DRIVER                       #
2238  * ###################################################
2239  */
2240
2241 /**************************************************************************
2242  *                              DRIVER_MapMsg32To16             [internal]
2243  *
2244  * Map a 32 bit driver message to a 16 bit driver message.
2245  */
2246 static WINMM_MapType DRIVER_MapMsg32To16(WORD wMsg, DWORD* lParam1, DWORD* lParam2)
2247 {
2248     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
2249
2250     switch (wMsg) {
2251     case DRV_LOAD:
2252     case DRV_ENABLE:
2253     case DRV_DISABLE:
2254     case DRV_FREE:
2255     case DRV_QUERYCONFIGURE:
2256     case DRV_REMOVE:
2257     case DRV_EXITSESSION:
2258     case DRV_EXITAPPLICATION:
2259     case DRV_POWER:
2260     case DRV_CLOSE:     /* should be 0/0 */
2261     case DRV_OPEN:      /* pass through */
2262         /* lParam1 and lParam2 are not used */
2263         ret = WINMM_MAP_OK;
2264         break;
2265     case DRV_CONFIGURE:
2266     case DRV_INSTALL:
2267         /* lParam1 is a handle to a window (conf) or to a driver (inst) or not used,
2268          * lParam2 is a pointer to DRVCONFIGINFO
2269          */
2270         if (*lParam2) {
2271             LPDRVCONFIGINFO16 dci16 = HeapAlloc( GetProcessHeap(), 0, sizeof(*dci16) );
2272             LPDRVCONFIGINFO     dci32 = (LPDRVCONFIGINFO)(*lParam2);
2273
2274             if (dci16) {
2275                 LPSTR str1;
2276                 INT len;
2277                 dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
2278
2279                 if (dci32->lpszDCISectionName) {
2280                     len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, NULL, 0, NULL, NULL );
2281                     str1 = HeapAlloc( GetProcessHeap(), 0, len );
2282                     if (str1) {
2283                         WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, str1, len, NULL, NULL );
2284                         dci16->lpszDCISectionName = MapLS( str1 );
2285                     } else {
2286                         return WINMM_MAP_NOMEM;
2287                     }
2288                 } else {
2289                     dci16->lpszDCISectionName = 0L;
2290                 }
2291                 if (dci32->lpszDCIAliasName) {
2292                     len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, NULL, 0, NULL, NULL );
2293                     str1 = HeapAlloc( GetProcessHeap(), 0, len );
2294                     if (str1) {
2295                         WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, str1, len, NULL, NULL );
2296                         dci16->lpszDCIAliasName = MapLS( str1 );
2297                     } else {
2298                         return WINMM_MAP_NOMEM;
2299                     }
2300                 } else {
2301                     dci16->lpszDCISectionName = 0L;
2302                 }
2303             } else {
2304                 return WINMM_MAP_NOMEM;
2305             }
2306             *lParam2 = MapLS( dci16 );
2307             ret = WINMM_MAP_OKMEM;
2308         } else {
2309             ret = WINMM_MAP_OK;
2310         }
2311         break;
2312     default:
2313         if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2314            FIXME("Unknown message 0x%04x\n", wMsg);
2315         }
2316         ret = WINMM_MAP_OK;
2317     }
2318     return ret;
2319 }
2320
2321 /**************************************************************************
2322  *                              DRIVER_UnMapMsg32To16           [internal]
2323  *
2324  * UnMap a 32 bit driver message to a 16 bit driver message.
2325  */
2326 static WINMM_MapType DRIVER_UnMapMsg32To16(WORD wMsg, DWORD lParam1, DWORD lParam2)
2327 {
2328     WINMM_MapType       ret = WINMM_MAP_MSGERROR;
2329
2330     switch (wMsg) {
2331     case DRV_LOAD:
2332     case DRV_ENABLE:
2333     case DRV_DISABLE:
2334     case DRV_FREE:
2335     case DRV_QUERYCONFIGURE:
2336     case DRV_REMOVE:
2337     case DRV_EXITSESSION:
2338     case DRV_EXITAPPLICATION:
2339     case DRV_POWER:
2340     case DRV_OPEN:
2341     case DRV_CLOSE:
2342         /* lParam1 and lParam2 are not used */
2343         break;
2344     case DRV_CONFIGURE:
2345     case DRV_INSTALL:
2346         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
2347         if (lParam2) {
2348             LPDRVCONFIGINFO16   dci16 = MapSL(lParam2);
2349             HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCISectionName) );
2350             HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCIAliasName) );
2351             UnMapLS( lParam2 );
2352             UnMapLS( dci16->lpszDCISectionName );
2353             UnMapLS( dci16->lpszDCIAliasName );
2354             HeapFree( GetProcessHeap(), 0, dci16 );
2355         }
2356         ret = WINMM_MAP_OK;
2357         break;
2358     default:
2359         if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2360             FIXME("Unknown message 0x%04x\n", wMsg);
2361         }
2362         ret = WINMM_MAP_OK;
2363     }
2364     return ret;
2365 }
2366
2367 /**************************************************************************
2368  *                              DRIVER_TryOpenDriver16          [internal]
2369  *
2370  * Tries to load a 16 bit driver whose DLL's (module) name is lpFileName.
2371  */
2372 static  LPWINE_DRIVER   DRIVER_OpenDriver16(LPCSTR fn, LPCSTR sn, LPARAM lParam2)
2373 {
2374     LPWINE_DRIVER       lpDrv = NULL;
2375     LPCSTR              cause = 0;
2376
2377     TRACE("(%s, %08lX);\n", debugstr_a(sn), lParam2);
2378
2379     lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
2380     if (lpDrv == NULL) {cause = "OOM"; goto exit;}
2381
2382     /* FIXME: shall we do some black magic here on sn ?
2383      *  drivers32 => drivers
2384      *  mci32 => mci
2385      * ...
2386      */
2387     lpDrv->d.d16.hDriver16 = OpenDriver16(fn, sn, lParam2);
2388     if (lpDrv->d.d16.hDriver16 == 0) {cause = "Not a 16 bit driver"; goto exit;}
2389     lpDrv->dwFlags = WINE_GDF_16BIT;
2390
2391     TRACE("=> %p\n", lpDrv);
2392     return lpDrv;
2393  exit:
2394     HeapFree(GetProcessHeap(), 0, lpDrv);
2395     TRACE("Unable to load 16 bit module %s: %s\n", debugstr_a(fn), cause);
2396     return NULL;
2397 }
2398
2399 /******************************************************************
2400  *              DRIVER_SendMessage16
2401  *
2402  *
2403  */
2404 static LRESULT  DRIVER_SendMessage16(HDRVR16 hDrv16, UINT msg, 
2405                                      LPARAM lParam1, LPARAM lParam2)
2406 {
2407     LRESULT             ret = 0;
2408     WINMM_MapType       map;
2409
2410     TRACE("Before sdm16 call hDrv=%04x wMsg=%04x p1=%08lx p2=%08lx\n",
2411           hDrv16, msg, lParam1, lParam2);
2412
2413     switch (map = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2)) {
2414     case WINMM_MAP_OKMEM:
2415     case WINMM_MAP_OK:
2416         ret = SendDriverMessage16(hDrv16, msg, lParam1, lParam2);
2417         if (map == WINMM_MAP_OKMEM)
2418             DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
2419     default:
2420         break;
2421     }
2422     return ret;
2423 }
2424
2425 /******************************************************************
2426  *              DRIVER_CloseDriver16
2427  *
2428  *
2429  */
2430 static LRESULT DRIVER_CloseDriver16(HDRVR16 hDrv16, LPARAM lParam1, LPARAM lParam2)
2431 {
2432     return CloseDriver16(hDrv16, lParam1, lParam2);
2433 }
2434
2435 /**************************************************************************
2436  *                              DrvOpen                 [MMSYSTEM.1100]
2437  */
2438 HDRVR16 WINAPI DrvOpen16(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
2439 {
2440     return OpenDriver16(lpDriverName, lpSectionName, lParam);
2441 }
2442
2443 /**************************************************************************
2444  *                              DrvClose                [MMSYSTEM.1101]
2445  */
2446 LRESULT WINAPI DrvClose16(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
2447 {
2448     return CloseDriver16(hDrv, lParam1, lParam2);
2449 }
2450
2451 /**************************************************************************
2452  *                              DrvSendMessage          [MMSYSTEM.1102]
2453  */
2454 LRESULT WINAPI DrvSendMessage16(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
2455                                 LPARAM lParam2)
2456 {
2457     return SendDriverMessage16(hDrv, msg, lParam1, lParam2);
2458 }
2459
2460 /**************************************************************************
2461  *                              DrvGetModuleHandle      [MMSYSTEM.1103]
2462  */
2463 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
2464 {
2465     return GetDriverModuleHandle16(hDrv);
2466 }
2467
2468 /**************************************************************************
2469  *                              DrvDefDriverProc        [MMSYSTEM.1104]
2470  */
2471 LRESULT WINAPI DrvDefDriverProc16(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
2472                                   DWORD dwParam1, DWORD dwParam2)
2473 {
2474     return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
2475 }
2476
2477 /**************************************************************************
2478  *                              DriverProc                      [MMSYSTEM.6]
2479  */
2480 LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
2481                             DWORD dwParam1, DWORD dwParam2)
2482 {
2483     TRACE("dwDevID=%08lx hDrv=%04x wMsg=%04x dwParam1=%08lx dwParam2=%08lx\n",
2484           dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2485
2486     return DrvDefDriverProc16(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2487 }
2488
2489 /* ###################################################
2490  * #                     TIME                        #
2491  * ###################################################
2492  */
2493
2494 /******************************************************************
2495  *              MMSYSTEM_MMTIME32to16
2496  *
2497  *
2498  */
2499 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16, const MMTIME* mmt32)
2500 {
2501     mmt16->wType = mmt32->wType;
2502     /* layout of rest is the same for 32/16,
2503      * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2504      */
2505     memcpy(&(mmt16->u), &(mmt32->u), sizeof(mmt16->u));
2506 }
2507
2508 /******************************************************************
2509  *              MMSYSTEM_MMTIME16to32
2510  *
2511  *
2512  */
2513 void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32, const MMTIME16* mmt16)
2514 {
2515     mmt32->wType = mmt16->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(&(mmt32->u), &(mmt16->u), sizeof(mmt16->u));
2520 }
2521
2522 /**************************************************************************
2523  *                              timeGetSystemTime       [MMSYSTEM.601]
2524  */
2525 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
2526 {
2527     TRACE("(%p, %u);\n", lpTime, wSize);
2528
2529     if (wSize >= sizeof(*lpTime)) {
2530         lpTime->wType = TIME_MS;
2531         TIME_MMTimeStart();
2532         lpTime->u.ms = WINMM_SysTimeMS;
2533
2534         TRACE("=> %lu\n", lpTime->u.ms);
2535     }
2536
2537     return 0;
2538 }
2539
2540 /**************************************************************************
2541  *                              timeSetEvent            [MMSYSTEM.602]
2542  */
2543 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol, LPTIMECALLBACK16 lpFunc,
2544                                  DWORD dwUser, UINT16 wFlags)
2545 {
2546     if (wFlags & WINE_TIMER_IS32)
2547         WARN("Unknown windows flag... wine internally used.. ooch\n");
2548
2549     return TIME_SetEventInternal(wDelay, wResol, (LPTIMECALLBACK)lpFunc,
2550                                  dwUser, wFlags & ~WINE_TIMER_IS32);
2551 }
2552
2553 /**************************************************************************
2554  *                              timeKillEvent           [MMSYSTEM.603]
2555  */
2556 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
2557 {
2558     return timeKillEvent(wID);
2559 }
2560
2561 /**************************************************************************
2562  *                              timeGetDevCaps          [MMSYSTEM.604]
2563  */
2564 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
2565 {
2566     TIMECAPS    caps;
2567     MMRESULT    ret;
2568     TRACE("(%p, %u) !\n", lpCaps, wSize);
2569
2570     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2571
2572     ret = timeGetDevCaps(&caps, sizeof(caps));
2573     if (ret == MMSYSERR_NOERROR) {
2574         TIMECAPS16 tc16;
2575         tc16.wPeriodMin = caps.wPeriodMin;
2576         tc16.wPeriodMax = caps.wPeriodMax;
2577         memcpy(lpCaps, &tc16, min(wSize, sizeof(tc16)));
2578     }
2579     return ret;
2580 }
2581
2582 /**************************************************************************
2583  *                              timeBeginPeriod [MMSYSTEM.605]
2584  */
2585 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
2586 {
2587     TRACE("(%u) !\n", wPeriod);
2588
2589     return timeBeginPeriod(wPeriod);
2590 }
2591
2592 /**************************************************************************
2593  *                              timeEndPeriod           [MMSYSTEM.606]
2594  */
2595 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
2596 {
2597     TRACE("(%u) !\n", wPeriod);
2598
2599     return timeEndPeriod(wPeriod);
2600 }
2601
2602 /**************************************************************************
2603  *                              mciSendString                   [MMSYSTEM.702]
2604  */
2605 DWORD WINAPI mciSendString16(LPCSTR lpstrCommand, LPSTR lpstrRet,
2606                              UINT16 uRetLen, HWND16 hwndCallback)
2607 {
2608     return mciSendStringA(lpstrCommand, lpstrRet, uRetLen, HWND_32(hwndCallback));
2609 }
2610
2611 /**************************************************************************
2612  *                      mciLoadCommandResource                  [MMSYSTEM.705]
2613  */
2614 UINT16 WINAPI mciLoadCommandResource16(HINSTANCE16 hInst, LPCSTR resname, UINT16 type)
2615 {
2616     HRSRC16 res;
2617     HGLOBAL16 handle;
2618     void *ptr;
2619
2620     if (!(res = FindResource16( hInst, resname, (LPSTR)RT_RCDATA))) return MCI_NO_COMMAND_TABLE;
2621     if (!(handle = LoadResource16( hInst, res ))) return MCI_NO_COMMAND_TABLE;
2622     ptr = LockResource16(handle);
2623     return MCI_SetCommandTable(ptr, type);
2624     /* FIXME: FreeResource */
2625 }
2626
2627 /**************************************************************************
2628  *                      mciFreeCommandResource                  [MMSYSTEM.713]
2629  */
2630 BOOL16 WINAPI mciFreeCommandResource16(UINT16 uTable)
2631 {
2632     TRACE("(%04x)!\n", uTable);
2633
2634     return mciFreeCommandResource(uTable);
2635 }
2636
2637 /* ###################################################
2638  * #                     MMIO                        #
2639  * ###################################################
2640  */
2641
2642 /****************************************************************
2643  *                      MMIO_Map32To16                  [INTERNAL]
2644  */
2645 static LRESULT  MMIO_Map32To16(DWORD wMsg, LPARAM* lp1, LPARAM* lp2)
2646 {
2647     switch (wMsg) {
2648     case MMIOM_CLOSE:
2649     case MMIOM_SEEK:
2650         /* nothing to do */
2651         break;
2652     case MMIOM_OPEN:
2653     case MMIOM_READ:
2654     case MMIOM_WRITE:
2655     case MMIOM_WRITEFLUSH:
2656         *lp1 = MapLS( (void *)*lp1 );
2657         break;
2658     case MMIOM_RENAME:
2659         *lp1 = MapLS( (void *)*lp1 );
2660         *lp2 = MapLS( (void *)*lp2 );
2661         break;
2662     default:
2663         if (wMsg < MMIOM_USER)
2664             TRACE("Not a mappable message (%ld)\n", wMsg);
2665     }
2666     return MMSYSERR_NOERROR;
2667 }
2668
2669 /****************************************************************
2670  *              MMIO_UnMap32To16                        [INTERNAL]
2671  */
2672 static LRESULT  MMIO_UnMap32To16(DWORD wMsg, LPARAM lParam1, LPARAM lParam2,
2673                                  LPARAM lp1, LPARAM lp2)
2674 {
2675     switch (wMsg) {
2676     case MMIOM_CLOSE:
2677     case MMIOM_SEEK:
2678         /* nothing to do */
2679         break;
2680     case MMIOM_OPEN:
2681     case MMIOM_READ:
2682     case MMIOM_WRITE:
2683     case MMIOM_WRITEFLUSH:
2684         UnMapLS( lp1 );
2685         break;
2686     case MMIOM_RENAME:
2687         UnMapLS( lp1 );
2688         UnMapLS( lp2 );
2689         break;
2690     default:
2691         if (wMsg < MMIOM_USER)
2692             TRACE("Not a mappable message (%ld)\n", wMsg);
2693     }
2694     return MMSYSERR_NOERROR;
2695 }
2696
2697 /******************************************************************
2698  *              MMIO_Callback16
2699  *
2700  *
2701  */
2702 static LRESULT MMIO_Callback16(SEGPTR cb16, LPMMIOINFO lpmmioinfo, UINT uMessage,
2703                                LPARAM lParam1, LPARAM lParam2)
2704 {
2705     LRESULT             result;
2706     MMIOINFO16          mmioInfo16;
2707     SEGPTR              segmmioInfo16;
2708     LPARAM              lp1 = lParam1, lp2 = lParam2;
2709     WORD args[7];
2710
2711     memset(&mmioInfo16, 0, sizeof(MMIOINFO16));
2712     mmioInfo16.lDiskOffset = lpmmioinfo->lDiskOffset;
2713     mmioInfo16.adwInfo[0]  = lpmmioinfo->adwInfo[0];
2714     mmioInfo16.adwInfo[1]  = lpmmioinfo->adwInfo[1];
2715     mmioInfo16.adwInfo[2]  = lpmmioinfo->adwInfo[2];
2716     mmioInfo16.adwInfo[3]  = lpmmioinfo->adwInfo[3];
2717     /* map (lParam1, lParam2) into (lp1, lp2) 32=>16 */
2718     if ((result = MMIO_Map32To16(uMessage, &lp1, &lp2)) != MMSYSERR_NOERROR)
2719         return result;
2720
2721     segmmioInfo16 = MapLS(&mmioInfo16);
2722     args[6] = HIWORD(segmmioInfo16);
2723     args[5] = LOWORD(segmmioInfo16);
2724     args[4] = uMessage;
2725     args[3] = HIWORD(lp1);
2726     args[2] = LOWORD(lp1);
2727     args[1] = HIWORD(lp2);
2728     args[0] = LOWORD(lp2);
2729     WOWCallback16Ex( cb16, WCB16_PASCAL, sizeof(args), args, &result );
2730     UnMapLS(segmmioInfo16);
2731     MMIO_UnMap32To16(uMessage, lParam1, lParam2, lp1, lp2);
2732
2733     lpmmioinfo->lDiskOffset = mmioInfo16.lDiskOffset;
2734     lpmmioinfo->adwInfo[0]  = mmioInfo16.adwInfo[0];
2735     lpmmioinfo->adwInfo[1]  = mmioInfo16.adwInfo[1];
2736     lpmmioinfo->adwInfo[2]  = mmioInfo16.adwInfo[2];
2737     lpmmioinfo->adwInfo[3]  = mmioInfo16.adwInfo[3];
2738
2739     return result;
2740 }
2741
2742 /******************************************************************
2743  *             MMIO_ResetSegmentedData
2744  *
2745  */
2746 static LRESULT     MMIO_SetSegmentedBuffer(HMMIO hmmio, SEGPTR ptr, BOOL release)
2747 {
2748     LPWINE_MMIO         wm;
2749
2750     if ((wm = MMIO_Get(hmmio)) == NULL)
2751         return MMSYSERR_INVALHANDLE;
2752     if (release) UnMapLS(wm->segBuffer16);
2753     wm->segBuffer16 = ptr;
2754     return MMSYSERR_NOERROR;
2755 }
2756
2757 /**************************************************************************
2758  *                              mmioOpen                [MMSYSTEM.1210]
2759  */
2760 HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16* lpmmioinfo16,
2761                           DWORD dwOpenFlags)
2762 {
2763     HMMIO       ret;
2764
2765     if (lpmmioinfo16) {
2766         MMIOINFO        mmioinfo;
2767
2768         memset(&mmioinfo, 0, sizeof(mmioinfo));
2769
2770         mmioinfo.dwFlags     = lpmmioinfo16->dwFlags;
2771         mmioinfo.fccIOProc   = lpmmioinfo16->fccIOProc;
2772         mmioinfo.pIOProc     = (LPMMIOPROC)lpmmioinfo16->pIOProc;
2773         mmioinfo.cchBuffer   = lpmmioinfo16->cchBuffer;
2774         mmioinfo.pchBuffer   = MapSL((DWORD)lpmmioinfo16->pchBuffer);
2775         mmioinfo.adwInfo[0]  = lpmmioinfo16->adwInfo[0];
2776         /* if we don't have a file name, it's likely a passed open file descriptor */
2777         if (!szFileName) 
2778             mmioinfo.adwInfo[0] = (DWORD)DosFileHandleToWin32Handle(mmioinfo.adwInfo[0]);
2779         mmioinfo.adwInfo[1]  = lpmmioinfo16->adwInfo[1];
2780         mmioinfo.adwInfo[2]  = lpmmioinfo16->adwInfo[2];
2781         mmioinfo.adwInfo[3]  = lpmmioinfo16->adwInfo[3];
2782
2783         ret = MMIO_Open(szFileName, &mmioinfo, dwOpenFlags, MMIO_PROC_16);
2784         MMIO_SetSegmentedBuffer(mmioinfo.hmmio, (SEGPTR)lpmmioinfo16->pchBuffer, FALSE);
2785
2786         lpmmioinfo16->wErrorRet = mmioinfo.wErrorRet;
2787         lpmmioinfo16->hmmio     = HMMIO_16(mmioinfo.hmmio);
2788     } else {
2789         ret = MMIO_Open(szFileName, NULL, dwOpenFlags, MMIO_PROC_32A);
2790     }
2791     return HMMIO_16(ret);
2792 }
2793
2794 /**************************************************************************
2795  *                              mmioClose               [MMSYSTEM.1211]
2796  */
2797 MMRESULT16 WINAPI mmioClose16(HMMIO16 hmmio, UINT16 uFlags)
2798 {
2799     MMIO_SetSegmentedBuffer(HMMIO_32(hmmio), (SEGPTR)NULL, TRUE);
2800     return mmioClose(HMMIO_32(hmmio), uFlags);
2801 }
2802
2803 /**************************************************************************
2804  *                              mmioRead                [MMSYSTEM.1212]
2805  */
2806 LONG WINAPI mmioRead16(HMMIO16 hmmio, HPSTR pch, LONG cch)
2807 {
2808     return mmioRead(HMMIO_32(hmmio), pch, cch);
2809 }
2810
2811 /**************************************************************************
2812  *                              mmioWrite               [MMSYSTEM.1213]
2813  */
2814 LONG WINAPI mmioWrite16(HMMIO16 hmmio, HPCSTR pch, LONG cch)
2815 {
2816     return mmioWrite(HMMIO_32(hmmio),pch,cch);
2817 }
2818
2819 /**************************************************************************
2820  *                              mmioSeek                [MMSYSTEM.1214]
2821  */
2822 LONG WINAPI mmioSeek16(HMMIO16 hmmio, LONG lOffset, INT16 iOrigin)
2823 {
2824     return mmioSeek(HMMIO_32(hmmio), lOffset, iOrigin);
2825 }
2826
2827 /**************************************************************************
2828  *                              mmioGetInfo             [MMSYSTEM.1215]
2829  */
2830 MMRESULT16 WINAPI mmioGetInfo16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags)
2831 {
2832     MMIOINFO            mmioinfo;
2833     MMRESULT            ret;
2834     LPWINE_MMIO         wm;
2835
2836     TRACE("(0x%04x,%p,0x%08x)\n", hmmio, lpmmioinfo, uFlags);
2837
2838     if ((wm = MMIO_Get(HMMIO_32(hmmio))) == NULL)
2839         return MMSYSERR_INVALHANDLE;
2840
2841     ret = mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, uFlags);
2842     if (ret != MMSYSERR_NOERROR) return ret;
2843
2844     lpmmioinfo->dwFlags     = mmioinfo.dwFlags;
2845     lpmmioinfo->fccIOProc   = mmioinfo.fccIOProc;
2846     lpmmioinfo->pIOProc     = (wm->ioProc->type == MMIO_PROC_16) ?
2847         (LPMMIOPROC16)wm->ioProc->pIOProc : NULL;
2848     lpmmioinfo->wErrorRet   = mmioinfo.wErrorRet;
2849     lpmmioinfo->hTask       = HTASK_16(mmioinfo.hTask);
2850     lpmmioinfo->cchBuffer   = mmioinfo.cchBuffer;
2851     lpmmioinfo->pchBuffer   = (void*)wm->segBuffer16;
2852     lpmmioinfo->pchNext     = (void*)(wm->segBuffer16 + (mmioinfo.pchNext - mmioinfo.pchBuffer));
2853     lpmmioinfo->pchEndRead  = (void*)(wm->segBuffer16 + (mmioinfo.pchEndRead - mmioinfo.pchBuffer));
2854     lpmmioinfo->pchEndWrite = (void*)(wm->segBuffer16 + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer));
2855     lpmmioinfo->lBufOffset  = mmioinfo.lBufOffset;
2856     lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset;
2857     lpmmioinfo->adwInfo[0]  = mmioinfo.adwInfo[0];
2858     lpmmioinfo->adwInfo[1]  = mmioinfo.adwInfo[1];
2859     lpmmioinfo->adwInfo[2]  = mmioinfo.adwInfo[2];
2860     lpmmioinfo->adwInfo[3]  = mmioinfo.adwInfo[3];
2861     lpmmioinfo->dwReserved1 = 0;
2862     lpmmioinfo->dwReserved2 = 0;
2863     lpmmioinfo->hmmio = HMMIO_16(mmioinfo.hmmio);
2864
2865     return MMSYSERR_NOERROR;
2866 }
2867
2868 /**************************************************************************
2869  *                              mmioSetInfo             [MMSYSTEM.1216]
2870  */
2871 MMRESULT16 WINAPI mmioSetInfo16(HMMIO16 hmmio, const MMIOINFO16* lpmmioinfo, UINT16 uFlags)
2872 {
2873     MMIOINFO            mmioinfo;
2874     MMRESULT            ret;
2875
2876     TRACE("(0x%04x,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
2877
2878     ret = mmioGetInfo(HMMIO_32(hmmio), &mmioinfo, 0);
2879     if (ret != MMSYSERR_NOERROR) return ret;
2880
2881     /* check if seg and lin buffers are the same */
2882     if (mmioinfo.cchBuffer != lpmmioinfo->cchBuffer  ||
2883         mmioinfo.pchBuffer != MapSL((DWORD)lpmmioinfo->pchBuffer)) 
2884         return MMSYSERR_INVALPARAM;
2885
2886     /* check pointers coherence */
2887     if (lpmmioinfo->pchNext < lpmmioinfo->pchBuffer ||
2888         lpmmioinfo->pchNext > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer ||
2889         lpmmioinfo->pchEndRead < lpmmioinfo->pchBuffer ||
2890         lpmmioinfo->pchEndRead > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer ||
2891         lpmmioinfo->pchEndWrite < lpmmioinfo->pchBuffer ||
2892         lpmmioinfo->pchEndWrite > lpmmioinfo->pchBuffer + lpmmioinfo->cchBuffer)
2893         return MMSYSERR_INVALPARAM;
2894
2895     mmioinfo.pchNext     = mmioinfo.pchBuffer + (lpmmioinfo->pchNext     - lpmmioinfo->pchBuffer);
2896     mmioinfo.pchEndRead  = mmioinfo.pchBuffer + (lpmmioinfo->pchEndRead  - lpmmioinfo->pchBuffer);
2897     mmioinfo.pchEndWrite = mmioinfo.pchBuffer + (lpmmioinfo->pchEndWrite - lpmmioinfo->pchBuffer);
2898
2899     return mmioSetInfo(HMMIO_32(hmmio), &mmioinfo, uFlags);
2900 }
2901
2902 /**************************************************************************
2903  *                              mmioSetBuffer           [MMSYSTEM.1217]
2904  */
2905 MMRESULT16 WINAPI mmioSetBuffer16(HMMIO16 hmmio, LPSTR pchBuffer,
2906                                   LONG cchBuffer, UINT16 uFlags)
2907 {
2908     MMRESULT    ret = mmioSetBuffer(HMMIO_32(hmmio), MapSL((DWORD)pchBuffer), 
2909                                     cchBuffer, uFlags);
2910
2911     if (ret == MMSYSERR_NOERROR)
2912         MMIO_SetSegmentedBuffer(HMMIO_32(hmmio), (DWORD)pchBuffer, TRUE);
2913     else
2914         UnMapLS((DWORD)pchBuffer);
2915     return ret;
2916 }
2917
2918 /**************************************************************************
2919  *                              mmioFlush               [MMSYSTEM.1218]
2920  */
2921 MMRESULT16 WINAPI mmioFlush16(HMMIO16 hmmio, UINT16 uFlags)
2922 {
2923     return mmioFlush(HMMIO_32(hmmio), uFlags);
2924 }
2925
2926 /***********************************************************************
2927  *                              mmioAdvance             [MMSYSTEM.1219]
2928  */
2929 MMRESULT16 WINAPI mmioAdvance16(HMMIO16 hmmio, MMIOINFO16* lpmmioinfo, UINT16 uFlags)
2930 {
2931     MMIOINFO    mmioinfo;
2932     LRESULT     ret;
2933
2934     /* WARNING: this heavily relies on mmioAdvance implementation (for choosing which
2935      * fields to init
2936      */
2937     if (lpmmioinfo)
2938     {
2939         mmioinfo.pchBuffer = MapSL((DWORD)lpmmioinfo->pchBuffer);
2940         mmioinfo.pchNext = MapSL((DWORD)lpmmioinfo->pchNext);
2941         mmioinfo.dwFlags = lpmmioinfo->dwFlags;
2942         mmioinfo.lBufOffset = lpmmioinfo->lBufOffset;
2943         ret = mmioAdvance(HMMIO_32(hmmio), &mmioinfo, uFlags);
2944     }
2945     else
2946         ret = mmioAdvance(HMMIO_32(hmmio), NULL, uFlags);
2947         
2948     if (ret != MMSYSERR_NOERROR) return ret;
2949
2950     if (lpmmioinfo)
2951     {
2952         lpmmioinfo->dwFlags = mmioinfo.dwFlags;
2953         lpmmioinfo->pchNext     = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchNext - mmioinfo.pchBuffer));
2954         lpmmioinfo->pchEndRead  = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndRead - mmioinfo.pchBuffer));
2955         lpmmioinfo->pchEndWrite = (void*)(lpmmioinfo->pchBuffer + (mmioinfo.pchEndWrite - mmioinfo.pchBuffer));
2956         lpmmioinfo->lBufOffset  = mmioinfo.lBufOffset;
2957         lpmmioinfo->lDiskOffset = mmioinfo.lDiskOffset;
2958     }
2959
2960     return MMSYSERR_NOERROR;
2961 }
2962
2963 /**************************************************************************
2964  *                              mmioStringToFOURCC      [MMSYSTEM.1220]
2965  */
2966 FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
2967 {
2968     return mmioStringToFOURCCA(sz, uFlags);
2969 }
2970
2971 /**************************************************************************
2972  *              mmioInstallIOProc    [MMSYSTEM.1221]
2973  */
2974 LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc, LPMMIOPROC16 pIOProc,
2975                                         DWORD dwFlags)
2976 {
2977     return (LPMMIOPROC16)MMIO_InstallIOProc(fccIOProc, (LPMMIOPROC)pIOProc,
2978                                             dwFlags, MMIO_PROC_16);
2979 }
2980
2981 /**************************************************************************
2982  *                              mmioSendMessage [MMSYSTEM.1222]
2983  */
2984 LRESULT WINAPI mmioSendMessage16(HMMIO16 hmmio, UINT16 uMessage,
2985                                  LPARAM lParam1, LPARAM lParam2)
2986 {
2987     return MMIO_SendMessage(HMMIO_32(hmmio), uMessage, 
2988                             lParam1, lParam2, MMIO_PROC_16);
2989 }
2990
2991 /**************************************************************************
2992  *                              mmioDescend             [MMSYSTEM.1223]
2993  */
2994 MMRESULT16 WINAPI mmioDescend16(HMMIO16 hmmio, LPMMCKINFO lpck,
2995                                 const MMCKINFO* lpckParent, UINT16 uFlags)
2996 {
2997     return mmioDescend(HMMIO_32(hmmio), lpck, lpckParent, uFlags);
2998 }
2999
3000 /**************************************************************************
3001  *                              mmioAscend              [MMSYSTEM.1224]
3002  */
3003 MMRESULT16 WINAPI mmioAscend16(HMMIO16 hmmio, MMCKINFO* lpck, UINT16 uFlags)
3004 {
3005     return mmioAscend(HMMIO_32(hmmio),lpck,uFlags);
3006 }
3007
3008 /**************************************************************************
3009  *                              mmioCreateChunk         [MMSYSTEM.1225]
3010  */
3011 MMRESULT16 WINAPI mmioCreateChunk16(HMMIO16 hmmio, MMCKINFO* lpck, UINT16 uFlags)
3012 {
3013     return mmioCreateChunk(HMMIO_32(hmmio), lpck, uFlags);
3014 }
3015
3016 /**************************************************************************
3017  *                              mmioRename              [MMSYSTEM.1226]
3018  */
3019 MMRESULT16 WINAPI mmioRename16(LPCSTR szFileName, LPCSTR szNewFileName,
3020                                MMIOINFO16* lpmmioinfo, DWORD dwRenameFlags)
3021 {
3022     BOOL        inst = FALSE;
3023     MMRESULT    ret;
3024     MMIOINFO    mmioinfo;
3025
3026     if (lpmmioinfo != NULL && lpmmioinfo->pIOProc != NULL && 
3027         lpmmioinfo->fccIOProc == 0) {
3028         FIXME("Can't handle this case yet\n");
3029         return MMSYSERR_ERROR;
3030     }
3031      
3032     /* this is a bit hacky, but it'll work if we get a fourCC code or nothing.
3033      * but a non installed ioproc without a fourcc won't do
3034      */
3035     if (lpmmioinfo && lpmmioinfo->fccIOProc && lpmmioinfo->pIOProc) {
3036         MMIO_InstallIOProc(lpmmioinfo->fccIOProc, (LPMMIOPROC)lpmmioinfo->pIOProc,
3037                            MMIO_INSTALLPROC, MMIO_PROC_16);
3038         inst = TRUE;
3039     }
3040     memset(&mmioinfo, 0, sizeof(mmioinfo));
3041     mmioinfo.fccIOProc = lpmmioinfo->fccIOProc;
3042     ret = mmioRenameA(szFileName, szNewFileName, &mmioinfo, dwRenameFlags);
3043     if (inst) {
3044         MMIO_InstallIOProc(lpmmioinfo->fccIOProc, NULL,
3045                            MMIO_REMOVEPROC, MMIO_PROC_16);
3046     }
3047     return ret;
3048 }
3049
3050 /* ###################################################
3051  * #                     JOYSTICK                    #
3052  * ###################################################
3053  */
3054
3055 /**************************************************************************
3056  *                              joyGetNumDevs           [MMSYSTEM.101]
3057  */
3058 UINT16 WINAPI joyGetNumDevs16(void)
3059 {
3060     return joyGetNumDevs();
3061 }
3062
3063 /**************************************************************************
3064  *                              joyGetDevCaps           [MMSYSTEM.102]
3065  */
3066 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
3067 {
3068     JOYCAPSA    jca;
3069     MMRESULT    ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
3070
3071     if (ret != JOYERR_NOERROR) return ret;
3072     lpCaps->wMid = jca.wMid;
3073     lpCaps->wPid = jca.wPid;
3074     strcpy(lpCaps->szPname, jca.szPname);
3075     lpCaps->wXmin = jca.wXmin;
3076     lpCaps->wXmax = jca.wXmax;
3077     lpCaps->wYmin = jca.wYmin;
3078     lpCaps->wYmax = jca.wYmax;
3079     lpCaps->wZmin = jca.wZmin;
3080     lpCaps->wZmax = jca.wZmax;
3081     lpCaps->wNumButtons = jca.wNumButtons;
3082     lpCaps->wPeriodMin = jca.wPeriodMin;
3083     lpCaps->wPeriodMax = jca.wPeriodMax;
3084
3085     if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
3086         lpCaps->wRmin = jca.wRmin;
3087         lpCaps->wRmax = jca.wRmax;
3088         lpCaps->wUmin = jca.wUmin;
3089         lpCaps->wUmax = jca.wUmax;
3090         lpCaps->wVmin = jca.wVmin;
3091         lpCaps->wVmax = jca.wVmax;
3092         lpCaps->wCaps = jca.wCaps;
3093         lpCaps->wMaxAxes = jca.wMaxAxes;
3094         lpCaps->wNumAxes = jca.wNumAxes;
3095         lpCaps->wMaxButtons = jca.wMaxButtons;
3096         strcpy(lpCaps->szRegKey, jca.szRegKey);
3097         strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
3098     }
3099
3100     return ret;
3101 }
3102
3103 /**************************************************************************
3104  *                              joyGetPosEx           [MMSYSTEM.110]
3105  */
3106 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
3107 {
3108     return joyGetPosEx(wID, lpInfo);
3109 }
3110
3111 /**************************************************************************
3112  *                              joyGetPos               [MMSYSTEM.103]
3113  */
3114 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
3115 {
3116     JOYINFO     ji;
3117     MMRESULT    ret;
3118
3119     TRACE("(%d, %p);\n", wID, lpInfo);
3120
3121     if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
3122         lpInfo->wXpos = ji.wXpos;
3123         lpInfo->wYpos = ji.wYpos;
3124         lpInfo->wZpos = ji.wZpos;
3125         lpInfo->wButtons = ji.wButtons;
3126     }
3127     return ret;
3128 }
3129
3130 /**************************************************************************
3131  *                              joyGetThreshold         [MMSYSTEM.104]
3132  */
3133 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
3134 {
3135     UINT        t;
3136     MMRESULT    ret;
3137
3138     ret = joyGetThreshold(wID, &t);
3139     if (ret == JOYERR_NOERROR)
3140         *lpThreshold = t;
3141     return ret;
3142 }
3143
3144 /**************************************************************************
3145  *                              joyReleaseCapture       [MMSYSTEM.105]
3146  */
3147 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
3148 {
3149     return joyReleaseCapture(wID);
3150 }
3151
3152 /**************************************************************************
3153  *                              joySetCapture           [MMSYSTEM.106]
3154  */
3155 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
3156 {
3157     return joySetCapture16(hWnd, wID, wPeriod, bChanged);
3158 }
3159
3160 /**************************************************************************
3161  *                              joySetThreshold         [MMSYSTEM.107]
3162  */
3163 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
3164 {
3165     return joySetThreshold16(wID,wThreshold);
3166 }
3167
3168 /**************************************************************************
3169  *                              joySetCalibration       [MMSYSTEM.109]
3170  */
3171 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
3172 {
3173     FIXME("(%04X): stub.\n", wID);
3174     return JOYERR_NOCANDO;
3175 }