Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2401 lines
66 KiB

  1. //==========================================================================//
  2. // Includes //
  3. //==========================================================================//
  4. #include <stdio.h>
  5. #include "perfmon.h"
  6. #include "alert.h" // External declarations for this file
  7. #include "addline.h" // for AddLine
  8. #include "fileutil.h" // for FileRead
  9. #include "legend.h"
  10. #include "line.h"
  11. #include "pmemory.h" // for MemoryXXX (mallloc-type) routines
  12. #include "owndraw.h" // for OwnerDraw macros
  13. #include "perfdata.h" // for UpdateLines
  14. #include "perfmops.h" // for SystemAdd
  15. #include "playback.h" // for PlaybackLines
  16. #include "status.h" // for StatusUpdateAlerts
  17. #include "system.h" // for SystemGet
  18. #include "utils.h"
  19. #include "menuids.h" // for IDM_VIEWALERT
  20. #include "fileopen.h" // for FileGetName
  21. #include "counters.h" // for CounterEntry
  22. #include <lmcons.h>
  23. #include <lmmsg.h>
  24. #include <lmerr.h>
  25. #include "perfmsg.h" // Alert eventlog message id
  26. #define WM_SEND_NETWORK_ALERT (WM_USER + 101)
  27. //==========================================================================//
  28. // Typedefs //
  29. //==========================================================================//
  30. typedef NET_API_STATUS
  31. (*pNetMessageBufferSend) (
  32. IN LPTSTR servername,
  33. IN LPTSTR msgname,
  34. IN LPTSTR fromname,
  35. IN LPBYTE buf,
  36. IN DWORD buflen
  37. );
  38. typedef struct ALERTENTRYSTRUCT {
  39. SYSTEMTIME SystemTime ;
  40. PLINE pLine ;
  41. FLOAT eValue ;
  42. BOOL bOver ;
  43. FLOAT eAlertValue ;
  44. LPTSTR lpszInstance ;
  45. LPTSTR lpszParent ;
  46. INT StringWidth ;
  47. } ALERTENTRY ;
  48. typedef ALERTENTRY *PALERTENTRY ;
  49. static HBRUSH hRedBrush ;
  50. //====
  51. //====
  52. //==========================================================================//
  53. // Constants //
  54. //==========================================================================//
  55. #define szNumberFormat TEXT("%12.3f")
  56. #define szMediumnNumberFormat TEXT("%12.0f")
  57. #define szLargeNumberFormat TEXT("%12.4e")
  58. #define eNumber ((FLOAT) 99999999.999)
  59. #define eLargeNumber ((FLOAT) 999999999999.0)
  60. #define szNumberPrototype TEXT("99999999.999")
  61. #define szConditionFormat TEXT(" %c ")
  62. #define szConditionPrototype TEXT(" > ")
  63. #define szDatePrototype TEXT("12/31/1999 ")
  64. #define szTimePrototype TEXT("12:34:56.9 pm ")
  65. #define ALERTLOGMAXITEMS 1000
  66. // enclose alert within double quotes to make it a single command line
  67. // argument rather then 10 args.
  68. #define szAlertFormat TEXT("\"%s %s %s %c %s %s, %s, %s, %s, %s\"")
  69. //==========================================================================//
  70. // Macros //
  71. //==========================================================================//
  72. #define AlertItemTopMargin() (yBorderHeight)
  73. //==========================================================================//
  74. // Local Functions //
  75. //==========================================================================//
  76. INT ExportAlertLine (PLINE pLine, FLOAT eValue, SYSTEMTIME *pSystemTime, HANDLE hExportFile) ;
  77. void
  78. AlertFormatFloat (
  79. LPTSTR lpValueBuf,
  80. FLOAT eValue
  81. )
  82. {
  83. if (eValue <= eNumber) {
  84. TSPRINTF (lpValueBuf, szNumberFormat, eValue) ;
  85. } else if (eValue <= eLargeNumber) {
  86. TSPRINTF (lpValueBuf, szMediumnNumberFormat, eValue) ;
  87. } else {
  88. TSPRINTF (lpValueBuf, szLargeNumberFormat, eValue) ;
  89. }
  90. ConvertDecimalPoint (lpValueBuf) ;
  91. }
  92. PALERT
  93. AllocateAlertData (
  94. HWND hWndAlert
  95. )
  96. {
  97. PALERT pAlert ;
  98. pAlert = AlertData (hWndAlert) ;
  99. pAlert->hWnd = hWndAlert ;
  100. pAlert->hAlertListBox = DialogControl (hWndAlert, IDD_ALERTLOG) ;
  101. pAlert->iStatus = iPMStatusClosed ;
  102. pAlert->bManualRefresh = FALSE ;
  103. pAlert->bModified = FALSE ;
  104. pAlert->Visual.iColorIndex = 0 ;
  105. pAlert->Visual.iWidthIndex = -1 ;
  106. pAlert->Visual.iStyleIndex = -1 ;
  107. pAlert->iIntervalMSecs = iDefaultAlertIntervalSecs * 1000 ;
  108. pAlert->pSystemFirst = NULL ;
  109. pAlert->pLineFirst = NULL ;
  110. pAlert->MessageName[0] = TEXT('\0') ;
  111. pAlert->bLegendOn = TRUE ;
  112. return (pAlert) ;
  113. }
  114. void FreeAlertData (PALERT pAlert) {}
  115. BOOL
  116. SetAlertTimer (
  117. PALERT pAlert
  118. )
  119. {
  120. if (pAlert->iStatus == iPMStatusCollecting)
  121. KillTimer (pAlert->hWnd, AlertTimerID) ;
  122. pAlert->iStatus = iPMStatusCollecting ;
  123. SetTimer (pAlert->hWnd, AlertTimerID, pAlert->iIntervalMSecs, NULL) ;
  124. return (TRUE) ;
  125. }
  126. BOOL
  127. ClearAlertTimer (
  128. PALERT pAlert
  129. )
  130. {
  131. if (!PlayingBackLog()) {
  132. KillTimer (pAlert->hWnd, AlertTimerID) ;
  133. }
  134. pAlert->iStatus = iPMStatusClosed ;
  135. return (TRUE) ;
  136. }
  137. BOOL
  138. AlertExec (
  139. LPTSTR lpszImageName,
  140. LPTSTR lpszCommandLine
  141. )
  142. /*
  143. Effect: WinExec is considered obsolete. We're supposed to use
  144. CreateProcess, which allows considerably more control.
  145. For perfmon, we only execute a program when an alert
  146. occurs, and we really don't know anything about the
  147. program, so can't really do much. We just set some
  148. defaults and go.
  149. Called By: SignalAlert only.
  150. */
  151. {
  152. STARTUPINFO si ;
  153. PROCESS_INFORMATION pi ;
  154. int StringLen ;
  155. TCHAR TempBuffer [ 5 * FilePathLen ] ;
  156. BOOL RetCode;
  157. DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;
  158. memset (&si, 0, sizeof (STARTUPINFO)) ;
  159. si.cb = sizeof (STARTUPINFO) ;
  160. si.dwFlags = STARTF_USESHOWWINDOW ;
  161. si.wShowWindow = SW_SHOWNOACTIVATE ;
  162. memset (&pi, 0, sizeof (PROCESS_INFORMATION)) ;
  163. lstrcpy (TempBuffer, lpszImageName) ;
  164. StringLen = lstrlen (TempBuffer) ;
  165. // see if this is a CMD or a BAT file
  166. // if it is then create a process with a console window, otherwise
  167. // assume it's an executable file that will create it's own window
  168. // or console if necessary
  169. //
  170. _tcslwr (TempBuffer);
  171. if ((_tcsstr(TempBuffer, TEXT(".bat")) != NULL) ||
  172. (_tcsstr(TempBuffer, TEXT(".cmd")) != NULL)) {
  173. dwCreationFlags |= CREATE_NEW_CONSOLE;
  174. } else {
  175. dwCreationFlags |= DETACHED_PROCESS;
  176. }
  177. // recopy the image name to the temp buffer since it was modified
  178. // (i.e. lowercased) for the previous comparison.
  179. lstrcpy (TempBuffer, lpszImageName) ;
  180. StringLen = lstrlen (TempBuffer) ;
  181. // now add on the alert text preceded with a space char
  182. TempBuffer [StringLen] = TEXT(' ') ;
  183. StringLen++ ;
  184. lstrcpy (&TempBuffer[StringLen], lpszCommandLine) ;
  185. // DETACHED_PROCESS is needed to get rid of the ugly console window
  186. // that SQL guys have been bitching..
  187. RetCode = CreateProcess (NULL, TempBuffer,
  188. NULL, NULL, FALSE,
  189. dwCreationFlags,
  190. // (DWORD) NORMAL_PRIORITY_CLASS | DETACHED_PROCESS,
  191. // (DWORD) NORMAL_PRIORITY_CLASS,
  192. NULL, NULL,
  193. &si, &pi) ;
  194. if (RetCode) {
  195. if (pi.hProcess && pi.hProcess != INVALID_HANDLE_VALUE) {
  196. CloseHandle (pi.hProcess) ;
  197. }
  198. if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE) {
  199. CloseHandle (pi.hThread) ;
  200. }
  201. }
  202. return RetCode ;
  203. }
  204. BOOL
  205. SendNetworkMessage (
  206. LPTSTR pText,
  207. DWORD TextLen,
  208. LPTSTR pMessageName
  209. )
  210. {
  211. NET_API_STATUS NetStatus;
  212. HANDLE dllHandle ;
  213. pNetMessageBufferSend SendFunction ;
  214. //
  215. // Dynamically link to netapi32.dll. If it's not there just return. Return
  216. // TRUE so we won't try to send this alert again.
  217. //
  218. dllHandle = LoadLibrary(TEXT("NetApi32.Dll")) ;
  219. if ( !dllHandle || dllHandle == INVALID_HANDLE_VALUE ) {
  220. return(TRUE) ;
  221. }
  222. //
  223. // Get the address of the service's main entry point. This
  224. // entry point has a well-known name.
  225. //
  226. SendFunction = (pNetMessageBufferSend)GetProcAddress(
  227. dllHandle, "NetMessageBufferSend") ;
  228. if (SendFunction == NULL) {
  229. FreeLibrary (dllHandle) ;
  230. return(TRUE) ;
  231. }
  232. NetStatus = (*SendFunction) (NULL, pMessageName,
  233. NULL, (LPBYTE)pText, TextLen * sizeof(TCHAR)) ;
  234. if (NetStatus != NERR_Success) {
  235. FreeLibrary (dllHandle) ;
  236. return (FALSE) ;
  237. }
  238. FreeLibrary (dllHandle) ;
  239. return (TRUE) ;
  240. }
  241. // this is the child thread used to send out network alert message.
  242. // This thread is created at init time and is destroyed at close time
  243. void
  244. NetAlertHandler (
  245. LPVOID *pDummy
  246. )
  247. {
  248. MSG msg;
  249. while (GetMessage (&msg, NULL, 0, 0)) {
  250. // we are only interested in this message
  251. if (LOWORD(msg.message) == WM_SEND_NETWORK_ALERT) {
  252. SendNetworkMessage ((LPTSTR)(msg.wParam),
  253. lstrlen ((LPTSTR)(msg.wParam)),
  254. (LPTSTR)(msg.lParam)) ;
  255. MemoryFree ((LPTSTR)(msg.wParam)) ;
  256. }
  257. }
  258. }
  259. void
  260. SignalAlert (
  261. HWND hWnd,
  262. HWND hWndAlerts,
  263. PLINE pLine,
  264. FLOAT eValue,
  265. SYSTEMTIME *pSystemTime,
  266. LPTSTR pSystemName,
  267. DWORD dwSystemState
  268. )
  269. /*
  270. Effect: Perform any actions necessary when a given alert line's
  271. condition is true. In particular, add the alert to the
  272. alert log. Also, depending on the user's wishes, signal
  273. a network alert or beep or run a program.
  274. If we are not viewing the alert screen, add one alert to
  275. the unviewed list.
  276. */
  277. {
  278. INT_PTR iIndex ;
  279. PALERT pAlert ;
  280. PALERTENTRY pAlertEntry ;
  281. TCHAR szTime [20] ;
  282. TCHAR szDate [20] ;
  283. TCHAR szInstance [256] ;
  284. TCHAR szParent [256] ;
  285. TCHAR szText [256 * 4] ;
  286. TCHAR eValueBuf [40] ;
  287. TCHAR eAlertValueBuf [40] ;
  288. TCHAR eAlertValueBuf1 [42] ;
  289. FLOAT eLocalValue ;
  290. DWORD TextSize = 0;
  291. LPTSTR lpAlertMsg ;
  292. LPTSTR lpEventLog[7] ;
  293. TCHAR NullBuff [2] ;
  294. NullBuff [0] = NullBuff [1] = TEXT('\0') ;
  295. pAlert = AlertData (hWnd) ;
  296. pAlertEntry = MemoryAllocate (sizeof (ALERTENTRY)) ;
  297. if (!pAlertEntry) {
  298. return ;
  299. }
  300. pAlertEntry->SystemTime = *pSystemTime ;
  301. pAlertEntry->pLine= pLine ;
  302. pAlertEntry->eValue = eValue ;
  303. if (pLine) {
  304. pAlertEntry->bOver = pLine->bAlertOver ;
  305. pAlertEntry->eAlertValue = pLine->eAlertValue ;
  306. }
  307. //=============================//
  308. // Determine Instance, Parent //
  309. //=============================//
  310. // It's possible that there will be no instance, therefore
  311. // the lnInstanceName would be NULL.
  312. if (pLine && pLine->lnObject.NumInstances > 0) {
  313. // Test for the parent object instance name title index.
  314. // If there is one, it implies that there will be a valid
  315. // Parent Object Name and a valid Parent Object Instance Name.
  316. // If the Parent Object title index is 0 then
  317. // just display the instance name.
  318. lstrcpy (szInstance, pLine->lnInstanceName) ;
  319. if (pLine->lnInstanceDef.ParentObjectTitleIndex && pLine->lnPINName) {
  320. // Get the Parent Object Name.
  321. lstrcpy (szParent, pLine->lnPINName) ;
  322. } else {
  323. szParent[0] = TEXT(' ') ;
  324. szParent[1] = TEXT('\0') ;
  325. }
  326. } else {
  327. if (pLine) {
  328. szInstance[0] = TEXT(' ') ;
  329. szInstance[1] = TEXT('\0') ;
  330. szParent[0] = TEXT(' ') ;
  331. szParent[1] = TEXT('\0') ;
  332. } else {
  333. // this is a system down/reconnect alert
  334. StringLoad (
  335. dwSystemState == SYSTEM_DOWN ?
  336. IDS_SYSTEM_DOWN : IDS_SYSTEM_UP,
  337. szInstance) ;
  338. lstrcpy (szParent, pSystemName) ;
  339. }
  340. }
  341. pAlertEntry->lpszInstance = StringAllocate (szInstance) ;
  342. pAlertEntry->lpszParent = StringAllocate (szParent) ;
  343. //=============================//
  344. // Add alert to Alert Log //
  345. //=============================//
  346. if (LBNumItems (hWndAlerts) >= ALERTLOGMAXITEMS)
  347. LBDelete (hWndAlerts, 0) ;
  348. iIndex = LBAdd (hWndAlerts, (LPARAM) pAlertEntry) ;
  349. LBSetSelection (hWndAlerts, iIndex) ;
  350. // no need to check other things if we
  351. // are playing back log
  352. if (PlayingBackLog()) {
  353. return ;
  354. }
  355. //=============================//
  356. // Update Status Line //
  357. //=============================//
  358. if (iPerfmonView != IDM_VIEWALERT) {
  359. if (pAlert->bSwitchToAlert) {
  360. SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWALERT, 0L) ;
  361. } else {
  362. // if iUnviewedAlerts is over 100, we will display "++"
  363. // so, no need to keep updating the icon...
  364. if (iUnviewedAlerts < 100) {
  365. iUnviewedAlerts ++ ;
  366. if (pLine) {
  367. crLastUnviewedAlert = pLine->Visual.crColor ;
  368. }
  369. StatusUpdateIcons (hWndStatus) ;
  370. }
  371. }
  372. }
  373. //===================================//
  374. // Check if we need to do anything //
  375. //===================================//
  376. szText[0] = TEXT('\0') ;
  377. if ((pAlert->bNetworkAlert && pAlert->MessageName[0])
  378. ||
  379. (pLine) &&
  380. (pLine->lpszAlertProgram &&
  381. (pLine->bEveryTime || !pLine->bAlerted))
  382. ||
  383. (pAlert->bEventLog)) {
  384. // format the alert line to be exported
  385. SystemTimeDateString (pSystemTime, szDate) ;
  386. SystemTimeTimeString (pSystemTime, szTime, TRUE) ;
  387. if (pLine) {
  388. AlertFormatFloat (eValueBuf, pAlertEntry->eValue) ;
  389. eLocalValue = pAlertEntry->eAlertValue ;
  390. if (eLocalValue < (FLOAT) 0.0) {
  391. eLocalValue = -eLocalValue ;
  392. }
  393. AlertFormatFloat (eAlertValueBuf, pAlertEntry->eAlertValue) ;
  394. TSPRINTF (szText,
  395. szAlertFormat,
  396. szDate,
  397. szTime,
  398. eValueBuf,
  399. (pLine->bAlertOver ? TEXT('>') : TEXT('<')),
  400. eAlertValueBuf,
  401. pLine->lnCounterName,
  402. szInstance,
  403. szParent,
  404. pLine->lnObjectName,
  405. pLine->lnSystemName) ;
  406. } else {
  407. lstrcpy (eValueBuf, DashLine) ;
  408. lstrcpy (eAlertValueBuf, eValueBuf) ;
  409. TSPRINTF (szText,
  410. szAlertFormat,
  411. szDate,
  412. szTime,
  413. eValueBuf,
  414. TEXT(' '),
  415. eAlertValueBuf,
  416. szInstance, // system up/down message
  417. NullBuff,
  418. NullBuff,
  419. NullBuff,
  420. szParent) ;
  421. }
  422. TextSize = sizeof(TCHAR) * (lstrlen(szText)+1) ;
  423. }
  424. if (szText[0] == TEXT('\0')) {
  425. // nothing to do
  426. return ;
  427. }
  428. //=============================//
  429. // Network Alert? //
  430. //=============================//
  431. SetHourglassCursor() ;
  432. if (pAlert->bNetworkAlert && pAlert->MessageName[0]) {
  433. if (pAlert->dwNetAlertThreadID) {
  434. // use thread to send the network alert.
  435. // the memory will be released by the child thread when done
  436. lpAlertMsg =
  437. (LPTSTR) MemoryAllocate (TextSize) ;
  438. if (lpAlertMsg) {
  439. lstrcpy (lpAlertMsg, szText) ;
  440. PostThreadMessage (pAlert->dwNetAlertThreadID,
  441. WM_SEND_NETWORK_ALERT,
  442. (WPARAM)lpAlertMsg,
  443. (LPARAM)pAlert->MessageName) ;
  444. }
  445. } else {
  446. // no thread available, use the slow way to send the network alert
  447. SendNetworkMessage (szText,
  448. (DWORD) lstrlen(szText),
  449. pAlert->MessageName) ;
  450. }
  451. }
  452. //=============================//
  453. // Run Program? //
  454. //=============================//
  455. if (pLine &&
  456. pLine->lpszAlertProgram &&
  457. (pLine->bEveryTime || !pLine->bAlerted)) {
  458. AlertExec (pLine->lpszAlertProgram, szText) ;
  459. pLine->bAlerted = TRUE ;
  460. }
  461. //===================================//
  462. // Log event to Application Log? //
  463. //===================================//
  464. if (pAlert->bEventLog) {
  465. if (hEventLog) {
  466. if (pLine) {
  467. lpEventLog[0] = pLine->lnSystemName ;
  468. lpEventLog[1] = pLine->lnObjectName ;
  469. lpEventLog[2] = pLine->lnCounterName ;
  470. lpEventLog[3] = szInstance ;
  471. lpEventLog[4] = szParent ;
  472. lpEventLog[5] = eValueBuf ;
  473. eAlertValueBuf1[0] = pLine->bAlertOver ? TEXT('>') : TEXT('<') ;
  474. eAlertValueBuf1[1] = TEXT(' ') ;
  475. lstrcpy (&eAlertValueBuf1[2], eAlertValueBuf) ;
  476. lpEventLog[6] = eAlertValueBuf1 ;
  477. } else {
  478. lpEventLog[0] = szParent ;
  479. lpEventLog[1] = szInstance ;
  480. }
  481. ReportEvent (hEventLog,
  482. (WORD)EVENTLOG_INFORMATION_TYPE,
  483. (WORD)0,
  484. (DWORD)(pLine ? MSG_ALERT_OCCURRED : MSG_ALERT_SYSTEM),
  485. (PSID)NULL,
  486. (WORD)(pLine ? 7 : 2),
  487. (DWORD)TextSize,
  488. (LPCTSTR *)lpEventLog,
  489. (LPVOID)(szText)) ;
  490. }
  491. }
  492. SetArrowCursor() ;
  493. }
  494. BOOL
  495. AlertCondition (
  496. PLINE pLine,
  497. FLOAT eValue
  498. )
  499. /*
  500. Effect: Return whether the alert test passed for line pLine,
  501. with current data value eValue.
  502. Internals: Don't *ever* say (bFoo == bBar), as non-FALSE values
  503. could be represented by any nonzero number. Use
  504. BoolEqual or equivalent.
  505. */
  506. {
  507. BOOL bOver ;
  508. bOver = eValue > pLine->eAlertValue ;
  509. return (BoolEqual (bOver, pLine->bAlertOver)) ;
  510. }
  511. INT
  512. static
  513. CheckAlerts (
  514. HWND hWnd,
  515. HWND hWndAlerts,
  516. SYSTEMTIME *pSystemTime,
  517. PLINE pLineFirst,
  518. HANDLE hExportFile,
  519. PPERFSYSTEM pSystemFirst
  520. )
  521. {
  522. FLOAT eValue ;
  523. PLINE pLine ;
  524. BOOL bAnyAlerts ;
  525. INT ErrCode = 0 ;
  526. PPERFSYSTEM pSystem ;
  527. bAnyAlerts = FALSE ;
  528. if (!PlayingBackLog()) {
  529. LBSetRedraw (hWndAlerts, FALSE) ;
  530. // check for system up/down
  531. for (pSystem = pSystemFirst ;
  532. pSystem ;
  533. pSystem = pSystem->pSystemNext) {
  534. if (pSystem->dwSystemState == SYSTEM_DOWN) {
  535. pSystem->dwSystemState = SYSTEM_DOWN_RPT ;
  536. SignalAlert (hWnd,
  537. hWndAlerts,
  538. NULL,
  539. (FLOAT) 0.0,
  540. pSystemTime,
  541. pSystem->sysName,
  542. SYSTEM_DOWN) ;
  543. } else if (pSystem->dwSystemState == SYSTEM_RECONNECT) {
  544. pSystem->dwSystemState = SYSTEM_RECONNECT_RPT ;
  545. SignalAlert (hWnd,
  546. hWndAlerts,
  547. NULL,
  548. (FLOAT) 0.0,
  549. pSystemTime,
  550. pSystem->sysName,
  551. SYSTEM_RECONNECT) ;
  552. }
  553. }
  554. }
  555. for (pLine = pLineFirst ;
  556. pLine ;
  557. pLine = pLine->pLineNext) {
  558. if (pLine->bFirstTime) {
  559. // skip until we have collect enough samples for the first data
  560. continue ;
  561. }
  562. // Get the new value for this line.
  563. eValue = CounterEntry (pLine) ;
  564. if (AlertCondition (pLine, eValue)) {
  565. bAnyAlerts = TRUE ;
  566. // the case that hExportFile is !NULL is when playingback log and that the
  567. // listbox is overflowed with alert. In this case, we have to
  568. // walk the log file again to re-generate all the alerts.
  569. if (hExportFile) {
  570. ErrCode = ExportAlertLine (pLine, eValue, pSystemTime, hExportFile) ;
  571. if (ErrCode) {
  572. break ;
  573. }
  574. } else {
  575. SignalAlert (hWnd,
  576. hWndAlerts,
  577. pLine,
  578. eValue,
  579. pSystemTime,
  580. NULL,
  581. 0) ;
  582. }
  583. }
  584. }
  585. if (!PlayingBackLog()) {
  586. LBSetRedraw (hWndAlerts, TRUE) ;
  587. }
  588. return (ErrCode) ;
  589. }
  590. void
  591. DrawAlertEntry (
  592. HWND hWnd,
  593. PALERT pAlert,
  594. PALERTENTRY pAlertEntry,
  595. LPDRAWITEMSTRUCT lpDI,
  596. HDC hDC
  597. )
  598. {
  599. PLINE pLine ;
  600. RECT rectUpdate ;
  601. TCHAR szTime [20] ;
  602. TCHAR szDate [20] ;
  603. TCHAR szText [256] ;
  604. HBRUSH hBrushPrevious ;
  605. FLOAT eLocalValue ;
  606. COLORREF preBkColor = 0;
  607. COLORREF preTextColor = 0;
  608. pLine = pAlertEntry->pLine ;
  609. SystemTimeDateString (&(pAlertEntry->SystemTime), szDate) ;
  610. SystemTimeTimeString (&(pAlertEntry->SystemTime), szTime, TRUE) ;
  611. if (DISelected (lpDI)) {
  612. preTextColor = SetTextColor (hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)) ;
  613. preBkColor = SetBkColor (hDC, GetSysColor (COLOR_HIGHLIGHT)) ;
  614. }
  615. //=============================//
  616. // Draw Color Dot //
  617. //=============================//
  618. rectUpdate.left = 0 ;
  619. rectUpdate.top = lpDI->rcItem.top ;
  620. rectUpdate.right = pAlert->xColorWidth ;
  621. rectUpdate.bottom = lpDI->rcItem.bottom ;
  622. ExtTextOut (hDC, rectUpdate.left, rectUpdate.top,
  623. ETO_CLIPPED | ETO_OPAQUE,
  624. &rectUpdate,
  625. NULL, 0,
  626. NULL) ;
  627. if (pLine) {
  628. hBrushPrevious = SelectBrush (hDC, pLine->hBrush) ;
  629. } else {
  630. if (hRedBrush == NULL) {
  631. hRedBrush = CreateSolidBrush (RGB (0xff, 0x00, 0x00)) ;
  632. }
  633. hBrushPrevious = SelectBrush (hDC, hRedBrush) ;
  634. }
  635. Ellipse (hDC,
  636. rectUpdate.left + 2,
  637. rectUpdate.top + 2,
  638. rectUpdate.right - 2,
  639. rectUpdate.bottom - 2) ;
  640. SelectBrush (hDC, hBrushPrevious) ;
  641. //=============================//
  642. // Draw Date //
  643. //=============================//
  644. rectUpdate.left = rectUpdate.right ;
  645. rectUpdate.right = rectUpdate.left + pAlert->xDateWidth ;
  646. ExtTextOut (hDC, rectUpdate.left, rectUpdate.top,
  647. ETO_CLIPPED | ETO_OPAQUE,
  648. &rectUpdate,
  649. szDate, lstrlen (szDate),
  650. NULL) ;
  651. //=============================//
  652. // Draw Time //
  653. //=============================//
  654. rectUpdate.left = rectUpdate.right ;
  655. rectUpdate.right = rectUpdate.left + pAlert->xTimeWidth ;
  656. ExtTextOut (hDC, rectUpdate.left, rectUpdate.top,
  657. ETO_CLIPPED | ETO_OPAQUE,
  658. &rectUpdate,
  659. szTime, lstrlen (szTime),
  660. NULL) ;
  661. //=============================//
  662. // Draw Alert Value //
  663. //=============================//
  664. SetTextAlign (hDC, TA_RIGHT) ;
  665. rectUpdate.left = rectUpdate.right ;
  666. rectUpdate.right = rectUpdate.left + pAlert->xNumberWidth ;
  667. if (pLine) {
  668. AlertFormatFloat (szText, pAlertEntry->eValue) ;
  669. } else {
  670. lstrcpy (szText, DashLine) ;
  671. }
  672. ExtTextOut (hDC, rectUpdate.right, rectUpdate.top,
  673. ETO_CLIPPED | ETO_OPAQUE,
  674. &rectUpdate,
  675. szText, lstrlen (szText),
  676. NULL) ;
  677. //=============================//
  678. // Draw Alert Condition //
  679. //=============================//
  680. rectUpdate.left = rectUpdate.right ;
  681. rectUpdate.right = rectUpdate.left + pAlert->xConditionWidth ;
  682. TSPRINTF (szText, szConditionFormat,
  683. pLine ?
  684. (pAlertEntry->bOver ? TEXT('>') : TEXT('<')) :
  685. TEXT(' ')
  686. ) ;
  687. ExtTextOut (hDC, rectUpdate.right, rectUpdate.top,
  688. ETO_CLIPPED | ETO_OPAQUE,
  689. &rectUpdate,
  690. szText, lstrlen (szText),
  691. NULL) ;
  692. //=============================//
  693. // Draw Trigger Value //
  694. //=============================//
  695. rectUpdate.left = rectUpdate.right ;
  696. rectUpdate.right = rectUpdate.left + pAlert->xNumberWidth ;
  697. if (pLine) {
  698. eLocalValue = pAlertEntry->eAlertValue ;
  699. if (eLocalValue < (FLOAT) 0.0) {
  700. eLocalValue = -eLocalValue ;
  701. }
  702. AlertFormatFloat (szText, pAlertEntry->eAlertValue) ;
  703. } else {
  704. lstrcpy (szText, DashLine) ;
  705. }
  706. ExtTextOut (hDC, rectUpdate.right, rectUpdate.top,
  707. ETO_CLIPPED | ETO_OPAQUE,
  708. &rectUpdate,
  709. szText, lstrlen (szText),
  710. NULL) ;
  711. //=============================//
  712. // Draw Rest //
  713. //=============================//
  714. SetTextAlign (hDC, TA_LEFT) ;
  715. rectUpdate.left = rectUpdate.right ;
  716. rectUpdate.right = 10000 ;
  717. if (pLine) {
  718. TSPRINTF (szText,
  719. TEXT(" %s, %s, %s, %s, %s"),
  720. pLine->lnCounterName,
  721. pAlertEntry->lpszInstance,
  722. pAlertEntry->lpszParent,
  723. pLine->lnObjectName,
  724. pLine->lnSystemName) ;
  725. } else {
  726. TSPRINTF (szText,
  727. TEXT(" %s, , , , %s"),
  728. pAlertEntry->lpszInstance,
  729. pAlertEntry->lpszParent) ;
  730. }
  731. ExtTextOut (hDC, rectUpdate.left, rectUpdate.top,
  732. ETO_OPAQUE,
  733. &rectUpdate,
  734. szText, lstrlen (szText),
  735. NULL) ;
  736. // check if we need to bring-up or resize the horiz scrollbar
  737. if (pAlertEntry->StringWidth == 0) {
  738. pAlertEntry->StringWidth = TextWidth (hDC, szText) + xScrollWidth +
  739. rectUpdate.left ;
  740. }
  741. if (pAlertEntry->StringWidth > pAlert->xTextExtent) {
  742. pAlert->xTextExtent = pAlertEntry->StringWidth ;
  743. LBSetHorzExtent (pAlert->hAlertListBox, pAlertEntry->StringWidth) ;
  744. }
  745. if (DISelected (lpDI)) {
  746. preTextColor = SetTextColor (hDC, preTextColor) ;
  747. preBkColor = SetBkColor (hDC, preBkColor) ;
  748. }
  749. }
  750. //==========================================================================//
  751. // Message Handlers //
  752. //==========================================================================//
  753. void
  754. static
  755. OnDrawItem (
  756. HWND hWnd,
  757. LPDRAWITEMSTRUCT lpDI
  758. )
  759. {
  760. HFONT hFontPrevious ;
  761. HDC hDC ;
  762. PALERT pAlert ;
  763. PALERTENTRY pAlertEntry ;
  764. // PLINESTRUCT pLine ;
  765. int iLBIndex ;
  766. hDC = lpDI->hDC ;
  767. iLBIndex = DIIndex (lpDI) ;
  768. pAlert = AlertData (hWnd) ;
  769. if (iLBIndex == -1) {
  770. pAlertEntry = NULL ;
  771. } else {
  772. pAlertEntry = (PALERTENTRY) LBData (pAlert->hAlertListBox, iLBIndex) ;
  773. if (pAlertEntry == (PALERTENTRY) LB_ERR) {
  774. pAlertEntry = NULL ;
  775. }
  776. }
  777. //=============================//
  778. // Draw Legend Item //
  779. //=============================//
  780. if (pAlertEntry) {
  781. hFontPrevious = SelectFont (hDC, pAlert->hFontItems) ;
  782. DrawAlertEntry (hWnd, pAlert, pAlertEntry, lpDI, hDC) ;
  783. SelectFont (hDC, hFontPrevious) ;
  784. }
  785. //=============================//
  786. // Draw Focus //
  787. //=============================//
  788. if (DIFocus (lpDI))
  789. DrawFocusRect (hDC, &(lpDI->rcItem)) ;
  790. }
  791. INT_PTR
  792. static
  793. OnCtlColor (
  794. HWND hDlg,
  795. HDC hDC
  796. )
  797. {
  798. SetTextColor (hDC, crBlack) ;
  799. // SetBkColor (hDC, crLightGray) ;
  800. // return ((int) hbLightGray) ;
  801. SetBkColor (hDC, ColorBtnFace) ;
  802. return ((INT_PTR) hBrushFace) ;
  803. }
  804. void
  805. AlertCreateThread (
  806. PALERT pAlert
  807. )
  808. {
  809. pAlert->hNetAlertThread = CreateThread(NULL, (DWORD)1024L,
  810. (LPTHREAD_START_ROUTINE)NetAlertHandler,
  811. NULL, (DWORD)0, &(pAlert->dwNetAlertThreadID)) ;
  812. if (!(pAlert->hNetAlertThread)) {
  813. // CreateThread failure, set its ID to zero
  814. // so we will not use the thread
  815. pAlert->dwNetAlertThreadID = 0 ;
  816. } else {
  817. SetThreadPriority (pAlert->hNetAlertThread, THREAD_PRIORITY_HIGHEST) ;
  818. }
  819. }
  820. void
  821. static
  822. OnInitDialog (
  823. HWND hDlg
  824. )
  825. {
  826. HDC hDC ;
  827. PALERT pAlert ;
  828. iUnviewedAlerts = 0 ;
  829. pAlert = AllocateAlertData (hDlg) ;
  830. if (!pAlert)
  831. return ;
  832. pAlert->iStatus = iPMStatusClosed ;
  833. pAlert->hFontItems = hFontScales ;
  834. hDC = GetDC (hDlg) ;
  835. SelectFont (hDC, pAlert->hFontItems) ;
  836. pAlert->yItemHeight = FontHeight (hDC, TRUE) + 2 * AlertItemTopMargin () ;
  837. pAlert->xColorWidth = pAlert->yItemHeight ;
  838. pAlert->xDateWidth = TextWidth (hDC, szDatePrototype) ;
  839. pAlert->xTimeWidth = TextWidth (hDC, szTimePrototype) ;
  840. pAlert->xNumberWidth = TextWidth (hDC, szNumberPrototype) ;
  841. pAlert->xConditionWidth = TextWidth (hDC, szConditionPrototype) ;
  842. // no Horz. scroll bar to begin with
  843. pAlert->xTextExtent = 0 ;
  844. pAlert->hNetAlertThread = 0;
  845. #if 0
  846. pAlert->hNetAlertThread = CreateThread(NULL, (DWORD)1024L,
  847. (LPTHREAD_START_ROUTINE)NetAlertHandler,
  848. NULL, (DWORD)0, &(pAlert->dwNetAlertThreadID)) ;
  849. if (!(pAlert->hNetAlertThread)) {
  850. // CreateThread failure, set its ID to zero
  851. // so we will not use the thread
  852. pAlert->dwNetAlertThreadID = 0 ;
  853. } else {
  854. SetThreadPriority (pAlert->hNetAlertThread, THREAD_PRIORITY_HIGHEST) ;
  855. }
  856. #endif
  857. ReleaseDC (hDlg, hDC) ;
  858. hWndAlertLegend = DialogControl (hDlg, IDD_ALERTLEGEND) ;
  859. UpdateAlertDisplay (hDlg) ;
  860. }
  861. void
  862. static
  863. OnMeasureItem (
  864. HWND hWnd,
  865. LPMEASUREITEMSTRUCT lpMI
  866. )
  867. /*
  868. Note: Since we have an LB_OWNERDRAWFIXED item in the alert
  869. dialog, we get this message *before* the WM_INITDIALOG
  870. message. Therefore we can't rely on any of the values
  871. set in that message handler.
  872. */
  873. {
  874. HDC hDC ;
  875. hDC = GetDC (hWnd) ;
  876. SelectFont (hDC, hFontScales) ;
  877. lpMI->itemHeight = FontHeight (hDC, TRUE) + 2 * AlertItemTopMargin () ;
  878. ReleaseDC (hWnd, hDC) ;
  879. }
  880. void
  881. static
  882. OnDeleteItem (
  883. HDLG hDlg,
  884. WPARAM wControlID,
  885. LPDELETEITEMSTRUCT lpDI
  886. )
  887. {
  888. PALERTENTRY pAlertEntry ;
  889. pAlertEntry = (PALERTENTRY) lpDI->itemData ;
  890. MemoryFree (pAlertEntry->lpszParent) ;
  891. MemoryFree (pAlertEntry->lpszInstance) ;
  892. MemoryFree (pAlertEntry) ;
  893. }
  894. void
  895. static
  896. OnSize (
  897. HWND hDlg,
  898. int xWidth,
  899. int yHeight
  900. )
  901. {
  902. SizeAlertComponents (hDlg) ;
  903. }
  904. void
  905. static
  906. OnDestroy (
  907. HWND hWnd
  908. )
  909. /*
  910. Effect: Perform any actions necessary when an AlertDisplay window
  911. is being destroyed. In particular, free the instance
  912. data for the log.
  913. Since we really only have one log window and one global
  914. log data structure, we don't free the structure. We do,
  915. however, delete the objects allocated within the structure.
  916. */
  917. {
  918. PALERT pAlert ;
  919. pAlert = AlertData (hWnd) ;
  920. FreeAlertData (pAlert) ;
  921. if (pAlert->dwNetAlertThreadID) {
  922. CloseHandle (pAlert->hNetAlertThread) ;
  923. }
  924. }
  925. //==========================================================================//
  926. // Exported Functions //
  927. //==========================================================================//
  928. BOOL
  929. AlertInitializeApplication (void)
  930. {
  931. return (TRUE) ;
  932. }
  933. INT_PTR
  934. APIENTRY
  935. AlertDisplayDlgProc (
  936. HWND hDlg,
  937. UINT iMessage,
  938. WPARAM wParam,
  939. LPARAM lParam
  940. )
  941. /*
  942. Note: This function must be exported in the application's
  943. linker-definition file, perfmon.def.
  944. */
  945. {
  946. switch (iMessage) {
  947. case WM_CTLCOLORDLG:
  948. case WM_CTLCOLOREDIT:
  949. case WM_CTLCOLORBTN:
  950. case WM_CTLCOLORSTATIC:
  951. return (OnCtlColor (hDlg, (HDC) wParam)) ;
  952. break ;
  953. case WM_DELETEITEM:
  954. OnDeleteItem (hDlg, wParam, (LPDELETEITEMSTRUCT) lParam) ;
  955. break ;
  956. case WM_DRAWITEM:
  957. OnDrawItem (hDlg, (LPDRAWITEMSTRUCT) lParam) ;
  958. break ;
  959. case WM_INITDIALOG:
  960. OnInitDialog (hDlg) ;
  961. break ;
  962. case WM_LBUTTONDOWN:
  963. DoWindowDrag (hDlg, lParam) ;
  964. break ;
  965. case WM_LBUTTONDBLCLK:
  966. SendMessage (hWndMain, WM_LBUTTONDBLCLK, wParam, lParam) ;
  967. break ;
  968. case WM_MEASUREITEM:
  969. OnMeasureItem (hDlg, (LPMEASUREITEMSTRUCT) lParam) ;
  970. break ;
  971. case WM_SIZE:
  972. OnSize (hDlg, LOWORD (lParam), HIWORD (lParam)) ;
  973. break ;
  974. case WM_TIMER:
  975. AlertTimer (hDlg, FALSE) ;
  976. break ;
  977. case WM_DESTROY:
  978. OnDestroy (hDlg) ;
  979. return (FALSE) ;
  980. break ;
  981. default:
  982. return (FALSE) ;
  983. } // switch
  984. return (TRUE) ;
  985. }
  986. HWND
  987. CreateAlertWindow (
  988. HWND hWndParent
  989. )
  990. /*
  991. Effect: Create the Alert window. This window is a child of
  992. hWndMain.
  993. Note: We dont worry about the size here, as this window
  994. will be resized whenever the main window is resized.
  995. */
  996. {
  997. HWND hWnd ;
  998. hWnd = CreateDialog (hInstance,
  999. MAKEINTRESOURCE (idDlgAlertDisplay),
  1000. hWndParent,
  1001. AlertDisplayDlgProc) ;
  1002. return (hWnd) ;
  1003. }
  1004. void
  1005. UpdateAlertDisplay (
  1006. HWND hWnd
  1007. )
  1008. /*
  1009. Effect: Set the values for the various controls in the Alert
  1010. display.
  1011. Called By: OnInitDialog, any other routines that change these
  1012. values.
  1013. */
  1014. {
  1015. PALERT pAlert ;
  1016. pAlert = AlertData (hWnd) ;
  1017. DialogSetInterval (hWnd, IDD_ALERTINTERVAL, pAlert->iIntervalMSecs) ;
  1018. }
  1019. BOOL
  1020. AlertInsertLine (
  1021. HWND hWnd,
  1022. PLINE pLine
  1023. )
  1024. {
  1025. PALERT pAlert ;
  1026. PLINE pLineEquivalent ;
  1027. pAlert = AlertData (hWnd) ;
  1028. pAlert->bModified = TRUE ;
  1029. pLineEquivalent = FindEquivalentLine (pLine, pAlert->pLineFirst) ;
  1030. // alert view is not permitted to have duplicate entries
  1031. if (pLineEquivalent) {
  1032. LINESTRUCT tempLine ;
  1033. tempLine = *pLineEquivalent ;
  1034. // copy the new alert line attributes
  1035. pLineEquivalent->Visual = pLine->Visual ;
  1036. pLineEquivalent->bAlertOver = pLine->bAlertOver ;
  1037. pLineEquivalent->eAlertValue = pLine->eAlertValue ;
  1038. pLineEquivalent->bEveryTime = pLine->bEveryTime ;
  1039. pLineEquivalent->lpszAlertProgram = pLine->lpszAlertProgram ;
  1040. pLine->lpszAlertProgram = tempLine.lpszAlertProgram ;
  1041. pLineEquivalent->hBrush = pLine->hBrush ;
  1042. pLine->hBrush = tempLine.hBrush ;
  1043. if (PlayingBackLog ()) {
  1044. PlaybackAlert (hWnd, 0) ;
  1045. WindowInvalidate (hWnd) ;
  1046. }
  1047. return (FALSE) ;
  1048. }
  1049. SystemAdd (&pAlert->pSystemFirst, pLine->lnSystemName, hWnd) ;
  1050. LineAppend (&pAlert->pLineFirst, pLine) ;
  1051. LegendAddItem (hWndAlertLegend, pLine) ;
  1052. if (!bDelayAddAction) {
  1053. SizeAlertComponents (hWndAlert) ;
  1054. LegendSetSelection (hWndAlertLegend,
  1055. LegendNumItems (hWndAlertLegend) - 1) ;
  1056. }
  1057. if (!bDelayAddAction) {
  1058. if (PlayingBackLog ()) {
  1059. PlaybackAlert (hWnd, 0) ;
  1060. WindowInvalidate (hWnd) ;
  1061. }
  1062. else if (pAlert->iStatus == iPMStatusClosed)
  1063. SetAlertTimer (pAlert) ;
  1064. }
  1065. return (TRUE) ;
  1066. }
  1067. void
  1068. AlertAddAction ()
  1069. {
  1070. PALERT pAlert ;
  1071. pAlert = AlertData (hWndAlert) ;
  1072. SizeAlertComponents (hWndAlert) ;
  1073. LegendSetSelection (hWndAlertLegend,
  1074. LegendNumItems (hWndAlertLegend) - 1) ;
  1075. if (PlayingBackLog ()) {
  1076. PlaybackAlert (hWndAlert, 0) ;
  1077. WindowInvalidate (hWndAlert) ;
  1078. } else if (pAlert->iStatus == iPMStatusClosed)
  1079. SetAlertTimer (pAlert) ;
  1080. }
  1081. void
  1082. SizeAlertComponents (
  1083. HWND hDlg
  1084. )
  1085. {
  1086. RECT rectClient ;
  1087. int xWidth, yHeight ;
  1088. int yLegendHeight ;
  1089. int yLegendTextHeight ;
  1090. int yLogHeight ;
  1091. int yLogTextHeight ;
  1092. int yIntervalHeight ;
  1093. int xIntervalTextWidth ;
  1094. int StartYPos ;
  1095. PALERT pAlert = AlertData(hDlg) ;
  1096. GetClientRect (hDlg, &rectClient) ;
  1097. xWidth = rectClient.right ;
  1098. yHeight = rectClient.bottom ;
  1099. if (pAlert->bLegendOn) {
  1100. yLegendHeight = LegendHeight (hWndAlertLegend, yHeight) ;
  1101. } else {
  1102. yLegendHeight = 0 ;
  1103. }
  1104. if (yHeight < 7 * xScrollWidth) {
  1105. // too small, just display the alert logs and hide all other
  1106. // items
  1107. DialogShow (hDlg, IDD_ALERTLEGEND, FALSE) ;
  1108. DialogShow (hDlg, IDD_ALERTLEGENDTEXT, FALSE) ;
  1109. DialogShow (hDlg, IDD_ALERTINTERVAL, FALSE) ;
  1110. DialogShow (hDlg, IDD_ALERTINTERVALTEXT, FALSE) ;
  1111. yLogTextHeight = DialogHeight (hDlg, IDD_ALERTLOGTEXT) ;
  1112. if (yHeight - yLogTextHeight > 3 * xScrollWidth) {
  1113. DialogMove (hDlg, IDD_ALERTLOGTEXT,
  1114. xScrollWidth,
  1115. xScrollWidth / 2,
  1116. NOCHANGE, NOCHANGE) ;
  1117. yLogTextHeight += xScrollWidth / 2 ;
  1118. DialogShow (hDlg, IDD_ALERTLOGTEXT, TRUE) ;
  1119. } else {
  1120. yLogTextHeight = 0 ;
  1121. DialogShow (hDlg, IDD_ALERTLOGTEXT, FALSE) ;
  1122. }
  1123. DialogMove (hDlg, IDD_ALERTLOG,
  1124. xScrollWidth,
  1125. xScrollWidth / 2 + yLogTextHeight,
  1126. xWidth - 2 * xScrollWidth,
  1127. yHeight - xScrollWidth) ;
  1128. } else if (yHeight <= 2 * yLegendHeight + 5 * xScrollWidth) {
  1129. if (pAlert->bLegendOn) {
  1130. yLegendHeight = min (yLegendHeight,
  1131. (yHeight - xScrollWidth) / 2) ;
  1132. } else {
  1133. yLegendHeight = 0 ;
  1134. }
  1135. yLogHeight = yHeight - yLegendHeight - xScrollWidth - 2 ;
  1136. DialogShow (hDlg, IDD_ALERTLEGENDTEXT, FALSE) ;
  1137. DialogShow (hDlg, IDD_ALERTINTERVAL, FALSE) ;
  1138. DialogShow (hDlg, IDD_ALERTINTERVALTEXT, FALSE) ;
  1139. yLogTextHeight = DialogHeight (hDlg, IDD_ALERTLOGTEXT) ;
  1140. if (yLogHeight - yLogTextHeight > 3 * xScrollWidth) {
  1141. DialogMove (hDlg, IDD_ALERTLOGTEXT,
  1142. xScrollWidth,
  1143. xScrollWidth / 2,
  1144. NOCHANGE, NOCHANGE) ;
  1145. yLogTextHeight += xScrollWidth / 2 ;
  1146. DialogShow (hDlg, IDD_ALERTLOGTEXT, TRUE) ;
  1147. } else {
  1148. yLogTextHeight = 0 ;
  1149. DialogShow (hDlg, IDD_ALERTLOGTEXT, FALSE) ;
  1150. }
  1151. DialogMove (hDlg, IDD_ALERTLOG,
  1152. xScrollWidth,
  1153. xScrollWidth / 2 + yLogTextHeight,
  1154. xWidth - 2 * xScrollWidth,
  1155. yLogHeight - yLogTextHeight) ;
  1156. DialogMove (hDlg, IDD_ALERTLEGEND,
  1157. xScrollWidth,
  1158. yLogHeight + xScrollWidth - 2,
  1159. xWidth - 2 * xScrollWidth,
  1160. yLegendHeight) ;
  1161. DialogShow (hDlg, IDD_ALERTLEGEND, pAlert->bLegendOn ? TRUE : FALSE) ;
  1162. } else {
  1163. if (pAlert->bLegendOn) {
  1164. DialogMove (hDlg, IDD_ALERTLEGEND,
  1165. xScrollWidth, yHeight - xScrollWidth / 2 - yLegendHeight,
  1166. xWidth - 2 * xScrollWidth,
  1167. yLegendHeight) ;
  1168. DialogMove (hDlg, IDD_ALERTLEGENDTEXT,
  1169. xScrollWidth,
  1170. DialogYPos (hDlg, IDD_ALERTLEGEND) - xScrollWidth,
  1171. NOCHANGE, NOCHANGE) ;
  1172. yLegendTextHeight = DialogYPos (hDlg, IDD_ALERTLEGENDTEXT) ;
  1173. } else {
  1174. yLegendTextHeight = yHeight - xScrollWidth / 2 - yLegendHeight ;
  1175. }
  1176. yLogTextHeight = DialogHeight (hDlg, IDD_ALERTLOGTEXT) ;
  1177. yIntervalHeight = DialogHeight (hDlg, IDD_ALERTINTERVAL) ;
  1178. yLogHeight = yLegendTextHeight - 4 * xScrollWidth ;
  1179. if (yLogHeight < 2 * xScrollWidth) {
  1180. yLogHeight = yLegendTextHeight - yLogTextHeight - xScrollWidth ;
  1181. }
  1182. DialogMove (hDlg, IDD_ALERTLOG,
  1183. xScrollWidth,
  1184. yLegendTextHeight - yLogHeight - xScrollWidth / 2,
  1185. xWidth - 2 * xScrollWidth,
  1186. yLogHeight) ;
  1187. DialogMove (hDlg, IDD_ALERTLOGTEXT,
  1188. xScrollWidth,
  1189. yLogTextHeight = DialogYPos (hDlg, IDD_ALERTLOG) - xScrollWidth,
  1190. xWidth - 2 * xScrollWidth, NOCHANGE) ;
  1191. DialogShow (hDlg, IDD_ALERTLEGEND, pAlert->bLegendOn ? TRUE : FALSE) ;
  1192. DialogShow (hDlg, IDD_ALERTLEGENDTEXT, pAlert->bLegendOn ? TRUE : FALSE) ;
  1193. DialogShow (hDlg, IDD_ALERTLOGTEXT, TRUE) ;
  1194. if (yLogTextHeight >= yIntervalHeight + xScrollWidth) {
  1195. StartYPos = (yLogTextHeight - yIntervalHeight) / 2 ;
  1196. xIntervalTextWidth = DialogWidth (hDlg, IDD_ALERTINTERVALTEXT) ;
  1197. DialogMove (hDlg, IDD_ALERTINTERVALTEXT,
  1198. xScrollWidth,
  1199. StartYPos + 1,
  1200. NOCHANGE, NOCHANGE) ;
  1201. DialogMove (hDlg, IDD_ALERTINTERVAL,
  1202. xScrollWidth + xIntervalTextWidth + 4,
  1203. StartYPos,
  1204. NOCHANGE, NOCHANGE) ;
  1205. DialogShow (hDlg, IDD_ALERTINTERVAL, TRUE) ;
  1206. DialogShow (hDlg, IDD_ALERTINTERVALTEXT, TRUE) ;
  1207. } else {
  1208. DialogShow (hDlg, IDD_ALERTINTERVAL, FALSE) ;
  1209. DialogShow (hDlg, IDD_ALERTINTERVALTEXT, FALSE) ;
  1210. }
  1211. }
  1212. WindowInvalidate (hDlg) ;
  1213. }
  1214. INT
  1215. PlaybackAlert (
  1216. HWND hWndAlert,
  1217. HANDLE hExportFile
  1218. )
  1219. {
  1220. PALERT pAlert ;
  1221. LOGPOSITION lp ;
  1222. PLOGINDEX pLogIndex ;
  1223. SYSTEMTIME SystemTime ;
  1224. SYSTEMTIME PreviousSystemTime ;
  1225. BOOL bFirstTime = TRUE ;
  1226. INT ErrCode = 0 ;
  1227. int iDisplayTics ;
  1228. DWORD TimeDiff ;
  1229. pAlert = AlertData (hWndAlert) ;
  1230. if (!pAlert->pLineFirst) {
  1231. // nothing to check
  1232. return ErrCode;
  1233. }
  1234. lp = PlaybackLog.StartIndexPos ;
  1235. iDisplayTics = PlaybackLog.iSelectedTics;
  1236. if (!hExportFile) {
  1237. LBReset (pAlert->hAlertListBox) ;
  1238. LBSetRedraw (pAlert->hAlertListBox, FALSE) ;
  1239. }
  1240. while (iDisplayTics) {
  1241. pLogIndex = IndexFromPosition (&lp) ;
  1242. if (pLogIndex)
  1243. SystemTime = pLogIndex->SystemTime ;
  1244. else
  1245. GetLocalTime (&SystemTime) ;
  1246. if (!bFirstTime) {
  1247. // check if it is time to do the alert checking
  1248. TimeDiff = (DWORD) SystemTimeDifference (&PreviousSystemTime,
  1249. &SystemTime, TRUE) ;
  1250. if (TimeDiff * 1000 >= pAlert->iIntervalMSecs) {
  1251. PlaybackLines (pAlert->pSystemFirst,
  1252. pAlert->pLineFirst,
  1253. lp.iPosition) ;
  1254. ErrCode = CheckAlerts (hWndAlert,
  1255. pAlert->hAlertListBox,
  1256. &SystemTime,
  1257. pAlert->pLineFirst,
  1258. hExportFile,
  1259. NULL) ;
  1260. if (ErrCode) {
  1261. break ;
  1262. }
  1263. PreviousSystemTime = SystemTime ;
  1264. }
  1265. } else {
  1266. // setup the data for the first time
  1267. bFirstTime = FALSE ;
  1268. PreviousSystemTime = SystemTime ;
  1269. PlaybackLines (pAlert->pSystemFirst,
  1270. pAlert->pLineFirst,
  1271. lp.iPosition) ;
  1272. }
  1273. if (!NextIndexPosition (&lp, FALSE))
  1274. break;
  1275. iDisplayTics-- ;
  1276. }
  1277. if (!hExportFile) {
  1278. LBSetRedraw (pAlert->hAlertListBox, TRUE) ;
  1279. }
  1280. return (ErrCode) ;
  1281. }
  1282. BOOL
  1283. AddAlert (
  1284. HWND hWndParent
  1285. )
  1286. {
  1287. PALERT pAlert ;
  1288. PLINE pCurrentLine ;
  1289. pAlert = AlertData (hWndAlert) ;
  1290. pCurrentLine = CurrentAlertLine (hWndAlert) ;
  1291. return (AddLine (hWndParent,
  1292. &(pAlert->pSystemFirst),
  1293. &(pAlert->Visual),
  1294. pCurrentLine ? pCurrentLine->lnSystemName : NULL,
  1295. LineTypeAlert)) ;
  1296. }
  1297. BOOL
  1298. EditAlert (
  1299. HWND hWndParent
  1300. )
  1301. {
  1302. PALERT pAlert ;
  1303. BOOL bOK ;
  1304. pAlert = AlertData (hWndAlert) ;
  1305. bOK = EditLine (hWndParent,
  1306. &(pAlert->pSystemFirst),
  1307. CurrentAlertLine (hWndAlert),
  1308. LineTypeAlert) ;
  1309. if (bOK && PlayingBackLog()) {
  1310. //re-do the alert using the new condition
  1311. PlaybackAlert (hWndAlert, 0) ;
  1312. WindowInvalidate (hWndAlert) ;
  1313. }
  1314. return (bOK) ;
  1315. }
  1316. // RemoveLineFromAlertListBox is called when we are deleting a line
  1317. // while monitoring current activity. We have to clear all the alert
  1318. // entries of this line because we are already doing this when
  1319. // playing back from log. Moreover, we are using the line structure
  1320. // while drawing the item.
  1321. //
  1322. void
  1323. RemoveLineFromAlertListBox (
  1324. PALERT pAlert,
  1325. PLINE pLine
  1326. )
  1327. {
  1328. int iIndex ;
  1329. int iNumOfAlerts ;
  1330. PALERTENTRY pAlertEntry ;
  1331. iNumOfAlerts = LBNumItems (pAlert->hAlertListBox) ;
  1332. if (iNumOfAlerts == 0 || iNumOfAlerts == (int) LB_ERR) {
  1333. return ;
  1334. }
  1335. LBSetRedraw (pAlert->hAlertListBox, FALSE) ;
  1336. // go thru the listbox from bottom to top
  1337. for (iIndex = iNumOfAlerts - 1; iIndex >= 0; iIndex-- ) {
  1338. pAlertEntry = (PALERTENTRY) LBData (pAlert->hAlertListBox, iIndex) ;
  1339. if (pAlertEntry != (PALERTENTRY) NULL && pAlertEntry) {
  1340. if (pAlertEntry->pLine == pLine) {
  1341. // remove it from the alert listbox.
  1342. LBDelete (pAlert->hAlertListBox, iIndex) ;
  1343. }
  1344. }
  1345. }
  1346. LBSetRedraw (pAlert->hAlertListBox, TRUE) ;
  1347. }
  1348. BOOL
  1349. AlertDeleteLine (
  1350. HWND hWndAlert,
  1351. PLINE pLine
  1352. )
  1353. /*
  1354. Effect: Delete the line pLine from the alerts associated with
  1355. window hWnd. Return whether the line could be deleted.
  1356. */
  1357. {
  1358. PALERT pAlert ;
  1359. pAlert = AlertData (hWndAlert) ;
  1360. pAlert->bModified = TRUE ;
  1361. LineRemove (&pAlert->pLineFirst, pLine) ;
  1362. LegendDeleteItem (hWndAlertLegend, pLine) ;
  1363. if (!pAlert->pLineFirst) {
  1364. // no need to collect data
  1365. ClearAlertTimer (pAlert) ;
  1366. // clear legend
  1367. ClearLegend (hWndAlertLegend) ;
  1368. // reset visual data
  1369. pAlert->Visual.iColorIndex = 0 ;
  1370. pAlert->Visual.iWidthIndex = 0 ;
  1371. pAlert->Visual.iStyleIndex = 0 ;
  1372. } else {
  1373. BuildValueListForSystems (
  1374. pAlert->pSystemFirst,
  1375. pAlert->pLineFirst) ;
  1376. }
  1377. if (!PlayingBackLog()) {
  1378. // delete any alert entry for this line
  1379. RemoveLineFromAlertListBox (pAlert, pLine) ;
  1380. }
  1381. SizeAlertComponents (hWndAlert) ;
  1382. if (PlayingBackLog ()) {
  1383. if (pAlert->pLineFirst)
  1384. PlaybackAlert (hWndAlert, 0) ;
  1385. else {
  1386. LBReset (pAlert->hAlertListBox) ;
  1387. }
  1388. WindowInvalidate (hWndAlert) ;
  1389. }
  1390. return (TRUE) ;
  1391. }
  1392. BOOL
  1393. ToggleAlertRefresh (
  1394. HWND hWnd
  1395. )
  1396. {
  1397. PALERT pAlert ;
  1398. pAlert = AlertData (hWnd) ;
  1399. if (pAlert->bManualRefresh)
  1400. SetAlertTimer (pAlert) ;
  1401. else
  1402. ClearAlertTimer (pAlert) ;
  1403. pAlert->bManualRefresh = !pAlert->bManualRefresh ;
  1404. return (pAlert->bManualRefresh) ;
  1405. }
  1406. BOOL
  1407. AlertRefresh (
  1408. HWND hWnd
  1409. )
  1410. {
  1411. PALERT pAlert ;
  1412. pAlert = AlertData (hWnd) ;
  1413. return (pAlert->bManualRefresh) ;
  1414. }
  1415. void
  1416. AlertTimer (
  1417. HWND hWnd,
  1418. BOOL bForce
  1419. )
  1420. /*
  1421. Effect: Perform all actions neccesary when an alert timer tick
  1422. or manual refresh occurs. In particular, get the current
  1423. values for each line in the alert window, and compare
  1424. the value against the alert conditions. For each alert
  1425. that may have occured, call SignalAlert.
  1426. Called By: AlertWndProc, in response to a WM_TIMER message.
  1427. OnCommand, in response to a IDM_REFRESHALERT notification.
  1428. */
  1429. {
  1430. PALERT pAlert ;
  1431. SYSTEMTIME SystemTime ;
  1432. pAlert = AlertData (hWnd) ;
  1433. if (PlayingBackLog ())
  1434. return ;
  1435. if (bForce || !pAlert->bManualRefresh) {
  1436. UpdateLines (&(pAlert->pSystemFirst), pAlert->pLineFirst) ;
  1437. GetLocalTime (&SystemTime) ;
  1438. CheckAlerts (hWnd,
  1439. pAlert->hAlertListBox,
  1440. &SystemTime,
  1441. pAlert->pLineFirst,
  1442. FALSE,
  1443. pAlert->pSystemFirst) ;
  1444. }
  1445. }
  1446. BOOL
  1447. OpenAlertVer1 (
  1448. HANDLE hFile,
  1449. DISKALERT *pDiskAlert,
  1450. PALERT pAlert,
  1451. DWORD dwMinorVersion
  1452. )
  1453. {
  1454. bDelayAddAction = TRUE ;
  1455. pAlert->Visual = pDiskAlert->Visual ;
  1456. pAlert->iIntervalMSecs = pDiskAlert->dwIntervalSecs ;
  1457. if (dwMinorVersion < 3) {
  1458. pAlert->iIntervalMSecs *= 1000 ;
  1459. }
  1460. pAlert->bNetworkAlert = pDiskAlert->bNetworkAlert ;
  1461. pAlert->bManualRefresh = pDiskAlert->bManualRefresh ;
  1462. pAlert->bSwitchToAlert = pDiskAlert->bSwitchToAlert ;
  1463. if (dwMinorVersion >= 2) {
  1464. lstrcpy (pAlert->MessageName, pDiskAlert->MessageName) ;
  1465. }
  1466. pAlert->bLegendOn = TRUE ;
  1467. if (dwMinorVersion >= 4) {
  1468. if (dwMinorVersion == 4)
  1469. pAlert->bEventLog = pDiskAlert->MiscOptions ;
  1470. else {
  1471. pAlert->bEventLog = pDiskAlert->MiscOptions & 0x01 ;
  1472. pAlert->bLegendOn = pDiskAlert->MiscOptions & 0x02 ;
  1473. }
  1474. } else {
  1475. pAlert->bEventLog = FALSE ;
  1476. // have to move the file pointer back for old pma file
  1477. FileSeekCurrent (hFile, -((int) (sizeof (pDiskAlert->MiscOptions)))) ;
  1478. }
  1479. if (pAlert->bNetworkAlert && pAlert->hNetAlertThread == 0) {
  1480. AlertCreateThread (pAlert) ;
  1481. }
  1482. ReadLines (hFile, pDiskAlert->dwNumLines,
  1483. &(pAlert->pSystemFirst), &(pAlert->pLineFirst), IDM_VIEWALERT) ;
  1484. bDelayAddAction = FALSE ;
  1485. AlertAddAction () ;
  1486. return (TRUE) ;
  1487. }
  1488. BOOL
  1489. OpenAlert (
  1490. HWND hWndAlert,
  1491. HANDLE hFile,
  1492. DWORD dwMajorVersion,
  1493. DWORD dwMinorVersion,
  1494. BOOL bAlertFile
  1495. )
  1496. {
  1497. PALERT pAlert ;
  1498. DISKALERT DiskAlert ;
  1499. BOOL bSuccess = TRUE ;
  1500. pAlert = AlertData (hWndAlert) ;
  1501. if (!pAlert) {
  1502. bSuccess = FALSE ;
  1503. goto Exit0 ;
  1504. }
  1505. if (!FileRead (hFile, &DiskAlert, sizeof (DISKALERT))) {
  1506. bSuccess = FALSE ;
  1507. goto Exit0 ;
  1508. }
  1509. switch (dwMajorVersion) {
  1510. case (1):
  1511. SetHourglassCursor() ;
  1512. ResetAlertView (hWndAlert) ;
  1513. OpenAlertVer1 (hFile, &DiskAlert, pAlert, dwMinorVersion) ;
  1514. // change to alert view if we are opening a
  1515. // alert file
  1516. if (bAlertFile && iPerfmonView != IDM_VIEWALERT) {
  1517. SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWALERT, 0L) ;
  1518. }
  1519. if (iPerfmonView == IDM_VIEWALERT) {
  1520. SetPerfmonOptions (&DiskAlert.perfmonOptions) ;
  1521. }
  1522. UpdateAlertDisplay (hWndAlert) ;
  1523. SetArrowCursor() ;
  1524. break ;
  1525. }
  1526. Exit0:
  1527. if (bAlertFile) {
  1528. CloseHandle (hFile) ;
  1529. }
  1530. return (bSuccess) ;
  1531. }
  1532. void
  1533. ResetAlertView (
  1534. HWND hWndAlert
  1535. )
  1536. {
  1537. PALERT pAlert ;
  1538. pAlert = AlertData (hWndAlert) ;
  1539. if (!pAlert)
  1540. return ;
  1541. ChangeSaveFileName (NULL, IDM_VIEWALERT) ;
  1542. if (pAlert->pSystemFirst) {
  1543. ResetAlert (hWndAlert) ;
  1544. }
  1545. }
  1546. void
  1547. ResetAlert (
  1548. HWND hWndAlert
  1549. )
  1550. {
  1551. PALERT pAlert ;
  1552. pAlert = AlertData (hWndAlert) ;
  1553. if (!pAlert)
  1554. return ;
  1555. ClearAlertTimer (pAlert) ;
  1556. ClearLegend (hWndAlertLegend) ;
  1557. if (pAlert->pLineFirst) {
  1558. FreeLines (pAlert->pLineFirst) ;
  1559. pAlert->pLineFirst = NULL ;
  1560. }
  1561. if (pAlert->pSystemFirst) {
  1562. FreeSystems (pAlert->pSystemFirst) ;
  1563. pAlert->pSystemFirst = NULL ;
  1564. }
  1565. pAlert->bModified = FALSE ;
  1566. // reset visual data
  1567. pAlert->Visual.iColorIndex = 0 ;
  1568. pAlert->Visual.iWidthIndex = 0 ;
  1569. pAlert->Visual.iStyleIndex = 0 ;
  1570. iUnviewedAlerts = 0 ;
  1571. if (iPerfmonView != IDM_VIEWALERT) {
  1572. StatusUpdateIcons (hWndStatus) ;
  1573. }
  1574. // remove the horiz. scrollbar
  1575. pAlert->xTextExtent = 0 ;
  1576. LBSetHorzExtent (pAlert->hAlertListBox, pAlert->xTextExtent) ;
  1577. LBReset (pAlert->hAlertListBox) ;
  1578. SizeAlertComponents (hWndAlert) ;
  1579. // WindowInvalidate (hWndAlert) ;
  1580. }
  1581. void
  1582. ClearAlertDisplay (
  1583. HWND hWnd
  1584. )
  1585. {
  1586. PALERT pAlert ;
  1587. pAlert = AlertData (hWnd) ;
  1588. // remove the horiz. scrollbar
  1589. pAlert->xTextExtent = 0 ;
  1590. LBSetHorzExtent (pAlert->hAlertListBox, pAlert->xTextExtent) ;
  1591. LBReset (pAlert->hAlertListBox) ;
  1592. }
  1593. BOOL
  1594. SaveAlert (
  1595. HWND hWndAlert,
  1596. HANDLE hInputFile,
  1597. BOOL bGetFileName
  1598. )
  1599. {
  1600. PALERT pAlert ;
  1601. PLINE pLine ;
  1602. HANDLE hFile = NULL;
  1603. DISKALERT DiskAlert ;
  1604. PERFFILEHEADER FileHeader ;
  1605. TCHAR szFileName [256] ;
  1606. BOOL newFileName = FALSE ;
  1607. if (hInputFile) {
  1608. // use the input file handle if it is available
  1609. // this is the case for saving workspace data
  1610. hFile = hInputFile ;
  1611. } else {
  1612. if (pAlertFullFileName) {
  1613. lstrcpy (szFileName, pAlertFullFileName) ;
  1614. }
  1615. if (bGetFileName || pAlertFullFileName == NULL) {
  1616. if (!FileGetName (hWndAlert, IDS_ALERTFILE, szFileName)) {
  1617. return (FALSE) ;
  1618. }
  1619. newFileName = TRUE ;
  1620. }
  1621. hFile = FileHandleCreate (szFileName) ;
  1622. if (hFile && newFileName) {
  1623. ChangeSaveFileName (szFileName, IDM_VIEWALERT) ;
  1624. } else if (!hFile) {
  1625. DlgErrorBox (hWndAlert, ERR_CANT_OPEN, szFileName) ;
  1626. }
  1627. }
  1628. if (!hFile || hFile == INVALID_HANDLE_VALUE)
  1629. return (FALSE) ;
  1630. pAlert = AlertData (hWndAlert) ;
  1631. if (!pAlert) {
  1632. if (!hInputFile) {
  1633. CloseHandle (hFile) ;
  1634. }
  1635. return (FALSE) ;
  1636. }
  1637. if (!hInputFile) {
  1638. memset (&FileHeader, 0, sizeof (FileHeader)) ;
  1639. lstrcpy (FileHeader.szSignature, szPerfAlertSignature) ;
  1640. FileHeader.dwMajorVersion = AlertMajorVersion ;
  1641. FileHeader.dwMinorVersion = AlertMinorVersion ;
  1642. if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER))) {
  1643. goto Exit0 ;
  1644. }
  1645. }
  1646. DiskAlert.Visual = pAlert->Visual ;
  1647. DiskAlert.dwIntervalSecs = pAlert->iIntervalMSecs ;
  1648. DiskAlert.dwNumLines = NumLines (pAlert->pLineFirst) ;
  1649. // fill in misc alert options
  1650. DiskAlert.MiscOptions = 0 ;
  1651. if (pAlert->bEventLog)
  1652. DiskAlert.MiscOptions = 0x01 ;
  1653. if (pAlert->bLegendOn)
  1654. DiskAlert.MiscOptions += 0x02 ;
  1655. // DiskAlert.bEventLog = pAlert->bEventLog ;
  1656. DiskAlert.bNetworkAlert = pAlert->bNetworkAlert ;
  1657. DiskAlert.bSwitchToAlert = pAlert->bSwitchToAlert ;
  1658. DiskAlert.bManualRefresh = pAlert->bManualRefresh ;
  1659. DiskAlert.perfmonOptions = Options ;
  1660. lstrcpy (DiskAlert.MessageName, pAlert->MessageName) ;
  1661. if (!FileWrite (hFile, &DiskAlert, sizeof (DISKALERT))) {
  1662. goto Exit0 ;
  1663. }
  1664. for (pLine = pAlert->pLineFirst; pLine; pLine = pLine->pLineNext) {
  1665. if (!WriteLine (pLine, hFile)) {
  1666. goto Exit0 ;
  1667. }
  1668. }
  1669. if (!hInputFile) {
  1670. CloseHandle (hFile) ;
  1671. }
  1672. return (TRUE) ;
  1673. Exit0:
  1674. if (!hInputFile) {
  1675. CloseHandle (hFile) ;
  1676. // only need to report error if not workspace
  1677. DlgErrorBox (hWndAlert, ERR_SETTING_FILE, szFileName) ;
  1678. }
  1679. return (FALSE) ;
  1680. }
  1681. BOOL
  1682. ExportAlertEntry (
  1683. HANDLE hFile,
  1684. PALERTENTRY pAlertEntry
  1685. )
  1686. {
  1687. TCHAR UnicodeBuff [LongTextLen] ;
  1688. CHAR TempBuff [LongTextLen * 2] ;
  1689. int StringLen ;
  1690. PLINE pLine ;
  1691. pLine = pAlertEntry->pLine ;
  1692. // export the alert date-time
  1693. strcpy (TempBuff, LineEndStr) ;
  1694. StringLen = strlen (TempBuff) ;
  1695. SystemTimeDateString (&(pAlertEntry->SystemTime), UnicodeBuff) ;
  1696. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1697. strcat (TempBuff, pDelimiter) ;
  1698. SystemTimeTimeString (&(pAlertEntry->SystemTime), UnicodeBuff, FALSE) ;
  1699. StringLen = strlen (TempBuff) ;
  1700. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1701. strcat (TempBuff, pDelimiter) ;
  1702. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1703. goto Exit0 ;
  1704. }
  1705. // export alert value and trigger condition
  1706. if (pLine) {
  1707. TSPRINTF (UnicodeBuff, szNumberFormat, pAlertEntry->eValue) ;
  1708. ConvertDecimalPoint (UnicodeBuff) ;
  1709. ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
  1710. strcat (TempBuff, pDelimiter) ;
  1711. StringLen = strlen (TempBuff) ;
  1712. TempBuff[StringLen] = pAlertEntry->bOver ? '>' : '<' ;
  1713. StringLen++ ;
  1714. TSPRINTF (UnicodeBuff, szNumberFormat, pAlertEntry->eAlertValue) ;
  1715. ConvertDecimalPoint (UnicodeBuff) ;
  1716. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1717. strcat (TempBuff, pDelimiter) ;
  1718. } else {
  1719. strcpy (TempBuff, pDelimiter) ;
  1720. strcat (TempBuff, pDelimiter) ;
  1721. }
  1722. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1723. goto Exit0 ;
  1724. }
  1725. // export Counter, Instance, & Parent names
  1726. if (pLine) {
  1727. ConvertUnicodeStr (TempBuff, pLine->lnCounterName) ;
  1728. } else {
  1729. // system up/down message is stored in lpszInstance.
  1730. ConvertUnicodeStr (TempBuff, pAlertEntry->lpszInstance) ;
  1731. }
  1732. strcat (TempBuff, pDelimiter) ;
  1733. StringLen = strlen (TempBuff) ;
  1734. if (pLine && !(strempty(pAlertEntry->lpszInstance))) {
  1735. ConvertUnicodeStr (&TempBuff[StringLen], pAlertEntry->lpszInstance) ;
  1736. }
  1737. strcat (TempBuff, pDelimiter) ;
  1738. StringLen = strlen (TempBuff) ;
  1739. if (pLine && !(strempty(pAlertEntry->lpszParent))) {
  1740. ConvertUnicodeStr (&TempBuff[StringLen], pAlertEntry->lpszParent) ;
  1741. }
  1742. strcat (TempBuff, pDelimiter) ;
  1743. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1744. goto Exit0 ;
  1745. }
  1746. // export object, & computer names
  1747. TempBuff[0] = '\0' ;
  1748. if (pLine) {
  1749. ConvertUnicodeStr (TempBuff, pLine->lnObjectName) ;
  1750. }
  1751. strcat (TempBuff, pDelimiter) ;
  1752. StringLen = strlen (TempBuff) ;
  1753. if (pLine) {
  1754. ConvertUnicodeStr (&TempBuff[StringLen], pLine->lnSystemName) ;
  1755. } else {
  1756. // system name for the system that is up or down is in
  1757. // lpszParent.
  1758. ConvertUnicodeStr (&TempBuff[StringLen], pAlertEntry->lpszParent) ;
  1759. }
  1760. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1761. goto Exit0 ;
  1762. }
  1763. return (TRUE) ;
  1764. Exit0:
  1765. return (FALSE) ;
  1766. }
  1767. INT
  1768. ExportAlertLine (
  1769. PLINE pLine,
  1770. FLOAT eValue,
  1771. SYSTEMTIME *pSystemTime,
  1772. HANDLE hExportFile
  1773. )
  1774. {
  1775. ALERTENTRY AlertEntry ;
  1776. TCHAR szInstance [256] ;
  1777. TCHAR szParent [256] ;
  1778. INT ErrCode = 0 ;
  1779. AlertEntry.SystemTime = *pSystemTime ;
  1780. AlertEntry.pLine= pLine ;
  1781. AlertEntry.eValue = eValue ;
  1782. AlertEntry.bOver = pLine->bAlertOver ;
  1783. AlertEntry.eAlertValue = pLine->eAlertValue ;
  1784. //=============================//
  1785. // Determine Instance, Parent //
  1786. //=============================//
  1787. // It's possible that there will be no instance, therefore
  1788. // the lnInstanceName would be NULL.
  1789. if (pLine->lnObject.NumInstances > 0) {
  1790. // Test for the parent object instance name title index.
  1791. // If there is one, it implies that there will be a valid
  1792. // Parent Object Name and a valid Parent Object Instance Name.
  1793. // If the Parent Object title index is 0 then
  1794. // just display the instance name.
  1795. lstrcpy (szInstance, pLine->lnInstanceName) ;
  1796. if (pLine->lnInstanceDef.ParentObjectTitleIndex && pLine->lnPINName) {
  1797. // Get the Parent Object Name.
  1798. lstrcpy (szParent, pLine->lnPINName) ;
  1799. } else {
  1800. szParent[0] = TEXT(' ') ;
  1801. szParent[1] = TEXT('\0') ;
  1802. }
  1803. } else {
  1804. szInstance[0] = TEXT(' ') ;
  1805. szInstance[1] = TEXT('\0') ;
  1806. szParent[0] = TEXT(' ') ;
  1807. szParent[1] = TEXT('\0') ;
  1808. }
  1809. AlertEntry.lpszInstance = szInstance ;
  1810. AlertEntry.lpszParent = szParent ;
  1811. if (!ExportAlertEntry (hExportFile, &AlertEntry)) {
  1812. ErrCode = ERR_EXPORT_FILE ;
  1813. }
  1814. return ErrCode ;
  1815. }
  1816. BOOL
  1817. ExportAlertLabels (
  1818. HANDLE hFile
  1819. )
  1820. {
  1821. TCHAR UnicodeBuff [LongTextLen] ;
  1822. CHAR TempBuff [LongTextLen * 2] ;
  1823. int StringLen ;
  1824. strcpy (TempBuff, LineEndStr) ;
  1825. StringLen = strlen (TempBuff) ;
  1826. StringLoad (IDS_EXPORT_DATE, UnicodeBuff) ;
  1827. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1828. strcat (TempBuff, pDelimiter) ;
  1829. StringLen = strlen (TempBuff) ;
  1830. StringLoad (IDS_EXPORT_TIME, UnicodeBuff) ;
  1831. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1832. strcat (TempBuff, pDelimiter) ;
  1833. StringLen = strlen (TempBuff) ;
  1834. StringLoad (IDS_LABELVALUE, UnicodeBuff) ;
  1835. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1836. strcat (TempBuff, pDelimiter) ;
  1837. StringLen = strlen (TempBuff) ;
  1838. StringLoad (IDS_ALERT_TRIGGER, UnicodeBuff) ;
  1839. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1840. strcat (TempBuff, pDelimiter) ;
  1841. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1842. goto Exit0 ;
  1843. }
  1844. StringLoad (IDS_COUNTERNAME, UnicodeBuff) ;
  1845. ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
  1846. strcat (TempBuff, pDelimiter) ;
  1847. StringLen = strlen (TempBuff) ;
  1848. StringLoad (IDS_INSTNAME, UnicodeBuff) ;
  1849. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1850. strcat (TempBuff, pDelimiter) ;
  1851. StringLen = strlen (TempBuff) ;
  1852. StringLoad (IDS_PARENT, UnicodeBuff) ;
  1853. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1854. strcat (TempBuff, pDelimiter) ;
  1855. StringLen = strlen (TempBuff) ;
  1856. StringLoad (IDS_OBJNAME, UnicodeBuff) ;
  1857. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1858. strcat (TempBuff, pDelimiter) ;
  1859. StringLen = strlen (TempBuff) ;
  1860. StringLoad (IDS_LABELSYSTEM, UnicodeBuff) ;
  1861. ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1862. if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
  1863. goto Exit0 ;
  1864. }
  1865. return (TRUE) ;
  1866. Exit0:
  1867. return (FALSE) ;
  1868. }
  1869. void
  1870. ExportAlert (void)
  1871. {
  1872. PALERT pAlert ;
  1873. HANDLE hFile = 0 ;
  1874. HWND hWndAlerts ;
  1875. PALERTENTRY pAlertEntry ;
  1876. int AlertTotal ;
  1877. int iIndex ;
  1878. LPTSTR pFileName = NULL ;
  1879. INT ErrCode = 0 ;
  1880. if (!(pAlert = AlertData (hWndAlert))) {
  1881. return ;
  1882. }
  1883. // see if there is anything to export..
  1884. if (!(pAlert->pLineFirst)) {
  1885. return ;
  1886. }
  1887. if (!(hWndAlerts = pAlert->hAlertListBox)) {
  1888. return ;
  1889. }
  1890. AlertTotal = LBNumItems (hWndAlerts) ;
  1891. if (AlertTotal == LB_ERR || AlertTotal == 0) {
  1892. return ;
  1893. }
  1894. SetHourglassCursor() ;
  1895. if (ErrCode = ExportFileOpen (hWndAlert, &hFile, pAlert->iIntervalMSecs, &pFileName)) {
  1896. goto Exit0 ;
  1897. }
  1898. if (!pFileName) {
  1899. // the case when user cancel.
  1900. goto Exit0 ;
  1901. }
  1902. // export the column labels
  1903. if (!ExportAlertLabels (hFile)) {
  1904. ErrCode = ERR_EXPORT_FILE ;
  1905. goto Exit0 ;
  1906. }
  1907. if (AlertTotal < ALERTLOGMAXITEMS || !PlayingBackLog()) {
  1908. for (iIndex = 0 ; iIndex < AlertTotal ; iIndex++) {
  1909. // get the alert data
  1910. pAlertEntry = (PALERTENTRY) LBData (hWndAlerts, iIndex) ;
  1911. if (!pAlertEntry || pAlertEntry == (PALERTENTRY)LB_ERR) {
  1912. // skip this entry if we hit an error
  1913. continue ;
  1914. }
  1915. // export the alert line
  1916. if (!ExportAlertEntry (hFile, pAlertEntry)) {
  1917. ErrCode = ERR_EXPORT_FILE ;
  1918. break ;
  1919. }
  1920. }
  1921. } else {
  1922. // we are playingback log and that the listbox does not
  1923. // contain all the alerts. In this case, have to walk the
  1924. // log file to re-generate all the alerts.
  1925. ErrCode = PlaybackAlert (hWndAlert, hFile) ;
  1926. }
  1927. Exit0:
  1928. SetArrowCursor() ;
  1929. if (hFile) {
  1930. CloseHandle (hFile) ;
  1931. }
  1932. if (pFileName) {
  1933. if (ErrCode) {
  1934. DlgErrorBox (hWndAlert, ErrCode, pFileName) ;
  1935. }
  1936. MemoryFree (pFileName) ;
  1937. }
  1938. }