332 lines
7.6 KiB
C++
332 lines
7.6 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (C) 1996-2001 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#include <assert.h>
|
||
|
#include <comutl.h>
|
||
|
#include "rpchdr.h"
|
||
|
#include "rpcsend.h"
|
||
|
#include "rpcmsg.h"
|
||
|
|
||
|
extern HRESULT RpcResToWmiRes( RPC_STATUS stat, HRESULT hrDefault );
|
||
|
|
||
|
/*****************************************************************
|
||
|
CMsgRpcSender
|
||
|
******************************************************************/
|
||
|
|
||
|
HRESULT CMsgRpcSender::Open( LPCWSTR wszTarget,
|
||
|
DWORD dwFlags,
|
||
|
WMIMSG_SNDR_AUTH_INFOP pAuthInfo,
|
||
|
LPCWSTR wszResponse,
|
||
|
IWmiMessageTraceSink* pTraceSink,
|
||
|
IWmiMessageSendReceive** ppSend )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
ENTER_API_CALL
|
||
|
|
||
|
CWbemPtr<CMsgRpcSend> pSend;
|
||
|
|
||
|
pSend = new CMsgRpcSend( m_pControl,
|
||
|
wszTarget,
|
||
|
dwFlags,
|
||
|
pAuthInfo,
|
||
|
wszResponse,
|
||
|
pTraceSink );
|
||
|
|
||
|
if ( (dwFlags & WMIMSG_FLAG_SNDR_LAZY_INIT) == 0 )
|
||
|
{
|
||
|
hr = pSend->EnsureSender();
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pSend->QueryInterface(IID_IWmiMessageSendReceive, (void**)ppSend);
|
||
|
|
||
|
EXIT_API_CALL
|
||
|
}
|
||
|
|
||
|
/*****************************************************************
|
||
|
CMsgRpcSend
|
||
|
******************************************************************/
|
||
|
|
||
|
CMsgRpcSend::CMsgRpcSend( CLifeControl* pCtl,
|
||
|
LPCWSTR wszTarget,
|
||
|
DWORD dwFlags,
|
||
|
WMIMSG_SNDR_AUTH_INFOP pAuthInfo,
|
||
|
LPCWSTR wszResponse,
|
||
|
IWmiMessageTraceSink* pTraceSink )
|
||
|
: CUnkBase<IWmiMessageSendReceive,&IID_IWmiMessageSendReceive>(pCtl),
|
||
|
m_dwFlags(dwFlags), m_pTraceSink( pTraceSink ),
|
||
|
m_hBinding(NULL), m_bInit(FALSE)
|
||
|
{
|
||
|
//
|
||
|
// save our computer name.
|
||
|
//
|
||
|
|
||
|
TCHAR achComputer[MAX_COMPUTERNAME_LENGTH+1];
|
||
|
ULONG ulSize = MAX_COMPUTERNAME_LENGTH+1;
|
||
|
GetComputerName( achComputer, &ulSize );
|
||
|
m_wsComputer = achComputer;
|
||
|
|
||
|
//
|
||
|
// if the target is NULL, then we use our computer name as the target.
|
||
|
//
|
||
|
|
||
|
if ( wszTarget != NULL && *wszTarget != '\0' )
|
||
|
{
|
||
|
m_wsTarget = wszTarget;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_wsTarget = m_wsComputer;
|
||
|
}
|
||
|
|
||
|
if ( pAuthInfo != NULL )
|
||
|
{
|
||
|
if ( pAuthInfo->wszTargetPrincipal != NULL )
|
||
|
{
|
||
|
m_wsTargetPrincipal = pAuthInfo->wszTargetPrincipal;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CMsgRpcSend::~CMsgRpcSend()
|
||
|
{
|
||
|
Clear();
|
||
|
}
|
||
|
|
||
|
HRESULT CMsgRpcSend::HandleTrace( HRESULT hr,
|
||
|
LPCWSTR wszTrace,
|
||
|
IUnknown* pCtx )
|
||
|
{
|
||
|
//
|
||
|
// we use the error sink approach instead of just returning an error
|
||
|
// because sometimes multiple senders are used in one send operation
|
||
|
// ( when using the multi send impl ) and we need to be able to
|
||
|
// distinguish which one failed.
|
||
|
//
|
||
|
|
||
|
if ( m_pTraceSink != NULL )
|
||
|
{
|
||
|
m_pTraceSink->Notify( hr, CLSID_WmiMessageRpcSender, wszTrace, pCtx );
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
void CMsgRpcSend::Clear()
|
||
|
{
|
||
|
if ( m_hBinding != NULL )
|
||
|
{
|
||
|
RpcBindingFree( &m_hBinding );
|
||
|
m_hBinding = NULL;
|
||
|
}
|
||
|
m_bInit = FALSE;
|
||
|
}
|
||
|
|
||
|
HRESULT CMsgRpcSend::EnsureSender()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
RPC_STATUS stat;
|
||
|
|
||
|
CInCritSec ics(&m_cs);
|
||
|
|
||
|
if ( m_bInit )
|
||
|
{
|
||
|
return WBEM_S_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
Clear();
|
||
|
|
||
|
//
|
||
|
// connect to the stub at the target.
|
||
|
//
|
||
|
|
||
|
stat = RpcBindingFromStringBinding( m_wsTarget, &m_hBinding );
|
||
|
|
||
|
if ( stat != RPC_S_OK )
|
||
|
{
|
||
|
return RpcResToWmiRes( stat, WMIMSG_E_INVALIDADDRESS );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// binding may be dynamic, so we may have to resolve it.
|
||
|
//
|
||
|
|
||
|
stat = RpcEpResolveBinding( m_hBinding,
|
||
|
IWmiMessageRemoteSendReceive_v1_0_c_ifspec );
|
||
|
|
||
|
if ( stat != RPC_S_OK )
|
||
|
{
|
||
|
return RpcResToWmiRes( stat, WMIMSG_E_TARGETNOTFOUND );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// set binding auth info based on auth and encryption flags.
|
||
|
//
|
||
|
|
||
|
RPC_SECURITY_QOS qos;
|
||
|
DWORD dwAuthnSvc, dwAuthzSvc, dwAuthnLevel;
|
||
|
|
||
|
LPWSTR wszPrincipal = NULL;
|
||
|
|
||
|
if ( m_wsTargetPrincipal.Length() > 0 )
|
||
|
{
|
||
|
wszPrincipal = m_wsTargetPrincipal;
|
||
|
}
|
||
|
|
||
|
qos.Version = RPC_C_SECURITY_QOS_VERSION;
|
||
|
qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
|
||
|
|
||
|
if ( m_dwFlags & WMIMSG_FLAG_SNDR_ENCRYPT )
|
||
|
{
|
||
|
dwAuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE;
|
||
|
dwAuthzSvc = RPC_C_AUTHZ_DEFAULT;
|
||
|
dwAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
|
||
|
qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
|
||
|
qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
|
||
|
}
|
||
|
else if ( m_dwFlags & WMIMSG_FLAG_SNDR_AUTHENTICATE )
|
||
|
{
|
||
|
dwAuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE;
|
||
|
dwAuthzSvc = RPC_C_AUTHZ_DEFAULT;
|
||
|
qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
|
||
|
qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
|
||
|
dwAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwAuthnSvc = RPC_C_AUTHN_NONE;
|
||
|
dwAuthzSvc = RPC_C_AUTHZ_NONE;
|
||
|
qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
|
||
|
qos.ImpersonationType = RPC_C_IMP_LEVEL_ANONYMOUS;
|
||
|
dwAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
|
||
|
}
|
||
|
|
||
|
stat = RpcBindingSetAuthInfoEx( m_hBinding,
|
||
|
wszPrincipal,
|
||
|
dwAuthnLevel,
|
||
|
dwAuthnSvc,
|
||
|
NULL,
|
||
|
dwAuthzSvc,
|
||
|
&qos );
|
||
|
|
||
|
if ( stat != RPC_S_OK )
|
||
|
{
|
||
|
return RpcResToWmiRes( stat, WMIMSG_E_AUTHFAILURE );
|
||
|
}
|
||
|
|
||
|
m_bInit = TRUE;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMsgRpcSend::PerformSend( PBYTE pData,
|
||
|
ULONG cData,
|
||
|
PBYTE pAuxData,
|
||
|
ULONG cAuxData )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
RpcTryExcept
|
||
|
{
|
||
|
hr = ::SendReceive( m_hBinding,
|
||
|
pData,
|
||
|
cData,
|
||
|
pAuxData,
|
||
|
cAuxData );
|
||
|
}
|
||
|
RpcExcept(1)
|
||
|
{
|
||
|
hr = RpcResToWmiRes( RpcExceptionCode(), S_OK );
|
||
|
}
|
||
|
RpcEndExcept
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CMsgRpcSend::SendReceive( PBYTE pData,
|
||
|
ULONG cData,
|
||
|
PBYTE pAuxData,
|
||
|
ULONG cAuxData,
|
||
|
DWORD dwFlagStatus,
|
||
|
IUnknown* pCtx )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
BYTE achHdr[512];
|
||
|
CBuffer HdrStrm( achHdr, 512, FALSE );
|
||
|
CMsgRpcHdr RpcHdr( m_wsComputer, cAuxData );
|
||
|
|
||
|
ENTER_API_CALL
|
||
|
|
||
|
hr = EnsureSender();
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
return HandleTrace( hr, m_wsTarget, pCtx );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// create our Rpc hdr and prepend it to the user's hdr data.
|
||
|
//
|
||
|
|
||
|
hr = RpcHdr.Persist( HdrStrm );
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
return HandleTrace( hr, m_wsTarget, pCtx );
|
||
|
}
|
||
|
|
||
|
hr = HdrStrm.Write( pAuxData, cAuxData, NULL );
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
return HandleTrace( hr, m_wsTarget, pCtx );
|
||
|
}
|
||
|
|
||
|
hr = PerformSend( pData,
|
||
|
cData,
|
||
|
HdrStrm.GetRawData(),
|
||
|
HdrStrm.GetIndex() );
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
//
|
||
|
// this is so the next call will reset us.
|
||
|
//
|
||
|
Clear();
|
||
|
|
||
|
hr = RpcResToWmiRes( hr, S_OK );
|
||
|
}
|
||
|
|
||
|
HandleTrace( hr, m_wsTarget, pCtx );
|
||
|
|
||
|
EXIT_API_CALL
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|