Figure 4 PerfSrvObject
PerfSrvObject.h
// PerfSrvObject.h : Declaration of the CPerfSrvObject
#ifndef __PERFSRVOBJECT_H_
#define __PERFSRVOBJECT_H_
#include "resource.h" // main symbols
#include "allincludes.h"
/////////////////////////////////////////////////////////////////////////////
// CPerfSrvObject
class ATL_NO_VTABLE CPerfSrvObject :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CPerfSrvObject, &CLSID_PerfSrvObject>,
public ISupportErrorInfo,
public IPersistStreamInitImpl<CPerfSrvObject>,
public IDispatchImpl<IPerfSrvObject, &IID_IPerfSrvObject, &LIBID_PERFSRVEXELib>
{
public:
static POTYPE s_POMap;
POTYPE& m_POMap;
POTYPE::iterator m_curPO;
CPerfSrvObject() : m_POMap(s_POMap), m_bof(false),
m_eof(false),m_bRequiresLoad(TRUE)
{
}
HRESULT FinalConstruct();
void FinalRelease();
DECLARE_REGISTRY_RESOURCEID(IDR_PERFSRVOBJECT)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CPerfSrvObject)
COM_INTERFACE_ENTRY(IPerfSrvObject)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY_IMPL(IPersistStreamInit)
COM_INTERFACE_ENTRY_IMPL_IID(IID_IPersistStream,IPersistStreamInit)
END_COM_MAP()
BEGIN_PROP_MAP(CPerfSrvObject)
END_PROP_MAP();
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
STDMETHOD(Load) (LPSTREAM pStream);
STDMETHOD(Save) (LPSTREAM pStream, BOOL bClearDirty);
private:
bool m_bof;
bool m_eof;
public:
STDMETHOD(Save)(/*[in]*/BSTR path,/*[in]*/BSTR name);
STDMETHOD(AddPO)(/*[in]*/BSTR name, /*[in]*/BSTR helpString);
STDMETHOD(GetNumCounters)(/*[out,retval]*/long* pNumCounters);
STDMETHOD(MoveFirst)();
STDMETHOD(MoveLast)();
STDMETHOD(MoveNext)();
STDMETHOD(MovePrevious)();
STDMETHOD(GetNumPOs)(/*[out,retval]*/long* pNumCounters);
STDMETHOD(GetCurrentPO)(/*[out,retval]*/IPerfPerformanceObject** pPO);
public:
STDMETHOD(Clear)();
STDMETHOD(FindFirst)(/*[in]*/ BSTR poName);
STDMETHOD(Load)(/*[in]*/BSTR path,/*[in]*/BSTR name);
bool m_bRequiresLoad;
bool m_bRequiresSave;
};
#endif //__PERFSRVOBJECT_H_
PerfSrvObject.cpp
// PerfSrvObject.cpp : Implementation of CPerfSrvObject
#include "stdafx.h"
#include <algorithm>
#include "PerfSrvExe.h"
#include "PerfSrvObject.h"
/////////////////////////////////////////////////////////////////////////////
// CPerfSrvObject
POTYPE CPerfSrvObject::s_POMap;
STDMETHODIMP CPerfSrvObject::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IPerfSrvObject
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
HRESULT CPerfSrvObject::FinalConstruct()
{
HRESULT hr = S_OK;
m_bRequiresLoad = TRUE;
if(m_POMap.size() > 0)
{
m_bRequiresLoad = FALSE;
}
return hr;
}
void CPerfSrvObject::FinalRelease()
{
/* POTYPE::iterator iter;
for(iter = m_POMap.begin();iter != m_POMap.end();iter++)
{
((*iter).second)->Release();
}
m_curPO = m_POMap.end();*/
Clear();
}
/***************************************************************************
Informational Methods
***************************************************************************/
STDMETHODIMP CPerfSrvObject::GetNumCounters(long *pNumCounters)
{
IPerfPerformanceObject *pTemp = (*m_curPO).second;
pTemp->get_m_numCounters(pNumCounters);
return S_OK;
}
STDMETHODIMP CPerfSrvObject::GetNumPOs(long *pNumCounters)
{
*pNumCounters = m_POMap.size();
return S_OK;
}
STDMETHODIMP CPerfSrvObject::GetCurrentPO(IPerfPerformanceObject** pPO)
{
*pPO = (IPerfPerformanceObject*)(*m_curPO).second;
((*m_curPO).second)->AddRef();
return S_OK;
}
/***************************************************************************
Positioning Methods
Things to be done:
- Add error handling
***************************************************************************/
STDMETHODIMP CPerfSrvObject::MoveFirst()
{
HRESULT hr = S_OK;
if(m_POMap.size() > 0)
{
m_bof = false;
m_eof = false;
m_curPO = m_POMap.begin();
}
else
{
ReportError repErr;
return repErr.WriteCOMError(IDS_MAPNOTINITIALIZED,"");
}
return hr;
}
STDMETHODIMP CPerfSrvObject::MoveLast()
{
if(m_POMap.size() > 0)
{
m_bof = false;
m_eof = false;
m_curPO = m_POMap.end();
m_curPO--;
}
else
{
ReportError repErr;
return repErr.WriteCOMError(IDS_MAPNOTINITIALIZED,"");
}
return S_OK;
}
STDMETHODIMP CPerfSrvObject::MoveNext()
{
HRESULT hr = S_OK;
ReportError repErr;
if(m_eof)
{
return repErr.WriteCOMError(IDS_ENDOFMAP,"");
}
else
{
if(m_bof)
{
MoveFirst();
m_bof = false;
}
else
{
m_curPO++;
}
if(m_curPO == m_POMap.end())
{
m_eof = true;
return repErr.WriteCOMError(IDS_ENDOFMAP,"");
}
}
return hr;
}
STDMETHODIMP CPerfSrvObject::MovePrevious()
{
HRESULT hr = S_OK;
ReportError repErr;
if(m_bof)
{
//Insert proper error handling later
return repErr.WriteCOMError(IDS_BEGINOFMAP,"");
}
else
{
if(m_curPO == m_POMap.begin() )
{
m_curPO = m_POMap.begin();
m_bof = true;
}
else
{
m_curPO--;
m_eof = false;
}
}
return hr;
}
/***************************************************************************
New Item Methods
***************************************************************************/
STDMETHODIMP CPerfSrvObject::AddPO(BSTR name, BSTR helpString)
{
HRESULT hr = S_OK;
CComObject<IPerfPerformanceObjectImpl> *pNew = NULL;
hr = CComObject<IPerfPerformanceObjectImpl>::CreateInstance(&pNew);
pNew->AddRef();
pNew->SetInfo(name,helpString,0);
_bstr_t poName(name);
m_POMap[poName] = pNew;
m_curPO = m_POMap.begin();
return hr;
}
STDMETHODIMP CPerfSrvObject::Save(BSTR path, BSTR name)
{
HRESULT hr = S_OK;
IStreamPtr pStream;
try
{
HGLOBAL hGlobal;
void *pData = NULL;
UCHAR *pDataCopy = NULL;
CComVariant varTemp;
CreateStreamOnHGlobal(NULL,TRUE,&pStream);
this->Save(pStream,TRUE);
GetHGlobalFromStream(pStream,&hGlobal);
pData = GlobalLock(hGlobal);
DWORD dwSize = GlobalSize(hGlobal);
USES_CONVERSION;
_bstr_t localPath(path);
_bstr_t localName(name);
char dataPath[MAX_PATH];
if(localName.length() > 0)
{
sprintf(dataPath,"%s\\%s",OLE2A(localPath),OLE2A(localName));
}
else if(localPath.length() > 0)
{
sprintf(dataPath,"%s",OLE2A(localPath));
}
else
{
ReportError repErr;
return repErr.WriteCOMError(IDS_NOFILEFOUND,"No Valid File Name");
}
HANDLE hFile =
CreateFile(dataPath,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
long retVal;
DWORD numWrite;
retVal = WriteFile(hFile,pData,dwSize, &numWrite, NULL);
CloseHandle(hFile);
GlobalUnlock(hGlobal);
GlobalFree(hGlobal);
}
catch(HRESULT hr)
{
hr = E_FAIL;
}
return S_OK;
}
STDMETHODIMP CPerfSrvObject::Load(LPSTREAM pStream)
{
HRESULT hr = S_OK;
long numPO;
ULONG cb;
IStreamPtr pIStream(pStream);
pStream->Read(&numPO,sizeof(long),&cb);
for(int x=0;x<numPO;x++)
{
HRESULT hr = S_OK;
CComObject<IPerfPerformanceObjectImpl> *pNew = NULL;
hr = CComObject<IPerfPerformanceObjectImpl>::CreateInstance(&pNew);
pNew->AddRef();
pNew->Read(pStream);
BSTR poName;
IPerfParentObject* pParent;
pNew->GetParent(&pParent);
pParent->get_m_name(&poName);
pParent->Release();
_bstr_t poBstrName(poName);
m_POMap[poBstrName] = pNew;
}
m_curPO = m_POMap.begin();
return hr;
}
STDMETHODIMP CPerfSrvObject::Save(LPSTREAM pStream, BOOL bClearDirty)
{
HRESULT hr = S_OK;
POTYPE::iterator iter;
long numCounters = 0;
long numPO = 0;
GetNumPOs(&numPO);
//write number of Performance Objects
ULONG cb;
pStream->Write(&numPO,sizeof(long),&cb);
for(iter = m_POMap.begin();iter != m_POMap.end();iter++)
{
IPerfPerformanceObject *pTemp = (*iter).second;
pTemp->Write(pStream);
//write something to stream saying no counter
if(pTemp->MoveFirst() == E_FAIL)
continue;
do
{
IPerfCounterObject* pCO = NULL;
hr = pTemp->GetCurrentCO(&pCO);
pCO->Write(pStream);
pCO->Release();
}while(pTemp->MoveNext() != E_FAIL) ;
}
return hr;
}
STDMETHODIMP CPerfSrvObject::Load(BSTR path, BSTR name)
{
HGLOBAL hGlobal;
IStreamPtr pStream;
void *pData = NULL;
UCHAR *pDataCopy = NULL;
CComVariant varTemp;
USES_CONVERSION;
HRESULT hr = S_OK;
if(!m_bRequiresLoad)
{
//make proper return after
//should return S_ALREADYLOADED
return hr;
}
_bstr_t localPath(path);
_bstr_t localName(name);
char dataPath[MAX_PATH];
if(localName.length() > 0)
{
sprintf(dataPath,"%s\\%s",OLE2A(localPath),OLE2A(localName));
}
else if(localPath.length() > 0)
{
sprintf(dataPath,"%s",OLE2A(localPath));
}
else
{
ReportError repErr;
return repErr.WriteCOMError(IDS_NOFILEFOUND,"No Valid File Name");
}
HANDLE hFile =
CreateFile(dataPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
ReportError repErr;
return repErr.WriteCOMError(IDS_NOFILEFOUND,dataPath);
}
DWORD dwSizeHigh,dwSizeLow;
dwSizeLow = GetFileSize (hFile, &dwSizeHigh);
hGlobal = GlobalAlloc(GMEM_MOVEABLE,dwSizeLow);
DWORD nBytesRead;
void *pGlobalVoid = GlobalLock(hGlobal);
hr = ReadFile(hFile, pGlobalVoid, dwSizeLow, &nBytesRead,NULL);
GlobalUnlock(hGlobal);
hr = CreateStreamOnHGlobal(hGlobal,TRUE,&pStream);
this->Load(pStream);
CloseHandle(hFile);
GlobalFree(hGlobal);
m_bRequiresLoad = FALSE;
return S_OK;
}
STDMETHODIMP CPerfSrvObject::FindFirst(BSTR poName)
{
HRESULT hr = S_OK;
_bstr_t nameToFind(poName);
m_curPO = m_POMap.find(nameToFind);
if(m_curPO == m_POMap.end())
{
USES_CONVERSION;
ReportError repErr;
return repErr.WriteCOMError(IDS_NORECORDFOUND,OLE2A(poName));
}
return hr;
}
STDMETHODIMP CPerfSrvObject::Clear()
{
POTYPE::iterator iter;
for(iter = m_POMap.begin();iter != m_POMap.end();iter++)
{
((*iter).second)->Release();
}
m_curPO = m_POMap.end();
m_bRequiresLoad = TRUE;
return S_OK;
}
Figure 6 IPerfPerformanceObject Methods
|
Method Name |
Description |
|
AddCounter |
Adds a counter object to the current PO |
|
GetCurrentCO |
Retrieves the CO that the current PO is responsible for |
|
GetParent |
Gets the parent interface that implements some common methods |
|
MoveFirst |
Moves to the first CO |
|
MoveLast |
Moves to the last CO |
|
MoveNext |
Moves to the next CO |
|
MovePrevious |
Moves to the previous CO |
|
FindFirst |
Finds the first CO based on its name |
|
Read |
Reads in a persisted PO/CO schema |
|
SetInfo |
A general method for setting the PO's name, help string, and index value |
|
Write |
Persists the current PO's information to a data stream |