//--------------------------------------------------------------------------- // // 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 - Dump Object\n"); dprintf("R - 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 //---------------------------------------------------------------------------