Tuesday, May 27, 2008 9:38 AM
Maurits
Spot the Bug - IMFOutputSchema
I found a simple but nasty bug the other day in this implementation of the IMFOutputSchema interface.
The symptoms: running this code outside of a debugger caused the app to crash. Running it under a debugger (to catch the crash) caused the app to run clean.
// outputschema.h
HRESULT CreateTrustedAudioDriversOutputSchema(
DWORD dwConfigData,
GUID guidOriginatorID,
IMFOutputSchema **ppMFOutputSchema
);
// outputschema.cpp
// ... various include files removed ...
// CMFAttributesImpl implements the IMFAttributes interface, minus the IUnknown methods
class CTrustedAudioDriversOutputSchema : public CMFAttributesImpl<IMFOutputSchema> {
friend
HRESULT CreateTrustedAudioDriversOutputSchema(
DWORD dwConfigData,
GUID guidOriginatorID,
IMFOutputSchema **ppMFOutputSchema
);
private:
CTrustedAudioDriversOutputSchema(DWORD dwConfigData, GUID guidOriginatorID);
~CTrustedAudioDriversOutputSchema();
ULONG m_cRefCount;
DWORD m_dwConfigData;
GUID m_guidOriginatorID;
public:
// IUnknown methods
HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [out] */ LPVOID *ppvObject
);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IMFOutputSchema methods
HRESULT STDMETHODCALLTYPE GetConfigurationData(__out DWORD *pdwVal);
HRESULT STDMETHODCALLTYPE GetOriginatorID(__out GUID *pguidOriginatorID);
HRESULT STDMETHODCALLTYPE GetSchemaType(__out GUID *pguidSchemaType);
}; // CTrustedAudioDriversOutputSchema
HRESULT CreateTrustedAudioDriversOutputSchema(
DWORD dwConfigData,
GUID guidOriginatorID,
IMFOutputSchema **ppMFOutputSchema
) {
if (NULL == ppMFOutputSchema) {
return E_POINTER;
}
*ppMFOutputSchema = NULL;
CTrustedAudioDriversOutputSchema *pSchema =
new CTrustedAudioDriversOutputSchema(dwConfigData, guidOriginatorID);
if (NULL == pSchema) {
LOG(eError, _T("new CTrustedAudioDriversOutputSchema returned a NULL pointer"));
return E_OUTOFMEMORY;
}
*ppMFOutputSchema = static_cast<IMFOutputSchema *>(pSchema);
return S_OK;
} // CreateTrustedAudioDriversOutputSchema
// constructor
CTrustedAudioDriversOutputSchema::CTrustedAudioDriversOutputSchema(
DWORD dwConfigData, GUID guidOriginatorID
)
: m_dwConfigData(dwConfigData)
, m_guidOriginatorID(guidOriginatorID)
{}
// destructor
CTrustedAudioDriversOutputSchema::~CTrustedAudioDriversOutputSchema() {}
#define RETURN_INTERFACE(T, iid, ppOut) \
if (IsEqualIID(__uuidof(T), (iid))) { \
this->AddRef(); \
*(ppOut) = static_cast<T *>(this); \
return S_OK; \
} else {} (void)0
// IUnknown::QueryInterface
HRESULT STDMETHODCALLTYPE
CTrustedAudioDriversOutputSchema::QueryInterface(
/* [in] */ REFIID riid,
/* [out] */ LPVOID *ppvObject
) {
if (NULL == ppvObject) {
return E_POINTER;
}
*ppvObject = NULL;
RETURN_INTERFACE(IUnknown, riid, ppvObject);
RETURN_INTERFACE(IMFAttributes, riid, ppvObject);
RETURN_INTERFACE(IMFOutputSchema, riid, ppvObject);
return E_NOINTERFACE;
}
// IUnknown::AddRef
ULONG STDMETHODCALLTYPE
CTrustedAudioDriversOutputSchema::AddRef() {
ULONG uNewRefCount = InterlockedIncrement(&m_cRefCount);
return uNewRefCount;
}
// IUnknown::Release
ULONG STDMETHODCALLTYPE
CTrustedAudioDriversOutputSchema::Release() {
ULONG uNewRefCount = InterlockedDecrement(&m_cRefCount);
if (0 == uNewRefCount) {
delete this;
}
return uNewRefCount;
}
// IMFOutputSchema::GetConfigurationData
HRESULT STDMETHODCALLTYPE
CTrustedAudioDriversOutputSchema::GetConfigurationData(__out DWORD *pdwVal) {
LOG(eInfo1, _T("IMFOutputSchema::GetConfigurationData called"));
if (NULL == pdwVal) { return E_POINTER; }
*pdwVal = m_dwConfigData;
return S_OK;
}
// IMFOutputSchema::GetOriginatorID
HRESULT STDMETHODCALLTYPE
CTrustedAudioDriversOutputSchema::GetOriginatorID(__out GUID *pguidOriginatorID) {
LOG(eInfo1, _T("IMFOutputSchema::GetOriginatorID called"));
if (NULL == pguidOriginatorID) { return E_POINTER; }
*pguidOriginatorID = m_guidOriginatorID;
return S_OK;
}
// IMFOutputSchema::GetSchemaType
HRESULT STDMETHODCALLTYPE
CTrustedAudioDriversOutputSchema::GetSchemaType(__out GUID *pguidSchemaType) {
LOG(eInfo1, _T("IMFOutputSchema::GetSchemaType called"));
if (NULL == pguidSchemaType) { return E_POINTER; }
*pguidSchemaType = MFPROTECTION_TRUSTEDAUDIODRIVERS;
return S_OK;
}