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

595 lines
16 KiB
C++

// Copyright (c) 1997-1999 Microsoft Corporation
// CWMIExtension.cpp : Implementation of the CWMIExtension class
#include "precomp.h"
extern ULONG g_ulObjCount;
//#include "wmiextension_i.c"
/////////////////////////////////////////////////////////////////////////////
//
/* Constructor */
CWMIExtension::CWMIExtension()
{
HRESULT hr;
ITypeLib *pITypeLib;
m_cRef = 0;
m_pUnkOuter = NULL;
m_pDispOuter = NULL;
m_pInner = NULL;
m_pSWMILocator = NULL;
m_bstrADsName = NULL;
m_pSWMIServices = NULL;
m_pSWMIObject = NULL;
m_pTypeInfo = NULL;
//Create inner object for controlling IUnknown implementation
m_pInner = new CInner(this);
if (m_pInner == NULL)
return;
hr = LoadRegTypeLib(LIBID_WMIEXTENSIONLib, 1,0,
PRIMARYLANGID(GetSystemDefaultLCID()), &pITypeLib);
if FAILED(hr)
return;
hr = pITypeLib->GetTypeInfoOfGuid(IID_IWMIExtension, &m_pTypeInfo);
pITypeLib->Release();
g_ulObjCount++; //global count for objects living in this DLL
};
CWMIExtension::~CWMIExtension()
{
if (m_pUnkOuter)
m_pUnkOuter = NULL;
if (m_pDispOuter)
m_pDispOuter = NULL;
if (m_pInner)
{
delete m_pInner;
m_pInner = NULL;
};
if (m_bstrADsName)
SysFreeString(m_bstrADsName);
if (m_pSWMIObject)
{
m_pSWMIObject->Release();
m_pSWMIObject = NULL;
};
if (m_pSWMIServices)
{
m_pSWMIServices->Release();
m_pSWMIServices = NULL;
};
if (m_pSWMILocator)
{
m_pSWMILocator->Release();
m_pSWMILocator = NULL;
};
if (m_pTypeInfo)
{
m_pTypeInfo->Release();
m_pTypeInfo = NULL;
};
g_ulObjCount--; //global count for objects living in this DLL
};
HRESULT
CWMIExtension::CreateExtension(IUnknown *pUnkOuter, void **ppv)
{
CWMIExtension FAR* pObj = NULL;
HRESULT hr;
IADs *pADs = NULL;
BSTR bstrTempADSName = NULL;
pObj = new CWMIExtension();
if (pObj == NULL)
return E_OUTOFMEMORY;
//No addref needed for outer unknown
pObj->m_pUnkOuter = pUnkOuter;
/*
//Due to the fact that ADSI instantiate us for every object, regardless of whether we're actually being used or not,
//I am moving the code to obtain a locator pointer to the actual functions that need to use it...
//Obtain a WMI Locator and store in member variable
hr = CoCreateInstance(CLSID_SWbemLocator, NULL, CLSCTX_INPROC_SERVER,
IID_ISWbemLocator, (void **)&pObj->m_pSWMILocator);
if FAILED(hr)
{
delete pObj;
return hr;
}
*/
/*
//Due to a bug in the locator security object, we cannot set the security settings here,
//but rather need to move this to the services pointer.
//Setup the impersonation and authentication levels for this locator
ISWbemSecurity *pSecurity = NULL;
hr = pObj->m_pSWMILocator->get_Security_(&pSecurity);
if FAILED(hr)
{
delete pObj;
return hr;
}
hr = pSecurity->put_ImpersonationLevel(wbemImpersonationLevelImpersonate);
hr = pSecurity->put_AuthenticationLevel(wbemAuthenticationLevelConnect);
hr = pSecurity->Release();
if FAILED(hr)
{
delete pObj;
return hr;
}
*/
//Obtain the name of this object from ADSI and store in member :
/* Moved to get_WMIObjectPath since here it doesn't work...
//Get a pointer to the IADs interface of the outer object
hr = pObj->m_pUnkOuter->QueryInterface(IID_IADs, (void **) &pADs );
if FAILED(hr)
return hr;
//Get the name of the outer object
// hr = pADs->get_Name(&bstrTempADSName);
VARIANT var;
VariantInit(&var);
hr = pADs->Get(L"cn", &var);
pObj->m_bstrADsName = SysAllocString(var.bstrVal);
VariantClear(&var);
pADs->Release();
*/
//Since ADSI is adding a "CN=" prefix to the actual machine name, we need to remove it
// pObj->m_bstrADsName = SysAllocString(wcschr(bstrTempADSName, L'=')+1);
// pObj->m_bstrADsName = SysAllocString(bstrTempADSName);
// SysFreeString(bstrTempADSName);
// if FAILED(hr)
// return hr;
//Return the controlling unknown implementation pointer, and addref as required
hr = pObj->m_pInner->QueryInterface(IID_IUnknown, ppv);
return hr;
};
/* IUnknown Methods */
STDMETHODIMP CWMIExtension::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
return m_pUnkOuter->QueryInterface(riid, ppv);
};
STDMETHODIMP_(ULONG)
CWMIExtension::AddRef(void)
{
++m_cRef;
return m_pUnkOuter->AddRef();
};
STDMETHODIMP_(ULONG)
CWMIExtension::Release(void)
{
--m_cRef;
return m_pUnkOuter->Release();
}
/* IDispatch methods */
//IDispatch implementation delegates to the aggregator in this case
STDMETHODIMP CWMIExtension::GetTypeInfoCount(unsigned int FAR* pctinfo)
{
IDispatch *pDisp;
HRESULT hr;
hr = m_pUnkOuter->QueryInterface(IID_IDispatch, (void **) &pDisp);
if FAILED(hr)
return hr;
hr = pDisp->GetTypeInfoCount(pctinfo);
pDisp->Release();
return hr;
}
STDMETHODIMP CWMIExtension::GetTypeInfo(unsigned int itinfo, LCID lcid,
ITypeInfo FAR* FAR* pptinfo)
{
IDispatch *pDisp;
HRESULT hr;
hr = m_pUnkOuter->QueryInterface(IID_IDispatch, (void **) &pDisp);
if FAILED(hr)
return hr;
hr = pDisp->GetTypeInfo(itinfo, lcid, pptinfo);
pDisp->Release();
return hr;
}
STDMETHODIMP CWMIExtension::GetIDsOfNames(REFIID iid, LPWSTR FAR* rgszNames,
unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
{
IDispatch *pDisp;
HRESULT hr;
hr = m_pUnkOuter->QueryInterface(IID_IDispatch, (void **) &pDisp);
if FAILED(hr)
return hr;
hr = pDisp->GetIDsOfNames(iid, rgszNames, cNames, lcid, rgdispid);
pDisp->Release();
return hr;
}
STDMETHODIMP CWMIExtension::Invoke(DISPID dispidMember, REFIID iid, LCID lcid,
unsigned short wFlags, DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo,
unsigned int FAR* puArgErr)
{
IDispatch *pDisp;
HRESULT hr;
hr = m_pUnkOuter->QueryInterface(IID_IDispatch, (void **) &pDisp);
if FAILED(hr)
return hr;
hr = pDisp->Invoke(dispidMember,
iid,
lcid,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr
);
pDisp->Release();
return hr;
}
/* IAdsExtension methods */
STDMETHODIMP CWMIExtension::Operate(ULONG dwCode, VARIANT varData1,
VARIANT varData2, VARIANT varData3)
{
HRESULT hr = S_OK;
switch (dwCode)
{
case ADS_EXT_INITCREDENTIALS:
// For debugging purpose you can prompt a dialog box
// MessageBox(NULL, "INITCRED", "ADsExt", MB_OK);
break;
default:
hr = E_FAIL;
break;
}
return hr;
}
STDMETHODIMP CWMIExtension::PrivateGetIDsOfNames(REFIID riid, OLECHAR ** rgszNames,
unsigned int cNames, LCID lcid, DISPID * rgdispid)
{
if (rgdispid == NULL)
{
return E_POINTER;
}
return DispGetIDsOfNames(m_pTypeInfo, rgszNames, cNames, rgdispid);
}
STDMETHODIMP CWMIExtension::PrivateInvoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS * pdispparams, VARIANT * pvarResult,
EXCEPINFO * pexcepinfo, UINT * puArgErr)
{
return DispInvoke( (IWMIExtension*)this,
m_pTypeInfo,
dispidMember,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr );
}
/* IWMIExtension methods */
STDMETHODIMP CWMIExtension::get_WMIObjectPath(BSTR FAR *strWMIObjectPath)
{
WCHAR wcSWMIName[1024];
HRESULT hr;
//Validate parameter
if (strWMIObjectPath == NULL)
return wbemErrInvalidParameter; //scripting enum
// Moved from CreateExtension() since it doesn't work there...
if (!m_bstrADsName)
{
IADs *pADs = NULL;
BSTR bstrTempADSName = NULL;
hr = m_pUnkOuter->QueryInterface(IID_IADs, (void **) &pADs );
if FAILED(hr)
return hr;
//Get the name of the outer object
hr = pADs->get_Name(&bstrTempADSName);
if FAILED(hr)
{
pADs->Release();
return hr;
}
//Since ADSI is adding a "CN=" prefix to the actual machine name, we need to remove it
m_bstrADsName = SysAllocString(wcschr(bstrTempADSName, L'=')+1);
SysFreeString(bstrTempADSName);
pADs->Release();
}
//Construct the path for matching (S)WMI object
wcscpy(wcSWMIName, L"WINMGMTS:{impersonationLevel=impersonate}!//");
wcscat(wcSWMIName, m_bstrADsName);
wcscat(wcSWMIName, L"/root/cimv2:Win32_ComputerSystem.Name=\"");
wcscat(wcSWMIName, m_bstrADsName);
wcscat(wcSWMIName, L"\"");
//Allocate out parameter and copy result to it
*strWMIObjectPath = SysAllocString(wcSWMIName);
return NOERROR;
}; //get_WMIObjectPath
STDMETHODIMP CWMIExtension::GetWMIObject(ISWbemObject FAR* FAR* objWMIObject)
{
HRESULT hr;
BSTR bstrObjPath;
//Validate parameter
if (objWMIObject == NULL)
return wbemErrInvalidParameter;
// Moved from CreateExtension() since it doesn't work there...
//Obtain the name of this object from ADSI and store in member, if not already there
if (!m_bstrADsName)
{
IADs *pADs = NULL;
BSTR bstrTempADSName = NULL;
hr = m_pUnkOuter->QueryInterface(IID_IADs, (void **) &pADs );
if FAILED(hr)
return hr;
//Get the name of the outer object
hr = pADs->get_Name(&bstrTempADSName);
if FAILED(hr)
{
pADs->Release();
return hr;
}
//Since ADSI is adding a "CN=" prefix to the actual machine name, we need to remove it
m_bstrADsName = SysAllocString(wcschr(bstrTempADSName, L'=')+1);
SysFreeString(bstrTempADSName);
pADs->Release();
}
//Obtain a WMI Locator and store in member variable, if not already there
if (!m_pSWMILocator)
{
hr = CoCreateInstance(CLSID_SWbemLocator, NULL, CLSCTX_INPROC_SERVER,
IID_ISWbemLocator, (void **)&m_pSWMILocator);
if FAILED(hr)
return hr;
}
//Get the respective SWMI services pointer if we don't have it already, and cache in member
if (!m_pSWMIServices)
{
BSTR bstrNamespace = SysAllocString(L"root\\cimv2");
hr = m_pSWMILocator->ConnectServer(m_bstrADsName, bstrNamespace, NULL, NULL, 0, NULL, 0, NULL, &m_pSWMIServices);
SysFreeString(bstrNamespace);
if FAILED(hr)
return hr;
//Setup the impersonation and authentication levels for this services pointer
ISWbemSecurity *pSecurity = NULL;
hr = m_pSWMIServices->get_Security_(&pSecurity);
if FAILED(hr)
return hr;
hr = pSecurity->put_ImpersonationLevel(wbemImpersonationLevelImpersonate);
hr = pSecurity->put_AuthenticationLevel(wbemAuthenticationLevelConnect);
hr = pSecurity->Release();
if FAILED(hr)
return hr;
};
//Get the SWMI object using this services pointer, if we don't have it already, and cache in member
if (!m_pSWMIObject)
{
WCHAR wcObjPath[256];
//Construct the path of the object
wcscpy(wcObjPath, L"Win32_ComputerSystem.Name=\"");
wcscat(wcObjPath, m_bstrADsName);
wcscat(wcObjPath, L"\"");
bstrObjPath = SysAllocString(wcObjPath);
hr = m_pSWMIServices->Get(bstrObjPath, 0, NULL, &m_pSWMIObject);
SysFreeString(bstrObjPath);
if FAILED(hr)
return hr;
};
//AddRef the object pointer before we hand it out...
m_pSWMIObject->AddRef();
*objWMIObject = m_pSWMIObject;
return NOERROR;
}; //GetWMIObject
STDMETHODIMP CWMIExtension::GetWMIServices(ISWbemServices FAR* FAR* objWMIServices)
{
HRESULT hr;
//Validate parameter
if (objWMIServices == NULL)
return wbemErrInvalidParameter;
// Moved from CreateExtension() since it doesn't work there...
//Obtain the name of this object from ADSI and store in member, if not already there
if (!m_bstrADsName)
{
IADs *pADs = NULL;
BSTR bstrTempADSName = NULL;
hr = m_pUnkOuter->QueryInterface(IID_IADs, (void **) &pADs );
if FAILED(hr)
return hr;
//Get the name of the outer object
hr = pADs->get_Name(&bstrTempADSName);
if FAILED(hr)
{
pADs->Release();
return hr;
}
//Since ADSI is adding a "CN=" prefix to the actual machine name, we need to remove it
m_bstrADsName = SysAllocString(wcschr(bstrTempADSName, L'=')+1);
SysFreeString(bstrTempADSName);
pADs->Release();
}
//Obtain a WMI Locator and store in member variable, if not already there
if (!m_pSWMILocator)
{
hr = CoCreateInstance(CLSID_SWbemLocator, NULL, CLSCTX_INPROC_SERVER,
IID_ISWbemLocator, (void **)&m_pSWMILocator);
if FAILED(hr)
return hr;
}
//Get the respective SWMI services pointer if we don't have it already, and cache in member
if (!m_pSWMIServices)
{
BSTR bstrNamespace = SysAllocString(L"root\\cimv2");
hr = m_pSWMILocator->ConnectServer(m_bstrADsName, bstrNamespace, NULL, NULL, 0, NULL, 0, NULL, &m_pSWMIServices);
SysFreeString(bstrNamespace);
if FAILED(hr)
return hr;
//Setup the impersonation and authentication levels for this services pointer
ISWbemSecurity *pSecurity = NULL;
hr = m_pSWMIServices->get_Security_(&pSecurity);
if FAILED(hr)
return hr;
hr = pSecurity->put_ImpersonationLevel(wbemImpersonationLevelImpersonate);
hr = pSecurity->put_AuthenticationLevel(wbemAuthenticationLevelConnect);
hr = pSecurity->Release();
if FAILED(hr)
return hr;
};
//AddRef the services pointer before we hand it out
m_pSWMIServices->AddRef();
*objWMIServices = m_pSWMIServices;
return NOERROR;
}; //GetWMIServices
/* Implementation of CInner class which implements the controlling IUnknown for the object */
//Constructor
CInner::CInner(CWMIExtension *pOwner)
{
m_cRef = 0;
m_pOwner = pOwner;
};
//Destructor
CInner::~CInner()
{
};
STDMETHODIMP CInner::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
if (riid == IID_IUnknown)
*ppv=(IUnknown *)this;
else if (riid == IID_IDispatch)
*ppv=(IDispatch *)m_pOwner;
else if (riid == IID_IWMIExtension)
*ppv=(IWMIExtension *)m_pOwner;
else if (riid == IID_IADsExtension)
*ppv=(IADsExtension *)m_pOwner;
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
((IUnknown *)*ppv)->AddRef();
return NOERROR;
};
STDMETHODIMP_(ULONG)
CInner::AddRef(void)
{
return ++m_cRef;
};
STDMETHODIMP_(ULONG)
CInner::Release(void)
{
if (--m_cRef != 0)
return m_cRef;
delete m_pOwner;
return 0;
};
// eof CWMIExtension.cpp