mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3481 lines
96 KiB
3481 lines
96 KiB
//***************************************************************************
|
|
//
|
|
// (c) 1999-2001 by Microsoft Corp. All Rights Reserved.
|
|
//
|
|
// repcache.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 _WIN32_DCOM
|
|
#include "precomp.h"
|
|
|
|
#include <repcache.h>
|
|
#include <wbemint.h>
|
|
#include <repdrvr.h>
|
|
#include <objbase.h>
|
|
#include <reputils.h>
|
|
#include <crc64.h>
|
|
#include <smrtptr.h>
|
|
|
|
typedef std::map<SQL_ID, bool> SQL_IDMap;
|
|
typedef std::map<SQL_ID, ULONG> SQLRefCountMap;
|
|
typedef std::map <SQL_ID, ClassData *> ClassCache;
|
|
typedef std::map <DWORD, DWORD> Properties;
|
|
typedef std::vector <SQL_ID> SQLIDs;
|
|
typedef std::map <_bstr_t, SQL_ID, _bstr_tNoCase> ClassNames;
|
|
|
|
|
|
#define MAX_WIDTH_SCHEMANAME 127 // Smallest property name for Jet / SQL
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::CObjectCache
|
|
//
|
|
//***************************************************************************
|
|
|
|
CObjectCache::CObjectCache()
|
|
{
|
|
m_dwMaxSize = 262140;
|
|
InitializeCriticalSection(&m_cs);
|
|
m_dwUsed = 0;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::~CObjectCache
|
|
//
|
|
//***************************************************************************
|
|
CObjectCache::~CObjectCache()
|
|
{
|
|
EmptyCache();
|
|
DeleteCriticalSection(&m_cs);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::EmptyCache
|
|
//
|
|
//***************************************************************************
|
|
void CObjectCache::EmptyCache()
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
m_ObjCache.Empty();
|
|
m_dwUsed = 0;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::GetObject
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CObjectCache::GetObject (LPCWSTR lpPath, IWbemClassObject **ppObj,
|
|
SQL_ID *dScopeId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
DWORD dwLock = 0;
|
|
|
|
SQL_ID dwID = 0;
|
|
|
|
dwID = CRC64::GenerateHashValue(lpPath);
|
|
hr = GetObject (dwID, ppObj, dScopeId);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::GetObject
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CObjectCache::GetObject (SQL_ID dObjectId, IWbemClassObject **ppObj,
|
|
SQL_ID *dScopeId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
CacheInfo *pObj = NULL;
|
|
|
|
hr = m_ObjCache.Get(dObjectId, &pObj);
|
|
if (pObj)
|
|
{
|
|
pObj->m_tLastAccess = time(0);
|
|
if (ppObj)
|
|
{
|
|
hr = pObj->m_pObj->Clone(ppObj);
|
|
}
|
|
|
|
if (dScopeId)
|
|
*dScopeId = pObj->m_dScopeId;
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::GetObjectId
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CObjectCache::GetObjectId (LPCWSTR lpPath, SQL_ID &dObjId, SQL_ID &dClassId, SQL_ID *dScopeId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
if (lpPath == NULL)
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
else
|
|
{
|
|
dObjId = CRC64::GenerateHashValue(lpPath);
|
|
CacheInfo *pTemp = NULL;
|
|
hr = m_ObjCache.Get(dObjId, &pTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dClassId = pTemp->m_dClassId;
|
|
if (dScopeId)
|
|
*dScopeId = pTemp->m_dScopeId;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::PutObject
|
|
//
|
|
//***************************************************************************
|
|
HRESULT CObjectCache::PutObject (SQL_ID dID, SQL_ID dClassId, SQL_ID dScopeId, LPCWSTR lpPath, bool bStrongCache, IWbemClassObject *_pObj)
|
|
{
|
|
// The cache can't exceed the maximum byte size.
|
|
// and must set current used
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
bool bNew = false;
|
|
|
|
if (!_pObj)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
IWbemClassObject *pObj = NULL;
|
|
hr = _pObj->Clone(&pObj);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
// Don't cache security descriptor
|
|
hr = pObj->Put(L"__SECURITY_DESCRIPTOR", 0, NULL, CIM_UINT8|CIM_FLAG_ARRAY);
|
|
|
|
CacheInfo *pTemp = NULL;
|
|
size_t NewSize;
|
|
|
|
hr = m_ObjCache.Get(dID, &pTemp);
|
|
if (FAILED(hr))
|
|
{
|
|
bNew = true;
|
|
NewSize = GetSize(pObj) + sizeof(CacheInfo) + wcslen(lpPath);
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
else
|
|
NewSize = (GetSize(pObj) - GetSize(pTemp->m_pObj));
|
|
|
|
if ((NewSize + m_dwUsed) > m_dwMaxSize)
|
|
hr = ResizeCache(NewSize, dID, bStrongCache);
|
|
|
|
if (SUCCEEDED(hr) && NewSize)
|
|
{
|
|
if (pTemp)
|
|
{
|
|
IWbemClassObject *pTempObj = pTemp->m_pObj;
|
|
if (pTempObj)
|
|
pTempObj->Release();
|
|
}
|
|
else
|
|
{
|
|
pTemp = new CacheInfo;
|
|
if (!pTemp)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
pTemp->m_bStrong = bStrongCache;
|
|
}
|
|
|
|
pTemp->m_dObjectId = dID;
|
|
pTemp->m_dClassId = dClassId;
|
|
pTemp->m_dScopeId = dScopeId;
|
|
pTemp->m_tLastAccess = time(0);
|
|
delete pTemp->m_sPath;
|
|
pTemp->m_sPath = Macro_CloneLPWSTR(lpPath);
|
|
pTemp->m_pObj = pObj;
|
|
pTemp->m_bStrong = ((int)pTemp->m_bStrong > (int)bStrongCache) ? pTemp->m_bStrong : bStrongCache; // Strong has precendence.
|
|
|
|
if (bNew)
|
|
{
|
|
hr = m_ObjCache.Insert(dID, pTemp);
|
|
}
|
|
|
|
m_dwUsed += NewSize;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::DeleteObject
|
|
//
|
|
//***************************************************************************
|
|
HRESULT CObjectCache::DeleteObject (SQL_ID dID)
|
|
{
|
|
// Set current used
|
|
// Recalculate the number of bytes used.
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
CacheInfo *pObj = NULL;
|
|
|
|
hr = m_ObjCache.Get(dID, &pObj);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (pObj->m_pObj)
|
|
{
|
|
m_dwUsed -= GetSize(pObj->m_pObj);
|
|
// pObj->m_pObj->Release();
|
|
}
|
|
m_dwUsed -= sizeof(CacheInfo);
|
|
m_dwUsed -= wcslen(pObj->m_sPath);
|
|
|
|
hr = m_ObjCache.Delete(dID);
|
|
}
|
|
|
|
if (hr == WBEM_E_NOT_FOUND)
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::ObjectExists
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CObjectCache::ObjectExists (SQL_ID dObjectId)
|
|
{
|
|
return (m_ObjCache.Exists(dObjectId));
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::SetCacheSize
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CObjectCache::SetCacheSize(const DWORD dwMaxSize)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
// Physically resize the cache.
|
|
// If that works, set the variable
|
|
|
|
if (dwMaxSize == 0)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
EmptyCache();
|
|
}
|
|
else if (m_dwMaxSize > dwMaxSize)
|
|
{
|
|
DWORD dwDiff = m_dwMaxSize - dwMaxSize;
|
|
hr = ResizeCache(dwDiff, 0);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
m_dwMaxSize = dwMaxSize;
|
|
|
|
return hr;
|
|
|
|
}
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::GetCurrentUsage
|
|
//
|
|
//***************************************************************************
|
|
HRESULT CObjectCache::GetCurrentUsage(DWORD &dwBytesUsed)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
dwBytesUsed = m_dwUsed;
|
|
|
|
return hr;
|
|
|
|
}
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::GetCacheSize
|
|
//
|
|
//***************************************************************************
|
|
HRESULT CObjectCache::GetCacheSize(DWORD &dwSizeInBytes)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
dwSizeInBytes = m_dwMaxSize;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::FindFirst
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CObjectCache::FindFirst(SQL_ID &dObjectId, SQL_ID &dClassId, SQL_ID *dScopeId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
CListElement *pTemp = NULL;
|
|
pTemp = m_ObjCache.FindFirst();
|
|
if (pTemp != NULL)
|
|
{
|
|
CacheInfo *pTmp = (CacheInfo *)pTemp->m_pObj;
|
|
|
|
pTmp->m_tLastAccess = time(0);
|
|
dObjectId = pTmp->m_dObjectId;
|
|
dClassId = pTmp->m_dClassId;
|
|
if (dScopeId)
|
|
*dScopeId = pTmp->m_dScopeId;
|
|
delete pTemp;
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::FindNext
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CObjectCache::FindNext (SQL_ID dLastId, SQL_ID &dObjectId, SQL_ID &dClassId, SQL_ID *dScopeId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
CListElement *pTemp = NULL;
|
|
pTemp = m_ObjCache.FindNext(dLastId);
|
|
if (pTemp != NULL)
|
|
{
|
|
CacheInfo *pTmp = (CacheInfo *)pTemp->m_pObj;
|
|
|
|
pTmp->m_tLastAccess = time(0);
|
|
dObjectId = pTmp->m_dObjectId;
|
|
dClassId = pTmp->m_dClassId;
|
|
if (dScopeId)
|
|
*dScopeId = pTmp->m_dScopeId;
|
|
delete pTemp;
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::GetSize
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD CObjectCache::GetSize(IWbemClassObject *pObj)
|
|
{
|
|
DWORD dwRet = 0;
|
|
_IWmiObject *pInt = NULL;
|
|
|
|
HRESULT hr = 0;
|
|
hr = pObj->QueryInterface(IID__IWmiObject, (void **)&pInt);
|
|
CReleaseMe rInt (pInt);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
/* No idea how big this can be. Is there a better way to do this?*/
|
|
DWORD dwSize = 0;
|
|
pInt->GetObjectMemory(NULL, dwSize, &dwRet);
|
|
}
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CObjectCache::ResizeCache
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CObjectCache::ResizeCache(DWORD dwReqBytes, SQL_ID dLeave, bool bForce)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// Try to free up dwReqBytes, starting with
|
|
// the oldest weakly cached objects.
|
|
// ========================================
|
|
|
|
while ((dwReqBytes + m_dwUsed) > m_dwMaxSize)
|
|
{
|
|
hr = WBEM_E_BUFFER_TOO_SMALL;
|
|
|
|
CListElement *pTemp = NULL;
|
|
pTemp = m_ObjCache.FindFirst();
|
|
while (pTemp != NULL)
|
|
{
|
|
SQL_ID dID = pTemp->m_dId;
|
|
if (dID && dID != dLeave)
|
|
{
|
|
CacheInfo *pTmp = (CacheInfo *)pTemp->m_pObj;
|
|
if (!pTmp->m_bStrong)
|
|
DeleteObject(dID);
|
|
|
|
if ((dwReqBytes + m_dwUsed) <= m_dwMaxSize)
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
delete pTemp;
|
|
pTemp = m_ObjCache.FindNext(dID);
|
|
}
|
|
|
|
if ((dwReqBytes + m_dwUsed) <= m_dwMaxSize)
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
}
|
|
|
|
// Only remove other strong cached elements
|
|
// if we have to.
|
|
// =========================================
|
|
|
|
if (bForce)
|
|
{
|
|
pTemp = m_ObjCache.FindFirst();
|
|
while (pTemp != NULL)
|
|
{
|
|
SQL_ID dID = pTemp->m_dId;
|
|
if (dID != dLeave)
|
|
{
|
|
DeleteObject(dID);
|
|
|
|
if ((dwReqBytes + m_dwUsed) <= m_dwMaxSize)
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
pTemp = m_ObjCache.FindNext(dID);
|
|
}
|
|
}
|
|
|
|
break; // if here, cache is empty.
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// LockData::GetMaxLock
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD LockData::GetMaxLock(bool bImmediate, bool bSubScopeOnly)
|
|
{
|
|
DWORD dwRet = 0;
|
|
|
|
for (int i = 0; i < m_List.size(); i++)
|
|
{
|
|
LockItem *pItem = m_List.at(i);
|
|
if (pItem)
|
|
{
|
|
if (bImmediate && pItem->m_bLockOnChild)
|
|
continue;
|
|
|
|
if (bSubScopeOnly && !(pItem->m_dwHandleType & WMIDB_HANDLE_TYPE_SUBSCOPED))
|
|
continue;
|
|
|
|
dwRet = GetMaxBytes(pItem->m_dwHandleType, dwRet);
|
|
}
|
|
}
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// LockData::LockExists
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool LockData::LockExists (DWORD dwHandleType)
|
|
{
|
|
bool bRet = false;
|
|
|
|
for (int i = 0; i < m_List.size(); i++)
|
|
{
|
|
LockItem *pItem = m_List.at(i);
|
|
if (pItem)
|
|
{
|
|
if (!pItem->m_bLockOnChild)
|
|
{
|
|
if ((pItem->m_dwHandleType & dwHandleType) == dwHandleType)
|
|
{
|
|
bRet = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::~CLockCache
|
|
//
|
|
//***************************************************************************
|
|
|
|
CLockCache::~CLockCache()
|
|
{
|
|
DeleteCriticalSection(&m_cs);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::GetHandle
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CLockCache::GetHandle(SQL_ID ObjId, DWORD dwType, IWmiDbHandle **ppRet)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
*ppRet = NULL;
|
|
|
|
LockData *temp = NULL;
|
|
hr = m_Cache.Get(ObjId, &temp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LockData *pData = (LockData *)temp;
|
|
if (pData)
|
|
{
|
|
LockItem *pItem = NULL;
|
|
for (int i = 0; i < pData->m_List.size(); i++)
|
|
{
|
|
pItem = pData->m_List.at(i);
|
|
if (pItem->m_dwHandleType == dwType)
|
|
{
|
|
if (pItem->m_pObj)
|
|
{
|
|
pItem->m_pObj->AddRef();
|
|
*ppRet = (IWmiDbHandle *)pItem->m_pObj;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::AddLock
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CLockCache::AddLock(bool bImmediate, SQL_ID ObjId, DWORD Type, IUnknown *pUnk, SQL_ID dNsId,
|
|
SQL_ID dClassId, CSchemaCache *pCache, bool bChg, bool bChildLock, SQL_ID SourceId,
|
|
DWORD *dwVersion)
|
|
{
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
SQL_ID dParentId = 0;
|
|
|
|
if (bChildLock)
|
|
Type &= ~WMIDB_HANDLE_TYPE_AUTODELETE;
|
|
|
|
if (Type & WMIDB_HANDLE_TYPE_AUTODELETE)
|
|
{
|
|
DWORD dwParentLock = 0;
|
|
GetCurrentLock(dNsId, false, dwParentLock);
|
|
if (!(dwParentLock & WMIDB_HANDLE_TYPE_AUTODELETE))
|
|
{
|
|
GetCurrentLock(dClassId, false, dwParentLock);
|
|
if (!(dwParentLock & WMIDB_HANDLE_TYPE_AUTODELETE))
|
|
{
|
|
SQL_ID ClassId = dClassId, dParentId = 0;
|
|
while (SUCCEEDED(pCache->GetParentId(ClassId, dParentId)))
|
|
{
|
|
GetCurrentLock(dParentId, false, dwParentLock);
|
|
if (dwParentLock & WMIDB_HANDLE_TYPE_AUTODELETE)
|
|
break;
|
|
ClassId = dParentId;
|
|
}
|
|
}
|
|
}
|
|
if (dwParentLock & WMIDB_HANDLE_TYPE_AUTODELETE)
|
|
return WBEM_E_INVALID_HANDLE_REQUEST;
|
|
}
|
|
|
|
// If this is a cookie, we really don't
|
|
// care what locks exist, and we do
|
|
// not need to add it to the list.
|
|
// Unless its an auto-delete handle...
|
|
// ======================================
|
|
|
|
if ((Type & 0xF)== WMIDB_HANDLE_TYPE_COOKIE &&
|
|
!(Type & WMIDB_HANDLE_TYPE_AUTODELETE))
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
// If this is a class,
|
|
// use its own ID as the Class ID.
|
|
// ==============================
|
|
|
|
if (dClassId == 1)
|
|
dClassId = ObjId;
|
|
|
|
LockData *temp = NULL;
|
|
hr = m_Cache.Get(ObjId, &temp);
|
|
|
|
LockData *pData = NULL;
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pData = (LockData *)temp;
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_S_NO_ERROR;
|
|
pData = new LockData;
|
|
if (pData)
|
|
{
|
|
pData->m_dObjectId = ObjId;
|
|
pData->m_dwStatus = 0; // Calculated at the end.
|
|
pData->m_dwNumLocks = 0;
|
|
pData->m_dwCompositeStatus = 0;
|
|
pData->m_dwVersion = 1;
|
|
pData->m_dwCompositeVersion = 1;
|
|
m_Cache.Insert(ObjId, pData);
|
|
|
|
// Load the owner list
|
|
|
|
if (!bChildLock)
|
|
{
|
|
SQL_ID dParent = 0, dClass = 0;
|
|
if (dClassId != 2)
|
|
{
|
|
pCache->GetParentNamespace(dNsId, dParent, &dClass);
|
|
while (dParent) // Don't propogate locks across namespaces!
|
|
{
|
|
pData->m_OwnerIds[dParent];
|
|
if (dClass == 2)
|
|
break;
|
|
pCache->GetParentNamespace(dParent, dParent, &dClass);
|
|
}
|
|
pData->m_OwnerIds[dNsId] = true;
|
|
}
|
|
|
|
if (dClassId != ObjId)
|
|
pData->m_OwnerIds[dClassId] = true;
|
|
while (SUCCEEDED(pCache->GetParentId(dClassId, dParentId)))
|
|
{
|
|
pData->m_OwnerIds[dParentId] = 1;
|
|
dClassId = dParentId;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Make sure the parent objects aren't directly locked.
|
|
// ====================================================
|
|
|
|
if (!CanLockHandle(ObjId, Type, bImmediate, false))
|
|
hr = WBEM_E_ACCESS_DENIED;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SQL_IDMap::iterator item = pData->m_OwnerIds.begin();
|
|
while (item != pData->m_OwnerIds.end())
|
|
{
|
|
if (!CanLockHandle((*item).first, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), true, true))
|
|
{
|
|
hr = WBEM_E_ACCESS_DENIED;
|
|
break;
|
|
}
|
|
item++;
|
|
}
|
|
}
|
|
|
|
// If all that worked, we can now attempt to
|
|
// add the lock to this object.
|
|
// =========================================
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LockItem *pItem = NULL;
|
|
|
|
// Now we need to see if this lock already exists
|
|
// for this handle type.
|
|
// ==============================================
|
|
|
|
pItem = new LockItem;
|
|
if (pItem)
|
|
{
|
|
pItem->m_dwHandleType = Type;
|
|
pItem->m_pObj = pUnk;
|
|
pItem->m_dSourceId = SourceId;
|
|
pItem->m_dwVersion = pData->m_dwVersion;
|
|
|
|
if (bChildLock)
|
|
pItem->m_bLockOnChild = true;
|
|
else
|
|
pItem->m_bLockOnChild = false;
|
|
|
|
// Attempt to lock all the parent objects.
|
|
// Pass in zeroes for namespace and class Ids
|
|
// so we don't recurse.
|
|
|
|
if (dNsId && dClassId != 2)
|
|
{
|
|
hr = AddLock(true, dNsId, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, true, ObjId);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SQL_ID dParent = 0, dClass = 0;
|
|
pCache->GetParentNamespace(dNsId, dParent, &dClass);
|
|
while (dParent)
|
|
{
|
|
hr = AddLock(true, dParent, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, true, ObjId);
|
|
// Don't propogate locks across namespaces.
|
|
if (dClass == 2)
|
|
break;
|
|
pCache->GetParentNamespace(dParent, dParent, &dClass);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (dClassId != 1 && dClassId != 0) // Disregard the __Class class
|
|
{
|
|
if (dClassId != ObjId) // We already saved this one.
|
|
hr = AddLock(true, dClassId, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, true, ObjId);
|
|
|
|
hr = pCache->GetParentId(dClassId, dParentId);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
hr = AddLock(true, dParentId, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, true, ObjId);
|
|
hr = pCache->GetParentId(dParentId, dParentId);
|
|
}
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
// If this is a blocking handle, make sure
|
|
// we lock out any existing handles on child
|
|
// objects. If there any other locks on sub
|
|
// components of this object, they should be
|
|
// in the list at this point.
|
|
// If this is a versioned handle, that needs
|
|
// to be invalidated if there is an immediate
|
|
// change to the parent object!!
|
|
|
|
if (Type & WMIDB_HANDLE_TYPE_SUBSCOPED)
|
|
{
|
|
for (int i = 0; i < pData->m_List.size(); i++)
|
|
{
|
|
LockItem *pTemp = pData->m_List.at(i);
|
|
if (pTemp && pTemp->m_dSourceId != 0)
|
|
AddLock(true, pTemp->m_dSourceId, (Type &~WMIDB_HANDLE_TYPE_SUBSCOPED), pUnk, 0, 0, 0, bChg, false, ObjId);
|
|
}
|
|
}
|
|
|
|
// Only increment version type if this object changed,
|
|
// or if there is an outstanding versioned|subscoped
|
|
// handle type on this object and a child object chgd.
|
|
// ====================================================
|
|
|
|
if (bChg)
|
|
{
|
|
if (!bChildLock)
|
|
{
|
|
pData->m_dwVersion++;
|
|
pData->m_dwCompositeVersion++;
|
|
pItem->m_dwVersion = pData->m_dwVersion;
|
|
}
|
|
else if (bChildLock && pData->LockExists(WMIDB_HANDLE_TYPE_VERSIONED|WMIDB_HANDLE_TYPE_SUBSCOPED))
|
|
pData->m_dwCompositeVersion++;
|
|
}
|
|
|
|
pData->m_List.push_back(pItem);
|
|
pData->m_dwNumLocks++;
|
|
|
|
// Update the lock type
|
|
// ====================
|
|
|
|
pData->m_dwStatus = pData->GetMaxLock(true);
|
|
pData->m_dwCompositeStatus = pData->GetMaxLock(false);
|
|
|
|
if (dwVersion)
|
|
{
|
|
if (bImmediate)
|
|
*dwVersion = pData->m_dwVersion;
|
|
else
|
|
*dwVersion = pData->m_dwCompositeVersion;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::DeleteLock
|
|
//
|
|
//***************************************************************************
|
|
HRESULT CLockCache::DeleteLock(SQL_ID ObjId, bool bChildLock, DWORD HandleType, bool bDelChildren, void *pObj)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
// If this is the only lock,
|
|
// remove the whole thing.
|
|
// Otherwise just remove the item
|
|
// Update the master lock
|
|
// ==============================
|
|
|
|
LockData *pData = NULL;
|
|
LockData *temp = NULL;
|
|
|
|
hr = m_Cache.Get(ObjId, &temp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pData = (LockData *)temp;
|
|
// If they specify a handle of zero,
|
|
// we delete all entries for this ID.
|
|
|
|
if (HandleType)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
LockItem *pItem = NULL;
|
|
for (int i = 0; i < pData->m_List.size(); i++)
|
|
{
|
|
pItem = pData->m_List.at(i);
|
|
if (pItem->m_dwHandleType == HandleType && (pItem->m_pObj == pObj))
|
|
{
|
|
if (bChildLock && !pItem->m_bLockOnChild)
|
|
continue;
|
|
|
|
if (pItem->m_pObj)
|
|
((CWmiDbHandle *)pItem->m_pObj)->m_dwHandleType = 0;
|
|
|
|
delete pItem;
|
|
pData->m_List.erase(&pData->m_List.at(i));
|
|
pData->m_dwNumLocks--;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pObj && !bFound)
|
|
{
|
|
for (int i = 0; i < pData->m_List.size(); i++)
|
|
{
|
|
pItem = pData->m_List.at(i);
|
|
if (pItem->m_dwHandleType == HandleType)
|
|
{
|
|
if (bChildLock && !pItem->m_bLockOnChild)
|
|
continue;
|
|
|
|
delete pItem;
|
|
pData->m_List.erase(&pData->m_List.at(i));
|
|
pData->m_dwNumLocks--;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bDelChildren)
|
|
{
|
|
// Remove this lock from all the
|
|
// owner objects (namespaces, classes)
|
|
// ===================================
|
|
|
|
SQL_IDMap::iterator walk = pData->m_OwnerIds.begin();
|
|
while (walk != pData->m_OwnerIds.end())
|
|
{
|
|
SQL_ID dId = (*walk).first;
|
|
hr = DeleteLock(dId, true, (HandleType &~WMIDB_HANDLE_TYPE_SUBSCOPED), false, pObj);
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
walk++;
|
|
}
|
|
|
|
// Remove this lock from the child
|
|
// objects that we previously
|
|
// locked out.
|
|
// ===============================
|
|
|
|
if (HandleType & WMIDB_HANDLE_TYPE_SUBSCOPED)
|
|
{
|
|
for (int i = 0; i < pData->m_List.size(); i++)
|
|
{
|
|
LockItem *pTemp = pData->m_List.at(i);
|
|
if (pTemp && pTemp->m_dSourceId != 0)
|
|
DeleteLock(pTemp->m_dSourceId, true, (HandleType &~WMIDB_HANDLE_TYPE_SUBSCOPED), false, pObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
// If that worked, we can
|
|
// remove this entry from the
|
|
// the lock cache.
|
|
// ===========================
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pData->m_dwStatus = pData->GetMaxLock(true);
|
|
pData->m_dwCompositeStatus = pData->GetMaxLock(false);
|
|
|
|
// Delete if this is the last lock...
|
|
if (!pData->m_dwNumLocks)
|
|
hr = m_Cache.Delete(ObjId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This object was deleted. We have to
|
|
// invalidate all the handles for this object.
|
|
// ==========================================
|
|
|
|
LockItem *pItem = NULL;
|
|
for (int i = 0; i < pData->m_List.size(); i++)
|
|
{
|
|
pItem = pData->m_List.at(i);
|
|
|
|
if (pItem && pItem->m_pObj)
|
|
((CWmiDbHandle *)pItem->m_pObj)->m_dwHandleType = WMIDB_HANDLE_TYPE_INVALID;
|
|
}
|
|
|
|
hr = m_Cache.Delete(ObjId);
|
|
}
|
|
}
|
|
else if (hr == WBEM_E_NOT_FOUND)
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::GetCurrentLock
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CLockCache::GetCurrentLock(SQL_ID ObjId, bool bImmediate, DWORD &HandleType, DWORD *Version)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
LockData *pData = NULL;
|
|
LockData *temp;
|
|
|
|
hr = m_Cache.Get(ObjId, &temp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pData = (LockData *)temp;
|
|
if (bImmediate)
|
|
HandleType = pData->m_dwStatus;
|
|
else
|
|
HandleType = pData->m_dwCompositeStatus;
|
|
|
|
if (Version)
|
|
{
|
|
if (bImmediate)
|
|
*Version = pData->m_dwVersion;
|
|
else
|
|
*Version = pData->m_dwCompositeVersion;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::GetAllLocks
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CLockCache::GetAllLocks(SQL_ID ObjId, SQL_ID ClassId, SQL_ID NsId, CSchemaCache *pSchema,
|
|
bool bImmediate, DWORD &HandleType, DWORD *Version)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
DWORD dwCurrType = 0, dwTemp = 0;
|
|
SQL_ID dParentId = 0;
|
|
|
|
hr = GetCurrentLock(ObjId, bImmediate, dwCurrType, Version);
|
|
|
|
if (SUCCEEDED(GetCurrentLock(ClassId, bImmediate, dwTemp)))
|
|
{
|
|
if (dwTemp & WMIDB_HANDLE_TYPE_SUBSCOPED)
|
|
dwCurrType = GetMaxBytes(dwCurrType, dwTemp);
|
|
}
|
|
|
|
if (SUCCEEDED(GetCurrentLock(NsId, bImmediate, dwTemp)))
|
|
{
|
|
if (dwTemp & WMIDB_HANDLE_TYPE_SUBSCOPED)
|
|
dwCurrType = GetMaxBytes(dwCurrType, dwTemp);
|
|
}
|
|
|
|
if (ClassId)
|
|
{
|
|
while (SUCCEEDED(pSchema->GetParentId(ClassId, dParentId)))
|
|
{
|
|
if (SUCCEEDED(GetCurrentLock(dParentId, bImmediate, dwTemp)))
|
|
{
|
|
if (dwTemp & WMIDB_HANDLE_TYPE_SUBSCOPED)
|
|
dwCurrType = GetMaxBytes(dwCurrType, dwTemp);
|
|
}
|
|
ClassId = dParentId;
|
|
}
|
|
}
|
|
HandleType = dwCurrType;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::CanLockHandle
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CLockCache::CanLockHandle (SQL_ID ObjId, DWORD RequestedHandleType, bool bImmediate, bool bSubscopedOnly)
|
|
{
|
|
bool bRet = true; // If not found, they can definitely lock it...
|
|
DWORD dwCurrType = 0;
|
|
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
LockData *pData = NULL;
|
|
LockData *temp;
|
|
|
|
HRESULT hr = m_Cache.Get(ObjId, &temp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pData = (LockData *)temp;
|
|
dwCurrType = pData->GetMaxLock(bImmediate, bSubscopedOnly);
|
|
|
|
if (bRet)
|
|
{
|
|
switch (dwCurrType & 0xF)
|
|
{
|
|
case WMIDB_HANDLE_TYPE_COOKIE:
|
|
case WMIDB_HANDLE_TYPE_VERSIONED: // Weak handles always succeed.
|
|
bRet = true;
|
|
break;
|
|
case WMIDB_HANDLE_TYPE_EXCLUSIVE: // Exclusive access.
|
|
if ((RequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_COOKIE &&
|
|
(RequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_VERSIONED)
|
|
bRet = false;
|
|
break;
|
|
case WMIDB_HANDLE_TYPE_PROTECTED: // Read only
|
|
if ((RequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_EXCLUSIVE)
|
|
bRet = true;
|
|
else
|
|
bRet = false;
|
|
break;
|
|
default:
|
|
bRet = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::CanRenderObject
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CLockCache::CanRenderObject (SQL_ID ObjId, SQL_ID ClassId, SQL_ID NsId, CSchemaCache *pSchema, DWORD RequestedHandleType, bool bImmediate)
|
|
{
|
|
bool bRet = true; // If not found, they can definitely lock it...
|
|
DWORD dwCurrType;
|
|
SQL_ID dParentId = 0;
|
|
|
|
// Get the lock for this
|
|
// object and all its ancestors.
|
|
// =============================
|
|
|
|
HRESULT hr = GetAllLocks(ObjId, ClassId, NsId, pSchema, bImmediate, RequestedHandleType);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dwCurrType = RequestedHandleType & 0xF;
|
|
switch (dwCurrType)
|
|
{
|
|
case WMIDB_HANDLE_TYPE_COOKIE:
|
|
case WMIDB_HANDLE_TYPE_VERSIONED: // Weak handles always succeed.
|
|
bRet = true;
|
|
break;
|
|
case WMIDB_HANDLE_TYPE_EXCLUSIVE: // Exclusive access.
|
|
bRet = false;
|
|
break;
|
|
case WMIDB_HANDLE_TYPE_PROTECTED: // Read only
|
|
if ((RequestedHandleType & 0xF) != WMIDB_HANDLE_TYPE_EXCLUSIVE)
|
|
bRet = true;
|
|
else
|
|
bRet = false;
|
|
break;
|
|
default:
|
|
bRet = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CLockCache::IncrementVersion
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CLockCache::IncrementVersion(SQL_ID ObjId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
LockData *pData = NULL;
|
|
LockData *temp;
|
|
|
|
hr = m_Cache.Get(ObjId, &temp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pData = (LockData *)temp;
|
|
pData->m_dwVersion++;
|
|
pData->m_dwCompositeVersion++;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// PropertyData::PropertyData
|
|
//
|
|
//***************************************************************************
|
|
|
|
PropertyData::PropertyData()
|
|
{
|
|
m_dwClassID = 0;
|
|
m_dwStorageType = 0;
|
|
m_dwCIMType = 0;
|
|
m_dwFlags = 0;
|
|
m_dwRefClassID = 0;
|
|
m_dwQPropID = 0;
|
|
m_dwFlavor = 0;
|
|
m_sPropertyName = NULL;
|
|
m_sDefaultValue = NULL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// PropertyData::GetSize
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD PropertyData::GetSize()
|
|
{
|
|
DWORD dwSize = 0;
|
|
|
|
if (m_sPropertyName)
|
|
dwSize += wcslen(m_sPropertyName)*2;
|
|
else
|
|
dwSize += sizeof(LPWSTR);
|
|
|
|
if (m_sDefaultValue)
|
|
dwSize += wcslen(m_sDefaultValue)*2;
|
|
else
|
|
dwSize += sizeof(LPWSTR);
|
|
|
|
dwSize += sizeof(m_dwClassID) +
|
|
sizeof(m_dwStorageType) +
|
|
sizeof(m_dwCIMType) +
|
|
sizeof(m_dwFlags) +
|
|
sizeof(m_dwRefClassID) +
|
|
sizeof(m_dwQPropID) +
|
|
sizeof(m_dwFlavor);
|
|
|
|
return dwSize;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// ClassData::ClassData
|
|
//
|
|
//***************************************************************************
|
|
|
|
ClassData::ClassData()
|
|
{
|
|
m_dwClassID = 0;
|
|
m_dwSuperClassID = 0;
|
|
m_dwDynastyID = 0;
|
|
m_dwScopeID = 0;
|
|
m_dwFlags = 0;
|
|
m_Properties = new PropertyList[10];
|
|
m_dwNumProps = 0;
|
|
m_dwArraySize = 10;
|
|
m_sName = NULL;
|
|
m_sObjectPath = NULL;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// ClassData::GetSize
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD ClassData::GetSize()
|
|
{
|
|
DWORD dwSize = 0;
|
|
|
|
if (m_sName)
|
|
dwSize += wcslen(m_sName)*2;
|
|
else
|
|
dwSize += sizeof(LPWSTR);
|
|
if (m_sObjectPath)
|
|
dwSize += wcslen(m_sObjectPath)*2;
|
|
else
|
|
dwSize += dwSize += sizeof(LPWSTR);
|
|
|
|
dwSize += sizeof(m_dwClassID) +
|
|
sizeof(m_dwSuperClassID) +
|
|
sizeof(m_dwDynastyID) +
|
|
sizeof(m_dwScopeID) +
|
|
sizeof(m_dwNumProps) +
|
|
sizeof(m_dwArraySize) +
|
|
sizeof(m_dwFlags);
|
|
|
|
for (int i=0; i < m_dwNumProps; i++)
|
|
{
|
|
dwSize += sizeof(PropertyList);
|
|
}
|
|
|
|
return dwSize;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// ClassData::InsertProperty
|
|
//
|
|
//***************************************************************************
|
|
|
|
void ClassData::InsertProperty (DWORD PropId, BOOL bIsKey)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
if (m_Properties)
|
|
{
|
|
for (int i = 0; i < m_dwNumProps; i++)
|
|
{
|
|
if (m_Properties[i].m_dwPropertyId == PropId)
|
|
{
|
|
bFound = TRUE;
|
|
m_Properties[i].m_bIsKey = bIsKey;
|
|
break;
|
|
}
|
|
}
|
|
if (!bFound)
|
|
{
|
|
if (m_dwNumProps == m_dwArraySize)
|
|
{
|
|
PropertyList *pList = new PropertyList[m_dwArraySize + 10];
|
|
if (pList)
|
|
{
|
|
memcpy(pList, m_Properties, sizeof(PropertyList) * m_dwArraySize);
|
|
delete m_Properties;
|
|
m_Properties = pList;
|
|
m_dwArraySize += 10;
|
|
}
|
|
}
|
|
|
|
m_Properties[m_dwNumProps].m_dwPropertyId = PropId;
|
|
m_Properties[m_dwNumProps].m_bIsKey = bIsKey;
|
|
m_dwNumProps++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClassData::DeleteProperty (DWORD PropId)
|
|
{
|
|
// Should we clean up the gaps here?
|
|
|
|
if (m_Properties)
|
|
{
|
|
for (int i = 0; i < m_dwNumProps; i++)
|
|
{
|
|
if (m_Properties[i].m_dwPropertyId == PropId)
|
|
{
|
|
m_Properties[i].m_dwPropertyId = 0;
|
|
m_Properties[i].m_bIsKey = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClassData::InsertDerivedClass (SQL_ID dID)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
|
|
for (int i = 0; i < m_DerivedIDs.size(); i++)
|
|
{
|
|
if (m_DerivedIDs.at(i) == dID)
|
|
{
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!bFound)
|
|
m_DerivedIDs.push_back(dID);
|
|
}
|
|
|
|
void ClassData::DeleteDerivedClass (SQL_ID dID)
|
|
{
|
|
for (int i = 0; i < m_DerivedIDs.size(); i++)
|
|
{
|
|
if (m_DerivedIDs.at(i) == dID)
|
|
{
|
|
m_DerivedIDs.erase(&m_DerivedIDs.at(i));
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// NamespaceData::GetSize
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD NamespaceData::GetSize()
|
|
{
|
|
DWORD dwSize = 0;
|
|
|
|
if (m_sNamespaceName)
|
|
dwSize += wcslen(m_sNamespaceName)*2;
|
|
else
|
|
dwSize += sizeof(LPWSTR);
|
|
|
|
if (m_sNamespaceKey)
|
|
dwSize += wcslen(m_sNamespaceKey)*2;
|
|
else
|
|
dwSize += sizeof(LPWSTR);
|
|
|
|
dwSize += sizeof(m_dNamespaceId) +
|
|
sizeof(m_dParentId) +
|
|
sizeof(m_dClassId);
|
|
|
|
return dwSize;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::CSchemaCache
|
|
//
|
|
//***************************************************************************
|
|
|
|
CSchemaCache::CSchemaCache()
|
|
{
|
|
m_dwTotalSize = 0;
|
|
m_dwMaxSize = 204800;
|
|
InitializeCriticalSection(&m_cs);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::~CSchemaCache
|
|
//
|
|
//***************************************************************************
|
|
|
|
CSchemaCache::~CSchemaCache()
|
|
{
|
|
EmptyCache();
|
|
DeleteCriticalSection(&m_cs);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::EmptyCache
|
|
//
|
|
//***************************************************************************
|
|
void CSchemaCache::EmptyCache()
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
m_Cache.Empty();
|
|
m_CCache.Empty();
|
|
m_CIndex.clear();
|
|
m_dwTotalSize = 0;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetPropertyInfo
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetPropertyInfo (DWORD dwPropertyID, _bstr_t *sName, SQL_ID *dwClassID, DWORD *dwStorageType,
|
|
DWORD *dwCIMType, DWORD *dwFlags, SQL_ID *dwRefClassID, _bstr_t *sDefaultValue, DWORD *pdwRefId, DWORD *pdwFlavor)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
PropertyData *pData = NULL;
|
|
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pData);
|
|
if (pData != NULL)
|
|
{
|
|
if (sName) *sName = pData->m_sPropertyName;
|
|
if (dwClassID) *dwClassID = pData->m_dwClassID;
|
|
if (dwStorageType) *dwStorageType = pData->m_dwStorageType;
|
|
if (dwCIMType) *dwCIMType = pData->m_dwCIMType;
|
|
if (dwFlags) *dwFlags = pData->m_dwFlags;
|
|
if (dwRefClassID) *dwRefClassID = pData->m_dwRefClassID;
|
|
if (sDefaultValue) *sDefaultValue = pData->m_sDefaultValue;
|
|
if (pdwRefId) *pdwRefId = pData->m_dwQPropID;
|
|
if (pdwFlavor) *pdwFlavor = pData->m_dwFlavor;
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetPropertyID
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetPropertyID (LPCWSTR lpName, SQL_ID dClassID, DWORD dwFlags, CIMTYPE ct,
|
|
DWORD &PropertyID, SQL_ID *ActualClass, DWORD *Flags, DWORD *Type, BOOL bSys)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
_bstr_t sIndexKey;
|
|
SQL_ID dCurrClass = dClassID;
|
|
|
|
PropertyID = 0;
|
|
|
|
if (lpName && wcslen(lpName) > 2 && lpName[0] == L'_' && lpName[1] == L'_')
|
|
bSys = TRUE;
|
|
|
|
// Try to find this property in this class,
|
|
// or its parent classes.
|
|
|
|
if (dClassID)
|
|
{
|
|
ClassData *pClass = NULL;
|
|
m_CCache.Get(dClassID, &pClass);
|
|
|
|
while (pClass)
|
|
{
|
|
for (int i = 0; i < pClass->m_dwNumProps; i++)
|
|
{
|
|
DWORD dwPropertyID = pClass->m_Properties[i].m_dwPropertyId;
|
|
PropertyData *pPData = NULL;
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pPData);
|
|
|
|
if (!pPData)
|
|
continue;
|
|
if (!_wcsnicmp(pPData->m_sPropertyName, lpName, MAX_WIDTH_SCHEMANAME))
|
|
{
|
|
BOOL bMatch = TRUE;
|
|
if ((dwFlags & REPDRVR_FLAG_NONPROP) ==
|
|
(pPData->m_dwFlags & REPDRVR_FLAG_NONPROP))
|
|
{
|
|
if (dwFlags & REPDRVR_FLAG_NONPROP)
|
|
{
|
|
if (ct != REPDRVR_IGNORE_CIMTYPE)
|
|
{
|
|
if (ct != pPData->m_dwCIMType)
|
|
bMatch = FALSE;
|
|
}
|
|
}
|
|
if (bMatch)
|
|
{
|
|
if (ActualClass)
|
|
*ActualClass = dCurrClass;
|
|
if (Flags)
|
|
*Flags = pPData->m_dwFlags;
|
|
if (Type)
|
|
*Type = pPData->m_dwStorageType;
|
|
PropertyID = dwPropertyID;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
dCurrClass = pClass->m_dwSuperClassID;
|
|
|
|
if (PropertyID || !dCurrClass)
|
|
break;
|
|
pClass = NULL;
|
|
m_CCache.Get(dCurrClass, &pClass);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CListElement *pNext = m_Cache.FindFirst();
|
|
while (pNext)
|
|
{
|
|
SQL_ID dLast = pNext->m_dId;
|
|
|
|
PropertyData *pTemp = (PropertyData *)pNext->m_pObj;
|
|
if (pTemp)
|
|
{
|
|
if (!_wcsnicmp(pTemp->m_sPropertyName,lpName, MAX_WIDTH_SCHEMANAME))
|
|
{
|
|
PropertyID = pNext->m_dId;
|
|
if (ActualClass)
|
|
*ActualClass = pTemp->m_dwClassID;
|
|
if (Flags)
|
|
*Flags = pTemp->m_dwFlags;
|
|
if (Type)
|
|
*Type = pTemp->m_dwStorageType;
|
|
break;
|
|
}
|
|
}
|
|
delete pNext;
|
|
pNext = m_Cache.FindNext(dLast);
|
|
}
|
|
}
|
|
|
|
if (PropertyID == 0)
|
|
{
|
|
if (!bSys)
|
|
hr = WBEM_E_NOT_FOUND;
|
|
else if (dClassID!= 1)
|
|
hr = GetPropertyID(lpName, 1, dwFlags, ct, PropertyID, ActualClass, Flags, Type, FALSE);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::AddPropertyInfo
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::AddPropertyInfo (DWORD dwPropertyID, LPCWSTR lpName, SQL_ID dwClassID, DWORD dwStorageType,
|
|
DWORD dwCIMType, DWORD dwFlags, SQL_ID dwRefClassID, LPCWSTR lpDefault, DWORD dwRefPropID, DWORD dwFlavor)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
PropertyData *pData = NULL;
|
|
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pData);
|
|
if (pData == NULL)
|
|
{
|
|
pData = new PropertyData;
|
|
if (!pData)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
m_Cache.Insert(dTemp, pData);
|
|
}
|
|
else
|
|
m_dwTotalSize -= pData->GetSize();
|
|
|
|
if (pData)
|
|
{
|
|
bool bTruncated = FALSE;
|
|
delete pData->m_sPropertyName;
|
|
pData->m_sPropertyName = TruncateLongText(lpName, MAX_WIDTH_SCHEMANAME,
|
|
bTruncated, MAX_WIDTH_SCHEMANAME, FALSE);
|
|
if (!pData->m_dwClassID)
|
|
pData->m_dwClassID = dwClassID;
|
|
pData->m_dwStorageType = dwStorageType;
|
|
pData->m_dwCIMType = dwCIMType;
|
|
pData->m_dwFlags = dwFlags;
|
|
pData->m_dwRefClassID = dwRefClassID;
|
|
pData->m_dwQPropID = dwRefPropID;
|
|
pData->m_dwFlavor = dwFlavor;
|
|
|
|
ClassData *pCData = NULL;
|
|
m_CCache.Get(dwClassID, &pCData);
|
|
if (pCData)
|
|
{
|
|
pCData->InsertProperty(dwPropertyID, FALSE);
|
|
if (dwFlags & REPDRVR_FLAG_KEYHOLE)
|
|
pCData->m_dwFlags |= REPDRVR_FLAG_KEYHOLE;
|
|
if (dwStorageType == WMIDB_STORAGE_IMAGE)
|
|
pCData->m_dwFlags |= REPDRVR_FLAG_IMAGE;
|
|
if (dwCIMType == CIM_OBJECT)
|
|
pCData->m_dwFlags |= REPDRVR_FLAG_IMAGE;
|
|
m_dwTotalSize += pCData->GetSize();
|
|
}
|
|
m_dwTotalSize += pData->GetSize();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::PropertyChanged
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CSchemaCache::PropertyChanged (LPCWSTR lpName, SQL_ID dwClassID, DWORD dwCIMType, LPCWSTR lpDefault,
|
|
DWORD dwFlags, SQL_ID dwRefClassID, DWORD dwRefPropID, DWORD dwFlavor)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
bool bChg = true;
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
DWORD dwPropertyID = 0;
|
|
PropertyData *pData = NULL;
|
|
|
|
hr = GetPropertyID(lpName, dwClassID, dwFlags, dwCIMType, dwPropertyID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pData);
|
|
if (pData != NULL)
|
|
{
|
|
bChg = false;
|
|
|
|
if (pData->m_dwFlags != dwFlags ||
|
|
pData->m_dwCIMType != dwCIMType ||
|
|
pData->m_dwRefClassID != dwRefClassID ||
|
|
pData->m_dwQPropID != dwRefPropID ||
|
|
_wcsicmp(pData->m_sDefaultValue,lpDefault) ||
|
|
pData->m_dwFlavor != dwFlavor)
|
|
bChg = true;
|
|
}
|
|
}
|
|
|
|
return bChg;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::IsQualifier
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CSchemaCache::IsQualifier(DWORD dwPropertyId)
|
|
{
|
|
bool bRet = false;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
PropertyData *pData = NULL;
|
|
SQL_ID dTemp = dwPropertyId;
|
|
m_Cache.Get(dTemp, &pData);
|
|
if (pData)
|
|
{
|
|
if (pData->m_dwFlags & REPDRVR_FLAG_QUALIFIER)
|
|
bRet = true;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::SetAuxiliaryPropertyInfo
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::SetAuxiliaryPropertyInfo (DWORD dwPropertyID, LPWSTR lpDefault, DWORD dwRefID)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
PropertyData *pData = NULL;
|
|
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pData);
|
|
if (pData)
|
|
{
|
|
delete pData->m_sDefaultValue;
|
|
pData->m_sDefaultValue = Macro_CloneLPWSTR(lpDefault);
|
|
pData->m_dwQPropID = dwRefID;
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::DeleteProperty
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::DeleteProperty (DWORD dwPropertyID, SQL_ID dClassId)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
PropertyData *pData = NULL;
|
|
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pData);
|
|
if (pData)
|
|
{
|
|
SQL_ID dwClassID = pData->m_dwClassID;
|
|
if (dwClassID == dClassId)
|
|
{
|
|
m_dwTotalSize -= pData->GetSize();
|
|
|
|
// delete pData;
|
|
m_Cache.Delete(dwPropertyID);
|
|
ClassData *pCData = NULL;
|
|
m_CCache.Get(dwClassID, &pCData);
|
|
if (pCData)
|
|
{
|
|
m_dwTotalSize -= pCData->GetSize();
|
|
pCData->DeleteProperty(dwPropertyID);
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetClassInfo
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetClassInfo (SQL_ID dwClassID, _bstr_t &sPath, SQL_ID &dwSuperClassID, SQL_ID &dwScopeID,
|
|
DWORD &dwTemp, _bstr_t *pName)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
ClassData *pClass = NULL;
|
|
m_CCache.Get(dwClassID, &pClass);
|
|
if (pClass)
|
|
{
|
|
sPath = pClass->m_sObjectPath;
|
|
if (pName)
|
|
*pName = pClass->m_sName;
|
|
dwSuperClassID = pClass->m_dwSuperClassID;
|
|
dwScopeID = pClass->m_dwScopeID;
|
|
dwTemp = pClass->m_dwFlags;
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::AddClassInfo
|
|
//
|
|
//***************************************************************************
|
|
HRESULT CSchemaCache::AddClassInfo (SQL_ID dwClassID, LPCWSTR lpName, SQL_ID dwSuperClassID, SQL_ID dDynastyId, SQL_ID dwScopeID,
|
|
LPCWSTR lpPath, DWORD dwFlags)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
ClassData *pClass = NULL;
|
|
m_CCache.Get(dwClassID, &pClass);
|
|
if (!pClass)
|
|
{
|
|
pClass = new ClassData;
|
|
if (!pClass)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
m_dwTotalSize -= pClass->GetSize();
|
|
|
|
if (pClass)
|
|
{
|
|
m_CCache.Insert(dwClassID, pClass);
|
|
wchar_t *wTemp = new wchar_t [MAX_WIDTH_SCHEMANAME+30];
|
|
CDeleteMe <wchar_t> r (wTemp);
|
|
if (wTemp)
|
|
{
|
|
bool bTruncated = FALSE;
|
|
delete pClass->m_sName;
|
|
pClass->m_sName = TruncateLongText(lpName, MAX_WIDTH_SCHEMANAME,
|
|
bTruncated, MAX_WIDTH_SCHEMANAME, FALSE);
|
|
|
|
if (wcslen(pClass->m_sName))
|
|
{
|
|
swprintf(wTemp , L"%s_%I64d", pClass->m_sName, dwScopeID);
|
|
m_CIndex[_bstr_t(wTemp)] = dwClassID;
|
|
}
|
|
|
|
pClass->m_dwClassID = dwClassID;
|
|
pClass->m_dwSuperClassID = dwSuperClassID;
|
|
pClass->m_dwDynastyID = dDynastyId;
|
|
|
|
pClass->m_dwScopeID = dwScopeID;
|
|
delete pClass->m_sObjectPath;
|
|
pClass->m_sObjectPath = Macro_CloneLPWSTR(lpPath);
|
|
pClass->m_dwFlags = dwFlags;
|
|
|
|
m_dwTotalSize += pClass->GetSize();
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (dwSuperClassID)
|
|
{
|
|
hr = m_CCache.Get(dwSuperClassID, &pClass);
|
|
if (FAILED(hr))
|
|
{
|
|
hr = AddClassInfo(dwSuperClassID, L"", 0, 0, 0, L"", 0);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_CCache.Get(dwSuperClassID, &pClass);
|
|
}
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pClass->InsertDerivedClass(dwClassID);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::DeleteClass
|
|
//
|
|
//***************************************************************************
|
|
HRESULT CSchemaCache::DeleteClass (SQL_ID dwClassID)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
SQL_ID dParent = 0;
|
|
|
|
// Ignore requests to delete meta_class.
|
|
if (dwClassID == 1)
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
ClassData *pClass = NULL;
|
|
m_CCache.Get(dwClassID, &pClass);
|
|
if (pClass)
|
|
{
|
|
dParent = pClass->m_dwSuperClassID;
|
|
wchar_t *wTemp = new wchar_t [wcslen(pClass->m_sName)+25];
|
|
CDeleteMe <wchar_t> r (wTemp);
|
|
if (wTemp)
|
|
{
|
|
swprintf(wTemp, L"%s_%I64d", pClass->m_sName, pClass->m_dwScopeID);
|
|
|
|
for (int i = 0; i < pClass->m_dwNumProps; i++)
|
|
DeleteProperty(pClass->m_Properties[i].m_dwPropertyId, dwClassID);
|
|
|
|
if (dParent != 0 && dParent != 1)
|
|
{
|
|
hr = m_CCache.Get(dParent, &pClass);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_dwTotalSize -= pClass->GetSize();
|
|
pClass->DeleteDerivedClass(dwClassID);
|
|
}
|
|
}
|
|
|
|
ClassNames::iterator it = m_CIndex.find(wTemp);
|
|
if (it != m_CIndex.end())
|
|
m_CIndex.erase(it);
|
|
m_CCache.Delete(dwClassID);
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetClassID
|
|
//
|
|
//***************************************************************************
|
|
HRESULT CSchemaCache::GetClassID (LPCWSTR lpName, SQL_ID dwScopeID, SQL_ID &dClassID, SQL_ID *pDynasty)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
BOOL bInNamespace = FALSE;
|
|
SQL_ID dClass;
|
|
dClassID = 0;
|
|
|
|
if (!lpName)
|
|
return WBEM_E_NOT_FOUND;
|
|
|
|
GetNamespaceClass(dwScopeID, dClass);
|
|
if (dClass == NAMESPACECLASSID ||
|
|
IsDerivedClass(NAMESPACECLASSID, dClass))
|
|
bInNamespace = TRUE;
|
|
|
|
SQL_ID dParent = 0;
|
|
|
|
bool bTrunc = FALSE;
|
|
|
|
LPWSTR lpClassName = TruncateLongText(lpName, MAX_WIDTH_SCHEMANAME,
|
|
bTrunc, MAX_WIDTH_SCHEMANAME, FALSE);
|
|
CDeleteMe<wchar_t> c (lpClassName);
|
|
|
|
int iLen = wcslen(lpClassName);
|
|
|
|
wchar_t *pTmp = new wchar_t [iLen+25];
|
|
CDeleteMe <wchar_t> r (pTmp);
|
|
if (pTmp)
|
|
{
|
|
swprintf(pTmp, L"%s_%I64d", lpClassName, dwScopeID);
|
|
|
|
dClassID = m_CIndex[pTmp];
|
|
if (!dClassID)
|
|
{
|
|
if (dwScopeID != 0)
|
|
{
|
|
// Check the hierarchy. Maybe this is
|
|
// under a different scope.
|
|
|
|
dParent = dwScopeID;
|
|
while (TRUE)
|
|
{
|
|
GetParentNamespace(dParent, dParent);
|
|
|
|
GetNamespaceClass(dParent, dClass);
|
|
if (dClass == NAMESPACECLASSID ||
|
|
IsDerivedClass(NAMESPACECLASSID, dClass))
|
|
{
|
|
if (bInNamespace)
|
|
break;
|
|
else
|
|
bInNamespace = TRUE;
|
|
}
|
|
|
|
swprintf(pTmp, L"%s_%I64d", lpClassName, dParent);
|
|
dClassID = m_CIndex[pTmp];
|
|
if (!dParent || dClassID)
|
|
break;
|
|
|
|
}
|
|
}
|
|
if (!dClassID)
|
|
{
|
|
swprintf(pTmp, L"%s_0", lpClassName);
|
|
dClassID = m_CIndex[pTmp];
|
|
}
|
|
}
|
|
|
|
|
|
if (!dClassID)
|
|
hr = WBEM_E_NOT_FOUND;
|
|
else if (pDynasty)
|
|
{
|
|
ClassData *pClass = NULL;
|
|
hr = m_CCache.Get(dClassID, &pClass);
|
|
if (SUCCEEDED(hr))
|
|
*pDynasty = pClass->m_dwDynastyID;
|
|
}
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetDynasty
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetDynasty (SQL_ID dClassId, SQL_ID &dDynasty, _bstr_t &sClassName)
|
|
{
|
|
HRESULT hr = 0;
|
|
_WMILockit lk(&m_cs);
|
|
|
|
ClassData *pClass = NULL;
|
|
dDynasty = 0;
|
|
|
|
hr = m_CCache.Get(dClassId, &pClass);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (pClass->m_dwSuperClassID == 1 || pClass->m_dwSuperClassID == 0)
|
|
{
|
|
dDynasty = dClassId;
|
|
sClassName = pClass->m_sName;
|
|
}
|
|
else
|
|
{
|
|
hr = GetDynasty(pClass->m_dwSuperClassID, dDynasty, sClassName);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetNamespaceID
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetNamespaceID(LPCWSTR lpKey, SQL_ID &dObjectId)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_bstr_t sName = lpKey;
|
|
if (!sName.length())
|
|
sName = L"root";
|
|
|
|
dObjectId = CRC64::GenerateHashValue(sName);
|
|
|
|
if (!m_NamespaceIds.Exists(dObjectId))
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetNamespaceClass
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetNamespaceClass(SQL_ID dScopeId, SQL_ID &dScopeClassId)
|
|
{
|
|
NamespaceData *pTemp = NULL;
|
|
HRESULT hr = m_NamespaceIds.Get(dScopeId, &pTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dScopeClassId=pTemp->m_dClassId;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetParentNamespace
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetParentNamespace(SQL_ID dObjectId, SQL_ID &dParentId, SQL_ID *dParentClassId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
dParentId = 0;
|
|
if (dObjectId)
|
|
{
|
|
NamespaceData *pTemp = NULL;
|
|
hr = m_NamespaceIds.Get(dObjectId, &pTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dParentId = pTemp->m_dParentId;
|
|
if (dParentClassId && dParentId)
|
|
{
|
|
m_NamespaceIds.Get(dParentId, &pTemp);
|
|
*dParentClassId = pTemp->m_dClassId;
|
|
}
|
|
else if (dParentClassId)
|
|
*dParentClassId = 0;
|
|
}
|
|
}
|
|
else
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetNamespaceName
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetNamespaceName(SQL_ID dObjectId, _bstr_t *sName, _bstr_t *sKey)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
if (dObjectId)
|
|
{
|
|
NamespaceData *pTemp = NULL;
|
|
hr = m_NamespaceIds.Get(dObjectId, &pTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (sName)
|
|
*sName = pTemp->m_sNamespaceName;
|
|
if (sKey)
|
|
*sKey = pTemp->m_sNamespaceName;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::AddNamespace
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::AddNamespace(LPCWSTR lpName, LPCWSTR lpKey, SQL_ID dObjectId, SQL_ID dParentId, SQL_ID dClassId)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if (dParentId == dObjectId)
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
else
|
|
{
|
|
// We need to generate an artificial key here,
|
|
// since our real key was generated from a compressed
|
|
// version of the key.
|
|
|
|
if (lpName && wcslen(lpName) && dObjectId != 0)
|
|
{
|
|
NamespaceData *pTemp = new NamespaceData;
|
|
if (pTemp)
|
|
{
|
|
pTemp->m_dNamespaceId = dObjectId;
|
|
delete pTemp->m_sNamespaceName;
|
|
pTemp->m_sNamespaceName = Macro_CloneLPWSTR(lpName);
|
|
pTemp->m_dParentId = dParentId;
|
|
pTemp->m_dClassId = dClassId;
|
|
|
|
m_NamespaceIds.Insert(dObjectId, pTemp);
|
|
m_dwTotalSize += pTemp->GetSize();
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
else
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::DeleteNamespace
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::DeleteNamespace(SQL_ID dId)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
HRESULT hr = 0;
|
|
|
|
if (dId)
|
|
{
|
|
NamespaceData *pTemp = NULL;
|
|
hr = m_NamespaceIds.Get(dId, &pTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pTemp -= pTemp->GetSize();
|
|
m_NamespaceIds.Delete(dId);
|
|
}
|
|
hr = WBEM_S_NO_ERROR;
|
|
}
|
|
else
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::IsSubScope
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CSchemaCache::IsSubScope(SQL_ID dParent, SQL_ID dPotentialSubScope)
|
|
{
|
|
bool bRet = false;
|
|
|
|
SQL_ID dParentID, dScopeClass = 0;
|
|
HRESULT hr = GetParentNamespace(dPotentialSubScope, dParentID, &dScopeClass);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (dParent == dParentID)
|
|
{
|
|
bRet = true;
|
|
break;
|
|
}
|
|
|
|
// Stop when we hit our own namespace
|
|
|
|
if (IsDerivedClass(NAMESPACECLASSID, dParent))
|
|
break;
|
|
|
|
hr = GetParentNamespace(dParentID, dParentID);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetSubScopes
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetSubScopes(SQL_ID dId, SQL_ID **ppScopes, int &iNumScopes)
|
|
{
|
|
HRESULT hr = 0;
|
|
|
|
int iSize = 10;
|
|
|
|
iNumScopes = 0;
|
|
SQL_ID *pTemp = new SQL_ID [iSize];
|
|
if (!pTemp)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
CListElement *pData = NULL;
|
|
SQL_ID dPrevious = 0;
|
|
|
|
pData = m_NamespaceIds.FindFirst();
|
|
|
|
while (pData != NULL && SUCCEEDED(hr))
|
|
{
|
|
dPrevious = pData->m_dId;
|
|
if (IsSubScope(dId, pData->m_dId))
|
|
{
|
|
if (iNumScopes >= iSize)
|
|
{
|
|
iSize += 10;
|
|
SQL_ID *ppNew = new SQL_ID [iSize];
|
|
if (ppNew)
|
|
{
|
|
memcpy(ppNew, pTemp, sizeof(SQL_ID) * iSize-10);
|
|
delete pTemp;
|
|
pTemp = ppNew;
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pTemp[iNumScopes] = pData->m_dId;
|
|
iNumScopes++;
|
|
}
|
|
delete pData;
|
|
|
|
pData = m_NamespaceIds.FindNext(dPrevious);
|
|
if (!pData)
|
|
break;
|
|
}
|
|
|
|
*ppScopes = pTemp;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetClassObject
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetClassObject (LPWSTR lpMachineName, LPWSTR lpNamespaceName, SQL_ID dScopeId,
|
|
SQL_ID dClassId, IWbemClassObject *pTemp)
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
IWbemQualifierSet *pQS = NULL;
|
|
|
|
ClassData *pData = NULL;
|
|
m_CCache.Get(dClassId, &pData);
|
|
if (!pData)
|
|
hr = WBEM_E_NOT_FOUND;
|
|
else
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VARIANT var;
|
|
|
|
VariantInit(&var);
|
|
|
|
// __CLASS
|
|
V_BSTR(&var) = Macro_CloneLPWSTR(pData->m_sName);
|
|
var.vt = VT_BSTR;
|
|
hr = pTemp->Put(L"__Class", 0, &var, CIM_STRING);
|
|
VariantClear(&var);
|
|
|
|
hr = DecorateWbemObj(lpMachineName, lpNamespaceName, dScopeId, pTemp, dClassId);
|
|
|
|
// Set common qualifiers.
|
|
|
|
pTemp->GetQualifierSet(&pQS);
|
|
if (pData->m_dwFlags & REPDRVR_FLAG_ABSTRACT)
|
|
SetBoolQualifier(pQS, L"abstract", 0);
|
|
pQS->Release();
|
|
|
|
// Get every property and qualifier
|
|
// for this class and all its parents.
|
|
// =======================================
|
|
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
while (TRUE)
|
|
{
|
|
for (int i = 0; i < pData->m_dwNumProps; i++)
|
|
{
|
|
DWORD dwPropertyID = pData->m_Properties[i].m_dwPropertyId;
|
|
PropertyData *pPData = NULL;
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pPData);
|
|
|
|
if (!pPData)
|
|
continue;
|
|
|
|
if (pPData->m_dwFlags & REPDRVR_FLAG_SYSTEM)
|
|
continue;
|
|
|
|
// If the property is an embedded object, we
|
|
// need to instantiate a new instance of this
|
|
// class and add it. Each property/qualifier
|
|
// will need to be added also.
|
|
// ===========================================
|
|
|
|
if (!(pPData->m_dwFlags & REPDRVR_FLAG_QUALIFIER) && !(pPData->m_dwFlags & REPDRVR_FLAG_METHOD)
|
|
&& !(pPData->m_dwFlags & REPDRVR_FLAG_IN_PARAM) && !(pPData->m_dwFlags & REPDRVR_FLAG_OUT_PARAM))
|
|
{
|
|
IWbemQualifierSet *pQS = NULL;
|
|
CIMTYPE ct = pPData->m_dwCIMType;
|
|
if (pPData->m_dwFlags & REPDRVR_FLAG_ARRAY)
|
|
{
|
|
ct |= CIM_FLAG_ARRAY;
|
|
var.vt = VT_NULL;
|
|
}
|
|
else
|
|
{
|
|
if (wcslen(pPData->m_sDefaultValue) > 0)
|
|
{
|
|
V_BSTR(&var) = SysAllocString(pPData->m_sDefaultValue);
|
|
var.vt = VT_BSTR;
|
|
}
|
|
else
|
|
{
|
|
var.vt = VT_NULL;
|
|
}
|
|
}
|
|
hr = pTemp->Put(pPData->m_sPropertyName, 0, &var, ct);
|
|
|
|
VariantClear(&var);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
for (i = 0; i < pData->m_dwNumProps; i++)
|
|
{
|
|
DWORD dwPropertyID = pData->m_Properties[i].m_dwPropertyId;
|
|
PropertyData *pPData = NULL;
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pPData);
|
|
|
|
if (!pPData)
|
|
continue;
|
|
|
|
if (pPData->m_dwFlags & REPDRVR_FLAG_SYSTEM)
|
|
continue;
|
|
|
|
if (pPData->m_dwFlags & REPDRVR_FLAG_QUALIFIER)
|
|
{
|
|
if (wcslen(pPData->m_sDefaultValue))
|
|
{
|
|
IWbemQualifierSet *pQS = NULL;
|
|
if (pPData->m_dwQPropID != 0)
|
|
{
|
|
// property or method qualifier
|
|
PropertyData *pData = NULL;
|
|
SQL_ID dTemp = pPData->m_dwQPropID;
|
|
m_Cache.Get(dTemp, &pData);
|
|
|
|
if (pData)
|
|
{
|
|
if (pData->m_dwFlags & REPDRVR_FLAG_METHOD)
|
|
hr = pTemp->GetMethodQualifierSet(pData->m_sPropertyName, &pQS);
|
|
else
|
|
hr = pTemp->GetPropertyQualifierSet(pData->m_sPropertyName, &pQS);
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
V_BSTR(&var) = SysAllocString(pPData->m_sDefaultValue);
|
|
var.vt = VT_BSTR;
|
|
pQS->Put(pPData->m_sPropertyName, &var, pPData->m_dwFlavor);
|
|
pQS->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// class qualifier
|
|
hr = pTemp->GetQualifierSet(&pQS);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
V_BSTR(&var) = SysAllocString(pPData->m_sDefaultValue);
|
|
var.vt = VT_BSTR;
|
|
pQS->Put(pPData->m_sPropertyName, &var, pPData->m_dwFlavor);
|
|
pQS->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IWbemClassObject *pIn = NULL, *pOut = NULL;
|
|
|
|
// This is a method or one of its parameters.
|
|
if (pPData->m_dwFlags & REPDRVR_FLAG_METHOD)
|
|
{
|
|
hr = pTemp->PutMethod(pPData->m_sPropertyName, 0, NULL, NULL);
|
|
}
|
|
else if ((pPData->m_dwFlags & REPDRVR_FLAG_IN_PARAM) ||
|
|
(pPData->m_dwFlags & REPDRVR_FLAG_OUT_PARAM))
|
|
{
|
|
// This is handled in GetObjectData.
|
|
}
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
|
|
if (pData->m_dwSuperClassID <= 1)
|
|
break;
|
|
else
|
|
{
|
|
m_CCache.Get(pData->m_dwSuperClassID, &pData);
|
|
if (!pData)
|
|
break;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetParentId
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetParentId (SQL_ID dClassId, SQL_ID &dParentId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pData = NULL;
|
|
m_CCache.Get(dClassId, &pData);
|
|
if (pData)
|
|
{
|
|
dParentId = pData->m_dwSuperClassID;
|
|
if (!dParentId || dParentId == 1) // Disregard __Class.
|
|
hr = WBEM_E_NOT_FOUND;
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetKeyholeProperty
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetKeyholeProperty (SQL_ID dClassId, DWORD &dwPropID, _bstr_t &sPropName)
|
|
{
|
|
HRESULT hr = WBEM_E_NOT_FOUND;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pData = NULL;
|
|
|
|
m_CCache.Get(dClassId, &pData);
|
|
if (pData)
|
|
{
|
|
if (pData->m_dwFlags & REPDRVR_FLAG_KEYHOLE)
|
|
{
|
|
// We know we have one.
|
|
for (int i = 0; i < pData->m_dwNumProps; i++)
|
|
{
|
|
DWORD dwPropertyID = pData->m_Properties[i].m_dwPropertyId;
|
|
PropertyData *pPData = NULL;
|
|
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pPData);
|
|
|
|
if (pPData && pPData->m_dwFlags & REPDRVR_FLAG_KEYHOLE)
|
|
{
|
|
dwPropID = dwPropertyID;
|
|
sPropName = pPData->m_sPropertyName;
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::IsInHierarchy
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CSchemaCache::IsInHierarchy(SQL_ID dParentId, SQL_ID dPotentialChild)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
bool bRet = false;
|
|
_WMILockit lk(&m_cs);
|
|
|
|
if (dParentId == dPotentialChild)
|
|
bRet = true;
|
|
else
|
|
{
|
|
bRet = IsDerivedClass(dParentId, dPotentialChild);
|
|
|
|
if (!bRet)
|
|
{
|
|
bRet = IsDerivedClass(dPotentialChild, dParentId);
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::IsDerivedClass
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CSchemaCache::IsDerivedClass(SQL_ID dParentId, SQL_ID dPotentialChild)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
bool bRet = false;
|
|
_WMILockit lk(&m_cs);
|
|
|
|
ClassData *pData = NULL;
|
|
hr = m_CCache.Get(dPotentialChild, &pData);
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
if (pData->m_dwSuperClassID == dParentId)
|
|
{
|
|
bRet = true;
|
|
break;
|
|
}
|
|
hr = m_CCache.Get(pData->m_dwSuperClassID, &pData);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::HasImageProp
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CSchemaCache::HasImageProp (SQL_ID dClassId)
|
|
{
|
|
bool bRet = false;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pData = NULL;
|
|
|
|
m_CCache.Get(dClassId, &pData);
|
|
if (pData)
|
|
{
|
|
if (pData->m_dwFlags & REPDRVR_FLAG_IMAGE)
|
|
{
|
|
bRet = true;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::Exists
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CSchemaCache::Exists (SQL_ID dClassId)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pData = NULL;
|
|
m_CCache.Get(dClassId, &pData);
|
|
if (pData && pData->m_dwDynastyID != 0)
|
|
bRet = TRUE;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::DecorateWbemObj
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::DecorateWbemObj(LPWSTR lpMachineName, LPWSTR lpNamespaceName,
|
|
SQL_ID dScopeId, IWbemClassObject *pTemp, SQL_ID dClassId)
|
|
{
|
|
_IWmiObject *pInt = NULL;
|
|
HRESULT hr = pTemp->QueryInterface(IID__IWmiObject, (void **)&pInt);
|
|
CReleaseMe r (pInt);
|
|
if (pInt)
|
|
{
|
|
wchar_t *pNs = NULL;
|
|
|
|
// Decorate this instance. This will let it generate the path.
|
|
|
|
// __NAMESPACE
|
|
|
|
NamespaceData *pTemp = NULL;
|
|
hr = m_NamespaceIds.Get(dScopeId, &pTemp);
|
|
if (SUCCEEDED(hr) && _wcsicmp(pTemp->m_sNamespaceName, L"root"))
|
|
{
|
|
pNs = new wchar_t [wcslen(lpNamespaceName)+wcslen(pTemp->m_sNamespaceName) + 2];
|
|
if (pNs)
|
|
swprintf(pNs, L"%s\\%s", lpNamespaceName, pTemp->m_sNamespaceName);
|
|
}
|
|
else
|
|
{
|
|
pNs = new wchar_t [wcslen(lpNamespaceName) + 1];
|
|
if (pNs)
|
|
wcscpy(pNs, lpNamespaceName);
|
|
}
|
|
|
|
CDeleteMe <wchar_t> d (pNs);
|
|
|
|
// Call some method to decorate the object
|
|
hr = pInt->SetDecoration(lpMachineName, pNs);
|
|
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetKeys
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetKeys(SQL_ID dNsID, LPCWSTR lpClassName, CWStringArray &arrKeys)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
SQL_ID dClassId;
|
|
|
|
hr = GetClassID(lpClassName, dNsID, dClassId);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pClass = NULL;
|
|
|
|
m_CCache.Get(dClassId, &pClass);
|
|
|
|
if (!pClass)
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
while (pClass)
|
|
{
|
|
for (int i = 0; i < pClass->m_dwNumProps; i++)
|
|
{
|
|
if (pClass->m_Properties[i].m_bIsKey)
|
|
{
|
|
PropertyData *pProp = NULL;
|
|
SQL_ID dTemp = pClass->m_Properties[i].m_dwPropertyId;
|
|
m_Cache.Get(dTemp, &pProp);
|
|
|
|
if (pProp)
|
|
arrKeys.Add(pProp->m_sPropertyName);
|
|
}
|
|
}
|
|
SQL_ID dSC = pClass->m_dwSuperClassID;
|
|
pClass = NULL;
|
|
if (!arrKeys.Size() && dSC)
|
|
m_CCache.Get(dSC, &pClass);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::IsKey
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CSchemaCache::IsKey(SQL_ID dClassId, DWORD dwPropID, BOOL &bLocal)
|
|
{
|
|
// Does this property already exist in the hierarchy as a key??
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
_WMILockit lkt(&m_cs);
|
|
BOOL bDone = FALSE;
|
|
|
|
ClassData *pClass = NULL;
|
|
|
|
m_CCache.Get(dClassId, &pClass);
|
|
bLocal = TRUE;
|
|
if (!pClass)
|
|
bRet = FALSE;
|
|
|
|
while (pClass)
|
|
{
|
|
for (int i = 0; i < pClass->m_dwNumProps; i++)
|
|
{
|
|
PropertyData *pProp = NULL;
|
|
SQL_ID dTemp = pClass->m_Properties[i].m_dwPropertyId;
|
|
if (dwPropID == dTemp)
|
|
{
|
|
bRet = (pClass->m_Properties[i].m_bIsKey); // Return the first place this ID is defined.
|
|
bDone = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bDone)
|
|
break;
|
|
|
|
SQL_ID dSC = pClass->m_dwSuperClassID;
|
|
pClass = NULL;
|
|
if (!bRet && !dSC)
|
|
{
|
|
m_CCache.Get(dSC, &pClass);
|
|
bLocal = FALSE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::SetIsKey
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::SetIsKey (SQL_ID dClassId, DWORD dwPropID, BOOL bIsKey)
|
|
{
|
|
HRESULT hr = 0;
|
|
BOOL bDone = FALSE;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pClass = NULL;
|
|
|
|
m_CCache.Get(dClassId, &pClass);
|
|
|
|
if (!pClass)
|
|
hr = WBEM_E_NOT_FOUND;
|
|
else
|
|
pClass->InsertProperty(dwPropID, bIsKey);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetKeyRoot
|
|
//
|
|
//***************************************************************************
|
|
|
|
LPWSTR CSchemaCache::GetKeyRoot (LPWSTR lpClassName, SQL_ID dScopeId)
|
|
{
|
|
LPWSTR lpRet = NULL;
|
|
|
|
SQL_ID dClassId;
|
|
SQL_ID dRetClass = 0;
|
|
HRESULT hr = GetClassID (lpClassName, dScopeId, dClassId);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pClass = NULL;
|
|
|
|
m_CCache.Get(dClassId, &pClass);
|
|
|
|
if (!pClass)
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
while (pClass)
|
|
{
|
|
// Find the topmost class that has a key property,
|
|
// or the topmost singleton or unkeyed class.
|
|
|
|
if (pClass->m_dwFlags & REPDRVR_FLAG_SINGLETON ||
|
|
pClass->m_dwFlags & REPDRVR_FLAG_UNKEYED)
|
|
{
|
|
dRetClass = pClass->m_dwClassID;
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < pClass->m_dwNumProps; i++)
|
|
{
|
|
if (pClass->m_Properties[i].m_bIsKey)
|
|
{
|
|
dRetClass = pClass->m_dwClassID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
SQL_ID dSC = pClass->m_dwSuperClassID;
|
|
pClass = NULL;
|
|
if (dSC)
|
|
m_CCache.Get(dSC, &pClass);
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (dRetClass)
|
|
{
|
|
m_CCache.Get(dRetClass, &pClass);
|
|
int iSize = wcslen(pClass->m_sName);
|
|
if (iSize)
|
|
{
|
|
lpRet = new wchar_t [iSize+1];
|
|
if (lpRet)
|
|
wcscpy(lpRet, pClass->m_sName);
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
}
|
|
|
|
return lpRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetPropertyList
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetPropertyList (SQL_ID dClassId, Properties &pProps, DWORD *pwNumProps)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pClass = NULL;
|
|
|
|
m_CCache.Get(dClassId, &pClass);
|
|
if (pClass)
|
|
{
|
|
for (int i = 0; i < pClass->m_dwNumProps; i++)
|
|
{
|
|
DWORD dwPropertyID = pClass->m_Properties[i].m_dwPropertyId;
|
|
pProps[dwPropertyID] = 0;
|
|
}
|
|
if (pwNumProps)
|
|
*pwNumProps = pClass->m_dwNumProps;
|
|
}
|
|
else
|
|
WBEM_E_NOT_FOUND;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::ValidateProperty
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::ValidateProperty (SQL_ID dObjectId, DWORD dwPropertyID, DWORD dwFlags, CIMTYPE cimtype, DWORD dwStorageType,
|
|
LPWSTR lpDefault, BOOL &bChg, BOOL &bIfNoInstances)
|
|
{
|
|
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
PropertyData *pData = NULL;
|
|
_WMILockit lkt(&m_cs);
|
|
bChg = TRUE; // We can't tell if the default changed or not, since it ain't cached.
|
|
BOOL bIfNoChildren = FALSE;
|
|
|
|
SQL_ID dTemp = dwPropertyID;
|
|
m_Cache.Get(dTemp, &pData);
|
|
if (pData)
|
|
{
|
|
if (pData->m_dwFlags != dwFlags ||
|
|
pData->m_dwCIMType != cimtype)
|
|
bChg = TRUE;
|
|
|
|
BOOL bLocal = FALSE;
|
|
BOOL bOldKeyStatus = IsKey(dObjectId, dwPropertyID, bLocal);
|
|
BOOL bNewKeyStatus = ((dwFlags & REPDRVR_FLAG_KEY) ? TRUE : FALSE);
|
|
|
|
if (bOldKeyStatus != bNewKeyStatus)
|
|
{
|
|
bIfNoChildren = TRUE;
|
|
bIfNoInstances = TRUE;
|
|
}
|
|
|
|
// Check for a legal conversion.
|
|
// We can only change datatypes to larger types of same storage type
|
|
// Except that we can change ints to larger reals.
|
|
if (pData->m_dwCIMType != cimtype)
|
|
{
|
|
if (dwStorageType != pData->m_dwStorageType)
|
|
{
|
|
if (!(pData->m_dwStorageType == WMIDB_STORAGE_NUMERIC &&
|
|
dwStorageType == WMIDB_STORAGE_REAL))
|
|
hr = WBEM_E_INVALID_OPERATION;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Make sure the conversion is to a bigger or same storage unit.
|
|
|
|
switch(cimtype)
|
|
{
|
|
case CIM_UINT8:
|
|
case CIM_SINT8:
|
|
switch(pData->m_dwCIMType)
|
|
{
|
|
case CIM_UINT8:
|
|
case CIM_SINT8:
|
|
case CIM_BOOLEAN:
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
default:
|
|
hr = WBEM_E_INVALID_OPERATION;
|
|
break;
|
|
}
|
|
break;
|
|
case CIM_UINT16:
|
|
case CIM_SINT16:
|
|
switch(pData->m_dwCIMType)
|
|
{
|
|
case CIM_UINT16:
|
|
case CIM_SINT16:
|
|
case CIM_UINT8:
|
|
case CIM_SINT8:
|
|
case CIM_BOOLEAN:
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
default:
|
|
hr = WBEM_E_INVALID_OPERATION;
|
|
break;
|
|
}
|
|
break;
|
|
case CIM_UINT32:
|
|
case CIM_SINT32:
|
|
case CIM_REAL32:
|
|
switch(pData->m_dwCIMType)
|
|
{
|
|
case CIM_UINT32:
|
|
case CIM_SINT32:
|
|
case CIM_UINT16:
|
|
case CIM_SINT16:
|
|
case CIM_UINT8:
|
|
case CIM_SINT8:
|
|
case CIM_BOOLEAN:
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
default:
|
|
hr = WBEM_E_INVALID_OPERATION;
|
|
break;
|
|
}
|
|
break;
|
|
case CIM_UINT64:
|
|
case CIM_SINT64:
|
|
switch(pData->m_dwCIMType)
|
|
{
|
|
case CIM_UINT64:
|
|
case CIM_SINT64:
|
|
case CIM_UINT32:
|
|
case CIM_SINT32:
|
|
case CIM_UINT16:
|
|
case CIM_SINT16:
|
|
case CIM_UINT8:
|
|
case CIM_SINT8:
|
|
case CIM_BOOLEAN:
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
default:
|
|
hr = WBEM_E_INVALID_OPERATION;
|
|
break;
|
|
}
|
|
break;
|
|
case CIM_REAL64:
|
|
switch(pData->m_dwCIMType)
|
|
{
|
|
case CIM_REAL32:
|
|
case CIM_UINT64:
|
|
case CIM_SINT64:
|
|
case CIM_UINT32:
|
|
case CIM_SINT32:
|
|
case CIM_UINT16:
|
|
case CIM_SINT16:
|
|
case CIM_UINT8:
|
|
case CIM_SINT8:
|
|
case CIM_BOOLEAN:
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
default:
|
|
hr = WBEM_E_INVALID_OPERATION;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
hr = WBEM_E_INVALID_OPERATION; // strings, refs, datetimes, etc.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bIfNoChildren)
|
|
{
|
|
// Fail if we have subclasses.
|
|
|
|
SQLIDs ids;
|
|
int iNumChildren = 0;
|
|
|
|
hr = GetDerivedClassList(dObjectId, ids, iNumChildren);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (iNumChildren != 0)
|
|
hr = WBEM_E_CLASS_HAS_CHILDREN;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & REPDRVR_FLAG_KEY)
|
|
bIfNoInstances = TRUE; // Can't add a key if there are instances.
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::FindProperty
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::FindProperty(SQL_ID dObjectId, LPWSTR lpPropName, DWORD dwFlags, CIMTYPE ct)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
// Does this property already exist in a derived class?
|
|
|
|
SQLIDs ids;
|
|
int iNumChildren = 0;
|
|
|
|
hr = GetDerivedClassList(dObjectId, ids, iNumChildren);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (int i = 0; i < iNumChildren; i++)
|
|
{
|
|
SQL_ID dTemp = ids.at(i);
|
|
DWORD dwTempID = 0;
|
|
if (GetPropertyID(lpPropName, dTemp, dwFlags, ct, dwTempID) == WBEM_S_NO_ERROR)
|
|
{
|
|
hr = WBEM_E_PROPAGATED_PROPERTY;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (!dObjectId)
|
|
hr = WBEM_S_NO_ERROR;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetDerivedClassList
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetDerivedClassList(SQL_ID dObjectId, SQL_ID **ppIDs,
|
|
int &iNumChildren, BOOL bImmediate)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
SQLIDs ids;
|
|
|
|
hr = GetDerivedClassList(dObjectId, ids, iNumChildren, bImmediate);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SQL_ID *pTemp = new SQL_ID [iNumChildren];
|
|
if (pTemp)
|
|
{
|
|
for (int i = 0; i < iNumChildren; i++)
|
|
{
|
|
pTemp[i] = ids.at(i);
|
|
}
|
|
*ppIDs = pTemp;
|
|
}
|
|
else
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetDerivedClassList
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetDerivedClassList(SQL_ID dObjectId, SQLIDs &children,
|
|
int &iNumChildren, BOOL bImmediate)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ClassData *pClass = NULL;
|
|
m_CCache.Get(dObjectId, &pClass);
|
|
if (pClass)
|
|
{
|
|
for (int i = 0; i < pClass->m_DerivedIDs.size(); i++)
|
|
{
|
|
SQL_ID dChild = pClass->m_DerivedIDs.at(i);
|
|
children.push_back(dChild);
|
|
iNumChildren++;
|
|
|
|
if (!bImmediate)
|
|
hr = GetDerivedClassList(dChild, children, iNumChildren);
|
|
}
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetHierarchy
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetHierarchy(SQL_ID dObjectId, SQL_ID **ppIDs, int &iNumIDs)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
int iSize = 0;
|
|
|
|
// Populate the ID list of derived *and* parent class IDs.
|
|
|
|
SQLIDs ids;
|
|
hr = GetHierarchy(dObjectId, ids, iNumIDs);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SQL_ID *pIDs = new SQL_ID [iNumIDs];
|
|
if (pIDs)
|
|
{
|
|
for (int i = 0; i < iNumIDs; i++)
|
|
{
|
|
pIDs[i] = ids.at(i);
|
|
}
|
|
*ppIDs = pIDs;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetHierarchy
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::GetHierarchy(SQL_ID dObjectId, SQLIDs &ids, int &iNumIDs)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
int iSize = 0;
|
|
|
|
// Populate the ID list of derived *and* parent class IDs.
|
|
hr = GetDerivedClassList(dObjectId, ids, iNumIDs);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SQL_ID dTemp = dObjectId;
|
|
|
|
// Load up all the parents.
|
|
|
|
while (SUCCEEDED(GetParentId(dTemp, dTemp)))
|
|
{
|
|
ids.push_back(dTemp);
|
|
iNumIDs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::ResizeCache
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::ResizeCache()
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
SQLIDs ids;
|
|
|
|
// Unload an existing dynasty to make room.
|
|
|
|
SQLRefCountMap::iterator item = m_DynastiesInUse.begin();
|
|
while (item != m_DynastiesInUse.end())
|
|
{
|
|
if ((*item).second == 0)
|
|
{
|
|
hr = DeleteDynasty((*item).first);
|
|
|
|
ids.push_back((*item).first);
|
|
|
|
if (m_dwTotalSize < m_dwMaxSize || item == m_DynastiesInUse.end())
|
|
break;
|
|
}
|
|
item++;
|
|
}
|
|
|
|
for (int i = 0; i < ids.size(); i++)
|
|
m_DynastiesInUse.erase(m_DynastiesInUse.find(ids.at(i)));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::LockDynasty
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::LockDynasty(SQL_ID dDynastyId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
ULONG uRefCount = 0;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
SQLRefCountMap::iterator it = m_DynastiesInUse.find(dDynastyId);
|
|
if (it != m_DynastiesInUse.end())
|
|
uRefCount = (*it).second;
|
|
|
|
InterlockedIncrement((LONG *) &uRefCount);
|
|
m_DynastiesInUse[dDynastyId] = uRefCount;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::UnlockDynasty
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::UnlockDynasty(SQL_ID dDynastyId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
_WMILockit lkt(&m_cs);
|
|
|
|
ULONG uRefCount = m_DynastiesInUse[dDynastyId];
|
|
InterlockedDecrement((LONG *) &uRefCount);
|
|
m_DynastiesInUse[dDynastyId] = uRefCount;
|
|
|
|
return hr;
|
|
|
|
}
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::DeleteDynasty
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CSchemaCache::DeleteDynasty(SQL_ID dDynastyId)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if (dDynastyId == 1)
|
|
return WBEM_S_NO_ERROR;
|
|
|
|
// Delete all class info for members of this dynasty.
|
|
|
|
SQLIDs ids;
|
|
int iNum;
|
|
// Immediate only, so we don't inadvertently
|
|
// blow away a protected dynasty.
|
|
|
|
hr = GetDerivedClassList(dDynastyId, ids, iNum, TRUE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DeleteClass(dDynastyId);
|
|
for (int i = 0; i < ids.size(); i++)
|
|
{
|
|
SQL_ID d = ids.at(i);
|
|
ULONG uRefCount = 0;
|
|
|
|
SQLRefCountMap::iterator it = m_DynastiesInUse.find(d);
|
|
if (it != m_DynastiesInUse.end())
|
|
uRefCount = (*it).second;
|
|
|
|
if (!uRefCount)
|
|
hr = DeleteDynasty(d);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::IsSystemClass
|
|
//
|
|
//***************************************************************************
|
|
|
|
BOOL CSchemaCache::IsSystemClass(SQL_ID dObjectId, SQL_ID dClassId)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
_WMILockit lkt(&m_cs);
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
ClassData *pClass = NULL;
|
|
if (dClassId == 1)
|
|
m_CCache.Get(dObjectId, &pClass);
|
|
else
|
|
m_CCache.Get(dClassId, &pClass);
|
|
|
|
if (pClass)
|
|
{
|
|
if (pClass->m_sName && pClass->m_sName[0] == L'_')
|
|
bRet = TRUE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CSchemaCache::GetWriteToken
|
|
//
|
|
//***************************************************************************
|
|
|
|
DWORD CSchemaCache::GetWriteToken(SQL_ID dObjectId, SQL_ID dClassId)
|
|
{
|
|
DWORD dwRet = WBEM_PARTIAL_WRITE_REP;
|
|
BOOL bRet = IsSystemClass(dObjectId, dClassId);
|
|
|
|
if (bRet)
|
|
dwRet = WBEM_FULL_WRITE_REP;
|
|
|
|
return dwRet;
|
|
}
|
|
|