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.
765 lines
20 KiB
765 lines
20 KiB
|
|
#include "precomp.h"
|
|
#include <sspi.h>
|
|
#include <secext.h>
|
|
#include <ntdsapi.h>
|
|
#include <stdio.h>
|
|
#include <buffer.h>
|
|
#include <winntsec.h>
|
|
#include <callsec.h>
|
|
#include <wbemint.h>
|
|
#include <wbemutil.h>
|
|
#include <arrtempl.h>
|
|
#include "fevprov.h"
|
|
#include "fwdhdr.h"
|
|
|
|
static LPWSTR g_wszEventClass = L"MSFT_ForwardedEvent";
|
|
static LPWSTR g_wszEventProp = L"Event";
|
|
static LPWSTR g_wszMachineProp = L"Machine";
|
|
static LPWSTR g_wszConsumerProp = L"Consumer";
|
|
static LPWSTR g_wszNamespaceProp = L"Namespace";
|
|
static LPWSTR g_wszAuthenticatedProp = L"Authenticated";
|
|
static LPWSTR g_wszAccountProp = L"Account";
|
|
static LPWSTR g_wszSDProp = L"SECURITY_DESCRIPTOR";
|
|
static LPWSTR g_wszTimeProp = L"Time";
|
|
|
|
// {0F3162C5-7B5A-469f-955C-79603B7EB5A6}
|
|
static const GUID g_guidQueueType =
|
|
{ 0xf3162c5, 0x7b5a, 0x469f, {0x95, 0x5c, 0x79, 0x60, 0x3b, 0x7e, 0xb5, 0xa6}};
|
|
|
|
LPCWSTR g_awszQueueNames[] = { L".\\private$\\WMIFwdGuaranteed",
|
|
L".\\private$\\WMIFwdExpress",
|
|
L".\\private$\\WMIFwdGuaranteedAuth",
|
|
L".\\private$\\WMIFwdExpressAuth",
|
|
L".\\WMIFwdGuaranteedEncrypt",
|
|
L".\\WMIFwdExpressEncrypt" };
|
|
|
|
BOOL g_adwQueueQos[] = { WMIMSG_FLAG_QOS_GUARANTEED,
|
|
WMIMSG_FLAG_QOS_EXPRESS,
|
|
WMIMSG_FLAG_QOS_GUARANTEED,
|
|
WMIMSG_FLAG_QOS_EXPRESS,
|
|
WMIMSG_FLAG_QOS_GUARANTEED,
|
|
WMIMSG_FLAG_QOS_EXPRESS };
|
|
|
|
BOOL g_abQueueAuth[] = { FALSE, FALSE, TRUE, TRUE, TRUE, TRUE };
|
|
|
|
extern BOOL AllowUnauthenticatedEvents();
|
|
|
|
/**************************************************************************
|
|
CFwdEventProv
|
|
***************************************************************************/
|
|
|
|
CFwdEventProv::CFwdEventProv( CLifeControl* pCtl, IUnknown* pUnk )
|
|
: CUnk( pCtl, pUnk ), m_XErrorSink( this ), m_XSendReceive( this ),
|
|
m_XProv( this ), m_XQuery( this ), m_XInit( this ),
|
|
m_lMachineProp(-1), m_lConsumerProp(-1), m_lNamespaceProp(-1),
|
|
m_lAuthProp(-1), m_lAccountProp(-1), m_lTimeProp(-1), m_lSDProp(-1)
|
|
{
|
|
}
|
|
|
|
CFwdEventProv::~CFwdEventProv()
|
|
{
|
|
|
|
}
|
|
|
|
void* CFwdEventProv::GetInterface( REFIID riid )
|
|
{
|
|
if ( riid == IID_IWbemEventProvider )
|
|
{
|
|
return &m_XProv;
|
|
}
|
|
else if ( riid == IID_IWbemProviderInit )
|
|
{
|
|
return &m_XInit;
|
|
}
|
|
else if ( riid == IID_IWmiMessageTraceSink )
|
|
{
|
|
return &m_XErrorSink;
|
|
}
|
|
else if ( riid == IID_IWmiMessageSendReceive )
|
|
{
|
|
return &m_XSendReceive;
|
|
}
|
|
else if ( riid == IID_IWbemEventProviderQuerySink )
|
|
{
|
|
return &m_XQuery;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
HRESULT CFwdEventProv::Init( IWbemServices* pSvc,
|
|
IWbemProviderInitSink* pInitSink )
|
|
{
|
|
ENTER_API_CALL
|
|
|
|
HRESULT hr;
|
|
|
|
m_pSvc = pSvc;
|
|
|
|
hr = pSvc->GetObject( g_wszEventClass,
|
|
0,
|
|
NULL,
|
|
&m_pEventClass,
|
|
NULL );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// get handles for all the properties in the event .
|
|
//
|
|
|
|
CWbemPtr<_IWmiObject> pWmiEventClass;
|
|
|
|
hr = m_pEventClass->QueryInterface( IID__IWmiObject,
|
|
(void**)&pWmiEventClass );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pWmiEventClass->GetPropertyHandleEx( g_wszMachineProp,
|
|
0,
|
|
NULL,
|
|
&m_lMachineProp );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pWmiEventClass->GetPropertyHandleEx( g_wszConsumerProp,
|
|
0,
|
|
NULL,
|
|
&m_lConsumerProp );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pWmiEventClass->GetPropertyHandleEx( g_wszNamespaceProp,
|
|
0,
|
|
NULL,
|
|
&m_lNamespaceProp );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pWmiEventClass->GetPropertyHandleEx( g_wszAuthenticatedProp,
|
|
0,
|
|
NULL,
|
|
&m_lAuthProp );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pWmiEventClass->GetPropertyHandleEx( g_wszSDProp,
|
|
0,
|
|
NULL,
|
|
&m_lSDProp );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pWmiEventClass->GetPropertyHandleEx( g_wszAccountProp,
|
|
0,
|
|
NULL,
|
|
&m_lAccountProp );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pWmiEventClass->GetPropertyHandleEx( g_wszTimeProp,
|
|
0,
|
|
NULL,
|
|
&m_lTimeProp );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = CoCreateInstance( CLSID_WmiSmartObjectUnmarshal,
|
|
NULL,
|
|
CLSCTX_INPROC,
|
|
IID_IWmiObjectMarshal,
|
|
(void**)&m_pMrsh );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return pInitSink->SetStatus( WBEM_S_INITIALIZED, 0 );
|
|
|
|
EXIT_API_CALL
|
|
}
|
|
|
|
HRESULT CFwdEventProv::InitializeEvent( IWbemClassObject* pOriginalEvent,
|
|
IWmiMessageReceiverContext* pRecvCtx,
|
|
LPCWSTR wszConsumer,
|
|
LPCWSTR wszNamespace,
|
|
PBYTE pSD,
|
|
ULONG cSD,
|
|
IWbemClassObject* pEvent )
|
|
{
|
|
HRESULT hr;
|
|
VARIANT var;
|
|
|
|
CWbemPtr<_IWmiObject> pWmiEvent;
|
|
hr = pEvent->QueryInterface( IID__IWmiObject, (void**)&pWmiEvent );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
SYSTEMTIME st;
|
|
BYTE achBuff[256];
|
|
CBuffer Buff( achBuff, 256, FALSE );
|
|
|
|
WCHAR* pwchBuff = (WCHAR*)Buff.GetRawData();
|
|
ULONG cBuff = Buff.GetSize() / 2;
|
|
|
|
//
|
|
// Time Sent
|
|
//
|
|
|
|
hr = pRecvCtx->GetTimeSent( &st );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
StringCchPrintfW( pwchBuff,
|
|
cBuff,
|
|
L"%04.4d%02.2d%02.2d%02.2d%02.2d%02.2d.%06.6d+000",
|
|
st.wYear, st.wMonth, st.wDay, st.wHour,
|
|
st.wMinute, st.wSecond, 0 );
|
|
|
|
hr = pWmiEvent->WritePropertyValue( m_lTimeProp,
|
|
(wcslen(pwchBuff)+1)*2,
|
|
Buff.GetRawData() );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Sending Machine
|
|
//
|
|
|
|
pwchBuff = (WCHAR*)Buff.GetRawData();
|
|
cBuff = Buff.GetSize() / 2;
|
|
|
|
hr = pRecvCtx->GetSendingMachine( pwchBuff, cBuff, &cBuff );
|
|
|
|
if ( hr == WBEM_S_FALSE )
|
|
{
|
|
hr = Buff.SetSize( cBuff*2 ); // note: size for wchars
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
pwchBuff = (WCHAR*)Buff.GetRawData();
|
|
cBuff = Buff.GetSize() / 2;
|
|
|
|
hr = pRecvCtx->GetSendingMachine( pwchBuff, cBuff, &cBuff );
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) && cBuff > 0 )
|
|
{
|
|
hr = pWmiEvent->WritePropertyValue( m_lMachineProp,
|
|
cBuff*2,
|
|
Buff.GetRawData() );
|
|
|
|
}
|
|
|
|
//
|
|
// Sender Authenticated
|
|
//
|
|
|
|
hr = pRecvCtx->IsSenderAuthenticated();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pWmiEvent->WriteDWORD( m_lAuthProp, hr == S_OK ? 1 : 0 );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Sender Identity
|
|
//
|
|
|
|
ULONG cSid;
|
|
hr = pRecvCtx->GetSenderId( Buff.GetRawData(), Buff.GetSize(), &cSid );
|
|
|
|
if ( hr == WBEM_S_FALSE )
|
|
{
|
|
hr = Buff.SetSize( cSid );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = pRecvCtx->GetSenderId( Buff.GetRawData(), Buff.GetSize(), &cSid );
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) && cSid > 0 )
|
|
{
|
|
hr = pWmiEvent->SetArrayPropRangeByHandle( m_lAccountProp,
|
|
WMIARRAY_FLAG_ALLELEMENTS,
|
|
0,
|
|
cSid,
|
|
cSid,
|
|
Buff.GetRawData() );
|
|
}
|
|
|
|
//
|
|
// Original Event
|
|
//
|
|
|
|
V_VT(&var) = VT_UNKNOWN;
|
|
V_UNKNOWN(&var) = pOriginalEvent;
|
|
|
|
hr = pEvent->Put( g_wszEventProp, 0, &var, NULL );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Sending Consumer Name
|
|
//
|
|
|
|
if ( wszConsumer != NULL )
|
|
{
|
|
hr = pWmiEvent->WritePropertyValue( m_lConsumerProp,
|
|
(wcslen(wszConsumer)+1)*2,
|
|
PBYTE(wszConsumer) );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Sending Consumer Namespace
|
|
//
|
|
|
|
if ( wszNamespace != NULL )
|
|
{
|
|
hr = pWmiEvent->WritePropertyValue( m_lNamespaceProp,
|
|
(wcslen(wszNamespace)+1)*2,
|
|
PBYTE(wszNamespace) );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// set the security descriptor on the event if specified.
|
|
//
|
|
|
|
if ( cSD > 0 )
|
|
{
|
|
hr = pWmiEvent->SetArrayPropRangeByHandle( m_lSDProp,
|
|
WMIARRAY_FLAG_ALLELEMENTS,
|
|
0,
|
|
cSD,
|
|
cSD,
|
|
pSD );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT CFwdEventProv::ProvideEvents( IWbemObjectSink* pSink, long lFlags )
|
|
{
|
|
ENTER_API_CALL
|
|
|
|
m_pEventSink = pSink;
|
|
|
|
//
|
|
// we were waiting to obtain the sink before starting up the
|
|
// receivers.
|
|
//
|
|
|
|
DEBUGTRACE((LOG_ESS,"FEVPROV: Begin Initializing.\n"));
|
|
|
|
BOOL bAllowUnauth = AllowUnauthenticatedEvents();
|
|
|
|
HRESULT hr;
|
|
#ifdef __WHISTLER_UNCUT
|
|
hr = InitializeQueues( bAllowUnauth );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
#endif
|
|
|
|
hr = InitializeReceivers( bAllowUnauth );
|
|
|
|
DEBUGTRACE((LOG_ESS,"FEVPROV: End Initializing.\n"));
|
|
|
|
return hr;
|
|
|
|
EXIT_API_CALL
|
|
}
|
|
|
|
HRESULT CFwdEventProv::InitializeQueues( BOOL bAllowUnauth )
|
|
{
|
|
HRESULT hr;
|
|
|
|
DWORD dwQuota = 0xffffffff;
|
|
PSECURITY_DESCRIPTOR pSecDesc = NULL;
|
|
|
|
CWbemPtr<IWmiMessageQueueManager> pQueueMgr;
|
|
|
|
hr = CoCreateInstance( CLSID_WmiMessageQueueManager,
|
|
NULL,
|
|
CLSCTX_INPROC,
|
|
IID_IWmiMessageQueueManager,
|
|
(void**)&pQueueMgr );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
for( int i=0 ; i < sizeof(g_adwQueueQos)/sizeof(DWORD); i++ )
|
|
{
|
|
if ( g_abQueueAuth[i] || (!g_abQueueAuth[i] && bAllowUnauth) )
|
|
{
|
|
hr = pQueueMgr->Create( g_awszQueueNames[i],
|
|
g_guidQueueType,
|
|
g_abQueueAuth[i],
|
|
g_adwQueueQos[i],
|
|
dwQuota,
|
|
pSecDesc );
|
|
|
|
if ( FAILED(hr) && hr != WBEM_E_ALREADY_EXISTS )
|
|
{
|
|
ERRORTRACE((LOG_ESS,"FEVPROV: Could not create/open queue %S, "
|
|
"HR=0x%x\n", g_awszQueueNames[i], hr ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// since we're not going to allow unauthenticated queues, make
|
|
// sure that we delete any existing ones so that there's not an
|
|
// open unauthenticated entry point on the machine. There will
|
|
// only be a queue actually there to clean up if we're
|
|
// transitioning from unauthenticated allowed to not allowed.
|
|
//
|
|
|
|
pQueueMgr->Destroy( g_awszQueueNames[i] );
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT CFwdEventProv::InitializeReceivers( BOOL bAllowUnauth )
|
|
{
|
|
HRESULT hr;
|
|
|
|
DWORD dwFlags = 0;
|
|
|
|
if ( !bAllowUnauth )
|
|
{
|
|
dwFlags |= WMIMSG_FLAG_RCVR_SECURE_ONLY;
|
|
}
|
|
|
|
//
|
|
// Initialize Sync DCOM Receiver.
|
|
//
|
|
|
|
hr = CoCreateInstance( CLSID_WmiMessageRpcReceiver,
|
|
NULL,
|
|
CLSCTX_INPROC,
|
|
IID_IWmiMessageReceiver,
|
|
(void**)&m_pDcomRcvr );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = m_pDcomRcvr->Open(
|
|
L"7879E40D-9FB5-450a-8A6D-00C89F349FCE@ncacn_ip_tcp:",
|
|
WMIMSG_FLAG_QOS_SYNCHRONOUS | dwFlags,
|
|
NULL,
|
|
&m_XSendReceive );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
ERRORTRACE((LOG_ESS,"FEVPROV: Could not open dcom rcvr, "
|
|
"HR=0x%x\n", hr ));
|
|
return hr;
|
|
}
|
|
|
|
#ifdef __WHISTLER_UNCUT
|
|
for( int i=0; i < sizeof(g_adwQueueQos)/sizeof(DWORD); i++ )
|
|
{
|
|
if ( g_abQueueAuth[i] || (!g_abQueueAuth[i] && bAllowUnauth) )
|
|
{
|
|
hr = CoCreateInstance( CLSID_WmiMessageMsmqReceiver,
|
|
NULL,
|
|
CLSCTX_INPROC,
|
|
IID_IWmiMessageReceiver,
|
|
(void**)&m_apQueueRcvr[i] );
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = m_apQueueRcvr[i]->Open( g_awszQueueNames[i],
|
|
g_adwQueueQos[i] | dwFlags,
|
|
NULL,
|
|
&m_XSendReceive );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
ERRORTRACE((LOG_ESS,"FEVPROV: Could not open rcvr for queue %S"
|
|
", HR=0x%x\n", g_awszQueueNames[i], hr ));
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT CFwdEventProv::NewQuery( DWORD dwId, LPWSTR wszQuery )
|
|
{
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT CFwdEventProv::CancelQuery( DWORD dwId )
|
|
{
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
HRESULT CFwdEventProv::Receive( PBYTE pData,
|
|
ULONG cData,
|
|
PBYTE pAuxData,
|
|
ULONG cAuxData,
|
|
DWORD dwStatus,
|
|
IUnknown* pCtx )
|
|
{
|
|
ENTER_API_CALL
|
|
|
|
HRESULT hr;
|
|
|
|
CBuffer DataStrm( pData, cData, FALSE );
|
|
CBuffer HdrStrm( pAuxData, cAuxData, FALSE );
|
|
|
|
//
|
|
// read and verify msg hdr - don't do much with it though - it mostly
|
|
// contains info for nack event prov.
|
|
//
|
|
|
|
CFwdMsgHeader FwdHdr;
|
|
|
|
hr = FwdHdr.Unpersist( HdrStrm );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// read objects and generate event.
|
|
//
|
|
|
|
#define MAXEVENTS 256
|
|
|
|
IWbemClassObject* apEvents[MAXEVENTS];
|
|
|
|
DWORD i=0;
|
|
hr = S_OK;
|
|
|
|
CWbemPtr<IWmiMessageReceiverContext> pRecvCtx;
|
|
|
|
if ( pCtx == NULL || pCtx->QueryInterface( IID_IWmiMessageReceiverContext,
|
|
(void**)&pRecvCtx ) != S_OK )
|
|
{
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
|
|
//
|
|
// if possible, convert our recv ctx to com context so that ess can
|
|
// impersonate the sender if necessary.
|
|
//
|
|
|
|
IWbemCallSecurity* pSec = NULL;
|
|
|
|
hr = pRecvCtx->ImpersonateSender();
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
pSec = CWbemCallSecurity::CreateInst(); // ref is 1 on create.
|
|
|
|
if ( pSec == NULL )
|
|
{
|
|
pRecvCtx->RevertToSelf();
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
hr = pSec->CloneThreadContext( FALSE );
|
|
|
|
pRecvCtx->RevertToSelf();
|
|
|
|
IUnknown* pUnkSec = NULL;
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = CoSwitchCallContext( pSec, &pUnkSec );
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
pSec->Release();
|
|
return hr;
|
|
}
|
|
|
|
_DBG_ASSERT( pUnkSec == NULL );
|
|
}
|
|
else if ( pRecvCtx->IsSenderAuthenticated() == S_FALSE )
|
|
{
|
|
//
|
|
// it is expected that ImpersonateClient will fail if
|
|
// the sender is not authenticated.
|
|
//
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// something else wrong here.
|
|
//
|
|
return WMIMSG_E_AUTHFAILURE;
|
|
}
|
|
|
|
const PSECURITY_DESCRIPTOR pSD = FwdHdr.GetTargetSD();
|
|
ULONG cSD = FwdHdr.GetTargetSDLength();
|
|
|
|
ULONG iData = DataStrm.GetIndex();
|
|
|
|
while( i < FwdHdr.GetNumObjects() && SUCCEEDED(hr) )
|
|
{
|
|
for( DWORD j=0; j < MAXEVENTS && j+i < FwdHdr.GetNumObjects(); j++ )
|
|
{
|
|
ULONG cUsed;
|
|
CWbemPtr<IWbemClassObject> pOriginalEvent;
|
|
|
|
hr = m_pMrsh->Unpack( cData-iData,
|
|
pData+iData,
|
|
0,
|
|
&pOriginalEvent,
|
|
&cUsed );
|
|
if ( FAILED(hr) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
iData += cUsed;
|
|
|
|
CWbemPtr<IWbemClassObject> pEvent;
|
|
|
|
hr = m_pEventClass->SpawnInstance( NULL, &pEvent );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
hr = InitializeEvent( pOriginalEvent,
|
|
pRecvCtx,
|
|
FwdHdr.GetConsumer(),
|
|
FwdHdr.GetNamespace(),
|
|
PBYTE(pSD),
|
|
cSD,
|
|
pEvent );
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
pEvent->AddRef();
|
|
apEvents[j] = pEvent;
|
|
}
|
|
|
|
i += j;
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = m_pEventSink->Indicate( j, apEvents );
|
|
}
|
|
|
|
for( DWORD k=0; k < j; k++ )
|
|
{
|
|
apEvents[k]->Release();
|
|
}
|
|
}
|
|
|
|
//
|
|
// if we switched the com call context, then switch it back.
|
|
//
|
|
|
|
if ( pSec != NULL )
|
|
{
|
|
IUnknown* pDummy;
|
|
|
|
if ( SUCCEEDED(CoSwitchCallContext( NULL, &pDummy ) ) )
|
|
{
|
|
_DBG_ASSERT( pDummy == pSec );
|
|
pSec->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
EXIT_API_CALL
|
|
}
|
|
|
|
HRESULT CFwdEventProv::HandleRecvError( HRESULT hr, LPCWSTR wszError )
|
|
{
|
|
//
|
|
// right now just log to ESS log.
|
|
//
|
|
ERRORTRACE((LOG_ESS,"FEVPROV: RECV Error, ErrorString=%S, HR=0x%x\n",
|
|
wszError, hr ));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|