winmm: Use the new 16=>32 thunks for Aux driver type.
[wine/wine-gecko.git] / dlls / winmm / mmsystem.c
blob154955391d0c6900f89f3d9b6ce417fb730eea14
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 "winemm.h"
44 #include "winemm16.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
50 static WINE_MMTHREAD* WINMM_GetmmThread(HANDLE16);
51 static LPWINE_DRIVER DRIVER_OpenDriver16(LPCWSTR, LPCWSTR, LPARAM);
52 static LRESULT DRIVER_CloseDriver16(HDRVR16, LPARAM, LPARAM);
53 static LRESULT DRIVER_SendMessage16(HDRVR16, UINT, LPARAM, LPARAM);
55 static CRITICAL_SECTION_DEBUG mmdrv_critsect_debug =
57 0, 0, &mmdrv_cs,
58 { &mmdrv_critsect_debug.ProcessLocksList, &mmdrv_critsect_debug.ProcessLocksList },
59 0, 0, { (DWORD_PTR)(__FILE__ ": mmsystem_mmdrv_cs") }
61 CRITICAL_SECTION mmdrv_cs = { &mmdrv_critsect_debug, -1, 0, 0, 0, 0 };
63 /* ###################################################
64 * # LIBRARY #
65 * ###################################################
68 /**************************************************************************
69 * DllEntryPoint (MMSYSTEM.4)
71 * MMSYSTEM DLL entry point
74 BOOL WINAPI MMSYSTEM_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
75 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
77 TRACE("%p 0x%x\n", hinstDLL, fdwReason);
79 switch (fdwReason) {
80 case DLL_PROCESS_ATTACH:
81 /* need to load WinMM in order to:
82 * - initiate correctly shared variables (WINMM_Init())
84 if (!GetModuleHandleA("WINMM.DLL"))
86 ERR("Could not load sibling WinMM.dll\n");
87 return FALSE;
89 /* hook in our 16 bit function pointers */
90 pFnGetMMThread16 = WINMM_GetmmThread;
91 pFnOpenDriver16 = DRIVER_OpenDriver16;
92 pFnCloseDriver16 = DRIVER_CloseDriver16;
93 pFnSendMessage16 = DRIVER_SendMessage16;
94 pFnReleaseThunkLock = ReleaseThunkLock;
95 pFnRestoreThunkLock = RestoreThunkLock;
96 MMDRV_Init16();
97 break;
98 case DLL_PROCESS_DETACH:
99 pFnGetMMThread16 = NULL;
100 pFnOpenDriver16 = NULL;
101 pFnCloseDriver16 = NULL;
102 pFnSendMessage16 = NULL;
103 pFnReleaseThunkLock = NULL;
104 pFnRestoreThunkLock = NULL;
105 /* FIXME: add equivalent for MMDRV_Init16() */
106 break;
107 case DLL_THREAD_ATTACH:
108 case DLL_THREAD_DETACH:
109 break;
111 return TRUE;
114 /**************************************************************************
115 * WEP [MMSYSTEM.1]
117 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
118 WORD cbHeapSize, LPSTR lpCmdLine)
120 TRACE("STUB: Unloading MMSystem DLL ... hInst=%04X\n", hInstance);
121 return TRUE;
124 /* ###################################################
125 * # PlaySound #
126 * ###################################################
129 /**************************************************************************
130 * PlaySound [MMSYSTEM.3]
132 BOOL16 WINAPI PlaySound16(LPCSTR pszSound, HMODULE16 hmod, DWORD fdwSound)
134 BOOL16 retv;
135 DWORD lc;
137 if ((fdwSound & SND_RESOURCE) == SND_RESOURCE)
139 HGLOBAL16 handle;
140 HRSRC16 res;
142 if (!(res = FindResource16( hmod, pszSound, "WAVE" ))) return FALSE;
143 if (!(handle = LoadResource16( hmod, res ))) return FALSE;
144 pszSound = LockResource16(handle);
145 fdwSound = (fdwSound & ~SND_RESOURCE) | SND_MEMORY;
146 /* FIXME: FreeResource16 */
149 ReleaseThunkLock(&lc);
150 retv = PlaySoundA(pszSound, 0, fdwSound);
151 RestoreThunkLock(lc);
153 return retv;
156 /**************************************************************************
157 * sndPlaySound [MMSYSTEM.2]
159 BOOL16 WINAPI sndPlaySound16(LPCSTR lpszSoundName, UINT16 uFlags)
161 BOOL16 retv;
162 DWORD lc;
164 ReleaseThunkLock(&lc);
165 retv = sndPlaySoundA(lpszSoundName, uFlags);
166 RestoreThunkLock(lc);
168 return retv;
171 /* ###################################################
172 * # MISC #
173 * ###################################################
176 /**************************************************************************
177 * mmsystemGetVersion [MMSYSTEM.5]
180 UINT16 WINAPI mmsystemGetVersion16(void)
182 return mmsystemGetVersion();
185 /**************************************************************************
186 * DriverCallback [MMSYSTEM.31]
188 BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HDRVR16 hDev,
189 WORD wMsg, DWORD dwUser, DWORD dwParam1,
190 DWORD dwParam2)
192 return DriverCallback(dwCallBack, uFlags, HDRVR_32(hDev), wMsg, dwUser, dwParam1, dwParam2);
195 /**************************************************************************
196 * OutputDebugStr [MMSYSTEM.30]
198 void WINAPI OutputDebugStr16(LPCSTR str)
200 OutputDebugStringA( str );
203 /* ###################################################
204 * # MIXER #
205 * ###################################################
208 /**************************************************************************
209 * Mixer devices. New to Win95
212 /**************************************************************************
213 * mixerGetNumDevs [MMSYSTEM.800]
215 UINT16 WINAPI mixerGetNumDevs16(void)
217 return mixerGetNumDevs();
220 /**************************************************************************
221 * mixerGetDevCaps [MMSYSTEM.801]
223 UINT16 WINAPI mixerGetDevCaps16(UINT16 uDeviceID, LPMIXERCAPS16 lpCaps,
224 UINT16 uSize)
226 MIXERCAPSA micA;
227 UINT ret;
229 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
231 ret = mixerGetDevCapsA(uDeviceID, &micA, sizeof(micA));
232 if (ret == MMSYSERR_NOERROR) {
233 MIXERCAPS16 mic16;
234 mic16.wMid = micA.wMid;
235 mic16.wPid = micA.wPid;
236 mic16.vDriverVersion = micA.vDriverVersion;
237 strcpy(mic16.szPname, micA.szPname);
238 mic16.fdwSupport = micA.fdwSupport;
239 mic16.cDestinations = micA.cDestinations;
240 memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
242 return ret;
245 /**************************************************************************
246 * mixerOpen [MMSYSTEM.802]
248 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix, UINT16 uDeviceID, DWORD dwCallback,
249 DWORD dwInstance, DWORD fdwOpen)
251 HMIXER hmix;
252 UINT ret;
254 ret = MIXER_Open(&hmix, uDeviceID, dwCallback, dwInstance, fdwOpen, FALSE);
255 if (lphmix) *lphmix = HMIXER_16(hmix);
256 return ret;
259 /**************************************************************************
260 * mixerClose [MMSYSTEM.803]
262 UINT16 WINAPI mixerClose16(HMIXER16 hMix)
264 return mixerClose(HMIXER_32(hMix));
267 /**************************************************************************
268 * mixerGetID (MMSYSTEM.806)
270 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix, LPUINT16 lpid, DWORD fdwID)
272 UINT xid;
273 UINT ret = mixerGetID(HMIXEROBJ_32(hmix), &xid, fdwID);
275 if (lpid)
276 *lpid = xid;
277 return ret;
280 /**************************************************************************
281 * mixerGetControlDetails [MMSYSTEM.808]
283 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix,
284 LPMIXERCONTROLDETAILS16 lpmcd,
285 DWORD fdwDetails)
287 DWORD ret = MMSYSERR_NOTENABLED;
288 SEGPTR sppaDetails;
290 TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
292 if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
293 return MMSYSERR_INVALPARAM;
295 sppaDetails = (SEGPTR)lpmcd->paDetails;
296 lpmcd->paDetails = MapSL(sppaDetails);
297 ret = mixerGetControlDetailsA(HMIXEROBJ_32(hmix),
298 (LPMIXERCONTROLDETAILS)lpmcd, fdwDetails);
299 lpmcd->paDetails = (LPVOID)sppaDetails;
301 return ret;
304 /**************************************************************************
305 * mixerGetLineControls [MMSYSTEM.807]
307 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,
308 LPMIXERLINECONTROLS16 lpmlc16,
309 DWORD fdwControls)
311 MIXERLINECONTROLSA mlcA;
312 DWORD ret;
313 unsigned int i;
314 LPMIXERCONTROL16 lpmc16;
316 TRACE("(%04x, %p, %08x)\n", hmix, lpmlc16, fdwControls);
318 if (lpmlc16 == NULL || lpmlc16->cbStruct != sizeof(*lpmlc16) ||
319 lpmlc16->cbmxctrl != sizeof(MIXERCONTROL16))
320 return MMSYSERR_INVALPARAM;
322 mlcA.cbStruct = sizeof(mlcA);
323 mlcA.dwLineID = lpmlc16->dwLineID;
324 mlcA.u.dwControlID = lpmlc16->u.dwControlID;
325 mlcA.u.dwControlType = lpmlc16->u.dwControlType;
326 mlcA.cControls = lpmlc16->cControls;
327 mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
328 mlcA.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
329 mlcA.cControls * mlcA.cbmxctrl);
331 ret = mixerGetLineControlsA(HMIXEROBJ_32(hmix), &mlcA, fdwControls);
333 if (ret == MMSYSERR_NOERROR) {
334 lpmlc16->dwLineID = mlcA.dwLineID;
335 lpmlc16->u.dwControlID = mlcA.u.dwControlID;
336 lpmlc16->u.dwControlType = mlcA.u.dwControlType;
337 lpmlc16->cControls = mlcA.cControls;
339 lpmc16 = MapSL(lpmlc16->pamxctrl);
341 for (i = 0; i < mlcA.cControls; i++) {
342 lpmc16[i].cbStruct = sizeof(MIXERCONTROL16);
343 lpmc16[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
344 lpmc16[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
345 lpmc16[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
346 lpmc16[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
347 strcpy(lpmc16[i].szShortName, mlcA.pamxctrl[i].szShortName);
348 strcpy(lpmc16[i].szName, mlcA.pamxctrl[i].szName);
349 /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
350 memcpy(&lpmc16[i].Bounds, &mlcA.pamxctrl[i].Bounds,
351 sizeof(mlcA.pamxctrl[i].Bounds));
352 /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
353 memcpy(&lpmc16[i].Metrics, &mlcA.pamxctrl[i].Metrics,
354 sizeof(mlcA.pamxctrl[i].Metrics));
358 HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
360 return ret;
363 /**************************************************************************
364 * mixerGetLineInfo [MMSYSTEM.805]
366 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix, LPMIXERLINE16 lpmli16,
367 DWORD fdwInfo)
369 MIXERLINEA mliA;
370 UINT ret;
372 TRACE("(%04x, %p, %08x)\n", hmix, lpmli16, fdwInfo);
374 if (lpmli16 == NULL || lpmli16->cbStruct != sizeof(*lpmli16))
375 return MMSYSERR_INVALPARAM;
377 mliA.cbStruct = sizeof(mliA);
378 switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) {
379 case MIXER_GETLINEINFOF_COMPONENTTYPE:
380 mliA.dwComponentType = lpmli16->dwComponentType;
381 break;
382 case MIXER_GETLINEINFOF_DESTINATION:
383 mliA.dwDestination = lpmli16->dwDestination;
384 break;
385 case MIXER_GETLINEINFOF_LINEID:
386 mliA.dwLineID = lpmli16->dwLineID;
387 break;
388 case MIXER_GETLINEINFOF_SOURCE:
389 mliA.dwDestination = lpmli16->dwDestination;
390 mliA.dwSource = lpmli16->dwSource;
391 break;
392 case MIXER_GETLINEINFOF_TARGETTYPE:
393 mliA.Target.dwType = lpmli16->Target.dwType;
394 mliA.Target.wMid = lpmli16->Target.wMid;
395 mliA.Target.wPid = lpmli16->Target.wPid;
396 mliA.Target.vDriverVersion = lpmli16->Target.vDriverVersion;
397 strcpy(mliA.Target.szPname, lpmli16->Target.szPname);
398 break;
399 default:
400 FIXME("Unsupported fdwControls=0x%08x\n", fdwInfo);
403 ret = mixerGetLineInfoA(HMIXEROBJ_32(hmix), &mliA, fdwInfo);
405 lpmli16->dwDestination = mliA.dwDestination;
406 lpmli16->dwSource = mliA.dwSource;
407 lpmli16->dwLineID = mliA.dwLineID;
408 lpmli16->fdwLine = mliA.fdwLine;
409 lpmli16->dwUser = mliA.dwUser;
410 lpmli16->dwComponentType = mliA.dwComponentType;
411 lpmli16->cChannels = mliA.cChannels;
412 lpmli16->cConnections = mliA.cConnections;
413 lpmli16->cControls = mliA.cControls;
414 strcpy(lpmli16->szShortName, mliA.szShortName);
415 strcpy(lpmli16->szName, mliA.szName);
416 lpmli16->Target.dwType = mliA.Target.dwType;
417 lpmli16->Target.dwDeviceID = mliA.Target.dwDeviceID;
418 lpmli16->Target.wMid = mliA.Target.wMid;
419 lpmli16->Target.wPid = mliA.Target.wPid;
420 lpmli16->Target.vDriverVersion = mliA.Target.vDriverVersion;
421 strcpy(lpmli16->Target.szPname, mliA.Target.szPname);
423 return ret;
426 /**************************************************************************
427 * mixerSetControlDetails [MMSYSTEM.809]
429 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,
430 LPMIXERCONTROLDETAILS16 lpmcd,
431 DWORD fdwDetails)
433 TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
434 return MMSYSERR_NOTENABLED;
437 /**************************************************************************
438 * mixerMessage [MMSYSTEM.804]
440 DWORD WINAPI mixerMessage16(HMIXER16 hmix, UINT16 uMsg, DWORD dwParam1,
441 DWORD dwParam2)
443 return mixerMessage(HMIXER_32(hmix), uMsg, dwParam1, dwParam2);
446 /* ###################################################
447 * # AUX #
448 * ###################################################
451 /**************************************************************************
452 * auxGetNumDevs [MMSYSTEM.350]
454 UINT16 WINAPI auxGetNumDevs16(void)
456 return auxGetNumDevs();
459 /**************************************************************************
460 * auxGetDevCaps [MMSYSTEM.351]
462 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID, LPAUXCAPS16 lpCaps, UINT16 uSize)
464 AUXCAPSA acA;
465 UINT ret;
467 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
469 ret = auxGetDevCapsA(uDeviceID, &acA, sizeof(acA));
470 if (ret == MMSYSERR_NOERROR) {
471 AUXCAPS16 ac16;
472 ac16.wMid = acA.wMid;
473 ac16.wPid = acA.wPid;
474 ac16.vDriverVersion = acA.vDriverVersion;
475 strcpy(ac16.szPname, acA.szPname);
476 ac16.wTechnology = acA.wTechnology;
477 ac16.dwSupport = acA.dwSupport;
478 memcpy(lpCaps, &ac16, min(uSize, sizeof(ac16)));
480 return ret;
483 /**************************************************************************
484 * auxGetVolume [MMSYSTEM.352]
486 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, LPDWORD lpdwVolume)
488 return auxGetVolume(uDeviceID, lpdwVolume);
491 /**************************************************************************
492 * auxSetVolume [MMSYSTEM.353]
494 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
496 return auxSetVolume(uDeviceID, dwVolume);
499 /**************************************************************************
500 * auxOutMessage [MMSYSTEM.354]
502 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
504 TRACE("(%04X, %04X, %08X, %08X)\n", uDeviceID, uMessage, dw1, dw2);
506 switch (uMessage) {
507 case AUXDM_GETNUMDEVS:
508 case AUXDM_SETVOLUME:
509 /* no argument conversion needed */
510 break;
511 case AUXDM_GETVOLUME:
512 return auxGetVolume(uDeviceID, MapSL(dw1));
513 case AUXDM_GETDEVCAPS:
514 return auxGetDevCaps16(uDeviceID, MapSL(dw1), dw2);
515 default:
516 TRACE("(%04x, %04x, %08x, %08x): unhandled message\n",
517 uDeviceID, uMessage, dw1, dw2);
518 break;
520 return auxOutMessage(uDeviceID, uMessage, dw1, dw2);
523 /* ###################################################
524 * # MIDI #
525 * ###################################################
528 /**************************************************************************
529 * midiOutGetNumDevs [MMSYSTEM.201]
531 UINT16 WINAPI midiOutGetNumDevs16(void)
533 return midiOutGetNumDevs();
536 /**************************************************************************
537 * midiOutGetDevCaps [MMSYSTEM.202]
539 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID, LPMIDIOUTCAPS16 lpCaps,
540 UINT16 uSize)
542 MIDIOUTCAPSA mocA;
543 UINT ret;
545 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
547 ret = midiOutGetDevCapsA(uDeviceID, &mocA, sizeof(mocA));
548 if (ret == MMSYSERR_NOERROR) {
549 MIDIOUTCAPS16 moc16;
550 moc16.wMid = mocA.wMid;
551 moc16.wPid = mocA.wPid;
552 moc16.vDriverVersion = mocA.vDriverVersion;
553 strcpy(moc16.szPname, mocA.szPname);
554 moc16.wTechnology = mocA.wTechnology;
555 moc16.wVoices = mocA.wVoices;
556 moc16.wNotes = mocA.wNotes;
557 moc16.wChannelMask = mocA.wChannelMask;
558 moc16.dwSupport = mocA.dwSupport;
559 memcpy(lpCaps, &moc16, min(uSize, sizeof(moc16)));
561 return ret;
564 /**************************************************************************
565 * midiOutGetErrorText [MMSYSTEM.203]
566 * midiInGetErrorText [MMSYSTEM.303]
568 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
570 return midiOutGetErrorTextA(uError, lpText, uSize);
573 /**************************************************************************
574 * midiOutOpen [MMSYSTEM.204]
576 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
577 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
579 HMIDIOUT hmo;
580 UINT ret;
582 ret = MIDI_OutOpen(&hmo, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
584 if (lphMidiOut != NULL) *lphMidiOut = HMIDIOUT_16(hmo);
585 return ret;
588 /**************************************************************************
589 * midiOutClose [MMSYSTEM.205]
591 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
593 return midiOutClose(HMIDIOUT_32(hMidiOut));
596 /**************************************************************************
597 * midiOutPrepareHeader [MMSYSTEM.206]
599 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut, /* [in] */
600 SEGPTR lpsegMidiOutHdr, /* [???] */
601 UINT16 uSize) /* [in] */
603 LPWINE_MLD wmld;
605 TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
607 if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
608 return MMSYSERR_INVALHANDLE;
610 return MMDRV_Message(wmld, MODM_PREPARE, lpsegMidiOutHdr, uSize, FALSE);
613 /**************************************************************************
614 * midiOutUnprepareHeader [MMSYSTEM.207]
616 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut, /* [in] */
617 SEGPTR lpsegMidiOutHdr, /* [???] */
618 UINT16 uSize) /* [in] */
620 LPWINE_MLD wmld;
621 LPMIDIHDR16 lpMidiOutHdr = MapSL(lpsegMidiOutHdr);
623 TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
625 if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
626 return MMSYSERR_NOERROR;
629 if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
630 return MMSYSERR_INVALHANDLE;
632 return MMDRV_Message(wmld, MODM_UNPREPARE, lpsegMidiOutHdr, uSize, FALSE);
635 /**************************************************************************
636 * midiOutShortMsg [MMSYSTEM.208]
638 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
640 return midiOutShortMsg(HMIDIOUT_32(hMidiOut), dwMsg);
643 /**************************************************************************
644 * midiOutLongMsg [MMSYSTEM.209]
646 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut, /* [in] */
647 LPMIDIHDR16 lpsegMidiOutHdr, /* [???] NOTE: SEGPTR */
648 UINT16 uSize) /* [in] */
650 LPWINE_MLD wmld;
652 TRACE("(%04X, %p, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
654 if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
655 return MMSYSERR_INVALHANDLE;
657 return MMDRV_Message(wmld, MODM_LONGDATA, (DWORD_PTR)lpsegMidiOutHdr, uSize, FALSE);
660 /**************************************************************************
661 * midiOutReset [MMSYSTEM.210]
663 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
665 return midiOutReset(HMIDIOUT_32(hMidiOut));
668 /**************************************************************************
669 * midiOutGetVolume [MMSYSTEM.211]
671 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
673 return midiOutGetVolume(HMIDIOUT_32(uDeviceID), lpdwVolume);
676 /**************************************************************************
677 * midiOutSetVolume [MMSYSTEM.212]
679 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
681 return midiOutSetVolume(HMIDIOUT_32(uDeviceID), dwVolume);
684 /**************************************************************************
685 * midiOutCachePatches [MMSYSTEM.213]
687 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
688 WORD* lpwPatchArray, UINT16 uFlags)
690 return midiOutCachePatches(HMIDIOUT_32(hMidiOut), uBank, lpwPatchArray,
691 uFlags);
694 /**************************************************************************
695 * midiOutCacheDrumPatches [MMSYSTEM.214]
697 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
698 WORD* lpwKeyArray, UINT16 uFlags)
700 return midiOutCacheDrumPatches(HMIDIOUT_32(hMidiOut), uPatch, lpwKeyArray, uFlags);
703 /**************************************************************************
704 * midiOutGetID [MMSYSTEM.215]
706 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
708 UINT devid;
709 UINT16 ret;
711 ret = midiOutGetID(HMIDIOUT_32(hMidiOut), &devid);
712 if (ret != MMSYSERR_NOERROR) return ret;
713 *lpuDeviceID = devid;
714 return ret;
717 /**************************************************************************
718 * midiOutMessage [MMSYSTEM.216]
720 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
721 DWORD dwParam1, DWORD dwParam2)
723 LPWINE_MLD wmld;
725 TRACE("(%04X, %04X, %08X, %08X)\n", hMidiOut, uMessage, dwParam1, dwParam2);
727 if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
728 return MMSYSERR_INVALHANDLE;
730 switch (uMessage) {
731 case MODM_OPEN:
732 case MODM_CLOSE:
733 FIXME("can't handle OPEN or CLOSE message!\n");
734 return MMSYSERR_NOTSUPPORTED;
736 case MODM_GETVOLUME:
737 return midiOutGetVolume16(hMidiOut, MapSL(dwParam1));
738 case MODM_LONGDATA:
739 return midiOutLongMsg16(hMidiOut, MapSL(dwParam1), dwParam2);
740 case MODM_PREPARE:
741 /* lpMidiOutHdr is still a segmented pointer for this function */
742 return midiOutPrepareHeader16(hMidiOut, dwParam1, dwParam2);
743 case MODM_UNPREPARE:
744 return midiOutUnprepareHeader16(hMidiOut, dwParam1, dwParam2);
746 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
749 /**************************************************************************
750 * midiInGetNumDevs [MMSYSTEM.301]
752 UINT16 WINAPI midiInGetNumDevs16(void)
754 return midiInGetNumDevs();
757 /**************************************************************************
758 * midiInGetDevCaps [MMSYSTEM.302]
760 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID, LPMIDIINCAPS16 lpCaps,
761 UINT16 uSize)
763 MIDIINCAPSA micA;
764 UINT ret;
766 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
768 ret = midiInGetDevCapsA(uDeviceID, &micA, uSize);
769 if (ret == MMSYSERR_NOERROR) {
770 MIDIINCAPS16 mic16;
771 mic16.wMid = micA.wMid;
772 mic16.wPid = micA.wPid;
773 mic16.vDriverVersion = micA.vDriverVersion;
774 strcpy(mic16.szPname, micA.szPname);
775 mic16.dwSupport = micA.dwSupport;
776 memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
778 return ret;
781 /**************************************************************************
782 * midiInOpen [MMSYSTEM.304]
784 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
785 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
787 HMIDIIN xhmid;
788 UINT ret;
790 ret = MIDI_InOpen(&xhmid, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
792 if (lphMidiIn) *lphMidiIn = HMIDIIN_16(xhmid);
793 return ret;
796 /**************************************************************************
797 * midiInClose [MMSYSTEM.305]
799 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
801 return midiInClose(HMIDIIN_32(hMidiIn));
804 /**************************************************************************
805 * midiInPrepareHeader [MMSYSTEM.306]
807 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn, /* [in] */
808 SEGPTR lpsegMidiInHdr, /* [???] */
809 UINT16 uSize) /* [in] */
811 LPWINE_MLD wmld;
813 TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
815 if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
816 return MMSYSERR_INVALHANDLE;
818 return MMDRV_Message(wmld, MIDM_PREPARE, lpsegMidiInHdr, uSize, FALSE);
821 /**************************************************************************
822 * midiInUnprepareHeader [MMSYSTEM.307]
824 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn, /* [in] */
825 SEGPTR lpsegMidiInHdr, /* [???] */
826 UINT16 uSize) /* [in] */
828 LPWINE_MLD wmld;
829 LPMIDIHDR16 lpMidiInHdr = MapSL(lpsegMidiInHdr);
831 TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
833 if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
834 return MMSYSERR_NOERROR;
837 if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
838 return MMSYSERR_INVALHANDLE;
840 return MMDRV_Message(wmld, MIDM_UNPREPARE, lpsegMidiInHdr, uSize, FALSE);
843 /**************************************************************************
844 * midiInAddBuffer [MMSYSTEM.308]
846 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn, /* [in] */
847 MIDIHDR16* lpsegMidiInHdr, /* [???] NOTE: SEGPTR */
848 UINT16 uSize) /* [in] */
850 LPWINE_MLD wmld;
852 TRACE("(%04X, %p, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
854 if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
855 return MMSYSERR_INVALHANDLE;
857 return MMDRV_Message(wmld, MIDM_ADDBUFFER, (DWORD_PTR)lpsegMidiInHdr, uSize, FALSE);
860 /**************************************************************************
861 * midiInStart [MMSYSTEM.309]
863 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
865 return midiInStart(HMIDIIN_32(hMidiIn));
868 /**************************************************************************
869 * midiInStop [MMSYSTEM.310]
871 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
873 return midiInStop(HMIDIIN_32(hMidiIn));
876 /**************************************************************************
877 * midiInReset [MMSYSTEM.311]
879 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
881 return midiInReset(HMIDIIN_32(hMidiIn));
884 /**************************************************************************
885 * midiInGetID [MMSYSTEM.312]
887 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
889 UINT devid;
890 UINT16 ret;
892 ret = midiInGetID(HMIDIIN_32(hMidiIn), &devid);
893 if (ret != MMSYSERR_NOERROR) return ret;
894 *lpuDeviceID = devid;
895 return ret;
898 /**************************************************************************
899 * midiInMessage [MMSYSTEM.313]
901 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
902 DWORD dwParam1, DWORD dwParam2)
904 LPWINE_MLD wmld;
906 TRACE("(%04X, %04X, %08X, %08X)\n", hMidiIn, uMessage, dwParam1, dwParam2);
908 switch (uMessage) {
909 case MIDM_OPEN:
910 case MIDM_CLOSE:
911 FIXME("can't handle OPEN or CLOSE message!\n");
912 return MMSYSERR_NOTSUPPORTED;
914 case MIDM_GETDEVCAPS:
915 return midiInGetDevCaps16(hMidiIn, MapSL(dwParam1), dwParam2);
916 case MIDM_PREPARE:
917 return midiInPrepareHeader16(hMidiIn, dwParam1, dwParam2);
918 case MIDM_UNPREPARE:
919 return midiInUnprepareHeader16(hMidiIn, dwParam1, dwParam2);
920 case MIDM_ADDBUFFER:
921 return midiInAddBuffer16(hMidiIn, MapSL(dwParam1), dwParam2);
924 if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
925 return MMSYSERR_INVALHANDLE;
927 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
930 /**************************************************************************
931 * midiStreamClose [MMSYSTEM.252]
933 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hMidiStrm)
935 return midiStreamClose(HMIDISTRM_32(hMidiStrm));
938 /**************************************************************************
939 * midiStreamOpen [MMSYSTEM.251]
941 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
942 DWORD cMidi, DWORD dwCallback,
943 DWORD dwInstance, DWORD fdwOpen)
945 HMIDISTRM hMidiStrm32;
946 MMRESULT ret;
947 UINT devid32;
949 if (!phMidiStrm || !devid)
950 return MMSYSERR_INVALPARAM;
951 devid32 = *devid;
952 ret = MIDI_StreamOpen(&hMidiStrm32, &devid32, cMidi, dwCallback,
953 dwInstance, fdwOpen, FALSE);
954 *phMidiStrm = HMIDISTRM_16(hMidiStrm32);
955 *devid = devid32;
956 return ret;
959 /**************************************************************************
960 * midiStreamOut [MMSYSTEM.254]
962 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hMidiStrm, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
964 return midiStreamOut(HMIDISTRM_32(hMidiStrm), (LPMIDIHDR)lpMidiHdr,
965 cbMidiHdr);
968 /**************************************************************************
969 * midiStreamPause [MMSYSTEM.255]
971 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hMidiStrm)
973 return midiStreamPause(HMIDISTRM_32(hMidiStrm));
976 /**************************************************************************
977 * midiStreamPosition [MMSYSTEM.253]
979 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hMidiStrm, LPMMTIME16 lpmmt16, UINT16 cbmmt)
981 MMTIME mmt32;
982 MMRESULT ret;
984 if (!lpmmt16)
985 return MMSYSERR_INVALPARAM;
986 MMSYSTEM_MMTIME16to32(&mmt32, lpmmt16);
987 ret = midiStreamPosition(HMIDISTRM_32(hMidiStrm), &mmt32, sizeof(MMTIME));
988 MMSYSTEM_MMTIME32to16(lpmmt16, &mmt32);
989 return ret;
992 /**************************************************************************
993 * midiStreamProperty [MMSYSTEM.250]
995 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hMidiStrm, LPBYTE lpPropData, DWORD dwProperty)
997 return midiStreamProperty(HMIDISTRM_32(hMidiStrm), lpPropData, dwProperty);
1000 /**************************************************************************
1001 * midiStreamRestart [MMSYSTEM.256]
1003 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hMidiStrm)
1005 return midiStreamRestart(HMIDISTRM_32(hMidiStrm));
1008 /**************************************************************************
1009 * midiStreamStop [MMSYSTEM.257]
1011 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hMidiStrm)
1013 return midiStreamStop(HMIDISTRM_32(hMidiStrm));
1016 /* ###################################################
1017 * # WAVE #
1018 * ###################################################
1021 /**************************************************************************
1022 * waveOutGetNumDevs [MMSYSTEM.401]
1024 UINT16 WINAPI waveOutGetNumDevs16(void)
1026 return waveOutGetNumDevs();
1029 /**************************************************************************
1030 * waveOutGetDevCaps [MMSYSTEM.402]
1032 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID,
1033 LPWAVEOUTCAPS16 lpCaps, UINT16 uSize)
1035 WAVEOUTCAPSA wocA;
1036 UINT ret;
1037 TRACE("(%u %p %u)!\n", uDeviceID, lpCaps, uSize);
1039 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1041 ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA));
1042 if (ret == MMSYSERR_NOERROR) {
1043 WAVEOUTCAPS16 woc16;
1044 woc16.wMid = wocA.wMid;
1045 woc16.wPid = wocA.wPid;
1046 woc16.vDriverVersion = wocA.vDriverVersion;
1047 strcpy(woc16.szPname, wocA.szPname);
1048 woc16.dwFormats = wocA.dwFormats;
1049 woc16.wChannels = wocA.wChannels;
1050 woc16.dwSupport = wocA.dwSupport;
1051 memcpy(lpCaps, &woc16, min(uSize, sizeof(woc16)));
1053 return ret;
1056 /**************************************************************************
1057 * waveOutGetErrorText [MMSYSTEM.403]
1058 * waveInGetErrorText [MMSYSTEM.503]
1060 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1062 return waveOutGetErrorTextA(uError, lpText, uSize);
1065 /**************************************************************************
1066 * waveOutOpen [MMSYSTEM.404]
1068 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
1069 LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1070 DWORD dwInstance, DWORD dwFlags)
1072 HANDLE hWaveOut;
1073 UINT ret;
1075 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1076 * call the 32 bit version
1077 * however, we need to promote correctly the wave mapper id
1078 * (0xFFFFFFFF and not 0x0000FFFF)
1080 ret = WAVE_Open(&hWaveOut, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1081 MMDRV_WAVEOUT, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1083 if (lphWaveOut != NULL) *lphWaveOut = HWAVEOUT_16(hWaveOut);
1084 return ret;
1087 /**************************************************************************
1088 * waveOutClose [MMSYSTEM.405]
1090 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
1092 DWORD level;
1093 UINT16 ret;
1095 ReleaseThunkLock(&level);
1096 ret = waveOutClose(HWAVEOUT_32(hWaveOut));
1097 RestoreThunkLock(level);
1098 return ret;
1101 /**************************************************************************
1102 * waveOutPrepareHeader [MMSYSTEM.406]
1104 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut, /* [in] */
1105 SEGPTR lpsegWaveOutHdr, /* [???] */
1106 UINT16 uSize) /* [in] */
1108 LPWINE_MLD wmld;
1109 LPWAVEHDR lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1110 UINT16 result;
1112 TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1114 if (lpWaveOutHdr == NULL) return MMSYSERR_INVALPARAM;
1116 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1117 return MMSYSERR_INVALHANDLE;
1119 if ((result = MMDRV_Message(wmld, WODM_PREPARE, lpsegWaveOutHdr,
1120 uSize, FALSE)) != MMSYSERR_NOTSUPPORTED)
1121 return result;
1123 if (lpWaveOutHdr->dwFlags & WHDR_INQUEUE)
1124 return WAVERR_STILLPLAYING;
1126 lpWaveOutHdr->dwFlags |= WHDR_PREPARED;
1127 lpWaveOutHdr->dwFlags &= ~WHDR_DONE;
1129 return MMSYSERR_NOERROR;
1132 /**************************************************************************
1133 * waveOutUnprepareHeader [MMSYSTEM.407]
1135 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut, /* [in] */
1136 SEGPTR lpsegWaveOutHdr, /* [???] */
1137 UINT16 uSize) /* [in] */
1139 LPWINE_MLD wmld;
1140 LPWAVEHDR lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1142 TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1144 if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
1145 return MMSYSERR_NOERROR;
1148 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1149 return MMSYSERR_INVALHANDLE;
1151 return MMDRV_Message(wmld, WODM_UNPREPARE, lpsegWaveOutHdr, uSize, FALSE);
1154 /**************************************************************************
1155 * waveOutWrite [MMSYSTEM.408]
1157 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut, /* [in] */
1158 LPWAVEHDR lpsegWaveOutHdr, /* [???] NOTE: SEGPTR */
1159 UINT16 uSize) /* [in] */
1161 LPWINE_MLD wmld;
1163 TRACE("(%04X, %p, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1165 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1166 return MMSYSERR_INVALHANDLE;
1168 return MMDRV_Message(wmld, WODM_WRITE, (DWORD_PTR)lpsegWaveOutHdr, uSize, FALSE);
1171 /**************************************************************************
1172 * waveOutBreakLoop [MMSYSTEM.419]
1174 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut16)
1176 DWORD level;
1177 UINT16 ret;
1179 ReleaseThunkLock(&level);
1180 ret = waveOutBreakLoop(HWAVEOUT_32(hWaveOut16));
1181 RestoreThunkLock(level);
1182 return ret;
1185 /**************************************************************************
1186 * waveOutPause [MMSYSTEM.409]
1188 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut16)
1190 DWORD level;
1191 UINT16 ret;
1193 ReleaseThunkLock(&level);
1194 ret = waveOutPause(HWAVEOUT_32(hWaveOut16));
1195 RestoreThunkLock(level);
1196 return ret;
1199 /**************************************************************************
1200 * waveOutReset [MMSYSTEM.411]
1202 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut16)
1204 DWORD level;
1205 UINT16 ret;
1207 ReleaseThunkLock(&level);
1208 ret = waveOutReset(HWAVEOUT_32(hWaveOut16));
1209 RestoreThunkLock(level);
1210 return ret;
1213 /**************************************************************************
1214 * waveOutRestart [MMSYSTEM.410]
1216 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut16)
1218 DWORD level;
1219 UINT16 ret;
1221 ReleaseThunkLock(&level);
1222 ret = waveOutRestart(HWAVEOUT_32(hWaveOut16));
1223 RestoreThunkLock(level);
1224 return ret;
1227 /**************************************************************************
1228 * waveOutGetPosition [MMSYSTEM.412]
1230 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
1231 UINT16 uSize)
1233 UINT ret;
1234 MMTIME mmt;
1236 mmt.wType = lpTime->wType;
1237 ret = waveOutGetPosition(HWAVEOUT_32(hWaveOut), &mmt, sizeof(mmt));
1238 MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1239 return ret;
1242 /**************************************************************************
1243 * waveOutGetPitch [MMSYSTEM.413]
1245 UINT16 WINAPI waveOutGetPitch16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1247 return waveOutGetPitch(HWAVEOUT_32(hWaveOut16), lpdw);
1250 /**************************************************************************
1251 * waveOutSetPitch [MMSYSTEM.414]
1253 UINT16 WINAPI waveOutSetPitch16(HWAVEOUT16 hWaveOut16, DWORD dw)
1255 return waveOutSetPitch(HWAVEOUT_32(hWaveOut16), dw);
1258 /**************************************************************************
1259 * waveOutGetPlaybackRate [MMSYSTEM.417]
1261 UINT16 WINAPI waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1263 return waveOutGetPlaybackRate(HWAVEOUT_32(hWaveOut16), lpdw);
1266 /**************************************************************************
1267 * waveOutSetPlaybackRate [MMSYSTEM.418]
1269 UINT16 WINAPI waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16, DWORD dw)
1271 return waveOutSetPlaybackRate(HWAVEOUT_32(hWaveOut16), dw);
1274 /**************************************************************************
1275 * waveOutGetVolume [MMSYSTEM.415]
1277 UINT16 WINAPI waveOutGetVolume16(UINT16 devid, LPDWORD lpdw)
1279 return waveOutGetVolume(HWAVEOUT_32(devid), lpdw);
1282 /**************************************************************************
1283 * waveOutSetVolume [MMSYSTEM.416]
1285 UINT16 WINAPI waveOutSetVolume16(UINT16 devid, DWORD dw)
1287 return waveOutSetVolume(HWAVEOUT_32(devid), dw);
1290 /**************************************************************************
1291 * waveOutGetID [MMSYSTEM.420]
1293 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
1295 UINT devid;
1296 UINT16 ret;
1298 ret = waveOutGetID(HWAVEOUT_32(hWaveOut), &devid);
1299 if (ret != MMSYSERR_NOERROR) return ret;
1300 *lpuDeviceID = devid;
1301 return ret;
1304 /**************************************************************************
1305 * waveOutMessage [MMSYSTEM.421]
1307 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
1308 DWORD dwParam1, DWORD dwParam2)
1310 LPWINE_MLD wmld;
1312 TRACE("(%04x, %u, %d, %d)\n", hWaveOut, uMessage, dwParam1, dwParam2);
1314 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL) {
1315 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, TRUE)) != NULL) {
1316 if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1317 dwParam1 = (DWORD)MapSL(dwParam1);
1318 return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1320 return MMSYSERR_INVALHANDLE;
1323 /* from M$ KB */
1324 if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1325 return MMSYSERR_INVALPARAM;
1327 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1330 /**************************************************************************
1331 * waveInGetNumDevs [MMSYSTEM.501]
1333 UINT16 WINAPI waveInGetNumDevs16(void)
1335 return waveInGetNumDevs();
1338 /**************************************************************************
1339 * waveInGetDevCaps [MMSYSTEM.502]
1341 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps,
1342 UINT16 uSize)
1344 WAVEINCAPSA wicA;
1345 UINT ret;
1347 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1349 ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA));
1350 if (ret == MMSYSERR_NOERROR) {
1351 WAVEINCAPS16 wic16;
1352 wic16.wMid = wicA.wMid;
1353 wic16.wPid = wicA.wPid;
1354 wic16.vDriverVersion = wicA.vDriverVersion;
1355 strcpy(wic16.szPname, wicA.szPname);
1356 wic16.dwFormats = wicA.dwFormats;
1357 wic16.wChannels = wicA.wChannels;
1358 memcpy(lpCaps, &wic16, min(uSize, sizeof(wic16)));
1360 return ret;
1363 /**************************************************************************
1364 * waveInOpen [MMSYSTEM.504]
1366 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
1367 LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1368 DWORD dwInstance, DWORD dwFlags)
1370 HANDLE hWaveIn;
1371 UINT ret;
1373 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1374 * call the 32 bit version
1375 * however, we need to promote correctly the wave mapper id
1376 * (0xFFFFFFFF and not 0x0000FFFF)
1378 ret = WAVE_Open(&hWaveIn, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1379 MMDRV_WAVEIN, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1381 if (lphWaveIn != NULL) *lphWaveIn = HWAVEIN_16(hWaveIn);
1382 return ret;
1385 /**************************************************************************
1386 * waveInClose [MMSYSTEM.505]
1388 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
1390 DWORD level;
1391 UINT16 ret;
1393 ReleaseThunkLock(&level);
1394 ret = waveInClose(HWAVEIN_32(hWaveIn));
1395 RestoreThunkLock(level);
1396 return ret;
1399 /**************************************************************************
1400 * waveInPrepareHeader [MMSYSTEM.506]
1402 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn, /* [in] */
1403 SEGPTR lpsegWaveInHdr, /* [???] */
1404 UINT16 uSize) /* [in] */
1406 LPWINE_MLD wmld;
1407 LPWAVEHDR lpWaveInHdr = MapSL(lpsegWaveInHdr);
1408 UINT16 ret;
1410 TRACE("(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
1412 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
1413 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1414 return MMSYSERR_INVALHANDLE;
1416 lpWaveInHdr->dwBytesRecorded = 0;
1418 ret = MMDRV_Message(wmld, WIDM_PREPARE, lpsegWaveInHdr, uSize, FALSE);
1419 return ret;
1422 /**************************************************************************
1423 * waveInUnprepareHeader [MMSYSTEM.507]
1425 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn, /* [in] */
1426 SEGPTR lpsegWaveInHdr, /* [???] */
1427 UINT16 uSize) /* [in] */
1429 LPWINE_MLD wmld;
1430 LPWAVEHDR lpWaveInHdr = MapSL(lpsegWaveInHdr);
1432 TRACE("(%04X, %08x, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1434 if (lpWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1436 if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED)) {
1437 return MMSYSERR_NOERROR;
1440 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1441 return MMSYSERR_INVALHANDLE;
1443 return MMDRV_Message(wmld, WIDM_UNPREPARE, lpsegWaveInHdr, uSize, FALSE);
1446 /**************************************************************************
1447 * waveInAddBuffer [MMSYSTEM.508]
1449 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn, /* [in] */
1450 WAVEHDR* lpsegWaveInHdr, /* [???] NOTE: SEGPTR */
1451 UINT16 uSize) /* [in] */
1453 LPWINE_MLD wmld;
1455 TRACE("(%04X, %p, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1457 if (lpsegWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1458 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1459 return MMSYSERR_INVALHANDLE;
1461 return MMDRV_Message(wmld, WIDM_ADDBUFFER, (DWORD_PTR)lpsegWaveInHdr, uSize, FALSE);
1464 /**************************************************************************
1465 * waveInReset [MMSYSTEM.511]
1467 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn16)
1469 DWORD level;
1470 UINT16 ret;
1472 ReleaseThunkLock(&level);
1473 ret = waveInReset(HWAVEIN_32(hWaveIn16));
1474 RestoreThunkLock(level);
1475 return ret;
1478 /**************************************************************************
1479 * waveInStart [MMSYSTEM.509]
1481 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn16)
1483 DWORD level;
1484 UINT16 ret;
1486 ReleaseThunkLock(&level);
1487 ret = waveInStart(HWAVEIN_32(hWaveIn16));
1488 RestoreThunkLock(level);
1489 return ret;
1492 /**************************************************************************
1493 * waveInStop [MMSYSTEM.510]
1495 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn16)
1497 DWORD level;
1498 UINT16 ret;
1500 ReleaseThunkLock(&level);
1501 ret = waveInStop(HWAVEIN_32(hWaveIn16));
1502 RestoreThunkLock(level);
1503 return ret;
1506 /**************************************************************************
1507 * waveInGetPosition [MMSYSTEM.512]
1509 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
1510 UINT16 uSize)
1512 UINT ret;
1513 MMTIME mmt;
1515 mmt.wType = lpTime->wType;
1516 ret = waveInGetPosition(HWAVEIN_32(hWaveIn), &mmt, sizeof(mmt));
1517 MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1518 return ret;
1521 /**************************************************************************
1522 * waveInGetID [MMSYSTEM.513]
1524 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
1526 UINT devid;
1527 UINT16 ret;
1529 ret = waveInGetID(HWAVEIN_32(hWaveIn), &devid);
1530 if (ret != MMSYSERR_NOERROR) return ret;
1531 *lpuDeviceID = devid;
1532 return ret;
1535 /**************************************************************************
1536 * waveInMessage [MMSYSTEM.514]
1538 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
1539 DWORD dwParam1, DWORD dwParam2)
1541 LPWINE_MLD wmld;
1543 TRACE("(%04x, %u, %d, %d)\n", hWaveIn, uMessage, dwParam1, dwParam2);
1545 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL) {
1546 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, TRUE)) != NULL) {
1547 if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1548 dwParam1 = (DWORD)MapSL(dwParam1);
1549 return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1551 return MMSYSERR_INVALHANDLE;
1554 /* from M$ KB */
1555 if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1556 return MMSYSERR_INVALPARAM;
1558 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1561 /* ###################################################
1562 * # TASK #
1563 * ###################################################
1566 /*#define USE_MM_TSK_WINE*/
1568 /**************************************************************************
1569 * mmTaskCreate [MMSYSTEM.900]
1571 * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
1572 * called upon creation with dwPmt as parameter.
1574 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
1576 HINSTANCE16 ret;
1577 HINSTANCE16 handle;
1578 char cmdline[16];
1579 DWORD showCmd = 0x40002;
1580 LOADPARAMS16 lp;
1582 TRACE("(%08x, %p, %08x);\n", spProc, lphMmTask, dwPmt);
1583 /* This to work requires NE modules to be started with a binary command line
1584 * which is not currently the case. A patch exists but has never been committed.
1585 * A workaround would be to integrate code for mmtask.tsk into Wine, but
1586 * this requires tremendous work (starting with patching tools/build to
1587 * create NE executables (and not only DLLs) for builtins modules.
1588 * EP 99/04/25
1590 FIXME("This is currently broken. It will fail\n");
1592 cmdline[0] = 0x0d;
1593 *(LPDWORD)(cmdline + 1) = (DWORD)spProc;
1594 *(LPDWORD)(cmdline + 5) = dwPmt;
1595 *(LPDWORD)(cmdline + 9) = 0;
1597 lp.hEnvironment = 0;
1598 lp.cmdLine = MapLS(cmdline);
1599 lp.showCmd = MapLS(&showCmd);
1600 lp.reserved = 0;
1602 #ifndef USE_MM_TSK_WINE
1603 handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
1604 #else
1605 handle = LoadModule16("mmtask.tsk", &lp);
1606 #endif
1607 if (handle < 32) {
1608 ret = (handle) ? 1 : 2;
1609 handle = 0;
1610 } else {
1611 ret = 0;
1613 if (lphMmTask)
1614 *lphMmTask = handle;
1616 UnMapLS( lp.cmdLine );
1617 UnMapLS( lp.showCmd );
1618 TRACE("=> 0x%04x/%d\n", handle, ret);
1619 return ret;
1622 #ifdef USE_MM_TSK_WINE
1623 /* C equivalent to mmtask.tsk binary content */
1624 void mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
1626 int len = cmdLine[0x80];
1628 if (len / 2 == 6) {
1629 void (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
1630 DWORD dwPmt = *((DWORD*)(cmdLine + 5));
1632 #if 0
1633 InitTask16(); /* FIXME: pmts / from context ? */
1634 InitApp(di);
1635 #endif
1636 if (SetMessageQueue16(0x40)) {
1637 WaitEvent16(0);
1638 if (HIWORD(fpProc)) {
1639 OldYield16();
1640 /* EPP StackEnter16(); */
1641 (fpProc)(dwPmt);
1645 OldYield16();
1646 OldYield16();
1647 OldYield16();
1648 ExitProcess(0);
1650 #endif
1652 /**************************************************************************
1653 * mmTaskBlock [MMSYSTEM.902]
1655 void WINAPI mmTaskBlock16(HINSTANCE16 hInst)
1657 MSG msg;
1659 do {
1660 GetMessageA(&msg, 0, 0, 0);
1661 if (msg.hwnd) {
1662 TranslateMessage(&msg);
1663 DispatchMessageA(&msg);
1665 } while (msg.message < 0x3A0);
1668 /**************************************************************************
1669 * mmTaskSignal [MMSYSTEM.903]
1671 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
1673 TRACE("(%04x);\n", ht);
1674 return PostThreadMessageW( HTASK_32(ht), WM_USER, 0, 0 );
1677 /**************************************************************************
1678 * mmGetCurrentTask [MMSYSTEM.904]
1680 HTASK16 WINAPI mmGetCurrentTask16(void)
1682 return GetCurrentTask();
1685 /**************************************************************************
1686 * mmTaskYield [MMSYSTEM.905]
1688 void WINAPI mmTaskYield16(void)
1690 MSG msg;
1692 if (PeekMessageA(&msg, 0, 0, 0, 0)) {
1693 WOWYield16();
1697 extern DWORD WINAPI GetProcessFlags(DWORD);
1699 /******************************************************************
1700 * WINMM_GetmmThread
1704 static WINE_MMTHREAD* WINMM_GetmmThread(HANDLE16 h)
1706 return MapSL(MAKESEGPTR(h, 0));
1709 DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID);
1711 /**************************************************************************
1712 * mmThreadCreate [MMSYSTEM.1120]
1714 * undocumented
1715 * Creates a MM thread, calling fpThreadAddr(dwPmt).
1716 * dwFlags:
1717 * bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
1718 * bit.1 set means to open a VxD for this thread (unsupported)
1720 LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD dwPmt, DWORD dwFlags)
1722 HANDLE16 hndl;
1723 LRESULT ret;
1725 TRACE("(%p, %p, %08x, %08x)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
1727 hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
1729 if (hndl == 0) {
1730 ret = 2;
1731 } else {
1732 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1734 #if 0
1735 /* force mmtask routines even if mmthread is required */
1736 /* this will work only if the patch about binary cmd line and NE tasks
1737 * is committed
1739 dwFlags |= 1;
1740 #endif
1742 lpMMThd->dwSignature = WINE_MMTHREAD_CREATED;
1743 lpMMThd->dwCounter = 0;
1744 lpMMThd->hThread = 0;
1745 lpMMThd->dwThreadID = 0;
1746 lpMMThd->fpThread = (DWORD)fpThreadAddr;
1747 lpMMThd->dwThreadPmt = dwPmt;
1748 lpMMThd->dwSignalCount = 0;
1749 lpMMThd->hEvent = 0;
1750 lpMMThd->hVxD = 0;
1751 lpMMThd->dwStatus = 0;
1752 lpMMThd->dwFlags = dwFlags;
1753 lpMMThd->hTask = 0;
1755 if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
1756 lpMMThd->hEvent = CreateEventW(NULL, FALSE, TRUE, NULL);
1758 TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
1759 if (lpMMThd->dwFlags & 2) {
1760 /* as long as we don't support MM VxD in wine, we don't need
1761 * to care about this flag
1763 /* FIXME("Don't know how to properly open VxD handles\n"); */
1764 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
1767 lpMMThd->hThread = CreateThread(0, 0, WINE_mmThreadEntryPoint,
1768 (LPVOID)(DWORD_PTR)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
1769 if (lpMMThd->hThread == 0) {
1770 WARN("Couldn't create thread\n");
1771 /* clean-up(VxDhandle...); devicedirectio... */
1772 if (lpMMThd->hEvent != 0)
1773 CloseHandle(lpMMThd->hEvent);
1774 ret = 2;
1775 } else {
1776 SetThreadPriority(lpMMThd->hThread, THREAD_PRIORITY_TIME_CRITICAL);
1777 TRACE("Got a nice thread hndl=%p id=0x%08x\n", lpMMThd->hThread, lpMMThd->dwThreadID);
1778 ret = 0;
1780 } else {
1781 /* get WINE_mmThreadEntryPoint()
1782 * 2047 is its ordinal in mmsystem.spec
1784 FARPROC16 fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
1786 TRACE("farproc seg=0x%p lin=%p\n", fp, MapSL((SEGPTR)fp));
1788 ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
1791 if (ret == 0) {
1792 if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
1793 WARN("Couldn't resume thread\n");
1795 while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
1796 UserYield16();
1801 if (ret != 0) {
1802 GlobalFree16(hndl);
1803 hndl = 0;
1806 if (lpHndl)
1807 *lpHndl = hndl;
1809 TRACE("ok => %ld\n", ret);
1810 return ret;
1813 /**************************************************************************
1814 * mmThreadSignal [MMSYSTEM.1121]
1816 void WINAPI mmThreadSignal16(HANDLE16 hndl)
1818 TRACE("(%04x)!\n", hndl);
1820 if (hndl) {
1821 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1823 lpMMThd->dwCounter++;
1824 if (lpMMThd->hThread != 0) {
1825 InterlockedIncrement(&lpMMThd->dwSignalCount);
1826 SetEvent(lpMMThd->hEvent);
1827 } else {
1828 mmTaskSignal16(lpMMThd->hTask);
1830 lpMMThd->dwCounter--;
1834 static void MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
1836 MSG msg;
1837 DWORD ret;
1839 if (lpMMThd->dwThreadID != GetCurrentThreadId())
1840 ERR("Not called by thread itself\n");
1842 for (;;) {
1843 ResetEvent(lpMMThd->hEvent);
1844 if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
1845 break;
1846 InterlockedIncrement(&lpMMThd->dwSignalCount);
1848 TRACE("S1\n");
1850 ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
1851 switch (ret) {
1852 case WAIT_OBJECT_0: /* Event */
1853 TRACE("S2.1\n");
1854 break;
1855 case WAIT_OBJECT_0 + 1: /* Msg */
1856 TRACE("S2.2\n");
1857 if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
1858 TranslateMessage(&msg);
1859 DispatchMessageA(&msg);
1861 break;
1862 default:
1863 WARN("S2.x unsupported ret val 0x%08x\n", ret);
1865 TRACE("S3\n");
1869 /**************************************************************************
1870 * mmThreadBlock [MMSYSTEM.1122]
1872 void WINAPI mmThreadBlock16(HANDLE16 hndl)
1874 TRACE("(%04x)!\n", hndl);
1876 if (hndl) {
1877 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1879 if (lpMMThd->hThread != 0) {
1880 DWORD lc;
1882 ReleaseThunkLock(&lc);
1883 MMSYSTEM_ThreadBlock(lpMMThd);
1884 RestoreThunkLock(lc);
1885 } else {
1886 mmTaskBlock16(lpMMThd->hTask);
1889 TRACE("done\n");
1892 /**************************************************************************
1893 * mmThreadIsCurrent [MMSYSTEM.1123]
1895 BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
1897 BOOL16 ret = FALSE;
1899 TRACE("(%04x)!\n", hndl);
1901 if (hndl && mmThreadIsValid16(hndl)) {
1902 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1903 ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
1905 TRACE("=> %d\n", ret);
1906 return ret;
1909 /**************************************************************************
1910 * mmThreadIsValid [MMSYSTEM.1124]
1912 BOOL16 WINAPI mmThreadIsValid16(HANDLE16 hndl)
1914 BOOL16 ret = FALSE;
1916 TRACE("(%04x)!\n", hndl);
1918 if (hndl) {
1919 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1921 if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
1922 lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
1923 IsTask16(lpMMThd->hTask)) {
1924 lpMMThd->dwCounter++;
1925 if (lpMMThd->hThread != 0) {
1926 DWORD dwThreadRet;
1927 if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
1928 dwThreadRet == STATUS_PENDING) {
1929 ret = TRUE;
1931 } else {
1932 ret = TRUE;
1934 lpMMThd->dwCounter--;
1937 TRACE("=> %d\n", ret);
1938 return ret;
1941 /**************************************************************************
1942 * mmThreadGetTask [MMSYSTEM.1125]
1944 HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
1946 HANDLE16 ret = 0;
1948 TRACE("(%04x)\n", hndl);
1950 if (mmThreadIsValid16(hndl)) {
1951 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1952 ret = lpMMThd->hTask;
1954 return ret;
1957 /**************************************************************************
1958 * __wine_mmThreadEntryPoint (MMSYSTEM.2047)
1960 DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID p)
1962 HANDLE16 hndl = (HANDLE16)(DWORD_PTR)p;
1963 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1965 TRACE("(%04x %p)\n", hndl, lpMMThd);
1967 lpMMThd->hTask = LOWORD(GetCurrentTask());
1968 TRACE("[10-%p] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
1969 lpMMThd->dwStatus = 0x10;
1970 MMSYSTEM_ThreadBlock(lpMMThd);
1971 TRACE("[20-%p]\n", lpMMThd->hThread);
1972 lpMMThd->dwStatus = 0x20;
1973 if (lpMMThd->fpThread) {
1974 WOWCallback16(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
1976 lpMMThd->dwStatus = 0x30;
1977 TRACE("[30-%p]\n", lpMMThd->hThread);
1978 while (lpMMThd->dwCounter) {
1979 Sleep(1);
1980 /* WOWYield16();*/
1982 TRACE("[XX-%p]\n", lpMMThd->hThread);
1983 /* paranoia */
1984 lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
1985 /* close lpMMThread->hVxD directIO */
1986 if (lpMMThd->hEvent)
1987 CloseHandle(lpMMThd->hEvent);
1988 GlobalFree16(hndl);
1989 TRACE("done\n");
1991 return 0;
1994 typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
1996 /**************************************************************************
1997 * mmShowMMCPLPropertySheet [MMSYSTEM.1150]
1999 BOOL16 WINAPI mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
2000 LPCSTR lpStrTab, LPCSTR lpStrTitle)
2002 HANDLE hndl;
2003 BOOL16 ret = FALSE;
2005 TRACE("(%p \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2007 hndl = LoadLibraryA("MMSYS.CPL");
2008 if (hndl != 0) {
2009 MMCPLCALLBACK fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
2010 if (fp != NULL) {
2011 DWORD lc;
2012 ReleaseThunkLock(&lc);
2013 ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2014 RestoreThunkLock(lc);
2016 FreeLibrary(hndl);
2019 return ret;
2022 /**************************************************************************
2023 * StackEnter [MMSYSTEM.32]
2025 void WINAPI StackEnter16(void)
2027 #ifdef __i386__
2028 /* mmsystem.dll from Win 95 does only this: so does Wine */
2029 __asm__("stc");
2030 #endif
2033 /**************************************************************************
2034 * StackLeave [MMSYSTEM.33]
2036 void WINAPI StackLeave16(void)
2038 #ifdef __i386__
2039 /* mmsystem.dll from Win 95 does only this: so does Wine */
2040 __asm__("stc");
2041 #endif
2044 /**************************************************************************
2045 * WMMMidiRunOnce [MMSYSTEM.8]
2047 void WINAPI WMMMidiRunOnce16(void)
2049 FIXME("(), stub!\n");
2052 /* ###################################################
2053 * # DRIVER #
2054 * ###################################################
2057 /**************************************************************************
2058 * DRIVER_MapMsg32To16 [internal]
2060 * Map a 32 bit driver message to a 16 bit driver message.
2062 static WINMM_MapType DRIVER_MapMsg32To16(WORD wMsg, LPARAM *lParam1, LPARAM *lParam2)
2064 WINMM_MapType ret = WINMM_MAP_MSGERROR;
2066 switch (wMsg) {
2067 case DRV_LOAD:
2068 case DRV_ENABLE:
2069 case DRV_DISABLE:
2070 case DRV_FREE:
2071 case DRV_QUERYCONFIGURE:
2072 case DRV_REMOVE:
2073 case DRV_EXITSESSION:
2074 case DRV_EXITAPPLICATION:
2075 case DRV_POWER:
2076 case DRV_CLOSE: /* should be 0/0 */
2077 case DRV_OPEN: /* pass through */
2078 /* lParam1 and lParam2 are not used */
2079 ret = WINMM_MAP_OK;
2080 break;
2081 case DRV_CONFIGURE:
2082 case DRV_INSTALL:
2083 /* lParam1 is a handle to a window (conf) or to a driver (inst) or not used,
2084 * lParam2 is a pointer to DRVCONFIGINFO
2086 if (*lParam2) {
2087 LPDRVCONFIGINFO16 dci16 = HeapAlloc( GetProcessHeap(), 0, sizeof(*dci16) );
2088 LPDRVCONFIGINFO dci32 = (LPDRVCONFIGINFO)(*lParam2);
2090 if (dci16) {
2091 LPSTR str1 = NULL,str2;
2092 INT len;
2093 dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
2095 if (dci32->lpszDCISectionName) {
2096 len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, NULL, 0, NULL, NULL );
2097 str1 = HeapAlloc( GetProcessHeap(), 0, len );
2098 if (str1) {
2099 WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, str1, len, NULL, NULL );
2100 dci16->lpszDCISectionName = MapLS( str1 );
2101 } else {
2102 HeapFree( GetProcessHeap(), 0, dci16);
2103 return WINMM_MAP_NOMEM;
2105 } else {
2106 dci16->lpszDCISectionName = 0L;
2108 if (dci32->lpszDCIAliasName) {
2109 len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, NULL, 0, NULL, NULL );
2110 str2 = HeapAlloc( GetProcessHeap(), 0, len );
2111 if (str2) {
2112 WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, str2, len, NULL, NULL );
2113 dci16->lpszDCIAliasName = MapLS( str2 );
2114 } else {
2115 HeapFree( GetProcessHeap(), 0, str1);
2116 HeapFree( GetProcessHeap(), 0, dci16);
2117 return WINMM_MAP_NOMEM;
2119 } else {
2120 dci16->lpszDCISectionName = 0L;
2122 } else {
2123 return WINMM_MAP_NOMEM;
2125 *lParam2 = MapLS( dci16 );
2126 ret = WINMM_MAP_OKMEM;
2127 } else {
2128 ret = WINMM_MAP_OK;
2130 break;
2131 default:
2132 if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2133 FIXME("Unknown message 0x%04x\n", wMsg);
2135 ret = WINMM_MAP_OK;
2137 return ret;
2140 /**************************************************************************
2141 * DRIVER_UnMapMsg32To16 [internal]
2143 * UnMap a 32 bit driver message to a 16 bit driver message.
2145 static WINMM_MapType DRIVER_UnMapMsg32To16(WORD wMsg, DWORD lParam1, DWORD lParam2)
2147 WINMM_MapType ret = WINMM_MAP_MSGERROR;
2149 switch (wMsg) {
2150 case DRV_LOAD:
2151 case DRV_ENABLE:
2152 case DRV_DISABLE:
2153 case DRV_FREE:
2154 case DRV_QUERYCONFIGURE:
2155 case DRV_REMOVE:
2156 case DRV_EXITSESSION:
2157 case DRV_EXITAPPLICATION:
2158 case DRV_POWER:
2159 case DRV_OPEN:
2160 case DRV_CLOSE:
2161 /* lParam1 and lParam2 are not used */
2162 break;
2163 case DRV_CONFIGURE:
2164 case DRV_INSTALL:
2165 /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
2166 if (lParam2) {
2167 LPDRVCONFIGINFO16 dci16 = MapSL(lParam2);
2168 HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCISectionName) );
2169 HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCIAliasName) );
2170 UnMapLS( lParam2 );
2171 UnMapLS( dci16->lpszDCISectionName );
2172 UnMapLS( dci16->lpszDCIAliasName );
2173 HeapFree( GetProcessHeap(), 0, dci16 );
2175 ret = WINMM_MAP_OK;
2176 break;
2177 default:
2178 if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2179 FIXME("Unknown message 0x%04x\n", wMsg);
2181 ret = WINMM_MAP_OK;
2183 return ret;
2186 /**************************************************************************
2187 * DRIVER_TryOpenDriver16 [internal]
2189 * Tries to load a 16 bit driver whose DLL's (module) name is lpFileName.
2191 static LPWINE_DRIVER DRIVER_OpenDriver16(LPCWSTR fn, LPCWSTR sn, LPARAM lParam2)
2193 LPWINE_DRIVER lpDrv = NULL;
2194 LPCSTR cause = NULL;
2195 LPSTR fnA = NULL, snA = NULL;
2196 unsigned len;
2198 TRACE("(%s, %s, %08lX);\n", debugstr_w(fn), debugstr_w(sn), lParam2);
2200 lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
2201 if (lpDrv == NULL) {cause = "OOM"; goto exit;}
2203 if (fn)
2205 len = WideCharToMultiByte( CP_ACP, 0, fn, -1, NULL, 0, NULL, NULL );
2206 fnA = HeapAlloc(GetProcessHeap(), 0, len);
2207 if (fnA == NULL) {cause = "OOM"; goto exit;}
2208 WideCharToMultiByte( CP_ACP, 0, fn, -1, fnA, len, NULL, NULL );
2211 if (sn)
2213 len = WideCharToMultiByte( CP_ACP, 0, sn, -1, NULL, 0, NULL, NULL );
2214 snA = HeapAlloc(GetProcessHeap(), 0, len);
2215 if (snA == NULL) {cause = "OOM"; goto exit;}
2216 WideCharToMultiByte( CP_ACP, 0, sn, -1, snA, len, NULL, NULL );
2219 /* FIXME: shall we do some black magic here on sn ?
2220 * drivers32 => drivers
2221 * mci32 => mci
2222 * ...
2224 lpDrv->d.d16.hDriver16 = OpenDriver16(fnA, snA, lParam2);
2225 if (lpDrv->d.d16.hDriver16 == 0) {cause = "Not a 16 bit driver"; goto exit;}
2226 lpDrv->dwFlags = WINE_GDF_16BIT;
2228 exit:
2229 HeapFree(GetProcessHeap(), 0, fnA);
2230 HeapFree(GetProcessHeap(), 0, snA);
2232 if (cause)
2234 TRACE("Unable to load 16 bit module %s[%s]: %s\n",
2235 debugstr_w(fn), debugstr_w(sn), cause);
2236 HeapFree(GetProcessHeap(), 0, lpDrv);
2237 return NULL;
2240 TRACE("=> %p\n", lpDrv);
2241 return lpDrv;
2244 /******************************************************************
2245 * DRIVER_SendMessage16
2249 static LRESULT DRIVER_SendMessage16(HDRVR16 hDrv16, UINT msg,
2250 LPARAM lParam1, LPARAM lParam2)
2252 LRESULT ret = 0;
2253 WINMM_MapType map;
2255 TRACE("Before sdm16 call hDrv=%04x wMsg=%04x p1=%08lx p2=%08lx\n",
2256 hDrv16, msg, lParam1, lParam2);
2258 switch (map = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2)) {
2259 case WINMM_MAP_OKMEM:
2260 case WINMM_MAP_OK:
2261 ret = SendDriverMessage16(hDrv16, msg, lParam1, lParam2);
2262 if (map == WINMM_MAP_OKMEM)
2263 DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
2264 default:
2265 break;
2267 return ret;
2270 /******************************************************************
2271 * DRIVER_CloseDriver16
2275 static LRESULT DRIVER_CloseDriver16(HDRVR16 hDrv16, LPARAM lParam1, LPARAM lParam2)
2277 return CloseDriver16(hDrv16, lParam1, lParam2);
2280 /**************************************************************************
2281 * DrvOpen [MMSYSTEM.1100]
2283 HDRVR16 WINAPI DrvOpen16(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
2285 return OpenDriver16(lpDriverName, lpSectionName, lParam);
2288 /**************************************************************************
2289 * DrvClose [MMSYSTEM.1101]
2291 LRESULT WINAPI DrvClose16(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
2293 return CloseDriver16(hDrv, lParam1, lParam2);
2296 /**************************************************************************
2297 * DrvSendMessage [MMSYSTEM.1102]
2299 LRESULT WINAPI DrvSendMessage16(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
2300 LPARAM lParam2)
2302 return SendDriverMessage16(hDrv, msg, lParam1, lParam2);
2305 /**************************************************************************
2306 * DrvGetModuleHandle [MMSYSTEM.1103]
2308 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
2310 return GetDriverModuleHandle16(hDrv);
2313 /**************************************************************************
2314 * DrvDefDriverProc [MMSYSTEM.1104]
2316 LRESULT WINAPI DrvDefDriverProc16(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
2317 DWORD dwParam1, DWORD dwParam2)
2319 return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
2322 /**************************************************************************
2323 * DriverProc [MMSYSTEM.6]
2325 LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
2326 DWORD dwParam1, DWORD dwParam2)
2328 TRACE("dwDevID=%08x hDrv=%04x wMsg=%04x dwParam1=%08x dwParam2=%08x\n",
2329 dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2331 return DrvDefDriverProc16(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2334 /* ###################################################
2335 * # TIME #
2336 * ###################################################
2339 /******************************************************************
2340 * MMSYSTEM_MMTIME32to16
2344 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16, const MMTIME* mmt32)
2346 mmt16->wType = mmt32->wType;
2347 /* layout of rest is the same for 32/16,
2348 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2350 memcpy(&(mmt16->u), &(mmt32->u), sizeof(mmt16->u));
2353 /******************************************************************
2354 * MMSYSTEM_MMTIME16to32
2358 void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32, const MMTIME16* mmt16)
2360 mmt32->wType = mmt16->wType;
2361 /* layout of rest is the same for 32/16,
2362 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2364 memcpy(&(mmt32->u), &(mmt16->u), sizeof(mmt16->u));
2367 /**************************************************************************
2368 * timeGetSystemTime [MMSYSTEM.601]
2370 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
2372 if (wSize >= sizeof(*lpTime)) {
2373 lpTime->wType = TIME_MS;
2374 lpTime->u.ms = GetTickCount();
2376 TRACE("=> %u\n", lpTime->u.ms);
2379 return 0;
2382 struct timer_entry {
2383 struct list entry;
2384 UINT id;
2385 LPTIMECALLBACK16 func16;
2386 DWORD user;
2389 static struct list timer_list = LIST_INIT(timer_list);
2391 static void CALLBACK timeCB3216(UINT id, UINT uMsg, DWORD_PTR user, DWORD_PTR dw1, DWORD_PTR dw2)
2393 struct timer_entry* te = (void*)user;
2394 WORD args[8];
2395 DWORD ret;
2397 args[7] = LOWORD(id);
2398 args[6] = LOWORD(uMsg);
2399 args[5] = HIWORD(te->user);
2400 args[4] = LOWORD(te->user);
2401 args[3] = HIWORD(dw1);
2402 args[2] = LOWORD(dw2);
2403 args[1] = HIWORD(dw2);
2404 args[0] = LOWORD(dw2);
2405 WOWCallback16Ex((DWORD)te->func16, WCB16_PASCAL, sizeof(args), args, &ret);
2408 /**************************************************************************
2409 * timeSetEvent [MMSYSTEM.602]
2411 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol, LPTIMECALLBACK16 lpFunc,
2412 DWORD dwUser, UINT16 wFlags)
2414 MMRESULT16 id;
2415 struct timer_entry* te;
2417 switch (wFlags & (TIME_CALLBACK_EVENT_SET|TIME_CALLBACK_EVENT_PULSE))
2419 case TIME_CALLBACK_EVENT_SET:
2420 case TIME_CALLBACK_EVENT_PULSE:
2421 id = timeSetEvent(wDelay, wResol, (LPTIMECALLBACK)lpFunc, dwUser, wFlags);
2422 break;
2423 case TIME_CALLBACK_FUNCTION:
2424 te = HeapAlloc(GetProcessHeap(), 0, sizeof(*te));
2425 if (!te) return 0;
2426 te->func16 = lpFunc;
2427 te->user = dwUser;
2428 id = te->id = timeSetEvent(wDelay, wResol, timeCB3216, (DWORD_PTR)te, wFlags);
2429 if (id)
2431 EnterCriticalSection(&mmdrv_cs);
2432 list_add_tail(&timer_list, &te->entry);
2433 LeaveCriticalSection(&mmdrv_cs);
2435 else HeapFree(GetProcessHeap(), 0, te);
2436 break;
2437 default:
2438 id = 0;
2439 break;
2441 return id;
2444 /**************************************************************************
2445 * timeKillEvent [MMSYSTEM.603]
2447 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
2449 MMRESULT16 ret = timeKillEvent(wID);
2450 struct timer_entry* te;
2452 if (ret == TIMERR_NOERROR)
2454 EnterCriticalSection(&mmdrv_cs);
2455 LIST_FOR_EACH_ENTRY(te, &timer_list, struct timer_entry, entry)
2457 if (wID == te->id)
2459 list_remove(&te->entry);
2460 HeapFree(GetProcessHeap(), 0, te);
2461 break;
2464 LeaveCriticalSection(&mmdrv_cs);
2466 return ret;
2469 /**************************************************************************
2470 * timeGetDevCaps [MMSYSTEM.604]
2472 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
2474 TIMECAPS caps;
2475 MMRESULT ret;
2476 TRACE("(%p, %u) !\n", lpCaps, wSize);
2478 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2480 ret = timeGetDevCaps(&caps, sizeof(caps));
2481 if (ret == MMSYSERR_NOERROR) {
2482 TIMECAPS16 tc16;
2483 tc16.wPeriodMin = caps.wPeriodMin;
2484 tc16.wPeriodMax = caps.wPeriodMax;
2485 memcpy(lpCaps, &tc16, min(wSize, sizeof(tc16)));
2487 return ret;
2490 /**************************************************************************
2491 * timeBeginPeriod [MMSYSTEM.605]
2493 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
2495 TRACE("(%u) !\n", wPeriod);
2497 return timeBeginPeriod(wPeriod);
2500 /**************************************************************************
2501 * timeEndPeriod [MMSYSTEM.606]
2503 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
2505 TRACE("(%u) !\n", wPeriod);
2507 return timeEndPeriod(wPeriod);
2510 /**************************************************************************
2511 * timeGetTime [MMSYSTEM.607]
2513 DWORD WINAPI timeGetTime16(void)
2515 return timeGetTime();
2518 /* ###################################################
2519 * # JOYSTICK #
2520 * ###################################################
2523 /**************************************************************************
2524 * joyGetNumDevs [MMSYSTEM.101]
2526 UINT16 WINAPI joyGetNumDevs16(void)
2528 return joyGetNumDevs();
2531 /**************************************************************************
2532 * joyGetDevCaps [MMSYSTEM.102]
2534 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
2536 JOYCAPSA jca;
2537 MMRESULT ret;
2539 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2541 ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
2543 if (ret != JOYERR_NOERROR) return ret;
2544 lpCaps->wMid = jca.wMid;
2545 lpCaps->wPid = jca.wPid;
2546 strcpy(lpCaps->szPname, jca.szPname);
2547 lpCaps->wXmin = jca.wXmin;
2548 lpCaps->wXmax = jca.wXmax;
2549 lpCaps->wYmin = jca.wYmin;
2550 lpCaps->wYmax = jca.wYmax;
2551 lpCaps->wZmin = jca.wZmin;
2552 lpCaps->wZmax = jca.wZmax;
2553 lpCaps->wNumButtons = jca.wNumButtons;
2554 lpCaps->wPeriodMin = jca.wPeriodMin;
2555 lpCaps->wPeriodMax = jca.wPeriodMax;
2557 if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
2558 lpCaps->wRmin = jca.wRmin;
2559 lpCaps->wRmax = jca.wRmax;
2560 lpCaps->wUmin = jca.wUmin;
2561 lpCaps->wUmax = jca.wUmax;
2562 lpCaps->wVmin = jca.wVmin;
2563 lpCaps->wVmax = jca.wVmax;
2564 lpCaps->wCaps = jca.wCaps;
2565 lpCaps->wMaxAxes = jca.wMaxAxes;
2566 lpCaps->wNumAxes = jca.wNumAxes;
2567 lpCaps->wMaxButtons = jca.wMaxButtons;
2568 strcpy(lpCaps->szRegKey, jca.szRegKey);
2569 strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
2572 return ret;
2575 /**************************************************************************
2576 * joyGetPosEx [MMSYSTEM.110]
2578 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
2580 return joyGetPosEx(wID, lpInfo);
2583 /**************************************************************************
2584 * joyGetPos [MMSYSTEM.103]
2586 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
2588 JOYINFO ji;
2589 MMRESULT ret;
2591 TRACE("(%d, %p);\n", wID, lpInfo);
2593 if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
2594 lpInfo->wXpos = ji.wXpos;
2595 lpInfo->wYpos = ji.wYpos;
2596 lpInfo->wZpos = ji.wZpos;
2597 lpInfo->wButtons = ji.wButtons;
2599 return ret;
2602 /**************************************************************************
2603 * joyGetThreshold [MMSYSTEM.104]
2605 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
2607 UINT t;
2608 MMRESULT ret;
2610 ret = joyGetThreshold(wID, &t);
2611 if (ret == JOYERR_NOERROR)
2612 *lpThreshold = t;
2613 return ret;
2616 /**************************************************************************
2617 * joyReleaseCapture [MMSYSTEM.105]
2619 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
2621 return joyReleaseCapture(wID);
2624 /**************************************************************************
2625 * joySetCapture [MMSYSTEM.106]
2627 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
2629 return joySetCapture(HWND_32(hWnd), wID, wPeriod, bChanged);
2632 /**************************************************************************
2633 * joySetThreshold [MMSYSTEM.107]
2635 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
2637 return joySetThreshold(wID,wThreshold);
2640 /**************************************************************************
2641 * joySetCalibration [MMSYSTEM.109]
2643 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
2645 FIXME("(%04X): stub.\n", wID);
2646 return JOYERR_NOCANDO;