/****************************************************************** CPingProvider.CPP -- WMI provider class implementation Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved Description: ******************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipexport.h" #include "icmpapi.h" #include ".\res_str.h" #include #include #include #include #include #include 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 ; }