2402 lines
66 KiB
C
2402 lines
66 KiB
C
//==========================================================================//
|
|
// Includes //
|
|
//==========================================================================//
|
|
|
|
#include <stdio.h>
|
|
#include "perfmon.h"
|
|
#include "alert.h" // External declarations for this file
|
|
|
|
#include "addline.h" // for AddLine
|
|
#include "fileutil.h" // for FileRead
|
|
#include "legend.h"
|
|
#include "line.h"
|
|
#include "pmemory.h" // for MemoryXXX (mallloc-type) routines
|
|
#include "owndraw.h" // for OwnerDraw macros
|
|
#include "perfdata.h" // for UpdateLines
|
|
#include "perfmops.h" // for SystemAdd
|
|
#include "playback.h" // for PlaybackLines
|
|
#include "status.h" // for StatusUpdateAlerts
|
|
#include "system.h" // for SystemGet
|
|
#include "utils.h"
|
|
#include "menuids.h" // for IDM_VIEWALERT
|
|
#include "fileopen.h" // for FileGetName
|
|
#include "counters.h" // for CounterEntry
|
|
|
|
#include <lmcons.h>
|
|
#include <lmmsg.h>
|
|
#include <lmerr.h>
|
|
|
|
#include "perfmsg.h" // Alert eventlog message id
|
|
|
|
#define WM_SEND_NETWORK_ALERT (WM_USER + 101)
|
|
|
|
//==========================================================================//
|
|
// Typedefs //
|
|
//==========================================================================//
|
|
|
|
typedef NET_API_STATUS
|
|
(*pNetMessageBufferSend) (
|
|
IN LPTSTR servername,
|
|
IN LPTSTR msgname,
|
|
IN LPTSTR fromname,
|
|
IN LPBYTE buf,
|
|
IN DWORD buflen
|
|
);
|
|
|
|
typedef struct ALERTENTRYSTRUCT {
|
|
SYSTEMTIME SystemTime ;
|
|
PLINE pLine ;
|
|
FLOAT eValue ;
|
|
BOOL bOver ;
|
|
FLOAT eAlertValue ;
|
|
LPTSTR lpszInstance ;
|
|
LPTSTR lpszParent ;
|
|
INT StringWidth ;
|
|
} ALERTENTRY ;
|
|
|
|
typedef ALERTENTRY *PALERTENTRY ;
|
|
|
|
static HBRUSH hRedBrush ;
|
|
|
|
//====
|
|
//====
|
|
|
|
//==========================================================================//
|
|
// Constants //
|
|
//==========================================================================//
|
|
|
|
|
|
#define szNumberFormat TEXT("%12.3f")
|
|
#define szMediumnNumberFormat TEXT("%12.0f")
|
|
#define szLargeNumberFormat TEXT("%12.4e")
|
|
#define eNumber ((FLOAT) 99999999.999)
|
|
#define eLargeNumber ((FLOAT) 999999999999.0)
|
|
|
|
#define szNumberPrototype TEXT("99999999.999")
|
|
|
|
|
|
#define szConditionFormat TEXT(" %c ")
|
|
#define szConditionPrototype TEXT(" > ")
|
|
|
|
#define szDatePrototype TEXT("12/31/1999 ")
|
|
#define szTimePrototype TEXT("12:34:56.9 pm ")
|
|
|
|
#define ALERTLOGMAXITEMS 1000
|
|
// enclose alert within double quotes to make it a single command line
|
|
// argument rather then 10 args.
|
|
#define szAlertFormat TEXT("\"%s %s %s %c %s %s, %s, %s, %s, %s\"")
|
|
|
|
|
|
//==========================================================================//
|
|
// Macros //
|
|
//==========================================================================//
|
|
|
|
|
|
#define AlertItemTopMargin() (yBorderHeight)
|
|
|
|
|
|
|
|
//==========================================================================//
|
|
// Local Functions //
|
|
//==========================================================================//
|
|
INT ExportAlertLine (PLINE pLine, FLOAT eValue, SYSTEMTIME *pSystemTime, HANDLE hExportFile) ;
|
|
|
|
void
|
|
AlertFormatFloat (
|
|
LPTSTR lpValueBuf,
|
|
FLOAT eValue
|
|
)
|
|
{
|
|
if (eValue <= eNumber) {
|
|
TSPRINTF (lpValueBuf, szNumberFormat, eValue) ;
|
|
} else if (eValue <= eLargeNumber) {
|
|
TSPRINTF (lpValueBuf, szMediumnNumberFormat, eValue) ;
|
|
} else {
|
|
TSPRINTF (lpValueBuf, szLargeNumberFormat, eValue) ;
|
|
}
|
|
ConvertDecimalPoint (lpValueBuf) ;
|
|
|
|
}
|
|
|
|
|
|
PALERT
|
|
AllocateAlertData (
|
|
HWND hWndAlert
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
|
|
pAlert->hWnd = hWndAlert ;
|
|
pAlert->hAlertListBox = DialogControl (hWndAlert, IDD_ALERTLOG) ;
|
|
pAlert->iStatus = iPMStatusClosed ;
|
|
pAlert->bManualRefresh = FALSE ;
|
|
pAlert->bModified = FALSE ;
|
|
|
|
pAlert->Visual.iColorIndex = 0 ;
|
|
pAlert->Visual.iWidthIndex = -1 ;
|
|
pAlert->Visual.iStyleIndex = -1 ;
|
|
|
|
pAlert->iIntervalMSecs = iDefaultAlertIntervalSecs * 1000 ;
|
|
pAlert->pSystemFirst = NULL ;
|
|
pAlert->pLineFirst = NULL ;
|
|
|
|
pAlert->MessageName[0] = TEXT('\0') ;
|
|
|
|
pAlert->bLegendOn = TRUE ;
|
|
|
|
return (pAlert) ;
|
|
}
|
|
|
|
|
|
void FreeAlertData (PALERT pAlert) {}
|
|
|
|
|
|
BOOL
|
|
SetAlertTimer (
|
|
PALERT pAlert
|
|
)
|
|
{
|
|
if (pAlert->iStatus == iPMStatusCollecting)
|
|
KillTimer (pAlert->hWnd, AlertTimerID) ;
|
|
|
|
pAlert->iStatus = iPMStatusCollecting ;
|
|
SetTimer (pAlert->hWnd, AlertTimerID, pAlert->iIntervalMSecs, NULL) ;
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ClearAlertTimer (
|
|
PALERT pAlert
|
|
)
|
|
{
|
|
if (!PlayingBackLog()) {
|
|
KillTimer (pAlert->hWnd, AlertTimerID) ;
|
|
}
|
|
pAlert->iStatus = iPMStatusClosed ;
|
|
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
AlertExec (
|
|
LPTSTR lpszImageName,
|
|
LPTSTR lpszCommandLine
|
|
)
|
|
/*
|
|
Effect: WinExec is considered obsolete. We're supposed to use
|
|
CreateProcess, which allows considerably more control.
|
|
For perfmon, we only execute a program when an alert
|
|
occurs, and we really don't know anything about the
|
|
program, so can't really do much. We just set some
|
|
defaults and go.
|
|
|
|
Called By: SignalAlert only.
|
|
*/
|
|
{
|
|
STARTUPINFO si ;
|
|
PROCESS_INFORMATION pi ;
|
|
int StringLen ;
|
|
TCHAR TempBuffer [ 5 * FilePathLen ] ;
|
|
BOOL RetCode;
|
|
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;
|
|
|
|
memset (&si, 0, sizeof (STARTUPINFO)) ;
|
|
si.cb = sizeof (STARTUPINFO) ;
|
|
si.dwFlags = STARTF_USESHOWWINDOW ;
|
|
si.wShowWindow = SW_SHOWNOACTIVATE ;
|
|
memset (&pi, 0, sizeof (PROCESS_INFORMATION)) ;
|
|
|
|
lstrcpy (TempBuffer, lpszImageName) ;
|
|
StringLen = lstrlen (TempBuffer) ;
|
|
|
|
// see if this is a CMD or a BAT file
|
|
// if it is then create a process with a console window, otherwise
|
|
// assume it's an executable file that will create it's own window
|
|
// or console if necessary
|
|
//
|
|
_tcslwr (TempBuffer);
|
|
if ((_tcsstr(TempBuffer, TEXT(".bat")) != NULL) ||
|
|
(_tcsstr(TempBuffer, TEXT(".cmd")) != NULL)) {
|
|
dwCreationFlags |= CREATE_NEW_CONSOLE;
|
|
} else {
|
|
dwCreationFlags |= DETACHED_PROCESS;
|
|
}
|
|
// recopy the image name to the temp buffer since it was modified
|
|
// (i.e. lowercased) for the previous comparison.
|
|
|
|
lstrcpy (TempBuffer, lpszImageName) ;
|
|
StringLen = lstrlen (TempBuffer) ;
|
|
|
|
// now add on the alert text preceded with a space char
|
|
TempBuffer [StringLen] = TEXT(' ') ;
|
|
StringLen++ ;
|
|
lstrcpy (&TempBuffer[StringLen], lpszCommandLine) ;
|
|
|
|
// DETACHED_PROCESS is needed to get rid of the ugly console window
|
|
// that SQL guys have been bitching..
|
|
RetCode = CreateProcess (NULL, TempBuffer,
|
|
NULL, NULL, FALSE,
|
|
dwCreationFlags,
|
|
// (DWORD) NORMAL_PRIORITY_CLASS | DETACHED_PROCESS,
|
|
// (DWORD) NORMAL_PRIORITY_CLASS,
|
|
NULL, NULL,
|
|
&si, &pi) ;
|
|
if (RetCode) {
|
|
if (pi.hProcess && pi.hProcess != INVALID_HANDLE_VALUE) {
|
|
CloseHandle (pi.hProcess) ;
|
|
}
|
|
if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE) {
|
|
CloseHandle (pi.hThread) ;
|
|
}
|
|
}
|
|
|
|
return RetCode ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SendNetworkMessage (
|
|
LPTSTR pText,
|
|
DWORD TextLen,
|
|
LPTSTR pMessageName
|
|
)
|
|
{
|
|
NET_API_STATUS NetStatus;
|
|
HANDLE dllHandle ;
|
|
pNetMessageBufferSend SendFunction ;
|
|
|
|
//
|
|
// Dynamically link to netapi32.dll. If it's not there just return. Return
|
|
// TRUE so we won't try to send this alert again.
|
|
//
|
|
|
|
dllHandle = LoadLibrary(TEXT("NetApi32.Dll")) ;
|
|
if ( !dllHandle || dllHandle == INVALID_HANDLE_VALUE ) {
|
|
return(TRUE) ;
|
|
}
|
|
|
|
//
|
|
// Get the address of the service's main entry point. This
|
|
// entry point has a well-known name.
|
|
//
|
|
|
|
SendFunction = (pNetMessageBufferSend)GetProcAddress(
|
|
dllHandle, "NetMessageBufferSend") ;
|
|
|
|
if (SendFunction == NULL) {
|
|
FreeLibrary (dllHandle) ;
|
|
return(TRUE) ;
|
|
}
|
|
|
|
NetStatus = (*SendFunction) (NULL, pMessageName,
|
|
NULL, (LPBYTE)pText, TextLen * sizeof(TCHAR)) ;
|
|
if (NetStatus != NERR_Success) {
|
|
FreeLibrary (dllHandle) ;
|
|
return (FALSE) ;
|
|
}
|
|
|
|
FreeLibrary (dllHandle) ;
|
|
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
// this is the child thread used to send out network alert message.
|
|
// This thread is created at init time and is destroyed at close time
|
|
void
|
|
NetAlertHandler (
|
|
LPVOID *pDummy
|
|
)
|
|
{
|
|
MSG msg;
|
|
|
|
while (GetMessage (&msg, NULL, 0, 0)) {
|
|
// we are only interested in this message
|
|
if (LOWORD(msg.message) == WM_SEND_NETWORK_ALERT) {
|
|
SendNetworkMessage ((LPTSTR)(msg.wParam),
|
|
lstrlen ((LPTSTR)(msg.wParam)),
|
|
(LPTSTR)(msg.lParam)) ;
|
|
MemoryFree ((LPTSTR)(msg.wParam)) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
SignalAlert (
|
|
HWND hWnd,
|
|
HWND hWndAlerts,
|
|
PLINE pLine,
|
|
FLOAT eValue,
|
|
SYSTEMTIME *pSystemTime,
|
|
LPTSTR pSystemName,
|
|
DWORD dwSystemState
|
|
)
|
|
/*
|
|
Effect: Perform any actions necessary when a given alert line's
|
|
condition is true. In particular, add the alert to the
|
|
alert log. Also, depending on the user's wishes, signal
|
|
a network alert or beep or run a program.
|
|
|
|
If we are not viewing the alert screen, add one alert to
|
|
the unviewed list.
|
|
*/
|
|
{
|
|
INT_PTR iIndex ;
|
|
PALERT pAlert ;
|
|
PALERTENTRY pAlertEntry ;
|
|
TCHAR szTime [20] ;
|
|
TCHAR szDate [20] ;
|
|
TCHAR szInstance [256] ;
|
|
TCHAR szParent [256] ;
|
|
TCHAR szText [256 * 4] ;
|
|
TCHAR eValueBuf [40] ;
|
|
TCHAR eAlertValueBuf [40] ;
|
|
TCHAR eAlertValueBuf1 [42] ;
|
|
FLOAT eLocalValue ;
|
|
DWORD TextSize = 0;
|
|
LPTSTR lpAlertMsg ;
|
|
LPTSTR lpEventLog[7] ;
|
|
TCHAR NullBuff [2] ;
|
|
|
|
NullBuff [0] = NullBuff [1] = TEXT('\0') ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
|
|
pAlertEntry = MemoryAllocate (sizeof (ALERTENTRY)) ;
|
|
if (!pAlertEntry) {
|
|
return ;
|
|
}
|
|
pAlertEntry->SystemTime = *pSystemTime ;
|
|
pAlertEntry->pLine= pLine ;
|
|
pAlertEntry->eValue = eValue ;
|
|
if (pLine) {
|
|
pAlertEntry->bOver = pLine->bAlertOver ;
|
|
pAlertEntry->eAlertValue = pLine->eAlertValue ;
|
|
}
|
|
|
|
|
|
//=============================//
|
|
// Determine Instance, Parent //
|
|
//=============================//
|
|
|
|
// It's possible that there will be no instance, therefore
|
|
// the lnInstanceName would be NULL.
|
|
|
|
if (pLine && pLine->lnObject.NumInstances > 0) {
|
|
// Test for the parent object instance name title index.
|
|
// If there is one, it implies that there will be a valid
|
|
// Parent Object Name and a valid Parent Object Instance Name.
|
|
|
|
// If the Parent Object title index is 0 then
|
|
// just display the instance name.
|
|
|
|
lstrcpy (szInstance, pLine->lnInstanceName) ;
|
|
if (pLine->lnInstanceDef.ParentObjectTitleIndex && pLine->lnPINName) {
|
|
// Get the Parent Object Name.
|
|
lstrcpy (szParent, pLine->lnPINName) ;
|
|
} else {
|
|
szParent[0] = TEXT(' ') ;
|
|
szParent[1] = TEXT('\0') ;
|
|
}
|
|
} else {
|
|
if (pLine) {
|
|
szInstance[0] = TEXT(' ') ;
|
|
szInstance[1] = TEXT('\0') ;
|
|
szParent[0] = TEXT(' ') ;
|
|
szParent[1] = TEXT('\0') ;
|
|
} else {
|
|
// this is a system down/reconnect alert
|
|
StringLoad (
|
|
dwSystemState == SYSTEM_DOWN ?
|
|
IDS_SYSTEM_DOWN : IDS_SYSTEM_UP,
|
|
szInstance) ;
|
|
lstrcpy (szParent, pSystemName) ;
|
|
}
|
|
}
|
|
|
|
|
|
pAlertEntry->lpszInstance = StringAllocate (szInstance) ;
|
|
pAlertEntry->lpszParent = StringAllocate (szParent) ;
|
|
|
|
//=============================//
|
|
// Add alert to Alert Log //
|
|
//=============================//
|
|
|
|
if (LBNumItems (hWndAlerts) >= ALERTLOGMAXITEMS)
|
|
LBDelete (hWndAlerts, 0) ;
|
|
|
|
iIndex = LBAdd (hWndAlerts, (LPARAM) pAlertEntry) ;
|
|
LBSetSelection (hWndAlerts, iIndex) ;
|
|
|
|
// no need to check other things if we
|
|
// are playing back log
|
|
if (PlayingBackLog()) {
|
|
return ;
|
|
}
|
|
|
|
//=============================//
|
|
// Update Status Line //
|
|
//=============================//
|
|
|
|
if (iPerfmonView != IDM_VIEWALERT) {
|
|
if (pAlert->bSwitchToAlert) {
|
|
SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWALERT, 0L) ;
|
|
} else {
|
|
// if iUnviewedAlerts is over 100, we will display "++"
|
|
// so, no need to keep updating the icon...
|
|
if (iUnviewedAlerts < 100) {
|
|
iUnviewedAlerts ++ ;
|
|
if (pLine) {
|
|
crLastUnviewedAlert = pLine->Visual.crColor ;
|
|
}
|
|
StatusUpdateIcons (hWndStatus) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
//===================================//
|
|
// Check if we need to do anything //
|
|
//===================================//
|
|
szText[0] = TEXT('\0') ;
|
|
if ((pAlert->bNetworkAlert && pAlert->MessageName[0])
|
|
||
|
|
(pLine) &&
|
|
(pLine->lpszAlertProgram &&
|
|
(pLine->bEveryTime || !pLine->bAlerted))
|
|
||
|
|
(pAlert->bEventLog)) {
|
|
// format the alert line to be exported
|
|
SystemTimeDateString (pSystemTime, szDate) ;
|
|
SystemTimeTimeString (pSystemTime, szTime, TRUE) ;
|
|
|
|
if (pLine) {
|
|
AlertFormatFloat (eValueBuf, pAlertEntry->eValue) ;
|
|
|
|
eLocalValue = pAlertEntry->eAlertValue ;
|
|
if (eLocalValue < (FLOAT) 0.0) {
|
|
eLocalValue = -eLocalValue ;
|
|
}
|
|
AlertFormatFloat (eAlertValueBuf, pAlertEntry->eAlertValue) ;
|
|
|
|
TSPRINTF (szText,
|
|
szAlertFormat,
|
|
szDate,
|
|
szTime,
|
|
eValueBuf,
|
|
(pLine->bAlertOver ? TEXT('>') : TEXT('<')),
|
|
eAlertValueBuf,
|
|
pLine->lnCounterName,
|
|
szInstance,
|
|
szParent,
|
|
pLine->lnObjectName,
|
|
pLine->lnSystemName) ;
|
|
} else {
|
|
lstrcpy (eValueBuf, DashLine) ;
|
|
lstrcpy (eAlertValueBuf, eValueBuf) ;
|
|
TSPRINTF (szText,
|
|
szAlertFormat,
|
|
szDate,
|
|
szTime,
|
|
eValueBuf,
|
|
TEXT(' '),
|
|
eAlertValueBuf,
|
|
szInstance, // system up/down message
|
|
NullBuff,
|
|
NullBuff,
|
|
NullBuff,
|
|
szParent) ;
|
|
}
|
|
|
|
TextSize = sizeof(TCHAR) * (lstrlen(szText)+1) ;
|
|
}
|
|
|
|
if (szText[0] == TEXT('\0')) {
|
|
// nothing to do
|
|
return ;
|
|
}
|
|
|
|
//=============================//
|
|
// Network Alert? //
|
|
//=============================//
|
|
|
|
SetHourglassCursor() ;
|
|
|
|
if (pAlert->bNetworkAlert && pAlert->MessageName[0]) {
|
|
|
|
if (pAlert->dwNetAlertThreadID) {
|
|
// use thread to send the network alert.
|
|
// the memory will be released by the child thread when done
|
|
lpAlertMsg =
|
|
(LPTSTR) MemoryAllocate (TextSize) ;
|
|
if (lpAlertMsg) {
|
|
lstrcpy (lpAlertMsg, szText) ;
|
|
PostThreadMessage (pAlert->dwNetAlertThreadID,
|
|
WM_SEND_NETWORK_ALERT,
|
|
(WPARAM)lpAlertMsg,
|
|
(LPARAM)pAlert->MessageName) ;
|
|
}
|
|
} else {
|
|
// no thread available, use the slow way to send the network alert
|
|
SendNetworkMessage (szText,
|
|
(DWORD) lstrlen(szText),
|
|
pAlert->MessageName) ;
|
|
}
|
|
}
|
|
|
|
|
|
//=============================//
|
|
// Run Program? //
|
|
//=============================//
|
|
|
|
if (pLine &&
|
|
pLine->lpszAlertProgram &&
|
|
(pLine->bEveryTime || !pLine->bAlerted)) {
|
|
AlertExec (pLine->lpszAlertProgram, szText) ;
|
|
pLine->bAlerted = TRUE ;
|
|
}
|
|
|
|
//===================================//
|
|
// Log event to Application Log? //
|
|
//===================================//
|
|
if (pAlert->bEventLog) {
|
|
if (hEventLog) {
|
|
if (pLine) {
|
|
lpEventLog[0] = pLine->lnSystemName ;
|
|
lpEventLog[1] = pLine->lnObjectName ;
|
|
lpEventLog[2] = pLine->lnCounterName ;
|
|
lpEventLog[3] = szInstance ;
|
|
lpEventLog[4] = szParent ;
|
|
lpEventLog[5] = eValueBuf ;
|
|
eAlertValueBuf1[0] = pLine->bAlertOver ? TEXT('>') : TEXT('<') ;
|
|
eAlertValueBuf1[1] = TEXT(' ') ;
|
|
lstrcpy (&eAlertValueBuf1[2], eAlertValueBuf) ;
|
|
lpEventLog[6] = eAlertValueBuf1 ;
|
|
} else {
|
|
lpEventLog[0] = szParent ;
|
|
lpEventLog[1] = szInstance ;
|
|
}
|
|
|
|
ReportEvent (hEventLog,
|
|
(WORD)EVENTLOG_INFORMATION_TYPE,
|
|
(WORD)0,
|
|
(DWORD)(pLine ? MSG_ALERT_OCCURRED : MSG_ALERT_SYSTEM),
|
|
(PSID)NULL,
|
|
(WORD)(pLine ? 7 : 2),
|
|
(DWORD)TextSize,
|
|
(LPCTSTR *)lpEventLog,
|
|
(LPVOID)(szText)) ;
|
|
}
|
|
}
|
|
SetArrowCursor() ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
AlertCondition (
|
|
PLINE pLine,
|
|
FLOAT eValue
|
|
)
|
|
/*
|
|
Effect: Return whether the alert test passed for line pLine,
|
|
with current data value eValue.
|
|
|
|
Internals: Don't *ever* say (bFoo == bBar), as non-FALSE values
|
|
could be represented by any nonzero number. Use
|
|
BoolEqual or equivalent.
|
|
*/
|
|
{
|
|
BOOL bOver ;
|
|
|
|
bOver = eValue > pLine->eAlertValue ;
|
|
|
|
return (BoolEqual (bOver, pLine->bAlertOver)) ;
|
|
}
|
|
|
|
|
|
INT
|
|
static
|
|
CheckAlerts (
|
|
HWND hWnd,
|
|
HWND hWndAlerts,
|
|
SYSTEMTIME *pSystemTime,
|
|
PLINE pLineFirst,
|
|
HANDLE hExportFile,
|
|
PPERFSYSTEM pSystemFirst
|
|
)
|
|
{
|
|
FLOAT eValue ;
|
|
PLINE pLine ;
|
|
BOOL bAnyAlerts ;
|
|
INT ErrCode = 0 ;
|
|
PPERFSYSTEM pSystem ;
|
|
|
|
bAnyAlerts = FALSE ;
|
|
if (!PlayingBackLog()) {
|
|
LBSetRedraw (hWndAlerts, FALSE) ;
|
|
|
|
// check for system up/down
|
|
for (pSystem = pSystemFirst ;
|
|
pSystem ;
|
|
pSystem = pSystem->pSystemNext) {
|
|
if (pSystem->dwSystemState == SYSTEM_DOWN) {
|
|
pSystem->dwSystemState = SYSTEM_DOWN_RPT ;
|
|
SignalAlert (hWnd,
|
|
hWndAlerts,
|
|
NULL,
|
|
(FLOAT) 0.0,
|
|
pSystemTime,
|
|
pSystem->sysName,
|
|
SYSTEM_DOWN) ;
|
|
} else if (pSystem->dwSystemState == SYSTEM_RECONNECT) {
|
|
pSystem->dwSystemState = SYSTEM_RECONNECT_RPT ;
|
|
SignalAlert (hWnd,
|
|
hWndAlerts,
|
|
NULL,
|
|
(FLOAT) 0.0,
|
|
pSystemTime,
|
|
pSystem->sysName,
|
|
SYSTEM_RECONNECT) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
for (pLine = pLineFirst ;
|
|
pLine ;
|
|
pLine = pLine->pLineNext) {
|
|
if (pLine->bFirstTime) {
|
|
// skip until we have collect enough samples for the first data
|
|
continue ;
|
|
}
|
|
|
|
// Get the new value for this line.
|
|
eValue = CounterEntry (pLine) ;
|
|
if (AlertCondition (pLine, eValue)) {
|
|
bAnyAlerts = TRUE ;
|
|
|
|
// the case that hExportFile is !NULL is when playingback log and that the
|
|
// listbox is overflowed with alert. In this case, we have to
|
|
// walk the log file again to re-generate all the alerts.
|
|
if (hExportFile) {
|
|
ErrCode = ExportAlertLine (pLine, eValue, pSystemTime, hExportFile) ;
|
|
if (ErrCode) {
|
|
break ;
|
|
}
|
|
} else {
|
|
SignalAlert (hWnd,
|
|
hWndAlerts,
|
|
pLine,
|
|
eValue,
|
|
pSystemTime,
|
|
NULL,
|
|
0) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!PlayingBackLog()) {
|
|
LBSetRedraw (hWndAlerts, TRUE) ;
|
|
}
|
|
|
|
return (ErrCode) ;
|
|
}
|
|
|
|
|
|
void
|
|
DrawAlertEntry (
|
|
HWND hWnd,
|
|
PALERT pAlert,
|
|
PALERTENTRY pAlertEntry,
|
|
LPDRAWITEMSTRUCT lpDI,
|
|
HDC hDC
|
|
)
|
|
{
|
|
PLINE pLine ;
|
|
RECT rectUpdate ;
|
|
|
|
TCHAR szTime [20] ;
|
|
TCHAR szDate [20] ;
|
|
TCHAR szText [256] ;
|
|
|
|
HBRUSH hBrushPrevious ;
|
|
FLOAT eLocalValue ;
|
|
COLORREF preBkColor = 0;
|
|
COLORREF preTextColor = 0;
|
|
|
|
pLine = pAlertEntry->pLine ;
|
|
|
|
SystemTimeDateString (&(pAlertEntry->SystemTime), szDate) ;
|
|
SystemTimeTimeString (&(pAlertEntry->SystemTime), szTime, TRUE) ;
|
|
|
|
if (DISelected (lpDI)) {
|
|
preTextColor = SetTextColor (hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)) ;
|
|
preBkColor = SetBkColor (hDC, GetSysColor (COLOR_HIGHLIGHT)) ;
|
|
}
|
|
|
|
//=============================//
|
|
// Draw Color Dot //
|
|
//=============================//
|
|
|
|
rectUpdate.left = 0 ;
|
|
rectUpdate.top = lpDI->rcItem.top ;
|
|
rectUpdate.right = pAlert->xColorWidth ;
|
|
rectUpdate.bottom = lpDI->rcItem.bottom ;
|
|
|
|
ExtTextOut (hDC, rectUpdate.left, rectUpdate.top,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rectUpdate,
|
|
NULL, 0,
|
|
NULL) ;
|
|
|
|
if (pLine) {
|
|
hBrushPrevious = SelectBrush (hDC, pLine->hBrush) ;
|
|
} else {
|
|
if (hRedBrush == NULL) {
|
|
hRedBrush = CreateSolidBrush (RGB (0xff, 0x00, 0x00)) ;
|
|
}
|
|
hBrushPrevious = SelectBrush (hDC, hRedBrush) ;
|
|
}
|
|
|
|
Ellipse (hDC,
|
|
rectUpdate.left + 2,
|
|
rectUpdate.top + 2,
|
|
rectUpdate.right - 2,
|
|
rectUpdate.bottom - 2) ;
|
|
|
|
SelectBrush (hDC, hBrushPrevious) ;
|
|
|
|
//=============================//
|
|
// Draw Date //
|
|
//=============================//
|
|
|
|
rectUpdate.left = rectUpdate.right ;
|
|
rectUpdate.right = rectUpdate.left + pAlert->xDateWidth ;
|
|
|
|
ExtTextOut (hDC, rectUpdate.left, rectUpdate.top,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rectUpdate,
|
|
szDate, lstrlen (szDate),
|
|
NULL) ;
|
|
|
|
//=============================//
|
|
// Draw Time //
|
|
//=============================//
|
|
|
|
rectUpdate.left = rectUpdate.right ;
|
|
rectUpdate.right = rectUpdate.left + pAlert->xTimeWidth ;
|
|
|
|
ExtTextOut (hDC, rectUpdate.left, rectUpdate.top,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rectUpdate,
|
|
szTime, lstrlen (szTime),
|
|
NULL) ;
|
|
|
|
//=============================//
|
|
// Draw Alert Value //
|
|
//=============================//
|
|
|
|
SetTextAlign (hDC, TA_RIGHT) ;
|
|
|
|
rectUpdate.left = rectUpdate.right ;
|
|
rectUpdate.right = rectUpdate.left + pAlert->xNumberWidth ;
|
|
|
|
if (pLine) {
|
|
AlertFormatFloat (szText, pAlertEntry->eValue) ;
|
|
} else {
|
|
lstrcpy (szText, DashLine) ;
|
|
}
|
|
|
|
ExtTextOut (hDC, rectUpdate.right, rectUpdate.top,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rectUpdate,
|
|
szText, lstrlen (szText),
|
|
NULL) ;
|
|
|
|
//=============================//
|
|
// Draw Alert Condition //
|
|
//=============================//
|
|
|
|
rectUpdate.left = rectUpdate.right ;
|
|
rectUpdate.right = rectUpdate.left + pAlert->xConditionWidth ;
|
|
|
|
TSPRINTF (szText, szConditionFormat,
|
|
pLine ?
|
|
(pAlertEntry->bOver ? TEXT('>') : TEXT('<')) :
|
|
TEXT(' ')
|
|
) ;
|
|
|
|
ExtTextOut (hDC, rectUpdate.right, rectUpdate.top,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rectUpdate,
|
|
szText, lstrlen (szText),
|
|
NULL) ;
|
|
|
|
//=============================//
|
|
// Draw Trigger Value //
|
|
//=============================//
|
|
|
|
rectUpdate.left = rectUpdate.right ;
|
|
rectUpdate.right = rectUpdate.left + pAlert->xNumberWidth ;
|
|
|
|
if (pLine) {
|
|
eLocalValue = pAlertEntry->eAlertValue ;
|
|
if (eLocalValue < (FLOAT) 0.0) {
|
|
eLocalValue = -eLocalValue ;
|
|
}
|
|
AlertFormatFloat (szText, pAlertEntry->eAlertValue) ;
|
|
} else {
|
|
lstrcpy (szText, DashLine) ;
|
|
}
|
|
|
|
ExtTextOut (hDC, rectUpdate.right, rectUpdate.top,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rectUpdate,
|
|
szText, lstrlen (szText),
|
|
NULL) ;
|
|
|
|
//=============================//
|
|
// Draw Rest //
|
|
//=============================//
|
|
|
|
SetTextAlign (hDC, TA_LEFT) ;
|
|
|
|
rectUpdate.left = rectUpdate.right ;
|
|
rectUpdate.right = 10000 ;
|
|
|
|
if (pLine) {
|
|
TSPRINTF (szText,
|
|
TEXT(" %s, %s, %s, %s, %s"),
|
|
pLine->lnCounterName,
|
|
pAlertEntry->lpszInstance,
|
|
pAlertEntry->lpszParent,
|
|
pLine->lnObjectName,
|
|
pLine->lnSystemName) ;
|
|
} else {
|
|
TSPRINTF (szText,
|
|
TEXT(" %s, , , , %s"),
|
|
pAlertEntry->lpszInstance,
|
|
pAlertEntry->lpszParent) ;
|
|
}
|
|
|
|
ExtTextOut (hDC, rectUpdate.left, rectUpdate.top,
|
|
ETO_OPAQUE,
|
|
&rectUpdate,
|
|
szText, lstrlen (szText),
|
|
NULL) ;
|
|
|
|
// check if we need to bring-up or resize the horiz scrollbar
|
|
if (pAlertEntry->StringWidth == 0) {
|
|
pAlertEntry->StringWidth = TextWidth (hDC, szText) + xScrollWidth +
|
|
rectUpdate.left ;
|
|
}
|
|
|
|
if (pAlertEntry->StringWidth > pAlert->xTextExtent) {
|
|
pAlert->xTextExtent = pAlertEntry->StringWidth ;
|
|
LBSetHorzExtent (pAlert->hAlertListBox, pAlertEntry->StringWidth) ;
|
|
}
|
|
|
|
if (DISelected (lpDI)) {
|
|
preTextColor = SetTextColor (hDC, preTextColor) ;
|
|
preBkColor = SetBkColor (hDC, preBkColor) ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================//
|
|
// Message Handlers //
|
|
//==========================================================================//
|
|
|
|
|
|
void
|
|
static
|
|
OnDrawItem (
|
|
HWND hWnd,
|
|
LPDRAWITEMSTRUCT lpDI
|
|
)
|
|
{
|
|
HFONT hFontPrevious ;
|
|
HDC hDC ;
|
|
PALERT pAlert ;
|
|
PALERTENTRY pAlertEntry ;
|
|
// PLINESTRUCT pLine ;
|
|
int iLBIndex ;
|
|
|
|
hDC = lpDI->hDC ;
|
|
iLBIndex = DIIndex (lpDI) ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
|
|
if (iLBIndex == -1) {
|
|
pAlertEntry = NULL ;
|
|
} else {
|
|
pAlertEntry = (PALERTENTRY) LBData (pAlert->hAlertListBox, iLBIndex) ;
|
|
if (pAlertEntry == (PALERTENTRY) LB_ERR) {
|
|
pAlertEntry = NULL ;
|
|
}
|
|
}
|
|
|
|
//=============================//
|
|
// Draw Legend Item //
|
|
//=============================//
|
|
|
|
if (pAlertEntry) {
|
|
hFontPrevious = SelectFont (hDC, pAlert->hFontItems) ;
|
|
DrawAlertEntry (hWnd, pAlert, pAlertEntry, lpDI, hDC) ;
|
|
SelectFont (hDC, hFontPrevious) ;
|
|
}
|
|
|
|
//=============================//
|
|
// Draw Focus //
|
|
//=============================//
|
|
|
|
if (DIFocus (lpDI))
|
|
DrawFocusRect (hDC, &(lpDI->rcItem)) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
INT_PTR
|
|
static
|
|
OnCtlColor (
|
|
HWND hDlg,
|
|
HDC hDC
|
|
)
|
|
{
|
|
SetTextColor (hDC, crBlack) ;
|
|
// SetBkColor (hDC, crLightGray) ;
|
|
// return ((int) hbLightGray) ;
|
|
SetBkColor (hDC, ColorBtnFace) ;
|
|
return ((INT_PTR) hBrushFace) ;
|
|
}
|
|
|
|
void
|
|
AlertCreateThread (
|
|
PALERT pAlert
|
|
)
|
|
{
|
|
pAlert->hNetAlertThread = CreateThread(NULL, (DWORD)1024L,
|
|
(LPTHREAD_START_ROUTINE)NetAlertHandler,
|
|
NULL, (DWORD)0, &(pAlert->dwNetAlertThreadID)) ;
|
|
|
|
if (!(pAlert->hNetAlertThread)) {
|
|
// CreateThread failure, set its ID to zero
|
|
// so we will not use the thread
|
|
pAlert->dwNetAlertThreadID = 0 ;
|
|
} else {
|
|
SetThreadPriority (pAlert->hNetAlertThread, THREAD_PRIORITY_HIGHEST) ;
|
|
}
|
|
}
|
|
|
|
void
|
|
static
|
|
OnInitDialog (
|
|
HWND hDlg
|
|
)
|
|
{
|
|
HDC hDC ;
|
|
PALERT pAlert ;
|
|
|
|
iUnviewedAlerts = 0 ;
|
|
|
|
pAlert = AllocateAlertData (hDlg) ;
|
|
if (!pAlert)
|
|
return ;
|
|
|
|
pAlert->iStatus = iPMStatusClosed ;
|
|
pAlert->hFontItems = hFontScales ;
|
|
|
|
hDC = GetDC (hDlg) ;
|
|
SelectFont (hDC, pAlert->hFontItems) ;
|
|
|
|
pAlert->yItemHeight = FontHeight (hDC, TRUE) + 2 * AlertItemTopMargin () ;
|
|
|
|
pAlert->xColorWidth = pAlert->yItemHeight ;
|
|
pAlert->xDateWidth = TextWidth (hDC, szDatePrototype) ;
|
|
pAlert->xTimeWidth = TextWidth (hDC, szTimePrototype) ;
|
|
pAlert->xNumberWidth = TextWidth (hDC, szNumberPrototype) ;
|
|
pAlert->xConditionWidth = TextWidth (hDC, szConditionPrototype) ;
|
|
|
|
// no Horz. scroll bar to begin with
|
|
pAlert->xTextExtent = 0 ;
|
|
pAlert->hNetAlertThread = 0;
|
|
#if 0
|
|
pAlert->hNetAlertThread = CreateThread(NULL, (DWORD)1024L,
|
|
(LPTHREAD_START_ROUTINE)NetAlertHandler,
|
|
NULL, (DWORD)0, &(pAlert->dwNetAlertThreadID)) ;
|
|
|
|
if (!(pAlert->hNetAlertThread)) {
|
|
// CreateThread failure, set its ID to zero
|
|
// so we will not use the thread
|
|
pAlert->dwNetAlertThreadID = 0 ;
|
|
} else {
|
|
SetThreadPriority (pAlert->hNetAlertThread, THREAD_PRIORITY_HIGHEST) ;
|
|
}
|
|
#endif
|
|
ReleaseDC (hDlg, hDC) ;
|
|
|
|
hWndAlertLegend = DialogControl (hDlg, IDD_ALERTLEGEND) ;
|
|
UpdateAlertDisplay (hDlg) ;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
static
|
|
OnMeasureItem (
|
|
HWND hWnd,
|
|
LPMEASUREITEMSTRUCT lpMI
|
|
)
|
|
/*
|
|
Note: Since we have an LB_OWNERDRAWFIXED item in the alert
|
|
dialog, we get this message *before* the WM_INITDIALOG
|
|
message. Therefore we can't rely on any of the values
|
|
set in that message handler.
|
|
*/
|
|
{
|
|
HDC hDC ;
|
|
|
|
hDC = GetDC (hWnd) ;
|
|
SelectFont (hDC, hFontScales) ;
|
|
|
|
lpMI->itemHeight = FontHeight (hDC, TRUE) + 2 * AlertItemTopMargin () ;
|
|
|
|
ReleaseDC (hWnd, hDC) ;
|
|
}
|
|
|
|
|
|
void
|
|
static
|
|
OnDeleteItem (
|
|
HDLG hDlg,
|
|
WPARAM wControlID,
|
|
LPDELETEITEMSTRUCT lpDI
|
|
)
|
|
{
|
|
PALERTENTRY pAlertEntry ;
|
|
|
|
pAlertEntry = (PALERTENTRY) lpDI->itemData ;
|
|
|
|
MemoryFree (pAlertEntry->lpszParent) ;
|
|
MemoryFree (pAlertEntry->lpszInstance) ;
|
|
|
|
MemoryFree (pAlertEntry) ;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
static
|
|
OnSize (
|
|
HWND hDlg,
|
|
int xWidth,
|
|
int yHeight
|
|
)
|
|
{
|
|
SizeAlertComponents (hDlg) ;
|
|
}
|
|
|
|
|
|
void
|
|
static
|
|
OnDestroy (
|
|
HWND hWnd
|
|
)
|
|
/*
|
|
Effect: Perform any actions necessary when an AlertDisplay window
|
|
is being destroyed. In particular, free the instance
|
|
data for the log.
|
|
|
|
Since we really only have one log window and one global
|
|
log data structure, we don't free the structure. We do,
|
|
however, delete the objects allocated within the structure.
|
|
*/
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
FreeAlertData (pAlert) ;
|
|
|
|
if (pAlert->dwNetAlertThreadID) {
|
|
CloseHandle (pAlert->hNetAlertThread) ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================//
|
|
// Exported Functions //
|
|
//==========================================================================//
|
|
|
|
|
|
BOOL
|
|
AlertInitializeApplication (void)
|
|
{
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
INT_PTR
|
|
APIENTRY
|
|
AlertDisplayDlgProc (
|
|
HWND hDlg,
|
|
UINT iMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
/*
|
|
Note: This function must be exported in the application's
|
|
linker-definition file, perfmon.def.
|
|
*/
|
|
{
|
|
switch (iMessage) {
|
|
case WM_CTLCOLORDLG:
|
|
case WM_CTLCOLOREDIT:
|
|
case WM_CTLCOLORBTN:
|
|
case WM_CTLCOLORSTATIC:
|
|
return (OnCtlColor (hDlg, (HDC) wParam)) ;
|
|
break ;
|
|
|
|
case WM_DELETEITEM:
|
|
OnDeleteItem (hDlg, wParam, (LPDELETEITEMSTRUCT) lParam) ;
|
|
break ;
|
|
|
|
case WM_DRAWITEM:
|
|
OnDrawItem (hDlg, (LPDRAWITEMSTRUCT) lParam) ;
|
|
break ;
|
|
|
|
case WM_INITDIALOG:
|
|
OnInitDialog (hDlg) ;
|
|
break ;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
DoWindowDrag (hDlg, lParam) ;
|
|
break ;
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
SendMessage (hWndMain, WM_LBUTTONDBLCLK, wParam, lParam) ;
|
|
break ;
|
|
|
|
case WM_MEASUREITEM:
|
|
OnMeasureItem (hDlg, (LPMEASUREITEMSTRUCT) lParam) ;
|
|
break ;
|
|
|
|
case WM_SIZE:
|
|
OnSize (hDlg, LOWORD (lParam), HIWORD (lParam)) ;
|
|
break ;
|
|
|
|
case WM_TIMER:
|
|
AlertTimer (hDlg, FALSE) ;
|
|
break ;
|
|
|
|
case WM_DESTROY:
|
|
OnDestroy (hDlg) ;
|
|
return (FALSE) ;
|
|
break ;
|
|
|
|
default:
|
|
return (FALSE) ;
|
|
} // switch
|
|
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
HWND
|
|
CreateAlertWindow (
|
|
HWND hWndParent
|
|
)
|
|
/*
|
|
Effect: Create the Alert window. This window is a child of
|
|
hWndMain.
|
|
|
|
Note: We dont worry about the size here, as this window
|
|
will be resized whenever the main window is resized.
|
|
|
|
*/
|
|
{
|
|
HWND hWnd ;
|
|
hWnd = CreateDialog (hInstance,
|
|
MAKEINTRESOURCE (idDlgAlertDisplay),
|
|
hWndParent,
|
|
AlertDisplayDlgProc) ;
|
|
|
|
return (hWnd) ;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
UpdateAlertDisplay (
|
|
HWND hWnd
|
|
)
|
|
/*
|
|
Effect: Set the values for the various controls in the Alert
|
|
display.
|
|
|
|
Called By: OnInitDialog, any other routines that change these
|
|
values.
|
|
*/
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
|
|
DialogSetInterval (hWnd, IDD_ALERTINTERVAL, pAlert->iIntervalMSecs) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
AlertInsertLine (
|
|
HWND hWnd,
|
|
PLINE pLine
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
PLINE pLineEquivalent ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
pAlert->bModified = TRUE ;
|
|
|
|
pLineEquivalent = FindEquivalentLine (pLine, pAlert->pLineFirst) ;
|
|
// alert view is not permitted to have duplicate entries
|
|
if (pLineEquivalent) {
|
|
LINESTRUCT tempLine ;
|
|
|
|
tempLine = *pLineEquivalent ;
|
|
|
|
// copy the new alert line attributes
|
|
pLineEquivalent->Visual = pLine->Visual ;
|
|
pLineEquivalent->bAlertOver = pLine->bAlertOver ;
|
|
pLineEquivalent->eAlertValue = pLine->eAlertValue ;
|
|
pLineEquivalent->bEveryTime = pLine->bEveryTime ;
|
|
|
|
pLineEquivalent->lpszAlertProgram = pLine->lpszAlertProgram ;
|
|
pLine->lpszAlertProgram = tempLine.lpszAlertProgram ;
|
|
|
|
pLineEquivalent->hBrush = pLine->hBrush ;
|
|
pLine->hBrush = tempLine.hBrush ;
|
|
|
|
if (PlayingBackLog ()) {
|
|
PlaybackAlert (hWnd, 0) ;
|
|
WindowInvalidate (hWnd) ;
|
|
}
|
|
|
|
return (FALSE) ;
|
|
}
|
|
SystemAdd (&pAlert->pSystemFirst, pLine->lnSystemName, hWnd) ;
|
|
|
|
LineAppend (&pAlert->pLineFirst, pLine) ;
|
|
|
|
LegendAddItem (hWndAlertLegend, pLine) ;
|
|
|
|
if (!bDelayAddAction) {
|
|
SizeAlertComponents (hWndAlert) ;
|
|
LegendSetSelection (hWndAlertLegend,
|
|
LegendNumItems (hWndAlertLegend) - 1) ;
|
|
}
|
|
|
|
if (!bDelayAddAction) {
|
|
if (PlayingBackLog ()) {
|
|
PlaybackAlert (hWnd, 0) ;
|
|
WindowInvalidate (hWnd) ;
|
|
}
|
|
|
|
else if (pAlert->iStatus == iPMStatusClosed)
|
|
SetAlertTimer (pAlert) ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
void
|
|
AlertAddAction ()
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
|
|
SizeAlertComponents (hWndAlert) ;
|
|
LegendSetSelection (hWndAlertLegend,
|
|
LegendNumItems (hWndAlertLegend) - 1) ;
|
|
|
|
if (PlayingBackLog ()) {
|
|
PlaybackAlert (hWndAlert, 0) ;
|
|
WindowInvalidate (hWndAlert) ;
|
|
} else if (pAlert->iStatus == iPMStatusClosed)
|
|
SetAlertTimer (pAlert) ;
|
|
}
|
|
|
|
void
|
|
SizeAlertComponents (
|
|
HWND hDlg
|
|
)
|
|
{
|
|
RECT rectClient ;
|
|
int xWidth, yHeight ;
|
|
int yLegendHeight ;
|
|
int yLegendTextHeight ;
|
|
int yLogHeight ;
|
|
int yLogTextHeight ;
|
|
int yIntervalHeight ;
|
|
int xIntervalTextWidth ;
|
|
int StartYPos ;
|
|
PALERT pAlert = AlertData(hDlg) ;
|
|
|
|
GetClientRect (hDlg, &rectClient) ;
|
|
xWidth = rectClient.right ;
|
|
yHeight = rectClient.bottom ;
|
|
|
|
if (pAlert->bLegendOn) {
|
|
yLegendHeight = LegendHeight (hWndAlertLegend, yHeight) ;
|
|
} else {
|
|
yLegendHeight = 0 ;
|
|
}
|
|
|
|
if (yHeight < 7 * xScrollWidth) {
|
|
// too small, just display the alert logs and hide all other
|
|
// items
|
|
DialogShow (hDlg, IDD_ALERTLEGEND, FALSE) ;
|
|
DialogShow (hDlg, IDD_ALERTLEGENDTEXT, FALSE) ;
|
|
|
|
DialogShow (hDlg, IDD_ALERTINTERVAL, FALSE) ;
|
|
DialogShow (hDlg, IDD_ALERTINTERVALTEXT, FALSE) ;
|
|
|
|
yLogTextHeight = DialogHeight (hDlg, IDD_ALERTLOGTEXT) ;
|
|
|
|
if (yHeight - yLogTextHeight > 3 * xScrollWidth) {
|
|
DialogMove (hDlg, IDD_ALERTLOGTEXT,
|
|
xScrollWidth,
|
|
xScrollWidth / 2,
|
|
NOCHANGE, NOCHANGE) ;
|
|
yLogTextHeight += xScrollWidth / 2 ;
|
|
DialogShow (hDlg, IDD_ALERTLOGTEXT, TRUE) ;
|
|
} else {
|
|
yLogTextHeight = 0 ;
|
|
DialogShow (hDlg, IDD_ALERTLOGTEXT, FALSE) ;
|
|
}
|
|
DialogMove (hDlg, IDD_ALERTLOG,
|
|
xScrollWidth,
|
|
xScrollWidth / 2 + yLogTextHeight,
|
|
xWidth - 2 * xScrollWidth,
|
|
yHeight - xScrollWidth) ;
|
|
} else if (yHeight <= 2 * yLegendHeight + 5 * xScrollWidth) {
|
|
if (pAlert->bLegendOn) {
|
|
yLegendHeight = min (yLegendHeight,
|
|
(yHeight - xScrollWidth) / 2) ;
|
|
} else {
|
|
yLegendHeight = 0 ;
|
|
}
|
|
|
|
|
|
yLogHeight = yHeight - yLegendHeight - xScrollWidth - 2 ;
|
|
|
|
DialogShow (hDlg, IDD_ALERTLEGENDTEXT, FALSE) ;
|
|
DialogShow (hDlg, IDD_ALERTINTERVAL, FALSE) ;
|
|
DialogShow (hDlg, IDD_ALERTINTERVALTEXT, FALSE) ;
|
|
|
|
yLogTextHeight = DialogHeight (hDlg, IDD_ALERTLOGTEXT) ;
|
|
if (yLogHeight - yLogTextHeight > 3 * xScrollWidth) {
|
|
DialogMove (hDlg, IDD_ALERTLOGTEXT,
|
|
xScrollWidth,
|
|
xScrollWidth / 2,
|
|
NOCHANGE, NOCHANGE) ;
|
|
yLogTextHeight += xScrollWidth / 2 ;
|
|
DialogShow (hDlg, IDD_ALERTLOGTEXT, TRUE) ;
|
|
} else {
|
|
yLogTextHeight = 0 ;
|
|
DialogShow (hDlg, IDD_ALERTLOGTEXT, FALSE) ;
|
|
}
|
|
|
|
DialogMove (hDlg, IDD_ALERTLOG,
|
|
xScrollWidth,
|
|
xScrollWidth / 2 + yLogTextHeight,
|
|
xWidth - 2 * xScrollWidth,
|
|
yLogHeight - yLogTextHeight) ;
|
|
|
|
DialogMove (hDlg, IDD_ALERTLEGEND,
|
|
xScrollWidth,
|
|
yLogHeight + xScrollWidth - 2,
|
|
xWidth - 2 * xScrollWidth,
|
|
yLegendHeight) ;
|
|
|
|
DialogShow (hDlg, IDD_ALERTLEGEND, pAlert->bLegendOn ? TRUE : FALSE) ;
|
|
} else {
|
|
if (pAlert->bLegendOn) {
|
|
DialogMove (hDlg, IDD_ALERTLEGEND,
|
|
xScrollWidth, yHeight - xScrollWidth / 2 - yLegendHeight,
|
|
xWidth - 2 * xScrollWidth,
|
|
yLegendHeight) ;
|
|
DialogMove (hDlg, IDD_ALERTLEGENDTEXT,
|
|
xScrollWidth,
|
|
DialogYPos (hDlg, IDD_ALERTLEGEND) - xScrollWidth,
|
|
NOCHANGE, NOCHANGE) ;
|
|
|
|
yLegendTextHeight = DialogYPos (hDlg, IDD_ALERTLEGENDTEXT) ;
|
|
} else {
|
|
yLegendTextHeight = yHeight - xScrollWidth / 2 - yLegendHeight ;
|
|
}
|
|
|
|
yLogTextHeight = DialogHeight (hDlg, IDD_ALERTLOGTEXT) ;
|
|
yIntervalHeight = DialogHeight (hDlg, IDD_ALERTINTERVAL) ;
|
|
yLogHeight = yLegendTextHeight - 4 * xScrollWidth ;
|
|
|
|
if (yLogHeight < 2 * xScrollWidth) {
|
|
yLogHeight = yLegendTextHeight - yLogTextHeight - xScrollWidth ;
|
|
}
|
|
DialogMove (hDlg, IDD_ALERTLOG,
|
|
xScrollWidth,
|
|
yLegendTextHeight - yLogHeight - xScrollWidth / 2,
|
|
xWidth - 2 * xScrollWidth,
|
|
yLogHeight) ;
|
|
DialogMove (hDlg, IDD_ALERTLOGTEXT,
|
|
xScrollWidth,
|
|
yLogTextHeight = DialogYPos (hDlg, IDD_ALERTLOG) - xScrollWidth,
|
|
xWidth - 2 * xScrollWidth, NOCHANGE) ;
|
|
|
|
DialogShow (hDlg, IDD_ALERTLEGEND, pAlert->bLegendOn ? TRUE : FALSE) ;
|
|
DialogShow (hDlg, IDD_ALERTLEGENDTEXT, pAlert->bLegendOn ? TRUE : FALSE) ;
|
|
DialogShow (hDlg, IDD_ALERTLOGTEXT, TRUE) ;
|
|
|
|
|
|
if (yLogTextHeight >= yIntervalHeight + xScrollWidth) {
|
|
StartYPos = (yLogTextHeight - yIntervalHeight) / 2 ;
|
|
xIntervalTextWidth = DialogWidth (hDlg, IDD_ALERTINTERVALTEXT) ;
|
|
DialogMove (hDlg, IDD_ALERTINTERVALTEXT,
|
|
xScrollWidth,
|
|
StartYPos + 1,
|
|
NOCHANGE, NOCHANGE) ;
|
|
DialogMove (hDlg, IDD_ALERTINTERVAL,
|
|
xScrollWidth + xIntervalTextWidth + 4,
|
|
StartYPos,
|
|
NOCHANGE, NOCHANGE) ;
|
|
|
|
DialogShow (hDlg, IDD_ALERTINTERVAL, TRUE) ;
|
|
DialogShow (hDlg, IDD_ALERTINTERVALTEXT, TRUE) ;
|
|
} else {
|
|
DialogShow (hDlg, IDD_ALERTINTERVAL, FALSE) ;
|
|
DialogShow (hDlg, IDD_ALERTINTERVALTEXT, FALSE) ;
|
|
}
|
|
}
|
|
|
|
WindowInvalidate (hDlg) ;
|
|
}
|
|
|
|
|
|
INT
|
|
PlaybackAlert (
|
|
HWND hWndAlert,
|
|
HANDLE hExportFile
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
LOGPOSITION lp ;
|
|
PLOGINDEX pLogIndex ;
|
|
SYSTEMTIME SystemTime ;
|
|
SYSTEMTIME PreviousSystemTime ;
|
|
BOOL bFirstTime = TRUE ;
|
|
INT ErrCode = 0 ;
|
|
int iDisplayTics ;
|
|
DWORD TimeDiff ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
|
|
if (!pAlert->pLineFirst) {
|
|
// nothing to check
|
|
return ErrCode;
|
|
}
|
|
|
|
lp = PlaybackLog.StartIndexPos ;
|
|
iDisplayTics = PlaybackLog.iSelectedTics;
|
|
|
|
if (!hExportFile) {
|
|
LBReset (pAlert->hAlertListBox) ;
|
|
LBSetRedraw (pAlert->hAlertListBox, FALSE) ;
|
|
}
|
|
|
|
while (iDisplayTics) {
|
|
|
|
pLogIndex = IndexFromPosition (&lp) ;
|
|
if (pLogIndex)
|
|
SystemTime = pLogIndex->SystemTime ;
|
|
else
|
|
GetLocalTime (&SystemTime) ;
|
|
|
|
if (!bFirstTime) {
|
|
// check if it is time to do the alert checking
|
|
TimeDiff = (DWORD) SystemTimeDifference (&PreviousSystemTime,
|
|
&SystemTime, TRUE) ;
|
|
if (TimeDiff * 1000 >= pAlert->iIntervalMSecs) {
|
|
PlaybackLines (pAlert->pSystemFirst,
|
|
pAlert->pLineFirst,
|
|
lp.iPosition) ;
|
|
ErrCode = CheckAlerts (hWndAlert,
|
|
pAlert->hAlertListBox,
|
|
&SystemTime,
|
|
pAlert->pLineFirst,
|
|
hExportFile,
|
|
NULL) ;
|
|
if (ErrCode) {
|
|
break ;
|
|
}
|
|
|
|
PreviousSystemTime = SystemTime ;
|
|
}
|
|
} else {
|
|
// setup the data for the first time
|
|
bFirstTime = FALSE ;
|
|
PreviousSystemTime = SystemTime ;
|
|
PlaybackLines (pAlert->pSystemFirst,
|
|
pAlert->pLineFirst,
|
|
lp.iPosition) ;
|
|
}
|
|
|
|
if (!NextIndexPosition (&lp, FALSE))
|
|
break;
|
|
|
|
iDisplayTics-- ;
|
|
}
|
|
|
|
if (!hExportFile) {
|
|
LBSetRedraw (pAlert->hAlertListBox, TRUE) ;
|
|
}
|
|
|
|
return (ErrCode) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
AddAlert (
|
|
HWND hWndParent
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
PLINE pCurrentLine ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
pCurrentLine = CurrentAlertLine (hWndAlert) ;
|
|
|
|
return (AddLine (hWndParent,
|
|
&(pAlert->pSystemFirst),
|
|
&(pAlert->Visual),
|
|
pCurrentLine ? pCurrentLine->lnSystemName : NULL,
|
|
LineTypeAlert)) ;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
EditAlert (
|
|
HWND hWndParent
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
BOOL bOK ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
|
|
bOK = EditLine (hWndParent,
|
|
&(pAlert->pSystemFirst),
|
|
CurrentAlertLine (hWndAlert),
|
|
LineTypeAlert) ;
|
|
|
|
if (bOK && PlayingBackLog()) {
|
|
//re-do the alert using the new condition
|
|
PlaybackAlert (hWndAlert, 0) ;
|
|
WindowInvalidate (hWndAlert) ;
|
|
}
|
|
|
|
return (bOK) ;
|
|
}
|
|
|
|
// RemoveLineFromAlertListBox is called when we are deleting a line
|
|
// while monitoring current activity. We have to clear all the alert
|
|
// entries of this line because we are already doing this when
|
|
// playing back from log. Moreover, we are using the line structure
|
|
// while drawing the item.
|
|
//
|
|
void
|
|
RemoveLineFromAlertListBox (
|
|
PALERT pAlert,
|
|
PLINE pLine
|
|
)
|
|
{
|
|
int iIndex ;
|
|
int iNumOfAlerts ;
|
|
PALERTENTRY pAlertEntry ;
|
|
|
|
iNumOfAlerts = LBNumItems (pAlert->hAlertListBox) ;
|
|
|
|
if (iNumOfAlerts == 0 || iNumOfAlerts == (int) LB_ERR) {
|
|
return ;
|
|
}
|
|
|
|
LBSetRedraw (pAlert->hAlertListBox, FALSE) ;
|
|
|
|
// go thru the listbox from bottom to top
|
|
for (iIndex = iNumOfAlerts - 1; iIndex >= 0; iIndex-- ) {
|
|
pAlertEntry = (PALERTENTRY) LBData (pAlert->hAlertListBox, iIndex) ;
|
|
if (pAlertEntry != (PALERTENTRY) NULL && pAlertEntry) {
|
|
if (pAlertEntry->pLine == pLine) {
|
|
// remove it from the alert listbox.
|
|
LBDelete (pAlert->hAlertListBox, iIndex) ;
|
|
}
|
|
}
|
|
}
|
|
LBSetRedraw (pAlert->hAlertListBox, TRUE) ;
|
|
}
|
|
|
|
BOOL
|
|
AlertDeleteLine (
|
|
HWND hWndAlert,
|
|
PLINE pLine
|
|
)
|
|
/*
|
|
Effect: Delete the line pLine from the alerts associated with
|
|
window hWnd. Return whether the line could be deleted.
|
|
*/
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
pAlert->bModified = TRUE ;
|
|
|
|
LineRemove (&pAlert->pLineFirst, pLine) ;
|
|
LegendDeleteItem (hWndAlertLegend, pLine) ;
|
|
|
|
if (!pAlert->pLineFirst) {
|
|
// no need to collect data
|
|
ClearAlertTimer (pAlert) ;
|
|
|
|
// clear legend
|
|
ClearLegend (hWndAlertLegend) ;
|
|
|
|
// reset visual data
|
|
pAlert->Visual.iColorIndex = 0 ;
|
|
pAlert->Visual.iWidthIndex = 0 ;
|
|
pAlert->Visual.iStyleIndex = 0 ;
|
|
} else {
|
|
BuildValueListForSystems (
|
|
pAlert->pSystemFirst,
|
|
pAlert->pLineFirst) ;
|
|
}
|
|
|
|
if (!PlayingBackLog()) {
|
|
// delete any alert entry for this line
|
|
RemoveLineFromAlertListBox (pAlert, pLine) ;
|
|
}
|
|
|
|
SizeAlertComponents (hWndAlert) ;
|
|
|
|
if (PlayingBackLog ()) {
|
|
if (pAlert->pLineFirst)
|
|
PlaybackAlert (hWndAlert, 0) ;
|
|
else {
|
|
LBReset (pAlert->hAlertListBox) ;
|
|
}
|
|
|
|
WindowInvalidate (hWndAlert) ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ToggleAlertRefresh (
|
|
HWND hWnd
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
|
|
if (pAlert->bManualRefresh)
|
|
SetAlertTimer (pAlert) ;
|
|
else
|
|
ClearAlertTimer (pAlert) ;
|
|
|
|
pAlert->bManualRefresh = !pAlert->bManualRefresh ;
|
|
return (pAlert->bManualRefresh) ;
|
|
}
|
|
|
|
BOOL
|
|
AlertRefresh (
|
|
HWND hWnd
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
|
|
return (pAlert->bManualRefresh) ;
|
|
}
|
|
|
|
|
|
void
|
|
AlertTimer (
|
|
HWND hWnd,
|
|
BOOL bForce
|
|
)
|
|
/*
|
|
Effect: Perform all actions neccesary when an alert timer tick
|
|
or manual refresh occurs. In particular, get the current
|
|
values for each line in the alert window, and compare
|
|
the value against the alert conditions. For each alert
|
|
that may have occured, call SignalAlert.
|
|
|
|
Called By: AlertWndProc, in response to a WM_TIMER message.
|
|
OnCommand, in response to a IDM_REFRESHALERT notification.
|
|
*/
|
|
{
|
|
PALERT pAlert ;
|
|
SYSTEMTIME SystemTime ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
|
|
if (PlayingBackLog ())
|
|
return ;
|
|
|
|
if (bForce || !pAlert->bManualRefresh) {
|
|
UpdateLines (&(pAlert->pSystemFirst), pAlert->pLineFirst) ;
|
|
GetLocalTime (&SystemTime) ;
|
|
CheckAlerts (hWnd,
|
|
pAlert->hAlertListBox,
|
|
&SystemTime,
|
|
pAlert->pLineFirst,
|
|
FALSE,
|
|
pAlert->pSystemFirst) ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
OpenAlertVer1 (
|
|
HANDLE hFile,
|
|
DISKALERT *pDiskAlert,
|
|
PALERT pAlert,
|
|
DWORD dwMinorVersion
|
|
)
|
|
{
|
|
bDelayAddAction = TRUE ;
|
|
pAlert->Visual = pDiskAlert->Visual ;
|
|
pAlert->iIntervalMSecs = pDiskAlert->dwIntervalSecs ;
|
|
if (dwMinorVersion < 3) {
|
|
pAlert->iIntervalMSecs *= 1000 ;
|
|
}
|
|
|
|
pAlert->bNetworkAlert = pDiskAlert->bNetworkAlert ;
|
|
pAlert->bManualRefresh = pDiskAlert->bManualRefresh ;
|
|
pAlert->bSwitchToAlert = pDiskAlert->bSwitchToAlert ;
|
|
|
|
if (dwMinorVersion >= 2) {
|
|
lstrcpy (pAlert->MessageName, pDiskAlert->MessageName) ;
|
|
}
|
|
|
|
pAlert->bLegendOn = TRUE ;
|
|
|
|
if (dwMinorVersion >= 4) {
|
|
if (dwMinorVersion == 4)
|
|
pAlert->bEventLog = pDiskAlert->MiscOptions ;
|
|
else {
|
|
pAlert->bEventLog = pDiskAlert->MiscOptions & 0x01 ;
|
|
pAlert->bLegendOn = pDiskAlert->MiscOptions & 0x02 ;
|
|
}
|
|
} else {
|
|
pAlert->bEventLog = FALSE ;
|
|
|
|
// have to move the file pointer back for old pma file
|
|
FileSeekCurrent (hFile, -((int) (sizeof (pDiskAlert->MiscOptions)))) ;
|
|
}
|
|
|
|
if (pAlert->bNetworkAlert && pAlert->hNetAlertThread == 0) {
|
|
AlertCreateThread (pAlert) ;
|
|
}
|
|
|
|
ReadLines (hFile, pDiskAlert->dwNumLines,
|
|
&(pAlert->pSystemFirst), &(pAlert->pLineFirst), IDM_VIEWALERT) ;
|
|
|
|
bDelayAddAction = FALSE ;
|
|
|
|
AlertAddAction () ;
|
|
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
OpenAlert (
|
|
HWND hWndAlert,
|
|
HANDLE hFile,
|
|
DWORD dwMajorVersion,
|
|
DWORD dwMinorVersion,
|
|
BOOL bAlertFile
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
DISKALERT DiskAlert ;
|
|
BOOL bSuccess = TRUE ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
if (!pAlert) {
|
|
bSuccess = FALSE ;
|
|
goto Exit0 ;
|
|
}
|
|
|
|
if (!FileRead (hFile, &DiskAlert, sizeof (DISKALERT))) {
|
|
bSuccess = FALSE ;
|
|
goto Exit0 ;
|
|
}
|
|
|
|
|
|
switch (dwMajorVersion) {
|
|
case (1):
|
|
|
|
SetHourglassCursor() ;
|
|
|
|
ResetAlertView (hWndAlert) ;
|
|
|
|
OpenAlertVer1 (hFile, &DiskAlert, pAlert, dwMinorVersion) ;
|
|
|
|
// change to alert view if we are opening a
|
|
// alert file
|
|
if (bAlertFile && iPerfmonView != IDM_VIEWALERT) {
|
|
SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWALERT, 0L) ;
|
|
}
|
|
|
|
if (iPerfmonView == IDM_VIEWALERT) {
|
|
SetPerfmonOptions (&DiskAlert.perfmonOptions) ;
|
|
}
|
|
UpdateAlertDisplay (hWndAlert) ;
|
|
|
|
SetArrowCursor() ;
|
|
|
|
break ;
|
|
}
|
|
|
|
Exit0:
|
|
|
|
if (bAlertFile) {
|
|
CloseHandle (hFile) ;
|
|
}
|
|
|
|
return (bSuccess) ;
|
|
}
|
|
|
|
|
|
void
|
|
ResetAlertView (
|
|
HWND hWndAlert
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
if (!pAlert)
|
|
return ;
|
|
|
|
ChangeSaveFileName (NULL, IDM_VIEWALERT) ;
|
|
|
|
if (pAlert->pSystemFirst) {
|
|
ResetAlert (hWndAlert) ;
|
|
}
|
|
}
|
|
|
|
void
|
|
ResetAlert (
|
|
HWND hWndAlert
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
if (!pAlert)
|
|
return ;
|
|
|
|
ClearAlertTimer (pAlert) ;
|
|
|
|
ClearLegend (hWndAlertLegend) ;
|
|
if (pAlert->pLineFirst) {
|
|
FreeLines (pAlert->pLineFirst) ;
|
|
pAlert->pLineFirst = NULL ;
|
|
}
|
|
|
|
if (pAlert->pSystemFirst) {
|
|
FreeSystems (pAlert->pSystemFirst) ;
|
|
pAlert->pSystemFirst = NULL ;
|
|
}
|
|
|
|
pAlert->bModified = FALSE ;
|
|
|
|
// reset visual data
|
|
pAlert->Visual.iColorIndex = 0 ;
|
|
pAlert->Visual.iWidthIndex = 0 ;
|
|
pAlert->Visual.iStyleIndex = 0 ;
|
|
|
|
iUnviewedAlerts = 0 ;
|
|
if (iPerfmonView != IDM_VIEWALERT) {
|
|
StatusUpdateIcons (hWndStatus) ;
|
|
}
|
|
|
|
// remove the horiz. scrollbar
|
|
pAlert->xTextExtent = 0 ;
|
|
LBSetHorzExtent (pAlert->hAlertListBox, pAlert->xTextExtent) ;
|
|
|
|
LBReset (pAlert->hAlertListBox) ;
|
|
SizeAlertComponents (hWndAlert) ;
|
|
|
|
// WindowInvalidate (hWndAlert) ;
|
|
}
|
|
|
|
|
|
void
|
|
ClearAlertDisplay (
|
|
HWND hWnd
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
|
|
pAlert = AlertData (hWnd) ;
|
|
|
|
// remove the horiz. scrollbar
|
|
pAlert->xTextExtent = 0 ;
|
|
LBSetHorzExtent (pAlert->hAlertListBox, pAlert->xTextExtent) ;
|
|
|
|
LBReset (pAlert->hAlertListBox) ;
|
|
}
|
|
|
|
BOOL
|
|
SaveAlert (
|
|
HWND hWndAlert,
|
|
HANDLE hInputFile,
|
|
BOOL bGetFileName
|
|
)
|
|
{
|
|
PALERT pAlert ;
|
|
PLINE pLine ;
|
|
HANDLE hFile = NULL;
|
|
DISKALERT DiskAlert ;
|
|
PERFFILEHEADER FileHeader ;
|
|
TCHAR szFileName [256] ;
|
|
BOOL newFileName = FALSE ;
|
|
|
|
if (hInputFile) {
|
|
// use the input file handle if it is available
|
|
// this is the case for saving workspace data
|
|
hFile = hInputFile ;
|
|
} else {
|
|
if (pAlertFullFileName) {
|
|
lstrcpy (szFileName, pAlertFullFileName) ;
|
|
}
|
|
if (bGetFileName || pAlertFullFileName == NULL) {
|
|
if (!FileGetName (hWndAlert, IDS_ALERTFILE, szFileName)) {
|
|
return (FALSE) ;
|
|
}
|
|
newFileName = TRUE ;
|
|
}
|
|
|
|
hFile = FileHandleCreate (szFileName) ;
|
|
|
|
if (hFile && newFileName) {
|
|
ChangeSaveFileName (szFileName, IDM_VIEWALERT) ;
|
|
} else if (!hFile) {
|
|
DlgErrorBox (hWndAlert, ERR_CANT_OPEN, szFileName) ;
|
|
}
|
|
}
|
|
|
|
if (!hFile || hFile == INVALID_HANDLE_VALUE)
|
|
return (FALSE) ;
|
|
|
|
pAlert = AlertData (hWndAlert) ;
|
|
if (!pAlert) {
|
|
if (!hInputFile) {
|
|
CloseHandle (hFile) ;
|
|
}
|
|
return (FALSE) ;
|
|
}
|
|
|
|
if (!hInputFile) {
|
|
memset (&FileHeader, 0, sizeof (FileHeader)) ;
|
|
lstrcpy (FileHeader.szSignature, szPerfAlertSignature) ;
|
|
FileHeader.dwMajorVersion = AlertMajorVersion ;
|
|
FileHeader.dwMinorVersion = AlertMinorVersion ;
|
|
|
|
if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER))) {
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
DiskAlert.Visual = pAlert->Visual ;
|
|
DiskAlert.dwIntervalSecs = pAlert->iIntervalMSecs ;
|
|
DiskAlert.dwNumLines = NumLines (pAlert->pLineFirst) ;
|
|
|
|
// fill in misc alert options
|
|
DiskAlert.MiscOptions = 0 ;
|
|
if (pAlert->bEventLog)
|
|
DiskAlert.MiscOptions = 0x01 ;
|
|
if (pAlert->bLegendOn)
|
|
DiskAlert.MiscOptions += 0x02 ;
|
|
|
|
// DiskAlert.bEventLog = pAlert->bEventLog ;
|
|
DiskAlert.bNetworkAlert = pAlert->bNetworkAlert ;
|
|
DiskAlert.bSwitchToAlert = pAlert->bSwitchToAlert ;
|
|
DiskAlert.bManualRefresh = pAlert->bManualRefresh ;
|
|
DiskAlert.perfmonOptions = Options ;
|
|
lstrcpy (DiskAlert.MessageName, pAlert->MessageName) ;
|
|
if (!FileWrite (hFile, &DiskAlert, sizeof (DISKALERT))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
for (pLine = pAlert->pLineFirst; pLine; pLine = pLine->pLineNext) {
|
|
if (!WriteLine (pLine, hFile)) {
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
if (!hInputFile) {
|
|
CloseHandle (hFile) ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
|
|
Exit0:
|
|
if (!hInputFile) {
|
|
CloseHandle (hFile) ;
|
|
|
|
// only need to report error if not workspace
|
|
DlgErrorBox (hWndAlert, ERR_SETTING_FILE, szFileName) ;
|
|
}
|
|
return (FALSE) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ExportAlertEntry (
|
|
HANDLE hFile,
|
|
PALERTENTRY pAlertEntry
|
|
)
|
|
{
|
|
TCHAR UnicodeBuff [LongTextLen] ;
|
|
CHAR TempBuff [LongTextLen * 2] ;
|
|
int StringLen ;
|
|
PLINE pLine ;
|
|
|
|
pLine = pAlertEntry->pLine ;
|
|
|
|
// export the alert date-time
|
|
|
|
strcpy (TempBuff, LineEndStr) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
SystemTimeDateString (&(pAlertEntry->SystemTime), UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
|
|
strcat (TempBuff, pDelimiter) ;
|
|
SystemTimeTimeString (&(pAlertEntry->SystemTime), UnicodeBuff, FALSE) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
// export alert value and trigger condition
|
|
|
|
if (pLine) {
|
|
TSPRINTF (UnicodeBuff, szNumberFormat, pAlertEntry->eValue) ;
|
|
ConvertDecimalPoint (UnicodeBuff) ;
|
|
ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
TempBuff[StringLen] = pAlertEntry->bOver ? '>' : '<' ;
|
|
StringLen++ ;
|
|
TSPRINTF (UnicodeBuff, szNumberFormat, pAlertEntry->eAlertValue) ;
|
|
ConvertDecimalPoint (UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
} else {
|
|
strcpy (TempBuff, pDelimiter) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
}
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
// export Counter, Instance, & Parent names
|
|
|
|
if (pLine) {
|
|
ConvertUnicodeStr (TempBuff, pLine->lnCounterName) ;
|
|
} else {
|
|
// system up/down message is stored in lpszInstance.
|
|
ConvertUnicodeStr (TempBuff, pAlertEntry->lpszInstance) ;
|
|
}
|
|
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
if (pLine && !(strempty(pAlertEntry->lpszInstance))) {
|
|
ConvertUnicodeStr (&TempBuff[StringLen], pAlertEntry->lpszInstance) ;
|
|
}
|
|
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
if (pLine && !(strempty(pAlertEntry->lpszParent))) {
|
|
ConvertUnicodeStr (&TempBuff[StringLen], pAlertEntry->lpszParent) ;
|
|
}
|
|
strcat (TempBuff, pDelimiter) ;
|
|
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
// export object, & computer names
|
|
TempBuff[0] = '\0' ;
|
|
if (pLine) {
|
|
ConvertUnicodeStr (TempBuff, pLine->lnObjectName) ;
|
|
}
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
if (pLine) {
|
|
ConvertUnicodeStr (&TempBuff[StringLen], pLine->lnSystemName) ;
|
|
} else {
|
|
// system name for the system that is up or down is in
|
|
// lpszParent.
|
|
ConvertUnicodeStr (&TempBuff[StringLen], pAlertEntry->lpszParent) ;
|
|
}
|
|
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
|
|
Exit0:
|
|
return (FALSE) ;
|
|
}
|
|
|
|
INT
|
|
ExportAlertLine (
|
|
PLINE pLine,
|
|
FLOAT eValue,
|
|
SYSTEMTIME *pSystemTime,
|
|
HANDLE hExportFile
|
|
)
|
|
{
|
|
ALERTENTRY AlertEntry ;
|
|
TCHAR szInstance [256] ;
|
|
TCHAR szParent [256] ;
|
|
INT ErrCode = 0 ;
|
|
|
|
AlertEntry.SystemTime = *pSystemTime ;
|
|
AlertEntry.pLine= pLine ;
|
|
AlertEntry.eValue = eValue ;
|
|
AlertEntry.bOver = pLine->bAlertOver ;
|
|
AlertEntry.eAlertValue = pLine->eAlertValue ;
|
|
|
|
|
|
//=============================//
|
|
// Determine Instance, Parent //
|
|
//=============================//
|
|
|
|
// It's possible that there will be no instance, therefore
|
|
// the lnInstanceName would be NULL.
|
|
|
|
if (pLine->lnObject.NumInstances > 0) {
|
|
// Test for the parent object instance name title index.
|
|
// If there is one, it implies that there will be a valid
|
|
// Parent Object Name and a valid Parent Object Instance Name.
|
|
|
|
// If the Parent Object title index is 0 then
|
|
// just display the instance name.
|
|
|
|
lstrcpy (szInstance, pLine->lnInstanceName) ;
|
|
if (pLine->lnInstanceDef.ParentObjectTitleIndex && pLine->lnPINName) {
|
|
// Get the Parent Object Name.
|
|
lstrcpy (szParent, pLine->lnPINName) ;
|
|
} else {
|
|
szParent[0] = TEXT(' ') ;
|
|
szParent[1] = TEXT('\0') ;
|
|
}
|
|
} else {
|
|
szInstance[0] = TEXT(' ') ;
|
|
szInstance[1] = TEXT('\0') ;
|
|
szParent[0] = TEXT(' ') ;
|
|
szParent[1] = TEXT('\0') ;
|
|
}
|
|
|
|
AlertEntry.lpszInstance = szInstance ;
|
|
AlertEntry.lpszParent = szParent ;
|
|
|
|
if (!ExportAlertEntry (hExportFile, &AlertEntry)) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
}
|
|
|
|
return ErrCode ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ExportAlertLabels (
|
|
HANDLE hFile
|
|
)
|
|
{
|
|
TCHAR UnicodeBuff [LongTextLen] ;
|
|
CHAR TempBuff [LongTextLen * 2] ;
|
|
int StringLen ;
|
|
|
|
strcpy (TempBuff, LineEndStr) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
StringLoad (IDS_EXPORT_DATE, UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
StringLoad (IDS_EXPORT_TIME, UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
StringLoad (IDS_LABELVALUE, UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
StringLoad (IDS_ALERT_TRIGGER, UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
StringLoad (IDS_COUNTERNAME, UnicodeBuff) ;
|
|
ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
StringLoad (IDS_INSTNAME, UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
StringLoad (IDS_PARENT, UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
StringLoad (IDS_OBJNAME, UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
StringLoad (IDS_LABELSYSTEM, UnicodeBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
|
|
Exit0:
|
|
return (FALSE) ;
|
|
}
|
|
|
|
|
|
void
|
|
ExportAlert (void)
|
|
{
|
|
PALERT pAlert ;
|
|
HANDLE hFile = 0 ;
|
|
HWND hWndAlerts ;
|
|
PALERTENTRY pAlertEntry ;
|
|
int AlertTotal ;
|
|
int iIndex ;
|
|
LPTSTR pFileName = NULL ;
|
|
INT ErrCode = 0 ;
|
|
|
|
if (!(pAlert = AlertData (hWndAlert))) {
|
|
return ;
|
|
}
|
|
|
|
// see if there is anything to export..
|
|
if (!(pAlert->pLineFirst)) {
|
|
return ;
|
|
}
|
|
|
|
if (!(hWndAlerts = pAlert->hAlertListBox)) {
|
|
return ;
|
|
}
|
|
|
|
AlertTotal = LBNumItems (hWndAlerts) ;
|
|
if (AlertTotal == LB_ERR || AlertTotal == 0) {
|
|
return ;
|
|
}
|
|
|
|
SetHourglassCursor() ;
|
|
|
|
if (ErrCode = ExportFileOpen (hWndAlert, &hFile, pAlert->iIntervalMSecs, &pFileName)) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
if (!pFileName) {
|
|
// the case when user cancel.
|
|
goto Exit0 ;
|
|
}
|
|
|
|
// export the column labels
|
|
if (!ExportAlertLabels (hFile)) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
goto Exit0 ;
|
|
}
|
|
if (AlertTotal < ALERTLOGMAXITEMS || !PlayingBackLog()) {
|
|
for (iIndex = 0 ; iIndex < AlertTotal ; iIndex++) {
|
|
// get the alert data
|
|
pAlertEntry = (PALERTENTRY) LBData (hWndAlerts, iIndex) ;
|
|
|
|
if (!pAlertEntry || pAlertEntry == (PALERTENTRY)LB_ERR) {
|
|
// skip this entry if we hit an error
|
|
continue ;
|
|
}
|
|
|
|
// export the alert line
|
|
if (!ExportAlertEntry (hFile, pAlertEntry)) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
break ;
|
|
}
|
|
}
|
|
} else {
|
|
// we are playingback log and that the listbox does not
|
|
// contain all the alerts. In this case, have to walk the
|
|
// log file to re-generate all the alerts.
|
|
ErrCode = PlaybackAlert (hWndAlert, hFile) ;
|
|
}
|
|
|
|
Exit0:
|
|
|
|
SetArrowCursor() ;
|
|
|
|
if (hFile) {
|
|
CloseHandle (hFile) ;
|
|
}
|
|
|
|
if (pFileName) {
|
|
if (ErrCode) {
|
|
DlgErrorBox (hWndAlert, ErrCode, pFileName) ;
|
|
}
|
|
|
|
MemoryFree (pFileName) ;
|
|
}
|
|
}
|