diff options
Diffstat (limited to 'private/mvdm/wow16/mmsystem/mixer.c')
-rw-r--r-- | private/mvdm/wow16/mmsystem/mixer.c | 1950 |
1 files changed, 1950 insertions, 0 deletions
diff --git a/private/mvdm/wow16/mmsystem/mixer.c b/private/mvdm/wow16/mmsystem/mixer.c new file mode 100644 index 000000000..36ff0e9f4 --- /dev/null +++ b/private/mvdm/wow16/mmsystem/mixer.c @@ -0,0 +1,1950 @@ +//==========================================================================; +// +// mixapi.c +// +// Copyright (C) 1992-1993 Microsoft Corporation. All Rights Reserved. +// +// Description: +// +// +// History: +// 6/27/93 cjp [curtisp] +// +//==========================================================================; +#define _WINDLL +#include <windows.h> +#include <windowsx.h> +#include <string.h> + +#include <mmsystem.h> +#include <mmddk.h> + +#include "mmreg.h" +#include "mmsysi.h" + +// +// fix a conflict will a bad define in MMREG.H that shipped with NT +// the define is bogus for some silly Media Vision crap... +// +// why not just build MSMIXMGR with a NEW mmreg.h?? +// +#ifdef MIXERR_BASE +#undef MIXERR_BASE +#endif // MIXERR_BASE + + +#define _INC_MMDDK +#include "msmixmgr.y" + + +#define WODM_MAPPER_STATUS (0x2000) +#define WAVEOUT_MAPPER_STATUS_DEVICE 0 +#define WIDM_MAPPER_STATUS (0x2000) +#define WAVEIN_MAPPER_STATUS_DEVICE 0 + +#include "idrv.h" +#include "mixmgri.h" +#include "debug.h" + +UINT FAR PASCAL +mmCallProc32( + DWORD uId, + DWORD uMsg, + DWORD dwInst, + DWORD dwP1, + DWORD dwP2, + DRIVERMSGPROC fp, + DWORD dwDirChange ); + +/* ------------------------------------------------------------------------- +** thunking global variables +** ------------------------------------------------------------------------- +*/ +DWORD mix32Lib; + +BOOL FAR PASCAL +InitMixerThunks( + void + ); + +DWORD CALLBACK +mxdMessage( + UINT uId, + UINT uMsg, + DWORD dwInstance, + DWORD dwParam1, + DWORD dwParam2 + ); + +#define CHECK_AND_INIT_THUNKS( _x_ ) \ + if ( (_x_) == 0L ) { \ + if ( InitMixerThunks() == FALSE ) { \ + return MMSYSERR_NODRIVER; \ + } \ + } + +UINT guTotalMixerDevs; // total mixer devices +DRIVERMSGPROC mix32Message; +typedef MMDRV MIXERDRV, *PMIXERDRV; + + +// +// +// +typedef struct tMIXERDEV { + UINT uHandleType; // for parameter validation + + struct tMIXERDEV *pmxdevNext; /* How quaint, a linked list... */ + PMIXERDRV pmxdrv; + UINT wDevice; + DWORD dwDrvUser; + UINT uDeviceID; + + DWORD fdwSupport; // from the driver's mixercaps + DWORD cDestinations; // from the driver's mixercaps + + DWORD dwCallback; // client's callback and inst data + DWORD dwInstance; + + DWORD fdwOpen; /* The open flags the caller used */ +} MIXERDEV, *PMIXERDEV; + +PMIXERDEV gpMixerDevHeader = NULL; /* A LL of open devices */ + +// +// mixer device driver list--add one to accomodate the MIXER_MAPPER. note +// that even if we are not compiling with mapper support we need to add +// one because other code relies on it (for other device mappers). +// +MIXERDRV mixerdrv[1]; + + + + +//==========================================================================; +// +// Mixer API's +// +// +//==========================================================================; + +//--------------------------------------------------------------------------; +// +// DWORD IMixerMapId +// +// Description: +// This function maps a logical id to a device driver table index and +// physical id. +// +// Arguments: +// PMIXERDRV pmxdrv: The array of mixer drivers. +// +// UINT uTotalNumDevs: The total number of mixer devices. +// +// UINT uId: The logical id to be mapped. +// +// Return (DWORD): +// The return value contains the dev[] array element id in the high word +// and the driver physical device number in the low word. +// +// Out of range values map to FFFF:FFFF +// +// History: +// 03/17/93 cjp [curtisp] +// +//--------------------------------------------------------------------------; + +DWORD NEAR PASCAL IMixerMapId( + PMIXERDRV pmxdrv, + UINT uTotalNumDevs, + UINT uId +) +{ + UINT u; + +#ifdef MIXER_MAPPER + // + // the mapper is always the last element of the MIXERDEV array. + // + if (uId == MIXER_MAPPER) + return (MAKELONG(0, MAXMIXERDRIVERS)); +#endif + + if (uId >= uTotalNumDevs) + return ((DWORD)-1); + +#ifdef DEBUG_RETAIL + if (fIdReverse) + uId = uTotalNumDevs - 1 - uId; +#endif + + for (u = 0; u < MAXMIXERDRIVERS; u++) + { + if (pmxdrv[u].bNumDevs > (BYTE)uId) + return (MAKELONG(uId, u)); + + uId -= pmxdrv[u].bNumDevs; + } + + return ((DWORD)-1); +} // IMixerMapId() + + +//--------------------------------------------------------------------------; +// +// DWORD IMixerMessageHandle +// +// Description: +// +// +// Arguments: +// HMIXER hmx: +// +// UINT uMsg: +// +// DWORD dwP1: +// +// DWORD dwP2: +// +// Return (DWORD): +// +// History: +// 03/17/93 cjp [curtisp] +// +//--------------------------------------------------------------------------; + +DWORD NEAR PASCAL IMixerMessageHandle( + HMIXER hmx, + UINT uMsg, + DWORD dwP1, + DWORD dwP2 +) +{ + PMIXERDEV pmxd; + DWORD dwRc; + + pmxd = (PMIXERDEV)hmx; + + dwRc = ((*(pmxd->pmxdrv->drvMessage)) + (pmxd->wDevice, uMsg, pmxd->dwDrvUser, dwP1, dwP2)); + + return dwRc; +} // IMixerMessageHandle() + + +//--------------------------------------------------------------------------; +// +// DWORD IMixerMessageId +// +// Description: +// +// +// Arguments: +// PMIXERDRV pmxdrv: +// +// UINT uTotalNumDevs: +// +// UINT uDeviceID: +// +// UINT uMsg: +// +// DWORD dwParam1: +// +// DWORD dwParam2: +// +// Return (DWORD): +// +// History: +// 03/17/93 cjp [curtisp] +// +//--------------------------------------------------------------------------; + +DWORD NEAR PASCAL IMixerMessageId( + PMIXERDRV pmxdrv, + UINT uTotalNumDevs, + UINT uDeviceID, + UINT uMsg, + DWORD dwParam1, + DWORD dwParam2 +) +{ + DWORD dwMap; + DWORD dwRc; + + dwMap = IMixerMapId(pmxdrv, uTotalNumDevs, uDeviceID); + + if (dwMap == (DWORD)-1) + return (MMSYSERR_BADDEVICEID); + + pmxdrv = (PMIXERDRV)&pmxdrv[HIWORD(dwMap)]; + if (!pmxdrv->drvMessage) + return (MMSYSERR_NODRIVER); + + dwRc = ((*(pmxdrv->drvMessage)) + ((UINT)dwMap, uMsg, 0L, dwParam1, dwParam2)); + + return dwRc; + +} // IMixerMessageId() + +/******************************Public*Routine******************************\ +* mixerGetNumDevs +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +UINT MIXAPI mixerGetNumDevs( + void +) +{ + + CHECK_AND_INIT_THUNKS(mix32Lib); + + return guTotalMixerDevs; +} + + + +/******************************Public*Routine******************************\ +* mixerGetDevCaps +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT MIXAPI mixerGetDevCaps( + UINT uMxId, + LPMIXERCAPS pmxcaps, + UINT cbmxcaps +) +{ + + MMRESULT mmr; + CHECK_AND_INIT_THUNKS(mix32Lib); + + if (0 == cbmxcaps) + return (MMSYSERR_NOERROR); + + V_WPOINTER(pmxcaps, cbmxcaps, MMSYSERR_INVALPARAM); + + if (uMxId >= MAXMIXERDRIVERS) + { + V_HANDLE((HMIXER)uMxId, TYPE_MIXER, MMSYSERR_INVALHANDLE); + + mmr = (MMRESULT)IMixerMessageHandle((HMIXER)uMxId, + MXDM_GETDEVCAPS, + (DWORD)pmxcaps, + (DWORD)cbmxcaps); + } + else + { + if (uMxId >= guTotalMixerDevs) + { + DebugErr1(DBF_ERROR, "mixerGetDevCaps: mixer device id is out of range (%u).", uMxId); + return (MMSYSERR_BADDEVICEID); + } + + mmr = (MMRESULT)IMixerMessageId(mixerdrv, + guTotalMixerDevs, + uMxId, + MXDM_GETDEVCAPS, + (DWORD)pmxcaps, + (DWORD)cbmxcaps); + } + return mmr; +} + + + +/******************************Public*Routine******************************\ +* mixerGetID +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT MIXAPI mixerGetID( + HMIXEROBJ hmxobj, + UINT FAR *puMxId, + DWORD fdwId +) +{ + CHECK_AND_INIT_THUNKS(mix32Lib); + return IMixerGetID( hmxobj, puMxId, NULL, fdwId ); +} + + +/*****************************Private*Routine******************************\ +* IMixerGetID +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT FNGLOBAL IMixerGetID( + HMIXEROBJ hmxobj, + UINT FAR *puMxId, + LPMIXERLINE pmxl, + DWORD fdwId +) +{ + MMRESULT mmr; + MIXERLINE mxl; + UINT u; + + V_DFLAGS(fdwId, MIXER_GETIDF_VALID, IMixerGetID, MMSYSERR_INVALFLAG); + V_WPOINTER(puMxId, sizeof(UINT), MMSYSERR_INVALPARAM); + + + // + // set to '-1' which would be the mixer mapper (if there was one) + // this way we will definitely fail any calls made on this id if + // this function fails and the caller doesn't check his return value. + // + *puMxId = (UINT)-1; + + + // + // + // + switch (MIXER_OBJECTF_TYPEMASK & fdwId) + { + case MIXER_OBJECTF_MIXER: + case MIXER_OBJECTF_HMIXER: + if ((UINT)hmxobj > MAXMIXERDRIVERS) + { + V_HANDLE(hmxobj, TYPE_MIXER, MMSYSERR_INVALHANDLE); + + *puMxId = ((PMIXERDEV)hmxobj)->uDeviceID; + return (MMSYSERR_NOERROR); + } + + if ((UINT)hmxobj >= guTotalMixerDevs) + { + DebugErr1(DBF_ERROR, "mixerGetID: mixer device id is out of range (%u).", hmxobj); + return (MMSYSERR_BADDEVICEID); + } + + *puMxId = (UINT)hmxobj; + return (MMSYSERR_NOERROR); + + + case MIXER_OBJECTF_HWAVEOUT: + { + UINT uId; + DWORD dwId; + + mmr = waveOutGetID((HWAVEOUT)hmxobj, &uId); + if (MMSYSERR_NOERROR != mmr) + { + return (MMSYSERR_INVALHANDLE); + } + + if (WAVE_MAPPER == uId) + { + mmr = (MMRESULT)waveOutMessage((HWAVEOUT)hmxobj, + WODM_MAPPER_STATUS, + WAVEOUT_MAPPER_STATUS_DEVICE, + (DWORD)(LPVOID)&dwId); + + if (MMSYSERR_NOERROR == mmr) + { + uId = (UINT)dwId; + } + } + + hmxobj = (HMIXEROBJ)uId; + } + + case MIXER_OBJECTF_WAVEOUT: + { + WAVEOUTCAPS woc; + + mmr = waveOutGetDevCaps((UINT)hmxobj, &woc, sizeof(woc)); + if (MMSYSERR_NOERROR != mmr) + return (MMSYSERR_BADDEVICEID); + + woc.szPname[SIZEOF(woc.szPname) - 1] = '\0'; + + mxl.Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT; + mxl.Target.dwDeviceID = (UINT)hmxobj; + mxl.Target.wMid = woc.wMid; + mxl.Target.wPid = woc.wPid; + mxl.Target.vDriverVersion = woc.vDriverVersion; + lstrcpy(mxl.Target.szPname, woc.szPname); + break; + } + + + case MIXER_OBJECTF_HWAVEIN: + { + UINT uId; + DWORD dwId; + + mmr = waveInGetID((HWAVEIN)hmxobj, &uId); + if (MMSYSERR_NOERROR != mmr) + { + return (MMSYSERR_INVALHANDLE); + } + + if (WAVE_MAPPER == uId) + { + mmr = (MMRESULT)waveInMessage((HWAVEIN)hmxobj, + WIDM_MAPPER_STATUS, + WAVEIN_MAPPER_STATUS_DEVICE, + (DWORD)(LPVOID)&dwId); + + if (MMSYSERR_NOERROR == mmr) + { + uId = (UINT)dwId; + } + } + + hmxobj = (HMIXEROBJ)uId; + } + + case MIXER_OBJECTF_WAVEIN: + { + WAVEINCAPS wic; + + mmr = waveInGetDevCaps((UINT)hmxobj, &wic, sizeof(wic)); + if (MMSYSERR_NOERROR != mmr) + return (MMSYSERR_BADDEVICEID); + + wic.szPname[SIZEOF(wic.szPname) - 1] = '\0'; + + mxl.Target.dwType = MIXERLINE_TARGETTYPE_WAVEIN; + mxl.Target.dwDeviceID = (UINT)hmxobj; + mxl.Target.wMid = wic.wMid; + mxl.Target.wPid = wic.wPid; + mxl.Target.vDriverVersion = wic.vDriverVersion; + lstrcpy(mxl.Target.szPname, wic.szPname); + break; + } + + + case MIXER_OBJECTF_HMIDIOUT: + mmr = midiOutGetID((HMIDIOUT)hmxobj, (UINT FAR *)&hmxobj); + if (MMSYSERR_NOERROR != mmr) + return (MMSYSERR_INVALHANDLE); + + case MIXER_OBJECTF_MIDIOUT: + { + MIDIOUTCAPS moc; + + mmr = midiOutGetDevCaps((UINT)hmxobj, &moc, sizeof(moc)); + if (MMSYSERR_NOERROR != mmr) + return (MMSYSERR_BADDEVICEID); + + moc.szPname[SIZEOF(moc.szPname) - 1] = '\0'; + + mxl.Target.dwType = MIXERLINE_TARGETTYPE_MIDIOUT; + mxl.Target.dwDeviceID = (UINT)hmxobj; + mxl.Target.wMid = moc.wMid; + mxl.Target.wPid = moc.wPid; + mxl.Target.vDriverVersion = moc.vDriverVersion; + lstrcpy(mxl.Target.szPname, moc.szPname); + break; + } + + + case MIXER_OBJECTF_HMIDIIN: + mmr = midiInGetID((HMIDIIN)hmxobj, (UINT FAR *)&hmxobj); + if (MMSYSERR_NOERROR != mmr) + return (MMSYSERR_INVALHANDLE); + + case MIXER_OBJECTF_MIDIIN: + { + MIDIINCAPS mic; + + mmr = midiInGetDevCaps((UINT)hmxobj, &mic, sizeof(mic)); + if (MMSYSERR_NOERROR != mmr) + return (MMSYSERR_BADDEVICEID); + + mic.szPname[SIZEOF(mic.szPname) - 1] = '\0'; + + mxl.Target.dwType = MIXERLINE_TARGETTYPE_MIDIIN; + mxl.Target.dwDeviceID = (UINT)hmxobj; + mxl.Target.wMid = mic.wMid; + mxl.Target.wPid = mic.wPid; + mxl.Target.vDriverVersion = mic.vDriverVersion; + lstrcpy(mxl.Target.szPname, mic.szPname); + break; + } + + + case MIXER_OBJECTF_AUX: + { + AUXCAPS ac; + + mmr = auxGetDevCaps((UINT)hmxobj, &ac, sizeof(ac)); + if (MMSYSERR_NOERROR != mmr) + return (MMSYSERR_BADDEVICEID); + + ac.szPname[SIZEOF(ac.szPname) - 1] = '\0'; + + mxl.Target.dwType = MIXERLINE_TARGETTYPE_AUX; + mxl.Target.dwDeviceID = (UINT)hmxobj; + mxl.Target.wMid = ac.wMid; + mxl.Target.wPid = ac.wPid; + mxl.Target.vDriverVersion = ac.vDriverVersion; + lstrcpy(mxl.Target.szPname, ac.szPname); + break; + } + + default: + DebugErr1(DBF_ERROR, "mixerGetID: unknown mixer object flag (%.08lXh).", + MIXER_OBJECTF_TYPEMASK & fdwId); + return (MMSYSERR_INVALFLAG); + } + + + // + // + // + // + mxl.cbStruct = sizeof(mxl); + mxl.dwDestination = (DWORD)-1L; + mxl.dwSource = (DWORD)-1L; + mxl.dwLineID = (DWORD)-1L; + mxl.fdwLine = 0; + mxl.dwUser = 0; + mxl.dwComponentType = (DWORD)-1L; + mxl.cChannels = 0; + mxl.cConnections = 0; + mxl.cControls = 0; + mxl.szShortName[0] = '\0'; + mxl.szName[0] = '\0'; + + + for (u = 0; u < guTotalMixerDevs; u++) + { + mmr = (MMRESULT)IMixerMessageId(mixerdrv, + guTotalMixerDevs, + u, + MXDM_GETLINEINFO, + (DWORD)(LPVOID)&mxl, + M_GLINFOF_TARGETTYPE); + + if (MMSYSERR_NOERROR == mmr) + { + *puMxId = u; + + if (NULL != pmxl) + { + DWORD cbStruct; + + cbStruct = pmxl->cbStruct; + + _fmemcpy(pmxl, &mxl, (UINT)cbStruct); + + pmxl->cbStruct = cbStruct; + } + + return (mmr); + } + } + + return (MMSYSERR_NODRIVER); +} // IMixerGetID() + + +/******************************Public*Routine******************************\ +* mixerOpen +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT MIXAPI mixerOpen( + LPHMIXER phmx, + UINT uMxId, + DWORD dwCallback, + DWORD dwInstance, + DWORD fdwOpen +) +{ + MMRESULT mmr; + DWORD dwMap; + PMIXERDRV pmxdrv; + PMIXERDEV pmxdev; + MIXEROPENDESC mxod; + DWORD dwDrvUser; + MIXERCAPS mxcaps; + + + CHECK_AND_INIT_THUNKS(mix32Lib); + + // + // + // + V_WPOINTER(phmx, sizeof(HMIXER), MMSYSERR_INVALPARAM); + + *phmx = NULL; + + // + // Don't allow callback functions - they're not useful and they + // cause headaches. Specifically for Windows NT the only way + // to cause an asynchronous callback to 16-bit land from a 32-bit DLL + // is to cause an interrupt but we don't want to require mixer stuff + // to be locked down to allow for this. + // + + if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION) + { + DebugErr(DBF_ERROR, "mixerOpen: CALLBACK_FUNCTION is not supported"); + return MMSYSERR_INVALFLAG; + } + + V_DCALLBACK(dwCallback, HIWORD(fdwOpen & CALLBACK_TYPEMASK), MMSYSERR_INVALPARAM); + V_DFLAGS(fdwOpen, MIXER_OPENF_VALID, mixerOpen, MMSYSERR_INVALFLAG); + + mmr = IMixerGetID((HMIXEROBJ)uMxId, &uMxId, NULL, (MIXER_OBJECTF_TYPEMASK & fdwOpen)); + if (MMSYSERR_NOERROR != mmr) + return (mmr); + + + // + // + // + // + dwMap = IMixerMapId(mixerdrv, guTotalMixerDevs, uMxId); + if ((DWORD)-1 == dwMap) + return (MMSYSERR_BADDEVICEID); + + pmxdrv = &mixerdrv[HIWORD(dwMap)]; + +#ifdef MIXER_MAPPER + // + // Default Mixer Mapper: + // + // If a mixer mapper is installed as a separate DLL then all mixer + // mapper messages are routed to it. If no mixer mapper is installed, + // simply loop through the mixer devices looking for a match. + // + if ((MIXER_MAPPER == uMxId) && (NULL == pmxdrv->drvMessage)) + { + for (uMxId = 0; uMxId < guTotalMixerDevs; uMxId++) + { + // try to open it + if (MMSYSERR_NOERROR == mmr) + break; + + } + + return (mmr); + } +#endif + + + // + // Get some memory for the dev structure + // + pmxdev = (PMIXERDEV)NewHandle(TYPE_MIXER, sizeof(MIXERDEV)); + if (NULL == pmxdev) + { + return (MMSYSERR_NOMEM); + } + + // + // initialize our open instance struct for the client + // + pmxdev->uHandleType = TYPE_MIXER; + pmxdev->pmxdrv = pmxdrv; + pmxdev->wDevice = LOWORD(dwMap); + pmxdev->uDeviceID = uMxId; + + // + // save the client's callback info + // + pmxdev->dwCallback = dwCallback; + pmxdev->dwInstance = dwInstance; + pmxdev->fdwOpen = fdwOpen; + + + // + // this should probably be done when the driver is booted.. can change + // this later.. + // + mmr = mixerGetDevCaps(uMxId, &mxcaps, sizeof(mxcaps)); + if (MMSYSERR_NOERROR != mmr) + { + DPF((0, "!mixerOpen() failing because mixerGetDevCaps() failed!")); + + FreeHandle((HMIXER)pmxdev); + return (mmr); + } + + // + // cache some stuff for parameter validation + // + pmxdev->fdwSupport = mxcaps.fdwSupport; + pmxdev->cDestinations = mxcaps.cDestinations; + + + // + // If we get here, no one has the device currently open. Let's + // go open it, then. + // + + // + // Load up our local MIXEROPENDESC struct + // + + mxod.hmx = (HMIXER)pmxdev; + mxod.pReserved0 = (LPVOID)(fdwOpen & ~MIXER_OBJECTF_TYPEMASK); + mxod.dwCallback = dwCallback; + mxod.dwInstance = dwInstance; + mmr = (MMRESULT)((*(pmxdrv->drvMessage))(LOWORD(dwMap), + MXDM_OPEN, + (DWORD)(LPDWORD)&dwDrvUser, + (DWORD)(LPVOID)&mxod, + (DWORD)uMxId )); + + + if (MMSYSERR_NOERROR != mmr) + { + FreeHandle((HMIXER)pmxdev); + } + else + { + pmxdrv->bUsage++; + pmxdev->dwDrvUser = dwDrvUser; + *phmx = (HMIXER)pmxdev; + + // + // Put this new device into the devlist chain. + // + + MIXMGR_ENTER; + + pmxdev->pmxdevNext = gpMixerDevHeader; + gpMixerDevHeader = pmxdev; + + MIXMGR_LEAVE; + } + return mmr; +} + + +/******************************Public*Routine******************************\ +* mixerClose +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT MIXAPI mixerClose( + HMIXER hmx +) +{ + MMRESULT mmr; + PMIXERDEV pmxdev; + PMIXERDEV pmxdevT; + + CHECK_AND_INIT_THUNKS(mix32Lib); + V_HANDLE(hmx, TYPE_MIXER, MMSYSERR_INVALHANDLE); + + + // + // if last open instance, then close it + // + mmr = (MMRESULT)IMixerMessageHandle(hmx, MXDM_CLOSE, 0L, 0L); + + if (MMSYSERR_NOERROR != mmr) + return (mmr); + + + // + // remove the mixer handle from the linked list + // + + MIXMGR_ENTER; + + pmxdev = (PMIXERDEV)hmx; + if (pmxdev == gpMixerDevHeader) + { + gpMixerDevHeader = pmxdev->pmxdevNext; + } + else + { + for (pmxdevT = gpMixerDevHeader; + pmxdevT && (pmxdevT->pmxdevNext != pmxdev); + pmxdevT = pmxdevT->pmxdevNext) + ; + + if (NULL == pmxdevT) + { + DebugErr1(DBF_ERROR, "mixerClose: invalid mixer handle (%.04Xh).", hmx); + return (MMSYSERR_INVALHANDLE); + } + + pmxdevT->pmxdevNext = pmxdev->pmxdevNext; + } + + MIXMGR_LEAVE; + + // + // dec usage count + // + pmxdev->pmxdrv->bUsage--; + + + // + // we're done with the memory block. now free the memory and return. + // + FreeHandle(hmx); + return mmr; +} + + +/******************************Public*Routine******************************\ +* mixerMessage +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +DWORD MIXAPI mixerMessage( + HMIXER hmx, + UINT uMsg, + DWORD dwParam1, + DWORD dwParam2 +) +{ + DWORD dw; + + CHECK_AND_INIT_THUNKS(mix32Lib); + V_HANDLE(hmx, TYPE_MIXER, MMSYSERR_INVALHANDLE); + + // + // don't allow any non-user range messages through this API + // + if (MXDM_USER > uMsg) + { + DebugErr1(DBF_ERROR, "mixerMessage: message must be in MXDM_USER range--what's this (%u)?", uMsg); + return (MMSYSERR_INVALPARAM); + } + + + dw = IMixerMessageHandle(hmx, uMsg, dwParam1, dwParam2); + return dw; +} + + +//--------------------------------------------------------------------------; +// +// BOOL IMixerIsValidComponentType +// +// Description: +// +// +// Arguments: +// DWORD dwComponentType: +// +// UINT uSrcDst: +// +// Return (BOOL): +// +// History: +// 10/06/93 cjp [curtisp] +// +//--------------------------------------------------------------------------; + +BOOL FNLOCAL IMixerIsValidComponentType( + DWORD dwComponentType, + DWORD fdwLine +) +{ + + if (0L == (MIXERLINE_LINEF_SOURCE & fdwLine)) + { + if (dwComponentType > MLCT_DST_LAST) + return (FALSE); + + return (TRUE); + } + else + { + if (dwComponentType < MLCT_SRC_FIRST) + return (FALSE); + + if (dwComponentType > MLCT_SRC_LAST) + return (FALSE); + + return (TRUE); + } + + return (FALSE); +} // IMixerIsValidComponentType() + + + +/******************************Public*Routine******************************\ +* mixerGetLineInfo +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT MIXAPI mixerGetLineInfo( + HMIXEROBJ hmxobj, + LPMIXERLINE pmxl, + DWORD fdwInfo +) +{ + DWORD fdwMxObjType; + MMRESULT mmr; + PMIXERDEV pmxdev; + UINT uMxId; + BOOL fSourceLine; + + CHECK_AND_INIT_THUNKS(mix32Lib); + + V_DFLAGS(fdwInfo, M_GLINFOF_VALID, mixerGetLineInfo, MMSYSERR_INVALFLAG); + V_WPOINTER(pmxl, sizeof(DWORD), MMSYSERR_INVALPARAM); + if (sizeof(MIXERLINE) > (UINT)pmxl->cbStruct) + { + DebugErr1(DBF_ERROR, "mixerGetLineInfo: structure size too small or cbStruct not initialized (%lu).", pmxl->cbStruct); + return (MMSYSERR_INVALPARAM); + } + V_WPOINTER(pmxl, pmxl->cbStruct, MMSYSERR_INVALPARAM); + + + // + // + // + fSourceLine = FALSE; + switch (fdwInfo & M_GLINFOF_QUERYMASK) + { + case M_GLINFOF_DESTINATION: + pmxl->dwSource = (DWORD)-1L; + pmxl->dwLineID = (DWORD)-1L; + pmxl->dwComponentType = (DWORD)-1L; + break; + + case M_GLINFOF_SOURCE: + fSourceLine = TRUE; + pmxl->dwLineID = (DWORD)-1L; + pmxl->dwComponentType = (DWORD)-1L; + break; + + case M_GLINFOF_LINEID: + pmxl->dwSource = (DWORD)-1L; + pmxl->dwDestination = (DWORD)-1L; + pmxl->dwComponentType = (DWORD)-1L; + break; + + case M_GLINFOF_COMPONENTTYPE: + pmxl->dwSource = (DWORD)-1L; + pmxl->dwDestination = (DWORD)-1L; + pmxl->dwLineID = (DWORD)-1L; + + if (!IMixerIsValidComponentType(pmxl->dwComponentType, 0) && + !IMixerIsValidComponentType(pmxl->dwComponentType, MIXERLINE_LINEF_SOURCE)) + { + DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid dwComponentType (%lu).", pmxl->dwComponentType); + return (MMSYSERR_INVALPARAM); + } + break; + + case M_GLINFOF_TARGETTYPE: + pmxl->dwSource = (DWORD)-1L; + pmxl->dwDestination = (DWORD)-1L; + pmxl->dwLineID = (DWORD)-1L; + pmxl->dwComponentType = (DWORD)-1L; + + if ((DWORD)MIXERLINE_TARGETTYPE_AUX < pmxl->Target.dwType) + { + DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid Target.dwType (%lu).", pmxl->Target.dwType); + return (MMSYSERR_INVALPARAM); + } + break; + + default: + DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid query flag (%.08lXh).", + fdwInfo & M_GLINFOF_QUERYMASK); + return (MMSYSERR_INVALFLAG); + } + + + + // + // + // + fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwInfo); + + mmr = IMixerGetID(hmxobj, &uMxId, pmxl, fdwMxObjType); + if (MMSYSERR_NOERROR != mmr) + { + DPF((0, "!IMixerGetLineInfo: IMixerGetID() failed!")); + return (mmr); + } + + if ((MIXER_OBJECTF_MIXER == fdwMxObjType) || + (MIXER_OBJECTF_HMIXER == fdwMxObjType)) + { + // + // if a mixer device id was passed, then null hmx so we use the + // correct message sender below + // + if ((UINT)hmxobj == uMxId) + hmxobj = NULL; + } + else + { + return (MMSYSERR_NOERROR); + } + + + // + // clear all fields before calling driver + // + if (NULL != hmxobj) + { + // + // + // + pmxdev = (PMIXERDEV)hmxobj; +#if 0 + if (pmxdev->cDestinations <= pmxl->dwDestination) + { + DebugErr1(DBF_ERROR, "mixerGetLineInfo: invalid destination index (%lu).", pmxl->dwDestination); + return (MMSYSERR_INVALPARAM); + } +#endif + + mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj, + MXDM_GETLINEINFO, + (DWORD)(LPVOID)pmxl, + fdwInfo); + } + else + { +#pragma message("----IMixerGetLineInfo: dwDestination not validated for ID's!!") + mmr = (MMRESULT)IMixerMessageId(mixerdrv, + guTotalMixerDevs, + uMxId, + MXDM_GETLINEINFO, + (DWORD)(LPVOID)pmxl, + fdwInfo); + } + + if (MMSYSERR_NOERROR != mmr) + return (mmr); + +#pragma message("----IMixerGetLineInfo: should validate mixer driver didn't hose us!") + + + // + // validate the driver's returned stuff... + // + // + if (sizeof(MIXERLINE) != (UINT)pmxl->cbStruct) + { + DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver returned invalid cbStruct (%lu).", pmxl->cbStruct); + pmxl->cbStruct = sizeof(MIXERLINE); + } + + if ((DWORD)-1L == pmxl->dwDestination) + { + DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwDestination member."); + } + if (fSourceLine) + { + if (0L == (MIXERLINE_LINEF_SOURCE & pmxl->fdwLine)) + { + DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to set MIXERLINE_LINEF_SOURCE."); + pmxl->fdwLine |= MIXERLINE_LINEF_SOURCE; + } + + if ((DWORD)-1L == pmxl->dwSource) + { + DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwSource member."); + } + } + if ((DWORD)-1L == pmxl->dwLineID) + { + DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver failed to init dwLineID member."); + } + if (pmxl->fdwLine & ~0x80008001L) + { + DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver set reserved line flags (%.08lXh)!", pmxl->fdwLine); + pmxl->fdwLine &= 0x80008001L; + } + if (!IMixerIsValidComponentType(pmxl->dwComponentType, pmxl->fdwLine)) + { + DebugErr1(DBF_ERROR, "mixerGetLineInfo: buggy driver returned invalid dwComponentType (%.08lXh).", pmxl->dwComponentType); + pmxl->dwComponentType = MIXERLINE_TARGETTYPE_UNDEFINED; + } + if (0L == pmxl->cChannels) + { + DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver returned zero channels?!?"); + pmxl->cChannels = 1; + } + if (fSourceLine) + { + if (0L != pmxl->cConnections) + { + DebugErr(DBF_ERROR, "mixerGetLineInfo: buggy driver returned non-zero connections on source?!?"); + pmxl->cConnections = 0; + } + } + + pmxl->szShortName[SIZEOF(pmxl->szShortName) - 1] = '\0'; + pmxl->szName[SIZEOF(pmxl->szName) - 1] = '\0'; + + + // + // Does this really need to be done if TARGETTYPE was requested? + // + + + // + // + // + if ((DWORD)MIXERLINE_TARGETTYPE_UNDEFINED != pmxl->Target.dwType) + { + UINT u; + + pmxl->Target.dwDeviceID = (DWORD)-1L; + + + // + // we have a wMid, wPid and szPname (supposedly) of type dwType + // so let's go find it... + // + switch (pmxl->Target.dwType) + { + case MIXERLINE_TARGETTYPE_WAVEOUT: + u = waveOutGetNumDevs(); + while (u--) + { + WAVEOUTCAPS woc; + + mmr = waveOutGetDevCaps(u, &woc, sizeof(woc)); + if (MMSYSERR_NOERROR != mmr) + continue; + + woc.szPname[SIZEOF(woc.szPname) - 1] = '\0'; + + if (woc.wMid != pmxl->Target.wMid) + continue; + + if (woc.wPid != pmxl->Target.wPid) + continue; + + if (woc.vDriverVersion != pmxl->Target.vDriverVersion) + continue; + + if (lstrcmp(woc.szPname, pmxl->Target.szPname)) + continue; + + pmxl->Target.dwDeviceID = u; + break; + } + break; + + case MIXERLINE_TARGETTYPE_WAVEIN: + u = waveInGetNumDevs(); + while (u--) + { + WAVEINCAPS wic; + + mmr = waveInGetDevCaps(u, &wic, sizeof(wic)); + if (MMSYSERR_NOERROR != mmr) + continue; + + wic.szPname[SIZEOF(wic.szPname) - 1] = '\0'; + + if (wic.wMid != pmxl->Target.wMid) + continue; + + if (wic.wPid != pmxl->Target.wPid) + continue; + + if (wic.vDriverVersion != pmxl->Target.vDriverVersion) + continue; + + if (lstrcmp(wic.szPname, pmxl->Target.szPname)) + continue; + + pmxl->Target.dwDeviceID = u; + break; + } + break; + + case MIXERLINE_TARGETTYPE_MIDIOUT: + u = midiOutGetNumDevs(); + while (u--) + { + MIDIOUTCAPS moc; + + mmr = midiOutGetDevCaps(u, &moc, sizeof(moc)); + if (MMSYSERR_NOERROR != mmr) + continue; + + moc.szPname[SIZEOF(moc.szPname) - 1] = '\0'; + + if (moc.wMid != pmxl->Target.wMid) + continue; + + if (moc.wPid != pmxl->Target.wPid) + continue; + + if (moc.vDriverVersion != pmxl->Target.vDriverVersion) + continue; + + if (lstrcmp(moc.szPname, pmxl->Target.szPname)) + continue; + + pmxl->Target.dwDeviceID = u; + break; + } + break; + + case MIXERLINE_TARGETTYPE_MIDIIN: + u = midiInGetNumDevs(); + while (u--) + { + MIDIINCAPS mic; + + mmr = midiInGetDevCaps(u, &mic, sizeof(mic)); + if (MMSYSERR_NOERROR != mmr) + continue; + + mic.szPname[SIZEOF(mic.szPname) - 1] = '\0'; + + if (mic.wMid != pmxl->Target.wMid) + continue; + + if (mic.wPid != pmxl->Target.wPid) + continue; + + if (mic.vDriverVersion != pmxl->Target.vDriverVersion) + continue; + + if (lstrcmp(mic.szPname, pmxl->Target.szPname)) + continue; + + pmxl->Target.dwDeviceID = u; + break; + } + break; + + case MIXERLINE_TARGETTYPE_AUX: + u = auxGetNumDevs(); + while (u--) + { + AUXCAPS ac; + + mmr = auxGetDevCaps(u, &ac, sizeof(ac)); + if (MMSYSERR_NOERROR != mmr) + continue; + + ac.szPname[SIZEOF(ac.szPname) - 1] = '\0'; + + if (ac.wMid != pmxl->Target.wMid) + continue; + + if (ac.wPid != pmxl->Target.wPid) + continue; + + if (ac.vDriverVersion != pmxl->Target.vDriverVersion) + continue; + + if (lstrcmp(ac.szPname, pmxl->Target.szPname)) + continue; + + pmxl->Target.dwDeviceID = u; + break; + } + break; + + default: + pmxl->Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED; + break; + } + } + + return mmr; +} + + +/******************************Public*Routine******************************\ +* mixerGetLineControls +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT MIXAPI mixerGetLineControls( + HMIXEROBJ hmxobj, + LPMIXERLINECONTROLS pmxlc, + DWORD fdwControls +) +{ + DWORD fdwMxObjType; + UINT uMxId; + MMRESULT mmr; + + CHECK_AND_INIT_THUNKS(mix32Lib); + V_DFLAGS(fdwControls, M_GLCONTROLSF_VALID, mixerGetLineControls, MMSYSERR_INVALFLAG); + V_WPOINTER(pmxlc, sizeof(DWORD), MMSYSERR_INVALPARAM); + + // + // the structure header for MIXERLINECONTROLS must be at least the + // minimum size + // + if (sizeof(MIXERLINECONTROLS) > (UINT)pmxlc->cbStruct) + { + DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbStruct not initialized (%lu).", pmxlc->cbStruct); + return (MMSYSERR_INVALPARAM); + } + V_WPOINTER(pmxlc, pmxlc->cbStruct, MMSYSERR_INVALPARAM); + + if (sizeof(MIXERCONTROL) > (UINT)pmxlc->cbmxctrl) + { + DebugErr1(DBF_ERROR, "mixerGetLineControls: structure size too small or cbmxctrl not initialized (%lu).", pmxlc->cbmxctrl); + return (MMSYSERR_INVALPARAM); + } + + + // + // + // + switch (M_GLCONTROLSF_QUERYMASK & fdwControls) + { + case M_GLCONTROLSF_ALL: + if (0L == pmxlc->cControls) + { + DebugErr(DBF_ERROR, "mixerGetLineControls: cControls cannot be zero."); + return (MMSYSERR_INVALPARAM); + } + + + pmxlc->dwControlID = (DWORD)-1L; + break; + + case M_GLCONTROLSF_ONEBYID: + pmxlc->dwLineID = (DWORD)-1L; + + // -- fall through -- + + case M_GLCONTROLSF_ONEBYTYPE: + pmxlc->cControls = (DWORD)1; + break; + + default: + DebugErr1(DBF_ERROR, "mixerGetLineControls: invalid query flags (%.08lXh).", + M_GLCONTROLSF_QUERYMASK & fdwControls); + return (MMSYSERR_INVALFLAG); + } + + V_WPOINTER(pmxlc->pamxctrl, pmxlc->cControls * pmxlc->cbmxctrl, MMSYSERR_INVALPARAM); + + + // + // + // + fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwControls); + + mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType); + if (MMSYSERR_NOERROR != mmr) + return (mmr); + + if ((MIXER_OBJECTF_MIXER == fdwMxObjType) || + (MIXER_OBJECTF_HMIXER == fdwMxObjType)) + { + // + // if a mixer device id was passed, then null hmx so we use the + // correct message sender below + // + if ((UINT)hmxobj == uMxId) + hmxobj = NULL; + } + else + { + hmxobj = NULL; + fdwControls &= ~MIXER_OBJECTF_TYPEMASK; + fdwControls |= MIXER_OBJECTF_MIXER; + } + + + + // + // + // + // + if (NULL != hmxobj) + { + mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj, + MXDM_GETLINECONTROLS, + (DWORD)pmxlc, + fdwControls); + } + else + { + mmr = (MMRESULT)IMixerMessageId(mixerdrv, + guTotalMixerDevs, + uMxId, + MXDM_GETLINECONTROLS, + (DWORD)pmxlc, + fdwControls); + } + + return mmr; +} + + +/******************************Public*Routine******************************\ +* mixerGetControlDetails +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT MIXAPI mixerGetControlDetails( + HMIXEROBJ hmxobj, + LPMIXERCONTROLDETAILS pmxcd, + DWORD fdwDetails +) +{ + DWORD fdwMxObjType; + MMRESULT mmr; + UINT uMxId; + UINT cDetails; + + CHECK_AND_INIT_THUNKS(mix32Lib); + V_DFLAGS(fdwDetails, M_GCDSF_VALID, mixerGetControlDetails, MMSYSERR_INVALFLAG); + V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM); + + // + // the structure header for MIXERCONTROLDETAILS must be at least the + // minimum size + // + if (sizeof(MIXERCONTROLDETAILS) > (UINT)pmxcd->cbStruct) + { + DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct); + return (MMSYSERR_INVALPARAM); + } + V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM); + + + switch (M_GCDSF_QUERYMASK & fdwDetails) + { + case M_GCDSF_VALUE: + // + // if both cChannels and cMultipleItems are zero, it is a + // custom control + // + if ((0L == pmxcd->cChannels) && (0L == pmxcd->cMultipleItems)) + { + if (0L == pmxcd->cbDetails) + { + DebugErr(DBF_ERROR, "mixerGetControlDetails: cbDetails cannot be zero."); + return (MMSYSERR_INVALPARAM); + } + + V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM); + + } + else + { + if (0L == pmxcd->cChannels) + { + DebugErr(DBF_ERROR, "mixerGetControlDetails: cChannels for _VALUE cannot be zero."); + return (MMSYSERR_INVALPARAM); + } + + + if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_SIGNED)) + { + DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails); + return (MMSYSERR_INVALPARAM); + } + + // + // + // + cDetails = (UINT)pmxcd->cChannels; + if (0L != pmxcd->cMultipleItems) + { + cDetails *= (UINT)pmxcd->cMultipleItems; + } + + V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM); + } + break; + + case M_GCDSF_LISTTEXT: + if (0L == pmxcd->cChannels) + { + DebugErr(DBF_ERROR, "mixerGetControlDetails: cChannels for _LISTTEXT cannot be zero."); + return (MMSYSERR_INVALPARAM); + } + + if (2L > pmxcd->cMultipleItems) + { + DebugErr(DBF_ERROR, "mixerGetControlDetails: cMultipleItems for _LISTTEXT must be 2 or greater."); + return (MMSYSERR_INVALPARAM); + } + + if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_LISTTEXT)) + { + DebugErr1(DBF_ERROR, "mixerGetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails); + return (MMSYSERR_INVALPARAM); + } + + cDetails = (UINT)pmxcd->cChannels * (UINT)pmxcd->cMultipleItems; + V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM); + break; + + default: + DebugErr1(DBF_ERROR, "mixerGetControlDetails: invalid query flags (%.08lXh).", + M_GCDSF_QUERYMASK & fdwDetails); + return (MMSYSERR_INVALFLAG); + } + + + + // + // + // + fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwDetails); + + mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType); + if (MMSYSERR_NOERROR != mmr) + return (mmr); + + if ((MIXER_OBJECTF_MIXER == fdwMxObjType) || + (MIXER_OBJECTF_HMIXER == fdwMxObjType)) + { + // + // if a mixer device id was passed, then null hmx so we use the + // correct message sender below + // + if ((UINT)hmxobj == uMxId) + hmxobj = NULL; + } + else + { + hmxobj = NULL; + fdwDetails &= ~MIXER_OBJECTF_TYPEMASK; + fdwDetails |= MIXER_OBJECTF_MIXER; + } + + // + // + // + // + if (NULL != hmxobj) + { + mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj, + MXDM_GETCONTROLDETAILS, + (DWORD)pmxcd, + fdwDetails); + } + else + { + mmr = (MMRESULT)IMixerMessageId(mixerdrv, + guTotalMixerDevs, + uMxId, + MXDM_GETCONTROLDETAILS, + (DWORD)pmxcd, + fdwDetails); + } + + return mmr; +} + + +/******************************Public*Routine******************************\ +* mixerSetControlDetails +* +* +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +MMRESULT MIXAPI mixerSetControlDetails( + HMIXEROBJ hmxobj, + LPMIXERCONTROLDETAILS pmxcd, + DWORD fdwDetails +) +{ + DWORD fdwMxObjType; + MMRESULT mmr; + UINT uMxId; + UINT cDetails; + + CHECK_AND_INIT_THUNKS(mix32Lib); + V_DFLAGS(fdwDetails, M_SCDF_VALID, mixerSetControlDetails, MMSYSERR_INVALFLAG); + V_WPOINTER(pmxcd, sizeof(DWORD), MMSYSERR_INVALPARAM); + + // + // the structure header for MIXERCONTROLDETAILS must be at least the + // minimum size + // + if (sizeof(MIXERCONTROLDETAILS) > (UINT)pmxcd->cbStruct) + { + DebugErr1(DBF_ERROR, "mixerSetControlDetails: structure size too small or cbStruct not initialized (%lu).", pmxcd->cbStruct); + return (MMSYSERR_INVALPARAM); + } + V_WPOINTER(pmxcd, pmxcd->cbStruct, MMSYSERR_INVALPARAM); + + + + switch (M_SCDF_QUERYMASK & fdwDetails) + { + case M_SCDF_VALUE: + // + // cChannels is zero for custom controls + // + if (0L == pmxcd->cChannels) + { + if (0L == pmxcd->cbDetails) + { + DebugErr(DBF_ERROR, "mixerSetControlDetails: cbDetails cannot be zero."); + return (MMSYSERR_INVALPARAM); + } + + V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM); + + // + // + // + if (0L != pmxcd->cMultipleItems) + { + DebugErr(DBF_ERROR, "mixerSetControlDetails: cMultipleItems must be zero for custom controls."); + return (MMSYSERR_INVALPARAM); + } + } + else + { + if (pmxcd->cbDetails < sizeof(MIXERCONTROLDETAILS_SIGNED)) + { + DebugErr1(DBF_ERROR, "mixerSetControlDetails: structure size too small or cbDetails not initialized (%lu).", pmxcd->cbDetails); + return (MMSYSERR_INVALPARAM); + } + + cDetails = (UINT)pmxcd->cChannels; + + // + // + // + if (0L != pmxcd->cMultipleItems) + { + cDetails *= (UINT)(pmxcd->cMultipleItems); + } + + V_WPOINTER(pmxcd->paDetails, cDetails * pmxcd->cbDetails, MMSYSERR_INVALPARAM); + } + break; + + case M_SCDF_CUSTOM: + if (0L == pmxcd->cbDetails) + { + DebugErr(DBF_ERROR, "mixerSetControlDetails: cbDetails cannot be zero for custom controls."); + return (MMSYSERR_INVALPARAM); + } + + if (0L != pmxcd->cChannels) + { + DebugErr(DBF_ERROR, "mixerSetControlDetails: cChannels must be zero for custom controls."); + return (MMSYSERR_INVALPARAM); + } + + V_WPOINTER(pmxcd->paDetails, pmxcd->cbDetails, MMSYSERR_INVALPARAM); + + // + // + // + if ((NULL != pmxcd->hwndOwner) && !IsWindow(pmxcd->hwndOwner)) + { + DebugErr1(DBF_ERROR, "mixerSetControlDetails: hwndOwner must be a valid window handle (%.04Xh).", pmxcd->hwndOwner); + return (MMSYSERR_INVALHANDLE); + } + break; + + default: + DebugErr1(DBF_ERROR, "mixerSetControlDetails: invalid query flags (%.08lXh).", + M_SCDF_QUERYMASK & fdwDetails); + return (MMSYSERR_INVALFLAG); + } + + + // + // + // + fdwMxObjType = (MIXER_OBJECTF_TYPEMASK & fdwDetails); + + mmr = IMixerGetID(hmxobj, &uMxId, NULL, fdwMxObjType); + if (MMSYSERR_NOERROR != mmr) + return (mmr); + + if ((MIXER_OBJECTF_MIXER == fdwMxObjType) || + (MIXER_OBJECTF_HMIXER == fdwMxObjType)) + { + // + // if a mixer device id was passed, then null hmx so we use the + // correct message sender below + // + if ((UINT)hmxobj == uMxId) + hmxobj = NULL; + } + else + { + fdwDetails &= ~MIXER_OBJECTF_TYPEMASK; + fdwDetails |= MIXER_OBJECTF_MIXER; + hmxobj = NULL; + } + + // + // + // + // + if (NULL != hmxobj) + { + mmr = (MMRESULT)IMixerMessageHandle((HMIXER)hmxobj, + MXDM_SETCONTROLDETAILS, + (DWORD)pmxcd, + fdwDetails); + } + else + { + mmr = (MMRESULT)IMixerMessageId(mixerdrv, + guTotalMixerDevs, + uMxId, + MXDM_SETCONTROLDETAILS, + (DWORD)pmxcd, + fdwDetails); + } + + return mmr; +} + +/*****************************Private*Routine******************************\ +* InitMixerThunks +* +* Initializes the thunking system. +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +BOOL FAR PASCAL +InitMixerThunks( + void + ) +{ + + /* + ** For WOW we have a fake device driver (that actually lives inside + ** this library). When an applications makes an api call to this + ** library we check to see is the WOW thunks are loaded. If they are + ** not loaded "InitWOWThunks" is called. This function loads the 32 + ** bit library and determines the total number of mixer devices + ** present in the system. It then sets mixerdrv[0].bUsage + ** and guTotalMixerDevs to this value. This appears to the 16 bit code + ** that we have one 16 bit device driver that supports all the + ** 32 bit devices !!. The entry point to this fake driver is + ** mxdMessage, which just passes the message through to the 32 bit + ** side. + */ + + mixerdrv[0].hDriver = NULL; + mixerdrv[0].bNumDevs = (BYTE)0; + mixerdrv[0].bUsage = 0; + mixerdrv[0].drvMessage = mxdMessage; + guTotalMixerDevs = 0; + + + /* + ** First try winmm.dll + */ + mix32Lib = LoadLibraryEx32W( "winmm.dll", NULL, 0L ); + if ( mix32Lib ) { + mix32Message = (DRIVERMSGPROC)GetProcAddress32W( mix32Lib, + "mxd32Message" ); + if ( mix32Message ) { + + mxdMessage( 0, MXDM_INIT, 0L, 0L, 0L ); + guTotalMixerDevs = (UINT)mxdMessage( 0, MXDM_GETNUMDEVS, + 0L, 0L, 0L ); + + mixerdrv[0].bNumDevs = (BYTE)guTotalMixerDevs; + return TRUE; + } + } + + /* + ** Then try msmix32.dll + */ + mix32Lib = LoadLibraryEx32W( "msmix32.dll", NULL, 0L ); + if ( mix32Lib ) { + + mix32Message = (DRIVERMSGPROC)GetProcAddress32W( mix32Lib, + "mxd32Message" ); + if ( mix32Message ) { + + mxdMessage( 0, MXDM_INIT, 0L, 0L, 0L ); + guTotalMixerDevs = (UINT)mxdMessage( 0, MXDM_GETNUMDEVS, + 0L, 0L, 0L ); + + mixerdrv[0].bNumDevs = (BYTE)guTotalMixerDevs; + return TRUE; + } + } + + /* + ** Give up !! + */ + return FALSE; + +} + + +/*****************************Private*Routine******************************\ +* mxdMessage +* +* Entry point for the fake WOW device driver. +* +* History: +* dd-mm-93 - StephenE - Created +* +\**************************************************************************/ +DWORD CALLBACK +mxdMessage( + UINT uId, + UINT uMsg, + DWORD dwInstance, + DWORD dwParam1, + DWORD dwParam2 + ) +{ + return mmCallProc32( (DWORD)uId, (DWORD)uMsg, dwInstance, + dwParam1, dwParam2, mix32Message, 0L ); +} |