Windows NT 4.0 source code leak
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.

2507 lines
66 KiB

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