summaryrefslogtreecommitdiffstats
path: root/private/mvdm/wow32/wmmstruc.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/wow32/wmmstruc.c')
-rw-r--r--private/mvdm/wow32/wmmstruc.c762
1 files changed, 762 insertions, 0 deletions
diff --git a/private/mvdm/wow32/wmmstruc.c b/private/mvdm/wow32/wmmstruc.c
new file mode 100644
index 000000000..8c10cae89
--- /dev/null
+++ b/private/mvdm/wow32/wmmstruc.c
@@ -0,0 +1,762 @@
+/*++
+ *
+ * WOW v1.0
+ *
+ * Copyright (c) 1991, Microsoft Corporation
+ *
+ * WMMSTRUC.C
+ *
+ *
+ * MultiMedia Structure copying functions (modelled after WSTRUC.C by jeffpar)
+ *
+ * For input structures, there are GETxxxx16 macros; for output structures
+ * there are PUTxxxx16 macros. Most or all of these macros will simply call
+ * the corresponding function below.
+ *
+ *
+ * WOW32 16-bit MultiMedia structure conversion support
+ *
+ * History:
+ * Created 13-Feb-1992 by Mike Tricker (miketri)
+ * Changed 16-Jul-1992 by Mike Tricker (miketri) Sorted out the Caps structure copies
+ * Changed 08-Oct-1992 by StephenE Made the thunks safe on MIPS
+ *
+ * Basically doing a GETVDMPTR of a null pointer is bad on MIPS, so is
+ * trying to get a pointer to zero bytes. On Intel these GETXXX macros
+ * don't really do anything.
+ *
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+#if 0
+MODNAME(wmmstruc.c);
+
+
+
+
+/**********************************************************************\
+ * getmmtime16
+ *
+ * Thunks an MMTIME structure from 16 bit to 32 bit space.
+ *
+ * Used by:
+ * waveOutGetPosition
+ * waveInGetPosition
+ * timeGetSystemTime
+ *
+\**********************************************************************/
+ULONG getmmtime16 (VPMMTIME16 vpmmt, LPMMTIME lpmmt)
+{
+ register PMMTIME16 pmmt16;
+
+#ifdef MIPS_COMPILER_PACKING_BUG
+ MMGETOPTPTR(vpmmt, 8, pmmt16);
+#else
+ MMGETOPTPTR(vpmmt, sizeof(MMTIME16), pmmt16);
+#endif
+
+ if ( pmmt16 == NULL ) {
+ dprintf1(( "getmmtime16 MMGETOPTPTR returned a NULL pointer" ));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ lpmmt->wType = (UINT)FETCHWORD(pmmt16->wType);
+
+ switch ( lpmmt->wType ) {
+ case TIME_MS:
+ lpmmt->u.ms = FETCHDWORD(pmmt16->u.ms);
+ break;
+
+ case TIME_SAMPLES:
+ lpmmt->u.sample = FETCHDWORD(pmmt16->u.sample);
+ break;
+
+ case TIME_BYTES:
+ lpmmt->u.cb = FETCHDWORD(pmmt16->u.cb);
+ break;
+
+ case TIME_SMPTE:
+ lpmmt->u.smpte.hour = pmmt16->u.smpte.hour;
+ lpmmt->u.smpte.min = pmmt16->u.smpte.min;
+ lpmmt->u.smpte.sec = pmmt16->u.smpte.sec;
+ lpmmt->u.smpte.frame = pmmt16->u.smpte.frame;
+ lpmmt->u.smpte.fps = pmmt16->u.smpte.fps;
+ lpmmt->u.smpte.dummy = pmmt16->u.smpte.dummy;
+ break;
+
+ case TIME_MIDI:
+ lpmmt->u.midi.songptrpos = FETCHDWORD(pmmt16->u.midi.songptrpos);
+ break;
+ }
+
+ FREEVDMPTR(pmmt16);
+ return MMSYSERR_NOERROR;
+}
+
+/**********************************************************************\
+ * Thunks an MMTIME structure from 32 bit back to 16 bit space.
+ *
+ * Used by:
+ * waveOutGetPosition
+ * waveInGetPosition
+ * timeGetSystemTime
+\**********************************************************************/
+ULONG putmmtime16 (VPMMTIME16 vpmmt, LPMMTIME lpmmt)
+{
+ register PMMTIME16 pmmt16;
+
+
+#ifdef MIPS_COMPILER_PACKING_BUG
+ MMGETOPTPTR(vpmmt, 8, pmmt16);
+#else
+ MMGETOPTPTR(vpmmt, sizeof(MMTIME16), pmmt16);
+#endif
+
+ if ( pmmt16 == NULL ) {
+ dprintf1(( "putmmtime16 MMGETOPTPTR returned a NULL pointer" ));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ STOREWORD(pmmt16->wType, (WORD)lpmmt->wType);
+
+ switch ( pmmt16->wType ) {
+
+ case TIME_MS:
+ STOREDWORD(pmmt16->u.ms, lpmmt->u.ms);
+ dprintf2(( "Time in MS is %x", lpmmt->u.ms ));
+ break;
+
+ case TIME_SAMPLES:
+ STOREDWORD(pmmt16->u.sample, lpmmt->u.sample);
+ dprintf2(( "Time in samples is %x", lpmmt->u.sample ));
+ break;
+
+ case TIME_BYTES:
+ STOREDWORD(pmmt16->u.cb, lpmmt->u.cb);
+ dprintf2(( "Time in bytes is %x", lpmmt->u.cb ));
+ break;
+
+ case TIME_SMPTE:
+ pmmt16->u.smpte.hour = lpmmt->u.smpte.hour;
+ pmmt16->u.smpte.min = lpmmt->u.smpte.min;
+ pmmt16->u.smpte.sec = lpmmt->u.smpte.sec;
+ pmmt16->u.smpte.frame = lpmmt->u.smpte.frame;
+ pmmt16->u.smpte.fps = lpmmt->u.smpte.fps;
+ pmmt16->u.smpte.dummy = lpmmt->u.smpte.dummy;
+ break;
+
+ case TIME_MIDI:
+ STOREDWORD(pmmt16->u.midi.songptrpos, lpmmt->u.midi.songptrpos);
+ dprintf2(( "Time in midi is %x", lpmmt->u.midi.songptrpos ));
+ break;
+ }
+
+#ifdef MIPS_COMPILER_PACKING_BUG
+ FLUSHVDMPTR(vpmmt, 8, pmmt16);
+#else
+ FLUSHVDMPTR(vpmmt, sizeof(MMTIME16), pmmt16);
+#endif
+ FREEVDMPTR(pmmt16);
+
+ return MMSYSERR_NOERROR;
+
+}
+
+/**********************************************************************\
+* Thunks a WAVEHDR structure from 16 bit to 32 bit space.
+*
+* Used by:
+* waveOutPrepareHeader
+* waveOutUnprepareHeader
+* waveOutWrite
+* waveInPrepareHeader
+* waveInUnprepareHeader
+* waveInAddBuffer
+*
+* Returns a 32 bit pointer to the 16 bit wave header. This wave header
+* should have been locked down by wave(In|Out)PrepareHeader. Therefore,
+* it is to store this pointer for use during the WOM_DONE callback message.
+*
+* With the WAVEHDR and MIDIHDR structs I am assured by Robin that the ->lpNext
+* field is only used by the driver, and is therefore in 32 bit space. It
+* therefore doesn't matter what gets passed back and forth (I hope !).
+*
+\**********************************************************************/
+PWAVEHDR16 getwavehdr16( VPWAVEHDR16 vpwhdr, LPWAVEHDR lpwhdr )
+{
+ register PWAVEHDR16 pwhdr16;
+
+ MMGETOPTPTR(vpwhdr, sizeof(WAVEHDR16), pwhdr16);
+ if ( pwhdr16 == NULL ) {
+ dprintf1(( "getwavehdr16 MMGETOPTPTR returned an invalid pointer" ));
+ return NULL;
+ }
+
+ if ( HIWORD(FETCHDWORD( pwhdr16->lpData )) != 0 ) {
+ GETMISCPTR(pwhdr16->lpData, lpwhdr->lpData);
+ }
+ else {
+ dprintf1(( "getwavehdr16 passed an invalid pointer to data" ));
+ lpwhdr->lpData = (VPSTR)NULL;
+ }
+
+ lpwhdr->dwBufferLength = FETCHDWORD(pwhdr16->dwBufferLength);
+ dprintf4(( "getwavehdr16: buffer length = %X", lpwhdr->dwBufferLength ));
+
+ lpwhdr->dwBytesRecorded = FETCHDWORD(pwhdr16->dwBytesRecorded);
+ lpwhdr->dwUser = FETCHDWORD(pwhdr16->dwUser);
+ lpwhdr->dwFlags = FETCHDWORD(pwhdr16->dwFlags);
+ lpwhdr->dwLoops = FETCHDWORD(pwhdr16->dwLoops);
+ lpwhdr->lpNext = (PWAVEHDR)FETCHDWORD(pwhdr16->lpNext);
+ lpwhdr->reserved = FETCHDWORD(pwhdr16->reserved);
+
+ return pwhdr16;
+}
+
+/**********************************************************************\
+* Thunks a WAVEHDR structure from 32 bit back to 16 bit space.
+*
+* Used by:
+* waveOutPrepareHeader
+* waveOutUnprepareHeader
+* waveOutWrite
+* waveInPrepareHeader
+* waveInUnprepareHeader
+* waveInAddBuffer
+*
+*
+* With the WAVEHDR and MIDIHDR structs I am assured by Robin that the ->lpNext
+* field is only used by the driver, and is therefore in 32 bit space. It
+* therefore doesn't matter what gets passed back and forth (I hope !).
+*
+\**********************************************************************/
+VOID putwavehdr16 (VPWAVEHDR16 vpwhdr, LPWAVEHDR lpwhdr)
+{
+ register PWAVEHDR16 pwhdr16;
+
+ MMGETOPTPTR(vpwhdr, sizeof(WAVEHDR16), pwhdr16);
+ if ( pwhdr16 == NULL ) {
+ dprintf1(( "getwavehdr16 MMGETOPTPTR returned a NULL pointer" ));
+ return;
+ }
+
+ STOREDWORD(pwhdr16->dwBufferLength, lpwhdr->dwBufferLength);
+ STOREDWORD(pwhdr16->dwBytesRecorded, lpwhdr->dwBytesRecorded);
+ STOREDWORD(pwhdr16->dwUser, lpwhdr->dwUser);
+ STOREDWORD(pwhdr16->dwFlags, lpwhdr->dwFlags);
+ STOREDWORD(pwhdr16->dwLoops, lpwhdr->dwLoops);
+ STOREDWORD(pwhdr16->lpNext, lpwhdr->lpNext);
+ STOREDWORD(pwhdr16->reserved, lpwhdr->reserved);
+
+ FLUSHVDMPTR(vpwhdr, sizeof(WAVEHDR16), pwhdr16);
+ FREEVDMPTR(pwhdr16);
+}
+
+
+/**********************************************************************\
+ * Thunks a WAVEOUTCAPS structure from 32 bit back to 16 bit space.
+ *
+ * Used by:
+ * waveOutGetDevCaps
+ *
+ * Remember that the ->vDriverVersion is a WORD in 16bit land and a UINT in
+ * 32 bit. This applies to WAVEIN/OUTCAPS, MIDIIN/OUTCAPS and AUXCAPS.
+ *
+\**********************************************************************/
+ULONG putwaveoutcaps16 (VPWAVEOUTCAPS16 vpwoc, LPWAVEOUTCAPS lpwoc, UINT uSize)
+{
+ INT i;
+ WAVEOUTCAPS16 Temp;
+ PWAVEOUTCAPS16 pwoc16;
+
+ /*
+ ** Just in case the app specified a NULL pointer. We have already
+ ** validated that uSize is not zero.
+ */
+
+ MMGETOPTPTR( vpwoc, min(uSize, sizeof(WAVEOUTCAPS16)), pwoc16 );
+ if ( pwoc16 == NULL ) {
+ dprintf1(( "putwaveoutcaps16 MMGETOPTPTR returned a NULL pointer" ));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ STOREWORD(Temp.wMid, lpwoc->wMid);
+ STOREWORD(Temp.wPid, lpwoc->wPid);
+ STOREWORD(Temp.vDriverVersion, (WORD)lpwoc->vDriverVersion);
+
+ /*
+ ** The product name string should be null terminated, but we want
+ ** the whole string anyway, so copy the whole MAXPNAMELEN bytes.
+ */
+ i = 0;
+ while (i < MAXPNAMELEN) {
+ Temp.szPname[i] = lpwoc->szPname[i++];
+ }
+
+ STOREDWORD(Temp.dwFormats, lpwoc->dwFormats);
+ STOREWORD(Temp.wChannels, lpwoc->wChannels);
+ STOREDWORD(Temp.dwSupport, lpwoc->dwSupport);
+
+ RtlCopyMemory( (LPVOID)pwoc16, &Temp, min(uSize, sizeof(WAVEOUTCAPS16)) );
+
+ FLUSHVDMPTR(vpwoc, min(uSize, sizeof(WAVEOUTCAPS16)), pwoc16);
+ FREEVDMPTR(pwoc16);
+
+ return MMSYSERR_NOERROR;
+
+}
+
+
+/**********************************************************************\
+ * Thunks a WAVEINCAPS structure from 32 bit back to 16 bit space.
+ *
+ * Used by:
+ * waveInGetDevCaps
+ *
+ * Remember that the ->vDriverVersion is a WORD in 16bit land and a UINT in
+ * 32 bit. This applies to WAVEIN/OUTCAPS, MIDIIN/OUTCAPS and AUXCAPS.
+ *
+\**********************************************************************/
+ULONG putwaveincaps16 (VPWAVEINCAPS16 vpwic, LPWAVEINCAPS lpwic, UINT uSize)
+{
+ INT i;
+ WAVEINCAPS16 Temp;
+ PWAVEINCAPS16 pwic16;
+
+ /*
+ ** Just in case the app specified a NULL pointer. We have already
+ ** validated that uSize is not zero.
+ */
+
+ MMGETOPTPTR(vpwic, min(uSize, sizeof(WAVEINCAPS16)), pwic16);
+ if ( pwic16 == NULL ) {
+ dprintf1(( "putwaveincaps16 MMGETOPTPTR returned a NULL pointer" ));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ STOREWORD(Temp.wMid, lpwic->wMid);
+ STOREWORD(Temp.wPid, lpwic->wPid);
+ STOREWORD(Temp.vDriverVersion, (WORD)lpwic->vDriverVersion);
+
+ /*
+ ** The product name string should be null terminated,
+ ** but we want the whole string anyway, so copy the whole
+ ** MAXPNAMELEN bytes.
+ */
+ i = 0;
+ while (i < MAXPNAMELEN) {
+ Temp.szPname[i] = lpwic->szPname[i++];
+ }
+
+ STOREDWORD(Temp.dwFormats, lpwic->dwFormats);
+ STOREWORD(Temp.wChannels, lpwic->wChannels);
+
+ RtlCopyMemory( (LPVOID)pwic16, &Temp, min(uSize, sizeof(WAVEINCAPS16)) );
+
+ FLUSHVDMPTR(vpwic, min(uSize, sizeof(WAVEINCAPS16)), pwic16);
+ FREEVDMPTR(pwic16);
+
+ return MMSYSERR_NOERROR;
+
+}
+
+/**********************************************************************\
+ * Thunks a MIDIHDR structure from 16 bit to 32 bit space.
+ *
+ * Used by:
+ * midiOutLongMsg
+ * midiInAddBuffer
+ * midiOutPrepareHdr
+ * midiOutUnprepareHdr
+ * midiInPrepareHdr
+ * midiInUnprepareHdr
+ *
+\**********************************************************************/
+PMIDIHDR16 getmidihdr16 (VPMIDIHDR16 vpmhdr, LPMIDIHDR lpmhdr)
+{
+ PMIDIHDR16 pmhdr16;
+
+ MMGETOPTPTR(vpmhdr, sizeof(MIDIHDR16), pmhdr16);
+ if ( pmhdr16 == NULL ) {
+ dprintf1(( "getmidihdr MMGETOPTPTR returned a NULL pointer" ));
+ return NULL;
+ }
+
+ if ( HIWORD(FETCHDWORD( pmhdr16->lpData )) != 0 ) {
+ GETMISCPTR(pmhdr16->lpData, lpmhdr->lpData);
+ }
+ else {
+ dprintf1(( "getmidihdr16 passed a NULL pointer to data" ));
+ lpmhdr->lpData = (VPSTR)NULL;
+ }
+
+ lpmhdr->dwBufferLength = FETCHDWORD(pmhdr16->dwBufferLength);
+ dprintf4(( "getmidihdr16: buffer length = %X", lpmhdr->dwBufferLength ));
+
+ lpmhdr->dwBytesRecorded = FETCHDWORD(pmhdr16->dwBytesRecorded);
+ lpmhdr->dwUser = FETCHDWORD(pmhdr16->dwUser);
+ lpmhdr->dwFlags = FETCHDWORD(pmhdr16->dwFlags);
+ lpmhdr->lpNext = (PMIDIHDR)FETCHDWORD(pmhdr16->lpNext);
+ lpmhdr->reserved = FETCHDWORD(pmhdr16->reserved);
+
+ return pmhdr16;
+}
+
+/**********************************************************************\
+* Thunks a MIDIHDR structure from 32 bit to 16 bit space.
+*
+* Used by:
+* midiOutLongMsg
+* midiInAddBuffer
+* midiOutPrepareHdr
+* midiOutUnprepareHdr
+* midiInPrepareHdr
+* midiInUnprepareHdr
+*
+\**********************************************************************/
+VOID putmidihdr16 (VPMIDIHDR16 vpmhdr, LPMIDIHDR lpmhdr)
+{
+ register PMIDIHDR16 pmhdr16;
+
+ MMGETOPTPTR(vpmhdr, sizeof(MIDIHDR16), pmhdr16);
+ if ( pmhdr16 == NULL ) {
+ dprintf1(( "putmidihdr MMGETOPTPTR returned a NULL pointer" ));
+ return;
+ }
+
+ STOREDWORD(pmhdr16->dwBufferLength, lpmhdr->dwBufferLength);
+ STOREDWORD(pmhdr16->dwBytesRecorded, lpmhdr->dwBytesRecorded);
+ STOREDWORD(pmhdr16->dwUser, lpmhdr->dwUser);
+ STOREDWORD(pmhdr16->dwFlags, lpmhdr->dwFlags);
+ STOREDWORD(pmhdr16->lpNext, lpmhdr->lpNext);
+ STOREDWORD(pmhdr16->reserved, lpmhdr->reserved);
+
+ FLUSHVDMPTR(vpmhdr, sizeof(MIDIHDR16), pmhdr16);
+ FREEVDMPTR(pmhdr16);
+}
+
+
+/**********************************************************************\
+ * Thunks an AUXCAPS structure from 32 bit back to 16 bit space.
+ *
+ * Used by:
+ * auxGetDevCaps
+ *
+ * Remember that the ->vDriverVersion is a WORD in 16bit land and a UINT in
+ * 32 bit. This applies to WAVEIN/OUTCAPS, MIDIIN/OUTCAPS and AUXCAPS.
+ *
+\**********************************************************************/
+ULONG putauxcaps16 (VPAUXCAPS16 vpauxc, LPAUXCAPS lpauxc, UINT uSize)
+{
+ INT i;
+ AUXCAPS16 Temp;
+ PAUXCAPS16 pauxc16;
+
+ /*
+ ** Just in case the app specified a NULL pointer. We have already
+ ** validated that uSize is not zero.
+ */
+
+ MMGETOPTPTR(vpauxc, min(uSize, sizeof(AUXCAPS16)), pauxc16);
+ if ( pauxc16 == NULL ) {
+ dprintf1(( "putauxcaps16 MMGETOPTPTR returned a NULL pointer" ));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ STOREWORD(Temp.wMid, lpauxc->wMid);
+ STOREWORD(Temp.wPid, lpauxc->wPid);
+ STOREWORD(Temp.vDriverVersion, (WORD)lpauxc->vDriverVersion);
+
+ /*
+ ** The product name string should be null terminated,
+ ** but we want the whole string anyway, so copy the whole
+ ** MAXPNAMELEN bytes.
+ */
+
+ i = 0;
+ while (i < MAXPNAMELEN) {
+ Temp.szPname[i] = lpauxc->szPname[i++];
+ }
+
+ STOREWORD(Temp.wTechnology, lpauxc->wTechnology);
+ STOREDWORD(Temp.dwSupport, lpauxc->dwSupport);
+
+ RtlCopyMemory( (LPVOID)pauxc16, &Temp, min(uSize, sizeof(AUXCAPS16)) );
+
+ FLUSHVDMPTR(vpauxc, min(uSize, sizeof(AUXCAPS16)), pauxc16);
+ FREEVDMPTR(pauxc16);
+ return MMSYSERR_NOERROR;
+}
+
+/**********************************************************************\
+ * Thunks a TIMECAPS structure from 32 bit back to 16 bit space.
+ *
+ * Used by:
+ * timeGetDevCaps
+ *
+\**********************************************************************/
+ULONG puttimecaps16(VPTIMECAPS16 vptimec, LPTIMECAPS lptimec, UINT uSize)
+{
+ PTIMECAPS16 ptimec16;
+ TIMECAPS16 Temp;
+
+ /*
+ ** Just in case the app specified a NULL pointer. We have already
+ ** validated that uSize is not zero.
+ */
+
+ MMGETOPTPTR(vptimec, min(uSize, sizeof(TIMECAPS16)), ptimec16);
+ if ( ptimec16 == NULL ) {
+ dprintf1(( "puttimecaps16 MMGETOPTPTR returned a NULL pointer" ));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ //
+ // Under NT, the minimum time period is about 15ms. But Win3.1 on a 386
+ // always returns 1ms. Encarta doesn't even bother testing the
+ // CD-ROM's speed if the minimum period is > 2ms, it just assumes
+ // it is too slow. So here we lie to WOW apps and always tell
+ // them 1ms just like Win3.1.
+ // John Vert (jvert) 17-Jun-1993
+ //
+ STOREWORD( Temp.wPeriodMin, 1 );
+
+ /*
+ ** In windows 3.1 the wPeriodMax value is 0xFFFF which is the
+ ** max value you can store in a word. In windows NT the
+ ** wPeriodMax is 0xF4240 (1000 seconds).
+ **
+ ** If we just cast the 32 bit value down to a 16bit value we
+ ** end up with 0x4240 which very small compared to real 32 bit
+ ** value.
+ **
+ ** Therefore I will take the minimum of wPeriodMax and 0xFFFF
+ ** that way will should remain consistant with Win 3.1 if
+ ** wPeriodMax is greater than 0xFFFF.
+ */
+ STOREWORD(Temp.wPeriodMax, (WORD)min( 0xFFFF, lptimec->wPeriodMax) );
+
+ RtlCopyMemory( (LPVOID)ptimec16, &Temp, min(uSize, sizeof(TIMECAPS16)) );
+
+ FLUSHVDMPTR(vptimec, min(uSize, sizeof(TIMECAPS16)), ptimec16);
+ FREEVDMPTR(ptimec16);
+ return MMSYSERR_NOERROR;
+}
+
+
+
+
+/**********************************************************************\
+ * Thunks a MIDIINCAPS structure from 32 bit back to 16 bit space.
+ *
+ * Used by:
+ * midiInGetDevCaps
+ *
+ * OK - heres the scoop:
+ *
+ * Robin observed that it is valid (in theory) to copy back more bytes than
+ * JUST those contained in the MIDIINCAPS16 structure...
+ * Unfortunately that would probably blow this lot clean out of the water, so
+ * we aren't going to worry about that possibility for now.
+ * We will thunk the ENTIRE structure (not least 'cos we ALWAYS request it in
+ * the 32 bit call), then copy the required number, <= sizeof(MIDIINCAPS16)
+ * back to the 16 bit app.
+ *
+ * pTemp is the pointer to our local copy of the complete MIDIOUTCAPS16
+\**********************************************************************/
+ULONG putmidiincaps16 (VPMIDIINCAPS16 vpmic, LPMIDIINCAPS lpmic, UINT uSize)
+{
+
+ INT i;
+ MIDIINCAPS16 Temp;
+ PMIDIINCAPS16 pmic16;
+
+ /*
+ ** Just in case the app specified a NULL pointer. We have already
+ ** validated that uSize is not zero.
+ */
+
+ MMGETOPTPTR(vpmic, min(uSize, sizeof(MIDIINCAPS16)), pmic16);
+ if ( pmic16 == NULL ) {
+ dprintf1(( "putmidiincaps16 MMGETOPTPTR returned a NULL pointer" ));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ STOREWORD(Temp.wMid, lpmic->wMid);
+ STOREWORD(Temp.wPid, lpmic->wPid);
+ STOREWORD(Temp.vDriverVersion, (WORD)lpmic->vDriverVersion);
+
+ /*
+ ** The product name string should be null terminated, but we want the whole
+ ** string anyway, so copy the whole MAXPNAMELEN bytes.
+ */
+ i = 0;
+ while (i < MAXPNAMELEN) {
+ Temp.szPname[i] = lpmic->szPname[i++];
+ }
+
+ RtlCopyMemory( (LPVOID)pmic16, &Temp, min(uSize, sizeof(MIDIINCAPS16)) );
+
+ FLUSHVDMPTR(vpmic, min(uSize, sizeof(MIDIINCAPS16)), pmic16);
+ FREEVDMPTR(pmic16);
+ return MMSYSERR_NOERROR;
+}
+
+
+
+/**********************************************************************\
+ * Thunks a MIDIOUTCAPS structure from 32 bit back to 16 bit space.
+ *
+ *
+ * OK - heres the scoop:
+ *
+ * Robin observed that it is valid (in theory) to copy back more bytes than
+ * JUST those contained in the MIDIOUTCAPS16 structure...
+ * Unfortunately that would probably blow this lot clean out of the water, so
+ * we aren't going to worry about that possibility for now.
+ * We will thunk the ENTIRE structure (not least 'cos we ALWAYS request it in
+ * the 32 bit call), then copy the required number, <= sizeof(MIDIOUTCAPS16)
+ * back to the 16 bit app.
+ *
+ * pTemp is the pointer to our local copy of the complete MIDIOUTCAPS16
+ *
+ * Used by:
+ * midiOutGetDevCaps
+ *
+\**********************************************************************/
+ULONG putmidioutcaps16 (VPMIDIOUTCAPS16 vpmoc, LPMIDIOUTCAPS lpmoc, UINT uSize)
+{
+
+ INT i;
+ MIDIOUTCAPS16 Temp;
+ PMIDIOUTCAPS16 pmoc16;
+
+ /*
+ ** Just in case the app specified a NULL pointer. We have already
+ ** validated that uSize is not zero.
+ */
+
+ MMGETOPTPTR(vpmoc, min(uSize, sizeof(MIDIINCAPS16)), pmoc16);
+ if ( pmoc16 == NULL ) {
+ dprintf1(( "putmidioutcaps16 MMGETOPTPTR returned a NULL pointer" ));
+ return MMSYSERR_INVALPARAM;
+ }
+
+ STOREWORD(Temp.wMid, lpmoc->wMid);
+ STOREWORD(Temp.wPid, lpmoc->wPid);
+ STOREWORD(Temp.vDriverVersion, (WORD)lpmoc->vDriverVersion);
+
+ /*
+ ** The product name string should be null terminated, but we want the whole
+ ** string anyway, so copy the whole MAXPNAMELEN bytes.
+ */
+ i = 0;
+ while (i < MAXPNAMELEN) {
+ Temp.szPname[i] = lpmoc->szPname[i++];
+ }
+
+ STOREWORD(Temp.wTechnology, lpmoc->wTechnology);
+ STOREWORD(Temp.wVoices, lpmoc->wVoices);
+ STOREWORD(Temp.wNotes, lpmoc->wNotes);
+ STOREWORD(Temp.wChannelMask, lpmoc->wChannelMask);
+ STOREDWORD(Temp.dwSupport, lpmoc->dwSupport);
+
+ RtlCopyMemory( (LPVOID)pmoc16, &Temp, min(uSize, sizeof(MIDIOUTCAPS16)) );
+
+ FLUSHVDMPTR(vpmoc, min(uSize, sizeof(MIDIOUTCAPS16)), pmoc16);
+ FREEVDMPTR(pmoc16);
+ return MMSYSERR_NOERROR;
+}
+
+
+
+
+/**********************************************************************\
+ * Thunks a JOYCAPS structure from 32 bit back to 16 bit space.
+ *
+ * Used by:
+ * joyGetDevCaps
+ *
+\**********************************************************************/
+ULONG putjoycaps16 (VPJOYCAPS16 vpjoyc, LPJOYCAPS lpjoyc, UINT uSize)
+{
+ INT i;
+ JOYCAPS16 Temp;
+ PJOYCAPS16 pjoyc16;
+
+ /*
+ ** Just in case the app specified a NULL pointer. We have already
+ ** validated that uSize is not zero.
+ */
+
+ MMGETOPTPTR(vpjoyc, min(uSize, sizeof(JOYCAPS16)), pjoyc16);
+ if ( pjoyc16 == NULL ) {
+ dprintf1(( "putjoycaps16 MMGETOPTPTR returned a NULL pointer" ));
+ return JOYERR_PARMS;
+ }
+
+ STOREWORD(Temp.wMid, lpjoyc->wMid);
+ STOREWORD(Temp.wPid, lpjoyc->wPid);
+
+ /*
+ ** The product name string should be null terminated,
+ ** but we want the whole string anyway, so copy the
+ ** whole MAXPNAMELEN bytes.
+ */
+
+ i = 0;
+ while (i < MAXPNAMELEN) {
+ Temp.szPname[i] = lpjoyc->szPname[i++];
+ }
+
+ STOREWORD(Temp.wXmin, lpjoyc->wXmin);
+ STOREWORD(Temp.wXmax, lpjoyc->wXmax);
+ STOREWORD(Temp.wYmin, lpjoyc->wYmin);
+ STOREWORD(Temp.wYmax, lpjoyc->wYmax);
+ STOREWORD(Temp.wZmin, lpjoyc->wZmin);
+ STOREWORD(Temp.wZmax, lpjoyc->wZmax);
+ STOREWORD(Temp.wNumButtons, lpjoyc->wNumButtons);
+ STOREWORD(Temp.wPeriodMin, lpjoyc->wPeriodMin);
+ STOREWORD(Temp.wPeriodMax, lpjoyc->wPeriodMax);
+
+ RtlCopyMemory( (LPVOID)pjoyc16, &Temp, min(uSize, sizeof(JOYCAPS16)) );
+
+ FLUSHVDMPTR(vpjoyc, min(uSize, sizeof(JOYCAPS16) ), pjoyc16);
+ FREEVDMPTR(pjoyc16);
+ return JOYERR_NOERROR;
+}
+
+
+/**********************************************************************\
+ * Thunks a JOYINFO structure from 32 bit back to 16 bit space.
+ *
+ * Used by:
+ * joyGetPos
+ *
+\**********************************************************************/
+ULONG putjoyinfo16 (VPJOYINFO16 vpjoyi, LPJOYINFO lpjoyi)
+{
+ PJOYINFO16 pjoyi16;
+
+ /*
+ ** Protect against NULL pointers
+ */
+
+ MMGETOPTPTR(vpjoyi, sizeof(JOYINFO16), pjoyi16);
+ if ( pjoyi16 == NULL ) {
+ dprintf1(( "putjoyinfo16 MMGETOPTPTR returned a NULL pointer" ));
+ return JOYERR_PARMS;
+ }
+
+ STOREWORD(pjoyi16->wXpos, lpjoyi->wXpos);
+ STOREWORD(pjoyi16->wYpos, lpjoyi->wYpos);
+ STOREWORD(pjoyi16->wZpos, lpjoyi->wZpos);
+ STOREWORD(pjoyi16->wButtons, lpjoyi->wButtons);
+
+ FLUSHVDMPTR(vpjoyi, sizeof(JOYINFO16), pjoyi16);
+ FREEVDMPTR(pjoyi16);
+ return JOYERR_NOERROR;
+}
+#endif