windows-nt/Source/XPSP1/NT/base/mvdm/wow32/wmmstruc.c
2020-09-26 16:20:57 +08:00

763 lines
23 KiB
C

/*++
*
* 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