2025-04-27 07:49:33 -04:00

503 lines
14 KiB
C++

//
// Copyright (c) 1997-1999 Microsoft Corporation
//
//
//***************************************************************************
#include "precomp.h"
#include <tchar.h>
#include <comdef.h>
#include <wbemtran.h>
#include <wbemprov.h>
#include "globals.h"
#include "wmixmlst.h"
#include "wmixmlstf.h"
#include "cwmixmlserv.h"
#include "xmlsec.h"
CWMIXMLEnumWbemClassObject :: CWMIXMLEnumWbemClassObject(IEnumWbemClassObject *pEnum)
{
InterlockedIncrement(&g_lComponents);
m_ReferenceCount = 0 ;
m_pEnum = NULL;
m_pEnum = pEnum;
if(m_pEnum)
m_pEnum->AddRef();
}
CWMIXMLEnumWbemClassObject :: ~CWMIXMLEnumWbemClassObject()
{
if(m_pEnum)
m_pEnum->Release();
}
//***************************************************************************
//
// CWMIXMLServices::QueryInterface
// CWMIXMLServices::AddRef
// CWMIXMLServices::Release
//
// Purpose: Standard COM routines needed for all interfaces
//
//***************************************************************************
STDMETHODIMP CWMIXMLEnumWbemClassObject::QueryInterface (
REFIID iid ,
LPVOID FAR *iplpv
)
{
*iplpv = NULL ;
if ( iid == IID_IUnknown )
{
*iplpv = ( IUnknown * ) this ;
}
else if ( iid == IID_IWmiXMLEnumWbemClassObject )
{
*iplpv = ( IWmiXMLEnumWbemClassObject * ) this ;
}
else
{
return E_NOINTERFACE;
}
( ( LPUNKNOWN ) *iplpv )->AddRef () ;
return S_OK;
}
STDMETHODIMP_( ULONG ) CWMIXMLEnumWbemClassObject :: AddRef ()
{
return InterlockedIncrement ( & m_ReferenceCount ) ;
}
STDMETHODIMP_(ULONG) CWMIXMLEnumWbemClassObject :: Release ()
{
LONG ref ;
if ( ( ref = InterlockedDecrement ( & m_ReferenceCount ) ) == 0 )
{
delete this ;
return 0 ;
}
else
{
return ref ;
}
}
HRESULT STDMETHODCALLTYPE CWMIXMLEnumWbemClassObject :: Next(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ long lTimeout,
/* [in] */ ULONG uCount,
/* [out, size_is(uCount), length_is(*puReturned)] */ IWbemClassObject** apObjects,
/*[out] */ ULONG* puReturned
)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
result = m_pEnum->Next(lTimeout, uCount, apObjects, puReturned);
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLEnumWbemClassObject :: FreeToken(
/* [in] */ DWORD_PTR dwToken)
{
HANDLE hToken = (HANDLE)dwToken;
CloseHandle(hToken);
return S_OK;
}
CWMIXMLServices :: CWMIXMLServices(IWbemServices *pServices)
{
InterlockedIncrement(&g_lComponents);
m_ReferenceCount = 0 ;
m_pServices = NULL;
m_pServices = pServices;
if(m_pServices)
m_pServices->AddRef();
}
CWMIXMLServices :: ~CWMIXMLServices()
{
if(m_pServices)
m_pServices->Release();
}
//***************************************************************************
//
// CWMIXMLServices::QueryInterface
// CWMIXMLServices::AddRef
// CWMIXMLServices::Release
//
// Purpose: Standard COM routines needed for all interfaces
//
//***************************************************************************
STDMETHODIMP CWMIXMLServices::QueryInterface (
REFIID iid ,
LPVOID FAR *iplpv
)
{
*iplpv = NULL ;
if ( iid == IID_IUnknown )
{
*iplpv = ( IUnknown * ) this ;
}
else if ( iid == IID_IWmiXMLWbemServices )
{
*iplpv = ( IWmiXMLWbemServices * ) this ;
}
else
{
return E_NOINTERFACE;
}
( ( LPUNKNOWN ) *iplpv )->AddRef () ;
return S_OK;
}
STDMETHODIMP_( ULONG ) CWMIXMLServices :: AddRef ()
{
return InterlockedIncrement ( & m_ReferenceCount ) ;
}
STDMETHODIMP_(ULONG) CWMIXMLServices :: Release ()
{
LONG ref ;
if ( ( ref = InterlockedDecrement ( & m_ReferenceCount ) ) == 0 )
{
delete this ;
return 0 ;
}
else
{
return ref ;
}
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: GetObject(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ const BSTR strObjectPath,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemClassObject __RPC_FAR *__RPC_FAR *ppObject,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
result = m_pServices->GetObject(strObjectPath, lFlags, pCtx, ppObject, ppCallResult);
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: PutClass(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ IWbemClassObject __RPC_FAR *pObject,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
result = m_pServices->PutClass(pObject, lFlags, pCtx, ppCallResult);
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: DeleteClass(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ const BSTR strClass,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
result = m_pServices->DeleteClass(strClass, lFlags, pCtx, ppCallResult);
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: CreateClassEnum(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ const BSTR strSuperclass,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [out] */ IWmiXMLEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
IEnumWbemClassObject *pEnum = NULL;
*ppEnum = NULL;
if(SUCCEEDED(result = m_pServices->CreateClassEnum(strSuperclass, lFlags, pCtx, &pEnum)))
{
// Wrap the enumerator in our own one
*ppEnum = new CWMIXMLEnumWbemClassObject(pEnum);
if(*ppEnum)
{
result = WBEM_S_NO_ERROR;
}
else
result = E_OUTOFMEMORY;
pEnum->Release();
}
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: PutInstance(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ IWbemClassObject __RPC_FAR *pInst,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
result = m_pServices->PutInstance(pInst, lFlags, pCtx, ppCallResult);
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: DeleteInstance(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ const BSTR strObjectPath,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
result = m_pServices->DeleteInstance(strObjectPath, lFlags, pCtx, ppCallResult);
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: CreateInstanceEnum(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ const BSTR strClass,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [out] */ IWmiXMLEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
IEnumWbemClassObject *pEnum = NULL;
*ppEnum = NULL;
if(SUCCEEDED(result = m_pServices->CreateInstanceEnum(strClass, lFlags, pCtx, &pEnum)))
{
// Wrap the enumerator in our own one
*ppEnum = new CWMIXMLEnumWbemClassObject(pEnum);
if(*ppEnum)
{
result = WBEM_S_NO_ERROR;
}
else
result = E_OUTOFMEMORY;
pEnum->Release();
}
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: ExecQuery(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ const BSTR strQueryLanguage,
/* [in] */ const BSTR strQuery,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [out] */ IWmiXMLEnumWbemClassObject __RPC_FAR *__RPC_FAR *ppEnum)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
IEnumWbemClassObject *pEnum = NULL;
*ppEnum = NULL;
if(SUCCEEDED(result = m_pServices->ExecQuery(strQueryLanguage, strQuery, lFlags, pCtx, &pEnum)))
{
// Wrap the enumerator in our own one
*ppEnum = new CWMIXMLEnumWbemClassObject(pEnum);
if(*ppEnum)
{
result = WBEM_S_NO_ERROR;
}
else
result = E_OUTOFMEMORY;
pEnum->Release();
}
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: ExecMethod(
/* [in] */ DWORD_PTR dwToken,
/* [in] */ const BSTR strObjectPath,
/* [in] */ const BSTR strMethodName,
/* [in] */ long lFlags,
/* [in] */ IWbemContext __RPC_FAR *pCtx,
/* [in] */ IWbemClassObject __RPC_FAR *pInParams,
/* [unique][in][out] */ IWbemClassObject __RPC_FAR *__RPC_FAR *ppOutParams,
/* [unique][in][out] */ IWbemCallResult __RPC_FAR *__RPC_FAR *ppCallResult)
{
HRESULT result = E_FAIL;
HANDLE hToken = (HANDLE)dwToken;
// Change the COM call context to our own one
IUnknown *pOldContext = NULL;
if(SUCCEEDED(result = CXmlCallSecurity::SwitchCOMToThreadContext(hToken, &pOldContext)))
{
// Talk to WinMgmt
result = m_pServices->ExecMethod(strObjectPath, strMethodName, lFlags, pCtx, pInParams, ppOutParams, ppCallResult);
// Switch back the context to the standard COM one
IUnknown *pXmlContext = NULL;
CoSwitchCallContext(pOldContext, &pXmlContext);
pXmlContext->Release();
}
// This handle was duplicated from the ISAPI extension on to the current process. Hence
// we need to close it here
CloseHandle(hToken);
return result;
}
HRESULT STDMETHODCALLTYPE CWMIXMLServices :: FreeToken(
/* [in] */ DWORD_PTR dwToken)
{
HANDLE hToken = (HANDLE)dwToken;
CloseHandle(hToken);
return S_OK;
}