/**************************************************************************** * * wdmdrv.h * * Function declarations, etc. for WDMAUD.DRV * * Copyright (C) Microsoft Corporation, 1997 - 1999 All Rights Reserved. * * History * 5-12-97 - Noel Cross (NoelC) * ***************************************************************************/ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #ifdef UNDER_NT #if (DBG) #define DEBUG #endif #endif #include #include /*************************************************************************** DEBUGGING SUPPORT ***************************************************************************/ #ifdef DEBUG extern VOID FAR __cdecl wdmaudDbgOut(LPSTR lpszFormat, ...); extern UINT uiDebugLevel; // debug level extern char szReturningErrorStr[]; extern char *MsgToAscii(ULONG ulMsg); // // Debug message levels: // #define DL_ERROR 0x00000000 #define DL_WARNING 0x00000001 #define DL_TRACE 0x00000002 #define DL_MAX 0x00000004 #define DL_MASK 0x000000FF // // 20 bits reserved for functional areas. If we find that this bit is set // in the DebugLevel variable, we will display every message of this type. // #define FA_AUX 0x80000000 #define FA_DEVICEIO 0x40000000 #define FA_SETUP 0x20000000 #define FA_MIDI 0x10000000 #define FA_WAVE 0x08000000 #define FA_RECORD 0x04000000 #define FA_EVENT 0x02000000 #define FA_MIXER 0x01000000 #define FA_DRV 0x00800000 #define FA_ASSERT 0x00400000 #define FA_RETURN 0x00200000 #define FA_SYNC 0x00100000 #define FA_MASK 0xFFFFF000 #define FA_ALL 0x00001000 extern VOID wdmaudDbgBreakPoint( ); extern UINT wdmaudDbgPreCheckLevel( UINT uiMsgLevel, char *pFunction, int iLine ); extern UINT wdmaudDbgPostCheckLevel( UINT uiMsgLevel ); extern char * wdmaudReturnString( ULONG ulMsg ); extern char szReturningErrorStr[]; //---------------------------------------------------------------------------- // // This debug macro is used like this: // // DPF(DL_WARNING|FA_MIXER,("Message %X %X %X ...",x,y,z,...) ); // // The output for this message will look like: // // WDMAUD.DRV FooFunction Warning Message 5 6 7 - Set BP on 64003452 to DBG // // The only difference between this code and the code in wdmaud.sys is that // to break in the debugger, you call DbgBreak() and to display a string you // call OutputDebugString(...). // // The call to wdmaudDbgPreCheckLevel displays: // // "WDMAUD.DRV FooFunction Warning " // // The call to wdmaudDbgOut displays the actual message // // "Message 5 6 7 ..." // // and the call to wdmaudDbgPostCheckLevel finishs the line // // " - Set BP on 64003452 to DBG" // //---------------------------------------------------------------------------- #define DPF(_x_,_y_) {if( wdmaudDbgPreCheckLevel(_x_,__FUNCTION__,__LINE__) ) { wdmaudDbgOut _y_; \ wdmaudDbgPostCheckLevel( _x_ ); }} // // Warning: Do not rap function calls in this return macro! Notice that // _mmr_ is used more then once, thus the function call would be made more // than once! // #define MMRRETURN( _mmr_ ) {if ( _mmr_ != MMSYSERR_NOERROR) \ { DPF(DL_WARNING|FA_RETURN, (szReturningErrorStr, _mmr_,MsgToAscii(_mmr_)) ); } \ return _mmr_;} // // It's bad form to put more then one expression in an assert macro. Why? because // you will not know exactly what expression failed the assert! // // dDbgAssert should be: // #define DPFASSERT(_exp_) {if( !(_exp_) ) {DPF(DL_ERROR|FA_ASSERT,("'%s'",#_exp_) );}} // #define WinAssert(exp) ((exp) ? (VOID)0 : dDbgAssert(#exp, __FILE__, __LINE__)) #define DbgBreak() DebugBreak() // The path trap macro ... #define DPFBTRAP() DPF(DL_ERROR|FA_ASSERT,("Path Trap, Please report") ); // // There are a number of internal structures that we want to keep tabs on. In // every case, there will be a signature in the structure that we can use when // verifying the content. // #define WAVEPREPAREDATA_SIGNATURE 'DPPW' //WPPD as seen in memory #define MIXERINSTANCE_SIGNATURE 'IMAW' // WAMI as seen in memory #else #define DPF( _x_,_y_ ) #define MMRRETURN( _mmr_ ) return (_mmr_) #define DPFASSERT(x) 0 #define DbgBreak() #endif #ifdef DEBUG // // Here are a couple of defines used to look for corruption paths // #define FOURTYTHREE 0x43434343 #define FOURTYTWO 0x42424242 #define FOURTYEIGHT 0x48484848 #else #define FOURTYTHREE NULL #define FOURTYTWO NULL #define FOURTYEIGHT NULL #endif /*************************************************************************** UNICODE SUPPORT ***************************************************************************/ // // Taken from winnt.h // // Neutral ANSI/UNICODE types and macros // #ifdef UNICODE #ifndef _TCHAR_DEFINED typedef WCHAR TCHAR, *PTCHAR; #define _TCHAR_DEFINED #define TEXT(quote) L##quote #endif /* !_TCHAR_DEFINED */ #else /* UNICODE */ #ifndef _TCHAR_DEFINED typedef char TCHAR, *PTCHAR; #define _TCHAR_DEFINED #define TEXT(quote) quote #endif /* !_TCHAR_DEFINED */ #endif /* UNICODE */ /**************************************************************************** Random defines and global variables ***************************************************************************/ #define WDMAUD_MAX_DEVICES 100 extern LPDEVICEINFO pWaveDeviceList; extern LPDEVICEINFO pMidiDeviceList; extern CRITICAL_SECTION wdmaudCritSec; #ifdef UNDER_NT #define CRITENTER EnterCriticalSection( (LPCRITICAL_SECTION)DeviceInfo->DeviceState->csQueue ) #define CRITLEAVE LeaveCriticalSection( (LPCRITICAL_SECTION)DeviceInfo->DeviceState->csQueue ) #else extern WORD gwCritLevel ; // critical section counter #define CRITENTER if (!(gwCritLevel++)) _asm { cli } #define CRITLEAVE if (!(--gwCritLevel)) _asm { sti } #endif #ifdef UNDER_NT #define CALLBACKARRAYSIZE 128 typedef struct { DWORD dwID; DWORD dwCallbackType; } CBINFO; typedef struct { ULONG GlobalIndex; CBINFO Callbacks[CALLBACKARRAYSIZE]; } CALLBACKS, *PCALLBACKS; #endif // // These two macros are for validating error return codes from wdmaud.sys. // // This first one sets the input and output buffer for a DeviceIoControl call to // a known bad value. // #define PRESETERROR(_di) _di->mmr=0xDEADBEEF // // This macro reads: if the return value from wdmaudIoControl is SUCCESS THEN // check to see if there was an error code placed in the device info structure. // If so (we don't find DEADBEEF there), that is the real error value to return. // But, if during the call the value didn't get set, we'll find DEADBEEF in the // error location! Thus,the check for DEADBEEF that simply restores the device // info mmr entry to SUCCESS. // #define POSTEXTRACTERROR(r, _di) if( r == MMSYSERR_NOERROR ) { \ if( _di->mmr != 0xDEADBEEF ) { \ r = _di->mmr; \ } else { \ DPF(DL_TRACE|FA_DEVICEIO, ("wdmaudIoControl didn't set mmr %X:%s", r, MsgToAscii(r)) ); \ _di->mmr = MMSYSERR_NOERROR; } } #define EXTRACTERROR(r, _di) if( r == MMSYSERR_NOERROR ) { r = _di->mmr; } /**************************************************************************** Struture definitions ***************************************************************************/ typedef struct _WAVEPREPAREDATA { struct _DEVICEINFO FAR *pdi; LPOVERLAPPED pOverlapped; // Overlapped structure // for completion #ifdef DEBUG DWORD dwSig; // WPPD #endif } WAVEPREPAREDATA, FAR *PWAVEPREPAREDATA; /**************************************************************************** Driver entry points ***************************************************************************/ BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wHeapSize, LPSTR lpszCmdLine ); BOOL WINAPI DllEntryPoint ( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ); LRESULT _loadds CALLBACK DriverProc ( DWORD id, HDRVR hDriver, WORD msg, LPARAM lParam1, LPARAM lParam2 ); DWORD FAR PASCAL _loadds wodMessage ( UINT id, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); DWORD FAR PASCAL _loadds widMessage ( UINT id, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); DWORD FAR PASCAL _loadds modMessage ( UINT id, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); DWORD FAR PASCAL _loadds midMessage ( UINT id, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); DWORD FAR PASCAL _loadds mxdMessage ( UINT id, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); /**************************************************************************** Local routines ***************************************************************************/ BOOL DrvInit(); HANDLE wdmaOpenKernelDevice(); VOID DrvEnd(); LPDEVICEINFO GlobalAllocDeviceInfo(LPCWSTR DeviceInterface); VOID GlobalFreeDeviceInfo(LPDEVICEINFO lpdi); MMRESULT wdmaudOpenDev ( LPDEVICEINFO DeviceInfo, LPWAVEFORMATEX lpWaveFormat ); MMRESULT FAR wdmaudCloseDev ( LPDEVICEINFO DeviceInfo ); MMRESULT FAR wdmaudGetDevCaps ( LPDEVICEINFO DeviceInfo, MDEVICECAPSEX FAR *MediaDeviceCapsEx ); DWORD FAR wdmaudGetNumDevs ( UINT DeviceType, LPCWSTR DeviceInterface ); DWORD FAR wdmaudAddRemoveDevNode ( UINT DeviceType, LPCWSTR DeviceInterface, BOOL fAdd ); DWORD FAR wdmaudSetPreferredDevice ( UINT DeviceType, UINT DeviceNumber, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); MMRESULT FAR wdmaudIoControl ( LPDEVICEINFO DeviceInfo, DWORD dwSize, LPVOID pData, ULONG IoCode ); MMRESULT wdmaudSetDeviceState ( LPDEVICEINFO DeviceInfo, ULONG IoCode ); MMRESULT wdmaudGetPos ( LPDEVICEINFO pClient, LPMMTIME lpmmt, DWORD dwSize, UINT DeviceType ); VOID FAR midiCallback ( LPDEVICEINFO pMidi, UINT msg, DWORD_PTR dw1, DWORD_PTR dw2 ); MMRESULT FAR midiOpen ( LPDEVICEINFO DeviceInfo, DWORD_PTR dwUser, LPMIDIOPENDESC pmod, DWORD dwParam2 ); VOID FAR midiCleanUp ( LPDEVICEINFO pClient ); MMRESULT midiInRead ( LPDEVICEINFO pClient, LPMIDIHDR pHdr ); MMRESULT FAR midiOutWrite ( LPDEVICEINFO pClient, DWORD ulEvent ); VOID FAR midiOutAllNotesOff ( LPDEVICEINFO pClient ); VOID FAR waveCallback ( LPDEVICEINFO pWave, UINT msg, DWORD_PTR dw1 ); MMRESULT waveOpen ( LPDEVICEINFO DeviceInfo, DWORD_PTR dwUser, LPWAVEOPENDESC pwod, DWORD dwParam2 ); VOID waveCleanUp ( LPDEVICEINFO pClient ); MMRESULT waveWrite ( LPDEVICEINFO pClient, LPWAVEHDR pHdr ); MMRESULT wdmaudSubmitWaveHeader ( LPDEVICEINFO DeviceInfo, LPWAVEHDR pHdr ); MMRESULT FAR wdmaudSubmitMidiOutHeader ( LPDEVICEINFO DeviceInfo, LPMIDIHDR pHdr ); MMRESULT wdmaudSubmitMidiInHeader ( LPDEVICEINFO DeviceInfo, LPMIDIHDR pHdrex ); VOID waveCompleteHeader ( LPDEVICEINFO DeviceInfo ); VOID midiInCompleteHeader ( LPDEVICEINFO DeviceInfo, DWORD dwTimeStamp, WORD wDataType ); VOID midiInEventCallback ( HANDLE MidiHandle, DWORD dwEvent ); #ifdef UNDER_NT PSECURITY_DESCRIPTOR BuildSecurityDescriptor ( DWORD AccessMask ); void DestroySecurityDescriptor ( PSECURITY_DESCRIPTOR pSd ); MMRESULT wdmaudPrepareWaveHeader ( LPDEVICEINFO DeviceInfo, LPWAVEHDR pHdr ); MMRESULT wdmaudUnprepareWaveHeader ( LPDEVICEINFO DeviceInfo, LPWAVEHDR pHdr ); MMRESULT wdmaudGetMidiData ( LPDEVICEINFO DeviceInfo, LPMIDIDATALISTENTRY pOldMidiDataListEntry ); void wdmaudParseMidiData ( LPDEVICEINFO DeviceInfo, LPMIDIDATALISTENTRY pMidiData ); void wdmaudFreeMidiData ( LPDEVICEINFO DeviceInfo, LPMIDIDATALISTENTRY pMidiData ); MMRESULT wdmaudFreeMidiQ ( LPDEVICEINFO DeviceInfo ); MMRESULT wdmaudCreateCompletionThread ( LPDEVICEINFO DeviceInfo ); MMRESULT wdmaudDestroyCompletionThread ( LPDEVICEINFO DeviceInfo ); #endif MMRESULT IsValidDeviceInfo( LPDEVICEINFO lpDeviceInfo ); MMRESULT IsValidDeviceState( LPDEVICESTATE lpDeviceState, BOOL bFullyConfigured ); MMRESULT IsValidWaveHeader( LPWAVEHDR pWaveHdr ); MMRESULT IsValidMidiHeader( LPMIDIHDR pMidiHdr ); MMRESULT IsValidPrepareWaveHeader( PWAVEPREPAREDATA pPrepare ); BOOL IsValidDeviceInterface( LPCWSTR DeviceInterface ); MMRESULT IsValidOverLapped( LPOVERLAPPED lpol ); MMRESULT IsValidMidiDataListEntry( LPMIDIDATALISTENTRY pMidiDataListEntry ); MMRESULT IsValidWaveOpenDesc( LPWAVEOPENDESC pwod ); #ifdef DEBUG #define ISVALIDDEVICEINFO(x) IsValidDeviceInfo(x) #define ISVALIDDEVICESTATE(x,y) IsValidDeviceState(x,y) #define ISVALIDWAVEHEADER(x) IsValidWaveHeader(x) #define ISVALIDMIDIHEADER(x) IsValidMidiHeader(x) #define ISVALIDPREPAREWAVEHEADER(x) IsValidPrepareWaveHeader(x) #define ISVALIDDEVICEINTERFACE(x) IsValidDeviceInterface(x) #define ISVALIDOVERLAPPED(x) IsValidOverLapped(x) #define ISVALIDMIDIDATALISTENTRY(x) IsValidMidiDataListEntry(x) #define ISVALIDWAVEOPENDESC(x) IsValidWaveOpenDesc(x) #else #define ISVALIDDEVICEINFO(x) #define ISVALIDDEVICESTATE(x,y) #define ISVALIDWAVEHEADER(x) #define ISVALIDMIDIHEADER(x) #define ISVALIDPREPAREWAVEHEADER(x) #define ISVALIDDEVICEINTERFACE(x) #define ISVALIDOVERLAPPED(x) #define ISVALIDMIDIDATALISTENTRY(x) #define ISVALIDWAVEOPENDESC(x) #endif #ifndef UNDER_NT VOID WaveDeviceCallback(); VOID MidiInDeviceCallback(); VOID MidiEventDeviceCallback(); VOID MixerDeviceCallback(); #endif PCALLBACKS wdmaGetCallbacks(); PCALLBACKS wdmaCreateCallbacks(); #ifdef __cplusplus } #endif