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