msvcrt: Added _wcsncoll and _wcsncoll_l implementation.
[wine] / dlls / mmsystem.dll16 / 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/list.h"
42 #include "wine/winuser16.h"
43 #include "winemm16.h"
44
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
48
49
50 static CRITICAL_SECTION_DEBUG mmdrv_critsect_debug =
51 {
52     0, 0, &mmdrv_cs,
53     { &mmdrv_critsect_debug.ProcessLocksList, &mmdrv_critsect_debug.ProcessLocksList },
54       0, 0, { (DWORD_PTR)(__FILE__ ": mmsystem_mmdrv_cs") }
55 };
56 CRITICAL_SECTION mmdrv_cs = { &mmdrv_critsect_debug, -1, 0, 0, 0, 0 };
57
58 /* ###################################################
59  * #                  LIBRARY                        #
60  * ###################################################
61  */
62
63 /**************************************************************************
64  *                      DllEntryPoint (MMSYSTEM.4)
65  *
66  * MMSYSTEM DLL entry point
67  *
68  */
69 BOOL WINAPI MMSYSTEM_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
70                              WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
71 {
72     static int done;
73
74     if (!done++) LoadLibrary16( "sound.drv" );
75     return TRUE;
76 }
77
78 /**************************************************************************
79  *                              WEP                     [MMSYSTEM.1]
80  */
81 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
82                         WORD cbHeapSize, LPSTR lpCmdLine)
83 {
84     TRACE("STUB: Unloading MMSystem DLL ... hInst=%04X\n", hInstance);
85     return TRUE;
86 }
87
88 /* ###################################################
89  * #                     TIME                        #
90  * ###################################################
91  */
92
93 /******************************************************************
94  *              MMSYSTEM_MMTIME32to16
95  *
96  *
97  */
98 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16, const MMTIME* mmt32)
99 {
100     mmt16->wType = mmt32->wType;
101     /* layout of rest is the same for 32/16,
102      * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
103      */
104     memcpy(&(mmt16->u), &(mmt32->u), sizeof(mmt16->u));
105 }
106
107 /**************************************************************************
108  *                              timeGetSystemTime       [MMSYSTEM.601]
109  */
110 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
111 {
112     if (wSize >= sizeof(*lpTime)) {
113         lpTime->wType = TIME_MS;
114         lpTime->u.ms = GetTickCount();
115
116         TRACE("=> %u\n", lpTime->u.ms);
117     }
118
119     return 0;
120 }
121
122 struct timer_entry {
123     struct list         entry;
124     UINT                id;
125     LPTIMECALLBACK16    func16;
126     DWORD               user;
127 };
128
129 static struct list timer_list = LIST_INIT(timer_list);
130
131 static void CALLBACK timeCB3216(UINT id, UINT uMsg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2)
132 {
133     struct timer_entry* te = (void*)user;
134     WORD                args[8];
135     DWORD               ret;
136
137     args[7] = LOWORD(id);
138     args[6] = LOWORD(uMsg);
139     args[5] = HIWORD(te->user);
140     args[4] = LOWORD(te->user);
141     args[3] = HIWORD(dw1);
142     args[2] = LOWORD(dw2);
143     args[1] = HIWORD(dw2);
144     args[0] = LOWORD(dw2);
145     WOWCallback16Ex((DWORD)te->func16, WCB16_PASCAL, sizeof(args), args, &ret);
146 }
147
148 /**************************************************************************
149  *                              timeSetEvent            [MMSYSTEM.602]
150  */
151 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol, LPTIMECALLBACK16 lpFunc,
152                                  DWORD dwUser, UINT16 wFlags)
153 {
154     MMRESULT16          id;
155     struct timer_entry* te;
156
157     switch (wFlags & (TIME_CALLBACK_EVENT_SET|TIME_CALLBACK_EVENT_PULSE))
158     {
159     case TIME_CALLBACK_EVENT_SET:
160     case TIME_CALLBACK_EVENT_PULSE:
161         id = timeSetEvent(wDelay, wResol, (LPTIMECALLBACK)lpFunc, dwUser, wFlags);
162         break;
163     case TIME_CALLBACK_FUNCTION:
164         te = HeapAlloc(GetProcessHeap(), 0, sizeof(*te));
165         if (!te) return 0;
166         te->func16 = lpFunc;
167         te->user = dwUser;
168         id = te->id = timeSetEvent(wDelay, wResol, timeCB3216, (DWORD_PTR)te, wFlags);
169         if (id)
170         {
171             EnterCriticalSection(&mmdrv_cs);
172             list_add_tail(&timer_list, &te->entry);
173             LeaveCriticalSection(&mmdrv_cs);
174         }
175         else HeapFree(GetProcessHeap(), 0, te);
176         break;
177     default:
178         id = 0;
179         break;
180     }
181     return id;
182 }
183
184 /**************************************************************************
185  *                              timeKillEvent           [MMSYSTEM.603]
186  */
187 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
188 {
189     MMRESULT16  ret = timeKillEvent(wID);
190     struct timer_entry* te;
191
192     if (ret == TIMERR_NOERROR)
193     {
194         EnterCriticalSection(&mmdrv_cs);
195         LIST_FOR_EACH_ENTRY(te, &timer_list, struct timer_entry, entry)
196         {
197             if (wID == te->id)
198             {
199                 list_remove(&te->entry);
200                 HeapFree(GetProcessHeap(), 0, te);
201                 break;
202             }
203         }
204         LeaveCriticalSection(&mmdrv_cs);
205     }
206     return ret;
207 }
208
209 /**************************************************************************
210  *                              timeGetDevCaps          [MMSYSTEM.604]
211  */
212 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
213 {
214     TIMECAPS    caps;
215     MMRESULT    ret;
216     TRACE("(%p, %u) !\n", lpCaps, wSize);
217
218     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
219
220     ret = timeGetDevCaps(&caps, sizeof(caps));
221     if (ret == MMSYSERR_NOERROR) {
222         TIMECAPS16 tc16;
223         tc16.wPeriodMin = caps.wPeriodMin;
224         tc16.wPeriodMax = caps.wPeriodMax;
225         memcpy(lpCaps, &tc16, min(wSize, sizeof(tc16)));
226     }
227     return ret;
228 }
229
230 /**************************************************************************
231  *                              timeBeginPeriod [MMSYSTEM.605]
232  */
233 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
234 {
235     TRACE("(%u) !\n", wPeriod);
236
237     return timeBeginPeriod(wPeriod);
238 }
239
240 /**************************************************************************
241  *                              timeEndPeriod           [MMSYSTEM.606]
242  */
243 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
244 {
245     TRACE("(%u) !\n", wPeriod);
246
247     return timeEndPeriod(wPeriod);
248 }
249
250 /**************************************************************************
251  *                              timeGetTime    [MMSYSTEM.607]
252  */
253 DWORD WINAPI timeGetTime16(void)
254 {
255     return timeGetTime();
256 }
257
258 /* ###################################################
259  * #                  PlaySound                      #
260  * ###################################################
261  */
262
263 /**************************************************************************
264  *                              PlaySound               [MMSYSTEM.3]
265  */
266 BOOL16 WINAPI PlaySound16(LPCSTR pszSound, HMODULE16 hmod, DWORD fdwSound)
267 {
268     BOOL16      retv;
269     DWORD       lc;
270
271     if ((fdwSound & SND_RESOURCE) == SND_RESOURCE)
272     {
273         HGLOBAL16 handle;
274         HRSRC16 res;
275
276         if (!(res = FindResource16( hmod, pszSound, "WAVE" ))) return FALSE;
277         if (!(handle = LoadResource16( hmod, res ))) return FALSE;
278         pszSound = LockResource16(handle);
279         fdwSound = (fdwSound & ~SND_RESOURCE) | SND_MEMORY;
280         /* FIXME: FreeResource16 */
281     }
282
283     ReleaseThunkLock(&lc);
284     retv = PlaySoundA(pszSound, 0, fdwSound);
285     RestoreThunkLock(lc);
286
287     return retv;
288 }
289
290 /**************************************************************************
291  *                              sndPlaySound            [MMSYSTEM.2]
292  */
293 BOOL16 WINAPI sndPlaySound16(LPCSTR lpszSoundName, UINT16 uFlags)
294 {
295     BOOL16      retv;
296     DWORD       lc;
297
298     ReleaseThunkLock(&lc);
299     retv = sndPlaySoundA(lpszSoundName, uFlags);
300     RestoreThunkLock(lc);
301
302     return retv;
303 }
304
305 /* ###################################################
306  * #                    MISC                         #
307  * ###################################################
308  */
309
310 /**************************************************************************
311  *                              mmsystemGetVersion      [MMSYSTEM.5]
312  *
313  */
314 UINT16 WINAPI mmsystemGetVersion16(void)
315 {
316     return mmsystemGetVersion();
317 }
318
319 /**************************************************************************
320  *                              DriverCallback                  [MMSYSTEM.31]
321  */
322 BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HDRVR16 hDev,
323                                WORD wMsg, DWORD dwUser, DWORD dwParam1,
324                                DWORD dwParam2)
325 {
326     return DriverCallback(dwCallBack, uFlags, HDRVR_32(hDev), wMsg, dwUser, dwParam1, dwParam2);
327 }
328
329 /**************************************************************************
330  *                      OutputDebugStr          [MMSYSTEM.30]
331  */
332 void WINAPI OutputDebugStr16(LPCSTR str)
333 {
334     OutputDebugStringA( str );
335 }
336
337 /* ###################################################
338  * #                    MIXER                        #
339  * ###################################################
340  */
341
342 /**************************************************************************
343  *      Mixer devices. New to Win95
344  */
345
346 /**************************************************************************
347  *                              mixerGetNumDevs                 [MMSYSTEM.800]
348  */
349 UINT16 WINAPI mixerGetNumDevs16(void)
350 {
351     return mixerGetNumDevs();
352 }
353
354 /**************************************************************************
355  *                              mixerGetDevCaps                 [MMSYSTEM.801]
356  */
357 UINT16 WINAPI mixerGetDevCaps16(UINT16 uDeviceID, LPMIXERCAPS16 lpCaps,
358                                 UINT16 uSize)
359 {
360     MIXERCAPSA  micA;
361     UINT        ret;
362
363     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
364
365     ret = mixerGetDevCapsA(uDeviceID, &micA, sizeof(micA));
366     if (ret == MMSYSERR_NOERROR) {
367         MIXERCAPS16 mic16;
368         mic16.wMid           = micA.wMid;
369         mic16.wPid           = micA.wPid;
370         mic16.vDriverVersion = micA.vDriverVersion;
371         strcpy(mic16.szPname, micA.szPname);
372         mic16.fdwSupport     = micA.fdwSupport;
373         mic16.cDestinations  = micA.cDestinations;
374         memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
375     }
376     return ret;
377 }
378
379 /**************************************************************************
380  *                              mixerOpen                       [MMSYSTEM.802]
381  */
382 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix, UINT16 uDeviceID, DWORD dwCallback,
383                           DWORD dwInstance, DWORD fdwOpen)
384 {
385     HMIXER                      hmix;
386     UINT                        ret;
387     struct mmsystdrv_thunk*     thunk;
388
389     if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, fdwOpen, MMSYSTDRV_MIXER)))
390     {
391         return MMSYSERR_NOMEM;
392     }
393     if ((fdwOpen & CALLBACK_TYPEMASK) != CALLBACK_NULL)
394         fdwOpen = (fdwOpen & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION;
395     ret = mixerOpen(&hmix, uDeviceID, (DWORD)thunk, dwInstance, fdwOpen);
396     if (ret == MMSYSERR_NOERROR)
397     {
398         if (lphmix) *lphmix = HMIXER_16(hmix);
399         if (thunk) MMSYSTDRV_SetHandle(thunk, hmix);
400     }
401     else MMSYSTDRV_DeleteThunk(thunk);
402     return ret;
403 }
404
405 /**************************************************************************
406  *                              mixerClose                      [MMSYSTEM.803]
407  */
408 UINT16 WINAPI mixerClose16(HMIXER16 hMix)
409 {
410     UINT        ret = mixerClose(HMIXER_32(hMix));
411
412     if (ret == MMSYSERR_NOERROR)
413         MMSYSTDRV_CloseHandle((void*)HMIXER_32(hMix));
414     return ret;
415 }
416
417 /**************************************************************************
418  *                              mixerGetID (MMSYSTEM.806)
419  */
420 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix, LPUINT16 lpid, DWORD fdwID)
421 {
422     UINT        xid;
423     UINT        ret = mixerGetID(HMIXEROBJ_32(hmix), &xid, fdwID);
424
425     if (lpid)
426         *lpid = xid;
427     return ret;
428 }
429
430 /**************************************************************************
431  *                              mixerGetControlDetails  [MMSYSTEM.808]
432  */
433 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix,
434                                        LPMIXERCONTROLDETAILS16 lpmcd,
435                                        DWORD fdwDetails)
436 {
437     DWORD       ret = MMSYSERR_NOTENABLED;
438     SEGPTR      sppaDetails;
439
440     TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
441
442     if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
443         return MMSYSERR_INVALPARAM;
444
445     sppaDetails = (SEGPTR)lpmcd->paDetails;
446     lpmcd->paDetails = MapSL(sppaDetails);
447     ret = mixerGetControlDetailsA(HMIXEROBJ_32(hmix),
448                                  (LPMIXERCONTROLDETAILS)lpmcd, fdwDetails);
449     lpmcd->paDetails = (LPVOID)sppaDetails;
450
451     return ret;
452 }
453
454 /**************************************************************************
455  *                              mixerGetLineControls            [MMSYSTEM.807]
456  */
457 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,
458                                      LPMIXERLINECONTROLS16 lpmlc16,
459                                      DWORD fdwControls)
460 {
461     MIXERLINECONTROLSA  mlcA;
462     DWORD               ret;
463     unsigned int        i;
464     LPMIXERCONTROL16    lpmc16;
465
466     TRACE("(%04x, %p, %08x)\n", hmix, lpmlc16, fdwControls);
467
468     if (lpmlc16 == NULL || lpmlc16->cbStruct != sizeof(*lpmlc16) ||
469         lpmlc16->cbmxctrl != sizeof(MIXERCONTROL16))
470         return MMSYSERR_INVALPARAM;
471
472     mlcA.cbStruct = sizeof(mlcA);
473     mlcA.dwLineID = lpmlc16->dwLineID;
474     mlcA.u.dwControlID = lpmlc16->u.dwControlID;
475     mlcA.u.dwControlType = lpmlc16->u.dwControlType;
476     mlcA.cControls = lpmlc16->cControls;
477     mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
478     mlcA.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
479                               mlcA.cControls * mlcA.cbmxctrl);
480
481     ret = mixerGetLineControlsA(HMIXEROBJ_32(hmix), &mlcA, fdwControls);
482
483     if (ret == MMSYSERR_NOERROR) {
484         lpmlc16->dwLineID = mlcA.dwLineID;
485         lpmlc16->u.dwControlID = mlcA.u.dwControlID;
486         lpmlc16->u.dwControlType = mlcA.u.dwControlType;
487         lpmlc16->cControls = mlcA.cControls;
488
489         lpmc16 = MapSL(lpmlc16->pamxctrl);
490
491         for (i = 0; i < mlcA.cControls; i++) {
492             lpmc16[i].cbStruct = sizeof(MIXERCONTROL16);
493             lpmc16[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
494             lpmc16[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
495             lpmc16[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
496             lpmc16[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
497             strcpy(lpmc16[i].szShortName, mlcA.pamxctrl[i].szShortName);
498             strcpy(lpmc16[i].szName, mlcA.pamxctrl[i].szName);
499             /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
500             memcpy(&lpmc16[i].Bounds, &mlcA.pamxctrl[i].Bounds,
501                    sizeof(mlcA.pamxctrl[i].Bounds));
502             /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
503             memcpy(&lpmc16[i].Metrics, &mlcA.pamxctrl[i].Metrics,
504                    sizeof(mlcA.pamxctrl[i].Metrics));
505         }
506     }
507
508     HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
509
510     return ret;
511 }
512
513 /**************************************************************************
514  *                              mixerGetLineInfo        [MMSYSTEM.805]
515  */
516 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix, LPMIXERLINE16 lpmli16,
517                                  DWORD fdwInfo)
518 {
519     MIXERLINEA          mliA;
520     UINT                ret;
521
522     TRACE("(%04x, %p, %08x)\n", hmix, lpmli16, fdwInfo);
523
524     if (lpmli16 == NULL || lpmli16->cbStruct != sizeof(*lpmli16))
525         return MMSYSERR_INVALPARAM;
526
527     mliA.cbStruct = sizeof(mliA);
528     switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) {
529     case MIXER_GETLINEINFOF_COMPONENTTYPE:
530         mliA.dwComponentType = lpmli16->dwComponentType;
531         break;
532     case MIXER_GETLINEINFOF_DESTINATION:
533         mliA.dwDestination = lpmli16->dwDestination;
534         break;
535     case MIXER_GETLINEINFOF_LINEID:
536         mliA.dwLineID = lpmli16->dwLineID;
537         break;
538     case MIXER_GETLINEINFOF_SOURCE:
539         mliA.dwDestination = lpmli16->dwDestination;
540         mliA.dwSource = lpmli16->dwSource;
541         break;
542     case MIXER_GETLINEINFOF_TARGETTYPE:
543         mliA.Target.dwType = lpmli16->Target.dwType;
544         mliA.Target.wMid = lpmli16->Target.wMid;
545         mliA.Target.wPid = lpmli16->Target.wPid;
546         mliA.Target.vDriverVersion = lpmli16->Target.vDriverVersion;
547         strcpy(mliA.Target.szPname, lpmli16->Target.szPname);
548         break;
549     default:
550         FIXME("Unsupported fdwControls=0x%08x\n", fdwInfo);
551     }
552
553     ret = mixerGetLineInfoA(HMIXEROBJ_32(hmix), &mliA, fdwInfo);
554
555     lpmli16->dwDestination      = mliA.dwDestination;
556     lpmli16->dwSource           = mliA.dwSource;
557     lpmli16->dwLineID           = mliA.dwLineID;
558     lpmli16->fdwLine            = mliA.fdwLine;
559     lpmli16->dwUser             = mliA.dwUser;
560     lpmli16->dwComponentType    = mliA.dwComponentType;
561     lpmli16->cChannels          = mliA.cChannels;
562     lpmli16->cConnections       = mliA.cConnections;
563     lpmli16->cControls          = mliA.cControls;
564     strcpy(lpmli16->szShortName, mliA.szShortName);
565     strcpy(lpmli16->szName, mliA.szName);
566     lpmli16->Target.dwType      = mliA.Target.dwType;
567     lpmli16->Target.dwDeviceID  = mliA.Target.dwDeviceID;
568     lpmli16->Target.wMid        = mliA.Target.wMid;
569     lpmli16->Target.wPid        = mliA.Target.wPid;
570     lpmli16->Target.vDriverVersion = mliA.Target.vDriverVersion;
571     strcpy(lpmli16->Target.szPname, mliA.Target.szPname);
572
573     return ret;
574 }
575
576 /**************************************************************************
577  *                              mixerSetControlDetails  [MMSYSTEM.809]
578  */
579 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,
580                                        LPMIXERCONTROLDETAILS16 lpmcd,
581                                        DWORD fdwDetails)
582 {
583     TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
584     return MMSYSERR_NOTENABLED;
585 }
586
587 /**************************************************************************
588  *                              mixerMessage            [MMSYSTEM.804]
589  */
590 DWORD WINAPI mixerMessage16(HMIXER16 hmix, UINT16 uMsg, DWORD dwParam1,
591                              DWORD dwParam2)
592 {
593     return mixerMessage(HMIXER_32(hmix), uMsg, dwParam1, dwParam2);
594 }
595
596 /* ###################################################
597  * #                     AUX                         #
598  * ###################################################
599  */
600
601 /**************************************************************************
602  *                              auxGetNumDevs           [MMSYSTEM.350]
603  */
604 UINT16 WINAPI auxGetNumDevs16(void)
605 {
606     return auxGetNumDevs();
607 }
608
609 /**************************************************************************
610  *                              auxGetDevCaps           [MMSYSTEM.351]
611  */
612 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID, LPAUXCAPS16 lpCaps, UINT16 uSize)
613 {
614     AUXCAPSA  acA;
615     UINT      ret;
616
617     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
618
619     ret = auxGetDevCapsA(uDeviceID, &acA, sizeof(acA));
620     if (ret == MMSYSERR_NOERROR) {
621         AUXCAPS16 ac16;
622         ac16.wMid           = acA.wMid;
623         ac16.wPid           = acA.wPid;
624         ac16.vDriverVersion = acA.vDriverVersion;
625         strcpy(ac16.szPname, acA.szPname);
626         ac16.wTechnology    = acA.wTechnology;
627         ac16.dwSupport      = acA.dwSupport;
628         memcpy(lpCaps, &ac16, min(uSize, sizeof(ac16)));
629     }
630     return ret;
631 }
632
633 /**************************************************************************
634  *                              auxGetVolume            [MMSYSTEM.352]
635  */
636 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, LPDWORD lpdwVolume)
637 {
638     return auxGetVolume(uDeviceID, lpdwVolume);
639 }
640
641 /**************************************************************************
642  *                              auxSetVolume            [MMSYSTEM.353]
643  */
644 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
645 {
646     return auxSetVolume(uDeviceID, dwVolume);
647 }
648
649 /**************************************************************************
650  *                              auxOutMessage           [MMSYSTEM.354]
651  */
652 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
653 {
654     TRACE("(%04X, %04X, %08X, %08X)\n", uDeviceID, uMessage, dw1, dw2);
655
656     switch (uMessage) {
657     case AUXDM_GETNUMDEVS:
658     case AUXDM_SETVOLUME:
659         /* no argument conversion needed */
660         break;
661     case AUXDM_GETVOLUME:
662         return auxGetVolume(uDeviceID, MapSL(dw1));
663     case AUXDM_GETDEVCAPS:
664         return auxGetDevCaps16(uDeviceID, MapSL(dw1), dw2);
665     default:
666         TRACE("(%04x, %04x, %08x, %08x): unhandled message\n",
667               uDeviceID, uMessage, dw1, dw2);
668         break;
669     }
670     return auxOutMessage(uDeviceID, uMessage, dw1, dw2);
671 }
672
673 /* ###################################################
674  * #                     MIDI                        #
675  * ###################################################
676  */
677
678 /**************************************************************************
679  *                              midiOutGetNumDevs       [MMSYSTEM.201]
680  */
681 UINT16 WINAPI midiOutGetNumDevs16(void)
682 {
683     return midiOutGetNumDevs();
684 }
685
686 /**************************************************************************
687  *                              midiOutGetDevCaps       [MMSYSTEM.202]
688  */
689 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID, LPMIDIOUTCAPS16 lpCaps,
690                                   UINT16 uSize)
691 {
692     MIDIOUTCAPSA        mocA;
693     UINT                ret;
694
695     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
696
697     ret = midiOutGetDevCapsA(uDeviceID, &mocA, sizeof(mocA));
698     if (ret == MMSYSERR_NOERROR) {
699         MIDIOUTCAPS16 moc16;
700         moc16.wMid            = mocA.wMid;
701         moc16.wPid            = mocA.wPid;
702         moc16.vDriverVersion  = mocA.vDriverVersion;
703         strcpy(moc16.szPname, mocA.szPname);
704         moc16.wTechnology     = mocA.wTechnology;
705         moc16.wVoices         = mocA.wVoices;
706         moc16.wNotes          = mocA.wNotes;
707         moc16.wChannelMask    = mocA.wChannelMask;
708         moc16.dwSupport       = mocA.dwSupport;
709         memcpy(lpCaps, &moc16, min(uSize, sizeof(moc16)));
710     }
711     return ret;
712  }
713
714 /**************************************************************************
715  *                              midiOutGetErrorText     [MMSYSTEM.203]
716  *                              midiInGetErrorText      [MMSYSTEM.303]
717  */
718 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
719 {
720     return midiOutGetErrorTextA(uError, lpText, uSize);
721 }
722
723 /**************************************************************************
724  *                              midiOutOpen             [MMSYSTEM.204]
725  */
726 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
727                             DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
728 {
729     HMIDIOUT                    hmo;
730     UINT                        ret;
731     struct mmsystdrv_thunk*     thunk;
732
733     if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, dwFlags, MMSYSTDRV_MIDIOUT)))
734     {
735         return MMSYSERR_NOMEM;
736     }
737     dwFlags = (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION;
738     ret = midiOutOpen(&hmo, uDeviceID, (DWORD)thunk, dwInstance, dwFlags);
739     if (ret == MMSYSERR_NOERROR)
740     {
741         if (lphMidiOut != NULL) *lphMidiOut = HMIDIOUT_16(hmo);
742         MMSYSTDRV_SetHandle(thunk, (void*)hmo);
743     }
744     else MMSYSTDRV_DeleteThunk(thunk);
745     return ret;
746 }
747
748 /**************************************************************************
749  *                              midiOutClose            [MMSYSTEM.205]
750  */
751 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
752 {
753     UINT        ret = midiOutClose(HMIDIOUT_32(hMidiOut));
754
755     if (ret == MMSYSERR_NOERROR)
756         MMSYSTDRV_CloseHandle((void*)HMIDIOUT_32(hMidiOut));
757     return ret;
758 }
759
760 /**************************************************************************
761  *                              midiOutPrepareHeader    [MMSYSTEM.206]
762  */
763 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
764                                      SEGPTR lpsegMidiOutHdr,      /* [???] */
765                                      UINT16 uSize)                /* [in] */
766 {
767     TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
768
769     return MMSYSTDRV_Message(HMIDIOUT_32(hMidiOut), MODM_PREPARE, lpsegMidiOutHdr, uSize);
770 }
771
772 /**************************************************************************
773  *                              midiOutUnprepareHeader  [MMSYSTEM.207]
774  */
775 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut,         /* [in] */
776                                        SEGPTR lpsegMidiOutHdr,      /* [???] */
777                                        UINT16 uSize)                /* [in] */
778 {
779     LPMIDIHDR16         lpMidiOutHdr = MapSL(lpsegMidiOutHdr);
780
781     TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
782
783     if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
784         return MMSYSERR_NOERROR;
785     }
786
787     return MMSYSTDRV_Message(HMIDIOUT_32(hMidiOut), MODM_UNPREPARE, lpsegMidiOutHdr, uSize);
788 }
789
790 /**************************************************************************
791  *                              midiOutShortMsg         [MMSYSTEM.208]
792  */
793 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
794 {
795     return midiOutShortMsg(HMIDIOUT_32(hMidiOut), dwMsg);
796 }
797
798 /**************************************************************************
799  *                              midiOutLongMsg          [MMSYSTEM.209]
800  */
801 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut,          /* [in] */
802                                SEGPTR lpsegMidiOutHdr,       /* [???] */
803                                UINT16 uSize)                 /* [in] */
804 {
805     TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
806
807     return MMSYSTDRV_Message(HMIDIOUT_32(hMidiOut), MODM_LONGDATA, lpsegMidiOutHdr, uSize);
808 }
809
810 /**************************************************************************
811  *                              midiOutReset            [MMSYSTEM.210]
812  */
813 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
814 {
815     return midiOutReset(HMIDIOUT_32(hMidiOut));
816 }
817
818 /**************************************************************************
819  *                              midiOutGetVolume        [MMSYSTEM.211]
820  */
821 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
822 {
823     return midiOutGetVolume(HMIDIOUT_32(uDeviceID), lpdwVolume);
824 }
825
826 /**************************************************************************
827  *                              midiOutSetVolume        [MMSYSTEM.212]
828  */
829 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
830 {
831     return midiOutSetVolume(HMIDIOUT_32(uDeviceID), dwVolume);
832 }
833
834 /**************************************************************************
835  *                              midiOutCachePatches             [MMSYSTEM.213]
836  */
837 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
838                                     WORD* lpwPatchArray, UINT16 uFlags)
839 {
840     return midiOutCachePatches(HMIDIOUT_32(hMidiOut), uBank, lpwPatchArray,
841                                uFlags);
842 }
843
844 /**************************************************************************
845  *                              midiOutCacheDrumPatches [MMSYSTEM.214]
846  */
847 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
848                                         WORD* lpwKeyArray, UINT16 uFlags)
849 {
850     return midiOutCacheDrumPatches(HMIDIOUT_32(hMidiOut), uPatch, lpwKeyArray, uFlags);
851 }
852
853 /**************************************************************************
854  *                              midiOutGetID            [MMSYSTEM.215]
855  */
856 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
857 {
858     UINT        devid;
859     UINT16      ret;
860
861     ret = midiOutGetID(HMIDIOUT_32(hMidiOut), &devid);
862     if (ret != MMSYSERR_NOERROR) return ret;
863     *lpuDeviceID = devid;
864     return ret;
865 }
866
867 /**************************************************************************
868  *                              midiOutMessage          [MMSYSTEM.216]
869  */
870 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
871                               DWORD dwParam1, DWORD dwParam2)
872 {
873     TRACE("(%04X, %04X, %08X, %08X)\n", hMidiOut, uMessage, dwParam1, dwParam2);
874
875     switch (uMessage) {
876     case MODM_OPEN:
877     case MODM_CLOSE:
878         FIXME("can't handle OPEN or CLOSE message!\n");
879         return MMSYSERR_NOTSUPPORTED;
880
881     case MODM_GETVOLUME:
882         return midiOutGetVolume16(hMidiOut, MapSL(dwParam1));
883     /* lpMidiOutHdr is still a segmented pointer for these functions */
884     case MODM_LONGDATA:
885         return midiOutLongMsg16(hMidiOut, dwParam1, dwParam2);
886     case MODM_PREPARE:
887         return midiOutPrepareHeader16(hMidiOut, dwParam1, dwParam2);
888     case MODM_UNPREPARE:
889         return midiOutUnprepareHeader16(hMidiOut, dwParam1, dwParam2);
890     }
891     return MMSYSTDRV_Message(HMIDIOUT_32(hMidiOut), uMessage, dwParam1, dwParam2);
892 }
893
894 /**************************************************************************
895  *                              midiInGetNumDevs        [MMSYSTEM.301]
896  */
897 UINT16 WINAPI midiInGetNumDevs16(void)
898 {
899     return midiInGetNumDevs();
900 }
901
902 /**************************************************************************
903  *                              midiInGetDevCaps        [MMSYSTEM.302]
904  */
905 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID, LPMIDIINCAPS16 lpCaps,
906                                  UINT16 uSize)
907 {
908     MIDIINCAPSA         micA;
909     UINT                ret;
910
911     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
912
913     ret = midiInGetDevCapsA(uDeviceID, &micA, uSize);
914     if (ret == MMSYSERR_NOERROR) {
915         MIDIINCAPS16 mic16;
916         mic16.wMid           = micA.wMid;
917         mic16.wPid           = micA.wPid;
918         mic16.vDriverVersion = micA.vDriverVersion;
919         strcpy(mic16.szPname, micA.szPname);
920         mic16.dwSupport      = micA.dwSupport;
921         memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
922     }
923     return ret;
924 }
925
926 /**************************************************************************
927  *                              midiInOpen              [MMSYSTEM.304]
928  */
929 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
930                            DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
931 {
932     HMIDIIN     hmid;
933     UINT        ret;
934     struct mmsystdrv_thunk*     thunk;
935
936     if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, dwFlags, MMSYSTDRV_MIDIIN)))
937     {
938         return MMSYSERR_NOMEM;
939     }
940     dwFlags = (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION;
941     ret = midiInOpen(&hmid, uDeviceID, (DWORD)thunk, dwInstance, dwFlags);
942     if (ret == MMSYSERR_NOERROR)
943     {
944         if (lphMidiIn) *lphMidiIn = HMIDIIN_16(hmid);
945         MMSYSTDRV_SetHandle(thunk, (void*)hmid);
946     }
947     else MMSYSTDRV_DeleteThunk(thunk);
948     return ret;
949 }
950
951 /**************************************************************************
952  *                              midiInClose             [MMSYSTEM.305]
953  */
954 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
955 {
956     UINT        ret = midiInClose(HMIDIIN_32(hMidiIn));
957
958     if (ret == MMSYSERR_NOERROR)
959         MMSYSTDRV_CloseHandle((void*)HMIDIIN_32(hMidiIn));
960     return ret;
961 }
962
963 /**************************************************************************
964  *                              midiInPrepareHeader     [MMSYSTEM.306]
965  */
966 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
967                                     SEGPTR lpsegMidiInHdr,     /* [???] */
968                                     UINT16 uSize)              /* [in] */
969 {
970     TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
971
972     return MMSYSTDRV_Message(HMIDIIN_32(hMidiIn), MIDM_PREPARE, lpsegMidiInHdr, uSize);
973 }
974
975 /**************************************************************************
976  *                              midiInUnprepareHeader   [MMSYSTEM.307]
977  */
978 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn,         /* [in] */
979                                       SEGPTR lpsegMidiInHdr,     /* [???] */
980                                       UINT16 uSize)              /* [in] */
981 {
982     LPMIDIHDR16         lpMidiInHdr = MapSL(lpsegMidiInHdr);
983
984     TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
985
986     if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
987         return MMSYSERR_NOERROR;
988     }
989
990     return MMSYSTDRV_Message(HMIDIIN_32(hMidiIn), MIDM_UNPREPARE, lpsegMidiInHdr, uSize);
991 }
992
993 /**************************************************************************
994  *                              midiInAddBuffer         [MMSYSTEM.308]
995  */
996 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn,         /* [in] */
997                                 SEGPTR lpsegMidiInHdr,     /* [???] */
998                                 UINT16 uSize)              /* [in] */
999 {
1000     TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
1001
1002     return MMSYSTDRV_Message(HMIDIIN_32(hMidiIn), MIDM_ADDBUFFER, lpsegMidiInHdr, uSize);
1003 }
1004
1005 /**************************************************************************
1006  *                              midiInStart                     [MMSYSTEM.309]
1007  */
1008 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
1009 {
1010     return midiInStart(HMIDIIN_32(hMidiIn));
1011 }
1012
1013 /**************************************************************************
1014  *                              midiInStop                      [MMSYSTEM.310]
1015  */
1016 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
1017 {
1018     return midiInStop(HMIDIIN_32(hMidiIn));
1019 }
1020
1021 /**************************************************************************
1022  *                              midiInReset                     [MMSYSTEM.311]
1023  */
1024 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
1025 {
1026     return midiInReset(HMIDIIN_32(hMidiIn));
1027 }
1028
1029 /**************************************************************************
1030  *                              midiInGetID                     [MMSYSTEM.312]
1031  */
1032 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
1033 {
1034     UINT        devid;
1035     UINT16      ret;
1036
1037     ret = midiInGetID(HMIDIIN_32(hMidiIn), &devid);
1038     if (ret != MMSYSERR_NOERROR) return ret;
1039     *lpuDeviceID = devid;
1040     return ret;
1041 }
1042
1043 /**************************************************************************
1044  *                              midiInMessage           [MMSYSTEM.313]
1045  */
1046 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
1047                              DWORD dwParam1, DWORD dwParam2)
1048 {
1049     TRACE("(%04X, %04X, %08X, %08X)\n", hMidiIn, uMessage, dwParam1, dwParam2);
1050
1051     switch (uMessage) {
1052     case MIDM_OPEN:
1053     case MIDM_CLOSE:
1054         FIXME("can't handle OPEN or CLOSE message!\n");
1055         return MMSYSERR_NOTSUPPORTED;
1056
1057     case MIDM_GETDEVCAPS:
1058         return midiInGetDevCaps16(hMidiIn, MapSL(dwParam1), dwParam2);
1059     case MIDM_PREPARE:
1060         return midiInPrepareHeader16(hMidiIn, dwParam1, dwParam2);
1061     case MIDM_UNPREPARE:
1062         return midiInUnprepareHeader16(hMidiIn, dwParam1, dwParam2);
1063     case MIDM_ADDBUFFER:
1064         return midiInAddBuffer16(hMidiIn, dwParam1, dwParam2);
1065     }
1066     return MMSYSTDRV_Message(HMIDIIN_32(hMidiIn), uMessage, dwParam1, dwParam2);
1067 }
1068
1069 /**************************************************************************
1070  *                              midiStreamClose                 [MMSYSTEM.252]
1071  */
1072 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hMidiStrm)
1073 {
1074     UINT        ret = midiStreamClose(HMIDISTRM_32(hMidiStrm));
1075     if (ret == MMSYSERR_NOERROR)
1076         MMSYSTDRV_CloseHandle((void*)HMIDISTRM_32(hMidiStrm));
1077     return ret;
1078 }
1079
1080 /**************************************************************************
1081  *                              midiStreamOpen                  [MMSYSTEM.251]
1082  */
1083 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
1084                                    DWORD cMidi, DWORD dwCallback,
1085                                    DWORD dwInstance, DWORD fdwOpen)
1086 {
1087     HMIDISTRM                   hMidiStrm32;
1088     MMRESULT                    ret;
1089     UINT                        devid32;
1090     struct mmsystdrv_thunk*     thunk;
1091
1092     if (!phMidiStrm || !devid)
1093         return MMSYSERR_INVALPARAM;
1094     devid32 = *devid;
1095
1096     if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, fdwOpen, MMSYSTDRV_MIDIOUT)))
1097     {
1098         return MMSYSERR_NOMEM;
1099     }
1100     fdwOpen = (fdwOpen & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION;
1101     ret = midiStreamOpen(&hMidiStrm32, &devid32, cMidi, (DWORD)thunk, dwInstance, fdwOpen);
1102     if (ret == MMSYSERR_NOERROR)
1103     {
1104         *phMidiStrm = HMIDISTRM_16(hMidiStrm32);
1105         *devid = devid32;
1106         MMSYSTDRV_SetHandle(thunk, hMidiStrm32);
1107     }
1108     else MMSYSTDRV_DeleteThunk(thunk);
1109     return ret;
1110 }
1111
1112 /**************************************************************************
1113  *                              midiStreamOut                   [MMSYSTEM.254]
1114  */
1115 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hMidiStrm, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
1116 {
1117     return midiStreamOut(HMIDISTRM_32(hMidiStrm), (LPMIDIHDR)lpMidiHdr,
1118                          cbMidiHdr);
1119 }
1120
1121 /**************************************************************************
1122  *                              midiStreamPause                 [MMSYSTEM.255]
1123  */
1124 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hMidiStrm)
1125 {
1126     return midiStreamPause(HMIDISTRM_32(hMidiStrm));
1127 }
1128
1129 /**************************************************************************
1130  *                              midiStreamPosition              [MMSYSTEM.253]
1131  */
1132 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hMidiStrm, LPMMTIME16 lpmmt16, UINT16 cbmmt)
1133 {
1134     MMTIME      mmt32;
1135     MMRESULT    ret;
1136
1137     if (!lpmmt16)
1138         return MMSYSERR_INVALPARAM;
1139     mmt32.wType = lpmmt16->wType;
1140     ret = midiStreamPosition(HMIDISTRM_32(hMidiStrm), &mmt32, sizeof(MMTIME));
1141     MMSYSTEM_MMTIME32to16(lpmmt16, &mmt32);
1142     return ret;
1143 }
1144
1145 /**************************************************************************
1146  *                              midiStreamProperty              [MMSYSTEM.250]
1147  */
1148 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hMidiStrm, LPBYTE lpPropData, DWORD dwProperty)
1149 {
1150     return midiStreamProperty(HMIDISTRM_32(hMidiStrm), lpPropData, dwProperty);
1151 }
1152
1153 /**************************************************************************
1154  *                              midiStreamRestart               [MMSYSTEM.256]
1155  */
1156 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hMidiStrm)
1157 {
1158     return midiStreamRestart(HMIDISTRM_32(hMidiStrm));
1159 }
1160
1161 /**************************************************************************
1162  *                              midiStreamStop                  [MMSYSTEM.257]
1163  */
1164 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hMidiStrm)
1165 {
1166     return midiStreamStop(HMIDISTRM_32(hMidiStrm));
1167 }
1168
1169 /* ###################################################
1170  * #                     WAVE                        #
1171  * ###################################################
1172  */
1173
1174 /**************************************************************************
1175  *                              waveOutGetNumDevs               [MMSYSTEM.401]
1176  */
1177 UINT16 WINAPI waveOutGetNumDevs16(void)
1178 {
1179     return waveOutGetNumDevs();
1180 }
1181
1182 /**************************************************************************
1183  *                              waveOutGetDevCaps               [MMSYSTEM.402]
1184  */
1185 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID,
1186                                   LPWAVEOUTCAPS16 lpCaps, UINT16 uSize)
1187 {
1188     WAVEOUTCAPSA        wocA;
1189     UINT                ret;
1190     TRACE("(%u %p %u)!\n", uDeviceID, lpCaps, uSize);
1191
1192     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1193
1194     ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA));
1195     if (ret == MMSYSERR_NOERROR) {
1196         WAVEOUTCAPS16 woc16;
1197         woc16.wMid           = wocA.wMid;
1198         woc16.wPid           = wocA.wPid;
1199         woc16.vDriverVersion = wocA.vDriverVersion;
1200         strcpy(woc16.szPname, wocA.szPname);
1201         woc16.dwFormats      = wocA.dwFormats;
1202         woc16.wChannels      = wocA.wChannels;
1203         woc16.dwSupport      = wocA.dwSupport;
1204         memcpy(lpCaps, &woc16, min(uSize, sizeof(woc16)));
1205     }
1206     return ret;
1207 }
1208
1209 /**************************************************************************
1210  *                              waveOutGetErrorText     [MMSYSTEM.403]
1211  *                              waveInGetErrorText      [MMSYSTEM.503]
1212  */
1213 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1214 {
1215     return waveOutGetErrorTextA(uError, lpText, uSize);
1216 }
1217
1218 /**************************************************************************
1219  *                      waveOutOpen                     [MMSYSTEM.404]
1220  */
1221 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
1222                             LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1223                             DWORD dwInstance, DWORD dwFlags)
1224 {
1225     HWAVEOUT                    hWaveOut;
1226     UINT                        ret;
1227     struct mmsystdrv_thunk*     thunk;
1228
1229     if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, dwFlags, MMSYSTDRV_WAVEOUT)))
1230     {
1231         return MMSYSERR_NOMEM;
1232     }
1233     dwFlags = (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION;
1234     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1235      * call the 32 bit version
1236      * however, we need to promote correctly the wave mapper id
1237      * (0xFFFFFFFF and not 0x0000FFFF)
1238      */
1239     ret = waveOutOpen(&hWaveOut, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1240                       lpFormat, (DWORD)thunk, dwInstance, dwFlags);
1241
1242     if (ret == MMSYSERR_NOERROR && !(dwFlags & WAVE_FORMAT_QUERY))
1243     {
1244          MMSYSTDRV_SetHandle(thunk, (void*)hWaveOut);
1245          if (lphWaveOut != NULL)
1246              *lphWaveOut = HWAVEOUT_16(hWaveOut);
1247     } else MMSYSTDRV_DeleteThunk(thunk);
1248     return ret;
1249 }
1250
1251 /**************************************************************************
1252  *                              waveOutClose            [MMSYSTEM.405]
1253  */
1254 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
1255 {
1256     DWORD       level;
1257     UINT16      ret;
1258
1259     ReleaseThunkLock(&level);
1260     ret = waveOutClose(HWAVEOUT_32(hWaveOut));
1261     RestoreThunkLock(level);
1262     if (ret == MMSYSERR_NOERROR)
1263         MMSYSTDRV_CloseHandle((void*)HWAVEOUT_32(hWaveOut));
1264     return ret;
1265 }
1266
1267 /**************************************************************************
1268  *                              waveOutPrepareHeader    [MMSYSTEM.406]
1269  */
1270 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,      /* [in] */
1271                                      SEGPTR lpsegWaveOutHdr,   /* [???] */
1272                                      UINT16 uSize)             /* [in] */
1273 {
1274     TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1275
1276     if (lpsegWaveOutHdr == 0) return MMSYSERR_INVALPARAM;
1277
1278     return MMSYSTDRV_Message(HWAVEOUT_32(hWaveOut), WODM_PREPARE, lpsegWaveOutHdr, uSize);
1279 }
1280
1281 /**************************************************************************
1282  *                              waveOutUnprepareHeader  [MMSYSTEM.407]
1283  */
1284 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,       /* [in] */
1285                                        SEGPTR lpsegWaveOutHdr,    /* [???] */
1286                                        UINT16 uSize)              /* [in] */
1287 {
1288     LPWAVEHDR           lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1289
1290     TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1291
1292     if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
1293         return MMSYSERR_NOERROR;
1294     }
1295
1296     return MMSYSTDRV_Message(HWAVEOUT_32(hWaveOut), WODM_UNPREPARE, lpsegWaveOutHdr, uSize);
1297 }
1298
1299 /**************************************************************************
1300  *                              waveOutWrite            [MMSYSTEM.408]
1301  */
1302 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut,       /* [in] */
1303                              SEGPTR lpsegWaveOutHdr,    /* [???] */
1304                              UINT16 uSize)              /* [in] */
1305 {
1306     TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1307
1308     return MMSYSTDRV_Message(HWAVEOUT_32(hWaveOut), WODM_WRITE, lpsegWaveOutHdr, uSize);
1309 }
1310
1311 /**************************************************************************
1312  *                              waveOutBreakLoop        [MMSYSTEM.419]
1313  */
1314 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut16)
1315 {
1316     DWORD       level;
1317     UINT16      ret;
1318
1319     ReleaseThunkLock(&level);
1320     ret = waveOutBreakLoop(HWAVEOUT_32(hWaveOut16));
1321     RestoreThunkLock(level);
1322     return ret;
1323 }
1324
1325 /**************************************************************************
1326  *                              waveOutPause            [MMSYSTEM.409]
1327  */
1328 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut16)
1329 {
1330     DWORD       level;
1331     UINT16      ret;
1332
1333     ReleaseThunkLock(&level);
1334     ret = waveOutPause(HWAVEOUT_32(hWaveOut16));
1335     RestoreThunkLock(level);
1336     return ret;
1337 }
1338
1339 /**************************************************************************
1340  *                              waveOutReset            [MMSYSTEM.411]
1341  */
1342 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut16)
1343 {
1344     DWORD       level;
1345     UINT16      ret;
1346
1347     ReleaseThunkLock(&level);
1348     ret = waveOutReset(HWAVEOUT_32(hWaveOut16));
1349     RestoreThunkLock(level);
1350     return ret;
1351 }
1352
1353 /**************************************************************************
1354  *                              waveOutRestart  [MMSYSTEM.410]
1355  */
1356 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut16)
1357 {
1358     DWORD       level;
1359     UINT16      ret;
1360
1361     ReleaseThunkLock(&level);
1362     ret = waveOutRestart(HWAVEOUT_32(hWaveOut16));
1363     RestoreThunkLock(level);
1364     return ret;
1365 }
1366
1367 /**************************************************************************
1368  *                              waveOutGetPosition      [MMSYSTEM.412]
1369  */
1370 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
1371                                    UINT16 uSize)
1372 {
1373     UINT        ret;
1374     MMTIME      mmt;
1375
1376     mmt.wType = lpTime->wType;
1377     ret = waveOutGetPosition(HWAVEOUT_32(hWaveOut), &mmt, sizeof(mmt));
1378     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1379     return ret;
1380 }
1381
1382 /**************************************************************************
1383  *                              waveOutGetPitch         [MMSYSTEM.413]
1384  */
1385 UINT16 WINAPI waveOutGetPitch16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1386 {
1387     return waveOutGetPitch(HWAVEOUT_32(hWaveOut16), lpdw);
1388 }
1389
1390 /**************************************************************************
1391  *                              waveOutSetPitch         [MMSYSTEM.414]
1392  */
1393 UINT16 WINAPI waveOutSetPitch16(HWAVEOUT16 hWaveOut16, DWORD dw)
1394 {
1395     return waveOutSetPitch(HWAVEOUT_32(hWaveOut16), dw);
1396 }
1397
1398 /**************************************************************************
1399  *                              waveOutGetPlaybackRate  [MMSYSTEM.417]
1400  */
1401 UINT16 WINAPI waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1402 {
1403     return waveOutGetPlaybackRate(HWAVEOUT_32(hWaveOut16), lpdw);
1404 }
1405
1406 /**************************************************************************
1407  *                              waveOutSetPlaybackRate  [MMSYSTEM.418]
1408  */
1409 UINT16 WINAPI waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16, DWORD dw)
1410 {
1411     return waveOutSetPlaybackRate(HWAVEOUT_32(hWaveOut16), dw);
1412 }
1413
1414 /**************************************************************************
1415  *                              waveOutGetVolume        [MMSYSTEM.415]
1416  */
1417 UINT16 WINAPI waveOutGetVolume16(UINT16 devid, LPDWORD lpdw)
1418 {
1419     return waveOutGetVolume(HWAVEOUT_32(devid), lpdw);
1420 }
1421
1422 /**************************************************************************
1423  *                              waveOutSetVolume        [MMSYSTEM.416]
1424  */
1425 UINT16 WINAPI waveOutSetVolume16(UINT16 devid, DWORD dw)
1426 {
1427     return waveOutSetVolume(HWAVEOUT_32(devid), dw);
1428 }
1429
1430 /**************************************************************************
1431  *                              waveOutGetID            [MMSYSTEM.420]
1432  */
1433 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
1434 {
1435     UINT        devid;
1436     UINT16      ret;
1437
1438     ret = waveOutGetID(HWAVEOUT_32(hWaveOut), &devid);
1439     if (ret != MMSYSERR_NOERROR) return ret;
1440     *lpuDeviceID = devid;
1441     return ret;
1442 }
1443
1444 /**************************************************************************
1445  *                              waveOutMessage          [MMSYSTEM.421]
1446  */
1447 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
1448                               DWORD dwParam1, DWORD dwParam2)
1449 {
1450     TRACE("(%04x, %u, %d, %d)\n", hWaveOut, uMessage, dwParam1, dwParam2);
1451
1452     if ((DWORD_PTR)hWaveOut < waveOutGetNumDevs())
1453     {
1454         if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1455             dwParam1 = (DWORD)MapSL(dwParam1);
1456     }
1457     else if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1458         /* from M$ KB */
1459         return MMSYSERR_INVALPARAM;
1460
1461     return MMSYSTDRV_Message(HWAVEOUT_32(hWaveOut), uMessage, dwParam1, dwParam2);
1462 }
1463
1464 /**************************************************************************
1465  *                              waveInGetNumDevs                [MMSYSTEM.501]
1466  */
1467 UINT16 WINAPI waveInGetNumDevs16(void)
1468 {
1469     return waveInGetNumDevs();
1470 }
1471
1472 /**************************************************************************
1473  *                              waveInGetDevCaps                [MMSYSTEM.502]
1474  */
1475 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps,
1476                                  UINT16 uSize)
1477 {
1478     WAVEINCAPSA wicA;
1479     UINT        ret;
1480
1481     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1482
1483     ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA));
1484     if (ret == MMSYSERR_NOERROR) {
1485         WAVEINCAPS16 wic16;
1486         wic16.wMid           = wicA.wMid;
1487         wic16.wPid           = wicA.wPid;
1488         wic16.vDriverVersion = wicA.vDriverVersion;
1489         strcpy(wic16.szPname, wicA.szPname);
1490         wic16.dwFormats      = wicA.dwFormats;
1491         wic16.wChannels      = wicA.wChannels;
1492         memcpy(lpCaps, &wic16, min(uSize, sizeof(wic16)));
1493     }
1494     return ret;
1495 }
1496
1497 /**************************************************************************
1498  *                              waveInOpen                      [MMSYSTEM.504]
1499  */
1500 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
1501                            LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1502                            DWORD dwInstance, DWORD dwFlags)
1503 {
1504     HWAVEIN                     hWaveIn;
1505     UINT                        ret;
1506     struct mmsystdrv_thunk*     thunk;
1507
1508     if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, dwFlags, MMSYSTDRV_WAVEIN)))
1509     {
1510         return MMSYSERR_NOMEM;
1511     }
1512     dwFlags = (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION;
1513     /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1514      * call the 32 bit version
1515      * however, we need to promote correctly the wave mapper id
1516      * (0xFFFFFFFF and not 0x0000FFFF)
1517      */
1518     ret = waveInOpen(&hWaveIn, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1519                      lpFormat, (DWORD)thunk, dwInstance, dwFlags);
1520
1521     if (ret == MMSYSERR_NOERROR && !(dwFlags & WAVE_FORMAT_QUERY))
1522     {
1523          MMSYSTDRV_SetHandle(thunk, (void*)hWaveIn);
1524          if (lphWaveIn != NULL)
1525              *lphWaveIn = HWAVEOUT_16(hWaveIn);
1526     } else MMSYSTDRV_DeleteThunk(thunk);
1527     return ret;
1528 }
1529
1530 /**************************************************************************
1531  *                              waveInClose                     [MMSYSTEM.505]
1532  */
1533 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
1534 {
1535     DWORD       level;
1536     UINT16      ret;
1537
1538     ReleaseThunkLock(&level);
1539     ret = waveInClose(HWAVEIN_32(hWaveIn));
1540     RestoreThunkLock(level);
1541     if (ret == MMSYSERR_NOERROR)
1542         MMSYSTDRV_CloseHandle((void*)HWAVEIN_32(hWaveIn));
1543     return ret;
1544 }
1545
1546 /**************************************************************************
1547  *                              waveInPrepareHeader             [MMSYSTEM.506]
1548  */
1549 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1550                                     SEGPTR lpsegWaveInHdr,   /* [???] */
1551                                     UINT16 uSize)            /* [in] */
1552 {
1553     LPWAVEHDR           lpWaveInHdr = MapSL(lpsegWaveInHdr);
1554
1555     TRACE("(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
1556
1557     if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
1558
1559     return MMSYSTDRV_Message(HWAVEIN_32(hWaveIn), WIDM_PREPARE, lpsegWaveInHdr, uSize);
1560 }
1561
1562 /**************************************************************************
1563  *                              waveInUnprepareHeader   [MMSYSTEM.507]
1564  */
1565 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,       /* [in] */
1566                                       SEGPTR lpsegWaveInHdr,   /* [???] */
1567                                       UINT16 uSize)            /* [in] */
1568 {
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     return MMSYSTDRV_Message(HWAVEIN_32(hWaveIn), WIDM_UNPREPARE, lpsegWaveInHdr, uSize);
1580 }
1581
1582 /**************************************************************************
1583  *                              waveInAddBuffer         [MMSYSTEM.508]
1584  */
1585 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,       /* [in] */
1586                                 SEGPTR lpsegWaveInHdr,   /* [???] */
1587                                 UINT16 uSize)            /* [in] */
1588 {
1589     TRACE("(%04X, %08x, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1590
1591     if (lpsegWaveInHdr == 0) return MMSYSERR_INVALPARAM;
1592
1593     return MMSYSTDRV_Message(HWAVEIN_32(hWaveIn), WIDM_ADDBUFFER, lpsegWaveInHdr, uSize);
1594 }
1595
1596 /**************************************************************************
1597  *                              waveInReset             [MMSYSTEM.511]
1598  */
1599 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn16)
1600 {
1601     DWORD       level;
1602     UINT16      ret;
1603
1604     ReleaseThunkLock(&level);
1605     ret = waveInReset(HWAVEIN_32(hWaveIn16));
1606     RestoreThunkLock(level);
1607     return ret;
1608 }
1609
1610 /**************************************************************************
1611  *                              waveInStart             [MMSYSTEM.509]
1612  */
1613 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn16)
1614 {
1615     DWORD       level;
1616     UINT16      ret;
1617
1618     ReleaseThunkLock(&level);
1619     ret = waveInStart(HWAVEIN_32(hWaveIn16));
1620     RestoreThunkLock(level);
1621     return ret;
1622 }
1623
1624 /**************************************************************************
1625  *                              waveInStop              [MMSYSTEM.510]
1626  */
1627 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn16)
1628 {
1629     DWORD       level;
1630     UINT16      ret;
1631
1632     ReleaseThunkLock(&level);
1633     ret = waveInStop(HWAVEIN_32(hWaveIn16));
1634     RestoreThunkLock(level);
1635     return ret;
1636 }
1637
1638 /**************************************************************************
1639  *                              waveInGetPosition       [MMSYSTEM.512]
1640  */
1641 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
1642                                   UINT16 uSize)
1643 {
1644     UINT        ret;
1645     MMTIME      mmt;
1646
1647     mmt.wType = lpTime->wType;
1648     ret = waveInGetPosition(HWAVEIN_32(hWaveIn), &mmt, sizeof(mmt));
1649     MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1650     return ret;
1651 }
1652
1653 /**************************************************************************
1654  *                              waveInGetID                     [MMSYSTEM.513]
1655  */
1656 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
1657 {
1658     UINT        devid;
1659     UINT16      ret;
1660
1661     ret = waveInGetID(HWAVEIN_32(hWaveIn), &devid);
1662     if (ret != MMSYSERR_NOERROR) return ret;
1663     *lpuDeviceID = devid;
1664     return ret;
1665 }
1666
1667 /**************************************************************************
1668  *                              waveInMessage           [MMSYSTEM.514]
1669  */
1670 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
1671                              DWORD dwParam1, DWORD dwParam2)
1672 {
1673     TRACE("(%04x, %u, %d, %d)\n", hWaveIn, uMessage, dwParam1, dwParam2);
1674
1675     if ((DWORD_PTR)hWaveIn < waveInGetNumDevs())
1676     {
1677         if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1678             dwParam1 = (DWORD)MapSL(dwParam1);
1679     }
1680     else if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1681         /* from M$ KB */
1682         return MMSYSERR_INVALPARAM;
1683
1684     return MMSYSTDRV_Message(HWAVEIN_32(hWaveIn), uMessage, dwParam1, dwParam2);
1685 }
1686
1687 /* ###################################################
1688  * #                     TASK                        #
1689  * ###################################################
1690  */
1691
1692 /*#define USE_MM_TSK_WINE*/
1693
1694 /**************************************************************************
1695  *                              mmTaskCreate            [MMSYSTEM.900]
1696  *
1697  * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
1698  * called upon creation with dwPmt as parameter.
1699  */
1700 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
1701 {
1702     HINSTANCE16         ret;
1703     HINSTANCE16         handle;
1704     char cmdline[16];
1705     DWORD showCmd = 0x40002;
1706     LOADPARAMS16 lp;
1707
1708     TRACE("(%08x, %p, %08x);\n", spProc, lphMmTask, dwPmt);
1709     /* This to work requires NE modules to be started with a binary command line
1710      * which is not currently the case. A patch exists but has never been committed.
1711      * A workaround would be to integrate code for mmtask.tsk into Wine, but
1712      * this requires tremendous work (starting with patching tools/build to
1713      * create NE executables (and not only DLLs) for builtins modules.
1714      * EP 99/04/25
1715      */
1716     FIXME("This is currently broken. It will fail\n");
1717
1718     cmdline[0] = 0x0d;
1719     *(LPDWORD)(cmdline + 1) = (DWORD)spProc;
1720     *(LPDWORD)(cmdline + 5) = dwPmt;
1721     *(LPDWORD)(cmdline + 9) = 0;
1722
1723     lp.hEnvironment = 0;
1724     lp.cmdLine = MapLS(cmdline);
1725     lp.showCmd = MapLS(&showCmd);
1726     lp.reserved = 0;
1727
1728 #ifndef USE_MM_TSK_WINE
1729     handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
1730 #else
1731     handle = LoadModule16("mmtask.tsk", &lp);
1732 #endif
1733     if (handle < 32) {
1734         ret = (handle) ? 1 : 2;
1735         handle = 0;
1736     } else {
1737         ret = 0;
1738     }
1739     if (lphMmTask)
1740         *lphMmTask = handle;
1741
1742     UnMapLS( lp.cmdLine );
1743     UnMapLS( lp.showCmd );
1744     TRACE("=> 0x%04x/%d\n", handle, ret);
1745     return ret;
1746 }
1747
1748 #ifdef USE_MM_TSK_WINE
1749 /* C equivalent to mmtask.tsk binary content */
1750 void    mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
1751 {
1752     int len = cmdLine[0x80];
1753
1754     if (len / 2 == 6) {
1755         void    (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
1756         DWORD   dwPmt  = *((DWORD*)(cmdLine + 5));
1757
1758 #if 0
1759         InitTask16(); /* FIXME: pmts / from context ? */
1760         InitApp(di);
1761 #endif
1762         if (SetMessageQueue16(0x40)) {
1763             WaitEvent16(0);
1764             if (HIWORD(fpProc)) {
1765                 OldYield16();
1766 /* EPP          StackEnter16(); */
1767                 (fpProc)(dwPmt);
1768             }
1769         }
1770     }
1771     OldYield16();
1772     OldYield16();
1773     OldYield16();
1774     ExitProcess(0);
1775 }
1776 #endif
1777
1778 /**************************************************************************
1779  *                              mmTaskBlock             [MMSYSTEM.902]
1780  */
1781 void WINAPI mmTaskBlock16(HINSTANCE16 hInst)
1782 {
1783     MSG         msg;
1784
1785     do {
1786         GetMessageA(&msg, 0, 0, 0);
1787         if (msg.hwnd) {
1788             TranslateMessage(&msg);
1789             DispatchMessageA(&msg);
1790         }
1791     } while (msg.message < 0x3A0);
1792 }
1793
1794 /**************************************************************************
1795  *                              mmTaskSignal            [MMSYSTEM.903]
1796  */
1797 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
1798 {
1799     TRACE("(%04x);\n", ht);
1800     return PostThreadMessageW( HTASK_32(ht), WM_USER, 0, 0 );
1801 }
1802
1803 /**************************************************************************
1804  *                              mmGetCurrentTask        [MMSYSTEM.904]
1805  */
1806 HTASK16 WINAPI mmGetCurrentTask16(void)
1807 {
1808     return GetCurrentTask();
1809 }
1810
1811 /**************************************************************************
1812  *                              mmTaskYield             [MMSYSTEM.905]
1813  */
1814 void    WINAPI  mmTaskYield16(void)
1815 {
1816     MSG         msg;
1817
1818     if (PeekMessageA(&msg, 0, 0, 0, 0)) {
1819         WOWYield16();
1820     }
1821 }
1822
1823 /******************************************************************
1824  *              WINMM_GetmmThread
1825  *
1826  *
1827  */
1828 static  WINE_MMTHREAD*  WINMM_GetmmThread(HANDLE16 h)
1829 {
1830     return MapSL(MAKESEGPTR(h, 0));
1831 }
1832
1833 static  void    MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
1834 {
1835     MSG         msg;
1836     DWORD       ret;
1837
1838     if (lpMMThd->dwThreadID != GetCurrentThreadId())
1839         ERR("Not called by thread itself\n");
1840
1841     for (;;) {
1842         ResetEvent(lpMMThd->hEvent);
1843         if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
1844             break;
1845         InterlockedIncrement(&lpMMThd->dwSignalCount);
1846
1847         TRACE("S1\n");
1848
1849         ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
1850         switch (ret) {
1851         case WAIT_OBJECT_0:     /* Event */
1852             TRACE("S2.1\n");
1853             break;
1854         case WAIT_OBJECT_0 + 1: /* Msg */
1855             TRACE("S2.2\n");
1856             if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
1857                 TranslateMessage(&msg);
1858                 DispatchMessageA(&msg);
1859             }
1860             break;
1861         default:
1862             WARN("S2.x unsupported ret val 0x%08x\n", ret);
1863         }
1864         TRACE("S3\n");
1865     }
1866 }
1867
1868 /**************************************************************************
1869  *                              mmThreadBlock           [MMSYSTEM.1122]
1870  */
1871 void    WINAPI mmThreadBlock16(HANDLE16 hndl)
1872 {
1873     TRACE("(%04x)!\n", hndl);
1874
1875     if (hndl) {
1876         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1877
1878         if (lpMMThd->hThread != 0) {
1879             DWORD       lc;
1880
1881             ReleaseThunkLock(&lc);
1882             MMSYSTEM_ThreadBlock(lpMMThd);
1883             RestoreThunkLock(lc);
1884         } else {
1885             mmTaskBlock16(lpMMThd->hTask);
1886         }
1887     }
1888     TRACE("done\n");
1889 }
1890
1891 /**************************************************************************
1892  *                              __wine_mmThreadEntryPoint (MMSYSTEM.2047)
1893  */
1894 DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID p)
1895 {
1896     HANDLE16            hndl = (HANDLE16)(DWORD_PTR)p;
1897     WINE_MMTHREAD*      lpMMThd = WINMM_GetmmThread(hndl);
1898
1899     TRACE("(%04x %p)\n", hndl, lpMMThd);
1900
1901     lpMMThd->hTask = LOWORD(GetCurrentTask());
1902     TRACE("[10-%p] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
1903     lpMMThd->dwStatus = 0x10;
1904     MMSYSTEM_ThreadBlock(lpMMThd);
1905     TRACE("[20-%p]\n", lpMMThd->hThread);
1906     lpMMThd->dwStatus = 0x20;
1907     if (lpMMThd->fpThread) {
1908         WOWCallback16(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
1909     }
1910     lpMMThd->dwStatus = 0x30;
1911     TRACE("[30-%p]\n", lpMMThd->hThread);
1912     while (lpMMThd->dwCounter) {
1913         Sleep(1);
1914         /* WOWYield16();*/
1915     }
1916     TRACE("[XX-%p]\n", lpMMThd->hThread);
1917     /* paranoia */
1918     lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
1919     /* close lpMMThread->hVxD directIO */
1920     if (lpMMThd->hEvent)
1921         CloseHandle(lpMMThd->hEvent);
1922     GlobalFree16(hndl);
1923     TRACE("done\n");
1924
1925     return 0;
1926 }
1927
1928 extern DWORD    WINAPI  GetProcessFlags(DWORD);
1929
1930 /**************************************************************************
1931  *                              mmThreadCreate          [MMSYSTEM.1120]
1932  *
1933  * undocumented
1934  * Creates a MM thread, calling fpThreadAddr(dwPmt).
1935  * dwFlags:
1936  *      bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
1937  *      bit.1 set means to open a VxD for this thread (unsupported)
1938  */
1939 LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD dwPmt, DWORD dwFlags)
1940 {
1941     HANDLE16            hndl;
1942     LRESULT             ret;
1943
1944     TRACE("(%p, %p, %08x, %08x)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
1945
1946     hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
1947
1948     if (hndl == 0) {
1949         ret = 2;
1950     } else {
1951         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
1952
1953 #if 0
1954         /* force mmtask routines even if mmthread is required */
1955         /* this will work only if the patch about binary cmd line and NE tasks
1956          * is committed
1957          */
1958         dwFlags |= 1;
1959 #endif
1960
1961         lpMMThd->dwSignature    = WINE_MMTHREAD_CREATED;
1962         lpMMThd->dwCounter      = 0;
1963         lpMMThd->hThread        = 0;
1964         lpMMThd->dwThreadID     = 0;
1965         lpMMThd->fpThread       = (DWORD)fpThreadAddr;
1966         lpMMThd->dwThreadPmt    = dwPmt;
1967         lpMMThd->dwSignalCount  = 0;
1968         lpMMThd->hEvent         = 0;
1969         lpMMThd->hVxD           = 0;
1970         lpMMThd->dwStatus       = 0;
1971         lpMMThd->dwFlags        = dwFlags;
1972         lpMMThd->hTask          = 0;
1973
1974         if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
1975             lpMMThd->hEvent = CreateEventW(NULL, FALSE, TRUE, NULL);
1976
1977             TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
1978             if (lpMMThd->dwFlags & 2) {
1979                 /* as long as we don't support MM VxD in wine, we don't need
1980                  * to care about this flag
1981                  */
1982                 /* FIXME("Don't know how to properly open VxD handles\n"); */
1983                 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
1984             }
1985
1986             lpMMThd->hThread = CreateThread(0, 0, WINE_mmThreadEntryPoint,
1987                                             (LPVOID)(DWORD_PTR)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
1988             if (lpMMThd->hThread == 0) {
1989                 WARN("Couldn't create thread\n");
1990                 /* clean-up(VxDhandle...); devicedirectio... */
1991                 if (lpMMThd->hEvent != 0)
1992                     CloseHandle(lpMMThd->hEvent);
1993                 ret = 2;
1994             } else {
1995                 SetThreadPriority(lpMMThd->hThread, THREAD_PRIORITY_TIME_CRITICAL);
1996                 TRACE("Got a nice thread hndl=%p id=0x%08x\n", lpMMThd->hThread, lpMMThd->dwThreadID);
1997                 ret = 0;
1998             }
1999         } else {
2000             /* get WINE_mmThreadEntryPoint()
2001              * 2047 is its ordinal in mmsystem.spec
2002              */
2003             FARPROC16   fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
2004
2005             TRACE("farproc seg=0x%p lin=%p\n", fp, MapSL((SEGPTR)fp));
2006
2007             ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
2008         }
2009
2010         if (ret == 0) {
2011             if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
2012                 WARN("Couldn't resume thread\n");
2013
2014             while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
2015                 MSG msg;
2016                 PeekMessageW( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
2017             }
2018         }
2019     }
2020
2021     if (ret != 0) {
2022         GlobalFree16(hndl);
2023         hndl = 0;
2024     }
2025
2026     if (lpHndl)
2027         *lpHndl = hndl;
2028
2029     TRACE("ok => %ld\n", ret);
2030     return ret;
2031 }
2032
2033 /**************************************************************************
2034  *                              mmThreadSignal          [MMSYSTEM.1121]
2035  */
2036 void WINAPI mmThreadSignal16(HANDLE16 hndl)
2037 {
2038     TRACE("(%04x)!\n", hndl);
2039
2040     if (hndl) {
2041         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2042
2043         lpMMThd->dwCounter++;
2044         if (lpMMThd->hThread != 0) {
2045             InterlockedIncrement(&lpMMThd->dwSignalCount);
2046             SetEvent(lpMMThd->hEvent);
2047         } else {
2048             mmTaskSignal16(lpMMThd->hTask);
2049         }
2050         lpMMThd->dwCounter--;
2051     }
2052 }
2053
2054 /**************************************************************************
2055  *                              mmThreadIsCurrent       [MMSYSTEM.1123]
2056  */
2057 BOOL16  WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
2058 {
2059     BOOL16              ret = FALSE;
2060
2061     TRACE("(%04x)!\n", hndl);
2062
2063     if (hndl && mmThreadIsValid16(hndl)) {
2064         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2065         ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
2066     }
2067     TRACE("=> %d\n", ret);
2068     return ret;
2069 }
2070
2071 /**************************************************************************
2072  *                              mmThreadIsValid         [MMSYSTEM.1124]
2073  */
2074 BOOL16  WINAPI  mmThreadIsValid16(HANDLE16 hndl)
2075 {
2076     BOOL16              ret = FALSE;
2077
2078     TRACE("(%04x)!\n", hndl);
2079
2080     if (hndl) {
2081         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2082
2083         if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
2084             lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
2085             IsTask16(lpMMThd->hTask)) {
2086             lpMMThd->dwCounter++;
2087             if (lpMMThd->hThread != 0) {
2088                 DWORD   dwThreadRet;
2089                 if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
2090                     dwThreadRet == STATUS_PENDING) {
2091                     ret = TRUE;
2092                 }
2093             } else {
2094                 ret = TRUE;
2095             }
2096             lpMMThd->dwCounter--;
2097         }
2098     }
2099     TRACE("=> %d\n", ret);
2100     return ret;
2101 }
2102
2103 /**************************************************************************
2104  *                              mmThreadGetTask         [MMSYSTEM.1125]
2105  */
2106 HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
2107 {
2108     HANDLE16    ret = 0;
2109
2110     TRACE("(%04x)\n", hndl);
2111
2112     if (mmThreadIsValid16(hndl)) {
2113         WINE_MMTHREAD*  lpMMThd = WINMM_GetmmThread(hndl);
2114         ret = lpMMThd->hTask;
2115     }
2116     return ret;
2117 }
2118
2119 typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
2120
2121 /**************************************************************************
2122  *                      mmShowMMCPLPropertySheet        [MMSYSTEM.1150]
2123  */
2124 BOOL16  WINAPI  mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
2125                                            LPCSTR lpStrTab, LPCSTR lpStrTitle)
2126 {
2127     HANDLE      hndl;
2128     BOOL16      ret = FALSE;
2129
2130     TRACE("(%p \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2131
2132     hndl = LoadLibraryA("MMSYS.CPL");
2133     if (hndl != 0) {
2134         MMCPLCALLBACK   fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
2135         if (fp != NULL) {
2136             DWORD       lc;
2137             ReleaseThunkLock(&lc);
2138             ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2139             RestoreThunkLock(lc);
2140         }
2141         FreeLibrary(hndl);
2142     }
2143
2144     return ret;
2145 }
2146
2147 /**************************************************************************
2148  *                      StackEnter              [MMSYSTEM.32]
2149  */
2150 void WINAPI StackEnter16(void)
2151 {
2152 #ifdef __i386__
2153     /* mmsystem.dll from Win 95 does only this: so does Wine */
2154     __asm__("stc");
2155 #endif
2156 }
2157
2158 /**************************************************************************
2159  *                      StackLeave              [MMSYSTEM.33]
2160  */
2161 void WINAPI StackLeave16(void)
2162 {
2163 #ifdef __i386__
2164     /* mmsystem.dll from Win 95 does only this: so does Wine */
2165     __asm__("stc");
2166 #endif
2167 }
2168
2169 /**************************************************************************
2170  *                      WMMMidiRunOnce          [MMSYSTEM.8]
2171  */
2172 void WINAPI WMMMidiRunOnce16(void)
2173 {
2174     FIXME("(), stub!\n");
2175 }
2176
2177
2178
2179 /* ###################################################
2180  * #                     JOYSTICK                    #
2181  * ###################################################
2182  */
2183
2184 /**************************************************************************
2185  *                              joyGetNumDevs           [MMSYSTEM.101]
2186  */
2187 UINT16 WINAPI joyGetNumDevs16(void)
2188 {
2189     return joyGetNumDevs();
2190 }
2191
2192 /**************************************************************************
2193  *                              joyGetDevCaps           [MMSYSTEM.102]
2194  */
2195 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
2196 {
2197     JOYCAPSA    jca;
2198     MMRESULT    ret;
2199
2200     if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2201
2202     ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
2203
2204     if (ret != JOYERR_NOERROR) return ret;
2205     lpCaps->wMid = jca.wMid;
2206     lpCaps->wPid = jca.wPid;
2207     strcpy(lpCaps->szPname, jca.szPname);
2208     lpCaps->wXmin = jca.wXmin;
2209     lpCaps->wXmax = jca.wXmax;
2210     lpCaps->wYmin = jca.wYmin;
2211     lpCaps->wYmax = jca.wYmax;
2212     lpCaps->wZmin = jca.wZmin;
2213     lpCaps->wZmax = jca.wZmax;
2214     lpCaps->wNumButtons = jca.wNumButtons;
2215     lpCaps->wPeriodMin = jca.wPeriodMin;
2216     lpCaps->wPeriodMax = jca.wPeriodMax;
2217
2218     if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
2219         lpCaps->wRmin = jca.wRmin;
2220         lpCaps->wRmax = jca.wRmax;
2221         lpCaps->wUmin = jca.wUmin;
2222         lpCaps->wUmax = jca.wUmax;
2223         lpCaps->wVmin = jca.wVmin;
2224         lpCaps->wVmax = jca.wVmax;
2225         lpCaps->wCaps = jca.wCaps;
2226         lpCaps->wMaxAxes = jca.wMaxAxes;
2227         lpCaps->wNumAxes = jca.wNumAxes;
2228         lpCaps->wMaxButtons = jca.wMaxButtons;
2229         strcpy(lpCaps->szRegKey, jca.szRegKey);
2230         strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
2231     }
2232
2233     return ret;
2234 }
2235
2236 /**************************************************************************
2237  *                              joyGetPosEx           [MMSYSTEM.110]
2238  */
2239 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
2240 {
2241     return joyGetPosEx(wID, lpInfo);
2242 }
2243
2244 /**************************************************************************
2245  *                              joyGetPos               [MMSYSTEM.103]
2246  */
2247 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
2248 {
2249     JOYINFO     ji;
2250     MMRESULT    ret;
2251
2252     TRACE("(%d, %p);\n", wID, lpInfo);
2253
2254     if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
2255         lpInfo->wXpos = ji.wXpos;
2256         lpInfo->wYpos = ji.wYpos;
2257         lpInfo->wZpos = ji.wZpos;
2258         lpInfo->wButtons = ji.wButtons;
2259     }
2260     return ret;
2261 }
2262
2263 /**************************************************************************
2264  *                              joyGetThreshold         [MMSYSTEM.104]
2265  */
2266 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
2267 {
2268     UINT        t;
2269     MMRESULT    ret;
2270
2271     ret = joyGetThreshold(wID, &t);
2272     if (ret == JOYERR_NOERROR)
2273         *lpThreshold = t;
2274     return ret;
2275 }
2276
2277 /**************************************************************************
2278  *                              joyReleaseCapture       [MMSYSTEM.105]
2279  */
2280 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
2281 {
2282     return joyReleaseCapture(wID);
2283 }
2284
2285 /**************************************************************************
2286  *                              joySetCapture           [MMSYSTEM.106]
2287  */
2288 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
2289 {
2290     return joySetCapture(HWND_32(hWnd), wID, wPeriod, bChanged);
2291 }
2292
2293 /**************************************************************************
2294  *                              joySetThreshold         [MMSYSTEM.107]
2295  */
2296 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
2297 {
2298     return joySetThreshold(wID,wThreshold);
2299 }
2300
2301 /**************************************************************************
2302  *                              joySetCalibration       [MMSYSTEM.109]
2303  */
2304 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
2305 {
2306     FIXME("(%04X): stub.\n", wID);
2307     return JOYERR_NOCANDO;
2308 }