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