2627 lines
80 KiB
C
2627 lines
80 KiB
C
/*++
|
||
|
||
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;
|
||
}
|