In versions of Windows before Windows XP, WDM audio drivers do not have a streamlined way of exposing multichannel nodes of the following types:
In particular, no mechanism exists for explicitly querying a node for the number of channels that it supports. Although workarounds exist for this problem, they have drawbacks. For example, a client can use the KSPROPERTY_AUDIO_VOLUMELEVEL property to iteratively query a volume node (KSNODETYPE_VOLUME) for the volume level of each channel—0, 1, and so on—until the request returns an error indicating that no more channels exist. Unfortunately, this technique requires multiple queries and is too inefficient to handle newer multichannel audio devices.
Windows XP and later operating systems overcome these limitations by defining two additional flag bits in the MembersFlags member of the KSPROPERTY_MEMBERSHEADER structure, which the property handler outputs in response to a basic-support query:
During a basic-support property request on a node, the handler sets this flag bit to indicate that the MembersCount member of KSPROPERTY_MEMBERSHEADER contains the number of channels that the node supports.
The handler bitwise ORs this flag bit with the KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL flag to indicate that a single property value is applied uniformly across all channels in a node. For example, if the hardware provides only a single volume-level control for all channels, the volume node's basic-support handler sets the KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM flag to indicate this restriction. If this flag is not set, the meaning is that the volume level for each channel can be controlled independently of the volume levels for the other channels.
In miniport drivers for Windows XP and later, the property handler for a multichannel volume node should set the KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL bit in response to a KSPROPERTY_AUDIO_VOLUMELEVEL basic-support query. The handler returns an array of KSPROPERTY_STEPPING_LONG structures—one for each channel exposed by the node—and sets MembersSize to sizeof(KSPROPERTY_STEPPING_LONG). Each array element describes a channel's minimum and maximum volume levels and the delta between successive values in the range. A different range can be specified for each individual channel so that channels with non-uniform ranges can be exposed correctly. For example, a subwoofer channel might have a range that differs from that of the other channels.
The following code example shows how to handle a basic-support query for an audio property with non-uniform property values. Variable pDescription in the first line of code below points to the KSPROPERTY_DESCRIPTION structure at the beginning of the data buffer into which the handler writes the basic-support information:
//
// Fill in the members header.
//
PKSPROPERTY_MEMBERSHEADER pMembers = PKSPROPERTY_MEMBERSHEADER(pDescription + 1);
pMembers->MembersFlags = KSPROPERTY_MEMBER_STEPPEDRANGES;
pMembers->MembersSize = sizeof(KSPROPERTY_STEPPING_LONG);
pMembers->MembersCount = ulNumChannels;
pMembers->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL;
//
// Fill in the stepped range with the driver default.
//
PKSPROPERTY_STEPPING_LONG pRange = PKSPROPERTY_STEPPING_LONG(pMembers + 1);
pRange->Reserved = 0;
for (ULONG i=0; i<ulNumChannels; i++)
{
pRange[i].Bounds.SignedMinimum = ulChannelMin[i];
pRange[i].Bounds.SignedMaximum = ulChannelMax[i];
pRange[i].SteppingDelta = ChannelStepping[i];
}
pPropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER) +
ulNumChannels*sizeof(KSPROPERTY_STEPPING_LONG);
The following figure shows the layout of the data buffer for this example. The pDescription, pMembers, and pRange pointers are shown pointing to their respective offsets within the buffer.

Layout of Data Buffer for Basic-Support Query Example
For this example, the handler sets MembersCount to ulNumChannels, the number of channels. The size in bytes of the range array is
MembersSize * MembersCount
Note that if the KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM flag were set in this example, the handler would set all of the KSPROPERTY_STEPPING_LONG structures in the array to the same range.
The basic-support handler for a tone node's KSPROPERTY_AUDIO_BASS, KSPROPERTY_AUDIO_TREBLE, or KSPROPERTY_AUDIO_MID property operates in similar fashion.
If a multichannel node has a property with a per-channel property value of type BOOL, the basic-support handler does not need to fill in a stepping-range array because the range is implicitly limited to the values TRUE and FALSE. In this case, the handler sets MembersSize to zero and MembersCount to the number of channels. Two examples of this type of property are a mute node's KSPROPERTY_AUDIO_MUTE property and a tone node's KSPROPERTY_AUDIO_BASS_BOOST property.
The following code example shows how to handle a multichannel node's basic-support request for a property with no stepping ranges:
//
// Fill in the members header.
//
PKSPROPERTY_MEMBERSHEADER pMembers = PKSPROPERTY_MEMBERSHEADER(pDescription + 1);
pMembers->MembersFlags = 0;
pMembers->MembersSize = 0;
pMembers->MembersCount = ulNumChannels;
pMembers->Flags = KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL;
pPropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER);
As before, the flag KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM can be bitwise ORed with the KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL flag in the MembersFlag field to indicate that the hardware applies the same property value uniformly across all channels in a node.
Using the MULTICHANNEL and UNIFORM flags eliminates the need to group the channels into pairs and expose a separate stereo volume node for each pair of channels, as is done in the ac97 sample driver in the Windows DDK. Because Windows versions earlier than Windows XP do not support these flags, your driver's basic-support handler should use the IPortClsVersion interface to query for the portcls.sys version in order to determine whether to use these flags.
The topology parser (in the kernel-mode WDMAud system driver, wdmaud.sys) obtains an audio device's topology from its WDM audio driver. The parser exposes that device as a traditional mixer device through the legacy Windows Multimedia mixer API. In Windows XP and later, WDMAud uses the KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL flag to determine the number of channels to report in the cChannels member of the MIXERLINE structure. Additionally, if the node's basic-support handler specifies the KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM flag, WDMAud sets the MIXERCONTROL_CONTROLF_UNIFORM flag in the corresponding MIXERCONTROL structure. Through this flag, applications can determine whether they can adjust each channel individually or all channels uniformly through a master control. For more information about MIXERCONTROL, MIXERLINE, and the mixer API, see the Platform SDK documentation.
In Windows XP and later, the SndVol32 volume-control program (see SysTray and SndVol32) displays controls for multichannel devices, as shown in the following figure.

SndVol32 Volume-Control Program
If SndVol32 detects a line that has more than two channels, it replaces the normal pan control with a button labeled Speaker Volume, which appears above the main volume slider in the preceding figure. Clicking on the Speaker Volume button will bring up a dialog displaying controls for all of the channels for a particular line, as shown in the following figure.

Advanced Audio Properties Dialog
Because the mixer API exposes channels by number, it infers the channel names from the speaker configuration that is currently selected in the Advanced Audio Properties dialog in the multimedia control panel.
For example, if a device exposes four channels on a line and the user has selected "Quadraphonic speakers", the channel names will be "Left" (channel 0), "Right" (channel 1), "Back Left" (channel 2), and "Back Right" (channel 3), as shown in the preceding figure. Changing the speaker configuration to "Surround sound speakers" will result in a channel mapping of "Left" (channel 0), "Right" (channel 1), "Front Center" (channel 2), and "Back Center" (channel 3).
At the driver level, the KSPROPERTY_AUDIO_CHANNEL_CONFIG property uses a mask value of KSAUDIO_SPEAKER_QUAD or KSAUDIO_SPEAKER_SURROUND to represent a quadraphonic or surround speaker configuration, respectively. Header file ksmedia.h defines these values as follows:
#define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)
#define KSAUDIO_SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \
SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER)
Either mask contains four bits that specify the speaker positions of the four channels. In either case, the KSPROPERTY_AUDIO_VOLUMELEVEL property identifies these same four channels as channels 0, 1, 2, and 3, respectively.
If the node's basic-support handler specifies the KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM flag, the sliders shown in the Speaker Volume dialog move in unison with changes made to any of the sliders.