763 lines
23 KiB
C
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
|