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.
 
 
 
 
 
 

1128 lines
20 KiB

//***************************************************************************
//
// PINGPROV.CPP
//
// Module: WMI PING PROVIDER
//
// Purpose: Implementation for the CPingProvider class.
//
// Copyright (c) 2000-2002 Microsoft Corporation, All Rights Reserved
//
//***************************************************************************
#include <initguid.h>
#ifndef INITGUID
#define INITGUID
#endif
#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 <Allocator.h>
#include <Thread.h>
#include <HashTable.h>
#include <pingprov.h>
#include <pingfac.h>
#include <pingtask.h>
#include <scopeguard.h>
/////////////////////////////////////////////////////////////////////////////
// Functions constructor, destructor and IUnknown
//***************************************************************************
//
// CPingProvider ::CPingProvider
// CPingProvider ::~CPingProvider
//
//***************************************************************************
CRITICAL_SECTION CPingProvider::s_CS;
CPingThread *CPingProvider::s_PingThread = NULL;
WmiAllocator *CPingProvider::s_Allocator = NULL;
WmiHashTable <CKeyEntry, ULONG, 12> *CPingProvider::s_HashTable = NULL;
LPCWSTR CPingProvider::s_KeyTable[PING_KEY_PROPERTY_COUNT] = {
Ping_Address,
Ping_Timeout,
Ping_TimeToLive,
Ping_BufferSize,
Ping_NoFragmentation,
Ping_TypeofService,
Ping_RecordRoute,
Ping_TimestampRoute,
Ping_SourceRouteType,
Ping_SourceRoute,
Ping_ResolveAddressNames
};
LONG CompareElement ( const CKeyEntry &a_Arg1 , const CKeyEntry & a_Arg2 )
{
LPCWSTR t_a1 = a_Arg1.Get();
LPCWSTR t_a2 = a_Arg2.Get();
if (t_a1 == t_a2)
{
return 0;
}
else if ((t_a1 == NULL) && (t_a1 != NULL))
{
return 1;
}
else if ((t_a1 == NULL) && (t_a1 != NULL))
{
return -1;
}
else
{
return (_wcsicmp(t_a1, t_a2));
}
}
BOOL operator== ( const CKeyEntry &a_Arg1 , const CKeyEntry &a_Arg2 )
{
return (CompareElement(a_Arg1, a_Arg2) == 0);
}
BOOL operator< ( const CKeyEntry &a_Arg1 , const CKeyEntry &a_Arg2 )
{
return (CompareElement(a_Arg1, a_Arg2) == -1);
}
ULONG Hash ( const CKeyEntry & a_Arg )
{
LPCWSTR t_a = a_Arg.Get();
ULONG t_RetVal = 0;
if (t_a != NULL)
{
switch (*t_a)
{
case L'A':
case L'a':
{
t_RetVal = 1;
}
break;
case L'B':
case L'b':
{
t_RetVal = 2;
}
break;
case L'N':
case L'n':
{
t_RetVal = 3;
}
break;
case L'R':
case L'r':
{
switch (wcslen(t_a))
{
case 11 : //wcslen(RecordRoute)
{
t_RetVal = 4;
}
break;
case 19 : //wcslen(ResolveAddressNames)
{
t_RetVal = 5;
}
break;
default:
{
}
}
}
break;
case L'S':
case L's':
{
switch (wcslen(t_a))
{
case 11 : //wcslen(SourceRoute)
{
t_RetVal = 6;
}
break;
case 15 : //wcslen(SourceRouteType)
{
t_RetVal = 7;
}
break;
default:
{
}
}
}
break;
case L'T':
case L't':
{
switch (wcslen(t_a))
{
case 7 : //wcslen(TimeOut)
{
t_RetVal = 8;
}
break;
case 10 : //wcslen(TimeToLive)
{
t_RetVal = 9;
}
break;
case 13 : //wcslen(TypeOfService)
{
t_RetVal = 10;
}
break;
case 14 : //wcslen(TimeStampRoute)
{
t_RetVal = 11;
}
break;
default:
{
}
}
}
break;
default:
{
}
}
}
return t_RetVal ;
}
CPingThread::CPingThread (WmiAllocator & a_Allocator)
: WmiThread < ULONG > ( a_Allocator , L"PingProviderThread") ,
m_Allocator ( a_Allocator ), m_Init(FALSE)
{
}
CPingThread::~CPingThread ()
{
}
WmiStatusCode CPingThread :: Initialize_Callback ()
{
WmiStatusCode t_RetVal = e_StatusCode_NotInitialized;
if (SUCCEEDED( CoInitializeEx ( NULL , COINIT_MULTITHREADED )) )
{
WSADATA t_WsaData ;
if (0 == WSAStartup (0x0101, & t_WsaData))
{
t_RetVal = e_StatusCode_Success ;
m_Init = TRUE;
}
else
{
CoUninitialize () ;
}
}
return t_RetVal ;
}
WmiStatusCode CPingThread :: UnInitialize_Callback ()
{
if (m_Init)
{
WSACleanup () ;
CoUninitialize () ;
}
return e_StatusCode_Success ;
}
CPingProvider ::CPingProvider () : m_referenceCount(0),
m_server(NULL),
m_notificationClassObject(NULL),
m_ClassObject(NULL),
m_bInitial(FALSE)
{
InterlockedIncrement ( & CPingProviderClassFactory :: s_ObjectsInProgress ) ;
}
CPingProvider ::~CPingProvider()
{
if ( m_server != NULL )
{
m_server->Release () ;
}
if ( m_ClassObject != NULL )
{
m_ClassObject->Release () ;
}
if ( m_notificationClassObject != NULL )
{
m_notificationClassObject->Release () ;
}
InterlockedDecrement ( & CPingProviderClassFactory :: s_ObjectsInProgress ) ;
}
HRESULT CPingProvider :: Global_Startup ()
{
HRESULT t_Result = S_OK ;
if ( s_Allocator)
{
if ( !s_PingThread )
{
WmiStatusCode t_StatusCode = WmiThread <ULONG> :: Static_Initialize ( *s_Allocator ) ;
if ( t_StatusCode != e_StatusCode_Success )
{
t_Result = WBEM_E_FAILED;
}
else
{
try
{
s_HashTable = ::new WmiHashTable <CKeyEntry, ULONG, 12> ( *s_Allocator ) ;
t_StatusCode = s_HashTable->Initialize () ;
if ( t_StatusCode != e_StatusCode_Success )
{
Global_Shutdown();
t_Result = WBEM_E_FAILED;
}
else
{
for (int x = 0; x < PING_KEY_PROPERTY_COUNT; x++)
{
CKeyEntry t_KeyEntry(s_KeyTable[x]);
t_StatusCode = s_HashTable->Insert ( t_KeyEntry , x ) ;
if ( t_StatusCode != e_StatusCode_Success )
{
Global_Shutdown();
t_Result = WBEM_E_FAILED;
break;
}
}
if (SUCCEEDED(t_Result))
{
s_PingThread = ::new CPingThread( *s_Allocator ) ;
s_PingThread->AddRef();
t_StatusCode = s_PingThread->Initialize () ;
if ( t_StatusCode != e_StatusCode_Success )
{
Global_Shutdown();
t_Result = WBEM_E_FAILED;
}
}
}
}
catch(...)
{
Global_Shutdown();
throw;
}
}
}
}
else
{
t_Result = WBEM_E_FAILED;
}
return t_Result ;
}
HRESULT CPingProvider :: Global_Shutdown ()
{
HRESULT t_Result = S_OK ;
if (s_Allocator && s_PingThread )
{
try
{
if (s_PingThread != NULL)
{
if (s_PingThread->GetHandle ())
{
HANDLE t_ThreadHandle = NULL ;
BOOL t_Status = DuplicateHandle (
GetCurrentProcess () ,
s_PingThread->GetHandle () ,
GetCurrentProcess () ,
& t_ThreadHandle,
0 ,
FALSE ,
DUPLICATE_SAME_ACCESS
) ;
s_PingThread->Release();
WaitForSingleObject ( t_ThreadHandle , INFINITE ) ;
CloseHandle ( t_ThreadHandle ) ;
}
else
{
s_PingThread->Release();
}
}
WmiStatusCode t_StatusCode = WmiThread <ULONG> :: Static_UnInitialize ( *s_Allocator ) ;
}
catch(...)
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
s_PingThread = NULL;
try
{
if (s_HashTable)
{
for (int x = 0; x < PING_KEY_PROPERTY_COUNT; x++)
{
CKeyEntry t_KeyEntry(s_KeyTable[x]);
s_HashTable->Delete ( t_KeyEntry ) ;
}
s_HashTable->UnInitialize () ;
::delete s_HashTable;
}
}
catch(...)
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
s_HashTable = NULL;
}
return t_Result ;
}
//***************************************************************************
//
// CPingProvider ::QueryInterface
// CPingProvider ::AddRef
// CPingProvider ::Release
//
// Purpose: IUnknown members for CPingProvider object.
//***************************************************************************
STDMETHODIMP CPingProvider ::QueryInterface (
REFIID iid ,
LPVOID FAR *iplpv
)
{
HRESULT t_hr = S_OK ;
SetStructuredExceptionHandler seh;
try
{
*iplpv = NULL ;
if ( iid == IID_IUnknown )
{
*iplpv = ( LPVOID ) ( IWbemProviderInit * ) this ;
}
else if ( iid == IID_IWbemProviderInit )
{
*iplpv = ( LPVOID ) ( IWbemProviderInit * ) this ;
}
else if ( iid == IID_IWbemServices )
{
*iplpv = ( LPVOID ) ( IWbemServices * ) this ;
}
if ( *iplpv )
{
( ( LPUNKNOWN ) *iplpv )->AddRef () ;
}
else
{
t_hr = E_NOINTERFACE ;
}
}
catch(Structured_Exception e_SE)
{
t_hr = E_UNEXPECTED;
}
catch(Heap_Exception e_HE)
{
t_hr = E_OUTOFMEMORY;
}
catch(...)
{
t_hr = E_UNEXPECTED;
}
return t_hr;
}
STDMETHODIMP_(ULONG) CPingProvider ::AddRef(void)
{
SetStructuredExceptionHandler seh;
try
{
return InterlockedIncrement ( & m_referenceCount ) ;
}
catch(Structured_Exception e_SE)
{
return 0;
}
catch(Heap_Exception e_HE)
{
return 0;
}
catch(...)
{
return 0;
}
}
STDMETHODIMP_(ULONG) CPingProvider ::Release(void)
{
LONG t_Ref = 0;
SetStructuredExceptionHandler seh;
try
{
if ( ( t_Ref = InterlockedDecrement ( & m_referenceCount ) ) == 0 )
{
delete this ;
return 0 ;
}
else
{
return t_Ref ;
}
}
catch(Structured_Exception e_SE)
{
return 0;
}
catch(Heap_Exception e_HE)
{
return 0;
}
catch(...)
{
return 0;
}
}
BOOL CPingProvider :: GetNotificationObject ( IWbemContext *a_Ctx , IWbemClassObject **a_ppObj )
{
*a_ppObj = NULL;
if ( m_notificationClassObject == NULL )
{
CreateNotificationObject ( a_Ctx ) ;
}
if ( m_notificationClassObject != NULL )
{
if ( FAILED (m_notificationClassObject->SpawnInstance(0, a_ppObj)) )
{
*a_ppObj = NULL;
}
}
return (*a_ppObj != NULL) ;
}
BOOL CPingProvider :: ImpersonateClient ( )
{
return SUCCEEDED(WbemCoImpersonateClient());
}
BOOL CPingProvider::GetClassObject (IWbemClassObject **a_ppClass )
{
BOOL t_RetVal = TRUE;
if ((a_ppClass == NULL) || (m_ClassObject == NULL))
{
t_RetVal = FALSE;
}
else
{
*a_ppClass = m_ClassObject;
(*a_ppClass)->AddRef();
}
return t_RetVal;
}
BOOL CPingProvider :: CreateNotificationObject (
IWbemContext *a_Ctx
)
{
BOOL t_Status = TRUE ;
HRESULT t_Result = m_server->GetObject (
WBEM_CLASS_EXTENDEDSTATUS ,
0 ,
a_Ctx,
& m_notificationClassObject ,
NULL
) ;
if ( ! SUCCEEDED ( t_Result ) )
{
t_Status = FALSE ;
}
return t_Status ;
}
/////////////////////////////////////////////////////////////////////////////
// Functions for the IWbemServices interface that are handled here
HRESULT CPingProvider ::OpenNamespace (
BSTR ObjectPath,
long lFlags,
IWbemContext FAR* pCtx,
IWbemServices FAR* FAR* ppNewContext,
IWbemCallResult FAR* FAR* ppErrorObject
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: CancelAsyncCall (
IWbemObjectSink __RPC_FAR *pSink
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: QueryObjectSink (
long lFlags,
IWbemObjectSink FAR* FAR* ppHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: GetObject (
BSTR ObjectPath,
long lFlags,
IWbemContext FAR *pCtx,
IWbemClassObject FAR* FAR *ppObject,
IWbemCallResult FAR* FAR *ppCallResult
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: GetObjectAsync (
BSTR ObjectPath,
long lFlags,
IWbemContext FAR *pCtx,
IWbemObjectSink FAR* pHandler
)
{
HRESULT t_Result = S_OK ;
SetStructuredExceptionHandler seh;
try
{
if (ImpersonateClient())
{
//
// auto CoRevertToSelf
//
ScopeGuard AutoCoRevertToSelf = MakeGuard ( CoRevertToSelf ) ;
/*
* Create Asynchronous GetObjectByPath object
*/
WSADATA t_WsaData ;
if (0 == WSAStartup (0x0101, & t_WsaData))
{
//
// auto WSA cleanup
//
ON_BLOCK_EXIT ( WSACleanup ) ;
CPingGetAsync *t_AsyncEvent = new CPingGetAsync ( this , ObjectPath , lFlags , pHandler , pCtx ) ;
if (t_AsyncEvent->GetThreadToken())
{
t_AsyncEvent->GetObject();
}
else
{
// Note that ExecQuery will delete this for us.
delete t_AsyncEvent;
}
}
else
{
t_Result = WBEM_E_FAILED;
}
#ifdef _DBG
//
// test return value in checked build
//
AutoCoRevertToSelf.Dismiss () ;
ASSERT ( S_OK == CoRevertToSelf() ) ;
#endif _DBG
}
else
{
t_Result = WBEM_E_ACCESS_DENIED;
}
}
catch(Structured_Exception e_SE)
{
t_Result = WBEM_E_UNEXPECTED;
}
catch(Heap_Exception e_HE)
{
t_Result = WBEM_E_OUT_OF_MEMORY;
}
catch(...)
{
t_Result = E_UNEXPECTED;
}
return t_Result ;
}
HRESULT CPingProvider :: PutClass (
IWbemClassObject FAR* pClass ,
long lFlags,
IWbemContext FAR *pCtx,
IWbemCallResult FAR* FAR* ppCallResult
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: PutClassAsync (
IWbemClassObject FAR* pClass,
long lFlags,
IWbemContext FAR *pCtx,
IWbemObjectSink FAR* pHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: DeleteClass (
BSTR Class,
long lFlags,
IWbemContext FAR *pCtx,
IWbemCallResult FAR* FAR* ppCallResult
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: DeleteClassAsync (
BSTR Class,
long lFlags,
IWbemContext FAR *pCtx,
IWbemObjectSink FAR* pHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: CreateClassEnum (
BSTR Superclass,
long lFlags,
IWbemContext FAR *pCtx,
IEnumWbemClassObject FAR *FAR *ppEnum
)
{
return WBEM_E_NOT_SUPPORTED ;
}
SCODE CPingProvider :: CreateClassEnumAsync (
BSTR Superclass,
long lFlags,
IWbemContext FAR* pCtx,
IWbemObjectSink FAR* pHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: PutInstance (
IWbemClassObject FAR *pInstance,
long lFlags,
IWbemContext FAR *pCtx,
IWbemCallResult FAR *FAR *ppCallResult
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: PutInstanceAsync (
IWbemClassObject FAR* pInstance,
long lFlags,
IWbemContext FAR *pCtx,
IWbemObjectSink FAR* pHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: DeleteInstance (
BSTR ObjectPath,
long lFlags,
IWbemContext FAR *pCtx,
IWbemCallResult FAR *FAR *ppCallResult
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: DeleteInstanceAsync (
BSTR ObjectPath,
long lFlags,
IWbemContext __RPC_FAR *pCtx,
IWbemObjectSink __RPC_FAR *pHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: CreateInstanceEnum (
BSTR Class,
long lFlags,
IWbemContext FAR *pCtx,
IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: CreateInstanceEnumAsync (
BSTR Class,
long lFlags,
IWbemContext __RPC_FAR *pCtx,
IWbemObjectSink FAR* pHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: ExecQuery (
BSTR QueryLanguage,
BSTR Query,
long lFlags,
IWbemContext FAR *pCtx,
IEnumWbemClassObject FAR *FAR *ppEnum
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: ExecQueryAsync (
BSTR QueryFormat,
BSTR Query,
long lFlags,
IWbemContext FAR* pCtx,
IWbemObjectSink FAR* pHandler
)
{
HRESULT t_Result = S_OK ;
SetStructuredExceptionHandler seh;
try
{
if (ImpersonateClient())
{
//
// auto CoRevertToSelf
//
ScopeGuard AutoCoRevertToSelf = MakeGuard ( CoRevertToSelf ) ;
/*
* Create Synchronous Query Instance object
*/
WSADATA t_WsaData ;
if (0 == WSAStartup (0x0101, & t_WsaData))
{
//
// auto WSA cleanup
//
ON_BLOCK_EXIT ( WSACleanup ) ;
CPingQueryAsync *t_AsyncEvent = new CPingQueryAsync ( this , QueryFormat , Query , lFlags , pHandler , pCtx ) ;
if (t_AsyncEvent->GetThreadToken())
{
t_AsyncEvent->ExecQuery();
}
else
{
// Note that ExecQuery will delete this for us.
delete t_AsyncEvent;
}
}
else
{
t_Result = WBEM_E_FAILED;
}
#ifdef _DBG
//
// test return value in checked build
//
AutoCoRevertToSelf.Dismiss () ;
ASSERT ( S_OK == CoRevertToSelf() ) ;
#endif _DBG
}
else
{
t_Result = WBEM_E_ACCESS_DENIED;
}
}
catch(Structured_Exception e_SE)
{
t_Result = WBEM_E_UNEXPECTED;
}
catch(Heap_Exception e_HE)
{
t_Result = WBEM_E_OUT_OF_MEMORY;
}
catch(...)
{
t_Result = WBEM_E_UNEXPECTED;
}
return t_Result ;
}
HRESULT CPingProvider :: ExecNotificationQuery (
BSTR QueryLanguage,
BSTR Query,
long lFlags,
IWbemContext __RPC_FAR *pCtx,
IEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: ExecNotificationQueryAsync (
BSTR QueryLanguage,
BSTR Query,
long lFlags,
IWbemContext __RPC_FAR *pCtx,
IWbemObjectSink __RPC_FAR *pHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT STDMETHODCALLTYPE CPingProvider :: ExecMethod (
BSTR ObjectPath,
BSTR MethodName,
long lFlags,
IWbemContext FAR *pCtx,
IWbemClassObject FAR *pInParams,
IWbemClassObject FAR *FAR *ppOutParams,
IWbemCallResult FAR *FAR *ppCallResult
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT STDMETHODCALLTYPE CPingProvider :: ExecMethodAsync (
BSTR ObjectPath,
BSTR MethodName,
long lFlags,
IWbemContext FAR *pCtx,
IWbemClassObject FAR *pInParams,
IWbemObjectSink FAR *pResponseHandler
)
{
return WBEM_E_NOT_SUPPORTED ;
}
HRESULT CPingProvider :: Initialize(
LPWSTR pszUser,
LONG lFlags,
LPWSTR pszNamespace,
LPWSTR pszLocale,
IWbemServices *pCIMOM, // For anybody
IWbemContext *pCtx,
IWbemProviderInitSink *pInitSink // For init signals
)
{
HRESULT t_result = S_OK;
SetStructuredExceptionHandler seh;
try
{
if ((pCIMOM == NULL) || (pCtx == NULL) || (pInitSink == NULL))
{
t_result = WBEM_E_FAILED;
}
if (SUCCEEDED(t_result))
{
CCritSecAutoUnlock t_lock( &s_CS ) ;
try
{
t_result = Global_Startup ();
if (SUCCEEDED(t_result))
{
if (!m_bInitial)
{
m_bInitial = TRUE;
m_server = pCIMOM ;
m_server->AddRef();
IWbemClassObject *t_Object = NULL;
if ( GetNotificationObject ( pCtx, &t_Object ) )
{
t_Object->Release () ;
t_result = m_server->GetObject (
PROVIDER_NAME_CPINGPROVIDER ,
0 ,
pCtx,
& m_ClassObject ,
NULL
) ;
if ( FAILED(t_result))
{
m_ClassObject = NULL ;
t_result = WBEM_E_FAILED ;
}
}
else
{
t_result = WBEM_E_FAILED ;
}
}
}
}
catch (...)
{
t_result = WBEM_E_FAILED;
}
try
{
pInitSink->SetStatus ( SUCCEEDED(t_result) ? (LONG)WBEM_S_INITIALIZED : (LONG)WBEM_E_FAILED , 0 ) ;
t_result = S_OK;
}
catch(...)
{
t_result = WBEM_E_FAILED;
}
}
}
catch(Structured_Exception e_SE)
{
t_result = WBEM_E_UNEXPECTED;
}
catch(Heap_Exception e_HE)
{
t_result = WBEM_E_OUT_OF_MEMORY;
}
catch(...)
{
t_result = WBEM_E_UNEXPECTED;
}
return t_result ;
}