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

605 lines
16 KiB
C++

//***************************************************************************
//
// Copyright (c) 1998-2000 Microsoft Corporation
//
// LOCATOR.CPP
//
// alanbos 15-Aug-96 Created.
//
// Defines the implementation of ISWbemLocator
//
//***************************************************************************
#include "precomp.h"
#include "objsink.h"
#define WBEMS_DEFAULT_SERVER L"."
extern CRITICAL_SECTION g_csErrorCache;
wchar_t *CSWbemLocator::s_pDefaultNamespace = NULL;
//***************************************************************************
//
// CSWbemLocator::CSWbemLocator
//
// DESCRIPTION:
//
// Constructor.
//
//***************************************************************************
CSWbemLocator::CSWbemLocator(CSWbemPrivilegeSet *pPrivilegeSet) :
m_pUnsecuredApartment (NULL),
m_pIServiceProvider (NULL),
m_cRef (0)
{
// Initialize the underlying locators
HRESULT result = CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator,
(LPVOID *) &m_pIWbemLocator);
EnsureGlobalsInitialized () ;
m_Dispatch.SetObj((ISWbemLocator *)this, IID_ISWbemLocator,
CLSID_SWbemLocator, L"SWbemLocator");
m_SecurityInfo = new CWbemLocatorSecurity (pPrivilegeSet);
if (m_SecurityInfo)
{
// Set the impersonation level by default in the locator - note
// that this must be done after EnsureGlobalsInitialized is called
m_SecurityInfo->put_ImpersonationLevel (CSWbemSecurity::GetDefaultImpersonationLevel ());
}
InterlockedIncrement(&g_cObj);
}
CSWbemLocator::CSWbemLocator(CSWbemLocator & csWbemLocator) :
m_pUnsecuredApartment (NULL),
m_pIServiceProvider (NULL),
m_cRef (0)
{
_RD(static char *me = "CSWbemLocator::CSWbemLocator()";)
// This is a smart COM pointers so no explicit AddRef required
m_pIWbemLocator = csWbemLocator.m_pIWbemLocator;
m_Dispatch.SetObj((ISWbemLocator *)this,IID_ISWbemLocator,
CLSID_SWbemLocator, L"SWbemLocator");
m_SecurityInfo = new CWbemLocatorSecurity (csWbemLocator.m_SecurityInfo);
InterlockedIncrement(&g_cObj);
}
//***************************************************************************
//
// CSWbemLocator::~CSWbemLocator
//
// DESCRIPTION:
//
// Destructor.
//
//***************************************************************************
CSWbemLocator::~CSWbemLocator(void)
{
InterlockedDecrement(&g_cObj);
RELEASEANDNULL(m_SecurityInfo)
RELEASEANDNULL(m_pUnsecuredApartment)
}
//***************************************************************************
// HRESULT CSWbemLocator::QueryInterface
// long CSWbemLocator::AddRef
// long CSWbemLocator::Release
//
// DESCRIPTION:
//
// Standard Com IUNKNOWN functions.
//
//***************************************************************************
STDMETHODIMP CSWbemLocator::QueryInterface (
IN REFIID riid,
OUT LPVOID *ppv
)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv = reinterpret_cast<IUnknown*>(this);
else if (IID_ISWbemLocator==riid)
*ppv = (ISWbemLocator *)this;
else if (IID_IDispatch==riid)
*ppv = (IDispatch *)((ISWbemLocator *)this);
else if (IID_IObjectSafety==riid)
*ppv = (IObjectSafety *)this;
else if (IID_IDispatchEx==riid)
*ppv = (IDispatchEx *)this;
else if (IID_ISupportErrorInfo==riid)
*ppv = (ISupportErrorInfo *)this;
else if (IID_IProvideClassInfo==riid)
*ppv = (IProvideClassInfo *)this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CSWbemLocator::AddRef(void)
{
InterlockedIncrement(&m_cRef);
return m_cRef;
}
STDMETHODIMP_(ULONG) CSWbemLocator::Release(void)
{
InterlockedDecrement(&m_cRef);
if (0L!=m_cRef)
return m_cRef;
delete this;
return 0;
}
// IDispatch methods should be inline
STDMETHODIMP CSWbemLocator::GetTypeInfoCount(UINT* pctinfo)
{
_RD(static char *me = "CSWbemLocator::GetTypeInfoCount()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.GetTypeInfoCount(pctinfo);}
STDMETHODIMP CSWbemLocator::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
_RD(static char *me = "CSWbemLocator::GetTypeInfo()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.GetTypeInfo(itinfo, lcid, pptinfo);}
STDMETHODIMP CSWbemLocator::GetIDsOfNames(REFIID riid, OLECHAR** rgszNames,
UINT cNames, LCID lcid, DISPID* rgdispid)
{
_RD(static char *me = "CSWbemLocator::GetIdsOfNames()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.GetIDsOfNames(riid, rgszNames, cNames,
lcid,
rgdispid);}
STDMETHODIMP CSWbemLocator::Invoke(DISPID dispidMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
_RD(static char *me = "CSWbemLocator::Invoke()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.Invoke(dispidMember, riid, lcid, wFlags,
pdispparams, pvarResult, pexcepinfo, puArgErr);}
// IDispatchEx methods should be inline
HRESULT STDMETHODCALLTYPE CSWbemLocator::GetDispID(
/* [in] */ BSTR bstrName,
/* [in] */ DWORD grfdex,
/* [out] */ DISPID __RPC_FAR *pid)
{
_RD(static char *me = "CSWbemLocator::GetDispID()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.GetDispID(bstrName, grfdex, pid);
}
/* [local] */ HRESULT STDMETHODCALLTYPE CSWbemLocator::InvokeEx(
/* [in] */ DISPID id,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [in] */ DISPPARAMS __RPC_FAR *pdp,
/* [out] */ VARIANT __RPC_FAR *pvarRes,
/* [out] */ EXCEPINFO __RPC_FAR *pei,
/* [unique][in] */ IServiceProvider __RPC_FAR *pspCaller)
{
HRESULT hr;
_RD(static char *me = "CSWbemLocator::InvokeEx()";)
_RPrint(me, "Called", (long)id, "id");
_RPrint(me, "Called", (long)wFlags, "wFlags");
/*
* Store away the service provider so that it can be accessed
* by calls that remote to CIMOM
*/
m_pIServiceProvider = pspCaller;
hr = m_Dispatch.InvokeEx(id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
m_pIServiceProvider = NULL;
return hr;
}
HRESULT STDMETHODCALLTYPE CSWbemLocator::DeleteMemberByName(
/* [in] */ BSTR bstr,
/* [in] */ DWORD grfdex)
{
_RD(static char *me = "CSWbemLocator::DeleteMemberByName()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.DeleteMemberByName(bstr, grfdex);
}
HRESULT STDMETHODCALLTYPE CSWbemLocator::DeleteMemberByDispID(
/* [in] */ DISPID id)
{
_RD(static char *me = "CSWbemLocator::DeletememberByDispId()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.DeleteMemberByDispID(id);
}
HRESULT STDMETHODCALLTYPE CSWbemLocator::GetMemberProperties(
/* [in] */ DISPID id,
/* [in] */ DWORD grfdexFetch,
/* [out] */ DWORD __RPC_FAR *pgrfdex)
{
_RD(static char *me = "CSWbemLocator::GetMemberProperties()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.GetMemberProperties(id, grfdexFetch, pgrfdex);
}
HRESULT STDMETHODCALLTYPE CSWbemLocator::GetMemberName(
/* [in] */ DISPID id,
/* [out] */ BSTR __RPC_FAR *pbstrName)
{
_RD(static char *me = "CSWbemLocator::GetMemberName()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.GetMemberName(id, pbstrName);
}
/*
* I don't think this needs implementing
*/
HRESULT STDMETHODCALLTYPE CSWbemLocator::GetNextDispID(
/* [in] */ DWORD grfdex,
/* [in] */ DISPID id,
/* [out] */ DISPID __RPC_FAR *pid)
{
_RD(static char *me = "CSWbemLocator::GetNextDispID()";)
HRESULT rc = S_FALSE;
_RPrint(me, "Called", 0, "");
if ((grfdex & fdexEnumAll) && pid) {
if (DISPID_STARTENUM == id) {
*pid = 1;
rc = S_OK;
} else if (1 == id) {
*pid = 2;
}
}
return rc;
}
HRESULT STDMETHODCALLTYPE CSWbemLocator::GetNameSpaceParent(
/* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk)
{
_RD(static char *me = "CSWbemLocator::GetNamespaceParent()";)
_RPrint(me, "Called", 0, "");
return m_Dispatch.GetNameSpaceParent(ppunk);
}
//***************************************************************************
// HRESULT CSWbemLocator::InterfaceSupportsErrorInfo
//
// DESCRIPTION:
//
// Standard Com ISupportErrorInfo functions.
//
//***************************************************************************
STDMETHODIMP CSWbemLocator::InterfaceSupportsErrorInfo (IN REFIID riid)
{
return (IID_ISWbemLocator == riid) ? S_OK : S_FALSE;
}
//***************************************************************************
//
// SCODE CSWbemLocator::ConnectServer
//
// DESCRIPTION:
//
// Initiate connection to namespace
//
// PARAMETERS:
//
// bsServer The Server to which to connect
// bsNamespace The namespace to connect to (default is reg lookup)
// bsUser The user ("" implies default to logged-on user)
// bsPassword The password ("" implies default to logged-on user's
// password if bsUser == "")
// bsLocale Requested locale
// bsAuthority Authority
// lSecurityFlags Currently 0 by default
// pContext If non-null, extra context info for the connection
// ppNamespace On successful return addresses the IWbemSServices
// connection to the namespace.
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
// Other WBEM error codes may be returned by ConnectServer etc., in which
// case these are passed on to the caller.
//
//***************************************************************************
HRESULT CSWbemLocator::ConnectServer (
BSTR bsServer,
BSTR bsNamespace,
BSTR bsUser,
BSTR bsPassword,
BSTR bsLocale,
BSTR bsAuthority,
long lSecurityFlags,
/*ISWbemValueBag*/ IDispatch *pContext,
ISWbemServices **ppNamespace
)
{
_RD(static char *me = "CSWbemLocator::ConnectServer";)
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if (NULL == ppNamespace)
hr = WBEM_E_INVALID_PARAMETER;
else if (m_pIWbemLocator && m_SecurityInfo)
{
bool useDefaultUser = (NULL == bsUser) || (0 == wcslen(bsUser));
bool useDefaultAuthority = (NULL != bsAuthority) && (0 == wcslen (bsAuthority));
// Build the namespace path
BSTR bsNamespacePath = BuildPath (bsServer, bsNamespace);
// Get the context
IWbemContext *pIContext = CSWbemNamedValueSet::GetIWbemContext (pContext, m_pIServiceProvider);
// Connect to the requested namespace
IWbemServices *pIWbemService = NULL;
bool needToResetSecurity = false;
HANDLE hThreadToken = NULL;
if (m_SecurityInfo->SetSecurity (bsUser, needToResetSecurity, hThreadToken))
hr = m_pIWbemLocator->ConnectServer (
bsNamespacePath,
(useDefaultUser) ? NULL : bsUser,
(useDefaultUser) ? NULL : bsPassword,
((NULL != bsLocale) && (0 < wcslen (bsLocale))) ? bsLocale : NULL,
lSecurityFlags,
(useDefaultAuthority) ? NULL : bsAuthority,
pIContext,
&pIWbemService);
if (needToResetSecurity)
m_SecurityInfo->ResetSecurity (hThreadToken);
if (WBEM_S_NO_ERROR == hr)
{
// Create a new CSWbemServices using the IWbemServices interface
// just returned. This will AddRef pIWbemService.
CSWbemServices *pService =
new CSWbemServices (
pIWbemService,
bsNamespacePath,
((NULL != bsAuthority) && (0 < wcslen (bsAuthority))) ? bsAuthority : NULL,
(useDefaultUser) ? NULL : bsUser,
(useDefaultUser) ? NULL : bsPassword,
m_SecurityInfo,
((NULL != bsLocale) && (0 < wcslen (bsLocale))) ? bsLocale : NULL
);
if (!pService)
hr = WBEM_E_OUT_OF_MEMORY;
else if (FAILED(hr = pService->QueryInterface (IID_ISWbemServices,
(PPVOID) ppNamespace)))
delete pService;
pIWbemService->Release ();
}
if (NULL != pIContext)
pIContext->Release ();
SysFreeString (bsNamespacePath);
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CSWbemLocator::BuildPath
//
// DESCRIPTION:
//
// Build a namespace path from a server and namespace
//
// PARAMETERS:
//
// bsServer The Server to which to connect
// bsNamespace The namespace to connect to (default is reg lookup)
//
// RETURN VALUES:
//
// The fully-formed namespace path
//
//***************************************************************************
BSTR CSWbemLocator::BuildPath (BSTR bsServer, BSTR bsNamespace)
{
BSTR namespacePath = NULL;
bool ok = false;
CComBSTR bsPath;
if ((NULL == bsServer) || (0 == wcslen(bsServer)))
bsServer = WBEMS_DEFAULT_SERVER;
// Use the default namespace if none supplied
if ((NULL == bsNamespace) || (0 == wcslen(bsNamespace)))
{
const wchar_t *defaultNamespace = GetDefaultNamespace ();
if (defaultNamespace)
{
CWbemPathCracker pathCracker;
pathCracker.SetServer (bsServer);
pathCracker.SetNamespacePath (defaultNamespace);
ok = pathCracker.GetPathText (bsPath, false, true);
}
}
else
{
CWbemPathCracker pathCracker;
pathCracker.SetServer (bsServer);
pathCracker.SetNamespacePath (bsNamespace);
ok = pathCracker.GetPathText (bsPath, false, true);
}
if (ok)
namespacePath = bsPath.Detach ();
return namespacePath;
}
//***************************************************************************
//
// SCODE CSWbemLocator::GetDefaultNamespace
//
// DESCRIPTION:
//
// Get the default namespace path
//
// PARAMETERS:
//
// None
//
// RETURN VALUES:
//
// The default Namespace.
//
//***************************************************************************
const wchar_t *CSWbemLocator::GetDefaultNamespace ()
{
if (!s_pDefaultNamespace)
{
// Get the value from the registry key
HKEY hKey;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WBEMS_RK_SCRIPTING, 0, KEY_QUERY_VALUE, &hKey))
{
DWORD dataLen = 0;
// Find out how much space to allocate first
if (ERROR_SUCCESS == RegQueryValueEx (hKey, WBEMS_RV_DEFNS,
NULL, NULL, NULL, &dataLen))
{
TCHAR *defNamespace = new TCHAR [dataLen];
if (defNamespace)
{
if (ERROR_SUCCESS == RegQueryValueEx (hKey, WBEMS_RV_DEFNS,
NULL, NULL, (LPBYTE) defNamespace, &dataLen))
{
#ifndef UNICODE
// Convert the multibyte value to its wide character equivalent
int wDataLen = MultiByteToWideChar(CP_ACP, 0, defNamespace, -1, NULL, 0);
s_pDefaultNamespace = new wchar_t [wDataLen];
if (s_pDefaultNamespace)
MultiByteToWideChar(CP_ACP, 0, defNamespace, -1, s_pDefaultNamespace, wDataLen);
#else
s_pDefaultNamespace = new wchar_t [wcslen (defNamespace) + 1];
if (s_pDefaultNamespace)
wcscpy (s_pDefaultNamespace, defNamespace);
#endif
}
delete [] defNamespace;
}
}
RegCloseKey (hKey);
}
// If we failed to read the registry OK, just use the default
if (!s_pDefaultNamespace)
{
#ifndef UNICODE
int wDataLen = MultiByteToWideChar(CP_ACP, 0, WBEMS_DEFNS, -1, NULL, 0);
s_pDefaultNamespace = new wchar_t [wDataLen];
if (s_pDefaultNamespace)
MultiByteToWideChar(CP_ACP, 0, WBEMS_DEFNS, -1, s_pDefaultNamespace, wDataLen);
#else
s_pDefaultNamespace = new wchar_t [wcslen (WBEMS_DEFNS) + 1];
if (s_pDefaultNamespace)
wcscpy (s_pDefaultNamespace, WBEMS_DEFNS);
#endif
}
}
return s_pDefaultNamespace;
}
//***************************************************************************
//
// SCODE CSWbemLocator::get_Security_
//
// DESCRIPTION:
//
// Return the security configurator
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CSWbemLocator::get_Security_ (
ISWbemSecurity **ppSecurity
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if (NULL == ppSecurity)
hr = WBEM_E_INVALID_PARAMETER;
{
*ppSecurity = NULL;
if (m_SecurityInfo)
{
if (SUCCEEDED (m_SecurityInfo->QueryInterface (IID_ISWbemSecurity,
(PPVOID) ppSecurity)))
hr = WBEM_S_NO_ERROR;
}
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}