mirror of
https://github.com/jamesstringer90/appsandbox.git
synced 2026-10-22 11:03:15 -05:00
- M15 wavminiport.cpp: reject PinId >= WaveDescriptor->PinCount in the proposed-format property handler. - M16 wavstream.cpp: guard divide-by-zero on m_ulDmaMovementRate and nAvgBytesPerSec in buffer allocation and presentation-position. - L14 topology.cpp: set PropertyRequest->ValueSize in both jack description GET paths. - L15 adaptercommon.cpp: balance the adapter instance count on the allocation-failure path.
1311 lines
41 KiB
C++
1311 lines
41 KiB
C++
#pragma warning (disable : 4127)
|
|
|
|
#include <initguid.h>
|
|
#include "driverdefs.h"
|
|
#include "pinnodes.h"
|
|
|
|
//=============================================================================
|
|
// Mixer register counts
|
|
//=============================================================================
|
|
|
|
#define MAX_TOPOLOGY_NODES 2
|
|
#define MAX_CHANNELS 2
|
|
//=============================================================================
|
|
// Sub-device cache entry
|
|
//=============================================================================
|
|
|
|
typedef struct _MINIPAIR_UNKNOWN
|
|
{
|
|
LIST_ENTRY ListEntry;
|
|
WCHAR Name[MAX_PATH];
|
|
PUNKNOWN PortInterface;
|
|
PUNKNOWN MiniportInterface;
|
|
PADAPTERPOWERMANAGEMENT PowerInterface;
|
|
} MINIPAIR_UNKNOWN;
|
|
|
|
//=============================================================================
|
|
// CVadAdapterCommon
|
|
//=============================================================================
|
|
|
|
class CVadAdapterCommon :
|
|
public IAdapterCommon,
|
|
public IAdapterPowerManagement,
|
|
public CUnknown
|
|
{
|
|
private:
|
|
PSERVICEGROUP m_pServiceGroupWave;
|
|
PDEVICE_OBJECT m_pDeviceObject;
|
|
PDEVICE_OBJECT m_pPhysicalDeviceObject;
|
|
WDFDEVICE m_WdfDevice;
|
|
DEVICE_POWER_STATE m_PowerState;
|
|
PPORTCLSETWHELPER m_pPortClsEtwHelper;
|
|
LIST_ENTRY m_SubdeviceCache;
|
|
|
|
static LONG m_AdapterInstances;
|
|
|
|
// Inline mixer state (no separate HW object)
|
|
BOOL m_MixerMute[MAX_TOPOLOGY_NODES][MAX_CHANNELS];
|
|
LONG m_MixerVolume[MAX_TOPOLOGY_NODES][MAX_CHANNELS];
|
|
LONG m_PeakMeter[MAX_TOPOLOGY_NODES][MAX_CHANNELS];
|
|
ULONG m_MixerMux;
|
|
BOOL m_bDevSpecific;
|
|
INT m_iDevSpecific;
|
|
UINT m_uiDevSpecific;
|
|
|
|
public:
|
|
DECLARE_STD_UNKNOWN();
|
|
DEFINE_STD_CONSTRUCTOR(CVadAdapterCommon);
|
|
~CVadAdapterCommon();
|
|
|
|
IMP_IAdapterPowerManagement;
|
|
|
|
STDMETHODIMP_(NTSTATUS) Init
|
|
(
|
|
_In_ PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
STDMETHODIMP_(PDEVICE_OBJECT) GetDeviceObject(void);
|
|
STDMETHODIMP_(PDEVICE_OBJECT) GetPhysicalDeviceObject(void);
|
|
STDMETHODIMP_(WDFDEVICE) GetWdfDevice(void);
|
|
|
|
STDMETHODIMP_(void) SetWaveServiceGroup
|
|
(
|
|
_In_ PSERVICEGROUP ServiceGroup
|
|
);
|
|
|
|
STDMETHODIMP_(BOOL) bDevSpecificRead();
|
|
STDMETHODIMP_(void) bDevSpecificWrite(_In_ BOOL bDevSpecific);
|
|
STDMETHODIMP_(INT) iDevSpecificRead();
|
|
STDMETHODIMP_(void) iDevSpecificWrite(_In_ INT iDevSpecific);
|
|
STDMETHODIMP_(UINT) uiDevSpecificRead();
|
|
STDMETHODIMP_(void) uiDevSpecificWrite(_In_ UINT uiDevSpecific);
|
|
|
|
STDMETHODIMP_(BOOL) MixerMuteRead(_In_ ULONG Index, _In_ ULONG Channel);
|
|
STDMETHODIMP_(void) MixerMuteWrite(_In_ ULONG Index, _In_ ULONG Channel, _In_ BOOL Value);
|
|
STDMETHODIMP_(ULONG) MixerMuxRead(void);
|
|
STDMETHODIMP_(void) MixerMuxWrite(_In_ ULONG Index);
|
|
STDMETHODIMP_(void) MixerReset(void);
|
|
STDMETHODIMP_(LONG) MixerVolumeRead(_In_ ULONG Index, _In_ ULONG Channel);
|
|
STDMETHODIMP_(void) MixerVolumeWrite(_In_ ULONG Index, _In_ ULONG Channel, _In_ LONG Value);
|
|
STDMETHODIMP_(LONG) MixerPeakMeterRead(_In_ ULONG Index, _In_ ULONG Channel);
|
|
|
|
STDMETHODIMP_(NTSTATUS) WriteEtwEvent
|
|
(
|
|
_In_ EPcMiniportEngineEvent miniportEventType,
|
|
_In_ ULONGLONG ullData1,
|
|
_In_ ULONGLONG ullData2,
|
|
_In_ ULONGLONG ullData3,
|
|
_In_ ULONGLONG ullData4
|
|
);
|
|
|
|
STDMETHODIMP_(VOID) SetEtwHelper(PPORTCLSETWHELPER _pPortClsEtwHelper);
|
|
|
|
STDMETHODIMP_(NTSTATUS) InstallSubdevice
|
|
(
|
|
_In_opt_ PIRP Irp,
|
|
_In_ PWSTR Name,
|
|
_In_ REFGUID PortClassId,
|
|
_In_ REFGUID MiniportClassId,
|
|
_In_opt_ PFNCREATEMINIPORT MiniportCreate,
|
|
_In_ ULONG cPropertyCount,
|
|
_In_reads_opt_(cPropertyCount) const VAD_DEVPROPERTY * pProperties,
|
|
_In_opt_ PVOID DeviceContext,
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_In_opt_ PRESOURCELIST ResourceList,
|
|
_In_ REFGUID PortInterfaceId,
|
|
_Out_opt_ PUNKNOWN * OutPortInterface,
|
|
_Out_opt_ PUNKNOWN * OutPortUnknown,
|
|
_Out_opt_ PUNKNOWN * OutMiniportUnknown
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS) UnregisterSubdevice(_In_opt_ PUNKNOWN UnknownPort);
|
|
|
|
STDMETHODIMP_(NTSTATUS) ConnectTopologies
|
|
(
|
|
_In_ PUNKNOWN UnknownTopology,
|
|
_In_ PUNKNOWN UnknownWave,
|
|
_In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
|
|
_In_ ULONG PhysicalConnectionCount
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS) DisconnectTopologies
|
|
(
|
|
_In_ PUNKNOWN UnknownTopology,
|
|
_In_ PUNKNOWN UnknownWave,
|
|
_In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
|
|
_In_ ULONG PhysicalConnectionCount
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS) InstallEndpointFilters
|
|
(
|
|
_In_opt_ PIRP Irp,
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_In_opt_ PVOID DeviceContext,
|
|
_Out_opt_ PUNKNOWN * UnknownTopology,
|
|
_Out_opt_ PUNKNOWN * UnknownWave,
|
|
_Out_opt_ PUNKNOWN * UnknownMiniportTopology,
|
|
_Out_opt_ PUNKNOWN * UnknownMiniportWave
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS) RemoveEndpointFilters
|
|
(
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_In_opt_ PUNKNOWN UnknownTopology,
|
|
_In_opt_ PUNKNOWN UnknownWave
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS) GetFilters
|
|
(
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_Out_opt_ PUNKNOWN *UnknownTopologyPort,
|
|
_Out_opt_ PUNKNOWN *UnknownTopologyMiniport,
|
|
_Out_opt_ PUNKNOWN *UnknownWavePort,
|
|
_Out_opt_ PUNKNOWN *UnknownWaveMiniport
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS) SetIdlePowerManagement
|
|
(
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_In_ BOOL bEnabled
|
|
);
|
|
|
|
STDMETHODIMP_(VOID) Cleanup();
|
|
|
|
friend NTSTATUS NewAdapterCommon
|
|
(
|
|
_Out_ PUNKNOWN * Unknown,
|
|
_In_ REFCLSID,
|
|
_In_opt_ PUNKNOWN UnknownOuter,
|
|
_In_ POOL_FLAGS PoolFlags
|
|
);
|
|
|
|
private:
|
|
NTSTATUS GetCachedSubdevice(_In_ PWSTR Name, _Out_opt_ PUNKNOWN *OutUnknownPort, _Out_opt_ PUNKNOWN *OutUnknownMiniport);
|
|
NTSTATUS CacheSubdevice(_In_ PWSTR Name, _In_ PUNKNOWN UnknownPort, _In_ PUNKNOWN UnknownMiniport);
|
|
NTSTATUS RemoveCachedSubdevice(_In_ PWSTR Name);
|
|
VOID EmptySubdeviceCache();
|
|
|
|
NTSTATUS CreateAudioInterfaceWithProperties
|
|
(
|
|
_In_ PCWSTR ReferenceString,
|
|
_In_ ULONG cPropertyCount,
|
|
_In_reads_opt_(cPropertyCount) const VAD_DEVPROPERTY *pProperties,
|
|
_Out_ _At_(AudioSymbolicLinkName->Buffer, __drv_allocatesMem(Mem)) PUNICODE_STRING AudioSymbolicLinkName
|
|
);
|
|
|
|
};
|
|
|
|
LONG CVadAdapterCommon::m_AdapterInstances = 0;
|
|
|
|
//=============================================================================
|
|
// Helper: set device interface properties
|
|
//=============================================================================
|
|
|
|
#pragma code_seg("PAGE")
|
|
static
|
|
NTSTATUS VadIoSetDeviceInterfacePropertyDataMultiple
|
|
(
|
|
_In_ PUNICODE_STRING SymbolicLinkName,
|
|
_In_ ULONG cPropertyCount,
|
|
_In_reads_opt_(cPropertyCount) const VAD_DEVPROPERTY *pProperties
|
|
)
|
|
{
|
|
NTSTATUS ntStatus;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (pProperties)
|
|
{
|
|
for (ULONG i = 0; i < cPropertyCount; i++)
|
|
{
|
|
ntStatus = IoSetDeviceInterfacePropertyData(
|
|
SymbolicLinkName,
|
|
pProperties[i].PropertyKey,
|
|
LOCALE_NEUTRAL,
|
|
PLUGPLAY_PROPERTY_PERSISTENT,
|
|
pProperties[i].Type,
|
|
pProperties[i].BufferSize,
|
|
pProperties[i].Buffer);
|
|
|
|
if (!NT_SUCCESS(ntStatus))
|
|
{
|
|
return ntStatus;
|
|
}
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//=============================================================================
|
|
// NewAdapterCommon
|
|
//=============================================================================
|
|
|
|
#pragma code_seg("PAGE")
|
|
NTSTATUS
|
|
NewAdapterCommon
|
|
(
|
|
_Out_ PUNKNOWN * Unknown,
|
|
_In_ REFCLSID,
|
|
_In_opt_ PUNKNOWN UnknownOuter,
|
|
_In_ POOL_FLAGS PoolFlags
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(Unknown);
|
|
|
|
NTSTATUS ntStatus;
|
|
|
|
if (InterlockedCompareExchange(&CVadAdapterCommon::m_AdapterInstances, 1, 0) != 0)
|
|
{
|
|
ntStatus = STATUS_DEVICE_BUSY;
|
|
DPF(D_ERROR, ("NewAdapterCommon failed, only one instance is allowed"));
|
|
goto Done;
|
|
}
|
|
|
|
{
|
|
CVadAdapterCommon *p = new(PoolFlags, VAD_ADAPTER_POOLTAG) CVadAdapterCommon(UnknownOuter);
|
|
if (p == NULL)
|
|
{
|
|
InterlockedDecrement(&CVadAdapterCommon::m_AdapterInstances);
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
DPF(D_ERROR, ("NewAdapterCommon failed, 0x%x", ntStatus));
|
|
goto Done;
|
|
}
|
|
|
|
*Unknown = PUNKNOWN((PADAPTERCOMMON)(p));
|
|
(*Unknown)->AddRef();
|
|
ntStatus = STATUS_SUCCESS;
|
|
}
|
|
|
|
Done:
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
CVadAdapterCommon::~CVadAdapterCommon(void)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::~CVadAdapterCommon]"));
|
|
|
|
SAFE_RELEASE(m_pPortClsEtwHelper);
|
|
SAFE_RELEASE(m_pServiceGroupWave);
|
|
|
|
if (m_WdfDevice)
|
|
{
|
|
WdfObjectDelete(m_WdfDevice);
|
|
m_WdfDevice = NULL;
|
|
}
|
|
|
|
InterlockedDecrement(&CVadAdapterCommon::m_AdapterInstances);
|
|
ASSERT(CVadAdapterCommon::m_AdapterInstances == 0);
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(PDEVICE_OBJECT) CVadAdapterCommon::GetDeviceObject(void)
|
|
{
|
|
PAGED_CODE();
|
|
return m_pDeviceObject;
|
|
}
|
|
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(PDEVICE_OBJECT) CVadAdapterCommon::GetPhysicalDeviceObject(void)
|
|
{
|
|
PAGED_CODE();
|
|
return m_pPhysicalDeviceObject;
|
|
}
|
|
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(WDFDEVICE) CVadAdapterCommon::GetWdfDevice(void)
|
|
{
|
|
PAGED_CODE();
|
|
return m_WdfDevice;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
NTSTATUS
|
|
CVadAdapterCommon::Init
|
|
(
|
|
_In_ PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::Init]"));
|
|
|
|
ASSERT(DeviceObject);
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
m_pServiceGroupWave = NULL;
|
|
m_pDeviceObject = DeviceObject;
|
|
m_pPhysicalDeviceObject = NULL;
|
|
m_WdfDevice = NULL;
|
|
m_PowerState = PowerDeviceD0;
|
|
m_pPortClsEtwHelper = NULL;
|
|
|
|
InitializeListHead(&m_SubdeviceCache);
|
|
|
|
ntStatus = PcGetPhysicalDeviceObject(DeviceObject, &m_pPhysicalDeviceObject);
|
|
IF_FAILED_ACTION_JUMP(
|
|
ntStatus,
|
|
DPF(D_ERROR, ("PcGetPhysicalDeviceObject failed, 0x%x", ntStatus)),
|
|
Done);
|
|
|
|
ntStatus = WdfDeviceMiniportCreate(WdfGetDriver(),
|
|
WDF_NO_OBJECT_ATTRIBUTES,
|
|
DeviceObject,
|
|
NULL,
|
|
NULL,
|
|
&m_WdfDevice);
|
|
IF_FAILED_ACTION_JUMP(
|
|
ntStatus,
|
|
DPF(D_ERROR, ("WdfDeviceMiniportCreate failed, 0x%x", ntStatus)),
|
|
Done);
|
|
|
|
// Initialize mixer state
|
|
MixerReset();
|
|
|
|
Done:
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(void) CVadAdapterCommon::MixerReset(void)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
RtlZeroMemory(m_MixerMute, sizeof(m_MixerMute));
|
|
RtlZeroMemory(m_PeakMeter, sizeof(m_PeakMeter));
|
|
m_MixerMux = 0;
|
|
m_bDevSpecific = FALSE;
|
|
m_iDevSpecific = 0;
|
|
m_uiDevSpecific = 0;
|
|
|
|
for (ULONG i = 0; i < MAX_TOPOLOGY_NODES; i++)
|
|
{
|
|
for (ULONG j = 0; j < MAX_CHANNELS; j++)
|
|
{
|
|
m_MixerVolume[i][j] = VOLUME_SIGNED_MAXIMUM;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg()
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CVadAdapterCommon::WriteEtwEvent
|
|
(
|
|
_In_ EPcMiniportEngineEvent miniportEventType,
|
|
_In_ ULONGLONG ullData1,
|
|
_In_ ULONGLONG ullData2,
|
|
_In_ ULONGLONG ullData3,
|
|
_In_ ULONGLONG ullData4
|
|
)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
if (m_pPortClsEtwHelper)
|
|
{
|
|
ntStatus = m_pPortClsEtwHelper->MiniportWriteEtwEvent(miniportEventType, ullData1, ullData2, ullData3, ullData4);
|
|
}
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(VOID) CVadAdapterCommon::SetEtwHelper(PPORTCLSETWHELPER _pPortClsEtwHelper)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
SAFE_RELEASE(m_pPortClsEtwHelper);
|
|
m_pPortClsEtwHelper = _pPortClsEtwHelper;
|
|
if (m_pPortClsEtwHelper)
|
|
{
|
|
m_pPortClsEtwHelper->AddRef();
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP CVadAdapterCommon::NonDelegatingQueryInterface
|
|
(
|
|
_In_ REFIID Interface,
|
|
_COM_Outptr_ PVOID * Object
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
ASSERT(Object);
|
|
|
|
if (IsEqualGUIDAligned(Interface, IID_IUnknown))
|
|
{
|
|
*Object = PVOID(PUNKNOWN(PADAPTERCOMMON(this)));
|
|
}
|
|
else if (IsEqualGUIDAligned(Interface, IID_IAdapterCommon))
|
|
{
|
|
*Object = PVOID(PADAPTERCOMMON(this));
|
|
}
|
|
else if (IsEqualGUIDAligned(Interface, IID_IAdapterPowerManagement))
|
|
{
|
|
*Object = PVOID(PADAPTERPOWERMANAGEMENT(this));
|
|
}
|
|
else
|
|
{
|
|
*Object = NULL;
|
|
}
|
|
|
|
if (*Object)
|
|
{
|
|
PUNKNOWN(*Object)->AddRef();
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(void) CVadAdapterCommon::SetWaveServiceGroup(_In_ PSERVICEGROUP ServiceGroup)
|
|
{
|
|
PAGED_CODE();
|
|
SAFE_RELEASE(m_pServiceGroupWave);
|
|
m_pServiceGroupWave = ServiceGroup;
|
|
if (m_pServiceGroupWave)
|
|
{
|
|
m_pServiceGroupWave->AddRef();
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// Mixer accessors
|
|
//=============================================================================
|
|
|
|
#pragma code_seg()
|
|
STDMETHODIMP_(BOOL) CVadAdapterCommon::bDevSpecificRead() { return m_bDevSpecific; }
|
|
STDMETHODIMP_(void) CVadAdapterCommon::bDevSpecificWrite(_In_ BOOL b) { m_bDevSpecific = b; }
|
|
STDMETHODIMP_(INT) CVadAdapterCommon::iDevSpecificRead() { return m_iDevSpecific; }
|
|
STDMETHODIMP_(void) CVadAdapterCommon::iDevSpecificWrite(_In_ INT i) { m_iDevSpecific = i; }
|
|
STDMETHODIMP_(UINT) CVadAdapterCommon::uiDevSpecificRead() { return m_uiDevSpecific; }
|
|
STDMETHODIMP_(void) CVadAdapterCommon::uiDevSpecificWrite(_In_ UINT ui) { m_uiDevSpecific = ui; }
|
|
|
|
STDMETHODIMP_(BOOL) CVadAdapterCommon::MixerMuteRead(_In_ ULONG Index, _In_ ULONG Channel)
|
|
{
|
|
if (Index < MAX_TOPOLOGY_NODES && Channel < MAX_CHANNELS)
|
|
{
|
|
return m_MixerMute[Index][Channel];
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
STDMETHODIMP_(void) CVadAdapterCommon::MixerMuteWrite(_In_ ULONG Index, _In_ ULONG Channel, _In_ BOOL Value)
|
|
{
|
|
if (Index < MAX_TOPOLOGY_NODES && Channel < MAX_CHANNELS)
|
|
{
|
|
m_MixerMute[Index][Channel] = Value;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CVadAdapterCommon::MixerMuxRead(void) { return m_MixerMux; }
|
|
STDMETHODIMP_(void) CVadAdapterCommon::MixerMuxWrite(_In_ ULONG Index) { m_MixerMux = Index; }
|
|
|
|
STDMETHODIMP_(LONG) CVadAdapterCommon::MixerVolumeRead(_In_ ULONG Index, _In_ ULONG Channel)
|
|
{
|
|
if (Index < MAX_TOPOLOGY_NODES && Channel < MAX_CHANNELS)
|
|
{
|
|
return m_MixerVolume[Index][Channel];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
STDMETHODIMP_(void) CVadAdapterCommon::MixerVolumeWrite(_In_ ULONG Index, _In_ ULONG Channel, _In_ LONG Value)
|
|
{
|
|
if (Index < MAX_TOPOLOGY_NODES && Channel < MAX_CHANNELS)
|
|
{
|
|
m_MixerVolume[Index][Channel] = Value;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(LONG) CVadAdapterCommon::MixerPeakMeterRead(_In_ ULONG Index, _In_ ULONG Channel)
|
|
{
|
|
if (Index < MAX_TOPOLOGY_NODES && Channel < MAX_CHANNELS)
|
|
{
|
|
return m_PeakMeter[Index][Channel];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//=============================================================================
|
|
// Power management
|
|
//=============================================================================
|
|
|
|
#pragma code_seg()
|
|
STDMETHODIMP_(void) CVadAdapterCommon::PowerChangeState(_In_ POWER_STATE NewState)
|
|
{
|
|
DPF_ENTER(("[CVadAdapterCommon::PowerChangeState]"));
|
|
|
|
PLIST_ENTRY le = NULL;
|
|
for (le = m_SubdeviceCache.Flink; le != &m_SubdeviceCache; le = le->Flink)
|
|
{
|
|
MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
|
|
if (pRecord->PowerInterface)
|
|
{
|
|
pRecord->PowerInterface->PowerChangeState(NewState);
|
|
}
|
|
}
|
|
|
|
if (NewState.DeviceState != m_PowerState)
|
|
{
|
|
switch (NewState.DeviceState)
|
|
{
|
|
case PowerDeviceD0:
|
|
case PowerDeviceD1:
|
|
case PowerDeviceD2:
|
|
case PowerDeviceD3:
|
|
m_PowerState = NewState.DeviceState;
|
|
DPF(D_VERBOSE, ("Entering D%u", ULONG(m_PowerState) - ULONG(PowerDeviceD0)));
|
|
break;
|
|
default:
|
|
DPF(D_VERBOSE, ("Unknown Device Power State"));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma code_seg()
|
|
STDMETHODIMP_(NTSTATUS) CVadAdapterCommon::QueryDeviceCapabilities(
|
|
_Inout_updates_bytes_(sizeof(DEVICE_CAPABILITIES)) PDEVICE_CAPABILITIES PowerDeviceCaps
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(PowerDeviceCaps);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#pragma code_seg()
|
|
STDMETHODIMP_(NTSTATUS) CVadAdapterCommon::QueryPowerChangeState(_In_ POWER_STATE NewStateQuery)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
PLIST_ENTRY le = NULL;
|
|
for (le = m_SubdeviceCache.Flink; le != &m_SubdeviceCache && NT_SUCCESS(status); le = le->Flink)
|
|
{
|
|
MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
|
|
if (pRecord->PowerInterface)
|
|
{
|
|
status = pRecord->PowerInterface->QueryPowerChangeState(NewStateQuery);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
//=============================================================================
|
|
// Audio interface creation
|
|
//=============================================================================
|
|
|
|
#pragma code_seg("PAGE")
|
|
NTSTATUS
|
|
CVadAdapterCommon::CreateAudioInterfaceWithProperties
|
|
(
|
|
_In_ PCWSTR ReferenceString,
|
|
_In_ ULONG cPropertyCount,
|
|
_In_reads_opt_(cPropertyCount) const VAD_DEVPROPERTY *pProperties,
|
|
_Out_ _At_(AudioSymbolicLinkName->Buffer, __drv_allocatesMem(Mem)) PUNICODE_STRING AudioSymbolicLinkName
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::CreateAudioInterfaceWithProperties]"));
|
|
|
|
NTSTATUS ntStatus;
|
|
UNICODE_STRING referenceString;
|
|
|
|
RtlInitUnicodeString(&referenceString, ReferenceString);
|
|
RtlZeroMemory(AudioSymbolicLinkName, sizeof(UNICODE_STRING));
|
|
|
|
ntStatus = IoRegisterDeviceInterface(
|
|
GetPhysicalDeviceObject(),
|
|
&KSCATEGORY_AUDIO,
|
|
&referenceString,
|
|
AudioSymbolicLinkName);
|
|
|
|
IF_FAILED_ACTION_JUMP(
|
|
ntStatus,
|
|
DPF(D_ERROR, ("CreateAudioInterfaceWithProperties: IoRegisterDeviceInterface failed, 0x%x", ntStatus)),
|
|
Done);
|
|
|
|
ntStatus = VadIoSetDeviceInterfacePropertyDataMultiple(AudioSymbolicLinkName, cPropertyCount, pProperties);
|
|
IF_FAILED_ACTION_JUMP(
|
|
ntStatus,
|
|
DPF(D_ERROR, ("VadIoSetDeviceInterfacePropertyDataMultiple failed, 0x%x", ntStatus)),
|
|
Done);
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
|
|
Done:
|
|
if (!NT_SUCCESS(ntStatus))
|
|
{
|
|
RtlFreeUnicodeString(AudioSymbolicLinkName);
|
|
RtlZeroMemory(AudioSymbolicLinkName, sizeof(UNICODE_STRING));
|
|
}
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
// InstallSubdevice
|
|
//=============================================================================
|
|
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CVadAdapterCommon::InstallSubdevice
|
|
(
|
|
_In_opt_ PIRP Irp,
|
|
_In_ PWSTR Name,
|
|
_In_ REFGUID PortClassId,
|
|
_In_ REFGUID MiniportClassId,
|
|
_In_opt_ PFNCREATEMINIPORT MiniportCreate,
|
|
_In_ ULONG cPropertyCount,
|
|
_In_reads_opt_(cPropertyCount) const VAD_DEVPROPERTY * pProperties,
|
|
_In_opt_ PVOID DeviceContext,
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_In_opt_ PRESOURCELIST ResourceList,
|
|
_In_ REFGUID PortInterfaceId,
|
|
_Out_opt_ PUNKNOWN * OutPortInterface,
|
|
_Out_opt_ PUNKNOWN * OutPortUnknown,
|
|
_Out_opt_ PUNKNOWN * OutMiniportUnknown
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[InstallSubDevice %S]", Name));
|
|
|
|
ASSERT(Name != NULL);
|
|
ASSERT(m_pDeviceObject != NULL);
|
|
|
|
NTSTATUS ntStatus;
|
|
PPORT port = NULL;
|
|
PUNKNOWN miniport = NULL;
|
|
PADAPTERCOMMON adapterCommon = NULL;
|
|
UNICODE_STRING symbolicLink = { 0 };
|
|
|
|
adapterCommon = PADAPTERCOMMON(this);
|
|
|
|
ntStatus = CreateAudioInterfaceWithProperties(Name, cPropertyCount, pProperties, &symbolicLink);
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
RtlFreeUnicodeString(&symbolicLink);
|
|
ntStatus = PcNewPort(&port, PortClassId);
|
|
}
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
if (MiniportCreate)
|
|
{
|
|
ntStatus =
|
|
MiniportCreate
|
|
(
|
|
&miniport,
|
|
MiniportClassId,
|
|
NULL,
|
|
POOL_FLAG_NON_PAGED,
|
|
adapterCommon,
|
|
DeviceContext,
|
|
MiniportPair
|
|
);
|
|
}
|
|
else
|
|
{
|
|
ntStatus =
|
|
PcNewMiniport
|
|
(
|
|
(PMINIPORT *)&miniport,
|
|
MiniportClassId
|
|
);
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
#pragma warning(push)
|
|
#pragma warning(disable:6387)
|
|
ntStatus =
|
|
port->Init
|
|
(
|
|
m_pDeviceObject,
|
|
Irp,
|
|
miniport,
|
|
adapterCommon,
|
|
ResourceList
|
|
);
|
|
#pragma warning (pop)
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ntStatus =
|
|
PcRegisterSubdevice
|
|
(
|
|
m_pDeviceObject,
|
|
Name,
|
|
port
|
|
);
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
if (OutPortUnknown)
|
|
{
|
|
ntStatus = port->QueryInterface(IID_IUnknown, (PVOID *)OutPortUnknown);
|
|
}
|
|
|
|
if (OutPortInterface)
|
|
{
|
|
ntStatus = port->QueryInterface(PortInterfaceId, (PVOID *)OutPortInterface);
|
|
}
|
|
|
|
if (OutMiniportUnknown)
|
|
{
|
|
ntStatus = miniport->QueryInterface(IID_IUnknown, (PVOID *)OutMiniportUnknown);
|
|
}
|
|
}
|
|
|
|
if (port)
|
|
{
|
|
port->Release();
|
|
}
|
|
|
|
if (miniport)
|
|
{
|
|
miniport->Release();
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(NTSTATUS) CVadAdapterCommon::UnregisterSubdevice(_In_opt_ PUNKNOWN UnknownPort)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::UnregisterSubdevice]"));
|
|
|
|
ASSERT(m_pDeviceObject != NULL);
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PUNREGISTERSUBDEVICE unregisterSubdevice = NULL;
|
|
|
|
if (NULL == UnknownPort)
|
|
{
|
|
return ntStatus;
|
|
}
|
|
|
|
ntStatus = UnknownPort->QueryInterface(
|
|
IID_IUnregisterSubdevice,
|
|
(PVOID *)&unregisterSubdevice);
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ntStatus = unregisterSubdevice->UnregisterSubdevice(m_pDeviceObject, UnknownPort);
|
|
unregisterSubdevice->Release();
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(NTSTATUS) CVadAdapterCommon::ConnectTopologies
|
|
(
|
|
_In_ PUNKNOWN UnknownTopology,
|
|
_In_ PUNKNOWN UnknownWave,
|
|
_In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
|
|
_In_ ULONG PhysicalConnectionCount
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::ConnectTopologies]"));
|
|
|
|
ASSERT(m_pDeviceObject != NULL);
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
for (ULONG i = 0; i < PhysicalConnectionCount && NT_SUCCESS(ntStatus); i++)
|
|
{
|
|
switch (PhysicalConnections[i].eType)
|
|
{
|
|
case CONNECTIONTYPE_TOPOLOGY_OUTPUT:
|
|
ntStatus = PcRegisterPhysicalConnection(
|
|
m_pDeviceObject,
|
|
UnknownTopology,
|
|
PhysicalConnections[i].ulTopology,
|
|
UnknownWave,
|
|
PhysicalConnections[i].ulWave);
|
|
break;
|
|
case CONNECTIONTYPE_WAVE_OUTPUT:
|
|
ntStatus = PcRegisterPhysicalConnection(
|
|
m_pDeviceObject,
|
|
UnknownWave,
|
|
PhysicalConnections[i].ulWave,
|
|
UnknownTopology,
|
|
PhysicalConnections[i].ulTopology);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(ntStatus))
|
|
{
|
|
DisconnectTopologies(UnknownTopology, UnknownWave, PhysicalConnections, PhysicalConnectionCount);
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(NTSTATUS) CVadAdapterCommon::DisconnectTopologies
|
|
(
|
|
_In_ PUNKNOWN UnknownTopology,
|
|
_In_ PUNKNOWN UnknownWave,
|
|
_In_ PHYSICALCONNECTIONTABLE* PhysicalConnections,
|
|
_In_ ULONG PhysicalConnectionCount
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::DisconnectTopologies]"));
|
|
|
|
ASSERT(m_pDeviceObject != NULL);
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
NTSTATUS ntStatus2 = STATUS_SUCCESS;
|
|
PUNREGISTERPHYSICALCONNECTION unregisterPhysicalConnection = NULL;
|
|
|
|
ntStatus = UnknownTopology->QueryInterface(
|
|
IID_IUnregisterPhysicalConnection,
|
|
(PVOID *)&unregisterPhysicalConnection);
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
for (ULONG i = 0; i < PhysicalConnectionCount; i++)
|
|
{
|
|
switch (PhysicalConnections[i].eType)
|
|
{
|
|
case CONNECTIONTYPE_TOPOLOGY_OUTPUT:
|
|
ntStatus2 = unregisterPhysicalConnection->UnregisterPhysicalConnection(
|
|
m_pDeviceObject,
|
|
UnknownTopology,
|
|
PhysicalConnections[i].ulTopology,
|
|
UnknownWave,
|
|
PhysicalConnections[i].ulWave);
|
|
break;
|
|
case CONNECTIONTYPE_WAVE_OUTPUT:
|
|
ntStatus2 = unregisterPhysicalConnection->UnregisterPhysicalConnection(
|
|
m_pDeviceObject,
|
|
UnknownWave,
|
|
PhysicalConnections[i].ulWave,
|
|
UnknownTopology,
|
|
PhysicalConnections[i].ulTopology);
|
|
break;
|
|
}
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ntStatus = ntStatus2;
|
|
}
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE(unregisterPhysicalConnection);
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
// Sub-device cache
|
|
//=============================================================================
|
|
|
|
#pragma code_seg("PAGE")
|
|
NTSTATUS CVadAdapterCommon::GetCachedSubdevice(
|
|
_In_ PWSTR Name,
|
|
_Out_opt_ PUNKNOWN *OutUnknownPort,
|
|
_Out_opt_ PUNKNOWN *OutUnknownMiniport
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
PLIST_ENTRY le = NULL;
|
|
BOOL bFound = FALSE;
|
|
|
|
for (le = m_SubdeviceCache.Flink; le != &m_SubdeviceCache && !bFound; le = le->Flink)
|
|
{
|
|
MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
|
|
if (0 == wcscmp(Name, pRecord->Name))
|
|
{
|
|
if (OutUnknownPort)
|
|
{
|
|
*OutUnknownPort = pRecord->PortInterface;
|
|
(*OutUnknownPort)->AddRef();
|
|
}
|
|
if (OutUnknownMiniport)
|
|
{
|
|
*OutUnknownMiniport = pRecord->MiniportInterface;
|
|
(*OutUnknownMiniport)->AddRef();
|
|
}
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
|
|
return bFound ? STATUS_SUCCESS : STATUS_OBJECT_NAME_NOT_FOUND;
|
|
}
|
|
|
|
#pragma code_seg("PAGE")
|
|
NTSTATUS CVadAdapterCommon::CacheSubdevice(
|
|
_In_ PWSTR Name,
|
|
_In_ PUNKNOWN UnknownPort,
|
|
_In_ PUNKNOWN UnknownMiniport
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
MINIPAIR_UNKNOWN *pNewSubdevice = NULL;
|
|
|
|
pNewSubdevice = new(POOL_FLAG_NON_PAGED, VAD_ADAPTER_POOLTAG) MINIPAIR_UNKNOWN;
|
|
if (!pNewSubdevice)
|
|
{
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
memset(pNewSubdevice, 0, sizeof(MINIPAIR_UNKNOWN));
|
|
ntStatus = RtlStringCchCopyW(pNewSubdevice->Name, SIZEOF_ARRAY(pNewSubdevice->Name), Name);
|
|
}
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
pNewSubdevice->PortInterface = UnknownPort;
|
|
pNewSubdevice->PortInterface->AddRef();
|
|
pNewSubdevice->MiniportInterface = UnknownMiniport;
|
|
pNewSubdevice->MiniportInterface->AddRef();
|
|
UnknownMiniport->QueryInterface(IID_IAdapterPowerManagement, (PVOID *)&(pNewSubdevice->PowerInterface));
|
|
InsertTailList(&m_SubdeviceCache, &pNewSubdevice->ListEntry);
|
|
}
|
|
|
|
if (!NT_SUCCESS(ntStatus))
|
|
{
|
|
if (pNewSubdevice)
|
|
{
|
|
delete pNewSubdevice;
|
|
}
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
#pragma code_seg("PAGE")
|
|
NTSTATUS CVadAdapterCommon::RemoveCachedSubdevice(_In_ PWSTR Name)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
PLIST_ENTRY le = NULL;
|
|
BOOL bRemoved = FALSE;
|
|
|
|
for (le = m_SubdeviceCache.Flink; le != &m_SubdeviceCache && !bRemoved; le = le->Flink)
|
|
{
|
|
MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
|
|
if (0 == wcscmp(Name, pRecord->Name))
|
|
{
|
|
SAFE_RELEASE(pRecord->PortInterface);
|
|
SAFE_RELEASE(pRecord->MiniportInterface);
|
|
SAFE_RELEASE(pRecord->PowerInterface);
|
|
memset(pRecord->Name, 0, sizeof(pRecord->Name));
|
|
RemoveEntryList(le);
|
|
bRemoved = TRUE;
|
|
delete pRecord;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bRemoved ? STATUS_SUCCESS : STATUS_OBJECT_NAME_NOT_FOUND;
|
|
}
|
|
|
|
#pragma code_seg("PAGE")
|
|
VOID CVadAdapterCommon::EmptySubdeviceCache()
|
|
{
|
|
PAGED_CODE();
|
|
|
|
while (!IsListEmpty(&m_SubdeviceCache))
|
|
{
|
|
PLIST_ENTRY le = RemoveHeadList(&m_SubdeviceCache);
|
|
MINIPAIR_UNKNOWN *pRecord = CONTAINING_RECORD(le, MINIPAIR_UNKNOWN, ListEntry);
|
|
SAFE_RELEASE(pRecord->PortInterface);
|
|
SAFE_RELEASE(pRecord->MiniportInterface);
|
|
SAFE_RELEASE(pRecord->PowerInterface);
|
|
memset(pRecord->Name, 0, sizeof(pRecord->Name));
|
|
delete pRecord;
|
|
}
|
|
}
|
|
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(VOID) CVadAdapterCommon::Cleanup()
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::Cleanup]"));
|
|
EmptySubdeviceCache();
|
|
}
|
|
|
|
//=============================================================================
|
|
// InstallEndpointFilters
|
|
//=============================================================================
|
|
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CVadAdapterCommon::InstallEndpointFilters
|
|
(
|
|
_In_opt_ PIRP Irp,
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_In_opt_ PVOID DeviceContext,
|
|
_Out_opt_ PUNKNOWN * UnknownTopology,
|
|
_Out_opt_ PUNKNOWN * UnknownWave,
|
|
_Out_opt_ PUNKNOWN * UnknownMiniportTopology,
|
|
_Out_opt_ PUNKNOWN * UnknownMiniportWave
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::InstallEndpointFilters]"));
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PUNKNOWN unknownTopology = NULL;
|
|
PUNKNOWN unknownWave = NULL;
|
|
BOOL bTopologyCreated = FALSE;
|
|
BOOL bWaveCreated = FALSE;
|
|
PUNKNOWN unknownMiniTopo = NULL;
|
|
PUNKNOWN unknownMiniWave = NULL;
|
|
|
|
if (UnknownTopology) { *UnknownTopology = NULL; }
|
|
if (UnknownWave) { *UnknownWave = NULL; }
|
|
if (UnknownMiniportTopology) { *UnknownMiniportTopology = NULL; }
|
|
if (UnknownMiniportWave) { *UnknownMiniportWave = NULL; }
|
|
|
|
ntStatus = GetCachedSubdevice(MiniportPair->TopoName, &unknownTopology, &unknownMiniTopo);
|
|
if (!NT_SUCCESS(ntStatus) || NULL == unknownTopology || NULL == unknownMiniTopo)
|
|
{
|
|
bTopologyCreated = TRUE;
|
|
|
|
ntStatus = InstallSubdevice(Irp,
|
|
MiniportPair->TopoName,
|
|
CLSID_PortTopology,
|
|
CLSID_PortTopology,
|
|
MiniportPair->TopoCreateCallback,
|
|
MiniportPair->TopoInterfacePropertyCount,
|
|
MiniportPair->TopoInterfaceProperties,
|
|
DeviceContext,
|
|
MiniportPair,
|
|
NULL,
|
|
IID_IPortTopology,
|
|
NULL,
|
|
&unknownTopology,
|
|
&unknownMiniTopo);
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ntStatus = CacheSubdevice(MiniportPair->TopoName, unknownTopology, unknownMiniTopo);
|
|
}
|
|
}
|
|
|
|
ntStatus = GetCachedSubdevice(MiniportPair->WaveName, &unknownWave, &unknownMiniWave);
|
|
if (!NT_SUCCESS(ntStatus) || NULL == unknownWave || NULL == unknownMiniWave)
|
|
{
|
|
bWaveCreated = TRUE;
|
|
|
|
ntStatus = InstallSubdevice(Irp,
|
|
MiniportPair->WaveName,
|
|
CLSID_PortWaveRT,
|
|
CLSID_PortWaveRT,
|
|
MiniportPair->WaveCreateCallback,
|
|
MiniportPair->WaveInterfacePropertyCount,
|
|
MiniportPair->WaveInterfaceProperties,
|
|
DeviceContext,
|
|
MiniportPair,
|
|
NULL,
|
|
IID_IPortWaveRT,
|
|
NULL,
|
|
&unknownWave,
|
|
&unknownMiniWave);
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
ntStatus = CacheSubdevice(MiniportPair->WaveName, unknownWave, unknownMiniWave);
|
|
}
|
|
}
|
|
|
|
if (unknownTopology && unknownWave)
|
|
{
|
|
ntStatus = ConnectTopologies(
|
|
unknownTopology,
|
|
unknownWave,
|
|
MiniportPair->PhysicalConnections,
|
|
MiniportPair->PhysicalConnectionCount);
|
|
}
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
if (UnknownTopology != NULL && unknownTopology != NULL)
|
|
{
|
|
unknownTopology->AddRef();
|
|
*UnknownTopology = unknownTopology;
|
|
}
|
|
if (UnknownWave != NULL && unknownWave != NULL)
|
|
{
|
|
unknownWave->AddRef();
|
|
*UnknownWave = unknownWave;
|
|
}
|
|
if (UnknownMiniportTopology != NULL && unknownMiniTopo != NULL)
|
|
{
|
|
unknownMiniTopo->AddRef();
|
|
*UnknownMiniportTopology = unknownMiniTopo;
|
|
}
|
|
if (UnknownMiniportWave != NULL && unknownMiniWave != NULL)
|
|
{
|
|
unknownMiniWave->AddRef();
|
|
*UnknownMiniportWave = unknownMiniWave;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bTopologyCreated && unknownTopology != NULL)
|
|
{
|
|
UnregisterSubdevice(unknownTopology);
|
|
RemoveCachedSubdevice(MiniportPair->TopoName);
|
|
}
|
|
if (bWaveCreated && unknownWave != NULL)
|
|
{
|
|
UnregisterSubdevice(unknownWave);
|
|
RemoveCachedSubdevice(MiniportPair->WaveName);
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE(unknownMiniTopo);
|
|
SAFE_RELEASE(unknownTopology);
|
|
SAFE_RELEASE(unknownMiniWave);
|
|
SAFE_RELEASE(unknownWave);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CVadAdapterCommon::RemoveEndpointFilters
|
|
(
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_In_opt_ PUNKNOWN UnknownTopology,
|
|
_In_opt_ PUNKNOWN UnknownWave
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::RemoveEndpointFilters]"));
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
if (UnknownTopology != NULL && UnknownWave != NULL)
|
|
{
|
|
ntStatus = DisconnectTopologies(
|
|
UnknownTopology,
|
|
UnknownWave,
|
|
MiniportPair->PhysicalConnections,
|
|
MiniportPair->PhysicalConnectionCount);
|
|
|
|
UnregisterSubdevice(UnknownWave);
|
|
RemoveCachedSubdevice(MiniportPair->WaveName);
|
|
|
|
UnregisterSubdevice(UnknownTopology);
|
|
RemoveCachedSubdevice(MiniportPair->TopoName);
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CVadAdapterCommon::GetFilters
|
|
(
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_Out_opt_ PUNKNOWN *UnknownTopologyPort,
|
|
_Out_opt_ PUNKNOWN *UnknownTopologyMiniport,
|
|
_Out_opt_ PUNKNOWN *UnknownWavePort,
|
|
_Out_opt_ PUNKNOWN *UnknownWaveMiniport
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::GetFilters]"));
|
|
|
|
NTSTATUS ntStatus;
|
|
PUNKNOWN unknownTopoPort = NULL;
|
|
PUNKNOWN unknownTopoMiniport = NULL;
|
|
PUNKNOWN unknownWavePort = NULL;
|
|
PUNKNOWN unknownWaveMiniport = NULL;
|
|
|
|
ntStatus = GetCachedSubdevice(MiniportPair->TopoName, &unknownTopoPort, &unknownTopoMiniport);
|
|
if (!NT_SUCCESS(ntStatus))
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
ntStatus = GetCachedSubdevice(MiniportPair->WaveName, &unknownWavePort, &unknownWaveMiniport);
|
|
if (!NT_SUCCESS(ntStatus))
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
if (UnknownTopologyPort && unknownTopoPort)
|
|
{
|
|
unknownTopoPort->AddRef();
|
|
*UnknownTopologyPort = unknownTopoPort;
|
|
}
|
|
if (UnknownTopologyMiniport && unknownTopoMiniport)
|
|
{
|
|
unknownTopoMiniport->AddRef();
|
|
*UnknownTopologyMiniport = unknownTopoMiniport;
|
|
}
|
|
if (UnknownWavePort && unknownWavePort)
|
|
{
|
|
unknownWavePort->AddRef();
|
|
*UnknownWavePort = unknownWavePort;
|
|
}
|
|
if (UnknownWaveMiniport && unknownWaveMiniport)
|
|
{
|
|
unknownWaveMiniport->AddRef();
|
|
*UnknownWaveMiniport = unknownWaveMiniport;
|
|
}
|
|
|
|
Done:
|
|
SAFE_RELEASE(unknownTopoPort);
|
|
SAFE_RELEASE(unknownTopoMiniport);
|
|
SAFE_RELEASE(unknownWavePort);
|
|
SAFE_RELEASE(unknownWaveMiniport);
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
//=============================================================================
|
|
#pragma code_seg("PAGE")
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CVadAdapterCommon::SetIdlePowerManagement
|
|
(
|
|
_In_ PENDPOINT_MINIPAIR MiniportPair,
|
|
_In_ BOOL bEnabled
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
DPF_ENTER(("[CVadAdapterCommon::SetIdlePowerManagement]"));
|
|
|
|
UNREFERENCED_PARAMETER(MiniportPair);
|
|
UNREFERENCED_PARAMETER(bEnabled);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#pragma code_seg()
|