You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1029 lines
26 KiB
1029 lines
26 KiB
/////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
#include "precomp.h"
|
|
|
|
#include <aclapi.h>
|
|
#include <groupsforuser.h>
|
|
#include <sql_1.h>
|
|
#include <flexq.h>
|
|
|
|
static CFlexArray g_apRequests; // Shared between all CWMIEvent instances to provide a master event list
|
|
|
|
extern CCriticalSection * g_pEventCs;
|
|
extern CCriticalSection * g_pListCs;
|
|
|
|
#include <helper.h>
|
|
|
|
typedef WaitExceptionPtrFnc < CCriticalSection*, void ( CCriticalSection::* ) (), CCriticalSection::Enter, 1000 > EnterCS;
|
|
typedef LeavePtrFnc < CCriticalSection*, void ( CCriticalSection::* ) (), CCriticalSection::Leave > LeaveCS;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
class CFlexQueueEx : public CFlexQueue
|
|
{
|
|
public:
|
|
|
|
void ResetQueue()
|
|
{
|
|
delete [] m_ppData;
|
|
m_ppData = NULL;
|
|
m_nSize = m_nHeadIndex = m_nTailIndex = 0;
|
|
}
|
|
};
|
|
|
|
CFlexQueueEx Q;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void WINAPI EventCallbackRoutine(PWNODE_HEADER WnodeHeader, ULONG_PTR Context)
|
|
{
|
|
HRESULT hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
|
|
bool bQueued = FALSE;
|
|
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
try
|
|
{
|
|
PWNODE_HEADER * pEventHeader = NULL;
|
|
|
|
//scope the use of the critsec...
|
|
{
|
|
CAutoBlock block (g_pListCs);
|
|
// Create a queue
|
|
pEventHeader = new PWNODE_HEADER;
|
|
if( pEventHeader )
|
|
{
|
|
*pEventHeader = WnodeHeader;
|
|
bQueued = Q.Enqueue(pEventHeader);
|
|
}
|
|
}
|
|
|
|
//
|
|
// The following code will be rarely called when the Queue
|
|
// does not grow due to memory exhaustion.
|
|
//
|
|
|
|
if( FALSE == bQueued ) {
|
|
((CWMIEvent*) Context)->WMIEventCallback(*pEventHeader);
|
|
delete pEventHeader;
|
|
}
|
|
|
|
while( TRUE )
|
|
{
|
|
//scope the use of the critsec...
|
|
{
|
|
CAutoBlock block( g_pListCs );
|
|
|
|
if( Q.GetQueueSize() == 0 )
|
|
{
|
|
Q.ResetQueue();
|
|
break;
|
|
}
|
|
|
|
pEventHeader = (PWNODE_HEADER *) Q.Dequeue();
|
|
if (pEventHeader == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
CWMIEvent * p = (CWMIEvent* ) Context;
|
|
p->WMIEventCallback(*pEventHeader);
|
|
}
|
|
}
|
|
catch( ... )
|
|
{
|
|
//don't throw outside of the provider, also make sure CoUninitialize happens...
|
|
}
|
|
|
|
CoUninitialize();
|
|
}
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
void CWMIEvent::SetEventHandler(IWbemObjectSink __RPC_FAR * pHandler)
|
|
{
|
|
CAutoBlock Block(g_pEventCs);
|
|
|
|
if( m_pEventHandler )
|
|
{
|
|
m_pEventHandler->Release();
|
|
}
|
|
|
|
m_pEventHandler = pHandler;
|
|
if( m_pEventHandler )
|
|
{
|
|
m_pEventHandler->AddRef();
|
|
}
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
void CWMIEvent::SetEventServices(IWbemServices __RPC_FAR * pServices)
|
|
{
|
|
CAutoBlock Block(g_pEventCs);
|
|
|
|
if( m_pEventServices )
|
|
{
|
|
m_pEventServices->Release();
|
|
}
|
|
m_pEventServices = pServices;
|
|
if( m_pEventServices )
|
|
{
|
|
m_pEventServices->AddRef();
|
|
}
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
void CWMIEvent::SetEventRepository(IWbemServices __RPC_FAR * pServices)
|
|
{
|
|
CAutoBlock Block(g_pEventCs);
|
|
|
|
if( m_pEventRepository )
|
|
{
|
|
m_pEventRepository->Release();
|
|
}
|
|
m_pEventRepository = pServices;
|
|
if( m_pEventRepository )
|
|
{
|
|
m_pEventRepository->AddRef();
|
|
}
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
void CWMIEvent::SetEventContext(IWbemContext __RPC_FAR * pCtx)
|
|
{
|
|
CAutoBlock Block(g_pEventCs);
|
|
|
|
if( m_pEventCtx )
|
|
{
|
|
m_pEventCtx->Release();
|
|
}
|
|
m_pEventCtx = pCtx;
|
|
if( m_pEventCtx )
|
|
{
|
|
m_pEventCtx->AddRef();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
CWMIEvent::CWMIEvent(int nType) :
|
|
m_nType ( nType ) ,
|
|
m_pEventHandler ( NULL ) ,
|
|
m_pEventServices ( NULL ) ,
|
|
m_pEventRepository ( NULL ) ,
|
|
m_pEventCtx ( NULL ) ,
|
|
m_bInitialized ( FALSE )
|
|
{
|
|
if ( TRUE == ( m_bInitialized = m_HandleMap.IsValid () ) )
|
|
{
|
|
m_lRef = 0;
|
|
|
|
if( m_nType != INTERNAL_EVENT )
|
|
{
|
|
InterlockedIncrement(&g_cObj);
|
|
}
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
CWMIEvent::~CWMIEvent()
|
|
{
|
|
if ( m_bInitialized )
|
|
{
|
|
ReleaseAllPointers ();
|
|
|
|
if( m_nType != INTERNAL_EVENT )
|
|
{
|
|
InterlockedDecrement(&g_cObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CWMIEvent::ReleaseAllPointers()
|
|
{
|
|
|
|
IWbemObjectSink * pHandler = NULL;
|
|
IWbemServices * pServices = NULL;
|
|
IWbemServices * pRepository = NULL;
|
|
IWbemContext * pCtx = NULL;
|
|
|
|
{
|
|
CAutoBlock Block(g_pEventCs);
|
|
pHandler = m_pEventHandler;
|
|
pServices = m_pEventServices;
|
|
pRepository = m_pEventRepository;
|
|
pCtx = m_pEventCtx;
|
|
|
|
m_pEventCtx = NULL;
|
|
m_pEventServices = NULL;
|
|
m_pEventRepository = NULL;
|
|
m_pEventHandler = NULL;
|
|
}
|
|
|
|
|
|
SAFE_RELEASE_PTR( pHandler );
|
|
SAFE_RELEASE_PTR( pServices );
|
|
SAFE_RELEASE_PTR( pRepository );
|
|
SAFE_RELEASE_PTR( pCtx );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOL CWMIEvent::RegisterForInternalEvents( )
|
|
{
|
|
BOOL fRc = FALSE;
|
|
|
|
if( SUCCEEDED(RegisterForRequestedEvent(BINARY_MOF_ID,RUNTIME_BINARY_MOFS_ADDED,MOF_ADDED)))
|
|
{
|
|
if( SUCCEEDED(RegisterForRequestedEvent(BINARY_MOF_ID,RUNTIME_BINARY_MOFS_DELETED,MOF_DELETED)))
|
|
{
|
|
fRc = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( FALSE == fRc )
|
|
{
|
|
//
|
|
// must clear global object so next
|
|
// initialization will have a chance
|
|
//
|
|
|
|
DeleteBinaryMofResourceEvent () ;
|
|
}
|
|
|
|
return fRc;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
HRESULT CWMIEvent::RemoveWMIEvent(DWORD dwId)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if( m_nType == WMIEVENT )
|
|
{
|
|
hr = CheckImpersonationLevel();
|
|
}
|
|
else
|
|
{
|
|
HRESULT t_TempResult = RevertToSelf();
|
|
#ifdef DBG
|
|
if ( FAILED ( t_TempResult ) )
|
|
{
|
|
DebugBreak();
|
|
}
|
|
#endif DBG
|
|
}
|
|
|
|
if( SUCCEEDED(hr))
|
|
{
|
|
CWMIManagement WMI;
|
|
|
|
EnterCS ecs ( g_pEventCs );
|
|
LeaveCS lcs ( g_pEventCs );
|
|
|
|
// ================================
|
|
// Remove all requests with this Id
|
|
// ================================
|
|
int nSize = g_apRequests.Size();
|
|
int i = 0;
|
|
|
|
while( i < nSize )
|
|
{
|
|
WMIEventRequest* pReq = (WMIEventRequest*) g_apRequests[i];
|
|
|
|
//
|
|
// we are about to remove standard events in this call
|
|
// that means we must skip hardcoded handles
|
|
//
|
|
if( ( !IsBinaryMofResourceEvent ( WMI_RESOURCE_MOF_ADDED_GUID,pReq->gGuid ) ) &&
|
|
( !IsBinaryMofResourceEvent ( WMI_RESOURCE_MOF_REMOVED_GUID,pReq->gGuid ) ) )
|
|
{
|
|
if(pReq->dwId == dwId)
|
|
{
|
|
g_apRequests.RemoveAt(i);
|
|
|
|
//
|
|
// leave critical section as the same critical
|
|
// section is used inside of the event callback
|
|
//
|
|
|
|
//
|
|
// left mark for scope deletion of lcs FALSE
|
|
// as we will re-enter the same critical section
|
|
//
|
|
// CancelWMIEventRegistartion nor
|
|
// NoMoreEventConsumersRegistered doesn't throw exception !
|
|
//
|
|
|
|
lcs.Exec( FALSE );
|
|
|
|
// Inform WMI we don't want this anymore as
|
|
// long as there are no more these guids in
|
|
// the list, there might be more than one
|
|
// event consumer registered.
|
|
// =========================================
|
|
|
|
//
|
|
// check agains 0 as we have removed from list already
|
|
//
|
|
|
|
if( NoMoreEventConsumersRegistered( pReq->gGuid ) == 0 )
|
|
{
|
|
ULONG_PTR uRc =(ULONG_PTR)this;
|
|
WMI.CancelWMIEventRegistration(pReq->gGuid,uRc);
|
|
}
|
|
|
|
delete pReq;
|
|
pReq = NULL;
|
|
|
|
//
|
|
// re-enter the same critical section here
|
|
// its flag of execution is FALSE which means
|
|
// that it will be left final time by destructor
|
|
// of LeaveCS data type ( lcs )
|
|
//
|
|
EnterCS ecs1 ( g_pEventCs );
|
|
|
|
nSize = g_apRequests.Size();
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
CheckImpersonationLevel();
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
HRESULT CWMIEvent::DeleteBinaryMofResourceEvent()
|
|
{
|
|
HRESULT t_TempResult = RevertToSelf();
|
|
#ifdef DBG
|
|
if ( FAILED ( t_TempResult ) )
|
|
{
|
|
DebugBreak();
|
|
}
|
|
#endif DBG
|
|
|
|
CWMIManagement WMI;
|
|
|
|
EnterCS ecs ( g_pEventCs );
|
|
LeaveCS lcs ( g_pEventCs );
|
|
|
|
// Remove all requests with this Id
|
|
// ================================
|
|
int nSize = g_apRequests.Size();
|
|
int i = 0;
|
|
|
|
while( i < nSize ){
|
|
|
|
WMIEventRequest* pReq = (WMIEventRequest*) g_apRequests[i];
|
|
|
|
if( ( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_ADDED_GUID,pReq->gGuid)) ||
|
|
( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_REMOVED_GUID,pReq->gGuid)))
|
|
{
|
|
g_apRequests.RemoveAt(i);
|
|
|
|
//
|
|
// leave critical section as the same critical
|
|
// section is used inside of the event callback
|
|
//
|
|
|
|
//
|
|
// left mark for scope deletion of lcs FALSE
|
|
// as we will re-enter the same critical section
|
|
//
|
|
// CancelWMIEventRegistartion doesn't throw exception !
|
|
//
|
|
|
|
lcs.Exec( FALSE );
|
|
|
|
ULONG_PTR uRc =(ULONG_PTR)this;
|
|
WMI.CancelWMIEventRegistration(pReq->gGuid,uRc);
|
|
|
|
delete pReq;
|
|
pReq = NULL;
|
|
|
|
//
|
|
// re-enter the same critical section here
|
|
// its flag of execution is FALSE which means
|
|
// that it will be left final time by destructor
|
|
// of LeaveCS data type ( lcs )
|
|
//
|
|
EnterCS ecs1 ( g_pEventCs );
|
|
|
|
nSize = g_apRequests.Size();
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
CheckImpersonationLevel();
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
int CWMIEvent::NoMoreEventConsumersRegistered(GUID gGuid)
|
|
{
|
|
EnterCS ecs(g_pEventCs);
|
|
LeaveCS lcs(g_pEventCs);
|
|
|
|
int nTotalNumberOfRegisteredEventConsumers = 0;
|
|
WMIEventRequest * pEvent;
|
|
|
|
for(int i = 0; i < g_apRequests.Size(); i++)
|
|
{
|
|
pEvent = (WMIEventRequest *) g_apRequests.GetAt(i);
|
|
if( pEvent->gGuid == gGuid)
|
|
{
|
|
nTotalNumberOfRegisteredEventConsumers++;
|
|
}
|
|
|
|
}
|
|
return nTotalNumberOfRegisteredEventConsumers;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOL CWMIEvent::IsGuidInListIfSoGetCorrectContext(GUID gGuid, WMIEventRequest *& pEvent )
|
|
{
|
|
EnterCS ecs(g_pEventCs);
|
|
LeaveCS lcs(g_pEventCs);
|
|
|
|
for( int i = 0; i < g_apRequests.Size(); i++ )
|
|
{
|
|
pEvent = (WMIEventRequest *) g_apRequests.GetAt(i);
|
|
if( pEvent->gGuid == gGuid){
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
pEvent = NULL;
|
|
return FALSE;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOL CWMIEvent::IsGuidInList(WCHAR * wcsGuid, WMIEventRequest *& pEvent)
|
|
{
|
|
EnterCS ecs(g_pEventCs);
|
|
LeaveCS lcs(g_pEventCs);
|
|
|
|
BOOL fRc = FALSE;
|
|
int Size = g_apRequests.Size();
|
|
|
|
for(int i =0 ; i < Size; i++ ){
|
|
|
|
pEvent = (WMIEventRequest *) g_apRequests.GetAt(i);
|
|
|
|
if( (_wcsicmp(pEvent->wcsGuid,wcsGuid)) == 0 ){
|
|
fRc = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return fRc;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
BOOL CWMIEvent::IsIndexInList ( WCHAR * wcsGuid, DWORD dwIndex )
|
|
{
|
|
EnterCS ecs(g_pEventCs);
|
|
LeaveCS lcs(g_pEventCs);
|
|
|
|
BOOL fRc = FALSE;
|
|
int Size = g_apRequests.Size();
|
|
|
|
for(int i =0 ; i < Size; i++ ){
|
|
|
|
WMIEventRequest* pEvent = (WMIEventRequest *) g_apRequests.GetAt(i);
|
|
|
|
if( (_wcsicmp(pEvent->wcsGuid,wcsGuid)) == 0 )
|
|
{
|
|
if ( pEvent->dwId == dwIndex )
|
|
{
|
|
fRc = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return fRc;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
HRESULT CWMIEvent::RegisterForRequestedEvent( DWORD dwId, WCHAR * wcsClass, WORD wType)
|
|
{
|
|
BOOL fRegistered = FALSE;
|
|
CWMIStandardShell WMI;
|
|
HRESULT hr = WBEM_E_ACCESS_DENIED;
|
|
BOOL fInternalEvent = TRUE;
|
|
if( wType == STANDARD_EVENT )
|
|
{
|
|
fInternalEvent = FALSE;
|
|
}
|
|
|
|
if( SUCCEEDED(WMI.Initialize (
|
|
wcsClass,
|
|
fInternalEvent,
|
|
&m_HandleMap,
|
|
TRUE,
|
|
WMIGUID_NOTIFICATION|WMIGUID_QUERY,
|
|
m_pEventServices,
|
|
m_pEventRepository,
|
|
m_pEventHandler,
|
|
m_pEventCtx
|
|
)))
|
|
{
|
|
|
|
if( m_nType == WMIEVENT )
|
|
{
|
|
hr = CheckImpersonationLevel();
|
|
}
|
|
else
|
|
{
|
|
HRESULT t_TempResult = RevertToSelf();
|
|
#ifdef DBG
|
|
if ( FAILED ( t_TempResult ) )
|
|
{
|
|
DebugBreak();
|
|
}
|
|
#endif DBG
|
|
|
|
hr = S_OK;
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
WCHAR wcsGuid[128];
|
|
|
|
hr = WMI.SetGuidForEvent( wType, wcsGuid, 128 );
|
|
if( SUCCEEDED(hr)){
|
|
|
|
WMIEventRequest * pAlreadyRegisteredEvent;
|
|
|
|
//===========================================================
|
|
// Keep a record of this guy, see if it is already registered
|
|
// if it is/isn't we call WDM with different flags
|
|
//===========================================================
|
|
fRegistered = IsGuidInList( wcsGuid, pAlreadyRegisteredEvent );
|
|
|
|
//===========================================================
|
|
// Register for the requested event
|
|
//===========================================================
|
|
ULONG_PTR uRc =(ULONG_PTR)this;
|
|
|
|
CLSID Guid;
|
|
hr = WMI.RegisterWMIEvent(wcsGuid,uRc,Guid,fRegistered);
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
BOOL bRegister = TRUE ;
|
|
if ( fRegistered )
|
|
{
|
|
//
|
|
// verify that there is no event request
|
|
// containing the index already in the global array
|
|
//
|
|
bRegister = !IsIndexInList ( wcsGuid, dwId ) ;
|
|
}
|
|
|
|
if ( bRegister )
|
|
{
|
|
//=======================================================
|
|
// If we succeeded, then add it to our list of events we
|
|
// are watching
|
|
//=======================================================
|
|
WMIEventRequest * pEvent = new WMIEventRequest;
|
|
if( pEvent ) {
|
|
pEvent->gGuid = Guid;
|
|
pEvent->dwId = dwId;
|
|
pEvent->fHardCoded = wType;
|
|
wcscpy( pEvent->wcsGuid,wcsGuid);
|
|
pEvent->SetClassName(wcsClass);
|
|
pEvent->AddPtrs(m_pEventHandler,m_pEventServices,m_pEventRepository,m_pEventCtx);
|
|
|
|
g_apRequests.Add(pEvent);
|
|
|
|
} else hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CheckImpersonationLevel();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
CWMIEventProvider::CWMIEventProvider(int nType) : CWMIEvent(nType)
|
|
{
|
|
if ( m_bInitialized )
|
|
{
|
|
m_hResyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
DEBUGTRACE((THISPROVIDER,"Event Provider constructed\n"));
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((THISPROVIDER,"Event Provider construction failed\n"));
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
CWMIEventProvider::~CWMIEventProvider()
|
|
{
|
|
if ( m_bInitialized )
|
|
{
|
|
UnInitializeProvider ( ) ;
|
|
|
|
DEBUGTRACE((THISPROVIDER,"No longer registered for WDM events\n"));
|
|
DEBUGTRACE((THISPROVIDER,"Event Provider denstructed\n"));
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CWMIEventProvider::QueryInterface(REFIID riid, void** ppv)
|
|
{
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
*ppv = NULL;
|
|
|
|
if(riid == IID_IUnknown)
|
|
{
|
|
*ppv = this;
|
|
}
|
|
else
|
|
if(riid == IID_IWbemEventProvider)
|
|
{
|
|
*ppv = (IWbemEventProvider*)this;
|
|
}
|
|
else if(riid == IID_IWbemEventProviderQuerySink)
|
|
{
|
|
*ppv = (IWbemEventProviderQuerySink*)this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IWbemProviderInit))
|
|
{
|
|
*ppv = (IWbemProviderInit *) this ;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IWbemEventProviderSecurity))
|
|
{
|
|
*ppv = (IWbemEventProviderSecurity *) this ;
|
|
}
|
|
|
|
if( *ppv)
|
|
{
|
|
AddRef();
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
ULONG STDMETHODCALLTYPE CWMIEventProvider::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_lRef);
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
ULONG STDMETHODCALLTYPE CWMIEventProvider::Release()
|
|
{
|
|
long lRef = InterlockedDecrement(&m_lRef);
|
|
|
|
if(lRef == 0){
|
|
//**********************************************
|
|
// reference count is zero, delete this object.
|
|
// and do all of the cleanup for this user,
|
|
//**********************************************
|
|
delete this ;
|
|
}
|
|
return lRef;
|
|
}
|
|
/////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CWMIEventProvider::Initialize(LPWSTR wszUser, long lFlags,
|
|
LPWSTR wszNamespace,
|
|
LPWSTR wszLocale,
|
|
IWbemServices* pNamespace,
|
|
IWbemContext* pCtx,
|
|
IWbemProviderInitSink* pSink)
|
|
{
|
|
HRESULT hr = WBEM_E_INVALID_PARAMETER;
|
|
if(pNamespace != NULL)
|
|
{
|
|
IWbemClassObject * pWMIClass = NULL;
|
|
if ( SUCCEEDED ( hr = pNamespace->GetObject(WMI_EVENT_CLASS, 0, NULL, &pWMIClass, NULL) ) )
|
|
{
|
|
hr = InitializeProvider (
|
|
wszNamespace,
|
|
wszLocale,
|
|
pNamespace,
|
|
pCtx,
|
|
pSink,
|
|
&m_HandleMap,
|
|
&m_pEventServices,
|
|
&m_pEventRepository,
|
|
&m_pEventCtx,
|
|
FALSE
|
|
) ;
|
|
}
|
|
|
|
SAFE_RELEASE_PTR(pWMIClass);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CWMIEventProvider::ProvideEvents(IWbemObjectSink __RPC_FAR *pSink,long lFlags)
|
|
{
|
|
EnterCS ecs(g_pEventCs);
|
|
LeaveCS lcs(g_pEventCs);
|
|
|
|
SetEventHandler(pSink);
|
|
|
|
// ===============================================================================
|
|
// Make sure any request added before this was called gets the updated handler
|
|
// PROVIDING it isn't the binary mof guid
|
|
// ===============================================================================
|
|
for(int i = 0; i < g_apRequests.Size(); i++)
|
|
{
|
|
WMIEventRequest* pReq = (WMIEventRequest*) g_apRequests[i];
|
|
if(!pReq->pHandler)
|
|
{
|
|
if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_ADDED_GUID,pReq->gGuid) ||
|
|
IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_REMOVED_GUID,pReq->gGuid) )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
if( !pReq->pHandler )
|
|
{
|
|
pReq->pHandler = pSink;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CWMIEventProvider::NewQuery( DWORD dwId, WBEM_WSTR wszLanguage, WBEM_WSTR wszQuery)
|
|
{
|
|
HRESULT hRes = WBEM_S_NO_ERROR;
|
|
|
|
if (_wcsicmp(wszLanguage, L"WQL") != 0)
|
|
{
|
|
hRes = WBEM_E_INVALID_QUERY_TYPE;
|
|
}
|
|
if( hRes == WBEM_S_NO_ERROR )
|
|
{
|
|
// Parse the query
|
|
// Construct the lex source
|
|
// ========================
|
|
CTextLexSource Source(wszQuery);
|
|
// Use the lex source to set up for parser
|
|
// =======================================
|
|
SQL1_Parser QueryParser(&Source);
|
|
|
|
SQL_LEVEL_1_RPN_EXPRESSION * pParse;
|
|
int ParseRetValue = QueryParser.Parse(&pParse);
|
|
if( SQL1_Parser::SUCCESS != ParseRetValue) {
|
|
hRes = WBEM_E_INVALID_QUERY;
|
|
}
|
|
else{
|
|
//Set the class
|
|
if( pParse )
|
|
{
|
|
hRes = RegisterForRequestedEvent(dwId,pParse->bsClassName,STANDARD_EVENT);
|
|
|
|
delete pParse;
|
|
pParse = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CWMIEventProvider::CancelQuery(DWORD dwId)
|
|
{
|
|
HRESULT hr = WBEM_E_FAILED;
|
|
hr = RemoveWMIEvent(dwId);
|
|
return hr;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
STDMETHODIMP CWMIEventProvider::AccessCheck(WBEM_CWSTR wszLanguage,
|
|
WBEM_CWSTR wszQuery,
|
|
long lSidLength,
|
|
const BYTE* aSid)
|
|
{
|
|
HRESULT hr = WBEM_E_ACCESS_DENIED;
|
|
|
|
//=======================================================
|
|
// Check platform
|
|
//=======================================================
|
|
if(!IsNT())
|
|
return WBEM_S_FALSE;
|
|
|
|
//=======================================================
|
|
// Check query language
|
|
//=======================================================
|
|
if (_wcsicmp(wszLanguage, L"WQL") != 0) {
|
|
return WBEM_E_INVALID_QUERY_TYPE;
|
|
}
|
|
|
|
//=======================================================
|
|
// If the PSid is NULL, then check impersonation level
|
|
// as usual - based on the thread
|
|
//=======================================================
|
|
|
|
PSID pSid = (PSID)aSid;
|
|
HANDLE hToken = NULL;
|
|
if(pSid == NULL){
|
|
//=================================================
|
|
// if this is the INTERNAL_EVENT class, then we
|
|
// do not want the local events set up again.
|
|
//=================================================
|
|
BOOL VerifyLocalEventsAreSetup = TRUE;
|
|
|
|
if( m_nType == INTERNAL_EVENT ){
|
|
VerifyLocalEventsAreSetup = FALSE;
|
|
}
|
|
|
|
hr = CheckImpersonationLevel() ;
|
|
}
|
|
else{
|
|
//=======================================================
|
|
// Parse the query
|
|
//=======================================================
|
|
CTextLexSource Source(wszQuery);
|
|
|
|
//=======================================================
|
|
// Use the lex source to set up for parser
|
|
//=======================================================
|
|
SQL1_Parser QueryParser(&Source);
|
|
|
|
SQL_LEVEL_1_RPN_EXPRESSION * pParse;
|
|
|
|
int ParseRetValue = QueryParser.Parse(&pParse);
|
|
if( SQL1_Parser::SUCCESS != ParseRetValue) {
|
|
return WBEM_E_INVALID_QUERY;
|
|
}
|
|
else{
|
|
if( pParse ){
|
|
|
|
CWMIStandardShell WMI;
|
|
if( SUCCEEDED(WMI.Initialize (
|
|
pParse->bsClassName,
|
|
FALSE,
|
|
&m_HandleMap,
|
|
TRUE,
|
|
WMIGUID_NOTIFICATION|WMIGUID_QUERY,
|
|
m_pEventServices,
|
|
m_pEventRepository,
|
|
m_pEventHandler,
|
|
m_pEventCtx
|
|
)))
|
|
{
|
|
CLSID * pGuid;
|
|
|
|
pGuid = WMI.GuidPtr();
|
|
if(pGuid != NULL)
|
|
{
|
|
//========================================
|
|
// Get the ACL
|
|
//========================================
|
|
PACL pDacl;
|
|
PSECURITY_DESCRIPTOR psd = NULL;
|
|
SE_OBJECT_TYPE ObjectType = SE_WMIGUID_OBJECT;
|
|
|
|
hr = WBEM_E_ACCESS_DENIED;
|
|
|
|
WCHAR * GuidName = NULL;
|
|
|
|
hr = UuidToString(pGuid, &GuidName);
|
|
if (hr == RPC_S_OK)
|
|
{
|
|
hr = S_OK;
|
|
DWORD dwRc = GetNamedSecurityInfo(GuidName,ObjectType,DACL_SECURITY_INFORMATION,NULL,NULL,&pDacl, NULL, &psd );
|
|
if( dwRc != ERROR_SUCCESS )
|
|
{
|
|
ERRORTRACE((THISPROVIDER, "GetNamedSecurityInfo returned %ld.\n", dwRc ));
|
|
hr = WBEM_E_ACCESS_DENIED;
|
|
}
|
|
}
|
|
if( GuidName )
|
|
{
|
|
RpcStringFree(&GuidName);
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
//====================================
|
|
// This is our own ACL walker
|
|
//====================================
|
|
|
|
DWORD dwAccessMask;
|
|
NTSTATUS st = GetAccessMask((PSID)pSid, pDacl, &dwAccessMask);
|
|
if(st)
|
|
{
|
|
ERRORTRACE((THISPROVIDER, "WDM event provider unable "
|
|
"to retrieve access mask for the creator of "
|
|
"registration %S: NT status %d.\n"
|
|
"Registration disabled\n", wszQuery,st));
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
if((dwAccessMask & WMIGUID_QUERY) == 0)
|
|
{
|
|
hr = WBEM_E_ACCESS_DENIED;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
m_nType = PERMANENT_EVENT;
|
|
}
|
|
}
|
|
if( psd != NULL)
|
|
{
|
|
AccFree( psd );
|
|
}
|
|
}
|
|
delete pParse;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////
|
|
void CWMIEvent::WMIEventCallback(PWNODE_HEADER WnodeHeader)
|
|
{
|
|
LPGUID EventGuid = &WnodeHeader->Guid;
|
|
|
|
ERRORTRACE((THISPROVIDER,"Received Event\n"));
|
|
//=======================================================
|
|
// We only support WNODE_FLAG_ALL_DATA and
|
|
// WNODE_FLAG_SINGLE_INSTANCE
|
|
//
|
|
// Parse thru whatever it is and send it off to HMOM
|
|
//=======================================================
|
|
if( WnodeHeader )
|
|
{
|
|
HRESULT hr;
|
|
WMIEventRequest * pEvent;
|
|
//===========================================================
|
|
// Make sure it is an event we want
|
|
//===========================================================
|
|
if( IsGuidInListIfSoGetCorrectContext( *EventGuid,pEvent))
|
|
{
|
|
|
|
CWMIStandardShell WMI;
|
|
//=======================================================
|
|
// See if a binary mof event is being added or deleted
|
|
//=======================================================
|
|
WORD wBinaryMofType = 0;
|
|
BOOL fInternalEvent = FALSE;
|
|
if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_ADDED_GUID,WnodeHeader->Guid))
|
|
{
|
|
fInternalEvent = TRUE;
|
|
wBinaryMofType = MOF_ADDED;
|
|
}
|
|
else if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_REMOVED_GUID,WnodeHeader->Guid))
|
|
{
|
|
fInternalEvent = TRUE;
|
|
wBinaryMofType = MOF_DELETED;
|
|
}
|
|
|
|
IWbemServices* pServices = NULL;
|
|
if( SUCCEEDED(pEvent->gipServices.Localize(&pServices)))
|
|
{
|
|
// release upon destruction
|
|
OnDeleteObj0 <IWbemServices, ULONG(__stdcall IWbemServices:: *)(), IWbemServices::Release> pServicesRelease (pServices);
|
|
|
|
IWbemServices* pRepository = NULL;
|
|
if( SUCCEEDED(pEvent->gipRepository.Localize(&pRepository)))
|
|
{
|
|
// release upon destruction
|
|
OnDeleteObj0 <IWbemServices, ULONG(__stdcall IWbemServices:: *)(), IWbemServices::Release> pRepositoryRelease (pRepository);
|
|
|
|
if( SUCCEEDED(WMI.Initialize (
|
|
pEvent->pwcsClass,
|
|
fInternalEvent,
|
|
&m_HandleMap,
|
|
TRUE,
|
|
WMIGUID_QUERY|WMIGUID_NOTIFICATION,
|
|
pServices,
|
|
pRepository,
|
|
pEvent->pHandler,
|
|
pEvent->pCtx
|
|
)))
|
|
{
|
|
//=======================================================
|
|
// If it was, then process it, otherwise go on... :)
|
|
//=======================================================
|
|
WMI.ProcessEvent(wBinaryMofType,WnodeHeader);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|