Leaked source code of windows server 2003
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.
 
 
 
 
 
 

442 lines
10 KiB

#include "precomp.h"
#include <stdio.h>
#include <assert.h>
#include "fconnspc.h"
LPCWSTR g_wszConsumer = L"Consumer";
LPWSTR g_wszTarget = L"Target";
LPWSTR g_wszQueued = L"Queued";
LPWSTR g_wszTargetUsed = L"TargetUsed";
LPCWSTR g_wszStatusCode = L"StatusCode";
LPCWSTR g_wszExecutionId = L"ExecutionId";
LPWSTR g_wszTraceClass = L"MSFT_FCExecutedTraceEvent";
LPWSTR g_wszTargetTraceClass = L"MSFT_FCTargetTraceEvent";
LPWSTR g_wszEvents = L"Events";
LPCWSTR g_wszTraceProvider
= L"Microsoft WMI Forwarding Consumer Trace Event Provider";
LPCWSTR g_wszTraceSuccessQuery =
L"SELECT * FROM MSFT_FCTraceEventBase WHERE StatusCode <= 1";
LPCWSTR g_wszTraceFailureQuery =
L"SELECT * FROM MSFT_FCTraceEventBase WHERE StatusCode > 1";
/**************************************************************************
CFwdConsQuerySink - this implements the ProviderQuerySink. This would
normally be implemented by CFwdConsNamespace, but we'd end up with a
circular reference on the DES.
****************************************************************************/
class CFwdConsQuerySink
: public CUnkBase<IWbemEventProviderQuerySink,&IID_IWbemEventProviderQuerySink>
{
CFwdConsNamespace* m_pNspc; // doesn't hold ref.
public:
STDMETHOD(NewQuery)( DWORD dwId, LPWSTR wszLanguage, LPWSTR wszQuery )
{
return m_pNspc->NewQuery( dwId, wszQuery );
}
STDMETHOD(CancelQuery)( DWORD dwId )
{
return m_pNspc->CancelQuery( dwId );
}
CFwdConsQuerySink( CFwdConsNamespace* pNspc )
: CUnkBase< IWbemEventProviderQuerySink,
&IID_IWbemEventProviderQuerySink>(NULL), m_pNspc( pNspc ) {}
public:
static HRESULT Create( CFwdConsNamespace* pNspc,
IWbemEventProviderQuerySink** ppSink )
{
CWbemPtr<IWbemEventProviderQuerySink> pSink;
pSink = new CFwdConsQuerySink( pNspc );
if ( pSink == NULL )
{
return WBEM_E_OUT_OF_MEMORY;
}
pSink->AddRef();
*ppSink = pSink;
return WBEM_S_NO_ERROR;
}
};
CFwdConsNamespace::~CFwdConsNamespace()
{
if ( m_pDES != NULL )
{
m_pDES->UnRegister();
}
}
HRESULT CFwdConsNamespace::InitializeTraceEventBase( IWbemClassObject* pTrace,
HRESULT hres,
CFwdContext* pCtx )
{
HRESULT hr;
VARIANT var;
V_VT(&var) = VT_UNKNOWN;
V_UNKNOWN(&var) = pCtx->m_pCons;
hr = pTrace->Put( g_wszConsumer, 0, &var, NULL );
if ( FAILED(hr) )
{
return hr;
}
WCHAR achExecutionId[64];
if ( StringFromGUID2( pCtx->m_guidExecution, achExecutionId, 64 ) == 0 )
{
return WBEM_E_CRITICAL_ERROR;
}
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = achExecutionId;
hr = pTrace->Put( g_wszExecutionId, 0, &var, NULL );
if ( FAILED(hr) )
{
return hr;
}
V_VT(&var) = VT_I4;
V_I4(&var) = hres;
return pTrace->Put( g_wszStatusCode, 0, &var, NULL );
}
//
// called after each execution of a forwarding consumer.
//
HRESULT CFwdConsNamespace::HandleTrace( HRESULT hres, CFwdContext* pCtx )
{
HRESULT hr;
CWbemPtr<IWbemEventSink> pTraceSink;
if ( SUCCEEDED(hres) )
{
if ( m_pTraceSuccessSink->IsActive() == WBEM_S_FALSE )
{
return WBEM_S_NO_ERROR;
}
else
{
pTraceSink = m_pTraceSuccessSink;
}
}
else if ( m_pTraceFailureSink->IsActive() == WBEM_S_FALSE )
{
return WBEM_S_NO_ERROR;
}
else
{
pTraceSink = m_pTraceFailureSink;
}
CWbemPtr<IWbemClassObject> pTrace;
hr = m_pTraceClass->SpawnInstance( 0, &pTrace );
if ( FAILED(hr) )
{
return hr;
}
hr = InitializeTraceEventBase( pTrace, hres, pCtx );
if ( FAILED(hr) )
{
return hr;
}
//
// set the events that were indicated in the trace event
//
VARIANT var;
V_VT(&var) = VT_ARRAY | VT_UNKNOWN;
V_ARRAY(&var) = SafeArrayCreateVector( VT_UNKNOWN, 0, pCtx->m_cEvents );
if ( V_ARRAY(&var) == NULL )
{
return WBEM_E_OUT_OF_MEMORY;
}
{
CPropSafeArray<IUnknown*> apEvents(V_ARRAY(&var));
for( ULONG i=0; i < pCtx->m_cEvents; i++ )
{
apEvents[i] = pCtx->m_apEvents[i];
apEvents[i]->AddRef();
}
}
hr = pTrace->Put( g_wszEvents, 0, &var, NULL );
VariantClear( &var );
if ( FAILED(hr) )
{
return hr;
}
//
// don't set other props on failure.
//
if ( FAILED(hres) )
{
return pTraceSink->Indicate( 1, &pTrace );
}
//
// it is possible that there may be not target.
//
if ( pCtx->m_wsTarget.Length() > 0 )
{
LPWSTR wszTarget = pCtx->m_wsTarget;
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = wszTarget;
hr = pTrace->Put( g_wszTargetUsed, 0, &var, NULL );
if ( FAILED(hr) )
{
return hr;
}
}
V_VT(&var) = VT_BOOL;
V_BOOL(&var) = pCtx->m_bQueued ? VARIANT_TRUE : VARIANT_FALSE;
hr = pTrace->Put( g_wszQueued, 0, &var, NULL );
if ( FAILED(hr) )
{
return hr;
}
return pTraceSink->Indicate( 1, &pTrace );
}
//
// This is called by Senders when their SendReceive() method is called for
// both error and success states. In both cases the wszTrace string will
// be the name of the sender. Senders, such as the multisender or fwdsender
// can call the sink multiple times since they can represent multiple
// connections. Since all Senders initialize themselves lazily, we don't
// have to worry about generating trace events when Open() calls fail.
//
STDMETHODIMP CFwdConsNamespace::Notify( HRESULT hres,
GUID guidSource,
LPCWSTR wszTrace,
IUnknown* pContext )
{
HRESULT hr;
//
// since we are the ones who created the context, we can safely cast.
//
CFwdContext* pCtx = (CFwdContext*)pContext;
if ( SUCCEEDED(hres) )
{
//
// save any state with the context about the successful send.
//
if ( guidSource == CLSID_WmiMessageMsmqSender )
{
pCtx->m_bQueued = TRUE;
}
pCtx->m_wsTarget = wszTrace;
}
CWbemPtr<IWbemEventSink> pTraceSink;
if ( SUCCEEDED(hres) )
{
if ( m_pTraceSuccessSink->IsActive() == WBEM_S_FALSE )
{
return WBEM_S_NO_ERROR;
}
else
{
pTraceSink = m_pTraceSuccessSink;
}
}
else if ( m_pTraceFailureSink->IsActive() == WBEM_S_FALSE )
{
return WBEM_S_NO_ERROR;
}
else
{
pTraceSink = m_pTraceFailureSink;
}
CWbemPtr<IWbemClassObject> pTrace;
hr = m_pTargetTraceClass->SpawnInstance( 0, &pTrace );
if ( FAILED(hr) )
{
return hr;
}
hr = InitializeTraceEventBase( pTrace, hres, pCtx );
if ( FAILED(hr) )
{
return hr;
}
LPWSTR wszTmp = LPWSTR(wszTrace);
VARIANT var;
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = wszTmp;
hr = pTrace->Put( g_wszTarget, 0, &var, NULL );
if ( FAILED(hr) )
{
return hr;
}
return pTraceSink->Indicate( 1, &pTrace );
}
HRESULT CFwdConsNamespace::Initialize( LPCWSTR wszNamespace )
{
HRESULT hr;
m_wsName = wszNamespace;
//
// register our decoupled event provider
//
hr = CoCreateInstance( CLSID_WbemDecoupledBasicEventProvider,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemDecoupledBasicEventProvider,
(void**)&m_pDES );
if ( FAILED(hr) )
{
return hr;
}
hr = m_pDES->Register( 0,
NULL,
NULL,
NULL,
wszNamespace,
g_wszTraceProvider,
NULL );
if ( FAILED(hr) )
{
return hr;
}
//
// get the service pointer for out namespace
//
hr = m_pDES->GetService( 0, NULL, &m_pSvc );
if ( FAILED(hr) )
{
return hr;
}
//
// get the decoupled event sink
//
CWbemPtr<IWbemObjectSink> pTraceObjectSink;
hr = m_pDES->GetSink( 0, NULL, &pTraceObjectSink );
if ( FAILED(hr) )
{
return hr;
}
CWbemPtr<IWbemEventSink> pTraceEventSink;
hr = pTraceObjectSink->QueryInterface( IID_IWbemEventSink,
(void**)&pTraceEventSink);
if ( FAILED(hr) )
{
return WBEM_E_CRITICAL_ERROR;
}
//
// get restricted query for successes.
//
hr = pTraceEventSink->GetRestrictedSink( 1,
&g_wszTraceSuccessQuery,
NULL,
&m_pTraceSuccessSink );
if ( FAILED(hr) )
{
return hr;
}
//
// get restricted query for failures.
//
hr = pTraceEventSink->GetRestrictedSink( 1,
&g_wszTraceFailureQuery,
NULL,
&m_pTraceFailureSink );
if ( FAILED(hr) )
{
return hr;
}
//
// more trace initialization
//
hr = m_pSvc->GetObject( g_wszTraceClass, 0, NULL, &m_pTraceClass, NULL );
if ( FAILED(hr) )
{
return hr;
}
hr = m_pSvc->GetObject( g_wszTargetTraceClass,
0,
NULL,
&m_pTargetTraceClass,
NULL );
if ( FAILED(hr) )
{
return hr;
}
return WBEM_S_NO_ERROR;
}