rpcrt4: Support multiple interfaces and transfer syntaxes in bind and bind ack messages.
[wine.git] / dlls / mmsystem.dll16 / mmsystem.c
blob94bb85faf6dc38776ac8295d3c28f99ddbb4d1a4
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MMSYSTEM functions
6 * Copyright 1993 Martin Ayotte
7 * 1998-2003 Eric Pouech
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.
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.
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
25 * Eric POUECH :
26 * 99/4 added mmTask and mmThread functions support
29 #include <stdarg.h>
30 #include <string.h>
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"
41 #include "wine/list.h"
42 #include "wine/winuser16.h"
43 #include "winemm16.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
50 static CRITICAL_SECTION_DEBUG mmdrv_critsect_debug =
52 0, 0, &mmdrv_cs,
53 { &mmdrv_critsect_debug.ProcessLocksList, &mmdrv_critsect_debug.ProcessLocksList },
54 0, 0, { (DWORD_PTR)(__FILE__ ": mmsystem_mmdrv_cs") }
56 CRITICAL_SECTION mmdrv_cs = { &mmdrv_critsect_debug, -1, 0, 0, 0, 0 };
58 /* ###################################################
59 * # LIBRARY #
60 * ###################################################
63 /**************************************************************************
64 * DllEntryPoint (MMSYSTEM.4)
66 * MMSYSTEM DLL entry point
69 BOOL WINAPI MMSYSTEM_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
70 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
72 TRACE("%p 0x%x\n", hinstDLL, fdwReason);
74 return TRUE;
77 /**************************************************************************
78 * WEP [MMSYSTEM.1]
80 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
81 WORD cbHeapSize, LPSTR lpCmdLine)
83 TRACE("STUB: Unloading MMSystem DLL ... hInst=%04X\n", hInstance);
84 return TRUE;
87 /* ###################################################
88 * # TIME #
89 * ###################################################
92 /******************************************************************
93 * MMSYSTEM_MMTIME32to16
97 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16, const MMTIME* mmt32)
99 mmt16->wType = mmt32->wType;
100 /* layout of rest is the same for 32/16,
101 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
103 memcpy(&(mmt16->u), &(mmt32->u), sizeof(mmt16->u));
106 /******************************************************************
107 * MMSYSTEM_MMTIME16to32
111 static void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32, const MMTIME16* mmt16)
113 mmt32->wType = mmt16->wType;
114 /* layout of rest is the same for 32/16,
115 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
117 memcpy(&(mmt32->u), &(mmt16->u), sizeof(mmt16->u));
120 /**************************************************************************
121 * timeGetSystemTime [MMSYSTEM.601]
123 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
125 if (wSize >= sizeof(*lpTime)) {
126 lpTime->wType = TIME_MS;
127 lpTime->u.ms = GetTickCount();
129 TRACE("=> %u\n", lpTime->u.ms);
132 return 0;
135 struct timer_entry {
136 struct list entry;
137 UINT id;
138 LPTIMECALLBACK16 func16;
139 DWORD user;
142 static struct list timer_list = LIST_INIT(timer_list);
144 static void CALLBACK timeCB3216(UINT id, UINT uMsg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2)
146 struct timer_entry* te = (void*)user;
147 WORD args[8];
148 DWORD ret;
150 args[7] = LOWORD(id);
151 args[6] = LOWORD(uMsg);
152 args[5] = HIWORD(te->user);
153 args[4] = LOWORD(te->user);
154 args[3] = HIWORD(dw1);
155 args[2] = LOWORD(dw2);
156 args[1] = HIWORD(dw2);
157 args[0] = LOWORD(dw2);
158 WOWCallback16Ex((DWORD)te->func16, WCB16_PASCAL, sizeof(args), args, &ret);
161 /**************************************************************************
162 * timeSetEvent [MMSYSTEM.602]
164 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol, LPTIMECALLBACK16 lpFunc,
165 DWORD dwUser, UINT16 wFlags)
167 MMRESULT16 id;
168 struct timer_entry* te;
170 switch (wFlags & (TIME_CALLBACK_EVENT_SET|TIME_CALLBACK_EVENT_PULSE))
172 case TIME_CALLBACK_EVENT_SET:
173 case TIME_CALLBACK_EVENT_PULSE:
174 id = timeSetEvent(wDelay, wResol, (LPTIMECALLBACK)lpFunc, dwUser, wFlags);
175 break;
176 case TIME_CALLBACK_FUNCTION:
177 te = HeapAlloc(GetProcessHeap(), 0, sizeof(*te));
178 if (!te) return 0;
179 te->func16 = lpFunc;
180 te->user = dwUser;
181 id = te->id = timeSetEvent(wDelay, wResol, timeCB3216, (DWORD_PTR)te, wFlags);
182 if (id)
184 EnterCriticalSection(&mmdrv_cs);
185 list_add_tail(&timer_list, &te->entry);
186 LeaveCriticalSection(&mmdrv_cs);
188 else HeapFree(GetProcessHeap(), 0, te);
189 break;
190 default:
191 id = 0;
192 break;
194 return id;
197 /**************************************************************************
198 * timeKillEvent [MMSYSTEM.603]
200 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
202 MMRESULT16 ret = timeKillEvent(wID);
203 struct timer_entry* te;
205 if (ret == TIMERR_NOERROR)
207 EnterCriticalSection(&mmdrv_cs);
208 LIST_FOR_EACH_ENTRY(te, &timer_list, struct timer_entry, entry)
210 if (wID == te->id)
212 list_remove(&te->entry);
213 HeapFree(GetProcessHeap(), 0, te);
214 break;
217 LeaveCriticalSection(&mmdrv_cs);
219 return ret;
222 /**************************************************************************
223 * timeGetDevCaps [MMSYSTEM.604]
225 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
227 TIMECAPS caps;
228 MMRESULT ret;
229 TRACE("(%p, %u) !\n", lpCaps, wSize);
231 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
233 ret = timeGetDevCaps(&caps, sizeof(caps));
234 if (ret == MMSYSERR_NOERROR) {
235 TIMECAPS16 tc16;
236 tc16.wPeriodMin = caps.wPeriodMin;
237 tc16.wPeriodMax = caps.wPeriodMax;
238 memcpy(lpCaps, &tc16, min(wSize, sizeof(tc16)));
240 return ret;
243 /**************************************************************************
244 * timeBeginPeriod [MMSYSTEM.605]
246 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
248 TRACE("(%u) !\n", wPeriod);
250 return timeBeginPeriod(wPeriod);
253 /**************************************************************************
254 * timeEndPeriod [MMSYSTEM.606]
256 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
258 TRACE("(%u) !\n", wPeriod);
260 return timeEndPeriod(wPeriod);
263 /**************************************************************************
264 * timeGetTime [MMSYSTEM.607]
266 DWORD WINAPI timeGetTime16(void)
268 return timeGetTime();
271 /* ###################################################
272 * # PlaySound #
273 * ###################################################
276 /**************************************************************************
277 * PlaySound [MMSYSTEM.3]
279 BOOL16 WINAPI PlaySound16(LPCSTR pszSound, HMODULE16 hmod, DWORD fdwSound)
281 BOOL16 retv;
282 DWORD lc;
284 if ((fdwSound & SND_RESOURCE) == SND_RESOURCE)
286 HGLOBAL16 handle;
287 HRSRC16 res;
289 if (!(res = FindResource16( hmod, pszSound, "WAVE" ))) return FALSE;
290 if (!(handle = LoadResource16( hmod, res ))) return FALSE;
291 pszSound = LockResource16(handle);
292 fdwSound = (fdwSound & ~SND_RESOURCE) | SND_MEMORY;
293 /* FIXME: FreeResource16 */
296 ReleaseThunkLock(&lc);
297 retv = PlaySoundA(pszSound, 0, fdwSound);
298 RestoreThunkLock(lc);
300 return retv;
303 /**************************************************************************
304 * sndPlaySound [MMSYSTEM.2]
306 BOOL16 WINAPI sndPlaySound16(LPCSTR lpszSoundName, UINT16 uFlags)
308 BOOL16 retv;
309 DWORD lc;
311 ReleaseThunkLock(&lc);
312 retv = sndPlaySoundA(lpszSoundName, uFlags);
313 RestoreThunkLock(lc);
315 return retv;
318 /* ###################################################
319 * # MISC #
320 * ###################################################
323 /**************************************************************************
324 * mmsystemGetVersion [MMSYSTEM.5]
327 UINT16 WINAPI mmsystemGetVersion16(void)
329 return mmsystemGetVersion();
332 /**************************************************************************
333 * DriverCallback [MMSYSTEM.31]
335 BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HDRVR16 hDev,
336 WORD wMsg, DWORD dwUser, DWORD dwParam1,
337 DWORD dwParam2)
339 return DriverCallback(dwCallBack, uFlags, HDRVR_32(hDev), wMsg, dwUser, dwParam1, dwParam2);
342 /**************************************************************************
343 * OutputDebugStr [MMSYSTEM.30]
345 void WINAPI OutputDebugStr16(LPCSTR str)
347 OutputDebugStringA( str );
350 /* ###################################################
351 * # MIXER #
352 * ###################################################
355 /**************************************************************************
356 * Mixer devices. New to Win95
359 /**************************************************************************
360 * mixerGetNumDevs [MMSYSTEM.800]
362 UINT16 WINAPI mixerGetNumDevs16(void)
364 return mixerGetNumDevs();
367 /**************************************************************************
368 * mixerGetDevCaps [MMSYSTEM.801]
370 UINT16 WINAPI mixerGetDevCaps16(UINT16 uDeviceID, LPMIXERCAPS16 lpCaps,
371 UINT16 uSize)
373 MIXERCAPSA micA;
374 UINT ret;
376 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
378 ret = mixerGetDevCapsA(uDeviceID, &micA, sizeof(micA));
379 if (ret == MMSYSERR_NOERROR) {
380 MIXERCAPS16 mic16;
381 mic16.wMid = micA.wMid;
382 mic16.wPid = micA.wPid;
383 mic16.vDriverVersion = micA.vDriverVersion;
384 strcpy(mic16.szPname, micA.szPname);
385 mic16.fdwSupport = micA.fdwSupport;
386 mic16.cDestinations = micA.cDestinations;
387 memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
389 return ret;
392 /**************************************************************************
393 * mixerOpen [MMSYSTEM.802]
395 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix, UINT16 uDeviceID, DWORD dwCallback,
396 DWORD dwInstance, DWORD fdwOpen)
398 HMIXER hmix;
399 UINT ret;
400 struct mmsystdrv_thunk* thunk;
402 if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, MMSYSTDRV_MIXER)))
404 return MMSYSERR_NOMEM;
406 if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
408 dwCallback = (DWORD)thunk;
411 ret = mixerOpen(&hmix, uDeviceID, dwCallback, dwInstance, fdwOpen);
412 if (ret == MMSYSERR_NOERROR)
414 if (lphmix) *lphmix = HMIXER_16(hmix);
415 if (thunk) MMSYSTDRV_SetHandle(thunk, hmix);
417 else MMSYSTDRV_DeleteThunk(thunk);
418 return ret;
421 /**************************************************************************
422 * mixerClose [MMSYSTEM.803]
424 UINT16 WINAPI mixerClose16(HMIXER16 hMix)
426 UINT ret = mixerClose(HMIXER_32(hMix));
428 if (ret == MMSYSERR_NOERROR)
429 MMSYSTDRV_CloseHandle((void*)HMIXER_32(hMix));
430 return ret;
433 /**************************************************************************
434 * mixerGetID (MMSYSTEM.806)
436 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix, LPUINT16 lpid, DWORD fdwID)
438 UINT xid;
439 UINT ret = mixerGetID(HMIXEROBJ_32(hmix), &xid, fdwID);
441 if (lpid)
442 *lpid = xid;
443 return ret;
446 /**************************************************************************
447 * mixerGetControlDetails [MMSYSTEM.808]
449 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix,
450 LPMIXERCONTROLDETAILS16 lpmcd,
451 DWORD fdwDetails)
453 DWORD ret = MMSYSERR_NOTENABLED;
454 SEGPTR sppaDetails;
456 TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
458 if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
459 return MMSYSERR_INVALPARAM;
461 sppaDetails = (SEGPTR)lpmcd->paDetails;
462 lpmcd->paDetails = MapSL(sppaDetails);
463 ret = mixerGetControlDetailsA(HMIXEROBJ_32(hmix),
464 (LPMIXERCONTROLDETAILS)lpmcd, fdwDetails);
465 lpmcd->paDetails = (LPVOID)sppaDetails;
467 return ret;
470 /**************************************************************************
471 * mixerGetLineControls [MMSYSTEM.807]
473 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,
474 LPMIXERLINECONTROLS16 lpmlc16,
475 DWORD fdwControls)
477 MIXERLINECONTROLSA mlcA;
478 DWORD ret;
479 unsigned int i;
480 LPMIXERCONTROL16 lpmc16;
482 TRACE("(%04x, %p, %08x)\n", hmix, lpmlc16, fdwControls);
484 if (lpmlc16 == NULL || lpmlc16->cbStruct != sizeof(*lpmlc16) ||
485 lpmlc16->cbmxctrl != sizeof(MIXERCONTROL16))
486 return MMSYSERR_INVALPARAM;
488 mlcA.cbStruct = sizeof(mlcA);
489 mlcA.dwLineID = lpmlc16->dwLineID;
490 mlcA.u.dwControlID = lpmlc16->u.dwControlID;
491 mlcA.u.dwControlType = lpmlc16->u.dwControlType;
492 mlcA.cControls = lpmlc16->cControls;
493 mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
494 mlcA.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
495 mlcA.cControls * mlcA.cbmxctrl);
497 ret = mixerGetLineControlsA(HMIXEROBJ_32(hmix), &mlcA, fdwControls);
499 if (ret == MMSYSERR_NOERROR) {
500 lpmlc16->dwLineID = mlcA.dwLineID;
501 lpmlc16->u.dwControlID = mlcA.u.dwControlID;
502 lpmlc16->u.dwControlType = mlcA.u.dwControlType;
503 lpmlc16->cControls = mlcA.cControls;
505 lpmc16 = MapSL(lpmlc16->pamxctrl);
507 for (i = 0; i < mlcA.cControls; i++) {
508 lpmc16[i].cbStruct = sizeof(MIXERCONTROL16);
509 lpmc16[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
510 lpmc16[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
511 lpmc16[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
512 lpmc16[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
513 strcpy(lpmc16[i].szShortName, mlcA.pamxctrl[i].szShortName);
514 strcpy(lpmc16[i].szName, mlcA.pamxctrl[i].szName);
515 /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
516 memcpy(&lpmc16[i].Bounds, &mlcA.pamxctrl[i].Bounds,
517 sizeof(mlcA.pamxctrl[i].Bounds));
518 /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
519 memcpy(&lpmc16[i].Metrics, &mlcA.pamxctrl[i].Metrics,
520 sizeof(mlcA.pamxctrl[i].Metrics));
524 HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
526 return ret;
529 /**************************************************************************
530 * mixerGetLineInfo [MMSYSTEM.805]
532 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix, LPMIXERLINE16 lpmli16,
533 DWORD fdwInfo)
535 MIXERLINEA mliA;
536 UINT ret;
538 TRACE("(%04x, %p, %08x)\n", hmix, lpmli16, fdwInfo);
540 if (lpmli16 == NULL || lpmli16->cbStruct != sizeof(*lpmli16))
541 return MMSYSERR_INVALPARAM;
543 mliA.cbStruct = sizeof(mliA);
544 switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) {
545 case MIXER_GETLINEINFOF_COMPONENTTYPE:
546 mliA.dwComponentType = lpmli16->dwComponentType;
547 break;
548 case MIXER_GETLINEINFOF_DESTINATION:
549 mliA.dwDestination = lpmli16->dwDestination;
550 break;
551 case MIXER_GETLINEINFOF_LINEID:
552 mliA.dwLineID = lpmli16->dwLineID;
553 break;
554 case MIXER_GETLINEINFOF_SOURCE:
555 mliA.dwDestination = lpmli16->dwDestination;
556 mliA.dwSource = lpmli16->dwSource;
557 break;
558 case MIXER_GETLINEINFOF_TARGETTYPE:
559 mliA.Target.dwType = lpmli16->Target.dwType;
560 mliA.Target.wMid = lpmli16->Target.wMid;
561 mliA.Target.wPid = lpmli16->Target.wPid;
562 mliA.Target.vDriverVersion = lpmli16->Target.vDriverVersion;
563 strcpy(mliA.Target.szPname, lpmli16->Target.szPname);
564 break;
565 default:
566 FIXME("Unsupported fdwControls=0x%08x\n", fdwInfo);
569 ret = mixerGetLineInfoA(HMIXEROBJ_32(hmix), &mliA, fdwInfo);
571 lpmli16->dwDestination = mliA.dwDestination;
572 lpmli16->dwSource = mliA.dwSource;
573 lpmli16->dwLineID = mliA.dwLineID;
574 lpmli16->fdwLine = mliA.fdwLine;
575 lpmli16->dwUser = mliA.dwUser;
576 lpmli16->dwComponentType = mliA.dwComponentType;
577 lpmli16->cChannels = mliA.cChannels;
578 lpmli16->cConnections = mliA.cConnections;
579 lpmli16->cControls = mliA.cControls;
580 strcpy(lpmli16->szShortName, mliA.szShortName);
581 strcpy(lpmli16->szName, mliA.szName);
582 lpmli16->Target.dwType = mliA.Target.dwType;
583 lpmli16->Target.dwDeviceID = mliA.Target.dwDeviceID;
584 lpmli16->Target.wMid = mliA.Target.wMid;
585 lpmli16->Target.wPid = mliA.Target.wPid;
586 lpmli16->Target.vDriverVersion = mliA.Target.vDriverVersion;
587 strcpy(lpmli16->Target.szPname, mliA.Target.szPname);
589 return ret;
592 /**************************************************************************
593 * mixerSetControlDetails [MMSYSTEM.809]
595 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,
596 LPMIXERCONTROLDETAILS16 lpmcd,
597 DWORD fdwDetails)
599 TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
600 return MMSYSERR_NOTENABLED;
603 /**************************************************************************
604 * mixerMessage [MMSYSTEM.804]
606 DWORD WINAPI mixerMessage16(HMIXER16 hmix, UINT16 uMsg, DWORD dwParam1,
607 DWORD dwParam2)
609 return mixerMessage(HMIXER_32(hmix), uMsg, dwParam1, dwParam2);
612 /* ###################################################
613 * # AUX #
614 * ###################################################
617 /**************************************************************************
618 * auxGetNumDevs [MMSYSTEM.350]
620 UINT16 WINAPI auxGetNumDevs16(void)
622 return auxGetNumDevs();
625 /**************************************************************************
626 * auxGetDevCaps [MMSYSTEM.351]
628 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID, LPAUXCAPS16 lpCaps, UINT16 uSize)
630 AUXCAPSA acA;
631 UINT ret;
633 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
635 ret = auxGetDevCapsA(uDeviceID, &acA, sizeof(acA));
636 if (ret == MMSYSERR_NOERROR) {
637 AUXCAPS16 ac16;
638 ac16.wMid = acA.wMid;
639 ac16.wPid = acA.wPid;
640 ac16.vDriverVersion = acA.vDriverVersion;
641 strcpy(ac16.szPname, acA.szPname);
642 ac16.wTechnology = acA.wTechnology;
643 ac16.dwSupport = acA.dwSupport;
644 memcpy(lpCaps, &ac16, min(uSize, sizeof(ac16)));
646 return ret;
649 /**************************************************************************
650 * auxGetVolume [MMSYSTEM.352]
652 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, LPDWORD lpdwVolume)
654 return auxGetVolume(uDeviceID, lpdwVolume);
657 /**************************************************************************
658 * auxSetVolume [MMSYSTEM.353]
660 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
662 return auxSetVolume(uDeviceID, dwVolume);
665 /**************************************************************************
666 * auxOutMessage [MMSYSTEM.354]
668 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
670 TRACE("(%04X, %04X, %08X, %08X)\n", uDeviceID, uMessage, dw1, dw2);
672 switch (uMessage) {
673 case AUXDM_GETNUMDEVS:
674 case AUXDM_SETVOLUME:
675 /* no argument conversion needed */
676 break;
677 case AUXDM_GETVOLUME:
678 return auxGetVolume(uDeviceID, MapSL(dw1));
679 case AUXDM_GETDEVCAPS:
680 return auxGetDevCaps16(uDeviceID, MapSL(dw1), dw2);
681 default:
682 TRACE("(%04x, %04x, %08x, %08x): unhandled message\n",
683 uDeviceID, uMessage, dw1, dw2);
684 break;
686 return auxOutMessage(uDeviceID, uMessage, dw1, dw2);
689 /* ###################################################
690 * # MIDI #
691 * ###################################################
694 /**************************************************************************
695 * midiOutGetNumDevs [MMSYSTEM.201]
697 UINT16 WINAPI midiOutGetNumDevs16(void)
699 return midiOutGetNumDevs();
702 /**************************************************************************
703 * midiOutGetDevCaps [MMSYSTEM.202]
705 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID, LPMIDIOUTCAPS16 lpCaps,
706 UINT16 uSize)
708 MIDIOUTCAPSA mocA;
709 UINT ret;
711 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
713 ret = midiOutGetDevCapsA(uDeviceID, &mocA, sizeof(mocA));
714 if (ret == MMSYSERR_NOERROR) {
715 MIDIOUTCAPS16 moc16;
716 moc16.wMid = mocA.wMid;
717 moc16.wPid = mocA.wPid;
718 moc16.vDriverVersion = mocA.vDriverVersion;
719 strcpy(moc16.szPname, mocA.szPname);
720 moc16.wTechnology = mocA.wTechnology;
721 moc16.wVoices = mocA.wVoices;
722 moc16.wNotes = mocA.wNotes;
723 moc16.wChannelMask = mocA.wChannelMask;
724 moc16.dwSupport = mocA.dwSupport;
725 memcpy(lpCaps, &moc16, min(uSize, sizeof(moc16)));
727 return ret;
730 /**************************************************************************
731 * midiOutGetErrorText [MMSYSTEM.203]
732 * midiInGetErrorText [MMSYSTEM.303]
734 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
736 return midiOutGetErrorTextA(uError, lpText, uSize);
739 /**************************************************************************
740 * midiOutOpen [MMSYSTEM.204]
742 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
743 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
745 HMIDIOUT hmo;
746 UINT ret;
747 struct mmsystdrv_thunk* thunk;
749 if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, MMSYSTDRV_MIDIOUT)))
751 return MMSYSERR_NOMEM;
753 if ((dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
755 dwCallback = (DWORD)thunk;
757 ret = midiOutOpen(&hmo, uDeviceID, dwCallback, dwInstance, dwFlags);
758 if (ret == MMSYSERR_NOERROR)
760 if (lphMidiOut != NULL) *lphMidiOut = HMIDIOUT_16(hmo);
761 MMSYSTDRV_SetHandle(thunk, (void*)hmo);
763 else MMSYSTDRV_DeleteThunk(thunk);
764 return ret;
767 /**************************************************************************
768 * midiOutClose [MMSYSTEM.205]
770 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
772 UINT ret = midiOutClose(HMIDIOUT_32(hMidiOut));
774 if (ret == MMSYSERR_NOERROR)
775 MMSYSTDRV_CloseHandle((void*)HMIDIOUT_32(hMidiOut));
776 return ret;
779 /**************************************************************************
780 * midiOutPrepareHeader [MMSYSTEM.206]
782 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut, /* [in] */
783 SEGPTR lpsegMidiOutHdr, /* [???] */
784 UINT16 uSize) /* [in] */
786 TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
788 return MMSYSTDRV_Message(HMIDIOUT_32(hMidiOut), MODM_PREPARE, lpsegMidiOutHdr, uSize);
791 /**************************************************************************
792 * midiOutUnprepareHeader [MMSYSTEM.207]
794 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut, /* [in] */
795 SEGPTR lpsegMidiOutHdr, /* [???] */
796 UINT16 uSize) /* [in] */
798 LPMIDIHDR16 lpMidiOutHdr = MapSL(lpsegMidiOutHdr);
800 TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
802 if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
803 return MMSYSERR_NOERROR;
806 return MMSYSTDRV_Message(HMIDIOUT_32(hMidiOut), MODM_UNPREPARE, lpsegMidiOutHdr, uSize);
809 /**************************************************************************
810 * midiOutShortMsg [MMSYSTEM.208]
812 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
814 return midiOutShortMsg(HMIDIOUT_32(hMidiOut), dwMsg);
817 /**************************************************************************
818 * midiOutLongMsg [MMSYSTEM.209]
820 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut, /* [in] */
821 LPMIDIHDR16 lpsegMidiOutHdr, /* [???] NOTE: SEGPTR */
822 UINT16 uSize) /* [in] */
824 TRACE("(%04X, %p, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
826 return MMSYSTDRV_Message(HMIDIOUT_32(hMidiOut), MODM_LONGDATA, (DWORD_PTR)lpsegMidiOutHdr, uSize);
829 /**************************************************************************
830 * midiOutReset [MMSYSTEM.210]
832 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
834 return midiOutReset(HMIDIOUT_32(hMidiOut));
837 /**************************************************************************
838 * midiOutGetVolume [MMSYSTEM.211]
840 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
842 return midiOutGetVolume(HMIDIOUT_32(uDeviceID), lpdwVolume);
845 /**************************************************************************
846 * midiOutSetVolume [MMSYSTEM.212]
848 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
850 return midiOutSetVolume(HMIDIOUT_32(uDeviceID), dwVolume);
853 /**************************************************************************
854 * midiOutCachePatches [MMSYSTEM.213]
856 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
857 WORD* lpwPatchArray, UINT16 uFlags)
859 return midiOutCachePatches(HMIDIOUT_32(hMidiOut), uBank, lpwPatchArray,
860 uFlags);
863 /**************************************************************************
864 * midiOutCacheDrumPatches [MMSYSTEM.214]
866 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
867 WORD* lpwKeyArray, UINT16 uFlags)
869 return midiOutCacheDrumPatches(HMIDIOUT_32(hMidiOut), uPatch, lpwKeyArray, uFlags);
872 /**************************************************************************
873 * midiOutGetID [MMSYSTEM.215]
875 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
877 UINT devid;
878 UINT16 ret;
880 ret = midiOutGetID(HMIDIOUT_32(hMidiOut), &devid);
881 if (ret != MMSYSERR_NOERROR) return ret;
882 *lpuDeviceID = devid;
883 return ret;
886 /**************************************************************************
887 * midiOutMessage [MMSYSTEM.216]
889 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
890 DWORD dwParam1, DWORD dwParam2)
892 TRACE("(%04X, %04X, %08X, %08X)\n", hMidiOut, uMessage, dwParam1, dwParam2);
894 switch (uMessage) {
895 case MODM_OPEN:
896 case MODM_CLOSE:
897 FIXME("can't handle OPEN or CLOSE message!\n");
898 return MMSYSERR_NOTSUPPORTED;
900 case MODM_GETVOLUME:
901 return midiOutGetVolume16(hMidiOut, MapSL(dwParam1));
902 case MODM_LONGDATA:
903 return midiOutLongMsg16(hMidiOut, MapSL(dwParam1), dwParam2);
904 case MODM_PREPARE:
905 /* lpMidiOutHdr is still a segmented pointer for this function */
906 return midiOutPrepareHeader16(hMidiOut, dwParam1, dwParam2);
907 case MODM_UNPREPARE:
908 return midiOutUnprepareHeader16(hMidiOut, dwParam1, dwParam2);
910 return MMSYSTDRV_Message(HMIDIOUT_32(hMidiOut), uMessage, dwParam1, dwParam2);
913 /**************************************************************************
914 * midiInGetNumDevs [MMSYSTEM.301]
916 UINT16 WINAPI midiInGetNumDevs16(void)
918 return midiInGetNumDevs();
921 /**************************************************************************
922 * midiInGetDevCaps [MMSYSTEM.302]
924 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID, LPMIDIINCAPS16 lpCaps,
925 UINT16 uSize)
927 MIDIINCAPSA micA;
928 UINT ret;
930 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
932 ret = midiInGetDevCapsA(uDeviceID, &micA, uSize);
933 if (ret == MMSYSERR_NOERROR) {
934 MIDIINCAPS16 mic16;
935 mic16.wMid = micA.wMid;
936 mic16.wPid = micA.wPid;
937 mic16.vDriverVersion = micA.vDriverVersion;
938 strcpy(mic16.szPname, micA.szPname);
939 mic16.dwSupport = micA.dwSupport;
940 memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
942 return ret;
945 /**************************************************************************
946 * midiInOpen [MMSYSTEM.304]
948 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
949 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
951 HMIDIIN hmid;
952 UINT ret;
953 struct mmsystdrv_thunk* thunk;
955 if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, MMSYSTDRV_MIDIIN)))
957 return MMSYSERR_NOMEM;
959 if ((dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
961 dwCallback = (DWORD)thunk;
963 ret = midiInOpen(&hmid, uDeviceID, dwCallback, dwInstance, dwFlags);
964 if (ret == MMSYSERR_NOERROR)
966 if (lphMidiIn) *lphMidiIn = HMIDIIN_16(hmid);
967 MMSYSTDRV_SetHandle(thunk, (void*)hmid);
969 else MMSYSTDRV_DeleteThunk(thunk);
970 return ret;
973 /**************************************************************************
974 * midiInClose [MMSYSTEM.305]
976 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
978 UINT ret = midiInClose(HMIDIIN_32(hMidiIn));
980 if (ret == MMSYSERR_NOERROR)
981 MMSYSTDRV_CloseHandle((void*)HMIDIIN_32(hMidiIn));
982 return ret;
985 /**************************************************************************
986 * midiInPrepareHeader [MMSYSTEM.306]
988 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn, /* [in] */
989 SEGPTR lpsegMidiInHdr, /* [???] */
990 UINT16 uSize) /* [in] */
992 TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
994 return MMSYSTDRV_Message(HMIDIIN_32(hMidiIn), MIDM_PREPARE, lpsegMidiInHdr, uSize);
997 /**************************************************************************
998 * midiInUnprepareHeader [MMSYSTEM.307]
1000 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn, /* [in] */
1001 SEGPTR lpsegMidiInHdr, /* [???] */
1002 UINT16 uSize) /* [in] */
1004 LPMIDIHDR16 lpMidiInHdr = MapSL(lpsegMidiInHdr);
1006 TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
1008 if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
1009 return MMSYSERR_NOERROR;
1012 return MMSYSTDRV_Message(HMIDIIN_32(hMidiIn), MIDM_UNPREPARE, lpsegMidiInHdr, uSize);
1015 /**************************************************************************
1016 * midiInAddBuffer [MMSYSTEM.308]
1018 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn, /* [in] */
1019 MIDIHDR16* lpsegMidiInHdr, /* [???] NOTE: SEGPTR */
1020 UINT16 uSize) /* [in] */
1022 TRACE("(%04X, %p, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
1024 return MMSYSTDRV_Message(HMIDIIN_32(hMidiIn), MIDM_ADDBUFFER, (DWORD_PTR)lpsegMidiInHdr, uSize);
1027 /**************************************************************************
1028 * midiInStart [MMSYSTEM.309]
1030 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
1032 return midiInStart(HMIDIIN_32(hMidiIn));
1035 /**************************************************************************
1036 * midiInStop [MMSYSTEM.310]
1038 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
1040 return midiInStop(HMIDIIN_32(hMidiIn));
1043 /**************************************************************************
1044 * midiInReset [MMSYSTEM.311]
1046 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
1048 return midiInReset(HMIDIIN_32(hMidiIn));
1051 /**************************************************************************
1052 * midiInGetID [MMSYSTEM.312]
1054 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
1056 UINT devid;
1057 UINT16 ret;
1059 ret = midiInGetID(HMIDIIN_32(hMidiIn), &devid);
1060 if (ret != MMSYSERR_NOERROR) return ret;
1061 *lpuDeviceID = devid;
1062 return ret;
1065 /**************************************************************************
1066 * midiInMessage [MMSYSTEM.313]
1068 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
1069 DWORD dwParam1, DWORD dwParam2)
1071 TRACE("(%04X, %04X, %08X, %08X)\n", hMidiIn, uMessage, dwParam1, dwParam2);
1073 switch (uMessage) {
1074 case MIDM_OPEN:
1075 case MIDM_CLOSE:
1076 FIXME("can't handle OPEN or CLOSE message!\n");
1077 return MMSYSERR_NOTSUPPORTED;
1079 case MIDM_GETDEVCAPS:
1080 return midiInGetDevCaps16(hMidiIn, MapSL(dwParam1), dwParam2);
1081 case MIDM_PREPARE:
1082 return midiInPrepareHeader16(hMidiIn, dwParam1, dwParam2);
1083 case MIDM_UNPREPARE:
1084 return midiInUnprepareHeader16(hMidiIn, dwParam1, dwParam2);
1085 case MIDM_ADDBUFFER:
1086 return midiInAddBuffer16(hMidiIn, MapSL(dwParam1), dwParam2);
1088 return MMSYSTDRV_Message(HMIDIIN_32(hMidiIn), uMessage, dwParam1, dwParam2);
1091 /**************************************************************************
1092 * midiStreamClose [MMSYSTEM.252]
1094 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hMidiStrm)
1096 UINT ret = midiStreamClose(HMIDISTRM_32(hMidiStrm));
1097 if (ret == MMSYSERR_NOERROR)
1098 MMSYSTDRV_CloseHandle((void*)HMIDISTRM_32(hMidiStrm));
1099 return ret;
1102 /**************************************************************************
1103 * midiStreamOpen [MMSYSTEM.251]
1105 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
1106 DWORD cMidi, DWORD dwCallback,
1107 DWORD dwInstance, DWORD fdwOpen)
1109 HMIDISTRM hMidiStrm32;
1110 MMRESULT ret;
1111 UINT devid32;
1112 struct mmsystdrv_thunk* thunk;
1114 if (!phMidiStrm || !devid)
1115 return MMSYSERR_INVALPARAM;
1116 devid32 = *devid;
1118 if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, MMSYSTDRV_MIDIOUT)))
1120 return MMSYSERR_NOMEM;
1122 if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
1124 dwCallback = (DWORD)thunk;
1126 ret = midiStreamOpen(&hMidiStrm32, &devid32, cMidi, dwCallback, dwInstance, fdwOpen);
1127 if (ret == MMSYSERR_NOERROR)
1129 *phMidiStrm = HMIDISTRM_16(hMidiStrm32);
1130 *devid = devid32;
1131 MMSYSTDRV_SetHandle(thunk, hMidiStrm32);
1133 else MMSYSTDRV_DeleteThunk(thunk);
1134 return ret;
1137 /**************************************************************************
1138 * midiStreamOut [MMSYSTEM.254]
1140 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hMidiStrm, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
1142 return midiStreamOut(HMIDISTRM_32(hMidiStrm), (LPMIDIHDR)lpMidiHdr,
1143 cbMidiHdr);
1146 /**************************************************************************
1147 * midiStreamPause [MMSYSTEM.255]
1149 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hMidiStrm)
1151 return midiStreamPause(HMIDISTRM_32(hMidiStrm));
1154 /**************************************************************************
1155 * midiStreamPosition [MMSYSTEM.253]
1157 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hMidiStrm, LPMMTIME16 lpmmt16, UINT16 cbmmt)
1159 MMTIME mmt32;
1160 MMRESULT ret;
1162 if (!lpmmt16)
1163 return MMSYSERR_INVALPARAM;
1164 MMSYSTEM_MMTIME16to32(&mmt32, lpmmt16);
1165 ret = midiStreamPosition(HMIDISTRM_32(hMidiStrm), &mmt32, sizeof(MMTIME));
1166 MMSYSTEM_MMTIME32to16(lpmmt16, &mmt32);
1167 return ret;
1170 /**************************************************************************
1171 * midiStreamProperty [MMSYSTEM.250]
1173 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hMidiStrm, LPBYTE lpPropData, DWORD dwProperty)
1175 return midiStreamProperty(HMIDISTRM_32(hMidiStrm), lpPropData, dwProperty);
1178 /**************************************************************************
1179 * midiStreamRestart [MMSYSTEM.256]
1181 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hMidiStrm)
1183 return midiStreamRestart(HMIDISTRM_32(hMidiStrm));
1186 /**************************************************************************
1187 * midiStreamStop [MMSYSTEM.257]
1189 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hMidiStrm)
1191 return midiStreamStop(HMIDISTRM_32(hMidiStrm));
1194 /* ###################################################
1195 * # WAVE #
1196 * ###################################################
1199 /**************************************************************************
1200 * waveOutGetNumDevs [MMSYSTEM.401]
1202 UINT16 WINAPI waveOutGetNumDevs16(void)
1204 return waveOutGetNumDevs();
1207 /**************************************************************************
1208 * waveOutGetDevCaps [MMSYSTEM.402]
1210 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID,
1211 LPWAVEOUTCAPS16 lpCaps, UINT16 uSize)
1213 WAVEOUTCAPSA wocA;
1214 UINT ret;
1215 TRACE("(%u %p %u)!\n", uDeviceID, lpCaps, uSize);
1217 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1219 ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA));
1220 if (ret == MMSYSERR_NOERROR) {
1221 WAVEOUTCAPS16 woc16;
1222 woc16.wMid = wocA.wMid;
1223 woc16.wPid = wocA.wPid;
1224 woc16.vDriverVersion = wocA.vDriverVersion;
1225 strcpy(woc16.szPname, wocA.szPname);
1226 woc16.dwFormats = wocA.dwFormats;
1227 woc16.wChannels = wocA.wChannels;
1228 woc16.dwSupport = wocA.dwSupport;
1229 memcpy(lpCaps, &woc16, min(uSize, sizeof(woc16)));
1231 return ret;
1234 /**************************************************************************
1235 * waveOutGetErrorText [MMSYSTEM.403]
1236 * waveInGetErrorText [MMSYSTEM.503]
1238 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1240 return waveOutGetErrorTextA(uError, lpText, uSize);
1243 /**************************************************************************
1244 * waveOutOpen [MMSYSTEM.404]
1246 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
1247 LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1248 DWORD dwInstance, DWORD dwFlags)
1250 HWAVEOUT hWaveOut;
1251 UINT ret;
1252 struct mmsystdrv_thunk* thunk;
1254 if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, MMSYSTDRV_WAVEOUT)))
1256 return MMSYSERR_NOMEM;
1258 if ((dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
1260 dwCallback = (DWORD)thunk;
1262 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1263 * call the 32 bit version
1264 * however, we need to promote correctly the wave mapper id
1265 * (0xFFFFFFFF and not 0x0000FFFF)
1267 ret = waveOutOpen(&hWaveOut, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1268 lpFormat, dwCallback, dwInstance, dwFlags);
1270 if (ret == MMSYSERR_NOERROR)
1272 if (lphWaveOut != NULL) *lphWaveOut = HWAVEOUT_16(hWaveOut);
1273 MMSYSTDRV_SetHandle(thunk, (void*)hWaveOut);
1275 else MMSYSTDRV_DeleteThunk(thunk);
1276 return ret;
1279 /**************************************************************************
1280 * waveOutClose [MMSYSTEM.405]
1282 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
1284 DWORD level;
1285 UINT16 ret;
1287 ReleaseThunkLock(&level);
1288 ret = waveOutClose(HWAVEOUT_32(hWaveOut));
1289 RestoreThunkLock(level);
1290 if (ret == MMSYSERR_NOERROR)
1291 MMSYSTDRV_CloseHandle((void*)HWAVEOUT_32(hWaveOut));
1292 return ret;
1295 /**************************************************************************
1296 * waveOutPrepareHeader [MMSYSTEM.406]
1298 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut, /* [in] */
1299 SEGPTR lpsegWaveOutHdr, /* [???] */
1300 UINT16 uSize) /* [in] */
1302 LPWAVEHDR lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1303 UINT16 result;
1305 TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1307 if (lpWaveOutHdr == NULL) return MMSYSERR_INVALPARAM;
1309 if ((result = MMSYSTDRV_Message(HWAVEOUT_32(hWaveOut), WODM_PREPARE, lpsegWaveOutHdr,
1310 uSize)) != MMSYSERR_NOTSUPPORTED)
1311 return result;
1313 if (lpWaveOutHdr->dwFlags & WHDR_INQUEUE)
1314 return WAVERR_STILLPLAYING;
1316 lpWaveOutHdr->dwFlags |= WHDR_PREPARED;
1317 lpWaveOutHdr->dwFlags &= ~WHDR_DONE;
1319 return MMSYSERR_NOERROR;
1322 /**************************************************************************
1323 * waveOutUnprepareHeader [MMSYSTEM.407]
1325 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut, /* [in] */
1326 SEGPTR lpsegWaveOutHdr, /* [???] */
1327 UINT16 uSize) /* [in] */
1329 LPWAVEHDR lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1331 TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1333 if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
1334 return MMSYSERR_NOERROR;
1337 return MMSYSTDRV_Message(HWAVEOUT_32(hWaveOut), WODM_UNPREPARE, lpsegWaveOutHdr, uSize);
1340 /**************************************************************************
1341 * waveOutWrite [MMSYSTEM.408]
1343 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut, /* [in] */
1344 LPWAVEHDR lpsegWaveOutHdr, /* [???] NOTE: SEGPTR */
1345 UINT16 uSize) /* [in] */
1347 TRACE("(%04X, %p, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1349 return MMSYSTDRV_Message(HWAVEOUT_32(hWaveOut), WODM_WRITE, (DWORD_PTR)lpsegWaveOutHdr, uSize);
1352 /**************************************************************************
1353 * waveOutBreakLoop [MMSYSTEM.419]
1355 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut16)
1357 DWORD level;
1358 UINT16 ret;
1360 ReleaseThunkLock(&level);
1361 ret = waveOutBreakLoop(HWAVEOUT_32(hWaveOut16));
1362 RestoreThunkLock(level);
1363 return ret;
1366 /**************************************************************************
1367 * waveOutPause [MMSYSTEM.409]
1369 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut16)
1371 DWORD level;
1372 UINT16 ret;
1374 ReleaseThunkLock(&level);
1375 ret = waveOutPause(HWAVEOUT_32(hWaveOut16));
1376 RestoreThunkLock(level);
1377 return ret;
1380 /**************************************************************************
1381 * waveOutReset [MMSYSTEM.411]
1383 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut16)
1385 DWORD level;
1386 UINT16 ret;
1388 ReleaseThunkLock(&level);
1389 ret = waveOutReset(HWAVEOUT_32(hWaveOut16));
1390 RestoreThunkLock(level);
1391 return ret;
1394 /**************************************************************************
1395 * waveOutRestart [MMSYSTEM.410]
1397 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut16)
1399 DWORD level;
1400 UINT16 ret;
1402 ReleaseThunkLock(&level);
1403 ret = waveOutRestart(HWAVEOUT_32(hWaveOut16));
1404 RestoreThunkLock(level);
1405 return ret;
1408 /**************************************************************************
1409 * waveOutGetPosition [MMSYSTEM.412]
1411 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
1412 UINT16 uSize)
1414 UINT ret;
1415 MMTIME mmt;
1417 mmt.wType = lpTime->wType;
1418 ret = waveOutGetPosition(HWAVEOUT_32(hWaveOut), &mmt, sizeof(mmt));
1419 MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1420 return ret;
1423 /**************************************************************************
1424 * waveOutGetPitch [MMSYSTEM.413]
1426 UINT16 WINAPI waveOutGetPitch16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1428 return waveOutGetPitch(HWAVEOUT_32(hWaveOut16), lpdw);
1431 /**************************************************************************
1432 * waveOutSetPitch [MMSYSTEM.414]
1434 UINT16 WINAPI waveOutSetPitch16(HWAVEOUT16 hWaveOut16, DWORD dw)
1436 return waveOutSetPitch(HWAVEOUT_32(hWaveOut16), dw);
1439 /**************************************************************************
1440 * waveOutGetPlaybackRate [MMSYSTEM.417]
1442 UINT16 WINAPI waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1444 return waveOutGetPlaybackRate(HWAVEOUT_32(hWaveOut16), lpdw);
1447 /**************************************************************************
1448 * waveOutSetPlaybackRate [MMSYSTEM.418]
1450 UINT16 WINAPI waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16, DWORD dw)
1452 return waveOutSetPlaybackRate(HWAVEOUT_32(hWaveOut16), dw);
1455 /**************************************************************************
1456 * waveOutGetVolume [MMSYSTEM.415]
1458 UINT16 WINAPI waveOutGetVolume16(UINT16 devid, LPDWORD lpdw)
1460 return waveOutGetVolume(HWAVEOUT_32(devid), lpdw);
1463 /**************************************************************************
1464 * waveOutSetVolume [MMSYSTEM.416]
1466 UINT16 WINAPI waveOutSetVolume16(UINT16 devid, DWORD dw)
1468 return waveOutSetVolume(HWAVEOUT_32(devid), dw);
1471 /**************************************************************************
1472 * waveOutGetID [MMSYSTEM.420]
1474 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
1476 UINT devid;
1477 UINT16 ret;
1479 ret = waveOutGetID(HWAVEOUT_32(hWaveOut), &devid);
1480 if (ret != MMSYSERR_NOERROR) return ret;
1481 *lpuDeviceID = devid;
1482 return ret;
1485 /**************************************************************************
1486 * waveOutMessage [MMSYSTEM.421]
1488 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
1489 DWORD dwParam1, DWORD dwParam2)
1491 TRACE("(%04x, %u, %d, %d)\n", hWaveOut, uMessage, dwParam1, dwParam2);
1493 if ((DWORD_PTR)hWaveOut < waveOutGetNumDevs())
1495 if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1496 dwParam1 = (DWORD)MapSL(dwParam1);
1498 else if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1499 /* from M$ KB */
1500 return MMSYSERR_INVALPARAM;
1502 return MMSYSTDRV_Message(HWAVEOUT_32(hWaveOut), uMessage, dwParam1, dwParam2);
1505 /**************************************************************************
1506 * waveInGetNumDevs [MMSYSTEM.501]
1508 UINT16 WINAPI waveInGetNumDevs16(void)
1510 return waveInGetNumDevs();
1513 /**************************************************************************
1514 * waveInGetDevCaps [MMSYSTEM.502]
1516 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps,
1517 UINT16 uSize)
1519 WAVEINCAPSA wicA;
1520 UINT ret;
1522 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1524 ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA));
1525 if (ret == MMSYSERR_NOERROR) {
1526 WAVEINCAPS16 wic16;
1527 wic16.wMid = wicA.wMid;
1528 wic16.wPid = wicA.wPid;
1529 wic16.vDriverVersion = wicA.vDriverVersion;
1530 strcpy(wic16.szPname, wicA.szPname);
1531 wic16.dwFormats = wicA.dwFormats;
1532 wic16.wChannels = wicA.wChannels;
1533 memcpy(lpCaps, &wic16, min(uSize, sizeof(wic16)));
1535 return ret;
1538 /**************************************************************************
1539 * waveInOpen [MMSYSTEM.504]
1541 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
1542 LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1543 DWORD dwInstance, DWORD dwFlags)
1545 HWAVEIN hWaveIn;
1546 UINT ret;
1547 struct mmsystdrv_thunk* thunk;
1549 if (!(thunk = MMSYSTDRV_AddThunk(dwCallback, MMSYSTDRV_WAVEIN)))
1551 return MMSYSERR_NOMEM;
1553 if ((dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
1555 dwCallback = (DWORD)thunk;
1557 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1558 * call the 32 bit version
1559 * however, we need to promote correctly the wave mapper id
1560 * (0xFFFFFFFF and not 0x0000FFFF)
1562 ret = waveInOpen(&hWaveIn, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1563 lpFormat, dwCallback, dwInstance, dwFlags);
1565 if (ret == MMSYSERR_NOERROR)
1567 if (lphWaveIn != NULL) *lphWaveIn = HWAVEIN_16(hWaveIn);
1568 MMSYSTDRV_SetHandle(thunk, (void*)hWaveIn);
1570 else MMSYSTDRV_DeleteThunk(thunk);
1571 return ret;
1574 /**************************************************************************
1575 * waveInClose [MMSYSTEM.505]
1577 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
1579 DWORD level;
1580 UINT16 ret;
1582 ReleaseThunkLock(&level);
1583 ret = waveInClose(HWAVEIN_32(hWaveIn));
1584 RestoreThunkLock(level);
1585 if (ret == MMSYSERR_NOERROR)
1586 MMSYSTDRV_CloseHandle((void*)HWAVEIN_32(hWaveIn));
1587 return ret;
1590 /**************************************************************************
1591 * waveInPrepareHeader [MMSYSTEM.506]
1593 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn, /* [in] */
1594 SEGPTR lpsegWaveInHdr, /* [???] */
1595 UINT16 uSize) /* [in] */
1597 LPWAVEHDR lpWaveInHdr = MapSL(lpsegWaveInHdr);
1598 UINT16 ret;
1600 TRACE("(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
1602 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
1603 lpWaveInHdr->dwBytesRecorded = 0;
1605 ret = MMSYSTDRV_Message(HWAVEIN_32(hWaveIn), WIDM_PREPARE, lpsegWaveInHdr, uSize);
1606 return ret;
1609 /**************************************************************************
1610 * waveInUnprepareHeader [MMSYSTEM.507]
1612 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn, /* [in] */
1613 SEGPTR lpsegWaveInHdr, /* [???] */
1614 UINT16 uSize) /* [in] */
1616 LPWAVEHDR lpWaveInHdr = MapSL(lpsegWaveInHdr);
1618 TRACE("(%04X, %08x, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1620 if (lpWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1622 if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED)) {
1623 return MMSYSERR_NOERROR;
1626 return MMSYSTDRV_Message(HWAVEIN_32(hWaveIn), WIDM_UNPREPARE, lpsegWaveInHdr, uSize);
1629 /**************************************************************************
1630 * waveInAddBuffer [MMSYSTEM.508]
1632 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn, /* [in] */
1633 WAVEHDR* lpsegWaveInHdr, /* [???] NOTE: SEGPTR */
1634 UINT16 uSize) /* [in] */
1636 TRACE("(%04X, %p, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1638 if (lpsegWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1640 return MMSYSTDRV_Message(HWAVEIN_32(hWaveIn), WIDM_ADDBUFFER, (DWORD_PTR)lpsegWaveInHdr, uSize);
1643 /**************************************************************************
1644 * waveInReset [MMSYSTEM.511]
1646 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn16)
1648 DWORD level;
1649 UINT16 ret;
1651 ReleaseThunkLock(&level);
1652 ret = waveInReset(HWAVEIN_32(hWaveIn16));
1653 RestoreThunkLock(level);
1654 return ret;
1657 /**************************************************************************
1658 * waveInStart [MMSYSTEM.509]
1660 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn16)
1662 DWORD level;
1663 UINT16 ret;
1665 ReleaseThunkLock(&level);
1666 ret = waveInStart(HWAVEIN_32(hWaveIn16));
1667 RestoreThunkLock(level);
1668 return ret;
1671 /**************************************************************************
1672 * waveInStop [MMSYSTEM.510]
1674 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn16)
1676 DWORD level;
1677 UINT16 ret;
1679 ReleaseThunkLock(&level);
1680 ret = waveInStop(HWAVEIN_32(hWaveIn16));
1681 RestoreThunkLock(level);
1682 return ret;
1685 /**************************************************************************
1686 * waveInGetPosition [MMSYSTEM.512]
1688 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
1689 UINT16 uSize)
1691 UINT ret;
1692 MMTIME mmt;
1694 mmt.wType = lpTime->wType;
1695 ret = waveInGetPosition(HWAVEIN_32(hWaveIn), &mmt, sizeof(mmt));
1696 MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1697 return ret;
1700 /**************************************************************************
1701 * waveInGetID [MMSYSTEM.513]
1703 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
1705 UINT devid;
1706 UINT16 ret;
1708 ret = waveInGetID(HWAVEIN_32(hWaveIn), &devid);
1709 if (ret != MMSYSERR_NOERROR) return ret;
1710 *lpuDeviceID = devid;
1711 return ret;
1714 /**************************************************************************
1715 * waveInMessage [MMSYSTEM.514]
1717 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
1718 DWORD dwParam1, DWORD dwParam2)
1720 TRACE("(%04x, %u, %d, %d)\n", hWaveIn, uMessage, dwParam1, dwParam2);
1722 if ((DWORD_PTR)hWaveIn < waveInGetNumDevs())
1724 if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1725 dwParam1 = (DWORD)MapSL(dwParam1);
1727 else if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1728 /* from M$ KB */
1729 return MMSYSERR_INVALPARAM;
1731 return MMSYSTDRV_Message(HWAVEIN_32(hWaveIn), uMessage, dwParam1, dwParam2);
1734 /* ###################################################
1735 * # TASK #
1736 * ###################################################
1739 /*#define USE_MM_TSK_WINE*/
1741 /**************************************************************************
1742 * mmTaskCreate [MMSYSTEM.900]
1744 * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
1745 * called upon creation with dwPmt as parameter.
1747 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
1749 HINSTANCE16 ret;
1750 HINSTANCE16 handle;
1751 char cmdline[16];
1752 DWORD showCmd = 0x40002;
1753 LOADPARAMS16 lp;
1755 TRACE("(%08x, %p, %08x);\n", spProc, lphMmTask, dwPmt);
1756 /* This to work requires NE modules to be started with a binary command line
1757 * which is not currently the case. A patch exists but has never been committed.
1758 * A workaround would be to integrate code for mmtask.tsk into Wine, but
1759 * this requires tremendous work (starting with patching tools/build to
1760 * create NE executables (and not only DLLs) for builtins modules.
1761 * EP 99/04/25
1763 FIXME("This is currently broken. It will fail\n");
1765 cmdline[0] = 0x0d;
1766 *(LPDWORD)(cmdline + 1) = (DWORD)spProc;
1767 *(LPDWORD)(cmdline + 5) = dwPmt;
1768 *(LPDWORD)(cmdline + 9) = 0;
1770 lp.hEnvironment = 0;
1771 lp.cmdLine = MapLS(cmdline);
1772 lp.showCmd = MapLS(&showCmd);
1773 lp.reserved = 0;
1775 #ifndef USE_MM_TSK_WINE
1776 handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
1777 #else
1778 handle = LoadModule16("mmtask.tsk", &lp);
1779 #endif
1780 if (handle < 32) {
1781 ret = (handle) ? 1 : 2;
1782 handle = 0;
1783 } else {
1784 ret = 0;
1786 if (lphMmTask)
1787 *lphMmTask = handle;
1789 UnMapLS( lp.cmdLine );
1790 UnMapLS( lp.showCmd );
1791 TRACE("=> 0x%04x/%d\n", handle, ret);
1792 return ret;
1795 #ifdef USE_MM_TSK_WINE
1796 /* C equivalent to mmtask.tsk binary content */
1797 void mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
1799 int len = cmdLine[0x80];
1801 if (len / 2 == 6) {
1802 void (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
1803 DWORD dwPmt = *((DWORD*)(cmdLine + 5));
1805 #if 0
1806 InitTask16(); /* FIXME: pmts / from context ? */
1807 InitApp(di);
1808 #endif
1809 if (SetMessageQueue16(0x40)) {
1810 WaitEvent16(0);
1811 if (HIWORD(fpProc)) {
1812 OldYield16();
1813 /* EPP StackEnter16(); */
1814 (fpProc)(dwPmt);
1818 OldYield16();
1819 OldYield16();
1820 OldYield16();
1821 ExitProcess(0);
1823 #endif
1825 /**************************************************************************
1826 * mmTaskBlock [MMSYSTEM.902]
1828 void WINAPI mmTaskBlock16(HINSTANCE16 hInst)
1830 MSG msg;
1832 do {
1833 GetMessageA(&msg, 0, 0, 0);
1834 if (msg.hwnd) {
1835 TranslateMessage(&msg);
1836 DispatchMessageA(&msg);
1838 } while (msg.message < 0x3A0);
1841 /**************************************************************************
1842 * mmTaskSignal [MMSYSTEM.903]
1844 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
1846 TRACE("(%04x);\n", ht);
1847 return PostThreadMessageW( HTASK_32(ht), WM_USER, 0, 0 );
1850 /**************************************************************************
1851 * mmGetCurrentTask [MMSYSTEM.904]
1853 HTASK16 WINAPI mmGetCurrentTask16(void)
1855 return GetCurrentTask();
1858 /**************************************************************************
1859 * mmTaskYield [MMSYSTEM.905]
1861 void WINAPI mmTaskYield16(void)
1863 MSG msg;
1865 if (PeekMessageA(&msg, 0, 0, 0, 0)) {
1866 WOWYield16();
1870 /******************************************************************
1871 * WINMM_GetmmThread
1875 static WINE_MMTHREAD* WINMM_GetmmThread(HANDLE16 h)
1877 return MapSL(MAKESEGPTR(h, 0));
1880 static void MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
1882 MSG msg;
1883 DWORD ret;
1885 if (lpMMThd->dwThreadID != GetCurrentThreadId())
1886 ERR("Not called by thread itself\n");
1888 for (;;) {
1889 ResetEvent(lpMMThd->hEvent);
1890 if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
1891 break;
1892 InterlockedIncrement(&lpMMThd->dwSignalCount);
1894 TRACE("S1\n");
1896 ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
1897 switch (ret) {
1898 case WAIT_OBJECT_0: /* Event */
1899 TRACE("S2.1\n");
1900 break;
1901 case WAIT_OBJECT_0 + 1: /* Msg */
1902 TRACE("S2.2\n");
1903 if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
1904 TranslateMessage(&msg);
1905 DispatchMessageA(&msg);
1907 break;
1908 default:
1909 WARN("S2.x unsupported ret val 0x%08x\n", ret);
1911 TRACE("S3\n");
1915 /**************************************************************************
1916 * mmThreadBlock [MMSYSTEM.1122]
1918 void WINAPI mmThreadBlock16(HANDLE16 hndl)
1920 TRACE("(%04x)!\n", hndl);
1922 if (hndl) {
1923 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1925 if (lpMMThd->hThread != 0) {
1926 DWORD lc;
1928 ReleaseThunkLock(&lc);
1929 MMSYSTEM_ThreadBlock(lpMMThd);
1930 RestoreThunkLock(lc);
1931 } else {
1932 mmTaskBlock16(lpMMThd->hTask);
1935 TRACE("done\n");
1938 /**************************************************************************
1939 * __wine_mmThreadEntryPoint (MMSYSTEM.2047)
1941 DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID p)
1943 HANDLE16 hndl = (HANDLE16)(DWORD_PTR)p;
1944 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1946 TRACE("(%04x %p)\n", hndl, lpMMThd);
1948 lpMMThd->hTask = LOWORD(GetCurrentTask());
1949 TRACE("[10-%p] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
1950 lpMMThd->dwStatus = 0x10;
1951 MMSYSTEM_ThreadBlock(lpMMThd);
1952 TRACE("[20-%p]\n", lpMMThd->hThread);
1953 lpMMThd->dwStatus = 0x20;
1954 if (lpMMThd->fpThread) {
1955 WOWCallback16(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
1957 lpMMThd->dwStatus = 0x30;
1958 TRACE("[30-%p]\n", lpMMThd->hThread);
1959 while (lpMMThd->dwCounter) {
1960 Sleep(1);
1961 /* WOWYield16();*/
1963 TRACE("[XX-%p]\n", lpMMThd->hThread);
1964 /* paranoia */
1965 lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
1966 /* close lpMMThread->hVxD directIO */
1967 if (lpMMThd->hEvent)
1968 CloseHandle(lpMMThd->hEvent);
1969 GlobalFree16(hndl);
1970 TRACE("done\n");
1972 return 0;
1975 extern DWORD WINAPI GetProcessFlags(DWORD);
1977 /**************************************************************************
1978 * mmThreadCreate [MMSYSTEM.1120]
1980 * undocumented
1981 * Creates a MM thread, calling fpThreadAddr(dwPmt).
1982 * dwFlags:
1983 * bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
1984 * bit.1 set means to open a VxD for this thread (unsupported)
1986 LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD dwPmt, DWORD dwFlags)
1988 HANDLE16 hndl;
1989 LRESULT ret;
1991 TRACE("(%p, %p, %08x, %08x)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
1993 hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
1995 if (hndl == 0) {
1996 ret = 2;
1997 } else {
1998 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2000 #if 0
2001 /* force mmtask routines even if mmthread is required */
2002 /* this will work only if the patch about binary cmd line and NE tasks
2003 * is committed
2005 dwFlags |= 1;
2006 #endif
2008 lpMMThd->dwSignature = WINE_MMTHREAD_CREATED;
2009 lpMMThd->dwCounter = 0;
2010 lpMMThd->hThread = 0;
2011 lpMMThd->dwThreadID = 0;
2012 lpMMThd->fpThread = (DWORD)fpThreadAddr;
2013 lpMMThd->dwThreadPmt = dwPmt;
2014 lpMMThd->dwSignalCount = 0;
2015 lpMMThd->hEvent = 0;
2016 lpMMThd->hVxD = 0;
2017 lpMMThd->dwStatus = 0;
2018 lpMMThd->dwFlags = dwFlags;
2019 lpMMThd->hTask = 0;
2021 if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
2022 lpMMThd->hEvent = CreateEventW(NULL, FALSE, TRUE, NULL);
2024 TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
2025 if (lpMMThd->dwFlags & 2) {
2026 /* as long as we don't support MM VxD in wine, we don't need
2027 * to care about this flag
2029 /* FIXME("Don't know how to properly open VxD handles\n"); */
2030 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
2033 lpMMThd->hThread = CreateThread(0, 0, WINE_mmThreadEntryPoint,
2034 (LPVOID)(DWORD_PTR)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
2035 if (lpMMThd->hThread == 0) {
2036 WARN("Couldn't create thread\n");
2037 /* clean-up(VxDhandle...); devicedirectio... */
2038 if (lpMMThd->hEvent != 0)
2039 CloseHandle(lpMMThd->hEvent);
2040 ret = 2;
2041 } else {
2042 SetThreadPriority(lpMMThd->hThread, THREAD_PRIORITY_TIME_CRITICAL);
2043 TRACE("Got a nice thread hndl=%p id=0x%08x\n", lpMMThd->hThread, lpMMThd->dwThreadID);
2044 ret = 0;
2046 } else {
2047 /* get WINE_mmThreadEntryPoint()
2048 * 2047 is its ordinal in mmsystem.spec
2050 FARPROC16 fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
2052 TRACE("farproc seg=0x%p lin=%p\n", fp, MapSL((SEGPTR)fp));
2054 ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
2057 if (ret == 0) {
2058 if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
2059 WARN("Couldn't resume thread\n");
2061 while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
2062 UserYield16();
2067 if (ret != 0) {
2068 GlobalFree16(hndl);
2069 hndl = 0;
2072 if (lpHndl)
2073 *lpHndl = hndl;
2075 TRACE("ok => %ld\n", ret);
2076 return ret;
2079 /**************************************************************************
2080 * mmThreadSignal [MMSYSTEM.1121]
2082 void WINAPI mmThreadSignal16(HANDLE16 hndl)
2084 TRACE("(%04x)!\n", hndl);
2086 if (hndl) {
2087 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2089 lpMMThd->dwCounter++;
2090 if (lpMMThd->hThread != 0) {
2091 InterlockedIncrement(&lpMMThd->dwSignalCount);
2092 SetEvent(lpMMThd->hEvent);
2093 } else {
2094 mmTaskSignal16(lpMMThd->hTask);
2096 lpMMThd->dwCounter--;
2100 /**************************************************************************
2101 * mmThreadIsCurrent [MMSYSTEM.1123]
2103 BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
2105 BOOL16 ret = FALSE;
2107 TRACE("(%04x)!\n", hndl);
2109 if (hndl && mmThreadIsValid16(hndl)) {
2110 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2111 ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
2113 TRACE("=> %d\n", ret);
2114 return ret;
2117 /**************************************************************************
2118 * mmThreadIsValid [MMSYSTEM.1124]
2120 BOOL16 WINAPI mmThreadIsValid16(HANDLE16 hndl)
2122 BOOL16 ret = FALSE;
2124 TRACE("(%04x)!\n", hndl);
2126 if (hndl) {
2127 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2129 if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
2130 lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
2131 IsTask16(lpMMThd->hTask)) {
2132 lpMMThd->dwCounter++;
2133 if (lpMMThd->hThread != 0) {
2134 DWORD dwThreadRet;
2135 if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
2136 dwThreadRet == STATUS_PENDING) {
2137 ret = TRUE;
2139 } else {
2140 ret = TRUE;
2142 lpMMThd->dwCounter--;
2145 TRACE("=> %d\n", ret);
2146 return ret;
2149 /**************************************************************************
2150 * mmThreadGetTask [MMSYSTEM.1125]
2152 HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
2154 HANDLE16 ret = 0;
2156 TRACE("(%04x)\n", hndl);
2158 if (mmThreadIsValid16(hndl)) {
2159 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2160 ret = lpMMThd->hTask;
2162 return ret;
2165 typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
2167 /**************************************************************************
2168 * mmShowMMCPLPropertySheet [MMSYSTEM.1150]
2170 BOOL16 WINAPI mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
2171 LPCSTR lpStrTab, LPCSTR lpStrTitle)
2173 HANDLE hndl;
2174 BOOL16 ret = FALSE;
2176 TRACE("(%p \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2178 hndl = LoadLibraryA("MMSYS.CPL");
2179 if (hndl != 0) {
2180 MMCPLCALLBACK fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
2181 if (fp != NULL) {
2182 DWORD lc;
2183 ReleaseThunkLock(&lc);
2184 ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2185 RestoreThunkLock(lc);
2187 FreeLibrary(hndl);
2190 return ret;
2193 /**************************************************************************
2194 * StackEnter [MMSYSTEM.32]
2196 void WINAPI StackEnter16(void)
2198 #ifdef __i386__
2199 /* mmsystem.dll from Win 95 does only this: so does Wine */
2200 __asm__("stc");
2201 #endif
2204 /**************************************************************************
2205 * StackLeave [MMSYSTEM.33]
2207 void WINAPI StackLeave16(void)
2209 #ifdef __i386__
2210 /* mmsystem.dll from Win 95 does only this: so does Wine */
2211 __asm__("stc");
2212 #endif
2215 /**************************************************************************
2216 * WMMMidiRunOnce [MMSYSTEM.8]
2218 void WINAPI WMMMidiRunOnce16(void)
2220 FIXME("(), stub!\n");
2223 /**************************************************************************
2224 * DrvOpen [MMSYSTEM.1100]
2226 HDRVR16 WINAPI DrvOpen16(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
2228 return OpenDriver16(lpDriverName, lpSectionName, lParam);
2231 /**************************************************************************
2232 * DrvClose [MMSYSTEM.1101]
2234 LRESULT WINAPI DrvClose16(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
2236 return CloseDriver16(hDrv, lParam1, lParam2);
2239 /**************************************************************************
2240 * DrvSendMessage [MMSYSTEM.1102]
2242 LRESULT WINAPI DrvSendMessage16(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
2243 LPARAM lParam2)
2245 return SendDriverMessage16(hDrv, msg, lParam1, lParam2);
2248 /**************************************************************************
2249 * DrvGetModuleHandle [MMSYSTEM.1103]
2251 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
2253 return GetDriverModuleHandle16(hDrv);
2256 /**************************************************************************
2257 * DrvDefDriverProc [MMSYSTEM.1104]
2259 LRESULT WINAPI DrvDefDriverProc16(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
2260 DWORD dwParam1, DWORD dwParam2)
2262 return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
2265 /**************************************************************************
2266 * DriverProc [MMSYSTEM.6]
2268 LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
2269 DWORD dwParam1, DWORD dwParam2)
2271 TRACE("dwDevID=%08x hDrv=%04x wMsg=%04x dwParam1=%08x dwParam2=%08x\n",
2272 dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2274 return DrvDefDriverProc16(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2277 /* ###################################################
2278 * # JOYSTICK #
2279 * ###################################################
2282 /**************************************************************************
2283 * joyGetNumDevs [MMSYSTEM.101]
2285 UINT16 WINAPI joyGetNumDevs16(void)
2287 return joyGetNumDevs();
2290 /**************************************************************************
2291 * joyGetDevCaps [MMSYSTEM.102]
2293 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
2295 JOYCAPSA jca;
2296 MMRESULT ret;
2298 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2300 ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
2302 if (ret != JOYERR_NOERROR) return ret;
2303 lpCaps->wMid = jca.wMid;
2304 lpCaps->wPid = jca.wPid;
2305 strcpy(lpCaps->szPname, jca.szPname);
2306 lpCaps->wXmin = jca.wXmin;
2307 lpCaps->wXmax = jca.wXmax;
2308 lpCaps->wYmin = jca.wYmin;
2309 lpCaps->wYmax = jca.wYmax;
2310 lpCaps->wZmin = jca.wZmin;
2311 lpCaps->wZmax = jca.wZmax;
2312 lpCaps->wNumButtons = jca.wNumButtons;
2313 lpCaps->wPeriodMin = jca.wPeriodMin;
2314 lpCaps->wPeriodMax = jca.wPeriodMax;
2316 if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
2317 lpCaps->wRmin = jca.wRmin;
2318 lpCaps->wRmax = jca.wRmax;
2319 lpCaps->wUmin = jca.wUmin;
2320 lpCaps->wUmax = jca.wUmax;
2321 lpCaps->wVmin = jca.wVmin;
2322 lpCaps->wVmax = jca.wVmax;
2323 lpCaps->wCaps = jca.wCaps;
2324 lpCaps->wMaxAxes = jca.wMaxAxes;
2325 lpCaps->wNumAxes = jca.wNumAxes;
2326 lpCaps->wMaxButtons = jca.wMaxButtons;
2327 strcpy(lpCaps->szRegKey, jca.szRegKey);
2328 strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
2331 return ret;
2334 /**************************************************************************
2335 * joyGetPosEx [MMSYSTEM.110]
2337 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
2339 return joyGetPosEx(wID, lpInfo);
2342 /**************************************************************************
2343 * joyGetPos [MMSYSTEM.103]
2345 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
2347 JOYINFO ji;
2348 MMRESULT ret;
2350 TRACE("(%d, %p);\n", wID, lpInfo);
2352 if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
2353 lpInfo->wXpos = ji.wXpos;
2354 lpInfo->wYpos = ji.wYpos;
2355 lpInfo->wZpos = ji.wZpos;
2356 lpInfo->wButtons = ji.wButtons;
2358 return ret;
2361 /**************************************************************************
2362 * joyGetThreshold [MMSYSTEM.104]
2364 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
2366 UINT t;
2367 MMRESULT ret;
2369 ret = joyGetThreshold(wID, &t);
2370 if (ret == JOYERR_NOERROR)
2371 *lpThreshold = t;
2372 return ret;
2375 /**************************************************************************
2376 * joyReleaseCapture [MMSYSTEM.105]
2378 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
2380 return joyReleaseCapture(wID);
2383 /**************************************************************************
2384 * joySetCapture [MMSYSTEM.106]
2386 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
2388 return joySetCapture(HWND_32(hWnd), wID, wPeriod, bChanged);
2391 /**************************************************************************
2392 * joySetThreshold [MMSYSTEM.107]
2394 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
2396 return joySetThreshold(wID,wThreshold);
2399 /**************************************************************************
2400 * joySetCalibration [MMSYSTEM.109]
2402 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
2404 FIXME("(%04X): stub.\n", wID);
2405 return JOYERR_NOCANDO;