| /* |
| * MMSYSTEM MCI and low level mapping functions |
| * |
| * Copyright 1999 Eric Pouech |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include <string.h> |
| #include <stdarg.h> |
| #include <stdio.h> |
| #include <assert.h> |
| #include "wine/winbase16.h" |
| #include "windef.h" |
| #include "winbase.h" |
| #include "winuser.h" |
| #include "wownt32.h" |
| #include "winemm16.h" |
| #include "digitalv.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(winmm); |
| |
| /* ================================= |
| * A U X M A P P E R S |
| * ================================= */ |
| |
| /* ================================= |
| * M I X E R M A P P E R S |
| * ================================= */ |
| |
| /************************************************************************** |
| * MMSYSTDRV_Mixer_Map16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_Mixer_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2) |
| { |
| return MMSYSTEM_MAP_MSGERROR; |
| } |
| |
| /************************************************************************** |
| * MMSYSTDRV_Mixer_UnMap16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_Mixer_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret) |
| { |
| #if 0 |
| MIXERCAPSA micA; |
| UINT ret = mixerGetDevCapsA(devid, &micA, sizeof(micA)); |
| |
| if (ret == MMSYSERR_NOERROR) { |
| mixcaps->wMid = micA.wMid; |
| mixcaps->wPid = micA.wPid; |
| mixcaps->vDriverVersion = micA.vDriverVersion; |
| strcpy(mixcaps->szPname, micA.szPname); |
| mixcaps->fdwSupport = micA.fdwSupport; |
| mixcaps->cDestinations = micA.cDestinations; |
| } |
| return ret; |
| #endif |
| return MMSYSTEM_MAP_MSGERROR; |
| } |
| |
| /************************************************************************** |
| * MMSYSTDRV_Mixer_MapCB |
| */ |
| static void MMSYSTDRV_Mixer_MapCB(DWORD uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2) |
| { |
| FIXME("NIY\n"); |
| } |
| |
| /* ================================= |
| * M I D I I N M A P P E R S |
| * ================================= */ |
| |
| /************************************************************************** |
| * MMSYSTDRV_MidiIn_Map16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_MidiIn_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2) |
| { |
| return MMSYSTEM_MAP_MSGERROR; |
| } |
| |
| /************************************************************************** |
| * MMSYSTDRV_MidiIn_UnMap16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_MidiIn_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret) |
| { |
| return MMSYSTEM_MAP_MSGERROR; |
| } |
| |
| /************************************************************************** |
| * MMSYSTDRV_MidiIn_MapCB [internal] |
| */ |
| static void MMSYSTDRV_MidiIn_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2) |
| { |
| switch (uMsg) { |
| case MIM_OPEN: |
| case MIM_CLOSE: |
| /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */ |
| |
| case MIM_DATA: |
| case MIM_MOREDATA: |
| case MIM_ERROR: |
| /* dwParam1 & dwParam2 are data, nothing to do */ |
| break; |
| case MIM_LONGDATA: |
| case MIM_LONGERROR: |
| { |
| LPMIDIHDR mh32 = (LPMIDIHDR)(*dwParam1); |
| SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)); |
| LPMIDIHDR16 mh16 = MapSL(segmh16); |
| |
| *dwParam1 = (DWORD)segmh16; |
| mh16->dwFlags = mh32->dwFlags; |
| mh16->dwBytesRecorded = mh32->dwBytesRecorded; |
| } |
| break; |
| default: |
| ERR("Unknown msg %u\n", uMsg); |
| } |
| } |
| |
| /* ================================= |
| * M I D I O U T M A P P E R S |
| * ================================= */ |
| |
| /************************************************************************** |
| * MMSYSTDRV_MidiOut_Map16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_MidiOut_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2) |
| { |
| MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR; |
| |
| switch (wMsg) { |
| case MODM_GETNUMDEVS: |
| case MODM_DATA: |
| case MODM_RESET: |
| case MODM_SETVOLUME: |
| ret = MMSYSTEM_MAP_OK; |
| break; |
| |
| case MODM_OPEN: |
| case MODM_CLOSE: |
| case MODM_GETVOLUME: |
| FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n"); |
| break; |
| |
| case MODM_GETDEVCAPS: |
| { |
| LPMIDIOUTCAPSW moc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIOUTCAPS16) + sizeof(MIDIOUTCAPSW)); |
| LPMIDIOUTCAPS16 moc16 = MapSL(*lpParam1); |
| |
| if (moc32) { |
| *(LPMIDIOUTCAPS16*)moc32 = moc16; |
| moc32 = (LPMIDIOUTCAPSW)((LPSTR)moc32 + sizeof(LPMIDIOUTCAPS16)); |
| *lpParam1 = (DWORD)moc32; |
| *lpParam2 = sizeof(MIDIOUTCAPSW); |
| |
| ret = MMSYSTEM_MAP_OKMEM; |
| } else { |
| ret = MMSYSTEM_MAP_NOMEM; |
| } |
| } |
| break; |
| case MODM_PREPARE: |
| { |
| LPMIDIHDR mh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMIDIHDR) + sizeof(MIDIHDR)); |
| LPMIDIHDR16 mh16 = MapSL(*lpParam1); |
| |
| if (mh32) { |
| *(LPMIDIHDR*)mh32 = (LPMIDIHDR)*lpParam1; |
| mh32 = (LPMIDIHDR)((LPSTR)mh32 + sizeof(LPMIDIHDR)); |
| mh32->lpData = MapSL((SEGPTR)mh16->lpData); |
| mh32->dwBufferLength = mh16->dwBufferLength; |
| mh32->dwBytesRecorded = mh16->dwBytesRecorded; |
| mh32->dwUser = mh16->dwUser; |
| mh32->dwFlags = mh16->dwFlags; |
| mh16->lpNext = (MIDIHDR16*)mh32; /* for reuse in unprepare and write */ |
| *lpParam1 = (DWORD)mh32; |
| *lpParam2 = offsetof(MIDIHDR,dwOffset); /* old size, without dwOffset */ |
| |
| ret = MMSYSTEM_MAP_OKMEM; |
| } else { |
| ret = MMSYSTEM_MAP_NOMEM; |
| } |
| } |
| break; |
| case MODM_UNPREPARE: |
| case MODM_LONGDATA: |
| { |
| LPMIDIHDR16 mh16 = MapSL(*lpParam1); |
| LPMIDIHDR mh32 = (MIDIHDR*)mh16->lpNext; |
| |
| *lpParam1 = (DWORD)mh32; |
| *lpParam2 = offsetof(MIDIHDR,dwOffset); |
| /* dwBufferLength can be reduced between prepare & write */ |
| if (wMsg == MODM_LONGDATA && mh32->dwBufferLength < mh16->dwBufferLength) { |
| ERR("Size of buffer has been increased from %d to %d, keeping initial value\n", |
| mh32->dwBufferLength, mh16->dwBufferLength); |
| } else |
| mh32->dwBufferLength = mh16->dwBufferLength; |
| ret = MMSYSTEM_MAP_OKMEM; |
| } |
| break; |
| |
| case MODM_CACHEPATCHES: |
| case MODM_CACHEDRUMPATCHES: |
| default: |
| FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2); |
| break; |
| } |
| return ret; |
| } |
| |
| /************************************************************************** |
| * MMSYSTDRV_MidiOut_UnMap16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_MidiOut_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret) |
| { |
| MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR; |
| |
| switch (wMsg) { |
| case MODM_GETNUMDEVS: |
| case MODM_DATA: |
| case MODM_RESET: |
| case MODM_SETVOLUME: |
| ret = MMSYSTEM_MAP_OK; |
| break; |
| |
| case MODM_OPEN: |
| case MODM_CLOSE: |
| case MODM_GETVOLUME: |
| FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n"); |
| break; |
| |
| case MODM_GETDEVCAPS: |
| { |
| LPMIDIOUTCAPSW moc32 = (LPMIDIOUTCAPSW)(*lpParam1); |
| LPMIDIOUTCAPS16 moc16 = *(LPMIDIOUTCAPS16*)((LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16)); |
| |
| moc16->wMid = moc32->wMid; |
| moc16->wPid = moc32->wPid; |
| moc16->vDriverVersion = moc32->vDriverVersion; |
| WideCharToMultiByte( CP_ACP, 0, moc32->szPname, -1, moc16->szPname, |
| sizeof(moc16->szPname), NULL, NULL ); |
| moc16->wTechnology = moc32->wTechnology; |
| moc16->wVoices = moc32->wVoices; |
| moc16->wNotes = moc32->wNotes; |
| moc16->wChannelMask = moc32->wChannelMask; |
| moc16->dwSupport = moc32->dwSupport; |
| HeapFree(GetProcessHeap(), 0, (LPSTR)moc32 - sizeof(LPMIDIOUTCAPS16)); |
| ret = MMSYSTEM_MAP_OK; |
| } |
| break; |
| case MODM_PREPARE: |
| case MODM_UNPREPARE: |
| case MODM_LONGDATA: |
| { |
| LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1); |
| LPMIDIHDR16 mh16 = MapSL(*(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR))); |
| |
| assert((MIDIHDR*)mh16->lpNext == mh32); |
| mh16->dwFlags = mh32->dwFlags; |
| |
| if (wMsg == MODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) { |
| HeapFree(GetProcessHeap(), 0, (LPSTR)mh32 - sizeof(LPMIDIHDR)); |
| mh16->lpNext = 0; |
| } |
| ret = MMSYSTEM_MAP_OK; |
| } |
| break; |
| |
| case MODM_CACHEPATCHES: |
| case MODM_CACHEDRUMPATCHES: |
| default: |
| FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2); |
| break; |
| } |
| return ret; |
| } |
| |
| /****************************************************************** |
| * MMSYSTDRV_MidiOut_MapCB |
| */ |
| static void MMSYSTDRV_MidiOut_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2) |
| { |
| switch (uMsg) { |
| case MOM_OPEN: |
| case MOM_CLOSE: |
| /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */ |
| break; |
| case MOM_POSITIONCB: |
| /* MIDIHDR.dwOffset exists since Win 32 only */ |
| FIXME("MOM_POSITIONCB/MEVT_F_CALLBACK wants MIDIHDR.dwOffset in 16 bit code\n"); |
| /* fall through */ |
| case MOM_DONE: |
| { |
| /* initial map is: 16 => 32 */ |
| LPMIDIHDR mh32 = (LPMIDIHDR)(*dwParam1); |
| SEGPTR segmh16 = *(SEGPTR*)((LPSTR)mh32 - sizeof(LPMIDIHDR)); |
| LPMIDIHDR16 mh16 = MapSL(segmh16); |
| |
| *dwParam1 = (DWORD)segmh16; |
| mh16->dwFlags = mh32->dwFlags; |
| } |
| break; |
| default: |
| ERR("Unknown msg %u\n", uMsg); |
| } |
| } |
| |
| /* ================================= |
| * W A V E I N M A P P E R S |
| * ================================= */ |
| |
| /************************************************************************** |
| * MMSYSTDRV_WaveIn_Map16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_WaveIn_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2) |
| { |
| MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR; |
| |
| switch (wMsg) { |
| case WIDM_GETNUMDEVS: |
| case WIDM_RESET: |
| case WIDM_START: |
| case WIDM_STOP: |
| ret = MMSYSTEM_MAP_OK; |
| break; |
| case WIDM_OPEN: |
| case WIDM_CLOSE: |
| FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n"); |
| break; |
| case WIDM_GETDEVCAPS: |
| { |
| LPWAVEINCAPSW wic32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEINCAPS16) + sizeof(WAVEINCAPSW)); |
| LPWAVEINCAPS16 wic16 = MapSL(*lpParam1); |
| |
| if (wic32) { |
| *(LPWAVEINCAPS16*)wic32 = wic16; |
| wic32 = (LPWAVEINCAPSW)((LPSTR)wic32 + sizeof(LPWAVEINCAPS16)); |
| *lpParam1 = (DWORD)wic32; |
| *lpParam2 = sizeof(WAVEINCAPSW); |
| |
| ret = MMSYSTEM_MAP_OKMEM; |
| } else { |
| ret = MMSYSTEM_MAP_NOMEM; |
| } |
| } |
| break; |
| case WIDM_GETPOS: |
| { |
| LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME)); |
| LPMMTIME16 mmt16 = MapSL(*lpParam1); |
| |
| if (mmt32) { |
| *(LPMMTIME16*)mmt32 = mmt16; |
| mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16)); |
| |
| mmt32->wType = mmt16->wType; |
| *lpParam1 = (DWORD)mmt32; |
| *lpParam2 = sizeof(MMTIME); |
| |
| ret = MMSYSTEM_MAP_OKMEM; |
| } else { |
| ret = MMSYSTEM_MAP_NOMEM; |
| } |
| } |
| break; |
| case WIDM_PREPARE: |
| { |
| LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR)); |
| LPWAVEHDR wh16 = MapSL(*lpParam1); |
| |
| if (wh32) { |
| *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1; |
| wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR)); |
| wh32->lpData = MapSL((SEGPTR)wh16->lpData); |
| wh32->dwBufferLength = wh16->dwBufferLength; |
| wh32->dwBytesRecorded = wh16->dwBytesRecorded; |
| wh32->dwUser = wh16->dwUser; |
| wh32->dwFlags = wh16->dwFlags; |
| wh32->dwLoops = wh16->dwLoops; |
| /* FIXME: nothing on wh32->lpNext */ |
| /* could link the wh32->lpNext at this level for memory house keeping */ |
| wh16->lpNext = wh32; /* for reuse in unprepare and write */ |
| *lpParam1 = (DWORD)wh32; |
| *lpParam2 = sizeof(WAVEHDR); |
| |
| ret = MMSYSTEM_MAP_OKMEM; |
| } else { |
| ret = MMSYSTEM_MAP_NOMEM; |
| } |
| } |
| break; |
| case WIDM_ADDBUFFER: |
| case WIDM_UNPREPARE: |
| { |
| LPWAVEHDR wh16 = MapSL(*lpParam1); |
| LPWAVEHDR wh32 = wh16->lpNext; |
| |
| *lpParam1 = (DWORD)wh32; |
| *lpParam2 = sizeof(WAVEHDR); |
| /* dwBufferLength can be reduced between prepare & write */ |
| if (wMsg == WIDM_ADDBUFFER && wh32->dwBufferLength < wh16->dwBufferLength) { |
| ERR("Size of buffer has been increased from %d to %d, keeping initial value\n", |
| wh32->dwBufferLength, wh16->dwBufferLength); |
| } else |
| wh32->dwBufferLength = wh16->dwBufferLength; |
| ret = MMSYSTEM_MAP_OKMEM; |
| } |
| break; |
| case WIDM_MAPPER_STATUS: |
| /* just a single DWORD */ |
| *lpParam2 = (DWORD)MapSL(*lpParam2); |
| ret = MMSYSTEM_MAP_OK; |
| break; |
| default: |
| FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2); |
| break; |
| } |
| return ret; |
| } |
| |
| /************************************************************************** |
| * MMSYSTDRV_WaveIn_UnMap16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_WaveIn_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret) |
| { |
| MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR; |
| |
| switch (wMsg) { |
| case WIDM_GETNUMDEVS: |
| case WIDM_RESET: |
| case WIDM_START: |
| case WIDM_STOP: |
| case WIDM_MAPPER_STATUS: |
| ret = MMSYSTEM_MAP_OK; |
| break; |
| case WIDM_OPEN: |
| case WIDM_CLOSE: |
| FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n"); |
| break; |
| case WIDM_GETDEVCAPS: |
| { |
| LPWAVEINCAPSW wic32 = (LPWAVEINCAPSW)(*lpParam1); |
| LPWAVEINCAPS16 wic16 = *(LPWAVEINCAPS16*)((LPSTR)wic32 - sizeof(LPWAVEINCAPS16)); |
| |
| wic16->wMid = wic32->wMid; |
| wic16->wPid = wic32->wPid; |
| wic16->vDriverVersion = wic32->vDriverVersion; |
| WideCharToMultiByte( CP_ACP, 0, wic32->szPname, -1, wic16->szPname, |
| sizeof(wic16->szPname), NULL, NULL ); |
| wic16->dwFormats = wic32->dwFormats; |
| wic16->wChannels = wic32->wChannels; |
| HeapFree(GetProcessHeap(), 0, (LPSTR)wic32 - sizeof(LPWAVEINCAPS16)); |
| ret = MMSYSTEM_MAP_OK; |
| } |
| break; |
| case WIDM_GETPOS: |
| { |
| LPMMTIME mmt32 = (LPMMTIME)(*lpParam1); |
| LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16)); |
| |
| MMSYSTEM_MMTIME32to16(mmt16, mmt32); |
| HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16)); |
| ret = MMSYSTEM_MAP_OK; |
| } |
| break; |
| case WIDM_ADDBUFFER: |
| case WIDM_PREPARE: |
| case WIDM_UNPREPARE: |
| { |
| LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1); |
| LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR))); |
| |
| assert(wh16->lpNext == wh32); |
| wh16->dwBytesRecorded = wh32->dwBytesRecorded; |
| wh16->dwFlags = wh32->dwFlags; |
| |
| if (wMsg == WIDM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) { |
| HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR)); |
| wh16->lpNext = 0; |
| } |
| ret = MMSYSTEM_MAP_OK; |
| } |
| break; |
| default: |
| FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2); |
| break; |
| } |
| return ret; |
| } |
| |
| /************************************************************************** |
| * MMSYSTDRV_WaveIn_MapCB [internal] |
| */ |
| static void MMSYSTDRV_WaveIn_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2) |
| { |
| switch (uMsg) { |
| case WIM_OPEN: |
| case WIM_CLOSE: |
| /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */ |
| break; |
| case WIM_DATA: |
| { |
| /* initial map is: 16 => 32 */ |
| LPWAVEHDR wh32 = (LPWAVEHDR)(*dwParam1); |
| SEGPTR segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)); |
| LPWAVEHDR wh16 = MapSL(segwh16); |
| |
| *dwParam1 = (DWORD)segwh16; |
| wh16->dwFlags = wh32->dwFlags; |
| wh16->dwBytesRecorded = wh32->dwBytesRecorded; |
| } |
| break; |
| default: |
| ERR("Unknown msg %u\n", uMsg); |
| } |
| } |
| |
| /* ================================= |
| * W A V E O U T M A P P E R S |
| * ================================= */ |
| |
| /************************************************************************** |
| * MMSYSTDRV_WaveOut_Map16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_WaveOut_Map16To32W (UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2) |
| { |
| MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR; |
| |
| switch (wMsg) { |
| /* nothing to do */ |
| case WODM_BREAKLOOP: |
| case WODM_CLOSE: |
| case WODM_GETNUMDEVS: |
| case WODM_PAUSE: |
| case WODM_RESET: |
| case WODM_RESTART: |
| case WODM_SETPITCH: |
| case WODM_SETPLAYBACKRATE: |
| case WODM_SETVOLUME: |
| ret = MMSYSTEM_MAP_OK; |
| break; |
| |
| case WODM_GETPITCH: |
| case WODM_GETPLAYBACKRATE: |
| case WODM_GETVOLUME: |
| case WODM_OPEN: |
| FIXME("Shouldn't be used: the corresponding 16 bit functions use the 32 bit interface\n"); |
| break; |
| |
| case WODM_GETDEVCAPS: |
| { |
| LPWAVEOUTCAPSW woc32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEOUTCAPS16) + sizeof(WAVEOUTCAPSW)); |
| LPWAVEOUTCAPS16 woc16 = MapSL(*lpParam1); |
| |
| if (woc32) { |
| *(LPWAVEOUTCAPS16*)woc32 = woc16; |
| woc32 = (LPWAVEOUTCAPSW)((LPSTR)woc32 + sizeof(LPWAVEOUTCAPS16)); |
| *lpParam1 = (DWORD)woc32; |
| *lpParam2 = sizeof(WAVEOUTCAPSW); |
| |
| ret = MMSYSTEM_MAP_OKMEM; |
| } else { |
| ret = MMSYSTEM_MAP_NOMEM; |
| } |
| } |
| break; |
| case WODM_GETPOS: |
| { |
| LPMMTIME mmt32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMMTIME16) + sizeof(MMTIME)); |
| LPMMTIME16 mmt16 = MapSL(*lpParam1); |
| |
| if (mmt32) { |
| *(LPMMTIME16*)mmt32 = mmt16; |
| mmt32 = (LPMMTIME)((LPSTR)mmt32 + sizeof(LPMMTIME16)); |
| |
| mmt32->wType = mmt16->wType; |
| *lpParam1 = (DWORD)mmt32; |
| *lpParam2 = sizeof(MMTIME); |
| |
| ret = MMSYSTEM_MAP_OKMEM; |
| } else { |
| ret = MMSYSTEM_MAP_NOMEM; |
| } |
| } |
| break; |
| case WODM_PREPARE: |
| { |
| LPWAVEHDR wh32 = HeapAlloc(GetProcessHeap(), 0, sizeof(LPWAVEHDR) + sizeof(WAVEHDR)); |
| LPWAVEHDR wh16 = MapSL(*lpParam1); |
| |
| if (wh32) { |
| *(LPWAVEHDR*)wh32 = (LPWAVEHDR)*lpParam1; |
| wh32 = (LPWAVEHDR)((LPSTR)wh32 + sizeof(LPWAVEHDR)); |
| wh32->lpData = MapSL((SEGPTR)wh16->lpData); |
| wh32->dwBufferLength = wh16->dwBufferLength; |
| wh32->dwBytesRecorded = wh16->dwBytesRecorded; |
| wh32->dwUser = wh16->dwUser; |
| wh32->dwFlags = wh16->dwFlags; |
| wh32->dwLoops = wh16->dwLoops; |
| /* FIXME: nothing on wh32->lpNext */ |
| /* could link the wh32->lpNext at this level for memory house keeping */ |
| wh16->lpNext = wh32; /* for reuse in unprepare and write */ |
| *lpParam1 = (DWORD)wh32; |
| *lpParam2 = sizeof(WAVEHDR); |
| |
| ret = MMSYSTEM_MAP_OKMEM; |
| } else { |
| ret = MMSYSTEM_MAP_NOMEM; |
| } |
| } |
| break; |
| case WODM_UNPREPARE: |
| case WODM_WRITE: |
| { |
| LPWAVEHDR wh16 = MapSL(*lpParam1); |
| LPWAVEHDR wh32 = wh16->lpNext; |
| |
| *lpParam1 = (DWORD)wh32; |
| *lpParam2 = sizeof(WAVEHDR); |
| /* dwBufferLength can be reduced between prepare & write */ |
| if (wMsg == WODM_WRITE && wh32->dwBufferLength < wh16->dwBufferLength) { |
| ERR("Size of buffer has been increased from %d to %d, keeping initial value\n", |
| wh32->dwBufferLength, wh16->dwBufferLength); |
| } else |
| wh32->dwBufferLength = wh16->dwBufferLength; |
| ret = MMSYSTEM_MAP_OKMEM; |
| } |
| break; |
| case WODM_MAPPER_STATUS: |
| *lpParam2 = (DWORD)MapSL(*lpParam2); |
| ret = MMSYSTEM_MAP_OK; |
| break; |
| default: |
| FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2); |
| break; |
| } |
| return ret; |
| } |
| |
| /************************************************************************** |
| * MMSYSTDRV_WaveOut_UnMap16To32W [internal] |
| */ |
| static MMSYSTEM_MapType MMSYSTDRV_WaveOut_UnMap16To32W(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT fn_ret) |
| { |
| MMSYSTEM_MapType ret = MMSYSTEM_MAP_MSGERROR; |
| |
| switch (wMsg) { |
| /* nothing to do */ |
| case WODM_BREAKLOOP: |
| case WODM_CLOSE: |
| case WODM_GETNUMDEVS: |
| case WODM_PAUSE: |
| case WODM_RESET: |
| case WODM_RESTART: |
| case WODM_SETPITCH: |
| case WODM_SETPLAYBACKRATE: |
| case WODM_SETVOLUME: |
| case WODM_MAPPER_STATUS: |
| ret = MMSYSTEM_MAP_OK; |
| break; |
| |
| case WODM_GETPITCH: |
| case WODM_GETPLAYBACKRATE: |
| case WODM_GETVOLUME: |
| case WODM_OPEN: |
| FIXME("Shouldn't be used: those 16 bit functions use the 32 bit interface\n"); |
| break; |
| |
| case WODM_GETDEVCAPS: |
| { |
| LPWAVEOUTCAPSW woc32 = (LPWAVEOUTCAPSW)(*lpParam1); |
| LPWAVEOUTCAPS16 woc16 = *(LPWAVEOUTCAPS16*)((LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16)); |
| |
| woc16->wMid = woc32->wMid; |
| woc16->wPid = woc32->wPid; |
| woc16->vDriverVersion = woc32->vDriverVersion; |
| WideCharToMultiByte( CP_ACP, 0, woc32->szPname, -1, woc16->szPname, |
| sizeof(woc16->szPname), NULL, NULL ); |
| woc16->dwFormats = woc32->dwFormats; |
| woc16->wChannels = woc32->wChannels; |
| woc16->dwSupport = woc32->dwSupport; |
| HeapFree(GetProcessHeap(), 0, (LPSTR)woc32 - sizeof(LPWAVEOUTCAPS16)); |
| ret = MMSYSTEM_MAP_OK; |
| } |
| break; |
| case WODM_GETPOS: |
| { |
| LPMMTIME mmt32 = (LPMMTIME)(*lpParam1); |
| LPMMTIME16 mmt16 = *(LPMMTIME16*)((LPSTR)mmt32 - sizeof(LPMMTIME16)); |
| |
| MMSYSTEM_MMTIME32to16(mmt16, mmt32); |
| HeapFree(GetProcessHeap(), 0, (LPSTR)mmt32 - sizeof(LPMMTIME16)); |
| ret = MMSYSTEM_MAP_OK; |
| } |
| break; |
| case WODM_PREPARE: |
| case WODM_UNPREPARE: |
| case WODM_WRITE: |
| { |
| LPWAVEHDR wh32 = (LPWAVEHDR)(*lpParam1); |
| LPWAVEHDR wh16 = MapSL(*(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR))); |
| |
| assert(wh16->lpNext == wh32); |
| wh16->dwFlags = wh32->dwFlags; |
| |
| if (wMsg == WODM_UNPREPARE && fn_ret == MMSYSERR_NOERROR) { |
| HeapFree(GetProcessHeap(), 0, (LPSTR)wh32 - sizeof(LPWAVEHDR)); |
| wh16->lpNext = 0; |
| } |
| ret = MMSYSTEM_MAP_OK; |
| } |
| break; |
| default: |
| FIXME("NIY: no conversion yet for %u [%lx,%lx]\n", wMsg, *lpParam1, *lpParam2); |
| break; |
| } |
| return ret; |
| } |
| |
| /************************************************************************** |
| * MMDRV_WaveOut_Callback [internal] |
| */ |
| static void MMSYSTDRV_WaveOut_MapCB(UINT uMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2) |
| { |
| switch (uMsg) { |
| case WOM_OPEN: |
| case WOM_CLOSE: |
| /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */ |
| break; |
| case WOM_DONE: |
| { |
| /* initial map is: 16 => 32 */ |
| LPWAVEHDR wh32 = (LPWAVEHDR)(*dwParam1); |
| SEGPTR segwh16 = *(SEGPTR*)((LPSTR)wh32 - sizeof(LPWAVEHDR)); |
| LPWAVEHDR wh16 = MapSL(segwh16); |
| |
| *dwParam1 = (DWORD)segwh16; |
| wh16->dwFlags = wh32->dwFlags; |
| } |
| break; |
| default: |
| ERR("Unknown msg %u\n", uMsg); |
| } |
| } |
| |
| /* ################################################### |
| * # DRIVER THUNKING # |
| * ################################################### |
| */ |
| typedef MMSYSTEM_MapType (*MMSYSTDRV_MAPMSG)(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2); |
| typedef MMSYSTEM_MapType (*MMSYSTDRV_UNMAPMSG)(UINT wMsg, DWORD_PTR* lpParam1, DWORD_PTR* lpParam2, MMRESULT ret); |
| typedef void (*MMSYSTDRV_MAPCB)(DWORD wMsg, DWORD_PTR* dwUser, DWORD_PTR* dwParam1, DWORD_PTR* dwParam2); |
| |
| #include <pshpack1.h> |
| #define MMSYSTDRV_MAX_THUNKS 32 |
| |
| static struct mmsystdrv_thunk |
| { |
| BYTE popl_eax; /* popl %eax (return address) */ |
| BYTE pushl_this; /* pushl this (this very thunk) */ |
| struct mmsystdrv_thunk* this; |
| BYTE pushl_eax; /* pushl %eax */ |
| BYTE jmp; /* ljmp MMDRV_Callback3216 */ |
| DWORD callback3216; |
| DWORD callback; /* callback value (function, window, event...) */ |
| DWORD flags; /* flags to control callback value (CALLBACK_???) */ |
| void* hMmdrv; /* Handle to 32bit mmdrv object */ |
| enum MMSYSTEM_DriverType kind; |
| } *MMSYSTDRV_Thunks; |
| |
| #include <poppack.h> |
| |
| static struct MMSYSTDRV_Type |
| { |
| MMSYSTDRV_MAPMSG mapmsg16to32W; |
| MMSYSTDRV_UNMAPMSG unmapmsg16to32W; |
| MMSYSTDRV_MAPCB mapcb; |
| } MMSYSTEM_DriversType[MMSYSTDRV_MAX] = |
| { |
| {MMSYSTDRV_Mixer_Map16To32W, MMSYSTDRV_Mixer_UnMap16To32W, MMSYSTDRV_Mixer_MapCB}, |
| {MMSYSTDRV_MidiIn_Map16To32W, MMSYSTDRV_MidiIn_UnMap16To32W, MMSYSTDRV_MidiIn_MapCB}, |
| {MMSYSTDRV_MidiOut_Map16To32W, MMSYSTDRV_MidiOut_UnMap16To32W, MMSYSTDRV_MidiOut_MapCB}, |
| {MMSYSTDRV_WaveIn_Map16To32W, MMSYSTDRV_WaveIn_UnMap16To32W, MMSYSTDRV_WaveIn_MapCB}, |
| {MMSYSTDRV_WaveOut_Map16To32W, MMSYSTDRV_WaveOut_UnMap16To32W, MMSYSTDRV_WaveOut_MapCB}, |
| }; |
| |
| /****************************************************************** |
| * MMSYSTDRV_Callback3216 |
| * |
| */ |
| static LRESULT CALLBACK MMSYSTDRV_Callback3216(struct mmsystdrv_thunk* thunk, HDRVR hDev, |
| DWORD wMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, |
| DWORD_PTR dwParam2) |
| { |
| WORD args[8]; |
| |
| assert(thunk->kind < MMSYSTDRV_MAX); |
| assert(MMSYSTEM_DriversType[thunk->kind].mapcb); |
| |
| MMSYSTEM_DriversType[thunk->kind].mapcb(wMsg, &dwUser, &dwParam1, &dwParam2); |
| |
| switch (thunk->flags & CALLBACK_TYPEMASK) { |
| case CALLBACK_NULL: |
| TRACE("Null !\n"); |
| break; |
| case CALLBACK_WINDOW: |
| TRACE("Window(%04X) handle=%p!\n", thunk->callback, hDev); |
| PostMessageA((HWND)thunk->callback, wMsg, (WPARAM)hDev, dwParam1); |
| break; |
| case CALLBACK_TASK: /* aka CALLBACK_THREAD */ |
| TRACE("Task(%04x) !\n", thunk->callback); |
| PostThreadMessageA(thunk->callback, wMsg, (WPARAM)hDev, dwParam1); |
| break; |
| case CALLBACK_FUNCTION: |
| /* 16 bit func, call it */ |
| TRACE("Function (16 bit) %x!\n", thunk->callback); |
| |
| args[7] = HDRVR_16(hDev); |
| args[6] = wMsg; |
| args[5] = HIWORD(dwUser); |
| args[4] = LOWORD(dwUser); |
| args[3] = HIWORD(dwParam1); |
| args[2] = LOWORD(dwParam1); |
| args[1] = HIWORD(dwParam2); |
| args[0] = LOWORD(dwParam2); |
| return WOWCallback16Ex(thunk->callback, WCB16_PASCAL, sizeof(args), args, NULL); |
| case CALLBACK_EVENT: |
| TRACE("Event(%08x) !\n", thunk->callback); |
| SetEvent((HANDLE)thunk->callback); |
| break; |
| default: |
| WARN("Unknown callback type %x\n", thunk->flags & CALLBACK_TYPEMASK); |
| return FALSE; |
| } |
| TRACE("Done\n"); |
| return TRUE; |
| } |
| |
| /****************************************************************** |
| * MMSYSTDRV_AddThunk |
| * |
| */ |
| struct mmsystdrv_thunk* MMSYSTDRV_AddThunk(DWORD callback, DWORD flags, enum MMSYSTEM_DriverType kind) |
| { |
| struct mmsystdrv_thunk* thunk; |
| |
| EnterCriticalSection(&mmdrv_cs); |
| if (!MMSYSTDRV_Thunks) |
| { |
| MMSYSTDRV_Thunks = VirtualAlloc(NULL, MMSYSTDRV_MAX_THUNKS * sizeof(*MMSYSTDRV_Thunks), |
| MEM_COMMIT, PAGE_EXECUTE_READWRITE); |
| if (!MMSYSTDRV_Thunks) |
| { |
| LeaveCriticalSection(&mmdrv_cs); |
| return NULL; |
| } |
| for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++) |
| { |
| thunk->popl_eax = 0x58; /* popl %eax */ |
| thunk->pushl_this = 0x68; /* pushl this */ |
| thunk->this = thunk; |
| thunk->pushl_eax = 0x50; /* pushl %eax */ |
| thunk->jmp = 0xe9; /* jmp MMDRV_Callback3216 */ |
| thunk->callback3216 = (char *)MMSYSTDRV_Callback3216 - (char *)(&thunk->callback3216 + 1); |
| thunk->callback = 0; |
| thunk->flags = CALLBACK_NULL; |
| thunk->hMmdrv = NULL; |
| thunk->kind = MMSYSTDRV_MAX; |
| } |
| } |
| for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++) |
| { |
| if (thunk->callback == 0 && thunk->hMmdrv == NULL) |
| { |
| thunk->callback = callback; |
| thunk->flags = flags; |
| thunk->hMmdrv = NULL; |
| thunk->kind = kind; |
| LeaveCriticalSection(&mmdrv_cs); |
| return thunk; |
| } |
| } |
| LeaveCriticalSection(&mmdrv_cs); |
| FIXME("Out of mmdrv-thunks. Bump MMDRV_MAX_THUNKS\n"); |
| return NULL; |
| } |
| |
| /****************************************************************** |
| * MMSYSTDRV_FindHandle |
| * |
| * Must be called with lock set |
| */ |
| static void* MMSYSTDRV_FindHandle(void* h) |
| { |
| struct mmsystdrv_thunk* thunk; |
| |
| for (thunk = MMSYSTDRV_Thunks; thunk < &MMSYSTDRV_Thunks[MMSYSTDRV_MAX_THUNKS]; thunk++) |
| { |
| if (thunk->hMmdrv == h) |
| { |
| if (thunk->kind >= MMSYSTDRV_MAX) FIXME("Kind isn't properly initialized %x\n", thunk->kind); |
| return thunk; |
| } |
| } |
| return NULL; |
| } |
| |
| /****************************************************************** |
| * MMSYSTDRV_SetHandle |
| * |
| */ |
| void MMSYSTDRV_SetHandle(struct mmsystdrv_thunk* thunk, void* h) |
| { |
| if (MMSYSTDRV_FindHandle(h)) FIXME("Already has a thunk for this handle %p!!!\n", h); |
| thunk->hMmdrv = h; |
| } |
| |
| /****************************************************************** |
| * MMSYSTDRV_DeleteThunk |
| */ |
| void MMSYSTDRV_DeleteThunk(struct mmsystdrv_thunk* thunk) |
| { |
| thunk->callback = 0; |
| thunk->flags = CALLBACK_NULL; |
| thunk->hMmdrv = NULL; |
| thunk->kind = MMSYSTDRV_MAX; |
| } |
| |
| /****************************************************************** |
| * MMSYSTDRV_CloseHandle |
| */ |
| void MMSYSTDRV_CloseHandle(void* h) |
| { |
| struct mmsystdrv_thunk* thunk; |
| |
| EnterCriticalSection(&mmdrv_cs); |
| if ((thunk = MMSYSTDRV_FindHandle(h))) |
| { |
| MMSYSTDRV_DeleteThunk(thunk); |
| } |
| LeaveCriticalSection(&mmdrv_cs); |
| } |
| |
| /****************************************************************** |
| * MMSYSTDRV_Message |
| */ |
| DWORD MMSYSTDRV_Message(void* h, UINT msg, DWORD_PTR param1, DWORD_PTR param2) |
| { |
| struct mmsystdrv_thunk* thunk = MMSYSTDRV_FindHandle(h); |
| struct MMSYSTDRV_Type* drvtype; |
| MMSYSTEM_MapType map; |
| DWORD ret; |
| |
| if (!thunk) return MMSYSERR_INVALHANDLE; |
| drvtype = &MMSYSTEM_DriversType[thunk->kind]; |
| |
| map = drvtype->mapmsg16to32W(msg, ¶m1, ¶m2); |
| switch (map) { |
| case MMSYSTEM_MAP_NOMEM: |
| ret = MMSYSERR_NOMEM; |
| break; |
| case MMSYSTEM_MAP_MSGERROR: |
| FIXME("NIY: no conversion yet 16->32 kind=%u msg=%u\n", thunk->kind, msg); |
| ret = MMSYSERR_ERROR; |
| break; |
| case MMSYSTEM_MAP_OK: |
| case MMSYSTEM_MAP_OKMEM: |
| TRACE("Calling message(msg=%u p1=0x%08lx p2=0x%08lx)\n", |
| msg, param1, param2); |
| switch (thunk->kind) |
| { |
| case MMSYSTDRV_MIXER: ret = mixerMessage (h, msg, param1, param2); break; |
| case MMSYSTDRV_MIDIIN: |
| switch (msg) |
| { |
| case MIDM_ADDBUFFER: ret = midiInAddBuffer(h, (LPMIDIHDR)param1, param2); break; |
| case MIDM_PREPARE: ret = midiInPrepareHeader(h, (LPMIDIHDR)param1, param2); break; |
| case MIDM_UNPREPARE: ret = midiInUnprepareHeader(h, (LPMIDIHDR)param1, param2); break; |
| default: ret = midiInMessage(h, msg, param1, param2); break; |
| } |
| break; |
| case MMSYSTDRV_MIDIOUT: |
| switch (msg) |
| { |
| case MODM_PREPARE: ret = midiOutPrepareHeader(h, (LPMIDIHDR)param1, param2); break; |
| case MODM_UNPREPARE: ret = midiOutUnprepareHeader(h, (LPMIDIHDR)param1, param2); break; |
| case MODM_LONGDATA: ret = midiOutLongMsg(h, (LPMIDIHDR)param1, param2); break; |
| default: ret = midiOutMessage(h, msg, param1, param2); break; |
| } |
| break; |
| case MMSYSTDRV_WAVEIN: |
| switch (msg) |
| { |
| case WIDM_ADDBUFFER: ret = waveInAddBuffer(h, (LPWAVEHDR)param1, param2); break; |
| case WIDM_PREPARE: ret = waveInPrepareHeader(h, (LPWAVEHDR)param1, param2); break; |
| case WIDM_UNPREPARE: ret = waveInUnprepareHeader(h, (LPWAVEHDR)param1, param2); break; |
| default: ret = waveInMessage(h, msg, param1, param2); break; |
| } |
| break; |
| case MMSYSTDRV_WAVEOUT: |
| switch (msg) |
| { |
| case WODM_PREPARE: ret = waveOutPrepareHeader(h, (LPWAVEHDR)param1, param2); break; |
| case WODM_UNPREPARE: ret = waveOutUnprepareHeader(h, (LPWAVEHDR)param1, param2); break; |
| case WODM_WRITE: ret = waveOutWrite(h, (LPWAVEHDR)param1, param2); break; |
| default: ret = waveOutMessage(h, msg, param1, param2); break; |
| } |
| break; |
| default: ret = MMSYSERR_INVALHANDLE; break; /* should never be reached */ |
| } |
| if (map == MMSYSTEM_MAP_OKMEM) |
| drvtype->unmapmsg16to32W(msg, ¶m1, ¶m2, ret); |
| break; |
| default: |
| FIXME("NIY\n"); |
| ret = MMSYSERR_NOTSUPPORTED; |
| break; |
| } |
| return ret; |
| } |