windows-nt/Source/XPSP1/NT/drivers/wdm/audio/legacy/wdmaud.sys/wdmsys.h
2020-09-26 16:20:57 +08:00

1972 lines
52 KiB
C

/****************************************************************************
*
* wdmsys.h
*
* Function declarations, etc. for WDMAUD.SYS
*
* Copyright (C) Microsoft Corporation, 1997 - 1999 All Rights Reserved.
*
* History
* 5-19-97 - Noel Cross (NoelC)
*
***************************************************************************/
#ifndef _WDMSYS_H_INCLUDED_
#define _WDMSYS_H_INCLUDED_
#ifdef UNDER_NT
#if DBG
#define DEBUG
#endif
#endif
#include <ntddk.h>
#include <windef.h>
#include <winerror.h>
#include <memory.h>
#include <stddef.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <tchar.h>
#include <conio.h>
#include <math.h>
// Make sure we will get correct multimedia structures from mmsystem.
#ifdef UNDER_NT
#ifndef _WIN32
#pragma message( "WARNING: _WIN32 not defined. Build not valid for NT." )
#endif
#ifndef UNICODE
#pragma message( "WARNING: UNICODE not defined. Build not valid for NT." )
#endif
#else
#pragma message( "WARNING: UNDER_NT not defined. Build not valid for NT." )
#endif
#define NOBITMAP
#include <mmsystem.h>
#include <mmreg.h>
#include <mmddk.h>
#undef NOBITMAP
#include <ks.h>
#include <ksmedia.h>
#include <swenum.h>
#include <ksdebug.h>
#include <midi.h>
#include <wdmaud.h>
#include "mixer.h"
#include "robust.h"
#define INIT_CODE code_seg("INIT", "CODE")
#define INIT_DATA data_seg("INIT", "DATA")
#define LOCKED_CODE code_seg(".text", "CODE")
#define LOCKED_DATA data_seg(".data", "DATA")
#define PAGEABLE_CODE code_seg("PAGE", "CODE")
#define PAGEABLE_DATA data_seg("PAGEDATA", "DATA")
#pragma PAGEABLE_CODE
#pragma PAGEABLE_DATA
/***************************************************************************
Constants
***************************************************************************/
#define PROFILE // turn on to help with debugging
#define WAVE_CONTROL_VOLUME 0
#define WAVE_CONTROL_RATE 1
#define WAVE_CONTROL_QUALITY 2
#define MAX_WAVE_CONTROLS 3
#define MIDI_CONTROL_VOLUME 0
#define MAX_MIDI_CONTROLS 1
#define WILD_CARD 0xfffffffe
#define INVALID_NODE 0xffffffff
#define MAXNUMDEVS 32
#define MAXDEVNODES 100
#define STR_MODULENAME "wdmaud.sys: "
#define STR_DEVICENAME TEXT("\\Device\\wdmaud")
#define STR_LINKNAME TEXT("\\DosDevices\\wdmaud")
#define STR_PNAME TEXT("%s (%d)")
#ifdef DEBUG
#define CONTEXT_SIGNATURE 'XNOC' // CONteXt structure
#define MIXERDEVICE_SIGNATURE 'DXIM' // MIXerDevice structure
#define MIXEROBJECT_SIGNATURE 'OXIM' // MIXerObject structure
#define HWLINK_SIGNATURE 'KLWH' //HWLINK signature
#endif
#define LIVE_CONTROL ((PMXLCONTROL)(-1))
#define INCREASE TRUE
#define DECREASE FALSE
/***************************************************************************
structure definitions
***************************************************************************/
typedef struct _WDMAPENDINGIRP_QUEUE {
LIST_ENTRY WdmaPendingIrpListHead;
KSPIN_LOCK WdmaPendingIrpListSpinLock;
IO_CSQ Csq;
} WDMAPENDINGIRP_QUEUE, *PWDMAPENDINGIRP_QUEUE;
extern WDMAPENDINGIRP_QUEUE wdmaPendingIrpQueue;
typedef struct _WDMAPENDINGIRP_CONTEXT {
IO_CSQ_IRP_CONTEXT IrpContext;
ULONG IrpDeviceType;
struct tag_WDMACONTEXT *pContext;
} WDMAPENDINGIRP_CONTEXT, *PWDMAPENDINGIRP_CONTEXT;
typedef struct tag_ALLOCATED_MDL_LIST_ITEM
{
LIST_ENTRY Next;
PMDL pMdl;
struct tag_WDMACONTEXT *pContext;
} ALLOCATED_MDL_LIST_ITEM , *PALLOCATED_MDL_LIST_ITEM;
//typedef struct tag_IOCTL_HISTORY_LIST_ITEM
//{
// LIST_ENTRY Next;
// PIRP pIrp;
// ULONG IoCode;
// NTSTATUS IoStatus;
// struct tag_WDMACONTEXT *pContext;
//} IOCTL_HISTORY_LIST_ITEM , *PIOCTL_HISTORY_LIST_ITEM;
typedef struct device_instance
{
PVOID pDeviceHeader;
} DEVICE_INSTANCE, *PDEVICE_INSTANCE;
typedef struct _CONTROL_NODE
{
GUID Control;
ULONG NodeId;
ULONG Reserved;
} CONTROL_NODE, *PCONTROL_NODE;
typedef struct _CONTROLS_LIST
{
ULONG Count;
ULONG Reserved;
CONTROL_NODE Controls[1];
} CONTROLS_LIST, *PCONTROLS_LIST;
typedef struct _WAVEPOSITION {
DWORD Operation; // Get / Set
DWORD BytePos;
} WAVEPOSITION, *PWAVEPOSITION, FAR *LPWAVEPOSITION;
typedef struct _DEVICEVOLUME {
DWORD Operation; // Get / Set
DWORD Channel;
DWORD Level;
} DEVICEVOLUME, *PDEVICEVOLUME, FAR *LPDEVICEVOLUME;
#define WAVE_PIN_INSTANCE_SIGNATURE ((ULONG)'SIPW') //WPIS
//
// This macro can be used with NT_SUCCESS to branch. Effectively returns an
// NTSTATUS code.
//
#define IsValidWavePinInstance(pwpi) ((pwpi->dwSig == WAVE_PIN_INSTANCE_SIGNATURE) ? \
STATUS_SUCCESS:STATUS_UNSUCCESSFUL)
//
// The Wave pin instance structure and the midi pin instance structure need to
// use a common header so that the duplicate servicing functions can be
// removed.
//
typedef struct _WAVEPININSTANCE
{
PFILE_OBJECT pFileObject;
PDEVICE_OBJECT pDeviceObject;
struct tag_WAVEDEVICE *pWaveDevice;
KSPIN_LOCK WavePinSpinLock; // For State Changes
BOOL fGraphRunning;
KSSTATE PinState;
KEVENT StopEvent;
KEVENT PauseEvent;
volatile ULONG NumPendingIos;
volatile BOOL StoppingSource; // Flag which indicates
// that the pin is in the
// stopping process
volatile BOOL PausingSource; // Flag which indicates
// that the pin is in the
// pausing process
ULONG DeviceNumber;
ULONG DataFlow;
BOOL fWaveQueued;
LPWAVEFORMATEX lpFormat;
DWORD dwFlags;
PCONTROLS_LIST pControlList;
HANDLE32 WaveHandle;
struct _WAVEPININSTANCE *Next;
DWORD dwSig; //Used to validate structure.
} WAVE_PIN_INSTANCE, *PWAVE_PIN_INSTANCE;
typedef struct _midiinhdr
{
LIST_ENTRY Next;
LPMIDIDATA pMidiData;
PIRP pIrp;
PMDL pMdl;
PWDMAPENDINGIRP_CONTEXT pPendingIrpContext;
} MIDIINHDR, *PMIDIINHDR;
#define MIDI_PIN_INSTANCE_SIGNATURE ((ULONG)'SIPM') //MPIS
//
// This macro can be used with NT_SUCCESS to branch. Effectively returns a
// NTSTATUS code.
//
#define IsValidMidiPinInstance(pmpi) ((pmpi->dwSig == MIDI_PIN_INSTANCE_SIGNATURE) ? \
STATUS_SUCCESS:STATUS_UNSUCCESSFUL)
typedef struct _MIDIPININSTANCE
{
PFILE_OBJECT pFileObject;
PDEVICE_OBJECT pDeviceObject;
struct tag_MIDIDEVICE *pMidiDevice;
KSPIN_LOCK MidiPinSpinLock; // For state changes
BOOL fGraphRunning;
KSSTATE PinState;
KEVENT StopEvent;
ULONG NumPendingIos;
volatile BOOL StoppingSource; // Flag which indicates
// that the pin is in the
// stopping process
LIST_ENTRY MidiInQueueListHead; // for midihdrs
KSPIN_LOCK MidiInQueueSpinLock;
KSEVENT MidiInNotify; // for notification of new midiin data
WORK_QUEUE_ITEM MidiInWorkItem;
ULONG DeviceNumber;
ULONG DataFlow;
PCONTROLS_LIST pControlList;
ULONG LastTimeMs;
ULONGLONG LastTimeNs;
BYTE bCurrentStatus;
DWORD dwSig; // Used to validate structure
} MIDI_PIN_INSTANCE, *PMIDI_PIN_INSTANCE;
#define STREAM_HEADER_EX_SIGNATURE ((ULONG)'XEHS') //SHEX
//
// This macro can be used with NT_SUCCESS to branch. Effectively returns a
// NTSTATUS code.
//
#define IsValidStreamHeaderEx(pshex) ((pshex->dwSig == STREAM_HEADER_EX_SIGNATURE) ? \
STATUS_SUCCESS:STATUS_UNSUCCESSFUL)
typedef struct _STREAM_HEADER_EX
{
KSSTREAM_HEADER Header;
IO_STATUS_BLOCK IoStatus;
union
{
PDWORD pdwBytesRecorded;
PWAVEHDR pWaveHdr;
PMIDIHDR pMidiHdr;
};
union
{
PWAVE_PIN_INSTANCE pWavePin;
PMIDI_PIN_INSTANCE pMidiPin;
};
PIRP pIrp;
PWAVEHDR pWaveHdrAligned;
PMDL pHeaderMdl;
PMDL pBufferMdl;
PWDMAPENDINGIRP_CONTEXT pPendingIrpContext;
DWORD dwSig; //Used To validate structure.
} STREAM_HEADER_EX, *PSTREAM_HEADER_EX;
//
// make sure that this structure doesn't exceed the size of
// the midihdr, otherwise the write_context defintion in
// vxd.asm needs to be updated.
//
typedef struct _wavehdrex
{
WAVEHDR wh;
PWAVE_PIN_INSTANCE pWaveInstance;
} WAVEINSTANCEHDR, *PWAVEINSTANCEHDR;
#define WRITE_CONTEXT_SIGNATURE ((ULONG)'GSCW') //WCSG
//
// This macro can be used with NT_SUCCESS to branch. Effectively returns a
// NTSTATUS code.
//
#define IsValidWriteContext(pwc) ((pwc->dwSig == WRITE_CONTEXT_SIGNATURE) ? \
STATUS_SUCCESS:STATUS_UNSUCCESSFUL)
typedef struct write_context
{
union
{
WAVEINSTANCEHDR whInstance;
MIDIHDR mh;
};
DWORD ClientContext;
DWORD ClientContext2;
WORD CallbackOffset;
WORD CallbackSegment;
DWORD ClientThread;
union
{
LPWAVEHDR WaveHeaderLinearAddress;
LPMIDIHDR MidiHeaderLinearAddress;
};
PVOID pCapturedWaveHdr;
PMDL pBufferMdl;
PWDMAPENDINGIRP_CONTEXT pPendingIrpContext;
DWORD dwSig; // Used to validate structure.
} WRITE_CONTEXT, *PWRITE_CONTEXT;
typedef struct tag_IDENTIFIERS
{
KSMULTIPLE_ITEM;
KSIDENTIFIER aIdentifiers[1]; // Array of identifiers
} IDENTIFIERS, *PIDENTIFIERS;
typedef struct tag_DATARANGES
{
KSMULTIPLE_ITEM;
KSDATARANGE aDataRanges[1];
} DATARANGES, *PDATARANGES;
typedef struct tag_KSPROPERTYPLUS
{
KSPROPERTY Property;
ULONG DeviceIndex;
} KSPROPERTYPLUS, *PKSPROPERTYPLUS;
//
// COMMONDEVICE
// DeviceInterface - the buffer for this string is allocated for all
// classes except mixer. For mixer, it is a pointer to a buffer
// allocated for one of the wave classes.
//
typedef struct tag_COMMONDEVICE
{
ULONG Device;
ULONG PinId;
PWSTR DeviceInterface;
PWSTR pwstrName;
ULONG PreferredDevice;
struct tag_WDMACONTEXT *pWdmaContext;
PKSCOMPONENTID ComponentId;
} COMMONDEVICE, *PCOMMONDEVICE;
typedef struct tag_WAVEDEVICE
{
COMMONDEVICE;
PDATARANGES AudioDataRanges;
PWAVE_PIN_INSTANCE pWavePin;
DWORD LeftVolume; // only used for output
DWORD RightVolume; // only used for output
DWORD dwVolumeID; // only used for output
DWORD cChannels; // only used for output
PKTIMER pTimer; // only used for output
PKDPC pDpc; // only used for output
BOOL fNeedToSetVol; // only used for output
} WAVEDEVICE, *PWAVEDEVICE;
typedef struct tag_MIDIDEVICE
{
COMMONDEVICE;
PDATARANGES MusicDataRanges;
PMIDI_PIN_INSTANCE pMidiPin;
DWORD dwVolumeID; // only used for output
DWORD cChannels; // only used for output
} MIDIDEVICE, *PMIDIDEVICE;
typedef struct tag_MIXERDEVICE
{
COMMONDEVICE;
ULONG cDestinations; // The no. of destinations on device
LINELIST listLines; // The list of all lines on the dev.
KSTOPOLOGY Topology; // The topology
ULONG Mapping; // Mapping algorithm for this device
PFILE_OBJECT pfo; // used for talking to SysAudio
#ifdef DEBUG
DWORD dwSig;
#endif
} MIXERDEVICE, *PMIXERDEVICE;
typedef struct tag_AUXDEVICE
{
COMMONDEVICE;
DWORD dwVolumeID;
DWORD cChannels;
} AUXDEVICE, *PAUXDEVICE;
typedef struct tag_DEVNODE_LIST_ITEM
{
LIST_ENTRY Next;
LONG cReference; // Number of device classes init'ed
LPWSTR DeviceInterface;
ULONG cDevices[MAX_DEVICE_CLASS]; // Count of devices for each class
BOOLEAN fAdded[MAX_DEVICE_CLASS];
} DEVNODE_LIST_ITEM, *PDEVNODE_LIST_ITEM;
typedef struct tag_WORK_LIST_ITEM
{
LIST_ENTRY Next;
VOID (*Function)(
PVOID Reference1,
PVOID Reference2
);
PVOID Reference1;
PVOID Reference2;
} WORK_LIST_ITEM, *PWORK_LIST_ITEM;
extern KMUTEX wdmaMutex;
typedef struct tag_WDMACONTEXT
{
LIST_ENTRY Next;
BOOL fInList;
BOOL fInitializeSysaudio;
KEVENT InitializedSysaudioEvent;
PFILE_OBJECT pFileObjectSysaudio;
KSEVENTDATA EventData;
ULONG VirtualWavePinId;
ULONG VirtualMidiPinId;
ULONG VirtualCDPinId;
ULONG PreferredSysaudioWaveDevice;
ULONG DevNodeListCount;
LIST_ENTRY DevNodeListHead;
PVOID NotificationEntry;
WORK_QUEUE_ITEM WorkListWorkItem;
LIST_ENTRY WorkListHead;
KSPIN_LOCK WorkListSpinLock;
LONG cPendingWorkList;
WORK_QUEUE_ITEM SysaudioWorkItem;
PKSWORKER WorkListWorkerObject;
PKSWORKER SysaudioWorkerObject;
WAVEDEVICE WaveOutDevs[MAXNUMDEVS];
WAVEDEVICE WaveInDevs[MAXNUMDEVS];
MIDIDEVICE MidiOutDevs[MAXNUMDEVS];
MIDIDEVICE MidiInDevs[MAXNUMDEVS];
MIXERDEVICE MixerDevs[MAXNUMDEVS];
AUXDEVICE AuxDevs[MAXNUMDEVS];
PCOMMONDEVICE apCommonDevice[MAX_DEVICE_CLASS][MAXNUMDEVS];
#ifdef DEBUG
DWORD dwSig;
#endif
} WDMACONTEXT, *PWDMACONTEXT;
#ifdef WIN32
#include <pshpack1.h>
#else
#ifndef RC_INVOKED
#pragma pack(1)
#endif
#endif
// This include needs to be here since it needs some of the declarations
// above
#include "kmxluser.h"
typedef WORD VERSION; /* major (high byte), minor (low byte) */
typedef struct waveoutcaps16_tag {
WORD wMid; /* manufacturer ID */
WORD wPid; /* product ID */
WORD vDriverVersion; /* version of the driver */
char szPname[MAXPNAMELEN]; /* product name (NULL terminated string) */
DWORD dwFormats; /* formats supported */
WORD wChannels; /* number of sources supported */
DWORD dwSupport; /* functionality supported by driver */
} WAVEOUTCAPS16, *PWAVEOUTCAPS16;
typedef struct waveincaps16_tag {
WORD wMid; /* manufacturer ID */
WORD wPid; /* product ID */
WORD vDriverVersion; /* version of the driver */
char szPname[MAXPNAMELEN]; /* product name (NULL terminated string) */
DWORD dwFormats; /* formats supported */
WORD wChannels; /* number of channels supported */
} WAVEINCAPS16, *PWAVEINCAPS16;
typedef struct midioutcaps16_tag {
WORD wMid; /* manufacturer ID */
WORD wPid; /* product ID */
WORD vDriverVersion; /* version of the driver */
char szPname[MAXPNAMELEN]; /* product name (NULL terminated string) */
WORD wTechnology; /* type of device */
WORD wVoices; /* # of voices (internal synth only) */
WORD wNotes; /* max # of notes (internal synth only) */
WORD wChannelMask; /* channels used (internal synth only) */
DWORD dwSupport; /* functionality supported by driver */
} MIDIOUTCAPS16, *PMIDIOUTCAPS16;
typedef struct midiincaps16_tag {
WORD wMid; /* manufacturer ID */
WORD wPid; /* product ID */
WORD vDriverVersion; /* version of the driver */
char szPname[MAXPNAMELEN]; /* product name (NULL terminated string) */
#if (WINVER >= 0x0400)
DWORD dwSupport; /* functionality supported by driver */
#endif
} MIDIINCAPS16, *PMIDIINCAPS16;
typedef struct mixercaps16_tag {
WORD wMid; /* manufacturer id */
WORD wPid; /* product id */
WORD vDriverVersion; /* version of the driver */
char szPname[MAXPNAMELEN]; /* product name */
DWORD fdwSupport; /* misc. support bits */
DWORD cDestinations; /* count of destinations */
} MIXERCAPS16, *PMIXERCAPS16;
typedef struct auxcaps16_tag {
WORD wMid; /* manufacturer ID */
WORD wPid; /* product ID */
WORD vDriverVersion; /* version of the driver */
char szPname[MAXPNAMELEN]; /* product name (NULL terminated string) */
WORD wTechnology; /* type of device */
DWORD dwSupport; /* functionality supported by driver */
} AUXCAPS16, *PAUXCAPS16;
typedef struct wavehdr_tag32 {
UINT32 lpData; /* pointer to locked data buffer */
DWORD dwBufferLength; /* length of data buffer */
DWORD dwBytesRecorded; /* used for input only */
UINT32 dwUser; /* for client's use */
DWORD dwFlags; /* assorted flags (see defines) */
DWORD dwLoops; /* loop control counter */
UINT32 lpNext; /* reserved for driver */
UINT32 reserved; /* reserved for driver */
} WAVEHDR32, *PWAVEHDR32, NEAR *NPWAVEHDR32, FAR *LPWAVEHDR32;
/* MIDI data block header */
typedef struct midihdr_tag32 {
UINT32 lpData; /* pointer to locked data block */
DWORD dwBufferLength; /* length of data in data block */
DWORD dwBytesRecorded; /* used for input only */
UINT32 dwUser; /* for client's use */
DWORD dwFlags; /* assorted flags (see defines) */
UINT32 lpNext; /* reserved for driver */
UINT32 reserved; /* reserved for driver */
#if (WINVER >= 0x0400)
DWORD dwOffset; /* Callback offset into buffer */
UINT32 dwReserved[8]; /* Reserved for MMSYSTEM */
#endif
} MIDIHDR32, *PMIDIHDR32, NEAR *NPMIDIHDR32, FAR *LPMIDIHDR32;
typedef struct tagMIXERLINEA32 {
DWORD cbStruct; /* size of MIXERLINE structure */
DWORD dwDestination; /* zero based destination index */
DWORD dwSource; /* zero based source index (if source) */
DWORD dwLineID; /* unique line id for mixer device */
DWORD fdwLine; /* state/information about line */
UINT32 dwUser; /* driver specific information */
DWORD dwComponentType; /* component type line connects to */
DWORD cChannels; /* number of channels line supports */
DWORD cConnections; /* number of connections [possible] */
DWORD cControls; /* number of controls at this line */
CHAR szShortName[MIXER_SHORT_NAME_CHARS];
CHAR szName[MIXER_LONG_NAME_CHARS];
struct {
DWORD dwType; /* MIXERLINE_TARGETTYPE_xxxx */
DWORD dwDeviceID; /* target device ID of device type */
WORD wMid; /* of target device */
WORD wPid; /* " */
MMVERSION vDriverVersion; /* " */
CHAR szPname[MAXPNAMELEN]; /* " */
} Target;
} MIXERLINEA32, *PMIXERLINEA32, *LPMIXERLINEA32;
typedef struct tagMIXERLINEW32 {
DWORD cbStruct; /* size of MIXERLINE structure */
DWORD dwDestination; /* zero based destination index */
DWORD dwSource; /* zero based source index (if source) */
DWORD dwLineID; /* unique line id for mixer device */
DWORD fdwLine; /* state/information about line */
UINT32 dwUser; /* driver specific information */
DWORD dwComponentType; /* component type line connects to */
DWORD cChannels; /* number of channels line supports */
DWORD cConnections; /* number of connections [possible] */
DWORD cControls; /* number of controls at this line */
WCHAR szShortName[MIXER_SHORT_NAME_CHARS];
WCHAR szName[MIXER_LONG_NAME_CHARS];
struct {
DWORD dwType; /* MIXERLINE_TARGETTYPE_xxxx */
DWORD dwDeviceID; /* target device ID of device type */
WORD wMid; /* of target device */
WORD wPid; /* " */
MMVERSION vDriverVersion; /* " */
WCHAR szPname[MAXPNAMELEN]; /* " */
} Target;
} MIXERLINEW32, *PMIXERLINEW32, *LPMIXERLINEW32;
#ifdef UNICODE
typedef MIXERLINEW32 MIXERLINE32;
typedef PMIXERLINEW32 PMIXERLINE32;
typedef LPMIXERLINEW32 LPMIXERLINE32;
#else
typedef MIXERLINEA32 MIXERLINE32;
typedef PMIXERLINEA32 PMIXERLINE32;
typedef LPMIXERLINEA32 LPMIXERLINE32;
#endif // UNICODE
typedef struct tagMIXERLINECONTROLSA32 {
DWORD cbStruct; /* size in bytes of MIXERLINECONTROLS */
DWORD dwLineID; /* line id (from MIXERLINE.dwLineID) */
union {
DWORD dwControlID; /* MIXER_GETLINECONTROLSF_ONEBYID */
DWORD dwControlType; /* MIXER_GETLINECONTROLSF_ONEBYTYPE */
};
DWORD cControls; /* count of controls pmxctrl points to */
DWORD cbmxctrl; /* size in bytes of _one_ MIXERCONTROL */
UINT32 pamxctrl; /* pointer to first MIXERCONTROL array */
} MIXERLINECONTROLSA32, *PMIXERLINECONTROLSA32, *LPMIXERLINECONTROLSA32;
typedef struct tagMIXERLINECONTROLSW32 {
DWORD cbStruct; /* size in bytes of MIXERLINECONTROLS */
DWORD dwLineID; /* line id (from MIXERLINE.dwLineID) */
union {
DWORD dwControlID; /* MIXER_GETLINECONTROLSF_ONEBYID */
DWORD dwControlType; /* MIXER_GETLINECONTROLSF_ONEBYTYPE */
};
DWORD cControls; /* count of controls pmxctrl points to */
DWORD cbmxctrl; /* size in bytes of _one_ MIXERCONTROL */
UINT32 pamxctrl; /* pointer to first MIXERCONTROL array */
} MIXERLINECONTROLSW32, *PMIXERLINECONTROLSW32, *LPMIXERLINECONTROLSW32;
#ifdef UNICODE
typedef MIXERLINECONTROLSW32 MIXERLINECONTROLS32;
typedef PMIXERLINECONTROLSW32 PMIXERLINECONTROLS32;
typedef LPMIXERLINECONTROLSW32 LPMIXERLINECONTROLS32;
#else
typedef MIXERLINECONTROLSA32 MIXERLINECONTROLS32;
typedef PMIXERLINECONTROLSA32 PMIXERLINECONTROLS32;
typedef LPMIXERLINECONTROLSA32 LPMIXERLINECONTROLS32;
#endif // UNICODE
typedef struct tMIXERCONTROLDETAILS32 {
DWORD cbStruct; /* size in bytes of MIXERCONTROLDETAILS */
DWORD dwControlID; /* control id to get/set details on */
DWORD cChannels; /* number of channels in paDetails array */
union {
UINT32 hwndOwner; /* for MIXER_SETCONTROLDETAILSF_CUSTOM */
DWORD cMultipleItems; /* if _MULTIPLE, the number of items per channel */
};
DWORD cbDetails; /* size of _one_ details_XX struct */
UINT32 paDetails; /* pointer to array of details_XX structs */
} MIXERCONTROLDETAILS32, *PMIXERCONTROLDETAILS32, FAR *LPMIXERCONTROLDETAILS32;
#ifdef WIN32
#include <poppack.h>
#else
#ifndef RC_INVOKED
#pragma pack()
#endif
#endif
#ifndef _WIN64
// WARNING WARNING WARNING!!!!
// If the below lines do not compile for 32 bit x86, you MUST sync the
// above wavehdr_tag32 structure up with the wavehdr_tag structure in
// mmsystem.w! It doesn't compile because someone changed mmsystem.w
// without changing the above structure.
// Make SURE when you sync it up that you use UINT32 for all elements
// that are normally 64bits on win64.
// You MUST also update all places that thunk the above structure!
// Look for all occurances of any of the wavehdr_tag32 typedefs in the
// wdmaud.sys directory.
struct wave_header_structures_are_in_sync {
char x[(sizeof (WAVEHDR32) == sizeof (WAVEHDR)) ? 1 : -1];
};
// WARNING WARNING WARNING!!!
// If above lines do not compile, see comment above and FIX!
// DO NOT COMMENT OUT THE LINES THAT DON'T COMPILE
#endif
#ifndef _WIN64
// WARNING WARNING WARNING!!!!
// If the below lines do not compile for 32 bit x86, you MUST sync the
// above midihdr_tag32 structure up with the midihdr_tag structure in
// mmsystem.w! It doesn't compile because someone changed mmsystem.w
// without changing the above structure.
// Make SURE when you sync it up that you use UINT32 for all elements
// that are normally 64bits on win64.
// You MUST also update all places that thunk the above structure!
// Look for all occurances of any of the midihdr_tag32 typedefs in the
// wdmaud.sys directory.
struct midi_header_structures_are_in_sync {
char x[(sizeof (MIDIHDR32) == sizeof (MIDIHDR)) ? 1 : -1];
};
// WARNING WARNING WARNING!!!
// If above lines do not compile, see comment above and FIX!
// DO NOT COMMENT OUT THE LINES THAT DON'T COMPILE
#endif
#ifndef _WIN64
// WARNING WARNING WARNING!!!!
// If the below lines do not compile for 32 bit x86, you MUST sync the
// above two tagMIXERLINEX32 structures up with the tagMIXERLINEX structures in
// mmsystem.w! It doesn't compile because someone changed mmsystem.w
// without changing the above structure.
// Make SURE when you sync it up that you use UINT32 for all elements
// that are normally 64bits on win64.
// You MUST also update all places that thunk the above structure!
// Look for all occurances of any of the MIXERLINE32 typedefs in the
// wdmaud.sys directory.
struct mixer_line_structures_are_in_sync {
char x[(sizeof (MIXERLINE32) == sizeof (MIXERLINE)) ? 1 : -1];
};
// WARNING WARNING WARNING!!!
// If above lines do not compile, see comment above and FIX!
// DO NOT COMMENT OUT THE LINES THAT DON'T COMPILE
#endif
#ifndef _WIN64
// WARNING WARNING WARNING!!!!
// If the below lines do not compile for 32 bit x86, you MUST sync the
// above two tagMIXERLINECONTROLSX32 structures up with the tagMIXERLINECONTROLSX structures in
// mmsystem.w! It doesn't compile because someone changed mmsystem.w
// without changing the above structure.
// Make SURE when you sync it up that you use UINT32 for all elements
// that are normally 64bits on win64.
// You MUST also update all places that thunk the above structure!
// Look for all occurances of any of the MIXERLINECONTROLS32 typedefs in the
// wdmaud.sys directory.
struct mixer_line_control_structures_are_in_sync {
char x[(sizeof (MIXERLINECONTROLS32) == sizeof (MIXERLINECONTROLS)) ? 1 : -1];
};
// WARNING WARNING WARNING!!!
// If above lines do not compile, see comment above and FIX!
// DO NOT COMMENT OUT THE LINES THAT DON'T COMPILE
#endif
#ifndef _WIN64
// WARNING WARNING WARNING!!!!
// If the below lines do not compile for 32 bit x86, you MUST sync the
// above tMIXERCONTROLDETAILS32 structure up with the tMIXERCONTROLDETAILS32 structure in
// mmsystem.w! It doesn't compile because someone changed mmsystem.w
// without changing the above structure.
// Make SURE when you sync it up that you use UINT32 for all elements
// that are normally 64bits on win64.
// You MUST also update all places that thunk the above structure!
// Look for all occurances of any of the MIXERCONTROLDETAILS32 typedefs in the
// wdmaud.sys directory.
struct mixer_control_details_structures_are_in_sync {
char x[(sizeof (MIXERCONTROLDETAILS32) == sizeof (MIXERCONTROLDETAILS)) ? 1 : -1];
};
// WARNING WARNING WARNING!!!
// If above lines do not compile, see comment above and FIX!
// DO NOT COMMENT OUT THE LINES THAT DON'T COMPILE
#endif
/***************************************************************************
Local prototypes
***************************************************************************/
//
// Device.c
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING usRegistryPathName
);
NTSTATUS
DispatchPnp(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
);
NTSTATUS
PnpAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
);
VOID
PnpDriverUnload(
IN PDRIVER_OBJECT DriverObject
);
//
// Ioctl.c
//
#ifdef PROFILE
VOID WdmaInitProfile();
VOID WdmaCleanupProfile();
NTSTATUS
AddMdlToList(
PMDL pMdl,
PWDMACONTEXT pWdmaContext
);
NTSTATUS
RemoveMdlFromList(
PMDL pMdl
);
#else
#define WdmaInitProfile()
#define AddMdlToList(pMdl,pWdmaContext)
#define RemoveMdlFromList(pMdl)
#endif
extern LIST_ENTRY WdmaPendingIrpListHead;
extern KSPIN_LOCK WdmaPendingIrpListSpinLock;
VOID
WdmaCsqInsertIrp(
IN struct _IO_CSQ *pCsq,
IN PIRP Irp
);
VOID
WdmaCsqRemoveIrp(
IN PIO_CSQ Csq,
IN PIRP Irp
);
PIRP
WdmaCsqPeekNextIrp(
IN PIO_CSQ Csq,
IN PIRP Irp,
IN PVOID PeekContext
);
VOID
WdmaCsqAcquireLock(
IN PIO_CSQ Csq,
OUT PKIRQL Irql
);
VOID
WdmaCsqReleaseLock(
IN PIO_CSQ Csq,
IN KIRQL Irql
);
VOID
WdmaCsqCompleteCanceledIrp(
IN PIO_CSQ pCsq,
IN PIRP Irp
);
NTSTATUS
AddIrpToPendingList(
PIRP pIrp,
ULONG IrpDeviceType,
PWDMACONTEXT pWdmaContext,
PWDMAPENDINGIRP_CONTEXT *ppPendingIrpContext
);
NTSTATUS
RemoveIrpFromPendingList(
PWDMAPENDINGIRP_CONTEXT pPendingIrpContext
);
VOID
wdmaudMapBuffer(
PIRP pIrp,
PVOID DataBuffer,
DWORD DataBufferSize,
PVOID *pMappedBuffer,
PMDL *ppMdl,
PWDMACONTEXT pContext,
BOOL bWrite
);
VOID
wdmaudUnmapBuffer(
PMDL pMdl
);
NTSTATUS
CaptureBufferToLocalPool(
PVOID DataBuffer,
DWORD DataBufferSize,
PVOID *ppMappedBuffer
#ifdef _WIN64
,DWORD ThunkBufferSize
#endif
);
NTSTATUS
CopyAndFreeCapturedBuffer(
PVOID DataBuffer,
DWORD DataBufferSize,
PVOID *ppMappedBuffer
);
NTSTATUS
SoundDispatchCreate(
IN PDEVICE_OBJECT pDO,
IN PIRP pIrp
);
NTSTATUS
SoundDispatchClose(
IN PDEVICE_OBJECT pDO,
IN PIRP pIrp
);
NTSTATUS
SoundDispatch(
IN PDEVICE_OBJECT pDO,
IN PIRP pIrp
);
NTSTATUS
SoundDispatchCleanup(
IN PDEVICE_OBJECT pDO,
IN PIRP pIrp
);
//
// wave.c
//
NTSTATUS
OpenWavePin(
PWDMACONTEXT pWdmaContext,
ULONG DeviceNumber,
LPWAVEFORMATEX lpFormat,
HANDLE32 DeviceHandle,
DWORD dwFlags,
ULONG DataFlow // DataFlow is either in or out.
);
VOID
CloseTheWavePin(
PWAVEDEVICE pWaveDev,
HANDLE32 DeviceHandle
);
VOID
CloseWavePin(
PWAVE_PIN_INSTANCE pWavePin
);
NTSTATUS
wqWriteWaveCallBack(
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp,
IN PWAVEHDR pWriteData
);
NTSTATUS
ssWriteWaveCallBack(
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp,
IN PSTREAM_HEADER_EX pStreamHeaderEx
);
NTSTATUS
WriteWaveOutPin(
PWAVEDEVICE pWaveOutDevice,
HANDLE32 DeviceHandle,
LPWAVEHDR pWriteData,
PSTREAM_HEADER_EX pStreamHeader,
PIRP pUserIrp,
PWDMACONTEXT pContext,
BOOL *pCompletedIrp
);
NTSTATUS
IoWavePin(
PWAVE_PIN_INSTANCE pWavePin,
ULONG Operation,
PWRITE_CONTEXT pWriteContext,
ULONG Size,
PVOID RefData,
PVOID CallBack
);
NTSTATUS
PosWavePin(
PWAVEDEVICE pWaveDevice,
HANDLE32 DeviceHandle,
PWAVEPOSITION pWavePos
);
NTSTATUS
BreakLoopWaveOutPin(
PWAVEDEVICE pWaveOutDevice,
HANDLE32 DeviceHandle
);
NTSTATUS
VolumeWaveOutPin(
ULONG DeviceNumber,
HANDLE32 DeviceHandle,
PDEVICEVOLUME pWaveVolume
);
NTSTATUS
VolumeWaveInPin(
ULONG DeviceNumber,
PDEVICEVOLUME pWaveVolume
);
NTSTATUS
VolumeWavePin(
PWAVE_PIN_INSTANCE pWavePin,
PDEVICEVOLUME pWaveVolume
);
NTSTATUS
ResetWaveOutPin(
PWAVEDEVICE pWaveOutDevice,
HANDLE32 DeviceHandle
);
NTSTATUS
ResetWavePin(
PWAVE_PIN_INSTANCE pWavePin,
KSRESET *pResetValue
);
NTSTATUS
StateWavePin(
PWAVEDEVICE pWaveInDevice,
HANDLE32 DeviceHandle,
KSSTATE State
);
NTSTATUS
ReadWaveCallBack(
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp,
IN PSTREAM_HEADER_EX pStreamHeader
);
NTSTATUS
ReadWaveInPin(
PWAVEDEVICE pWaveInDevice,
HANDLE32 DeviceHandle,
PSTREAM_HEADER_EX pStreamHeader,
PIRP pUserIrp,
PWDMACONTEXT pContext,
BOOL *pCompletedIrp
);
ULONG
FindMixerForDevNode(
IN PMIXERDEVICE paMixerDevice,
IN PCWSTR DeviceInterface
);
NTSTATUS
FindVolumeControl(
IN PWDMACONTEXT pWdmaContext,
IN PCWSTR DeviceInterface,
IN DWORD DeviceType
);
NTSTATUS
IsVolumeControl(
IN PWDMACONTEXT pWdmaContext,
IN PCWSTR DeviceInterface,
IN DWORD dwComponentType,
IN PDWORD pdwControlID,
IN PDWORD pcChannels
);
NTSTATUS
SetVolume(
IN PWDMACONTEXT pWdmaContext,
IN DWORD DeviceNumber,
IN DWORD DeviceType,
IN DWORD LeftChannel,
IN DWORD RightChannel
);
NTSTATUS
GetVolume(
IN PWDMACONTEXT pWdmaContext,
IN DWORD DeviceNumber,
IN DWORD DeviceType,
OUT PDWORD LeftChannel,
OUT PDWORD RightChannel
);
VOID
CleanupWavePins(
IN PWAVEDEVICE pWaveDevice
);
VOID
CleanupWaveDevices(
PWDMACONTEXT pWdmaContext
);
NTSTATUS
wdmaudPrepareIrp(
PIRP pIrp,
ULONG IrpDeviceType,
PWDMACONTEXT pWdmaContext,
PWDMAPENDINGIRP_CONTEXT *ppPendingIrpContext
);
NTSTATUS
wdmaudUnprepareIrp(
PIRP pIrp,
NTSTATUS IrpStatus,
ULONG_PTR Information,
PWDMAPENDINGIRP_CONTEXT pPendingIrpContext
);
//
// midi.c
//
NTSTATUS
OpenMidiPin(
PWDMACONTEXT pWdmaContext,
ULONG DeviceNumber,
ULONG DataFlow //DataFlow is either in or out.
);
VOID
CloseMidiDevicePin(
PMIDIDEVICE pMidiDevice
);
VOID
CloseMidiPin(
PMIDI_PIN_INSTANCE pMidiPin
);
NTSTATUS
WriteMidiEventCallBack(
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp,
IN PSTREAM_HEADER_EX pStreamHeader
);
NTSTATUS
WriteMidiEventPin(
PMIDIDEVICE pMidiOutDevice,
ULONG ulEvent
);
NTSTATUS
WriteMidiCallBack(
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp,
IN PSTREAM_HEADER_EX pStreamHeader
);
NTSTATUS
WriteMidiOutPin(
LPMIDIHDR pMidiHdr,
PSTREAM_HEADER_EX pStreamHeader,
BOOL *pCompletedIrp
);
ULONGLONG
GetCurrentMidiTime(
VOID
);
NTSTATUS
ResetMidiInPin(
PMIDI_PIN_INSTANCE pMidiPin
);
NTSTATUS
StateMidiOutPin(
PMIDI_PIN_INSTANCE pMidiPin,
KSSTATE State
);
NTSTATUS
StateMidiInPin(
PMIDI_PIN_INSTANCE pMidiPin,
KSSTATE State
);
NTSTATUS
ReadMidiCallBack(
PDEVICE_OBJECT pDeviceObject,
PIRP pIrp,
IN PSTREAM_HEADER_EX pStreamHeader
);
VOID
ReadMidiEventWorkItem(
PSTREAM_HEADER_EX pStreamHeader,
PVOID NotUsed
);
NTSTATUS
ReadMidiPin(
PMIDI_PIN_INSTANCE pMidiPin
);
NTSTATUS
AddBufferToMidiInQueue(
PMIDI_PIN_INSTANCE pMidiPin,
PMIDIINHDR pNewMidiInHdr
);
VOID
CleanupMidiDevices(
PWDMACONTEXT pWdmaContext
);
// from NTKERN
NTSYSAPI NTSTATUS NTAPI NtClose
(
IN HANDLE Handle
);
//
// sysaudio.c
//
/*
NTSTATUS
AllocMem(
POOL_TYPE PoolType,
PVOID *pp,
ULONG size,
ULONG ultag
);
VOID
FreeMem(
PVOID *pp
);
*/
NTSTATUS
OpenSysAudioPin(
ULONG Device,
ULONG PinId,
KSPIN_DATAFLOW DataFlowRequested,
PKSPIN_CONNECT pPinConnect,
PFILE_OBJECT *ppFileObjectPin,
PDEVICE_OBJECT *ppDeviceObjectPin,
PCONTROLS_LIST pControlList
);
VOID
CloseSysAudio(
PWDMACONTEXT pWdmaContext,
PFILE_OBJECT pFileObjectPin
);
NTSTATUS
OpenSysAudio(
PHANDLE pHandle,
PFILE_OBJECT *ppFileObject
);
NTSTATUS
OpenDevice(
IN PWSTR pwstrDevice,
OUT PHANDLE pHandle
);
NTSTATUS
GetPinProperty(
PFILE_OBJECT pFileObject,
ULONG PropertyId,
ULONG PinId,
ULONG cbProperty,
PVOID pProperty
);
NTSTATUS
GetPinPropertyEx(
PFILE_OBJECT pFileObject,
ULONG PropertyId,
ULONG PinId,
PVOID *ppProperty
);
VOID
GetControlNodes(
PFILE_OBJECT pDeviceFileObject,
PFILE_OBJECT pPinFileObject,
ULONG PinId,
PCONTROLS_LIST pControlList
);
ULONG
ControlNodeFromGuid(
PFILE_OBJECT pDeviceFileObject,
PFILE_OBJECT pPinFileObject,
ULONG PinId,
GUID* NodeType
);
PVOID
GetTopologyProperty(
PFILE_OBJECT pDeviceFileObject,
ULONG PropertyId
);
PKSTOPOLOGY_CONNECTION
FindConnection(
PKSTOPOLOGY_CONNECTION pConnections,
ULONG NumConnections,
ULONG FromNode,
ULONG FromPin,
ULONG ToNode,
ULONG ToPin
);
ULONG
GetFirstConnectionIndex(
PFILE_OBJECT pPinFileObject
);
VOID
UpdatePreferredDevice(
PWDMACONTEXT pWdmaContext
);
NTSTATUS
SetPreferredDevice(
PWDMACONTEXT pContext,
LPDEVICEINFO pDeviceInfo
);
NTSTATUS
GetSysAudioProperty(
PFILE_OBJECT pFileObject,
ULONG PropertyId,
ULONG DeviceIndex,
ULONG cbProperty,
PVOID pProperty
);
NTSTATUS
SetSysAudioProperty(
PFILE_OBJECT pFileObject,
ULONG PropertyId,
ULONG cbProperty,
PVOID pProperty
);
WORD
GetMidiTechnology(
PKSDATARANGE_MUSIC MusicDataRange
);
DWORD
GetFormats(
PKSDATARANGE_AUDIO AudioDataRange
);
NTSTATUS
wdmaudGetDevCaps(
PWDMACONTEXT pWdmaContext,
DWORD DeviceType,
DWORD DeviceNumber,
LPBYTE lpCaps,
DWORD dwSize
);
NTSTATUS
wdmaudGetNumDevs(
PWDMACONTEXT pWdmaContext,
DWORD DeviceType,
LPCTSTR DeviceInterface,
LPDWORD lpNumberOfDevices
);
BOOL
IsEqualInterface(
PKSPIN_INTERFACE pInterface1,
PKSPIN_INTERFACE pInterface2
);
DWORD
wdmaudTranslateDeviceNumber(
PWDMACONTEXT pWdmaContext,
DWORD DeviceType,
PCWSTR DeviceInterface,
DWORD DeviceNumber
);
NTSTATUS
AddDevice(
PWDMACONTEXT pWdmaContext,
ULONG Device,
DWORD DeviceType,
PCWSTR DeviceInterface,
ULONG PinId,
PWSTR pwstrName,
BOOL fUsePreferred,
PDATARANGES pDataRange,
PKSCOMPONENTID ComponentId
);
NTSTATUS
PinProperty(
PFILE_OBJECT pFileObject,
const GUID *pPropertySet,
ULONG ulPropertyId,
ULONG ulFlags,
ULONG cbProperty,
PVOID pProperty
);
NTSTATUS
PinMethod(
PFILE_OBJECT pFileObject,
const GUID *pMethodSet,
ULONG ulMethodId,
ULONG ulFlags,
ULONG cbMethod,
PVOID pMethod
);
VOID
CopyAnsiStringtoUnicodeString(
LPWSTR lpwstr,
LPCSTR lpstr,
int len
);
VOID
CopyUnicodeStringtoAnsiString(
LPSTR lpstr,
LPCWSTR lpwstr,
int len
);
NTSTATUS
AttachVirtualSource(
PFILE_OBJECT pFileObject,
ULONG ulPinId
);
NTSTATUS
SysAudioPnPNotification(
IN PVOID NotificationStructure,
IN PVOID Context
);
NTSTATUS
InitializeSysaudio(
PVOID Reference1,
PVOID Reference2
);
VOID
UninitializeSysaudio(
);
NTSTATUS
AddDevNode(
PWDMACONTEXT pWdmaContext,
PCWSTR DeviceInterface,
UINT DeviceType
);
VOID
RemoveDevNode(
PWDMACONTEXT pWdmaContext,
PCWSTR DeviceInterface,
UINT DeviceType
);
NTSTATUS
ProcessDevNodeListItem(
PWDMACONTEXT pWdmaContext,
PDEVNODE_LIST_ITEM pDevNodeListItem,
ULONG DeviceType
);
VOID
SysaudioAddRemove(
PWDMACONTEXT pWdmaContext
);
NTSTATUS
QueueWorkList(
PWDMACONTEXT pWdmaContext,
VOID (*Function)(
PVOID Reference1,
PVOID Reference2
),
PVOID Reference1,
PVOID Reference2
);
VOID
WorkListWorker(
PVOID pReference
);
NTSTATUS
AddFsContextToList(
PWDMACONTEXT pWdmaContext
);
NTSTATUS
RemoveFsContextFromList(
PWDMACONTEXT pWdmaContext
);
typedef NTSTATUS (FNCONTEXTCALLBACK)(PWDMACONTEXT pContext,PVOID pvoidRefData,PVOID pvoidRefData2);
NTSTATUS
HasMixerBeenInitialized(
PWDMACONTEXT pContext,
PVOID pvoidRefData,
PVOID pvoidRefData2
);
NTSTATUS
EnumFsContext(
FNCONTEXTCALLBACK fnCallback,
PVOID pvoidRefData,
PVOID pvoidRefData2
);
VOID
WdmaContextCleanup(
PWDMACONTEXT pWdmaContext
);
VOID
WdmaGrabMutex(
PWDMACONTEXT pWdmaContext
);
VOID
WdmaReleaseMutex(
PWDMACONTEXT pWdmaContext
);
int
MyWcsicmp(
const wchar_t *,
const wchar_t *
);
void
LockedWaveIoCount(
PWAVE_PIN_INSTANCE pCurWavePin,
BOOL bIncrease
);
void
LockedMidiIoCount(
PMIDI_PIN_INSTANCE pCurMidiPin,
BOOL bIncrease
);
void
MidiCompleteIo(
PMIDI_PIN_INSTANCE pMidiPin,
BOOL Yield
);
NTSTATUS
StatePin(
IN PFILE_OBJECT pFileObject,
IN KSSTATE State,
OUT PKSSTATE pResultingState
);
//==========================================================================
//
// In order to better track memory allocations, if you include the following
// all memory allocations will be tagged.
//
//==========================================================================
//
// For memory allocation routines we need some memory tags. Well, here they
// are.
//
#define TAG_AudD_DEVICEINFO ((ULONG)'DduA')
#define TAG_AudC_CONTROL ((ULONG)'CduA')
#define TAG_AudE_EVENT ((ULONG)'EduA')
#define TAG_AuDF_HARDWAREEVENT ((ULONG)'FDuA')
#define TAG_AudL_LINE ((ULONG)'LduA')
#define TAG_AuDA_CHANNEL ((ULONG)'ADuA')
#define TAG_AuDB_CHANNEL ((ULONG)'BDuA')
#define TAG_AuDC_CHANNEL ((ULONG)'CDuA')
#define TAG_AuDD_CHANNEL ((ULONG)'DDuA')
#define TAG_AuDE_CHANNEL ((ULONG)'EDuA')
#define TAG_AudS_SUPERMIX ((ULONG)'SduA')
#define TAG_Audl_MIXLEVEL ((ULONG)'lduA')
#define TAG_AudN_NODE ((ULONG)'NduA')
#define TAG_Audn_PEERNODE ((ULONG)'nduA')
//#define TAG_AudP_PROPERTY ((ULONG)'PduA')
#define TAG_AudQ_PROPERTY ((ULONG)'QduA')
#define TAG_Audq_PROPERTY ((ULONG)'qduA')
#define TAG_AudV_PROPERTY ((ULONG)'VduA')
#define TAG_Audv_PROPERTY ((ULONG)'vduA')
#define TAG_AudU_PROPERTY ((ULONG)'UduA')
#define TAG_Audu_PROPERTY ((ULONG)'uduA')
#define TAG_Auda_PROPERTY ((ULONG)'aduA')
#define TAG_AudA_PROPERTY ((ULONG)'AduA')
#define TAG_Audp_NAME ((ULONG)'pduA')
#define TAG_AudG_GETMUXLINE ((ULONG)'GduA')
#define TAG_AudI_INSTANCE ((ULONG)'IduA')
#define TAG_Audd_DETAILS ((ULONG)'dduA')
#define TAG_Audi_PIN ((ULONG)'iduA')
#define TAG_Audt_CONNECT ((ULONG)'tduA')
#define TAG_Audh_STREAMHEADER ((ULONG)'hduA')
#define TAG_Audm_MUSIC ((ULONG)'mduA')
#define TAG_Audx_CONTEXT ((ULONG)'xduA')
#define TAG_AudT_TIMER ((ULONG)'TduA')
#define TAG_AudF_FORMAT ((ULONG)'FduA')
#define TAG_AudM_MDL ((ULONG)'MduA')
#define TAG_AudR_IRP ((ULONG)'RduA')
#define TAG_AudB_BUFFER ((ULONG)'BduA')
#define TAG_Aude_MIDIHEADER ((ULONG)'eduA')
#define TAG_AuDN_NOTIFICATION ((ULONG)'NDuA')
#define TAG_AuDL_LINK ((ULONG)'LDuA')
/***************************************************************************
DEBUGGING SUPPORT
***************************************************************************/
#ifdef DEBUG
//-----------------------------------------------------------------------------
//
// Debug support for wdmaud.sys on NT is found here.
//
// To start with, There will be four different levels or debugging information.
// With each level, there will be functional area. Thus, you can turn on
// debug output for just driver calls, api tracing or whatnot.
//
//-----------------------------------------------------------------------------
//
// 8 bits reserved for debug leves.
//
#define DL_ERROR 0x00000000
#define DL_WARNING 0x00000001
#define DL_TRACE 0x00000002
#define DL_MAX 0x00000004
#define DL_PATHTRAP 0x00000080
#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_HARDWAREEVENT 0x80000000
#define FA_MIXER 0x40000000
#define FA_IOCTL 0x20000000
#define FA_SYSAUDIO 0x10000000
#define FA_PERSIST 0x08000000
#define FA_PROPERTY 0x04000000
#define FA_USER 0x02000000
#define FA_WAVE 0x01000000
#define FA_MIDI 0x00800000
#define FA_INSTANCE 0x00400000
#define FA_NOTE 0x00200000
#define FA_KS 0x00100000
#define FA_MASK 0xFFFFF000
#define FA_ASSERT 0x00002000
#define FA_ALL 0x00001000
//
// 4 bits reserved for return codes. The 3 lower bits map directly to status
// codes shifted right 22 bits. One bit represents that fact that we have a
// return statement.
//
#define RT_ERROR 0x00000300 // 0xCxxxxxxx >> 22 == 0x0000003xx
#define RT_WARNING 0x00000200 // 0x8xxxxxxx >> 22 == 0x0000002xx
#define RT_INFO 0x00000100 // 0x4xxxxxxx >> 22 == 0x0000001xx
#define RT_MASK 0x00000300
#define RT_RETURN 0x00000800
//-----------------------------------------------------------------------------
// Macro might look like this.
//
// Take the string that we want to output and add "WDMAUD.SYS" and ("Error" or
// "warning" or whatever) to the front of the string. Next, follow that with
// the function name and line number in the file that the function is found in.
// Then display the error message and then close the message with a breakpoint
// statement.
//
// The logic goes like this. If the user wants to see these messages ok. Else
// bail. If so, wdmaudDbgPreCheckLevel will return TRUE and it will have
// formated the start of the string. It will look like:
//
// WDMAUD.SYS Erorr OurFooFunction(456)
//
// Next, the message string with the variable arguements will be displayed, like:
//
// WDMAUD.SYS Warning OurFooFunction(456) Invalid Data Queue returning C0000109
//
// Then, wdmaudDbgPostCheckLevel will be called to post format the message and
// see if the user wanted to trap on this output.
//
// WDMAUD.SYS Warning OutFooFunction(456) Invalid Data Queue returning C0000109 &DL=ff680123
//
// The internal version will append "See \\debugtips\wdmaud.sys\wdmaud.htm" to
// the end
//
// if( wdmaudDbgPreCheckLevel(TypeOfMessageInCode) )
// {
// DbgPrintF( _x_ ); // output the actual string here.
// if( wdmaudDbgPostCheckLevel(Variable) )
// DbgBreakPoint();
// }
//
// DPF( DL_WARNING|DL_ALL, ("Invalid queue %X",Queue) );
//
//-----------------------------------------------------------------------------
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[];
extern UINT uiDebugLevel;
#define DPF(_x_,_y_) {if( wdmaudDbgPreCheckLevel(_x_,__FUNCTION__,__LINE__) ) { DbgPrint _y_; \
wdmaudDbgPostCheckLevel( _x_ ); }}
//
// Writing macros are easy, it's figuring out when they are useful that is more
// difficult! In this code, The RETURN macro replaces the return keyword in the
// debug builds when returning an NTSTATUS code. Then, when tracking debug output
// the return debug line will be displayed based on the type of error the status
// value represents.
//
// Notice that the error code is shifted 22 bits and ORed with RT_RETURN. Thus
// a value of "0xCxxxxxxx" will be seen as an error message, "0x8xxxxxxx" will
// be seen as a warning and "0x4xxxxxxx" will be seen as a message.
//
// Key, if uiDebugLevel is DL_ERROR or DL_WARNING all NTSTATUS Error message will be displayed
// if uiDebugLevel is DL_TRACE, all warning return codes and error return codes
// will be displayed and if uiDebugLevel is set to DL_MAX all return messages will
// displayed including success codes.
//
// RETURN(Status);
//
// WARNING: Do not rap functions in this macro! Notice that _status_ is used more
// then once! Thus, the function will get called more then once! Don't do it.
#define RETURN(_status_) {DPF((RT_RETURN|DL_WARNING|((unsigned long)_status_>>22)),("%X:%s",_status_,wdmaudReturnString(_status_))); return (_status_);}
//
// _list_ is parameters for wdmaudExclusionList. Like (_status_,STATUS_INVALID_PARAMETER,STATUS_NOT_FOUND,...).
// wdmaudExclusionList takes a variable number of parameters. If the status value is
// found in the list of error codes supplied, the function returns TRUE.
//
extern int __cdecl
wdmaudExclusionList(
int count,
unsigned long status,
...
);
//
// Thus, this macro reads: We have a return code that we're going to return. Is
// it a special return code that we don't need to display? NO - show the debug
// spew. YES - just return it.
//
// _status_ = The status in question
// _y_ = Parameters to wdmaudExclusionList "( the status in question, exclution values, .... )"
//
#define DPFRETURN( _status_,_y_ ) {if( !wdmaudExclusionList _y_ ) { \
if( wdmaudDbgPreCheckLevel((RT_RETURN|DL_WARNING|(_status_>>22)),__FUNCTION__,__LINE__) ) { \
DbgPrint ("%X:%s",_status_,wdmaudReturnString(_status_) ); \
wdmaudDbgPostCheckLevel( (RT_RETURN|DL_WARNING|(_status_>>22)) ); \
} } return (_status_);}
//
// 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!
//
#define DPFASSERT(_exp_) {if( !(_exp_) ) {DPF(DL_ERROR|FA_ASSERT,("'%s'",#_exp_) );}}
#ifdef WANT_TRAPS
//
// Branch trap. This macro is used when testing code to make sure that you've
// hit all branches in the new code. Every time you hit one validate that the
// code does the correct thing and then remove it from the source. We should
// ship with none of these lines left in the code!!!!!!
//
#define DPFBTRAP() DPF(DL_PATHTRAP,("Please report") )
#else
#define DPFBTRAP()
#endif
//
// There are a number of new routines in the checked build that validate structure
// types for us now. These should be used inside the DPFASSERT() macro. Thus,
// Under retail they don't have to be defined.
//
BOOL
IsValidDeviceInfo(
IN LPDEVICEINFO pDeviceInfo
);
BOOL
IsValidMixerObject(
IN PMIXEROBJECT pmxobj
);
BOOL
IsValidMixerDevice(
IN PMIXERDEVICE pmxd
);
BOOL
IsValidControl(
IN PMXLCONTROL pControl
);
BOOL
IsValidWdmaContext(
IN PWDMACONTEXT pWdmaContext
);
BOOL
IsValidLine(
IN PMXLLINE pLine
);
VOID
GetuiDebugLevel(
);
#else
#define DPF(_x_,_y_)
#define RETURN( _status_ ) return (_status_)
#define DPFRETURN( _status_,_y_ ) return (_status_)
#define DPFASSERT(_exp_)
#define DPFBTRAP()
#endif
VOID
kmxlFindAddressInNoteList(
IN PMXLCONTROL pControl
);
VOID
kmxlCleanupNoteList(
);
NTSTATUS
kmxlDisableControlChangeNotifications(
IN PMXLCONTROL pControl
);
VOID
kmxlRemoveContextFromNoteList(
PWDMACONTEXT pContext
);
VOID
kmxlPersistHWControlWorker(
PVOID pReference
);
#endif // _WDMSYS_H_INCLUDED_