/***********************************************************************\ * * WOW v1.0 * * Copyright (c) 1991, Microsoft Corporation * * WMMEDIA2.C * WOW32 16-bit MultiMedia API support * * Contains: * Midi IN apis * Midi OUT apis * Wave IN apis * Wave OUT apis * * * History: * Created 21-Jan-1992 by Mike Tricker (MikeTri), after jeffpar * Changed 15-Jul-1992 by Mike Tricker (MikeTri), fixing GetDevCaps calls * 26-Jul-1992 by Stephen Estrop (StephenE) thunks for mciSendCommand * 30-Jul-1992 by Mike Tricker (MikeTri), fixing Wave/Midi/MMIO * 03-Aug-1992 by Mike Tricker (MikeTri), added proper error handling * 08-Oct-1992 by StephenE spawned from the original wmmedia.c * \***********************************************************************/ // // We define NO_STRICT so that the compiler doesn't moan and groan when // I use the FARPROC type for the Multi-Media api loading. // #define NO_STRICT #define OEMRESOURCE #include "precomp.h" #pragma hdrstop #if 0 MODNAME(wmmedia2.c); // A 32 bit ptr to the 16 bit callback data extern PCALLBACK_DATA pCallBackData; extern CRITICAL_SECTION mmCriticalSection; #if DBG /* ** AllocCount maintains a count of the number XXM_DONE messages that ** we expect to receive before the device is closed. When the device is ** closed this count should be zero. ** */ int AllocWaveCount = 0; int AllocMidiCount = 0; int mmTraceWave = 0; int mmTraceMidi = 0; #endif /* --------------------------------------------------------------------- ** MIDI Output API's ** --------------------------------------------------------------------- */ /**********************************************************************\ * * WMM32midiOutGetNumDevs * * This function retrieves the number of MIDI output devices present * in the system. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutGetNumDevs(PVDMFRAME pFrame) { static FARPROC mmAPI = NULL; ULONG ul; UNREFERENCED_PARAMETER(pFrame); GET_MULTIMEDIA_API( "midiOutGetNumDevs", mmAPI, MMSYSERR_NODRIVER ); trace_midi(( "midiOutGetNumDevs()" )); ul = GETWORD16((*mmAPI)() ); trace_midi(( "-> %ld\n", ul )); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutGetDevCaps * * This function queries a specified MIDI output device to determine its * capabilities. * * * * We will now change things... * * Step 1: get the ENTIRE Caps structure, irrespective of the number of bytes * requested * (previously I was getting the requested number of bytes via * parg16->f3 (plus 2 'cos of the WORD -> UINT change for version - * which was wrong anyway...) ) * * Step 2: thunk the ENTIRE structure in to a 16 bit local variable * * Step 3: RtlCopyMemory the REQUESTED number of bytes from the local copy * to the "real" structure within the app * * Thanks to RCBS for sorting me out once again ! * * * \**********************************************************************/ ULONG FASTCALL WMM32midiOutGetDevCaps(PVDMFRAME pFrame) { register PMIDIOUTGETDEVCAPS16 parg16; static FARPROC mmAPI = NULL; ULONG ul; MIDIOUTCAPS midioutcaps; GET_MULTIMEDIA_API( "midiOutGetDevCapsA", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTGETDEVCAPS16), parg16); trace_midi(( "midiOutGetDevCaps( %x, %x, %x )", INT32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the size parameter was zero return straight away. Note that this ** is not an error. */ if ( UINT32( parg16->f3 ) == 0 ) { ul = MMSYSERR_NOERROR; } else { ul = GETWORD16((*mmAPI)( INT32(parg16->f1), &midioutcaps, sizeof(MIDIOUTCAPS) )); /* ** This must now thunk the ENTIRE structure, then copy parg16->f3 ** bytes onto the "real" structure in the app, but only if the call ** returned success. */ if ( ul == MMSYSERR_NOERROR ) { ul = PUTMIDIOUTCAPS16(parg16->f2, &midioutcaps, UINT32(parg16->f3)); } } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutGetErrorText * * This function retrieves a textual description of the error * identified by the specified error number. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutGetErrorText(PVDMFRAME pFrame) { register PMIDIOUTGETERRORTEXT16 parg16; static FARPROC mmAPI = NULL; ULONG ul = MMSYSERR_NOERROR; PSZ pszText; GET_MULTIMEDIA_API( "midiOutGetErrorTextA", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTGETERRORTEXT16), parg16); trace_midi(( "midiOutGetErrorText( %x, %x, %x )", UINT32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** Test against a zero length string and a NULL pointer. If 0 is passed ** as the buffer length then the manual says we should return ** MMSYSERR_NOERR. MMGETOPTPTR only returns a pointer if parg16->f2 is ** not NULL. */ MMGETOPTPTR( parg16->f2, UINT32(parg16->f3), pszText ); if ( pszText != NULL ) { ul = GETWORD16((*mmAPI)( UINT32(parg16->f1), pszText, UINT32(parg16->f3) )); FLUSHVDMPTR(DWORD32(parg16->f2), UINT32(parg16->f3), pszText); FREEVDMPTR(pszText); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /***********************************************************************\ * * WMM32midiOutOpen * * This function opens a specified MIDI output device for playback. * \***********************************************************************/ ULONG FASTCALL WMM32midiOutOpen(PVDMFRAME pFrame) { register PMIDIOUTOPEN16 parg16; static FARPROC mmAPI = NULL; ULONG ul = MMSYSERR_NOERROR; UINT uDevID; PINSTANCEDATA pInstanceData; LPHMIDIOUT lpHMidiOut; // pointer to handle in 16 bit app space HMIDIOUT Hand32; // 32bit handle GET_MULTIMEDIA_API( "midiOutOpen", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTOPEN16), parg16); trace_midi(( "midiOutOpen( %x, %x, %x, %x, %x )", DWORD32( parg16->f1 ), INT32 ( parg16->f2 ), DWORD32( parg16->f3 ), DWORD32( parg16->f4 ), DWORD32( parg16->f5 ) )); /* ** Get the device ID. We use INT32 here not UINT32 to make sure that ** negative values (such as MIDI_MAPPER (-1)) get thunked correctly. */ uDevID = (UINT)INT32(parg16->f2); /* ** Map the 16 bit pointer is one was specified. */ MMGETOPTPTR( parg16->f1, sizeof(HMIDIOUT16), lpHMidiOut ); if ( lpHMidiOut ) { /* ** Create InstanceData block to be used by our callback routine. ** ** NOTE: Although we malloc it here we don't free it. ** This is not a mistake - it must not be freed before the ** callback routine has used it - so it does the freeing. ** ** If the malloc fails we bomb down to the bottom, ** set ul to MMSYSERR_NOMEM and exit gracefully. ** ** We always have a callback functions. This is to ensure that ** the MIDIHDR structure keeps getting copied back from ** 32 bit space to 16 bit, as it contains flags which ** applications are liable to keep checking. */ if ( pInstanceData = malloc_w(sizeof(INSTANCEDATA)) ) { dprintf2(( "WM32midiOutOpen: Allocated instance buffer at %8X", pInstanceData )); pInstanceData->dwCallback = DWORD32(parg16->f3); pInstanceData->dwCallbackInstance = DWORD32(parg16->f4); pInstanceData->dwFlags = DWORD32(parg16->f5); ul = GETWORD16((*mmAPI)( &Hand32, uDevID, (DWORD)W32CommonDeviceOpen, (DWORD)pInstanceData, CALLBACK_FUNCTION )); } else { ul = MMSYSERR_NOMEM; } /* ** If the call returns success update the 16 bit handle, ** otherwise don't, and free the memory we malloc'd earlier, as ** the callback that would have freed it will never get callled. */ if ( ul == MMSYSERR_NOERROR ) { HMIDIOUT16 Hand16 = GETHMIDIOUT16(Hand32); trace_midi(( "Handle -> %x", Hand16 )); STOREWORD ( *lpHMidiOut, Hand16 ); FLUSHVDMPTR( DWORD32(parg16->f1), sizeof(HMIDIOUT16), lpHMidiOut ); } /* ** We only free the memory if we actually allocated any */ else if ( pInstanceData ) { free_w(pInstanceData); } /* ** Regardless of sucess or failure we need to free the pointer ** to the 16 bit MidiIn handle. */ FREEVDMPTR ( lpHMidiOut ); } else { ul = MMSYSERR_INVALPARAM; } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutClose * * This function closes the specified MIDI output device. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutClose(PVDMFRAME pFrame) { register PMIDIOUTCLOSE16 parg16; static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "midiOutClose", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTCLOSE16), parg16); trace_midi(( "midiOutClose( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16( (*mmAPI)(HMIDIOUT32(parg16->f1) )); trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutPrepareHeader * * This function prepares the specified midiform header. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutPrepareHeader(PVDMFRAME pFrame) { register PMIDIOUTPREPAREHEADER3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; MIDIHDR midihdr; GET_MULTIMEDIA_API( "midiOutPrepareHeader", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTPREPAREHEADER3216), parg16); trace_midi(( "midiOutPrepareHeader( %x %x %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), WORD32( parg16->f3 ) )); GETMIDIHDR16(parg16->f2, &midihdr); ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), &midihdr, WORD32(parg16->f3) ) ); /* ** Only update the 16 bit structure if the call returns success ** */ if ( !ul ) { PUTMIDIHDR16(parg16->f2, &midihdr); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutUnprepareHeader * * This function prepares the specified midiform header. * This function cleans up the preparation performed by midiOutPrepareHeader. * The function must be called after the device driver has finished with a * data block. You must call this function before freeing the data buffer. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutUnprepareHeader(PVDMFRAME pFrame) { register PMIDIOUTUNPREPAREHEADER3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; MIDIHDR midihdr; GET_MULTIMEDIA_API( "midiOutUnprepareHeader", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTUNPREPAREHEADER3216), parg16); trace_midi(( "midiOutUnprepareHeader( %x %x %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), WORD32( parg16->f3 ) )); GETMIDIHDR16(parg16->f2, &midihdr); ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), &midihdr, WORD32(parg16->f3) ) ); /* ** Only update the 16 bit structure if the call returns success */ if (!ul) { PUTMIDIHDR16(parg16->f2, &midihdr); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutShortMsg * * This function sends a short MIDI message to the specified MIDI output device. * Use this function to send any MIDI message except for system exclusive * messages. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutShortMsg(PVDMFRAME pFrame) { register PMIDIOUTSHORTMSG16 parg16; static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "midiOutShortMsg", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTSHORTMSG16), parg16); trace_midi(( "midiOutShortMsg( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), DWORD32(parg16->f2) )); trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutLongMsg * * This function sends a long MIDI message to the specified MIDI output * device. Use this function to send system exclusive messages or to * send a buffer filled with short messages. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutLongMsg(PVDMFRAME pFrame) { register PMIDIOUTLONGMSG16 parg16; static FARPROC mmAPI = NULL; ULONG ul; PMIDIHDR32 pMidihdr32; GET_MULTIMEDIA_API( "midiOutLongMsg", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTLONGMSG16), parg16); trace_midi(( "midiOutLongMsg( %x, %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the given size of the MIDIHDR structure is too small ** or the lphdr is invalid return an error ** */ if ( UINT32(parg16->f3) < sizeof(MIDIHDR16) || HIWORD( DWORD32(parg16->f2) ) == 0 ) { ul = MMSYSERR_INVALPARAM; } else { if ( pMidihdr32 = malloc_w(sizeof(MIDIHDR32)) ) { PMIDIHDR lpwhdr; #if DBG AllocMidiCount++; dprintf2(( "M>> %8X (%d)", pMidihdr32, AllocMidiCount )); #endif /* Copy across the midi header stuff. Note that lpwhdr (a ** 32 bit ptr to a 32 bit midi header) is used to make the ** pointer stuff a bit less hairy. ** ** pMidihdr32->pMidihdr32 is a 32 bit ptr to a 16 bit midi header ** pMidihdr32->pMidihdr16 is a 16 bit ptr to a 16 bit midi header ** pMidihdr32->Midihdr is a 32 bit midi header */ lpwhdr = &(pMidihdr32->Midihdr); pMidihdr32->pMidihdr16 = (PMIDIHDR16)DWORD32(parg16->f2); pMidihdr32->pMidihdr32 = GETMIDIHDR16(DWORD32(parg16->f2), lpwhdr); /* ** GETMIDIHDR16 can return NULL, in which case we should set ** lpwhdr to NULL too and call midiOutLongMessage only to get the ** correct error code. */ if ( pMidihdr32->pMidihdr32 == NULL ) { lpwhdr = NULL; } ul = GETWORD16( (*mmAPI)( HMIDIOUT32(parg16->f1), lpwhdr, UINT32(parg16->f3) ) ); /* ** If the call fails we need to free the memory we malloc'd ** above, as the callback that would have freed it will never ** get called. ** */ if ( ul == MMSYSERR_NOERROR ) { /* ** Make sure we reflect any changes that midiOutLongMessage did ** to the MIDIHDR back to 16 bit land. ** ** This is important because some apps poll the ** MHDR_DONE bit !! */ COPY_MIDIOUTHDR16_FLAGS( pMidihdr32->pMidihdr32, pMidihdr32->Midihdr ); } else { #if DBG AllocMidiCount--; dprintf2(( "M<< \t%8X (%d)", pMidihdr32, AllocMidiCount )); #endif free_w( pMidihdr32 ); } } else { ul = MMSYSERR_NOMEM; } } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutReset * * This function turns off all notes on al MIDI channels for the specified * MIDI output deice. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutReset(PVDMFRAME pFrame) { register PMIDIOUTRESET16 parg16; static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "midiOutReset", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTRESET16), parg16); trace_midi(( "midiOutReset( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1) )); trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutGetVolume * * This function returns the current volume setting of a MIDI output device. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutGetVolume(PVDMFRAME pFrame) { register PMIDIOUTGETVOLUME16 parg16; static FARPROC mmAPI = NULL; ULONG ul; LPDWORD lpdwVolume; DWORD dwVolume; GET_MULTIMEDIA_API( "midiOutGetVolume", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTGETVOLUME16), parg16); trace_midi(( "midiOutGetVolume( %x, %x )", INT32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( INT32(parg16->f1), &dwVolume )); if ( ul == MMSYSERR_NOERROR ) { MMGETOPTPTR( parg16->f2, sizeof(DWORD), lpdwVolume); if ( lpdwVolume ) { STOREDWORD ( *lpdwVolume, dwVolume ); FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(DWORD), lpdwVolume ); FREEVDMPTR ( lpdwVolume ); } else { ul = MMSYSERR_INVALPARAM; } } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutSetVolume * * This function sets the volume of a MIDI output device. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutSetVolume(PVDMFRAME pFrame) { register PMIDIOUTSETVOLUME16 parg16; static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "midiOutSetVolume", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTSETVOLUME16), parg16); trace_midi(( "midiOutSetVolume( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( INT32(parg16->f1), DWORD32(parg16->f2) )); trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutCachePatches * * This function requests that an internal MIDI synthesizer device preload a * specified set of patches. Some synthesizers are not capable of keeping all * patches loaded simultaneously and must load data from disk when they receive * MIDI program change messages. Caching patches ensures specified patches are * immediately available. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutCachePatches(PVDMFRAME pFrame) { register PMIDIOUTCACHEPATCHES16 parg16; static FARPROC mmAPI = NULL; ULONG ul = MMSYSERR_INVALPARAM; LPPATCHARRAY lppa1; GET_MULTIMEDIA_API( "midiOutCachePatches", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTCACHEPATCHES16), parg16); trace_midi(( "midiOutCachePatches( %x, %x, %x, %x )", WORD32( parg16->f1 ), UINT32( parg16->f2 ), DWORD32( parg16->f3 ), UINT32( parg16->f4 ) )); /* ** GETMISCPTR checks that parg16->f3 is not zero so we need not bother. */ GETMISCPTR( DWORD32( parg16->f3 ), lppa1 ); if ( lppa1 ) { ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), UINT32(parg16->f2), lppa1, UINT32(parg16->f4) )); FREEMISCPTR( lppa1 ); } else { dprintf1(( "WMM32midiOutCachePatches passed a NULL pointer" )); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutCacheDrumPatches * * This function requests that an internal MIDI synthesizer device preload a * specified set of key-based percussion patches. Some synthesizers are not * capable of keeping all percussion patches loaded simultaneously. Caching * patches ensures specified patches are immediately available. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutCacheDrumPatches(PVDMFRAME pFrame) { register PMIDIOUTCACHEDRUMPATCHES16 parg16; static FARPROC mmAPI = NULL; ULONG ul = MMSYSERR_INVALPARAM; LPKEYARRAY lpka1; GET_MULTIMEDIA_API( "midiOutCacheDrumPatches", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTCACHEDRUMPATCHES16), parg16); trace_midi(( "midiOutCacheDrumPatches( %x, %x, %x, %x )", WORD32( parg16->f1 ), UINT32( parg16->f2 ), DWORD32( parg16->f3 ), UINT32( parg16->f4 ) )); GETMISCPTR( DWORD32( parg16->f3 ), lpka1 ); if ( lpka1 ) { ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), UINT32(parg16->f2), lpka1, UINT32(parg16->f4) ) ); FREEMISCPTR(lpka1); } else { dprintf1(( "WMM32midiOutCacheDrumPatches passed a NULL pointer" )); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutGetID * * This function gets the device ID for a MIDI output device. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutGetID(PVDMFRAME pFrame) { register PMIDIOUTGETID16 parg16; static FARPROC mmAPI = NULL; ULONG ul; UINT dwDeviceID32; LPWORD lpwDeviceID16; GET_MULTIMEDIA_API( "midiOutGetID", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTGETID16), parg16); trace_midi(( "midiOutGetID( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( (HMIDIOUT)HMIDIOUT32(parg16->f1), &dwDeviceID32 )); /* ** Only copy the ID back to 16 bit space if the call was sucessful ** */ if ( ul == MMSYSERR_NOERROR ) { MMGETOPTPTR( parg16->f2, sizeof(WORD), lpwDeviceID16 ); if ( lpwDeviceID16 ) { STOREWORD ( *lpwDeviceID16, dwDeviceID32 ); FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(WORD), lpwDeviceID16 ); FREEVDMPTR ( lpwDeviceID16 ); } else { ul = MMSYSERR_INVALPARAM; } } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiOutMessage * * This function sends a message to the specified MIDI output device. * \**********************************************************************/ ULONG FASTCALL WMM32midiOutMessage(PVDMFRAME pFrame) { register PMIDIOUTMESSAGE3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "midiOutMessage", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTMESSAGE16), parg16); trace_midi(( "midiOutMessage( %x, %x, %x, %x )", WORD32( parg16->f1 ), UINT32( parg16->f2 ), DWORD32( parg16->f3 ), DWORD32( parg16->f4 ) )); if ( (UINT32(parg16->f2) >= DRV_BUFFER_LOW) && (UINT32(parg16->f2) <= DRV_BUFFER_HIGH) ) { LPDWORD lpdwParam1; GETMISCPTR(parg16->f3, lpdwParam1); ul = GETDWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), UINT32(parg16->f2), (DWORD)lpdwParam1, DWORD32(parg16->f4))); FREEMISCPTR(lpdwParam1); } else { ul = GETDWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), MAKELONG( WORD32(parg16->f2), 0xFFFF ), DWORD32(parg16->f3), DWORD32(parg16->f4) )); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /* --------------------------------------------------------------------- ** MIDI Input API's ** --------------------------------------------------------------------- */ /**********************************************************************\ * * WMM32midiInGetNumDevs * * This function retrieves the number of MIDI input devices in the system. * \**********************************************************************/ ULONG FASTCALL WMM32midiInGetNumDevs(PVDMFRAME pFrame) { static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "midiInGetNumDevs", mmAPI, MMSYSERR_NODRIVER ); UNREFERENCED_PARAMETER(pFrame); trace_midi(( "midiInGetNumDevs()" )); ul = GETWORD16((*mmAPI)() ); trace_midi(( "-> %ld\n", ul )); RETURN(ul); } /**********************************************************************\ * * WMM32midiInGetDevCaps * * This function queries a specified MIDI input device to determine its * capabilities. * \**********************************************************************/ ULONG FASTCALL WMM32midiInGetDevCaps(PVDMFRAME pFrame) { ULONG ul; MIDIINCAPS midiincaps1; register PMIDIINGETDEVCAPS16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInGetDevCapsA", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINGETDEVCAPS16), parg16); trace_midi(( "midiInGetDevCaps( %x, %x, %x )", INT32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); if ( UINT32( parg16->f3 ) == 0 ) { ul = MMSYSERR_NOERROR; } else { ul = GETWORD16((*mmAPI)(INT32(parg16->f1), &midiincaps1, sizeof(MIDIINCAPS) ) ); /* ** This must now thunk the ENTIRE structure, then copy parg16->f3 ** bytes onto the "real" structure in the app, but only if the ** call returned success. */ if ( ul == MMSYSERR_NOERROR ) { ul = PUTMIDIINCAPS16( parg16->f2, &midiincaps1, UINT32(parg16->f3) ); } } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInGetErrorText * * This function retrieves a textual description of the error identified by the * specified error number. * \**********************************************************************/ ULONG FASTCALL WMM32midiInGetErrorText(PVDMFRAME pFrame) { register PMIDIINGETERRORTEXT16 parg16; ULONG ul = MMSYSERR_NOERROR; PSZ pszText; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInGetErrorTextA", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR( pFrame, sizeof(MIDIINGETERRORTEXT16), parg16 ); trace_midi(( "midiInGetErrorText( %x, %x, %x )", UINT32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** Test against a zero length string and a NULL pointer. If 0 is passed ** as the buffer length then the manual says we should return ** MMSYSERR_NOERR. */ MMGETOPTPTR( parg16->f2, UINT32(parg16->f3), pszText ); if ( pszText != NULL ) { ul = GETWORD16( (*mmAPI)( UINT32(parg16->f1), pszText, UINT32(parg16->f3) ) ); FLUSHVDMPTR( DWORD32(parg16->f2), UINT32(parg16->f3), pszText); FREEVDMPTR( pszText ); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInOpen * * This function opens a specified MIDI input device. * \***********************************************************************/ ULONG FASTCALL WMM32midiInOpen(PVDMFRAME pFrame) { ULONG ul=0; UINT uDevID; PINSTANCEDATA pInstanceData; LPHMIDIIN lpHMidiIn; // pointer to handle in 16 bit app space HMIDIIN Hand32; // 32bit handle register PMIDIINOPEN16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInOpen", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINOPEN16), parg16); trace_midi(( "midiInOpen( %x, %x, %x, %x, %x )", DWORD32( parg16->f1 ), INT32 ( parg16->f2 ), DWORD32( parg16->f3 ), DWORD32( parg16->f4 ), DWORD32( parg16->f5 ) )); /* ** Get the device ID. We use INT32 here not UINT32 to make sure that ** negative values (such as MIDI_MAPPER (-1)) get thunked correctly. */ uDevID = (UINT)INT32(parg16->f2); /* ** Map the 16 bit pointer is one was specified. */ MMGETOPTPTR( parg16->f1, sizeof(HMIDIIN), lpHMidiIn ); if ( lpHMidiIn ) { /* ** Create InstanceData block to be used by our callback routine. ** ** NOTE: Although we malloc it here we don't free it. ** This is not a mistake - it must not be freed before the ** callback routine has used it - so it does the freeing. ** ** If the malloc fails we bomb down to the bottom, ** set ul to MMSYSERR_NOMEM and exit gracefully. ** ** We always have a callback functions. This is to ensure that ** the MIDIHDR structure keeps getting copied back from ** 32 bit space to 16 bit, as it contains flags which ** applications are liable to keep checking. */ if ( pInstanceData = malloc_w(sizeof(INSTANCEDATA) ) ) { dprintf2(( "WM32midiInOpen: Allocated instance buffer at %8X", pInstanceData )); pInstanceData->dwCallback = DWORD32(parg16->f3); pInstanceData->dwCallbackInstance = DWORD32(parg16->f4); pInstanceData->dwFlags = DWORD32(parg16->f5); ul = GETWORD16((*mmAPI)( &Hand32, uDevID, (DWORD)W32CommonDeviceOpen, (DWORD)pInstanceData, CALLBACK_FUNCTION )); } else { ul = (ULONG)MMSYSERR_NOMEM; } /* ** If the call returns success update the 16 bit handle, ** otherwise don't, and free the memory we malloc'd earlier, as ** the callback that would have freed it will never get callled. */ if ( ul == MMSYSERR_NOERROR ) { HMIDIIN16 Hand16 = GETHMIDIIN16(Hand32); trace_midi(( "Handle -> %x", Hand16 )); STOREWORD ( *lpHMidiIn, Hand16 ); FLUSHVDMPTR( DWORD32(parg16->f1), sizeof(HMIDIIN), lpHMidiIn ); } /* ** We only free the memory if we actually allocated any and the ** 32 bit call failed. */ else if ( pInstanceData ) { free_w(pInstanceData); } /* ** Regardless of sucess or failure we need to free the pointer ** to the 16 bit MidiIn handle. */ FREEVDMPTR ( lpHMidiIn ); } else { ul = MMSYSERR_INVALPARAM; } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInClose * * This function closes the specified MIDI input device. * \**********************************************************************/ ULONG FASTCALL WMM32midiInClose(PVDMFRAME pFrame) { ULONG ul; register PMIDIINCLOSE16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInClose", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINCLOSE16), parg16); trace_midi(( "midiInClose( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)(HMIDIIN32(parg16->f1) ) ); trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInPrepareHeader * * This function prepares the specified midiform header. * \**********************************************************************/ ULONG FASTCALL WMM32midiInPrepareHeader(PVDMFRAME pFrame) { register PMIDIOUTPREPAREHEADER3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; MIDIHDR midihdr; GET_MULTIMEDIA_API( "midiInPrepareHeader", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTPREPAREHEADER3216), parg16); trace_midi(( "midiInPrepareHeader( %x %x %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), WORD32( parg16->f3 ) )); GETMIDIHDR16(parg16->f2, &midihdr); ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), &midihdr, WORD32(parg16->f3) ) ); /* ** Only update the 16 bit structure if the call returns success ** */ if ( !ul ) { PUTMIDIHDR16(parg16->f2, &midihdr); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInUnprepareHeader * * This function prepares the specified midiform header. * This function cleans up the preparation performed by midiInPrepareHeader. * The function must be called after the device driver has finished with a * data block. You must call this function before freeing the data buffer. * \**********************************************************************/ ULONG FASTCALL WMM32midiInUnprepareHeader(PVDMFRAME pFrame) { register PMIDIOUTUNPREPAREHEADER3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; MIDIHDR midihdr; GET_MULTIMEDIA_API( "midiInUnprepareHeader", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIOUTUNPREPAREHEADER3216), parg16); trace_midi(( "midiInUnprepareHeader( %x %x %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), WORD32( parg16->f3 ) )); GETMIDIHDR16(parg16->f2, &midihdr); ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), &midihdr, WORD32(parg16->f3) ) ); /* ** Only update the 16 bit structure if the call returns success */ if (!ul) { PUTMIDIHDR16(parg16->f2, &midihdr); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInAddBuffer * * This function sends an input buffer to a specified opened MIDI input device. * When the buffer is filled, it is sent back to the application. Input buffers * are used only for system exclusive messages. * \**********************************************************************/ ULONG FASTCALL WMM32midiInAddBuffer(PVDMFRAME pFrame) { ULONG ul; PMIDIHDR32 pMidihdr32; register PMIDIINADDBUFFER16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInAddBuffer", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINADDBUFFER16), parg16); trace_midi(( "midiInAddBuffer( %x, %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the given size of the MIDIHDR structure is too small ** or the lphdr is invalid return an error ** */ if ( UINT32(parg16->f3) < sizeof(MIDIHDR16) || HIWORD( DWORD32(parg16->f2) ) == 0 ) { ul = (ULONG)MMSYSERR_INVALPARAM; } else { if (pMidihdr32 = malloc_w(sizeof(MIDIHDR32) ) ) { PMIDIHDR lpwhdr; #if DBG AllocMidiCount++; dprintf2(( "M>> %8X (%d)", pMidihdr32, AllocMidiCount )); #endif /* Copy across the midi header stuff. Note that lpwhdr (a ** 32 bit ptr to a 32 bit midi header) is used to make the ** pointer stuff a bit less hairy. ** ** pMidihdr32->Midihdr is a 32 bit midi header ** pMidihdr32->pMidihdr16 is a 16 bit ptr to a 16 bit midi header ** pMidihdr32->pMidihdr32 is a 32 bit ptr to a 16 bit midi header */ lpwhdr = &(pMidihdr32->Midihdr); pMidihdr32->pMidihdr16 = (PMIDIHDR16)DWORD32(parg16->f2); pMidihdr32->pMidihdr32 = GETMIDIHDR16(DWORD32(parg16->f2), lpwhdr); /* ** GETMIDIHDR16 can return NULL, in which case we should set ** lpwhdr to NULL too and call midiInAddBuffer only to get the ** correct error code. */ if ( pMidihdr32->pMidihdr32 == NULL ) { lpwhdr = NULL; } ul = GETWORD16((*mmAPI)( HMIDIIN32(parg16->f1), lpwhdr, UINT32(parg16->f3) )); /* ** If the call fails we need to free the memory we malloc'd ** above, as the callback that would have freed it will never ** get called. ** */ if ( ul == MMSYSERR_NOERROR ) { /* ** Make sure we reflect any changes that midiInAddBuffer did ** to the MIDIHDR back to 16 bit land. ** ** This is important because some apps poll the ** MHDR_DONE bit !! */ COPY_MIDIINHDR16_FLAGS( pMidihdr32->pMidihdr32, pMidihdr32->Midihdr ); } else { #if DBG AllocMidiCount--; dprintf2(( "M<< \t%8X (%d)", pMidihdr32, AllocMidiCount )); #endif free_w( pMidihdr32 ); } } else { ul = (ULONG)MMSYSERR_NOMEM; } } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInStart * * This function starts MIDI input on the specified MIDI input device. * \**********************************************************************/ ULONG FASTCALL WMM32midiInStart(PVDMFRAME pFrame) { ULONG ul; register PMIDIINSTART16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInStart", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINSTART16), parg16); trace_midi(( "midiInStart( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)(HMIDIIN32(parg16->f1) ) ); trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInStop * * This function terminates MIDI input on the specified MIDI input device. * \**********************************************************************/ ULONG FASTCALL WMM32midiInStop(PVDMFRAME pFrame) { ULONG ul; register PMIDIINSTOP16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInStop", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINSTOP16), parg16); trace_midi(( "midiInStop( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)(HMIDIIN32(parg16->f1) ) ); trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInReset * * This function stops input on a given MIDI input device and marks all pending * input buffers as done. * \**********************************************************************/ ULONG FASTCALL WMM32midiInReset(PVDMFRAME pFrame) { ULONG ul; register PMIDIINRESET16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInReset", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINRESET16), parg16); trace_midi(( "midiInReset( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)(HMIDIIN32(parg16->f1) ) ); trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInGetID * * This function gets the device ID for a MIDI input device. * \**********************************************************************/ ULONG FASTCALL WMM32midiInGetID(PVDMFRAME pFrame) { register PMIDIINGETID16 parg16; static FARPROC mmAPI = NULL; ULONG ul; UINT dwDeviceID32; LPWORD lpwDeviceID16; GET_MULTIMEDIA_API( "midiInGetID", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINGETID16), parg16); trace_midi(( "midiInGetID( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( HMIDIIN32(parg16->f1), &dwDeviceID32 )); /* ** Only copy the ID back to 16 bit space if the call was sucessful ** */ if ( ul == MMSYSERR_NOERROR ) { MMGETOPTPTR( parg16->f2, sizeof(WORD), lpwDeviceID16 ); if ( lpwDeviceID16 ) { STOREWORD ( *lpwDeviceID16, dwDeviceID32 ); FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(WORD), lpwDeviceID16 ); FREEVDMPTR ( lpwDeviceID16 ); } else { ul = MMSYSERR_INVALPARAM; } } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32midiInMessage * * This function sends a message to the specified MIDI input device. * \**********************************************************************/ ULONG FASTCALL WMM32midiInMessage(PVDMFRAME pFrame) { ULONG ul; register PMIDIINMESSAGE3216 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "midiInMessage", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(MIDIINMESSAGE16), parg16); trace_midi(( "midiInMessage( %x, %x, %x, %x )", WORD32( parg16->f1 ), UINT32( parg16->f2 ), DWORD32( parg16->f3 ), DWORD32( parg16->f4 ) )); if ( (UINT32(parg16->f2) >= DRV_BUFFER_LOW) && (UINT32(parg16->f2) <= DRV_BUFFER_HIGH) ) { LPDWORD lpdwParam1; GETMISCPTR(parg16->f3, lpdwParam1); ul = GETDWORD16((*mmAPI)( HMIDIIN32(parg16->f1), UINT32(parg16->f2), (DWORD)lpdwParam1, DWORD32(parg16->f4))); FREEMISCPTR(lpdwParam1); } else { ul = GETDWORD16((*mmAPI)( HMIDIIN32(parg16->f1), MAKELONG( WORD32(parg16->f2), 0xFFFF ), DWORD32(parg16->f3), DWORD32(parg16->f4) )); } trace_midi(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /* --------------------------------------------------------------------- ** WAVE Output API's ** --------------------------------------------------------------------- */ /**********************************************************************\ * * WMM32waveOutGetNumDevs * * This function retrieves the number of waveform output devices present in the * system. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutGetNumDevs(PVDMFRAME pFrame) { static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "waveOutGetNumDevs", mmAPI, MMSYSERR_NODRIVER ); trace_wave(( "waveOutGetNumDevs()" )); ul = GETWORD16((*mmAPI)() ); trace_wave(( "-> %ld\n", ul )); RETURN(ul); UNREFERENCED_PARAMETER(pFrame); } /**********************************************************************\ * * WMM32waveOutGetDevCaps * * This function queries a specified waveform device to determine its * capabilities. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutGetDevCaps(PVDMFRAME pFrame) { register PWAVEOUTGETDEVCAPS16 parg16; static FARPROC mmAPI = NULL; ULONG ul; WAVEOUTCAPS waveoutcaps; GET_MULTIMEDIA_API( "waveOutGetDevCapsA", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTGETDEVCAPS16), parg16); trace_wave(( "waveOutGetDevCaps( %x, %x, %x )", INT32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the size parameter was zero return straight away. Note that this ** is not an error. */ if ( UINT32( parg16->f3 ) == 0 ) { ul = MMSYSERR_NOERROR; } else { ul = GETWORD16((*mmAPI)( INT32(parg16->f1), &waveoutcaps, sizeof(WAVEOUTCAPS) )); /* ** Don't update the 16 bit structure if the call failed ** */ if ( ul == MMSYSERR_NOERROR ) { ul = PUTWAVEOUTCAPS16(parg16->f2, &waveoutcaps, UINT32(parg16->f3)); } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutGetErrorText * * This function retrieves a textual description of the error identified by the * specified error number. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutGetErrorText(PVDMFRAME pFrame) { register PWAVEOUTGETERRORTEXT16 parg16; static FARPROC mmAPI = NULL; ULONG ul = MMSYSERR_NOERROR; PSZ pszText; GET_MULTIMEDIA_API( "waveOutGetErrorTextA", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTGETERRORTEXT16), parg16); trace_wave(( "waveOutGetErrorText( %x, %x, %x )", UINT32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** Test against a zero length string and a NULL pointer. If 0 is passed ** as the buffer length then the manual says we should return ** MMSYSERR_NOERR. MMGETOPTPTR only returns a pointer if parg16->f2 is ** not NULL. */ MMGETOPTPTR( parg16->f2, UINT32(parg16->f3), pszText ); if ( pszText != NULL ) { ul = GETWORD16( (*mmAPI)( UINT32(parg16->f1), pszText, UINT32(parg16->f3) ) ); FLUSHVDMPTR( DWORD32(parg16->f2), UINT32(parg16->f3), pszText); FREEVDMPTR(pszText); } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutOpen * * This function opens a specified waveform output device for playback. * * As of November 1992 we map the 16 bit Wave Format data directly to the * the 32 bit side, no thunking of the parameters is performed. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutOpen(PVDMFRAME pFrame) { ULONG ul = MMSYSERR_NOERROR; UINT uDevID; PINSTANCEDATA pInstanceData = NULL; DWORD dwFlags; PWAVEFORMAT16 lpWaveformData; LPHWAVEOUT lphWaveOut = NULL; // pointer to handle in 16 bit app space HWAVEOUT Hand32; // 32bit handle register PWAVEOUTOPEN16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveOutOpen", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTOPEN16), parg16); trace_wave(( "waveOutOpen( %x, %x, %x, %x, %x, %x )", DWORD32( parg16->f1 ), INT32 ( parg16->f2 ), DWORD32( parg16->f3 ), DWORD32( parg16->f4 ), DWORD32( parg16->f5 ), DWORD32( parg16->f6 ) )); /* ** Get the device ID. We use INT32 here not UINT32 to make sure that ** negative values (such as WAVE_MAPPER (-1)) get thunked correctly. ** Also, get the flags to be used. */ uDevID = (UINT)INT32(parg16->f2); dwFlags = DWORD32(parg16->f6); /* ** Get a pointer to the WAVEFORMAT structure. Because the format of this ** structure is exactly the same in 32 and 16 bit land I will use ** GETMISCPTR to get a generic pointer to the data. The stuff being ** pointed to could be full of unaligned WORDs, but the 32 bit code ** would have to cope with this anyway. */ GETMISCPTR( parg16->f3, lpWaveformData ); if ( lpWaveformData == (PWAVEFORMAT16)NULL ) { ul = (ULONG)MMSYSERR_INVALPARAM; goto exit_function; } /* ** We don't need a callback routine when the WAVE_FORMAT_QUERY flag ** is specified. */ if ( !(dwFlags & WAVE_FORMAT_QUERY) ) { /* ** Map the 16 bit pointer is one was specified. */ MMGETOPTPTR( parg16->f1, sizeof(HWAVEOUT), lphWaveOut ); if ( lphWaveOut == NULL ) { ul = MMSYSERR_INVALPARAM; } /* ** Create InstanceData block to be used by our callback routine. ** ** NOTE: Although we malloc it here we don't free it. ** This is not a mistake - it must not be freed before the ** callback routine has used it - so it does the freeing. ** ** If the malloc fails we bomb down to the bottom, ** set ul to MMSYSERR_NOMEM and exit gracefully. ** ** We always have a callback functions. This is to ensure that ** the WAVEHDR structure keeps getting copied back from ** 32 bit space to 16 bit, as it contains flags which ** applications are liable to keep checking. */ else if ( pInstanceData = malloc_w(sizeof(INSTANCEDATA) ) ) { DWORD dwNewFlags = CALLBACK_FUNCTION; dprintf2(( "WM32waveOutOpen: Allocated instance buffer at %8X", pInstanceData )); pInstanceData->dwCallback = DWORD32(parg16->f4);; pInstanceData->dwCallbackInstance = DWORD32(parg16->f5); pInstanceData->dwFlags = dwFlags; dwNewFlags |= (dwFlags & WAVE_ALLOWSYNC); ul = GETWORD16((*mmAPI)( &Hand32, uDevID, (LPWAVEFORMAT)lpWaveformData, (DWORD)W32CommonDeviceOpen, (DWORD)pInstanceData, dwNewFlags )); /* ** If the call returns success update the 16 bit handle, ** otherwise don't, and free the memory we malloc'd earlier, as ** the callback that would have freed it will never get callled. */ if ( ul == MMSYSERR_NOERROR ) { HWAVEOUT16 Hand16 = GETHWAVEOUT16(Hand32); trace_wave(( "Handle -> %x", Hand16 )); STOREWORD ( *lphWaveOut, Hand16); FLUSHVDMPTR( DWORD32(parg16->f1), sizeof(HWAVEOUT), lphWaveOut ); } else { dprintf2(( "WM32waveOutOpen: Freeing instance buffer at %8X", pInstanceData )); free_w(pInstanceData); } /* ** Regardless of sucess or failure we need to free the pointer ** to the 16 bit WaveOut handle. */ FREEVDMPTR ( lphWaveOut ); } else { ul = (ULONG)MMSYSERR_NOMEM; } } else { ul = GETWORD16((*mmAPI)( NULL, uDevID, (LPWAVEFORMAT)lpWaveformData, DWORD32(parg16->f4), DWORD32(parg16->f5), dwFlags )); } /* ** Regardless of sucess or failure we need to free the pointer to the ** 16 bit WaveFormatData. */ FREEMISCPTR( lpWaveformData ); exit_function: trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutClose * * This function closes the specified waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutClose(PVDMFRAME pFrame) { register PWAVEOUTCLOSE16 parg16; static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "waveOutClose", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTCLOSE16), parg16); trace_wave(( "waveOutClose( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutPrepareHeader * * This function prepares the specified waveform header. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutPrepareHeader(PVDMFRAME pFrame) { register PWAVEOUTPREPAREHEADER3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; WAVEHDR wavehdr; GET_MULTIMEDIA_API( "waveOutPrepareHeader", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTPREPAREHEADER3216), parg16); trace_wave(( "waveOutPrepareHeader( %x %x %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), WORD32( parg16->f3 ) )); GETWAVEHDR16(parg16->f2, &wavehdr); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &wavehdr, WORD32(parg16->f3) ) ); /* ** Only update the 16 bit structure if the call returns success ** */ if ( !ul ) { PUTWAVEHDR16(parg16->f2, &wavehdr); } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutUnprepareHeader * * This function prepares the specified waveform header. * This function cleans up the preparation performed by waveOutPrepareHeader. * The function must be called after the device driver has finished with a * data block. You must call this function before freeing the data buffer. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutUnprepareHeader(PVDMFRAME pFrame) { register PWAVEOUTUNPREPAREHEADER3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; WAVEHDR wavehdr; GET_MULTIMEDIA_API( "waveOutUnprepareHeader", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTUNPREPAREHEADER3216), parg16); trace_wave(( "waveOutUnprepareHeader( %x %x %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), WORD32( parg16->f3 ) )); GETWAVEHDR16(parg16->f2, &wavehdr); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &wavehdr, WORD32(parg16->f3) ) ); /* ** Only update the 16 bit structure if the call returns success */ if (!ul) { PUTWAVEHDR16(parg16->f2, &wavehdr); } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutWrite * * This function sends a data block to the specified waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutWrite(PVDMFRAME pFrame) { register PWAVEOUTWRITE16 parg16; static FARPROC mmAPI = NULL; ULONG ul; PWAVEHDR32 pWavehdr32; GET_MULTIMEDIA_API( "waveOutWrite", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTWRITE16), parg16); trace_wave(( "waveOutWrite( %x, %x, %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the given size of the WAVEHDR structure is too small ** or the lphdr is invalid return an error ** */ if ( UINT32(parg16->f3) < sizeof(WAVEHDR16) || HIWORD( DWORD32(parg16->f2) ) == 0 ) { ul = (ULONG)MMSYSERR_INVALPARAM; } else { if ( pWavehdr32 = malloc_w( sizeof(WAVEHDR32) ) ) { PWAVEHDR lpwhdr; /* used to simplify ptr stuff later on */ #if DBG AllocWaveCount++; dprintf2(( "W>> %8X (%d)", pWavehdr32, AllocWaveCount )); #endif /* Copy across the wave header stuff. Note that lpwhdr (a ** 32 bit ptr to a 32 bit wave header) is used to make the ** pointer stuff a bit less hairy. ** ** pWavehdr32->Wavehdr is a 32 bit wave header ** pWavehdr32->pWavehdr16 is a 16 bit ptr to a 16 bit wave header ** pWavehdr32->pWavehdr32 is a 32 bit ptr to a 16 bit wave header */ lpwhdr = &(pWavehdr32->Wavehdr); pWavehdr32->pWavehdr16 = (PWAVEHDR16)DWORD32(parg16->f2); pWavehdr32->pWavehdr32 = GETWAVEHDR16(DWORD32(parg16->f2), lpwhdr); /* ** GETWAVEHDR16 can return NULL, in which case we should set ** lpwhdr to NULL too and call waveOutWrite only to get the ** correct error code. */ if ( pWavehdr32->pWavehdr32 == NULL ) { lpwhdr = NULL; } ul = GETWORD16( (*mmAPI)( HWAVEOUT32(parg16->f1), lpwhdr, UINT32(parg16->f3) ) ); /* If the call fails we need to free the memory we malloc'd ** above, as the callback that would have freed it will never ** get called. */ if ( ul == MMSYSERR_NOERROR ) { /* Make sure we reflect any changes that waveOutWrite did ** to the WAVEHDR back to 16 bit land. ** ** This is important because some apps (waveedit) poll the ** WHDR_DONE bit !! */ COPY_WAVEOUTHDR16_FLAGS( pWavehdr32->pWavehdr32, pWavehdr32->Wavehdr ); } else { #if DBG AllocWaveCount--; dprintf2(( "W<< \t%8X (%d)", pWavehdr32, AllocWaveCount )); #endif free_w( pWavehdr32 ); } } else { ul = (ULONG)MMSYSERR_NOMEM; } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutPause * * This function pauses playback on a specified waveform output device. The * current playback position is saved. Use wavOutRestart to resume playback from * the current playback position. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutPause(PVDMFRAME pFrame) { ULONG ul; register PWAVEOUTPAUSE16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveOutPause", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTPAUSE16), parg16); trace_wave(( "waveOutGetPause( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutRestart * * This function restarts a paused waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutRestart(PVDMFRAME pFrame) { ULONG ul; register PWAVEOUTRESTART16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveOutRestart", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTRESTART16), parg16); trace_wave(( "waveOutRestart( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutReset * * This function stops playback on a given waveform output device and resets the * current position to 0. All pending playback buffers are marked as done and * returned to the application. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutReset(PVDMFRAME pFrame) { ULONG ul; register PWAVEOUTRESET16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveOutReset", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTRESET16), parg16); trace_wave(( "waveOutReset( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16( (*mmAPI)( HWAVEOUT32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutGetPosition * * This function retrieves the current palyback position of the specified * waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutGetPosition(PVDMFRAME pFrame) { register PWAVEOUTGETPOSITION16 parg16; static FARPROC mmAPI = NULL; MMTIME mmtime; ULONG ul = MMSYSERR_INVALPARAM; GET_MULTIMEDIA_API( "waveOutGetPosition", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTGETPOSITION16), parg16); trace_wave(( "waveOutGetPosition( %x, %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the given size of the MMTIME structure is too small return an error ** ** There is a problem here on MIPS. For some reason the MIPS ** compiler thinks a MMTIME16 structure is 10 bytes big. We ** have a pragma in wowmmed.h to align this structure on byte ** boundaries therefore I guess this is a compiler bug! ** ** If the input structure is not large enough we return immediately */ #ifdef MIPS_COMPILER_PACKING_BUG if ( UINT32(parg16->f3) >= 8 ) { #else if ( UINT32(parg16->f3) >= sizeof(MMTIME16) ) { #endif ul = GETMMTIME16( parg16->f2, &mmtime); if ( ul == MMSYSERR_NOERROR ) { ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &mmtime, sizeof(MMTIME) )); /* ** Only update the 16 bit structure if the call returns success ** */ if ( ul == MMSYSERR_NOERROR ) { ul = PUTMMTIME16( parg16->f2, &mmtime); } } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutGetPitch * * This function queries the current pitch setting of a waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutGetPitch(PVDMFRAME pFrame) { register PWAVEOUTGETPITCH16 parg16; static FARPROC mmAPI = NULL; ULONG ul = MMSYSERR_INVALPARAM; LPDWORD lpdwPitch; DWORD dwPitch; GET_MULTIMEDIA_API( "waveOutGetPitch", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTGETPITCH16), parg16); trace_wave(( "waveOutGetPitch( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &dwPitch )); if ( ul == MMSYSERR_NOERROR ) { MMGETOPTPTR( parg16->f2, sizeof(DWORD), lpdwPitch); if ( lpdwPitch ) { STOREDWORD ( *lpdwPitch, dwPitch ); FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(DWORD), lpdwPitch ); FREEVDMPTR ( lpdwPitch ); } else { ul = MMSYSERR_INVALPARAM; } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutSetPitch * * This function sets the pitch of a waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutSetPitch(PVDMFRAME pFrame) { register PWAVEOUTSETPITCH16 parg16; static FARPROC mmAPI = NULL; ULONG ul; GET_MULTIMEDIA_API( "waveOutSetPitch", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTSETPITCH16), parg16); trace_wave(( "waveOutSetPitch( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), DWORD32(parg16->f2) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutGetVolume * * This function queries the current volume setting of a waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutGetVolume(PVDMFRAME pFrame) { register PWAVEOUTGETVOLUME16 parg16; static FARPROC mmAPI = NULL; ULONG ul; LPDWORD lpdwVolume; DWORD dwVolume; GET_MULTIMEDIA_API( "waveOutGetVolume", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTGETVOLUME16), parg16); trace_wave(( "waveOutGetVolume( %x, %x )", INT32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( INT32(parg16->f1), &dwVolume )); if ( ul == MMSYSERR_NOERROR ) { MMGETOPTPTR( parg16->f2, sizeof(DWORD), lpdwVolume); if ( lpdwVolume ) { STOREDWORD ( *lpdwVolume, dwVolume ); FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(DWORD), lpdwVolume ); FREEVDMPTR ( lpdwVolume ); } else { ul = MMSYSERR_INVALPARAM; } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutSetVolume * * This function sets the volume of a waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutSetVolume(PVDMFRAME pFrame) { ULONG ul; register PWAVEOUTSETVOLUME16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveOutSetVolume", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTSETVOLUME16), parg16); trace_wave(( "waveOutSetVolume( %x, %x )", INT32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( INT32(parg16->f1), DWORD32(parg16->f2) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutGetPlaybackRate * * This function queries the current playback rate setting of a waveform output * device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutGetPlaybackRate(PVDMFRAME pFrame) { register PWAVEOUTGETPLAYBACKRATE16 parg16; static FARPROC mmAPI = NULL; ULONG ul; LPDWORD lpdwRate; DWORD dwRate; GET_MULTIMEDIA_API( "waveOutGetPlaybackRate", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTGETPLAYBACKRATE16), parg16); trace_wave(( "waveOutGetPlaybackRate( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &dwRate )); if ( ul == MMSYSERR_NOERROR ) { MMGETOPTPTR( parg16->f2, sizeof(DWORD), lpdwRate ); if ( lpdwRate ) { STOREDWORD ( *lpdwRate, dwRate ); FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(DWORD), lpdwRate ); FREEVDMPTR ( lpdwRate ); } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutSetPlaybackRate * * This function sets the playback rate of a waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutSetPlaybackRate(PVDMFRAME pFrame) { ULONG ul; register PWAVEOUTSETPLAYBACKRATE16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveOutSetPlaybackRate", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTSETPLAYBACKRATE16), parg16); trace_wave(( "waveOutSetPlaybackRate( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), DWORD32(parg16->f2) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutBreakLoop * * This function breaks a loop on a given waveform output device and allows * playback to continue with the next block in the driver list. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutBreakLoop(PVDMFRAME pFrame) { ULONG ul; register PWAVEOUTBREAKLOOP16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveOutBreakLoop", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTBREAKLOOP16), parg16); trace_wave(( "waveOutBreakLoop( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutGetID * * This function gets the device ID for a waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutGetID(PVDMFRAME pFrame) { register PWAVEOUTGETID16 parg16; static FARPROC mmAPI = NULL; ULONG ul; UINT dwDeviceID32; LPWORD lpwDeviceID16; GET_MULTIMEDIA_API( "waveOutGetID", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTGETID16), parg16); trace_wave(( "waveOutGetID( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &dwDeviceID32 )); /* ** Only copy the ID back to 16 bit space if the call was sucessful ** */ if ( ul == MMSYSERR_NOERROR ) { MMGETOPTPTR( parg16->f2, sizeof(WORD), lpwDeviceID16 ); if ( lpwDeviceID16 ) { STOREWORD ( *lpwDeviceID16, dwDeviceID32 ); FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(WORD), lpwDeviceID16 ); FREEVDMPTR ( lpwDeviceID16 ); } else { ul = MMSYSERR_INVALPARAM; } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveOutMessage * * This function send a message to a waveform output device. * \**********************************************************************/ ULONG FASTCALL WMM32waveOutMessage(PVDMFRAME pFrame) { ULONG ul; register PWAVEOUTMESSAGE3216 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveOutMessage", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEOUTMESSAGE16), parg16); trace_wave(( "waveOutMessage( %x, %x, %x, %x )", WORD32( parg16->f1 ), UINT32( parg16->f2 ), DWORD32( parg16->f3 ), DWORD32( parg16->f4 ) )); if ( (UINT32(parg16->f2) >= DRV_BUFFER_LOW) && (UINT32(parg16->f2) <= DRV_BUFFER_HIGH) ) { LPDWORD lpdwParam1; GETMISCPTR(parg16->f3, lpdwParam1); ul = GETDWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), UINT32(parg16->f2), (DWORD)lpdwParam1, DWORD32(parg16->f4) )); FREEMISCPTR(lpdwParam1); } else { ul = GETDWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), MAKELONG( WORD32(parg16->f2), 0xFFFF ), DWORD32(parg16->f3), DWORD32(parg16->f4) )); } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /* --------------------------------------------------------------------- ** WAVE Input API's ** --------------------------------------------------------------------- */ /**********************************************************************\ * * WMM32waveInGetNumDevs * * This function returns the number of waveform input devices. * \**********************************************************************/ ULONG FASTCALL WMM32waveInGetNumDevs(PVDMFRAME pFrame) { ULONG ul; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInGetNumDevs", mmAPI, MMSYSERR_NODRIVER ); UNREFERENCED_PARAMETER(pFrame); trace_wave(( "waveInGetNumDevs()" )); ul = GETWORD16((*mmAPI)() ); trace_wave(( "-> %ld\n", ul )); RETURN(ul); } /**********************************************************************\ * * WMM32waveInGetDevCaps * * This function queries a specified waveform input device to determine its * capabilities. * \**********************************************************************/ ULONG FASTCALL WMM32waveInGetDevCaps(PVDMFRAME pFrame) { ULONG ul; WAVEINCAPS waveincaps1; register PWAVEINGETDEVCAPS16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInGetDevCapsA", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINGETDEVCAPS16), parg16); trace_wave(( "waveInGetDevCaps( %x, %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the size parameter was zero return straight away. Note that this ** is not an error. */ if ( UINT32( parg16->f3 ) == 0 ) { ul = MMSYSERR_NOERROR; } else { ul = GETWORD16((*mmAPI)(INT32(parg16->f1), &waveincaps1, sizeof(WAVEINCAPS) ) ); /* ** Don't update the 16 bit structure if the call failed ** */ if ( ul == MMSYSERR_NOERROR ) { ul = PUTWAVEINCAPS16(parg16->f2, &waveincaps1, UINT32(parg16->f3)); } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInGetErrorText * * This function retrieves a textual description of the error identified by the * specified error number. * \**********************************************************************/ ULONG FASTCALL WMM32waveInGetErrorText(PVDMFRAME pFrame) { ULONG ul = MMSYSERR_NOERROR; PSZ pszText; register PWAVEINGETERRORTEXT16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInGetErrorTextA", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINGETERRORTEXT16), parg16); trace_wave(( "waveInGetErrorText( %x, %x, %x )", UINT32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** Test against a zero length string and a NULL pointer. If 0 is passed ** as the buffer length then the manual says we should return ** MMSYSERR_NOERR. MMGETOPTPTR only returns a pointer if parg16->f2 is ** not NULL. */ MMGETOPTPTR( parg16->f2, UINT32(parg16->f3), pszText ); if ( pszText != NULL ) { ul = GETWORD16((*mmAPI)( UINT32(parg16->f1), pszText, UINT32(parg16->f3) )); FLUSHVDMPTR( DWORD32(parg16->f2), UINT32(parg16->f3), pszText); FREEVDMPTR(pszText); } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInOpen * * This function opens a specified waveform input device for recording. * * As of November 1992 we map the 16 bit Wave Format data directly to the * the 32 bit side, no thunking of the parameters is performed. * * \**********************************************************************/ ULONG FASTCALL WMM32waveInOpen(PVDMFRAME pFrame) { ULONG ul=0; UINT uDevID; PINSTANCEDATA pInstanceData = NULL; DWORD dwFlags; PWAVEFORMAT16 lpWaveformData; LPHWAVEIN lphWaveIn; // pointer to handle in 16 bit app space HWAVEIN Hand32; // 32bit handle register PWAVEINOPEN16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInOpen", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINOPEN16), parg16); trace_wave(( "waveInOpen( %x, %x, %x, %x, %x, %x )", DWORD32( parg16->f1 ), INT32 ( parg16->f2 ), DWORD32( parg16->f3 ), DWORD32( parg16->f4 ), DWORD32( parg16->f5 ), DWORD32( parg16->f6 ) )); /* ** Get the device ID. We use INT32 here not UINT32 to make sure that ** negative values (such as WAVE_MAPPER (-1)) get thunked correctly. */ uDevID = (UINT)INT32(parg16->f2); /* ** Get the flags to be used. */ dwFlags = DWORD32(parg16->f6); /* ** Get a pointer to the WAVEFORMAT structure. Because the format of this ** structure is exactly the same in 32 and 16 bit land I will use ** GETMISCPTR to get a generic pointer to the data. The stuff being ** pointed to could be full of unaligned WORDs, but the 32 bit code ** would have to cope with this anyway. */ GETMISCPTR( DWORD32(parg16->f3), lpWaveformData ); if ( lpWaveformData == (PWAVEFORMAT16)NULL ) { ul = (ULONG)MMSYSERR_INVALPARAM; goto exit_function; } /* ** We don't need a callback routine when the WAVE_FORMAT_QUERY flag ** is specified. */ if ( !( dwFlags & WAVE_FORMAT_QUERY ) ) { /* ** Map the 16 bit pointer is one was specified. */ MMGETOPTPTR( parg16->f1, sizeof(HWAVEIN), lphWaveIn ); if ( lphWaveIn == NULL ) { ul = MMSYSERR_INVALPARAM; } /* ** Create InstanceData block to be used by our callback routine. ** ** NOTE: Although we malloc it here we don't free it. ** This is not a mistake - it must not be freed before the ** callback routine has used it - so it does the freeing. ** ** If the malloc fails we bomb down to the bottom, ** set ul to MMSYSERR_NOMEM and exit gracefully. ** ** We always have a callback functions. This is to ensure that ** the WAVEHDR structure keeps getting copied back from ** 32 bit space to 16 bit, as it contains flags which ** applications are liable to keep checking. */ else if ( pInstanceData = malloc_w(sizeof(INSTANCEDATA) ) ) { DWORD dwNewFlags = CALLBACK_FUNCTION; dprintf2(( "WM32waveInOpen: Allocated instance buffer at %8X", pInstanceData )); pInstanceData->dwCallback = DWORD32(parg16->f4);; pInstanceData->dwCallbackInstance = DWORD32(parg16->f5); pInstanceData->dwFlags = dwFlags; dwNewFlags |= (dwFlags & WAVE_ALLOWSYNC); ul = GETWORD16( (*mmAPI)( &Hand32, uDevID, (LPWAVEFORMAT)lpWaveformData, (DWORD)W32CommonDeviceOpen, (DWORD)pInstanceData, dwNewFlags ) ); /* ** If the call returns success update the 16 bit handle, ** otherwise don't, and free the memory we malloc'd earlier, as ** the callback that would have freed it will never get callled. */ if ( ul == MMSYSERR_NOERROR ) { HWAVEIN16 Hand16 = GETHWAVEIN16(Hand32); trace_wave(( "Handle -> %x", Hand16 )); STOREWORD ( *lphWaveIn, Hand16 ); FLUSHVDMPTR( DWORD32(parg16->f1), sizeof(HWAVEIN), lphWaveIn ); } else { free_w(pInstanceData); } /* ** Regardless of sucess or failure we need to free the pointer ** to the 16 bit WaveIn handle. */ FREEVDMPTR ( lphWaveIn ); } else { ul = (ULONG)MMSYSERR_NOMEM; } } else { ul = GETWORD16( (*mmAPI)( NULL, uDevID, (LPWAVEFORMAT)lpWaveformData, DWORD32(parg16->f4), DWORD32(parg16->f5), dwFlags) ); } /* ** Regardless of sucess or failure we need to free the pointer to the ** 16 bit WaveFormatData. */ FREEMISCPTR( lpWaveformData ); exit_function: trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInClose * * This function closes the specified waveform input device. * \**********************************************************************/ ULONG FASTCALL WMM32waveInClose(PVDMFRAME pFrame) { ULONG ul; register PWAVEINCLOSE16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInClose", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINCLOSE16), parg16); trace_wave(( "waveInClose( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInPrepareHeader * * This function prepares the specified waveform header. * \**********************************************************************/ ULONG FASTCALL WMM32waveInPrepareHeader(PVDMFRAME pFrame) { register PWAVEINPREPAREHEADER3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; WAVEHDR wavehdr; GET_MULTIMEDIA_API( "waveInPrepareHeader", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINPREPAREHEADER3216), parg16); trace_wave(( "waveInPrepareHeader( %x %x %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), WORD32( parg16->f3 ) )); GETWAVEHDR16(parg16->f2, &wavehdr); ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1), &wavehdr, WORD32(parg16->f3) ) ); /* ** Only update the 16 bit structure if the call returns success ** */ if ( !ul ) { PUTWAVEHDR16(parg16->f2, &wavehdr); } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInUnprepareHeader * * This function prepares the specified waveform header. * This function cleans up the preparation performed by waveInPrepareHeader. * The function must be called after the device driver has finished with a * data block. You must call this function before freeing the data buffer. * \**********************************************************************/ ULONG FASTCALL WMM32waveInUnprepareHeader(PVDMFRAME pFrame) { register PWAVEINUNPREPAREHEADER3216 parg16; static FARPROC mmAPI = NULL; ULONG ul; WAVEHDR wavehdr; GET_MULTIMEDIA_API( "waveInUnprepareHeader", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINUNPREPAREHEADER3216), parg16); trace_wave(( "waveInUnprepareHeader( %x %x %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), WORD32( parg16->f3 ) )); GETWAVEHDR16(parg16->f2, &wavehdr); ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1), &wavehdr, WORD32(parg16->f3) ) ); /* ** Only update the 16 bit structure if the call returns success */ if (!ul) { PUTWAVEHDR16(parg16->f2, &wavehdr); } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInAddBuffer * * This function sends an input buffer to a waveform input device. * When the buffer is filled it is sent back to the application. * \**********************************************************************/ ULONG FASTCALL WMM32waveInAddBuffer(PVDMFRAME pFrame) { ULONG ul; PWAVEHDR32 pWavehdr32; register PWAVEINADDBUFFER16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInAddBuffer", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINADDBUFFER16), parg16); trace_wave(( "waveInAddBuffer( %x, %x, %x)", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the given size of the WAVEHDR structure is too small ** or the lphdr is invalid return an error ** */ if ( UINT32(parg16->f3) < sizeof(WAVEHDR16) || HIWORD( DWORD32(parg16->f2) ) == 0 ) { ul = (ULONG)MMSYSERR_INVALPARAM; } else { if (pWavehdr32 = malloc_w(sizeof(WAVEHDR32) ) ) { PWAVEHDR lpwhdr; /* used to simplify ptr stuff later on */ #if DBG AllocWaveCount++; dprintf2(( "W>> %8X (%d)", pWavehdr32, AllocWaveCount )); #endif /* Copy across the wave header stuff. Note that lpwhdr (a ** 32 bit ptr to a 32 bit wave header) is used to make the ** pointer stuff a bit less hairy. ** ** pWavehdr32->Wavehdr is a 32 bit wave header ** pWavehdr32->pWavehdr16 is a 16 bit ptr to a 16 bit wave header ** pWavehdr32->pWavehdr32 is a 32 bit ptr to a 16 bit wave header */ lpwhdr = &(pWavehdr32->Wavehdr); pWavehdr32->pWavehdr16 = (PWAVEHDR16)DWORD32(parg16->f2); pWavehdr32->pWavehdr32 = GETWAVEHDR16(DWORD32(parg16->f2), lpwhdr); /* ** GETWAVEHDR16 can return NULL, in which case we should set ** lpwhdr to NULL too and call waveInAddBuffer only to get the ** correct error code. */ if ( pWavehdr32->pWavehdr32 == NULL ) { lpwhdr = NULL; } ul = GETWORD16( (*mmAPI)( HWAVEIN32(parg16->f1), lpwhdr, UINT32(parg16->f3) ) ); /* ** If the call fails we need to free the memory we malloc'd ** above, as the callback that would have freed it will never ** get called. ** */ if ( ul == MMSYSERR_NOERROR ) { /* ** Make sure we reflect any changes that waveInAddBuffer did ** to the WAVEHDR back to 16 bit land. ** ** This is important because some apps (waveedit) poll the ** WHDR_DONE bit !! */ COPY_WAVEINHDR16_FLAGS( pWavehdr32->pWavehdr32, pWavehdr32->Wavehdr ); } else { #if DBG AllocWaveCount--; dprintf2(( "W<< \t%8X (%d)", pWavehdr32, AllocWaveCount )); #endif free_w( pWavehdr32 ); } } else { ul = (ULONG)MMSYSERR_NOMEM; } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInStart * * This function starts input on the specified waveform input device. * \**********************************************************************/ ULONG FASTCALL WMM32waveInStart(PVDMFRAME pFrame) { ULONG ul; register PWAVEINSTART16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInStart", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINSTART16), parg16); trace_wave(( "waveInStart( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInStop * * This function stops waveform input. * \**********************************************************************/ ULONG FASTCALL WMM32waveInStop(PVDMFRAME pFrame) { ULONG ul; register PWAVEINSTOP16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInStop", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINSTOP16), parg16); trace_wave(( "waveInStop( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInReset * * This function stops input on a given waveform input device and resets the * current position to 0. All pending buffers are marked as done and returned * to the application. * \**********************************************************************/ ULONG FASTCALL WMM32waveInReset(PVDMFRAME pFrame) { ULONG ul; register PWAVEINRESET16 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInReset", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINRESET16), parg16); trace_wave(( "waveInReset( %x )", WORD32( parg16->f1 ) )); ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1) )); trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInGetPosition * * This function retrieves the current input position of the specified waveform * input device. * \**********************************************************************/ ULONG FASTCALL WMM32waveInGetPosition(PVDMFRAME pFrame) { register PWAVEINGETPOSITION16 parg16; MMTIME mmtime; ULONG ul = MMSYSERR_INVALPARAM; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInGetPosition", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINGETPOSITION16), parg16); trace_wave(( "waveInGetPosition( %x, %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ), UINT32( parg16->f3 ) )); /* ** If the given size of the MMTIME structure is too small return an error ** ** There is a problem here on MIPS. For some reason the MIPS ** compiler thinks a MMTIME16 structure is 10 bytes big. We ** have a pragma in wowmmed.h to align this structure on byte ** boundaries therefore I guess this is a compiler bug! ** ** If the input structure is not large enough we return immediately */ #ifdef MIPS_COMPILER_PACKING_BUG if ( UINT32(parg16->f3) >= 8 ) { #else if ( UINT32(parg16->f3) >= sizeof(MMTIME16) ) { #endif ul = GETMMTIME16( parg16->f2, &mmtime ); if ( ul == MMSYSERR_NOERROR ) { ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1), &mmtime, sizeof(MMTIME) )); /* ** Only update the 16 bit structure if the call returns success ** */ if ( ul == MMSYSERR_NOERROR ) { ul = PUTMMTIME16( parg16->f2, &mmtime ); } } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInGetID * * This function gets the device ID for a waveform input device. * \**********************************************************************/ ULONG FASTCALL WMM32waveInGetID(PVDMFRAME pFrame) { register PWAVEINGETID16 parg16; ULONG ul; UINT dwDeviceID32; LPWORD lpwDeviceID16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInGetID", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINGETID16), parg16); trace_wave(( "waveInGetID( %x, %x )", WORD32( parg16->f1 ), DWORD32( parg16->f2 ) )); ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1), &dwDeviceID32 )); /* ** Only copy the ID back to 16 bit space if the call was sucessful ** */ if ( ul == MMSYSERR_NOERROR ) { MMGETOPTPTR( parg16->f2, sizeof(WORD), lpwDeviceID16 ); if ( lpwDeviceID16 ) { STOREWORD ( *lpwDeviceID16, dwDeviceID32 ); FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(WORD), lpwDeviceID16 ); FREEVDMPTR ( lpwDeviceID16 ); } else { ul = MMSYSERR_INVALPARAM; } } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * WMM32waveInMessage * * This function sends a message to a waveform input device. * \**********************************************************************/ ULONG FASTCALL WMM32waveInMessage(PVDMFRAME pFrame) { ULONG ul; register PWAVEINMESSAGE3216 parg16; static FARPROC mmAPI = NULL; GET_MULTIMEDIA_API( "waveInMessage", mmAPI, MMSYSERR_NODRIVER ); GETARGPTR(pFrame, sizeof(WAVEINMESSAGE16), parg16); trace_wave(( "waveInMessage( %x, %x, %x, %x )", WORD32( parg16->f1 ), UINT32( parg16->f2 ), DWORD32( parg16->f3 ), DWORD32( parg16->f4 ) )); if ( (UINT32(parg16->f2) >= DRV_BUFFER_LOW) && (UINT32(parg16->f2) <= DRV_BUFFER_HIGH) ) { LPDWORD lpdwParam1; GETMISCPTR(parg16->f3, lpdwParam1); ul = GETDWORD16((*mmAPI)( HWAVEIN32(parg16->f1), UINT32(parg16->f2), (DWORD)lpdwParam1, DWORD32(parg16->f4) )); FREEMISCPTR(lpdwParam1); } else { ul = GETDWORD16((*mmAPI)( HWAVEIN32(parg16->f1), MAKELONG( WORD32(parg16->f2), 0xFFFF ), DWORD32(parg16->f3), DWORD32(parg16->f4) )); } trace_wave(( "-> %ld\n", ul )); FREEARGPTR(parg16); RETURN(ul); } /**********************************************************************\ * * W32CommonDeviceOpen * * This routine is the callback which is ALWAYS called by wave and midi * functions. This is done to ensure that the XXXXHDR structure keeps * getting copied back from 32 bit space to 16 bit, as it contains flags * which the application is liable to keep checking. * * The way this whole business works is that the wave/midi data stays in 16 * bit space, but the XXXXHDR is copied to the 32 bit side, with the * address of the data thunked accordingly so that Robin's device driver * can still get at the data but we don't have the performance penalty of * copying it back and forth all the time, not least because it is liable * to be rather large... * * It also handles the tidying up of memory which is reserved to store * the XXXXHDR, and the instance data (HWND/Callback address; instance * data; flags) which the xxxxOpen calls pass to this routine, enabling * it to forward messages or call callback as required. * * This routine handles all the messages that get sent from Robin's * driver, and in fact thunks them back to the correct 16 bit form. In * theory there should be no MM_ format messages from the 16 bit side, so * I can zap 'em out of WMSG16. However the 32 bit side should thunk the * mesages correctly and forward them to the 16 bit side and thence to * the app. * * However... I discover that somewhere in the system the wParam Msg * parameter (which is 32 bits in Win32 and 16 bits in Win16) is having * the top 16 bits trashed (zeroed actually). As I pass a 32 bit handle * in it, to be thunked in WMDISP32 back to a 16 bit handle, the loss of * the top 16 bits is not conducive to correct thunking. Soooo, no more * thunking in WMDISP32 - I do it all here and Post the correct 16 bit * message. * * Hence WMTBL32 (the 32 bit message switch table) contains the * NoThunking entry for all the MM_ messages - I'll do 'em myself thank * you. * * * For the MM_WIM_DATA and MM_WOM_DONE message dwParam1 points to the * following data struture. * * P32HDR is a 32 bit pointer to the original 16 bit header * P16HDR is a 16 bit far pointer to the original 16 bit header * * If we need to refernece the original header we must do via the * P32HDR pointer. * * +---------+ * | P32HDR +----->+---------+ * +---------+ | 16 bit | * | P16HDR +----->| | This is the original * dwParam1 ----->+---------+ | Wave | wave header passed to * | 32 bit | | Header | us by the Win 16 app. * This is the 32 | | | | * bit wave | Wave | +---------+ * header that we | Header | * thunked at | | * earlier. +---------+ * * * We must ensure that the 32 bit structure is completely hidden from the * 16 bit application, ie. the 16 bit app only see's the wave header that it * passed to us earlier. * * * NOTE: dwParam2 is junk * * \**********************************************************************/ VOID W32CommonDeviceOpen( HANDLE handle, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ) { PWAVEHDR32 pWavehdr32; PMIDIHDR32 pMidihdr32; PINSTANCEDATA pInstanceData; WORD Handle; switch (uMsg) { /* ------------------------------------------------------------ ** MIDI INPUT MESSAGES ** ------------------------------------------------------------ */ case MM_MIM_LONGDATA: /* ** This message is sent to a window when an input buffer has been ** filled with MIDI system-exclusive data and is being returned to ** the application. */ case MM_MIM_LONGERROR: /* ** This message is sent to a window when an invalid MIDI ** system-exclusive message is received. */ pMidihdr32 = (PMIDIHDR32)( (PBYTE)dwParam1 - (sizeof(PMIDIHDR16) * 2) ); WOW32ASSERT( pMidihdr32 ); COPY_MIDIINHDR16_FLAGS( pMidihdr32->pMidihdr32, pMidihdr32->Midihdr ); dwParam1 = (DWORD)pMidihdr32->pMidihdr16; case MM_MIM_DATA: /* ** This message is sent to a window when a MIDI message is ** received by a MIDI input device. */ case MM_MIM_ERROR: /* ** This message is sent to a window when an invalid MIDI message ** is received. */ case MM_MIM_OPEN: /* ** This message is sent to a window when a MIDI input device is opened. ** We process this message the same way as MM_MIM_CLOSE (see below) */ case MM_MIM_CLOSE: /* ** This message is sent to a window when a MIDI input device is ** closed. The device handle is no longer valid once this message ** has been sent. */ Handle = GETHMIDIIN16(handle); break; /* ------------------------------------------------------------ ** MIDI OUTPUT MESSAGES ** ------------------------------------------------------------ */ case MM_MOM_DONE: /* ** This message is sent to a window when the specified ** system-exclusive buffer has been played and is being returned to ** the application. */ pMidihdr32 = (PMIDIHDR32)( (PBYTE)dwParam1 - (sizeof(PMIDIHDR16) * 2) ); WOW32ASSERT( pMidihdr32 ); COPY_MIDIOUTHDR16_FLAGS( pMidihdr32->pMidihdr32, pMidihdr32->Midihdr ); dwParam1 = (DWORD)pMidihdr32->pMidihdr16; case MM_MOM_OPEN: /* ** This message is sent to a window when a MIDI output device is opened. ** We process this message the same way as MM_MOM_CLOSE (see below) */ case MM_MOM_CLOSE: /* ** This message is sent to a window when a MIDI output device is ** closed. The device handle is no longer valid once this message ** has been sent. */ Handle = GETHMIDIOUT16(handle); break; /* ------------------------------------------------------------ ** WAVE INPUT MESSAGES ** ------------------------------------------------------------ */ case MM_WIM_DATA: /* ** This message is sent to a window when waveform data is present ** in the input buffer and the buffer is being returned to the ** application. The message can be sent either when the buffer ** is full, or after the waveInReset function is called. */ pWavehdr32 = (PWAVEHDR32)( (PBYTE)dwParam1 - (sizeof(PWAVEHDR16) * 2)); WOW32ASSERT( pWavehdr32 ); COPY_WAVEINHDR16_FLAGS( pWavehdr32->pWavehdr32, pWavehdr32->Wavehdr ); dwParam1 = (DWORD)pWavehdr32->pWavehdr16; case MM_WIM_OPEN: /* ** This message is sent to a window when a waveform input ** device is opened. ** ** We process this message the same way as MM_WIM_CLOSE (see below) */ case MM_WIM_CLOSE: /* ** This message is sent to a window when a waveform input device is ** closed. The device handle is no longer valid once the message has ** been sent. */ Handle = GETHWAVEIN16(handle); break; /* ------------------------------------------------------------ ** WAVE OUTPUT MESSAGES ** ------------------------------------------------------------ */ case MM_WOM_DONE: /* ** This message is sent to a window when the specified output ** buffer is being returned to the application. Buffers are returned ** to the application when they have been played, or as the result of ** a call to waveOutReset. */ pWavehdr32 = (PWAVEHDR32)( (PBYTE)dwParam1 - (sizeof(PWAVEHDR16) * 2)); WOW32ASSERT( pWavehdr32 ); COPY_WAVEOUTHDR16_FLAGS( pWavehdr32->pWavehdr32, pWavehdr32->Wavehdr ); dwParam1 = (DWORD)pWavehdr32->pWavehdr16; case MM_WOM_OPEN: /* ** This message is sent to a window when a waveform output device ** is opened. ** ** We process this message the same way as MM_WOM_CLOSE (see below) */ case MM_WOM_CLOSE: /* ** This message is sent to a window when a waveform output device ** is closed. The device handle is no longer valid once the ** message has been sent. */ Handle = GETHWAVEOUT16(handle); break; #if DBG default: dprintf(( "Unknown message received in CallBack function " )); dprintf(( "best call StephenE or MikeTri" )); return; #endif } /* ** Now make the CallBack, or PostMessage call depending ** on the flags passed to original (wave|midi)(In|Out)Open call. */ pInstanceData = (PINSTANCEDATA)dwInstance; WOW32ASSERT( pInstanceData ); switch (pInstanceData->dwFlags & CALLBACK_TYPEMASK) { case CALLBACK_WINDOW: dprintf2(( "WINDOW callback identified" )); PostMessage( HWND32( LOWORD(pInstanceData->dwCallback) ), uMsg, Handle, dwParam1 ); break; case CALLBACK_TASK: case CALLBACK_FUNCTION: { DWORD dwFlags; if ( (pInstanceData->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_TASK ) { dprintf2(( "TASK callback identified" )); dwFlags = DCB_TASK; } else { dprintf2(( "FUNCTION callback identified" )); dwFlags = DCB_FUNCTION; } WOW32DriverCallback( pInstanceData->dwCallback, dwFlags, Handle, LOWORD( uMsg ), pInstanceData->dwCallbackInstance, dwParam1, dwParam2 ); } break; } /* ** Now, free up any storage that was allocated during the waveOutOpen ** and waveInOpen. This should only be freed during the MM_WOM_CLOSE or ** MM_WIM_CLOSE message. ** ** Also, free up any storage that was allocated during the waveOutWrite ** and waveInAddBuffer call. This should only be freed during the ** MM_WOM_DONE or MM_WIM_DATA message. */ switch (uMsg) { case MM_MIM_CLOSE: case MM_MOM_CLOSE: case MM_WIM_CLOSE: case MM_WOM_CLOSE: dprintf2(( "W32CommonDeviceOpen: Freeing device open buffer at %X", pInstanceData )); dprintf2(( "Alloc Midi count = %d", AllocMidiCount )); dprintf2(( "Alloc Wave count = %d", AllocWaveCount )); free_w( pInstanceData ); FREEHWAVEIN16( Handle ); break; case MM_WIM_DATA: case MM_WOM_DONE: # if DBG AllocWaveCount--; dprintf2(( "W<< \t%8X (%d)", pWavehdr32, AllocWaveCount )); # endif free_w( pWavehdr32 ); break; case MM_MIM_LONGDATA: case MM_MIM_LONGERROR: case MM_MOM_DONE: # if DBG AllocMidiCount--; dprintf2(( "M<< \t%8X (%d)", pMidihdr32, AllocMidiCount )); # endif free_w( pMidihdr32 ); break; } } #endif