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