push 8b07bf1f08b23b9893a622b47d2be359556765b1
[wine/hacks.git] / dlls / winmm / mmsystem.c
blobced17095cc5bc0defc83218c4e207ed0f572ce4f
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/winuser16.h"
42 #include "winemm.h"
43 #include "winemm16.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(mmsys);
49 static WINE_MMTHREAD* WINMM_GetmmThread(HANDLE16);
50 static LPWINE_DRIVER DRIVER_OpenDriver16(LPCWSTR, LPCWSTR, LPARAM);
51 static LRESULT DRIVER_CloseDriver16(HDRVR16, LPARAM, LPARAM);
52 static LRESULT DRIVER_SendMessage16(HDRVR16, UINT, LPARAM, LPARAM);
54 /* ###################################################
55 * # LIBRARY #
56 * ###################################################
59 /**************************************************************************
60 * DllEntryPoint (MMSYSTEM.4)
62 * MMSYSTEM DLL entry point
65 BOOL WINAPI MMSYSTEM_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
66 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
68 TRACE("%p 0x%x\n", hinstDLL, fdwReason);
70 switch (fdwReason) {
71 case DLL_PROCESS_ATTACH:
72 /* need to load WinMM in order to:
73 * - initiate correctly shared variables (WINMM_Init())
75 if (!GetModuleHandleA("WINMM.DLL"))
77 ERR("Could not load sibling WinMM.dll\n");
78 return FALSE;
80 /* hook in our 16 bit function pointers */
81 pFnGetMMThread16 = WINMM_GetmmThread;
82 pFnOpenDriver16 = DRIVER_OpenDriver16;
83 pFnCloseDriver16 = DRIVER_CloseDriver16;
84 pFnSendMessage16 = DRIVER_SendMessage16;
85 pFnReleaseThunkLock = ReleaseThunkLock;
86 pFnRestoreThunkLock = RestoreThunkLock;
87 MMDRV_Init16();
88 break;
89 case DLL_PROCESS_DETACH:
90 pFnGetMMThread16 = NULL;
91 pFnOpenDriver16 = NULL;
92 pFnCloseDriver16 = NULL;
93 pFnSendMessage16 = NULL;
94 pFnReleaseThunkLock = NULL;
95 pFnRestoreThunkLock = NULL;
96 /* FIXME: add equivalent for MMDRV_Init16() */
97 break;
98 case DLL_THREAD_ATTACH:
99 case DLL_THREAD_DETACH:
100 break;
102 return TRUE;
105 /**************************************************************************
106 * WEP [MMSYSTEM.1]
108 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
109 WORD cbHeapSize, LPSTR lpCmdLine)
111 TRACE("STUB: Unloading MMSystem DLL ... hInst=%04X\n", hInstance);
112 return TRUE;
115 /* ###################################################
116 * # PlaySound #
117 * ###################################################
120 /**************************************************************************
121 * PlaySound [MMSYSTEM.3]
123 BOOL16 WINAPI PlaySound16(LPCSTR pszSound, HMODULE16 hmod, DWORD fdwSound)
125 BOOL16 retv;
126 DWORD lc;
128 if ((fdwSound & SND_RESOURCE) == SND_RESOURCE)
130 HGLOBAL16 handle;
131 HRSRC16 res;
133 if (!(res = FindResource16( hmod, pszSound, "WAVE" ))) return FALSE;
134 if (!(handle = LoadResource16( hmod, res ))) return FALSE;
135 pszSound = LockResource16(handle);
136 fdwSound = (fdwSound & ~SND_RESOURCE) | SND_MEMORY;
137 /* FIXME: FreeResource16 */
140 ReleaseThunkLock(&lc);
141 retv = PlaySoundA(pszSound, 0, fdwSound);
142 RestoreThunkLock(lc);
144 return retv;
147 /**************************************************************************
148 * sndPlaySound [MMSYSTEM.2]
150 BOOL16 WINAPI sndPlaySound16(LPCSTR lpszSoundName, UINT16 uFlags)
152 BOOL16 retv;
153 DWORD lc;
155 ReleaseThunkLock(&lc);
156 retv = sndPlaySoundA(lpszSoundName, uFlags);
157 RestoreThunkLock(lc);
159 return retv;
162 /* ###################################################
163 * # MISC #
164 * ###################################################
167 /**************************************************************************
168 * mmsystemGetVersion [MMSYSTEM.5]
171 UINT16 WINAPI mmsystemGetVersion16(void)
173 return mmsystemGetVersion();
176 /**************************************************************************
177 * DriverCallback [MMSYSTEM.31]
179 BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HDRVR16 hDev,
180 WORD wMsg, DWORD dwUser, DWORD dwParam1,
181 DWORD dwParam2)
183 return DriverCallback(dwCallBack, uFlags, HDRVR_32(hDev), wMsg, dwUser, dwParam1, dwParam2);
186 /**************************************************************************
187 * OutputDebugStr [MMSYSTEM.30]
189 void WINAPI OutputDebugStr16(LPCSTR str)
191 OutputDebugStringA( str );
195 /* ###################################################
196 * # MIXER #
197 * ###################################################
200 /**************************************************************************
201 * Mixer devices. New to Win95
204 /**************************************************************************
205 * mixerGetNumDevs [MMSYSTEM.800]
207 UINT16 WINAPI mixerGetNumDevs16(void)
209 return mixerGetNumDevs();
212 /**************************************************************************
213 * mixerGetDevCaps [MMSYSTEM.801]
215 UINT16 WINAPI mixerGetDevCaps16(UINT16 uDeviceID, LPMIXERCAPS16 lpCaps,
216 UINT16 uSize)
218 MIXERCAPSA micA;
219 UINT ret;
221 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
223 ret = mixerGetDevCapsA(uDeviceID, &micA, sizeof(micA));
224 if (ret == MMSYSERR_NOERROR) {
225 MIXERCAPS16 mic16;
226 mic16.wMid = micA.wMid;
227 mic16.wPid = micA.wPid;
228 mic16.vDriverVersion = micA.vDriverVersion;
229 strcpy(mic16.szPname, micA.szPname);
230 mic16.fdwSupport = micA.fdwSupport;
231 mic16.cDestinations = micA.cDestinations;
232 memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
234 return ret;
237 /**************************************************************************
238 * mixerOpen [MMSYSTEM.802]
240 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix, UINT16 uDeviceID, DWORD dwCallback,
241 DWORD dwInstance, DWORD fdwOpen)
243 HMIXER hmix;
244 UINT ret;
246 ret = MIXER_Open(&hmix, uDeviceID, dwCallback, dwInstance, fdwOpen, FALSE);
247 if (lphmix) *lphmix = HMIXER_16(hmix);
248 return ret;
251 /**************************************************************************
252 * mixerClose [MMSYSTEM.803]
254 UINT16 WINAPI mixerClose16(HMIXER16 hMix)
256 return mixerClose(HMIXER_32(hMix));
259 /**************************************************************************
260 * mixerGetID (MMSYSTEM.806)
262 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix, LPUINT16 lpid, DWORD fdwID)
264 UINT xid;
265 UINT ret = mixerGetID(HMIXEROBJ_32(hmix), &xid, fdwID);
267 if (lpid)
268 *lpid = xid;
269 return ret;
272 /**************************************************************************
273 * mixerGetControlDetails [MMSYSTEM.808]
275 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix,
276 LPMIXERCONTROLDETAILS16 lpmcd,
277 DWORD fdwDetails)
279 DWORD ret = MMSYSERR_NOTENABLED;
280 SEGPTR sppaDetails;
282 TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
284 if (lpmcd == NULL || lpmcd->cbStruct != sizeof(*lpmcd))
285 return MMSYSERR_INVALPARAM;
287 sppaDetails = (SEGPTR)lpmcd->paDetails;
288 lpmcd->paDetails = MapSL(sppaDetails);
289 ret = mixerGetControlDetailsA(HMIXEROBJ_32(hmix),
290 (LPMIXERCONTROLDETAILS)lpmcd, fdwDetails);
291 lpmcd->paDetails = (LPVOID)sppaDetails;
293 return ret;
296 /**************************************************************************
297 * mixerGetLineControls [MMSYSTEM.807]
299 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix,
300 LPMIXERLINECONTROLS16 lpmlc16,
301 DWORD fdwControls)
303 MIXERLINECONTROLSA mlcA;
304 DWORD ret;
305 unsigned int i;
306 LPMIXERCONTROL16 lpmc16;
308 TRACE("(%04x, %p, %08x)\n", hmix, lpmlc16, fdwControls);
310 if (lpmlc16 == NULL || lpmlc16->cbStruct != sizeof(*lpmlc16) ||
311 lpmlc16->cbmxctrl != sizeof(MIXERCONTROL16))
312 return MMSYSERR_INVALPARAM;
314 mlcA.cbStruct = sizeof(mlcA);
315 mlcA.dwLineID = lpmlc16->dwLineID;
316 mlcA.u.dwControlID = lpmlc16->u.dwControlID;
317 mlcA.u.dwControlType = lpmlc16->u.dwControlType;
318 mlcA.cControls = lpmlc16->cControls;
319 mlcA.cbmxctrl = sizeof(MIXERCONTROLA);
320 mlcA.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
321 mlcA.cControls * mlcA.cbmxctrl);
323 ret = mixerGetLineControlsA(HMIXEROBJ_32(hmix), &mlcA, fdwControls);
325 if (ret == MMSYSERR_NOERROR) {
326 lpmlc16->dwLineID = mlcA.dwLineID;
327 lpmlc16->u.dwControlID = mlcA.u.dwControlID;
328 lpmlc16->u.dwControlType = mlcA.u.dwControlType;
329 lpmlc16->cControls = mlcA.cControls;
331 lpmc16 = MapSL(lpmlc16->pamxctrl);
333 for (i = 0; i < mlcA.cControls; i++) {
334 lpmc16[i].cbStruct = sizeof(MIXERCONTROL16);
335 lpmc16[i].dwControlID = mlcA.pamxctrl[i].dwControlID;
336 lpmc16[i].dwControlType = mlcA.pamxctrl[i].dwControlType;
337 lpmc16[i].fdwControl = mlcA.pamxctrl[i].fdwControl;
338 lpmc16[i].cMultipleItems = mlcA.pamxctrl[i].cMultipleItems;
339 strcpy(lpmc16[i].szShortName, mlcA.pamxctrl[i].szShortName);
340 strcpy(lpmc16[i].szName, mlcA.pamxctrl[i].szName);
341 /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
342 memcpy(&lpmc16[i].Bounds, &mlcA.pamxctrl[i].Bounds,
343 sizeof(mlcA.pamxctrl[i].Bounds));
344 /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
345 memcpy(&lpmc16[i].Metrics, &mlcA.pamxctrl[i].Metrics,
346 sizeof(mlcA.pamxctrl[i].Metrics));
350 HeapFree(GetProcessHeap(), 0, mlcA.pamxctrl);
352 return ret;
355 /**************************************************************************
356 * mixerGetLineInfo [MMSYSTEM.805]
358 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix, LPMIXERLINE16 lpmli16,
359 DWORD fdwInfo)
361 MIXERLINEA mliA;
362 UINT ret;
364 TRACE("(%04x, %p, %08x)\n", hmix, lpmli16, fdwInfo);
366 if (lpmli16 == NULL || lpmli16->cbStruct != sizeof(*lpmli16))
367 return MMSYSERR_INVALPARAM;
369 mliA.cbStruct = sizeof(mliA);
370 switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) {
371 case MIXER_GETLINEINFOF_COMPONENTTYPE:
372 mliA.dwComponentType = lpmli16->dwComponentType;
373 break;
374 case MIXER_GETLINEINFOF_DESTINATION:
375 mliA.dwDestination = lpmli16->dwDestination;
376 break;
377 case MIXER_GETLINEINFOF_LINEID:
378 mliA.dwLineID = lpmli16->dwLineID;
379 break;
380 case MIXER_GETLINEINFOF_SOURCE:
381 mliA.dwDestination = lpmli16->dwDestination;
382 mliA.dwSource = lpmli16->dwSource;
383 break;
384 case MIXER_GETLINEINFOF_TARGETTYPE:
385 mliA.Target.dwType = lpmli16->Target.dwType;
386 mliA.Target.wMid = lpmli16->Target.wMid;
387 mliA.Target.wPid = lpmli16->Target.wPid;
388 mliA.Target.vDriverVersion = lpmli16->Target.vDriverVersion;
389 strcpy(mliA.Target.szPname, lpmli16->Target.szPname);
390 break;
391 default:
392 FIXME("Unsupported fdwControls=0x%08x\n", fdwInfo);
395 ret = mixerGetLineInfoA(HMIXEROBJ_32(hmix), &mliA, fdwInfo);
397 lpmli16->dwDestination = mliA.dwDestination;
398 lpmli16->dwSource = mliA.dwSource;
399 lpmli16->dwLineID = mliA.dwLineID;
400 lpmli16->fdwLine = mliA.fdwLine;
401 lpmli16->dwUser = mliA.dwUser;
402 lpmli16->dwComponentType = mliA.dwComponentType;
403 lpmli16->cChannels = mliA.cChannels;
404 lpmli16->cConnections = mliA.cConnections;
405 lpmli16->cControls = mliA.cControls;
406 strcpy(lpmli16->szShortName, mliA.szShortName);
407 strcpy(lpmli16->szName, mliA.szName);
408 lpmli16->Target.dwType = mliA.Target.dwType;
409 lpmli16->Target.dwDeviceID = mliA.Target.dwDeviceID;
410 lpmli16->Target.wMid = mliA.Target.wMid;
411 lpmli16->Target.wPid = mliA.Target.wPid;
412 lpmli16->Target.vDriverVersion = mliA.Target.vDriverVersion;
413 strcpy(lpmli16->Target.szPname, mliA.Target.szPname);
415 return ret;
418 /**************************************************************************
419 * mixerSetControlDetails [MMSYSTEM.809]
421 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix,
422 LPMIXERCONTROLDETAILS16 lpmcd,
423 DWORD fdwDetails)
425 TRACE("(%04x, %p, %08x)\n", hmix, lpmcd, fdwDetails);
426 return MMSYSERR_NOTENABLED;
429 /**************************************************************************
430 * mixerMessage [MMSYSTEM.804]
432 DWORD WINAPI mixerMessage16(HMIXER16 hmix, UINT16 uMsg, DWORD dwParam1,
433 DWORD dwParam2)
435 return mixerMessage(HMIXER_32(hmix), uMsg, dwParam1, dwParam2);
438 /**************************************************************************
439 * auxGetNumDevs [MMSYSTEM.350]
441 UINT16 WINAPI auxGetNumDevs16(void)
443 return auxGetNumDevs();
446 /* ###################################################
447 * # AUX #
448 * ###################################################
451 /**************************************************************************
452 * auxGetDevCaps [MMSYSTEM.351]
454 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID, LPAUXCAPS16 lpCaps, UINT16 uSize)
456 AUXCAPSA acA;
457 UINT ret;
459 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
461 ret = auxGetDevCapsA(uDeviceID, &acA, sizeof(acA));
462 if (ret == MMSYSERR_NOERROR) {
463 AUXCAPS16 ac16;
464 ac16.wMid = acA.wMid;
465 ac16.wPid = acA.wPid;
466 ac16.vDriverVersion = acA.vDriverVersion;
467 strcpy(ac16.szPname, acA.szPname);
468 ac16.wTechnology = acA.wTechnology;
469 ac16.dwSupport = acA.dwSupport;
470 memcpy(lpCaps, &ac16, min(uSize, sizeof(ac16)));
472 return ret;
475 /**************************************************************************
476 * auxGetVolume [MMSYSTEM.352]
478 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, LPDWORD lpdwVolume)
480 return auxGetVolume(uDeviceID, lpdwVolume);
483 /**************************************************************************
484 * auxSetVolume [MMSYSTEM.353]
486 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
488 return auxSetVolume(uDeviceID, dwVolume);
491 /**************************************************************************
492 * auxOutMessage [MMSYSTEM.354]
494 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
496 TRACE("(%04X, %04X, %08X, %08X)\n", uDeviceID, uMessage, dw1, dw2);
498 switch (uMessage) {
499 case AUXDM_GETNUMDEVS:
500 case AUXDM_SETVOLUME:
501 /* no argument conversion needed */
502 break;
503 case AUXDM_GETVOLUME:
504 return auxGetVolume16(uDeviceID, MapSL(dw1));
505 case AUXDM_GETDEVCAPS:
506 return auxGetDevCaps16(uDeviceID, MapSL(dw1), dw2);
507 default:
508 TRACE("(%04x, %04x, %08x, %08x): unhandled message\n",
509 uDeviceID, uMessage, dw1, dw2);
510 break;
512 return auxOutMessage(uDeviceID, uMessage, dw1, dw2);
515 /* ###################################################
516 * # MCI #
517 * ###################################################
520 /**************************************************************************
521 * mciGetErrorString [MMSYSTEM.706]
523 BOOL16 WINAPI mciGetErrorString16(DWORD wError, LPSTR lpstrBuffer, UINT16 uLength)
525 return mciGetErrorStringA(wError, lpstrBuffer, uLength);
528 /**************************************************************************
529 * mciDriverNotify [MMSYSTEM.711]
531 BOOL16 WINAPI mciDriverNotify16(HWND16 hWndCallBack, UINT16 wDevID, UINT16 wStatus)
533 TRACE("(%04X, %04x, %04X)\n", hWndCallBack, wDevID, wStatus);
535 return PostMessageA(HWND_32(hWndCallBack), MM_MCINOTIFY, wStatus, wDevID);
538 /**************************************************************************
539 * mciGetDriverData [MMSYSTEM.708]
541 DWORD WINAPI mciGetDriverData16(UINT16 uDeviceID)
543 return mciGetDriverData(uDeviceID);
546 /**************************************************************************
547 * mciSetDriverData [MMSYSTEM.707]
549 BOOL16 WINAPI mciSetDriverData16(UINT16 uDeviceID, DWORD data)
551 return mciSetDriverData(uDeviceID, data);
554 /**************************************************************************
555 * mciSendCommand [MMSYSTEM.701]
557 DWORD WINAPI mciSendCommand16(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
559 DWORD dwRet;
561 TRACE("(%04X, %s, %08X, %08X)\n",
562 wDevID, MCI_MessageToString(wMsg), dwParam1, dwParam2);
564 dwRet = MCI_SendCommand(wDevID, wMsg, dwParam1, dwParam2, FALSE);
565 dwRet = MCI_CleanUp(dwRet, wMsg, (DWORD)MapSL(dwParam2));
566 TRACE("=> %d\n", dwRet);
567 return dwRet;
570 /**************************************************************************
571 * mciGetDeviceID [MMSYSTEM.703]
573 UINT16 WINAPI mciGetDeviceID16(LPCSTR lpstrName)
575 TRACE("(\"%s\")\n", lpstrName);
577 return mciGetDeviceIDA(lpstrName);
580 /**************************************************************************
581 * mciSetYieldProc [MMSYSTEM.714]
583 BOOL16 WINAPI mciSetYieldProc16(UINT16 uDeviceID, YIELDPROC16 fpYieldProc, DWORD dwYieldData)
585 LPWINE_MCIDRIVER wmd;
587 TRACE("(%u, %p, %08x)\n", uDeviceID, fpYieldProc, dwYieldData);
589 if (!(wmd = MCI_GetDriver(uDeviceID))) {
590 WARN("Bad uDeviceID\n");
591 return FALSE;
594 wmd->lpfnYieldProc = (YIELDPROC)fpYieldProc;
595 wmd->dwYieldData = dwYieldData;
596 wmd->bIs32 = FALSE;
598 return TRUE;
601 /**************************************************************************
602 * mciGetDeviceIDFromElementID [MMSYSTEM.715]
604 UINT16 WINAPI mciGetDeviceIDFromElementID16(DWORD dwElementID, LPCSTR lpstrType)
606 FIXME("(%u, %s) stub\n", dwElementID, lpstrType);
607 return 0;
610 /**************************************************************************
611 * mciGetYieldProc [MMSYSTEM.716]
613 YIELDPROC16 WINAPI mciGetYieldProc16(UINT16 uDeviceID, DWORD* lpdwYieldData)
615 LPWINE_MCIDRIVER wmd;
617 TRACE("(%u, %p)\n", uDeviceID, lpdwYieldData);
619 if (!(wmd = MCI_GetDriver(uDeviceID))) {
620 WARN("Bad uDeviceID\n");
621 return NULL;
623 if (!wmd->lpfnYieldProc) {
624 WARN("No proc set\n");
625 return NULL;
627 if (wmd->bIs32) {
628 WARN("Proc is 32 bit\n");
629 return NULL;
631 if (lpdwYieldData) *lpdwYieldData = wmd->dwYieldData;
632 return (YIELDPROC16)wmd->lpfnYieldProc;
635 /**************************************************************************
636 * mciGetCreatorTask [MMSYSTEM.717]
638 HTASK16 WINAPI mciGetCreatorTask16(UINT16 uDeviceID)
640 return HTASK_16(mciGetCreatorTask(uDeviceID));
643 /**************************************************************************
644 * mciDriverYield [MMSYSTEM.710]
646 UINT16 WINAPI mciDriverYield16(UINT16 uDeviceID)
648 LPWINE_MCIDRIVER wmd;
649 UINT16 ret = 0;
651 /* TRACE("(%04x)\n", uDeviceID); */
653 if (!(wmd = MCI_GetDriver(uDeviceID)) || !wmd->lpfnYieldProc || wmd->bIs32) {
654 UserYield16();
655 } else {
656 ret = wmd->lpfnYieldProc(uDeviceID, wmd->dwYieldData);
659 return ret;
662 /* ###################################################
663 * # MIDI #
664 * ###################################################
667 /**************************************************************************
668 * midiOutGetNumDevs [MMSYSTEM.201]
670 UINT16 WINAPI midiOutGetNumDevs16(void)
672 return midiOutGetNumDevs();
675 /**************************************************************************
676 * midiOutGetDevCaps [MMSYSTEM.202]
678 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID, LPMIDIOUTCAPS16 lpCaps,
679 UINT16 uSize)
681 MIDIOUTCAPSA mocA;
682 UINT ret;
684 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
686 ret = midiOutGetDevCapsA(uDeviceID, &mocA, sizeof(mocA));
687 if (ret == MMSYSERR_NOERROR) {
688 MIDIOUTCAPS16 moc16;
689 moc16.wMid = mocA.wMid;
690 moc16.wPid = mocA.wPid;
691 moc16.vDriverVersion = mocA.vDriverVersion;
692 strcpy(moc16.szPname, mocA.szPname);
693 moc16.wTechnology = mocA.wTechnology;
694 moc16.wVoices = mocA.wVoices;
695 moc16.wNotes = mocA.wNotes;
696 moc16.wChannelMask = mocA.wChannelMask;
697 moc16.dwSupport = mocA.dwSupport;
698 memcpy(lpCaps, &moc16, min(uSize, sizeof(moc16)));
700 return ret;
703 /**************************************************************************
704 * midiOutGetErrorText [MMSYSTEM.203]
705 * midiInGetErrorText [MMSYSTEM.303]
707 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
709 return midiOutGetErrorTextA(uError, lpText, uSize);
712 /**************************************************************************
713 * midiOutOpen [MMSYSTEM.204]
715 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
716 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
718 HMIDIOUT hmo;
719 UINT ret;
721 ret = MIDI_OutOpen(&hmo, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
723 if (lphMidiOut != NULL) *lphMidiOut = HMIDIOUT_16(hmo);
724 return ret;
727 /**************************************************************************
728 * midiOutClose [MMSYSTEM.205]
730 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
732 return midiOutClose(HMIDIOUT_32(hMidiOut));
735 /**************************************************************************
736 * midiOutPrepareHeader [MMSYSTEM.206]
738 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut, /* [in] */
739 SEGPTR lpsegMidiOutHdr, /* [???] */
740 UINT16 uSize) /* [in] */
742 LPWINE_MLD wmld;
744 TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
746 if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
747 return MMSYSERR_INVALHANDLE;
749 return MMDRV_Message(wmld, MODM_PREPARE, lpsegMidiOutHdr, uSize, FALSE);
752 /**************************************************************************
753 * midiOutUnprepareHeader [MMSYSTEM.207]
755 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut, /* [in] */
756 SEGPTR lpsegMidiOutHdr, /* [???] */
757 UINT16 uSize) /* [in] */
759 LPWINE_MLD wmld;
760 LPMIDIHDR16 lpMidiOutHdr = MapSL(lpsegMidiOutHdr);
762 TRACE("(%04X, %08x, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
764 if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) {
765 return MMSYSERR_NOERROR;
768 if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
769 return MMSYSERR_INVALHANDLE;
771 return MMDRV_Message(wmld, MODM_UNPREPARE, lpsegMidiOutHdr, uSize, FALSE);
774 /**************************************************************************
775 * midiOutShortMsg [MMSYSTEM.208]
777 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
779 return midiOutShortMsg(HMIDIOUT_32(hMidiOut), dwMsg);
782 /**************************************************************************
783 * midiOutLongMsg [MMSYSTEM.209]
785 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut, /* [in] */
786 LPMIDIHDR16 lpsegMidiOutHdr, /* [???] NOTE: SEGPTR */
787 UINT16 uSize) /* [in] */
789 LPWINE_MLD wmld;
791 TRACE("(%04X, %p, %d)\n", hMidiOut, lpsegMidiOutHdr, uSize);
793 if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
794 return MMSYSERR_INVALHANDLE;
796 return MMDRV_Message(wmld, MODM_LONGDATA, (DWORD_PTR)lpsegMidiOutHdr, uSize, FALSE);
799 /**************************************************************************
800 * midiOutReset [MMSYSTEM.210]
802 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
804 return midiOutReset(HMIDIOUT_32(hMidiOut));
807 /**************************************************************************
808 * midiOutGetVolume [MMSYSTEM.211]
810 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
812 return midiOutGetVolume(HMIDIOUT_32(uDeviceID), lpdwVolume);
815 /**************************************************************************
816 * midiOutSetVolume [MMSYSTEM.212]
818 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
820 return midiOutSetVolume(HMIDIOUT_32(uDeviceID), dwVolume);
823 /**************************************************************************
824 * midiOutCachePatches [MMSYSTEM.213]
826 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
827 WORD* lpwPatchArray, UINT16 uFlags)
829 return midiOutCachePatches(HMIDIOUT_32(hMidiOut), uBank, lpwPatchArray,
830 uFlags);
833 /**************************************************************************
834 * midiOutCacheDrumPatches [MMSYSTEM.214]
836 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
837 WORD* lpwKeyArray, UINT16 uFlags)
839 return midiOutCacheDrumPatches(HMIDIOUT_32(hMidiOut), uPatch, lpwKeyArray, uFlags);
842 /**************************************************************************
843 * midiOutGetID [MMSYSTEM.215]
845 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
847 UINT devid;
848 UINT16 ret;
850 ret = midiOutGetID(HMIDIOUT_32(hMidiOut), &devid);
851 if (ret != MMSYSERR_NOERROR) return ret;
852 *lpuDeviceID = devid;
853 return ret;
856 /**************************************************************************
857 * midiOutMessage [MMSYSTEM.216]
859 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
860 DWORD dwParam1, DWORD dwParam2)
862 LPWINE_MLD wmld;
864 TRACE("(%04X, %04X, %08X, %08X)\n", hMidiOut, uMessage, dwParam1, dwParam2);
866 if ((wmld = MMDRV_Get(HMIDIOUT_32(hMidiOut), MMDRV_MIDIOUT, FALSE)) == NULL)
867 return MMSYSERR_INVALHANDLE;
869 switch (uMessage) {
870 case MODM_OPEN:
871 case MODM_CLOSE:
872 FIXME("can't handle OPEN or CLOSE message!\n");
873 return MMSYSERR_NOTSUPPORTED;
875 case MODM_GETVOLUME:
876 return midiOutGetVolume16(hMidiOut, MapSL(dwParam1));
877 case MODM_LONGDATA:
878 return midiOutLongMsg16(hMidiOut, MapSL(dwParam1), dwParam2);
879 case MODM_PREPARE:
880 /* lpMidiOutHdr is still a segmented pointer for this function */
881 return midiOutPrepareHeader16(hMidiOut, dwParam1, dwParam2);
882 case MODM_UNPREPARE:
883 return midiOutUnprepareHeader16(hMidiOut, dwParam1, dwParam2);
885 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, TRUE);
888 /**************************************************************************
889 * midiInGetNumDevs [MMSYSTEM.301]
891 UINT16 WINAPI midiInGetNumDevs16(void)
893 return midiInGetNumDevs();
896 /**************************************************************************
897 * midiInGetDevCaps [MMSYSTEM.302]
899 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID, LPMIDIINCAPS16 lpCaps,
900 UINT16 uSize)
902 MIDIINCAPSA micA;
903 UINT ret;
905 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
907 ret = midiInGetDevCapsA(uDeviceID, &micA, uSize);
908 if (ret == MMSYSERR_NOERROR) {
909 MIDIINCAPS16 mic16;
910 mic16.wMid = micA.wMid;
911 mic16.wPid = micA.wPid;
912 mic16.vDriverVersion = micA.vDriverVersion;
913 strcpy(mic16.szPname, micA.szPname);
914 mic16.dwSupport = micA.dwSupport;
915 memcpy(lpCaps, &mic16, min(uSize, sizeof(mic16)));
917 return ret;
920 /**************************************************************************
921 * midiInOpen [MMSYSTEM.304]
923 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
924 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
926 HMIDIIN xhmid;
927 UINT ret;
929 ret = MIDI_InOpen(&xhmid, uDeviceID, dwCallback, dwInstance, dwFlags, FALSE);
931 if (lphMidiIn) *lphMidiIn = HMIDIIN_16(xhmid);
932 return ret;
935 /**************************************************************************
936 * midiInClose [MMSYSTEM.305]
938 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
940 return midiInClose(HMIDIIN_32(hMidiIn));
943 /**************************************************************************
944 * midiInPrepareHeader [MMSYSTEM.306]
946 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn, /* [in] */
947 SEGPTR lpsegMidiInHdr, /* [???] */
948 UINT16 uSize) /* [in] */
950 LPWINE_MLD wmld;
952 TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
954 if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
955 return MMSYSERR_INVALHANDLE;
957 return MMDRV_Message(wmld, MIDM_PREPARE, lpsegMidiInHdr, uSize, FALSE);
960 /**************************************************************************
961 * midiInUnprepareHeader [MMSYSTEM.307]
963 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn, /* [in] */
964 SEGPTR lpsegMidiInHdr, /* [???] */
965 UINT16 uSize) /* [in] */
967 LPWINE_MLD wmld;
968 LPMIDIHDR16 lpMidiInHdr = MapSL(lpsegMidiInHdr);
970 TRACE("(%04X, %08x, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
972 if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) {
973 return MMSYSERR_NOERROR;
976 if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
977 return MMSYSERR_INVALHANDLE;
979 return MMDRV_Message(wmld, MIDM_UNPREPARE, lpsegMidiInHdr, uSize, FALSE);
982 /**************************************************************************
983 * midiInAddBuffer [MMSYSTEM.308]
985 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn, /* [in] */
986 MIDIHDR16* lpsegMidiInHdr, /* [???] NOTE: SEGPTR */
987 UINT16 uSize) /* [in] */
989 LPWINE_MLD wmld;
991 TRACE("(%04X, %p, %d)\n", hMidiIn, lpsegMidiInHdr, uSize);
993 if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
994 return MMSYSERR_INVALHANDLE;
996 return MMDRV_Message(wmld, MIDM_ADDBUFFER, (DWORD_PTR)lpsegMidiInHdr, uSize, FALSE);
999 /**************************************************************************
1000 * midiInStart [MMSYSTEM.309]
1002 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
1004 return midiInStart(HMIDIIN_32(hMidiIn));
1007 /**************************************************************************
1008 * midiInStop [MMSYSTEM.310]
1010 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
1012 return midiInStop(HMIDIIN_32(hMidiIn));
1015 /**************************************************************************
1016 * midiInReset [MMSYSTEM.311]
1018 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
1020 return midiInReset(HMIDIIN_32(hMidiIn));
1023 /**************************************************************************
1024 * midiInGetID [MMSYSTEM.312]
1026 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
1028 UINT devid;
1029 UINT16 ret;
1031 ret = midiInGetID(HMIDIIN_32(hMidiIn), &devid);
1032 if (ret != MMSYSERR_NOERROR) return ret;
1033 *lpuDeviceID = devid;
1034 return ret;
1037 /**************************************************************************
1038 * midiInMessage [MMSYSTEM.313]
1040 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
1041 DWORD dwParam1, DWORD dwParam2)
1043 LPWINE_MLD wmld;
1045 TRACE("(%04X, %04X, %08X, %08X)\n", hMidiIn, uMessage, dwParam1, dwParam2);
1047 switch (uMessage) {
1048 case MIDM_OPEN:
1049 case MIDM_CLOSE:
1050 FIXME("can't handle OPEN or CLOSE message!\n");
1051 return MMSYSERR_NOTSUPPORTED;
1053 case MIDM_GETDEVCAPS:
1054 return midiInGetDevCaps16(hMidiIn, MapSL(dwParam1), dwParam2);
1055 case MIDM_PREPARE:
1056 return midiInPrepareHeader16(hMidiIn, dwParam1, dwParam2);
1057 case MIDM_UNPREPARE:
1058 return midiInUnprepareHeader16(hMidiIn, dwParam1, dwParam2);
1059 case MIDM_ADDBUFFER:
1060 return midiInAddBuffer16(hMidiIn, MapSL(dwParam1), dwParam2);
1063 if ((wmld = MMDRV_Get(HMIDIIN_32(hMidiIn), MMDRV_MIDIIN, FALSE)) == NULL)
1064 return MMSYSERR_INVALHANDLE;
1066 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1069 /**************************************************************************
1070 * midiStreamClose [MMSYSTEM.252]
1072 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hMidiStrm)
1074 return midiStreamClose(HMIDISTRM_32(hMidiStrm));
1077 /**************************************************************************
1078 * midiStreamOpen [MMSYSTEM.251]
1080 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
1081 DWORD cMidi, DWORD dwCallback,
1082 DWORD dwInstance, DWORD fdwOpen)
1084 HMIDISTRM hMidiStrm32;
1085 MMRESULT ret;
1086 UINT devid32;
1088 if (!phMidiStrm || !devid)
1089 return MMSYSERR_INVALPARAM;
1090 devid32 = *devid;
1091 ret = MIDI_StreamOpen(&hMidiStrm32, &devid32, cMidi, dwCallback,
1092 dwInstance, fdwOpen, FALSE);
1093 *phMidiStrm = HMIDISTRM_16(hMidiStrm32);
1094 *devid = devid32;
1095 return ret;
1098 /**************************************************************************
1099 * midiStreamOut [MMSYSTEM.254]
1101 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hMidiStrm, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
1103 return midiStreamOut(HMIDISTRM_32(hMidiStrm), (LPMIDIHDR)lpMidiHdr,
1104 cbMidiHdr);
1107 /**************************************************************************
1108 * midiStreamPause [MMSYSTEM.255]
1110 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hMidiStrm)
1112 return midiStreamPause(HMIDISTRM_32(hMidiStrm));
1115 /**************************************************************************
1116 * midiStreamPosition [MMSYSTEM.253]
1118 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hMidiStrm, LPMMTIME16 lpmmt16, UINT16 cbmmt)
1120 MMTIME mmt32;
1121 MMRESULT ret;
1123 if (!lpmmt16)
1124 return MMSYSERR_INVALPARAM;
1125 MMSYSTEM_MMTIME16to32(&mmt32, lpmmt16);
1126 ret = midiStreamPosition(HMIDISTRM_32(hMidiStrm), &mmt32, sizeof(MMTIME));
1127 MMSYSTEM_MMTIME32to16(lpmmt16, &mmt32);
1128 return ret;
1131 /**************************************************************************
1132 * midiStreamProperty [MMSYSTEM.250]
1134 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hMidiStrm, LPBYTE lpPropData, DWORD dwProperty)
1136 return midiStreamProperty(HMIDISTRM_32(hMidiStrm), lpPropData, dwProperty);
1139 /**************************************************************************
1140 * midiStreamRestart [MMSYSTEM.256]
1142 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hMidiStrm)
1144 return midiStreamRestart(HMIDISTRM_32(hMidiStrm));
1147 /**************************************************************************
1148 * midiStreamStop [MMSYSTEM.257]
1150 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hMidiStrm)
1152 return midiStreamStop(HMIDISTRM_32(hMidiStrm));
1155 /* ###################################################
1156 * # WAVE #
1157 * ###################################################
1160 /**************************************************************************
1161 * waveOutGetNumDevs [MMSYSTEM.401]
1163 UINT16 WINAPI waveOutGetNumDevs16(void)
1165 return waveOutGetNumDevs();
1168 /**************************************************************************
1169 * waveOutGetDevCaps [MMSYSTEM.402]
1171 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID,
1172 LPWAVEOUTCAPS16 lpCaps, UINT16 uSize)
1174 WAVEOUTCAPSA wocA;
1175 UINT ret;
1176 TRACE("(%u %p %u)!\n", uDeviceID, lpCaps, uSize);
1178 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1180 ret = waveOutGetDevCapsA(uDeviceID, &wocA, sizeof(wocA));
1181 if (ret == MMSYSERR_NOERROR) {
1182 WAVEOUTCAPS16 woc16;
1183 woc16.wMid = wocA.wMid;
1184 woc16.wPid = wocA.wPid;
1185 woc16.vDriverVersion = wocA.vDriverVersion;
1186 strcpy(woc16.szPname, wocA.szPname);
1187 woc16.dwFormats = wocA.dwFormats;
1188 woc16.wChannels = wocA.wChannels;
1189 woc16.dwSupport = wocA.dwSupport;
1190 memcpy(lpCaps, &woc16, min(uSize, sizeof(woc16)));
1192 return ret;
1195 /**************************************************************************
1196 * waveOutGetErrorText [MMSYSTEM.403]
1197 * waveInGetErrorText [MMSYSTEM.503]
1199 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1201 return waveOutGetErrorTextA(uError, lpText, uSize);
1204 /**************************************************************************
1205 * waveOutOpen [MMSYSTEM.404]
1207 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
1208 LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1209 DWORD dwInstance, DWORD dwFlags)
1211 HANDLE hWaveOut;
1212 UINT ret;
1214 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1215 * call the 32 bit version
1216 * however, we need to promote correctly the wave mapper id
1217 * (0xFFFFFFFF and not 0x0000FFFF)
1219 ret = WAVE_Open(&hWaveOut, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1220 MMDRV_WAVEOUT, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1222 if (lphWaveOut != NULL) *lphWaveOut = HWAVEOUT_16(hWaveOut);
1223 return ret;
1226 /**************************************************************************
1227 * waveOutClose [MMSYSTEM.405]
1229 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
1231 DWORD level;
1232 UINT16 ret;
1234 ReleaseThunkLock(&level);
1235 ret = waveOutClose(HWAVEOUT_32(hWaveOut));
1236 RestoreThunkLock(level);
1237 return ret;
1240 /**************************************************************************
1241 * waveOutPrepareHeader [MMSYSTEM.406]
1243 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut, /* [in] */
1244 SEGPTR lpsegWaveOutHdr, /* [???] */
1245 UINT16 uSize) /* [in] */
1247 LPWINE_MLD wmld;
1248 LPWAVEHDR lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1249 UINT16 result;
1251 TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1253 if (lpWaveOutHdr == NULL) return MMSYSERR_INVALPARAM;
1255 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1256 return MMSYSERR_INVALHANDLE;
1258 if ((result = MMDRV_Message(wmld, WODM_PREPARE, lpsegWaveOutHdr,
1259 uSize, FALSE)) != MMSYSERR_NOTSUPPORTED)
1260 return result;
1262 if (lpWaveOutHdr->dwFlags & WHDR_INQUEUE)
1263 return WAVERR_STILLPLAYING;
1265 lpWaveOutHdr->dwFlags |= WHDR_PREPARED;
1266 lpWaveOutHdr->dwFlags &= ~WHDR_DONE;
1268 return MMSYSERR_NOERROR;
1271 /**************************************************************************
1272 * waveOutUnprepareHeader [MMSYSTEM.407]
1274 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut, /* [in] */
1275 SEGPTR lpsegWaveOutHdr, /* [???] */
1276 UINT16 uSize) /* [in] */
1278 LPWINE_MLD wmld;
1279 LPWAVEHDR lpWaveOutHdr = MapSL(lpsegWaveOutHdr);
1281 TRACE("(%04X, %08x, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1283 if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
1284 return MMSYSERR_NOERROR;
1287 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1288 return MMSYSERR_INVALHANDLE;
1290 return MMDRV_Message(wmld, WODM_UNPREPARE, lpsegWaveOutHdr, uSize, FALSE);
1293 /**************************************************************************
1294 * waveOutWrite [MMSYSTEM.408]
1296 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut, /* [in] */
1297 LPWAVEHDR lpsegWaveOutHdr, /* [???] NOTE: SEGPTR */
1298 UINT16 uSize) /* [in] */
1300 LPWINE_MLD wmld;
1302 TRACE("(%04X, %p, %u);\n", hWaveOut, lpsegWaveOutHdr, uSize);
1304 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL)
1305 return MMSYSERR_INVALHANDLE;
1307 return MMDRV_Message(wmld, WODM_WRITE, (DWORD_PTR)lpsegWaveOutHdr, uSize, FALSE);
1310 /**************************************************************************
1311 * waveOutBreakLoop [MMSYSTEM.419]
1313 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut16)
1315 DWORD level;
1316 UINT16 ret;
1318 ReleaseThunkLock(&level);
1319 ret = waveOutBreakLoop(HWAVEOUT_32(hWaveOut16));
1320 RestoreThunkLock(level);
1321 return ret;
1324 /**************************************************************************
1325 * waveOutPause [MMSYSTEM.409]
1327 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut16)
1329 DWORD level;
1330 UINT16 ret;
1332 ReleaseThunkLock(&level);
1333 ret = waveOutPause(HWAVEOUT_32(hWaveOut16));
1334 RestoreThunkLock(level);
1335 return ret;
1338 /**************************************************************************
1339 * waveOutReset [MMSYSTEM.411]
1341 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut16)
1343 DWORD level;
1344 UINT16 ret;
1346 ReleaseThunkLock(&level);
1347 ret = waveOutReset(HWAVEOUT_32(hWaveOut16));
1348 RestoreThunkLock(level);
1349 return ret;
1352 /**************************************************************************
1353 * waveOutRestart [MMSYSTEM.410]
1355 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut16)
1357 DWORD level;
1358 UINT16 ret;
1360 ReleaseThunkLock(&level);
1361 ret = waveOutRestart(HWAVEOUT_32(hWaveOut16));
1362 RestoreThunkLock(level);
1363 return ret;
1366 /**************************************************************************
1367 * waveOutGetPosition [MMSYSTEM.412]
1369 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
1370 UINT16 uSize)
1372 UINT ret;
1373 MMTIME mmt;
1375 mmt.wType = lpTime->wType;
1376 ret = waveOutGetPosition(HWAVEOUT_32(hWaveOut), &mmt, sizeof(mmt));
1377 MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1378 return ret;
1381 /**************************************************************************
1382 * waveOutGetPitch [MMSYSTEM.413]
1384 UINT16 WINAPI waveOutGetPitch16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1386 return waveOutGetPitch(HWAVEOUT_32(hWaveOut16), lpdw);
1389 /**************************************************************************
1390 * waveOutSetPitch [MMSYSTEM.414]
1392 UINT16 WINAPI waveOutSetPitch16(HWAVEOUT16 hWaveOut16, DWORD dw)
1394 return waveOutSetPitch(HWAVEOUT_32(hWaveOut16), dw);
1397 /**************************************************************************
1398 * waveOutGetPlaybackRate [MMSYSTEM.417]
1400 UINT16 WINAPI waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16, LPDWORD lpdw)
1402 return waveOutGetPlaybackRate(HWAVEOUT_32(hWaveOut16), lpdw);
1405 /**************************************************************************
1406 * waveOutSetPlaybackRate [MMSYSTEM.418]
1408 UINT16 WINAPI waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16, DWORD dw)
1410 return waveOutSetPlaybackRate(HWAVEOUT_32(hWaveOut16), dw);
1413 /**************************************************************************
1414 * waveOutGetVolume [MMSYSTEM.415]
1416 UINT16 WINAPI waveOutGetVolume16(UINT16 devid, LPDWORD lpdw)
1418 return waveOutGetVolume(HWAVEOUT_32(devid), lpdw);
1421 /**************************************************************************
1422 * waveOutSetVolume [MMSYSTEM.416]
1424 UINT16 WINAPI waveOutSetVolume16(UINT16 devid, DWORD dw)
1426 return waveOutSetVolume(HWAVEOUT_32(devid), dw);
1429 /**************************************************************************
1430 * waveOutGetID [MMSYSTEM.420]
1432 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
1434 UINT devid;
1435 UINT16 ret;
1437 ret = waveOutGetID(HWAVEOUT_32(hWaveOut), &devid);
1438 if (ret != MMSYSERR_NOERROR) return ret;
1439 *lpuDeviceID = devid;
1440 return ret;
1443 /**************************************************************************
1444 * waveOutMessage [MMSYSTEM.421]
1446 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
1447 DWORD dwParam1, DWORD dwParam2)
1449 LPWINE_MLD wmld;
1451 TRACE("(%04x, %u, %d, %d)\n", hWaveOut, uMessage, dwParam1, dwParam2);
1453 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, FALSE)) == NULL) {
1454 if ((wmld = MMDRV_Get(HWAVEOUT_32(hWaveOut), MMDRV_WAVEOUT, TRUE)) != NULL) {
1455 if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1456 dwParam1 = (DWORD)MapSL(dwParam1);
1457 return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1459 return MMSYSERR_INVALHANDLE;
1462 /* from M$ KB */
1463 if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1464 return MMSYSERR_INVALPARAM;
1466 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1469 /**************************************************************************
1470 * waveInGetNumDevs [MMSYSTEM.501]
1472 UINT16 WINAPI waveInGetNumDevs16(void)
1474 return waveInGetNumDevs();
1477 /**************************************************************************
1478 * waveInGetDevCaps [MMSYSTEM.502]
1480 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps,
1481 UINT16 uSize)
1483 WAVEINCAPSA wicA;
1484 UINT ret;
1486 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
1488 ret = waveInGetDevCapsA(uDeviceID, &wicA, sizeof(wicA));
1489 if (ret == MMSYSERR_NOERROR) {
1490 WAVEINCAPS16 wic16;
1491 wic16.wMid = wicA.wMid;
1492 wic16.wPid = wicA.wPid;
1493 wic16.vDriverVersion = wicA.vDriverVersion;
1494 strcpy(wic16.szPname, wicA.szPname);
1495 wic16.dwFormats = wicA.dwFormats;
1496 wic16.wChannels = wicA.wChannels;
1497 memcpy(lpCaps, &wic16, min(uSize, sizeof(wic16)));
1499 return ret;
1502 /**************************************************************************
1503 * waveInOpen [MMSYSTEM.504]
1505 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
1506 LPCWAVEFORMATEX lpFormat, DWORD dwCallback,
1507 DWORD dwInstance, DWORD dwFlags)
1509 HANDLE hWaveIn;
1510 UINT ret;
1512 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
1513 * call the 32 bit version
1514 * however, we need to promote correctly the wave mapper id
1515 * (0xFFFFFFFF and not 0x0000FFFF)
1517 ret = WAVE_Open(&hWaveIn, (uDeviceID == (UINT16)-1) ? (UINT)-1 : uDeviceID,
1518 MMDRV_WAVEIN, lpFormat, dwCallback, dwInstance, dwFlags, FALSE);
1520 if (lphWaveIn != NULL) *lphWaveIn = HWAVEIN_16(hWaveIn);
1521 return ret;
1524 /**************************************************************************
1525 * waveInClose [MMSYSTEM.505]
1527 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
1529 DWORD level;
1530 UINT16 ret;
1532 ReleaseThunkLock(&level);
1533 ret = waveInClose(HWAVEIN_32(hWaveIn));
1534 RestoreThunkLock(level);
1535 return ret;
1538 /**************************************************************************
1539 * waveInPrepareHeader [MMSYSTEM.506]
1541 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn, /* [in] */
1542 SEGPTR lpsegWaveInHdr, /* [???] */
1543 UINT16 uSize) /* [in] */
1545 LPWINE_MLD wmld;
1546 LPWAVEHDR lpWaveInHdr = MapSL(lpsegWaveInHdr);
1547 UINT16 ret;
1549 TRACE("(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
1551 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
1552 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1553 return MMSYSERR_INVALHANDLE;
1555 lpWaveInHdr->dwBytesRecorded = 0;
1557 ret = MMDRV_Message(wmld, WIDM_PREPARE, lpsegWaveInHdr, uSize, FALSE);
1558 return ret;
1561 /**************************************************************************
1562 * waveInUnprepareHeader [MMSYSTEM.507]
1564 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn, /* [in] */
1565 SEGPTR lpsegWaveInHdr, /* [???] */
1566 UINT16 uSize) /* [in] */
1568 LPWINE_MLD wmld;
1569 LPWAVEHDR lpWaveInHdr = MapSL(lpsegWaveInHdr);
1571 TRACE("(%04X, %08x, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1573 if (lpWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1575 if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED)) {
1576 return MMSYSERR_NOERROR;
1579 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1580 return MMSYSERR_INVALHANDLE;
1582 return MMDRV_Message(wmld, WIDM_UNPREPARE, lpsegWaveInHdr, uSize, FALSE);
1585 /**************************************************************************
1586 * waveInAddBuffer [MMSYSTEM.508]
1588 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn, /* [in] */
1589 WAVEHDR* lpsegWaveInHdr, /* [???] NOTE: SEGPTR */
1590 UINT16 uSize) /* [in] */
1592 LPWINE_MLD wmld;
1594 TRACE("(%04X, %p, %u);\n", hWaveIn, lpsegWaveInHdr, uSize);
1596 if (lpsegWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
1597 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL)
1598 return MMSYSERR_INVALHANDLE;
1600 return MMDRV_Message(wmld, WIDM_ADDBUFFER, (DWORD_PTR)lpsegWaveInHdr, uSize, FALSE);
1603 /**************************************************************************
1604 * waveInReset [MMSYSTEM.511]
1606 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn16)
1608 DWORD level;
1609 UINT16 ret;
1611 ReleaseThunkLock(&level);
1612 ret = waveInReset(HWAVEIN_32(hWaveIn16));
1613 RestoreThunkLock(level);
1614 return ret;
1617 /**************************************************************************
1618 * waveInStart [MMSYSTEM.509]
1620 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn16)
1622 DWORD level;
1623 UINT16 ret;
1625 ReleaseThunkLock(&level);
1626 ret = waveInStart(HWAVEIN_32(hWaveIn16));
1627 RestoreThunkLock(level);
1628 return ret;
1631 /**************************************************************************
1632 * waveInStop [MMSYSTEM.510]
1634 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn16)
1636 DWORD level;
1637 UINT16 ret;
1639 ReleaseThunkLock(&level);
1640 ret = waveInStop(HWAVEIN_32(hWaveIn16));
1641 RestoreThunkLock(level);
1642 return ret;
1645 /**************************************************************************
1646 * waveInGetPosition [MMSYSTEM.512]
1648 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
1649 UINT16 uSize)
1651 UINT ret;
1652 MMTIME mmt;
1654 mmt.wType = lpTime->wType;
1655 ret = waveInGetPosition(HWAVEIN_32(hWaveIn), &mmt, sizeof(mmt));
1656 MMSYSTEM_MMTIME32to16(lpTime, &mmt);
1657 return ret;
1660 /**************************************************************************
1661 * waveInGetID [MMSYSTEM.513]
1663 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
1665 UINT devid;
1666 UINT16 ret;
1668 ret = waveInGetID(HWAVEIN_32(hWaveIn), &devid);
1669 if (ret != MMSYSERR_NOERROR) return ret;
1670 *lpuDeviceID = devid;
1671 return ret;
1674 /**************************************************************************
1675 * waveInMessage [MMSYSTEM.514]
1677 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
1678 DWORD dwParam1, DWORD dwParam2)
1680 LPWINE_MLD wmld;
1682 TRACE("(%04x, %u, %d, %d)\n", hWaveIn, uMessage, dwParam1, dwParam2);
1684 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, FALSE)) == NULL) {
1685 if ((wmld = MMDRV_Get(HWAVEIN_32(hWaveIn), MMDRV_WAVEIN, TRUE)) != NULL) {
1686 if (uMessage == DRV_QUERYDRVENTRY || uMessage == DRV_QUERYDEVNODE)
1687 dwParam1 = (DWORD)MapSL(dwParam1);
1688 return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
1690 return MMSYSERR_INVALHANDLE;
1693 /* from M$ KB */
1694 if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
1695 return MMSYSERR_INVALPARAM;
1697 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2, FALSE);
1700 /* ###################################################
1701 * # TASK #
1702 * ###################################################
1705 /*#define USE_MM_TSK_WINE*/
1707 /**************************************************************************
1708 * mmTaskCreate [MMSYSTEM.900]
1710 * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
1711 * called upon creation with dwPmt as parameter.
1713 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR spProc, HINSTANCE16 *lphMmTask, DWORD dwPmt)
1715 HINSTANCE16 ret;
1716 HINSTANCE16 handle;
1717 char cmdline[16];
1718 DWORD showCmd = 0x40002;
1719 LOADPARAMS16 lp;
1721 TRACE("(%08x, %p, %08x);\n", spProc, lphMmTask, dwPmt);
1722 /* This to work requires NE modules to be started with a binary command line
1723 * which is not currently the case. A patch exists but has never been committed.
1724 * A workaround would be to integrate code for mmtask.tsk into Wine, but
1725 * this requires tremendous work (starting with patching tools/build to
1726 * create NE executables (and not only DLLs) for builtins modules.
1727 * EP 99/04/25
1729 FIXME("This is currently broken. It will fail\n");
1731 cmdline[0] = 0x0d;
1732 *(LPDWORD)(cmdline + 1) = (DWORD)spProc;
1733 *(LPDWORD)(cmdline + 5) = dwPmt;
1734 *(LPDWORD)(cmdline + 9) = 0;
1736 lp.hEnvironment = 0;
1737 lp.cmdLine = MapLS(cmdline);
1738 lp.showCmd = MapLS(&showCmd);
1739 lp.reserved = 0;
1741 #ifndef USE_MM_TSK_WINE
1742 handle = LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp);
1743 #else
1744 handle = LoadModule16("mmtask.tsk", &lp);
1745 #endif
1746 if (handle < 32) {
1747 ret = (handle) ? 1 : 2;
1748 handle = 0;
1749 } else {
1750 ret = 0;
1752 if (lphMmTask)
1753 *lphMmTask = handle;
1755 UnMapLS( lp.cmdLine );
1756 UnMapLS( lp.showCmd );
1757 TRACE("=> 0x%04x/%d\n", handle, ret);
1758 return ret;
1761 #ifdef USE_MM_TSK_WINE
1762 /* C equivalent to mmtask.tsk binary content */
1763 void mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
1765 int len = cmdLine[0x80];
1767 if (len / 2 == 6) {
1768 void (*fpProc)(DWORD) = MapSL(*((DWORD*)(cmdLine + 1)));
1769 DWORD dwPmt = *((DWORD*)(cmdLine + 5));
1771 #if 0
1772 InitTask16(); /* FIXME: pmts / from context ? */
1773 InitApp(di);
1774 #endif
1775 if (SetMessageQueue16(0x40)) {
1776 WaitEvent16(0);
1777 if (HIWORD(fpProc)) {
1778 OldYield16();
1779 /* EPP StackEnter16(); */
1780 (fpProc)(dwPmt);
1784 OldYield16();
1785 OldYield16();
1786 OldYield16();
1787 ExitProcess(0);
1789 #endif
1791 /**************************************************************************
1792 * mmTaskBlock [MMSYSTEM.902]
1794 void WINAPI mmTaskBlock16(HINSTANCE16 hInst)
1796 MSG msg;
1798 do {
1799 GetMessageA(&msg, 0, 0, 0);
1800 if (msg.hwnd) {
1801 TranslateMessage(&msg);
1802 DispatchMessageA(&msg);
1804 } while (msg.message < 0x3A0);
1807 /**************************************************************************
1808 * mmTaskSignal [MMSYSTEM.903]
1810 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
1812 TRACE("(%04x);\n", ht);
1813 return PostThreadMessageW( HTASK_32(ht), WM_USER, 0, 0 );
1816 /**************************************************************************
1817 * mmGetCurrentTask [MMSYSTEM.904]
1819 HTASK16 WINAPI mmGetCurrentTask16(void)
1821 return GetCurrentTask();
1824 /**************************************************************************
1825 * mmTaskYield [MMSYSTEM.905]
1827 void WINAPI mmTaskYield16(void)
1829 MSG msg;
1831 if (PeekMessageA(&msg, 0, 0, 0, 0)) {
1832 WOWYield16();
1836 extern DWORD WINAPI GetProcessFlags(DWORD);
1838 /******************************************************************
1839 * WINMM_GetmmThread
1843 static WINE_MMTHREAD* WINMM_GetmmThread(HANDLE16 h)
1845 return MapSL(MAKESEGPTR(h, 0));
1848 DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID);
1850 /**************************************************************************
1851 * mmThreadCreate [MMSYSTEM.1120]
1853 * undocumented
1854 * Creates a MM thread, calling fpThreadAddr(dwPmt).
1855 * dwFlags:
1856 * bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
1857 * bit.1 set means to open a VxD for this thread (unsupported)
1859 LRESULT WINAPI mmThreadCreate16(FARPROC16 fpThreadAddr, LPHANDLE16 lpHndl, DWORD dwPmt, DWORD dwFlags)
1861 HANDLE16 hndl;
1862 LRESULT ret;
1864 TRACE("(%p, %p, %08x, %08x)!\n", fpThreadAddr, lpHndl, dwPmt, dwFlags);
1866 hndl = GlobalAlloc16(sizeof(WINE_MMTHREAD), GMEM_SHARE|GMEM_ZEROINIT);
1868 if (hndl == 0) {
1869 ret = 2;
1870 } else {
1871 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1873 #if 0
1874 /* force mmtask routines even if mmthread is required */
1875 /* this will work only if the patch about binary cmd line and NE tasks
1876 * is committed
1878 dwFlags |= 1;
1879 #endif
1881 lpMMThd->dwSignature = WINE_MMTHREAD_CREATED;
1882 lpMMThd->dwCounter = 0;
1883 lpMMThd->hThread = 0;
1884 lpMMThd->dwThreadID = 0;
1885 lpMMThd->fpThread = (DWORD)fpThreadAddr;
1886 lpMMThd->dwThreadPmt = dwPmt;
1887 lpMMThd->dwSignalCount = 0;
1888 lpMMThd->hEvent = 0;
1889 lpMMThd->hVxD = 0;
1890 lpMMThd->dwStatus = 0;
1891 lpMMThd->dwFlags = dwFlags;
1892 lpMMThd->hTask = 0;
1894 if ((dwFlags & 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
1895 lpMMThd->hEvent = CreateEventW(NULL, FALSE, TRUE, NULL);
1897 TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd);
1898 if (lpMMThd->dwFlags & 2) {
1899 /* as long as we don't support MM VxD in wine, we don't need
1900 * to care about this flag
1902 /* FIXME("Don't know how to properly open VxD handles\n"); */
1903 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
1906 lpMMThd->hThread = CreateThread(0, 0, WINE_mmThreadEntryPoint,
1907 (LPVOID)(DWORD_PTR)hndl, CREATE_SUSPENDED, &lpMMThd->dwThreadID);
1908 if (lpMMThd->hThread == 0) {
1909 WARN("Couldn't create thread\n");
1910 /* clean-up(VxDhandle...); devicedirectio... */
1911 if (lpMMThd->hEvent != 0)
1912 CloseHandle(lpMMThd->hEvent);
1913 ret = 2;
1914 } else {
1915 SetThreadPriority(lpMMThd->hThread, THREAD_PRIORITY_TIME_CRITICAL);
1916 TRACE("Got a nice thread hndl=%p id=0x%08x\n", lpMMThd->hThread, lpMMThd->dwThreadID);
1917 ret = 0;
1919 } else {
1920 /* get WINE_mmThreadEntryPoint()
1921 * 2047 is its ordinal in mmsystem.spec
1923 FARPROC16 fp = GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR)2047);
1925 TRACE("farproc seg=0x%p lin=%p\n", fp, MapSL((SEGPTR)fp));
1927 ret = (fp == 0) ? 2 : mmTaskCreate16((DWORD)fp, 0, hndl);
1930 if (ret == 0) {
1931 if (lpMMThd->hThread && !ResumeThread(lpMMThd->hThread))
1932 WARN("Couldn't resume thread\n");
1934 while (lpMMThd->dwStatus != 0x10) { /* test also HIWORD of dwStatus */
1935 UserYield16();
1940 if (ret != 0) {
1941 GlobalFree16(hndl);
1942 hndl = 0;
1945 if (lpHndl)
1946 *lpHndl = hndl;
1948 TRACE("ok => %ld\n", ret);
1949 return ret;
1952 /**************************************************************************
1953 * mmThreadSignal [MMSYSTEM.1121]
1955 void WINAPI mmThreadSignal16(HANDLE16 hndl)
1957 TRACE("(%04x)!\n", hndl);
1959 if (hndl) {
1960 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
1962 lpMMThd->dwCounter++;
1963 if (lpMMThd->hThread != 0) {
1964 InterlockedIncrement(&lpMMThd->dwSignalCount);
1965 SetEvent(lpMMThd->hEvent);
1966 } else {
1967 mmTaskSignal16(lpMMThd->hTask);
1969 lpMMThd->dwCounter--;
1973 static void MMSYSTEM_ThreadBlock(WINE_MMTHREAD* lpMMThd)
1975 MSG msg;
1976 DWORD ret;
1978 if (lpMMThd->dwThreadID != GetCurrentThreadId())
1979 ERR("Not called by thread itself\n");
1981 for (;;) {
1982 ResetEvent(lpMMThd->hEvent);
1983 if (InterlockedDecrement(&lpMMThd->dwSignalCount) >= 0)
1984 break;
1985 InterlockedIncrement(&lpMMThd->dwSignalCount);
1987 TRACE("S1\n");
1989 ret = MsgWaitForMultipleObjects(1, &lpMMThd->hEvent, FALSE, INFINITE, QS_ALLINPUT);
1990 switch (ret) {
1991 case WAIT_OBJECT_0: /* Event */
1992 TRACE("S2.1\n");
1993 break;
1994 case WAIT_OBJECT_0 + 1: /* Msg */
1995 TRACE("S2.2\n");
1996 if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
1997 TranslateMessage(&msg);
1998 DispatchMessageA(&msg);
2000 break;
2001 default:
2002 WARN("S2.x unsupported ret val 0x%08x\n", ret);
2004 TRACE("S3\n");
2008 /**************************************************************************
2009 * mmThreadBlock [MMSYSTEM.1122]
2011 void WINAPI mmThreadBlock16(HANDLE16 hndl)
2013 TRACE("(%04x)!\n", hndl);
2015 if (hndl) {
2016 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2018 if (lpMMThd->hThread != 0) {
2019 DWORD lc;
2021 ReleaseThunkLock(&lc);
2022 MMSYSTEM_ThreadBlock(lpMMThd);
2023 RestoreThunkLock(lc);
2024 } else {
2025 mmTaskBlock16(lpMMThd->hTask);
2028 TRACE("done\n");
2031 /**************************************************************************
2032 * mmThreadIsCurrent [MMSYSTEM.1123]
2034 BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hndl)
2036 BOOL16 ret = FALSE;
2038 TRACE("(%04x)!\n", hndl);
2040 if (hndl && mmThreadIsValid16(hndl)) {
2041 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2042 ret = (GetCurrentThreadId() == lpMMThd->dwThreadID);
2044 TRACE("=> %d\n", ret);
2045 return ret;
2048 /**************************************************************************
2049 * mmThreadIsValid [MMSYSTEM.1124]
2051 BOOL16 WINAPI mmThreadIsValid16(HANDLE16 hndl)
2053 BOOL16 ret = FALSE;
2055 TRACE("(%04x)!\n", hndl);
2057 if (hndl) {
2058 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2060 if (!IsBadWritePtr(lpMMThd, sizeof(WINE_MMTHREAD)) &&
2061 lpMMThd->dwSignature == WINE_MMTHREAD_CREATED &&
2062 IsTask16(lpMMThd->hTask)) {
2063 lpMMThd->dwCounter++;
2064 if (lpMMThd->hThread != 0) {
2065 DWORD dwThreadRet;
2066 if (GetExitCodeThread(lpMMThd->hThread, &dwThreadRet) &&
2067 dwThreadRet == STATUS_PENDING) {
2068 ret = TRUE;
2070 } else {
2071 ret = TRUE;
2073 lpMMThd->dwCounter--;
2076 TRACE("=> %d\n", ret);
2077 return ret;
2080 /**************************************************************************
2081 * mmThreadGetTask [MMSYSTEM.1125]
2083 HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
2085 HANDLE16 ret = 0;
2087 TRACE("(%04x)\n", hndl);
2089 if (mmThreadIsValid16(hndl)) {
2090 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2091 ret = lpMMThd->hTask;
2093 return ret;
2096 /**************************************************************************
2097 * __wine_mmThreadEntryPoint (MMSYSTEM.2047)
2099 DWORD WINAPI WINE_mmThreadEntryPoint(LPVOID p)
2101 HANDLE16 hndl = (HANDLE16)(DWORD_PTR)p;
2102 WINE_MMTHREAD* lpMMThd = WINMM_GetmmThread(hndl);
2104 TRACE("(%04x %p)\n", hndl, lpMMThd);
2106 lpMMThd->hTask = LOWORD(GetCurrentTask());
2107 TRACE("[10-%p] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
2108 lpMMThd->dwStatus = 0x10;
2109 MMSYSTEM_ThreadBlock(lpMMThd);
2110 TRACE("[20-%p]\n", lpMMThd->hThread);
2111 lpMMThd->dwStatus = 0x20;
2112 if (lpMMThd->fpThread) {
2113 WOWCallback16(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
2115 lpMMThd->dwStatus = 0x30;
2116 TRACE("[30-%p]\n", lpMMThd->hThread);
2117 while (lpMMThd->dwCounter) {
2118 Sleep(1);
2119 /* WOWYield16();*/
2121 TRACE("[XX-%p]\n", lpMMThd->hThread);
2122 /* paranoia */
2123 lpMMThd->dwSignature = WINE_MMTHREAD_DELETED;
2124 /* close lpMMThread->hVxD directIO */
2125 if (lpMMThd->hEvent)
2126 CloseHandle(lpMMThd->hEvent);
2127 GlobalFree16(hndl);
2128 TRACE("done\n");
2130 return 0;
2133 typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
2135 /**************************************************************************
2136 * mmShowMMCPLPropertySheet [MMSYSTEM.1150]
2138 BOOL16 WINAPI mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
2139 LPCSTR lpStrTab, LPCSTR lpStrTitle)
2141 HANDLE hndl;
2142 BOOL16 ret = FALSE;
2144 TRACE("(%p \"%s\" \"%s\" \"%s\")\n", hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2146 hndl = LoadLibraryA("MMSYS.CPL");
2147 if (hndl != 0) {
2148 MMCPLCALLBACK fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
2149 if (fp != NULL) {
2150 DWORD lc;
2151 ReleaseThunkLock(&lc);
2152 ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
2153 RestoreThunkLock(lc);
2155 FreeLibrary(hndl);
2158 return ret;
2161 /**************************************************************************
2162 * StackEnter [MMSYSTEM.32]
2164 void WINAPI StackEnter16(void)
2166 #ifdef __i386__
2167 /* mmsystem.dll from Win 95 does only this: so does Wine */
2168 __asm__("stc");
2169 #endif
2172 /**************************************************************************
2173 * StackLeave [MMSYSTEM.33]
2175 void WINAPI StackLeave16(void)
2177 #ifdef __i386__
2178 /* mmsystem.dll from Win 95 does only this: so does Wine */
2179 __asm__("stc");
2180 #endif
2183 /**************************************************************************
2184 * WMMMidiRunOnce [MMSYSTEM.8]
2186 void WINAPI WMMMidiRunOnce16(void)
2188 FIXME("(), stub!\n");
2191 /* ###################################################
2192 * # DRIVER #
2193 * ###################################################
2196 /**************************************************************************
2197 * DRIVER_MapMsg32To16 [internal]
2199 * Map a 32 bit driver message to a 16 bit driver message.
2201 static WINMM_MapType DRIVER_MapMsg32To16(WORD wMsg, LPARAM *lParam1, LPARAM *lParam2)
2203 WINMM_MapType ret = WINMM_MAP_MSGERROR;
2205 switch (wMsg) {
2206 case DRV_LOAD:
2207 case DRV_ENABLE:
2208 case DRV_DISABLE:
2209 case DRV_FREE:
2210 case DRV_QUERYCONFIGURE:
2211 case DRV_REMOVE:
2212 case DRV_EXITSESSION:
2213 case DRV_EXITAPPLICATION:
2214 case DRV_POWER:
2215 case DRV_CLOSE: /* should be 0/0 */
2216 case DRV_OPEN: /* pass through */
2217 /* lParam1 and lParam2 are not used */
2218 ret = WINMM_MAP_OK;
2219 break;
2220 case DRV_CONFIGURE:
2221 case DRV_INSTALL:
2222 /* lParam1 is a handle to a window (conf) or to a driver (inst) or not used,
2223 * lParam2 is a pointer to DRVCONFIGINFO
2225 if (*lParam2) {
2226 LPDRVCONFIGINFO16 dci16 = HeapAlloc( GetProcessHeap(), 0, sizeof(*dci16) );
2227 LPDRVCONFIGINFO dci32 = (LPDRVCONFIGINFO)(*lParam2);
2229 if (dci16) {
2230 LPSTR str1 = NULL,str2;
2231 INT len;
2232 dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
2234 if (dci32->lpszDCISectionName) {
2235 len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, NULL, 0, NULL, NULL );
2236 str1 = HeapAlloc( GetProcessHeap(), 0, len );
2237 if (str1) {
2238 WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCISectionName, -1, str1, len, NULL, NULL );
2239 dci16->lpszDCISectionName = MapLS( str1 );
2240 } else {
2241 HeapFree( GetProcessHeap(), 0, dci16);
2242 return WINMM_MAP_NOMEM;
2244 } else {
2245 dci16->lpszDCISectionName = 0L;
2247 if (dci32->lpszDCIAliasName) {
2248 len = WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, NULL, 0, NULL, NULL );
2249 str2 = HeapAlloc( GetProcessHeap(), 0, len );
2250 if (str2) {
2251 WideCharToMultiByte( CP_ACP, 0, dci32->lpszDCIAliasName, -1, str2, len, NULL, NULL );
2252 dci16->lpszDCIAliasName = MapLS( str2 );
2253 } else {
2254 HeapFree( GetProcessHeap(), 0, str1);
2255 HeapFree( GetProcessHeap(), 0, dci16);
2256 return WINMM_MAP_NOMEM;
2258 } else {
2259 dci16->lpszDCISectionName = 0L;
2261 } else {
2262 return WINMM_MAP_NOMEM;
2264 *lParam2 = MapLS( dci16 );
2265 ret = WINMM_MAP_OKMEM;
2266 } else {
2267 ret = WINMM_MAP_OK;
2269 break;
2270 default:
2271 if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2272 FIXME("Unknown message 0x%04x\n", wMsg);
2274 ret = WINMM_MAP_OK;
2276 return ret;
2279 /**************************************************************************
2280 * DRIVER_UnMapMsg32To16 [internal]
2282 * UnMap a 32 bit driver message to a 16 bit driver message.
2284 static WINMM_MapType DRIVER_UnMapMsg32To16(WORD wMsg, DWORD lParam1, DWORD lParam2)
2286 WINMM_MapType ret = WINMM_MAP_MSGERROR;
2288 switch (wMsg) {
2289 case DRV_LOAD:
2290 case DRV_ENABLE:
2291 case DRV_DISABLE:
2292 case DRV_FREE:
2293 case DRV_QUERYCONFIGURE:
2294 case DRV_REMOVE:
2295 case DRV_EXITSESSION:
2296 case DRV_EXITAPPLICATION:
2297 case DRV_POWER:
2298 case DRV_OPEN:
2299 case DRV_CLOSE:
2300 /* lParam1 and lParam2 are not used */
2301 break;
2302 case DRV_CONFIGURE:
2303 case DRV_INSTALL:
2304 /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
2305 if (lParam2) {
2306 LPDRVCONFIGINFO16 dci16 = MapSL(lParam2);
2307 HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCISectionName) );
2308 HeapFree( GetProcessHeap(), 0, MapSL(dci16->lpszDCIAliasName) );
2309 UnMapLS( lParam2 );
2310 UnMapLS( dci16->lpszDCISectionName );
2311 UnMapLS( dci16->lpszDCIAliasName );
2312 HeapFree( GetProcessHeap(), 0, dci16 );
2314 ret = WINMM_MAP_OK;
2315 break;
2316 default:
2317 if (!((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100))) {
2318 FIXME("Unknown message 0x%04x\n", wMsg);
2320 ret = WINMM_MAP_OK;
2322 return ret;
2325 /**************************************************************************
2326 * DRIVER_TryOpenDriver16 [internal]
2328 * Tries to load a 16 bit driver whose DLL's (module) name is lpFileName.
2330 static LPWINE_DRIVER DRIVER_OpenDriver16(LPCWSTR fn, LPCWSTR sn, LPARAM lParam2)
2332 LPWINE_DRIVER lpDrv = NULL;
2333 LPCSTR cause = NULL;
2334 LPSTR fnA = NULL, snA = NULL;
2335 unsigned len;
2337 TRACE("(%s, %s, %08lX);\n", debugstr_w(fn), debugstr_w(sn), lParam2);
2339 lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
2340 if (lpDrv == NULL) {cause = "OOM"; goto exit;}
2342 if (fn)
2344 len = WideCharToMultiByte( CP_ACP, 0, fn, -1, NULL, 0, NULL, NULL );
2345 fnA = HeapAlloc(GetProcessHeap(), 0, len);
2346 if (fnA == NULL) {cause = "OOM"; goto exit;}
2347 WideCharToMultiByte( CP_ACP, 0, fn, -1, fnA, len, NULL, NULL );
2350 if (sn)
2352 len = WideCharToMultiByte( CP_ACP, 0, sn, -1, NULL, 0, NULL, NULL );
2353 snA = HeapAlloc(GetProcessHeap(), 0, len);
2354 if (snA == NULL) {cause = "OOM"; goto exit;}
2355 WideCharToMultiByte( CP_ACP, 0, sn, -1, snA, len, NULL, NULL );
2358 /* FIXME: shall we do some black magic here on sn ?
2359 * drivers32 => drivers
2360 * mci32 => mci
2361 * ...
2363 lpDrv->d.d16.hDriver16 = OpenDriver16(fnA, snA, lParam2);
2364 if (lpDrv->d.d16.hDriver16 == 0) {cause = "Not a 16 bit driver"; goto exit;}
2365 lpDrv->dwFlags = WINE_GDF_16BIT;
2367 exit:
2368 HeapFree(GetProcessHeap(), 0, fnA);
2369 HeapFree(GetProcessHeap(), 0, snA);
2371 if (cause)
2373 TRACE("Unable to load 16 bit module %s[%s]: %s\n",
2374 debugstr_w(fn), debugstr_w(sn), cause);
2375 HeapFree(GetProcessHeap(), 0, lpDrv);
2376 return NULL;
2379 TRACE("=> %p\n", lpDrv);
2380 return lpDrv;
2383 /******************************************************************
2384 * DRIVER_SendMessage16
2388 static LRESULT DRIVER_SendMessage16(HDRVR16 hDrv16, UINT msg,
2389 LPARAM lParam1, LPARAM lParam2)
2391 LRESULT ret = 0;
2392 WINMM_MapType map;
2394 TRACE("Before sdm16 call hDrv=%04x wMsg=%04x p1=%08lx p2=%08lx\n",
2395 hDrv16, msg, lParam1, lParam2);
2397 switch (map = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2)) {
2398 case WINMM_MAP_OKMEM:
2399 case WINMM_MAP_OK:
2400 ret = SendDriverMessage16(hDrv16, msg, lParam1, lParam2);
2401 if (map == WINMM_MAP_OKMEM)
2402 DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
2403 default:
2404 break;
2406 return ret;
2409 /******************************************************************
2410 * DRIVER_CloseDriver16
2414 static LRESULT DRIVER_CloseDriver16(HDRVR16 hDrv16, LPARAM lParam1, LPARAM lParam2)
2416 return CloseDriver16(hDrv16, lParam1, lParam2);
2419 /**************************************************************************
2420 * DrvOpen [MMSYSTEM.1100]
2422 HDRVR16 WINAPI DrvOpen16(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
2424 return OpenDriver16(lpDriverName, lpSectionName, lParam);
2427 /**************************************************************************
2428 * DrvClose [MMSYSTEM.1101]
2430 LRESULT WINAPI DrvClose16(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
2432 return CloseDriver16(hDrv, lParam1, lParam2);
2435 /**************************************************************************
2436 * DrvSendMessage [MMSYSTEM.1102]
2438 LRESULT WINAPI DrvSendMessage16(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
2439 LPARAM lParam2)
2441 return SendDriverMessage16(hDrv, msg, lParam1, lParam2);
2444 /**************************************************************************
2445 * DrvGetModuleHandle [MMSYSTEM.1103]
2447 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
2449 return GetDriverModuleHandle16(hDrv);
2452 /**************************************************************************
2453 * DrvDefDriverProc [MMSYSTEM.1104]
2455 LRESULT WINAPI DrvDefDriverProc16(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
2456 DWORD dwParam1, DWORD dwParam2)
2458 return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
2461 /**************************************************************************
2462 * DriverProc [MMSYSTEM.6]
2464 LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
2465 DWORD dwParam1, DWORD dwParam2)
2467 TRACE("dwDevID=%08x hDrv=%04x wMsg=%04x dwParam1=%08x dwParam2=%08x\n",
2468 dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2470 return DrvDefDriverProc16(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
2473 /* ###################################################
2474 * # TIME #
2475 * ###################################################
2478 /******************************************************************
2479 * MMSYSTEM_MMTIME32to16
2483 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16, const MMTIME* mmt32)
2485 mmt16->wType = mmt32->wType;
2486 /* layout of rest is the same for 32/16,
2487 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2489 memcpy(&(mmt16->u), &(mmt32->u), sizeof(mmt16->u));
2492 /******************************************************************
2493 * MMSYSTEM_MMTIME16to32
2497 void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32, const MMTIME16* mmt16)
2499 mmt32->wType = mmt16->wType;
2500 /* layout of rest is the same for 32/16,
2501 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
2503 memcpy(&(mmt32->u), &(mmt16->u), sizeof(mmt16->u));
2506 /**************************************************************************
2507 * timeGetSystemTime [MMSYSTEM.601]
2509 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
2511 if (wSize >= sizeof(*lpTime)) {
2512 lpTime->wType = TIME_MS;
2513 lpTime->u.ms = GetTickCount();
2515 TRACE("=> %u\n", lpTime->u.ms);
2518 return 0;
2521 /**************************************************************************
2522 * timeSetEvent [MMSYSTEM.602]
2524 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol, LPTIMECALLBACK16 lpFunc,
2525 DWORD dwUser, UINT16 wFlags)
2527 if (wFlags & WINE_TIMER_IS32)
2528 WARN("Unknown windows flag... wine internally used.. ooch\n");
2530 return TIME_SetEventInternal(wDelay, wResol, (LPTIMECALLBACK)lpFunc,
2531 dwUser, wFlags & ~WINE_TIMER_IS32);
2534 /**************************************************************************
2535 * timeKillEvent [MMSYSTEM.603]
2537 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
2539 return timeKillEvent(wID);
2542 /**************************************************************************
2543 * timeGetDevCaps [MMSYSTEM.604]
2545 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
2547 TIMECAPS caps;
2548 MMRESULT ret;
2549 TRACE("(%p, %u) !\n", lpCaps, wSize);
2551 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2553 ret = timeGetDevCaps(&caps, sizeof(caps));
2554 if (ret == MMSYSERR_NOERROR) {
2555 TIMECAPS16 tc16;
2556 tc16.wPeriodMin = caps.wPeriodMin;
2557 tc16.wPeriodMax = caps.wPeriodMax;
2558 memcpy(lpCaps, &tc16, min(wSize, sizeof(tc16)));
2560 return ret;
2563 /**************************************************************************
2564 * timeBeginPeriod [MMSYSTEM.605]
2566 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
2568 TRACE("(%u) !\n", wPeriod);
2570 return timeBeginPeriod(wPeriod);
2573 /**************************************************************************
2574 * timeEndPeriod [MMSYSTEM.606]
2576 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
2578 TRACE("(%u) !\n", wPeriod);
2580 return timeEndPeriod(wPeriod);
2583 /**************************************************************************
2584 * mciSendString [MMSYSTEM.702]
2586 DWORD WINAPI mciSendString16(LPCSTR lpstrCommand, LPSTR lpstrRet,
2587 UINT16 uRetLen, HWND16 hwndCallback)
2589 return mciSendStringA(lpstrCommand, lpstrRet, uRetLen, HWND_32(hwndCallback));
2592 /**************************************************************************
2593 * mciLoadCommandResource [MMSYSTEM.705]
2595 UINT16 WINAPI mciLoadCommandResource16(HINSTANCE16 hInst, LPCSTR resname, UINT16 type)
2597 HRSRC16 res;
2598 HGLOBAL16 handle;
2599 const BYTE* ptr16;
2600 BYTE* ptr32;
2601 unsigned pos = 0, size = 1024, len;
2602 const char* str;
2603 DWORD flg;
2604 WORD eid;
2605 UINT16 ret = MCIERR_OUT_OF_MEMORY;
2607 if (!(res = FindResource16( hInst, resname, (LPSTR)RT_RCDATA))) return MCI_NO_COMMAND_TABLE;
2608 if (!(handle = LoadResource16( hInst, res ))) return MCI_NO_COMMAND_TABLE;
2609 ptr16 = LockResource16(handle);
2610 /* converting the 16 bit resource table into a 32W one */
2611 if ((ptr32 = HeapAlloc(GetProcessHeap(), 0, size)))
2613 do {
2614 str = (LPCSTR)ptr16;
2615 ptr16 += strlen(str) + 1;
2616 flg = *(const DWORD*)ptr16;
2617 eid = *(const WORD*)(ptr16 + sizeof(DWORD));
2618 ptr16 += sizeof(DWORD) + sizeof(WORD);
2619 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0) * sizeof(WCHAR);
2620 if (pos + len + sizeof(DWORD) + sizeof(WORD) > size)
2622 while (pos + len * sizeof(WCHAR) + sizeof(DWORD) + sizeof(WORD) > size) size += 1024;
2623 ptr32 = HeapReAlloc(GetProcessHeap(), 0, ptr32, size);
2624 if (!ptr32) goto the_end;
2626 MultiByteToWideChar(CP_ACP, 0, str, -1, (LPWSTR)(ptr32 + pos), len / sizeof(WCHAR));
2627 *(DWORD*)(ptr32 + pos + len) = flg;
2628 *(WORD*)(ptr32 + pos + len + sizeof(DWORD)) = eid;
2629 pos += len + sizeof(DWORD) + sizeof(WORD);
2630 } while (eid != MCI_END_COMMAND_LIST);
2632 the_end:
2633 FreeResource16( handle );
2634 if (ptr32) ret = MCI_SetCommandTable(ptr32, type);
2635 return ret;
2638 /**************************************************************************
2639 * mciFreeCommandResource [MMSYSTEM.713]
2641 BOOL16 WINAPI mciFreeCommandResource16(UINT16 uTable)
2643 TRACE("(%04x)!\n", uTable);
2645 return MCI_DeleteCommandTable(uTable, TRUE);
2648 /* ###################################################
2649 * # JOYSTICK #
2650 * ###################################################
2653 /**************************************************************************
2654 * joyGetNumDevs [MMSYSTEM.101]
2656 UINT16 WINAPI joyGetNumDevs16(void)
2658 return joyGetNumDevs();
2661 /**************************************************************************
2662 * joyGetDevCaps [MMSYSTEM.102]
2664 MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize)
2666 JOYCAPSA jca;
2667 MMRESULT ret;
2669 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
2671 ret = joyGetDevCapsA(wID, &jca, sizeof(jca));
2673 if (ret != JOYERR_NOERROR) return ret;
2674 lpCaps->wMid = jca.wMid;
2675 lpCaps->wPid = jca.wPid;
2676 strcpy(lpCaps->szPname, jca.szPname);
2677 lpCaps->wXmin = jca.wXmin;
2678 lpCaps->wXmax = jca.wXmax;
2679 lpCaps->wYmin = jca.wYmin;
2680 lpCaps->wYmax = jca.wYmax;
2681 lpCaps->wZmin = jca.wZmin;
2682 lpCaps->wZmax = jca.wZmax;
2683 lpCaps->wNumButtons = jca.wNumButtons;
2684 lpCaps->wPeriodMin = jca.wPeriodMin;
2685 lpCaps->wPeriodMax = jca.wPeriodMax;
2687 if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */
2688 lpCaps->wRmin = jca.wRmin;
2689 lpCaps->wRmax = jca.wRmax;
2690 lpCaps->wUmin = jca.wUmin;
2691 lpCaps->wUmax = jca.wUmax;
2692 lpCaps->wVmin = jca.wVmin;
2693 lpCaps->wVmax = jca.wVmax;
2694 lpCaps->wCaps = jca.wCaps;
2695 lpCaps->wMaxAxes = jca.wMaxAxes;
2696 lpCaps->wNumAxes = jca.wNumAxes;
2697 lpCaps->wMaxButtons = jca.wMaxButtons;
2698 strcpy(lpCaps->szRegKey, jca.szRegKey);
2699 strcpy(lpCaps->szOEMVxD, jca.szOEMVxD);
2702 return ret;
2705 /**************************************************************************
2706 * joyGetPosEx [MMSYSTEM.110]
2708 MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo)
2710 return joyGetPosEx(wID, lpInfo);
2713 /**************************************************************************
2714 * joyGetPos [MMSYSTEM.103]
2716 MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo)
2718 JOYINFO ji;
2719 MMRESULT ret;
2721 TRACE("(%d, %p);\n", wID, lpInfo);
2723 if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) {
2724 lpInfo->wXpos = ji.wXpos;
2725 lpInfo->wYpos = ji.wYpos;
2726 lpInfo->wZpos = ji.wZpos;
2727 lpInfo->wButtons = ji.wButtons;
2729 return ret;
2732 /**************************************************************************
2733 * joyGetThreshold [MMSYSTEM.104]
2735 MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold)
2737 UINT t;
2738 MMRESULT ret;
2740 ret = joyGetThreshold(wID, &t);
2741 if (ret == JOYERR_NOERROR)
2742 *lpThreshold = t;
2743 return ret;
2746 /**************************************************************************
2747 * joyReleaseCapture [MMSYSTEM.105]
2749 MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID)
2751 return joyReleaseCapture(wID);
2754 /**************************************************************************
2755 * joySetCapture [MMSYSTEM.106]
2757 MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged)
2759 return joySetCapture(HWND_32(hWnd), wID, wPeriod, bChanged);
2762 /**************************************************************************
2763 * joySetThreshold [MMSYSTEM.107]
2765 MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold)
2767 return joySetThreshold(wID,wThreshold);
2770 /**************************************************************************
2771 * joySetCalibration [MMSYSTEM.109]
2773 MMRESULT16 WINAPI joySetCalibration16(UINT16 wID)
2775 FIXME("(%04X): stub.\n", wID);
2776 return JOYERR_NOCANDO;