windows-nt/Source/XPSP1/NT/admin/wmi/wbem/providers/wdmprovider/wmiprov.cpp
2020-09-26 16:20:57 +08:00

680 lines
21 KiB
C++

/////////////////////////////////////////////////////////////////////
//
// WMIProv.CPP
//
// Module: WMI Provider class methods
//
// Purpose: Provider class definition. An object of this class is
// created by the class factory for each connection.
//
// Copyright (c) 1997-2002 Microsoft Corporation, All Rights Reserved
//
/////////////////////////////////////////////////////////////////////
#include "precomp.h"
long glInits = -1;
long glEventsRegistered = -1;
long glProvObj = 0;
extern CWMIEvent * g_pBinaryMofEvent;
extern CCriticalSection * g_pSharedLocalEventsCs;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void VerifyLocalEventsAreRegistered()
{
if( InterlockedIncrement(&glEventsRegistered) == 1 )
{
if( g_pBinaryMofEvent )
{
if( !g_pBinaryMofEvent->RegisterForInternalEvents())
{
glEventsRegistered = 0; // start over again next time
}
else
{
ERRORTRACE((THISPROVIDER,"Successfully Registered for Mof Events\n"));
}
}
}
ERRORTRACE((THISPROVIDER,"Local Events Verified called, glEventsRegistered: %ld\n", glEventsRegistered));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT SetupLocalEvents()
{
HRESULT hr = S_OK;
CAutoBlock Block(g_pSharedLocalEventsCs);
if( g_pBinaryMofEvent == NULL )
{
g_pBinaryMofEvent = (CWMIEvent *)new CWMIEvent(INTERNAL_EVENT); // This is the global guy that catches events of new drivers being added at runtime.
if(g_pBinaryMofEvent)
{
glEventsRegistered = 0;
VerifyLocalEventsAreRegistered();
}
else
{
hr = E_OUTOFMEMORY;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void DeleteLocalEvents()
{
CAutoBlock Block(g_pSharedLocalEventsCs);
if( g_pBinaryMofEvent )
{
g_pBinaryMofEvent->DeleteAllLeftOverEvents();
g_pBinaryMofEvent->DeleteBinaryMofResourceEvent();
g_pBinaryMofEvent->ReleaseAllPointers();
SAFE_DELETE_PTR(g_pBinaryMofEvent);
glEventsRegistered = -1;
ERRORTRACE((THISPROVIDER,"No longer registered for Mof events\n"));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ProcessAllBinaryMofs(CHandleMap * pMap, IWbemServices __RPC_FAR *pNamespace,IWbemContext __RPC_FAR *pCtx,BOOL bProcessMofs)
{
CWMIBinMof Mof;
if( SUCCEEDED( Mof.Initialize(pMap,TRUE,WMIGUID_EXECUTE|WMIGUID_QUERY,pNamespace,NULL,pCtx)))
{
RevertToSelf();
if(bProcessMofs)
{
Mof.ProcessListOfWMIBinaryMofsFromWMI();
}
//==============================================================
// Register for hardcoded event to be notified of WMI updates
// make it a member var, so it stays around for the life
// of the provider
//==============================================================
if( g_pBinaryMofEvent )
{
CAutoBlock Block(g_pSharedLocalEventsCs);
g_pBinaryMofEvent->SetEventServices(pNamespace);
g_pBinaryMofEvent->SetEventContext(pCtx);
g_pBinaryMofEvent->ReadyForInternalEvents(TRUE);
VerifyLocalEventsAreRegistered();
}
}
CheckImpersonationLevelAndVerifyInternalEvents(FALSE);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//*********************************************************************
// Check the impersonation level
//*********************************************************************
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CheckImpersonationLevelAndVerifyInternalEvents(BOOL fVerifyLocalEvents)
{
HRESULT hr = WBEM_E_ACCESS_DENIED;
HANDLE hThreadTok;
if (IsNT())
{
if( GetUserThreadToken(&hThreadTok) )
{
DWORD dwImp, dwBytesReturned;
if (GetTokenInformation( hThreadTok, TokenImpersonationLevel, &dwImp, sizeof(DWORD), &dwBytesReturned)){
if( fVerifyLocalEvents )
{
if( glEventsRegistered < 2 )
{
VerifyLocalEventsAreRegistered();
}
}
// Is the impersonation level Impersonate?
if ((dwImp == SecurityImpersonation) || ( dwImp == SecurityDelegation) )
{
hr = WBEM_S_NO_ERROR;
}
else
{
hr = WBEM_E_ACCESS_DENIED;
ERRORTRACE((THISPROVIDER,IDS_ImpersonationFailed));
}
}
else
{
hr = WBEM_E_FAILED;
ERRORTRACE((THISPROVIDER,IDS_ImpersonationFailed));
}
// Done with this handle
CloseHandle(hThreadTok);
}
}
else
{
// let win9X in...
hr = WBEM_S_NO_ERROR;
}
return hr;
}
////////////////////////////////////////////////////////////////////
//
//
//
////////////////////////////////////////////////////////////////////
HRESULT CWMI_Prov::PutInstanceAsync(IWbemClassObject __RPC_FAR * pIWbemClassObject,
long lFlags,
IWbemContext __RPC_FAR *pCtx,
IWbemObjectSink __RPC_FAR *pHandler )
{
HRESULT hr = WBEM_E_FAILED;
SetStructuredExceptionHandler seh;
if(pIWbemClassObject == NULL || pHandler == NULL )
{
return WBEM_E_INVALID_PARAMETER;
}
//===========================================================
// Get the class name
//===========================================================
CVARIANT vName;
hr = pIWbemClassObject->Get(L"__CLASS", 0, &vName, NULL, NULL);
if( SUCCEEDED(hr))
{
CWMIStandardShell WMI;
if( SUCCEEDED(WMI.Initialize(vName.GetStr(),FALSE,&m_HandleMap,TRUE,WMIGUID_SET|WMIGUID_QUERY,m_pIWbemServices,pHandler,pCtx)))
{
if (SUCCEEDED(hr = CheckImpersonationLevelAndVerifyInternalEvents(TRUE)))
{
//=======================================================
// If there is not a context object, then we know we are
// supposed to put the whole thing, otherwise we are
// supposed to put only the properties specified.
//=======================================================
try
{
if( !pCtx )
{
hr = WMI.FillInAndSubmitWMIDataBlob(pIWbemClassObject,PUT_WHOLE_INSTANCE,vName);
}
else
{
//===================================================
// If we have a ctx object and the __PUT_EXTENSIONS
// property is not specified, then we know we are
// supposed to put the whole thing
//===================================================
CVARIANT vPut;
if( SUCCEEDED(pCtx->GetValue(L"__PUT_EXT_PROPERTIES", 0, &vPut)))
{
hr = WMI.FillInAndSubmitWMIDataBlob(pIWbemClassObject,PUT_PROPERTIES_IN_LIST_ONLY,vPut);
}
else
{
hr = WMI.FillInAndSubmitWMIDataBlob(pIWbemClassObject,PUT_WHOLE_INSTANCE,vPut);
}
}
}
STANDARD_CATCH
}
}
hr = WMI.SetErrorMessage(hr);
}
return hr;
}
////////////////////////////////////////////////////////////////////
//******************************************************************
//
// PUBLIC FUNCTIONS
//
//******************************************************************
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
//
// CWMI_Prov::CWMI_Prov
//
////////////////////////////////////////////////////////////////////
CWMI_Prov::CWMI_Prov()
{
#if defined(_AMD64_) || defined(_IA64_)
m_Allocator = NULL;
m_HashTable = NULL;
m_ID = 0;
try
{
InitializeCriticalSection(&m_CS);
WmiAllocator t_Allocator ;
WmiStatusCode t_StatusCode = t_Allocator.New (
( void ** ) & m_Allocator ,
sizeof ( WmiAllocator )
) ;
if ( t_StatusCode == e_StatusCode_Success )
{
:: new ( ( void * ) m_Allocator ) WmiAllocator ;
t_StatusCode = m_Allocator->Initialize () ;
if ( t_StatusCode != e_StatusCode_Success )
{
t_Allocator.Delete ( ( void * ) m_Allocator ) ;
m_Allocator = NULL;
DeleteCriticalSection(&m_CS);
}
else
{
m_HashTable = ::new WmiHashTable <LONG, ULONG_PTR, 17> ( *m_Allocator ) ;
t_StatusCode = m_HashTable->Initialize () ;
if ( t_StatusCode != e_StatusCode_Success )
{
m_HashTable->UnInitialize () ;
::delete m_HashTable;
m_HashTable = NULL;
m_Allocator->UnInitialize ();
t_Allocator.Delete ( ( void * ) m_Allocator ) ;
m_Allocator = NULL;
DeleteCriticalSection(&m_CS);
}
}
}
else
{
m_Allocator = NULL;
DeleteCriticalSection(&m_CS);
}
}
catch (...)
{
}
#endif
m_cRef=0;
m_pIWbemServices = NULL;
InterlockedIncrement(&g_cObj);
InterlockedIncrement(&glProvObj);
ERRORTRACE((THISPROVIDER,"Instance Provider constructed\n"));
}
////////////////////////////////////////////////////////////////////
//
// CWMI_Prov::~CWMI_Prov
//
////////////////////////////////////////////////////////////////////
CWMI_Prov::~CWMI_Prov(void)
{
SAFE_RELEASE_PTR( m_pIWbemServices );
InterlockedDecrement(&g_cObj);
if(InterlockedDecrement(&glProvObj) == 0)
{
glInits = -1;
}
ERRORTRACE((THISPROVIDER,"Instance Provider destructed\n"));
#if defined(_AMD64_) || defined(_IA64_)
if (m_HashTable)
{
WmiAllocator t_Allocator ;
m_HashTable->UnInitialize () ;
::delete m_HashTable;
m_HashTable = NULL;
m_Allocator->UnInitialize ();
t_Allocator.Delete ( ( void * ) m_Allocator ) ;
m_Allocator = NULL;
DeleteCriticalSection(&m_CS);
}
#endif
}
////////////////////////////////////////////////////////////////////
//
// QueryInterface
//
////////////////////////////////////////////////////////////////////
STDMETHODIMP CWMI_Prov::QueryInterface(REFIID riid, PPVOID ppvObj)
{
HRESULT hr = E_NOINTERFACE;
*ppvObj = NULL;
if (IsEqualIID(riid, IID_IUnknown))
{
*ppvObj =(IWbemServices *) this ;
}
else if (IsEqualIID(riid, IID_IWbemServices))
{
*ppvObj =(IWbemServices *) this ;
}
else if (IsEqualIID(riid, IID_IWbemProviderInit))
{
*ppvObj = (IWbemProviderInit *) this ;
}
else if(riid == IID_IWbemProviderInit)
{
*ppvObj = (LPVOID)(IWbemProviderInit*)this;
}
else if (riid == IID_IWbemHiPerfProvider)
{
*ppvObj = (LPVOID)(IWbemHiPerfProvider*)this;
}
if(*ppvObj)
{
AddRef();
hr = NOERROR;
}
return hr;
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMI_Prov::Initialize(
/* [in] */ LPWSTR pszUser,
/* [in] */ LONG lFlags,
/* [in] */ LPWSTR pszNamespace,
/* [in] */ LPWSTR pszLocale,
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink)
{
if(pNamespace == NULL){
return WBEM_E_INVALID_PARAMETER;
}
//===============================================
m_pIWbemServices = pNamespace;
m_pIWbemServices->AddRef();
if( InterlockedIncrement(&glInits) == 0 )
{
ProcessAllBinaryMofs(&m_HandleMap, pNamespace, pCtx);
}
pInitSink->SetStatus(WBEM_S_NO_ERROR, 0);
return WBEM_S_NO_ERROR;
}
//////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CWMI_Prov::AddRef(void)
{
return InterlockedIncrement((long*)&m_cRef);
}
STDMETHODIMP_(ULONG) CWMI_Prov::Release(void)
{
ULONG cRef = InterlockedDecrement( (long*) &m_cRef);
if ( !cRef ){
delete this;
return 0;
}
return cRef;
}
////////////////////////////////////////////////////////////////////
//
// CWMI_Prov::OpenNamespace
//
////////////////////////////////////////////////////////////////////
HRESULT CWMI_Prov::OpenNamespace(
/* [in] */ BSTR Namespace,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemServices __RPC_FAR *__RPC_FAR *ppWorkingNamespace,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppResult)
{
return WBEM_E_PROVIDER_NOT_CAPABLE ;
}
////////////////////////////////////////////////////////////////////
//
// CWMI_Prov::CreateInstanceEnumAsync
//
// Purpose: Asynchronously enumerates the instances of the
// given class.
//
////////////////////////////////////////////////////////////////
HRESULT CWMI_Prov::CreateInstanceEnumAsync(BSTR wcsClass,
long lFlags,
IWbemContext __RPC_FAR *pCtx,
IWbemObjectSink __RPC_FAR * pHandler)
{
HRESULT hr = WBEM_E_FAILED;
SetStructuredExceptionHandler seh;
CWMIStandardShell WMI;
if( SUCCEEDED(WMI.Initialize(wcsClass,FALSE,&m_HandleMap,TRUE,WMIGUID_QUERY,m_pIWbemServices,pHandler,pCtx)))
{
if (SUCCEEDED(hr = CheckImpersonationLevelAndVerifyInternalEvents(TRUE)))
{
//============================================================
// Init and get the WMI Data block
//============================================================
if( pHandler != NULL )
{
//============================================================
// Parse through all of it
//============================================================
try
{
hr = WMI.ProcessAllInstances();
}
STANDARD_CATCH
}
}
WMI.SetErrorMessage(hr);
}
return hr;
}
//***************************************************************************
HRESULT CWMI_Prov::ExecQueryAsync( BSTR QueryLanguage,
BSTR Query,
long lFlags,
IWbemContext __RPC_FAR *pCtx,
IWbemObjectSink __RPC_FAR *pHandler)
{
WCHAR wcsClass[_MAX_PATH+2];
HRESULT hr = WBEM_E_FAILED;
SetStructuredExceptionHandler seh;
BOOL fRc = FALSE;
//============================================================
// Do a check of arguments and make sure we have pointers
//============================================================
if( pHandler == NULL )
{
return WBEM_E_INVALID_PARAMETER;
}
try
{
//============================================================
// Get the properties and class to get
//============================================================
fRc = GetParsedPropertiesAndClass(Query,wcsClass);
}
STANDARD_CATCH
CWMIStandardShell WMI;
if( SUCCEEDED(WMI.Initialize(wcsClass,FALSE,&m_HandleMap,TRUE,WMIGUID_NOTIFICATION|WMIGUID_QUERY,m_pIWbemServices,pHandler,pCtx)))
{
if( fRc )
{
hr = CheckImpersonationLevelAndVerifyInternalEvents(TRUE);
}
hr = WMI.SetErrorMessage(hr);
}
return hr;
}
//***************************************************************************
//
// CWMI_Prov::GetObjectAsync
//
// Purpose: Asynchronously creates an instance given a particular path value.
//
// NOTE 1: If there is an instance name in the returned WNODE, then this is a
// dynamic instance. You can tell because the pWNSI->OffsetInstanceName
// field will not be blank. If this is the case, then the name will not
// be contained within the datablock, but must instead be retrieved
// from the WNODE. See NOTE 1, below.
//
//***************************************************************************
HRESULT CWMI_Prov::GetObjectAsync(BSTR ObjectPath, long lFlags,
IWbemContext __RPC_FAR *pCtx,
IWbemObjectSink __RPC_FAR * pHandler )
{
HRESULT hr = WBEM_E_NOT_FOUND;
SetStructuredExceptionHandler seh;
WCHAR wcsClass[_MAX_PATH*2];
WCHAR wcsInstance[_MAX_PATH*2];
//============================================================
// Do a check of arguments and make sure we have pointers
//============================================================
if(ObjectPath == NULL || pHandler == NULL )
{
return WBEM_E_INVALID_PARAMETER;
}
try
{
memset(wcsClass,NULL,_MAX_PATH*2);
//============================================================
// Get the path and instance name
//============================================================
hr = GetParsedPath( ObjectPath,wcsClass,wcsInstance,m_pIWbemServices );
}
STANDARD_CATCH
if( SUCCEEDED(hr) )
{
if (SUCCEEDED(hr = CheckImpersonationLevelAndVerifyInternalEvents(TRUE)))
{
try
{
CWMIStandardShell WMI;
if( SUCCEEDED(WMI.Initialize(wcsClass,FALSE,&m_HandleMap,TRUE,WMIGUID_QUERY,m_pIWbemServices,pHandler,pCtx)))
{
//============================================================
// Get the WMI Block
//============================================================
hr = WMI.ProcessSingleInstance(wcsInstance);
hr = WMI.SetErrorMessage(hr);
}
}
STANDARD_CATCH
}
}
return hr;
}
/************************************************************************
* *
*CWMIMethod::ExecMethodAsync *
* *
*Purpose: This is the Async function implementation *
************************************************************************/
STDMETHODIMP CWMI_Prov::ExecMethodAsync(BSTR ObjectPath,
BSTR MethodName,
long lFlags,
IWbemContext __RPC_FAR * pCtx,
IWbemClassObject __RPC_FAR * pIWbemClassObject,
IWbemObjectSink __RPC_FAR * pHandler)
{
CVARIANT vName;
HRESULT hr = WBEM_E_FAILED;
IWbemClassObject * pClass = NULL; //This is an IWbemClassObject.
WCHAR wcsClass[_MAX_PATH*2];
WCHAR wcsInstance[_MAX_PATH*2];
SetStructuredExceptionHandler seh;
try
{
//============================================================
// Get the path and instance name and check to make sure it
// is valid
//============================================================
hr = GetParsedPath( ObjectPath,wcsClass,wcsInstance ,m_pIWbemServices);
}
STANDARD_CATCH
CWMIStandardShell WMI;
if( SUCCEEDED(WMI.Initialize(wcsClass,FALSE,&m_HandleMap,TRUE,WMIGUID_EXECUTE|WMIGUID_QUERY,m_pIWbemServices,pHandler,pCtx)))
{
if (SUCCEEDED(hr = CheckImpersonationLevelAndVerifyInternalEvents(TRUE)))
{
//================================================================
// We are ok, so proceed
//================================================================
hr = m_pIWbemServices->GetObject(wcsClass, 0, pCtx, &pClass, NULL);
if( SUCCEEDED(hr) )
{
//==========================================================
// Now, get the list of Input and Output parameters
//==========================================================
IWbemClassObject * pOutClass = NULL; //This is an IWbemClassObject.
IWbemClassObject * pInClass = NULL; //This is an IWbemClassObject.
hr = pClass->GetMethod(MethodName, 0, &pInClass, &pOutClass);
if( SUCCEEDED(hr) )
{
try
{
hr = WMI.ExecuteMethod( wcsInstance, MethodName,pClass, pIWbemClassObject,pInClass, pOutClass);
}
STANDARD_CATCH
}
SAFE_RELEASE_PTR( pOutClass );
SAFE_RELEASE_PTR( pInClass );
SAFE_RELEASE_PTR( pClass );
}
}
hr = WMI.SetErrorMessage(hr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIHiPerfProvider::Initialize(
/* [in] */ LPWSTR pszUser,
/* [in] */ LONG lFlags,
/* [in] */ LPWSTR pszNamespace,
/* [in] */ LPWSTR pszLocale,
/* [in] */ IWbemServices __RPC_FAR *pNamespace,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink)
{
if(pNamespace == NULL){
return WBEM_E_INVALID_PARAMETER;
}
//===============================================
m_pIWbemServices = pNamespace;
m_pIWbemServices->AddRef();
if( InterlockedIncrement(&glInits) == 0 )
{
ProcessAllBinaryMofs(&m_HandleMap, pNamespace, pCtx,FALSE);
}
pInitSink->SetStatus(WBEM_S_NO_ERROR, 0);
return WBEM_S_NO_ERROR;
}
////////////////////////////////////////////////////////////////////
//******************************************************************
//
// PRIVATE FUNCTIONS
//
//******************************************************************
////////////////////////////////////////////////////////////////////