#pragma option push -b -a8 -pc -A- /*P_O_Push*/ //// bpcsuspend.h - header file for interface that allows external apps // to request that the bpc video server release all of its devices and // shutdown its directshow graph. // USAGE: // in order to request that the bpc subsystem release its devices // create an instance of the CBPCSuspend class // to check if this succeeded use the IsBPCSuspended member function. if IsBPCSuspended returns false // then that means that there are active bpc video clients and you must treat this as you would a // device busy or device open type of failure. // when you are done with the devices destroy the CBPCSuspend class and this will notify vidsvr // that it can resume using the devices and return to background data capturing // // NOTE: you must compile vidsvr.odl and include the resulting .h before including this file // NOTE: you must have initialized com prior on this thread prior to using this object. // // CLSID_BPCSuspend comes from the header file generated from compiling vidsvr.odl // IBPCSuspended comes from the header file generated from compiling vidsvr.odl // theory of operation: // by using GetActiveObject instead of CoCreateInstance we don't force vidsvr to be loaded just to find // out that it wasn't running in the first place. // by returning an object that must be released to free the devices so that vidsvr can continue background // data capture we utilize COM to manage this resource. this means that if the external app that requested // the devices crashes or leaks then the suspension object will be automatically released and // vidsvr can resume using the devices without requiring a system reboot or some other unfriendly intervention. #ifndef _MSBPCVideo_H_ #error you must include the .h generated from compiling vidsvr.odl before including this file #endif #ifndef BPCSUSP_H #define BPCSUSP_H #pragma once #include #ifdef _CPPUNWIND #pragma message("bpcsusp.h using exceptions") #define BPCTRY try { #ifdef _DEBUG #define BPCCATCH } catch(...) { OutputDebugString("CBPCSuspend exception\r\n");} #else #define BPCCATCH } catch(...) {} #endif #define BPCNOTHROW throw() #else #define BPCTRY #define BPCCATCH #define BPCNOTHROW #endif class CBPCSuspend { IDispatch* m_pSuspended; bool m_fBPCExists; public: inline CBPCSuspend() BPCNOTHROW : m_pSuspended(NULL), m_fBPCExists(false) { BPCTRY #ifdef _DEBUG OutputDebugString("CBPCSuspend()::CBPCSuspend()\r\n"); TCHAR msgtemp[256]; #endif IUnknown *pUnkSuspendor = NULL; DWORD dwReserved; HRESULT hr = GetActiveObject(CLSID_BPCSuspend, &dwReserved, &pUnkSuspendor); if (SUCCEEDED(hr) && pUnkSuspendor) { IBPCSuspend *pSuspendor = NULL; hr = pUnkSuspendor->QueryInterface(IID_IBPCSuspend, reinterpret_cast(&pSuspendor)); pUnkSuspendor->Release(); if (SUCCEEDED(hr) && pSuspendor) { #ifdef _DEBUG OutputDebugString("CBPCSuspend()::CBPCSuspend() BPC exists\r\n"); #endif m_fBPCExists = true; hr = pSuspendor->DeviceRelease(0L, &m_pSuspended); if (FAILED(hr) || !m_pSuspended) { #ifdef _DEBUG wsprintf(msgtemp, "CBPCSuspend()::CBPCSuspend() Suspendor->DeviceRelease() rc = %lx\r\n", hr); OutputDebugString(msgtemp); #endif ASSERT(!m_pSuspended); } #ifdef _DEBUG else { wsprintf(msgtemp, "CBPCSuspend()::CBPCSuspend() BPC video server suspended\r\n"); OutputDebugString(msgtemp); } #endif pSuspendor->Release(); } } else { #ifdef _DEBUG wsprintf(msgtemp, "CBPCSuspend()::CBPCSuspend() GetActiveObject() rc = %lx\r\n", hr); OutputDebugString(msgtemp); #endif } BPCCATCH } inline ~CBPCSuspend() BPCNOTHROW { BPCTRY if (m_fBPCExists && m_pSuspended) { m_pSuspended->Release(); m_pSuspended = NULL; } BPCCATCH } inline bool IsBPCSuspended() BPCNOTHROW { // if m_fBPCExists but we weren't able to retrieve a suspension object then // there are active video clients and you must treat this as a device busy/failed to open type error if (m_fBPCExists && !m_pSuspended) { return false; } return true; } }; #endif // end of file - bpcsusp.h #pragma option pop /*P_O_Pop*/