621 lines
18 KiB
C
621 lines
18 KiB
C
//
|
||
// Foreign computer support needs more work (a-robw)
|
||
//
|
||
#ifdef FOREIGN_COMPUTER_SUPPORT
|
||
#undef FOREIGN_COMPUTER_SUPPORT
|
||
#endif
|
||
|
||
#include "perfmon.h"
|
||
#include "system.h" // external declarations for this file
|
||
|
||
#include "perfdata.h"
|
||
#include "perfmops.h"
|
||
#include "playback.h" // for PlayingBackLog
|
||
#include "pmemory.h"
|
||
#include "utils.h" // for strsame, et al
|
||
#include "sizes.h"
|
||
|
||
|
||
DWORD
|
||
SystemCount(
|
||
PPERFSYSTEM pSystemFirst
|
||
)
|
||
{
|
||
PPERFSYSTEM pSystem ;
|
||
DWORD iNumSystems ;
|
||
|
||
iNumSystems = 0 ;
|
||
|
||
for (pSystem = pSystemFirst ;
|
||
pSystem ;
|
||
pSystem = pSystem->pSystemNext) {
|
||
iNumSystems++ ;
|
||
}
|
||
|
||
return iNumSystems ;
|
||
}
|
||
|
||
|
||
BOOL
|
||
SystemSetupThread (PPERFSYSTEM pSystem)
|
||
{
|
||
DWORD dwThreadID ;
|
||
HANDLE hThread ;
|
||
HANDLE hStateDataMutex ;
|
||
HANDLE hPerfDataEvent ;
|
||
SECURITY_ATTRIBUTES SecAttr ;
|
||
PPERFDATA pSystemPerfData ;
|
||
|
||
|
||
SecAttr.nLength = sizeof (SecAttr) ;
|
||
SecAttr.bInheritHandle = TRUE ;
|
||
SecAttr.lpSecurityDescriptor = NULL ;
|
||
|
||
hThread = CreateThread (&SecAttr, 1024L,
|
||
(LPTHREAD_START_ROUTINE)PerfDataThread, (LPVOID)(pSystem), 0L, &dwThreadID);
|
||
|
||
if (!hThread) {
|
||
SystemFree (pSystem, TRUE);
|
||
return (FALSE) ;
|
||
}
|
||
|
||
// create a State Data Lock mutex
|
||
hStateDataMutex = CreateMutex (&SecAttr, FALSE, NULL);
|
||
if (!hStateDataMutex) {
|
||
CloseHandle (hThread) ;
|
||
SystemFree (pSystem, TRUE);
|
||
return (FALSE);
|
||
}
|
||
hPerfDataEvent = CreateEvent (&SecAttr, TRUE, 0L, NULL) ;
|
||
if (!hPerfDataEvent) {
|
||
CloseHandle (hStateDataMutex) ;
|
||
CloseHandle (hThread) ;
|
||
SystemFree (pSystem, TRUE);
|
||
return (FALSE);
|
||
}
|
||
|
||
// allocate Perfdata
|
||
pSystemPerfData = (PPERFDATA) MemoryAllocate (4096L) ;
|
||
if (!pSystemPerfData) {
|
||
CloseHandle (hPerfDataEvent) ;
|
||
CloseHandle (hStateDataMutex) ;
|
||
CloseHandle (hThread) ;
|
||
SystemFree (pSystem, TRUE);
|
||
return (FALSE);
|
||
}
|
||
// now setup the pSystem..
|
||
pSystem->dwThreadID = dwThreadID ;
|
||
pSystem->hThread = hThread ;
|
||
pSystem->hPerfDataEvent = hPerfDataEvent ;
|
||
pSystem->pSystemPerfData = pSystemPerfData ;
|
||
pSystem->hStateDataMutex = hStateDataMutex ;
|
||
|
||
return (TRUE) ;
|
||
}
|
||
|
||
PPERFSYSTEM
|
||
SystemCreate (
|
||
LPCTSTR lpszSystemName
|
||
)
|
||
{
|
||
PPERFSYSTEM pSystem ;
|
||
PPERFDATA pLocalPerfData = NULL;
|
||
DWORD Status ;
|
||
DWORD dwMemSize;
|
||
TCHAR GlobalValueBuffer[] = L"Global" ;
|
||
TCHAR ForeignValueBuffer[8+MAX_SYSTEM_NAME_LENGTH+1] =
|
||
L"Foreign " ;
|
||
|
||
// attempt to allocate system data structure
|
||
|
||
pSystem = MemoryAllocate (sizeof (PERFSYSTEM)) ;
|
||
if (!pSystem) {
|
||
SetLastError (ERROR_OUTOFMEMORY) ;
|
||
return (NULL) ;
|
||
}
|
||
|
||
// initialize name and help table pointers
|
||
|
||
pSystem->CounterInfo.pNextTable = NULL;
|
||
pSystem->CounterInfo.dwLangId = 0;
|
||
pSystem->CounterInfo.dwLastId = 0;
|
||
pSystem->CounterInfo.TextString = NULL;
|
||
|
||
lstrcpy (pSystem->sysName, lpszSystemName) ;
|
||
|
||
// try to open key to registry, error code is in GetLastError()
|
||
|
||
pSystem->sysDataKey = OpenSystemPerfData(lpszSystemName);
|
||
|
||
// if a Null Key was returned then:
|
||
// a) there's no such computer
|
||
// b) the system is a foreign computer
|
||
//
|
||
// before giving up, then see if it's a foreign computer
|
||
|
||
if (!pSystem->sysDataKey) {
|
||
|
||
// build foreign computer string
|
||
|
||
lstrcat(ForeignValueBuffer, lpszSystemName) ;
|
||
|
||
// assign System value name pointer to the local variable for trial
|
||
|
||
pSystem->lpszValue = ForeignValueBuffer;
|
||
|
||
// try to get data from the computer to see if it's for real
|
||
// otherwise, give up and return NULL
|
||
|
||
pLocalPerfData = MemoryAllocate (STARTING_SYSINFO_SIZE);
|
||
if (pLocalPerfData == NULL) { // no mem so give up
|
||
pSystem->lpszValue = NULL;
|
||
SystemFree (pSystem, TRUE);
|
||
SetLastError (ERROR_OUTOFMEMORY);
|
||
return (NULL);
|
||
} else {
|
||
pSystem->sysDataKey = HKEY_PERFORMANCE_DATA; // local machine
|
||
bCloseLocalMachine = TRUE ;
|
||
|
||
dwMemSize = STARTING_SYSINFO_SIZE;
|
||
Status = GetSystemPerfData (
|
||
pSystem->sysDataKey,
|
||
pSystem->lpszValue,
|
||
pLocalPerfData,
|
||
&dwMemSize);
|
||
|
||
// success means a valid buffer came back
|
||
// more data means someone tried (so it's probably good (?)
|
||
|
||
if ((Status == ERROR_MORE_DATA) || (Status == ERROR_SUCCESS)) {
|
||
if (Status == ERROR_SUCCESS) {
|
||
// see if a perf buffer was returned
|
||
if ((dwMemSize > 0) &&
|
||
pLocalPerfData->Signature[0] == (WCHAR)'P' &&
|
||
pLocalPerfData->Signature[1] == (WCHAR)'E' &&
|
||
pLocalPerfData->Signature[2] == (WCHAR)'R' &&
|
||
pLocalPerfData->Signature[3] == (WCHAR)'F' ) {
|
||
// valid buffer so continue
|
||
} else {
|
||
// invalid so unable to connect to that machine
|
||
pSystem->lpszValue = NULL;
|
||
SystemFree (pSystem, TRUE);
|
||
SetLastError (ERROR_BAD_NET_NAME); // unable to find name
|
||
return (NULL);
|
||
}
|
||
} else {
|
||
// assume that if MORE_DATA is returned that SOME
|
||
// data was attempted so the buffer must be valid
|
||
// (we hope)
|
||
}
|
||
MemoryFree ((LPMEMORY)pLocalPerfData) ;
|
||
pLocalPerfData = NULL;
|
||
|
||
// if we are reading from a setting file, let this pass thru'
|
||
if (bDelayAddAction == TRUE) {
|
||
pSystem->sysDataKey = NULL ;
|
||
pSystem->FailureTime = GetTickCount();
|
||
pSystem->dwSystemState = SYSTEM_DOWN;
|
||
|
||
// Free any memory that may have created
|
||
SystemFree (pSystem, FALSE) ;
|
||
|
||
pSystem->lpszValue = MemoryAllocate (TEMP_BUF_LEN*sizeof(WCHAR));
|
||
|
||
if (!pSystem->lpszValue) {
|
||
// unable to allocate memory
|
||
SystemFree (pSystem, TRUE);
|
||
SetLastError (ERROR_OUTOFMEMORY);
|
||
return (NULL) ;
|
||
} else {
|
||
lstrcpy (pSystem->lpszValue, GlobalValueBuffer);
|
||
}
|
||
|
||
// Setup the thread's stuff
|
||
if (SystemSetupThread (pSystem))
|
||
return (pSystem) ;
|
||
else
|
||
return NULL;
|
||
}
|
||
} else {
|
||
// some other error was returned so pack up and leave
|
||
pSystem->lpszValue = NULL;
|
||
SystemFree (pSystem, TRUE);
|
||
SetLastError (ERROR_BAD_NET_NAME); // unable to find name
|
||
return (NULL);
|
||
}
|
||
|
||
if (pLocalPerfData != NULL) {
|
||
MemoryFree ((LPMEMORY)pLocalPerfData); // don't really need anything from it
|
||
}
|
||
|
||
// ok, so we've established that a foreign data provider
|
||
// exists, now to finish the initialization.
|
||
|
||
// change system name in structure to get counter names
|
||
|
||
lstrcpy (pSystem->sysName, LocalComputerName);
|
||
|
||
Status = GetSystemNames(pSystem); // get counter names & explain text
|
||
if (Status != ERROR_SUCCESS) {
|
||
// unable to get names so bail out
|
||
pSystem->lpszValue = NULL;
|
||
SystemFree (pSystem, TRUE);
|
||
SetLastError (Status);
|
||
return (NULL) ;
|
||
}
|
||
|
||
// restore computer name for displays, etc.
|
||
|
||
lstrcpy (pSystem->sysName, lpszSystemName);
|
||
|
||
// allocate value string buffer
|
||
pSystem->lpszValue = MemoryAllocate (TEMP_BUF_LEN*sizeof(WCHAR));
|
||
if (!pSystem->lpszValue) {
|
||
// unable to allocate memory
|
||
SystemFree (pSystem, TRUE);
|
||
SetLastError (ERROR_OUTOFMEMORY);
|
||
return (NULL) ;
|
||
} else {
|
||
lstrcpy (pSystem->lpszValue, ForeignValueBuffer);
|
||
}
|
||
}
|
||
} else {
|
||
// if here, then a connection to the system's registry was established
|
||
// so continue with the system data structure initialization
|
||
|
||
// get counter names & explain text from local computer
|
||
|
||
Status = GetSystemNames(pSystem);
|
||
if (Status != ERROR_SUCCESS) {
|
||
// unable to get names so bail out
|
||
SystemFree (pSystem, TRUE);
|
||
SetLastError (Status);
|
||
return (NULL) ;
|
||
}
|
||
|
||
// allocate value string buffer
|
||
pSystem->lpszValue = MemoryAllocate(TEMP_BUF_LEN*sizeof(WCHAR));
|
||
|
||
if (!pSystem->lpszValue) {
|
||
// unable to allocate memory
|
||
SystemFree (pSystem, TRUE);
|
||
SetLastError (ERROR_OUTOFMEMORY);
|
||
return (NULL) ;
|
||
} else {
|
||
SetSystemValueNameToGlobal (pSystem);
|
||
}
|
||
}
|
||
|
||
// initialize remaining system pointers
|
||
|
||
pSystem->pSystemNext = NULL ;
|
||
pSystem->FailureTime = 0;
|
||
|
||
// setup data for thread data collection
|
||
if (!PlayingBackLog()) {
|
||
// create a thread for data collection
|
||
if (!SystemSetupThread (pSystem))
|
||
return (NULL) ;
|
||
}
|
||
|
||
SetLastError (ERROR_SUCCESS);
|
||
|
||
return (pSystem) ;
|
||
} // SystemCreate
|
||
|
||
PPERFSYSTEM
|
||
SystemGet (
|
||
PPERFSYSTEM pSystemFirst,
|
||
LPCTSTR lpszSystemName
|
||
)
|
||
{
|
||
PPERFSYSTEM pSystem ;
|
||
|
||
if (!pSystemFirst) {
|
||
return (NULL) ;
|
||
}
|
||
|
||
for (pSystem = pSystemFirst ;
|
||
pSystem ;
|
||
pSystem = pSystem->pSystemNext) {
|
||
if (strsamei (pSystem->sysName, lpszSystemName)) {
|
||
return (pSystem) ;
|
||
}
|
||
} // for
|
||
|
||
return (NULL) ;
|
||
}
|
||
|
||
PPERFSYSTEM
|
||
SystemAdd (
|
||
PPPERFSYSTEM ppSystemFirst,
|
||
LPCTSTR lpszSystemName,
|
||
HWND hDlg // owner window for error messages
|
||
)
|
||
{
|
||
PPERFSYSTEM pSystem ;
|
||
PPERFSYSTEM pSystemPrev = NULL;
|
||
TCHAR szMessage[256];
|
||
DWORD dwLastError;
|
||
|
||
if (!*ppSystemFirst) {
|
||
*ppSystemFirst = SystemCreate (lpszSystemName) ;
|
||
dwLastError = GetLastError();
|
||
// save return value
|
||
pSystem = *ppSystemFirst;
|
||
|
||
} else {
|
||
for (pSystem = *ppSystemFirst ;
|
||
pSystem ;
|
||
pSystem = pSystem->pSystemNext) {
|
||
pSystemPrev = pSystem ;
|
||
if (strsamei (pSystem->sysName, lpszSystemName)) {
|
||
return (pSystem) ;
|
||
}
|
||
} // for
|
||
|
||
pSystemPrev->pSystemNext = SystemCreate (lpszSystemName) ;
|
||
// save return value
|
||
pSystem = pSystemPrev->pSystemNext;
|
||
}
|
||
|
||
// display message box here if an error occured trying to add
|
||
// this system
|
||
|
||
if (pSystem == NULL) {
|
||
dwLastError = GetLastError();
|
||
if (dwLastError == ERROR_ACCESS_DENIED) {
|
||
DlgErrorBox (hDlg, ERR_ACCESS_DENIED);
|
||
} else {
|
||
DlgErrorBox (hDlg, ERR_UNABLE_CONNECT);
|
||
}
|
||
SetLastError (dwLastError); // to propogate up to caller
|
||
}
|
||
|
||
return (pSystem);
|
||
}
|
||
|
||
void
|
||
SystemFree (
|
||
PPERFSYSTEM pSystem,
|
||
BOOL bDeleteTheSystem
|
||
)
|
||
{ // SystemFree
|
||
|
||
PCOUNTERTEXT pCounter, pNextCounter;
|
||
|
||
if (!pSystem) {
|
||
// can't proceed
|
||
return ;
|
||
}
|
||
|
||
if (pSystem->sysDataKey && pSystem->sysDataKey != HKEY_PERFORMANCE_DATA) {
|
||
// close the remote computer key
|
||
RegCloseKey (pSystem->sysDataKey);
|
||
pSystem->sysDataKey = 0 ;
|
||
}
|
||
|
||
for (pCounter = pSystem->CounterInfo.pNextTable, pNextCounter = NULL;
|
||
pCounter;
|
||
pCounter = pNextCounter) {
|
||
pNextCounter = pCounter->pNextTable;
|
||
MemoryFree (pCounter);
|
||
}
|
||
pSystem->CounterInfo.pNextTable = NULL ;
|
||
|
||
if (pSystem->CounterInfo.TextString) {
|
||
MemoryFree (pSystem->CounterInfo.TextString);
|
||
pSystem->CounterInfo.TextString = NULL ;
|
||
}
|
||
|
||
if (pSystem->CounterInfo.HelpTextString) {
|
||
MemoryFree (pSystem->CounterInfo.HelpTextString);
|
||
pSystem->CounterInfo.HelpTextString = NULL ;
|
||
}
|
||
pSystem->CounterInfo.dwLastId = 0 ;
|
||
pSystem->CounterInfo.dwHelpSize = 0 ;
|
||
pSystem->CounterInfo.dwCounterSize = 0 ;
|
||
|
||
if (bDeleteTheSystem) {
|
||
#if 0
|
||
// cleanup all the data collection variables
|
||
if (pSystem->hPerfDataEvent)
|
||
CloseHandle (pSystem->hPerfDataEvent) ;
|
||
|
||
if (pSystem->hStateDataMutex)
|
||
CloseHandle (pSystem->hStateDataMutex) ;
|
||
|
||
if (pSystem->hThread)
|
||
CloseHandle (pSystem->hThread) ;
|
||
|
||
if (pSystem->pSystemPerfData)
|
||
MemoryFree (pSystem->pSystemPerfData);
|
||
|
||
if (pSystem->lpszValue) {
|
||
MemoryFree (pSystem->lpszValue);
|
||
pSystem->lpszValue = NULL ;
|
||
}
|
||
MemoryFree (pSystem) ;
|
||
#endif
|
||
if (pSystem->hThread) {
|
||
// let the thread clean up memory
|
||
PostThreadMessage (
|
||
pSystem->dwThreadID,
|
||
WM_FREE_SYSTEM,
|
||
(WPARAM)0,
|
||
(LPARAM)0) ;
|
||
} else {
|
||
// if no thread, clean up memory here.
|
||
// Should not happen.
|
||
if (pSystem->pSystemPerfData)
|
||
MemoryFree ((LPMEMORY)pSystem->pSystemPerfData);
|
||
|
||
if (pSystem->lpszValue) {
|
||
MemoryFree (pSystem->lpszValue);
|
||
pSystem->lpszValue = NULL ;
|
||
}
|
||
MemoryFree (pSystem) ;
|
||
}
|
||
}
|
||
}
|
||
|
||
void
|
||
DeleteUnusedSystems (
|
||
PPPERFSYSTEM ppSystemFirst ,
|
||
int iNoUseSystems
|
||
)
|
||
{
|
||
PPERFSYSTEM pPrevSys, pCurrentSys, pNextSys ;
|
||
|
||
// delete all the marked system from the list header until
|
||
// we hit one that is not marked
|
||
while ((*ppSystemFirst)->bSystemNoLongerNeeded) {
|
||
// delect from the list header
|
||
pCurrentSys = *ppSystemFirst ;
|
||
*ppSystemFirst = pCurrentSys->pSystemNext ;
|
||
SystemFree (pCurrentSys, TRUE) ;
|
||
iNoUseSystems-- ;
|
||
if (iNoUseSystems <= 0 || !(*ppSystemFirst)) {
|
||
// done
|
||
break ;
|
||
}
|
||
}
|
||
|
||
if (iNoUseSystems <= 0 || !(*ppSystemFirst)) {
|
||
return ;
|
||
}
|
||
|
||
// now walk the list and delete each marked system
|
||
for (pPrevSys = *ppSystemFirst, pCurrentSys = pPrevSys->pSystemNext ;
|
||
pCurrentSys && iNoUseSystems > 0 ;
|
||
pCurrentSys = pNextSys) {
|
||
|
||
if (pCurrentSys->bSystemNoLongerNeeded) {
|
||
// the current system is marked, updated the list and free
|
||
// this system. No need to change pPrevSys here
|
||
pNextSys = pPrevSys->pSystemNext = pCurrentSys->pSystemNext ;
|
||
SystemFree (pCurrentSys, TRUE) ;
|
||
iNoUseSystems-- ;
|
||
} else {
|
||
// pCurrentSys is OK, update the 2 list pointers and
|
||
// carry on looping
|
||
pPrevSys = pCurrentSys ;
|
||
pNextSys = pCurrentSys->pSystemNext ;
|
||
}
|
||
}
|
||
}
|
||
|
||
void
|
||
FreeSystems (
|
||
PPERFSYSTEM pSystemFirst
|
||
)
|
||
{
|
||
PPERFSYSTEM pSystem, pSystemNext ;
|
||
|
||
|
||
for (pSystem = pSystemFirst;
|
||
pSystem;
|
||
pSystem = pSystemNext) {
|
||
pSystemNext = pSystem->pSystemNext ;
|
||
SystemFree (pSystem, TRUE) ;
|
||
}
|
||
} // FreeSystems
|
||
|
||
PPERFSYSTEM
|
||
GetComputer (
|
||
HDLG hDlg,
|
||
WORD wControlID,
|
||
BOOL bWarn,
|
||
PPERFDATA *ppPerfData,
|
||
PPERFSYSTEM *ppSystemFirst
|
||
)
|
||
/*
|
||
Effect: Attempt to set the current computer to the one in the
|
||
hWndComputers dialog edit box. If this computer system
|
||
can be found, load the objects, etc. for the computer
|
||
and set pSystem and ppPerfdata to the values for this
|
||
system.
|
||
*/
|
||
{ // GetComputer
|
||
TCHAR szComputer [MAX_SYSTEM_NAME_LENGTH + 1] ;
|
||
PPERFSYSTEM pSystem;
|
||
TCHAR tempBuffer [LongTextLen] ;
|
||
DWORD dwBufferSize = 0;
|
||
LPTSTR pBuffer = NULL ;
|
||
DWORD dwLastError;
|
||
|
||
DialogText (hDlg, wControlID, szComputer) ;
|
||
|
||
// If necessary, add the system to the lists for this view.
|
||
pSystem = SystemGet (*ppSystemFirst, szComputer) ;
|
||
if (!pSystem) {
|
||
pSystem = SystemAdd (ppSystemFirst, szComputer, hDlg) ;
|
||
}
|
||
|
||
if (!pSystem && bWarn) {
|
||
dwLastError = GetLastError();
|
||
|
||
EditSetModified (GetDlgItem(hDlg, wControlID), FALSE) ;
|
||
|
||
// unable to get specified computer so set to:
|
||
// the first computer in the system list if present
|
||
// -- or --
|
||
// set he local machine if not.
|
||
|
||
pSystem = *ppSystemFirst; // set to first in list
|
||
|
||
if (pSystem == NULL) {
|
||
// this would mean the user can't access the local
|
||
// system since normally that would be the first one
|
||
// so the machine name will be restored to the
|
||
// local machine (for lack of a better one) but the
|
||
// system won't be added unless they want to explicitly
|
||
|
||
DialogSetString (hDlg, wControlID, LocalComputerName) ;
|
||
} else {
|
||
// set to name in system structure
|
||
DialogSetString (hDlg, wControlID, pSystem->sysName);
|
||
}
|
||
|
||
if (dwLastError != ERROR_ACCESS_DENIED) {
|
||
DlgErrorBox (hDlg, ERR_COMPUTERNOTFOUND) ;
|
||
} else {
|
||
// the appropriate error message has already been displayed
|
||
}
|
||
|
||
SetFocus (DialogControl(hDlg, wControlID)) ;
|
||
}
|
||
|
||
if (pSystem) {
|
||
if (PlayingBackLog ()) {
|
||
*ppPerfData =
|
||
LogDataFromPosition (pSystem, &(PlaybackLog.StartIndexPos)) ;
|
||
} else {
|
||
if (pSystem->lpszValue) {
|
||
// save the previous lpszValue string before
|
||
// SetSystemValueNameToGlobal mess it up
|
||
dwBufferSize = MemorySize (pSystem->lpszValue) ;
|
||
if (dwBufferSize <= sizeof(tempBuffer)) {
|
||
pBuffer = tempBuffer ;
|
||
} else {
|
||
pBuffer = MemoryAllocate (dwBufferSize) ;
|
||
}
|
||
memcpy (pBuffer, pSystem->lpszValue, dwBufferSize) ;
|
||
}
|
||
|
||
SetSystemValueNameToGlobal (pSystem);
|
||
UpdateSystemData (pSystem, ppPerfData) ;
|
||
|
||
if (pSystem->lpszValue) {
|
||
// retore the previous lpszValue string
|
||
memcpy (pSystem->lpszValue, pBuffer, dwBufferSize) ;
|
||
if (pBuffer != tempBuffer) {
|
||
MemoryFree (pBuffer) ;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return (pSystem) ;
|
||
|
||
} // GetComputer
|
||
|