Windows2003-3790/multimedia/media/winmm/winmmi.h
2020-09-30 16:53:55 +02:00

1448 lines
50 KiB
C++

/***************************************************************************
* winmmi.h
*
* Copyright (c) 1990-2001 Microsoft Corporation
*
* private include file
*
* History
*
* 15 Jan 92 - Robin Speed (RobinSp) and Steve Davies (SteveDav) -
* major NT update
* 6 Feb 92 - LaurieGr replaced HLOCAL by HANDLE
*
***************************************************************************/
/***************************************************************************
Useful include files for winmm component
***************************************************************************/
#define DEBUG_RETAIL /* Parameter checking is IN */
#if DBG
#ifndef DEBUG
#define DEBUG
#endif
#endif
#ifndef WINMMI_H
#define WINMMI_H /* Protect against double inclusion */
#ifndef RC_INVOKED
#include <string.h>
#include <stdio.h>
#endif /* RC_INVOKED */
#include <windows.h>
#include "mmsystem.h" /* Pick up the public header */
#include "mmsysp.h" /* pick up the internal definitions */
#include "mmcommon.h" /* pick up the definitions common to the NT project */
#ifndef NODDK
#include "mmddkp.h"
#endif
extern BOOL WinmmRunningInWOW; // Are we running in WOW
/*--------------------------------------------------------------------*\
* Unicode helper macros
\*--------------------------------------------------------------------*/
#define SZCODE CHAR
#define WSZCODE WCHAR
#define BYTE_GIVEN_CHAR(x) ( (x) * sizeof( WCHAR ) )
#define CHAR_GIVEN_BYTE(x) ( (x) / sizeof( WCHAR ) )
int Iwcstombs(LPSTR lpstr, LPCWSTR lpwstr, int len);
int Imbstowcs(LPWSTR lpwstr, LPCSTR lpstr, int len);
/***************************************************************************
Definitions to help with common windows code
***************************************************************************/
#define HPSTR LPSTR
#ifndef RC_INVOKED /* These are defined to RC */
#define STATICDT
#define STATICFN
#define STATIC
#if DBG
extern void InitDebugLevel(void);
void mciCheckLocks(void);
#undef STATICDT
#undef STATICFN
#undef STATIC
#define STATICDT
#define STATICFN
#define STATIC
#else
#define InitDebugLevel()
#endif /* DBG */
#endif /* RC_INVOKED */
/**************************************************************************
**************************************************************************/
#define APPLICATION_DESKTOP_NAME TEXT("Default")
/**************************************************************************
Strings related to INI files
**************************************************************************/
/*
// File and section names for sound aliases
*/
#define SOUND_INI_FILE L"win.ini"
#define SOUND_SECTION L"Sounds"
#define SOUND_DEFAULT L".Default"
#define SOUND_RESOURCE_TYPE_SOUND L"SOUND" // in .rc file
#define SOUND_RESOURCE_TYPE_WAVE L"WAVE" // in .rc file
extern WSZCODE szSystemDefaultSound[]; // Name of the default sound
extern WSZCODE szSoundSection[]; // WIN.INI section for sounds
extern WSZCODE wszSystemIni[]; // defined in Winmm.c
extern WSZCODE wszDrivers[]; // defined in Winmm.c
extern WSZCODE wszNull[]; // defined in Winmm.c
// HACK!! HACK!! Should update \nt\private\inc\mmcommon.h
#ifndef MMDRVI_MIXER
#define MMDRVI_MIXER 0x0007
#define MXD_MESSAGE "mxdMessage";
#endif
#define STR_ALIAS_SYSTEMASTERISK 3000
#define STR_ALIAS_SYSTEMQUESTION 3001
#define STR_ALIAS_SYSTEMHAND 3002
#define STR_ALIAS_SYSTEMEXIT 3003
#define STR_ALIAS_SYSTEMSTART 3004
#define STR_ALIAS_SYSTEMWELCOME 3005
#define STR_ALIAS_SYSTEMEXCLAMATION 3006
#define STR_ALIAS_SYSTEMDEFAULT 3007
#define STR_LABEL_APPGPFAULT 3008
#define STR_LABEL_CLOSE 3009
#define STR_LABEL_EMPTYRECYCLEBIN 3010
#define STR_LABEL_MAXIMIZE 3011
#define STR_LABEL_MENUCOMMAND 3012
#define STR_LABEL_MENUPOPUP 3013
#define STR_LABEL_MINIMIZE 3014
#define STR_LABEL_OPEN 3015
#define STR_LABEL_RESTOREDOWN 3016
#define STR_LABEL_RESTOREUP 3017
#define STR_LABEL_RINGIN 3018
#define STR_LABEL_RINGOUT 3019
#define STR_LABEL_SYSTEMASTERISK 3020
#define STR_LABEL_SYSTEMDEFAULT 3021
#define STR_LABEL_SYSTEMEXCLAMATION 3022
#define STR_LABEL_SYSTEMEXIT 3023
#define STR_LABEL_SYSTEMHAND 3024
#define STR_LABEL_SYSTEMQUESTION 3025
#define STR_LABEL_SYSTEMSTART 3026
#define STR_WINDOWS_APP_NAME 3027
#define STR_EXPLORER_APP_NAME 3028
#define STR_JOYSTICKNAME 3029
/*
// File and section names for the mci functions
*/
#define MCIDRIVERS_INI_FILE L"system.ini"
#define MCI_HANDLERS MCI_SECTION
/***********************************************************************
*
* Wrap InitializeCriticalSection to make it easier to handle error
*
***********************************************************************/
_inline BOOL mmInitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
{
try {
InitializeCriticalSection(lpCriticalSection);
return TRUE;
} except (EXCEPTION_EXECUTE_HANDLER) {
return FALSE;
}
}
/***********************************************************************
*
* Speed up profile stuff by going straight to the registry
*
***********************************************************************/
LONG
RegQuerySzValue(
HKEY hkey,
PCTSTR pValueName,
PTSTR *ppstrValue
);
VOID mmRegFree(VOID);
BOOL
mmRegCreateUserKey (
LPCWSTR lpszPathName,
LPCWSTR lpszKeyName
);
BOOL
mmRegQueryUserKey (
LPCWSTR lpszKeyName
);
BOOL
mmRegDeleteUserKey (
LPCWSTR lpszKeyName
);
BOOL
mmRegSetUserValue (
LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
LPCWSTR lpszValue
);
BOOL
mmRegQueryUserValue (
LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
ULONG dwLen,
LPWSTR lpszValue
);
BOOL
mmRegCreateMachineKey (
LPCWSTR lpszPath,
LPCWSTR lpszNewKey
);
BOOL
mmRegSetMachineValue (
LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
LPCWSTR lpszValue
);
BOOL
mmRegQueryMachineValue (
LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
ULONG dwLen,
LPWSTR lpszValue
);
DWORD
winmmGetProfileString(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD nSize
);
DWORD
winmmGetPrivateProfileString(
LPCWSTR lpSection,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD nSize,
LPCWSTR lpFileName
);
/***********************************************************************
*
* Used by hwndNotify code
*
***********************************************************************/
extern BOOL sndMessage( LPWSTR lszSoundName, UINT wFlags );
extern BOOL InitAsyncSound(VOID);
extern CRITICAL_SECTION WavHdrCritSec;
extern CRITICAL_SECTION SoundCritSec;
extern CRITICAL_SECTION mciGlobalCritSec;
/***********************************************************************
*
* Critical section for NumDevs/DeviceID's, and other stuff
*
***********************************************************************/
extern CRITICAL_SECTION NumDevsCritSec;
extern HANDLE hEventApiInit;
extern CRITICAL_SECTION midiStrmHdrCritSec;
extern CRITICAL_SECTION joyCritSec; //in joy.c, qzheng
extern CRITICAL_SECTION ResolutionCritSec; //in time.c
extern CRITICAL_SECTION TimerThreadCritSec; //in time.c
/***********************************************************************
*
* Flag deduced by initialization to special case running in the server
*
***********************************************************************/
extern BOOL WinmmRunningInServer; // Are we running in the user/base server?
/***********************************************************************
*
* prototypes from "winmm.c"
*
***********************************************************************/
void WaveMapperInit(void);
void MidiMapperInit(void);
void midiEmulatorInit(void);
/***********************************************************************
*
* prototypes from "mmiomisc.c"
*
***********************************************************************/
PBYTE AsciiStrToUnicodeStr( PBYTE pdst, PBYTE pmax, LPCSTR psrc );
PBYTE UnicodeStrToAsciiStr( PBYTE pdst, PBYTE pmax, LPCWSTR psrc);
LPWSTR AllocUnicodeStr( LPCSTR lpSourceStr );
BOOL FreeUnicodeStr( LPWSTR lpStr );
LPSTR AllocAsciiStr( LPCWSTR lpSourceStr );
BOOL FreeAsciiStr( LPSTR lpStr );
/***********************************************************************
*
* prototypes from "mmio.c"
*
***********************************************************************/
void mmioCleanupIOProcs(HANDLE hTask);
/***********************************************************************
*
* Timer functions
*
***********************************************************************/
#ifndef MMNOTIMER
BOOL TimeInit(void);
void TimeCleanup(DWORD ThreadId);
UINT timeSetEventInternal(UINT wDelay, UINT wResolution,
LPTIMECALLBACK lpFunction, DWORD_PTR dwUser, UINT wFlags, BOOL IsWOW);
#endif // !MMNOTIMER
/***********************************************************************
*
* Information structure used to play sounds
*
***********************************************************************/
#define PLAY_NAME_SIZE 256
typedef struct _PLAY_INFO {
HANDLE hModule;
HANDLE hRequestingTask; // Handle of thread that requested sound
DWORD dwFlags;
WCHAR szName[1]; // the structure will be allocated large enough for the name
} PLAY_INFO, *PPLAY_INFO;
#define WAIT_FOREVER ((DWORD)(-1))
/***************************************************************************
global data
***************************************************************************/
extern HANDLE ghInst;
HANDLE hHeap;
extern DWORD gTlsIndex;
extern BOOL gfDisablePreferredDeviceReordering;
/***************************************************************************
*
* Define the product version to be returned from
* mmsystemgetversion and any other messagebox or
* API that needs the public product version.
*
***************************************************************************/
#define MMSYSTEM_VERSION 0X030A
typedef UINT MMMESSAGE; // Multi media message type (internal)
#ifndef WM_MM_RESERVED_FIRST // Copy constants from winuserp.h
#define WM_MM_RESERVED_FIRST 0x03A0
#define WM_MM_RESERVED_LAST 0x03DF
#endif
#define MM_POLYMSGBUFRDONE (WM_MM_RESERVED_FIRST+0x2B)
#define MM_SND_PLAY (WM_MM_RESERVED_FIRST+0x2C)
#define MM_SND_ABORT (WM_MM_RESERVED_FIRST+0x2D)
#define MM_SND_SEND (WM_MM_RESERVED_FIRST+0x2E)
#define MM_SND_WAIT (WM_MM_RESERVED_FIRST+0x2F)
#define MCIWAITMSG (MM_SND_WAIT)
#if MM_SND_WAIT > WM_MM_RESERVED_LAST
#error "MM_SND_WAIT is defined beyond the reserved WM_MM range"
#endif
/***************************************************************************
DEBUGGING SUPPORT
***************************************************************************/
#if DBG
#ifdef DEBUGLEVELVAR
// So that other WINMM related modules can use their own debug level
// variable
#define winmmDebugLevel DEBUGLEVELVAR
#endif
extern int winmmDebugLevel;
extern void winmmDbgOut(LPSTR lpszFormat, ...);
extern void dDbgAssert(LPSTR exp, LPSTR file, int line);
DWORD __dwEval;
extern void winmmDbgOut(LPSTR lpszFormat, ...);
#define dprintf( _x_ ) winmmDbgOut _x_
#define dprintf1( _x_ ) if (winmmDebugLevel >= 1) winmmDbgOut _x_
#define dprintf2( _x_ ) if (winmmDebugLevel >= 2) winmmDbgOut _x_
#define dprintf3( _x_ ) if (winmmDebugLevel >= 3) winmmDbgOut _x_
#define dprintf4( _x_ ) if (winmmDebugLevel >= 4) winmmDbgOut _x_
#define dprintf5( _x_ ) if (winmmDebugLevel >= 5) winmmDbgOut _x_
#define dprintf6( _x_ ) if (winmmDebugLevel >= 6) winmmDbgOut _x_
#define WinAssert(exp) \
((exp) ? (void)0 : dDbgAssert(#exp, __FILE__, __LINE__))
#define WinEval(exp) \
((__dwEval=(DWORD)(exp)), \
__dwEval ? (void)0 : dDbgAssert(#exp, __FILE__, __LINE__), __dwEval)
#define DOUT(x) (OutputDebugStringA x, 0)
// #define DOUTX(x) (OutputDebugStringA x, 0)
// #define ROUTS(x) (OutputDebugStringA(x), OutputDebugStringA("\r\n"), 0)
#define ROUTSW(x) (OutputDebugStringW x, OutputDebugStringW(L"\r\n"), 0)
#define ROUT(x) (OutputDebugStringA x, OutputDebugStringA("\r\n"), 0)
// #define ROUTX(x) (OutputDebugStringA(x), 0)
#else
#define dprintf(x) ((void) 0)
#define dprintf1(x) ((void) 0)
#define dprintf2(x) ((void) 0)
#define dprintf3(x) ((void) 0)
#define dprintf4(x) ((void) 0)
#define dprintf5(x) ((void) 0)
#define dprintf6(x) ((void) 0)
#define WinAssert(exp) ((void) 0)
#define WinEval(exp) (exp)
#define DOUT(x) ((void) 0)
// #define DOUTX(x) ((void) 0)
// #define ROUTS(x) ((void) 0)
#define ROUT(x) ((void) 0)
// #define ROUTX(x) ((void) 0)
#endif
/***************************************************************************
Resource IDs
***************************************************************************/
#define IDS_TASKSTUB 2000
#define STR_MCIUNKNOWN 2001 /* "Unknown error returned from MCI command" */
// #define STR_WAVEINPUT 2004
// #define STR_WAVEOUTPUT 2005
// #define STR_MIDIINPUT 2006
// #define STR_MIDIOUTPUT 2007
#define STR_MCISSERRTXT 2009
#define STR_MCISCERRTXT 2010
#define STR_MIDIMAPPER 2011
#define STR_DRIVERS 2012
#define STR_SYSTEMINI 2013
#define STR_BOOT 2014
/***************************************************************************
Memory allocation using our local heap
***************************************************************************/
HANDLE hHeap;
PVOID winmmAlloc(DWORD cb);
PVOID winmmReAlloc(PVOID ptr, DWORD cb);
#define winmmFree(ptr) HeapFree(hHeap, 0, (ptr))
void Squirt(LPSTR lpszFormat, ...);
/***************************************************************************
LOCKING AND UNLOCKING MEMORY
***************************************************************************/
#if 0
BOOL HugePageLock(LPVOID lpArea, DWORD dwLength);
void HugePageUnlock(LPVOID lpArea, DWORD dwLength);
#else
#define HugePageLock(lpArea, dwLength) (TRUE)
#define HugePageUnlock(lpArea, dwLength)
#endif
/***************************************************************************
Pnp Structures and related functions.
***************************************************************************/
void ClientUpdatePnpInfo();
//#ifdef DBG
#if 0
#define EnterNumDevs(a) Squirt("Allocating NumDevs CS [%s]", a); EnterCriticalSection(&NumDevsCritSec)
#define LeaveNumDevs(a) LeaveCriticalSection(&NumDevsCritSec); Squirt("Releasing NumDevs CS [%s]", a)
#else
#define EnterNumDevs(a) EnterCriticalSection(&NumDevsCritSec)
#define LeaveNumDevs(a) LeaveCriticalSection(&NumDevsCritSec)
#endif
BOOL wdmDevInterfaceInc(IN PCWSTR pstrDeviceInterface);
BOOL wdmDevInterfaceDec(IN PCWSTR pstrDeviceInterface);
/****************************************************************************
API to install/remove/query a MMSYS driver
****************************************************************************/
/* generic prototype for audio device driver entry-point functions
// midMessage(), modMessage(), widMessage(), wodMessage(), auxMessage()
*/
typedef DWORD (APIENTRY *DRIVERMSGPROC)(DWORD, DWORD, DWORD_PTR, DWORD_PTR, DWORD_PTR);
/*
@doc INTERNAL MMSYSTEM
@type UINT | HMD |
This type definition specifies a handle to media resource entry. This
can be used as a unique identifier when specifying a media resource.
*/
DECLARE_HANDLE(HMD);
typedef struct _MMDRV* PMMDRV;
void mregAddDriver(IN PMMDRV pdrvZ, IN PMMDRV pdrv);
MMRESULT mregCreateStringIdFromDriverPort(IN PMMDRV pdrv, IN UINT port, OUT PWSTR* pStringId, OUT ULONG* pcbStringId);
MMRESULT mregGetIdFromStringId(IN PMMDRV pdrvZ, IN PCWSTR StringId, OUT UINT *puDeviceID);
BOOL FAR PASCAL mregHandleInternalMessages(IN PMMDRV pdrv, DWORD dwType, UINT Port, UINT msg, DWORD_PTR dw1, DWORD_PTR dw2, MMRESULT * pmmr);
DWORD FAR PASCAL mregDriverInformation(UINT uDeviceID, WORD fwClass, UINT uMessage, DWORD dwParam1, DWORD dwParam2);
UINT FAR PASCAL mregIncUsage(HMD hmd);
UINT FAR PASCAL mregIncUsagePtr(IN PMMDRV pmd);
UINT FAR PASCAL mregDecUsage(HMD hmd);
UINT FAR PASCAL mregDecUsagePtr(IN PMMDRV pmd);
MMRESULT FAR PASCAL mregFindDevice(UINT uDeviceID, WORD fwFindDevice, HMD FAR* phmd, UINT FAR* puDevicePort);
/*****************************************************************************
Driver stuff - This will change when we work out the real
installable driver story on NT
****************************************************************************/
LRESULT DrvClose(HANDLE hDriver, LPARAM lParam1, LPARAM lParam2);
HANDLE DrvOpen(LPCWSTR szDriverName, LPCWSTR szSectionName, LPARAM lParam2);
LRESULT DrvSendMessage(HANDLE hDriver, UINT message, LPARAM lParam1, LPARAM lParam2);
//HMODULE APIENTRY DrvGetModuleHandle(HDRVR hDriver);
BOOL DrvIsPreXp(IN HANDLE hDriver);
typedef DWORD (DRVPROC)(HANDLE hDriver, UINT msg, LONG lp1, LONG lp2);
typedef DRVPROC *LPDRVPROC;
//
// Init and Cleanup Joystick service, in joy.c
//
BOOL JoyInit(void);
void JoyCleanup(void);
/*
** Special function for creating threads inside the server process (we only
** use this to create the thread for playing sounds)
*/
BOOLEAN CreateServerPlayingThread(PVOID ThreadStartRoutine);
/*
// exclude some stuff if MMDDK.H is not included
*/
#ifdef MMDDKINC /* use this to test for MMDDK.H */
#define MMDRV_DESERTED 0x00000001
#define MMDRV_MAPPER 0x00000002
#define MMDRV_PREXP 0x00000004
//
// base drv instance list node struct
//
typedef struct _MMDRV *PMMDRV;
typedef struct _MMDRV
{
PMMDRV Next;
PMMDRV Prev;
PMMDRV NextStringIdDictNode;
PMMDRV PrevStringIdDictNode;
HANDLE hDriver; /* handle to the module */
WCHAR wszMessage[20]; /* name of entry point */
DRIVERMSGPROC drvMessage; /* pointer to entry point */
ULONG NumDevs; /* number of devices supported */
ULONG Usage; /* usage count (number of handle's open) */
// ISSUE-2001/01/05-FrankYe Rename cookie to DeviceInterface
PCWSTR cookie; /* PnP driver device interface */
DWORD fdwDriver; /* flags for driver */
CRITICAL_SECTION MixerCritSec; /* Serialize use of mixer */
WCHAR wszDrvEntry[64]; /* driver filename */
WCHAR wszSessProtocol[10];
/* Session protocol name, empty
if console driver */
} MMDRV, *PMMDRV;
#ifndef MMNOMIDI
/****************************************************************************
Preferred devices
****************************************************************************/
void waveOutGetCurrentConsoleVoiceComId(PUINT pPrefId, PDWORD pdwFlags);
void waveOutGetCurrentPreferredId(PUINT pPrefId, PDWORD pdwFlags);
MMRESULT waveOutSetPersistentConsoleVoiceComId(UINT PrefId, DWORD dwFlags);
MMRESULT waveOutSetPersistentPreferredId(UINT PrefId, DWORD dwFlags);
void waveInGetCurrentConsoleVoiceComId(PUINT pPrefId, PDWORD pdwFlags);
void waveInGetCurrentPreferredId(PUINT pPrefId, PDWORD pdwFlags);
MMRESULT waveInSetPersistentPreferredId(UINT PrefId, DWORD dwFlags);
MMRESULT waveInSetPersistentConsoleVoiceComId(UINT PrefId, DWORD dwFlags);
void midiOutGetCurrentPreferredId(PUINT pPrefId, PDWORD dwFlags);
MMRESULT midiOutSetPersistentPreferredId(UINT PrefId, DWORD dwFlags);
void InvalidatePreferredDevices(void);
void RefreshPreferredDevices(void);
/****************************************************************************
Clock routines used by MIDI. These routines provide clocks which run
at the current tempo or SMPTE rate based on timeGetTime().
****************************************************************************/
typedef DWORD MILLISECS;
typedef long TICKS;
#define CLK_CS_PAUSED 0x00000001L
#define CLK_CS_RUNNING 0x00000002L
#define CLK_TK_NOW ((TICKS)-1L)
//
// This structure is allocated by the client (probably in a handle structure)
// in MMSYSTEM's DS and passed as a near pointer.
//
typedef struct tag_clock *PCLOCK;
typedef DWORD (FAR PASCAL *CLK_TIMEBASE)(PCLOCK);
typedef struct tag_clock
{
MILLISECS msPrev;
TICKS tkPrev;
MILLISECS msT0;
DWORD dwNum;
DWORD dwDenom;
DWORD dwState;
CLK_TIMEBASE fnTimebase;
} CLOCK;
void FAR PASCAL clockInit(PCLOCK pclock, MILLISECS msPrev, TICKS tkPrev, CLK_TIMEBASE fnTimebase);
void FAR PASCAL clockSetRate(PCLOCK pclock, TICKS tkWhen, DWORD dwNum, DWORD dwDenom);
void FAR PASCAL clockPause(PCLOCK pclock, TICKS tkWhen);
void FAR PASCAL clockRestart(PCLOCK pclock, TICKS tkWhen, MILLISECS msWhen);
TICKS FAR PASCAL clockTime(PCLOCK pclock);
MILLISECS FAR PASCAL clockMsTime(PCLOCK pclock);
MILLISECS FAR PASCAL clockOffsetTo(PCLOCK pclock, TICKS tkWhen);
/****************************************************************************
Macros and prototypes shared by the MIDI subsystem.
****************************************************************************/
// #pragma message() with file/line numbers!
//
#define __PRAGMSG(l,x,c) message(__FILE__"("#l") : "c": "x)
#define _WARN(l,x) __PRAGMSG(l,x, "warning")
#define WARNMSG(x) _WARN(__LINE__,x)
#define _FIX(l,x) __PRAGMSG(l,x, "fix")
#define FIXMSG(x) _FIX(__LINE__,x)
#define DEFAULT_TEMPO 500000L // 500,000 uSec/qn == 120 BPM
#define DEFAULT_TIMEDIV 24 // 24 ticks per quarter note
#define DEFAULT_CBTIMEOUT 100 // 100 milliseconds
#define PM_STATE_READY 0 // polymsg ready to play
#define PM_STATE_BLOCKED 1 // Blocked on outgoing SysEx
#define PM_STATE_EMPTY 2 // No polymsg queued
#define PM_STATE_STOPPED 3 // Just opened/reset/stopped
// No polymsg sent yet.
#define PM_STATE_PAUSED 4 // Paused at some position
#define MIN_PERIOD 1 // millisecs of timer resolution
//
// Macros for dealing with time division dword
//
#define IS_SMPTE 0x00008000L
#define METER_NUM(dw) (UINT)((HIWORD(dw)>>8)&0x00FF)
#define METER_DENOM(dw) (UINT)(HIWORD(dw)&0x00FF)
#define TICKS_PER_QN(dw) (UINT)((dw)&0x7FFF)
#define SMPTE_FORMAT(dw) (((int)((dw)&0xFF00))>>8)
#define TICKS_PER_FRAME(dw) (UINT)((dw)&0x00FF)
//
// Constants for 30-Drop format conversion
//
#define S30D_FRAMES_PER_10MIN 17982
#define S30D_FRAMES_PER_MIN 1798
//
// SMPTE formats from MIDI file time division
//
#define SMPTE_24 24
#define SMPTE_25 25
#define SMPTE_30DROP 29
#define SMPTE_30 30
//
// Stuff that's part of MIDI spec
//
#define MIDI_NOTEOFF (BYTE)(0x80)
#define MIDI_NOTEON (BYTE)(0x90)
#define MIDI_CONTROLCHANGE (BYTE)(0xB0)
#define MIDI_SYSEX (BYTE)(0xF0)
#define MIDI_TIMING_CLK (BYTE)(0xF8)
#define MIDI_SUSTAIN (BYTE)(0x40) // w/ MIDI_CONTROLCHANGE
//
// Indices into dwReserved[] fields of struct
//
// 0,1,2 -- MMSYSTEM (core, emulator)
// 3,4,5 -- MIDI mapper
// 6,7 -- DDK (3rd party drivers)
#define MH_REFCNT 0 // MMSYSTEM core (stream header only)
#define MH_PARENT 0 // MMSYSTEM core (shadow header only)
#define MH_STREAM 0 // Emulator (long msg header only)
#define MH_SHADOW 1 // MMSYSTEM core (stream header only)
#define MH_BUFIDX 1 // Emulator (shadow header only)
#define MH_STRMPME 2 // Emulator (shadow header, long msg header)
/*****************************************************************************
*
* @doc INTERNAL MIDI
*
* @types MIDIDRV | This structure contains all of the information about an
* open <t HMIDIIN> or <t HMIDIOUT> handle.
*
* @field HMD | hmd |
* Handle to media device for this driver.
*
* @field UINT | uDevice |
* Index of this device off of HMD (subunit number relative to this driver).
*
* @field DRIVERMSGPROC | drvMessage |
* Pointer to the associated driver entry point.
*
* @field DWORD | dwDrvUser |
* Driver user DWORD; used by driver to differentiate open instance. Set
* by driver on OPEN message; passed back to driver on every call.
*
* @field PMIDIDRV | pdevNext |
* Specifies the next handle in the linked list of open handles.
* (Only kept for <t HMIDIOUT> handles.
*
* @field UINT | uLockCount |
* Semaphore to serialize access to the handle structure between API calls
* and interrupt callbacks.
*
* @field DWORD | dwTimeDiv |
* The time division setting that is active right now during polymsg playback
* on this handle. The format is the same as described for
* <f midiOutSetTimeDivision>.
*
* @field DWORD | dwTempo |
* Current tempo for polymsg out in microseconds per quarter note (as in the
* Standard MIDI File specification).
*
* @field DWORD | dwPolyMsgState |
* The current state of polymsg playback for emulation.
* @flag PM_STATE_READY | Events may be played and are waiting.
* @flag PM_STATE_BLOCKED | Driver is busy sending SysEx; don't play anything
* else.
* @flag PM_STATE_EMPTY | Not busy but nothing else in the queue to play.
* @flag PM_STATE_PAUSED | Device has been paused with <f midiOutPause>.
*
* @field DWORD | dwSavedState |
* If the device is paused, this field will contain the state to be
* restored when restart occurs.
*
* @field LPMIDIHDR | lpmhFront |
* Front of queue of MIDIHDR's waiting to be played via polymsg in/out. The
* header pointed to by this field is the header currently being played/
* recorded.
*
* @field LPMIDIHDR | lpmhRear |
* End of MIDIHDR queue. Buffers are inserted from the app here.
*
* @field DWORD | dwCallback |
* Address of user callback.
*
* @field DWORD | dwFlags |
* User-supplied callback flags.
*
* @field BOOL | fEmulate |
* TRUE if we are emulating polymsg in/out.
*
* @field BOOL | fReset |
* TRUE if we're in the middle of a MIDM_RESET. Checked to see if we should
* give our shadow buffers back to the driver or retain them for cleanup.
*
* @field BOOL | fStarted |
* TRUE if MIDI input has been started.
*
* @field UINT | uCBTimeout |
* Time in milliseconds that a buffer can be help in MIDI input w/o being
* called back.
*
* @field UINT | uCBTimer |
* Timer ID of the timer which is being used to determine if a MIDI
* input buffer has been queued for too long.
*
* @field DWORD | dwInputBuffers |
* The maximum number of input buffers that have been prepared on this handle.
* Used for calculating shadow buffer pool.
*
* @field DWORD | cbInputBuffers |
* The maximum size of input buffer which has been prepared on this handle.
* Used for calculating shadow buffer pool.
*
* @field DWORD | dwShadowBuffers |
* The current number of shadow buffers allocated on this handle.
*
* @field CLOCK | clock |
* Clock maintained by the clock API's for timebase of both output and
* input emulation.
*
* @field DWORD | tkNextEventDue | Tick time of the next event due
* on polymsg emulation.
*
* @field TICKS | tkTimeOfLastEvent | Tick time that emulator sent the
* last event.
*
* @field DWORD | tkPlayed | Total ticks played on stream.
*
* @field DWORD | tkTime | Tick position in stream now.
*
* @field DWORD | dwTimebase | Flag indicating where timebase is coming
* from. May be one of:
* @flag MIDI_TBF_INTERNAL | Timebase is <f timeGetTime>
* @flag MIDI_TBF_MIDICLK | Timebase is MIDI input clocks.
*
* @field BYTE | rbNoteOn[] | Array of note-on counts per-channel per-note.
* Only allocated for output handles which are doing COOKED mode emulation.
*
*****************************************************************************/
#define ELESIZE(t,e) (sizeof(((t*)NULL)->e))
//#define MDV_F_EXPANDSTATUS 0x00000001L
#define MDV_F_EMULATE 0x00000002L
#define MDV_F_RESET 0x00000004L
#define MDV_F_STARTED 0x00000008L
#define MDV_F_ZOMBIE 0x00000010L
#define MDV_F_SENDING 0x00000020L
#define MDV_F_OWNED 0x00000040L
#define MDV_F_LOCKED 0x00000080L
#define MEM_MAX_LATENESS 64
typedef MMDRV MIDIDRV, *PMIDIDRV;
typedef struct midistrm_tag *PMIDISTRM;
typedef struct mididev_tag *PMIDIDEV;
typedef struct midiemu_tag *PMIDIEMU;
typedef struct mididev_tag {
PMIDIDRV mididrv;
UINT wDevice;
DWORD_PTR dwDrvUser;
UINT uDeviceID;
DWORD fdwHandle;
PMIDIDEV pmThru; /* pointer to midi thru device */
PMIDIEMU pme; /* Iff owned by emulator */
} MIDIDEV;
typedef MIDIDEV *PMIDIDEV;
extern MIDIDRV midioutdrvZ; /* output device driver list */
extern MIDIDRV midiindrvZ; /* input device driver list */
extern UINT wTotalMidiOutDevs; /* total midi output devices */
extern UINT wTotalMidiInDevs; /* total midi input devices */
typedef struct midiemusid_tag {
DWORD dwStreamID;
HMIDI hMidi;
} MIDIEMUSID, *PMIDIEMUSID;
typedef struct midiemu_tag {
PMIDIEMU pNext;
HMIDISTRM hStream;
DWORD fdwDev;
LONG lLockCount; // Must be 32-bit aligned
CRITICAL_SECTION CritSec; // Serialize access
DWORD dwSignature; // Cookie to keep track of validity
DWORD dwTimeDiv; // Time division in use right now
DWORD dwTempo; // Current tempo
DWORD dwPolyMsgState; // Ready or blocked on SysEx
DWORD dwSavedState; // State saved when paused
LPMIDIHDR lpmhFront ; // Front of PolyMsg queue
LPMIDIHDR lpmhRear ; // Rear of PolyMsg queue
DWORD_PTR dwCallback; // User callback
DWORD dwFlags; // User callback flags
DWORD_PTR dwInstance;
DWORD dwSupport; // From MODM_GETDEVCAPS
BYTE bRunningStatus; // Track running status
//
// Rewrite midiOutPolyMsg timekeeping - new stuff!!!
//
CLOCK clock;
TICKS tkNextEventDue; // Tick time of next event
TICKS tkTimeOfLastEvent; // Tick time of last received event
TICKS tkPlayed; // Cumulative ticks played so far
TICKS tkTime; // Tick position in stream *NOW*
LPBYTE rbNoteOn; // Count of notes on per channel per note
UINT cSentLongMsgs; // Oustanding long messages
UINT chMidi; // # Stream ID's
UINT cPostedBuffers; // Posted to mmtask for cleanup
#ifdef DEBUG
DWORD cEvents;
UINT auLateness[MEM_MAX_LATENESS];
// 0..64 milliseconds late
#endif
MIDIEMUSID rIds[]; // HMIDI's indexed by stream ID
} MIDIEMU;
#define MSI_F_EMULATOR 0x00000001L
#define MSI_F_FIRST 0x00000002L
#define MSI_F_OPENED 0x00000004L
#define MSI_F_INITIALIZEDCRITICALSECTION 0x00000008L
#define MSE_SIGNATURE 0x12341234L
typedef struct midistrmid_tag {
HMD hmd;
UINT uDevice;
DRIVERMSGPROC drvMessage;
DWORD_PTR dwDrvUser;
DWORD fdwId;
CRITICAL_SECTION CritSec;
} MIDISTRMID, *PMIDISTRMID;
#define MDS_F_STOPPING 0x00000001L
typedef struct midistrm_tag {
DWORD fdwOpen;
DWORD fdwStrm;
DWORD_PTR dwCallback;
DWORD_PTR dwInstance;
DWORD cDrvrs; // # unique drivers in rgIds[]
DWORD cIds;
MIDISTRMID rgIds[];
} MIDISTRM;
/*****************************************************************************
*
* @doc INTERNAL MIDI
*
* @types MIDIHDREXT |
* This structure is allocated by <f midiOutPolyMsg> and is pointed to by the
* <t reserved> field of the associated <t MIDIHDR>. It contains information
* about what embedded long messages are in the polymsg buffer described
* by the MIDIHDR.
*
* The <t MIDIHDREXT> is followed by multiple <t MIDIDHR> structures, also
* allocated by <f midiOutPolyMsg>, which describe each of the embedded
* long messages which need to be played.
*
* @field DWORD | dwTimeDivision |
* The time division specified with <f midiOutPolyMsg> to play this buffer
* with.
*
* @field UINT | nHeaders |
* The number of <t MIDIHDR> structures which follow the end of this
* <MIDIHDREXT>.
*
* @field LPMIDIHDR | lpmidihdr |
* Pointer to the next <t MIDIHDR> structure due to be played.
*
*
*****************************************************************************/
typedef struct midihdrext_tag {
UINT nHeaders ;
LPMIDIHDR lpmidihdr ;
} MIDIHDREXT, FAR *LPMIDIHDREXT ;
extern HANDLE g_hClosepme;
/*
* Internal prototypes for MIDI
*/
extern MMRESULT midiReferenceDriverById(
IN PMIDIDRV pwavedrvZ,
IN UINT id,
OUT PMIDIDRV *ppwavedrv OPTIONAL,
OUT UINT *pport OPTIONAL
);
extern BOOL FAR PASCAL midiLockPageable(void);
extern void NEAR PASCAL midiUnlockPageable(void);
extern MMRESULT NEAR PASCAL midiPrepareHeader(LPMIDIHDR lpMidiHdr, UINT wSize);
extern MMRESULT NEAR PASCAL midiUnprepareHeader(LPMIDIHDR lpMidiHdr, UINT wSize);
extern STATIC MMRESULT midiMessage(HMIDI hMidi, UINT msg, DWORD_PTR dwP1, DWORD_PTR dwP2);
extern DWORD FAR PASCAL midiStreamMessage(PMIDISTRMID pmsi, UINT msg, DWORD_PTR dwP1, DWORD_PTR dwP2);
extern DWORD FAR PASCAL midiStreamBroadcast(PMIDISTRM pms, UINT msg, DWORD_PTR dwP1, DWORD_PTR dwP2);
extern STATIC MMRESULT midiIDMessage(PMIDIDRV pmididrvZ, UINT wTotalNumDevs, UINT_PTR uDeviceID, UINT wMessage, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
extern MMRESULT NEAR PASCAL midiGetPosition(PMIDISTRM pms, LPMMTIME pmmt, UINT cbmmt);
extern MMRESULT NEAR PASCAL midiGetErrorText(MMRESULT wError, LPSTR lpText, UINT wSize);
extern MMRESULT WINAPI midiOutGetID(HMIDIOUT hMidiOut, UINT FAR* lpuDeviceID);
extern MMRESULT FAR PASCAL mseOutSend(PMIDIEMU pme, LPMIDIHDR lpMidiHdr, UINT cbMidiHdr);
extern void FAR PASCAL midiOutSetClockRate(PMIDIEMU pme, TICKS tkWhen);
extern BOOL NEAR PASCAL midiOutScheduleNextEvent(PMIDIEMU pme);
#ifdef DEBUG
extern void NEAR PASCAL midiOutPlayNextPolyEvent(PMIDIEMU pme, DWORD dwStartTime);
#else
extern void NEAR PASCAL midiOutPlayNextPolyEvent(PMIDIEMU pme);
#endif
extern void NEAR PASCAL midiOutDequeueAndCallback(PMIDIEMU pme);
extern void FAR PASCAL midiOutNukePMBuffer(PMIDIEMU pme, LPMIDIHDR lpmh);
extern void CALLBACK midiOutTimerTick(UINT uTimerID, UINT wMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
extern void CALLBACK midiOutCallback(HMIDIOUT hMidiOut, WORD wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
extern void NEAR PASCAL midiOutAllNotesOff(PMIDIEMU pme);
extern void CALLBACK midiOutStreamCallback(HMIDISTRM hMidiOut, WORD wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
extern MMRESULT midiInSetThru (HMIDI hmi, HMIDIOUT hmo, BOOL bAdd);
// mseXXX - MIDI Stream Emulator
//
extern DWORD FAR PASCAL mseMessage(UINT msg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
#endif /* ifndef MMNOMIDI */
#ifndef MMNOWAVE
typedef MMDRV WAVEDRV, *PWAVEDRV;
extern WAVEDRV waveoutdrvZ; /* output device driver list */
extern WAVEDRV waveindrvZ; /* input device driver list */
extern UINT wTotalWaveOutDevs; /* total wave output devices */
extern UINT wTotalWaveInDevs; /* total wave input devices */
extern MMRESULT waveReferenceDriverById(
IN PWAVEDRV pwavedrvZ,
IN UINT id,
OUT PWAVEDRV *ppwavedrv OPTIONAL,
OUT UINT *pport OPTIONAL
);
#endif /*ifndef MMNOWAVE */
#ifndef MMNOMIXER
typedef MMDRV MIXERDRV, *PMIXERDRV;
extern MIXERDRV mixerdrvZ; /* mixer device driver list */
extern UINT guTotalMixerDevs; /* total mixer devices */
MMRESULT mixerReferenceDriverById(
IN UINT id,
OUT PMIXERDRV *ppdrv OPTIONAL,
OUT UINT *pport OPTIONAL
);
#endif /*ifndef MMNOMIXER */
#ifndef MMNOAUX
typedef MMDRV AUXDRV, *PAUXDRV;
extern AUXDRV auxdrvZ; /* auxiliary device driver list */
extern UINT wTotalAuxDevs; /* total auxiliary output devices */
MMRESULT auxReferenceDriverById(
IN UINT id,
OUT PAUXDRV *ppauxdrv OPTIONAL,
OUT UINT *pport OPTIONAL
);
#endif /* ifndef MMNOAUX */
#ifdef DEBUG_RETAIL
extern BYTE fIdReverse;
#endif /* ifdef DEBUG_RETAIL */
#endif //ifdef MMDDKINC
/****************************************************************************
handle apis's
****************************************************************************/
/*
// all MMSYSTEM handles are tagged with the following structure.
//
// a MMSYSTEM handle is really a fixed local memory object.
//
// the functions NewHandle() and FreeHandle() create and release a MMSYSTEM
// handle.
//
*/
typedef struct tagHNDL {
struct tagHNDL *pNext; // link to next handle
UINT uType; // type of handle wave, midi, mmio, ...
DWORD fdwHandle; // Particulars about this handle, Deserted? Busy?
HANDLE hThread; // task that owns it
UINT h16; // Corresponding WOW handle
PCWSTR cookie; // Device interface name for driver handles
CRITICAL_SECTION CritSec; // Serialize access
} HNDL, *PHNDL;
/*************************************************************************/
#define MMHANDLE_DESERTED MMDRV_DESERTED
#define MMHANDLE_BUSY 0x00000002
#define HtoPH(h) ((PHNDL)(h)-1)
#define PHtoH(ph) ((ph) ? (HANDLE)((PHNDL)(ph)+1) : 0)
#define HtoPT(t,h) ((t)(h))
#define PTtoH(t,pt) ((t)(pt))
//
// Handles can be tested for ownership and reserved at the same time
//
#define ENTER_MM_HANDLE(h) (EnterCriticalSection(&HtoPH(h)->CritSec))
#define LEAVE_MM_HANDLE(h) ((void)LeaveCriticalSection(&HtoPH(h)->CritSec))
/*
// all wave and midi handles will be linked into
// a global list, so we can enumerate them latter if needed.
//
// all handle structures start with a HNDL structure, that contain common fields
//
// pHandleList points to the first handle in the list
//
// HandleListCritSec protects the handle list
//
// the NewHandle() and FreeHandle() functions are used to add/remove
// a handle to/from the list
*/
PHNDL pHandleList;
CRITICAL_SECTION HandleListCritSec;
extern HANDLE NewHandle(UINT uType, PCWSTR cookie, UINT size);
extern void ReleaseHandleListResource();
extern void AcquireHandleListResourceShared();
extern void AcquireHandleListResourceExclusive();
extern void FreeHandle(HANDLE h);
extern void InvalidateHandle(HANDLE h);
#define GetHandleType(h) (HtoPH(h)->uType)
#define GetHandleOwner(h) (HtoPH(h)->hThread)
#define GetHandleFirst() (PHtoH(pHandleList))
#define GetHandleNext(h) (PHtoH(HtoPH(h)->pNext))
#define SetHandleOwner(h,hOwn) (HtoPH(h)->hThread = (hOwn))
#define SetHandleFlag(h,f) (HtoPH(h)->fdwHandle |= (f))
#define ClearHandleFlag(h,f) (HtoPH(h)->fdwHandle &= (~(f)))
#define CheckHandleFlag(h,f) (HtoPH(h)->fdwHandle & (f))
#define IsHandleDeserted(h) (0 != CheckHandleFlag((h), MMHANDLE_DESERTED))
#define IsHandleBusy(h) (0 != CheckHandleFlag((h), MMHANDLE_BUSY))
#define GetWOWHandle(h) (HtoPH(h)->h16)
#define SetWOWHandle(h, myh16) (HtoPH(h)->h16 = (myh16))
/**************************************************************************
Test whether the current process is the WOW process. This
is not a very nice test to have to make but it's the best we
can think of until the WOW people come up with a proper call
**************************************************************************/
#define IS_WOW_PROCESS (NULL != GetModuleHandleW(L"WOW32.DLL"))
/****************************************************************************
user debug support
****************************************************************************/
#define DebugErr(x,y)
#define DebugErr1(flags, sz, a)
#ifdef DEBUG_RETAIL
#define MM_GET_DEBUG DRV_USER
#define MM_GET_DEBUGOUT DRV_USER+1
#define MM_SET_DEBUGOUT DRV_USER+2
#define MM_GET_MCI_DEBUG DRV_USER+3
#define MM_SET_MCI_DEBUG DRV_USER+4
#define MM_GET_MM_DEBUG DRV_USER+5
#define MM_SET_MM_DEBUG DRV_USER+6
#define MM_HINFO_NEXT DRV_USER+10
#define MM_HINFO_TASK DRV_USER+11
#define MM_HINFO_TYPE DRV_USER+12
#define MM_HINFO_MCI DRV_USER+20
#define MM_DRV_RESTART DRV_USER+30
/*
// these validation routines can be found in DEBUG.C
*/
// The kernel validation is turned OFF because it appeared to test every page
// before use and this took over a minute for soundrec with a 10MB buffer
//
//#define USE_KERNEL_VALIDATION
#ifdef USE_KERNEL_VALIDATION
#define ValidateReadPointer(p, len) (!IsBadReadPtr(p, len))
#define ValidateWritePointer(p, len) (!IsBadWritePtr(p, len))
#define ValidateString(lsz, max_len) (!IsBadStringPtrA(lsz, max_len))
#define ValidateStringW(lsz, max_len) (!IsBadStringPtrW(lsz, max_len))
#else
BOOL ValidateReadPointer(LPVOID p, DWORD len);
BOOL ValidateWritePointer(LPVOID p, DWORD len);
BOOL ValidateString(LPCSTR lsz, DWORD max_len);
BOOL ValidateStringW(LPCWSTR lsz, DWORD max_len);
#endif // USE_KERNEL_VALIDATION
BOOL ValidateHandle(HANDLE h, UINT uType);
BOOL ValidateHeader(LPVOID p, UINT uSize, UINT uType);
BOOL ValidateCallbackType(DWORD_PTR dwCallback, UINT uType);
/********************************************************************
* When time permits we should change to using the Kernel supplied and
* supported validation routines:
*
* BOOL WINAPI IsBadReadPtr(CONST VOID *lp, UINT ucb );
* BOOL WINAPI IsBadWritePtr(LPVOID lp, UINT ucb );
* BOOL WINAPI IsBadHugeReadPtr(CONST VOID *lp, UINT ucb);
* BOOL WINAPI IsBadHugeWritePtr(LPVOID lp, UINT ucb);
* BOOL WINAPI IsBadCodePtr(FARPROC lpfn);
* BOOL WINAPI IsBadStringPtrA(LPCSTR lpsz, UINT ucchMax);
* BOOL WINAPI IsBadStringPtrW(LPCWSTR lpsz, UINT ucchMax);
*
* These routines can be found in * \nt\private\WINDOWS\BASE\CLIENT\PROCESS.C
*
********************************************************************/
#define V_HANDLE(h, t, r) { if (!ValidateHandle(h, t)) return (r); }
#define V_HANDLE_ACQ(h, t, r) { AcquireHandleListResourceShared(); if (!ValidateHandle(h, t)) { ReleaseHandleListResource(); return (r);} }
#define BAD_HANDLE(h, t) ( !(ValidateHandle((h), (t))) )
#define V_HEADER(p, w, t, r) { if (!ValidateHeader((p), (w), (t))) return (r); }
#define V_RPOINTER(p, l, r) { if (!ValidateReadPointer((PVOID)(p), (l))) return (r); }
#define V_RPOINTER0(p, l, r) { if ((p) && !ValidateReadPointer((PVOID)(p), (l))) return (r); }
#define V_WPOINTER(p, l, r) { if (!ValidateWritePointer((PVOID)(p), (l))) return (r); }
#define V_WPOINTER0(p, l, r) { if ((p) && !ValidateWritePointer((PVOID)(p), (l))) return (r); }
#define V_DCALLBACK(d, w, r) { if ((d) && !ValidateCallbackType((d), (w))) return(r); }
//#define V_DCALLBACK(d, w, r) 0
#define V_TCALLBACK(d, r) 0
#define V_CALLBACK(f, r) { if (IsBadCodePtr((f))) return (r); }
#define V_CALLBACK0(f, r) { if ((f) && IsBadCodePtr((f))) return (r); }
#define V_STRING(s, l, r) { if (!ValidateString(s,l)) return (r); }
#define V_STRING_W(s, l, r) { if (!ValidateStringW(s,l)) return (r); }
#define V_FLAGS(t, b, f, r) { if ((t) & ~(b)) { return (r); }}
#define V_DFLAGS(t, b, f, r) { if ((t) & ~(b)) {/* LogParamError(ERR_BAD_DFLAGS, (FARPROC)(f), (LPVOID)(DWORD)(t));*/ return (r); }}
#define V_MMSYSERR(e, f, t, r) { /* LogParamError(e, (FARPROC)(f), (LPVOID)(DWORD)(t));*/ return (r); }
#else /*ifdef DEBUG_RETAIL */
#define V_HANDLE(h, t, r) { if (!(h)) return (r); }
#define V_HANDLE_ACQ(h, t, r) { AcquireHandleListResourceShared(); if (!ValidateHandle(h, t)) { ReleaseHandleListResource(); return (r);} }
#define BAD_HANDLE(h, t) ( !(ValidateHandle((h), (t))) )
#define V_HEADER(p, w, t, r) { if (!(p)) return (r); }
#define V_RPOINTER(p, l, r) { if (!(p)) return (r); }
#define V_RPOINTER0(p, l, r) 0
#define V_WPOINTER(p, l, r) { if (!(p)) return (r); }
#define V_WPOINTER0(p, l, r) 0
#define V_DCALLBACK(d, w, r) { if ((d) && !ValidateCallbackType((d), (w))) return(r); }
//#define V_DCALLBACK(d, w, r) 0
#define V_TCALLBACK(d, r) 0
#define V_CALLBACK(f, r) { if (IsBadCodePtr((f))) return (r); }
#define V_CALLBACK0(f, r) { if ((f) && IsBadCodePtr((f))) return (r); }
//#define V_CALLBACK(f, r) { if (!(f)) return (r); }
#define V_CALLBACK0(f, r) 0
#define V_STRING(s, l, r) { if (!(s)) return (r); }
#define V_STRING_W(s, l, r) { if (!(s)) return (r); }
#define V_FLAGS(t, b, f, r) 0
#define V_DFLAGS(t, b, f, r) { if ((t) & ~(b)) return (r); }
#define V_MMSYSERR(e, f, t, r) { return (r); }
#endif /* ifdef DEBUG_RETAIL */
/**************************************************************************
//
//**************************************************************************/
#define TYPE_UNKNOWN 0
#define TYPE_WAVEOUT 1
#define TYPE_WAVEIN 2
#define TYPE_MIDIOUT 3
#define TYPE_MIDIIN 4
#define TYPE_MMIO 5
#define TYPE_MCI 6
#define TYPE_DRVR 7
#define TYPE_MIXER 8
#define TYPE_MIDISTRM 9
#define TYPE_AUX 10
/**************************************************************************/
/****************************************************************************
RIFF constants used to access wave files
****************************************************************************/
#define FOURCC_FMT mmioFOURCC('f', 'm', 't', ' ')
#define FOURCC_DATA mmioFOURCC('d', 'a', 't', 'a')
#define FOURCC_WAVE mmioFOURCC('W', 'A', 'V', 'E')
extern HWND hwndNotify;
void FAR PASCAL WaveOutNotify(DWORD wParam, LONG lParam); // in PLAYWAV.C
/*
// Things not in Win32
*/
#define GetCurrentTask() ((HANDLE)(DWORD_PTR)GetCurrentThreadId())
/*
// other stuff
*/
// Maximum length, including the terminating NULL, of an Scheme entry.
//
#define SCH_TYPE_MAX_LENGTH 64
// Maximum length, including the terminating NULL, of an Event entry.
//
#define EVT_TYPE_MAX_LENGTH 32
// Maximum length, including the terminating NULL, of an App entry.
//
#define APP_TYPE_MAX_LENGTH 64
// Sound event names can be a fully qualified filepath with a NULL
// terminator.
//
#define MAX_SOUND_NAME_CHARS 144
// sound atom names are composed of:
// <1 char id>
// <reg key name>
// <1 char sep>
// <filepath>
//
#define MAX_SOUND_ATOM_CHARS (1 + 40 + 1 + MAX_SOUND_NAME_CHARS)
#if 0
#undef hmemcpy
#define hmemcpy CopyMemory
#endif
//
// for terminal server defination and security
//
extern BOOL WinmmRunningInSession;
extern WCHAR SessionProtocolName[];
extern BOOL gfLogon;
BOOL IsWinlogon(void);
BOOL WTSCurrentSessionIsDisconnected(void);
// Keep winmm loaded
extern BOOL LoadWINMM();
#endif /* WINMMI_H */