|
|
/*++
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; }
|