//*************************************************************************** // // PINGPROV.CPP // // Module: WMI PING PROVIDER // // Purpose: Implementation for the CPingProvider class. // // Copyright (c) 2000-2002 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #include #ifndef INITGUID #define INITGUID #endif #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 #include #include #include #include #include #include ///////////////////////////////////////////////////////////////////////////// // 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 *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 :: Static_Initialize ( *s_Allocator ) ; if ( t_StatusCode != e_StatusCode_Success ) { t_Result = WBEM_E_FAILED; } else { try { s_HashTable = ::new WmiHashTable ( *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 :: 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 ; }