Leaked source code of windows server 2003
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

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