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.
829 lines
20 KiB
829 lines
20 KiB
/*===================================================================
|
|
Microsoft Denali
|
|
|
|
Microsoft Confidential.
|
|
Copyright 1996 Microsoft Corporation. All Rights Reserved.
|
|
|
|
Component: Main
|
|
|
|
File: perfdef.h
|
|
|
|
Owner: DmitryR
|
|
|
|
Data definitions shared between asp.dll and aspperf.dll
|
|
===================================================================*/
|
|
|
|
#ifndef _ASP_PERFDEF_H
|
|
#define _ASP_PERFDEF_H
|
|
|
|
#include <pudebug.h>
|
|
|
|
/*===================================================================
|
|
Definitions of names, sizes and mapped data block structures
|
|
===================================================================*/
|
|
|
|
// Mutex name to access the main file map
|
|
#define SZ_PERF_MUTEX "Global\\ASP_PERFMON_MUTEX"
|
|
|
|
// WaitForSingleObject arg (how long to wait for mutext before failing)
|
|
#define PERM_MUTEX_WAIT 1000
|
|
|
|
// Main shared file map name
|
|
#define SZ_PERF_MAIN_FILEMAP "Global\\ASP_PERFMON_MAIN_BLOCK"
|
|
|
|
// Max number of registered (ASP) processes in main file map
|
|
#define C_PERF_PROC_MAX 1024
|
|
|
|
// Structure that defines main file map
|
|
struct CPerfMainBlockData
|
|
{
|
|
DWORD m_dwTimestamp; // time (GetTickCount()) of the last change
|
|
DWORD m_cItems; // number of registred processes
|
|
|
|
// array of process WAM CLS IDs
|
|
CLSID m_rgClsIds[C_PERF_PROC_MAX];
|
|
};
|
|
|
|
#define CB_PERF_MAIN_BLOCK (sizeof(struct CPerfMainBlockData))
|
|
|
|
// Name for per-process file map
|
|
#define SZ_PERF_PROC_FILEMAP_PREFIX "Global\\ASP_PERFMON_BLOCK_"
|
|
#define CCH_PERF_PROC_FILEMAP_PREFIX 25
|
|
|
|
// Number of counters in per-process file map
|
|
#define C_PERF_PROC_COUNTERS 37
|
|
|
|
struct CPerfProcBlockData
|
|
{
|
|
CLSID m_ClsId; // process CLS ID
|
|
DWORD m_rgdwCounters[C_PERF_PROC_COUNTERS]; // array counters
|
|
};
|
|
|
|
#define CB_PERF_PROC_BLOCK (sizeof(struct CPerfProcBlockData))
|
|
#define CB_COUNTERS (sizeof(DWORD) * C_PERF_PROC_COUNTERS)
|
|
|
|
|
|
|
|
/*===================================================================
|
|
CSharedMemBlock -- generic shared memory block
|
|
===================================================================*/
|
|
|
|
class CSharedMemBlock
|
|
{
|
|
private:
|
|
HANDLE m_hMemory;
|
|
void *m_pMemory;
|
|
|
|
protected:
|
|
SECURITY_ATTRIBUTES m_sa;
|
|
|
|
public:
|
|
inline CSharedMemBlock() : m_hMemory(NULL), m_pMemory(NULL) {
|
|
m_sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
m_sa.lpSecurityDescriptor = NULL;
|
|
m_sa.bInheritHandle = FALSE;
|
|
}
|
|
inline ~CSharedMemBlock() {
|
|
UnInitMap();
|
|
if (m_sa.lpSecurityDescriptor)
|
|
free(m_sa.lpSecurityDescriptor);
|
|
}
|
|
|
|
inline void *PMemory() { return m_pMemory; }
|
|
|
|
HRESULT InitSD();
|
|
HRESULT InitMap(LPCSTR szName, DWORD dwSize);
|
|
HRESULT UnInitMap();
|
|
private:
|
|
HRESULT CreateSids( PSID *ppBuiltInAdministrators,
|
|
PSID *ppPowerUsers,
|
|
PSID *ppAuthenticatedUsers);
|
|
};
|
|
|
|
//
|
|
// CreateSids
|
|
//
|
|
// Create 3 Security IDs
|
|
//
|
|
// Caller must free memory allocated to SIDs on success.
|
|
//
|
|
// Returns: HRESULT indicating SUCCESS or FAILURE
|
|
//
|
|
inline HRESULT CSharedMemBlock::CreateSids(
|
|
PSID *ppBuiltInAdministrators,
|
|
PSID *ppPowerUsers,
|
|
PSID *ppAuthenticatedUsers
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
*ppBuiltInAdministrators = NULL;
|
|
*ppPowerUsers = NULL;
|
|
*ppAuthenticatedUsers = NULL;
|
|
|
|
//
|
|
// An SID is built from an Identifier Authority and a set of Relative IDs
|
|
// (RIDs). The Authority of interest to us SECURITY_NT_AUTHORITY.
|
|
//
|
|
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
//
|
|
// Each RID represents a sub-unit of the authority. Two of the SIDs we
|
|
// want to build, Local Administrators, and Power Users, are in the "built
|
|
// in" domain. The other SID, for Authenticated users, is based directly
|
|
// off of the authority.
|
|
//
|
|
// For examples of other useful SIDs consult the list in
|
|
// \nt\public\sdk\inc\ntseapi.h.
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&NtAuthority,
|
|
2, // 2 sub-authorities
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0,0,0,0,0,0,
|
|
ppBuiltInAdministrators)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
} else if (!AllocateAndInitializeSid(&NtAuthority,
|
|
2, // 2 sub-authorities
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_POWER_USERS,
|
|
0,0,0,0,0,0,
|
|
ppPowerUsers)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
} else if (!AllocateAndInitializeSid(&NtAuthority,
|
|
1, // 1 sub-authority
|
|
SECURITY_AUTHENTICATED_USER_RID,
|
|
0,0,0,0,0,0,0,
|
|
ppAuthenticatedUsers)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
if (*ppBuiltInAdministrators) {
|
|
FreeSid(*ppBuiltInAdministrators);
|
|
*ppBuiltInAdministrators = NULL;
|
|
}
|
|
|
|
if (*ppPowerUsers) {
|
|
FreeSid(*ppPowerUsers);
|
|
*ppPowerUsers = NULL;
|
|
}
|
|
|
|
if (*ppAuthenticatedUsers) {
|
|
FreeSid(*ppAuthenticatedUsers);
|
|
*ppAuthenticatedUsers = NULL;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// InitSD
|
|
//
|
|
// Creates a SECURITY_DESCRIPTOR with specific DACLs.
|
|
//
|
|
|
|
inline HRESULT CSharedMemBlock::InitSD()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PSID pAuthenticatedUsers = NULL;
|
|
PSID pBuiltInAdministrators = NULL;
|
|
PSID pPowerUsers = NULL;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
|
|
if (m_sa.lpSecurityDescriptor != NULL) {
|
|
return S_OK;
|
|
}
|
|
|
|
if (FAILED(hr = CreateSids(&pBuiltInAdministrators,
|
|
&pPowerUsers,
|
|
&pAuthenticatedUsers)));
|
|
|
|
|
|
else {
|
|
|
|
//
|
|
// Calculate the size of and allocate a buffer for the DACL, we need
|
|
// this value independently of the total alloc size for ACL init.
|
|
//
|
|
|
|
ULONG AclSize;
|
|
|
|
//
|
|
// "- sizeof (ULONG)" represents the SidStart field of the
|
|
// ACCESS_ALLOWED_ACE. Since we're adding the entire length of the
|
|
// SID, this field is counted twice.
|
|
//
|
|
|
|
AclSize = sizeof (ACL) +
|
|
(3 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) +
|
|
GetLengthSid(pAuthenticatedUsers) +
|
|
GetLengthSid(pBuiltInAdministrators) +
|
|
GetLengthSid(pPowerUsers);
|
|
|
|
pSD = malloc(SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
|
|
|
|
if (!pSD) {
|
|
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
} else {
|
|
|
|
ACL *Acl;
|
|
|
|
Acl = (ACL *)((BYTE *)pSD + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
|
|
if (!InitializeAcl(Acl,
|
|
AclSize,
|
|
ACL_REVISION)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
} else if (!AddAccessAllowedAce(Acl,
|
|
ACL_REVISION,
|
|
SYNCHRONIZE | GENERIC_ALL,
|
|
pAuthenticatedUsers)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
} else if (!AddAccessAllowedAce(Acl,
|
|
ACL_REVISION,
|
|
SYNCHRONIZE | GENERIC_ALL,
|
|
pPowerUsers)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
} else if (!AddAccessAllowedAce(Acl,
|
|
ACL_REVISION,
|
|
SYNCHRONIZE | GENERIC_ALL,
|
|
pBuiltInAdministrators)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
} else if (!InitializeSecurityDescriptor(pSD,
|
|
SECURITY_DESCRIPTOR_REVISION)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
} else if (!SetSecurityDescriptorDacl(pSD,
|
|
TRUE,
|
|
Acl,
|
|
FALSE)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pAuthenticatedUsers)
|
|
FreeSid(pAuthenticatedUsers);
|
|
|
|
if (pBuiltInAdministrators)
|
|
FreeSid(pBuiltInAdministrators);
|
|
|
|
if (pPowerUsers)
|
|
FreeSid(pPowerUsers);
|
|
|
|
if (FAILED(hr) && pSD) {
|
|
free(pSD);
|
|
pSD = NULL;
|
|
}
|
|
|
|
m_sa.lpSecurityDescriptor = pSD;
|
|
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT CSharedMemBlock::InitMap
|
|
(
|
|
LPCSTR szName,
|
|
DWORD dwSize
|
|
)
|
|
{
|
|
BOOL fNew = FALSE;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (FAILED(hr = InitSD())) {
|
|
return hr;
|
|
}
|
|
|
|
// Try to open existing
|
|
m_hMemory = OpenFileMappingA
|
|
(
|
|
FILE_MAP_ALL_ACCESS,
|
|
FALSE,
|
|
szName
|
|
);
|
|
if (!m_hMemory)
|
|
{
|
|
m_hMemory = CreateFileMappingA
|
|
(
|
|
INVALID_HANDLE_VALUE,
|
|
&m_sa,
|
|
PAGE_READWRITE,
|
|
0,
|
|
dwSize,
|
|
szName
|
|
);
|
|
fNew = TRUE;
|
|
}
|
|
if (!m_hMemory)
|
|
return E_FAIL;
|
|
|
|
m_pMemory = MapViewOfFile
|
|
(
|
|
m_hMemory,
|
|
FILE_MAP_ALL_ACCESS,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
if (!m_pMemory)
|
|
{
|
|
UnInitMap();
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (fNew)
|
|
memset(m_pMemory, 0, dwSize);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
inline HRESULT CSharedMemBlock::UnInitMap()
|
|
{
|
|
if (m_pMemory)
|
|
{
|
|
UnmapViewOfFile(m_pMemory);
|
|
m_pMemory = NULL;
|
|
}
|
|
if (m_hMemory)
|
|
{
|
|
CloseHandle(m_hMemory);
|
|
m_hMemory = NULL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/*===================================================================
|
|
CPerfProcBlock - class representing pref data for a single process
|
|
===================================================================*/
|
|
|
|
class CPerfProcBlock : public CSharedMemBlock
|
|
{
|
|
|
|
friend class CPerfMainBlock;
|
|
|
|
protected:
|
|
DWORD m_fInited : 1;
|
|
DWORD m_fMemCSInited : 1;
|
|
DWORD m_fReqCSInited : 1;
|
|
|
|
// critical sections (only used in ASP.DLL)
|
|
CRITICAL_SECTION m_csMemLock; // CS for memory counters
|
|
CRITICAL_SECTION m_csReqLock; // CS for per-request counters
|
|
|
|
// block of counters
|
|
CPerfProcBlockData *m_pData;
|
|
|
|
// next process data (used in ASPPERF.DLL)
|
|
CPerfProcBlock *m_pNext;
|
|
|
|
// access shared memory
|
|
HRESULT MapMemory(const CLSID &ClsId);
|
|
|
|
public:
|
|
inline CPerfProcBlock()
|
|
: m_fInited(FALSE),
|
|
m_fMemCSInited(FALSE), m_fReqCSInited(FALSE),
|
|
m_pData(NULL), m_pNext(NULL)
|
|
{}
|
|
|
|
inline ~CPerfProcBlock() { UnInit(); }
|
|
|
|
HRESULT InitCriticalSections();
|
|
|
|
HRESULT InitExternal(const CLSID &ClsId); // from ASPPERF.DLL
|
|
|
|
HRESULT InitForThisProcess // from ASP.DLL
|
|
(
|
|
const CLSID &ClsId,
|
|
DWORD *pdwInitCounters = NULL
|
|
);
|
|
|
|
HRESULT UnInit();
|
|
};
|
|
|
|
inline HRESULT CPerfProcBlock::MapMemory
|
|
(
|
|
const CLSID &ClsId
|
|
)
|
|
{
|
|
// Construct unique map name with CLSID
|
|
char szMapName[CCH_PERF_PROC_FILEMAP_PREFIX+32+1];
|
|
strcpy(szMapName, SZ_PERF_PROC_FILEMAP_PREFIX);
|
|
|
|
char *pszHex = szMapName + CCH_PERF_PROC_FILEMAP_PREFIX;
|
|
DWORD *pdwHex = (DWORD *)&ClsId;
|
|
for (int i = 0; i < 4; i++, pszHex += 8, pdwHex++)
|
|
sprintf(pszHex, "%08x", *pdwHex);
|
|
|
|
// create or open the map
|
|
HRESULT hr = InitMap(szMapName, CB_PERF_PROC_BLOCK);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_pData = (CPerfProcBlockData *)PMemory();
|
|
|
|
if (m_pData->m_ClsId == CLSID_NULL)
|
|
m_pData->m_ClsId = ClsId;
|
|
else if (m_pData->m_ClsId != ClsId)
|
|
hr = E_FAIL; // cls id mismatch
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT CPerfProcBlock::InitCriticalSections()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_fMemCSInited)
|
|
{
|
|
__try { INITIALIZE_CRITICAL_SECTION(&m_csMemLock); }
|
|
__except(1) { hr = E_UNEXPECTED; }
|
|
if (SUCCEEDED(hr))
|
|
m_fMemCSInited = TRUE;
|
|
else
|
|
return hr;
|
|
}
|
|
|
|
if (!m_fReqCSInited)
|
|
{
|
|
__try { INITIALIZE_CRITICAL_SECTION(&m_csReqLock); }
|
|
__except(1) { hr = E_UNEXPECTED; }
|
|
if (SUCCEEDED(hr))
|
|
m_fReqCSInited = TRUE;
|
|
else
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
inline HRESULT CPerfProcBlock::InitExternal
|
|
(
|
|
const CLSID &ClsId
|
|
)
|
|
{
|
|
HRESULT hr = MapMemory(ClsId);
|
|
if (SUCCEEDED(hr))
|
|
m_fInited = TRUE;
|
|
else
|
|
UnInit();
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT CPerfProcBlock::InitForThisProcess
|
|
(
|
|
const CLSID &ClsId,
|
|
DWORD *pdwInitCounters
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Map the shared memory
|
|
if (SUCCEEDED(hr))
|
|
hr = MapMemory(ClsId);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// init the counters
|
|
if (pdwInitCounters)
|
|
memcpy(m_pData->m_rgdwCounters, pdwInitCounters, CB_COUNTERS);
|
|
else
|
|
memset(m_pData->m_rgdwCounters, 0, CB_COUNTERS);
|
|
|
|
m_fInited = TRUE;
|
|
}
|
|
else
|
|
{
|
|
UnInit();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT CPerfProcBlock::UnInit()
|
|
{
|
|
if (m_fMemCSInited)
|
|
{
|
|
DeleteCriticalSection(&m_csMemLock);
|
|
m_fMemCSInited = FALSE;
|
|
}
|
|
if (m_fReqCSInited)
|
|
{
|
|
DeleteCriticalSection(&m_csReqLock);
|
|
m_fReqCSInited = FALSE;
|
|
}
|
|
|
|
UnInitMap();
|
|
|
|
m_pData = NULL;
|
|
m_pNext = NULL;
|
|
m_fInited = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
/*===================================================================
|
|
CPerfMainBlock - class representing the main perf data
|
|
===================================================================*/
|
|
|
|
class CPerfMainBlock : public CSharedMemBlock
|
|
{
|
|
private:
|
|
DWORD m_fInited : 1;
|
|
|
|
// the process block directory
|
|
CPerfMainBlockData *m_pData;
|
|
|
|
// mutex to access the process block directory
|
|
HANDLE m_hMutex;
|
|
|
|
// first process data (used in ASPPERF.DLL)
|
|
CPerfProcBlock *m_pProcBlock;
|
|
|
|
// timestamp of main block when the list of process blocks
|
|
// last loaded -- to make decide to reload (ASPPREF.DLL only)
|
|
DWORD m_dwTimestamp;
|
|
|
|
public:
|
|
inline CPerfMainBlock()
|
|
: m_fInited(FALSE),
|
|
m_pData(NULL), m_hMutex(NULL),
|
|
m_pProcBlock(NULL), m_dwTimestamp(NULL)
|
|
{}
|
|
|
|
inline ~CPerfMainBlock() { UnInit(); }
|
|
|
|
HRESULT Init();
|
|
HRESULT UnInit();
|
|
|
|
// lock / unlock using mutex
|
|
HRESULT Lock();
|
|
HRESULT UnLock();
|
|
|
|
// add/remove process record to the main block (used from ASP.DLL)
|
|
HRESULT AddProcess(const CLSID &ClsId);
|
|
HRESULT RemoveProcess(const CLSID &ClsId);
|
|
|
|
// load CPerfProcBlock blocks from the main block into
|
|
// objects (used from APPPREF.DLL)
|
|
HRESULT Load();
|
|
|
|
// gather (sum-up) the statistics from each proc block
|
|
HRESULT GetStats(DWORD *pdwCounters);
|
|
};
|
|
|
|
inline HRESULT CPerfMainBlock::Init()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (FAILED(hr = InitSD())) {
|
|
return hr;
|
|
}
|
|
|
|
m_hMutex = OpenMutexA(MUTEX_ALL_ACCESS, FALSE, SZ_PERF_MUTEX);
|
|
if (!m_hMutex)
|
|
{
|
|
|
|
m_hMutex = CreateMutexA(&m_sa, FALSE, SZ_PERF_MUTEX);
|
|
|
|
}
|
|
|
|
if (!m_hMutex)
|
|
hr = E_FAIL;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = InitMap(SZ_PERF_MAIN_FILEMAP, CB_PERF_MAIN_BLOCK);
|
|
if (SUCCEEDED(hr))
|
|
m_pData = (CPerfMainBlockData *)PMemory();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
m_fInited = TRUE;
|
|
else
|
|
UnInit();
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT CPerfMainBlock::UnInit()
|
|
{
|
|
while (m_pProcBlock)
|
|
{
|
|
CPerfProcBlock *pNext = m_pProcBlock->m_pNext;
|
|
m_pProcBlock->UnInit();
|
|
delete m_pProcBlock;
|
|
m_pProcBlock = pNext;
|
|
}
|
|
|
|
if (m_hMutex)
|
|
{
|
|
CloseHandle(m_hMutex);
|
|
m_hMutex = NULL;
|
|
}
|
|
|
|
UnInitMap();
|
|
|
|
m_dwTimestamp = 0;
|
|
m_pData = NULL;
|
|
m_pProcBlock = NULL;
|
|
m_fInited = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
inline HRESULT CPerfMainBlock::Lock()
|
|
{
|
|
if (!m_hMutex)
|
|
return E_FAIL;
|
|
if (WaitForSingleObject(m_hMutex, PERM_MUTEX_WAIT) == WAIT_TIMEOUT)
|
|
return E_FAIL;
|
|
return S_OK;
|
|
}
|
|
|
|
inline HRESULT CPerfMainBlock::UnLock()
|
|
{
|
|
if (m_hMutex)
|
|
ReleaseMutex(m_hMutex);
|
|
return S_OK;
|
|
}
|
|
|
|
inline HRESULT CPerfMainBlock::AddProcess
|
|
(
|
|
const CLSID &ClsId
|
|
)
|
|
{
|
|
if (!m_fInited)
|
|
return E_FAIL;
|
|
|
|
if (FAILED(Lock())) // lock mutex
|
|
return E_FAIL;
|
|
HRESULT hr = S_OK;
|
|
|
|
BOOL fFound = FALSE;
|
|
// find
|
|
for (DWORD i = 0; i < m_pData->m_cItems; i++)
|
|
{
|
|
if (m_pData->m_rgClsIds[i] == ClsId)
|
|
{
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// add only if not already there
|
|
if (!fFound)
|
|
{
|
|
if (m_pData->m_cItems < C_PERF_PROC_MAX)
|
|
{
|
|
m_pData->m_rgClsIds[m_pData->m_cItems] = ClsId;
|
|
m_pData->m_cItems++;
|
|
m_pData->m_dwTimestamp = GetTickCount();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
UnLock(); // unlock mutex
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT CPerfMainBlock::RemoveProcess
|
|
(
|
|
const CLSID &ClsId
|
|
)
|
|
{
|
|
if (!m_fInited)
|
|
return E_FAIL;
|
|
|
|
if (FAILED(Lock())) // lock mutex
|
|
return E_FAIL;
|
|
HRESULT hr = S_OK;
|
|
|
|
int iFound = -1;
|
|
// find
|
|
for (DWORD i = 0; i < m_pData->m_cItems; i++)
|
|
{
|
|
if (m_pData->m_rgClsIds[i] == ClsId)
|
|
{
|
|
iFound = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// remove
|
|
if (iFound >= 0)
|
|
{
|
|
for (i = iFound; i < m_pData->m_cItems-1; i++)
|
|
m_pData->m_rgClsIds[i] = m_pData->m_rgClsIds[i+1];
|
|
|
|
m_pData->m_cItems--;
|
|
m_pData->m_dwTimestamp = GetTickCount();
|
|
}
|
|
|
|
UnLock(); // unlock mutex
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT CPerfMainBlock::Load()
|
|
{
|
|
if (!m_fInited)
|
|
return E_FAIL;
|
|
|
|
if (m_dwTimestamp == m_pData->m_dwTimestamp)
|
|
return S_OK; // already up-to-date
|
|
|
|
// clear out what we have
|
|
while (m_pProcBlock)
|
|
{
|
|
CPerfProcBlock *pNext = m_pProcBlock->m_pNext;
|
|
m_pProcBlock->UnInit();
|
|
delete m_pProcBlock;
|
|
m_pProcBlock = pNext;
|
|
}
|
|
|
|
if (FAILED(Lock())) // lock mutex
|
|
return E_FAIL;
|
|
HRESULT hr = S_OK;
|
|
|
|
// populate new objects for blocks
|
|
for (DWORD i = 0; i < m_pData->m_cItems; i++)
|
|
{
|
|
CPerfProcBlock *pBlock = new CPerfProcBlock;
|
|
if (!pBlock)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
hr = pBlock->InitExternal(m_pData->m_rgClsIds[i]);
|
|
if (FAILED(hr))
|
|
{
|
|
delete pBlock;
|
|
continue;
|
|
}
|
|
|
|
pBlock->m_pNext = m_pProcBlock;
|
|
m_pProcBlock = pBlock;
|
|
}
|
|
|
|
// remember timestamp
|
|
m_dwTimestamp = SUCCEEDED(hr) ? m_pData->m_dwTimestamp : 0;
|
|
|
|
UnLock(); // unlock mutex
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT CPerfMainBlock::GetStats
|
|
(
|
|
DWORD *pdwCounters
|
|
)
|
|
{
|
|
if (!m_fInited)
|
|
return E_FAIL;
|
|
|
|
// reload if needed
|
|
if (FAILED(Load()))
|
|
return E_FAIL;
|
|
|
|
// init
|
|
memset(pdwCounters, 0, CB_COUNTERS);
|
|
|
|
// gather
|
|
CPerfProcBlock *pBlock = m_pProcBlock;
|
|
while (pBlock)
|
|
{
|
|
for (int i = 0; i < C_PERF_PROC_COUNTERS; i++)
|
|
pdwCounters[i] += pBlock->m_pData->m_rgdwCounters[i];
|
|
pBlock = pBlock->m_pNext;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
#endif // _ASP_PERFDEF_H
|