Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2626 lines
78 KiB

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
ctrtest.c
Abstract:
Program to test the extensible counter dll's
Author:
Bob Watson (bobw) 8 Feb 99
Revision History:
--*/
#include <windows.h>
#include <process.h>
#include <winperf.h>
#include <stdio.h>
#include <stdlib.h>
#include <pdhmsg.h>
#include "strings.h"
#include "ctrtest.h"
///////////////////////////////////////////////////////////////////////////////////////
//
// Data Structures
//
///////////////////////////////////////////////////////////////////////////////////////
typedef struct _LOCAL_THREAD_DATA {
DWORD dwNumObjects;
DWORD dwCycleCount;
DWORD dwLoopCount;
BOOL bTestContents;
BOOL bDisplay;
BOOL bStopOnError;
} LOCAL_THREAD_DATA, *PLOCAL_THREAD_DATA;
///////////////////////////////////////////////////////////////////////////////////////
//
// Globals & Constants
//
///////////////////////////////////////////////////////////////////////////////////////
HANDLE g_hEvent;
EXT_OBJECT* g_pExtObjects = NULL;
LOCAL_THREAD_DATA g_LTData;
BOOL g_fRand = FALSE;
FILE* g_pOutput = NULL;
LPWSTR* g_pNameTable;
DWORD g_dwLastIndex;
HANDLE g_hTestHeap = NULL;
LONG lEventLogLevel = LOG_DEBUG;
LONG lExtCounterTestLevel = EXT_TEST_ALL;
#define PERFVAL_NOCONFIG 0
#define PERFVAL_PASS 1
#define PERFVAL_FAIL 2
#define PERFVAL_TIMEOUT 3
static const WCHAR cszDefaultLangId[] = {L"009"};
static const WCHAR cszNamesKey[] = {L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"};
static const WCHAR cszLastHelp[] = {L"Last Help"};
static const WCHAR cszLastCounter[] = {L"Last Counter"};
static const WCHAR cszVersionName[] = {L"Version"};
static const WCHAR cszCounterName[] = {L"Counter "};
static const WCHAR cszHelpName[] = {L"Explain "};
static const WCHAR cszCounters[] = {L"Counters"};
static const WCHAR cszNotFound[] = {L"*** NOT FOUND ***"};
LPWSTR szTestErrorMessage = NULL;
#define MAX_BUF_SIZE ((DWORD)(1024 * 1024 * 8))
#define PERFLIB_TIMER_INTERVAL 200 // 200 ms Timer
///////////////////////////////////////////////////////////////////////////////////////
//
// Code
//
///////////////////////////////////////////////////////////////////////////////////////
DWORD
InitializeExtObj(EXT_OBJECT* pExtObj)
{
DWORD dwStatus = ERROR_SUCCESS;
BOOL bUseQueryFn = FALSE;
DWORD dwType;
DWORD dwSize;
DWORD dwMemBlockSize = 0; //sizeof(EXT_OBJECT);
DWORD dwOpenTimeout;
DWORD dwCollectTimeout;
DWORD dwObjectArray[MAX_PERF_OBJECTS_IN_QUERY_FUNCTION];
DWORD dwObjIndex = 0;
DWORD dwLinkageStringLen = 0;
DWORD dwFlags = 0;
DWORD dwKeep;
CHAR szOpenProcName[MAX_PATH];
CHAR szCollectProcName[MAX_PATH];
CHAR szCloseProcName[MAX_PATH];
WCHAR szLibraryString[MAX_PATH];
WCHAR szLibraryExpPath[MAX_PATH];
WCHAR mszObjectList[MAX_PATH];
WCHAR szLinkageKeyPath[MAX_PATH];
WCHAR szLinkageString[MAX_PATH];
WCHAR szServicePath[MAX_PATH];
WCHAR szMutexName[MAX_PATH];
WCHAR szPID[32];
LPBYTE szStringBlock;
LPSTR pNextStringA;
LPWSTR pNextStringW;
LPWSTR szThisChar;
LPWSTR szThisObject;
HKEY hServicesKey = NULL;
HKEY hPerfKey = NULL;
LPWSTR szServiceName;
HKEY hKeyLinkage;
HeapValidate (g_hTestHeap, 0, NULL);
if (pExtObj == NULL)
{
dwStatus = ERROR_INVALID_DATA;
}
else
{
// Open the performance subkey
lstrcpyW (szServicePath, cszHklmServicesKey);
dwStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE, szServicePath,
0, KEY_READ, &hServicesKey);
lstrcpyW (szServicePath, pExtObj->szServiceName);
lstrcatW (szServicePath, cszPerformance);
dwStatus = RegOpenKeyExW (hServicesKey, szServicePath,
0, KEY_READ, &hPerfKey);
szServiceName = (LPWSTR)pExtObj->szServiceName;
if ( ERROR_SUCCESS != dwStatus )
{
dwStatus = ERROR_INVALID_DATA;
}
// Read the performance DLL name
if (dwStatus == ERROR_SUCCESS)
{
dwType = 0;
dwSize = sizeof(szLibraryString);
memset (szLibraryString, 0, sizeof(szLibraryString));
memset (szLibraryExpPath, 0, sizeof(szLibraryExpPath));
dwStatus = RegQueryValueExW (hPerfKey,
cszDLLValue,
NULL,
&dwType,
(LPBYTE)szLibraryString,
&dwSize);
if (dwStatus == ERROR_SUCCESS)
{
if (dwType == REG_EXPAND_SZ)
{
// expand any environment vars
dwSize = ExpandEnvironmentStringsW(
szLibraryString,
szLibraryExpPath,
MAX_PATH);
if ((dwSize > MAX_PATH) || (dwSize == 0))
{
dwStatus = ERROR_INVALID_DLL;
}
else
{
dwSize += 1;
dwSize *= sizeof(WCHAR);
dwMemBlockSize += DWORD_MULTIPLE(dwSize);
}
}
else if (dwType == REG_SZ)
{
// look for dll and save full file Path
dwSize = SearchPathW (
NULL, // use standard system search path
szLibraryString,
NULL,
MAX_PATH,
szLibraryExpPath,
NULL);
if ((dwSize > MAX_PATH) || (dwSize == 0))
{
dwStatus = ERROR_INVALID_DLL;
}
else
{
dwSize += 1;
dwSize *= sizeof(WCHAR);
dwMemBlockSize += DWORD_MULTIPLE(dwSize);
}
}
else
{
dwStatus = ERROR_INVALID_DLL;
}
}
}
// Open Function
if (dwStatus == ERROR_SUCCESS)
{
dwType = 0;
dwSize = sizeof(szOpenProcName);
memset (szOpenProcName, 0, sizeof(szOpenProcName));
dwStatus = RegQueryValueExA (hPerfKey,
caszOpenValue,
NULL,
&dwType,
(LPBYTE)szOpenProcName,
&dwSize);
}
// Open Timeout
if (dwStatus == ERROR_SUCCESS)
{
// add in size of previous string
// the size value includes the Term. NULL
dwMemBlockSize += DWORD_MULTIPLE(dwSize);
// we have the procedure name so get the timeout value
dwType = 0;
dwSize = sizeof(dwOpenTimeout);
dwStatus = RegQueryValueExW (hPerfKey,
cszOpenTimeout,
NULL,
&dwType,
(LPBYTE)&dwOpenTimeout,
&dwSize);
// if error, then apply default
if ((dwStatus != ERROR_SUCCESS) || (dwType != REG_DWORD))
{
dwOpenTimeout = 10000;
dwStatus = ERROR_SUCCESS;
}
}
// Close Function
if (dwStatus == ERROR_SUCCESS)
{
dwType = 0;
dwSize = sizeof(szCloseProcName);
memset (szCloseProcName, 0, sizeof(szCloseProcName));
dwStatus = RegQueryValueExA (hPerfKey,
caszCloseValue,
NULL,
&dwType,
(LPBYTE)szCloseProcName,
&dwSize);
}
// Collect Function
if (dwStatus == ERROR_SUCCESS)
{
// add in size of previous string
// the size value includes the Term. NULL
dwMemBlockSize += DWORD_MULTIPLE(dwSize);
// try to look up the query function which is the
// preferred interface if it's not found, then
// try the collect function name. If that's not found,
// then bail
dwType = 0;
dwSize = sizeof(szCollectProcName);
memset (szCollectProcName, 0, sizeof(szCollectProcName));
dwStatus = RegQueryValueExA (hPerfKey,
caszQueryValue,
NULL,
&dwType,
(LPBYTE)szCollectProcName,
&dwSize);
if (dwStatus == ERROR_SUCCESS)
{
// add in size of the Query Function Name
// the size value includes the Term. NULL
dwMemBlockSize += DWORD_MULTIPLE(dwSize);
// get next string
bUseQueryFn = TRUE;
// the query function can support a static object list
// so look it up
}
else
{
// the QueryFunction wasn't found so look up the
// Collect Function name instead
dwType = 0;
dwSize = sizeof(szCollectProcName);
memset (szCollectProcName, 0, sizeof(szCollectProcName));
dwStatus = RegQueryValueExA (hPerfKey,
caszCollectValue,
NULL,
&dwType,
(LPBYTE)szCollectProcName,
&dwSize);
if (dwStatus == ERROR_SUCCESS)
{
// add in size of Collect Function Name
// the size value includes the Term. NULL
dwMemBlockSize += DWORD_MULTIPLE(dwSize);
}
}
}
// Collect Timeout
if (dwStatus == ERROR_SUCCESS)
{
// we have the procedure name so get the timeout value
dwType = 0;
dwSize = sizeof(dwCollectTimeout);
dwStatus = RegQueryValueExW (hPerfKey,
cszCollectTimeout,
NULL,
&dwType,
(LPBYTE)&dwCollectTimeout,
&dwSize);
// if error, then apply default
if ((dwStatus != ERROR_SUCCESS) || (dwType != REG_DWORD))
{
dwCollectTimeout = 10000;
dwStatus = ERROR_SUCCESS;
}
}
// Object List
if (dwStatus == ERROR_SUCCESS)
{
dwType = 0;
dwSize = sizeof(mszObjectList);
memset (mszObjectList, 0, sizeof(mszObjectList));
dwStatus = RegQueryValueExW (hPerfKey,
cszObjListValue,
NULL,
&dwType,
(LPBYTE)mszObjectList,
&dwSize);
if (dwStatus == ERROR_SUCCESS)
{
if (dwType != REG_MULTI_SZ)
{
// convert space delimited list to msz
for (szThisChar = mszObjectList; *szThisChar != 0; szThisChar++)
{
if (*szThisChar == L' ') *szThisChar = L'\0';
}
++szThisChar;
*szThisChar = 0; // add MSZ term Null
}
for (szThisObject = mszObjectList, dwObjIndex = 0;
(*szThisObject != 0) && (dwObjIndex < MAX_PERF_OBJECTS_IN_QUERY_FUNCTION);
szThisObject += lstrlenW(szThisObject) + 1)
{
dwObjectArray[dwObjIndex] = wcstoul(szThisObject, NULL, 10);
dwObjIndex++;
}
if (*szThisObject != 0)
{
// BUGBUG: log error idicating too many object ID's are
// in the list.
}
}
else
{
// reset status since not having this is
// not a showstopper
dwStatus = ERROR_SUCCESS;
}
}
// Keep Resident
if (dwStatus == ERROR_SUCCESS)
{
dwType = 0;
dwKeep = 0;
dwSize = sizeof(dwKeep);
dwStatus = RegQueryValueExW (hPerfKey,
cszKeepResident,
NULL,
&dwType,
(LPBYTE)&dwKeep,
&dwSize);
if ((dwStatus == ERROR_SUCCESS) && (dwType == REG_DWORD))
{
if (dwKeep == 1)
{
dwFlags |= PERF_EO_KEEP_RESIDENT;
}
else
{
// no change.
}
}
else
{
// not fatal, just use the defaults.
dwStatus = ERROR_SUCCESS;
}
}
// Linkage
if (dwStatus == ERROR_SUCCESS)
{
memset (szLinkageString, 0, sizeof(szLinkageString));
lstrcpyW (szLinkageKeyPath, szServiceName);
lstrcatW (szLinkageKeyPath, cszLinkageKey);
dwStatus = RegOpenKeyExW (
hServicesKey,
szLinkageKeyPath,
0L,
KEY_READ,
&hKeyLinkage);
if (dwStatus == ERROR_SUCCESS)
{
// look up export value string
dwSize = sizeof(szLinkageString);
dwType = 0;
dwStatus = RegQueryValueExW (
hKeyLinkage,
cszExportValue,
NULL,
&dwType,
(LPBYTE)&szLinkageString,
&dwSize);
if ((dwStatus != ERROR_SUCCESS) ||
((dwType != REG_SZ) && (dwType != REG_MULTI_SZ)))
{
// clear buffer
memset (szLinkageString, 0, sizeof(szLinkageString));
dwLinkageStringLen = 0;
// not finding a linkage key is not fatal so correct
// status
dwStatus = ERROR_SUCCESS;
}
else
{
// add size of linkage string to buffer
// the size value includes the Term. NULL
dwLinkageStringLen = dwSize;
dwMemBlockSize += DWORD_MULTIPLE(dwSize);
}
RegCloseKey (hKeyLinkage);
}
else
{
// not finding a linkage key is not fatal so correct
// status
dwStatus = ERROR_SUCCESS;
}
}
if (hServicesKey != NULL)
RegCloseKey (hServicesKey);
if (hPerfKey != NULL)
RegCloseKey (hPerfKey);
// Copy data to Performance Library Data Structure
if (dwStatus == ERROR_SUCCESS)
{
// allocate and initialize a new ext. object block
szStringBlock = (LPBYTE)HeapAlloc(g_hTestHeap, HEAP_ZERO_MEMORY, dwMemBlockSize);
if (szStringBlock != NULL)
{
// copy values to new buffer (all others are NULL)
pNextStringA = (LPSTR)szStringBlock;
// copy Open Procedure Name
pExtObj->szOpenProcName = pNextStringA;
lstrcpyA (pNextStringA, szOpenProcName);
pNextStringA += lstrlenA (pNextStringA) + 1;
pNextStringA = (LPSTR)ALIGN_ON_DWORD(pNextStringA);
pExtObj->dwOpenTimeout = dwOpenTimeout;
// copy collect function or query function, depending
pExtObj->szCollectProcName = pNextStringA;
lstrcpyA (pNextStringA, szCollectProcName);
pNextStringA += lstrlenA (pNextStringA) + 1;
pNextStringA = (LPSTR)ALIGN_ON_DWORD(pNextStringA);
pExtObj->dwCollectTimeout = dwCollectTimeout;
// copy Close Procedure Name
pExtObj->szCloseProcName = pNextStringA;
lstrcpyA (pNextStringA, szCloseProcName);
pNextStringA += lstrlenA (pNextStringA) + 1;
pNextStringA = (LPSTR)ALIGN_ON_DWORD(pNextStringA);
// copy Library path
pNextStringW = (LPWSTR)pNextStringA;
pExtObj->szLibraryName = pNextStringW;
lstrcpyW (pNextStringW, szLibraryExpPath);
pNextStringW += lstrlenW (pNextStringW) + 1;
pNextStringW = (LPWSTR)ALIGN_ON_DWORD(pNextStringW);
// copy Linkage String if there is one
if (*szLinkageString != 0) {
pExtObj->szLinkageString = pNextStringW;
memcpy (pNextStringW, szLinkageString, dwLinkageStringLen);
// length includes extra NULL char and is in BYTES
pNextStringW += (dwLinkageStringLen / sizeof (WCHAR));
pNextStringW = (LPWSTR)ALIGN_ON_DWORD(pNextStringW);
}
// load flags
if (bUseQueryFn) {
dwFlags |= PERF_EO_QUERY_FUNC;
}
pExtObj->dwFlags = dwFlags;
// load Object array
if (dwObjIndex > 0) {
pExtObj->dwNumObjects = dwObjIndex;
memcpy (pExtObj->dwObjList,
dwObjectArray, (dwObjIndex * sizeof(dwObjectArray[0])));
}
pExtObj->llLastUsedTime = 0;
// create Mutex name
lstrcpyW (szMutexName, pExtObj->szServiceName);
lstrcatW (szMutexName, (LPCWSTR)L"_Perf_Library_Lock_PID_");
_ultow ((ULONG)GetCurrentProcessId(), szPID, 16);
lstrcatW (szMutexName, szPID);
pExtObj->hMutex = CreateMutexW (NULL, FALSE, szMutexName);
pExtObj->bValid = TRUE;
} else {
dwStatus = ERROR_OUTOFMEMORY;
}
}
}
HeapValidate (g_hTestHeap, 0, NULL);
if (ERROR_SUCCESS != dwStatus)
{
pExtObj->bValid = FALSE;
}
return dwStatus;
}
DWORD
FinializeExtObj(PEXT_OBJECT pInfo)
{
DWORD dwStatus = ERROR_SUCCESS;
// then close everything
if (pInfo->hMutex != NULL) {
CloseHandle (pInfo->hMutex);
pInfo->hMutex = NULL;
}
if ( NULL != pInfo->szOpenProcName )
HeapFree(g_hTestHeap, 0, pInfo->szOpenProcName);
if ( NULL != pInfo->szServiceName )
HeapFree(g_hTestHeap, 0, pInfo->szServiceName);
if ( NULL != pInfo->szQueryString )
HeapFree(g_hTestHeap, 0, pInfo->szQueryString);
return dwStatus;
}
DWORD
OpenLibrary (
EXT_OBJECT *pExtObj)
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwOpenEvent;
UINT nErrorMode;
// check to see if the library has already been opened
LARGE_INTEGER liStartTime, liEndTime, liFreq;
if (pExtObj != NULL)
{
// then load library & look up functions
nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS);
pExtObj->hLibrary = LoadLibraryExW (pExtObj->szLibraryName,
NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (pExtObj->hLibrary != NULL) {
// lookup function names
pExtObj->OpenProc = (OPENPROC)GetProcAddress(
pExtObj->hLibrary, pExtObj->szOpenProcName);
if (pExtObj->OpenProc == NULL) {
wprintf ((LPCWSTR)L"\nOpen Procedure \"%s\" not found in \"%s\"",
pExtObj->szOpenProcName, pExtObj->szLibraryName);
}
} else {
// unable to load library
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tLoadLibraryEx Failed for the \"%s\" Performance Library", GetCurrentThreadId(), pExtObj->szServiceName);
dwStatus = GetLastError();
}
if (dwStatus == ERROR_SUCCESS) {
if (pExtObj->dwFlags & PERF_EO_QUERY_FUNC) {
pExtObj->QueryProc = (QUERYPROC)GetProcAddress (
pExtObj->hLibrary, pExtObj->szCollectProcName);
pExtObj->CollectProc = (COLLECTPROC)pExtObj->QueryProc;
} else {
pExtObj->CollectProc = (COLLECTPROC)GetProcAddress (
pExtObj->hLibrary, pExtObj->szCollectProcName);
pExtObj->QueryProc = (QUERYPROC)pExtObj->CollectProc;
}
if (pExtObj->CollectProc == NULL) {
wprintf ((LPCWSTR)L"\nCollect Procedure \"%s\" not found in \"%s\"",
pExtObj->szCollectProcName, pExtObj->szLibraryName);
}
}
if (dwStatus == ERROR_SUCCESS) {
pExtObj->CloseProc = (CLOSEPROC)GetProcAddress (
pExtObj->hLibrary, pExtObj->szCloseProcName);
if (pExtObj->CloseProc == NULL) {
wprintf ((LPCWSTR)L"\nClose Procedure \"%s\" not found in \"%s\"",
pExtObj->szCloseProcName, pExtObj->szLibraryName);
}
}
if (dwStatus == ERROR_SUCCESS) {
__try {
if ((pExtObj->hMutex != NULL) &&
(pExtObj->OpenProc != NULL)){
dwStatus = WaitForSingleObject (
pExtObj->hMutex,
pExtObj->dwOpenTimeout);
if (dwStatus != WAIT_TIMEOUT) {
QueryPerformanceCounter (&liStartTime);
// dwStatus = (*pExtObj->OpenProc)(pExtObj->szLinkageString);
QueryPerformanceCounter (&liEndTime);
// release the lock
ReleaseMutex(pExtObj->hMutex);
if ( dwStatus != ERROR_SUCCESS )
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \t%S failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pExtObj->szOpenProcName, pExtObj->szServiceName, dwStatus);
}
} else {
pExtObj->dwLockoutCount++;
}
} else {
dwStatus = ERROR_LOCK_FAILED;
}
// check the result.
if (dwStatus != ERROR_SUCCESS) {
dwOpenEvent = WBEMPERF_OPEN_PROC_FAILURE;
} else {
InterlockedIncrement((LONG *)&pExtObj->dwOpenCount);
pExtObj->llFunctionTime = liEndTime.QuadPart - liStartTime.QuadPart;
pExtObj->llOpenTime += pExtObj->llFunctionTime;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwStatus = GetExceptionCode();
dwOpenEvent = WBEMPERF_OPEN_PROC_EXCEPTION;
}
}
QueryPerformanceFrequency (&liFreq);
pExtObj->llTimeBase = liFreq.QuadPart;
if (dwStatus != ERROR_SUCCESS) {
// clear fields
pExtObj->OpenProc = NULL;
pExtObj->CollectProc = NULL;
pExtObj->QueryProc = NULL;
pExtObj->CloseProc = NULL;
if (pExtObj->hLibrary != NULL) {
FreeLibrary (pExtObj->hLibrary);
pExtObj->hLibrary = NULL;
}
} else {
GetSystemTimeAsFileTime ((FILETIME *)&pExtObj->llLastUsedTime);
}
} // else no buffer returned
return dwStatus;
}
DWORD
ClearSafeBuffer( PSAFE_BUFFER pSafeBufferBlock )
{
DWORD dwStatus = ERROR_SUCCESS;
if (pSafeBufferBlock != NULL)
{
if (pSafeBufferBlock->lpBuffer != NULL)
HeapFree (g_hTestHeap, 0, pSafeBufferBlock->lpBuffer);
pSafeBufferBlock->lpLowGuardPage = NULL;
pSafeBufferBlock->lpHiGuardPage = NULL;
pSafeBufferBlock->lpEndPointer = NULL;
pSafeBufferBlock->lpBuffer = NULL;
pSafeBufferBlock->lpSafeBuffer = NULL;
pSafeBufferBlock->lpCallBuffer = NULL;
}
else
{
dwStatus = ERROR_INVALID_DATA;
}
return dwStatus;
}
DWORD
CreateSafeBuffer( PSAFE_BUFFER pSafeBufferBlock )
{
DWORD dwStatus = ERROR_SUCCESS;
if (NULL == pSafeBufferBlock)
{
dwStatus = ERROR_INVALID_DATA;
}
if (dwStatus == ERROR_SUCCESS)
{
if (pSafeBufferBlock->lpBuffer != NULL)
HeapFree (g_hTestHeap, 0, pSafeBufferBlock->lpBuffer);
pSafeBufferBlock->dwBufSize += pSafeBufferBlock->dwBufSizeIncrement;
pSafeBufferBlock->dwCallBufSize = pSafeBufferBlock->dwBufSize;
pSafeBufferBlock->lpBuffer = HeapAlloc (g_hTestHeap,
HEAP_ZERO_MEMORY,
pSafeBufferBlock->dwBufSize + (2*GUARD_PAGE_SIZE));
if (NULL != pSafeBufferBlock->lpBuffer)
{
// set buffer pointers
pSafeBufferBlock->lpLowGuardPage = pSafeBufferBlock->lpBuffer;
pSafeBufferBlock->lpSafeBuffer = (LPBYTE)pSafeBufferBlock->lpBuffer + GUARD_PAGE_SIZE;
pSafeBufferBlock->lpCallBuffer = pSafeBufferBlock->lpSafeBuffer;
pSafeBufferBlock->lpHiGuardPage = (LPBYTE)pSafeBufferBlock->lpCallBuffer + pSafeBufferBlock->dwBufSize;
pSafeBufferBlock->lpEndPointer = (LPBYTE)pSafeBufferBlock->lpHiGuardPage + GUARD_PAGE_SIZE;
memset (pSafeBufferBlock->lpLowGuardPage, GUARD_PAGE_CHAR, GUARD_PAGE_SIZE);
memset (pSafeBufferBlock->lpHiGuardPage, GUARD_PAGE_CHAR, GUARD_PAGE_SIZE);
}
else
{
dwStatus = ERROR_OUTOFMEMORY;
}
}
if (dwStatus != ERROR_SUCCESS)
{
dwStatus = ClearSafeBuffer( pSafeBufferBlock );
}
return dwStatus;
}
DWORD
CheckGuardBytes( PSAFE_BUFFER pSafeBufferBlock, PEXT_OBJECT pObj )
{
DWORD dwStatus = ERROR_SUCCESS;
LPDWORD lpCheckPointer;
//
// check for buffer corruption here
//
if (lExtCounterTestLevel <= EXT_TEST_BASIC)
{
//
// check 1: bytes left should be the same as
// new data buffer ptr - orig data buffer ptr
//
if (pSafeBufferBlock->dwCallBufSize != (DWORD)((LPBYTE)pSafeBufferBlock->lpCallBuffer - (LPBYTE)pSafeBufferBlock->lpSafeBuffer))
{
pObj->dwBadPointers++;
dwStatus = ERROR_INVALID_DATA;
}
//
// check 2: buffer after ptr should be < hi Guard page ptr
//
if ((dwStatus == ERROR_SUCCESS) &&
((LPBYTE)pSafeBufferBlock->lpCallBuffer >= (LPBYTE)pSafeBufferBlock->lpHiGuardPage))
{
// see if they exceeded the allocated memory
if ((LPBYTE)pSafeBufferBlock->lpCallBuffer >= (LPBYTE)pSafeBufferBlock->lpEndPointer)
{
// even worse!!
}
pObj->dwBufferSizeErrors++;
dwStatus = ERROR_INVALID_DATA;
}
//
// check 3: check lo guard page for corruption
//
if (dwStatus == ERROR_SUCCESS )
{
for (lpCheckPointer = (LPDWORD)pSafeBufferBlock->lpLowGuardPage;
lpCheckPointer < (LPDWORD)pSafeBufferBlock->lpSafeBuffer;
lpCheckPointer++)
{
if (*lpCheckPointer != GUARD_PAGE_DWORD)
{
pObj->dwLowerGPViolations++;
dwStatus = ERROR_INVALID_DATA;
break;
}
}
}
//
// check 4: check hi guard page for corruption
//
if (dwStatus == ERROR_SUCCESS)
{
for (lpCheckPointer = (LPDWORD)pSafeBufferBlock->lpHiGuardPage;
lpCheckPointer < (LPDWORD)pSafeBufferBlock->lpEndPointer;
lpCheckPointer++)
{
if (*lpCheckPointer != GUARD_PAGE_DWORD)
{
pObj->dwUpperGPViolations++;
dwStatus = ERROR_INVALID_DATA;
break;
}
}
}
}
if (dwStatus != ERROR_SUCCESS)
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tGuardbyte violation for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pObj->szServiceName, dwStatus);
}
return dwStatus;
}
DWORD
ValidateBuffer( PSAFE_BUFFER pSafeBufferBlock, EXT_OBJECT *pThisExtObj )
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwObjectBufSize;
DWORD dwIndex;
LONG lInstIndex;
PERF_OBJECT_TYPE *pObject, *pNextObject;
PERF_INSTANCE_DEFINITION *pInstance;
PERF_DATA_BLOCK *pPerfData;
BOOL bForeignDataBuffer;
if (NULL == pSafeBufferBlock)
{
dwStatus = ERROR_INVALID_DATA;
}
// Validate the blob size
if ( dwStatus == ERROR_SUCCESS )
{
if (( pSafeBufferBlock->dwCallBufSize < 0 ) ||
( pSafeBufferBlock->dwCallBufSize > pSafeBufferBlock->dwBufSize ))
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tBuffer size parameter does not match the buffer displacement in the data returned for the \"%s\" performance library", GetCurrentThreadId(), pThisExtObj->szServiceName);
pThisExtObj->dwBufferSizeErrors++;
dwStatus = ERROR_INVALID_PARAMETER;
}
}
// Validate the byte alignment
if (dwStatus == ERROR_SUCCESS)
{
if (pSafeBufferBlock->dwCallBufSize & 0x00000007)
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tByte Allignment Error in the data returned for the \"%s\" performance library", GetCurrentThreadId(), pThisExtObj->szServiceName);
pThisExtObj->dwAlignmentErrors++;
dwStatus = ERROR_INVALID_DATA;
}
}
if ( dwStatus == ERROR_SUCCESS )
{
dwStatus = CheckGuardBytes( pSafeBufferBlock, pThisExtObj );
}
if ((lExtCounterTestLevel <= EXT_TEST_ALL) && (dwStatus == ERROR_SUCCESS))
{
//
// Internal consistency checks
//
//
// Check 5: Check object length field values
//
// first test to see if this is a foreign
// computer data block or not
//
pPerfData = (PERF_DATA_BLOCK *)pSafeBufferBlock->lpSafeBuffer;
if ((pPerfData->Signature[0] == (WCHAR)'P') &&
(pPerfData->Signature[1] == (WCHAR)'E') &&
(pPerfData->Signature[2] == (WCHAR)'R') &&
(pPerfData->Signature[3] == (WCHAR)'F'))
{
// if this is a foreign computer data block, then the
// first object is after the header
pObject = (PERF_OBJECT_TYPE *) ((LPBYTE)pPerfData + pPerfData->HeaderLength);
bForeignDataBuffer = TRUE;
}
else
{
// otherwise, if this is just a buffer from
// an extensible counter, the object starts
// at the beginning of the buffer
pObject = (PERF_OBJECT_TYPE *)pSafeBufferBlock->lpSafeBuffer;
bForeignDataBuffer = FALSE;
}
// go to where the pointers say the end of the
// buffer is and then see if it's where it
// should be
dwObjectBufSize = 0;
for (dwIndex = 0; dwIndex < pThisExtObj->dwNumObjectsRet; dwIndex++)
{
dwObjectBufSize += pObject->TotalByteLength;
pObject = (PERF_OBJECT_TYPE *)((LPBYTE)pObject +
pObject->TotalByteLength);
}
if (((LPBYTE)pObject != (LPBYTE)pSafeBufferBlock->lpCallBuffer) ||
(dwObjectBufSize > pSafeBufferBlock->dwCallBufSize))
{
// then a length field is incorrect. This is FATAL
// since it can corrupt the rest of the buffer
// and render the buffer unusable.
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tObject in blob overruns the buffer boundary in the data returned for the \"%s\" Performance Library", GetCurrentThreadId(), pThisExtObj->szServiceName);
pThisExtObj->dwObjectSizeErrors++;
dwStatus = ERROR_INVALID_DATA;
}
//
// Test 6: Test instance field size values
//
if (dwStatus == ERROR_SUCCESS)
{
// set object pointer
if (bForeignDataBuffer)
{
pObject = (PERF_OBJECT_TYPE *) (
(LPBYTE)pPerfData + pPerfData->HeaderLength);
}
else
{
// otherwise, if this is just a buffer from
// an extensible counter, the object starts
// at the beginning of the buffer
pObject = (PERF_OBJECT_TYPE *)pSafeBufferBlock->lpSafeBuffer;
}
for (dwIndex = 0; dwIndex < pThisExtObj->dwNumObjectsRet; dwIndex++)
{
pNextObject = (PERF_OBJECT_TYPE *)((LPBYTE)pObject +
pObject->TotalByteLength);
if (pObject->NumInstances != PERF_NO_INSTANCES)
{
pInstance = (PERF_INSTANCE_DEFINITION *)
((LPBYTE)pObject + pObject->DefinitionLength);
lInstIndex = 0;
while (lInstIndex < pObject->NumInstances)
{
PERF_COUNTER_BLOCK *pCounterBlock;
// NOTE: this does not walk the instance/counter block, nor does it check the validity of the addresses
pCounterBlock = (PERF_COUNTER_BLOCK *)
((PCHAR) pInstance + pInstance->ByteLength);
pInstance = (PERF_INSTANCE_DEFINITION *)
((PCHAR) pCounterBlock + pCounterBlock->ByteLength);
lInstIndex++;
}
if ((LPBYTE)pInstance > (LPBYTE)pNextObject)
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tInsatnce data overruns the following object data in the data returned for the \"%s\" Performance Library", GetCurrentThreadId(), pThisExtObj->szServiceName);
dwStatus = ERROR_INVALID_DATA;
}
}
if (dwStatus != ERROR_SUCCESS)
{
break;
}
else
{
pObject = pNextObject;
}
}
if (dwStatus != ERROR_SUCCESS)
{
pThisExtObj->dwInstanceSizeErrors++;
}
}
}
return dwStatus;
}
DWORD
ValidateBlob( PSAFE_BUFFER pSafeBufferBlock, EXT_OBJECT *pThisExtObj )
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD nObjIdx, nCtrIdx;
DWORD dwLastId = g_dwLastIndex;
PERF_OBJECT_TYPE * pObjDef = NULL;
PERF_COUNTER_DEFINITION * pCtrDef;
// Validate the data
// =================
if (pSafeBufferBlock->dwBufSize >= MAX_BUF_SIZE) {
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tCollectFunction for %s requires a buffer > %d bytes", GetCurrentThreadId(), pThisExtObj->szServiceName, MAX_BUF_SIZE);
if (pSafeBufferBlock->lpBuffer != NULL) HeapFree (g_hTestHeap, 0, pSafeBufferBlock->lpBuffer);
dwStatus = ERROR_INVALID_PARAMETER;
} else if (pSafeBufferBlock->lpBuffer == NULL) {
dwStatus = ERROR_OUTOFMEMORY;
} else {
// Validate the objects
// ====================
pObjDef = (PERF_OBJECT_TYPE *)pSafeBufferBlock->lpSafeBuffer;
for (nObjIdx = 0; nObjIdx < pThisExtObj->dwNumObjectsRet; nObjIdx++) {
// test object name & help
if ((pObjDef->ObjectNameTitleIndex <= dwLastId) &&
(pObjDef->ObjectNameTitleIndex > 0)) {
if (g_pNameTable[pObjDef->ObjectNameTitleIndex ] == NULL) {
// no string
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tNo Object Name Display String for index %d", GetCurrentThreadId(), pObjDef->ObjectNameTitleIndex );
dwStatus = ERROR_BADKEY;
} else {
// probably ok
}
} else {
// id out of range
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tObject Name Index values are bad or missing", GetCurrentThreadId());
dwStatus = ERROR_BADKEY;
}
if ((pObjDef->ObjectHelpTitleIndex <= dwLastId) &&
(pObjDef->ObjectHelpTitleIndex> 0)) {
if (g_pNameTable[pObjDef->ObjectHelpTitleIndex] == NULL) {
// no string
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tNo Object Help Display String for index %d", GetCurrentThreadId(), pObjDef->ObjectHelpTitleIndex );
dwStatus = ERROR_BADKEY;
} else {
// probably ok
}
} else {
// id out of range
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tObject Help Index values are bad or missing", GetCurrentThreadId());
dwStatus = ERROR_BADKEY;
}
// Validate the counters
// =====================
pCtrDef = FirstCounter (pObjDef);
for (nCtrIdx = 0; nCtrIdx < pObjDef->NumCounters; nCtrIdx++) {
if ((pCtrDef->CounterNameTitleIndex <= dwLastId) &&
(pCtrDef->CounterNameTitleIndex > 0)) {
if ((g_pNameTable[pCtrDef->CounterNameTitleIndex ] == NULL) &&
((pCtrDef->CounterType & PERF_COUNTER_BASE) == 0)) {
// no string
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tNo Counter Name Display String for index %d", GetCurrentThreadId(), pCtrDef->CounterNameTitleIndex );
dwStatus = ERROR_BADKEY;
} else {
// probably ok
}
} else {
// id out of range
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tCounter Name Index values are bad or missing", GetCurrentThreadId());
dwStatus = ERROR_BADKEY;
}
// test counter defs
if ((pCtrDef->CounterHelpTitleIndex <= dwLastId) &&
(pCtrDef->CounterHelpTitleIndex> 0)) {
if ((g_pNameTable[pCtrDef->CounterHelpTitleIndex] == NULL) &&
((pCtrDef->CounterType & PERF_COUNTER_BASE) == 0)) {
// no string
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tNo Counter Help Display String for index %d", GetCurrentThreadId(), pCtrDef->CounterHelpTitleIndex );
dwStatus = ERROR_BADKEY;
} else {
// probably ok
}
} else {
// id out of range
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR:\tCounter Help Index values are bad or missing", GetCurrentThreadId());
dwStatus = ERROR_BADKEY;
}
if (nCtrIdx < ( pObjDef->NumCounters - 1 ) )
pCtrDef = NextCounter (pCtrDef);
}
if ( nObjIdx < ( pThisExtObj->dwNumObjectsRet - 1 ) )
pObjDef = NextObject (pObjDef);
}
}
return dwStatus;
}
DWORD
Validate( PSAFE_BUFFER pSafeBufferBlock, EXT_OBJECT *pThisExtObj )
{
DWORD dwStatus = ERROR_SUCCESS;
dwStatus = ValidateBuffer( pSafeBufferBlock, pThisExtObj );
if (dwStatus == ERROR_SUCCESS)
{
dwStatus = ValidateBlob( pSafeBufferBlock, pThisExtObj );
if ( dwStatus != ERROR_SUCCESS )
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tBlob Data Validation failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pThisExtObj->szServiceName, dwStatus);
}
}
else
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tBuffer Validation failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pThisExtObj->szServiceName, dwStatus);
}
return dwStatus;
}
//***************************************************************************
//
// CollectData (LPBYTE pBuffer,
// LPDWORD pdwBufferSize,
// LPWSTR pszItemList)
//
// Collects data from the perf objects and libraries added to the access
// object
//
// Inputs:
//
// pBuffer - pointer to start of data block
// where data is being collected
//
// pdwBufferSize - pointer to size of data buffer
//
// pszItemList - string to pass to ext DLL
//
// Outputs:
//
// *lppDataDefinition - set to location for next Type
// Definition if successful
//
// Returns:
//
// 0 if successful, else Win 32 error code of failure
//
//
//***************************************************************************
//
DWORD
CollectData (EXT_OBJECT *pThisExtObj)
{
DWORD dwStatus = ERROR_SUCCESS; // Failure code
SAFE_BUFFER SafeBufferBlock; // Buffer block
DWORD NumObjectTypes = 0; // Number of object returned from collection function
LARGE_INTEGER liStartTime, // Collect start time
liEndTime, // Collect end time
liFreq; // Timer frequency
DOUBLE dMs = 0; // Timer data
memset(&SafeBufferBlock, 0, sizeof(SAFE_BUFFER));
SafeBufferBlock.dwBufSize = 4098;
SafeBufferBlock.dwBufSizeIncrement = 1024;
// Collect the data
// ================
dwStatus = ERROR_MORE_DATA;
while ((dwStatus == ERROR_MORE_DATA) && (SafeBufferBlock.dwBufSize < MAX_BUF_SIZE))
{
// allocate a local block of memory to pass to the
// extensible counter function.
dwStatus = CreateSafeBuffer( &SafeBufferBlock );
if ( dwStatus == ERROR_SUCCESS )
{
// initialize values to pass to the extensible counter function
NumObjectTypes = 0;
if ((pThisExtObj->hMutex != NULL) &&
(pThisExtObj->CollectProc != NULL))
{
dwStatus = WaitForSingleObject ( pThisExtObj->hMutex, pThisExtObj->dwCollectTimeout);
if (dwStatus != WAIT_TIMEOUT)
{
__try
{
QueryPerformanceCounter (&liStartTime);
{
LPBYTE pBuffer = SafeBufferBlock.lpCallBuffer;
DWORD dwBufSize = SafeBufferBlock.dwCallBufSize;
dwStatus = (*pThisExtObj->CollectProc) (
(LPWSTR)pThisExtObj->szQueryString,
&pBuffer,
&dwBufSize,
&NumObjectTypes);
SafeBufferBlock.dwCallBufSize = dwBufSize;
SafeBufferBlock.lpCallBuffer = pBuffer;
}
QueryPerformanceCounter (&liEndTime);
if (( dwStatus != ERROR_SUCCESS ) && ( dwStatus != ERROR_MORE_DATA ))
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \t%S failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pThisExtObj->szCollectProcName, pThisExtObj->szServiceName, dwStatus);
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
dwStatus = GetExceptionCode();
InterlockedIncrement ((LONG *)&pThisExtObj->dwExceptionCount);
}
ReleaseMutex (pThisExtObj->hMutex);
}
else
{
pThisExtObj->dwLockoutCount++;
}
}
else
{
dwStatus = ERROR_LOCK_FAILED;
}
} // if CreateSafeBuffer()
} // While
// Copy the data
// =============
if (dwStatus == ERROR_SUCCESS)
{
// Validate the collection time
if (dwStatus == ERROR_SUCCESS)
{
liFreq.QuadPart = 0;
QueryPerformanceFrequency (&liFreq);
pThisExtObj->llTimeBase = liFreq.QuadPart;
pThisExtObj->llFunctionTime = liEndTime.QuadPart - liStartTime.QuadPart;
pThisExtObj->llCollectTime += pThisExtObj->llFunctionTime;
// check the time spent in this function
dMs = (DOUBLE)pThisExtObj->llFunctionTime;
dMs /= (DOUBLE)pThisExtObj->llTimeBase;
dMs *= 1000.0;
if (dMs > (DOUBLE)pThisExtObj->dwCollectTimeout)
{
dwStatus = ERROR_TIMEOUT;
}
}
// Copy the data
if (dwStatus == ERROR_SUCCESS)
{
// External object data
GetSystemTimeAsFileTime((FILETIME*)&pThisExtObj->llLastUsedTime);
pThisExtObj->dwNumObjectsRet = NumObjectTypes;
pThisExtObj->dwRetBufSize = SafeBufferBlock.dwCallBufSize;
// increment perf counters
InterlockedIncrement ((LONG *)&pThisExtObj->dwCollectCount);
}
// Validate the data
if ((dwStatus == ERROR_SUCCESS) &&
(g_LTData.bTestContents))
{
dwStatus = Validate( &SafeBufferBlock, pThisExtObj );
}
}
ClearSafeBuffer(&SafeBufferBlock);
if ((dwStatus != ERROR_SUCCESS) &&
(dwStatus != WAIT_TIMEOUT)) // don't count timeouts as function errors
{
InterlockedIncrement ((LONG *)&pThisExtObj->dwErrorCount);
}
return dwStatus;
}
DWORD
CloseLibrary (
EXT_OBJECT *pInfo
)
{
DWORD dwStatus = ERROR_SUCCESS;
if (pInfo != NULL) {
// if there's a close proc to call, then
// call close procedure to close anything that may have
// been allocated by the library
if ((pInfo->hMutex != NULL) &&
(pInfo->CloseProc != NULL)){
dwStatus = WaitForSingleObject (
pInfo->hMutex,
pInfo->dwOpenTimeout);
if (dwStatus != WAIT_TIMEOUT) {
if (pInfo->CloseProc != NULL) {
dwStatus = (*pInfo->CloseProc) ();
if ( dwStatus != ERROR_SUCCESS )
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \t%S failed for the \"%s\" Performance Library: 0x%X", GetCurrentThreadId(), pInfo->szCloseProcName, pInfo->szServiceName, dwStatus);
}
}
ReleaseMutex(pInfo->hMutex);
} else {
pInfo->dwLockoutCount++;
}
} else {
dwStatus = ERROR_LOCK_FAILED;
}
if (pInfo->hLibrary != NULL) {
FreeLibrary (pInfo->hLibrary);
pInfo->hLibrary = NULL;
}
}
return dwStatus;
}
static
LPWSTR
*BuildNameTable(
LPCWSTR szMachineName,
LPCWSTR lpszLangIdArg, // unicode value of Language subkey
PDWORD pdwLastItem, // size of array in elements
PDWORD pdwIdArray // array for index ID's
)
/*++
BuildNameTable
Arguments:
hKeyRegistry
Handle to an open registry (this can be local or remote.) and
is the value returned by RegConnectRegistry or a default key.
lpszLangId
The unicode id of the language to look up. (default is 409)
Return Value:
pointer to an allocated table. (the caller must MemoryFree it when finished!)
the table is an array of pointers to zero terminated strings. NULL is
returned if an error occured.
--*/
{
HKEY hKeyRegistry; // handle to registry db with counter names
LPWSTR *lpReturnValue;
LPCWSTR lpszLangId;
LPWSTR *lpCounterId;
LPWSTR lpCounterNames;
LPWSTR lpHelpText;
LPWSTR lpThisName;
LONG lWin32Status;
DWORD dwValueType;
DWORD dwArraySize;
DWORD dwBufferSize;
DWORD dwCounterSize;
DWORD dwHelpSize;
DWORD dwThisCounter;
DWORD dwLastId;
DWORD dwLastHelpId;
DWORD dwLastCounterIdUsed;
DWORD dwLastHelpIdUsed;
HKEY hKeyValue;
HKEY hKeyNames;
LPWSTR lpValueNameString;
WCHAR CounterNameBuffer [50];
WCHAR HelpNameBuffer [50];
SetLastError (ERROR_SUCCESS);
szTestErrorMessage = NULL;
if (szMachineName != NULL) {
lWin32Status = RegConnectRegistryW (szMachineName,
HKEY_LOCAL_MACHINE,
&hKeyRegistry);
} else {
lWin32Status = ERROR_SUCCESS;
hKeyRegistry = HKEY_LOCAL_MACHINE;
}
lpValueNameString = NULL; //initialize to NULL
lpReturnValue = NULL;
hKeyValue = NULL;
hKeyNames = NULL;
// check for null arguments and insert defaults if necessary
if (!lpszLangIdArg) {
lpszLangId = cszDefaultLangId;
} else {
lpszLangId = lpszLangIdArg;
}
// open registry to get number of items for computing array size
lWin32Status = RegOpenKeyExW (
hKeyRegistry,
cszNamesKey,
0L,
KEY_READ,
&hKeyValue);
if (lWin32Status != ERROR_SUCCESS) {
szTestErrorMessage = (LPWSTR)L"Unable to Open Perflib key";
goto BNT_BAILOUT;
}
// get config info
dwValueType = 0;
dwBufferSize = sizeof (pdwIdArray[4]);
lWin32Status = RegQueryValueExW (
hKeyValue,
(LPCWSTR)L"Disable Performance Counters",
0L,
&dwValueType,
(LPBYTE)&pdwIdArray[4],
&dwBufferSize);
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
if (lWin32Status == ERROR_FILE_NOT_FOUND) {
// this is OK since the value need not be present
pdwIdArray[4] = (DWORD)-1;
lWin32Status = ERROR_SUCCESS;
} else {
szTestErrorMessage = (LPWSTR)L"Unable to read Disable Performance Counters value";
goto BNT_BAILOUT;
}
}
dwValueType = 0;
dwBufferSize = sizeof (pdwIdArray[5]);
lWin32Status = RegQueryValueExW (
hKeyValue,
(LPCWSTR)L"ExtCounterTestLevel",
0L,
&dwValueType,
(LPBYTE)&pdwIdArray[5],
&dwBufferSize);
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
if (lWin32Status == ERROR_FILE_NOT_FOUND) {
// this is OK since the value need not be present
pdwIdArray[5] = (DWORD)-1;
lWin32Status = ERROR_SUCCESS;
} else {
szTestErrorMessage = (LPWSTR)L"Unable to read ExCounterTestLevel value";
goto BNT_BAILOUT;
}
}
dwValueType = 0;
dwBufferSize = sizeof (pdwIdArray[6]);
lWin32Status = RegQueryValueExW (
hKeyValue,
(LPCWSTR)L"Base Index",
0L,
&dwValueType,
(LPBYTE)&pdwIdArray[6],
&dwBufferSize);
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
szTestErrorMessage = (LPWSTR)L"Unable to read Base Index value";
goto BNT_BAILOUT;
}
// get number of items
dwBufferSize = sizeof (dwLastHelpId);
lWin32Status = RegQueryValueExW (
hKeyValue,
cszLastHelp,
0L,
&dwValueType,
(LPBYTE)&dwLastHelpId,
&dwBufferSize);
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
szTestErrorMessage = (LPWSTR)L"Unable to read Last Help value";
goto BNT_BAILOUT;
}
pdwIdArray[2] = dwLastHelpId;
// get number of items
dwBufferSize = sizeof (dwLastId);
lWin32Status = RegQueryValueExW (
hKeyValue,
cszLastCounter,
0L,
&dwValueType,
(LPBYTE)&dwLastId,
&dwBufferSize);
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
szTestErrorMessage = (LPWSTR)L"Unable to read Last Counter value";
goto BNT_BAILOUT;
}
pdwIdArray[0] = dwLastId;
if (dwLastId < dwLastHelpId)
dwLastId = dwLastHelpId;
dwArraySize = dwLastId * sizeof(LPWSTR);
// get Perflib system version
if (szMachineName[0] == 0) {
hKeyNames = HKEY_PERFORMANCE_DATA;
} else {
lWin32Status = RegConnectRegistryW (szMachineName,
HKEY_PERFORMANCE_DATA,
&hKeyNames);
}
lstrcpyW (CounterNameBuffer, cszCounterName);
lstrcatW (CounterNameBuffer, lpszLangId);
lstrcpyW (HelpNameBuffer, cszHelpName);
lstrcatW (HelpNameBuffer, lpszLangId);
// get size of counter names and add that to the arrays
dwBufferSize = 0;
lWin32Status = RegQueryValueExW (
hKeyNames,
CounterNameBuffer,
0L,
&dwValueType,
NULL,
&dwBufferSize);
if (lWin32Status != ERROR_SUCCESS) {
szTestErrorMessage = (LPWSTR)L"Unable to query counter string size";
goto BNT_BAILOUT;
}
dwCounterSize = dwBufferSize;
// get size of counter names and add that to the arrays
if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwBufferSize = 0;
lWin32Status = RegQueryValueExW (
hKeyNames,
HelpNameBuffer,
0L,
&dwValueType,
NULL,
&dwBufferSize);
if (lWin32Status != ERROR_SUCCESS) {
szTestErrorMessage = (LPWSTR)L"Unable to query help string size";
goto BNT_BAILOUT;
}
dwHelpSize = dwBufferSize;
lpReturnValue = (LPWSTR *)HeapAlloc (g_hTestHeap, 0,dwArraySize + dwCounterSize + dwHelpSize);
if (!lpReturnValue) {
lWin32Status = ERROR_OUTOFMEMORY;
szTestErrorMessage = (LPWSTR)L"Unable to allocate name string buffer";
goto BNT_BAILOUT;
}
// initialize pointers into buffer
lpCounterId = lpReturnValue;
lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize);
lpHelpText = (LPWSTR)((LPBYTE)lpCounterNames + dwCounterSize);
// read counters into memory
dwBufferSize = dwCounterSize;
lWin32Status = RegQueryValueExW (
hKeyNames,
CounterNameBuffer,
0L,
&dwValueType,
(LPBYTE)lpCounterNames,
&dwBufferSize);
if (lWin32Status != ERROR_SUCCESS) {
szTestErrorMessage = (LPWSTR)L"Unable to query counter string contents";
goto BNT_BAILOUT;
}
dwBufferSize = dwHelpSize;
lWin32Status = RegQueryValueExW (
hKeyNames,
HelpNameBuffer,
0L,
&dwValueType,
(LPBYTE)lpHelpText,
&dwBufferSize);
if (lWin32Status != ERROR_SUCCESS) {
szTestErrorMessage = (LPWSTR)L"Unable to query help string contents";
goto BNT_BAILOUT;
}
dwLastCounterIdUsed = 0;
dwLastHelpIdUsed = 0;
// load counter array items
for (lpThisName = lpCounterNames;
*lpThisName;
lpThisName += (lstrlenW(lpThisName)+1) ) {
// first string should be an integer (in decimal unicode digits)
dwThisCounter = wcstoul (lpThisName, NULL, 10);
if (dwThisCounter == 0) {
lWin32Status = ERROR_BADKEY;
szTestErrorMessage = (LPWSTR)L"Bad counter string entry, CONFIG_String_LastCounter is last valid counter string index";
goto BNT_BAILOUT; // bad entry
}
// point to corresponding counter name
lpThisName += (lstrlenW(lpThisName)+1);
// and load array element;
lpCounterId[dwThisCounter] = lpThisName;
if (dwThisCounter > dwLastCounterIdUsed) dwLastCounterIdUsed = dwThisCounter;
}
pdwIdArray[1] = dwLastCounterIdUsed;
for (lpThisName = lpHelpText;
*lpThisName;
lpThisName += (lstrlenW(lpThisName)+1) ) {
// first string should be an integer (in decimal unicode digits)
dwThisCounter = wcstoul (lpThisName, NULL, 10);
if (dwThisCounter == 0) {
lWin32Status = ERROR_BADKEY;
szTestErrorMessage = (LPWSTR)L"Bad help string entry, CONFIG_String_LastHelp is last valid counter string index";
goto BNT_BAILOUT; // bad entry
}
// point to corresponding counter name
lpThisName += (lstrlenW(lpThisName)+1);
// and load array element;
lpCounterId[dwThisCounter] = lpThisName;
if (dwThisCounter > dwLastHelpIdUsed) dwLastHelpIdUsed= dwThisCounter;
}
pdwIdArray[3] = dwLastHelpIdUsed;
dwLastId = dwLastHelpIdUsed;
if (dwLastId < dwLastCounterIdUsed) dwLastId = dwLastCounterIdUsed;
if (pdwLastItem) *pdwLastItem = dwLastId;
HeapFree (g_hTestHeap, 0, (LPVOID)lpValueNameString);
RegCloseKey (hKeyValue);
RegCloseKey (hKeyNames);
RegCloseKey(hKeyRegistry);
return lpReturnValue;
BNT_BAILOUT:
if (lWin32Status != ERROR_SUCCESS) {
SetLastError (lWin32Status);
}
if (lpValueNameString) {
HeapFree (g_hTestHeap, 0, (LPVOID)lpValueNameString);
}
if (lpReturnValue) {
HeapFree (g_hTestHeap, 0, (LPVOID)lpValueNameString);
}
if (hKeyValue)
RegCloseKey (hKeyValue);
if (hKeyNames)
RegCloseKey (hKeyNames);
if (hKeyRegistry)
RegCloseKey(hKeyRegistry);
return NULL;
}
DWORD
CycleTest (
DWORD dwThreadId,
PEXT_OBJECT pObj
)
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwLoopCount = g_LTData.dwLoopCount;
BOOL bPrintData = g_LTData.bDisplay;
DOUBLE dMs;
UNREFERENCED_PARAMETER (dwThreadId);
// Open the Library
// ================
dwStatus = OpenLibrary (pObj);
if ((dwStatus == ERROR_SUCCESS) &&
(pObj != NULL)) {
// an object info block was returned
dMs = (DOUBLE)pObj->llOpenTime; // ticks used
dMs /= (DOUBLE)pObj->llTimeBase; // ticks/sec
dMs *= 1000.0; // ms/Sec
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_OpenServiceName: \t%s", GetCurrentThreadId(), pObj->szServiceName);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_OpenProcTime: \t%12.5f mSec", GetCurrentThreadId(), dMs);
// fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_OpenProcTimeout: \t%6d.00000 mSec", GetCurrentThreadId(), pObj->dwOpenTimeout);
// check for timeout
if (dMs > (DOUBLE)pObj->dwOpenTimeout) {
dwStatus = ERROR_TIMEOUT;
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tOpen procedure exceeded timeout", GetCurrentThreadId());
CloseLibrary (pObj);
}
} else {
// no object block returned
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tUnable to open the \"%s\" Performance Library", GetCurrentThreadId(), pObj->szServiceName);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORCODE:\t0x%8.8x (%dL)", GetCurrentThreadId(), dwStatus, dwStatus);
}
// Collect Data for "dwLoopCount" times
// ====================================
if (dwStatus == ERROR_SUCCESS)
{
HeapValidate (g_hTestHeap, 0, NULL);
// call collect function
do
{
// get the data again
dwStatus = CollectData (pObj);
HeapValidate (g_hTestHeap, 0, NULL);
} while (--dwLoopCount > 0);
// Close Library
// =============
// Even if we get an error, we should try to close the library
// ===========================================================
CloseLibrary (pObj);
// Report Status
// =============
if (dwStatus == ERROR_SUCCESS) {
// dump collect fn stats.
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_ServiceName: \t%s", GetCurrentThreadId(), pObj->szServiceName);
if ((pObj->dwCollectCount > 0) && (pObj->dwNumObjectsRet > 0)){
// don't compute time if no objects were returned
dMs = (DOUBLE)pObj->llCollectTime;
dMs /= (DOUBLE)pObj->llTimeBase;
dMs *= 1000.0;
dMs /= (DOUBLE)pObj->dwCollectCount;
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_AvgCollectProcTime: \t%12.5f mSec", GetCurrentThreadId(), dMs);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_CollectProcTimeout: \t%6d.00000 mSec", GetCurrentThreadId(), pObj->dwCollectTimeout);
}
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_ObjectsRet: \t%d", GetCurrentThreadId(), pObj->dwNumObjectsRet);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:INFO_RetBuffSize: \t%d", GetCurrentThreadId(), pObj->dwRetBufSize);
} else {
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERROR: \tCollect procedure returned an error", GetCurrentThreadId());
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORCODE:\t0x%8.8x (%dL)", GetCurrentThreadId(), dwStatus, dwStatus);
// output the contents of the info buffer
if (dwStatus == ERROR_TIMEOUT) {
// dump collect fn stats.
dMs = (DOUBLE)pObj->llFunctionTime;
dMs /= (DOUBLE)pObj->llTimeBase;
dMs *= 1000.0;
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectService: \t%s", GetCurrentThreadId(), pObj->szServiceName);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectProcTime:\t%12.5f mSec", GetCurrentThreadId(), dMs);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectTimeout: \t%6d.00000 mSec", GetCurrentThreadId(), pObj->dwCollectTimeout);
}
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectService: \t%s", GetCurrentThreadId(), pObj->szServiceName);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectTime: \t%I64u", GetCurrentThreadId(), pObj->llCollectTime);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CollectCount:\t%d", GetCurrentThreadId(), pObj->dwCollectCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_OpenCount: \t%d", GetCurrentThreadId(), pObj->dwOpenCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_CloseCount: \t%d", GetCurrentThreadId(), pObj->dwCloseCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_LockoutCount:\t%d", GetCurrentThreadId(), pObj->dwLockoutCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_ErrorCount: \t%d", GetCurrentThreadId(), pObj->dwErrorCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_Exceptions: \t%d", GetCurrentThreadId(), pObj->dwExceptionCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_LowerGPErrs: \t%d", GetCurrentThreadId(), pObj->dwLowerGPViolations);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_UpperGPErrs: \t%d", GetCurrentThreadId(), pObj->dwUpperGPViolations);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_BadPointers: \t%d", GetCurrentThreadId(), pObj->dwBadPointers);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_BufSizeErrs: \t%d", GetCurrentThreadId(), pObj->dwBufferSizeErrors);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_AlignErrors: \t%d", GetCurrentThreadId(), pObj->dwAlignmentErrors);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_ObjSizeErrs: \t%d", GetCurrentThreadId(), pObj->dwObjectSizeErrors);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_InstSizeErrs:\t%d", GetCurrentThreadId(), pObj->dwInstanceSizeErrors);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_TimeBase: \t%I64u", GetCurrentThreadId(), pObj->llTimeBase);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_FunctionTime:\t%I64u", GetCurrentThreadId(), pObj->llFunctionTime);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_ObjectsRet: \t%d", GetCurrentThreadId(), pObj->dwNumObjectsRet);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ERRORINFO_RetBuffSize: \t%d", GetCurrentThreadId(), pObj->dwRetBufSize);
}
}
HeapValidate (g_hTestHeap, 0, NULL);
return dwStatus;
}
unsigned __stdcall CycleThreadProc( void * lpThreadArg )
{
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwCycleCount = g_LTData.dwCycleCount;
DWORD dwThreadNum = *((DWORD*)lpThreadArg);
PEXT_OBJECT pObj = NULL;
EXT_OBJECT ThreadObj;
DWORD dwThisThread = GetCurrentThreadId();
HeapValidate (g_hTestHeap, 0, NULL);
srand( GetTickCount() );
do {
// If the rand flag is set, randomly choose an object to hit
if (g_fRand)
{
pObj = &g_pExtObjects[rand()%g_LTData.dwNumObjects];
}
else
{
pObj = &g_pExtObjects[dwThreadNum];
}
if ( pObj->bValid )
{
memcpy(&ThreadObj, pObj, sizeof(EXT_OBJECT));
dwStatus = CycleTest(dwThisThread, &ThreadObj);
// What error handling mode are we using?
if (g_LTData.bStopOnError)
{
if (( ERROR_SUCCESS != dwStatus ) &&
(ERROR_INVALID_DATA != dwStatus))
{
SetEvent( g_hEvent );
}
else
{
if ( WAIT_OBJECT_0 == WaitForSingleObject( g_hEvent, 0 ) )
break;
dwStatus = ERROR_SUCCESS;
}
}
}
} while (--dwCycleCount > 0);
HeapValidate (g_hTestHeap, 0, NULL);
return dwStatus;
}
DWORD Initialize( WCHAR* szIniFileName, DWORD* pdwThreadCount )
{
DWORD dwStatus = ERROR_SUCCESS;
BOOL bStatus = FALSE;
WCHAR wcsReturnBuff[256];
WCHAR wcsKeyName[256];
DWORD dwCtr = 0;
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_INI_File_Name:\t%s", szIniFileName);
fwprintf (g_pOutput, (LPCWSTR)L"\n");
// LTData
GetPrivateProfileStringW( L"Main", L"NumObjects", L"0", wcsReturnBuff, 256, szIniFileName );
g_LTData.dwNumObjects = wcstoul(wcsReturnBuff, NULL, 10);
GetPrivateProfileStringW( L"Main", L"CycleCount", L"0", wcsReturnBuff, 256, szIniFileName );
g_LTData.dwCycleCount = wcstoul(wcsReturnBuff, NULL, 10);
GetPrivateProfileStringW( L"Main", L"LoopCount", L"0", wcsReturnBuff, 256, szIniFileName );
g_LTData.dwLoopCount = wcstoul(wcsReturnBuff, NULL, 10);
GetPrivateProfileStringW( L"Main", L"StopOnError", L"0", wcsReturnBuff, 256, szIniFileName );
g_LTData.bStopOnError = wcstoul(wcsReturnBuff, NULL, 10);
g_LTData.bDisplay = TRUE;
g_LTData.bTestContents = TRUE;
// Other
GetPrivateProfileStringW( L"Main", L"NumThreads", L"0", wcsReturnBuff, 256, szIniFileName );
*pdwThreadCount = wcstoul(wcsReturnBuff, NULL, 10);
if ( *pdwThreadCount < g_LTData.dwNumObjects )
{
*pdwThreadCount = g_LTData.dwNumObjects;
}
GetPrivateProfileStringW( L"Main", L"Random", L"0", wcsReturnBuff, 256, szIniFileName );
g_fRand = wcstoul(wcsReturnBuff, NULL, 10);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Number_Of_Perf_Objects: \t%d", g_LTData.dwNumObjects);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Number_Of_Test_Cycles: \t%d", g_LTData.dwCycleCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Number_Of_Collects_Per_Cycle:\t%d", g_LTData.dwLoopCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Display_Results: \t%s", (g_LTData.bDisplay?L"Yes":L"No"));
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Validate_Data: \t%s", (g_LTData.bTestContents?L"Yes":L"No"));
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Number_Of_Threads: \t%d", *pdwThreadCount);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Randomize_Perf_Objects: \t%s", (g_fRand?L"Yes":L"No"));
fwprintf (g_pOutput, (LPCWSTR)L"\n");
g_pExtObjects = (EXT_OBJECT*) HeapAlloc(g_hTestHeap,
HEAP_ZERO_MEMORY,
g_LTData.dwNumObjects * sizeof(EXT_OBJECT));
if ( NULL != g_pExtObjects )
{
for( dwCtr = 0; dwCtr < g_LTData.dwNumObjects; dwCtr++ )
{
// Service name
swprintf( wcsKeyName, L"Object%d", dwCtr );
GetPrivateProfileStringW( L"Main", wcsKeyName, L"PerfProc", wcsReturnBuff, 256, szIniFileName );
g_pExtObjects[dwCtr].szServiceName = (WCHAR*) HeapAlloc( g_hTestHeap, 0,
( wcslen( wcsReturnBuff ) + 1 ) * sizeof(WCHAR) );
wcscpy( g_pExtObjects[dwCtr].szServiceName, wcsReturnBuff );
// Query string
swprintf( wcsKeyName, L"Counter%d", dwCtr );
GetPrivateProfileStringW( L"Main", wcsKeyName, L"Global", wcsReturnBuff, 256, szIniFileName );
g_pExtObjects[dwCtr].szQueryString = (WCHAR*) HeapAlloc( g_hTestHeap, 0,
( wcslen( wcsReturnBuff ) + 1 ) * sizeof(WCHAR) );
wcscpy( g_pExtObjects[dwCtr].szQueryString, wcsReturnBuff );
// At least one object has to succeed
bStatus = ( ( ERROR_SUCCESS == InitializeExtObj( &g_pExtObjects[dwCtr] )) || bStatus);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Perf_Object: \t%s : %s",g_pExtObjects[dwCtr].szServiceName, (g_pExtObjects[dwCtr].bValid?L"Active":L"Inactive"));
}
}
fwprintf (g_pOutput, (LPCWSTR)L"\n");
if (!bStatus)
{
dwStatus = ERROR_INVALID_DATA;
}
return dwStatus;
}
int
WriteTestResultHeader()
{
OSVERSIONINFOW osInfo;
WCHAR szMachineName[MAX_PATH];
DWORD dwSize;
SYSTEMTIME stStart;
memset (&osInfo, 0, sizeof(osInfo));
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
memset (szMachineName, 0, sizeof(szMachineName));
memset (&stStart, 0, sizeof(stStart));
GetVersionExW (&osInfo);
dwSize = sizeof(szMachineName) / sizeof (szMachineName[0]);
GetComputerNameW (&szMachineName[0], &dwSize);
GetLocalTime (&stStart);
fwprintf (g_pOutput, (LPCWSTR)L"\n[TESTRESULT]");
fwprintf (g_pOutput, (LPCWSTR)L"\n\tTEST: \tPerf Counter DLL Validation");
fwprintf (g_pOutput, (LPCWSTR)L"\n\tBUILD: \t%d", osInfo.dwBuildNumber);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tMACHINE:\t%s", szMachineName);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t%d:START TIME:\t%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d",
GetCurrentThreadId(),
stStart.wMonth, stStart.wDay, stStart.wYear % 100,
stStart.wHour, stStart.wMinute, stStart.wSecond );
return 0;
}
int
WriteTestConfigData(
LPDWORD pdwIdInfo
)
{
fwprintf (g_pOutput, (LPCWSTR)L"\n\t");
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Perflib_LastCounter:\t%d", pdwIdInfo[0]);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_String_LastCounter: \t%d", pdwIdInfo[1]);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Perflib_LastHelp: \t%d", pdwIdInfo[2]);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_String_LastHelp: \t%d", pdwIdInfo[3]);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_Disabled: \t%d", pdwIdInfo[4]);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_ExtCounterTestLevel:\t%d", pdwIdInfo[5]);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_BaseIndex: \t%d", pdwIdInfo[6]);
// fwprintf (g_pOutput, (LPCWSTR)L"\n\tCONFIG_BaseOsObject : \t%d", pdwIdInfo[7]);
return 0;
}
DWORD
WriteGroupConfig(
HKEY hKeyPerfSubKey,
DWORD *pIds
)
{
DWORD nRetStatus = (int)ERROR_SUCCESS;
DWORD lStatus;
DWORD dwData;
DWORD dwBufferSize;
DWORD dwValueType;
WCHAR szStringBuffer[MAX_PATH*2];
dwBufferSize = sizeof(szStringBuffer);
dwValueType = 0;
memset (szStringBuffer, 0, sizeof(szStringBuffer));
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Library",
0L,
&dwValueType,
(LPBYTE)&szStringBuffer[0],
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:ONFIG_Library:\t%s",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
if (lStatus != ERROR_SUCCESS) nRetStatus = lStatus;
dwBufferSize = sizeof(szStringBuffer);
dwValueType = 0;
memset (szStringBuffer, 0, sizeof(szStringBuffer));
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Open",
0L,
&dwValueType,
(LPBYTE)&szStringBuffer[0],
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Open:\t%s",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
if (lStatus != ERROR_SUCCESS) nRetStatus = lStatus;
dwBufferSize = sizeof(szStringBuffer);
dwValueType = 0;
memset (szStringBuffer, 0, sizeof(szStringBuffer));
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Collect",
0L,
&dwValueType,
(LPBYTE)&szStringBuffer[0],
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Collect:\t%s",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
if (lStatus != ERROR_SUCCESS) nRetStatus = lStatus;
dwBufferSize = sizeof(szStringBuffer);
dwValueType = 0;
memset (szStringBuffer, 0, sizeof(szStringBuffer));
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Object List",
0L,
&dwValueType,
(LPBYTE)&szStringBuffer[0],
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Object List:\t%s",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
dwBufferSize = sizeof(szStringBuffer);
dwValueType = 0;
memset (szStringBuffer, 0, sizeof(szStringBuffer));
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Close",
0L,
&dwValueType,
(LPBYTE)&szStringBuffer[0],
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Close:\t%s",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? szStringBuffer : cszNotFound));
if (lStatus != ERROR_SUCCESS) nRetStatus = lStatus;
dwBufferSize = sizeof(dwData);
dwValueType = 0;
dwData = 0;
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"First Counter",
0L,
&dwValueType,
(LPBYTE)&dwData,
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_First Counter:\t%d",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? dwData : (DWORD)-1));
if (lStatus != ERROR_SUCCESS) {
if (lStatus == ERROR_FILE_NOT_FOUND) {
if (!pIds[4]) {
// then this hasn't been installed yet
nRetStatus = ERROR_SERVICE_DISABLED;
} else {
// then this is a base OS service
nRetStatus = ERROR_SUCCESS;
}
} else {
// some other error so return
nRetStatus = lStatus;
}
pIds[0] = (DWORD)-1;
} else {
pIds[0] = dwData;
}
dwBufferSize = sizeof(dwData);
dwValueType = 0;
dwData = 0;
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Last Counter",
0L,
&dwValueType,
(LPBYTE)&dwData,
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Last Counter:\t%d",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? dwData : (DWORD)-1));
if (lStatus != ERROR_SUCCESS) {
if (lStatus == ERROR_FILE_NOT_FOUND) {
if (!pIds[4]) {
// then this hasn't been installed yet
nRetStatus = ERROR_SERVICE_DISABLED;
} else {
// then this is a base OS service
nRetStatus = ERROR_SUCCESS;
}
} else {
// some other error so return
nRetStatus = lStatus;
}
pIds[1] = (DWORD)-1;
} else {
pIds[1] = dwData;
}
dwBufferSize = sizeof(dwData);
dwValueType = 0;
dwData = 0;
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"First Help",
0L,
&dwValueType,
(LPBYTE)&dwData,
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_First Help:\t%d",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? dwData : (DWORD)-1));
if (lStatus != ERROR_SUCCESS) {
if (lStatus == ERROR_FILE_NOT_FOUND) {
if (!pIds[4]) {
// then this hasn't been installed yet
nRetStatus = ERROR_SERVICE_DISABLED;
} else {
// then this is a base OS service
nRetStatus = ERROR_SUCCESS;
}
} else {
// some other error so return
nRetStatus = lStatus;
}
pIds[2] = (DWORD)-1;
} else {
pIds[2] = dwData;
}
dwBufferSize = sizeof(dwData);
dwValueType = 0;
dwData = 0;
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Last Help",
0L,
&dwValueType,
(LPBYTE)&dwData,
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Last Help:\t%d",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? dwData : (DWORD)-1));
if (lStatus != ERROR_SUCCESS) {
if (lStatus == ERROR_FILE_NOT_FOUND) {
if (!pIds[4]) {
// then this hasn't been installed yet
nRetStatus = ERROR_SERVICE_DISABLED;
} else {
// then this is a base OS service
nRetStatus = ERROR_SUCCESS;
}
} else {
// some other error so return
nRetStatus = lStatus;
}
pIds[3] = (DWORD)-1;
} else {
pIds[3] = dwData;
}
dwBufferSize = sizeof(dwData);
dwValueType = 0;
dwData = 0;
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Open Timeout",
0L,
&dwValueType,
(LPBYTE)&dwData,
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Open Timeout:\t%d",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? dwData : (DWORD)10000));
dwBufferSize = sizeof(dwData);
dwValueType = 0;
dwData = 0;
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Collect Timeout",
0L,
&dwValueType,
(LPBYTE)&dwData,
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Collect Timeout:\t%d",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? dwData : (DWORD)10000));
dwBufferSize = sizeof(dwData);
dwValueType = 0;
dwData = 0;
lStatus = RegQueryValueExW (
hKeyPerfSubKey,
(LPCWSTR)L"Disable Performance Counters",
0L,
&dwValueType,
(LPBYTE)&dwData,
&dwBufferSize);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\t%d:CONFIG_Disable Performance Counters:\t%d",
GetCurrentThreadId(),
(lStatus == ERROR_SUCCESS ? dwData : (DWORD)0));
if ((lStatus == ERROR_SUCCESS) && (dwData != 0)){
nRetStatus = ERROR_SERVICE_DISABLED;
}
return nRetStatus;
}
int
WriteTestResultTrailer(
DWORD dwTestResult
)
{
SYSTEMTIME stEnd;
LPWSTR szResult;
memset (&stEnd, 0, sizeof(stEnd));
GetLocalTime (&stEnd);
switch (dwTestResult) {
case PERFVAL_PASS:
szResult = (LPWSTR)L"PASS"; break;
case PERFVAL_FAIL:
szResult = (LPWSTR)L"FAIL"; break;
case PERFVAL_TIMEOUT:
szResult = (LPWSTR)L"TIMEOUT"; break;
case PERFVAL_NOCONFIG:
default:
szResult = (LPWSTR)L"NOCONFIG"; break;
}
fwprintf (g_pOutput, (LPCWSTR)L"\n\n\tRESULT: \t%s", szResult);
fwprintf (g_pOutput, (LPCWSTR)L"\n\tEND TIME:\t%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d",
stEnd.wMonth, stEnd.wDay, stEnd.wYear % 100,
stEnd.wHour, stEnd.wMinute, stEnd.wSecond);
fwprintf (g_pOutput, (LPCWSTR)L"\n[/TESTRESULT]");
fwprintf (g_pOutput, (LPCWSTR)L"\n");
return 0;
}
int
WriteGroupHeader(
LPCWSTR szGroupName
)
{
SYSTEMTIME stStart;
memset (&stStart, 0, sizeof(stStart));
GetLocalTime (&stStart);
fwprintf (g_pOutput, (LPCWSTR)L"\n\n\t[GROUP: %s]", szGroupName);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\tSTART TIME:\t%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d.%3.3d",
stStart.wMonth, stStart.wDay, stStart.wYear % 100,
stStart.wHour, stStart.wMinute, stStart.wSecond, stStart.wMilliseconds );
return 0;
}
int
WriteGroupTrailer(
DWORD dwTestResult
)
{
LPWSTR szResult;
SYSTEMTIME stEnd;
memset (&stEnd, 0, sizeof(stEnd));
GetLocalTime (&stEnd);
switch (dwTestResult) {
case PERFVAL_PASS:
szResult = (LPWSTR)L"PASS"; break;
case PERFVAL_FAIL:
szResult = (LPWSTR)L"FAIL"; break;
case PERFVAL_TIMEOUT:
szResult = (LPWSTR)L"TIMEOUT"; break;
case PERFVAL_NOCONFIG:
default:
szResult = (LPWSTR)L"NOCONFIG"; break;
}
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\tEND TIME:\t%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d.%3.3d",
stEnd.wMonth, stEnd.wDay, stEnd.wYear % 100,
stEnd.wHour, stEnd.wMinute, stEnd.wSecond, stEnd.wMilliseconds );
fwprintf (g_pOutput, (LPCWSTR)L"\n\t\tRESULT: %s", szResult);
fwprintf (g_pOutput, (LPCWSTR)L"\n\t[/GROUP]");
return 0;
}
int
WriteTestError (
DWORD dwTabLevel,
DWORD dwStatus
)
{
DWORD dwIndent;
fwprintf (g_pOutput, (LPCWSTR)L"\n");
for (dwIndent = 0; dwIndent < dwTabLevel; dwIndent++) {
fwprintf (g_pOutput, (LPCWSTR)L"\t");
}
fwprintf (g_pOutput, (LPCWSTR)L"%d:ERROR: \t%s", GetCurrentThreadId(), (szTestErrorMessage != NULL ? szTestErrorMessage : (LPCWSTR)L"No Error"));
fwprintf (g_pOutput, (LPCWSTR)L"\n");
for (dwIndent = 0; dwIndent < dwTabLevel; dwIndent++) {
fwprintf (g_pOutput, (LPCWSTR)L"\t");
}
fwprintf (g_pOutput, (LPCWSTR)L"%d:ERRORCODE:\t0x%8.8x (%d)", GetCurrentThreadId(), dwStatus, dwStatus);
return 0;
}
int
__cdecl
wmain(
int argc,
WCHAR *argv[]
)
{
DWORD dwStatus;
DWORD dwLastElement = 0;
DWORD dwIdArray[8];
DWORD dwTID = 0;
DWORD dwObj;
DWORD dwTestResult = PERFVAL_NOCONFIG;
DWORD dwThreadCount = 0;
LOCAL_THREAD_DATA* pCurLTData = NULL;
HANDLE hThreads[MAXIMUM_WAIT_OBJECTS];
DWORD dwThisThread;
WCHAR* pwcsINIFile = L".\\ctrtest.ini";
BOOL fRand = FALSE;
int nIndex = 0;
// Set up environment
g_hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if ( NULL == g_hEvent )
return ERROR_INVALID_ACCESS;
g_pOutput = stdout;
g_hTestHeap = HeapCreate (HEAP_GENERATE_EXCEPTIONS, 0x10000, 0);
if (g_hTestHeap == NULL)
return (ERROR_OUTOFMEMORY);
WriteTestResultHeader(g_pOutput);
memset (&dwIdArray[0], 0, sizeof(dwIdArray));
g_pNameTable = BuildNameTable (
(LPCWSTR)L"",
(LPCWSTR)L"009",
&dwLastElement, // size of array in elements
&dwIdArray[0]);
g_dwLastIndex = dwLastElement;
WriteTestConfigData(&dwIdArray[0]);
if (g_pNameTable == NULL) {
// check for name table errors
dwStatus = GetLastError(); // so we don't continue
dwTestResult = PERFVAL_FAIL;
WriteTestError (1, dwStatus);
}
else
{
if ( argc > 1 )
{
pwcsINIFile = argv[1];
}
// Load up object/ctr data
dwStatus = Initialize( pwcsINIFile, &dwThreadCount );
if ( ERROR_SUCCESS == dwStatus )
{
srand( GetTickCount() );
// create threads
for (dwThisThread = 0; dwThisThread < dwThreadCount; dwThisThread++)
{
hThreads[dwThisThread] = (HANDLE) _beginthreadex( NULL, 0,
CycleThreadProc, (void*) &dwThisThread, 0, &dwTID );
}
// Let these all run through
dwStatus = WaitForMultipleObjects (dwThreadCount, hThreads, TRUE, INFINITE);
if (dwStatus != WAIT_TIMEOUT)
dwStatus = ERROR_SUCCESS;
for (dwThisThread = 0; dwThisThread < dwThreadCount; dwThisThread++) {
CloseHandle (hThreads[dwThisThread]);
}
}
}
WriteTestResultTrailer(dwTestResult);
for (dwObj = 0; dwObj < g_LTData.dwNumObjects; dwObj++)
{
FinializeExtObj(&g_pExtObjects[dwObj]);
}
if ( NULL != g_pNameTable )
HeapFree(g_hTestHeap, 0, g_pNameTable);
if ( NULL != g_pExtObjects )
HeapFree(g_hTestHeap, 0, g_pExtObjects);
if ( NULL != g_hTestHeap )
HeapDestroy (g_hTestHeap);
CloseHandle( g_hEvent );
return (int)dwStatus;
}