windows-nt/Source/XPSP1/NT/drivers/wdm/audio/sysaudio/fni.cpp

341 lines
8.3 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//---------------------------------------------------------------------------
//
// Module: fni.cpp
//
// Description:
//
// Filter Node Instance
//
//@@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"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
CFilterNodeInstance::~CFilterNodeInstance(
)
{
Assert(this);
DPF1(95, "~CFilterNodeInstance: %08x", this);
RemoveListCheck();
UnregisterTargetDeviceChangeNotification();
//
// if hFilter == NULL && pFileObject != NULL
// it means that this filter instance is for a GFX
// do not try to dereference the file object in that case
//
if( (hFilter != NULL) && (pFileObject != NULL) ) {
AssertFileObject(pFileObject);
ObDereferenceObject(pFileObject);
}
if(hFilter != NULL) {
AssertStatus(ZwClose(hFilter));
}
}
NTSTATUS
CFilterNodeInstance::Create(
PFILTER_NODE_INSTANCE *ppFilterNodeInstance,
PLOGICAL_FILTER_NODE pLogicalFilterNode,
PDEVICE_NODE pDeviceNode,
BOOL fReuseInstance
)
{
PFILTER_NODE_INSTANCE pFilterNodeInstance = NULL;
PLOGICAL_FILTER_NODE pLogicalFilterNode2;
NTSTATUS Status = STATUS_SUCCESS;
Assert(pLogicalFilterNode);
Assert(pLogicalFilterNode->pFilterNode);
if(pLogicalFilterNode->GetType() & FILTER_TYPE_AEC) {
FOR_EACH_LIST_ITEM(
&pLogicalFilterNode->pFilterNode->lstLogicalFilterNode,
pLogicalFilterNode2) {
FOR_EACH_LIST_ITEM(
&pLogicalFilterNode2->lstFilterNodeInstance,
pFilterNodeInstance) {
pFilterNodeInstance->AddRef();
ASSERT(NT_SUCCESS(Status));
goto exit;
} END_EACH_LIST_ITEM
} END_EACH_LIST_ITEM
}
else {
if(fReuseInstance) {
FOR_EACH_LIST_ITEM(
&pLogicalFilterNode->lstFilterNodeInstance,
pFilterNodeInstance) {
if(pDeviceNode == NULL ||
pDeviceNode == pFilterNodeInstance->pDeviceNode) {
pFilterNodeInstance->AddRef();
ASSERT(NT_SUCCESS(Status));
goto exit;
}
} END_EACH_LIST_ITEM
}
}
Status = Create(&pFilterNodeInstance, pLogicalFilterNode->pFilterNode);
if(!NT_SUCCESS(Status)) {
goto exit;
}
pFilterNodeInstance->pDeviceNode = pDeviceNode;
pFilterNodeInstance->AddList(&pLogicalFilterNode->lstFilterNodeInstance);
exit:
*ppFilterNodeInstance = pFilterNodeInstance;
return(Status);
}
NTSTATUS
CFilterNodeInstance::Create(
PFILTER_NODE_INSTANCE *ppFilterNodeInstance,
PFILTER_NODE pFilterNode
)
{
PFILTER_NODE_INSTANCE pFilterNodeInstance = NULL;
NTSTATUS Status = STATUS_SUCCESS;
Assert(pFilterNode);
pFilterNodeInstance = new FILTER_NODE_INSTANCE;
if(pFilterNodeInstance == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
pFilterNodeInstance->pFilterNode = pFilterNode;
pFilterNodeInstance->AddRef();
if(pFilterNode->GetType() & FILTER_TYPE_GFX) {
//
// if it is a GFX do not try to open the device, just re-use
// the file object which we cached during AddGfx
//
pFilterNodeInstance->pFileObject = pFilterNode->GetFileObject();
pFilterNodeInstance->hFilter = NULL;
Status = STATUS_SUCCESS;
}
else {
//
// if it is not a GFX go ahead and open the device.
//
Status = pFilterNode->OpenDevice(&pFilterNodeInstance->hFilter);
}
if(!NT_SUCCESS(Status)) {
DPF2(10, "CFilterNodeInstance::Create OpenDevice Failed: %08x FN: %08x",
Status,
pFilterNode);
pFilterNodeInstance->hFilter = NULL;
goto exit;
}
if (pFilterNodeInstance->hFilter) {
Status = ObReferenceObjectByHandle(
pFilterNodeInstance->hFilter,
GENERIC_READ | GENERIC_WRITE,
NULL,
KernelMode,
(PVOID*)&pFilterNodeInstance->pFileObject,
NULL);
}
if(!NT_SUCCESS(Status)) {
Trap();
pFilterNodeInstance->pFileObject = NULL;
goto exit;
}
AssertFileObject(pFilterNodeInstance->pFileObject);
Status = pFilterNodeInstance->RegisterTargetDeviceChangeNotification();
if(!NT_SUCCESS(Status)) {
goto exit;
}
DPF2(95, "CFilterNodeInstance::Create %08x FN: %08x",
pFilterNodeInstance,
pFilterNode);
exit:
if(!NT_SUCCESS(Status)) {
if (pFilterNodeInstance) {
pFilterNodeInstance->Destroy();
}
pFilterNodeInstance = NULL;
}
*ppFilterNodeInstance = pFilterNodeInstance;
return(Status);
}
//---------------------------------------------------------------------------
NTSTATUS
CFilterNodeInstance::RegisterTargetDeviceChangeNotification(
)
{
NTSTATUS Status;
ASSERT(gpDeviceInstance != NULL);
ASSERT(gpDeviceInstance->pPhysicalDeviceObject != NULL);
ASSERT(pNotificationHandle == NULL);
Status = IoRegisterPlugPlayNotification(
EventCategoryTargetDeviceChange,
0,
pFileObject,
gpDeviceInstance->pPhysicalDeviceObject->DriverObject,
(NTSTATUS (*)(PVOID, PVOID))
CFilterNodeInstance::TargetDeviceChangeNotification,
this,
&pNotificationHandle);
if(!NT_SUCCESS(Status)) {
if(Status != STATUS_NOT_IMPLEMENTED) {
goto exit;
}
Status = STATUS_SUCCESS;
}
DPF2(100, "RegisterTargetDeviceChangeNotification: FNI: %08x PFO: %08x",
this,
this->pFileObject);
exit:
return(Status);
}
VOID
CFilterNodeInstance::UnregisterTargetDeviceChangeNotification(
)
{
HANDLE hNotification;
DPF1(100, "UnregisterTargetDeviceChangeNotification: FNI: %08x", this);
hNotification = pNotificationHandle;
if(hNotification != NULL) {
pNotificationHandle = NULL;
IoUnregisterPlugPlayNotification(hNotification);
}
}
NTSTATUS
CFilterNodeInstance::DeviceQueryRemove(
)
{
PGRAPH_NODE_INSTANCE pGraphNodeInstance;
PDEVICE_NODE pDeviceNode;
PGRAPH_NODE pGraphNode;
FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
FOR_EACH_LIST_ITEM(&pDeviceNode->lstGraphNode, pGraphNode) {
FOR_EACH_LIST_ITEM(
&pGraphNode->lstGraphNodeInstance,
pGraphNodeInstance) {
for(ULONG n = 0;
n < pGraphNodeInstance->Topology.TopologyNodesCount;
n++) {
pGraphNodeInstance->
papFilterNodeInstanceTopologyTable[n]->Destroy();
pGraphNodeInstance->
papFilterNodeInstanceTopologyTable[n] = NULL;
}
} END_EACH_LIST_ITEM
} END_EACH_LIST_ITEM
} END_EACH_LIST_ITEM
return(STATUS_SUCCESS);
}
NTSTATUS
CFilterNodeInstance::TargetDeviceChangeNotification(
IN PTARGET_DEVICE_REMOVAL_NOTIFICATION pNotification,
IN PFILTER_NODE_INSTANCE pFilterNodeInstance
)
{
DPF3(5, "TargetDeviceChangeNotification: FNI: %08x PFO: %08x %s",
pFilterNodeInstance,
pNotification->FileObject,
DbgGuid2Sz(&pNotification->Event));
if(IsEqualGUID(
&pNotification->Event,
&GUID_TARGET_DEVICE_REMOVE_COMPLETE) ||
IsEqualGUID(
&pNotification->Event,
&GUID_TARGET_DEVICE_QUERY_REMOVE)) {
NTSTATUS Status = STATUS_SUCCESS;
LARGE_INTEGER li = {0, 10000}; // wait for 1 ms
Status = KeWaitForMutexObject(
&gMutex,
Executive,
KernelMode,
FALSE,
&li);
if(Status != STATUS_TIMEOUT) {
DeviceQueryRemove();
ReleaseMutex();
}
else {
DPF1(5, "TargetDeviceChangeNotification: FAILED %08x", Status);
}
}
return(STATUS_SUCCESS);
}
//---------------------------------------------------------------------------
#ifdef DEBUG
ENUMFUNC
CFilterNodeInstance::Dump(
)
{
if(this == NULL) {
return(STATUS_CONTINUE);
}
if(ulDebugFlags & (DEBUG_FLAGS_VERBOSE | DEBUG_FLAGS_OBJECT)) {
dprintf("FNI: %08x cRef %02x FO %08x H %08x DN %08x FN %08x NH %08x\n",
this,
cReference,
pFileObject,
hFilter,
pDeviceNode,
pFilterNode,
pNotificationHandle);
dprintf(" %s\n", pFilterNode->DumpName());
}
return(STATUS_CONTINUE);
}
#endif
//---------------------------------------------------------------------------