1972 lines
52 KiB
C
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_
|
|
|