|
|
//***************************************************************************
//
// (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
//
// repdrvr.cpp
//
// cvadai 19-Mar-99 Created as prototype for Quasar.
//
//***************************************************************************
#define _REPDRVR_CPP_
#pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the
#pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class
#define DBINITCONSTANTS // Initialize OLE constants...
#define INITGUID // ...once in each app.
#define _WIN32_DCOM
#include "precomp.h"
#include <std.h>
#include <sqlexec.h>
#include <sqlcache.h>
#include <repdrvr.h>
#include <wbemint.h>
#include <math.h>
#include <resource.h>
#include <reputils.h>
#include <crc64.h>
#include <smrtptr.h>
#include <wmiutils.h>
#include <wbemtime.h>
#include <reg.h>
//#include <icecap.h>
// Statics
_WMILockit::_WMILockit(CRITICAL_SECTION *pCS) { EnterCriticalSection(pCS); m_cs = pCS; }
_WMILockit::~_WMILockit() { LeaveCriticalSection(m_cs); }
#define REPDRVR_FLAG_FLUSH_ALL 0x1
extern long g_cObj;
typedef std::map<SQL_ID, CacheInfo *> SchemaCache; typedef std::map<_bstr_t, SQL_ID, C_wchar_LessCase> PathIndex; typedef std::map <SQL_ID, LockData *> LockCache; typedef std::vector<LockItem *> LockList; typedef std::map <DWORD, DWORD> Properties; typedef std::vector <SessionLock *> SessionLocks; typedef std::map <DWORD, CESSHolder *> ESSObjs; typedef std::map<SQL_ID, bool> SQL_IDMap; typedef std::vector <SQL_ID> SQLIDs; typedef std::map <DWORD, SQLIDs> SessionDynasties;
// Contrived method of generating proc names,
// since we are limited to 30 characters.
#define PROCTYPE_GET 1
#define PROCTYPE_PUT 2
#define PROCTYPE_DEL 3
LPWSTR StripSlashes(LPWSTR lpText) { wchar_t *pszTemp = NULL; if (lpText) { pszTemp = new wchar_t [wcslen(lpText)+1]; if (pszTemp) { int iPos = 0; int iLen = wcslen(lpText); if (iLen) { BOOL bOnSlash = FALSE; for (int i = 0; i < iLen; i++) { WCHAR t = lpText[i]; if (t == '\\') { if (lpText[i+1] == '\\' && !bOnSlash) { bOnSlash = TRUE; continue; } } pszTemp[iPos] = t; bOnSlash = FALSE; iPos++; } } pszTemp[iPos] = '\0'; } } return pszTemp; }
int GetDiff(SYSTEMTIME tEnd, SYSTEMTIME tStart) { int iRet = 0;
__int64 iTemp = (tEnd.wDay * 1000000000) + (tEnd.wHour * 10000000) + (tEnd.wMinute * 100000) + (tEnd.wSecond * 1000) + tEnd.wMilliseconds; iTemp -= ((tStart.wDay * 1000000000) + (tStart.wHour * 10000000) + (tStart.wMinute * 100000) + (tStart.wSecond * 1000) + tStart.wMilliseconds);
iRet = (int) iTemp;
return iRet; }
CWbemClassObjectProps::CWbemClassObjectProps (CWmiDbSession *pSession, CSQLConnection *pConn, IWbemClassObject *pObj, CSchemaCache *pCache, SQL_ID dScopeID) { lpClassName = GetPropertyVal(L"__Class", pObj); lpNamespace = GetPropertyVal(L"__Namespace", pObj); lpSuperClass = GetPropertyVal(L"__SuperClass", pObj); lpDynasty = GetPropertyVal(L"__Dynasty", pObj); LPWSTR lpTemp = GetPropertyVal(L"__Genus", pObj); CDeleteMe <wchar_t> r(lpTemp); if (lpTemp) dwGenus = _wtoi(lpTemp);
// If pConn is blank, this should already be loaded.
if (pConn) { if (FAILED(pSession->LoadClassInfo(pConn, lpClassName, dScopeID, FALSE))) { if (lpSuperClass) pSession->LoadClassInfo(pConn, lpSuperClass, dScopeID, FALSE); } }
if (dwGenus == 1) lpRelPath = GetPropertyVal(L"__Class", pObj); else { LPWSTR lpTemp = GetPropertyVal(L"__RelPath", pObj); CDeleteMe <wchar_t> d (lpTemp);
lpRelPath = StripSlashes(lpTemp); if (lpRelPath) { LPWSTR lpNewClass = pCache->GetKeyRoot(lpClassName, dScopeID); if (lpNewClass) { LPWSTR lpPtr = lpRelPath + wcslen(lpClassName); LPWSTR lpTemp2 = new wchar_t [wcslen(lpNewClass) + wcslen(lpPtr) + 1]; if (lpTemp2) { wcscpy(lpTemp2, lpNewClass); wcscat(lpTemp2, lpPtr); delete lpRelPath; lpRelPath = lpTemp2; } delete lpNewClass; } } } lpKeyString = NULL;
}
CWbemClassObjectProps::~CWbemClassObjectProps() { delete lpClassName; delete lpNamespace; delete lpRelPath; delete lpSuperClass; delete lpKeyString; delete lpDynasty; }
//***************************************************************************
//
// ConvertBlobToObject
//
//***************************************************************************
HRESULT ConvertBlobToObject (IWbemClassObject *pNewObj, BYTE *pBuffer, DWORD dwLen, _IWmiObject **ppNewObj) { HRESULT hr = WBEM_S_NO_ERROR;
IWbemClassObject *pEmbed = NULL; _IWmiObject *pInt = NULL; if (pNewObj) hr = pNewObj->Clone(&pEmbed); else { _IWmiObject *pClass = NULL; // Handle blank Instance prototypes
hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER, IID__IWmiObject, (void **)&pClass); CReleaseMe r (pClass); if (pClass) { hr = pClass->WriteProp(L"__Class", 0, 4, 4, CIM_STRING, L"X"); if (SUCCEEDED(hr)) { hr = pClass->SpawnInstance(0, &pEmbed); } } }
if (SUCCEEDED(hr)) { hr = pEmbed->QueryInterface(IID__IWmiObject, (void **)&pInt); CReleaseMe r (pInt); if (SUCCEEDED(hr)) { LPVOID pTaskMem = NULL;
if (SUCCEEDED(hr)) { pTaskMem = CoTaskMemAlloc( dwLen );
if ( NULL != pTaskMem ) { // Copy the memory
CopyMemory( pTaskMem, pBuffer, dwLen ); hr = pInt->SetObjectMemory(pTaskMem, dwLen); if (SUCCEEDED(hr)) { *ppNewObj = pInt; } else { _IWmiObject *pClass = NULL; hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER, IID__IWmiObject, (void **)&pClass); if (SUCCEEDED(hr)) { hr = pClass->SetObjectMemory(pTaskMem, dwLen); if (SUCCEEDED(hr)) { *ppNewObj = pClass; } } } } else { hr = WBEM_E_OUT_OF_MEMORY; } } } } return hr; }
void ConvertDataToString(WCHAR * lpKey, BYTE* pData, DWORD dwType, BOOL bQuotes) { WCHAR *pFr; WCHAR *pTo, *pOrig; pFr = (LPWSTR)pData; switch(dwType) { case CIM_STRING: case CIM_REFERENCE: if (bQuotes) { pTo = lpKey; *pTo = L'\"'; *pTo++; while (*pFr) { if (*pFr == L'\"') { *pTo = L'\\'; *pTo++; *pTo = L'\"'; } else *pTo = *pFr; pFr++; pTo++; } *pTo = L'\"'; *pTo++; *pTo = L'\0'; } else wcscpy(lpKey, (LPWSTR)pData); break; case CIM_SINT32: swprintf(lpKey, L"%d", *(int *)pData); break; case CIM_UINT32: swprintf(lpKey, L"%u", *(unsigned *)pData); break; case CIM_SINT16: swprintf(lpKey, L"%hd", *(signed short *)pData); break; case CIM_UINT16: swprintf(lpKey, L"%hu", *(unsigned short *)pData); break; case CIM_SINT8: swprintf(lpKey, L"%d", *(signed char *)pData); break; case CIM_UINT8: swprintf(lpKey, L"%u", *(unsigned char *)pData); break; case CIM_UINT64: swprintf(lpKey, L"%I64u", *(unsigned __int64 *)pData); break; case CIM_SINT64: swprintf(lpKey, L"%I64d", *(__int64 *)pData); break; case CIM_BOOLEAN: // String, either TRUE or FALSE
if (*pFr) wcscpy(lpKey, L"TRUE"); else wcscpy(lpKey, L"FALSE"); break; default: break; } }
HRESULT MakeKeyListString(SQL_ID dScopeId, CSchemaCache *pCache, LPWSTR lpClass, IWbemPathKeyList *pKeyList, LPWSTR lpKeyString) { HRESULT hr = 0;
if (!pKeyList) return 0;
if (!lpKeyString) return WBEM_E_INVALID_PARAMETER;
ULONG uNumKeys = 0; hr = pKeyList->GetCount(&uNumKeys); if (SUCCEEDED(hr)) { if (!uNumKeys) { ULONGLONG uIsSingleton = 0; hr = pKeyList->GetInfo(0, &uIsSingleton); if (SUCCEEDED(hr)) { if (uIsSingleton) wcscat(lpKeyString, L"=@"); else hr = WBEM_E_INVALID_PARAMETER; } } else { // Get the key list from the schema cache
CWStringArray arrKeys; hr = pCache->GetKeys(dScopeId, lpClass, arrKeys); if (SUCCEEDED(hr)) { if (arrKeys.Size() != uNumKeys) { hr = WBEM_E_INVALID_QUERY; } else { BOOL bFound = FALSE;
for (int i = 0; i < arrKeys.Size(); i++) { bFound = FALSE; DWORD dwLen2 = 1024; BYTE bBuff[1024]; wchar_t wName [1024]; ULONG ct;
for (ULONG j = 0; j < arrKeys.Size(); j++) { ULONG dwLen1 = 1024, dwLen2 = 1024; hr = pKeyList->GetKey(j, 0, &dwLen1, wName, &dwLen2, bBuff, &ct); if (SUCCEEDED(hr) && (!wcslen(wName) || !_wcsnicmp(wName, arrKeys.GetAt(i), 127))) { if (i > 0) wcscat(lpKeyString, L","); else wcscat(lpKeyString, L"."); wcscat(lpKeyString, arrKeys.GetAt(i)); wcscat(lpKeyString, L"="); wchar_t wValue[1024]; ConvertDataToString(wValue, bBuff, ct, TRUE);
if (FAILED(hr)) break; wcscat(lpKeyString, wValue); bFound = TRUE; break; } } if (!bFound) hr = WBEM_E_INVALID_PARAMETER;
if (FAILED(hr)) break; } } } } } return hr; }
BOOL IsDerivedFrom(IWbemClassObject *pObj, LPWSTR lpClassName, BOOL bDirectOnly) { BOOL bRet = FALSE; VARIANT vTemp; CClearMe c (&vTemp); LPWSTR lpClass = GetPropertyVal(L"__Class", pObj); CDeleteMe <wchar_t> d (lpClass); HRESULT hr = WBEM_S_NO_ERROR;
if (!bDirectOnly) { if (!_wcsicmp(lpClassName, lpClass)) bRet = TRUE; }
if (!bRet) { hr = pObj->Get(L"__Derivation", 0, &vTemp, NULL, NULL); if (SUCCEEDED(hr)) { SAFEARRAY *psaArray = V_ARRAY(&vTemp); if (psaArray) { long lLBound, lUBound; SafeArrayGetLBound(psaArray, 1, &lLBound); SafeArrayGetUBound(psaArray, 1, &lUBound);
lUBound -= lLBound; lUBound += 1;
for (int i = 0; i < lUBound; i++) { VARIANT vT2; VariantInit(&vT2); LPWSTR lpValue = NULL; hr = GetVariantFromArray(psaArray, i, VT_BSTR, vT2); lpValue = GetStr(vT2); CDeleteMe <wchar_t> r (lpValue); VariantClear(&vT2);
if (lpValue && !_wcsicmp(lpValue, lpClassName)) { bRet = TRUE; break; } } } } }
return bRet; }
POLARITY BOOL SetObjectAccess( IN HANDLE hObj) { PSECURITY_DESCRIPTOR pSD; DWORD dwLastErr = 0; BOOL bRet = FALSE;
// no point if we arnt on nt
pSD = (PSECURITY_DESCRIPTOR)CWin32DefaultArena::WbemMemAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH); if(pSD == NULL) return FALSE;
ZeroMemory(pSD, SECURITY_DESCRIPTOR_MIN_LENGTH); if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) goto Cleanup; if(!SetSecurityDescriptorDacl(pSD, TRUE, NULL, FALSE)) goto Cleanup;
bRet = SetKernelObjectSecurity(hObj, DACL_SECURITY_INFORMATION, pSD);
Cleanup: if(bRet == FALSE) dwLastErr = GetLastError(); CWin32DefaultArena::WbemMemFree(pSD); return bRet; }
HINSTANCE CWmiDbController::GetResourceDll (LCID lLocale) { HINSTANCE hRCDll = NULL; wchar_t wLibName[501];
GetModuleFileName(NULL, wLibName, 500); wchar_t *pLibName = wcsrchr(wLibName, L'\\'); wchar_t *pTop = (wchar_t *)wLibName; if (pLibName) { int iPos = pLibName - pTop + 1; wLibName[iPos] = '\0'; }
swprintf(wLibName, L"%s%08X\\reprc.dll", wLibName, lLocale); hRCDll = LoadLibrary(wLibName);
return hRCDll; }
LPWSTR GetKeyString (LPWSTR lpString) { if (!lpString) return NULL; else return StripQuotes(lpString); }
//***************************************************************************
//
// CWmiDbHandle::CWmiDbHandle
//
//***************************************************************************
CWmiDbHandle::CWmiDbHandle() { m_dwHandleType = WMIDB_HANDLE_TYPE_NO_CACHE | WMIDB_HANDLE_TYPE_COOKIE; m_uRefCount = 0; m_bDefault = TRUE; m_bSecDesc = FALSE; m_dObjectId = 0; m_dClassId = 0; m_dwVersion = 1; m_pSession = NULL; m_pData = NULL; }
//***************************************************************************
//
// CWmiDbHandle::CWmiDbHandle
//
//***************************************************************************
CWmiDbHandle::~CWmiDbHandle() {
}
//***************************************************************************
//
// CWmiDbHandle::QueryInterface
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbHandle::QueryInterface( /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) { *ppvObject = 0;
if (IID_IUnknown==riid || IID_IWmiDbHandle==riid ) { *ppvObject = (IWmiDbHandle*)this; AddRef(); return S_OK; } else if (IID_IWbemClassObject == riid || IID__IWmiObject == riid) { if (!m_pData && m_pSession && m_dwHandleType != WMIDB_HANDLE_TYPE_INVALID) { if (m_dObjectId) { HRESULT hr = QueryInterface_Internal(NULL, ppvObject); return hr; } } else if (m_pData) { *ppvObject = m_pData; m_pData->AddRef(); return S_OK; } else return E_HANDLE; }
return E_NOINTERFACE; }
//***************************************************************************
//
// CWmiDbHandle::QueryInterface_Internal
//
//***************************************************************************
HRESULT CWmiDbHandle::QueryInterface_Internal(CSQLConnection *pConn, void __RPC_FAR *__RPC_FAR *ppvObject, LPWSTR lpKey) { IWbemClassObject *pNew = NULL; HRESULT hr = WBEM_S_NO_ERROR;
try { if (m_pData) { *ppvObject = m_pData; m_pData->AddRef(); return S_OK; } else { hr = ((CWmiDbSession *)m_pSession)->GetObjectData(pConn, m_dObjectId, m_dClassId, m_dScopeId, m_dwHandleType, m_dwVersion, &pNew, FALSE, lpKey, m_bSecDesc); if (SUCCEEDED(hr) && pNew) { *ppvObject = (IWbemClassObject *)pNew; // Cookie handles must be reread each time.
if ((m_dwHandleType & 0xF) != WMIDB_HANDLE_TYPE_COOKIE) { _WMILockit lkt(((CWmiDbSession *)m_pSession)->GetCS()); m_pData = pNew; pNew->AddRef(); // For ourselves.
} return S_OK; } else if (SUCCEEDED(hr)) hr = WBEM_E_FAILED; else if (hr == WBEM_E_CRITICAL_ERROR && (!m_pSession || !((CWmiDbSession *)m_pSession)->m_pController)) hr = WBEM_E_SHUTTING_DOWN; } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbHandle::QueryInterface_Internal (%I64d)\n", m_dObjectId)); hr = WBEM_E_CRITICAL_ERROR; }
return hr; }
//***************************************************************************
//
// CWmiDbHandle::AddRef
//
//***************************************************************************
ULONG STDMETHODCALLTYPE CWmiDbHandle::AddRef( ) { if (m_pSession) m_pSession->AddRef(); // We can't safely keep track of this
// so we will only addref it once.
// ==================================
//if (m_pData)
// m_pData->AddRef();
InterlockedIncrement((LONG *) &m_uRefCount); return m_uRefCount;
}
//***************************************************************************
//
// CWmiDbHandle::Release
//
//***************************************************************************
ULONG STDMETHODCALLTYPE CWmiDbHandle::Release( ) {
ULONG uNewCount = m_uRefCount; uNewCount = InterlockedDecrement((LONG *) &m_uRefCount); HRESULT hr = 0;
try { // Only if we haven't shut down.
if (m_pSession && (((CWmiDbSession *)m_pSession)->m_pController)) { if (!uNewCount) { if ((m_dwHandleType & 0xF000) == WMIDB_HANDLE_TYPE_AUTODELETE) { hr = ((CWmiDbSession *)m_pSession)->Delete((IWmiDbHandle *)this); if (FAILED(hr)) return uNewCount; } else if (m_dwHandleType != WMIDB_HANDLE_TYPE_INVALID) { ((CWmiDbSession *)m_pSession)->CleanCache(m_dObjectId, m_dwHandleType, this); } if (((CWmiDbSession *)m_pSession)->m_pController) ((CWmiDbController *)((CWmiDbSession *)m_pSession)->m_pController)->SubtractHandle(); ((CWmiDbSession *)m_pSession)->UnlockDynasties(); } m_pSession->Release(); } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbHandle::Release (%I64d)\n", m_dObjectId)); hr = WBEM_E_CRITICAL_ERROR; }
if (0 != uNewCount) return uNewCount;
// To be safe, we will only add ref
// this once, and release it once.
// ================================
if (m_pData) m_pData->Release(); delete this;
return uNewCount;
} //***************************************************************************
//
// CWmiDbHandle::GetHandleType
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbHandle::GetHandleType( /* [out] */ DWORD __RPC_FAR *pdwType)
{ HRESULT hr = WBEM_S_NO_ERROR;
if (pdwType) *pdwType = m_dwHandleType; else hr = WBEM_E_INVALID_PARAMETER;
return hr; }
//***************************************************************************
//
// CESSManager::CESSManager
//
//***************************************************************************
CESSManager::CESSManager() { m_EventSubSys = NULL; }
//***************************************************************************
//
// CESSManager::~CESSManager
//
//***************************************************************************
CESSManager::~CESSManager() { // Release our ESS pointer.
if (m_EventSubSys) m_EventSubSys->Release(); }
//***************************************************************************
//
// CESSManager::InitializeESS
//
//***************************************************************************
void CESSManager::InitializeESS() { HRESULT hres = CoCreateInstance(CLSID_IWmiCoreServices, NULL, CLSCTX_INPROC_SERVER, IID__IWmiCoreServices, (void**)&m_EventSubSys); if(FAILED(hres)) { ERRORTRACE((LOG_WBEMCORE,"CRITICAL: Event system not available!!!!\n")); } }
//***************************************************************************
//
// CESSManager::AddInsertRecord
//
//***************************************************************************
HRESULT CESSManager::AddInsertRecord(CSQLConnection *pConn, LPWSTR lpGUID, LPWSTR lpNamespace, LPWSTR lpClass, DWORD dwGenus, IWbemClassObject *pOldObj, IWbemClassObject *pNewObj) { HRESULT hr = WBEM_S_NO_ERROR;
if (m_EventSubSys) { if (lpGUID && wcslen(lpGUID)) { // Write record to the database.
hr = CSQLExecProcedure::InsertUncommittedEvent(pConn, lpGUID, lpNamespace, lpClass, pOldObj, pNewObj, m_Schema); } else { long lType = 0;
if (!pOldObj && pNewObj) { if (dwGenus == 1) lType = WBEM_EVENTTYPE_ClassCreation; else { if (IsDerivedFrom(pNewObj, L"__Namespace")) lType = WBEM_EVENTTYPE_NamespaceCreation; else lType = WBEM_EVENTTYPE_InstanceCreation; } } else { if (dwGenus == 1) lType = WBEM_EVENTTYPE_ClassModification; else { if (IsDerivedFrom(pOldObj, L"__Namespace")) lType = WBEM_EVENTTYPE_NamespaceModification; else lType = WBEM_EVENTTYPE_InstanceModification; } }
CESSHolder *pHolder = new CESSHolder (lType, lpNamespace, lpClass, (_IWmiObject *)pOldObj, (_IWmiObject *)pNewObj); if (!pHolder) hr = WBEM_E_OUT_OF_MEMORY;
m_ESSObjs[GetCurrentThreadId()] = pHolder; } }
return hr; }
//***************************************************************************
//
// CESSManager::AddDeleteRecord
//
//***************************************************************************
HRESULT CESSManager::AddDeleteRecord(CSQLConnection *pConn, LPWSTR lpGUID, LPWSTR lpNamespace, LPWSTR lpClass, DWORD dwGenus, IWbemClassObject *pObj) { HRESULT hr = WBEM_S_NO_ERROR;
if (m_EventSubSys) { // Write record to the database
if (lpGUID && wcslen(lpGUID)) { // Write record to the database.
hr = CSQLExecProcedure::InsertUncommittedEvent(pConn, lpGUID, lpNamespace, lpClass, NULL, pObj, m_Schema); } else { long lType = 0;
if (dwGenus == 1) lType = WBEM_EVENTTYPE_ClassDeletion; else { if (IsDerivedFrom(pObj, L"__Namespace")) lType = WBEM_EVENTTYPE_NamespaceDeletion; else lType = WBEM_EVENTTYPE_InstanceDeletion; }
CESSHolder *pHolder = new CESSHolder (lType, lpNamespace, lpClass, (_IWmiObject *)pObj, NULL); if (!pHolder) hr = WBEM_E_OUT_OF_MEMORY;
m_ESSObjs[GetCurrentThreadId()] = pHolder; }
}
return hr; }
//***************************************************************************
//
// CESSManager::CommitAll
//
//***************************************************************************
HRESULT CESSManager::CommitAll(LPCWSTR lpGUID, LPCWSTR lpRootNs) {
HRESULT hr = WBEM_S_NO_ERROR;
if (m_EventSubSys) { if (lpGUID && wcslen(lpGUID)) { CSQLConnection *pConn = NULL; hr = m_Conns->GetConnection(&pConn, FALSE, FALSE, 30); if (SUCCEEDED(hr)) { hr = CSQLExecProcedure::CommitEvents(pConn, m_EventSubSys, lpRootNs, lpGUID, m_Schema, m_Objects); m_Conns->ReleaseConnection(pConn);
} } else { DWORD dwThread = GetCurrentThreadId(); CESSHolder *pH = m_ESSObjs[dwThread]; if (pH) pH->Deliver(m_EventSubSys, lpRootNs); delete pH; m_ESSObjs[dwThread] = NULL; } }
return hr; }
//***************************************************************************
//
// CESSManager::DeleteAll
//
//***************************************************************************
HRESULT CESSManager::DeleteAll(LPCWSTR lpGUID) {
HRESULT hr = WBEM_S_NO_ERROR;
// Delete from DB
if (m_EventSubSys) { if (lpGUID && wcslen(lpGUID)) { CSQLConnection *pConn = NULL; hr = m_Conns->GetConnection(&pConn, FALSE, FALSE, 30); if (SUCCEEDED(hr)) { hr = CSQLExecProcedure::DeleteUncommittedEvents(pConn, lpGUID, m_Schema, m_Objects); m_Conns->ReleaseConnection(pConn); } } else { DWORD dwThread = GetCurrentThreadId(); CESSHolder *pH = m_ESSObjs[dwThread]; delete pH; m_ESSObjs[dwThread] = NULL;
} }
return hr; }
//***************************************************************************
//
// CESSHolder::CESSHolder
//
//***************************************************************************
CESSHolder::CESSHolder(long lType, LPWSTR lpNs, LPWSTR lpClass, _IWmiObject *pOld, _IWmiObject *pNew) { m_lType = lType; if (lpNs && wcslen(lpNs)) m_sNamespace = lpNs; else m_sNamespace = L""; m_sClass = lpClass;
if (pOld) pOld->AddRef(); if (pNew) pNew->AddRef(); pOldObject = pOld; pNewObject = pNew; }
//***************************************************************************
//
// CESSHolder::Deliver
//
//***************************************************************************
HRESULT CESSHolder::Deliver (_IWmiCoreServices *pCS, LPCWSTR lpRootNs) { HRESULT hr = WBEM_S_NO_ERROR;
DWORD dwNumObjs = 0;
if (pOldObject) dwNumObjs++; if (pNewObject) dwNumObjs++;
_bstr_t sTemp = L"\\\\.\\"; sTemp += lpRootNs; if (m_sNamespace.length() && _wcsnicmp(m_sNamespace, L"root", 4)) { sTemp += L"\\"; sTemp += m_sNamespace; }
_IWmiObject **pObjs = new _IWmiObject * [dwNumObjs]; if (pObjs) { if (pNewObject) pObjs[0] = pNewObject; else pObjs[0] = pOldObject; if (pOldObject && pNewObject) pObjs[1] = pOldObject;
hr = pCS->DeliverIntrinsicEvent(sTemp, m_lType, NULL, m_sClass, NULL, dwNumObjs, pObjs);
delete pObjs;
if (pOldObject) pOldObject->Release(); if (pNewObject) pNewObject->Release(); } else hr = WBEM_E_OUT_OF_MEMORY;
return hr; }
//***************************************************************************
//
// CWmiDbController::CWmiDbController
//
//***************************************************************************
CWmiDbController::CWmiDbController() { InitializeCriticalSection(&m_cs);
m_dwTimeOut = 10*1000; // 30 seconds default
m_dwCurrentStatus = 0; // No status
m_uRefCount = 0; m_pIMalloc = NULL; m_InitProperties = NULL; m_rgInitPropSet = NULL; m_dwTotalHits = 0; m_dwCacheHits = 0; m_dwTotalHandles = 0; m_bCacheInit = 0; m_bIsAdmin = 0; m_bESSEnabled = 0;
CoInitialize(NULL); ESSMgr.SetConnCache(&ConnCache); ESSMgr.SetObjectCache(&ObjectCache); ESSMgr.SetSchemaCache(&SchemaCache); }
//***************************************************************************
//
// CWmiDbController::CWmiDbController
//
//***************************************************************************
CWmiDbController::~CWmiDbController() { Shutdown(0); if (m_pIMalloc) m_pIMalloc->Release(); delete m_InitProperties; delete m_rgInitPropSet; g_cObj--; DeleteCriticalSection(&m_cs); }
//***************************************************************************
//
// CWmiDbController::QueryInterface
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbController::QueryInterface( /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) { *ppvObject = 0;
if (IID_IUnknown==riid || IID_IWmiDbController==riid ) { *ppvObject = (IWmiDbController*)this; AddRef(); return S_OK; }
return E_NOINTERFACE;
}
//***************************************************************************
//
// CWmiDbController::AddRef
//
//***************************************************************************
ULONG STDMETHODCALLTYPE CWmiDbController::AddRef( ) { InterlockedIncrement((LONG *) &m_uRefCount); return m_uRefCount;
} //***************************************************************************
//
// CWmiDbController::Release
//
//***************************************************************************
ULONG STDMETHODCALLTYPE CWmiDbController::Release( ) { ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount); if (0 != uNewCount) return uNewCount; delete this; return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
// CWmiDbController::FreeLogonTemplate
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbController::FreeLogonTemplate( /* [out][in] */ WMIDB_LOGON_TEMPLATE __RPC_FAR *__RPC_FAR *pTemplate) { HRESULT hr = WBEM_S_NO_ERROR;
try { if (!pTemplate || !*pTemplate) hr = WBEM_E_INVALID_PARAMETER; else { WMIDB_LOGON_TEMPLATE *pTemp = *pTemplate;
for (int i = 0; i < (int)pTemp->dwArraySize; i++) { VariantClear(&(pTemp->pParm[i].Value)); SysFreeString(pTemp->pParm[i].strParmDisplayName); } delete []pTemp->pParm;
delete *pTemplate; *pTemplate = NULL; } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::FreeLogonTemplate\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr;
}
//***************************************************************************
//
// CWmiDbController::Logon
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbController::Logon( /* [in] */ WMIDB_LOGON_TEMPLATE __RPC_FAR *pLogonParms, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwRequestedHandleType, /* [out] */ IWmiDbSession __RPC_FAR *__RPC_FAR *ppSession, /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppRootNamespace) { HRESULT hr = WBEM_S_NO_ERROR;
if (!pLogonParms) return WBEM_E_INVALID_PARAMETER;
if (dwFlags &~ WMIDB_FLAG_NO_INIT &~ WMIDB_FLAG_ADMIN_VERIFIED) return WBEM_E_INVALID_PARAMETER;
// Not yet clear what we need to do.
// Best guess is: we get a SQL connection, shove it into an IWmiDbSession,
// and give it back to the user.
try { if (m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) hr = WBEM_E_SHUTTING_DOWN;
else { if (!ppSession) hr = WBEM_E_INVALID_PARAMETER; else { _WMILockit lkt(&m_cs); IWmiDbSession *pSession = NULL; hr = GetUnusedSession(pLogonParms, dwFlags, dwRequestedHandleType, &pSession); if (SUCCEEDED(hr)) { *ppSession = pSession; // hopefully this interface will be corrected...
if (!(dwFlags & WMIDB_FLAG_NO_INIT)) { if (!m_bCacheInit) { hr = ((CWmiDbSession *)pSession)->LoadSchemaCache();
// We don't want to return a handle if we couldn't load the schema cache.
if (SUCCEEDED(hr)) m_bCacheInit = TRUE; } if (dwFlags & WMIDB_FLAG_ADMIN_VERIFIED) m_bIsAdmin = TRUE;
// Now see if we can get a handle to the root namespace...
hr = ((CWmiDbSession *)pSession)->GetObject_Internal(L"root", dwFlags, dwRequestedHandleType, NULL, ppRootNamespace);
((CWmiDbSession *)pSession)->m_sNamespacePath = L"root"; // Temporary default
wchar_t wMachineName[1024]; DWORD dwLen=1024; if (!GetComputerName(wMachineName, &dwLen)) { hr = GetLastError(); return WBEM_E_FAILED; } ((CWmiDbSession *)pSession)->m_sMachineName = wMachineName;
if (!m_bESSEnabled) { ESSMgr.InitializeESS(); if (ESSMgr.m_EventSubSys) m_bESSEnabled = TRUE; } } else if (ppRootNamespace) *ppRootNamespace = NULL; }
}
} } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::Logon\n")); hr = WBEM_E_CRITICAL_ERROR; } return hr; }
//***************************************************************************
//
// CWmiDbController::Shutdown
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbController::Shutdown( /* [in] */ DWORD dwFlags) { HRESULT hr = WBEM_S_NO_ERROR;
if (dwFlags != 0) return WBEM_E_INVALID_PARAMETER;
if (m_dwCurrentStatus) hr = m_dwCurrentStatus; else m_dwCurrentStatus = WBEM_E_SHUTTING_DOWN;
try { FlushCache(REPDRVR_FLAG_FLUSH_ALL);
hr = ConnCache.ClearConnections();
for (int i = 0; i < m_Sessions.size(); i++) { IWmiDbSession *pSession = m_Sessions[i]; if (pSession) { ((CWmiDbSession *)pSession)->ShutDown(); pSession->Release(); } } m_Sessions.clear();
} catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::Shutdown\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr;
}
//***************************************************************************
//
// CWmiDbController::SetCallTimeout
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbController::SetCallTimeout( /* [in] */ DWORD dwMaxTimeout) { HRESULT hr = WBEM_S_NO_ERROR;
if (dwMaxTimeout < 1000) return WBEM_E_INVALID_PARAMETER;
if (m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) hr = WBEM_E_SHUTTING_DOWN; else m_dwTimeOut = dwMaxTimeout;
return hr;
}
//***************************************************************************
//
// CWmiDbController::SetCacheValue
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbController::SetCacheValue( /* [in] */ DWORD dwMaxBytes) { HRESULT hr = WBEM_S_NO_ERROR;
try {
if (m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) hr = WBEM_E_SHUTTING_DOWN; else { ObjectCache.SetCacheSize(dwMaxBytes); SchemaCache.SetMaxSize(dwMaxBytes); } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::SetCacheValue\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr;
}
//***************************************************************************
//
// CWmiDbController::FlushCache
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbController::FlushCache( DWORD dwFlags) { HRESULT hr = WBEM_S_NO_ERROR;
try { // Remove all data from the cache.
{ _WMILockit lkt(&m_cs); ObjectCache.EmptyCache(); }
if (dwFlags == REPDRVR_FLAG_FLUSH_ALL) { // Remove all SQL connections. We will reconnect later.
hr = ConnCache.ClearConnections();
// Clear all internal caches. These will be restored on the next connection.
{ _WMILockit lkt(&m_cs); SchemaCache.EmptyCache(); }
m_bCacheInit = FALSE; } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::FlushCache\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr; }
//***************************************************************************
//
// CWmiDbController::GetStatistics
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbController::GetStatistics( /* [in] */ DWORD dwParameter, /* [out] */ DWORD __RPC_FAR *pdwValue) { HRESULT hr = WBEM_S_NO_ERROR; DWORD dwTemp1 = 0; DWORD dwTemp2 = 0; _WMILockit _lk(&m_cs);
try { if (!pdwValue) hr = WBEM_E_INVALID_PARAMETER; else { switch (dwParameter) { case WMIDB_FLAG_TOTAL_HANDLES: *pdwValue = m_dwTotalHandles; break; case WMIDB_FLAG_CACHE_SATURATION: ObjectCache.GetCurrentUsage(dwTemp1); ObjectCache.GetCacheSize(dwTemp2); if (dwTemp2 > 0) *pdwValue = 100*(((double)dwTemp1/(double)dwTemp2)); break; case WMIDB_FLAG_CACHE_HIT_RATE: if (m_dwTotalHits > 0) *pdwValue = 100*((double)m_dwCacheHits / (double)m_dwTotalHits); break; default: hr = WBEM_E_NOT_SUPPORTED; break; } } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::GetStatistics\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr;
}
//***************************************************************************
//
// CWmiDbController::GetUnusedSession
//
//***************************************************************************
HRESULT CWmiDbController::GetUnusedSession(WMIDB_LOGON_TEMPLATE *pLogon, DWORD dwFlags, DWORD dwHandleType, IWmiDbSession **pSess) { HRESULT hr = WBEM_S_NO_ERROR; _WMILockit lkt(&m_cs);
CWmiDbSession *pSession = NULL;
Sessions::iterator walk = m_Sessions.begin();
while (walk != m_Sessions.end()) { pSession = *walk; if (!(pSession)->m_bInUse) { (pSession)->m_bInUse = TRUE; break; } walk++; }
if (!pSession) { hr = SetConnProps(pLogon);
if (SUCCEEDED(hr)) { pSession = new CWmiDbSession(this); if (pSession) { (pSession)->m_bInUse = TRUE; pSession->m_dwLocale = pLogon->pParm[4].Value.lVal; m_Sessions.push_back(pSession); pSession->m_pIMalloc = m_pIMalloc; pSession->AddRef(); // For us
pSession->AddRef(); // For the end user.
*pSess = pSession; } else hr = WBEM_E_OUT_OF_MEMORY; } } else { hr = SetConnProps(pLogon); pSession->m_dwLocale = pLogon->pParm[4].Value.lVal; pSession->AddRef(); }
hr = ConnCache.SetCredentials(m_rgInitPropSet); hr = ConnCache.SetMaxConnections (20); hr = ConnCache.SetTimeoutSecs(60); if (pLogon->pParm[3].Value.vt == VT_BSTR) hr = ConnCache.SetDatabase(pLogon->pParm[3].Value.bstrVal); else hr = ConnCache.SetDatabase(L""); // This isn't a SQL db.
// Make sure the login credentials worked.
// If they specified "No initialization", they
// don't intend to use the database - they are
// probably going to perform a backup or restore.
if (!(dwFlags & WMIDB_FLAG_NO_INIT)) { CSQLConnection *pConn; hr = ConnCache.GetConnection(&pConn, FALSE, FALSE, 30); if (SUCCEEDED(hr)) ConnCache.ReleaseConnection(pConn); }
return hr; }
//***************************************************************************
//
// CWmiDbController::SetConnProps
//
//***************************************************************************
HRESULT CWmiDbController::SetConnProps(WMIDB_LOGON_TEMPLATE *pLogon) { HRESULT hr = WBEM_S_NO_ERROR; ULONG nProps = pLogon->dwArraySize + 2 ;
// This just sets the latest connection properties.
// MOVE ME: SQL Server-specific optimization.
// wchar_t wMachineName[MAX_COMPUTERNAME_LENGTH+1];
// DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
// GetComputerName(wMachineName, &dwSize);
// if (!wcscmp(pLogon->pParm[0].strParmDisplayName, wMachineName))
// wcscpy(wMachineName, L".");
// else
// wcscpy(wMachineName, pLogon->pParm[0].Value.bstrVal);
if (!m_InitProperties) { m_InitProperties = new DBPROP[nProps]; if (!m_InitProperties) return WBEM_E_OUT_OF_MEMORY;
m_rgInitPropSet = new DBPROPSET; if (!m_rgInitPropSet) { delete m_InitProperties; return WBEM_E_OUT_OF_MEMORY; } }
int i = 0;
m_InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED; m_InitProperties[i].dwPropertyID = DBPROP_INIT_PROMPT; m_InitProperties[i].vValue.vt = VT_I2; m_InitProperties[i].vValue.iVal = DBPROMPT_NOPROMPT; m_InitProperties[i].colid = DB_NULLID; i++;
for (i = 1; i < (pLogon->dwArraySize + 1); i++ ) { m_InitProperties[i].colid = DB_NULLID; VariantInit(&m_InitProperties[i].vValue); m_InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED; m_InitProperties[i].dwPropertyID = pLogon->pParm[i-1].dwId; m_InitProperties[i].vValue.vt = pLogon->pParm[i-1].Value.vt; if (pLogon->pParm[i-1].Value.vt == VT_BSTR) m_InitProperties[i].vValue.bstrVal = SysAllocString(pLogon->pParm[i-1].Value.bstrVal); else if (pLogon->pParm[i-1].Value.vt == VT_I4) m_InitProperties[i].vValue.lVal = pLogon->pParm[i-1].Value.lVal; }
m_InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED; m_InitProperties[i].colid = DB_NULLID; m_InitProperties[i].dwPropertyID = DBPROP_INIT_TIMEOUT; m_InitProperties[i].vValue.vt = VT_I4; m_InitProperties[i].vValue.lVal = (long)m_dwTimeOut; m_rgInitPropSet->guidPropertySet = DBPROPSET_DBINIT; m_rgInitPropSet->cProperties = nProps; m_rgInitPropSet->rgProperties = m_InitProperties; return hr; }
//***************************************************************************
//
// CWmiDbController::ReleaseSession
//
//***************************************************************************
HRESULT CWmiDbController::ReleaseSession(IWmiDbSession *pSession) { HRESULT hr = WBEM_S_NO_ERROR; _WMILockit lkt(&m_cs);
// Mark connection unused and stick back in cache.
Sessions::iterator walk = m_Sessions.begin();
while (walk != m_Sessions.end()) { CWmiDbSession *pConn2 = *walk; if (pConn2 == ((CWmiDbSession *)pSession)) { pConn2->m_bInUse = FALSE; break; } }
return hr; }
//***************************************************************************
//
// CWmiDbController::IncrementHitCount
//
//***************************************************************************
void CWmiDbController::IncrementHitCount (bool bCacheUsed) { _WMILockit lkt(&m_cs);
m_dwTotalHits++; if (bCacheUsed) m_dwCacheHits++; } //***************************************************************************
//
// CWmiDbController::AddHandle
//
//***************************************************************************
void CWmiDbController::AddHandle() { _WMILockit lkt(&m_cs); m_dwTotalHandles++; }
//***************************************************************************
//
// CWmiDbController::SubtractHandle
//
//***************************************************************************
void CWmiDbController::SubtractHandle() { _WMILockit lkt(&m_cs); if (m_dwTotalHandles > 0) m_dwTotalHandles--; }
//***************************************************************************
//
// CWmiDbController::HasSecurityDescriptor
//
//***************************************************************************
BOOL CWmiDbController::HasSecurityDescriptor(SQL_ID ObjId) { BOOL bRet = FALSE;
_WMILockit _Lk(&m_cs);
SQL_IDMap::iterator it = SecuredIDs.find(ObjId); if (it != SecuredIDs.end()) bRet = TRUE;
return bRet; }
//***************************************************************************
//
// CWmiDbController::HasSecurityDescriptor
//
//***************************************************************************
void CWmiDbController::AddSecurityDescriptor(SQL_ID ObjId) { _WMILockit _Lk(&m_cs);
SecuredIDs[ObjId] = true; }
//***************************************************************************
//
// CWmiDbController::HasSecurityDescriptor
//
//***************************************************************************
void CWmiDbController::RemoveSecurityDescriptor(SQL_ID ObjId) { _WMILockit _Lk(&m_cs);
SQL_IDMap::iterator it = SecuredIDs.find(ObjId); if (it != SecuredIDs.end()) SecuredIDs.erase(it);
}
//***************************************************************************
//
// CWmiDbSession::CWmiDbSession
//
//***************************************************************************
CWmiDbSession::CWmiDbSession(IWmiDbController *pControl) { m_uRefCount = 0; m_pController = pControl; m_dwLocale = 0; m_bInUse = false; m_pIMalloc = NULL; m_bIsDistributed = FALSE; m_pController->AddRef(); } //***************************************************************************
//
// CWmiDbSession::CWmiDbSession
//
//***************************************************************************
CWmiDbSession::~CWmiDbSession() { if (m_pController) { ((CWmiDbController *)m_pController)->ReleaseSession(this); m_pController->Release(); } if (m_pIMalloc) m_pIMalloc->Release(); }
//***************************************************************************
//
// CWmiDbSession::QueryInterface
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::QueryInterface( /* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) { *ppvObject = 0;
if (IID_IUnknown==riid || IID_IWmiDbSession==riid ) { *ppvObject = (IWmiDbSession*)this; AddRef(); return S_OK; } else if (IID_IWmiDbBatchSession == riid) { *ppvObject = (IWmiDbBatchSession*)this; AddRef(); return S_OK; } else if (IID_IWbemTransaction == riid) { *ppvObject = (IWbemTransaction*)this; AddRef(); return S_OK; } else if (IID_IWmiDbBackupRestore == riid) { *ppvObject = (IWmiDbBackupRestore*)this; AddRef(); return S_OK; }
return E_NOINTERFACE;
}
//***************************************************************************
//
// CWmiDbSession::AddRef
//
//***************************************************************************
ULONG STDMETHODCALLTYPE CWmiDbSession::AddRef( ) { InterlockedIncrement((LONG *) &m_uRefCount); return m_uRefCount;
} //***************************************************************************
//
// CWmiDbSession::Release
//
//***************************************************************************
ULONG STDMETHODCALLTYPE CWmiDbSession::Release( ) { ULONG uNewCount = InterlockedDecrement((LONG *) &m_uRefCount); if (0 != uNewCount) return uNewCount; delete this; return WBEM_S_NO_ERROR;
}
//***************************************************************************
//
// CWmiDbSession::GetObject
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::GetObject( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ IWbemPath __RPC_FAR *pPath, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwRequestedHandleType, /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult) { HRESULT hr = WBEM_S_NO_ERROR;
// SYSTEMTIME tStartTime, tEndTime;
// GetLocalTime(&tStartTime);
// StartCAP();
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
if (!pScope || !pPath || dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID || !ppResult || (dwRequestedHandleType & ~WMIDB_HANDLE_TYPE_COOKIE &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE &~WMIDB_HANDLE_TYPE_SUBSCOPED &~WMIDB_HANDLE_TYPE_SCOPE &~WMIDB_HANDLE_TYPE_CONTAINER)) return WBEM_E_INVALID_PARAMETER;
try { { _WMILockit lkt(GetCS()); if (!((CWmiDbController *)m_pController)->m_bCacheInit) { hr = LoadSchemaCache(); if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE; else return hr; } }
_bstr_t sNewPath;
SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
if (SUCCEEDED(hr)) { LPWSTR lpNewPath = NULL; BOOL bStoreDefault = TRUE; SQL_ID dStorageClassId = 0; hr = NormalizeObjectPathGet(pScope, pPath, &lpNewPath, &bStoreDefault, &dStorageClassId, &dScopeId); CDeleteMe <wchar_t> r(lpNewPath); if (SUCCEEDED(hr)) { if (bStoreDefault) { // Handle the __Instances container.
// since this is not a real object.
if (dStorageClassId == INSTANCESCLASSID) { if (((dwRequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_COOKIE && (dwRequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_VERSIONED) || !bStoreDefault) hr = WBEM_E_INVALID_PARAMETER; else { SQL_ID dScopeId2 = dScopeId; hr = GetObject_Internal(L"__Instances", dwFlags, dwRequestedHandleType, &dScopeId2, ppResult); if (SUCCEEDED(hr)) { SQL_ID dClassId; hr = GetSchemaCache()->GetClassID(lpNewPath, dScopeId, dClassId); if (SUCCEEDED(hr)) { CWmiDbHandle *pTemp = (CWmiDbHandle *)*ppResult; pTemp->m_dObjectId = dClassId; pTemp->m_dClassId = INSTANCESCLASSID; pTemp->m_dScopeId = dScopeId; } } } } else hr = GetObject_Internal(lpNewPath, dwFlags, dwRequestedHandleType, &dScopeId, ppResult); if (SUCCEEDED(hr)) { // Mark this object as "custom" if
// this is a descendant of a custom scope,
// or if this is a custom namespace.
CWmiDbHandle *pTemp = (CWmiDbHandle *)*ppResult;
pTemp->m_bDefault = ((CWmiDbHandle *)pScope)->m_bDefault; if (pTemp->m_dClassId == MAPPEDNSCLASSID) pTemp->m_bDefault = FALSE; } }
// Use the custom storage mechanism.
else { // This needs to take care of all security and locks!!
hr = CustomGetObject(pScope, pPath, lpNewPath, dwFlags, dwRequestedHandleType, ppResult); }
// GetLocalTime(&tEndTime);
// ERRORTRACE((LOG_WBEMCORE, "IWmiDbSession::GetObject (%S) - %ld ms\n", lpNewPath, GetDiff(tEndTime, tStartTime)));
} } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::GetObject\n")); hr = WBEM_E_CRITICAL_ERROR; }
// StopCAP();
return hr;
}
//***************************************************************************
//
// CWmiDbSession::GetObjectDirect
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::GetObjectDirect( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ IWbemPath __RPC_FAR *pPath, /* [in] */ DWORD dwFlags, /* [in] */ REFIID riid, /* [iid_is][out] */ LPVOID __RPC_FAR *pObj) { HRESULT hr = WBEM_S_NO_ERROR;
try { if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
IWmiDbHandle *pHandle= NULL; CSQLConnection *pConn = NULL; hr = GetSQLCache()->GetConnection(&pConn, FALSE, IsDistributed()); if (SUCCEEDED(hr)) { LPWSTR lpNewPath = NULL; BOOL bStoreDefault = TRUE; SQL_ID dStorageClassId = 0; SQL_ID dScopeId; IWmiDbHandle *pHandle = NULL;
hr = NormalizeObjectPathGet(pScope, pPath, &lpNewPath, &bStoreDefault, &dStorageClassId, &dScopeId, pConn); CDeleteMe <wchar_t> r(lpNewPath);
if (!bStoreDefault || (dStorageClassId == INSTANCESCLASSID)) hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE, &pHandle); else if (SUCCEEDED(hr)) hr = GetObject_Internal(lpNewPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE, &dScopeId, &pHandle, pConn);
if (SUCCEEDED(hr)) { CReleaseMe r (pHandle); hr = ((CWmiDbHandle *)pHandle)->QueryInterface_Internal(pConn, pObj); } GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed()); } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::GetObjectDirect\n")); hr = WBEM_E_CRITICAL_ERROR; } return hr; }
//***************************************************************************
//
// CWmiDbSession::GetObject
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::GetObject_Internal( /* [in] */ LPWSTR lpPath, /* The full path */ /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwRequestedHandleType, /* [in] */ SQL_ID *pScopeId, /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult, CSQLConnection *pConn) { HRESULT hr = WBEM_S_NO_ERROR;
bool bImmediate = !(dwRequestedHandleType & WMIDB_HANDLE_TYPE_SUBSCOPED);
SQL_ID dScopeId = 0; if (pScopeId) dScopeId = *pScopeId;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; if (!lpPath) return WBEM_E_INVALID_PARAMETER;
*ppResult = NULL;
SQL_ID dObjId = 0, dClassId = 0;
LPWSTR lpKey = GetKeyString(lpPath);
CDeleteMe <wchar_t> r(lpKey); BOOL bGetScope = FALSE;
BOOL bNeedToRelease = FALSE; if (!pConn) { hr = GetSQLCache()->GetConnection(&pConn, FALSE, IsDistributed()); bNeedToRelease = TRUE; if (FAILED(hr)) return hr; }
// Special-case: Go up to the previous scope
if (!wcscmp(lpPath, L"..")) { hr = GetSchemaCache()->GetParentNamespace(dScopeId, dObjId, &dClassId); if (FAILED(hr)) { BOOL bExists = FALSE; hr = GetObjectCache()->GetObject(dScopeId, NULL, &dObjId); if (FAILED(hr)) bGetScope = TRUE; else hr = CSQLExecProcedure::ObjectExists(pConn, dObjId, bExists, &dClassId, NULL); } } else hr = GetObjectCache()->GetObjectId(lpKey, dObjId, dClassId, &dScopeId);
if (FAILED(hr)) { hr = WBEM_S_NO_ERROR; if (SUCCEEDED(hr)) { BOOL bExists = FALSE; if (!bGetScope) { hr = CSQLExecProcedure::ObjectExists(pConn, dObjId, bExists, &dClassId, &dScopeId); if (hr == E_NOTIMPL) { hr = CSQLExecProcedure::GetObjectIdByPath(pConn, lpKey, dObjId, dClassId, &dScopeId); if (dObjId) bExists = TRUE; } } else { // If we are getting the parent object,
// hit the db again to find the essentials there.
hr = CSQLExecProcedure::ObjectExists(pConn, dScopeId, bExists, &dClassId, &dObjId); if (SUCCEEDED(hr)) hr = CSQLExecProcedure::ObjectExists(pConn, dObjId, bExists, &dClassId, &dScopeId); }
if (SUCCEEDED(hr) && bExists) { // If a cookie or protected handle, just ref count.
// If exclusive, there can be only one.
// If versioned, we need to keep each version separate.
if ((dwRequestedHandleType & 0xF) == WMIDB_HANDLE_TYPE_COOKIE || (dwRequestedHandleType & 0xF) == WMIDB_HANDLE_TYPE_PROTECTED) ((CWmiDbController *)m_pController)->LockCache.GetHandle(dObjId, dwRequestedHandleType, ppResult);
if (*ppResult == NULL) { // If this object exists, try and obtain the requested lock.
CWmiDbHandle *pTemp = new CWmiDbHandle; if (pTemp) { DWORD dwVersion = 0; pTemp->m_pSession = this; AddRef_Lock();
// If this is a class, we want to lock its parents.
if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) { DWORD dwReq = WBEM_ENABLE;
if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR) dwReq |= READ_CONTROL;
hr = VerifyObjectSecurity(pConn, dObjId, dClassId, dScopeId, 0, dwReq); } if (SUCCEEDED(hr)) { if (IsDistributed()) { // Does this lock exist locally?
hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(false, dObjId, WMIDB_HANDLE_TYPE_PROTECTED, pTemp, dScopeId, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, false, 0, 0, &dwVersion);
if (FAILED(hr)) { // OK if the lock has already been taken
// on this session...
if (LockExists(dObjId)) hr = WBEM_S_NO_ERROR; } if (SUCCEEDED(hr)) hr = AddTransLock(dObjId, WMIDB_HANDLE_TYPE_PROTECTED); } if (SUCCEEDED(hr)) { hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjId, dwRequestedHandleType, pTemp, dScopeId, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, false, 0, 0, &dwVersion); } } if (FAILED(hr)) { delete pTemp; *ppResult = NULL; } else { // We have the lock. They will have to call Release() to
// free it up.
((CWmiDbController *)m_pController)->AddHandle(); pTemp->AddRef(); pTemp->m_dwHandleType = dwRequestedHandleType; pTemp->m_dObjectId = dObjId; pTemp->m_bDefault = TRUE;
pTemp->m_dClassId = dClassId; pTemp->m_dScopeId = dScopeId; pTemp->m_dwVersion = dwVersion; if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR) pTemp->m_bSecDesc = TRUE; if (ppResult) *ppResult = pTemp; } } else { if (ppResult) *ppResult = NULL; hr = WBEM_E_OUT_OF_MEMORY; } if (m_pController) ((CWmiDbController *)m_pController)->IncrementHitCount(false); }
} else if (SUCCEEDED(hr)) hr = WBEM_E_NOT_FOUND; } } else { if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) { DWORD dwReq = WBEM_ENABLE;
if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR) dwReq |= READ_CONTROL;
hr = VerifyObjectSecurity(pConn, dObjId, dClassId, dScopeId, 0, dwReq); } if (SUCCEEDED(hr)) { // At this point, we know that the object has been
// cached. Try to obtain a lock.
// ===============================================
CWmiDbHandle *pTemp = new CWmiDbHandle; if (pTemp) { DWORD dwVersion = 0; pTemp->m_pSession = this; hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjId, dwRequestedHandleType, pTemp, dScopeId, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, false, 0, 0, &dwVersion); if (SUCCEEDED(hr)) { AddRef_Lock(); ((CWmiDbController *)m_pController)->AddHandle(); pTemp->AddRef(); pTemp->m_dwHandleType = dwRequestedHandleType; pTemp->m_dObjectId = dObjId; pTemp->m_bDefault = TRUE; pTemp->m_dClassId = dClassId; pTemp->m_dScopeId = dScopeId; pTemp->m_dwVersion = dwVersion; pTemp->m_pData = NULL; if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR) pTemp->m_bSecDesc = TRUE;
if (ppResult) *ppResult = pTemp;
// We won't bother attaching the object part until they
// ask for it.
} else { delete pTemp; *ppResult = NULL; } } else { hr = WBEM_E_OUT_OF_MEMORY; } }
if (m_pController) ((CWmiDbController *)m_pController)->IncrementHitCount(true); }
if (bNeedToRelease) GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
if (pScopeId) *pScopeId = dScopeId;
return hr; }
//***************************************************************************
//
// CWmiDbSession::PutObject
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::PutObject( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ REFIID riid, /* [iid_is][in] */ LPVOID pObjToPut, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwRequestedHandleType, /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult) {
HRESULT hr = 0; CSQLConnection *pConn = NULL;
AddRef_Lock();
// StartCAP();
//SYSTEMTIME tStartTime, tEndTime;
//GetLocalTime(&tStartTime);
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
if (dwFlags & ~WBEM_FLAG_CREATE_ONLY & ~WBEM_FLAG_UPDATE_ONLY & ~WBEM_FLAG_CREATE_OR_UPDATE & ~WMIDB_DISABLE_EVENTS & ~WBEM_FLAG_USE_SECURITY_DESCRIPTOR &~ WBEM_FLAG_REMOVE_CHILD_SECURITY & ~WMIDB_FLAG_ADMIN_VERIFIED &~ WBEM_FLAG_UPDATE_SAFE_MODE &~ WBEM_FLAG_UPDATE_FORCE_MODE) return WBEM_E_INVALID_PARAMETER;
if ((ppResult && (dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID)) || !pScope || !pObjToPut) return WBEM_E_INVALID_PARAMETER;
if (riid != IID_IWbemClassObject && riid != IID_IWmiDbHandle && riid != IID__IWmiObject) return WBEM_E_NOT_SUPPORTED; try { { _WMILockit lkt(GetCS()); if (!((CWmiDbController *)m_pController)->m_bCacheInit) { hr = LoadSchemaCache(); if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE; else return hr; } }
hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed()); if (SUCCEEDED(hr)) { _bstr_t sWaste = L""; BOOL bSys = FALSE;
hr = PutObject(pConn, pScope, 0, L"", (IUnknown *)pObjToPut, dwFlags, dwRequestedHandleType, sWaste, ppResult); if (SUCCEEDED(hr) && ppResult) { CWmiDbHandle *pTemp = (CWmiDbHandle *)*ppResult;
pTemp->m_bDefault = ((CWmiDbHandle *)pScope)->m_bDefault; if (pTemp->m_dClassId == MAPPEDNSCLASSID) pTemp->m_bDefault = FALSE; }
GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
if (!(dwFlags & WMIDB_DISABLE_EVENTS) && !IsDistributed()) { if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath); }
} } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::PutObject\n")); hr = WBEM_E_CRITICAL_ERROR; }
// StopCAP();
UnlockDynasties();
return hr;
}
//***************************************************************************
//
// CWmiDbSession::PutObject
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::PutObject( CSQLConnection *pConn, IWmiDbHandle __RPC_FAR *pScope, SQL_ID dScopeID, LPWSTR lpScopePath, /* [in] */ IUnknown __RPC_FAR *pObjToPut, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwRequestedHandleType, _bstr_t &sPath, /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult, BOOL bStoreAsClass ) { HRESULT hr = WBEM_S_NO_ERROR; SQL_ID dObjectId = 0; IWmiDbHandle *pHandle = NULL; bool bClass = false, bLockVerified = false;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
if ((dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID) && ppResult) return WBEM_E_INVALID_PARAMETER;
if (dwRequestedHandleType & ~WMIDB_HANDLE_TYPE_COOKIE &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE &~WMIDB_HANDLE_TYPE_SUBSCOPED&~WMIDB_HANDLE_TYPE_AUTODELETE &~WMIDB_HANDLE_TYPE_CONTAINER &~ WMIDB_HANDLE_TYPE_SCOPE ) return WBEM_E_INVALID_PARAMETER;
bool bImmediate = !(dwRequestedHandleType & WMIDB_HANDLE_TYPE_SUBSCOPED); SQL_ID dClassId = 0;
// Hand this to the repository, to ensure that it cleans up
// any autodelete objects on failure.
dwFlags |= (dwRequestedHandleType & WMIDB_HANDLE_TYPE_AUTODELETE);
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
// Normalize the object path.
sPath = L""; BOOL bStoreDefault = TRUE; IWbemClassObject *pOutObj = NULL; LPWSTR lpScope = NULL; if (pScope) { if (GetSchemaCache()->IsDerivedClass (INSTANCESCLASSID, ((CWmiDbHandle *)pScope)->m_dClassId) || ((CWmiDbHandle *)pScope)->m_dClassId == INSTANCESCLASSID) hr = WBEM_E_INVALID_OPERATION; else { CWbemClassObjectProps *pProps= NULL; hr = NormalizeObjectPath(pScope, (LPWSTR)NULL, &lpScope, FALSE, &pProps, &bStoreDefault, pConn); CDeleteMe <CWbemClassObjectProps> r (pProps);
dScopeID = ((CWmiDbHandle *)pScope)->m_dObjectId; if (SUCCEEDED(hr) && dScopeID) { SQL_ID dParent = 0; LPWSTR lpScopeKey = GetKeyString(lpScope); CDeleteMe <wchar_t> r1 (lpScopeKey); if (FAILED(GetSchemaCache()->GetNamespaceID(lpScopeKey, dParent))) { if (pProps) { DWORD dwTempHandle = ((CWmiDbHandle *)pScope)->m_dwHandleType; ((CWmiDbHandle *)pScope)->m_dwHandleType |= WMIDB_HANDLE_TYPE_STRONG_CACHE;
IWbemClassObject *pObj = NULL; hr = ((CWmiDbHandle *)pScope)->QueryInterface_Internal(pConn, (void **)&pObj); CReleaseMe r (pObj); ((CWmiDbHandle *)pScope)->m_dwHandleType = dwTempHandle; if (SUCCEEDED(hr)) { if (pProps->lpNamespace && wcslen(pProps->lpNamespace)) GetSchemaCache()->GetNamespaceID(pProps->lpNamespace, dParent); hr = GetSchemaCache()->AddNamespace(lpScope, lpScopeKey, dScopeID, dParent, ((CWmiDbHandle *)pScope)->m_dClassId); CSQLExecProcedure::InsertScopeMap(pConn, dScopeID, lpScopeKey, dParent); } } else if (lpScope && wcslen(lpScope)) { delete lpScope; return WBEM_E_INVALID_OPERATION; } } } }
if (SUCCEEDED(hr) && !dScopeID) hr = WBEM_E_INVALID_OBJECT; } else if (lpScopePath != NULL) { lpScope = new wchar_t [wcslen(lpScopePath) + 1]; if (!lpScope) return WBEM_E_OUT_OF_MEMORY; wcscpy(lpScope, lpScopePath); }
CDeleteMe <wchar_t> r (lpScope);
// Validate that this object has permission to
// write this object, and the handle is not out of date.
// =====================================================
if (SUCCEEDED(hr)) { hr = pObjToPut->QueryInterface(IID_IWmiDbHandle, (void **)&pHandle); CReleaseMe rHandle (pHandle); if (SUCCEEDED(hr)) { CWmiDbHandle *pTemp = (CWmiDbHandle *)pHandle; dObjectId = pTemp->m_dObjectId;
// If they took out a protected lock,
// they can't modify it either.
// =================================
if (pTemp->m_dwHandleType == WMIDB_HANDLE_TYPE_PROTECTED) hr = WBEM_E_ACCESS_DENIED; else { hr = VerifyObjectLock(dObjectId, pTemp->m_dwHandleType, pTemp->m_dwVersion); if (SUCCEEDED(hr)) { bLockVerified = true; } } } else { dObjectId = 0; bLockVerified = 0; hr = 0; }
if (SUCCEEDED(hr)) { // Get the IWbemClassobject interface. If none, fail.
IWbemClassObject *pObj = NULL; bool bClass = false;
hr = pObjToPut->QueryInterface(IID_IWbemClassObject, (void **)&pObj); CReleaseMe r2 (pObj); if (SUCCEEDED(hr)) { VARIANT vTemp; VariantInit(&vTemp); CClearMe c (&vTemp); CWbemClassObjectProps objprops (this, pConn, pObj, &((CWmiDbController *)m_pController)->SchemaCache, dScopeID); if (!objprops.lpClassName) { hr = WBEM_E_INVALID_OBJECT; goto Exit; } BOOL bNs = FALSE;
if (IsDerivedFrom(pObj, L"__Instances")) { hr = WBEM_E_INVALID_OPERATION; } else { if (objprops.dwGenus == 1 || bStoreAsClass) bClass = true;
if (pScope) { SQL_ID dId = ((CWmiDbHandle *)pScope)->m_dClassId; if (objprops.lpClassName && wcslen(objprops.lpClassName) >=2) { if (objprops.lpClassName[0] == L'_' && objprops.lpClassName[1] == L'_') { bStoreDefault = TRUE;
if (objprops.dwGenus == 1) { dScopeID = 0; lpScope = NULL; } } else if (dId == MAPPEDNSCLASSID) bStoreDefault = FALSE; } } if (objprops.dwGenus == 2 && IsDerivedFrom(pObj, L"__Namespace")) { delete objprops.lpRelPath; objprops.lpRelPath = GetPropertyVal(L"Name", pObj); if (!objprops.lpRelPath) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } bNs = TRUE; }
if (lpScope && dScopeID != ROOTNAMESPACEID) { if (!wcslen(lpScope)) { ERRORTRACE((LOG_WBEMCORE, "Invalid scope text in CWmiDbSession::PutObject (%I64d) \n", dScopeID)); hr = WBEM_E_INVALID_PARAMETER; goto Exit; } LPWSTR lpPath = NULL, lpPtr = NULL; int iLen = wcslen(lpScope);
if (objprops.lpRelPath) { if (_wcsnicmp(objprops.lpRelPath, lpScope, iLen) || ((wcslen(objprops.lpRelPath) > iLen) && objprops.lpRelPath[iLen] != L'\\')) { lpPtr = new wchar_t [wcslen(objprops.lpRelPath) + wcslen(lpScope) + 10]; if (!lpPtr) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } lpPath = lpPtr; if (!bNs) swprintf(lpPath, L"%s:%s", lpScope, objprops.lpRelPath); else swprintf(lpPath, L"%s\\%s", lpScope, objprops.lpRelPath); if (!_wcsnicmp(lpPath, L"root", wcslen(L"root"))) lpPtr += wcslen(L"root")+1; sPath = lpPtr; } else sPath += objprops.lpRelPath; } CDeleteMe <wchar_t> r4 (lpPath);
} else { if (objprops.lpRelPath) { sPath += objprops.lpRelPath; } } }
if (wcslen(objprops.lpClassName) > REPDRVR_NAME_LIMIT) hr = WBEM_E_CLASS_NAME_TOO_WIDE; else objprops.lpKeyString = GetKeyString(sPath);
if (dScopeID) { //hr = VerifyObjectSecurity(pConn, dObjectId, dClassId, dScopeID, 0, dwRequired);
if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) hr = VerifyObjectSecurity(pConn, dScopeID, 0, sPath, &objprops, dwRequestedHandleType, WBEM_PARTIAL_WRITE_REP, dObjectId, dClassId); else hr = VerifyObjectSecurity(pConn, dScopeID, 0, sPath, &objprops, dwRequestedHandleType, 0, dObjectId, dClassId); }
if (SUCCEEDED(hr)) { bool bChanged = false; bool bNew = false;
if (bClass) { SQL_ID dTemp = 0; if (FAILED(GetSchemaCache()->GetClassID(objprops.lpClassName, dScopeID, dTemp))) bNew = true;
BOOL bIgnoreDefaults = (bStoreAsClass ? TRUE: FALSE); hr = PutClass(pConn, dScopeID, lpScope, &objprops, pObj, dwFlags, dObjectId, sPath, bChanged, bIgnoreDefaults); dClassId = 1;
// After we have put the class, *then*
// we see if we need to set it up in the
// custom database.
if (!bStoreDefault && SUCCEEDED(hr)) { // Update the mapping for this class.
hr = CustomCreateMapping(pConn, objprops.lpClassName, pObj, pScope); } } else if (dClassId) { // If this is a custom repository,
// forward this request to the custom rep code.
if (bStoreDefault) { hr = PutInstance(pConn, pScope, dScopeID, lpScope, &objprops, pObj, dwFlags, dObjectId, dClassId, sPath, bChanged); } else { hr = CustomPutInstance(pConn, pScope, dClassId, dwFlags, &pObj); pOutObj = pObj; } } else hr = WBEM_E_INVALID_CLASS;
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) { // Render return handle as needed.
if (ppResult) { if (pHandle) { pHandle->AddRef(); *ppResult = pHandle;
// Bump up version number, so other outstanding handles
// know this object changed.
hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjectId, WMIDB_HANDLE_TYPE_VERSIONED, NULL, dScopeID, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, true, 0, 0);
if (SUCCEEDED(hr)) hr = ((CWmiDbController *)m_pController)->LockCache.DeleteLock(dObjectId, false, WMIDB_HANDLE_TYPE_VERSIONED, true, NULL); } else { DWORD dwVersion = 0; CWmiDbHandle *pTemp = new CWmiDbHandle; if (!pTemp) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; }
pTemp->m_pSession = this;
hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjectId, dwRequestedHandleType, pTemp, dScopeID, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, true, 0, 0, &dwVersion);
if (SUCCEEDED(hr)) { AddRef_Lock(); ((CWmiDbController *)m_pController)->AddHandle(); pTemp->m_dObjectId = dObjectId; pTemp->m_dClassId = dClassId;
pTemp->m_bDefault = TRUE; pTemp->m_dScopeId = dScopeID; pTemp->m_pSession = this; pTemp->m_pData = pOutObj; if (pOutObj) pOutObj->AddRef(); pTemp->AddRef(); pTemp->m_dwVersion = dwVersion; pTemp->m_dwHandleType = dwRequestedHandleType; if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR) pTemp->m_bSecDesc = TRUE;
*ppResult = pTemp; } else { *ppResult = NULL; delete pTemp; } }
} else { // Bump up version number, so other outstanding handles
// know this object changed.
hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(bImmediate, dObjectId, WMIDB_HANDLE_TYPE_VERSIONED, NULL, dScopeID, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, true, 0, 0);
((CWmiDbController *)m_pController)->LockCache.DeleteLock(dObjectId, false, WMIDB_HANDLE_TYPE_VERSIONED, true, NULL); }
// Add an exclusive lock on this object...
// If cannot lock, check locally and see if we have one.
if (IsDistributed()) { hr = ((CWmiDbController *)m_pController)->LockCache.AddLock(false, dObjectId, WMIDB_HANDLE_TYPE_EXCLUSIVE, NULL, dScopeID, dClassId, &((CWmiDbController *)m_pController)->SchemaCache, true, 0, 0); if (FAILED(hr)) { if (LockExists(dObjectId)) hr = WBEM_S_NO_ERROR; } if (SUCCEEDED(hr)) { hr = AddTransLock(dObjectId, WMIDB_HANDLE_TYPE_EXCLUSIVE); } }
// Update the object in the cache if necessary
// Either they want it cached now, or the
// object already exists in the cache.
// ===========================================
if (SUCCEEDED(hr)) { if (GetObjectCache()->ObjectExists(dObjectId) || (dwRequestedHandleType & 0xF00) == WMIDB_HANDLE_TYPE_WEAK_CACHE || (dwRequestedHandleType & 0xF00) == WMIDB_HANDLE_TYPE_STRONG_CACHE) { bool bCacheType = ((dwRequestedHandleType & 0xF00) == WMIDB_HANDLE_TYPE_STRONG_CACHE) ? 1 : 0; LPWSTR lpKey = GetKeyString(sPath); CDeleteMe <wchar_t> r6(lpKey);
GetObjectCache()->PutObject(dObjectId, dClassId, dScopeID, lpKey, bCacheType, pObj); } // Regardless, if we have updated a class,
// we need to remove the instances
// and subclasses from the cache.
// ================================
if (bClass && !bNew) { SQL_ID dObjId = 0, dClassId = 0;
HRESULT hTemp = GetObjectCache()->FindFirst(dObjId, dClassId); while (SUCCEEDED(hTemp)) { if (dClassId == 1) dClassId = dObjId;
if (GetSchemaCache()->IsDerivedClass(dObjectId, dClassId)) GetObjectCache()->DeleteObject(dObjId);
hTemp = GetObjectCache()->FindNext(dObjId, dObjId, dClassId); } } } } } } } } }
if (SUCCEEDED(hr) && (dwFlags & WBEM_FLAG_REMOVE_CHILD_SECURITY)) { // Is this a recursive put (WBEM_FLAG_REMOVE_CHILD_SECURITY)? We need to recursively erase all security on all child objects.
// * Enumerate all dependent objects that have SDs.
// * Call PutObject on each *with* the Use_SD flag, but without the remove_child_security
// flag
SQLIDs ObjIds, ClassIds, ScopeIds; hr = CSQLExecProcedure::EnumerateSecuredChildren(pConn, &((CWmiDbController *)m_pController)->SchemaCache, dObjectId, dClassId, dScopeID, ObjIds, ClassIds, ScopeIds); if (SUCCEEDED(hr)) { for (int i = 0; i < ObjIds.size(); i++) { // Get the old object.
// Strip off the __SECURITY_DESCRIPTOR property
// Put it again.
SQL_ID dObjectId = ObjIds.at(i), dClassId = ClassIds.at(i), dScopeId = ScopeIds.at(i);
_bstr_t sScopeKey; hr = GetSchemaCache()->GetNamespaceName(dScopeId, NULL, &sScopeKey);
DWORD dwTemp; IWbemClassObject *pObj = NULL;
hr = GetObjectData(pConn, dObjectId, dClassId, dScopeId, 0, dwTemp, &pObj, FALSE, NULL); CReleaseMe r (pObj); if (SUCCEEDED(hr)) { hr = pObj->Put(L"__SECURITY_DESCRIPTOR", 0, NULL, CIM_FLAG_ARRAY|CIM_UINT8); if (SUCCEEDED(hr)) { _bstr_t sPath; hr = PutObject(pConn, NULL, dScopeId, sScopeKey, pObj, WBEM_FLAG_USE_SECURITY_DESCRIPTOR, 0, sPath, NULL, FALSE); } } } } else if (hr == E_NOTIMPL) hr = WBEM_S_NO_ERROR; }
Exit:
return hr; }
//***************************************************************************
//
// CWmiDbSession::UpdateHierarchy
//
//***************************************************************************
HRESULT CWmiDbSession::UpdateHierarchy(CSQLConnection *pConn, SQL_ID dClassId, DWORD dwFlags, LPCWSTR lpScopePath, CWbemClassObjectProps *pProps, _IWmiObject *pObj) {
HRESULT hr = WBEM_S_NO_ERROR;
// Enumerate subclasses (from the cache),
// forcibly update them, and add to ESS cache
int iNumDerived = 0; SQL_ID *pIDs = NULL;
hr = GetSchemaCache()->GetDerivedClassList(dClassId, &pIDs, iNumDerived, TRUE); if (SUCCEEDED(hr)) { CDeleteMe <SQL_ID> d3 (pIDs);
// If there are instances, fail now.
BOOL bInstances = FALSE; hr = CSQLExecProcedure::HasInstances(pConn, dClassId, pIDs, iNumDerived, bInstances); if (bInstances) return WBEM_E_CLASS_HAS_INSTANCES; for (int i = 0; i < iNumDerived; i++) { IWbemClassObject *pSubClass = NULL; hr = GetClassObject(pConn, pIDs[i], &pSubClass); CReleaseMe r2 (pSubClass); if (SUCCEEDED(hr)) { _IWmiObject *pNew = NULL; hr = ((_IWmiObject *)pObj)->Update(((_IWmiObject *)pSubClass), WBEM_FLAG_UPDATE_FORCE_MODE, &pNew); if (SUCCEEDED(hr)) { if(!(dwFlags & WMIDB_DISABLE_EVENTS)) { ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID, (LPWSTR)lpScopePath, pProps->lpClassName, pProps->dwGenus, pSubClass, pNew); }
hr = UpdateHierarchy(pConn, pIDs[i], dwFlags, lpScopePath, pProps, pNew); if (FAILED(hr)) break;
// Update the subclass object in the repository.
// Can only be done after all children have been updated.
hr = CSQLExecProcedure::UpdateClassBlob(pConn, pIDs[i], pNew); if (FAILED(hr)) break; } else break; } } } return hr; }
//***************************************************************************
//
// CWmiDbSession::PutClass
//
//***************************************************************************
HRESULT CWmiDbSession::PutClass( CSQLConnection *pConn, /* [in] */ SQL_ID dScopeID, /* [in] */ LPCWSTR lpScopePath, CWbemClassObjectProps *pProps, /* [in] */ IWbemClassObject *pObj, DWORD dwFlags, /* [in/out] */ SQL_ID &dObjectId, /* [out] */ _bstr_t &sObjectPath, bool &bChg, BOOL bIgnoreDefaults) { HRESULT hr = WBEM_S_NO_ERROR; SQL_ID dTempScopeID = 0; bool bNewObj = (dObjectId == 0) ? 1 : 0; SQL_ID dSuperClassId = 1; SQL_ID dDynasty = 0; wchar_t wSuperClass[450];
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR) return WBEM_E_INVALID_PARAMETER;
// See if anything changed.
if (dObjectId) { IWbemClassObject *pOldObj = NULL; DWORD dwTemp; hr = GetObjectData(pConn, dObjectId, 1, dScopeID, 0, dwTemp, &pOldObj, FALSE, NULL); CReleaseMe r (pOldObj);
if (SUCCEEDED(hr) && !(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) { DWORD dwRequired = 0; if (pProps->lpClassName[0] == L'_') dwRequired = WBEM_FULL_WRITE_REP; else dwRequired = WBEM_PARTIAL_WRITE_REP;
hr = VerifyObjectSecurity(pConn, dObjectId, 1, dScopeID, 0, dwRequired); if (FAILED(hr)) { return hr; } }
if (SUCCEEDED(hr)) { // Backward compatibility: always log an event,
// even though nothing has changed.
if(!(dwFlags & WMIDB_DISABLE_EVENTS)) { ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID, (LPWSTR)lpScopePath, pProps->lpClassName, pProps->dwGenus, pOldObj, pObj); }
hr = pOldObj->CompareTo(0, pObj); if (WBEM_S_NO_ERROR == hr) return WBEM_S_NO_ERROR; // Nothing changed. Don't bother updating.
else { // Did this impact subclasses? If so,
// enumerate and add ESS records.
BOOL bImmediate = FALSE;
hr = ((_IWmiObject *)pOldObj)->ReconcileWith(WMIOBJECT_RECONCILE_FLAG_TESTRECONCILE, (_IWmiObject *)pObj); if (hr != WBEM_S_NO_ERROR) { hr = UpdateHierarchy(pConn, dObjectId, dwFlags, lpScopePath, pProps, (_IWmiObject *)pObj);
}
} } else hr = WBEM_S_NO_ERROR; } else { if(!(dwFlags & WMIDB_DISABLE_EVENTS)) { ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID, (LPWSTR)lpScopePath, pProps->lpClassName, pProps->dwGenus, NULL, pObj); } }
bChg = true;
// Generate the object path.
if (!wcslen(pProps->lpRelPath) || !wcslen(pProps->lpClassName)) return WBEM_E_INVALID_OBJECT; if (pProps->lpSuperClass && wcslen(pProps->lpSuperClass)) { if (FAILED(GetSchemaCache()->GetClassID (pProps->lpSuperClass, dScopeID, dSuperClassId))) return WBEM_E_INVALID_CLASS;
if (lpScopePath != NULL && wcslen(lpScopePath)) swprintf(wSuperClass, L"%s:%s", lpScopePath, pProps->lpSuperClass); else wcscpy(wSuperClass, pProps->lpSuperClass); } else wSuperClass[0] = L'\0';
(GetSchemaCache()->GetClassID (pProps->lpDynasty, dScopeID, dDynasty));
if (SUCCEEDED(hr)) { IRowset *pIRowset = NULL; DWORD dwRows = 0;
DWORD dwClassFlags = 0; IWbemQualifierSet *pQS = NULL;
hr = pObj->GetQualifierSet(&pQS); if (SUCCEEDED(hr)) { CReleaseMe r (pQS); dwClassFlags = GetQualifierFlag(L"Abstract", pQS) ? REPDRVR_FLAG_ABSTRACT : 0; dwClassFlags |= GetQualifierFlag(L"Singleton", pQS) ? REPDRVR_FLAG_SINGLETON : 0; dwClassFlags |= GetQualifierFlag(L"Unkeyed", pQS) ? REPDRVR_FLAG_UNKEYED : 0; dwClassFlags |= GetQualifierFlag(L"HasClassRefs", pQS) ? REPDRVR_FLAG_CLASSREFS : 0; BOOL bExists = FALSE;
// If exists, only update the class if super class or flags changed
// (They can't change the name or scope without changing the
// path, right?)
_bstr_t sName; SQL_ID dSuperClass = 1;
if (SUCCEEDED(GetSchemaCache()->GetClassInfo (dObjectId, sName, dSuperClass, dTempScopeID, dwFlags))) bExists = TRUE;
LPWSTR lpObjKey, lpParentKey; lpObjKey = pProps->lpKeyString; lpParentKey = GetKeyString(wSuperClass); CDeleteMe <wchar_t> r2(lpParentKey);
if (!lpObjKey || !wcslen(lpObjKey)) { ERRORTRACE((LOG_WBEMCORE, "Invalid object path in CWmiDbSession::PutClass (%S) \n", sObjectPath)); hr = WBEM_E_INVALID_PARAMETER; } else { // Insert the data.
// Ensure that we don't end up reporting to ourself.
// Enumerate the __Derivation property of the IWbemClassObject,
// and see if the class is in its own ancestry.
if (IsDerivedFrom(pObj, pProps->lpClassName, TRUE)) hr = WBEM_E_CIRCULAR_REFERENCE; if (SUCCEEDED(hr)) { _IWmiObject *pInt = NULL; hr = pObj->QueryInterface(IID__IWmiObject, (void **)&pInt); CReleaseMe r (pInt); if (SUCCEEDED(hr)) { BYTE *pBuff; BYTE buff[128]; DWORD dwLen = 0;
pInt->Unmerge(0, 128, &dwLen, &buff);
if (dwLen > 0) { pBuff = new BYTE [dwLen]; if (pBuff) { DWORD dwLen1; hr = pInt->Unmerge(0, dwLen, &dwLen1, pBuff); if (SUCCEEDED(hr)) { hr = CSQLExecProcedure::InsertClass(pConn, pProps->lpClassName, lpObjKey, sObjectPath, dScopeID, dSuperClassId, dDynasty, 0, pBuff, dwLen1, dwClassFlags, dwFlags, dObjectId);
if (SUCCEEDED(hr)) { if (!dDynasty) dDynasty = dObjectId; hr = GetSchemaCache()->AddClassInfo(dObjectId, pProps->lpClassName, dSuperClassId, dDynasty, dScopeID, lpObjKey, dwClassFlags); } } delete pBuff; } else hr = WBEM_E_OUT_OF_MEMORY; } } } }
if (SUCCEEDED(hr)) { // Get a map of this classes' property IDs
// Qualifiers won't be present, but that's OK now.
// ==============================================
Properties props;
if (!bNewObj) hr = GetSchemaCache()->GetPropertyList(dObjectId, props);
// Iterate through all properties, qualifiers, methods.
// Only update ones that changed and update cache.
// Check off/Add ID as we encounter them.
// ====================================================
BSTR strName; VARIANT vTemp; CIMTYPE cimtype; long lPropFlavor = 0; IWbemQualifierSet *pQS = NULL;
// Properties
//((_IWmiObject *)pObj)->BeginEnumerationEx(WBEM_FLAG_CLASS_LOCAL_AND_OVERRIDES, WMIOBJECT_BEGINENUMEX_FLAG_GETEXTPROPS);
pObj->BeginEnumeration(WBEM_FLAG_CLASS_LOCAL_AND_OVERRIDES); while (pObj->Next(0, &strName, &vTemp, &cimtype, &lPropFlavor) == S_OK) { CFreeMe f1 (strName); pObj->GetPropertyQualifierSet(strName, &pQS); if (pQS) { CReleaseMe r (pQS); lPropFlavor = (REPDRVR_FLAG_CLASSREFS & dwClassFlags); lPropFlavor |= (GetQualifierFlag(L"key", pQS)) ? REPDRVR_FLAG_KEY : 0; lPropFlavor |= (GetQualifierFlag(L"indexed", pQS)) ? REPDRVR_FLAG_INDEXED : 0; lPropFlavor |= (GetQualifierFlag(L"keyhole", pQS)) ? REPDRVR_FLAG_KEYHOLE : 0; lPropFlavor |= (GetQualifierFlag(L"not_null", pQS)) ? REPDRVR_FLAG_NOT_NULL : 0; }
if (bIgnoreDefaults) VariantClear(&vTemp);
hr = InsertPropertyDef(pConn, pObj, dScopeID, dObjectId, strName, vTemp, cimtype, lPropFlavor, 0,props);
VariantClear(&vTemp); if (FAILED(hr)) break; }
// No need to insert qualifiers or methods.
// We are only creating schema so it can
// be queried when we get instances.
// Delete any properties, methods that
// were not found, remove from cache.
// Qualifiers can simply be deleted,
// since they aren't cached.
// ===================================
if (SUCCEEDED(hr) && !bNewObj) { _bstr_t sSQL; bool bInit = false;
Properties::iterator item = props.begin(); while (item != props.end()) { DWORD dwID = (*item).first;
if (!GetSchemaCache()->IsQualifier(dwID)) { if (!(*item).second) { SQL_ID dClass = 0;
hr = GetSchemaCache()->GetPropertyInfo (dwID, NULL, &dClass); if (dClass == dObjectId) { CSQLExecProcedure::DeleteProperty(pConn, dwID); GetSchemaCache()->DeleteProperty(dwID, dClass); } hr = WBEM_S_NO_ERROR; } } item++; } } else if (FAILED(hr) && bNewObj) { hr = GetSchemaCache()->DeleteClass(dObjectId); } } } }
return hr; }
//***************************************************************************
//
// CWmiDbSession::InsertPropertyDef
//
//***************************************************************************
HRESULT CWmiDbSession::InsertPropertyDef(CSQLConnection *pConn, IWbemClassObject *pObj, SQL_ID dScopeId, SQL_ID dObjectId, LPWSTR lpPropName, VARIANT vDefault, CIMTYPE cimtype, long dwFlags, DWORD dRefId, Properties &props) { HRESULT hr = WBEM_S_NO_ERROR; bool bArray = false;
if (cimtype & CIM_FLAG_ARRAY) bArray = true;
dwFlags |= (bArray) ? REPDRVR_FLAG_ARRAY : 0; cimtype &= ~CIM_FLAG_ARRAY;
// If this is an embedded object or reference,
// set the class ID of the embedded object, if any.
SQL_ID dRefClassId = 0; if (cimtype == CIM_REFERENCE || cimtype == CIM_OBJECT) { IWbemQualifierSet *pQS = NULL; hr = pObj->GetPropertyQualifierSet(lpPropName, &pQS); if (SUCCEEDED(hr)) { VARIANT vValue; VariantInit(&vValue); CReleaseMe r (pQS); CClearMe c (&vValue);
hr = pQS->Get(L"CIMTYPE", 0, &vValue, NULL);
// Since previously, wbem did not do any type checking of references
// or embedded objects, we generate the IDs for the classes if
// they aren't already present. This will still fail for instances.
if (!_wcsnicmp(vValue.bstrVal, L"ref", 3) && wcslen(vValue.bstrVal) > 3) { LPWSTR lpPtr = (LPWSTR)vValue.bstrVal; lpPtr += 4; hr = GetSchemaCache()->GetClassID(lpPtr, dScopeId, dRefClassId); if (hr == WBEM_E_NOT_FOUND) { _bstr_t sScopeKey; hr = GetSchemaCache()->GetNamespaceName(dScopeId, NULL, &sScopeKey); if (SUCCEEDED(hr)) { _bstr_t sNewName = lpPtr; sNewName += L"?"; sNewName += sScopeKey; dRefClassId = CRC64::GenerateHashValue(sNewName); hr = WBEM_S_NO_ERROR; } } } else if (!_wcsnicmp(vValue.bstrVal, L"object", 6) && wcslen(vValue.bstrVal) > 6) { LPWSTR lpPtr = (LPWSTR)vValue.bstrVal; lpPtr += 7; hr = GetSchemaCache()->GetClassID(lpPtr, dScopeId, dRefClassId); if (hr == WBEM_E_NOT_FOUND) { _bstr_t sScopeKey; hr = GetSchemaCache()->GetNamespaceName(dScopeId, NULL, &sScopeKey); if (SUCCEEDED(hr)) { _bstr_t sNewName = lpPtr; sNewName += L"?"; sNewName += sScopeKey; dRefClassId = CRC64::GenerateHashValue(sNewName); hr = WBEM_S_NO_ERROR; } } } } }
// We can't verify that a property changed, since we currently aren't
// caching the defaults, so will insert regardless.
DWORD dwPropertyID = 0;
if (wcslen(lpPropName) > REPDRVR_NAME_LIMIT) { hr = WBEM_E_PROPERTY_NAME_TOO_WIDE; } else { BOOL bChg = TRUE; SQL_ID dOrigClass = 0;
if ((GetSchemaCache()->GetPropertyID (lpPropName, dObjectId, dwFlags, cimtype, dwPropertyID, &dOrigClass)) == WBEM_S_NO_ERROR) { } else if (!(dwFlags & (REPDRVR_FLAG_NONPROP &~ REPDRVR_FLAG_METHOD))) { // Does this property exist on the derived class already?
if (SUCCEEDED(hr)) { hr = GetSchemaCache()->FindProperty(dObjectId, lpPropName, dwFlags, cimtype); } }
if (SUCCEEDED(hr)) { BOOL bIsKey = FALSE; if (bChg) { LPWSTR lpVal = GetStr(vDefault); CDeleteMe <wchar_t> r(lpVal); hr = CSQLExecProcedure::InsertClassData(pConn, pObj, &((CWmiDbController *)m_pController)->SchemaCache, dScopeId, dObjectId, lpPropName, cimtype, GetStorageType(cimtype, bArray), lpVal, dRefClassId, dRefId, dwFlags, 0, 0, dwPropertyID, dOrigClass, &bIsKey); }
if (SUCCEEDED(hr)) { hr = GetSchemaCache()->AddPropertyInfo (dwPropertyID, lpPropName, dObjectId, GetStorageType(cimtype, bArray), cimtype, dwFlags, 0, L"", dRefId, 0); // don't cache the default!
if (bIsKey) GetSchemaCache()->SetIsKey(dObjectId, dwPropertyID);
props[dwPropertyID] = 1; } } }
return hr; }
//***************************************************************************
//
// CWmiDbSession::InsertQualifiers
//
//***************************************************************************
HRESULT CWmiDbSession::InsertQualifiers (CSQLConnection *pConn, IWmiDbHandle *pScope, SQL_ID dObjectId, DWORD PropID, DWORD Flags, IWbemQualifierSet *pQS, Properties &props) { HRESULT hr = WBEM_S_NO_ERROR;
BSTR strName; VARIANT vTemp; VariantInit(&vTemp); long lPropFlavor = 0;
pQS->BeginEnumeration(0); while (pQS->Next(0, &strName, &vTemp, &lPropFlavor) == S_OK) { CFreeMe f (strName); lPropFlavor = lPropFlavor&~WBEM_FLAVOR_ORIGIN_PROPAGATED&~WBEM_FLAVOR_ORIGIN_SYSTEM&~WBEM_FLAVOR_AMENDED;
hr = InsertQualifier(pConn, pScope, dObjectId, strName, vTemp, lPropFlavor, Flags & REPDRVR_FLAG_QUALIFIER, PropID, props);
VariantClear(&vTemp); if (FAILED(hr)) break; } pQS->EndEnumeration();
return hr; }
//***************************************************************************
//
// CWmiDbSession::InsertQualifier
//
//***************************************************************************
HRESULT CWmiDbSession::InsertQualifier( CSQLConnection *pConn,IWmiDbHandle *pScope, SQL_ID dObjectId, LPWSTR lpQualifierName, VARIANT vValue, long lQfrFlags, DWORD dwFlags, DWORD PropID, Properties &props) { HRESULT hr = WBEM_S_NO_ERROR; dwFlags |= REPDRVR_FLAG_QUALIFIER;
// This will only insert the qualifier definition
// and the initial data.
// Insert the qualifier, unless its one of the
// system quartet: key, indexed, keyhole, not_null
// ==================================================
if (!_wcsicmp(lpQualifierName, L"abstract")) return WBEM_S_NO_ERROR;
if (!_wcsicmp(lpQualifierName, L"cimtype")) { if ((wcslen(vValue.bstrVal) > 3 && !_wcsnicmp(vValue.bstrVal, L"ref", 3)) || (wcslen(vValue.bstrVal) > 6 && !_wcsnicmp(vValue.bstrVal, L"object", 6))) { } else return WBEM_S_NO_ERROR; // CIMTypes are generated automatically.
}
bool bArray = false; CIMTYPE ct;
switch((vValue.vt &~ CIM_FLAG_ARRAY)) { case VT_R4: case VT_R8: ct = CIM_REAL64; break; case VT_BSTR: ct = CIM_STRING; break; case VT_BOOL: ct = CIM_BOOLEAN; break; default: ct = CIM_UINT32; break; }
if (vValue.vt & VT_ARRAY) bArray = true;
dwFlags |= (bArray) ? REPDRVR_FLAG_ARRAY : 0;
DWORD dwPropertyID = 0;
if (wcslen(lpQualifierName) > REPDRVR_NAME_LIMIT) { hr = WBEM_E_QUALIFIER_NAME_TOO_WIDE; } else { if (SUCCEEDED(hr)) { LPWSTR lpVal = GetStr(vValue); CDeleteMe <wchar_t> r(lpVal);
try {
GetSchemaCache()->GetPropertyID (lpQualifierName, 1, dwFlags, ct, dwPropertyID); hr = CSQLExecProcedure::InsertClassData(pConn, NULL, &((CWmiDbController *)m_pController)->SchemaCache, 0, 1, lpQualifierName, ct, GetStorageType(ct, bArray), lpVal,0, PropID, dwFlags, lQfrFlags, 0, dwPropertyID);
if (SUCCEEDED(hr)) { hr = GetSchemaCache()->AddPropertyInfo (dwPropertyID, lpQualifierName, 1, GetStorageType(ct, bArray), ct, dwFlags, 0, L"", PropID, lQfrFlags); // don't cache the default!
// Add any array defaults.
// =======================
if (vValue.vt & VT_ARRAY) hr = InsertArray(pConn, pScope, dObjectId, 1, dwPropertyID, vValue, lQfrFlags, PropID); } } catch (...) { hr = WBEM_E_CRITICAL_ERROR; } } } return hr; }
//***************************************************************************
//
// CWmiDbSession::PutInstance
//
//***************************************************************************
HRESULT CWmiDbSession::PutInstance( CSQLConnection *pConn, IWmiDbHandle *pScope, /* [in] */ SQL_ID dScopeID, /* [in] */ LPCWSTR lpScopePath, CWbemClassObjectProps *pProps, /* [in] */ IWbemClassObject *pObj, DWORD dwFlags, /* [in/out] */ SQL_ID &dObjectId, /* [out] */ SQL_ID &dClassId, /* [out] */ _bstr_t &sObjectPath, bool &bChg) { HRESULT hr = WBEM_S_NO_ERROR;
bool bUpdate = (dObjectId == 0) ? false : true;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
SQL_ID dTestId = dObjectId; if (!dTestId) { if (pProps->lpKeyString) dTestId = CRC64::GenerateHashValue(pProps->lpKeyString); }
BOOL bGetSD = FALSE; if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR) bGetSD = TRUE;
IWbemClassObject *pOldObj = NULL; DWORD dwTemp; hr = GetObjectData(pConn, dTestId, dClassId, dScopeID, 0, dwTemp, &pOldObj, FALSE, NULL, bGetSD); CReleaseMe r (pOldObj); if (SUCCEEDED(hr)) { if (SUCCEEDED(hr) && !(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) { DWORD dwRequired = 0; if (dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR) dwRequired = WRITE_DAC; else { if (pProps->lpClassName[0] == L'_') dwRequired = WBEM_FULL_WRITE_REP; else dwRequired = WBEM_PARTIAL_WRITE_REP; }
hr = VerifyObjectSecurity(pConn, dTestId, dClassId, dScopeID, 0, dwRequired); if (FAILED(hr)) { return hr; } }
if(!(dwFlags & WMIDB_DISABLE_EVENTS)) { LPWSTR lpClass = pProps->lpClassName; BOOL bRelease = FALSE;
if (IsDerivedFrom(pObj, L"__Namespace")) { lpClass = GetPropertyVal(L"Name", pObj); bRelease = TRUE; }
((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID, (LPWSTR)lpScopePath, lpClass, pProps->dwGenus, pOldObj, pObj);
if (bRelease) delete lpClass; }
hr = pOldObj->CompareTo(0, pObj); if (WBEM_S_NO_ERROR == hr) return WBEM_S_NO_ERROR; // Nothing changed. Don't bother updating.
} else { hr = WBEM_S_NO_ERROR; if(!(dwFlags & WMIDB_DISABLE_EVENTS)) { ((CWmiDbController *)m_pController)->ESSMgr.AddInsertRecord(pConn, m_sGUID, (LPWSTR)lpScopePath, pProps->lpClassName, pProps->dwGenus, NULL, pObj); } }
bChg = true;
if (SUCCEEDED(hr)) { IRowset *pIRowset = NULL; DWORD dwNumRows = 0;
// Generate unkeyed or keyhole path if none (and if class is one of the two)
if (!bUpdate ) { bool bUnkeyed = false; _bstr_t sName; SQL_ID dTemp1, dTemp2; DWORD dwFlags = 0; hr = GetSchemaCache()->GetClassInfo (dClassId, sName, dTemp1, dTemp2, dwFlags); if (SUCCEEDED(hr) && (dwFlags & REPDRVR_FLAG_UNKEYED)) { bUnkeyed = true; hr = CSQLExecProcedure::GetNextUnkeyedPath(pConn, dClassId, sObjectPath); } // Cannot add instances to an abstract class.
if (dwFlags & REPDRVR_FLAG_ABSTRACT) return WBEM_E_INVALID_OPERATION;
DWORD dwKeyholePropID = 0; _bstr_t sKeyholeProp;
if (SUCCEEDED(hr) && SUCCEEDED(GetSchemaCache()->GetKeyholeProperty(dClassId, dwKeyholePropID, sKeyholeProp))) { hr = SetKeyhole(pConn, pObj, dwKeyholePropID, sKeyholeProp, lpScopePath, sObjectPath); delete pProps->lpRelPath; pProps->lpRelPath = GetPropertyVal(L"__RelPath", pObj); }
if (!bUnkeyed && !pProps->lpRelPath) hr = WBEM_E_INVALID_OBJECT; // path cannot be blank at this point.
}
if (SUCCEEDED(hr)) // we have a valid path.
hr = InsertPropertyValues(pConn, pScope, sObjectPath, dObjectId, dClassId, dScopeID, dwFlags, pProps, pObj); }
return hr;
}
//***************************************************************************
//
// CWmiDbSession::SetKeyhole
//
//***************************************************************************
HRESULT CWmiDbSession::SetKeyhole (CSQLConnection *pConn, IWbemClassObject *pObj, DWORD dwKeyholePropID, LPWSTR sKeyholeProp, LPCWSTR lpScopePath, _bstr_t &sPath) { HRESULT hr = WBEM_S_NO_ERROR;
// See if it is populated.
CIMTYPE ct = 0; long lFlags = 0; VARIANT vTemp; VariantInit(&vTemp); _bstr_t sNewValue; SQL_ID dNextId = 0;
hr = pObj->Get(sKeyholeProp, 0, &vTemp, &ct, &lFlags); LPWSTR lpVal = GetStr(vTemp); CDeleteMe <wchar_t> r(lpVal); VariantClear(&vTemp);
if (!lpVal || !wcslen(lpVal) || !_wcsicmp(lpVal,L"0")) { // Execute stored procedure.
// =========================
hr = CSQLExecProcedure::GetNextKeyhole(pConn, dwKeyholePropID, dNextId); if (SUCCEEDED(hr)) { // If a string property, just
// convert the number to text.
// ==========================
if (ct == CIM_STRING) // We really want a GUID here!!!!
{ wchar_t szTmp[20]; swprintf(szTmp, L"%ld", dNextId); V_BSTR(&vTemp) = szTmp; vTemp.vt = VT_BSTR; } else { V_I4(&vTemp) = dNextId; vTemp.vt = VT_I4; }
// Try to update the key value,
// and get the object path again.
// ==============================
hr = pObj->Put(sKeyholeProp, 0, &vTemp, ct); if (SUCCEEDED(hr)) { hr = pObj->Get(L"__RelPath", 0, &vTemp, NULL, NULL); sPath = vTemp.bstrVal; if (lpScopePath != NULL) { _bstr_t sTemp = sPath; sPath = _bstr_t(lpScopePath) + L":" + sTemp; } } } }
return hr;
}
InsertQfrValues * ReAllocQfrValues (InsertQfrValues *pVals, int iNumVals, int iAdd) { InsertQfrValues * pRet = new InsertQfrValues[iNumVals + iAdd]; if (pRet) { int iSize = sizeof(InsertQfrValues) * iNumVals; /*
for (int i = 0; i < iNumVals; i++) { if (pVals[i].pValue) iSize += wcslen(pVals[i].pValue)+ 1; if (pVals[i].pRefKey) iSize += wcslen(pVals[i].pRefKey) + 1; } */ memcpy(pRet, pVals, iSize); delete pVals; } else delete pVals; return pRet; }
// Strip off local prefixes. Any unresolved path
// not in this format might not be an object stored
// in this database.
LPWSTR StripUnresolvedName (LPWSTR lpPath) { LPWSTR lpRet = new wchar_t [wcslen(lpPath) + 1]; if (lpRet) { if (wcslen(lpPath) > 2) { if (wcsstr(lpPath, L"\\\\.\\root")) lpPath += 9; }
wcscpy(lpRet, lpPath); } return lpRet; }
//***************************************************************************
//
// TestSD
//
//***************************************************************************
HRESULT TestSD(VARIANT * pvTemp) { if(pvTemp->vt != (VT_ARRAY | VT_UI1)) { return WBEM_E_INVALID_PARAMETER; } SAFEARRAY * psa = pvTemp->parray; PSECURITY_DESCRIPTOR pSD; HRESULT hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pSD); if(FAILED(hr)) return WBEM_E_INVALID_PARAMETER; BOOL bRet = IsValidSecurityDescriptor(pSD); if(bRet == FALSE) { SafeArrayUnaccessData(psa); return WBEM_E_INVALID_PARAMETER; }
PSID pSid = 0; BOOL bDefaulted; BOOL bRes = GetSecurityDescriptorOwner(pSD, &pSid, &bDefaulted); if (!bRes || !IsValidSid(pSid)) { SafeArrayUnaccessData(psa); return WBEM_E_INVALID_PARAMETER; }
pSid = 0; bRes = GetSecurityDescriptorGroup(pSD, &pSid, &bDefaulted); if (!bRes || !IsValidSid(pSid)) { SafeArrayUnaccessData(psa); return WBEM_E_INVALID_PARAMETER; }
SafeArrayUnaccessData(psa); return (bRet) ? S_OK : WBEM_E_INVALID_PARAMETER; }
//***************************************************************************
//
// CWmiDbSession::InsertPropertyValues
//
//***************************************************************************
HRESULT CWmiDbSession::InsertPropertyValues (CSQLConnection *pConn, IWmiDbHandle *pScope, LPWSTR lpPath, SQL_ID &dObjectId, SQL_ID dClassId, SQL_ID dScopeId, DWORD dwFlags, CWbemClassObjectProps *pProps, IWbemClassObject *pObj) { HRESULT hr = WBEM_S_NO_ERROR;
BSTR strName; CIMTYPE cimtype; long lPropFlavor = 0; SQL_ID dRefClassId = 0, dRefID = 0; CWStringArray arrObjProps; int iPos = 0, iQfrPos = 0; bool bDone = false; VARIANT vTemp; BOOL bRemoveSD = FALSE; CClearMe c (&vTemp); Properties props; InsertPropValues *pPropValues = NULL; InsertQfrValues *pQVals = NULL;
LPWSTR lpCount = GetPropertyVal(L"__Property_Count", pObj); CDeleteMe <wchar_t> r(lpCount); int iNumProps = 10; if (lpCount) iNumProps += _wtoi(lpCount);
if (iNumProps) { pPropValues = new InsertPropValues[iNumProps]; if (!pPropValues) return WBEM_E_OUT_OF_MEMORY; } if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) { delete pPropValues; return WBEM_E_SHUTTING_DOWN; }
// Insert properties.
// ==================
((_IWmiObject *)pObj)->BeginEnumerationEx(WBEM_FLAG_NONSYSTEM_ONLY, WMIOBJECT_BEGINENUMEX_FLAG_GETEXTPROPS); // ((_IWmiObject *)pObj)->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
while (pObj->Next(0, &strName, &vTemp, &cimtype, &lPropFlavor) == S_OK) { CFreeMe f (strName);
// Ignore security unless they are setting it explicitly.
if (!_wcsicmp(strName, L"__SECURITY_DESCRIPTOR")) { if (!(dwFlags & WBEM_FLAG_USE_SECURITY_DESCRIPTOR)) { VariantClear(&vTemp); continue; } else { if (vTemp.vt == VT_NULL) bRemoveSD = TRUE; } }
// Skip embedded objects and arrays
// until we have an ObjectId...
// ===================================
IWbemQualifierSet *pQS = NULL; hr = pObj->GetPropertyQualifierSet(strName, &pQS); if (SUCCEEDED(hr)) { CReleaseMe r (pQS); if ((GetQualifierFlag(L"not_null", pQS) != 0) && (vTemp.vt == VT_NULL)) { hr = WBEM_E_ILLEGAL_NULL; VariantClear(&vTemp); break; } }
if ((cimtype == CIM_OBJECT && vTemp.vt == VT_UNKNOWN) || ((cimtype & CIM_FLAG_ARRAY) && (vTemp.vt & CIM_FLAG_ARRAY))) arrObjProps.Add(strName); else { DWORD dPropID, dwFlags2, dwType; SQL_ID dNewClassID = dClassId; hr = GetSchemaCache()->GetPropertyID(strName, dClassId, 0, cimtype, dPropID, &dNewClassID, &dwFlags2, &dwType);
if (SUCCEEDED(hr)) { LPWSTR lpVal = GetStr(vTemp); CDeleteMe <wchar_t> r(lpVal);
pPropValues[iPos].iPropID = dPropID; pPropValues[iPos].pValue = NULL; pPropValues[iPos].pRefKey = NULL; pPropValues[iPos].bLong = false; pPropValues[iPos].iFlavor = 0; pPropValues[iPos].iQfrID = 0; pPropValues[iPos].dClassId = dNewClassID; pPropValues[iPos].iStorageType = dwType; pPropValues[iPos].bIndexed = (dwFlags2 & (REPDRVR_FLAG_INDEXED + REPDRVR_FLAG_KEY)) ? TRUE : FALSE;
if (cimtype == CIM_REFERENCE) { // If no scope, don't bother trying to
// store this reference,
// since the end result will be invalid.
// ======================================
if (!pScope) { VariantClear(&vTemp); continue; }
pPropValues[iPos].bIndexed = TRUE; // References are always keys
LPWSTR lpTemp = NULL; IWbemPath *pPath = NULL;
hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &pPath); CReleaseMe r8 (pPath); if (SUCCEEDED(hr)) { if (lpVal) { pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, lpVal); hr = NormalizeObjectPathGet(pScope, pPath, &lpTemp, NULL, NULL, NULL, pConn); CDeleteMe <wchar_t> r1(lpTemp); if (SUCCEEDED(hr)) { LPWSTR lpTemp2 = NULL; lpTemp2 = GetKeyString(lpTemp); CDeleteMe <wchar_t> d (lpTemp2); pPropValues[iPos].pRefKey = new wchar_t [21]; if (pPropValues[iPos].pRefKey) swprintf(pPropValues[iPos].pRefKey, L"%I64d", CRC64::GenerateHashValue(lpTemp2)); else hr = WBEM_E_OUT_OF_MEMORY; } else { hr = WBEM_S_NO_ERROR; // Strip off the root namespace prefix and generate the
// pseudo-name. We have no way of knowing if they entered this
// path correctly.
LPWSTR lpTemp3 = StripUnresolvedName (lpVal); CDeleteMe <wchar_t> d2 (lpTemp3);
LPWSTR lpTemp2 = NULL; lpTemp2 = GetKeyString(lpTemp3); CDeleteMe <wchar_t> d (lpTemp2); pPropValues[iPos].pRefKey = new wchar_t [21]; if (pPropValues[iPos].pRefKey) swprintf(pPropValues[iPos].pRefKey, L"%I64d", CRC64::GenerateHashValue(lpTemp2)); else hr = WBEM_E_OUT_OF_MEMORY; }
pPropValues[iPos].pValue = new wchar_t[wcslen(lpVal)+1]; if (pPropValues[iPos].pValue) wcscpy(pPropValues[iPos].pValue,lpVal); else hr = WBEM_E_OUT_OF_MEMORY; } else pPropValues[iPos].pValue = NULL; } else { VariantClear(&vTemp); break; } } else { if (lpVal) { pPropValues[iPos].pValue = new wchar_t[wcslen(lpVal)+1]; if (pPropValues[iPos].pValue) wcscpy(pPropValues[iPos].pValue,lpVal); else hr = WBEM_E_OUT_OF_MEMORY; } else pPropValues[iPos].pValue = NULL;
pPropValues[iPos].pRefKey = NULL; } pPropValues[iPos].iPos = 0; iPos++; } else { VariantClear(&vTemp); break; } } VariantClear(&vTemp); }
LPWSTR lpObjectKey = pProps->lpKeyString; if (!wcslen(lpObjectKey)) { ERRORTRACE((LOG_WBEMCORE, "Invalid object path in CWmiDbSession::InsertPropertyValues (%S) \n", lpPath));
delete pProps->lpKeyString; lpObjectKey = new wchar_t [wcslen(lpPath)+1]; if (lpObjectKey) wcscpy(lpObjectKey, lpPath); else hr = WBEM_E_OUT_OF_MEMORY; pProps->lpKeyString = lpObjectKey; }
if (SUCCEEDED(hr)) { BOOL bCheck=FALSE; CSQLExecProcedure::NeedsToCheckKeyMigration(bCheck); if (bCheck) { SQL_ID *pIDs= NULL; int iNumIDs = 0; hr = GetSchemaCache()->GetHierarchy(dClassId, &pIDs, iNumIDs); if (SUCCEEDED(hr)) { hr = CSQLExecProcedure::CheckKeyMigration(pConn, lpObjectKey, pProps->lpClassName, dClassId, dScopeId, pIDs, iNumIDs); delete pIDs; } } }
if (SUCCEEDED(hr)) hr = CSQLExecProcedure::InsertPropertyBatch (pConn, lpObjectKey, lpPath, pProps->lpClassName, dClassId, dScopeId, dwFlags, pPropValues, iPos, dObjectId); delete pPropValues;
// If there's no scope, quit now.
// This can only happen if we are only updating
// the security descriptor.
// ============================================
if (!pScope) return hr;
// Insert qualifiers next.
// ======================
if (SUCCEEDED(hr)) { iQfrPos = 0; iNumProps *=2 + 10 + arrObjProps.Size(); // How do we calculate how many qualifiers there will be??
pQVals = new InsertQfrValues[iNumProps]; if (!pQVals) return WBEM_E_OUT_OF_MEMORY;
VariantClear(&vTemp);
// PROPERTY QUALIFIERS
pObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY); while (pObj->Next(0, &strName, &vTemp, &cimtype, &lPropFlavor) == S_OK) { CFreeMe f (strName); IWbemQualifierSet *pQS = NULL; hr = pObj->GetPropertyQualifierSet(strName, &pQS); if (hr == WBEM_S_NO_ERROR) { CReleaseMe r (pQS); DWORD dwRefID = 0; hr = GetSchemaCache()->GetPropertyID(strName, dClassId, 0, cimtype, dwRefID); if (SUCCEEDED(hr)) hr = FormatBatchInsQfrs(pConn, pScope, dObjectId, dClassId, dwRefID, pQS, iQfrPos, &pQVals, props, iNumProps); } VariantClear(&vTemp); }
// Instance qualifiers
if (SUCCEEDED(hr)) { IWbemQualifierSet *pQS = NULL; hr = pObj->GetQualifierSet(&pQS); CReleaseMe r (pQS); if (SUCCEEDED(hr)) hr = FormatBatchInsQfrs(pConn, pScope, dObjectId, dClassId, 0, pQS, iQfrPos, &pQVals, props, iNumProps);
if (SUCCEEDED(hr)) { bool bToUpdate = false;
// Insert arrays and embedded objects last...
for (int i = 0; i < arrObjProps.Size(); i++) {
VARIANT vTemp; VariantInit(&vTemp); CIMTYPE cimtype;
// OPTIMIZATION: Retrieve the buffer and write it directly,
// for all byte arrays.
if (!_wcsicmp(arrObjProps.GetAt(i), L"__SECURITY_DESCRIPTOR")) { BYTE *pBuff = NULL; long handle;
hr = ((_IWmiObject *)pObj)->GetPropertyHandleEx(arrObjProps.GetAt(i), 0, NULL, &handle); if (SUCCEEDED(hr)) { ULONG uSize = 0; hr = ((_IWmiObject *)pObj)->GetArrayPropAddrByHandle(handle, 0, &uSize, (LPVOID *)&pBuff);
if (SUCCEEDED(hr)) { // Set this in the database
long why[1]; unsigned char t; SAFEARRAYBOUND aBounds[1]; aBounds[0].cElements = uSize; aBounds[0].lLbound = 0; SAFEARRAY* pArray = SafeArrayCreate(VT_UI1, 1, aBounds); vTemp.vt = VT_I1; for (int i = 0; i < uSize; i++) { why[0] = i; t = pBuff[i]; hr = SafeArrayPutElement(pArray, why, &t); } vTemp.vt = VT_ARRAY|VT_UI1; V_ARRAY(&vTemp) = pArray; cimtype = CIM_UINT8 + CIM_FLAG_ARRAY; } } } else pObj->Get(arrObjProps.GetAt(i), 0, &vTemp, &cimtype, NULL);
if (cimtype == CIM_OBJECT) { bToUpdate = true; IUnknown *pTemp = NULL; pTemp = V_UNKNOWN(&vTemp); if (pTemp) { DWORD dPropID; SQL_ID dNewClassID = dClassId; hr = GetSchemaCache()->GetPropertyID(arrObjProps.GetAt(i), dClassId, 0, CIM_OBJECT, dPropID, &dNewClassID); if (SUCCEEDED(hr)) hr = InsertArray(pConn, pScope, dObjectId, dClassId, dPropID, vTemp, 0, 0, lpObjectKey, lpPath, dScopeId, cimtype); else break; } VariantClear(&vTemp); } else // Its an array, a blob, or a very long string.
{ DWORD dPropID; SQL_ID dNewClassID = dClassId; hr = GetSchemaCache()->GetPropertyID(arrObjProps.GetAt(i), dClassId, 0, cimtype, dPropID, &dNewClassID); if (SUCCEEDED(hr)) { if (!_wcsicmp(arrObjProps.GetAt(i), L"__SECURITY_DESCRIPTOR")) { hr = TestSD(&vTemp); if(FAILED(hr)) { VariantClear( &vTemp ); break; } } hr = InsertArray(pConn, pScope, dObjectId, dClassId, dPropID, vTemp, 0, 0, lpObjectKey, lpPath, dScopeId, cimtype); if (SUCCEEDED(hr) && !_wcsicmp(arrObjProps.GetAt(i), L"__SECURITY_DESCRIPTOR")) { ((CWmiDbController *)m_pController)->AddSecurityDescriptor(dObjectId);
// Is this an instance of __ThisNamespace? We need to copy this SD to the current scope object
if (dClassId == THISNAMESPACEID) { hr = InsertArray(pConn, pScope, dScopeId, NAMESPACECLASSID, dPropID, vTemp, 0, 0, NULL, NULL, 0, cimtype); if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->AddSecurityDescriptor(dScopeId); }
} } VariantClear( &vTemp ); }
if (FAILED(hr)) break; }
if (SUCCEEDED(hr) && iQfrPos) hr = CSQLExecProcedure::InsertBatch (pConn, dObjectId, dClassId, dScopeId, pQVals, iQfrPos); } } }
if (SUCCEEDED(hr)) { if ((dClassId == NAMESPACECLASSID || GetSchemaCache()->IsDerivedClass(NAMESPACECLASSID, dClassId))) { hr = GetSchemaCache()->AddNamespace(lpPath, lpObjectKey, dObjectId, dScopeId, dClassId); CSQLExecProcedure::InsertScopeMap(pConn, dObjectId, lpPath, dScopeId); } if (bRemoveSD) { ((CWmiDbController *)m_pController)->RemoveSecurityDescriptor(dObjectId); if (dClassId == THISNAMESPACEID) ((CWmiDbController *)m_pController)->RemoveSecurityDescriptor(dScopeId); } }
delete pQVals;
return hr; }
//***************************************************************************
//
// CWmiDbSession::FormatBatchInsQfrs
//
//***************************************************************************
HRESULT CWmiDbSession::FormatBatchInsQfrs (CSQLConnection *pConn,IWmiDbHandle *pScope, SQL_ID dObjectId, SQL_ID dClassId, DWORD dPropID, IWbemQualifierSet *pQS, int &iPos, InsertQfrValues **ppVals, Properties &props, int &iNumProps) { HRESULT hr = WBEM_S_NO_ERROR;
BSTR strTemp; VARIANT vTemp; long lTemp; InsertQfrValues *pVals = *ppVals;
pQS->BeginEnumeration(0); while (pQS->Next(0, &strTemp, &vTemp, &lTemp) == S_OK) { CFreeMe f (strTemp); // Don't bother with unstorable qualifiers.
if (lTemp & (WBEM_FLAVOR_ORIGIN_SYSTEM+WBEM_FLAVOR_ORIGIN_PROPAGATED+WBEM_FLAVOR_AMENDED)) { VariantClear(&vTemp); continue; }
lTemp &= ~WBEM_FLAVOR_ORIGIN_PROPAGATED&~WBEM_FLAVOR_ORIGIN_SYSTEM&~WBEM_FLAVOR_AMENDED;
// Each qualifier, if not found in the cache,
// will need to be inserted...
DWORD dQfrID =0; CIMTYPE ct = 0;
switch((vTemp.vt & (0xFFF))) { case VT_BSTR: ct = CIM_STRING; break; case VT_R8: case VT_R4: ct = CIM_REAL64; break; case VT_BOOL: ct = CIM_BOOLEAN; break; default: ct = CIM_UINT32; break; }
if (FAILED(GetSchemaCache()->GetPropertyID(strTemp, 1, REPDRVR_FLAG_QUALIFIER, ct, dQfrID))) { hr = InsertQualifier (pConn, pScope, dObjectId,strTemp, vTemp, lTemp, 0, dPropID,props); if (FAILED(hr)) { VariantClear(&vTemp); break; } } if (FAILED(GetSchemaCache()->GetPropertyID(strTemp, 1, REPDRVR_FLAG_QUALIFIER, ct, dQfrID))) continue;
if (iPos == iNumProps) { pVals = ReAllocQfrValues (pVals, iNumProps, iNumProps+10); iNumProps += 10;
if (!pVals) { VariantClear(&vTemp); return WBEM_E_OUT_OF_MEMORY; } *ppVals = pVals; }
// Add this ID to the batch...
hr = FormatBatchInsQfrValues(pConn, pScope, dObjectId, dQfrID, vTemp, lTemp, pVals, props, iPos, dPropID);
VariantClear(&vTemp);
if (FAILED(hr)) break; } pQS->EndEnumeration(); return hr; }
//***************************************************************************
//
// CWmiDbSession::FormatBatchInsQfrValues
//
//***************************************************************************
HRESULT CWmiDbSession::FormatBatchInsQfrValues(CSQLConnection *pConn,IWmiDbHandle *pScope, SQL_ID dObjectId, DWORD dwQfrID, VARIANT &vTemp, long lFlavor, InsertQfrValues *pVals, Properties &props, int &iPos, DWORD PropID) { if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
HRESULT hr = WBEM_S_NO_ERROR;
bool bArray = false; if (vTemp.vt & VT_ARRAY) bArray = true;
if (!bArray) { LPWSTR lpVal = GetStr(vTemp); CDeleteMe <wchar_t> r1 (lpVal); pVals[iPos].iPos = 0; pVals[iPos].iPropID = dwQfrID;
pVals[iPos].pValue = (lpVal ? new wchar_t [wcslen(lpVal)+1] : NULL); pVals[iPos].pRefKey = NULL; pVals[iPos].bLong = false; if (lpVal) wcscpy(pVals[iPos].pValue, lpVal); pVals[iPos].iFlavor = lFlavor; pVals[iPos].iQfrID = PropID; pVals[iPos].dClassId = 1; // always, for qualifiers.
pVals[iPos].bIndexed = false; // never indexed
switch(vTemp.vt) { case VT_BSTR: pVals[iPos].iStorageType = WMIDB_STORAGE_STRING; break; case VT_R4: case VT_R8: pVals[iPos].iStorageType = WMIDB_STORAGE_REAL; break; default: pVals[iPos].iStorageType = WMIDB_STORAGE_NUMERIC; break; } iPos++; } else hr = InsertArray(pConn, pScope, dObjectId, 0, dwQfrID, vTemp, lFlavor, PropID);
return hr; }
//***************************************************************************
//
// CWmiDbSession::DeleteObject
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::DeleteObject( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ DWORD dwFlags, /* [in] */ REFIID riid, /* [iid_is][in] */ LPVOID pObjToPut) { HRESULT hr = WBEM_S_NO_ERROR;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
if (!pObjToPut || !pScope) return WBEM_E_INVALID_PARAMETER;
if (dwFlags & ~WMIDB_DISABLE_EVENTS & ~WMIDB_FLAG_ADMIN_VERIFIED) return WBEM_E_INVALID_PARAMETER;
if (riid != IID_IWbemClassObject && riid != IID_IWmiDbHandle && riid != IID__IWmiObject && riid != IID_IWbemPath) return WBEM_E_NOT_SUPPORTED;
SQL_ID dScopeId, dScopeClassId, dClassId, dObjectId; LPWSTR lpClass = NULL, lpNamespace = NULL; _IWmiObject *pObj = NULL;
try { { _WMILockit lkt(GetCS()); if (!((CWmiDbController *)m_pController)->m_bCacheInit) { hr = LoadSchemaCache(); if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE; else return hr; } }
// If this is the __Instances container
// reject this operation..
if (GetSchemaCache()->IsDerivedClass (INSTANCESCLASSID, ((CWmiDbHandle *)pScope)->m_dClassId) || ((CWmiDbHandle *)pScope)->m_dClassId == INSTANCESCLASSID) return WBEM_E_INVALID_OPERATION;
// We only really support IWmiDbHandles and IWbemPaths
CSQLConnection *pConn = NULL;
if (SUCCEEDED(hr)) { AddRef_Lock();
IWmiDbHandle *pHandle = NULL; IWbemPath *pPath = 0; if (riid == IID_IWmiDbHandle) { pHandle = (IWmiDbHandle *)pObjToPut; if (pHandle) { dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId; dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId; dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId; dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId;
if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId, GetSchemaCache()->GetWriteToken(dObjectId, dClassId)); if (SUCCEEDED(hr)) { hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed()); if (SUCCEEDED(hr)) { if(!(dwFlags & WMIDB_DISABLE_EVENTS)) hr = IssueDeletionEvents(pConn, dObjectId, dClassId, dScopeId, NULL);
if (!((CWmiDbHandle *)pHandle)->m_bDefault) hr = CustomDelete(pConn, pScope, pHandle);
hr = Delete(pHandle, pConn); GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed()); } } } } else if (riid == IID_IWbemPath) { pPath = (IWbemPath *)pObjToPut; if (pPath) { hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE|WMIDB_HANDLE_TYPE_EXCLUSIVE, &pHandle); CReleaseMe r2 (pHandle); if (SUCCEEDED(hr)) { dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId; dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId; dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId; dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId;
if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId, GetSchemaCache()->GetWriteToken(dObjectId, dClassId)); if (SUCCEEDED(hr)) { hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed()); if (SUCCEEDED(hr)) { if(!(dwFlags & WMIDB_DISABLE_EVENTS)) hr = IssueDeletionEvents(pConn, dObjectId, dClassId, dScopeId, NULL);
if (!((CWmiDbHandle *)pHandle)->m_bDefault) hr = CustomDelete(pConn, pScope, pHandle);
hr = Delete(pHandle, pConn); GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed()); } } } } } else if (riid == IID_IWbemClassObject || riid == IID__IWmiObject) { pObj = (_IWmiObject *)pObjToPut; if (pObj) { lpClass = GetPropertyVal(L"__Class", pObj); LPWSTR lpPath = GetPropertyVal(L"__RelPath", pObj); if (lpPath) { hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &pPath); CReleaseMe r2 (pPath); if (SUCCEEDED(hr)) { pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, lpPath); hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE|WMIDB_HANDLE_TYPE_EXCLUSIVE, &pHandle); CReleaseMe r3 (pHandle); if (SUCCEEDED(hr)) { dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId; dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId; dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId; dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId;
if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId, GetSchemaCache()->GetWriteToken(dObjectId, dClassId)); if (SUCCEEDED(hr)) { hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed()); if (SUCCEEDED(hr)) { if(!(dwFlags & WMIDB_DISABLE_EVENTS)) hr = IssueDeletionEvents(pConn, dObjectId, dClassId, dScopeId, (IWbemClassObject *)pObj);
if (!((CWmiDbHandle *)pHandle)->m_bDefault) hr = CustomDelete(pConn, pScope, pHandle);
hr = Delete(pHandle, pConn); GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed()); } } } } } } } else hr = WBEM_E_NOT_SUPPORTED;
if (!IsDistributed() && !(dwFlags & WMIDB_DISABLE_EVENTS) ) { if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath); } UnlockDynasties(); } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::DeleteObject\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr;
}
//***************************************************************************
//
// CWmiDbSession::IssueDeletionEvents
//
//***************************************************************************
HRESULT CWmiDbSession::IssueDeletionEvents (CSQLConnection *pConn, SQL_ID dObjectId, SQL_ID dClassId, SQL_ID dScopeId, IWbemClassObject *_pObj) { HRESULT hr = WBEM_S_NO_ERROR;
if (((CWmiDbController *)m_pController)->m_bESSEnabled) { if (_pObj) _pObj->AddRef();
// The rules:
// Instance: we don't issue a deletion event for any subobjects, period.
// Class: issue delete events for all subclasses, not instances
DWORD dwGenus = 1; if (dClassId != 1) dwGenus = 2;
IWbemClassObject *pObj = _pObj;
if (!pObj) { // Get the object.
if (FAILED(GetObjectCache()->GetObject(dObjectId, &pObj, NULL))) { DWORD dwTemp; hr = GetObjectData(pConn, dObjectId, dClassId, dScopeId, WMIDB_HANDLE_TYPE_EXCLUSIVE, dwTemp, &pObj, FALSE, NULL); } }
CReleaseMe r (pObj);
// FIXME: Need to handle custom repdrvr deletion events!
if (!pObj) return WBEM_S_NO_ERROR;
// Get the namespace.
_bstr_t sNamespace, sClass;
GetSchemaCache()->GetNamespaceName(dScopeId, &sNamespace); if (!_wcsicmp(sNamespace, L"root")) sNamespace = L"";
_bstr_t sPath; SQL_ID dTemp1, dTemp2; DWORD dwTemp;
if (dwGenus == 1) GetSchemaCache()->GetClassInfo (dObjectId, sPath, dTemp1, dTemp2, dwTemp, &sClass); else GetSchemaCache()->GetClassInfo (dClassId, sPath, dTemp1, dTemp2, dwTemp, &sClass);
((CWmiDbController *)m_pController)->ESSMgr.AddDeleteRecord(pConn, m_sGUID, sNamespace, sClass, dwGenus, pObj);
// If this is a class, enumerate
// subclasses and issue deletion events
if (dwGenus == 1) { SQL_ID *pIDs = NULL; int iNumDerived = 0; hr = GetSchemaCache()->GetDerivedClassList(dObjectId, &pIDs, iNumDerived); if (SUCCEEDED(hr)) { for (int i = 0; i < iNumDerived; i++) { IWbemClassObject *pOldObj = NULL; hr = GetClassObject(pConn, pIDs[i], &pOldObj); CReleaseMe r (pOldObj); if (SUCCEEDED(hr)) { LPWSTR lpClassName = GetPropertyVal(L"__Class", pOldObj); CDeleteMe <wchar_t> d2 (lpClassName); ((CWmiDbController *)m_pController)->ESSMgr.AddDeleteRecord(pConn, m_sGUID, sNamespace, sClass, dwGenus, pOldObj); } } delete pIDs; }
if (GetSchemaCache()->IsDerivedClass(dObjectId, NAMESPACECLASSID)) { // If this is a class derived from __Namespace,
// we have to enumerate the INSTANCES and issue events for them
// ============================================================
} }
} return hr; }
//***************************************************************************
//
// CWmiDbSession::RenameObject
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::RenameObject( /* [in] */ IWbemPath __RPC_FAR *pOldPath, /* [in] */ IWbemPath __RPC_FAR *pNewPath, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwRequestedHandleType, /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult) { HRESULT hr = WBEM_S_NO_ERROR; IWmiDbHandle *pRet = NULL;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
if (!pOldPath || !pNewPath) return WBEM_E_INVALID_PARAMETER;
// This has to handle moving an object from one scope or namespace
// to another, as well as renaming the keys.
// Moving from one container to another does not work.
try { ULONGLONG uIsInstance1 = 0, uIsInstance2 = 0;
hr = pOldPath->GetInfo(0, &uIsInstance1); hr = pNewPath->GetInfo(0, &uIsInstance2);
if (!(uIsInstance1 & WBEMPATH_INFO_IS_INST_REF) || !(uIsInstance2 & WBEMPATH_INFO_IS_INST_REF)) hr = WBEM_E_INVALID_OPERATION; else { DWORD dwLen = 512; wchar_t wClass1 [512], wClass2[512];
hr = pOldPath->GetClassName(&dwLen, wClass1); hr = pNewPath->GetClassName(&dwLen, wClass2);
if (wcscmp(wClass1, wClass2)) hr = WBEM_E_INVALID_OPERATION; else { IWmiDbHandle *pOld = NULL; IWmiDbHandle *pNewScope = NULL;
LPWSTR lpOldPath, lpOldKey, lpNewPath, lpNewKey; hr = NormalizeObjectPathGet(NULL, pOldPath, &lpOldPath); if (FAILED(hr)) goto Exit; CDeleteMe <wchar_t> d10(lpOldPath);
hr = GetObject_Internal(lpOldPath, 0, WMIDB_HANDLE_TYPE_VERSIONED, NULL, &pOld); if (FAILED(hr)) goto Exit; CReleaseMe r (pOld);
if (SUCCEEDED(hr)) { SQL_ID dScopeID = ((CWmiDbHandle *)pOld)->m_dScopeId;
_IWmiObject *pObj = NULL; hr = pOld->QueryInterface(IID__IWmiObject, (void **)&pObj); if (SUCCEEDED(hr)) { CReleaseMe r6 (pObj);
IWbemPathKeyList *pKeys1 = NULL, *pKeys2 = NULL; CWStringArray arrKeys; hr = GetSchemaCache()->GetKeys( dScopeID, wClass1, arrKeys); if (SUCCEEDED(hr)) { hr = pOldPath->GetKeyList(&pKeys1); CReleaseMe r4(pKeys1);
if (FAILED(hr)) goto Exit; hr = pNewPath->GetKeyList(&pKeys2); CReleaseMe r5 (pKeys2); if (FAILED(hr)) goto Exit;
ULONG uOldNum = 0, uNewNum = 0;
hr = pKeys1->GetCount(&uOldNum); if (FAILED(hr)) goto Exit;
hr = pKeys2->GetCount(&uNewNum); if (FAILED(hr)) goto Exit;
if (arrKeys.Size() != uOldNum || arrKeys.Size() != uNewNum) { hr = WBEM_E_INVALID_OBJECT; goto Exit; } else if (arrKeys.Size() > 0) { for (int i = 0; i < arrKeys.Size(); i++) { ULONG uBufSize = 512; ULONG ct2 = 0; BOOL bFound = FALSE;
for (ULONG j = 0; j < arrKeys.Size(); j++) { VARIANT vTemp; VariantInit(&vTemp); CClearMe c (&vTemp); wchar_t wBuff[1024]; ULONG uBufSize = 1024; CIMTYPE ct = 0; pObj->Get(arrKeys.GetAt(i), 0, NULL, &ct, NULL);
hr = pKeys2->GetKey2(j, 0, &uBufSize, wBuff, &vTemp, &ct2); if (FAILED(hr)) goto Exit; if (!wcslen(wBuff) || !wcscmp(arrKeys.GetAt(i), wBuff)) { bFound = TRUE; hr = pObj->Put(arrKeys.GetAt(i), 0, &vTemp, ct); if (FAILED(hr)) goto Exit; break; } } if (!bFound) { hr = WBEM_E_INVALID_PARAMETER; goto Exit; } } } else hr = WBEM_E_INVALID_OPERATION; // Cannot rename singleton
}
if (SUCCEEDED(hr)) { pNewPath->DeleteClassPart(0);
LPWSTR lpNewScope = NULL; hr = NormalizeObjectPathGet(NULL, pNewPath, &lpNewScope); if (FAILED(hr)) goto Exit; CDeleteMe <wchar_t> d14 (lpNewScope);
hr = GetObject_Internal(lpNewScope, 0, WMIDB_HANDLE_TYPE_VERSIONED, NULL, &pNewScope); if (FAILED(hr)) goto Exit;
if (SUCCEEDED(hr)) { // Create the new object
if (!dwRequestedHandleType) dwRequestedHandleType = WMIDB_HANDLE_TYPE_COOKIE;
_bstr_t sWaste; IWmiDbHandle *pHandle = 0;
hr = PutObject( pNewScope, IID_IWbemClassObject, pObj, 0, dwRequestedHandleType, &pHandle);
if (SUCCEEDED(hr)) { // Enumerate the subscopes of the old object,
IWmiDbIterator *pIt = NULL; hr = Enumerate(pOld, 0, WMIDB_HANDLE_TYPE_COOKIE, &pIt); if (SUCCEEDED(hr)) { IWbemClassObject *pResult = NULL; DWORD dwNum = 0; while (pIt->NextBatch(1, 0, 0, 0, IID_IWbemClassObject, &dwNum, (void **)&pResult) == 0) { hr = PutObject( pHandle, IID_IWbemClassObject, pResult, 0, 0, NULL); pResult->Release(); if (FAILED(hr)) break; } pIt->Release(); }
((CWmiDbHandle *)pOld)->m_dwHandleType |= WMIDB_HANDLE_TYPE_CONTAINER;
// Enumerate any collection members (if this was a collection).
hr = Enumerate(pOld, 0, WMIDB_HANDLE_TYPE_COOKIE, &pIt); if (SUCCEEDED(hr)) { IWbemClassObject *pResult = NULL; DWORD dwNum = 0; while (pIt->NextBatch(1, 0, 0, 0, IID_IWbemClassObject, &dwNum, (void **)&pResult) == 0) { hr = PutObject( pHandle, IID_IWbemClassObject, pResult, 0, 0, NULL); pResult->Release(); if (FAILED(hr)) break; } pIt->Release(); }
// If all that worked, kill the old object. This will leave
// dangling references, but that's OK.
if (SUCCEEDED(hr)) hr = Delete (pOld); }
if (ppResult) *ppResult = pHandle; else if (pHandle) pHandle->Release(); } } } } } } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::RenameObject")); hr = WBEM_E_CRITICAL_ERROR; }
Exit:
return hr; }
//***************************************************************************
//
// CWmiDbSession::AddObject
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::AddObject( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ IWbemPath __RPC_FAR *pPath, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwRequestedHandleType, /* [out] */ IWmiDbHandle __RPC_FAR *__RPC_FAR *ppResult) { HRESULT hr = WBEM_S_NO_ERROR;
if (!pScope || !pPath) return WBEM_E_INVALID_PARAMETER;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
if (dwRequestedHandleType & ~WMIDB_HANDLE_TYPE_COOKIE &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE &~WMIDB_HANDLE_TYPE_SUBSCOPED&~WMIDB_HANDLE_TYPE_CONTAINER&~ WMIDB_HANDLE_TYPE_SCOPE) return WBEM_E_INVALID_PARAMETER;
try { { _WMILockit lkt(GetCS()); if (!((CWmiDbController *)m_pController)->m_bCacheInit) { hr = LoadSchemaCache(); if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE; else return hr; } }
if (GetSchemaCache()->IsDerivedClass (INSTANCESCLASSID, ((CWmiDbHandle *)pScope)->m_dClassId) || ((CWmiDbHandle *)pScope)->m_dClassId == INSTANCESCLASSID ) return WBEM_E_INVALID_OPERATION;
// This needs to add an object as a contained instance.
// * Create a new instance of __Container_Association
// * Call PutObject
IWmiDbHandle *pContainerAssoc = NULL;
hr = GetObject_Internal(L"__Container_Association", 0, WMIDB_HANDLE_TYPE_VERSIONED, NULL, &pContainerAssoc); if (SUCCEEDED(hr)) { IWbemClassObject *pClassObj = NULL; hr = pContainerAssoc->QueryInterface(IID_IWbemClassObject, (void **)&pClassObj); CReleaseMe r1 (pClassObj), r2 (pContainerAssoc); if (SUCCEEDED(hr)) { IWbemClassObject *pObj = NULL; pClassObj->SpawnInstance(0, &pObj); CReleaseMe r (pObj);
LPWSTR lpContainer = NULL, lpContainee; hr = NormalizeObjectPath(pScope, (LPCWSTR)NULL, &lpContainer); CDeleteMe <wchar_t> d1 (lpContainer); if (SUCCEEDED(hr)) { hr = NormalizeObjectPathGet(NULL, pPath, &lpContainee); CDeleteMe <wchar_t> d2 (lpContainee); if (SUCCEEDED(hr)) { VARIANT vContainer, vContainee; CClearMe c1 (&vContainer), c2 (&vContainee); VariantInit(&vContainer); VariantInit(&vContainee); vContainer.bstrVal = SysAllocString(lpContainer); vContainee.bstrVal = SysAllocString(lpContainee); vContainer.vt = VT_BSTR; vContainee.vt = VT_BSTR;
hr = pObj->Put(L"Container", 0, &vContainer, CIM_REFERENCE); if (SUCCEEDED(hr)) { hr = pObj->Put(L"Containee", 0, &vContainee, CIM_REFERENCE); if (SUCCEEDED(hr)) { // Stick this object in the
// parent's scope.
SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
IWmiDbHandle *pParentScope = NULL;
hr = GetObject_Internal(L"..", 0, WMIDB_HANDLE_TYPE_VERSIONED, &dScopeId, &pParentScope); CReleaseMe r (pParentScope); if (SUCCEEDED(hr)) hr = PutObject(pParentScope, IID_IWbemClassObject, pObj, dwFlags, dwRequestedHandleType, ppResult); } } } } } } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::AddObject\n")); hr = WBEM_E_CRITICAL_ERROR; } return hr; }
//***************************************************************************
//
// CWmiDbSession::RemoveObject
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::RemoveObject( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ IWbemPath __RPC_FAR *pPath, /* [in] */ DWORD dwFlags) { HRESULT hr = WBEM_S_NO_ERROR;
// This needs to remove an object from the container.
// * Retrieves the handle to the container association
// * Calls DeleteObject
if (!pScope || !pPath) return WBEM_E_INVALID_PARAMETER;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; try { { _WMILockit lkt(GetCS()); if (!((CWmiDbController *)m_pController)->m_bCacheInit) { hr = LoadSchemaCache(); if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE; else return hr; } }
if (GetSchemaCache()->IsDerivedClass (INSTANCESCLASSID, ((CWmiDbHandle *)pScope)->m_dClassId) || ((CWmiDbHandle *)pScope)->m_dClassId == INSTANCESCLASSID) return WBEM_E_INVALID_OPERATION;
LPWSTR lpContainer = NULL, lpContainee; hr = NormalizeObjectPath(pScope, (LPCWSTR)NULL, &lpContainer); CDeleteMe <wchar_t> d1 (lpContainer); if (SUCCEEDED(hr)) { hr = NormalizeObjectPathGet(NULL, pPath, &lpContainee); CDeleteMe <wchar_t> d2 (lpContainee);
wchar_t *pTemp = new wchar_t [wcslen(lpContainer)+wcslen(lpContainee)+50]; if (pTemp) { CDeleteMe <wchar_t> d (pTemp);
swprintf(pTemp, L"__Container_Association.Container='%s',Containee='%s'", lpContainer, lpContainee);
IWbemPath *pPath = NULL; hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &pPath);
CReleaseMe r8 (pPath); if (SUCCEEDED(hr)) { hr = pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pTemp);
IWmiDbHandle *pParentScope = NULL; SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
hr = GetObject_Internal(L"..", 0, WMIDB_HANDLE_TYPE_VERSIONED, &dScopeId, &pParentScope); CReleaseMe r (pParentScope); if (SUCCEEDED(hr)) hr = DeleteObject(pParentScope, dwFlags, IID_IWbemPath, pPath); } } else hr = WBEM_E_OUT_OF_MEMORY; } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::RemoveObject\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr; }
//***************************************************************************
//
// CWmiDbSession::SetDecoration
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::SetDecoration( /* [in] */ LPWSTR lpMachineName, /* [in] */ LPWSTR lpNamespacePath) { HRESULT hr = WBEM_S_NO_ERROR;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
try { if (!lpMachineName || !lpNamespacePath) hr = WBEM_E_INVALID_PARAMETER; else { m_sMachineName = lpMachineName; m_sNamespacePath = lpNamespacePath; } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::SetDecoration\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr; }
//***************************************************************************
//
// CWmiDbSession::PutObjects
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::PutObjects( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwHandleType, /* [in] */ WMIOBJECT_BATCH __RPC_FAR *pBatch)
{ HRESULT hr = WBEM_S_NO_ERROR; HRESULT hrRet=0;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
if (dwHandleType == WMIDB_HANDLE_TYPE_INVALID || !pBatch ||!pScope) return WBEM_E_INVALID_PARAMETER;
if (dwFlags &~WMIDB_FLAG_BEST_EFFORT &~WMIDB_FLAG_ATOMIC & ~WBEM_FLAG_CREATE_ONLY & ~WBEM_FLAG_UPDATE_ONLY & ~WBEM_FLAG_CREATE_OR_UPDATE & ~WBEM_FLAG_USE_SECURITY_DESCRIPTOR &~ WBEM_FLAG_REMOVE_CHILD_SECURITY) return WBEM_E_INVALID_PARAMETER;
try { CSQLConnection *pConn = NULL;
hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed()); if (SUCCEEDED(hr)) { AddRef_Lock();
for (int i = 0; i < pBatch->dwArraySize; i++) { IUnknown *pUnk = (IUnknown *)pBatch->pElements[i].pHandle; if (pUnk) { IWmiDbHandle *pTemp = NULL; _bstr_t sWaste; hr = PutObject(pConn, pScope, 0, L"", pUnk, dwFlags&~WMIDB_FLAG_BEST_EFFORT&~WMIDB_FLAG_ATOMIC, dwHandleType, sWaste, &pTemp); if (SUCCEEDED(hr)) pBatch->pElements[i].pReturnHandle = pTemp; pBatch->pElements[i].hRes = hr; } else { pBatch->pElements[i].hRes = WBEM_E_INVALID_PARAMETER; hr = WBEM_E_INVALID_PARAMETER; } if (FAILED(hr) && (dwFlags == WMIDB_FLAG_ATOMIC)) // If one fails, keep going.
{ hrRet = hr; break; } else if (FAILED(hr)) hrRet = WBEM_S_PARTIAL_RESULTS;
}
if (FAILED(hr) && !(dwFlags & WMIDB_FLAG_ATOMIC)) hr = WBEM_S_NO_ERROR;
GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
if (!IsDistributed() && !(dwFlags & WMIDB_DISABLE_EVENTS) ) { if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath); } UnlockDynasties(); } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::PutObjects\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hrRet;
}
//***************************************************************************
//
// CWmiDbSession::GetObjects
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::GetObjects( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwHandleType, /* [in, out] */ WMIOBJECT_BATCH __RPC_FAR *pBatch) { HRESULT hr = WBEM_S_NO_ERROR; HRESULT hrRet = 0;
// This is really just a query, except that we need
// to set return values in the struct.
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; if (dwHandleType == WMIDB_HANDLE_TYPE_INVALID || !pBatch ||!pScope) return WBEM_E_INVALID_PARAMETER;
if (dwHandleType & ~WMIDB_HANDLE_TYPE_COOKIE &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE &~WMIDB_HANDLE_TYPE_SUBSCOPED &~WMIDB_HANDLE_TYPE_SCOPE &~WMIDB_HANDLE_TYPE_CONTAINER) return WBEM_E_INVALID_PARAMETER;
if (dwFlags &~WMIDB_FLAG_BEST_EFFORT &~WMIDB_FLAG_ATOMIC & ~WBEM_FLAG_USE_SECURITY_DESCRIPTOR) return WBEM_E_INVALID_PARAMETER;
try { AddRef_Lock();
if (SUCCEEDED(hr)) { for (int i = 0; i < pBatch->dwArraySize; i++) { IWbemPath *pPath = pBatch->pElements[i].pPath; IWmiDbHandle *pTemp = NULL;
hr = GetObject(pScope, pPath, pBatch->pElements[i].dwFlags, dwHandleType, &pTemp); if (SUCCEEDED(hr)) { pBatch->pElements[i].pReturnHandle = pTemp; pBatch->pElements[i].hRes = hr; pBatch->pElements[i].dwFlags = dwFlags; }
if (FAILED(hr) && (dwFlags == WMIDB_FLAG_ATOMIC)) // If one fails, keep going.
{ hrRet = hr; break; } else if (FAILED(hr)) hrRet = WBEM_S_PARTIAL_RESULTS; } } UnlockDynasties(); } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::GetObjects\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hrRet;
}
//***************************************************************************
//
// CWmiDbSession::DeleteObjects
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::DeleteObjects( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ DWORD dwFlags, /* [in] */ WMIOBJECT_BATCH __RPC_FAR *pBatch)
{ HRESULT hr = WBEM_S_NO_ERROR; HRESULT hrRet = 0;
if (!pBatch || !pScope) return WBEM_E_INVALID_PARAMETER;
if (dwFlags &~WMIDB_FLAG_BEST_EFFORT &~WMIDB_FLAG_ATOMIC &~ WMIDB_FLAG_ADMIN_VERIFIED) return WBEM_E_INVALID_PARAMETER;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
try { { _WMILockit lkt(GetCS()); if (!((CWmiDbController *)m_pController)->m_bCacheInit) { hr = LoadSchemaCache(); if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE; else return hr; } } CSQLConnection *pConn = NULL;
SQL_ID dScopeId, dClassId, dObjectId; hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed()); if (SUCCEEDED(hr)) { AddRef_Lock();
for (int i = 0; i < pBatch->dwArraySize; i++) { IUnknown *pUnk = (IUnknown *)pBatch->pElements[i].pHandle; if (pUnk) { IWmiDbHandle *pHandle = NULL; if (SUCCEEDED(pUnk->QueryInterface(IID_IWmiDbHandle, (void **)&pHandle))) { CReleaseMe r (pHandle); dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId; dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId; dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId; SQL_ID dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId;
if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId, GetSchemaCache()->GetWriteToken(dObjectId, dClassId)); if (SUCCEEDED(hr)) { if (!((CWmiDbHandle *)pHandle)->m_bDefault) hr = CustomDelete(pConn, pScope, pHandle);
hr = Delete(pHandle, pConn); } } else pBatch->pElements[i].hRes = WBEM_E_INVALID_PARAMETER; } else if (pBatch->pElements[i].pPath) { // Problem: We need the binary object path to include the scope!!!
IWbemPath *pPath = pBatch->pElements[i].pPath; if (pPath) { IWmiDbHandle *pHandle = NULL; hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE|WMIDB_HANDLE_TYPE_EXCLUSIVE, &pHandle); CReleaseMe r (pHandle); if (SUCCEEDED(hr)) { dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId; dClassId = ((CWmiDbHandle *)pHandle)->m_dClassId; dObjectId = ((CWmiDbHandle *)pHandle)->m_dObjectId; SQL_ID dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId;
if (!(dwFlags & WMIDB_FLAG_ADMIN_VERIFIED)) hr = VerifyObjectSecurity(NULL, dObjectId, dClassId, dScopeId, dScopeClassId, GetSchemaCache()->GetWriteToken(dObjectId, dClassId)); if (SUCCEEDED(hr)) { if (!((CWmiDbHandle *)pHandle)->m_bDefault) hr = CustomDelete(pConn, pScope, pHandle);
hr = Delete(pHandle, pConn); } } } } else pBatch->pElements[i].hRes = WBEM_E_INVALID_PARAMETER;
pBatch->pElements[i].hRes = hr; if (FAILED(hr) && (dwFlags == WMIDB_FLAG_ATOMIC)) // If one fails, keep going.
{ hrRet = hr; break; } else if (FAILED(hr)) hrRet = WBEM_S_PARTIAL_RESULTS; }
GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed());
if (!IsDistributed() && !(dwFlags & WMIDB_DISABLE_EVENTS) ) { if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath); } UnlockDynasties(); } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::DeleteObjects\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hrRet;
}
//***************************************************************************
//
// CWmiDbSession::Begin
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::Begin( /* [in] */ ULONG uTimeout, /* [in] */ ULONG uFlags, /* [in] */ GUID __RPC_FAR *pTransGUID) { HRESULT hr = WBEM_S_NO_ERROR;
// There can't be an existing transaction.
if (m_sGUID.length() > 0) return WBEM_E_INVALID_OPERATION;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
// Get or Create a __Transaction instance for this GUID
// Transaction state = Pending
// ================================================
wchar_t wGUID[128]; StringFromGUID2(*pTransGUID, wGUID, 128);
wchar_t wPath[255]; swprintf(wPath, L"__Transaction.GUID=\"%s\"", (LPCWSTR)wGUID);
IWmiDbHandle *pHandle = NULL; hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle); CReleaseMe r1 (pHandle); if (SUCCEEDED(hr)) { _IWmiObject *pObj = NULL; hr = pObj->QueryInterface(IID__IWmiObject, (void **)&pObj); CReleaseMe r2 (pObj); if (SUCCEEDED(hr)) { ULONG uState = 0; LPWSTR lpTemp = NULL; lpTemp = GetPropertyVal(L"State", pObj); CDeleteMe <wchar_t> d (lpTemp); uState = _wtol(lpTemp);
//hr = pObj->ReadProp(L"State", 0, sizeof(ULONG), NULL,
// NULL, NULL, NULL, &uState);
if (uState > WBEM_TRANSACTION_STATE_PENDING) { return WBEM_E_ALREADY_EXISTS; } } } else { // Create a new one.
_IWmiObject *pObj = NULL; hr = GetObject_Internal(L"__Transaction", 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle); CReleaseMe r2 (pHandle); if (SUCCEEDED(hr)) { hr = pHandle->QueryInterface(IID__IWmiObject, (void **)&pObj); if (SUCCEEDED(hr)) { CReleaseMe r3 (pObj);
IWbemClassObject *pInst2 = NULL; pObj->SpawnInstance(0, &pInst2); CReleaseMe r (pInst2); if (pInst2) { _IWmiObject *pInst = (_IWmiObject *)pInst2;
ULONG uTemp = WBEM_TRANSACTION_STATE_PENDING; WBEMTime tNow(time(0)); BSTR sTime = tNow.GetDMTF(TRUE); CFreeMe f (sTime);
pInst->WriteProp(L"GUID", 0, (wcslen(wGUID)*2)+2, 1, CIM_STRING, wGUID); pInst->WriteProp(L"State", 0, sizeof(ULONG), 1, CIM_UINT32, &uTemp);
pInst->WriteProp(L"Start", 0, (wcslen(sTime)*2)+2, 1, CIM_DATETIME, sTime); pInst->WriteProp(L"LastUpdate", 0, (wcslen(sTime)*2)+2, 1, CIM_DATETIME, sTime);
CSQLConnection *pConn = NULL; hr = GetSQLCache()->GetConnection(&pConn, FALSE, FALSE); if (SUCCEEDED(hr)) { _bstr_t sPath; hr = PutObject(pConn, NULL, ROOTNAMESPACEID, L"", pInst, 0, NULL, sPath, NULL, FALSE); GetSQLCache()->ReleaseConnection(pConn, hr); } } } } } if (SUCCEEDED(hr)) { m_bIsDistributed = TRUE; m_sGUID = wGUID; }
return hr; } //***************************************************************************
//
// CWmiDbSession::Rollback
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::Rollback( /* [in] */ ULONG uFlags) { HRESULT hr = WBEM_S_NO_ERROR;
if (m_sGUID.length() == 0) return WBEM_E_INVALID_OPERATION;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
// Rollback and release the transaction.
// ======================================
CSQLConnection *pConn = NULL; hr = GetSQLCache()->GetConnection(&pConn, FALSE, TRUE); if (SUCCEEDED(hr)) { GetSQLCache()->FinalRollback(pConn); GetSQLCache()->ReleaseConnection(pConn, 0, TRUE); } else return hr;
AddRef_Lock(); CleanTransLocks();
wchar_t wPath[255]; swprintf(wPath, L"__Transaction.GUID=\"%s\"", (LPCWSTR)m_sGUID);
m_sGUID = L""; m_bIsDistributed = FALSE;
// __Transaction state = rolled back
// =================================
IWmiDbHandle *pHandle = NULL; hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle); CReleaseMe r1 (pHandle); if (SUCCEEDED(hr)) { _IWmiObject *pObj = NULL; hr = pHandle->QueryInterface(IID__IWmiObject, (void **)&pObj); CReleaseMe r2 (pObj); if (SUCCEEDED(hr)) { hr = GetSQLCache()->GetConnection(&pConn, FALSE, FALSE); if (SUCCEEDED(hr)) { ULONG uState = WBEM_TRANSACTION_STATE_ROLLED_BACK; pObj->WriteProp(L"State", 0, sizeof(ULONG), 1, CIM_UINT32, &uState); _bstr_t sPath; hr = PutObject(pConn, NULL, ROOTNAMESPACEID, L"", pObj, 0, NULL, sPath, NULL, FALSE); GetSQLCache()->ReleaseConnection(pConn, hr); } } } // Delete all events and remove all locks.
if (SUCCEEDED(hr)) hr = ((CWmiDbController *)m_pController)->ESSMgr.DeleteAll(m_sGUID);
// Remove any affected dynasties from the cache,
// to make sure we force a reread from the db.
UnlockDynasties(TRUE);
return hr; } //***************************************************************************
//
// CWmiDbSession::Commit
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::Commit( /* [in] */ ULONG uFlags) { HRESULT hr = WBEM_S_NO_ERROR;
if (m_sGUID.length() == 0) return WBEM_E_INVALID_OPERATION;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
// __Transaction state = EventPlayback
// Include this as final query.
// ===================================
AddRef_Lock(); wchar_t wPath[255]; swprintf(wPath, L"__Transaction.GUID=\"%s\"", (LPCWSTR)m_sGUID);
IWmiDbHandle *pHandle = NULL; hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle); if (SUCCEEDED(hr)) { _IWmiObject *pObj = NULL; hr = pHandle->QueryInterface(IID__IWmiObject, (void **)&pObj); CReleaseMe r2 (pObj); if (SUCCEEDED(hr)) { CSQLConnection *pConn = NULL; hr = GetSQLCache()->GetConnection(&pConn, FALSE, TRUE); if (SUCCEEDED(hr)) { ULONG uState = WBEM_TRANSACTION_STATE_EVENT_PLAYBACK; pObj->WriteProp(L"State", 0, sizeof(ULONG), 1, CIM_UINT32, &uState); _bstr_t sPath; hr = PutObject(pConn, NULL, ROOTNAMESPACEID, L"", pObj, 0, NULL, sPath, NULL, FALSE);
// Commit the transaction in the database
// ======================================
if (SUCCEEDED(hr)) { GetSQLCache()->FinalCommit(pConn); GetSQLCache()->ReleaseConnection(pConn, hr, TRUE);
// Commit our events.
// ==================
hr = ((CWmiDbController *)m_pController)->ESSMgr.CommitAll(m_sGUID, m_sNamespacePath); } } } pHandle->Release(); }
CleanTransLocks();
m_sGUID = L""; m_bIsDistributed = FALSE;
if (SUCCEEDED(hr)) { // Transaction state = Completed
IWmiDbHandle *pHandle2 = NULL; hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle2); CReleaseMe r3 (pHandle2); if (SUCCEEDED(hr)) { _IWmiObject *pObj = NULL; hr = pHandle2->QueryInterface(IID__IWmiObject, (void **)&pObj); CReleaseMe r2 (pObj); if (SUCCEEDED(hr)) { CSQLConnection *pConn = NULL; hr = GetSQLCache()->GetConnection(&pConn, FALSE, FALSE); if (SUCCEEDED(hr)) { ULONG uState = WBEM_TRANSACTION_STATE_COMPLETED; pObj->WriteProp(L"State", 0, sizeof(ULONG), 1, CIM_UINT32, &uState); _bstr_t sPath; hr = PutObject(pConn, NULL, ROOTNAMESPACEID, L"", pObj, 0, NULL, sPath, NULL, FALSE); GetSQLCache()->ReleaseConnection(pConn, hr); } } } }
UnlockDynasties();
return hr; } //***************************************************************************
//
// CWmiDbSession::QueryState
//
//***************************************************************************
HRESULT STDMETHODCALLTYPE CWmiDbSession::QueryState( /* [in] */ ULONG uFlags, /* [out] */ ULONG __RPC_FAR *puState) { HRESULT hr = WBEM_S_NO_ERROR;
if (m_sGUID.length() == 0) return WBEM_E_INVALID_OPERATION;
if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN;
// This should be stored in the root namespace.
wchar_t wPath[255]; swprintf(wPath, L"__Transaction.GUID=\"%s\"", (LPWSTR)m_sGUID);
IWmiDbHandle *pHandle = NULL; hr = GetObject_Internal(wPath, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHandle); CReleaseMe r1 (pHandle); if (SUCCEEDED(hr)) { _IWmiObject *pObj = NULL; hr = pHandle->QueryInterface(IID__IWmiObject, (void **)&pObj); CReleaseMe r2 (pObj); if (SUCCEEDED(hr)) { LPWSTR lpTemp = GetPropertyVal(L"State", pObj); CDeleteMe <wchar_t> d (lpTemp); *puState = _wtol(lpTemp); //hr = pObj->ReadProp(L"State", 0, sizeof(ULONG), NULL,
// NULL, NULL, NULL, puState);
} }
return hr; }
//***************************************************************************
//
// CWmiDbSession::NormalizeObjectPathGet
//
//***************************************************************************
HRESULT CWmiDbSession::NormalizeObjectPathGet(IWmiDbHandle __RPC_FAR *pScope, IWbemPath __RPC_FAR *pPath, LPWSTR * lpNewPath, BOOL *bDefault, SQL_ID *pClassId, SQL_ID *pScopeId, CSQLConnection *pConn) { HRESULT hr = WBEM_S_NO_ERROR; BOOL bNs = FALSE; BOOL bDone = FALSE; LPWSTR lpTempPath = NULL; BOOL bDelete = TRUE; BOOL bIsRelative = TRUE; SQL_ID dScopeId = 0; if (pScope) dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId;
// For retrieval behavior, we only want to know if
// the object is found in the default namespace
// or the custom repository.
if (bDefault) *bDefault = TRUE;
if (!pPath) hr = WBEM_E_INVALID_PARAMETER; else { ULONGLONG uIsInstance = 0; hr = pPath->GetInfo(0, &uIsInstance);
wchar_t wTemp[1]; DWORD dwLen = 1;
if (!(uIsInstance & WBEMPATH_INFO_IS_PARENT)) { pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, wTemp); if (dwLen) { dwLen += 1024; lpTempPath = new wchar_t [dwLen]; if (lpTempPath) hr = pPath->GetText(WBEMPATH_GET_ORIGINAL, &dwLen, lpTempPath); else { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } } } else { lpTempPath = new wchar_t [4096]; if (!lpTempPath) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } }
// First, are we just asking to find the current parent.
// Special case.
if (!(uIsInstance & WBEMPATH_INFO_IS_PARENT) && !wcslen(lpTempPath)) { hr = WBEM_E_INVALID_PARAMETER; goto Exit; }
if (SUCCEEDED(hr)) { if (uIsInstance & WBEMPATH_INFO_IS_PARENT) { if (bDefault) *bDefault = TRUE; if (lpNewPath) { wcscpy(lpTempPath, L".."); *lpNewPath = lpTempPath; bDelete = FALSE; } } // This must be a path to an object.
else { wchar_t wServer[128]; ULONG uLen = 128; hr = pPath->GetServer(&uLen, wServer); if (SUCCEEDED(hr) && wcslen(wServer) > 1) bIsRelative = FALSE;
SQL_ID dClassId = 0; WCHAR *pClass = new wchar_t [512]; if (!pClass) hr = WBEM_E_OUT_OF_MEMORY; else { DWORD dwLen = 1024; hr = pPath->GetClassName(&dwLen, pClass); if (FAILED(hr)) { delete pClass; pClass = NULL; } CDeleteMe <wchar_t> r0 (pClass);
// We have a valid path (we hope).
// Go through each namespace and scope
// until we have hit the instance or class.
ULONG dwNumNamespaces = 0, dwNumScopes = 0; wchar_t wBuff[1024]; BOOL bNeedSlash = FALSE;
pPath->GetNamespaceCount(&dwNumNamespaces); pPath->GetScopeCount(&dwNumScopes);
lpTempPath[0] = L'\0';
// Process the namespaces.
for (ULONG i = 0; i < dwNumNamespaces; i++) { dwLen = 1024; hr = pPath->GetNamespaceAt(i, &dwLen, wBuff); if (SUCCEEDED(hr)) { if (bNeedSlash) wcscat(lpTempPath, L"\\"); else bNeedSlash = TRUE; wcscat(lpTempPath, wBuff);
if (!_wcsicmp(lpTempPath, m_sNamespacePath)) { bNeedSlash = FALSE; lpTempPath[0] = L'\0'; } } }
if (wcslen(lpTempPath)) { LPWSTR lpKey = GetKeyString(lpTempPath); CDeleteMe <wchar_t> r2 (lpKey); if (!lpKey || !wcslen(lpKey)) { ERRORTRACE((LOG_WBEMCORE, "Invalid scope text in CWmiDbSession::NormalizeObjectPathGet (%S) \n", lpTempPath)); hr = WBEM_E_INVALID_PARAMETER; goto Exit; } hr = GetSchemaCache()->GetNamespaceID(lpKey, dScopeId); if (FAILED(hr)) goto Exit; }
// Process scopes.
if (dwNumScopes) dwNumScopes--;
for ( i = 0; i < dwNumScopes; i++) { dwLen = 1024; IWbemPathKeyList *pScopeKeys = NULL; hr = pPath->GetScope(i, &dwLen, wBuff, &pScopeKeys); if (SUCCEEDED(hr)) { if (bNeedSlash) wcscat(lpTempPath, L":"); else bNeedSlash = TRUE; LoadClassInfo(pConn, wBuff, dScopeId, TRUE);
LPWSTR lpTemp = GetSchemaCache()->GetKeyRoot(wBuff, dScopeId); CDeleteMe <wchar_t> d (lpTemp); if (lpTemp) { wcscat(lpTempPath, lpTemp); } else wcscat(lpTempPath, wBuff); // OK.. Could be a remote path
hr = MakeKeyListString(dScopeId, &((CWmiDbController *)m_pController)->SchemaCache, wBuff, pScopeKeys, lpTempPath); } }
if (wcslen(lpTempPath)) { LPWSTR lpKey = GetKeyString(lpTempPath); CDeleteMe <wchar_t> r2 (lpKey); if (!lpKey || !wcslen(lpKey)) { ERRORTRACE((LOG_WBEMCORE, "Invalid scope text in CWmiDbSession::NormalizeObjectPathGet (%S) \n", lpTempPath)); hr = WBEM_E_INVALID_PARAMETER; goto Exit; }
hr = GetSchemaCache()->GetNamespaceID(lpKey, dScopeId); if (FAILED(hr)) goto Exit; }
if (pClass && wcslen(pClass)) { BOOL bDeep = (uIsInstance & WBEMPATH_INFO_IS_INST_REF);
// Make sure this dynasty is in the cache.
LoadClassInfo(pConn, pClass, dScopeId, bDeep);
// If this is a class or instance, process the data
hr = GetSchemaCache()->GetClassID (pClass, dScopeId, dClassId); if (SUCCEEDED(hr) && pClass) { IWbemPathKeyList *pKeyList = NULL;
if (dClassId == INSTANCESCLASSID && (uIsInstance & WBEMPATH_INFO_IS_INST_REF)) { if (lpNewPath) { dwLen = 1024;
hr = pPath->GetKeyList(&pKeyList); CReleaseMe r (pKeyList);
hr = pKeyList->GetKey(0, 0, NULL, NULL, &dwLen, lpTempPath, NULL); *lpNewPath = lpTempPath; bDelete = FALSE; bDone = TRUE; } } else {
// If they specified a path like '__Namespace="root" '...
if ((!_wcsicmp(pClass, L"__Namespace") || GetSchemaCache()->IsDerivedClass(NAMESPACECLASSID, dClassId)) && (uIsInstance & WBEMPATH_INFO_IS_INST_REF)) { bNs = TRUE; hr = pPath->GetKeyList(&pKeyList); CReleaseMe r (pKeyList); if (SUCCEEDED(hr)) { dwLen = 1024; hr = pKeyList->GetKey(0, 0, NULL, NULL, &dwLen, lpTempPath, NULL); } } else { if (bNeedSlash) wcscat(lpTempPath, L":");
if (uIsInstance & WBEMPATH_INFO_IS_CLASS_REF) wcscat(lpTempPath, pClass); else { LPWSTR lpTemp = GetSchemaCache()->GetKeyRoot(pClass, dScopeId); CDeleteMe <wchar_t> d (lpTemp); if (lpTemp) wcscat(lpTempPath, lpTemp); else { hr = WBEM_E_INVALID_OBJECT_PATH; goto Exit; } }
if (uIsInstance & WBEMPATH_INFO_IS_CLASS_REF && wcslen(pClass) > 2 && pClass[0] == L'_' && pClass[1] == L'_') { *lpNewPath = lpTempPath; bDelete = FALSE; bDone = TRUE; } else if (uIsInstance & WBEMPATH_INFO_IS_INST_REF) { hr = pPath->GetKeyList(&pKeyList); CReleaseMe r (pKeyList); if (SUCCEEDED(hr)) { hr = MakeKeyListString(dScopeId, &((CWmiDbController *)m_pController)->SchemaCache, pClass, pKeyList, lpTempPath); } if (bDefault) { // Instances of system classes are always default
// Other instances are whatever their scope is.
if (wcslen(pClass) >= 2 && pClass[0] == L'_' && pClass[1] == L'_') *bDefault = TRUE; // all system classes are default
else if (pScope) // other instances inherit from the scope.
*bDefault = ((CWmiDbHandle *)pScope)->m_bDefault;
} } } } } else { if (uIsInstance & WBEMPATH_INFO_IS_INST_REF) { IWbemPathKeyList *pKeyList = NULL; hr = pPath->GetKeyList(&pKeyList); CReleaseMe rm1(pKeyList); if (SUCCEEDED(hr)) { ULONG uNumKeys = 0; hr = pKeyList->GetCount(&uNumKeys); if (SUCCEEDED(hr)) { if (!uNumKeys) bNs = TRUE; } } else bNs = TRUE; } else bNs = TRUE;
if (bNs) { if (!wcslen(lpTempPath) && pClass) wcscpy(lpTempPath, pClass); } else hr = WBEM_E_NOT_FOUND; } } else bNs = TRUE;
if (bNs) { // This is a namespace.
dClassId = NAMESPACECLASSID; hr = WBEM_S_NO_ERROR; }
if (dClassId == INSTANCESCLASSID) bDone = TRUE;
if (SUCCEEDED(hr) && !bDone) { hr = NormalizeObjectPath(pScope, lpTempPath, lpNewPath, bNs, NULL, NULL, pConn, TRUE); bDelete = TRUE; } else if (SUCCEEDED(hr)) { *lpNewPath = lpTempPath; bDelete = FALSE; } if (pClassId) *pClassId = dClassId; if (pScopeId) *pScopeId = dScopeId;
} } } }
Exit: if (bDelete || FAILED(hr)) delete lpTempPath;
return hr; }
//***************************************************************************
//
// CWmiDbSession::NormalizeObjectPath
//
//***************************************************************************
HRESULT CWmiDbSession::NormalizeObjectPath(IWmiDbHandle __RPC_FAR *pScope, LPCWSTR lpPath, LPWSTR * lpNewPath, BOOL bNamespace, CWbemClassObjectProps **ppProps, BOOL *bDefault, CSQLConnection *pConn, BOOL bNoTrunc) { HRESULT hr = WBEM_S_NO_ERROR; IWbemClassObject *pScObj = NULL; // For other behavior, we are interested if the
// object is part of a custom mapping.
// Don't use our default phony namespace.
if (pScope && ((CWmiDbHandle *)pScope)->m_dObjectId != ROOTNAMESPACEID) { DWORD dwTempHandle = ((CWmiDbHandle *)pScope)->m_dwHandleType; ((CWmiDbHandle *)pScope)->m_dwHandleType |= WMIDB_HANDLE_TYPE_STRONG_CACHE; LoadClassInfo(pConn, ((CWmiDbHandle *)pScope)->m_dClassId, FALSE); hr = ((CWmiDbHandle *)pScope)->QueryInterface_Internal(pConn, (void **)&pScObj); ((CWmiDbHandle *)pScope)->m_dwHandleType = dwTempHandle; } CReleaseMe r (pScObj);
if (SUCCEEDED(hr)) hr = NormalizeObjectPath(pScObj, pScope, lpPath, lpNewPath, bNamespace, ppProps, bDefault, bNoTrunc);
return hr; }
//***************************************************************************
//
// CWmiDbSession::NormalizeObjectPath
//
//***************************************************************************
HRESULT CWmiDbSession::NormalizeObjectPath(IWbemClassObject __RPC_FAR *pScope, IWmiDbHandle *pScope2, LPCWSTR lpPath, LPWSTR * lpNewPath, BOOL bNamespace, CWbemClassObjectProps **ppProps, BOOL *bDefault, BOOL bNoTrunc) { HRESULT hr = WBEM_S_NO_ERROR; _WMILockit lkt(GetCS()); int iSize = 0; if (lpPath) iSize += wcslen(lpPath); iSize += m_sNamespacePath.length();
LPWSTR lpTemp = NULL;
// Don't add our phony namespace to the path.
if (pScope) { CWbemClassObjectProps *pProps = new CWbemClassObjectProps(this, NULL, pScope, &((CWmiDbController *)m_pController)->SchemaCache, ((CWmiDbHandle *)pScope2)->m_dScopeId);
// Next, *undecorate* it. See if the front
// matches the default stuff, and if so, strip it off.
// If it doesn't this is an invalid decoration.
if (pProps) { if (pProps->lpRelPath) iSize += wcslen(pProps->lpRelPath); iSize += 50; if (pProps->lpNamespace) iSize += wcslen(pProps->lpNamespace)+1;
lpTemp = new wchar_t [iSize]; // Save this pointer, since we are assigning it to the return value.
if (lpTemp) { wcscpy(lpTemp,L"");
if (pProps->lpNamespace) { int iLen = wcslen(m_sNamespacePath); if (!_wcsnicmp(pProps->lpNamespace, (const wchar_t*)m_sNamespacePath, iLen)) { if (wcslen(pProps->lpNamespace) == iLen) { wcscpy(pProps->lpNamespace, L""); } else { wchar_t *wTmp = new wchar_t [wcslen(pProps->lpNamespace) + 1]; if (wTmp) { CDeleteMe <wchar_t> r (wTmp); wcscpy(wTmp, pProps->lpNamespace); LPWSTR lpTmp = wTmp + iLen + 1; wcscpy(lpTemp, lpTmp);
if (ppProps) { delete pProps->lpNamespace; pProps->lpNamespace = new wchar_t [wcslen(lpTemp)+1]; if (pProps->lpNamespace) wcscpy(pProps->lpNamespace, lpTemp); else hr = WBEM_E_OUT_OF_MEMORY; } } else hr = WBEM_E_OUT_OF_MEMORY; } } else hr = WBEM_E_INVALID_NAMESPACE; }
if (SUCCEEDED(hr)) { SQL_ID dClassId = 0; GetSchemaCache()->GetClassID (pProps->lpClassName, ((CWmiDbHandle *)pScope2)->m_dObjectId, dClassId); if (!_wcsicmp(L"__Namespace", pProps->lpClassName) || GetSchemaCache()->IsDerivedClass(NAMESPACECLASSID, dClassId) ) { VARIANT vTemp; CClearMe v (&vTemp); if (wcslen(lpTemp)) wcscat(lpTemp, L"\\"); pScope->Get(L"Name", 0, &vTemp, NULL, NULL); if (vTemp.vt == VT_BSTR) wcscat(lpTemp, vTemp.bstrVal); } else { if (wcslen(lpTemp)) wcscat(lpTemp, L":");
if (pProps->lpRelPath) { wcscat(lpTemp, pProps->lpRelPath); } else hr = WBEM_E_INVALID_OBJECT; }
if (lpPath != NULL) { int iLen = wcslen(lpTemp); BOOL bAppend = TRUE; if (!_wcsnicmp(lpPath, lpTemp, iLen)) { int iLen2 = wcslen(lpPath); if (iLen2 > iLen) { if (lpPath[iLen] == L':' || lpPath[iLen] == L'\\') bAppend = FALSE; } else if (iLen2 == iLen) bAppend = FALSE; } if (bAppend) { if (!bNamespace) wcscat(lpTemp, L":"); else wcscat(lpTemp, L"\\"); wcscat(lpTemp, lpPath); } else wcscpy(lpTemp, lpPath); } } if (SUCCEEDED(hr)) { if (ppProps) *ppProps = pProps; else delete pProps; } } else hr = WBEM_E_OUT_OF_MEMORY; } else hr = WBEM_E_OUT_OF_MEMORY; } else { if (!lpPath) iSize = 20;
lpTemp = new wchar_t [iSize]; if (lpTemp) { if (lpPath) wcscpy(lpTemp, lpPath); else lpTemp[0] = L'\0'; } else hr = WBEM_E_OUT_OF_MEMORY; } if (SUCCEEDED(hr)) *lpNewPath = lpTemp; else delete lpTemp;
return hr; }
//***************************************************************************
//
// CWmiDbSession::CleanCache
//
//***************************************************************************
HRESULT CWmiDbSession::CleanCache(SQL_ID dObjId, DWORD dwLockType, void *pObj) { HRESULT hr = WBEM_S_NO_ERROR; hr = ((CWmiDbController *)m_pController)->LockCache.DeleteLock(dObjId, false, dwLockType, true, pObj); if (SUCCEEDED(hr)) { // Only remove this item from the cache
// if we deleted the object itself.
// ====================================
if (!dwLockType) { GetObjectCache()->DeleteObject(dObjId); GetSchemaCache()->DeleteClass(dObjId); GetSchemaCache()->DeleteNamespace(dObjId); } }
return hr; }
//***************************************************************************
//
// CWmiDbSession::VerifyObjectLock
//
//***************************************************************************
HRESULT CWmiDbSession::VerifyObjectLock (SQL_ID dObjectId, DWORD dwType, DWORD dwVer) { HRESULT hr = WBEM_S_NO_ERROR;
DWORD dwLockType, dwVersion; bool bImmediate = true;
if ((dwType & 0xF0000000) == WMIDB_HANDLE_TYPE_SUBSCOPED) bImmediate = false; hr = ((CWmiDbController *)m_pController)->LockCache.GetCurrentLock(dObjectId, bImmediate, dwLockType, &dwVersion); if (SUCCEEDED(hr)) { // This handle was invalidated by someone else.
if (!dwType) hr = E_HANDLE; // This is a versioned handle, which was out-of-date.
else if ((dwType & 0xF) == WMIDB_HANDLE_TYPE_VERSIONED) { if (dwVer < dwVersion) hr = WBEM_E_HANDLE_OUT_OF_DATE; }
// There is a lock outstanding which has precedence
// over this one.
if (((dwLockType & 0xF) == WMIDB_HANDLE_TYPE_PROTECTED || (dwLockType & 0xF) == WMIDB_HANDLE_TYPE_EXCLUSIVE) && ((dwLockType & 0xF) != (dwType & 0xF))) hr = WBEM_E_ACCESS_DENIED; } else hr = 0;
return hr; }
//***************************************************************************
//
// CWmiDbSession::ShutDown
//
//***************************************************************************
HRESULT CWmiDbSession::ShutDown () { HRESULT hr = WBEM_S_NO_ERROR;
_WMILockit lkt(GetCS());
try { if (m_pController) { ((CWmiDbController *)m_pController)->ReleaseSession(this); m_pController->Release(); m_pController = NULL; } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::ShutDown\n")); hr = WBEM_E_CRITICAL_ERROR; }
return hr; }
//***************************************************************************
//
// CWmiDbSession::AddTransLock
//
//***************************************************************************
HRESULT CWmiDbSession::AddTransLock(SQL_ID dObjectId, DWORD dwHandleType) { HRESULT hr = WBEM_S_NO_ERROR;
SessionLock *pLock = new SessionLock; if (pLock) { DWORD dwVersion = 0;
pLock->dObjectId = dObjectId; pLock->dwHandleType = dwHandleType;
m_TransLocks.push_back(pLock); } else hr = WBEM_E_OUT_OF_MEMORY;
return hr;
}
//***************************************************************************
//
// CWmiDbSession::CleanTransLocks
//
//***************************************************************************
HRESULT CWmiDbSession::CleanTransLocks() { HRESULT hr = WBEM_S_NO_ERROR;
for (int i = 0; i < m_TransLocks.size(); i++) { SessionLock *pLock = m_TransLocks.at(i); if (pLock) { hr = ((CWmiDbController *)m_pController)->LockCache.DeleteLock( pLock->dObjectId, false, pLock->dwHandleType); } }
m_TransLocks.clear();
return hr; }
//***************************************************************************
//
// CWmiDbSession::LockExists
//
//***************************************************************************
BOOL CWmiDbSession::LockExists (SQL_ID dObjId) { BOOL bRet = FALSE;
for (int i = 0; i < m_TransLocks.size(); i++) { SessionLock *pLock = m_TransLocks.at(i); if (pLock) { if (pLock->dObjectId == dObjId) { bRet = TRUE; break; } } }
return bRet;
}
//***************************************************************************
//
// CWmiDbSession::UnlockDynasties
//
//***************************************************************************
HRESULT CWmiDbSession::UnlockDynasties(BOOL bDelete) { HRESULT hr = WBEM_S_NO_ERROR; _WMILockit lkt(GetCS());
DWORD dwRefCount = Release_Lock(); if (!dwRefCount) { DWORD dwThread = GetCurrentThreadId();
SQLIDs *pIDs = &m_Dynasties[dwThread];
// Reference count per object (IWmiDbHandle, IWmiDbIterator)
// Backup fail-safe for handles and queries.
if (pIDs) { for (int i = 0; i < pIDs->size(); i++) { SQL_ID dClass = pIDs->at(i); if (!bDelete) GetSchemaCache()->UnlockDynasty(dClass); else GetSchemaCache()->DeleteDynasty(dClass); } pIDs->clear(); } SessionDynasties::iterator it = m_Dynasties.find(dwThread); if (it != m_Dynasties.end()) m_Dynasties.erase(it); }
return hr; }
//***************************************************************************
//
// CWmiDbSession::DeleteRows
//
//***************************************************************************
HRESULT CWmiDbSession::DeleteRows(IWmiDbHandle *pScope, IWmiDbIterator *pIterator, REFIID iid) { HRESULT hr = WBEM_S_NO_ERROR;
CFlexArray arrHandles;
IUnknown *pRet = NULL;
DWORD dwNumRet = 0;
// WARNING: This is NOT SCALABLE!!!!
// We're doing it this way because ESS expects
// an event to be fired for each result row of a
// delete query. This should be optimized by
// deleting all the results in one go, and notifying
// ESS that the class had some of its members deleted
HRESULT hRes = pIterator->NextBatch(1, 0, 0, WMIDB_HANDLE_TYPE_COOKIE, iid, &dwNumRet, (void **)&pRet); while (SUCCEEDED(hRes) && dwNumRet) { arrHandles.Add(pRet);
hRes = pIterator->NextBatch(1, 0, 0, WMIDB_HANDLE_TYPE_COOKIE, iid, &dwNumRet, (void **)&pRet); }
// When the iterator returns the last row,
// it will release the db connection
if (arrHandles.Size()) { // Transact this operation so we don't fire events until
// all objects have been deleted.
int iPos = 0; GUID transguid; CoCreateGuid(&transguid);
hr = Begin(0, 0, &transguid); if (SUCCEEDED(hr)) { for (iPos = 0; iPos < arrHandles.Size(); iPos++) { IUnknown *pHandle = (IUnknown *)arrHandles.GetAt(iPos); if (FAILED(hr = DeleteObject(pScope, 0, iid, (void *)pHandle))) { pHandle->Release(); break; } pHandle->Release(); } } if (SUCCEEDED(hr)) hr = Commit(0); else { hr = Rollback(0); // Clean up the handles that were left over.
for (int i = iPos+1; i < arrHandles.Size(); i++) { IUnknown *pHandle = (IUnknown *)arrHandles.GetAt(i); pHandle->Release(); } } }
return hr; }
//***************************************************************************
//
// CWmiDbSession::AddRef_Lock
//
//***************************************************************************
DWORD CWmiDbSession::AddRef_Lock() { DWORD dwThreadId = GetCurrentThreadId();
DWORD dwRefCount = m_ThreadRefCount[dwThreadId]; InterlockedIncrement((LONG *) &dwRefCount); m_ThreadRefCount[dwThreadId] = dwRefCount;
return dwRefCount;
}
//***************************************************************************
//
// CWmiDbSession::Release_Lock
//
//***************************************************************************
DWORD CWmiDbSession::Release_Lock() { DWORD dwThreadId = GetCurrentThreadId();
DWORD dwRefCount = m_ThreadRefCount[dwThreadId]; if (dwRefCount > 0) InterlockedDecrement((LONG *) &dwRefCount);
m_ThreadRefCount[dwThreadId] = dwRefCount;
return dwRefCount; }
|