Article ID: 178885
Article Last Modified on 11/21/2006
================== netperf.h ================================
#define TYPE_MASK 0x00000300
#define TYPE_NOT_SUPPORTED -1
#define TYPE_DWORD 0
#define TYPE_LARGE 1
#define MAX_INDEX 3000
typedef struct
{
DWORDLONG dwlPerf_Time;
DWORDLONG dwlPerf_Frequency;
DWORDLONG dwlBytes_Total;
DWORDLONG dwlBytes_Received;
DWORDLONG dwlBytes_Transmitted;
DWORD dwSessions_Timed_Out;
DWORD dwSessions_Errored_Out;
DWORD dwSessions_Logged_Off;
DWORD dwSessions_Forced_Off;
DWORD dwErrors_Logon;
DWORD dwErrors_Access_Permissions;
DWORD dwErrors_Granted_Access;
DWORD dwErrors_System;
DWORD dwBlocking_Requests_Rejected;
DWORD dwWork_Item_Shortages;
DWORD dwFiles_Opened_Total;
DWORD dwFiles_Open;
DWORD dwServer_Sessions;
DWORD dwContext_Blocks_Queued;
DWORD dwLogon_Total;
}SERVER_STATS, *PSERVER_STATS;
typedef struct
{
TCHAR *szName;
int nType;
union
{
DWORD dwCounter;
DWORDLONG dwlCounter;
};
}COUNTER;
// Function to return server statistics.
LONG GetServerStats(TCHAR *szMachine, PSERVER_STATS pServerStats);
LONG GetCounterNames(TCHAR *szMachine, LPVOID *lplpCounterNames);
void GetCounterIndices(DWORD Index[], LPVOID lpCounterNames,
COUNTER Counter[], DWORD dwNumCounters);
LONG GetObjectData(TCHAR *szMachine, int nIndex, LPVOID *lplpObj);
void InitServerStats(PSERVER_STATS pServerStats, COUNTER Counter[]);
LONG GetCounters(LPVOID lpObj, COUNTER Counter[],
DWORD dwNumCounters, DWORD Index[]);
================== netperf.c ================================
#include "netperf.h"
LONG GetServerStats(TCHAR *szMachine, PSERVER_STATS pServerStats)
{
LPVOID lpServerObj, lpCounterNames;
DWORD dwNumCounters;
LONG lErr;
DWORD Index[MAX_INDEX + 1];
COUNTER Counter[] = {{_T("Server"), -1, 0},
{_T("Bytes Total/sec"), -1, 0},
{_T("Bytes Received/sec"), -1, 0},
{_T("Bytes Transmitted/sec"), -1, 0},
{_T("Sessions Timed Out"), -1, 0},
{_T("Sessions Errored Out"), -1, 0},
{_T("Sessions Logged Off"), -1, 0},
{_T("Sessions Forced Off"), -1, 0},
{_T("Errors Logon"), -1, 0},
{_T("Errors Access Permissions"), -1, 0},
{_T("Errors Granted Access"), -1, 0},
{_T("Errors System"), -1, 0},
{_T("Blocking Requests Rejected"), -1, 0},
{_T("Work Item Shortages"), -1, 0},
{_T("Files Opened Total"), -1, 0},
{_T("Files Open"), -1, 0},
{_T("Server Sessions"), -1, 0},
{_T("Context Blocks Queued/sec"), -1, 0},
{_T("Logon Total"), -1, 0}};
// Get the list of counter names and indices.
lErr = GetCounterNames(szMachine, &lpCounterNames);
if(lErr != ERROR_SUCCESS)
{
return lErr;
}
dwNumCounters = sizeof(Counter) / sizeof(COUNTER);
// Retrieve and save the indices for counters of interest.
GetCounterIndices(Index, lpCounterNames, Counter, dwNumCounters);
// Get the performance data for the "Server" object.
lErr = GetObjectData(szMachine, Index[0], &lpServerObj);
if(lErr != ERROR_SUCCESS)
{
GlobalFreePtr(lpCounterNames);
return lErr;
}
// Retrieve selected counter data from the "Server" object.
lErr = GetCounters(lpServerObj, Counter, dwNumCounters, Index);
if(lErr != ERROR_SUCCESS)
{
GlobalFreePtr(lpServerObj);
GlobalFreePtr(lpCounterNames);
return lErr;
}
// Initialize the SERVER_STATS data structure with our results.
InitServerStats(pServerStats, Counter);
// Save PerfTime and PerfFreq as well.
pServerStats->dwlPerf_Time =
((PPERF_DATA_BLOCK)lpServerObj)->PerfTime.HighPart << 32 |
((PPERF_DATA_BLOCK)lpServerObj)->PerfTime.LowPart;
pServerStats->dwlPerf_Frequency =
((PPERF_DATA_BLOCK)lpServerObj)->PerfFreq.HighPart << 32 |
((PPERF_DATA_BLOCK)lpServerObj)->PerfFreq.LowPart;
GlobalFreePtr(lpServerObj);
GlobalFreePtr(lpCounterNames);
return lErr;
}
LONG GetCounterNames(TCHAR *szMachine, LPVOID *lplpCounterNames)
{
DWORD dwType, dwCount = 10000, dwCountRet;
LONG lErr;
HKEY hKey1, hKey2;
if(szMachine && *szMachine)
{
lErr = RegConnectRegistry(szMachine, HKEY_LOCAL_MACHINE, &hKey1);
if(lErr != ERROR_SUCCESS)
{
return lErr; // Unable to connect
}
}
else
{
hKey1 = HKEY_LOCAL_MACHINE;
}
lErr = RegOpenKeyEx(hKey1,
(LPCTSTR)_T(
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009"
),
0, KEY_READ, &hKey2);
RegCloseKey(hKey1);
if(lErr != ERROR_SUCCESS)
{
return lErr; // Not running NT
}
*lplpCounterNames = NULL;
// Keep trying until the buffer is large enough.
do
{
if(*lplpCounterNames) GlobalFreePtr(*lplpCounterNames);
*lplpCounterNames = (LPVOID *)GlobalAllocPtr(GHND, dwCount);
dwCountRet = dwCount;
// Get the counters data.
lErr = RegQueryValueEx(hKey2, (LPCTSTR)_T("Counters"), NULL,
&dwType, (LPBYTE)*lplpCounterNames, &dwCountRet);
dwCount += 1000;
}while(lErr != ERROR_SUCCESS);
RegCloseKey(hKey2);
return ERROR_SUCCESS;
}
void GetCounterIndices(DWORD Index[], LPVOID lpCounterNames,
COUNTER Counter[], DWORD dwNumCounters)
{
DWORD i;
TCHAR *szCur = (TCHAR *)lpCounterNames;
// While not at end of list.
while(*szCur)
{
for(i = 0; i < dwNumCounters; i++)
{
if(!lstrcmp(szCur, Counter[i].szName))
{
TCHAR *szIndex;
// We have a match, so back up to index.
szIndex = szCur;
szIndex -= 2;
while(*szIndex) szIndex--;
szIndex++;
if(i == 0)
{ // Store "Server" index as Index[0].
Index[i] = _ttoi((const TCHAR *)szIndex);
}
else
{ // Otherwise, store index into Counter array.
Index[_ttoi((const TCHAR *)szIndex)] = i;
}
break;
}
}
// Next string.
szCur = _tcschr(szCur, 0);
szCur++;
}
}
LONG GetObjectData(TCHAR *szMachine, int nIndex, LPVOID *lplpObj)
{
HKEY hKey;
DWORD dwType, dwCount = 1000, dwCountRet;
LONG lErr;
TCHAR szIndex[17];
if(szMachine && *szMachine)
{
// Connect to remote machine.
lErr = RegConnectRegistry(szMachine, HKEY_PERFORMANCE_DATA,
&hKey);
if(lErr != ERROR_SUCCESS)
{
return lErr; // Unable to connect.
}
}
else
{
hKey = HKEY_PERFORMANCE_DATA;
}
*lplpObj = NULL;
_itot(nIndex, szIndex, 10);
// Keep trying until the buffer is large enough.
do
{
if(*lplpObj) GlobalFreePtr(*lplpObj);
*lplpObj = (LPVOID)GlobalAllocPtr(GHND, dwCount);
dwCountRet = dwCount;
// Get the server object data.
lErr = RegQueryValueEx(hKey, szIndex, NULL, &dwType,
(LPBYTE)*lplpObj, &dwCountRet);
dwCount += 1000;
}while(lErr != ERROR_SUCCESS);
RegCloseKey(HKEY_PERFORMANCE_DATA);
return ERROR_SUCCESS;
}
void InitServerStats(PSERVER_STATS pServerStats, COUNTER Counter[])
{
pServerStats->dwlBytes_Total = Counter[1].dwlCounter;
pServerStats->dwlBytes_Received = Counter[2].dwlCounter;
pServerStats->dwlBytes_Transmitted = Counter[3].dwlCounter;
pServerStats->dwSessions_Timed_Out = Counter[4].dwCounter;
pServerStats->dwSessions_Errored_Out = Counter[5].dwCounter;
pServerStats->dwSessions_Logged_Off = Counter[6].dwCounter;
pServerStats->dwSessions_Forced_Off = Counter[7].dwCounter;
pServerStats->dwErrors_Logon = Counter[8].dwCounter;
pServerStats->dwErrors_Access_Permissions = Counter[9].dwCounter;
pServerStats->dwErrors_Granted_Access = Counter[10].dwCounter;
pServerStats->dwErrors_System = Counter[11].dwCounter;
pServerStats->dwBlocking_Requests_Rejected = Counter[12].dwCounter;
pServerStats->dwWork_Item_Shortages = Counter[13].dwCounter;
pServerStats->dwFiles_Opened_Total = Counter[14].dwCounter;
pServerStats->dwFiles_Open = Counter[15].dwCounter;
pServerStats->dwServer_Sessions = Counter[16].dwCounter;
pServerStats->dwContext_Blocks_Queued = Counter[17].dwCounter;
pServerStats->dwLogon_Total = Counter[18].dwCounter;
}
LONG GetCounters(LPVOID lpObj, COUNTER Counter[],
DWORD dwNumCounters, DWORD Index[])
{
PPERF_DATA_BLOCK pDataBlock;
PPERF_OBJECT_TYPE pObject;
PPERF_COUNTER_DEFINITION pCounterDef;
DWORD i;
pDataBlock = (PPERF_DATA_BLOCK)lpObj;
if(!pDataBlock->LittleEndian)
{
return ERROR_NOT_SUPPORTED; // Big-endian format not handled.
}
pObject = (PPERF_OBJECT_TYPE)((BYTE *)pDataBlock +
pDataBlock->HeaderLength);
// Multiple objects may be returned.
while(pObject->ObjectNameTitleIndex != Index[0])
{
pObject = (PPERF_OBJECT_TYPE)((BYTE *)pObject +
pObject->TotalByteLength);
}
// Find the first counter definition.
pCounterDef = (PPERF_COUNTER_DEFINITION)((BYTE *)pObject +
pObject->HeaderLength);
for(i = 0; i < pObject->NumCounters; i++)
{
DWORD dwIndex;
// Ignore any data that you do not explicitly seek.
if(Index[pCounterDef->CounterNameTitleIndex] > 0)
{
switch(pCounterDef->CounterType & TYPE_MASK)
{
case PERF_SIZE_DWORD:
dwIndex = pCounterDef->CounterNameTitleIndex;
Counter[Index[dwIndex]].nType = TYPE_DWORD;
// Save the offsets first, and update with data later.
dwIndex = pCounterDef->CounterNameTitleIndex;
Counter[Index[dwIndex]].dwCounter =
pCounterDef->CounterOffset;
break;
case PERF_SIZE_LARGE:
dwIndex = pCounterDef->CounterNameTitleIndex;
Counter[Index[dwIndex]].nType = TYPE_LARGE;
// Save the offsets first, and update with data later.
dwIndex = pCounterDef->CounterNameTitleIndex;
Counter[Index[dwIndex]].dwCounter =
pCounterDef->CounterOffset;
break;
default:
dwIndex = pCounterDef->CounterNameTitleIndex;
Counter[Index[dwIndex]].nType = TYPE_NOT_SUPPORTED;
break;
}
}
// Next counter.
pCounterDef = (PPERF_COUNTER_DEFINITION)((BYTE *)pCounterDef +
pCounterDef->ByteLength);
}
// No instances, so pCounterDef is now pointing
// at the PERF_COUNTER_BLOCK.
// Update data.
for(i = 1; i < dwNumCounters; i++)
{
if(Counter[i].dwlCounter != (DWORDLONG)-1)
{
switch(Counter[i].nType)
{
case TYPE_DWORD:
Counter[i].dwCounter = *(DWORD *)((BYTE *)pCounterDef +
Counter[i].dwCounter);
break;
case TYPE_LARGE:
Counter[i].dwlCounter =
*(DWORDLONG *)((BYTE *)pCounterDef +
Counter[i].dwCounter);
break;
}
}
}
return ERROR_SUCCESS;
}
Keywords: kbdswnet2003swept kbapi kbbug kbcode kbnetwork kbpending KB178885