374 lines
8.4 KiB
C++
374 lines
8.4 KiB
C++
/*++
|
|
|
|
Copyright (C) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
WmiCache.cpp
|
|
|
|
Abstract:
|
|
|
|
WMI cache for _IWmiObject's. Used within wbemcore only. When memory threshold
|
|
is hit, objects are stored in disk-based store. When size of disk-based store
|
|
gets too big, additions to cache fail.
|
|
|
|
History:
|
|
|
|
paulall 10-Mar-2000 Created.
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "wbemint.h"
|
|
#include "wbemcli.h"
|
|
#include "WmiCache.h"
|
|
#include <arrtempl.h>
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
CWmiCache::CWmiCache()
|
|
: m_lRefCount(0), m_nEnum(0)
|
|
{
|
|
InitializeCriticalSection(&m_cs);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
CWmiCache::~CWmiCache()
|
|
{
|
|
Empty(0, NULL);
|
|
DeleteCriticalSection(&m_cs);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
|
{
|
|
*ppvObj = 0;
|
|
|
|
if (IID_IUnknown==riid || IID__IWmiCache==riid)
|
|
{
|
|
*ppvObj = (_IWmiCache*)this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
ULONG CWmiCache::AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_lRefCount);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
ULONG CWmiCache::Release()
|
|
{
|
|
ULONG uNewCount = InterlockedDecrement(&m_lRefCount);
|
|
if (0 == uNewCount)
|
|
delete this;
|
|
return uNewCount;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::SetConfigValue(
|
|
/*[in]*/ ULONG uID,
|
|
/*[in]*/ ULONG uValue
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::GetConfigValue(
|
|
/*[in]*/ ULONG uID,
|
|
/*[out]*/ ULONG *puValue
|
|
)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::Empty(
|
|
/*[in]*/ ULONG uFlags,
|
|
/*[in]*/ LPCWSTR wszClass
|
|
)
|
|
{
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
while(m_objects.Size())
|
|
{
|
|
CWmiCacheObject *pObj = (CWmiCacheObject*)m_objects[m_objects.Size()-1];
|
|
pObj->m_pObj->Release();
|
|
delete pObj;
|
|
m_objects.RemoveAt(m_objects.Size()-1);
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Also subsumes replace functionality
|
|
//
|
|
// __PATH Property is used as a real key
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::AddObject(
|
|
/*[in]*/ ULONG uFlags,
|
|
/*[in]*/ _IWmiObject *pObj
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
int nPathHash = 0;
|
|
hr = HashPath(pObj, &nPathHash);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CWmiCacheObject *pCacheObj = new CWmiCacheObject(nPathHash, pObj);
|
|
if (pCacheObj == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
pObj->AddRef();
|
|
|
|
int nRet = m_objects.Add(pCacheObj);
|
|
if (nRet != CFlexArray::no_error)
|
|
{
|
|
pObj->Release();
|
|
if (nRet == CFlexArray::out_of_memory)
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
else
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::DeleteByPath(
|
|
/*[in]*/ ULONG uFlags,
|
|
/*[in]*/ LPCWSTR wszFullPath
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
int nPathHash = 0;
|
|
hr = HashPath(wszFullPath, &nPathHash);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (int i = 0; i != m_objects.Size(); i++)
|
|
{
|
|
CWmiCacheObject *pObj = (CWmiCacheObject*)m_objects[i];
|
|
|
|
if (pObj->m_nHash = nPathHash)
|
|
{
|
|
hr = ComparePath(wszFullPath, pObj->m_pObj);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_objects.RemoveAt(i);
|
|
pObj->m_pObj->Release();
|
|
delete pObj;
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
}
|
|
else if (hr != WBEM_E_NOT_FOUND)
|
|
break;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::DeleteByPointer(
|
|
/*[in]*/ ULONG uFlags,
|
|
/*[in]*/ _IWmiObject *pTarget
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_E_NOT_FOUND;
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (int i = 0; i != m_objects.Size(); i++)
|
|
{
|
|
if (m_objects[i] == pTarget)
|
|
{
|
|
m_objects.RemoveAt(i);
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::GetByPath(
|
|
/*[in]*/ ULONG uFlags,
|
|
/*[in]*/ LPCWSTR wszFullPath,
|
|
/*[out]*/ _IWmiObject **pObj
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
int nPathHash = 0;
|
|
hr = HashPath(wszFullPath, &nPathHash);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = WBEM_E_NOT_FOUND;
|
|
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (int i = 0; i != m_objects.Size(); i++)
|
|
{
|
|
CWmiCacheObject *pCacheObj = (CWmiCacheObject*)m_objects[i];
|
|
|
|
if (pCacheObj->m_nHash == nPathHash)
|
|
{
|
|
hr = ComparePath(wszFullPath, pCacheObj ->m_pObj);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*pObj = pCacheObj->m_pObj;
|
|
(*pObj)->AddRef();
|
|
hr = WBEM_S_NO_ERROR;
|
|
break;
|
|
}
|
|
else if (hr != WBEM_E_NOT_FOUND)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// Filters: uFlags==0==all, uFlags==WMICACHE_CLASS_SHALLOW, WMICACHE_CLASS_DEEP
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::BeginEnum(
|
|
/*[in]*/ ULONG uFlags,
|
|
/*[in]*/ LPCWSTR wszFilter
|
|
)
|
|
{
|
|
if (uFlags != 0)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
m_nEnum = 0;
|
|
return WBEM_S_NO_ERROR;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
//***************************************************************************
|
|
STDMETHODIMP CWmiCache::Next(
|
|
/*[in]*/ ULONG uBufSize,
|
|
/*[out, size_is(uBufSize), length_is(*puReturned)]*/ _IWmiObject **pObjects,
|
|
/*[out]*/ ULONG *puReturned
|
|
)
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
EnterCriticalSection(&m_cs);
|
|
|
|
for (ULONG i = 0; i != uBufSize; i++, m_nEnum++)
|
|
{
|
|
if (m_nEnum == m_objects.Size())
|
|
{
|
|
hr = WBEM_S_NO_MORE_DATA;
|
|
break;
|
|
}
|
|
pObjects[i] = ((CWmiCacheObject*)m_objects[m_nEnum])->m_pObj;
|
|
pObjects[i]->AddRef();
|
|
}
|
|
|
|
*puReturned = i;
|
|
|
|
LeaveCriticalSection(&m_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWmiCache::HashPath(const wchar_t *wszPath, int *pnHash)
|
|
{
|
|
DWORD dwHash = 0;
|
|
|
|
while (*wszPath)
|
|
{
|
|
dwHash = (dwHash << 4) + *wszPath++;
|
|
DWORD dwTemp = dwHash & 0xF0000000;
|
|
if (dwTemp)
|
|
dwHash ^= dwTemp >> 24;
|
|
dwHash &= ~dwTemp;
|
|
}
|
|
|
|
|
|
*pnHash = (int)dwHash;
|
|
return WBEM_S_NO_ERROR;;
|
|
}
|
|
|
|
HRESULT CWmiCache::HashPath(_IWmiObject *pObj, int *pnHash)
|
|
{
|
|
VARIANT varPath;
|
|
VariantInit(&varPath);
|
|
HRESULT hr = pObj->Get(L"__PATH", 0, &varPath, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HashPath(V_BSTR(&varPath), pnHash);
|
|
VariantClear(&varPath);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWmiCache::ComparePath(const wchar_t *wszPath, _IWmiObject *pObject)
|
|
{
|
|
VARIANT varPath;
|
|
VariantInit(&varPath);
|
|
HRESULT hr = pObject->Get(L"__PATH", 0, &varPath, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (wcscmp(wszPath, V_BSTR(&varPath)) == 0)
|
|
hr = WBEM_S_NO_ERROR;
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
VariantClear(&varPath);
|
|
}
|
|
return hr;
|
|
}
|