A DirectShow developer complained on sudden failure of Core Audio IMMDevice::Activate
call supposed to instantiate a DirectShow filter for a given device.
The problem appeared to be related to installed DirectShowSpy and its interference with the API calls. The symptom was of the following kind: when Activate
was called for different types of objects, the calls all succeeded except interoperation with DirectShow (activation for IBaseFilter
), e.g. EnumerateAudioDevices
output:
IAudioClient 0x00000000
IAudioEndpointVolume 0x00000000
IAudioMeterInformation 0x00000000
IAudioSessionManager 0x00000000
IAudioSessionManager2 0x00000000
IBaseFilter REGDB_E_CLASSNOTREG
IDeviceTopology 0x00000000
IMFTrustedOutput 0x00000000
When Core Audio is requested to do DirectShow activation, the API creates and instance of System Device Enumerator, which is forwarded the activation call to. DirectShowSpy intercepts these calls, however what it did not do was support for unknown COM interfaces, and support for undocumented IMMDeviceActivator
interface which is used internally by the APIs to forward the activation call.
So, System Device Enumerator implements documented ICreateDevEnum
and then it also implements undocumented internal IMMDeviceActivator
. The entire sequence call is as follows:
// Top level code:
CComPtr<IMMDevice> pDevice = ...; // Audio endpoint interface
pDevice->Activate(..., __uuidof(IBaseFilter), ...)
// API:
STDMETHOD(Activate)(...)
{
// ...
if(requested is IBaseFilter)
{
CComPtr<IMMDeviceActivator> pDeviceActivator;
pDeviceActivator.CoCreateInstace(CLSID_SystemDeviceEnum);
return pDeviceActivator->Activate(pDevice, ...)
}
DirectShowSpy’s failure to provide IMMDeviceActivator
resulted in symptom in question and is fixed with version 1.0.0.2106 and on. The failure code is not so much descriptive, but of course the APIs did not expect external hook and failure is not actually a supposed possible behavior there.
System Device Enumerator matches the known devices to the provided Core Audio device and creates an instance of respective filter – this is how APIs work together. DirectShowSpy prints these calls out to its log.
roatlbase.h(1582): TraceModuleVersion: "D:\...\DirectShowSpy-Win32.dll" version is 1.0.0.2107, running in "D:\...\EnumerateAudioDevices-Win32.exe" at 0x63210000
dllmain.h(36): CDirectShowSpyModule::CDirectShowSpyModule: this 0x633963A4
SystemDeviceEnumeratorSpy.h(669): CSystemDeviceEnumeratorSpyT<...>::CSystemDeviceEnumeratorSpyT: this 0x02F1DA68
SystemDeviceEnumeratorSpy.h(681): CSystemDeviceEnumeratorSpyT<...>::FinalConstruct: pszPath "D:\...\EnumerateAudioDevices-Win32.exe", this 0x02F1DA68, m_dwRef 1
SystemDeviceEnumeratorSpy.h(49): CSystemDeviceEnumeratorSpyT<...>::InternalQueryInterface: 0x02F1DA68, Interface {3B0D0EA4-D0A9-4B0E-935B-09516746FAC0}, Result 0x00000000
SystemDeviceEnumeratorSpy.h(49): CSystemDeviceEnumeratorSpyT<...>::InternalQueryInterface: 0x02F1DA68, Interface {3B0D0EA4-D0A9-4B0E-935B-09516746FAC0}, Result 0x00000000
SystemDeviceEnumeratorSpy.h(808): CSystemDeviceEnumeratorSpyT<...>::Activate: this 0x02F1DA68, InterfaceIdentifier {56A86895-0AD4-11CE-B03A-0020AF0BA770}, pMmDevice 0x0054E7F8
SystemDeviceEnumeratorSpy.h(815): CSystemDeviceEnumeratorSpyT<...>::Activate: nActivateResult 0x00000000
SystemDeviceEnumeratorSpy.h(673): CSystemDeviceEnumeratorSpyT<...>::~CSystemDeviceEnumeratorSpyT: this 0x02F1DA68
Download links
- Binaries:
- 32-bit: DirectShowSpy-Win32.dll (1.0.0.2107)
- 64-bit: DirectShowSpy-x64.dll (1.0.0.2106)
- Shortcuts to Exported Functions: Helper .BAT files
- License: This software is free to use
- Installation Instructions: Original post