You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2035 lines
58 KiB
2035 lines
58 KiB
/*++
|
|
|
|
Copyright (C) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Abstract:
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CREP.CPP
|
|
//
|
|
// Wrappers for repository drivers
|
|
//
|
|
// raymcc 27-Apr-00 WMI Repository init & mapping layer
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "precomp.h"
|
|
#include <wbemcore.h>
|
|
#include <oahelp.inl>
|
|
#include <unk.h>
|
|
|
|
extern IClassFactory* g_pQueryFact;
|
|
|
|
// ESE only.
|
|
// =========
|
|
|
|
IWmiDbController *CRepository::m_pEseController = 0;
|
|
IWmiDbSession *CRepository::m_pEseSession = 0;
|
|
IWmiDbHandle *CRepository::m_pEseRoot = 0;
|
|
|
|
//
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
class CNamespaceListSink : public CUnkBase<IWbemObjectSink, &IID_IWbemObjectSink>
|
|
{
|
|
CWStringArray &m_aNamespaceList;
|
|
public:
|
|
CNamespaceListSink(CWStringArray &aNamespaceList)
|
|
: m_aNamespaceList(aNamespaceList)
|
|
{
|
|
}
|
|
~CNamespaceListSink()
|
|
{
|
|
}
|
|
STDMETHOD(Indicate)(long lNumObjects, IWbemClassObject** apObjects)
|
|
{
|
|
HRESULT hRes;
|
|
for (int i = 0; i != lNumObjects; i++)
|
|
{
|
|
if (apObjects[i] != NULL)
|
|
{
|
|
_IWmiObject *pInst = NULL;
|
|
hRes = apObjects[i]->QueryInterface(IID__IWmiObject, (void**)&pInst);
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
CReleaseMe rm(pInst);
|
|
|
|
BSTR strKey = NULL;
|
|
hRes = pInst->GetKeyString(0, &strKey);
|
|
if(FAILED(hRes))
|
|
return hRes;
|
|
CSysFreeMe sfm(strKey);
|
|
if (m_aNamespaceList.Add(strKey) != CWStringArray::no_error)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
STDMETHOD(SetStatus)(long lFlags, HRESULT hresResult, BSTR, IWbemClassObject*)
|
|
{
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CRepository::Init
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CRepository::Init()
|
|
{
|
|
HRESULT hRes;
|
|
IWmiDbController *pController = 0;
|
|
WMIDB_LOGON_TEMPLATE *pTemplate = 0;
|
|
IWmiDbSession *pSession= 0;
|
|
IWmiDbHandle *pRoot = 0;
|
|
|
|
// Retrieve the CLSID of the default driver.
|
|
// =========================================
|
|
CLSID clsid;
|
|
hRes = ConfigMgr::GetDefaultRepDriverClsId(clsid);
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
hRes = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IWmiDbController, (void **)&pController);
|
|
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
CReleaseMe _1(pController);
|
|
|
|
hRes = pController->GetLogonTemplate(0x409, 0, &pTemplate);
|
|
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
//
|
|
// Commenting out code since its not used for its intended 'purposes' anymore. Provides
|
|
// an excellent opportunity to pass the TlsIndex of the securityFlag to the
|
|
// repository though.
|
|
WMIDB_LOGON_PARAMETER LogonParam ;
|
|
V_VT (&(pTemplate->pParm->Value)) = VT_I4 ;
|
|
V_I4 (&(pTemplate->pParm->Value)) = CCoreQueue::GetSecFlagTlsIndex ( ) ;
|
|
|
|
|
|
//
|
|
//for (DWORD i = 0; i < pTemplate->dwArraySize; i++)
|
|
//{
|
|
// if (!wbem_wcsicmp(pTemplate->pParm[i].strParmDisplayName, L"Server"))
|
|
// {
|
|
// pTemplate->pParm[i].Value.bstrVal = 0;
|
|
// pTemplate->pParm[i].Value.vt = VT_BSTR;
|
|
// }
|
|
// else if (!wbem_wcsicmp(pTemplate->pParm[i].strParmDisplayName, L"Database"))
|
|
// {
|
|
// WString sDir = ConfigMgr::GetWorkingDir();
|
|
// sDir += "\\repository\\wmi.edb";
|
|
|
|
// pTemplate->pParm[i].Value.bstrVal = SysAllocString(LPWSTR(sDir));
|
|
// pTemplate->pParm[i].Value.vt = VT_BSTR;
|
|
// }
|
|
// else if (!wbem_wcsicmp(pTemplate->pParm[i].strParmDisplayName, L"UserID"))
|
|
// {
|
|
// pTemplate->pParm[i].Value.bstrVal = SysAllocString(L"Admin");
|
|
// pTemplate->pParm[i].Value.vt = VT_BSTR;
|
|
// }
|
|
// else if (!wbem_wcsicmp(pTemplate->pParm[i].strParmDisplayName, L"Password"))
|
|
// {
|
|
// pTemplate->pParm[i].Value.bstrVal = SysAllocString(L"");
|
|
// pTemplate->pParm[i].Value.vt = VT_BSTR;
|
|
// }
|
|
//}
|
|
|
|
// Logon to Jet.
|
|
// =============
|
|
|
|
hRes = pController->Logon(pTemplate, 0, WMIDB_HANDLE_TYPE_VERSIONED, &pSession, &pRoot);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
m_pEseSession = pSession;
|
|
m_pEseRoot = pRoot; // Refcount is ok
|
|
}
|
|
|
|
pController->FreeLogonTemplate(&pTemplate);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
m_pEseController = pController;
|
|
m_pEseController->AddRef();
|
|
}
|
|
|
|
// Ensure ROOT and ROOT\DEFAULT are there.
|
|
// =======================================
|
|
|
|
if (SUCCEEDED(hRes))
|
|
hRes = EnsureDefault(); // SEC:REVIEWED 2002-03-22 : Needs exception handler
|
|
|
|
if (SUCCEEDED(hRes))
|
|
hRes = UpgradeSystemClasses(); // SEC:REVIEWED 2002-03-22 : Needs exception handler
|
|
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
DWORD dwMaxSize;
|
|
HKEY hKey;
|
|
long lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"SOFTWARE\\Microsoft\\WBEM\\CIMOM",
|
|
0, KEY_READ | KEY_WRITE, &hKey);
|
|
if(lRes)
|
|
return lRes;
|
|
CRegCloseMe cm(hKey);
|
|
|
|
DWORD dwLen = sizeof(DWORD);
|
|
lRes = RegQueryValueExW(hKey, L"Max Class Cache Size", NULL, NULL,
|
|
(LPBYTE)&dwMaxSize, &dwLen);
|
|
|
|
if(lRes != ERROR_SUCCESS)
|
|
{
|
|
dwMaxSize = 5000000;
|
|
lRes = RegSetValueExW(hKey, L"Max Class Cache Size", 0, REG_DWORD,
|
|
(LPBYTE)&dwMaxSize, sizeof(DWORD));
|
|
}
|
|
m_pEseController->SetCacheValue(dwMaxSize);
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
HRESULT CRepository::EnsureDefault()
|
|
{
|
|
HRESULT hRes;
|
|
IWmiDbSession *pSession = NULL;
|
|
IWmiDbSessionEx *pSessionEx = NULL;
|
|
IWmiDbHandle *pRootNs = 0, *pRootDefaultNs = 0, *pRootSecurityNs = 0;
|
|
|
|
//Create a new session...
|
|
hRes = CRepository::GetNewSession(&pSession);
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
//Get an EX version that supports transactioning...
|
|
pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pSessionEx);
|
|
if (pSessionEx)
|
|
{
|
|
pSession->Release();
|
|
pSession = pSessionEx;
|
|
}
|
|
CReleaseMe relMe1(pSession);
|
|
|
|
//If we have transactionable session, use it!
|
|
if (pSessionEx)
|
|
{
|
|
hRes = pSessionEx->BeginWriteTransaction(0);
|
|
if (FAILED(hRes))
|
|
{
|
|
return hRes;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
//First we work on the ROOT namespace
|
|
//-----------------------------------
|
|
hRes = OpenEseNs(pSession, L"ROOT", &pRootNs);
|
|
if (hRes == WBEM_E_NOT_FOUND)
|
|
{
|
|
//Create as it does not exist...
|
|
hRes = CreateEseNs(pSession, L"ROOT", &pRootNs);
|
|
}
|
|
|
|
//Unfortunately, root always seems to have been created, so cannot actually optimise this one!
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Create objects that only reside in the root namespace
|
|
hRes = EnsureNsSystemRootObjects(pSession, pRootNs, NULL, NULL);
|
|
}
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Create generic instances that exist in all namespaces
|
|
hRes = EnsureNsSystemInstances(pSession, pRootNs, NULL, NULL);
|
|
}
|
|
if (hRes == WBEM_E_NOT_FOUND)
|
|
{
|
|
//Something bad happened! This error has a special meaning
|
|
//later on, so remapping so something safer!
|
|
hRes = WBEM_E_FAILED;
|
|
}
|
|
|
|
//Next we work on the ROOT\DEFAULT namesapce...
|
|
//---------------------------------------------
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = OpenEseNs(pSession, L"ROOT\\DEFAULT", &pRootDefaultNs);
|
|
}
|
|
if (hRes == WBEM_E_NOT_FOUND)
|
|
{
|
|
//Create the namespace as it does not exist and add all the standard
|
|
//stuff that is needed in there...
|
|
hRes = CreateEseNs(pSession, L"ROOT\\DEFAULT", &pRootDefaultNs);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Need to auto-recover MOFs as this point guarentees that this is
|
|
//a new repository
|
|
ConfigMgr::SetDefaultMofLoadingNeeded();
|
|
}
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Create generic instances that exist in all namespaces
|
|
hRes = EnsureNsSystemInstances(pSession, pRootDefaultNs, pSession, pRootNs);
|
|
}
|
|
}
|
|
if (hRes == WBEM_E_NOT_FOUND)
|
|
{
|
|
//Something bad happened! This error has a special meaning
|
|
//later on, so remapping so something safer!
|
|
hRes = WBEM_E_FAILED;
|
|
}
|
|
|
|
//Finally we work on the ROOT\SECURITY namespace
|
|
//-----------------------------------------------
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = OpenEseNs(pSession, L"ROOT\\SECURITY", &pRootSecurityNs);
|
|
}
|
|
if (hRes == WBEM_E_NOT_FOUND)
|
|
{
|
|
//The namespace is not there so create it
|
|
hRes = CreateEseNs(pSession, L"ROOT\\SECURITY", &pRootSecurityNs);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Store system instances that exist in all namespaces
|
|
hRes = EnsureNsSystemInstances(pSession, pRootSecurityNs, pSession, pRootNs);
|
|
}
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Store the security objects into the namespace. These only reside in this
|
|
//namespace
|
|
hRes = EnsureNsSystemSecurityObjects(pSession, pRootSecurityNs, pSession, pRootNs);
|
|
}
|
|
}
|
|
}
|
|
catch (...) // not sure about this one
|
|
{
|
|
ExceptionCounter c;
|
|
ERRORTRACE((LOG_WBEMCORE, "Creation of empty repository caused a very critical error!\n"));
|
|
hRes = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Commit the transaction
|
|
if (pSessionEx)
|
|
{
|
|
hRes = pSessionEx->CommitTransaction(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WBEMCORE, "Creation of empty repository failed with error <0x%X>!\n", hRes));
|
|
if (pSessionEx)
|
|
pSessionEx->AbortTransaction(0);
|
|
}
|
|
|
|
if (pRootNs)
|
|
pRootNs->Release();
|
|
if (pRootDefaultNs)
|
|
pRootDefaultNs->Release();
|
|
if (pRootSecurityNs)
|
|
pRootSecurityNs->Release();
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
HRESULT CRepository::Shutdown(BOOL bIsSystemShutDown)
|
|
{
|
|
if (m_pEseRoot)
|
|
{
|
|
m_pEseRoot->Release();
|
|
m_pEseRoot = NULL;
|
|
}
|
|
|
|
if (m_pEseSession)
|
|
{
|
|
m_pEseSession->Release();
|
|
m_pEseSession = NULL;
|
|
}
|
|
|
|
if (m_pEseController)
|
|
{
|
|
m_pEseController->Shutdown(bIsSystemShutDown?WMIDB_SHUTDOWN_MACHINE_DOWN:0);
|
|
m_pEseController->Release();
|
|
m_pEseController = NULL;
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
// ok
|
|
|
|
HRESULT CRepository::GetDefaultSession(
|
|
OUT IWmiDbSession **pSession
|
|
)
|
|
{
|
|
if (m_pEseSession == 0)
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
|
|
*pSession = m_pEseSession;
|
|
(*pSession)->AddRef();
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CRepository::OpenNs
|
|
//
|
|
// ESE only
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
HRESULT CRepository::OpenEseNs(
|
|
IN IWmiDbSession *pSession,
|
|
IN LPCWSTR pszNamespace,
|
|
OUT IWmiDbHandle **pHandle
|
|
)
|
|
{
|
|
if (pHandle == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if (pSession == NULL)
|
|
pSession = m_pEseSession;
|
|
|
|
*pHandle = 0;
|
|
|
|
// Check for virtual root ns (one level up from ROOT).
|
|
// ===================================================
|
|
if (pszNamespace == 0)
|
|
{
|
|
if (m_pEseRoot == 0)
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
|
|
*pHandle = m_pEseRoot;
|
|
(*pHandle)->AddRef();
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// Loop through the nested namespaces until we get to the last one.
|
|
// ================================================================
|
|
size_t tmpLength = wcslen(pszNamespace)+1;
|
|
wchar_t* pszSource = new wchar_t[tmpLength];
|
|
CVectorDeleteMe<wchar_t> vdm1(pszSource);
|
|
if (pszSource == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
StringCchCopyW(pszSource, tmpLength, pszNamespace);
|
|
LPCWSTR pszDelimit = L"\\";
|
|
LPWSTR pszTok = wcstok(LPWSTR(pszSource), pszDelimit);
|
|
HRESULT hRes = 0;
|
|
IWmiDbHandle *pCurrent = m_pEseRoot;
|
|
IWmiDbHandle *pTmp = 0;
|
|
if (pCurrent)
|
|
pCurrent->AddRef();
|
|
else
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
|
|
while (pszTok)
|
|
{
|
|
// Current namespace is <pszTok>
|
|
// =============================
|
|
|
|
IWbemPath *pPath = ConfigMgr::GetNewPath();
|
|
if (pPath == 0)
|
|
{
|
|
pCurrent->Release();
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CReleaseMe _1(pPath);
|
|
|
|
WString sPath;
|
|
try
|
|
{
|
|
sPath = "__namespace='";
|
|
sPath += pszTok; // SEC:REVIEWED 2002-03-22 : Needs long-name check
|
|
sPath += "'";
|
|
}
|
|
catch (CX_MemoryException &)
|
|
{
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
};
|
|
|
|
pPath->SetText(WBEMPATH_TREAT_SINGLE_IDENT_AS_NS | WBEMPATH_CREATE_ACCEPT_ALL , sPath);
|
|
|
|
hRes = pSession->GetObject(pCurrent, pPath, 0, WMIDB_HANDLE_TYPE_COOKIE, &pTmp);
|
|
|
|
pszTok = wcstok(NULL, pszDelimit); // SEC:REVIEWED 2002-03-22 : What happens if ill formed?
|
|
pCurrent->Release();
|
|
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
// If here, we got it. So either we are done, or we need to keep going.
|
|
// =====================================================================
|
|
if (pszTok)
|
|
pCurrent = pTmp;
|
|
else
|
|
{
|
|
// All done
|
|
*pHandle = pTmp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
// Executed; seems to work
|
|
|
|
HRESULT CRepository::GetObject(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR pszObjectPath, // NS relative only for now
|
|
IN ULONG uFlags,
|
|
OUT IWbemClassObject **pObj
|
|
)
|
|
{
|
|
HRESULT hRes;
|
|
|
|
//
|
|
// Check if the session supports faster interface
|
|
//
|
|
|
|
IWmiDbSessionEx* pEx = NULL;
|
|
hRes = pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pEx);
|
|
if(SUCCEEDED(hRes))
|
|
{
|
|
CReleaseMe rm1(pEx);
|
|
|
|
hRes = pEx->GetObjectByPath(pNs, pszObjectPath, uFlags,
|
|
IID_IWbemClassObject, (void**)pObj);
|
|
}
|
|
else
|
|
{
|
|
// Path to object.
|
|
// ===============
|
|
IWbemPath *pPath = ConfigMgr::GetNewPath();
|
|
if (pPath == 0)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
CReleaseMe _1(pPath);
|
|
pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pszObjectPath);
|
|
|
|
|
|
// Get it.
|
|
// =======
|
|
|
|
hRes = pSession->GetObjectDirect(pNs, pPath, uFlags, IID_IWbemClassObject, (void **)pObj);
|
|
}
|
|
|
|
if (FAILED(hRes))
|
|
{
|
|
// DEBUGTRACE((LOG_REPDRV, "Failed with 0x%X\n", hRes));
|
|
return hRes;
|
|
}
|
|
else
|
|
{
|
|
#ifdef TESTONLY
|
|
BSTR str = 0;
|
|
(*pObj)->GetObjectText(0, &str);
|
|
DEBUGTRACE((LOG_REPDRV, " GetObject() Text = \n%S\n\n", str));
|
|
SysFreeString(str);
|
|
#endif
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Does not support nesting yet
|
|
//
|
|
//***************************************************************************
|
|
// ok
|
|
|
|
HRESULT CRepository::CreateEseNs(
|
|
IN IWmiDbSession *pSession,
|
|
IN LPCWSTR pszNamespace,
|
|
OUT IWmiDbHandle **pHandle
|
|
)
|
|
{
|
|
HRESULT hRes = 0;
|
|
|
|
if (pszNamespace == 0 || pHandle == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if (pSession == NULL)
|
|
{
|
|
pSession = m_pEseSession;
|
|
}
|
|
|
|
// Loop through each namespace and try to open it. If we can
|
|
// keep going. If we fail, create it at the current level and
|
|
// return the handle.
|
|
// ===========================================================
|
|
|
|
size_t tmpLength = wcslen(pszNamespace)+1;
|
|
wchar_t* pszSource = new wchar_t[tmpLength];
|
|
CVectorDeleteMe<wchar_t> vdm1(pszSource);
|
|
if (pszSource == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
StringCchCopyW(pszSource, tmpLength, pszNamespace);
|
|
LPCWSTR pszDelimit = L"\\";
|
|
LPWSTR pszTok = wcstok(LPWSTR(pszSource), pszDelimit); // First ns token
|
|
IWmiDbHandle *pCurrent = m_pEseRoot;
|
|
IWmiDbHandle *pTmp = 0;
|
|
pCurrent->AddRef();
|
|
|
|
while (pszTok)
|
|
{
|
|
// Current namespace is <pszTok>
|
|
// =============================
|
|
|
|
IWbemPath *pPath = ConfigMgr::GetNewPath();
|
|
if (pPath == 0)
|
|
{
|
|
pCurrent->Release();
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CReleaseMe _1(pPath);
|
|
|
|
WString sPath = "__namespace='";
|
|
sPath += pszTok;
|
|
sPath += "'";
|
|
|
|
pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, sPath);
|
|
|
|
hRes = pSession->GetObject(pCurrent, pPath, 0, WMIDB_HANDLE_TYPE_COOKIE, &pTmp);
|
|
|
|
size_t tmpLenght = wcslen(pszTok)+1;
|
|
wchar_t* TmpStr = new wchar_t[tmpLenght];
|
|
if (TmpStr == NULL)
|
|
{
|
|
pCurrent->Release();
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CVectorDeleteMe<wchar_t> vdm1(TmpStr);
|
|
*TmpStr = 0;
|
|
|
|
if (pszTok)
|
|
StringCchCopyW(TmpStr, tmpLenght, pszTok);
|
|
|
|
pszTok = wcstok(NULL, pszDelimit);
|
|
|
|
if (FAILED(hRes))
|
|
{
|
|
// If here, we try to create the namespace.
|
|
// ========================================
|
|
|
|
// Get a copy of class __Namespace
|
|
// ================================
|
|
IWbemClassObject *pNsClass = 0;
|
|
|
|
hRes = GetObject(pSession, pCurrent, L"__Namespace", 0,
|
|
&pNsClass);
|
|
if (FAILED(hRes))
|
|
{
|
|
pCurrent->Release();
|
|
return hRes;
|
|
}
|
|
|
|
CReleaseMe _1(pNsClass);
|
|
|
|
IWbemClassObject *pNs;
|
|
pNsClass->SpawnInstance(0, &pNs);
|
|
CReleaseMe _(pNs);
|
|
|
|
CVARIANT v;
|
|
v.SetStr(TmpStr);
|
|
pNs->Put(L"Name", 0, &v, 0);
|
|
|
|
hRes = pSession->PutObject(pCurrent, IID_IWbemClassObject, pNs, WBEM_FLAG_CREATE_ONLY, WMIDB_HANDLE_TYPE_VERSIONED, &pTmp);
|
|
if (FAILED(hRes))
|
|
{
|
|
pCurrent->Release();
|
|
return hRes;
|
|
}
|
|
pCurrent->Release();
|
|
pCurrent = pTmp;
|
|
if (pszTok)
|
|
continue;
|
|
*pHandle = pTmp;
|
|
break;
|
|
}
|
|
|
|
// If here, we got it. So either we are done, or we need to keep going.
|
|
// =====================================================================
|
|
|
|
else if (pszTok)
|
|
{
|
|
pCurrent->Release();
|
|
pCurrent = pTmp;
|
|
}
|
|
else
|
|
{
|
|
// All done
|
|
*pHandle = pTmp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
// Executed; seems to work
|
|
|
|
HRESULT CRepository::PutObject(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN REFIID riid,
|
|
IN LPVOID pObj,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
if (pNs == 0 || pObj == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if(dwFlags & WBEM_FLAG_NO_EVENTS)
|
|
{
|
|
dwFlags |= WMIDB_DISABLE_EVENTS;
|
|
}
|
|
|
|
// Mask out unrecognized flags
|
|
dwFlags &= (WBEM_FLAG_OWNER_UPDATE | WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_CREATE_ONLY | WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_UPDATE_SAFE_MODE | WBEM_FLAG_UPDATE_FORCE_MODE
|
|
| WBEM_FLAG_USE_SECURITY_DESCRIPTOR | WMIDB_FLAG_ADMIN_VERIFIED | WMIDB_DISABLE_EVENTS);
|
|
|
|
HRESULT hRes;
|
|
try
|
|
{
|
|
hRes = pSession->PutObject(pNs, riid, pObj, dwFlags, 0, 0);
|
|
}
|
|
catch(...)
|
|
{
|
|
ExceptionCounter c;
|
|
hRes = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
// inspected; no execution history
|
|
|
|
HRESULT CRepository::ExecQuery(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR pszQuery,
|
|
IN IWbemObjectSink *pSink,
|
|
IN LONG lFlags
|
|
)
|
|
{
|
|
HRESULT hRes = 0;
|
|
|
|
IWbemQuery *pQuery = NULL;
|
|
hRes = g_pQueryFact->CreateInstance(0, IID_IWbemQuery, (void **)&pQuery);
|
|
|
|
if (FAILED(hRes))
|
|
{
|
|
pSink->SetStatus(0, WBEM_E_CRITICAL_ERROR, 0, 0);
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
|
|
CReleaseMe _1(pQuery);
|
|
|
|
hRes = pQuery->Parse(L"SQL", pszQuery, 0);
|
|
if (FAILED(hRes))
|
|
{
|
|
pSink->SetStatus(0, WBEM_E_INVALID_QUERY, 0, 0);
|
|
return WBEM_E_INVALID_QUERY;
|
|
}
|
|
|
|
// Now, execute the query.
|
|
// =======================
|
|
|
|
IWmiDbIterator *pIterator = NULL;
|
|
|
|
try
|
|
{
|
|
hRes = pSession->ExecQuery(pNs, pQuery, lFlags, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pIterator);
|
|
}
|
|
catch(...)
|
|
{
|
|
ExceptionCounter c;
|
|
hRes = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
|
|
// If this is a "delete" query, there
|
|
// will be no iterator.
|
|
// ==================================
|
|
|
|
if (FAILED(hRes) || !pIterator)
|
|
{
|
|
pSink->SetStatus(0, hRes, 0, 0);
|
|
return hRes;
|
|
}
|
|
|
|
// If here, there are results, I guess.
|
|
// ====================================
|
|
|
|
REFIID riid = IID_IWbemClassObject;
|
|
DWORD dwObjects = 0;
|
|
|
|
// Convert current thread to a fiber
|
|
// =================================
|
|
|
|
// First, uncovert the thread to prevent a leak if we are already
|
|
// converted. There is no way of checking, sadly.
|
|
|
|
void* pFiber = NULL;
|
|
|
|
_TEB *pTeb = NtCurrentTeb();
|
|
BOOL bIsThisThreadAlreadyAFiber = (pTeb->HasFiberData != 0);
|
|
|
|
if (!bIsThisThreadAlreadyAFiber)
|
|
pFiber = ConvertThreadToFiber(NULL);
|
|
else
|
|
pFiber = GetCurrentFiber();
|
|
|
|
if(pFiber == NULL)
|
|
{
|
|
if (pIterator)
|
|
pIterator->Release();
|
|
|
|
pSink->SetStatus(0, WBEM_E_OUT_OF_MEMORY, 0, 0);
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
// Extract everything from the iterator
|
|
// ====================================
|
|
|
|
while (1)
|
|
{
|
|
IWbemClassObject *pObj = 0;
|
|
DWORD dwReturned = 0;
|
|
|
|
hRes = pIterator->NextBatch(
|
|
1, // one at a time for now
|
|
5, // Timeout seconds(or milliseconds? who knows...)
|
|
0, // Flags
|
|
WMIDB_HANDLE_TYPE_COOKIE,
|
|
riid,
|
|
pFiber,
|
|
&dwReturned,
|
|
(LPVOID *) &pObj
|
|
);
|
|
|
|
if (dwReturned == 0 || pObj == 0 || FAILED(hRes))
|
|
break;
|
|
|
|
dwObjects += dwReturned;
|
|
hRes = pSink->Indicate(1, &pObj);
|
|
pObj->Release();
|
|
if (FAILED(hRes)) // Allow an early cancellation
|
|
break;
|
|
}
|
|
|
|
if (pIterator)
|
|
{
|
|
pIterator->Cancel(hRes, pFiber);
|
|
pIterator->Release();
|
|
}
|
|
|
|
if (!bIsThisThreadAlreadyAFiber)
|
|
ConvertFiberToThread();
|
|
|
|
if (SUCCEEDED(hRes))
|
|
hRes = WBEM_S_NO_ERROR;
|
|
hRes = pSink->SetStatus(0, hRes, 0, 0);
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
// inspected; no execution history
|
|
|
|
HRESULT CRepository::QueryClasses(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN ULONG uFlags, // WBEM_FLAG_DEEP = 0, WBEM_FLAG_SHALLOW = 1,
|
|
IN LPCWSTR pszSuperclass,
|
|
IN IWbemObjectSink *pSink
|
|
)
|
|
{
|
|
HRESULT hRes;
|
|
|
|
// Build the query required for simple class operations.
|
|
// =====================================================
|
|
|
|
WString sQuery = L"select * from meta_class";
|
|
|
|
if (pszSuperclass)
|
|
{
|
|
if (uFlags & WBEM_FLAG_SHALLOW)
|
|
{
|
|
sQuery += " where ";
|
|
sQuery += " __SuperClass = '";
|
|
sQuery += pszSuperclass;
|
|
sQuery += "'";
|
|
|
|
}
|
|
else
|
|
{
|
|
if (wcslen(pszSuperclass) > 0)
|
|
{
|
|
sQuery += " where ";
|
|
sQuery += "__this isa '";
|
|
sQuery += pszSuperclass;
|
|
sQuery += "'";
|
|
sQuery += " and __class <> '";
|
|
sQuery += pszSuperclass;
|
|
sQuery += "'";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Ship it to the more general query function.
|
|
// ===========================================
|
|
|
|
hRes = CRepository::ExecQuery(pSession, pNs, sQuery, pSink, uFlags);
|
|
return hRes;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
// inspected; no execution history
|
|
|
|
HRESULT CRepository::DeleteObject(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN REFIID riid,
|
|
IN LPVOID pObj,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
return pSession->DeleteObject(pNs, dwFlags, riid, pObj);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CRepository::DeleteByPath(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR pszPath,
|
|
IN DWORD uFlags
|
|
)
|
|
{
|
|
HRESULT hRes;
|
|
|
|
if(uFlags & WBEM_FLAG_NO_EVENTS)
|
|
{
|
|
uFlags |= WMIDB_DISABLE_EVENTS;
|
|
}
|
|
|
|
//
|
|
// Check if the session supports faster interface
|
|
//
|
|
|
|
IWmiDbSessionEx* pEx = NULL;
|
|
hRes = pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pEx);
|
|
if(SUCCEEDED(hRes))
|
|
{
|
|
CReleaseMe rm1(pEx);
|
|
|
|
hRes = pEx->DeleteObjectByPath(pNs, pszPath, uFlags);
|
|
}
|
|
else
|
|
{
|
|
IWmiDbHandle *pHandle = NULL;
|
|
|
|
// Path to object.
|
|
// ===============
|
|
IWbemPath *pPath = ConfigMgr::GetNewPath();
|
|
if (pPath == 0)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
CReleaseMe _1(pPath);
|
|
pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pszPath);
|
|
|
|
hRes = pSession->GetObject(pNs, pPath, 0, WMIDB_HANDLE_TYPE_COOKIE|WMIDB_HANDLE_TYPE_EXCLUSIVE, &pHandle);
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
hRes = DeleteObject(pSession, pNs, IID_IWmiDbHandle, pHandle, uFlags);
|
|
pHandle->Release();
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
// visually ok
|
|
|
|
HRESULT CRepository::InheritsFrom(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR pszSuperclass,
|
|
IN LPCWSTR pszSubclass
|
|
)
|
|
{
|
|
IWbemClassObject *pObj = 0;
|
|
|
|
HRESULT hRes = GetObject(pSession, pNs, pszSubclass, 0, &pObj);
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
CReleaseMe _(pObj);
|
|
|
|
hRes = pObj->InheritsFrom(pszSuperclass);
|
|
|
|
return hRes;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
|
|
HRESULT CRepository::GetRefClasses(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR pszClass,
|
|
IN BOOL bIncludeSubclasses,
|
|
OUT CWStringArray &aClasses
|
|
)
|
|
{
|
|
WString sQuery = "references of {";
|
|
sQuery +=pszClass;
|
|
sQuery += "}";
|
|
|
|
CSynchronousSink* pRefClassSink = CSynchronousSink::Create();
|
|
if (pRefClassSink == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
pRefClassSink->AddRef();
|
|
CReleaseMe _1(pRefClassSink);
|
|
|
|
HRESULT hRes = CRepository::ExecQuery(pSession, pNs, sQuery, pRefClassSink, 0);
|
|
|
|
if (FAILED(hRes) && hRes != WBEM_E_NOT_FOUND)
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
|
|
pRefClassSink->GetStatus(&hRes, NULL, NULL);
|
|
|
|
CRefedPointerArray<IWbemClassObject>& raObjects = pRefClassSink->GetObjects();
|
|
|
|
for (int i = 0; i < raObjects.GetSize(); i++)
|
|
{
|
|
IWbemClassObject *pClsDef = (IWbemClassObject *) raObjects[i];
|
|
|
|
CVARIANT vGenus;
|
|
hRes = pClsDef->Get(L"__GENUS", 0, &vGenus, 0, 0);
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
if(V_VT(&vGenus) == VT_I4 && V_I4(&vGenus) == 1)
|
|
{
|
|
CVARIANT v;
|
|
if(SUCCEEDED(pClsDef->Get(L"__CLASS", 0, &v, 0, 0)) && VT_BSTR == V_VT(&v))
|
|
{
|
|
if (CFlexArray::no_error != aClasses.Add(v.GetStr()))
|
|
{
|
|
// ???
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
|
|
HRESULT CRepository::GetInstanceRefs(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR pszTargetObject,
|
|
IN IWbemObjectSink *pSink
|
|
)
|
|
{
|
|
WString sQuery = "references of {";
|
|
sQuery += pszTargetObject;
|
|
sQuery += "}";
|
|
|
|
HRESULT hRes = ExecQuery(pSession, pNs, sQuery, pSink, 0);
|
|
|
|
return hRes;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
|
|
HRESULT CRepository::GetClassesWithRefs(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN IWbemObjectSink *pSink
|
|
)
|
|
{
|
|
// TBD: Jet Blue
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CRepository::BuildClassHierarchy
|
|
//
|
|
// Notes:
|
|
// Builds a decorated class hierarchy tree. Doesn't use dyn classes yet.
|
|
//
|
|
// <pNs>
|
|
// The namespace to use for classes.
|
|
//
|
|
// <pBaseClassName>
|
|
// May not be null.
|
|
//
|
|
// <lFlags>
|
|
// Not used yet.
|
|
//
|
|
// <pDynasty>
|
|
// Receives the class dynasty tree.
|
|
//
|
|
// Verification:
|
|
// (a) Verifies that pBaseClassName is a class which has a key or inherits one.
|
|
//
|
|
//******************************************************************************
|
|
//
|
|
|
|
HRESULT CRepository::BuildClassHierarchy(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR pBaseClassName,
|
|
IN LONG lFlags,
|
|
OUT wmilib::auto_ptr<CDynasty> & pDynasty
|
|
)
|
|
{
|
|
if (pNs == 0 || pBaseClassName == 0 )
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// First, execute a schema query for all the classes in the dynasty.
|
|
// We verify that the base as a key, or else it is an error.
|
|
//
|
|
// TBD: Dynamic classes are not merged in yet
|
|
//
|
|
// ================================================================
|
|
|
|
WString sQuery = "select * from meta_class where __this isa '";
|
|
sQuery += pBaseClassName;
|
|
sQuery += "'";
|
|
|
|
CSynchronousSink* pRefClassSink = CSynchronousSink::Create();
|
|
if (pRefClassSink == NULL) return WBEM_E_OUT_OF_MEMORY;
|
|
pRefClassSink->AddRef();
|
|
CReleaseMe _1(pRefClassSink);
|
|
|
|
HRESULT hRes = CRepository::ExecQuery(pSession, pNs, sQuery, pRefClassSink, 0);
|
|
if (FAILED(hRes)) return hRes;
|
|
pRefClassSink->Block();
|
|
pRefClassSink->GetStatus(&hRes, NULL, NULL);
|
|
|
|
CRefedPointerArray<IWbemClassObject>& raObjects = pRefClassSink->GetObjects();
|
|
|
|
// Find root class amongst all those relatives.
|
|
// ============================================
|
|
|
|
CFlexArray aClasses;
|
|
IWbemClassObject *pRoot = 0;
|
|
|
|
for (int i = 0; i < raObjects.GetSize(); i++)
|
|
{
|
|
IWbemClassObject *pClsDef = (IWbemClassObject *) raObjects[i];
|
|
|
|
_variant_t v;
|
|
hRes = pClsDef->Get(L"__CLASS", 0, &v, 0, 0);
|
|
if (FAILED(hRes)) return hRes;
|
|
if (VT_BSTR != V_VT(&v)) return WBEM_E_INVALID_OBJECT;
|
|
|
|
if (0 == wbem_wcsicmp(V_BSTR(&v), pBaseClassName))
|
|
pRoot = pClsDef;
|
|
else
|
|
{
|
|
if (CFlexArray::no_error != aClasses.Add(pClsDef))
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
if (pRoot == 0) // Did we find it?
|
|
return WBEM_E_NOT_FOUND;
|
|
|
|
// Algorithm:
|
|
// Add root class first, enqueue the ptr.
|
|
//
|
|
// (a) Dequeue ptr into pCurrentClass
|
|
// (b) Find all classes which have pCurrentClass as the parent
|
|
// For each, create a CDynasty, add it to the current dynasty
|
|
// and enqueue each. Remove enqueued class from array.
|
|
// (c) Goto (a)
|
|
|
|
CFlexQueue Q;
|
|
pDynasty.reset( CDynasty::Create(pRoot));
|
|
if (NULL == pDynasty.get()) return WBEM_E_OUT_OF_MEMORY;
|
|
Q.Enqueue(pDynasty.get());
|
|
|
|
while (aClasses.Size())
|
|
{
|
|
CDynasty *pCurrent = (CDynasty *) Q.Dequeue();
|
|
if (pCurrent == 0)
|
|
break;
|
|
|
|
_variant_t vClassName;
|
|
hRes = pCurrent->m_pClassObj->Get(L"__CLASS", 0, &vClassName, 0, 0);
|
|
if (FAILED(hRes)) return hRes;
|
|
if (VT_BSTR != V_VT(&vClassName)) return WBEM_E_INVALID_OBJECT;
|
|
|
|
for (int i = 0; i < aClasses.Size(); i++)
|
|
{
|
|
IWbemClassObject *pCandidate = (IWbemClassObject *) aClasses[i];
|
|
|
|
_variant_t vSuperClass;
|
|
hRes = pCandidate->Get(L"__SUPERCLASS", 0, &vSuperClass, 0, 0);
|
|
if (FAILED(hRes)) return hRes;
|
|
//if (VT_BSTR != V_VT(&vClassName)) return WBEM_E_INVALID_PROPERTY_TYPE;
|
|
|
|
if (vSuperClass.vt == VT_BSTR && wbem_wcsicmp(V_BSTR(&vSuperClass), V_BSTR(&vClassName)) == 0)
|
|
{
|
|
wmilib::auto_ptr<CDynasty> pNewChild( CDynasty::Create(pCandidate));
|
|
if (pNewChild.get() == NULL) return WBEM_E_OUT_OF_MEMORY;
|
|
pCurrent->AddChild(pNewChild.get()); // throw
|
|
Q.Enqueue(pNewChild.get());
|
|
pNewChild.release();
|
|
aClasses.RemoveAt(i);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
|
|
HRESULT CRepository::FindKeyRoot(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR wszClassName,
|
|
OUT IWbemClassObject** ppKeyRootClass
|
|
)
|
|
{
|
|
if (pNs == 0 || wszClassName == 0 || ppKeyRootClass == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Work through derivation until we find the class with the key.
|
|
// =============================================================
|
|
|
|
*ppKeyRootClass = 0;
|
|
|
|
HRESULT hRes;
|
|
IWbemClassObject* pLastClass = NULL;
|
|
WString sNextClass = wszClassName; // throw
|
|
|
|
while (1)
|
|
{
|
|
IWbemClassObject *pNextClass = 0;
|
|
|
|
hRes = CRepository::GetObject(pSession, pNs, sNextClass, 0, &pNextClass);
|
|
if (FAILED(hRes)) break;
|
|
CReleaseMe rm(pNextClass);
|
|
|
|
CVARIANT v;
|
|
hRes = pNextClass->Get(L"__SUPERCLASS", 0, &v, 0, 0);
|
|
|
|
if ( FAILED(hRes) ) break;
|
|
|
|
if ( V_VT(&v) == VT_NULL )
|
|
{
|
|
sNextClass.Empty();
|
|
}
|
|
else
|
|
{
|
|
sNextClass = v.GetStr(); // throw
|
|
}
|
|
|
|
BSTR strProp = 0;
|
|
LONG lFlavor = 0;
|
|
pNextClass->BeginEnumeration(WBEM_FLAG_KEYS_ONLY);
|
|
hRes = pNextClass->Next(0, &strProp, 0, 0, &lFlavor);
|
|
|
|
// WBEM_S_NO_ERROR means we got a property that was defined as a key
|
|
if (hRes == WBEM_S_NO_ERROR)
|
|
{
|
|
SysFreeString(strProp);
|
|
|
|
if ( pLastClass ) pLastClass->Release();
|
|
pLastClass = pNextClass;
|
|
pLastClass->AddRef();
|
|
}
|
|
else if ( hRes == WBEM_S_NO_MORE_DATA )
|
|
{
|
|
// If we don't have a last class, then we didn't find anything. Otherwise,
|
|
// since we found no key's here, the last class was the one that defined the
|
|
// keys
|
|
|
|
if ( pLastClass )
|
|
{
|
|
*ppKeyRootClass = pLastClass;
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// outta here
|
|
break;
|
|
|
|
}
|
|
else
|
|
{
|
|
// Otherwise something is just plain wrong
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return WBEM_E_NOT_FOUND;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
// visually ok
|
|
|
|
HRESULT CRepository::TableScanQuery(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN LPCWSTR pszClassName,
|
|
IN QL_LEVEL_1_RPN_EXPRESSION *pExp, // NOT USED
|
|
IN DWORD dwFlags,
|
|
IN IWbemObjectSink *pSink
|
|
)
|
|
{
|
|
WString sQuery = "select * from ";
|
|
sQuery += pszClassName;
|
|
HRESULT hRes = CRepository::ExecQuery(pSession, pNs, sQuery, pSink, 0);
|
|
return hRes;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
HRESULT CRepository::InitDriver(
|
|
IN ULONG uFlags,
|
|
IN IWbemClassObject *pMappedNs,
|
|
OUT IWmiDbController **pResultController,
|
|
OUT IWmiDbSession **pResultRootSession,
|
|
OUT IWmiDbHandle **pResultVirtualRoot
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
HRESULT CRepository::EnsureNsSystemInstances(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN IWmiDbSession *pParentSession,
|
|
IN IWmiDbHandle *pParentNs
|
|
)
|
|
{
|
|
HRESULT hRes;
|
|
|
|
// Do a get and see if __WmiMappedDriverNamespace is there.
|
|
// ========================================================
|
|
|
|
IWbemClassObject *pTestObj = 0;
|
|
hRes = GetObject(pSession, pNs, L"__systemsecurity=@", 0, &pTestObj);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
pTestObj->Release();
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// If here, it's a new namespace that has to be populated with system classes.
|
|
// ===========================================================================
|
|
|
|
CCoreServices *pSvc = CCoreServices::CreateInstance();
|
|
if (pSvc == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
_IWmiObject *Objects[256];
|
|
ULONG uSize = 256;
|
|
hRes = pSvc->GetSystemObjects(GET_SYSTEM_STD_INSTANCES, &uSize, Objects);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
for (int i = 0; i < uSize; i++)
|
|
{
|
|
IWbemClassObject *pObj;
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = Objects[i]->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pObj);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
AutoRevertSecTlsFlag secFlag ( (LPVOID) 0 ) ;
|
|
hRes = PutObject(pSession, pNs, IID_IWbemClassObject, pObj, WMIDB_DISABLE_EVENTS);
|
|
pObj->Release();
|
|
if (FAILED(hRes))
|
|
{
|
|
ERRORTRACE((LOG_WBEMCORE, "Creation of system instances failed during repository creation <0x%X>!\n", hRes));
|
|
}
|
|
}
|
|
}
|
|
Objects[i]->Release();
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = SetSecurityForNS(pSession, pNs, pParentSession, pParentNs);
|
|
if (FAILED(hRes))
|
|
{
|
|
ERRORTRACE((LOG_WBEMCORE, "Setting of security on namespace failed during repository creation <0x%X>!\n", hRes));
|
|
}
|
|
}
|
|
|
|
pSvc->Release();
|
|
return hRes;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
HRESULT CRepository::EnsureNsSystemRootObjects(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN IWmiDbSession *pParentSession,
|
|
IN IWmiDbHandle *pParentNs
|
|
)
|
|
{
|
|
HRESULT hRes;
|
|
|
|
// Do a get and see if __EventSinkCacheControl=@ is there.
|
|
// ========================================================
|
|
|
|
IWbemClassObject *pTestObj = 0;
|
|
hRes = GetObject(pSession, pNs, L"__EventSinkCacheControl=@", 0, &pTestObj);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
pTestObj->Release();
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// If here, it's a new namespace that has to be populated with system classes.
|
|
// ===========================================================================
|
|
|
|
CCoreServices *pSvc = CCoreServices::CreateInstance();
|
|
if (pSvc == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
CReleaseMe _rm(pSvc);
|
|
_IWmiObject *Objects[256];
|
|
ULONG uSize = 256;
|
|
hRes = pSvc->GetSystemObjects(GET_SYSTEM_ROOT_OBJECTS, &uSize, Objects);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
for (int i = 0; i < uSize; i++)
|
|
{
|
|
IWbemClassObject *pObj;
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = Objects[i]->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pObj);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = PutObject(pSession, pNs, IID_IWbemClassObject, pObj, WMIDB_DISABLE_EVENTS);
|
|
pObj->Release();
|
|
if (FAILED(hRes))
|
|
{
|
|
ERRORTRACE((LOG_WBEMCORE, "Creation of system root objects failed during repository creation <0x%X>!\n", hRes));
|
|
}
|
|
}
|
|
}
|
|
Objects[i]->Release();
|
|
}
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
HRESULT CRepository::EnsureNsSystemSecurityObjects(
|
|
IN IWmiDbSession *pSession,
|
|
IN IWmiDbHandle *pNs,
|
|
IN IWmiDbSession *pParentSession,
|
|
IN IWmiDbHandle *pParentNs
|
|
)
|
|
{
|
|
HRESULT hRes;
|
|
|
|
// Do a get and see if __User is there.
|
|
// ========================================================
|
|
|
|
IWbemClassObject *pTestObj = 0;
|
|
hRes = GetObject(pSession, pNs, L"__User", 0, &pTestObj);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
pTestObj->Release();
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// If here, it's a new namespace that has to be populated with system classes.
|
|
// ===========================================================================
|
|
|
|
CCoreServices *pSvc = CCoreServices::CreateInstance();
|
|
if (pSvc == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
_IWmiObject *Objects[256];
|
|
ULONG uSize = 256;
|
|
hRes = pSvc->GetSystemObjects(GET_SYSTEM_SECURITY_OBJECTS, &uSize, Objects);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
for (int i = 0; i < uSize; i++)
|
|
{
|
|
IWbemClassObject *pObj;
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = Objects[i]->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pObj);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = PutObject(pSession, pNs, IID_IWbemClassObject, pObj, WMIDB_DISABLE_EVENTS);
|
|
pObj->Release();
|
|
if (FAILED(hRes))
|
|
{
|
|
ERRORTRACE((LOG_WBEMCORE, "Creation of system security objects failed during repository creation <0x%X>!\n", hRes));
|
|
}
|
|
}
|
|
}
|
|
Objects[i]->Release();
|
|
}
|
|
}
|
|
|
|
|
|
pSvc->Release();
|
|
return hRes;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Adjusted for all repository drivers. Works for scopes or namespaces.
|
|
// If a scope is being opened, <pScope> will be set on return and
|
|
// <pbIsNamespace> will point to FALSE. Otherwise, <pScope> is set to
|
|
// point to NULL and <pbIsNamespace> points to TRUE.
|
|
//
|
|
// If <pszScope> is NULL, a pointer to the virtual ROOT in ESE
|
|
// is returned.
|
|
//
|
|
//***************************************************************************
|
|
//
|
|
HRESULT CRepository::OpenScope(
|
|
IN IWmiDbSession *pParentSession, //Parent session to use to
|
|
IN LPWSTR pszTargetScope, // NS or scope
|
|
IN GUID *pTransGuid, // Transaction GUID for connection
|
|
OUT IWmiDbController **pDriver, // Driver
|
|
OUT IWmiDbSession **pSession, // Session
|
|
OUT IWmiDbHandle **pScope, // Scope
|
|
OUT IWmiDbHandle **pNs // Nearest NS
|
|
)
|
|
{
|
|
HRESULT hRes;
|
|
ULONG uNsCount = 0;
|
|
// uScopeCount = 0;
|
|
|
|
if (pNs == 0 || pSession == 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Default settings.
|
|
// =================
|
|
|
|
if (pScope)
|
|
*pScope = 0;
|
|
|
|
*pNs = 0;
|
|
*pSession = 0;
|
|
if (pDriver)
|
|
*pDriver = 0;
|
|
|
|
// Check for virtual root ns (the parent to ROOT).
|
|
// ===============================================
|
|
|
|
if (pszTargetScope == 0)
|
|
{
|
|
if (m_pEseRoot == 0)
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
|
|
if (pDriver)
|
|
{
|
|
m_pEseController->AddRef();
|
|
*pDriver = m_pEseController;
|
|
}
|
|
|
|
m_pEseSession->AddRef();
|
|
*pSession = m_pEseSession;
|
|
|
|
m_pEseRoot->AddRef();
|
|
*pNs = m_pEseRoot;
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// Parse the path.
|
|
// ===============
|
|
|
|
IWbemPath *pPath = ConfigMgr::GetNewPath();
|
|
if (pPath == 0)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
CReleaseMe _1(pPath);
|
|
|
|
hRes = pPath->SetText(WBEMPATH_TREAT_SINGLE_IDENT_AS_NS | WBEMPATH_CREATE_ACCEPT_ALL , pszTargetScope);
|
|
if (FAILED(hRes))
|
|
return WBEM_E_INVALID_NAMESPACE;
|
|
|
|
// Analyze it. Is it just a namespace?
|
|
// Build the namespace string and normalize it.
|
|
// ============================================
|
|
|
|
hRes = pPath->GetNamespaceCount(&uNsCount);
|
|
//hRes = pPath->GetScopeCount(&uScopeCount);
|
|
|
|
// Starting handles at ROOT.
|
|
// =========================
|
|
|
|
IWmiDbHandle *pTempNs = 0;
|
|
IWmiDbHandle *pMostRecent = 0;
|
|
IWmiDbHandle *pMostRecentScope = 0;
|
|
|
|
IWmiDbSession *pTempSession = m_pEseSession; // Default virtual root
|
|
IWmiDbController *pTempDriver = m_pEseController; // Default driver
|
|
|
|
//Use the override if available
|
|
if (pParentSession)
|
|
pTempSession = pParentSession;
|
|
|
|
pTempSession->AddRef(); // For later release
|
|
pTempDriver->AddRef(); // For later release
|
|
|
|
hRes = OpenEseNs(pTempSession, L"ROOT", &pMostRecent);
|
|
if (FAILED(hRes))
|
|
{
|
|
pTempSession->Release();
|
|
pTempDriver->Release();
|
|
return WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
|
|
// Starting driver.
|
|
// ================
|
|
|
|
|
|
WString sNsDecoration = "ROOT";
|
|
|
|
// open up each namespace successively, mapping it.
|
|
// ===============================================
|
|
|
|
for (ULONG u = 0; u < uNsCount; u++)
|
|
{
|
|
IWbemClassObject *pNsRep = 0;
|
|
|
|
ULONG uLen = 0;
|
|
// Get next namespace token name.
|
|
// ==============================
|
|
hRes = pPath->GetNamespaceAt(u, &uLen, NULL);
|
|
if(FAILED(hRes))
|
|
goto Error;
|
|
|
|
WCHAR* Buf = new WCHAR[uLen+1];
|
|
if (Buf == NULL)
|
|
{
|
|
hRes = WBEM_E_OUT_OF_MEMORY;
|
|
goto Error;
|
|
}
|
|
CVectorDeleteMe<WCHAR> vdm(Buf);
|
|
hRes = pPath->GetNamespaceAt(u, &uLen, Buf);
|
|
if (FAILED(hRes) || *Buf == 0)
|
|
goto Error;
|
|
|
|
if ((u == 0) && (wbem_wcsicmp(L"root", Buf) != 0))
|
|
{
|
|
hRes = WBEM_E_INVALID_NAMESPACE;
|
|
goto Error;
|
|
}
|
|
else if (u == 0)
|
|
continue;
|
|
|
|
// Build a relative scope path.
|
|
// ============================
|
|
WString sPath = "__namespace='";
|
|
sPath += Buf;
|
|
sPath += "'";
|
|
|
|
sNsDecoration += "\\";
|
|
sNsDecoration += Buf;
|
|
|
|
IWbemPath *pNewPath = ConfigMgr::GetNewPath();
|
|
if (pNewPath == 0)
|
|
{
|
|
hRes = WBEM_E_OUT_OF_MEMORY;
|
|
goto Error;
|
|
}
|
|
CReleaseMe rm1(pNewPath);
|
|
|
|
hRes = pNewPath->SetText(WBEMPATH_TREAT_SINGLE_IDENT_AS_NS | WBEMPATH_CREATE_ACCEPT_ALL , sPath);
|
|
if (FAILED(hRes))
|
|
goto Error;
|
|
|
|
// Get the reprsentation object.
|
|
// =============================
|
|
|
|
hRes = pTempSession->GetObjectDirect(pMostRecent, pNewPath, 0, IID_IWbemClassObject, (void **) &pNsRep);
|
|
if (hRes == WBEM_E_NOT_FOUND)
|
|
{
|
|
//If a namespace does not exist it should return a different namespace...
|
|
hRes = WBEM_E_INVALID_NAMESPACE;
|
|
goto Error;
|
|
}
|
|
else if (FAILED(hRes))
|
|
goto Error;
|
|
CReleaseMe _(pNsRep);
|
|
|
|
// Now move down one namespace.
|
|
// =============================
|
|
|
|
hRes = pTempSession->GetObject(pMostRecent, pNewPath, 0, WMIDB_HANDLE_TYPE_COOKIE, &pTempNs);
|
|
|
|
ReleaseIfNotNULL(pMostRecent);
|
|
pMostRecent = pTempNs;
|
|
pTempNs = 0;
|
|
|
|
if (FAILED(hRes))
|
|
goto Error;
|
|
}
|
|
|
|
// Final.
|
|
// ======
|
|
ReleaseIfNotNULL(pTempNs);
|
|
|
|
if (pScope)
|
|
*pScope = pMostRecentScope;
|
|
|
|
*pNs = pMostRecent;
|
|
*pSession = pTempSession;
|
|
if (pDriver)
|
|
*pDriver = pTempDriver;
|
|
|
|
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
Error:
|
|
ReleaseIfNotNULL(pMostRecent);
|
|
ReleaseIfNotNULL(pTempNs);
|
|
ReleaseIfNotNULL(pTempDriver);
|
|
ReleaseIfNotNULL(pTempSession);
|
|
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT CRepository::GetNewSession(IWmiDbSession **ppSession)
|
|
{
|
|
HRESULT hRes;
|
|
IWmiDbController *pController = 0;
|
|
WMIDB_LOGON_TEMPLATE *pTemplate = 0;
|
|
IWmiDbSession *pSession= 0;
|
|
IWmiDbHandle *pRoot = 0;
|
|
|
|
// Retrieve the CLSID of the default driver.
|
|
// =========================================
|
|
CLSID clsid;
|
|
hRes = ConfigMgr::GetDefaultRepDriverClsId(clsid);
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
hRes = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IWmiDbController, (void **)&pController);
|
|
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
CReleaseMe _1(pController);
|
|
|
|
hRes = pController->GetLogonTemplate(0x409, 0, &pTemplate);
|
|
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
hRes = pController->Logon(pTemplate, 0, WMIDB_HANDLE_TYPE_VERSIONED, &pSession, &pRoot);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
*ppSession = pSession;
|
|
pRoot->Release();
|
|
}
|
|
|
|
pController->FreeLogonTemplate(&pTemplate);
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT CRepository::UpgradeSystemClasses()
|
|
{
|
|
DWORD dwOldVer = 0;
|
|
DWORD dwNewVer = 0;
|
|
HRESULT hRes;
|
|
|
|
hRes = m_pEseController->GetRepositoryVersions(&dwOldVer, &dwNewVer);
|
|
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
if (dwOldVer < 4)
|
|
{
|
|
//Lower versions stored system classes in every namespace! We
|
|
//should delete them!
|
|
CWStringArray aListRootSystemClasses;
|
|
|
|
//Retrieve the list...
|
|
hRes = GetListOfRootSystemClasses(aListRootSystemClasses); // SEC:REVIEWED 2002-03-22 : Needs EH, throws on low-mem
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Create a new session...
|
|
IWmiDbSession *pSession = NULL;
|
|
IWmiDbSessionEx *pSessionEx = NULL;
|
|
hRes = CRepository::GetNewSession(&pSession);
|
|
if (FAILED(hRes))
|
|
return hRes;
|
|
|
|
//Get an EX version that supports transactioning...
|
|
pSession->QueryInterface(IID_IWmiDbSessionEx, (void**)&pSessionEx);
|
|
if (pSessionEx)
|
|
{
|
|
pSession->Release();
|
|
pSession = pSessionEx;
|
|
}
|
|
CReleaseMe relMe1(pSession);
|
|
|
|
//If we have transactionable session, use it!
|
|
if (pSessionEx)
|
|
{
|
|
hRes = pSessionEx->BeginWriteTransaction(0);
|
|
if (FAILED(hRes))
|
|
{
|
|
return hRes;
|
|
}
|
|
}
|
|
try
|
|
{
|
|
//Recursively do the deletion, starting at root, however don't delete
|
|
//the ones in root itself!
|
|
hRes = RecursiveDeleteClassesFromNamespace(pSession, L"root", aListRootSystemClasses, false);
|
|
}
|
|
catch (CX_Exception &) // Only WStringArray should throw
|
|
{
|
|
hRes = WBEM_E_CRITICAL_ERROR;
|
|
}
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
//Commit the transaction
|
|
if (pSessionEx)
|
|
{
|
|
hRes = pSessionEx->CommitTransaction(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERRORTRACE((LOG_WBEMCORE, "Removal of ROOT ONLY system classes from non-ROOT namespace failed during repository upgrade <0x%X>!\n", hRes));
|
|
if (pSessionEx)
|
|
pSessionEx->AbortTransaction(0);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
HRESULT CRepository::GetListOfRootSystemClasses(CWStringArray &aListRootSystemClasses)
|
|
{
|
|
CCoreServices *pSvc = CCoreServices::CreateInstance();
|
|
if (pSvc == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
_IWmiObject *Objects[256];
|
|
ULONG uSize = 256;
|
|
HRESULT hRes;
|
|
hRes = pSvc->GetSystemObjects(GET_SYSTEM_ROOT_OBJECTS, &uSize, Objects);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
for (int i = 0; i < uSize; i++)
|
|
{
|
|
_IWmiObject *pObj;
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = Objects[i]->QueryInterface(IID__IWmiObject, (LPVOID *) &pObj);
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
if (pObj->IsObjectInstance() != S_OK)
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
hRes = pObj->Get(L"__CLASS", 0, &var, 0, 0);
|
|
if (SUCCEEDED(hRes) && (V_VT(&var) == VT_BSTR))
|
|
{
|
|
if (aListRootSystemClasses.Add(V_BSTR(&var)) != CWStringArray::no_error)
|
|
hRes = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
pObj->Release();
|
|
}
|
|
}
|
|
Objects[i]->Release();
|
|
}
|
|
}
|
|
|
|
pSvc->Release();
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
// throws because of the WStringArray
|
|
//
|
|
//
|
|
HRESULT CRepository::RecursiveDeleteClassesFromNamespace(IWmiDbSession *pSession,
|
|
const wchar_t *wszNamespace,
|
|
CWStringArray &aListRootSystemClasses,
|
|
bool bDeleteInThisNamespace)
|
|
{
|
|
HRESULT hRes = WBEM_S_NO_ERROR;
|
|
IWmiDbHandle *pNs = NULL;
|
|
//Open Namespace
|
|
hRes = OpenEseNs(pSession, wszNamespace, &pNs);
|
|
CReleaseMe rmNS(pNs);
|
|
|
|
//Delete classes from this namespace if necessary
|
|
if (SUCCEEDED(hRes) && bDeleteInThisNamespace)
|
|
{
|
|
for (int i = 0; i != aListRootSystemClasses.Size(); i++)
|
|
{
|
|
hRes = DeleteByPath(pSession, pNs, aListRootSystemClasses[i], 0);
|
|
if (hRes == WBEM_E_NOT_FOUND)
|
|
hRes = WBEM_S_NO_ERROR;
|
|
else if (FAILED(hRes))
|
|
break;
|
|
}
|
|
}
|
|
if (FAILED(hRes)) return hRes;
|
|
|
|
//Special class that needs to be deleted is the __classes, and needs to go from all
|
|
//namespaces
|
|
hRes = DeleteByPath(pSession, pNs, L"__classes", 0);
|
|
if (hRes == WBEM_E_NOT_FOUND) hRes = WBEM_S_NO_ERROR;
|
|
if (FAILED(hRes)) return hRes;
|
|
|
|
//Enumerate child namespaces...
|
|
CWStringArray aListNamespaces;
|
|
CNamespaceListSink * pSink = new CNamespaceListSink(aListNamespaces); // SEC:REVIEWED 2002-03-22 : How does this object handle out-of-mem on the <aListNamespaces> ?
|
|
if (pSink == NULL) return WBEM_E_OUT_OF_MEMORY;
|
|
pSink->AddRef();
|
|
CReleaseMe rmSink(pSink);
|
|
|
|
hRes = ExecQuery(pSession, pNs, L"select * from __namespace", pSink, 0);
|
|
if (FAILED(hRes)) return hRes;
|
|
|
|
//Work through list and call ourselves with that namespace name...
|
|
for (int i = 0; i != aListNamespaces.Size(); i++)
|
|
{
|
|
//Build the full name of this namespace
|
|
size_t tmpLength = wcslen(wszNamespace) + wcslen(aListNamespaces[i]) + wcslen(L"\\") + 1;
|
|
wmilib::auto_buffer<WCHAR> wszChildNamespace( new WCHAR[tmpLength]);
|
|
if (wszChildNamespace.get() == NULL) return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
StringCchCopyW(wszChildNamespace.get(), tmpLength, wszNamespace);
|
|
StringCchCatW(wszChildNamespace.get(), tmpLength, L"\\");
|
|
StringCchCatW(wszChildNamespace.get(), tmpLength, aListNamespaces[i]);
|
|
|
|
//Do the deletion...
|
|
hRes = RecursiveDeleteClassesFromNamespace(pSession, wszChildNamespace.get(), aListRootSystemClasses, true);
|
|
if (FAILED(hRes)) return hRes;
|
|
}
|
|
|
|
return hRes;
|
|
}
|