windows-nt/Source/XPSP1/NT/drivers/wdm/audio/sysaudio/util.cpp
2020-09-26 16:20:57 +08:00

2135 lines
56 KiB
C++

//---------------------------------------------------------------------------
//
// Module: util.c
//
// Description:
//
//
//@@BEGIN_MSINTERNAL
// Development Team:
// Mike McLaughlin
//
// History: Date Author Comment
//
// To Do: Date Author Comment
//
//@@END_MSINTERNAL
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
//
//---------------------------------------------------------------------------
#include "common.h"
#define SMALL_BLOCK_SIZE 32
extern KSDATARANGE DataRangeWildCard;
extern KSDATARANGE VirtualPinDataRange;
//===========================================================================
//===========================================================================
#pragma LOCKED_DATA
#ifdef DEBUG
//#define MEMORY_LIST
ULONG ulDebugFlags = 0;
ULONG ulDebugNumber = MAXULONG;
#ifdef UNDER_NT
int SYSAUDIOTraceLevel = 5;
#else
int SYSAUDIOTraceLevel = 50;
#endif
ULONG cAllocMem = 0;
ULONG cAllocMemSmall = 0;
ULONG cAllocMem64 = 0;
ULONG cAllocMem128 = 0;
ULONG cbMemoryUsage = 0;
#endif
//===========================================================================
//===========================================================================
LIST_ENTRY glehQueueWorkList;
KSPIN_LOCK gSpinLockQueueWorkList;
WORK_QUEUE_ITEM gWorkItem;
LONG gcQueueWorkList = 0;
KMUTEX gMutex;
PKSWORKER gWorkerObject = NULL;
PKSWORKER gCriticalWorkerObject = NULL;
#ifdef USE_ZONES
ZONE_HEADER gZone;
#endif
#ifdef MEMORY_LIST
LIST_ENTRY gleMemoryHead;
KSPIN_LOCK gSpinLockMemoryHead;
#endif
#pragma PAGEABLE_DATA
//===========================================================================
//===========================================================================
#pragma INIT_CODE
#pragma INIT_DATA
NTSTATUS
InitializeUtil()
{
NTSTATUS Status = STATUS_SUCCESS;
#ifdef USE_ZONES
PVOID pInitial = NULL;
pInitial = ExAllocatePoolWithTag(PagedPool, 4096, 0x41535953);
if(pInitial == NULL) {
Trap();
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
Status = ExInitializeZone(&gZone, SMALL_BLOCK_SIZE, pInitial, 4096);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
#endif
#ifdef MEMORY_LIST
InitializeListHead(&gleMemoryHead);
KeInitializeSpinLock(&gSpinLockMemoryHead);
#endif
#ifdef DEBUG
#ifndef UNDER_NT
#ifdef _X86_
InitializeDebug();
#endif
#endif
#endif
KeInitializeSpinLock(&gSpinLockQueueWorkList);
InitializeListHead(&glehQueueWorkList);
ExInitializeWorkItem(
&gWorkItem,
CQueueWorkListData::AsyncWorker,
NULL);
//
// Note... if we fail during preparation, the DriverUnload() routine
// calls the DeinitializeUtil() function which handles the clean up.
//
Status = KsRegisterWorker(DelayedWorkQueue, &gWorkerObject);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
Status = KsRegisterWorker(CriticalWorkQueue, &gCriticalWorkerObject);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
exit:
#ifdef USE_ZONES
if(!NT_SUCCESS(Status)) {
if(pInitial != NULL) {
//
// Make sure UninitializeMemory doesn't also try to free this.
//
gZone.SegmentList.Next = NULL;
//
// Free initial zone page if failure
//
ExFreePool(pInitial);
}
}
#endif
return(Status);
}
#pragma PAGEABLE_CODE
#pragma PAGEABLE_DATA
VOID
UninitializeUtil()
{
if(gWorkerObject != NULL) {
KsUnregisterWorker(gWorkerObject);
gWorkerObject = NULL;
}
if(gCriticalWorkerObject != NULL) {
KsUnregisterWorker(gCriticalWorkerObject);
gCriticalWorkerObject = NULL;
}
}
VOID
UninitializeMemory()
{
#ifdef USE_ZONES
PSINGLE_LIST_ENTRY psle, psleNext;
psle = gZone.SegmentList.Next;
while(psle != NULL) {
psleNext = psle->Next;
ExFreePool(psle);
psle = psleNext;
}
#endif
ASSERT(cbMemoryUsage == 0);
}
NTSTATUS
DispatchInvalidDeviceRequest(
IN PDEVICE_OBJECT pdo,
IN PIRP pIrp
)
{
return KsDispatchInvalidDeviceRequest(pdo,pIrp);
}
BOOLEAN
DispatchFastIoDeviceControlFailure(
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength,
IN ULONG IoControlCode,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
return KsDispatchFastIoDeviceControlFailure(
FileObject,
Wait,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
IoControlCode,
IoStatus,
DeviceObject);
}
BOOLEAN
DispatchFastReadFailure(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
{
return KsDispatchFastReadFailure(
FileObject,
FileOffset,
Length,
Wait,
LockKey,
Buffer,
IoStatus,
DeviceObject);
}
BOOL
CompareDataRange(
PKSDATARANGE pDataRange1,
PKSDATARANGE pDataRange2
)
{
KSDATARANGE_AUDIO DataRangeAudioIntersection;
if(CompareDataRangeGuids(pDataRange1, pDataRange2)) {
//
// See if there is a valid intersection
//
if(DataIntersectionAudio(
(PKSDATARANGE_AUDIO)pDataRange1,
(PKSDATARANGE_AUDIO)pDataRange2,
&DataRangeAudioIntersection)) {
return(TRUE);
}
if(pDataRange1 == &DataRangeWildCard ||
pDataRange2 == &DataRangeWildCard ||
pDataRange1 == &VirtualPinDataRange ||
pDataRange2 == &VirtualPinDataRange) {
return(TRUE);
}
return(FALSE);
}
return(FALSE);
}
BOOL DataIntersectionRange(
PKSDATARANGE pDataRange1,
PKSDATARANGE pDataRange2,
PKSDATARANGE pDataRangeIntersection
)
{
// Pick up pDataRange1 values by default.
*pDataRangeIntersection = *pDataRange1;
if(IsEqualGUID(&pDataRange1->MajorFormat, &pDataRange2->MajorFormat) ||
IsEqualGUID(&pDataRange1->MajorFormat, &KSDATAFORMAT_TYPE_WILDCARD)) {
pDataRangeIntersection->MajorFormat = pDataRange2->MajorFormat;
}
else if(!IsEqualGUID(
&pDataRange2->MajorFormat,
&KSDATAFORMAT_TYPE_WILDCARD)) {
return FALSE;
}
if(IsEqualGUID(&pDataRange1->SubFormat, &pDataRange2->SubFormat) ||
IsEqualGUID(&pDataRange1->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD)) {
pDataRangeIntersection->SubFormat = pDataRange2->SubFormat;
}
else if(!IsEqualGUID(
&pDataRange2->SubFormat,
&KSDATAFORMAT_SUBTYPE_WILDCARD)) {
return FALSE;
}
if(IsEqualGUID(&pDataRange1->Specifier, &pDataRange2->Specifier) ||
IsEqualGUID(&pDataRange1->Specifier, &KSDATAFORMAT_SPECIFIER_WILDCARD)) {
pDataRangeIntersection->Specifier = pDataRange2->Specifier;
}
else if(!IsEqualGUID(
&pDataRange2->Specifier,
&KSDATAFORMAT_SPECIFIER_WILDCARD)) {
return FALSE;
}
pDataRangeIntersection->Reserved = 0; // Must be zero
return(TRUE);
}
BOOL
DataIntersectionAudio(
PKSDATARANGE_AUDIO pDataRangeAudio1,
PKSDATARANGE_AUDIO pDataRangeAudio2,
PKSDATARANGE_AUDIO pDataRangeAudioIntersection
)
{
if((IsEqualGUID(
&pDataRangeAudio1->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
IsEqualGUID(
&pDataRangeAudio1->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_DSOUND)) &&
IsEqualGUID(
&pDataRangeAudio2->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_WILDCARD)) {
pDataRangeAudioIntersection->MaximumChannels =
pDataRangeAudio1->MaximumChannels;
pDataRangeAudioIntersection->MaximumSampleFrequency =
pDataRangeAudio1->MaximumSampleFrequency;
pDataRangeAudioIntersection->MinimumSampleFrequency =
pDataRangeAudio1->MinimumSampleFrequency;
pDataRangeAudioIntersection->MaximumBitsPerSample =
pDataRangeAudio1->MaximumBitsPerSample;
pDataRangeAudioIntersection->MinimumBitsPerSample =
pDataRangeAudio1->MinimumBitsPerSample;
return(TRUE);
}
if(IsEqualGUID(
&pDataRangeAudio1->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_WILDCARD) &&
(IsEqualGUID(
&pDataRangeAudio2->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
IsEqualGUID(
&pDataRangeAudio2->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_DSOUND))) {
pDataRangeAudioIntersection->MaximumChannels =
pDataRangeAudio2->MaximumChannels;
pDataRangeAudioIntersection->MaximumSampleFrequency =
pDataRangeAudio2->MaximumSampleFrequency;
pDataRangeAudioIntersection->MinimumSampleFrequency =
pDataRangeAudio2->MinimumSampleFrequency;
pDataRangeAudioIntersection->MaximumBitsPerSample =
pDataRangeAudio2->MaximumBitsPerSample;
pDataRangeAudioIntersection->MinimumBitsPerSample =
pDataRangeAudio2->MinimumBitsPerSample;
return(TRUE);
}
if((IsEqualGUID(
&pDataRangeAudio1->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
IsEqualGUID(
&pDataRangeAudio1->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_DSOUND)) &&
(IsEqualGUID(
&pDataRangeAudio2->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
IsEqualGUID(
&pDataRangeAudio2->DataRange.Specifier,
&KSDATAFORMAT_SPECIFIER_DSOUND))) {
if(pDataRangeAudio1->MaximumChannels <
pDataRangeAudio2->MaximumChannels) {
pDataRangeAudioIntersection->MaximumChannels =
pDataRangeAudio1->MaximumChannels;
}
else {
pDataRangeAudioIntersection->MaximumChannels =
pDataRangeAudio2->MaximumChannels;
}
if(pDataRangeAudio1->MaximumSampleFrequency <
pDataRangeAudio2->MaximumSampleFrequency) {
pDataRangeAudioIntersection->MaximumSampleFrequency =
pDataRangeAudio1->MaximumSampleFrequency;
}
else {
pDataRangeAudioIntersection->MaximumSampleFrequency =
pDataRangeAudio2->MaximumSampleFrequency;
}
if(pDataRangeAudio1->MinimumSampleFrequency >
pDataRangeAudio2->MinimumSampleFrequency) {
pDataRangeAudioIntersection->MinimumSampleFrequency =
pDataRangeAudio1->MinimumSampleFrequency;
}
else {
pDataRangeAudioIntersection->MinimumSampleFrequency =
pDataRangeAudio2->MinimumSampleFrequency;
}
if(pDataRangeAudioIntersection->MaximumSampleFrequency <
pDataRangeAudioIntersection->MinimumSampleFrequency ) {
DPF2(110, "DataIntersectionAudio: SR %08x %08x",
pDataRangeAudio1,
pDataRangeAudio2);
return(FALSE);
}
if(pDataRangeAudio1->MaximumBitsPerSample <
pDataRangeAudio2->MaximumBitsPerSample) {
pDataRangeAudioIntersection->MaximumBitsPerSample =
pDataRangeAudio1->MaximumBitsPerSample;
}
else {
pDataRangeAudioIntersection->MaximumBitsPerSample =
pDataRangeAudio2->MaximumBitsPerSample;
}
if(pDataRangeAudio1->MinimumBitsPerSample >
pDataRangeAudio2->MinimumBitsPerSample) {
pDataRangeAudioIntersection->MinimumBitsPerSample =
pDataRangeAudio1->MinimumBitsPerSample;
}
else {
pDataRangeAudioIntersection->MinimumBitsPerSample =
pDataRangeAudio2->MinimumBitsPerSample;
}
if(pDataRangeAudioIntersection->MaximumBitsPerSample <
pDataRangeAudioIntersection->MinimumBitsPerSample ) {
DPF2(110, "DataIntersectionAudio: BPS %08x %08x",
pDataRangeAudio1,
pDataRangeAudio2);
return(FALSE);
}
return(TRUE);
}
return(FALSE);
}
BOOL
CompareDataRangeExact(
PKSDATARANGE pDataRange1,
PKSDATARANGE pDataRange2
)
{
if(pDataRange1 == NULL || pDataRange2 == NULL) {
Trap();
return(FALSE);
}
ASSERT(pDataRange1->Reserved == pDataRange2->Reserved);
if(pDataRange1->FormatSize == pDataRange2->FormatSize) {
return(!memcmp(pDataRange1, pDataRange2, pDataRange1->FormatSize));
}
return(FALSE);
}
BOOL
CompareDataRangeGuids(
PKSDATARANGE pDataRange1,
PKSDATARANGE pDataRange2
)
{
if(pDataRange1 == NULL || pDataRange2 == NULL) {
Trap();
return(FALSE);
}
if((IsEqualGUID(&pDataRange1->MajorFormat, &pDataRange2->MajorFormat) ||
IsEqualGUID(&pDataRange1->MajorFormat, &KSDATAFORMAT_TYPE_WILDCARD) ||
IsEqualGUID(&pDataRange2->MajorFormat, &KSDATAFORMAT_TYPE_WILDCARD)) &&
(IsEqualGUID(&pDataRange1->SubFormat, &pDataRange2->SubFormat) ||
IsEqualGUID(&pDataRange1->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD) ||
IsEqualGUID(&pDataRange2->SubFormat, &KSDATAFORMAT_SUBTYPE_WILDCARD)) &&
(IsEqualGUID(&pDataRange1->Specifier, &pDataRange2->Specifier) ||
IsEqualGUID(&pDataRange1->Specifier, &KSDATAFORMAT_SPECIFIER_WILDCARD) ||
IsEqualGUID(&pDataRange2->Specifier, &KSDATAFORMAT_SPECIFIER_WILDCARD))) {
return(TRUE);
}
return(FALSE);
}
BOOL
CompareIdentifier(
PKSIDENTIFIER pIdentifier1,
PKSIDENTIFIER pIdentifier2
)
{
if(pIdentifier1 == NULL || pIdentifier2 == NULL) {
Trap();
return(FALSE);
}
if(pIdentifier1 == INTERNAL_WILDCARD ||
pIdentifier2 == INTERNAL_WILDCARD) {
return(TRUE);
}
if(IsEqualGUID(&pIdentifier1->Set, &pIdentifier2->Set) &&
(pIdentifier1->Id == pIdentifier2->Id)) {
return(TRUE);
}
return(FALSE);
}
PWAVEFORMATEXTENSIBLE
GetWaveFormatExtensible(
PKSPIN_CONNECT pPinConnect
)
{
ASSERT(pPinConnect);
PWAVEFORMATEXTENSIBLE pWaveFormatExt = NULL;
PKSDATAFORMAT pDataFormat = (PKSDATAFORMAT) (pPinConnect + 1);
if(IsEqualGUID(&pDataFormat->Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) {
pWaveFormatExt = (PWAVEFORMATEXTENSIBLE)
&PKSDATAFORMAT_WAVEFORMATEX(pDataFormat)->WaveFormatEx;
}
else if(IsEqualGUID(&pDataFormat->Specifier, &KSDATAFORMAT_SPECIFIER_DSOUND)) {
pWaveFormatExt = (PWAVEFORMATEXTENSIBLE)
&PKSDATAFORMAT_DSOUND(pDataFormat)->BufferDesc.WaveFormatEx;
}
else {
DPF(5, "Unknown format specifier");
}
return pWaveFormatExt;
} // GetWaveFormatExtensible
void
ModifyPinConnect(
PKSPIN_CONNECT pPinConnect,
WORD nChannels
)
{
ASSERT(pPinConnect);
PKSDATAFORMAT pDataFormat = (PKSDATAFORMAT) (pPinConnect + 1);
PWAVEFORMATEXTENSIBLE pWaveFormatExt = NULL;
pWaveFormatExt = GetWaveFormatExtensible(pPinConnect);
if (NULL != pWaveFormatExt) {
if (IsEqualGUID(&pDataFormat->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
pWaveFormatExt->Format.nChannels = nChannels;
pWaveFormatExt->Format.nBlockAlign =
(pWaveFormatExt->Format.wBitsPerSample / 8) *
pWaveFormatExt->Format.nChannels;
pWaveFormatExt->Format.nAvgBytesPerSec =
pWaveFormatExt->Format.nSamplesPerSec *
pWaveFormatExt->Format.nBlockAlign;
if (WAVE_FORMAT_EXTENSIBLE == pWaveFormatExt->Format.wFormatTag) {
if (1 == nChannels) {
pWaveFormatExt->dwChannelMask = SPEAKER_FRONT_CENTER;
}
else if (2 == nChannels) {
pWaveFormatExt->dwChannelMask =
SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
}
}
}
else {
DPF(5, "ModifyPinConnect : Not touching NON-PCM formats.");
}
}
} // ModifyPinConnect
NTSTATUS
OpenDevice(
PWSTR pwstrDevice,
PHANDLE pHandle
)
{
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING UnicodeDeviceString;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString(&UnicodeDeviceString, pwstrDevice);
InitializeObjectAttributes(
&ObjectAttributes,
&UnicodeDeviceString,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
return(ZwCreateFile(pHandle,
GENERIC_READ | GENERIC_WRITE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
0,
NULL,
0));
}
NTSTATUS
GetPinProperty(
PFILE_OBJECT pFileObject,
ULONG PropertyId,
ULONG PinId,
ULONG cbProperty,
PVOID pProperty
)
{
ULONG BytesReturned;
KSP_PIN Pin;
NTSTATUS Status;
Pin.Property.Set = KSPROPSETID_Pin;
Pin.Property.Id = PropertyId;
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
Pin.PinId = PinId;
Pin.Reserved = 0;
AssertFileObject(pFileObject);
Status = KsSynchronousIoControlDevice(
pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
&Pin,
sizeof(Pin),
pProperty,
cbProperty,
&BytesReturned);
if(!NT_SUCCESS(Status)) {
DPF2(10,
"GetPinProperty: id %d p %d KsSynchronousIoControlDevice FAILED",
PropertyId,
PinId);
goto exit;
}
ASSERT(BytesReturned == cbProperty);
exit:
return(Status);
}
NTSTATUS
PinConnectionProperty(
PFILE_OBJECT pFileObject,
ULONG ulPropertyId,
ULONG ulFlags,
ULONG cbProperty,
PVOID pProperty
)
{
KSIDENTIFIER Property;
ULONG BytesReturned;
NTSTATUS Status;
Property.Set = KSPROPSETID_Connection;
Property.Id = ulPropertyId;
Property.Flags = ulFlags;
AssertFileObject(pFileObject);
Status = KsSynchronousIoControlDevice(
pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
&Property,
sizeof(Property),
pProperty,
cbProperty,
&BytesReturned);
if(!NT_SUCCESS(Status)) {
DPF(10, "SetPinConnectionProperty: KsSynchronousIoControlDevice Failed");
goto exit;
}
exit:
return(Status);
}
NTSTATUS
GetPinPropertyEx(
PFILE_OBJECT pFileObject,
ULONG PropertyId,
ULONG PinId,
PVOID *ppProperty
)
{
ULONG BytesReturned;
NTSTATUS Status;
KSP_PIN Pin;
Pin.Property.Set = KSPROPSETID_Pin;
Pin.Property.Id = PropertyId;
Pin.Property.Flags = KSPROPERTY_TYPE_GET;
Pin.PinId = PinId;
Pin.Reserved = 0;
AssertFileObject(pFileObject);
Status = KsSynchronousIoControlDevice(
pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
&Pin,
sizeof(KSP_PIN),
NULL,
0,
&BytesReturned);
ASSERT(!NT_SUCCESS(Status));
if(Status != STATUS_BUFFER_OVERFLOW) {
goto exit;
}
if(BytesReturned == 0) {
*ppProperty = NULL;
Status = STATUS_SUCCESS;
goto exit;
}
*ppProperty = new BYTE[BytesReturned];
if(*ppProperty == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
AssertFileObject(pFileObject);
Status = KsSynchronousIoControlDevice(
pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
&Pin,
sizeof(KSP_PIN),
*ppProperty,
BytesReturned,
&BytesReturned);
if(!NT_SUCCESS(Status)) {
Trap();
delete *ppProperty;
*ppProperty = NULL;
goto exit;
}
exit:
if(Status == STATUS_PROPSET_NOT_FOUND ||
Status == STATUS_NOT_FOUND) {
Status = STATUS_SUCCESS;
*ppProperty = NULL;
}
return(Status);
}
NTSTATUS
GetPinProperty2(
PFILE_OBJECT pFileObject,
ULONG ulPropertyId,
ULONG ulPinId,
ULONG cbInput,
PVOID pInputData,
PVOID *ppPropertyOutput
)
{
ULONG cbPropertyInput = sizeof(KSP_PIN);
ULONG BytesReturned;
NTSTATUS Status;
PKSP_PIN pPin;
cbPropertyInput += cbInput;
pPin = (PKSP_PIN)new BYTE[cbPropertyInput];
if(pPin == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
pPin->Property.Set = KSPROPSETID_Pin;
pPin->Property.Id = ulPropertyId;
pPin->Property.Flags = KSPROPERTY_TYPE_GET;
pPin->PinId = ulPinId;
pPin->Reserved = 0;
if(pInputData != NULL) {
memcpy(pPin + 1, pInputData, cbInput);
}
AssertFileObject(pFileObject);
Status = KsSynchronousIoControlDevice(
pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
pPin,
cbPropertyInput,
NULL,
0,
&BytesReturned);
ASSERT(!NT_SUCCESS(Status));
if(Status != STATUS_BUFFER_OVERFLOW) {
DPF(10, "GetPinProperty2: KsSynchronousIoControlDevice 1 Failed");
goto exit;
}
if(BytesReturned == 0) {
*ppPropertyOutput = NULL;
Status = STATUS_SUCCESS;
goto exit;
}
*ppPropertyOutput = new BYTE[BytesReturned];
if(*ppPropertyOutput == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
AssertFileObject(pFileObject);
Status = KsSynchronousIoControlDevice(
pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
pPin,
cbPropertyInput,
*ppPropertyOutput,
BytesReturned,
&BytesReturned);
if(!NT_SUCCESS(Status)) {
DPF(10, "GetPinProperty2: KsSynchronousIoControlDevice 2 Failed");
delete *ppPropertyOutput;
goto exit;
}
exit:
delete [] pPin;
if(!NT_SUCCESS(Status)) {
*ppPropertyOutput = NULL;
if(Status == STATUS_PROPSET_NOT_FOUND ||
Status == STATUS_NOT_FOUND) {
Status = STATUS_SUCCESS;
}
}
return(Status);
}
NTSTATUS
GetProperty(
PFILE_OBJECT pFileObject,
CONST GUID *pguidPropertySet,
ULONG ulPropertyId,
ULONG cbInput,
PVOID pInputData,
PVOID *ppPropertyOutput
)
{
ULONG BytesReturned;
ULONG cbPropertyInput = sizeof(KSPROPERTY);
PKSPROPERTY pPropertyInput;
NTSTATUS Status;
cbPropertyInput += cbInput;
pPropertyInput = (PKSPROPERTY)new BYTE[cbPropertyInput];
if(pPropertyInput == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
pPropertyInput->Set = *pguidPropertySet;
pPropertyInput->Id = ulPropertyId;
pPropertyInput->Flags = KSPROPERTY_TYPE_GET;
if(pInputData != NULL) {
Trap();
memcpy(pPropertyInput + 1, pInputData, cbInput);
}
AssertFileObject(pFileObject);
Status = KsSynchronousIoControlDevice(
pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
pPropertyInput,
cbPropertyInput,
NULL,
0,
&BytesReturned);
ASSERT(!NT_SUCCESS(Status));
if(Status != STATUS_BUFFER_OVERFLOW) {
DPF(10, "GetProperty: KsSynchronousIoControlDevice 1 Failed");
goto exit;
}
if(BytesReturned == 0) {
*ppPropertyOutput = NULL;
Status = STATUS_SUCCESS;
goto exit;
}
*ppPropertyOutput = new BYTE[BytesReturned];
if(*ppPropertyOutput == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
AssertFileObject(pFileObject);
Status = KsSynchronousIoControlDevice(
pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
pPropertyInput,
cbPropertyInput,
*ppPropertyOutput,
BytesReturned,
&BytesReturned);
if(!NT_SUCCESS(Status)) {
DPF(10, "GetProperty: KsSynchronousIoControlDevice 2 Failed");
delete *ppPropertyOutput;
goto exit;
}
exit:
delete [] pPropertyInput;
if(!NT_SUCCESS(Status)) {
*ppPropertyOutput = NULL;
if(Status == STATUS_PROPSET_NOT_FOUND ||
Status == STATUS_NOT_FOUND) {
Status = STATUS_SUCCESS;
}
}
return(Status);
}
CQueueWorkListData::CQueueWorkListData(
NTSTATUS (*Function)(PVOID Reference1, PVOID Reference2),
PVOID Reference1,
PVOID Reference2
)
{
this->Function = Function;
this->Reference1 = Reference1;
this->Reference2 = Reference2;
}
NTSTATUS
CQueueWorkListData::QueueAsyncList(
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
ExInterlockedInsertTailList(
&glehQueueWorkList,
&leNext,
&gSpinLockQueueWorkList);
// Schedule the workitem, if it is not already running.
//
if(InterlockedIncrement(&gcQueueWorkList) == 1) {
ntStatus = KsQueueWorkItem(gWorkerObject, &gWorkItem);
}
return ntStatus;
}
VOID
CQueueWorkListData::AsyncWorker(
IN OUT PVOID pReference
)
{
PQUEUE_WORK_LIST_DATA pQueueWorkListData;
PLIST_ENTRY ple;
::GrabMutex();
while(
(ple = ExInterlockedRemoveHeadList(
&glehQueueWorkList,
&gSpinLockQueueWorkList)) != NULL) {
pQueueWorkListData =
CONTAINING_RECORD(ple, QUEUE_WORK_LIST_DATA, leNext);
Assert(pQueueWorkListData);
(*pQueueWorkListData->Function)
(pQueueWorkListData->Reference1,
pQueueWorkListData->Reference2);
delete pQueueWorkListData;
if(InterlockedDecrement(&gcQueueWorkList) == 0) {
break;
}
}
::ReleaseMutex();
}
NTSTATUS
QueueWorkList(
NTSTATUS (*Function)(PVOID Reference1, PVOID Reference2),
PVOID Reference1,
PVOID Reference2
)
{
NTSTATUS Status = STATUS_SUCCESS;
PQUEUE_WORK_LIST_DATA pQueueWorkListData = NULL;
pQueueWorkListData = new QUEUE_WORK_LIST_DATA(
Function,
Reference1,
Reference2);
if(pQueueWorkListData == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
Status = pQueueWorkListData->QueueAsyncList();
exit:
return(Status);
}
VOID
GetDefaultOrder(
ULONG fulType,
PULONG pulOrder
)
{
if(fulType != 0) {
if(*pulOrder == ORDER_NONE) {
if(fulType & FILTER_TYPE_ENDPOINT) {
*pulOrder = ORDER_ENDPOINT;
return;
}
if(fulType & FILTER_TYPE_VIRTUAL) {
*pulOrder = ORDER_VIRTUAL;
return;
}
if(fulType & FILTER_TYPE_GFX) {
*pulOrder = ORDER_GFX;
return;
}
if(fulType & FILTER_TYPE_INTERFACE_TRANSFORM) {
*pulOrder = ORDER_INTERFACE_TRANSFORM;
return;
}
if(fulType & FILTER_TYPE_AEC) {
*pulOrder = ORDER_AEC;
return;
}
if(fulType & FILTER_TYPE_MIC_ARRAY_PROCESSOR) {
*pulOrder = ORDER_MIC_ARRAY_PROCESSOR;
return;
}
if(fulType & FILTER_TYPE_SPLITTER) {
*pulOrder = ORDER_SPLITTER;
return;
}
if(fulType & FILTER_TYPE_MIXER) {
*pulOrder = ORDER_MIXER;
return;
}
if(fulType & FILTER_TYPE_SYNTHESIZER) {
*pulOrder = ORDER_SYNTHESIZER;
return;
}
if(fulType & FILTER_TYPE_DRM_DESCRAMBLE) {
*pulOrder = ORDER_DRM_DESCRAMBLE;
return;
}
if(fulType & FILTER_TYPE_DATA_TRANSFORM) {
*pulOrder = ORDER_DATA_TRANSFORM;
return;
}
}
}
}
//===========================================================================
// ISSUE-2001/03/06-alpers
// This is a temporary solution for GFX glitching problem.
// In BlackComb time-frame after the right fix is implemented, we should delete
// this definition and references to it.
//
#define STATIC_KSPROPSETID_Frame\
0xA60D8368L, 0x5324, 0x4893, 0xB0, 0x20, 0xC4, 0x31, 0xA5, 0x0B, 0xCB, 0xE3
DEFINE_GUIDSTRUCT("A60D8368-5324-4893-B020-C431A50BCBE3", KSPROPSETID_Frame);
#define KSPROPSETID_Frame DEFINE_GUIDNAMED(KSPROPSETID_Frame)
typedef enum {
KSPROPERTY_FRAME_HOLDING
} KSPROPERTY_FRAME;
//===========================================================================
NTSTATUS
SetKsFrameHolding(
PFILE_OBJECT pFileObject
)
{
KSPROPERTY Property;
NTSTATUS ntStatus;
ULONG ulBytesReturned;
BOOL fFrameEnable = TRUE;
ASSERT(pFileObject);
//
// Form the IOCTL packet & send it down
//
Property.Set = KSPROPSETID_Frame;
Property.Id = KSPROPERTY_FRAME_HOLDING;
Property.Flags = KSPROPERTY_TYPE_SET;
DPF(60,"Sending KSPROPERTY_FRAME_HOLDING");
//
// We actually throw away the status we got back from the device.
//
ntStatus = KsSynchronousIoControlDevice(pFileObject,
KernelMode,
IOCTL_KS_PROPERTY,
&Property,
sizeof(Property),
&fFrameEnable,
sizeof(fFrameEnable),
&ulBytesReturned);
DPF1(60,"KSPROPERTY_FRAME_HOLDING %s",
(NT_SUCCESS(ntStatus)) ? "Succeeded" : "Failed");
return ntStatus;
} // SetKsFrameHolding
//---------------------------------------------------------------------------
#pragma LOCKED_CODE
//
// Zero initializes the block.
//
void * __cdecl operator new( size_t size )
{
PVOID p;
ASSERT(size != 0);
ASSERT(size < 0x10000);
#if defined(USE_ZONES) || defined(DEBUG)
size += sizeof(ULONGLONG);
#endif
#ifdef MEMORY_LIST
size += sizeof(LIST_ENTRY);
#endif
#ifdef USE_ZONES
if(size <= SMALL_BLOCK_SIZE) {
if(ExIsFullZone(&gZone)) {
p = ExAllocatePoolWithTag(PagedPool, 4096, 0x41535953); // SYSA
if(p != NULL) {
if(!NT_SUCCESS(ExExtendZone(&gZone, p, 4096))) {
Trap();
ExFreePool(p);
DPF(5, "ExExtendZone FAILED");
return(NULL);
}
}
}
p = ExAllocateFromZone(&gZone);
}
else {
p = ExAllocatePoolWithTag(PagedPool, size, 0x41535953); // SYSA
}
#else
p = ExAllocatePoolWithTag(PagedPool, size, 0x41535953); // SYSA
#endif
if(p != NULL) {
RtlZeroMemory(p, size);
#if defined(USE_ZONES) || defined(DEBUG)
*((PULONG)p) = size;
p = ((PULONGLONG)p) + 1;
#endif
#ifdef MEMORY_LIST
ExInterlockedInsertTailList(
&gleMemoryHead,
((PLIST_ENTRY)p),
&gSpinLockMemoryHead);
p = ((PLIST_ENTRY)p) + 1;
#endif
#ifdef DEBUG
cbMemoryUsage += size;
++cAllocMem;
if(size <= SMALL_BLOCK_SIZE) {
++cAllocMemSmall;
}
else if(size <= 64) {
++cAllocMem64;
}
else if(size <= 128) {
++cAllocMem128;
}
#endif
}
AssertAligned(p);
return(p);
}
//
// Frees memory
//
void __cdecl operator delete( void *p )
{
if(p != NULL) {
#ifdef MEMORY_LIST
KIRQL OldIrql;
p = ((PLIST_ENTRY)p) - 1;
KeAcquireSpinLock(&gSpinLockMemoryHead, &OldIrql);
RemoveEntryList((PLIST_ENTRY)p);
KeReleaseSpinLock(&gSpinLockMemoryHead, OldIrql);
#endif
#if defined(USE_ZONES) || defined(DEBUG)
ULONG size;
AssertAligned(p);
p = ((PULONGLONG)p) - 1;
size = *((PULONG)p);
#endif
#ifdef DEBUG
cbMemoryUsage -= size;
--cAllocMem;
if(size <= SMALL_BLOCK_SIZE) {
--cAllocMemSmall;
}
else if(size <= 64) {
--cAllocMem64;
}
else if(size <= 128) {
--cAllocMem128;
}
#endif
#ifdef USE_ZONES
if(size <= SMALL_BLOCK_SIZE) {
ExFreeToZone(&gZone, p);
}
else {
ExFreePool(p);
}
#else
ExFreePool(p);
#endif
}
}
#pragma PAGEABLE_CODE
//---------------------------------------------------------------------------
#ifdef DEBUG
VOID
DumpPinConnect(
LONG Level,
PKSPIN_CONNECT pPinConnect
)
{
DPF1(Level, " PinId: %d", pPinConnect->PinId);
DPF1(Level, "Interface: %s", DbgIdentifier2Sz(&pPinConnect->Interface));
DPF1(Level, " Medium: %s", DbgIdentifier2Sz(&pPinConnect->Medium));
DumpDataFormat(Level, ((PKSDATAFORMAT)(pPinConnect + 1)));
}
VOID
DumpDataFormat(
LONG Level,
PKSDATAFORMAT pDataFormat
)
{
DPF2(Level,
" FormatSize: %02x Flags: %08x",
pDataFormat->FormatSize,
pDataFormat->Flags);
DPF2(Level,
" SampleSize: %02x Reserved: %08x",
pDataFormat->SampleSize,
pDataFormat->Reserved);
DPF1(Level, "MajorFormat: %s", DbgGuid2Sz(&pDataFormat->MajorFormat));
DPF1(Level, " SubFormat: %s", DbgGuid2Sz(&pDataFormat->SubFormat));
DPF1(Level, " Specifier: %s", DbgGuid2Sz(&pDataFormat->Specifier));
if(IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,
&pDataFormat->Specifier)) {
DumpWaveFormatEx(
Level,
"WaveFmtEx",
&((PKSDATAFORMAT_WAVEFORMATEX)pDataFormat)->WaveFormatEx);
}
if(IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_DSOUND,
&pDataFormat->Specifier)) {
DumpWaveFormatEx(
Level,
"DSOUND",
&((PKSDATAFORMAT_DSOUND)pDataFormat)->BufferDesc.WaveFormatEx);
}
}
VOID
DumpWaveFormatEx(
LONG Level,
PSZ pszSpecifier,
WAVEFORMATEX *pWaveFormatEx
)
{
DPF8(Level, "%s T %u SR %u CH %u BPS %u ABPS %u BA %u cb %u",
pszSpecifier,
pWaveFormatEx->wFormatTag,
pWaveFormatEx->nSamplesPerSec,
pWaveFormatEx->nChannels,
pWaveFormatEx->wBitsPerSample,
pWaveFormatEx->nAvgBytesPerSec,
pWaveFormatEx->nBlockAlign,
pWaveFormatEx->cbSize);
if(pWaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
DPF3(Level, "VBPS %u CHMASK %08x %s",
((PWAVEFORMATEXTENSIBLE)pWaveFormatEx)->Samples.wValidBitsPerSample,
((PWAVEFORMATEXTENSIBLE)pWaveFormatEx)->dwChannelMask,
DbgGuid2Sz(&((PWAVEFORMATEXTENSIBLE)pWaveFormatEx)->SubFormat));
}
}
VOID
DumpDataRange(
LONG Level,
PKSDATARANGE_AUDIO pDataRangeAudio
)
{
DPF2(Level,
" FormatSize: %02x Flags: %08x",
pDataRangeAudio->DataRange.FormatSize,
pDataRangeAudio->DataRange.Flags);
DPF2(Level,
" SampleSize: %02x Reserved: %08x",
pDataRangeAudio->DataRange.SampleSize,
pDataRangeAudio->DataRange.Reserved);
DPF1(Level, "MajorFormat: %s",
DbgGuid2Sz(&pDataRangeAudio->DataRange.MajorFormat));
DPF1(Level, " SubFormat: %s",
DbgGuid2Sz(&pDataRangeAudio->DataRange.SubFormat));
DPF1(Level, " Specifier: %s",
DbgGuid2Sz(&pDataRangeAudio->DataRange.Specifier));
if(IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,
&pDataRangeAudio->DataRange.Specifier)) {
DPF5(Level, "WaveFmtEx: MaxCH %d MaxSR %u MinSR %u MaxBPS %u MinBPS %u",
pDataRangeAudio->MaximumChannels,
pDataRangeAudio->MinimumSampleFrequency,
pDataRangeAudio->MaximumSampleFrequency,
pDataRangeAudio->MinimumBitsPerSample,
pDataRangeAudio->MaximumBitsPerSample);
}
if(IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_DSOUND,
&pDataRangeAudio->DataRange.Specifier)) {
DPF5(Level, "DSOUND: MaxCH %d MaxSR %u MinSR %u MaxBPS %u MinBPS %u",
pDataRangeAudio->MaximumChannels,
pDataRangeAudio->MinimumSampleFrequency,
pDataRangeAudio->MaximumSampleFrequency,
pDataRangeAudio->MinimumBitsPerSample,
pDataRangeAudio->MaximumBitsPerSample);
}
}
VOID
DumpDataRangeAudio(
PKSDATARANGE_AUDIO pDataRangeAudio
)
{
if(IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_DSOUND,
&pDataRangeAudio->DataRange.Specifier) ||
IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,
&pDataRangeAudio->DataRange.Specifier)) {
dprintf(" MaxCH %d MaxSR %u MinSR %u MaxBPS %u MinBPS %u\n",
pDataRangeAudio->MaximumChannels,
pDataRangeAudio->MaximumSampleFrequency,
pDataRangeAudio->MinimumSampleFrequency,
pDataRangeAudio->MaximumBitsPerSample,
pDataRangeAudio->MinimumBitsPerSample);
}
}
VOID
DumpfulType(
ULONG fulType
)
{
if(fulType & FILTER_TYPE_AUDIO) {
dprintf("AUDIO ");
}
if(fulType & FILTER_TYPE_GFX) {
dprintf("GFX ");
}
if(fulType & FILTER_TYPE_TOPOLOGY) {
dprintf("TOPOLOGY ");
}
if(fulType & FILTER_TYPE_BRIDGE) {
dprintf("BRIDGE ");
}
if(fulType & FILTER_TYPE_RENDERER) {
dprintf("RENDERER ");
}
if(fulType & FILTER_TYPE_CAPTURER) {
dprintf("CAPTURER ");
}
if(fulType & FILTER_TYPE_MIXER) {
dprintf("MIXER ");
}
if(fulType & FILTER_TYPE_SPLITTER) {
dprintf("SPLITTER ");
}
if(fulType & FILTER_TYPE_SYNTHESIZER) {
dprintf("SYNTHESIZER ");
}
if(fulType & FILTER_TYPE_DRM_DESCRAMBLE) {
dprintf("DRM_DESCRAMBLE ");
}
if(fulType & FILTER_TYPE_DATA_TRANSFORM) {
dprintf("DATA_TRANSFORM ");
}
if(fulType & FILTER_TYPE_AEC) {
dprintf("AEC ");
}
if(fulType & FILTER_TYPE_MIC_ARRAY_PROCESSOR) {
dprintf("MIC_ARRAY_PROCESSOR ");
}
if(fulType & FILTER_TYPE_COMMUNICATION_TRANSFORM) {
dprintf("COMMUNICATION_TRANSFORM ");
}
if(fulType & FILTER_TYPE_INTERFACE_TRANSFORM) {
dprintf("INTERFACE_TRANSFORM ");
}
if(fulType & FILTER_TYPE_MEDIUM_TRANSFORM) {
dprintf("MEDIUM_TRANSFORM ");
}
if(fulType & FILTER_TYPE_VIRTUAL) {
dprintf("VIRTUAL ");
}
}
ENUMFUNC
DumpListData(
PVOID pData
)
{
dprintf(" %08x", pData);
return(STATUS_CONTINUE);
}
PSZ
DbgUnicode2Sz(
PWSTR pwstr
)
{
static char sz[256];
UNICODE_STRING UnicodeString;
ANSI_STRING AnsiString;
sz[0] = '\0';
if(pwstr != NULL) {
RtlInitUnicodeString(&UnicodeString, pwstr);
RtlInitAnsiString(&AnsiString, sz);
AnsiString.MaximumLength = sizeof(sz);
RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
}
return(sz);
}
PSZ
DbgIdentifier2Sz(
PKSIDENTIFIER pIdentifier
)
{
static char sz[256];
sz[0] = '\0';
if(pIdentifier != NULL && pIdentifier != INTERNAL_WILDCARD) {
if(IsEqualGUID(
&KSMEDIUMSETID_Standard,
&pIdentifier->Set) &&
(pIdentifier->Id == KSMEDIUM_STANDARD_DEVIO)) {
return("KSMEDIUM_STANDARD_DEVIO");
}
if(IsEqualGUID(
&KSINTERFACESETID_Standard,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSINTERFACE_STANDARD_STREAMING:
return("KSINTERFACE_STANDARD_STREAMING");
case KSINTERFACE_STANDARD_LOOPED_STREAMING:
return("KSINTERFACE_STANDARD_LOOPED_STREAMING");
case KSINTERFACE_STANDARD_CONTROL:
return("KSINTERFACE_STANDARD_CONTROL");
}
}
if(IsEqualGUID(
&KSINTERFACESETID_Media,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSINTERFACE_MEDIA_MUSIC:
return("KSINTERFACE_MEDIA_MUSIC");
case KSINTERFACE_MEDIA_WAVE_BUFFERED:
return("KSINTERFACE_MEDIA_WAVE_BUFFERED");
case KSINTERFACE_MEDIA_WAVE_QUEUED:
return("KSINTERFACE_MEDIA_WAVE_QUEUED");
}
}
if(IsEqualGUID(
&KSPROPSETID_Pin,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSPROPERTY_PIN_CINSTANCES:
return("KSPROPERTY_PIN_CINSTANCES");
case KSPROPERTY_PIN_CTYPES:
return("KSPROPERTY_PIN_CTYPES");
case KSPROPERTY_PIN_DATAFLOW:
return("KSPROPERTY_PIN_DATAFLOW");
case KSPROPERTY_PIN_DATARANGES:
return("KSPROPERTY_PIN_DATARANGES");
case KSPROPERTY_PIN_DATAINTERSECTION:
return("KSPROPERTY_PIN_DATAINTERSECTION");
case KSPROPERTY_PIN_INTERFACES:
return("KSPROPERTY_PIN_INTERFACES");
case KSPROPERTY_PIN_MEDIUMS:
return("KSPROPERTY_PIN_MEDIUMS");
case KSPROPERTY_PIN_COMMUNICATION:
return("KSPROPERTY_PIN_COMMUNICATION");
case KSPROPERTY_PIN_GLOBALCINSTANCES:
return("KSPROPERTY_PIN_GLOBALCINSTANCES");
case KSPROPERTY_PIN_NECESSARYINSTANCES:
return("KSPROPERTY_PIN_NECESSARYINSTANCES");
case KSPROPERTY_PIN_PHYSICALCONNECTION:
return("KSPROPERTY_PIN_PHYSICALCONNECTION");
case KSPROPERTY_PIN_CATEGORY:
return("KSPROPERTY_PIN_CATEGORY");
case KSPROPERTY_PIN_NAME:
return("KSPROPERTY_PIN_NAME");
case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
return("KSPROPERTY_PIN_CONSTRAINEDDATARANGES");
}
}
if(IsEqualGUID(
&KSPROPSETID_Connection,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSPROPERTY_CONNECTION_STATE:
return("KSPROPERTY_CONNECTION_STATE");
case KSPROPERTY_CONNECTION_PRIORITY:
return("KSPROPERTY_CONNECTION_PRIORITY");
case KSPROPERTY_CONNECTION_DATAFORMAT:
return("KSPROPERTY_CONNECTION_DATAFORMAT");
case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
return("KSPROPERTY_CONNECTION_ALLOCATORFRAMING");
case KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT:
return("KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT");
case KSPROPERTY_CONNECTION_ACQUIREORDERING:
return("KSPROPERTY_CONNECTION_ACQUIREORDERING");
case KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX:
return("KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX");
}
}
if(IsEqualGUID(
&KSPROPSETID_Stream,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSPROPERTY_STREAM_ALLOCATOR:
return("KSPROPERTY_STREAM_ALLOCATOR");
case KSPROPERTY_STREAM_MASTERCLOCK:
return("KSPROPERTY_STREAM_MASTERCLOCK");
}
sprintf(sz, "KSPROPSETID_Stream Id: %02x", pIdentifier->Id);
return(sz);
}
if(IsEqualGUID(
&KSPROPSETID_Clock,
&pIdentifier->Set)) {
sprintf(sz, "KSPROPSETID_Clock Id: %02x", pIdentifier->Id);
return(sz);
}
if(IsEqualGUID(
&KSPROPSETID_StreamAllocator,
&pIdentifier->Set)) {
sprintf(sz, "KSPROPSETID_StreamAllocator Id: %02x",
pIdentifier->Id);
return(sz);
}
if(IsEqualGUID(
&KSPROPSETID_StreamInterface,
&pIdentifier->Set)) {
sprintf(sz, "KSPROPSETID_StreamInterface Id: %02x",
pIdentifier->Id);
return(sz);
}
if(IsEqualGUID(
&KSPROPSETID_Topology,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSPROPERTY_TOPOLOGY_CATEGORIES:
return("KSPROPERTY_TOPOLOGY_CATEGORIES");
case KSPROPERTY_TOPOLOGY_NODES:
return("KSPROPERTY_TOPOLOGY_NODES");
case KSPROPERTY_TOPOLOGY_CONNECTIONS:
return("KSPROPERTY_TOPOLOGY_CONNECTIONS");
case KSPROPERTY_TOPOLOGY_NAME:
return("KSPROPERTY_TOPOLOGY_NAME");
default:
sprintf(sz, "KSPROPSETID_Topology Id: %02x",
pIdentifier->Id);
return(sz);
}
}
if(IsEqualGUID(
&KSPROPSETID_Audio,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSPROPERTY_AUDIO_VOLUMELEVEL:
return("KSPROPERTY_AUDIO_VOLUMELEVEL");
case KSPROPERTY_AUDIO_MUTE:
return("KSPROPERTY_AUDIO_MUTE");
case KSPROPERTY_AUDIO_MIX_LEVEL_TABLE:
return("KSPROPERTY_AUDIO_MIX_LEVEL_TABLE");
case KSPROPERTY_AUDIO_MIX_LEVEL_CAPS:
return("KSPROPERTY_AUDIO_MIX_LEVEL_CAPS");
case KSPROPERTY_AUDIO_MUX_SOURCE:
return("KSPROPERTY_AUDIO_MUX_SOURCE");
case KSPROPERTY_AUDIO_BASS:
return("KSPROPERTY_AUDIO_BASS");
case KSPROPERTY_AUDIO_MID:
return("KSPROPERTY_AUDIO_MID");
case KSPROPERTY_AUDIO_TREBLE:
return("KSPROPERTY_AUDIO_TREBLE");
case KSPROPERTY_AUDIO_BASS_BOOST:
return("KSPROPERTY_AUDIO_BASS_BOOST");
case KSPROPERTY_AUDIO_AGC:
return("KSPROPERTY_AUDIO_AGC");
default:
sprintf(sz, "KSPROPSETID_Audio Id: %02x", pIdentifier->Id);
return(sz);
}
}
if(IsEqualGUID(
&KSPROPSETID_Sysaudio,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSPROPERTY_SYSAUDIO_DEVICE_COUNT:
return("KSPROPERTY_SYSAUDIO_DEVICE_COUNT");
case KSPROPERTY_SYSAUDIO_DEVICE_FRIENDLY_NAME:
return("KSPROPERTY_SYSAUDIO_DEVICE_FRIENDLY_NAME");
case KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE:
return("KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE");
case KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME:
return("KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME");
case KSPROPERTY_SYSAUDIO_SELECT_GRAPH:
return("KSPROPERTY_SYSAUDIO_SELECT_GRAPH");
case KSPROPERTY_SYSAUDIO_CREATE_VIRTUAL_SOURCE:
return("KSPROPERTY_SYSAUDIO_CREATE_VIRTUAL_SOURCE");
case KSPROPERTY_SYSAUDIO_DEVICE_DEFAULT:
return("KSPROPERTY_SYSAUDIO_DEVICE_DEFAULT");
case KSPROPERTY_SYSAUDIO_ALWAYS_CREATE_VIRTUAL_SOURCE:
return("KSPROPERTY_SYSAUDIO_ALWAYS_CREATE_VIRTUAL_SOURCE");
case KSPROPERTY_SYSAUDIO_ADDREMOVE_LOCK:
return("KSPROPERTY_SYSAUDIO_ADDREMOVE_LOCK");
case KSPROPERTY_SYSAUDIO_ADDREMOVE_UNLOCK:
return("KSPROPERTY_SYSAUDIO_ADDREMOVE_UNLOCK");
case KSPROPERTY_SYSAUDIO_RENDER_PIN_INSTANCES:
return("KSPROPERTY_SYSAUDIO_RENDER_PIN_INSTANCES");
case KSPROPERTY_SYSAUDIO_RENDER_CONNECTION_INDEX:
return("KSPROPERTY_SYSAUDIO_RENDER_CONNECTION_INDEX");
default:
sprintf(sz, "KSPROPSETID_Sysaudio Id: %02x",
pIdentifier->Id);
return(sz);
}
}
if(IsEqualGUID(
&KSEVENTSETID_Connection,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSEVENT_CONNECTION_POSITIONUPDATE:
return("KSEVENT_CONNECTION_POSITIONUPDATE");
case KSEVENT_CONNECTION_DATADISCONTINUITY:
return("KSEVENT_CONNECTION_DATADISCONTINUITY");
case KSEVENT_CONNECTION_TIMEDISCONTINUITY:
return("KSEVENT_CONNECTION_TIMEDISCONTINUITY");
case KSEVENT_CONNECTION_PRIORITY:
return("KSEVENT_CONNECTION_PRIORITY");
case KSEVENT_CONNECTION_ENDOFSTREAM:
return("KSEVENT_CONNECTION_ENDOFSTREAM");
}
}
if(IsEqualGUID(
&KSEVENTSETID_Clock,
&pIdentifier->Set)) {
switch(pIdentifier->Id) {
case KSEVENT_CLOCK_INTERVAL_MARK:
return("KSEVENT_CLOCK_INTERVAL_MARK");
case KSEVENT_CLOCK_POSITION_MARK:
return("KSEVENT_CLOCK_POSITION_MARK");
}
}
if(IsEqualGUID(
&GUID_NULL,
&pIdentifier->Set)) {
sprintf(sz, "GUID_NULL Id: %02x", pIdentifier->Id);
return(sz);
}
sprintf(sz, "Set: %s Id: %02x",
DbgGuid2Sz(&pIdentifier->Set),
pIdentifier->Id);
}
else {
sprintf(sz, "%08x", (ULONG_PTR)pIdentifier);
}
return(sz);
}
PSZ
DbgGuid2Sz(
GUID *pGuid
)
{
static char sz[256];
if(pGuid == NULL) {
return("NO GUID");
}
if(IsEqualGUID(
&GUID_NULL,
pGuid)) {
return("GUID_NULL");
}
if(IsEqualGUID(
&KSDATAFORMAT_TYPE_AUDIO,
pGuid)) {
return("KSDATAFORMAT_TYPE_AUDIO");
}
if(IsEqualGUID(
&KSDATAFORMAT_SUBTYPE_ANALOG,
pGuid)) {
return("KSDATAFORMAT_SUBTYPE_ANALOG");
}
if(IsEqualGUID(
&KSDATAFORMAT_SUBTYPE_PCM,
pGuid)) {
return("KSDATAFORMAT_SUBTYPE_PCM");
}
if(IsEqualGUID(
&KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
pGuid)) {
return("KSDATAFORMAT_SUBTYPE_IEEE_FLOAT");
}
if(IsEqualGUID(
&KSDATAFORMAT_TYPE_MUSIC,
pGuid)) {
return("KSDATAFORMAT_TYPE_MUSIC");
}
if(IsEqualGUID(
&KSDATAFORMAT_SUBTYPE_MIDI,
pGuid)) {
return("KSDATAFORMAT_SUBTYPE_MIDI");
}
if(IsEqualGUID(
&KSDATAFORMAT_SUBTYPE_MIDI_BUS,
pGuid)) {
return("KSDATAFORMAT_SUBTYPE_MIDI_BUS");
}
if(IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_DSOUND,
pGuid)) {
return("KSDATAFORMAT_SPECIFIER_DSOUND");
}
if(IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_WAVEFORMATEX,
pGuid)) {
return("KSDATAFORMAT_SPECIFIER_WAVEFORMATEX");
}
if(IsEqualGUID(
&KSDATAFORMAT_SPECIFIER_NONE,
pGuid)) {
return("KSDATAFORMAT_SPECIFIER_NONE");
}
if(IsEqualGUID(
&KSCATEGORY_AUDIO,
pGuid)) {
return("KSCATEGORY_AUDIO");
}
if(IsEqualGUID(
&KSNODETYPE_SPEAKER,
pGuid)) {
return("KSNODETYPE_SPEAKER");
}
if(IsEqualGUID(
&KSNODETYPE_MICROPHONE,
pGuid)) {
return("KSNODETYPE_MICROPHONE");
}
if(IsEqualGUID(
&KSNODETYPE_CD_PLAYER,
pGuid)) {
return("KSNODETYPE_CD_PLAYER");
}
if(IsEqualGUID(
&KSNODETYPE_LEGACY_AUDIO_CONNECTOR,
pGuid)) {
return("KSNODETYPE_LEGACY_AUDIO_CONNECTOR");
}
if(IsEqualGUID(
&KSNODETYPE_ANALOG_CONNECTOR,
pGuid)) {
return("KSNODETYPE_ANALOG_CONNECTOR");
}
if(IsEqualGUID(
&KSCATEGORY_WDMAUD_USE_PIN_NAME,
pGuid)) {
return("KSCATEGORY_WDMAUD_USE_PIN_NAME");
}
if(IsEqualGUID(
&KSNODETYPE_LINE_CONNECTOR,
pGuid)) {
return("KSNODETYPE_LINE_CONNECTOR");
}
if(IsEqualGUID(
&GUID_TARGET_DEVICE_QUERY_REMOVE,
pGuid)) {
return("GUID_TARGET_DEVICE_QUERY_REMOVE");
}
if(IsEqualGUID(
&GUID_TARGET_DEVICE_REMOVE_CANCELLED,
pGuid)) {
return("GUID_TARGET_DEVICE_REMOVE_CANCELLED");
}
if(IsEqualGUID(
&GUID_TARGET_DEVICE_REMOVE_COMPLETE,
pGuid)) {
return("GUID_TARGET_DEVICE_REMOVE_COMPLETE");
}
if(IsEqualGUID(
&PINNAME_CAPTURE,
pGuid)) {
return("PINNAME_CAPTURE");
}
if(IsEqualGUID(&KSNODETYPE_DAC, pGuid)) {
return("KSNODETYPE_DAC");
}
if(IsEqualGUID(&KSNODETYPE_ADC, pGuid)) {
return("KSNODETYPE_ADC");
}
if(IsEqualGUID(&KSNODETYPE_SRC, pGuid)) {
return("KSNODETYPE_SRC");
}
if(IsEqualGUID(&KSNODETYPE_SUPERMIX, pGuid)) {
return("KSNODETYPE_SUPERMIX");
}
if(IsEqualGUID( &KSNODETYPE_MUX, pGuid)) {
return("KSNODETYPE_MUX");
}
if(IsEqualGUID( &KSNODETYPE_DEMUX, pGuid)) {
return("KSNODETYPE_DEMUX");
}
if(IsEqualGUID(&KSNODETYPE_SUM, pGuid)) {
return("KSNODETYPE_SUM");
}
if(IsEqualGUID(&KSNODETYPE_MUTE, pGuid)) {
return("KSNODETYPE_MUTE");
}
if(IsEqualGUID(&KSNODETYPE_VOLUME, pGuid)) {
return("KSNODETYPE_VOLUME");
}
if(IsEqualGUID(&KSNODETYPE_TONE, pGuid)) {
return("KSNODETYPE_TONE");
}
if(IsEqualGUID(&KSNODETYPE_AGC, pGuid)) {
return("KSNODETYPE_AGC");
}
if(IsEqualGUID(&KSNODETYPE_SYNTHESIZER, pGuid)) {
return("KSNODETYPE_SYNTHESIZER");
}
if(IsEqualGUID(&KSNODETYPE_SWSYNTH, pGuid)) {
return("KSNODETYPE_SWSYNTH");
}
if(IsEqualGUID(&KSNODETYPE_3D_EFFECTS, pGuid)) {
return("KSNODETYPE_3D_EFFECTS");
}
sprintf(sz, "%08x %04x %04x %02x%02x%02x%02x%02x%02x%02x%02x",
pGuid->Data1,
pGuid->Data2,
pGuid->Data3,
pGuid->Data4[0],
pGuid->Data4[1],
pGuid->Data4[2],
pGuid->Data4[3],
pGuid->Data4[4],
pGuid->Data4[5],
pGuid->Data4[6],
pGuid->Data4[7]);
return(sz);
}
//---------------------------------------------------------------------------
#ifndef UNDER_NT
#ifdef _X86_
extern ULONG nFilter;
extern ULONG nDevice;
extern ULONG nLogicalFilter;
VOID
DebugCommand(
)
{
PKSDATAFORMAT pDataFormat;
PKSDATARANGE pDataRange;
PCOBJ pcobj;
CHAR c;
nFilter = 0;
nDevice = 0;
nLogicalFilter = 0;
ulDebugFlags = 0;
ulDebugNumber = MAXULONG;
while((c = DebugGetCommandChar()) != '\0') {
switch(c) {
case 'A':
ulDebugFlags |= DEBUG_FLAGS_ADDRESS;
break;
case 'D':
ulDebugFlags |= DEBUG_FLAGS_DEVICE;
break;
case 'F':
ulDebugFlags |= DEBUG_FLAGS_FILTER;
break;
case 'L':
ulDebugFlags |= DEBUG_FLAGS_LOGICAL_FILTER;
break;
case 'P':
ulDebugFlags |= DEBUG_FLAGS_PIN;
break;
case 'I':
ulDebugFlags |= DEBUG_FLAGS_INSTANCE;
break;
case 'G':
ulDebugFlags |= DEBUG_FLAGS_GRAPH;
break;
case 'T':
ulDebugFlags |= DEBUG_FLAGS_TOPOLOGY;
break;
case 'R':
pDataRange = (PKSDATARANGE)DebugEvaluateExpression();
if(ulDebugFlags & DEBUG_FLAGS_FILTER) {
DumpDataFormat(MAXULONG, pDataRange);
}
else {
DumpDataRangeAudio((PKSDATARANGE_AUDIO)pDataRange);
}
return;
case 'O':
ulDebugFlags |= DEBUG_FLAGS_OBJECT;
pcobj = (PCOBJ)DebugEvaluateExpression();
if(PFILTER_INSTANCE(pcobj)->m_Signature.IsAssert()) {
PFILTER_INSTANCE(pcobj)->Dump();
return;
}
if(PPIN_INSTANCE(pcobj)->m_Signature.IsAssert()) {
PPIN_INSTANCE(pcobj)->Dump();
return;
}
if(PINSTANCE(pcobj)->m_Signature.IsAssert()) {
PINSTANCE(pcobj)->Dump();
return;
}
pcobj->Dump();
return;
case 'V':
ulDebugFlags |= DEBUG_FLAGS_VERBOSE;
break;
case 'X':
ulDebugFlags |= DEBUG_FLAGS_DETAILS;
break;
case '?':
dprintf(".S[D|F|V|I|O]\n");
dprintf("[L|P|T|A|V|X]O <addr> - Dump Object\n");
dprintf("R <addr> - Dump DataRange\n");
dprintf("D[0-9][L|P|T][A|V|X] - Devices\n");
dprintf("F[0-9][L|P|T][A|V|X] - Filters\n");
dprintf("G[0-9][L|P|T][A|V|X] - Graphs\n");
dprintf("I[0-9][L|P|T][A|V|X] - Instances\n");
dprintf(" 0-9 - Device or Filter number\n");
dprintf(" L - Logical Filter Nodes\n");
dprintf(" P - Pins\n");
dprintf(" T - Topology\n");
dprintf(" A - Addresses\n");
dprintf(" V - Verbose\n");
dprintf(" X - Details\n");
return;
default:
if(c >= '0' && c <= '9') {
if(ulDebugNumber == MAXULONG) {
ulDebugNumber++;
}
ulDebugNumber *= 10;
ulDebugNumber += c - '0';
}
break;
}
}
if((ulDebugFlags != 0) &&
(ulDebugFlags &
(DEBUG_FLAGS_DEVICE |
DEBUG_FLAGS_FILTER |
DEBUG_FLAGS_INSTANCE |
DEBUG_FLAGS_LOGICAL_FILTER |
DEBUG_FLAGS_GRAPH)) == 0) {
ulDebugFlags |= DEBUG_FLAGS_DEVICE;
}
DumpSysAudio();
}
VOID
DebugDotCommand(
)
{
DebugCommand();
__asm xor eax, eax
__asm retf
}
VOID
InitializeDebug(
)
{
static char *pszHelp = ".S - Dump System Audio Driver data structures\n";
__asm {
_emit 0xcd
_emit 0x20
_emit 0xc1
_emit 0x00
_emit 0x01
_emit 0x00
jz exitlab
mov bl, 'S'
mov esi, offset DebugDotCommand
mov edi, pszHelp
mov eax, 0x70 // DS_RegisterDotCommand
int 41h
exitlab:
}
}
VOID
UninitializeDebug(
)
{
__asm {
_emit 0xcd
_emit 0x20
_emit 0xc1
_emit 0x00
_emit 0x01
_emit 0x00
jz exitlab
mov bl, 'S'
mov eax, 0x72 // DS_DeRegisterDotCommand
int 41h
exitlab:
}
}
VOID __cdecl
dprintf(
PSZ pszFmt,
...
)
{
__asm mov esi, [pszFmt]
__asm lea edi, [pszFmt+4]
__asm mov eax, 0x73
__asm int 41h
}
CHAR
DebugGetCommandChar(
)
{
CHAR c;
__asm mov ax, 0x77 // get command char
__asm mov bl, 1 // get char
__asm int 41h
__asm or ah, ah
__asm jnz morechars
__asm mov al, ah
morechars:
__asm movzx eax, al
__asm mov c, al
return(c);
}
ULONG
DebugEvaluateExpression(
)
{
ULONG ul;
__asm mov ax, 0x78 // EvaluateExpression
__asm int 41h
__asm mov ul, ebx
return(ul);
}
#endif // _X86_
#endif // UNDER_NT
#endif // DEBUG
//---------------------------------------------------------------------------
// End of File: util.c
//---------------------------------------------------------------------------