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