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.
1275 lines
28 KiB
1275 lines
28 KiB
/******************************************************************
|
|
|
|
CPingProvider.CPP -- WMI provider class implementation
|
|
|
|
|
|
|
|
Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
|
|
|
|
|
|
Description:
|
|
|
|
******************************************************************/
|
|
|
|
#include <stdafx.h>
|
|
#include <ntddtcp.h>
|
|
#include <ipinfo.h>
|
|
#include <tdiinfo.h>
|
|
#include <winsock2.h>
|
|
#include <provimex.h>
|
|
#include <provexpt.h>
|
|
#include <provtempl.h>
|
|
#include <provmt.h>
|
|
#include <typeinfo.h>
|
|
#include <provcont.h>
|
|
#include <provevt.h>
|
|
#include <provthrd.h>
|
|
#include <provlog.h>
|
|
#include <provval.h>
|
|
#include <provtype.h>
|
|
#include <provtree.h>
|
|
#include <provdnf.h>
|
|
#include <winsock.h>
|
|
#include "ipexport.h"
|
|
#include "icmpapi.h"
|
|
|
|
#include ".\res_str.h"
|
|
|
|
#include <Allocator.h>
|
|
#include <Thread.h>
|
|
#include <HashTable.h>
|
|
|
|
#include <PingProv.h>
|
|
#include <Pingtask.h>
|
|
#include <Pingfac.h>
|
|
|
|
extern HMODULE ghModule ;
|
|
|
|
// Property names
|
|
//===============
|
|
|
|
const WCHAR *Ping_Address = L"Address" ;
|
|
const WCHAR *Ping_Timeout = L"Timeout" ;
|
|
const WCHAR *Ping_TimeToLive = L"TimeToLive" ;
|
|
const WCHAR *Ping_BufferSize = L"BufferSize" ;
|
|
const WCHAR *Ping_NoFragmentation = L"NoFragmentation" ;
|
|
const WCHAR *Ping_TypeofService = L"TypeofService" ;
|
|
const WCHAR *Ping_RecordRoute = L"RecordRoute" ;
|
|
const WCHAR *Ping_TimestampRoute = L"TimestampRoute" ;
|
|
const WCHAR *Ping_SourceRouteType = L"SourceRouteType" ;
|
|
const WCHAR *Ping_SourceRoute = L"SourceRoute" ;
|
|
const WCHAR *Ping_ResolveAddressNames = L"ResolveAddressNames" ;
|
|
|
|
const static WCHAR *Ping_StatusCode = L"StatusCode" ;
|
|
const static WCHAR *Ping_ResponseTime = L"ResponseTime" ;
|
|
const static WCHAR *Ping_RouteRecord = L"RouteRecord" ;
|
|
const static WCHAR *Ping_ReplySize = L"ReplySize" ;
|
|
const static WCHAR *Ping_ReplyInconsistency = L"ReplyInconsistency" ;
|
|
const static WCHAR *Ping_ResponseTimeToLive = L"ResponseTimeToLive" ;
|
|
const static WCHAR *Ping_ProtocolAddress = L"ProtocolAddress" ;
|
|
const static WCHAR *Ping_TimeStampRecord = L"TimeStampRecord" ;
|
|
const static WCHAR *Ping_TimeStampRecordAddress = L"TimeStampRecordAddress" ;
|
|
const static WCHAR *Ping_TimeStampRecordAddressResolved = L"TimeStampRecordAddressResolved" ;
|
|
const static WCHAR *Ping_RouteRecordResolved = L"RouteRecordResolved" ;
|
|
const static WCHAR *Ping_ProtocolAddressResolved = L"ProtocolAddressResolved" ;
|
|
const static WCHAR *Ping_ResolveError = L"PrimaryAddressResolutionStatus" ;
|
|
|
|
CPingTaskObject::CPingErrorObject::~CPingErrorObject()
|
|
{
|
|
if (m_Description != NULL)
|
|
{
|
|
delete [] m_Description;
|
|
}
|
|
}
|
|
|
|
void CPingTaskObject::CPingErrorObject::SetInfo(LPCWSTR a_description, HRESULT a_status)
|
|
{
|
|
m_Status = a_status;
|
|
|
|
if (m_Description != NULL)
|
|
{
|
|
delete [] m_Description;
|
|
m_Description = NULL;
|
|
}
|
|
|
|
if (a_description != NULL)
|
|
{
|
|
int t_len = wcslen(a_description);
|
|
|
|
if (t_len > 0)
|
|
{
|
|
m_Description = new WCHAR[t_len+1];
|
|
m_Description[t_len] = L'\0';
|
|
wcsncpy(m_Description, a_description, t_len);
|
|
}
|
|
}
|
|
}
|
|
|
|
CPingTaskObject::CPingTaskObject (CPingProvider *a_Provider ,
|
|
IWbemObjectSink *a_NotificationHandler ,
|
|
IWbemContext *a_Ctx
|
|
): m_NotificationHandler(NULL),
|
|
m_Ctx(NULL),
|
|
m_Provider(NULL),
|
|
m_PingCount(0),
|
|
m_ThreadToken(NULL)
|
|
{
|
|
InitializeCriticalSection(&m_CS);
|
|
|
|
if (a_NotificationHandler != NULL)
|
|
{
|
|
m_NotificationHandler = a_NotificationHandler;
|
|
m_NotificationHandler->AddRef();
|
|
}
|
|
|
|
if (a_Ctx != NULL)
|
|
{
|
|
m_Ctx = a_Ctx;
|
|
m_Ctx->AddRef();
|
|
}
|
|
|
|
if (a_Provider != NULL)
|
|
{
|
|
m_Provider = a_Provider;
|
|
m_Provider->AddRef();
|
|
}
|
|
}
|
|
|
|
CPingTaskObject::~CPingTaskObject ()
|
|
{
|
|
if (m_NotificationHandler != NULL)
|
|
{
|
|
IWbemClassObject *t_NotifyStatus = NULL ;
|
|
BOOL t_Status = TRUE;
|
|
|
|
if ( FAILED(m_ErrorObject.GetStatus ()) )
|
|
{
|
|
t_Status = GetStatusObject ( &t_NotifyStatus ) ;
|
|
}
|
|
|
|
if ( t_Status )
|
|
{
|
|
m_NotificationHandler->SetStatus ( 0 , m_ErrorObject.GetStatus () , 0 , t_NotifyStatus ) ;
|
|
|
|
if (t_NotifyStatus)
|
|
{
|
|
t_NotifyStatus->Release () ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_NotificationHandler->SetStatus ( 0 , m_ErrorObject.GetStatus () , 0 , NULL ) ;
|
|
}
|
|
|
|
m_NotificationHandler->Release();
|
|
m_NotificationHandler = NULL;
|
|
}
|
|
|
|
if (m_Ctx != NULL)
|
|
{
|
|
m_Ctx->Release();
|
|
m_Ctx = NULL;
|
|
}
|
|
|
|
if (m_Provider != NULL)
|
|
{
|
|
m_Provider->Release();
|
|
m_Provider = NULL;
|
|
}
|
|
|
|
if (m_ThreadToken != NULL)
|
|
{
|
|
CloseHandle(m_ThreadToken);
|
|
m_ThreadToken = NULL;
|
|
}
|
|
|
|
DeleteCriticalSection(&m_CS);
|
|
}
|
|
|
|
void CPingTaskObject::DecrementPingCount()
|
|
{
|
|
if (0 == InterlockedDecrement(&m_PingCount))
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
BOOL CPingTaskObject :: GetThreadToken()
|
|
{
|
|
BOOL t_RetVal = OpenThreadToken(
|
|
GetCurrentThread(), // handle to thread
|
|
TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, // access to process
|
|
TRUE, // use thread security
|
|
&m_ThreadToken // pointer to token handle
|
|
);
|
|
|
|
if (!t_RetVal)
|
|
{
|
|
SetErrorInfo(IDS_DUP_THRDTOKEN ,
|
|
WBEM_E_ACCESS_DENIED ) ;
|
|
}
|
|
|
|
return t_RetVal;
|
|
}
|
|
|
|
BOOL CPingTaskObject :: SetThreadToken(BOOL a_Reset)
|
|
{
|
|
BOOL t_RetVal = ::SetThreadToken(NULL, a_Reset ? NULL : m_ThreadToken);
|
|
|
|
return t_RetVal;
|
|
}
|
|
|
|
BOOL CPingTaskObject :: GetStatusObject ( IWbemClassObject **a_NotifyObject )
|
|
{
|
|
HRESULT t_Result = WBEM_E_FAILED ;
|
|
|
|
if ( m_Provider->GetNotificationObject ( m_Ctx, a_NotifyObject ) )
|
|
{
|
|
_variant_t t_Variant((long) m_ErrorObject.GetStatus (), VT_I4) ;
|
|
t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_STATUSCODE , 0 , & t_Variant , 0 ) ;
|
|
|
|
if ( SUCCEEDED ( t_Result ) )
|
|
{
|
|
LPCWSTR t_descr = m_ErrorObject.GetDescription ();
|
|
|
|
if ( t_descr != NULL )
|
|
{
|
|
t_Variant = t_descr ;
|
|
|
|
t_Result = (*a_NotifyObject)->Put ( WBEM_PROPERTY_PROVSTATUSMESSAGE , 0 , & t_Variant , 0 ) ;
|
|
|
|
if ( ! SUCCEEDED ( t_Result ) )
|
|
{
|
|
(*a_NotifyObject)->Release () ;
|
|
*a_NotifyObject = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
(*a_NotifyObject)->Release () ;
|
|
*a_NotifyObject = NULL ;
|
|
}
|
|
}
|
|
|
|
return (SUCCEEDED (t_Result)) ;
|
|
}
|
|
|
|
|
|
BOOL CPingTaskObject::GetClassObject ( IWbemClassObject **a_ppClass )
|
|
{
|
|
BOOL t_bRetVal = FALSE;
|
|
|
|
if ((a_ppClass != NULL) && (m_Provider != NULL))
|
|
{
|
|
*a_ppClass = NULL;
|
|
|
|
if (m_Provider->GetClassObject(a_ppClass) && ((*a_ppClass) != NULL))
|
|
{
|
|
t_bRetVal = TRUE;
|
|
}
|
|
}
|
|
|
|
return t_bRetVal;
|
|
}
|
|
|
|
HRESULT CPingTaskObject::Icmp_ResolveAddress ( LPCWSTR a_Path , ULONG &a_IpAddress, DWORD *a_pdwErr )
|
|
{
|
|
HRESULT t_Result = WBEM_E_NOT_FOUND ;
|
|
|
|
if (a_pdwErr)
|
|
{
|
|
*a_pdwErr = 0 ;
|
|
}
|
|
|
|
ProvIpAddressType t_IpAddress ( a_Path ) ;
|
|
|
|
if ( ! t_IpAddress.IsValid () )
|
|
{
|
|
char *t_AnsiAddress = UnicodeToDbcsString ( a_Path ) ;
|
|
|
|
if ( t_AnsiAddress )
|
|
{
|
|
struct hostent *t_HostEntry = gethostbyname ( t_AnsiAddress ) ;
|
|
|
|
if ( t_HostEntry )
|
|
{
|
|
/*
|
|
* If we find a host entry, set up the internet address
|
|
*/
|
|
t_IpAddress = ProvIpAddressType ( ntohl ( * ( long * ) t_HostEntry->h_addr ) ) ;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwErr = WSAGetLastError();
|
|
|
|
if (a_pdwErr)
|
|
{
|
|
*a_pdwErr = dwErr ;
|
|
}
|
|
}
|
|
|
|
delete [] t_AnsiAddress ;
|
|
}
|
|
}
|
|
|
|
if ( t_IpAddress.IsValid () )
|
|
{
|
|
a_IpAddress = htonl ( t_IpAddress.GetValue () ) ;
|
|
|
|
t_Result = S_OK ;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
HRESULT CPingTaskObject::SetInstanceKeys(IWbemClassObject *a_Inst , CPingCallBackObject *a_Reply)
|
|
{
|
|
if ((a_Inst == NULL) || (a_Reply == NULL))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
//set all 11 keys!
|
|
|
|
HRESULT t_RetVal = SetUint32Property( a_Inst, Ping_Timeout, a_Reply->GetTimeout() ) ;
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetUint32Property( a_Inst, Ping_TimeToLive, a_Reply->GetTimeToLive() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetUint32Property( a_Inst, Ping_BufferSize, a_Reply->GetSendSize() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetUint32Property( a_Inst, Ping_TypeofService, a_Reply->GetTypeofService() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetUint32Property( a_Inst, Ping_RecordRoute, a_Reply->GetRecordRoute() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetUint32Property( a_Inst, Ping_TimestampRoute, a_Reply->GetTimestampRoute() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetUint32Property( a_Inst, Ping_SourceRouteType, a_Reply->GetSourceRouteType() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetBOOLProperty( a_Inst, Ping_NoFragmentation, a_Reply->GetNoFragmentation() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetBOOLProperty( a_Inst, Ping_ResolveAddressNames, a_Reply->GetResolveAddress() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetStringProperty( a_Inst, Ping_SourceRoute, a_Reply->GetSourceRoute() ) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
t_RetVal = SetStringProperty( a_Inst, Ping_Address, a_Reply->GetAddressString()) ;
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
//not a key so we don't report if this fails...
|
|
SetUint32Property( a_Inst, Ping_ResolveError, a_Reply->GetResolveError() ) ;
|
|
}
|
|
|
|
return t_RetVal;
|
|
}
|
|
|
|
HRESULT CPingTaskObject::SetUint32Property(
|
|
|
|
IWbemClassObject *a_Inst,
|
|
LPCWSTR a_Name,
|
|
ULONG a_Val
|
|
)
|
|
{
|
|
if ((a_Inst == NULL) || (a_Name == NULL))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
_variant_t t_var((long)a_Val);
|
|
|
|
return (a_Inst->Put(a_Name, 0, &t_var, 0));
|
|
}
|
|
|
|
HRESULT CPingTaskObject::SetUint32ArrayProperty(
|
|
|
|
IWbemClassObject *a_Inst ,
|
|
LPCWSTR a_Name ,
|
|
ULONG* a_Vals ,
|
|
ULONG a_Count
|
|
)
|
|
{
|
|
if ((a_Inst == NULL) || (a_Name == NULL))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
SAFEARRAYBOUND t_rgsabound[1];
|
|
SAFEARRAY* t_psa = NULL;
|
|
t_rgsabound[0].lLbound = 0;
|
|
t_rgsabound[0].cElements = a_Count;
|
|
t_psa = SafeArrayCreate(VT_I4, 1, t_rgsabound);
|
|
HRESULT t_RetVal = S_OK;
|
|
|
|
if (NULL != t_psa)
|
|
{
|
|
try
|
|
{
|
|
LONG *t_pdata = NULL;
|
|
|
|
if (SUCCEEDED(SafeArrayAccessData(t_psa, (void **)&t_pdata)))
|
|
{
|
|
try
|
|
{
|
|
memcpy((void *)t_pdata, (void *)a_Vals, a_Count*sizeof(ULONG));
|
|
SafeArrayUnaccessData(t_psa);
|
|
}
|
|
catch (...)
|
|
{
|
|
SafeArrayUnaccessData(t_psa);
|
|
throw;
|
|
}
|
|
|
|
VARIANT t_var;
|
|
VariantInit(&t_var);
|
|
t_var.vt = VT_ARRAY|VT_I4;
|
|
t_var.parray = t_psa;
|
|
t_psa = NULL;
|
|
|
|
try
|
|
{
|
|
t_RetVal = a_Inst->Put(a_Name, 0, &t_var, 0);
|
|
}
|
|
catch (...)
|
|
{
|
|
VariantClear(&t_var);
|
|
throw;
|
|
}
|
|
|
|
VariantClear(&t_var);
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
if (t_psa != NULL)
|
|
{
|
|
SafeArrayDestroy(t_psa);
|
|
}
|
|
|
|
throw;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
return t_RetVal;
|
|
}
|
|
|
|
|
|
HRESULT CPingTaskObject::SetStringProperty(
|
|
|
|
IWbemClassObject *a_Inst,
|
|
LPCWSTR a_Name,
|
|
LPCWSTR a_Val
|
|
)
|
|
{
|
|
if ((a_Inst == NULL) || (a_Name == NULL))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
_variant_t t_var(a_Val);
|
|
|
|
return (a_Inst->Put(a_Name, 0, &t_var, 0));
|
|
}
|
|
|
|
HRESULT CPingTaskObject::SetBOOLProperty(
|
|
|
|
IWbemClassObject *a_Inst,
|
|
LPCWSTR a_Name,
|
|
BOOL a_Val
|
|
)
|
|
{
|
|
if ((a_Inst == NULL) || (a_Name == NULL))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
_variant_t t_var(a_Val ? true : false);
|
|
|
|
return (a_Inst->Put(a_Name, 0, &t_var, 0));
|
|
}
|
|
|
|
void CPingTaskObject::IPAddressToString(_variant_t &a_var, ULONG a_Val, BOOL a_Resolve)
|
|
{
|
|
if (!a_Resolve)
|
|
{
|
|
ProvIpAddressType t_ProtocolAddress ( ntohl(a_Val) ) ;
|
|
wchar_t *t_AddressString = t_ProtocolAddress.GetStringValue () ;
|
|
a_var = t_AddressString;
|
|
delete [] t_AddressString ;
|
|
}
|
|
else
|
|
{
|
|
struct in_addr t_Address;
|
|
t_Address.S_un.S_addr = a_Val; //assumes in param in network order when resolving
|
|
struct hostent *t_hostent = gethostbyaddr((char *) &t_Address, sizeof(t_Address), AF_INET);
|
|
|
|
if (t_hostent != NULL)
|
|
{
|
|
a_var = t_hostent->h_name;
|
|
}
|
|
else
|
|
{
|
|
ProvIpAddressType t_ProtocolAddress ( ntohl(a_Val) ) ;
|
|
wchar_t *t_AddressString = t_ProtocolAddress.GetStringValue () ;
|
|
a_var = t_AddressString;
|
|
delete [] t_AddressString ;
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT CPingTaskObject::SetIPProperty(
|
|
|
|
IWbemClassObject *a_Inst ,
|
|
LPCWSTR a_Name ,
|
|
ULONG a_Val ,
|
|
BOOL a_Resolve
|
|
)
|
|
{
|
|
if ((a_Inst == NULL) || (a_Name == NULL))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
_variant_t t_var;
|
|
IPAddressToString(t_var, a_Val, a_Resolve);
|
|
|
|
return (a_Inst->Put(a_Name, 0, &t_var, 0));
|
|
}
|
|
|
|
HRESULT CPingTaskObject::SetIPArrayProperty(
|
|
|
|
IWbemClassObject *a_Inst ,
|
|
LPCWSTR a_Name ,
|
|
ULONG* a_Vals ,
|
|
ULONG a_Count ,
|
|
BOOL a_Resolve
|
|
)
|
|
{
|
|
if ((a_Inst == NULL) || (a_Name == NULL))
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
SAFEARRAYBOUND t_rgsabound[1];
|
|
SAFEARRAY* t_psa = NULL;
|
|
t_rgsabound[0].lLbound = 0;
|
|
t_rgsabound[0].cElements = a_Count;
|
|
t_psa = SafeArrayCreate(VT_BSTR, 1, t_rgsabound);
|
|
HRESULT t_RetVal = S_OK;
|
|
|
|
if (NULL != t_psa)
|
|
{
|
|
try
|
|
{
|
|
BSTR *t_pdata = NULL;
|
|
|
|
if (SUCCEEDED(SafeArrayAccessData(t_psa, (void **)&t_pdata)))
|
|
{
|
|
try
|
|
{
|
|
for (int i = 0; i < a_Count; i++)
|
|
{
|
|
_variant_t t_var;
|
|
IPAddressToString(t_var, a_Vals[i], a_Resolve);
|
|
VARIANT t_NoDelVar = t_var.Detach() ;
|
|
t_pdata[i] = t_NoDelVar.bstrVal;
|
|
}
|
|
|
|
SafeArrayUnaccessData(t_psa);
|
|
}
|
|
catch (...)
|
|
{
|
|
SafeArrayUnaccessData(t_psa);
|
|
throw;
|
|
}
|
|
|
|
VARIANT t_var;
|
|
VariantInit(&t_var);
|
|
t_var.vt = VT_ARRAY|VT_BSTR;
|
|
t_var.parray = t_psa;
|
|
t_psa = NULL;
|
|
|
|
try
|
|
{
|
|
t_RetVal = a_Inst->Put(a_Name, 0, &t_var, 0);
|
|
}
|
|
catch (...)
|
|
{
|
|
VariantClear(&t_var);
|
|
throw;
|
|
}
|
|
|
|
VariantClear(&t_var);
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
if (t_psa != NULL)
|
|
{
|
|
SafeArrayDestroy(t_psa);
|
|
}
|
|
|
|
throw;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
return t_RetVal;
|
|
}
|
|
|
|
HRESULT CPingTaskObject::Icmp_IndicateResolveError (CPingCallBackObject *a_Reply)
|
|
{
|
|
HRESULT t_RetVal = S_OK;
|
|
IWbemClassObjectPtr t_Cls;
|
|
IWbemClassObjectPtr t_Inst;
|
|
|
|
if (a_Reply != NULL)
|
|
{
|
|
if (GetClassObject ( &t_Cls ) )
|
|
{
|
|
t_RetVal = t_Cls->SpawnInstance(0, &t_Inst);
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
//put the keys...
|
|
t_RetVal = SetInstanceKeys(t_Inst , a_Reply);
|
|
|
|
if (SUCCEEDED(t_RetVal))
|
|
{
|
|
//Indicate!
|
|
IWbemClassObject *t_pTmp = (IWbemClassObject*) t_Inst;
|
|
m_NotificationHandler->Indicate(1, &t_pTmp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//should not be NULL!!
|
|
t_RetVal = WBEM_E_FAILED;
|
|
}
|
|
|
|
return t_RetVal;
|
|
}
|
|
|
|
HRESULT CPingTaskObject::Icmp_DecodeAndIndicate (CPingCallBackObject *a_Reply)
|
|
{
|
|
HRESULT t_RetVal = S_OK;
|
|
PICMP_ECHO_REPLY t_Reply = ( PICMP_ECHO_REPLY ) a_Reply->GetReplyBuffer() ;
|
|
IWbemClassObjectPtr t_Cls;
|
|
IWbemClassObjectPtr t_Inst;
|
|
|
|
if (t_Reply != NULL)
|
|
{
|
|
|
|
if (GetClassObject ( &t_Cls ) )
|
|
{
|
|
t_RetVal = t_Cls->SpawnInstance(0, &t_Inst);
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
//put the keys...
|
|
t_RetVal = SetInstanceKeys(t_Inst , a_Reply);
|
|
}
|
|
|
|
if (SUCCEEDED (t_RetVal))
|
|
{
|
|
ULONG t_StatusCode = 0;
|
|
|
|
if ( ( 0 != IcmpParseReplies(t_Reply, a_Reply->GetSendSize()) ) &&
|
|
( t_Reply->Status == IP_SUCCESS ) )
|
|
{
|
|
ProvIpAddressType t_IpAddress((ULONG)ntohl(t_Reply->Address ));
|
|
SetIPProperty(t_Inst , Ping_ProtocolAddress, t_Reply->Address , FALSE);
|
|
|
|
if (a_Reply->GetResolveAddress())
|
|
{
|
|
SetIPProperty(t_Inst , Ping_ProtocolAddressResolved, t_Reply->Address , TRUE);
|
|
}
|
|
|
|
SetUint32Property( t_Inst, Ping_ResponseTime, t_Reply->RoundTripTime ) ;
|
|
SetUint32Property( t_Inst, Ping_ResponseTimeToLive, t_Reply->Options.Ttl ) ;
|
|
SetUint32Property( t_Inst, Ping_ReplySize, t_Reply->DataSize ) ;
|
|
|
|
BOOL t_ReplyInconsistency = FALSE;
|
|
|
|
if ( t_Reply->DataSize == a_Reply->GetSendSize() )
|
|
{
|
|
try
|
|
{
|
|
UCHAR *t_SendPtr = & ( a_Reply->GetSendBuffer() [ 0 ] );
|
|
UCHAR *t_ReplyPtr = (UCHAR*) t_Reply->Data ;
|
|
|
|
for (ULONG t_Index = 0; t_Index < t_Reply->DataSize; t_Index ++ )
|
|
{
|
|
if ( *t_SendPtr ++ != *t_ReplyPtr ++ )
|
|
{
|
|
t_ReplyInconsistency = TRUE ;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
t_ReplyInconsistency = TRUE ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_ReplyInconsistency = TRUE ;
|
|
}
|
|
|
|
SetBOOLProperty( t_Inst, Ping_ReplyInconsistency, t_ReplyInconsistency ) ;
|
|
|
|
if ( t_Reply->Options.OptionsSize )
|
|
{
|
|
ULONG t_RouteSourceCount = 0;
|
|
ULONG *t_RouteSource = NULL;
|
|
ULONG t_TimestampCount = 0;
|
|
ULONG *t_Timestamp = NULL;
|
|
ULONG *t_TimestampRoute = NULL;
|
|
|
|
HRESULT t_Result = Icmp_DecodeResponse (
|
|
|
|
t_Reply ,
|
|
t_RouteSourceCount ,
|
|
t_RouteSource ,
|
|
t_TimestampCount ,
|
|
t_TimestampRoute ,
|
|
t_Timestamp
|
|
) ;
|
|
|
|
if (SUCCEEDED (t_Result))
|
|
{
|
|
if (t_RouteSource != NULL)
|
|
{
|
|
SetIPArrayProperty(
|
|
|
|
t_Inst ,
|
|
Ping_RouteRecord ,
|
|
t_RouteSource ,
|
|
t_RouteSourceCount ,
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
if (t_TimestampRoute != NULL)
|
|
{
|
|
SetIPArrayProperty(
|
|
|
|
t_Inst ,
|
|
Ping_TimeStampRecordAddress ,
|
|
t_TimestampRoute ,
|
|
t_TimestampCount ,
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
if (t_Timestamp != NULL)
|
|
{
|
|
SetUint32ArrayProperty(
|
|
|
|
t_Inst ,
|
|
Ping_TimeStampRecord ,
|
|
t_Timestamp ,
|
|
t_TimestampCount
|
|
);
|
|
}
|
|
|
|
if (a_Reply->GetResolveAddress())
|
|
{
|
|
if (t_RouteSource != NULL)
|
|
{
|
|
SetIPArrayProperty(
|
|
|
|
t_Inst ,
|
|
Ping_RouteRecordResolved ,
|
|
t_RouteSource ,
|
|
t_RouteSourceCount ,
|
|
TRUE
|
|
);
|
|
}
|
|
|
|
if (t_TimestampRoute != NULL)
|
|
{
|
|
SetIPArrayProperty(
|
|
|
|
t_Inst ,
|
|
Ping_TimeStampRecordAddressResolved ,
|
|
t_TimestampRoute ,
|
|
t_TimestampCount ,
|
|
TRUE
|
|
);
|
|
}
|
|
}
|
|
|
|
delete [] t_RouteSource;
|
|
delete [] t_TimestampRoute;
|
|
delete [] t_Timestamp;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_StatusCode = t_Reply->Status ;
|
|
}
|
|
|
|
SetUint32Property( t_Inst, Ping_StatusCode, t_StatusCode ) ;
|
|
}
|
|
|
|
if (SUCCEEDED(t_RetVal))
|
|
{
|
|
//Indicate!
|
|
IWbemClassObject *t_pTmp = (IWbemClassObject*) t_Inst;
|
|
m_NotificationHandler->Indicate(1, &t_pTmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_RetVal = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//should not be NULL!!
|
|
t_RetVal = WBEM_E_FAILED;
|
|
}
|
|
|
|
return t_RetVal;
|
|
}
|
|
|
|
void CPingTaskObject::SetErrorInfo(DWORD a_ErrMsgID, HRESULT a_HRes, BOOL a_Force)
|
|
{
|
|
CCritSecAutoUnlock t_AutoLockUnlock(&m_CS);
|
|
|
|
if (a_Force || SUCCEEDED(m_ErrorObject.GetStatus()) )
|
|
{
|
|
//convert id to string...
|
|
WCHAR t_ErrMsgBuff[255];
|
|
WCHAR *t_ErrMsg = t_ErrMsgBuff;
|
|
int t_buffSz = 255;
|
|
int t_copied = LoadString(ghModule, a_ErrMsgID, t_ErrMsg, t_buffSz);
|
|
|
|
//try expanding a couple of times
|
|
//if it is still too big, too bad it'll be truncated
|
|
//not even localized strings should be this big (1500chars = 3k)
|
|
for (int i = 2; (i < 4) && (t_copied == t_buffSz); i++)
|
|
{
|
|
t_ErrMsg = new WCHAR[t_buffSz * i];
|
|
t_buffSz = t_buffSz * i;
|
|
t_copied = LoadString(ghModule, a_ErrMsgID, t_ErrMsg, t_buffSz);
|
|
}
|
|
|
|
m_ErrorObject.SetInfo(t_ErrMsg, a_HRes);
|
|
|
|
if (t_ErrMsg != t_ErrMsgBuff)
|
|
{
|
|
delete [] t_ErrMsg;
|
|
}
|
|
}
|
|
}
|
|
|
|
HRESULT CPingTaskObject::Icmp_DecodeResponse (PICMP_ECHO_REPLY a_Reply ,
|
|
ULONG &a_RouteSourceCount ,
|
|
ULONG *&a_RouteSource ,
|
|
ULONG &a_TimestampCount ,
|
|
ULONG *&a_TimestampRoute ,
|
|
ULONG *&a_Timestamp)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
uchar *t_OptionPtr = a_Reply->Options.OptionsData ;
|
|
uchar *t_EndPtr = t_OptionPtr + a_Reply->Options.OptionsSize ;
|
|
BOOL t_Done = FALSE ;
|
|
|
|
try
|
|
{
|
|
while ( ( t_OptionPtr < t_EndPtr ) && ! t_Done )
|
|
{
|
|
// Get the option type
|
|
|
|
switch ( t_OptionPtr [ 0 ] )
|
|
{
|
|
case IP_OPT_EOL:
|
|
{
|
|
t_Done = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IP_OPT_NOP:
|
|
{
|
|
t_OptionPtr ++ ;
|
|
}
|
|
break ;
|
|
|
|
case IP_OPT_SECURITY:
|
|
{
|
|
t_OptionPtr += 11 ;
|
|
}
|
|
break ;
|
|
|
|
case IP_OPT_SID:
|
|
{
|
|
t_OptionPtr += 4;
|
|
}
|
|
break;
|
|
|
|
case IP_OPT_RR:
|
|
case IP_OPT_LSRR:
|
|
case IP_OPT_SSRR:
|
|
{
|
|
if ( ( t_OptionPtr + 3 ) <= t_EndPtr )
|
|
{
|
|
ULONG t_OptionLength = t_OptionPtr [ 1 ] ;
|
|
|
|
if ( ( ( t_OptionPtr + t_OptionLength ) > t_EndPtr ) || ( t_OptionLength < 3 ) )
|
|
{
|
|
// INVALID_RR_OPTION
|
|
|
|
t_Done = TRUE ;
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
else
|
|
{
|
|
ULONG t_RouteTableEndOffset = t_OptionPtr [ 2 ] ;
|
|
|
|
if ( t_RouteTableEndOffset < 4 )
|
|
{
|
|
// Advance because the entry is a bad encoding, require 4 bytes for atleast one address
|
|
|
|
t_OptionPtr += t_OptionLength ;
|
|
}
|
|
else
|
|
{
|
|
if ( t_RouteTableEndOffset > ( t_OptionLength + 1 ) )
|
|
{
|
|
// The actual route table end index is larger than the option itself, therefore decode as much as possible
|
|
|
|
t_RouteTableEndOffset = t_OptionLength + 1 ;
|
|
}
|
|
|
|
// Count the entries
|
|
|
|
ULONG t_RouteEntryOffset = 4 ;
|
|
a_RouteSourceCount = 0;
|
|
|
|
while ( ( t_RouteEntryOffset + 3 ) < t_RouteTableEndOffset )
|
|
{
|
|
a_RouteSourceCount ++ ;
|
|
t_RouteEntryOffset += 4 ;
|
|
}
|
|
|
|
// Extract the routes
|
|
|
|
if (a_RouteSourceCount > 0)
|
|
{
|
|
a_RouteSource = new ULONG[a_RouteSourceCount];
|
|
a_RouteSourceCount = 0;
|
|
t_RouteEntryOffset = 4 ;
|
|
|
|
while ( ( t_RouteEntryOffset + 3 ) < t_RouteTableEndOffset )
|
|
{
|
|
// a_RouteSource[a_RouteSourceCount++] = * ( ( IPAddr * ) ( t_OptionPtr + t_RouteEntryOffset - 1 ) ) ;
|
|
memcpy ( &a_RouteSource[a_RouteSourceCount++], t_OptionPtr + t_RouteEntryOffset - 1, sizeof ( IPAddr ) );
|
|
t_RouteEntryOffset += 4 ;
|
|
}
|
|
}
|
|
// Advance to the next option
|
|
|
|
t_OptionPtr += t_OptionLength ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// INVALID_RR_OPTION
|
|
|
|
t_Done = TRUE ;
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IP_OPT_TS:
|
|
{
|
|
if ( ( t_OptionPtr + 4 ) <= t_EndPtr )
|
|
{
|
|
ULONG t_OptionLength = t_OptionPtr [ 1 ] ;
|
|
ULONG t_TimestampTableEndOffset = t_OptionPtr [ 2 ] ;
|
|
|
|
if ( t_TimestampTableEndOffset >= 5 )
|
|
{
|
|
if ( t_TimestampTableEndOffset > ( t_OptionLength + 1 ) )
|
|
{
|
|
// The actual timestamp table end index is larger than the option itself, therefore decode as much as possible
|
|
|
|
t_TimestampTableEndOffset = t_OptionLength + 1 ;
|
|
}
|
|
|
|
ULONG t_AddressMode = t_OptionPtr [ 3 ] & 1 ;
|
|
|
|
// Count the entries
|
|
|
|
ULONG t_TimestampEntryOffset = 5 ;
|
|
|
|
while ( ( t_TimestampEntryOffset + 3 ) < t_TimestampTableEndOffset )
|
|
{
|
|
if ( t_AddressMode )
|
|
{
|
|
if ( ( t_TimestampEntryOffset + 8 ) <= t_TimestampTableEndOffset )
|
|
{
|
|
t_TimestampEntryOffset += 8 ;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_TimestampEntryOffset += 4 ;
|
|
}
|
|
|
|
a_TimestampCount++ ;
|
|
}
|
|
|
|
// Extract the entries
|
|
if (a_TimestampCount > 0)
|
|
{
|
|
a_TimestampRoute = new ULONG[a_TimestampCount];
|
|
a_Timestamp = new ULONG[a_TimestampCount];
|
|
a_TimestampCount = 0;
|
|
t_TimestampEntryOffset = 5 ;
|
|
|
|
while ( ( t_TimestampEntryOffset + 3 ) < t_TimestampTableEndOffset )
|
|
{
|
|
if (( t_AddressMode ) && ( ( t_TimestampEntryOffset + 8 ) <= t_TimestampTableEndOffset ))
|
|
{
|
|
// a_TimestampRoute[a_TimestampCount] = * ( ( IPAddr * ) ( t_OptionPtr + t_TimestampEntryOffset - 1 ) ) ;
|
|
memcpy ( &a_TimestampRoute[a_TimestampCount], t_OptionPtr + t_TimestampEntryOffset - 1, sizeof ( IPAddr ) );
|
|
t_TimestampEntryOffset += 4 ;
|
|
}
|
|
else
|
|
{
|
|
a_TimestampRoute[a_TimestampCount] = 0;
|
|
}
|
|
|
|
// a_Timestamp[a_TimestampCount++] = * ( ( ULONG * ) ( t_OptionPtr + t_TimestampEntryOffset - 1 ) ) ;
|
|
memcpy ( &a_Timestamp[a_TimestampCount++], t_OptionPtr + t_TimestampEntryOffset - 1, sizeof ( ULONG ) );
|
|
t_TimestampEntryOffset += 4 ;
|
|
}
|
|
}
|
|
|
|
t_OptionPtr += t_OptionLength ;
|
|
}
|
|
else
|
|
{
|
|
// INVALID_RR_OPTION
|
|
|
|
t_Done = TRUE ;
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// INVALID_TS_OPTION
|
|
|
|
t_Done = TRUE ;
|
|
t_Result = WBEM_E_FAILED ;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if ( ( t_OptionPtr + 2 ) > t_EndPtr )
|
|
{
|
|
t_Done = TRUE ;
|
|
}
|
|
else
|
|
{
|
|
t_OptionPtr += t_OptionPtr [ 1 ] ;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
if (a_RouteSource != NULL)
|
|
{
|
|
delete [] a_RouteSource;
|
|
a_RouteSource = NULL;
|
|
}
|
|
|
|
if (a_TimestampRoute != NULL)
|
|
{
|
|
delete [] a_TimestampRoute;
|
|
a_TimestampRoute = NULL;
|
|
}
|
|
|
|
if (a_Timestamp != NULL)
|
|
{
|
|
delete [] a_Timestamp;
|
|
a_Timestamp = NULL;
|
|
}
|
|
|
|
throw;
|
|
}
|
|
|
|
if (FAILED(t_Result))
|
|
{
|
|
if (a_RouteSource != NULL)
|
|
{
|
|
delete [] a_RouteSource;
|
|
a_RouteSource = NULL;
|
|
}
|
|
|
|
if (a_TimestampRoute != NULL)
|
|
{
|
|
delete [] a_TimestampRoute;
|
|
a_TimestampRoute = NULL;
|
|
}
|
|
|
|
if (a_Timestamp != NULL)
|
|
{
|
|
delete [] a_Timestamp;
|
|
a_Timestamp = NULL;
|
|
}
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|
|
HRESULT CPingTaskObject::Icmp_RequestResponse (
|
|
|
|
LPCWSTR a_AddressString ,
|
|
ULONG a_Address ,
|
|
ULONG a_TimeToLive ,
|
|
ULONG a_Timeout ,
|
|
ULONG a_SendSize ,
|
|
BOOL a_NoFragmentation ,
|
|
ULONG a_TypeofService ,
|
|
ULONG a_RecordRoute ,
|
|
ULONG a_TimestampRoute ,
|
|
ULONG a_SourceRouteType ,
|
|
LPCWSTR a_SourceRoute,
|
|
BOOL a_ResolveAddress,
|
|
ULONG a_ResolveError
|
|
)
|
|
{
|
|
HRESULT t_Result = S_OK ;
|
|
|
|
CPingCallBackObject *t_Ctxt = new CPingCallBackObject(
|
|
|
|
this,
|
|
a_AddressString,
|
|
a_Address,
|
|
a_TimeToLive,
|
|
a_Timeout,
|
|
a_SendSize,
|
|
a_NoFragmentation,
|
|
a_TypeofService,
|
|
a_RecordRoute,
|
|
a_TimestampRoute,
|
|
a_SourceRouteType,
|
|
a_SourceRoute,
|
|
a_ResolveAddress,
|
|
a_ResolveError
|
|
);
|
|
t_Ctxt->AddRef();
|
|
|
|
try
|
|
{
|
|
if (a_ResolveError == 0)
|
|
{
|
|
//attach t_Ctxt to thread and make the thread do a
|
|
//t_Ctxt->SendEcho();
|
|
BOOL t_Sent = FALSE;
|
|
WmiStatusCode t_StatusCode = t_Ctxt->Initialize () ;
|
|
|
|
if (t_StatusCode == e_StatusCode_Success )
|
|
{
|
|
t_StatusCode = CPingProvider :: s_PingThread->EnQueue (0 , *t_Ctxt) ;
|
|
|
|
if (t_StatusCode == e_StatusCode_Success )
|
|
{
|
|
t_Sent = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!t_Sent)
|
|
{
|
|
t_Result = WBEM_E_FAILED ;
|
|
SetErrorInfo(IDS_ICMPECHO ,
|
|
WBEM_E_FAILED ) ;
|
|
try
|
|
{
|
|
t_Ctxt->Release();
|
|
}
|
|
catch(...)
|
|
{
|
|
t_Ctxt = NULL;
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
t_Result = Icmp_IndicateResolveError(t_Ctxt);
|
|
t_Ctxt->Disconnect();
|
|
t_Ctxt->Release();
|
|
t_Ctxt = NULL;
|
|
|
|
if (SUCCEEDED(t_Result))
|
|
{
|
|
DecrementPingCount();
|
|
}
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
t_Ctxt->Release();
|
|
throw;
|
|
}
|
|
|
|
return t_Result ;
|
|
}
|
|
|