summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow32/wmmedia2.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/mvdm/wow32/wmmedia2.c3382
1 files changed, 3382 insertions, 0 deletions
diff --git a/private/mvdm/wow32/wmmedia2.c b/private/mvdm/wow32/wmmedia2.c
new file mode 100644
index 000000000..df5e10043
--- /dev/null
+++ b/private/mvdm/wow32/wmmedia2.c
@@ -0,0 +1,3382 @@
+/***********************************************************************\
+
+*
+* 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