|
|
1.1 root 1: /*****************************************************************************
2: *
3: * Log.c - This module handles the Logging.
4: *
5: * Microsoft Confidential
6: * Copyright (c) 1992-1993 Microsoft Corporation
7: *
8: *
9: ****************************************************************************/
10:
11:
12: //==========================================================================//
13: // Includes //
14: //==========================================================================//
15:
16: #include <stdio.h>
17:
18: #include "perfmon.h"
19: #include "log.h"
20:
21: #include "fileutil.h"
22: #include "owndraw.h"
23: #include "pmemory.h" // for MemoryXXX (mallloc-type) routines
24: #include "perfmops.h" // for SystemAdd
25: #include "perfdata.h"
26: #include "playback.h" // for PlayingBackLog
27: #include "status.h" // for StatusUpdateIcons
28: #include "system.h" // for SystemAdd
29: #include "utils.h"
30: #include "fileopen.h" // for FileGetName
31: #include "command.h"
32:
33: extern TCHAR LOCAL_SYS_CODE_NAME[] ;
34:
35: //==========================================================================//
36: // Funtion Prototypes //
37: //==========================================================================//
38:
39:
40: BOOL LogWriteStartBookmark (HWND hWnd, SYSTEMTIME *pSystemTime) ;
41: BOOL LogWriteBookmarkData (HWND hWnd, PBOOKMARK pBookMark) ;
42:
43:
44: //==========================================================================//
45: // Constants //
46: //==========================================================================//
47:
48:
49:
50: #define LogNameMinLen 15
51: #define LogObjectMinLen 20
52:
53: // This is set to 1 min
54: #define LARGE_INTERVAL 60
55:
56: //=============================//
57: // Log Class //
58: //=============================//
59:
60:
61: #define dwLogClassStyle (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS)
62: #define iLogClassExtra (0)
63: #define iLogWindowExtra (0)
64: #define dwLogWindowStyle (WS_CHILD)
65:
66:
67: //==========================================================================//
68: // Local Data //
69: //==========================================================================//
70:
71:
72:
73: int xStatusWidth ;
74: int xNameMinWidth ;
75:
76: TCHAR szClosed [ShortTextLen] ;
77: TCHAR szCollecting [ShortTextLen] ;
78: // TCHAR szPaused [ControlStringLen + 1] ;
79:
80:
81: HWND hWndLogEntries ;
82:
83: LOGINDEXBLOCK *pLogIndexBlock ;
84:
85:
86: //==========================================================================//
87: // Macros //
88: //==========================================================================//
89:
90:
91: #define LogEntryN(hWndLogEntries, iIndex) \
92: ((PLOGENTRY) LBData (hWndLogEntries, iIndex))
93:
94:
95: //==========================================================================//
96: // Local Functions //
97: //==========================================================================//
98:
99: void LogAddEntryToList (PLOGENTRY *ppLogEntryFirst, PLOGENTRY pLogNewEntry)
100: {
101: // insert the new entry at the beginning
102: pLogNewEntry->pNextLogEntry = *ppLogEntryFirst ;
103: *ppLogEntryFirst = pLogNewEntry ;
104: }
105:
106: void LogDeleteEntryFromList (PLOGENTRY *ppLogEntryFirst, PLOGENTRY pLogEntryDel)
107: {
108: PLOGENTRY pLogEntry ;
109:
110: if (*ppLogEntryFirst == pLogEntryDel)
111: {
112: *ppLogEntryFirst = pLogEntryDel->pNextLogEntry ;
113: }
114: else
115: {
116: for (pLogEntry = *ppLogEntryFirst ;
117: pLogEntry ;
118: pLogEntry = pLogEntry->pNextLogEntry)
119: {
120: if (pLogEntry->pNextLogEntry == pLogEntryDel)
121: {
122: // found, remove this entry from the list
123: pLogEntry->pNextLogEntry =
124: pLogEntryDel->pNextLogEntry ;
125: break ;
126: }
127: }
128: }
129: }
130:
131:
132: // LogDeleteIndex - delete the log entry specified by iIndex
133: // and do memory clean-up
134: void static LogDeleteIndex (HWND hWndLogEntries, int iIndex)
135: {
136: PLOGENTRY pLogEntry ;
137: PLOG pLog ;
138:
139: pLogEntry = (PLOGENTRY) LBData(hWndLogEntries, iIndex) ;
140:
141:
142: if (pLogEntry && pLogEntry != (PLOGENTRY)LB_ERR)
143: {
144: pLog = LogData (hWndLog) ;
145:
146: if (pLog->pLogEntryFirst)
147: {
148: LogDeleteEntryFromList (&(pLog->pLogEntryFirst), pLogEntry) ;
149: }
150:
151: MemoryFree (pLogEntry) ;
152: }
153:
154: LBDelete (hWndLogEntries, iIndex) ;
155: }
156:
157:
158: void LogEntriesChanged (HWND hWndLogEntries)
159: /*
160: Effect: Perform any actions needed when an entry has been added or
161: removed from the log. In particular, determine if a new
162: "Object" column width is appropriate. If it is, then
163: change the width and redraw the log entries list.
164: */
165: { // LogEntriesChanged
166: int iIndex ;
167: int iIndexNum ;
168: int xCol1Width ;
169: HDC hDC ;
170: PLOG pLog ;
171: PLOGENTRY pLogEntry ;
172: PPERFSYSTEM pSystem;
173:
174: pLog = LogData (hWndLog) ;
175: xCol1Width = 0 ;
176:
177: hDC = GetDC (hWndLog) ;
178: iIndexNum = LBNumItems (hWndLogEntries) ;
179:
180: // clear value Strings for all systems
181:
182: for (pSystem = pLog->pSystemFirst;
183: pSystem;
184: pSystem = pSystem->pSystemNext) {
185: if (pSystem) {
186: RemoveObjectsFromSystem (pSystem);
187: }
188: }
189:
190: for (iIndex = 0 ;
191: iIndex < iIndexNum ;
192: iIndex++)
193: { // for all items in the list
194: pLogEntry = LogEntryN (hWndLogEntries, iIndex) ;
195: xCol1Width = max (TextWidth (hDC, pLogEntry->szObject),
196: xCol1Width) ;
197:
198: pSystem = SystemGet (pLog->pSystemFirst, pLogEntry->szComputer);
199: if (pSystem) {
200: AppendObjectToValueList (
201: pLogEntry->ObjectTitleIndex,
202: pSystem->lpszValue);
203: }
204:
205: } // for
206:
207: xCol1Width += 2 * xScrollWidth ;
208: xCol1Width = max (xCol1Width,
209: TextAvgWidth (hDC, LogObjectMinLen)) ;
210: if (xCol1Width != pLog->xCol1Width)
211: {
212: pLog->xCol1Width = xCol1Width ;
213: WindowInvalidate (hWndLogEntries) ;
214: }
215: ReleaseDC (hWndLog, hDC) ;
216: } // LogEntriesChanged
217:
218:
219: LPTSTR StatusText (int iPMStatus)
220: /*
221: Effect: Return a string representation of the log status
222: iPMStatus.
223:
224: Note: Since these are globals, we can just return a pointer
225: to them. The user of this routine should not free
226: these pointers or modify the string.
227: */
228: {
229: switch (iPMStatus)
230: { // switch
231: case iPMStatusClosed:
232: return (szClosed) ;
233:
234: case iPMStatusCollecting:
235: return (szCollecting) ;
236:
237: // case iPMStatusPaused:
238: // return (szPaused) ;
239:
240: default:
241: return (szClosed) ;
242: } // switch
243: } // StatusText
244:
245:
246: PLOG AllocateLogData (HWND hWndLog)
247: {
248: PLOG pLog ;
249:
250: pLog = LogData (hWndLog) ;
251:
252: pLog->iStatus = iPMStatusClosed ;
253: pLog->bManualRefresh = FALSE ;
254:
255: // let's not give it a filename
256:
257: /*!!
258: FileCombine (pLog->szFilePath,
259: szDefaultLogDirectory, szDefaultLogFileName) ;
260: !!*/
261: strclr (pLog->szFilePath) ;
262:
263: pLog->pSystemFirst = NULL;
264: pLog->lFileSize = 0L ;
265: pLog->iIntervalMSecs = iDefaultLogIntervalSecs * 1000 ;
266:
267: pLog->pPerfData = (PPERFDATA) MemoryAllocate (STARTING_SYSINFO_SIZE) ;
268: pLog->pLogData = (PPERFDATA) MemoryAllocate (STARTING_SYSINFO_SIZE) ;
269: pLog->dwDetailLevel = PERF_DETAIL_WIZARD ;
270: LogEntriesChanged (hWndLogEntries) ;
271:
272: return (pLog) ;
273: } // AllocateLogData
274:
275:
276: void FreeLogData (PLOG pLog)
277: { // FreeLogData
278: MemoryFree (pLog->pPerfData) ;
279: MemoryFree (pLog->pLogData) ;
280: } // FreeLogData
281:
282:
283: void UpdateLogSize (HWND hWnd)
284: /*
285: Effect: Set the size value to the current size. Also change the
286: size entry in the status line.
287: */
288: { // UpdateLogSize
289: PLOG pLog ;
290: TCHAR szSize [ShortTextLen + 1] ;
291:
292: pLog = LogData (hWnd) ;
293:
294: LongToCommaString (pLog->lFileSize, szSize) ;
295: SetDlgItemText (hWnd, IDD_LOGSIZE, szSize) ;
296:
297: if (!PlayingBackLog())
298: {
299: StatusUpdateIcons (hWndStatus) ;
300: }
301: } // UpdateLogSize
302:
303:
304: HANDLE LogAppendSetup(PLOG pLog, PLOGHEADER pLogFileHeader)
305: { // LogAppendSetup
306: PLOGHEADER pHeader ;
307: LOGPOSITION LP ;
308: DWORD lPreviousIndexBlock ;
309: DWORD lNextIndexBlock ;
310: PLOGHEADER pPlaybackLogHeader ;
311: HANDLE hMapHandle ;
312:
313: pHeader = (PLOGHEADER) FileMap(pLog->hFile, &hMapHandle) ;
314: if (!pHeader ||
315: !strsame(pHeader->szSignature, LogFileSignature) ||
316: pHeader->wVersion != LogFileVersion ||
317: pHeader->wRevision != LogFileRevision)
318: {
319: if (pHeader)
320: {
321: FileUnMap((LPVOID)pHeader, hMapHandle) ;
322: }
323: return 0 ;
324: }
325:
326: *pLogFileHeader = *pHeader ;
327:
328:
329: LP.pIndexBlock = FirstIndexBlock(pHeader) ;
330: LP.iIndex = 0 ;
331: LP.iPosition = 0 ;
332: lPreviousIndexBlock = pHeader->iLength ;
333: lNextIndexBlock = LP.pIndexBlock->lNextBlockOffset ;
334:
335: // since inside NextReLogIndexPosition would eventually call
336: // PlaybackSeek for large log file, we have to temporarily
337: // setup PlaybackLog.pHeader. Not a good fix but it works...
338: pPlaybackLogHeader = PlaybackLog.pHeader ;
339: PlaybackLog.pHeader = pHeader ;
340: while (NextReLogIndexPosition(&LP))
341: {
342: if (LP.pIndexBlock->lNextBlockOffset != lNextIndexBlock)
343: {
344: lPreviousIndexBlock = lNextIndexBlock ;
345: lNextIndexBlock = LP.pIndexBlock->lNextBlockOffset ;
346: }
347: }
348:
349: PlaybackLog.pHeader = pPlaybackLogHeader ;
350: if (!pLogIndexBlock)
351: {
352: pLogIndexBlock = (LOGINDEXBLOCK *) MemoryAllocate (sizeof(LOGINDEXBLOCK)) ;
353: }
354: *pLogIndexBlock = *LP.pIndexBlock ;
355: pLog->lIndexBlockOffset = lPreviousIndexBlock ;
356: pLog->iIndex = ++LP.iIndex ;
357: pLog->lFileSize = FileSeekEnd(pLog->hFile, 0) ;
358:
359: FileUnMap((LPVOID)pHeader, hMapHandle) ;
360: return pLog->hFile ;
361: } // LogAppendSetup
362:
363: void LogRemoveCounterName (PLOG pLog)
364: {
365: PPERFSYSTEM pSystem ;
366:
367: if (pLog->pBaseCounterName)
368: {
369: MemoryFree (pLog->pBaseCounterName) ;
370: }
371: pLog->pBaseCounterName = 0 ;
372: pLog->lBaseCounterNameSize = 0 ;
373: pLog->lBaseCounterNameOffset = 0 ;
374:
375: // clear all the system marker to indicate they have not been
376: // saved
377: for (pSystem = pLog->pSystemFirst ;
378: pSystem ;
379: pSystem = pSystem->pSystemNext)
380: {
381: pSystem->bSystemCounterNameSaved = FALSE ;
382: }
383: }
384:
385: int CreateLogFile (PLOG pLog, BOOL bCreateFile, BOOL bSameFile)
386: { // CreateLogFile
387: HANDLE returnHandle ;
388: LOGHEADER LogFileHeader ;
389: long lCurPosition ;
390: LOGFILECOUNTERNAME CounterNameRecord ;
391:
392: pLog->lFileSize = 0 ;
393:
394: if (!pLogIndexBlock)
395: {
396: pLogIndexBlock = (LOGINDEXBLOCK *) MemoryAllocate (sizeof(LOGINDEXBLOCK)) ;
397: }
398:
399: lstrcpy (pLogIndexBlock->szSignature, LogIndexSignature) ;
400: pLog->hFile = FileHandleOpen (pLog->szFilePath) ;
401: if (pLog->hFile != INVALID_HANDLE_VALUE)
402: {
403: // if this is a pre-existing log file, set up to append to it
404: returnHandle = LogAppendSetup(pLog, &LogFileHeader) ;
405: if (!returnHandle)
406: {
407: // this is not a log file...
408: CloseHandle (pLog->hFile) ;
409: return (ERR_BAD_LOG_FILE) ;
410: }
411:
412: pLog->hFile = returnHandle ;
413: }
414:
415: if (bCreateFile && (!pLog->hFile || pLog->hFile == INVALID_HANDLE_VALUE))
416: {
417: // Create a new log file if needed.
418: pLog->hFile = FileHandleCreate (pLog->szFilePath) ;
419: if (!pLog->hFile)
420: return (ERR_LOG_FILE) ;
421: lstrcpy (LogFileHeader.szSignature, LogFileSignature) ;
422: LogFileHeader.wVersion = LogFileVersion ;
423: LogFileHeader.wRevision = LogFileRevision ;
424: LogFileHeader.iLength = sizeof (LOGHEADER) ;
425: LogFileHeader.lBaseCounterNameOffset = 0 ;
426: if (!FileWrite (pLog->hFile, &LogFileHeader, sizeof (LogFileHeader)))
427: {
428: CloseHandle (pLog->hFile) ;
429: return (ERR_LOG_FILE) ;
430: }
431:
432: pLog->iIndex = 0 ;
433: pLog->lIndexBlockOffset = FileTell (pLog->hFile) ;
434: FileSeekCurrent (pLog->hFile, sizeof (LOGINDEXBLOCK)) ;
435: pLog->lFileSize = sizeof(LOGHEADER) + sizeof (LOGINDEXBLOCK) ;
436: pLogIndexBlock->iNumIndexes = 0 ;
437: pLogIndexBlock->lNextBlockOffset = 0 ;
438:
439: // get rid of any previous counter names and get ready for start
440: if (!bSameFile)
441: {
442: LogRemoveCounterName (pLog) ;
443: }
444: }
445: else if (bCreateFile)
446: {
447: // this is an existing log file, setup the counter names
448: // LogFileHeader already has the header info filled in
449: // by LogAppendSetup
450: if (!bSameFile || !pLog->pBaseCounterName)
451: {
452: // get rid of any previous counter names
453: LogRemoveCounterName (pLog) ;
454:
455: // read the new names and get ready for start
456: lCurPosition = FileTell (pLog->hFile) ;
457:
458: FileSeekBegin (pLog->hFile,
459: LogFileHeader.lBaseCounterNameOffset) ;
460:
461: if (!(FileRead (pLog->hFile,
462: &CounterNameRecord,
463: sizeof (CounterNameRecord))))
464: {
465: FileSeekBegin (pLog->hFile,
466: lCurPosition) ;
467: goto EXIT ;
468: }
469:
470: FileSeekBegin (pLog->hFile,
471: CounterNameRecord.lCurrentCounterNameOffset) ;
472:
473: if (!(pLog->pBaseCounterName = MemoryAllocate (
474: CounterNameRecord.lUnmatchCounterNames)))
475: {
476: FileSeekBegin (pLog->hFile,
477: lCurPosition) ;
478: goto EXIT ;
479: }
480: if (!(FileRead (pLog->hFile,
481: pLog->pBaseCounterName,
482: CounterNameRecord.lUnmatchCounterNames)))
483: {
484: MemoryFree (pLog->pBaseCounterName) ;
485: pLog->pBaseCounterName = NULL ;
486: FileSeekBegin (pLog->hFile,
487: lCurPosition) ;
488: goto EXIT ;
489: }
490: // we got the data, fill in other info
491: pLog->lBaseCounterNameSize =
492: CounterNameRecord.lUnmatchCounterNames ;
493: pLog->lBaseCounterNameOffset =
494: LogFileHeader.lBaseCounterNameOffset ;
495:
496: FileSeekBegin (pLog->hFile,
497: lCurPosition) ;
498: }
499: }
500:
501: EXIT:
502:
503: return (0) ;
504:
505: } // CreateLogFile
506:
507:
508: BOOL LogGetSystemPerfData (PLOG pLog,
509: HKEY hKey)
510: {
511: long lError ;
512: DWORD dwSize;
513:
514: while (TRUE)
515: {
516: dwSize = MemorySize (pLog->pPerfData);
517: lError = GetSystemPerfData (hKey, L"Global", pLog->pPerfData,
518: &dwSize) ;
519:
520: if (!lError)
521: return (TRUE) ;
522:
523: if (lError == ERROR_MORE_DATA)
524: {
525: pLog->pPerfData = MemoryResize (pLog->pPerfData,
526: MemorySize (pLog->pPerfData) +
527: dwPerfDataIncrease) ;
528: if (!pLog->pPerfData)
529: return (FALSE) ;
530: }
531: else
532: {
533: return (FALSE) ;
534: }
535: } // while
536: }
537:
538: void LogWriteIndexBlock (PLOG pLog)
539: {
540: FileSeekBegin (pLog->hFile,
541: pLog->lIndexBlockOffset) ;
542: pLogIndexBlock->lNextBlockOffset = 0 ;
543: FileWrite (pLog->hFile,
544: (LPSTR) pLogIndexBlock,
545: sizeof (LOGINDEXBLOCK)) ;
546: } // LogWriteIndexBlock
547:
548:
549: BOOL LogWriteIndex (PLOG pLog,
550: UINT uFlags,
551: SYSTEMTIME *pSystemTime,
552: LONG lDataOffset,
553: int iSystemsLogged)
554: { // LogWriteIndex
555: LOGINDEX Index ;
556: long lNextBlockOffset ;
557: BOOL WriteOK ;
558: //=============================//
559: // Add Index Block Entry //
560: //=============================//
561: //=============================//
562: // Index Block Full? //
563: //=============================//
564:
565: WriteOK = TRUE ;
566:
567: if (pLog->iIndex == LogFileBlockMaxIndexes - 1)
568: {
569: lNextBlockOffset = FileTell (pLog->hFile) ;
570: pLogIndexBlock->lNextBlockOffset = lNextBlockOffset ;
571: FileSeekBegin (pLog->hFile,
572: pLog->lIndexBlockOffset) ;
573: WriteOK = FileWrite (pLog->hFile,
574: (LPSTR) pLogIndexBlock,
575: sizeof (LOGINDEXBLOCK)) ;
576: if (WriteOK)
577: {
578: FileSeekBegin (pLog->hFile,
579: lNextBlockOffset) ;
580: // Fake file end until we really write the block
581: pLogIndexBlock->iNumIndexes = 0 ;
582: pLogIndexBlock->lNextBlockOffset = 0 ;
583: WriteOK = FileWrite (pLog->hFile,
584: (LPSTR) pLogIndexBlock,
585: sizeof (LOGINDEXBLOCK)) ;
586: if (WriteOK)
587: {
588: pLog->lIndexBlockOffset = lNextBlockOffset ;
589: pLog->iIndex = 0 ;
590: pLog->lFileSize += sizeof (LOGINDEXBLOCK) ;
591: }
592: }
593: } // if
594:
595: //=============================//
596: // Add Index Block Entry //
597: //=============================//
598:
599: Index.uFlags = uFlags ;
600: Index.SystemTime = *pSystemTime ;
601: Index.lDataOffset = lDataOffset ;
602: Index.iSystemsLogged = iSystemsLogged ;
603:
604: pLogIndexBlock->aIndexes [pLog->iIndex] = Index ;
605: pLog->iIndex++ ;
606: pLogIndexBlock->iNumIndexes++ ;
607:
608: // write out the index block if the log interval if too large
609: if (pLog->iIntervalMSecs >= LARGE_INTERVAL * 1000 )
610: {
611: LONG lCurPosition ;
612:
613: // save the current file position
614: lCurPosition = FileTell (pLog->hFile) ;
615:
616: // flush the index block to the file
617: LogWriteIndexBlock (pLog) ;
618:
619: // restore previous file position since
620: // LogWriteIndexBlock has messed it up
621: FileSeekBegin (pLog->hFile, lCurPosition) ;
622: }
623: return (WriteOK) ;
624: } // LogWriteIndex
625:
626:
627:
628: BOOL LogWritePerfData (HWND hWnd,
629: PLOG pLog,
630: PPERFDATA pPerfData,
631: SYSTEMTIME *pSystemTime,
632: DWORD iNumSystems,
633: BOOL bWriteIndex)
634: { // LogWritePerfData
635: LONG lSize ;
636: BOOL WriteOK ;
637: LONG lCurPosition ;
638:
639: lSize = pPerfData->TotalByteLength ;
640:
641: lCurPosition = FileTell (pLog->hFile) ;
642:
643: //=============================//
644: // Write Perf Data //
645: //=============================//
646:
647: WriteOK = FileWrite (pLog->hFile, (LPSTR) pPerfData, lSize) ;
648: if (WriteOK)
649: {
650: pLog->lFileSize += lSize ;
651:
652: if (bWriteIndex)
653: {
654: WriteOK = LogWriteIndex (pLog,
655: LogFileIndexData,
656: pSystemTime,
657: lCurPosition,
658: iNumSystems) ;
659: }
660: }
661: if ( !WriteOK )
662: {
663: CloseLog (hWnd, pLog) ;
664: PrepareMenu (GetMenu (hWndMain)) ;
665: UpdateLogDisplay (hWnd) ;
666: DlgErrorBox (hWnd, ERR_LOG_FILE, pLog->szFilePath) ;
667: }
668: return (WriteOK) ;
669: } // LogWritePerfData
670:
671:
672: //==========================================================================//
673: // Message Handlers //
674: //==========================================================================//
675:
676:
677: void static OnSize (HWND hDlg,
678: int xWidth,
679: int yHeight)
680: /*
681: Effect: Perform any actions necessary when the log window (dialog)
682: is resized. In particular, move and resize some of the
683: dialogs controls.
684:
685: Internals: The rightmost control, the log status, contains one of
686: only several values. These values are all within
687: xStatusWidth, computed at init time. Put this control
688: one scroll width away from the right edge at fixed
689: width. Move its associated text prompt with it. Then
690: use the remaining space for the filename control, which
691: can probably use it.
692:
693: To Do: Need to consider minimum first.
694: */
695: { // OnSize
696: int xStatusPos ;
697: int xStatusTextPos ;
698: int xNameWidth ;
699: int xMinWidth ;
700:
701: //=============================//
702: // Enough space for minimums? //
703: //=============================//
704:
705: xMinWidth =
706: xScrollWidth + // margin before prompt
707: DialogWidth (hDlg, IDD_LOGFILETEXT) + // width of prompt
708: xNameMinWidth + // width of name
709: xScrollWidth +
710: DialogWidth (hDlg, IDD_LOGSTATUSTEXT) +
711: DialogWidth (hDlg, IDD_LOGSTATUS) +
712: xScrollWidth ;
713:
714:
715: xStatusPos = xWidth - xStatusWidth - xScrollWidth ;
716: DialogMove (hDlg, IDD_LOGSTATUS,
717: xStatusPos, NOCHANGE,
718: xStatusWidth, NOCHANGE) ;
719:
720: xStatusTextPos = xStatusPos -
721: DialogWidth (hDlg, IDD_LOGSTATUSTEXT) -
722: xScrollWidth ;
723: DialogMove (hDlg, IDD_LOGSTATUSTEXT,
724: xStatusTextPos, NOCHANGE,
725: NOCHANGE, NOCHANGE) ;
726:
727: xNameWidth = xStatusTextPos -
728: DialogWidth (hDlg, IDD_LOGFILETEXT) -
729: 2 * xScrollWidth ;
730: DialogMove (hDlg, IDD_LOGFILE,
731: NOCHANGE, NOCHANGE,
732: xNameWidth, NOCHANGE) ;
733:
734: DialogMove (hDlg, IDD_LOGSIZE,
735: DialogXPos (hDlg, IDD_LOGFILE), NOCHANGE,
736: DialogWidth (hDlg, IDD_LOGFILE), NOCHANGE) ;
737:
738: DialogMove (hDlg, IDD_LOGINTERVALTEXT,
739: DialogXPos (hDlg, IDD_LOGSTATUSTEXT), NOCHANGE,
740: DialogWidth (hDlg, IDD_LOGSTATUSTEXT), NOCHANGE) ;
741:
742: DialogMove (hDlg, IDD_LOGINTERVAL,
743: DialogXPos (hDlg, IDD_LOGSTATUS), NOCHANGE,
744: DialogWidth (hDlg, IDD_LOGSTATUS), NOCHANGE) ;
745:
746: DialogMove (hDlg, IDD_LOGENTRIESTEXT,
747: xScrollWidth, NOCHANGE, NOCHANGE, NOCHANGE) ;
748:
749: DialogMove (hDlg, IDD_LOGENTRIES,
750: xScrollWidth, NOCHANGE,
751: xWidth - 2 * xScrollWidth,
752: yHeight - DialogYPos (hDlg, IDD_LOGENTRIES) - yScrollHeight) ;
753: WindowInvalidate (hDlg) ;
754: } // OnSize
755:
756:
757: int OnCtlColor (HWND hDlg,
758: HDC hDC)
759: {
760: SetTextColor (hDC, crBlack) ;
761: SetBkColor (hDC, crLightGray) ;
762: return ((int) hbLightGray) ;
763: }
764:
765:
766: void static OnInitDialog (HWND hDlg)
767: {
768: HDC hDC ;
769: PLOG pLog ;
770:
771: hWndLogEntries = DialogControl (hDlg, IDD_LOGENTRIES) ;
772:
773: pLog = AllocateLogData (hDlg) ;
774: if (!pLog)
775: return ;
776:
777: StringLoad (IDS_CLOSED, szClosed) ;
778: // StringLoad (IDS_PAUSED, szPaused) ;
779: StringLoad (IDS_COLLECTING, szCollecting) ;
780: UpdateLogDisplay (hDlg) ;
781:
782: hDC = GetDC (hDlg) ;
783: xStatusWidth = max (TextWidth (hDC, szClosed),
784: TextWidth (hDC, szCollecting)) ;
785: // max (TextWidth (hDC, szPaused),
786: // TextWidth (hDC, szCollecting))) ;
787: xStatusWidth += xScrollWidth ;
788:
789: xNameMinWidth = TextAvgWidth (hDC, LogNameMinLen) ;
790: ReleaseDC (hDlg, hDC) ;
791: }
792:
793:
794:
795: void static OnDestroy (HWND hWnd)
796: /*
797: Effect: Perform any actions necessary when a LogDisplay window
798: is being destroyed. In particular, free the instance
799: data for the log.
800:
801: Since we really only have one log window and one global
802: log data structure, we don't free the structure. We do,
803: however, delete the objects allocated within the structure.
804: */
805: { // OnDestroy
806: PLOG pLog ;
807:
808: pLog = LogData (hWnd) ;
809: FreeLogData (pLog) ;
810: } // OnDestroy
811:
812:
813: void static OnDrawItem (HWND hWnd, LPDRAWITEMSTRUCT lpDI)
814: { // OnDrawItem
815: HDC hDC ;
816: RECT rectComputer, rectObject ;
817: PLOGENTRY pLogEntry ;
818: PLOG pLog ;
819: COLORREF preBkColor ;
820: COLORREF preTextColor ;
821:
822: pLog = LogData (hWnd) ;
823:
824: pLogEntry = LogEntryN (hWndLogEntries, DIIndex (lpDI)) ;
825:
826: // LogEntryN (SendMessage) will return LB_ERR for error, have to
827: // check for that case
828: if (!pLogEntry || pLogEntry == (PLOGENTRY)LB_ERR)
829: {
830: return ;
831: }
832:
833: hDC = lpDI->hDC ;
834:
835: SelectFont (hDC, hFontScales) ;
836:
837: if (DISelected (lpDI))
838: { // if
839: preTextColor = SetTextColor (hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)) ;
840: preBkColor = SetBkColor (hDC, GetSysColor (COLOR_HIGHLIGHT)) ;
841: } // if
842:
843: rectObject.left = lpDI->rcItem.left ;
844: rectObject.top = lpDI->rcItem.top ;
845: rectObject.right = rectObject.left + pLog->xCol1Width ;
846: rectObject.bottom = lpDI->rcItem.bottom ;
847:
848: ExtTextOut (hDC,
849: rectObject.left + xScrollWidth, rectObject.top,
850: ETO_OPAQUE,
851: &rectObject,
852: pLogEntry->szObject,
853: lstrlen (pLogEntry->szObject),
854: NULL) ;
855:
856:
857: rectComputer.left = rectObject.right ;
858: rectComputer.top = lpDI->rcItem.top ;
859: rectComputer.right = lpDI->rcItem.right ;
860: rectComputer.bottom = lpDI->rcItem.bottom ;
861:
862: ExtTextOut (hDC,
863: rectComputer.left, rectComputer.top,
864: ETO_OPAQUE,
865: &rectComputer,
866: pLogEntry->szComputer,
867: lstrlen (pLogEntry->szComputer),
868: NULL) ;
869:
870: if (DIFocus (lpDI))
871: DrawFocusRect (hDC, &(lpDI->rcItem)) ;
872:
873: if (DISelected (lpDI))
874: { // if
875: preTextColor = SetTextColor (hDC, preTextColor) ;
876: preBkColor = SetBkColor (hDC, preBkColor) ;
877: } // if
878: // RestoreDC (hDC, -1) ;
879: } // OnDrawItem
880:
881:
882:
883: //==========================================================================//
884: // Exported Functions //
885: //==========================================================================//
886:
887:
888: int APIENTRY LogDisplayDlgProc (HWND hDlg,
889: unsigned iMessage,
890: WPARAM wParam,
891: LONG lParam)
892: /*
893: Note: This function must be exported in the application's
894: linker-definition file, perfmon.def.
895: */
896: { // LogDisplayDlgProc
897: // HDC hDC ;
898:
899: switch (iMessage)
900: {
901: case WM_INITDIALOG:
902: OnInitDialog (hDlg) ;
903: break ;
904:
905: case WM_CTLCOLORDLG:
906: case WM_CTLCOLOREDIT:
907: case WM_CTLCOLORBTN:
908: case WM_CTLCOLORSTATIC:
909: return (OnCtlColor (hDlg, (HDC) wParam)) ;
910: break ;
911:
912: case WM_DRAWITEM:
913: OnDrawItem (hDlg, (LPDRAWITEMSTRUCT) lParam) ;
914: break ;
915:
916: case WM_LBUTTONDBLCLK:
917: SendMessage (hWndMain, WM_LBUTTONDBLCLK, wParam, lParam) ;
918: break ;
919:
920: case WM_LBUTTONDOWN:
921: DoWindowDrag (lParam) ;
922: break ;
923:
924: case WM_SIZE:
925: OnSize (hDlg, LOWORD (lParam), HIWORD (lParam)) ;
926: break ;
927:
928: case WM_TIMER:
929: LogTimer (hDlg, FALSE) ;
930: break ;
931:
932: case WM_DESTROY:
933: OnDestroy (hDlg) ;
934: return (FALSE) ;
935: break ;
936:
937: default:
938: return (FALSE) ;
939: } // switch
940:
941: return (TRUE) ;
942: } // LogDisplayDlgProc
943:
944:
945: #if 0
946: PLOG LogData (HWND hWndLog)
947: {
948: return (&Log) ;
949: }
950: #endif
951:
952: HWND CreateLogWindow (HWND hWndParent)
953: /*
954: Effect: Create the Log window. This window is a child of
955: hWndMain.
956:
957: Note: We dont worry about the size here, as this window
958: will be resized whenever the main window is resized.
959:
960: */
961: { // CreateLogWindow
962: HWND hWnd ;
963: hWnd = CreateDialog (hInstance,
964: MAKEINTRESOURCE (idDlgLogDisplay),
965: hWndParent,
966: (DLGPROC) LogDisplayDlgProc) ;
967:
968: return (hWnd) ;
969: } // CreateLogWindow
970:
971:
972:
973: void UpdateLogDisplay (HWND hWnd)
974: /*
975: Effect: Set the values for the various controls in the log
976: display.
977:
978: Called By: OnInitDialog, any other routines that change these
979: values.
980: */
981: { // UpdateLogDisplay
982: PLOG pLog ;
983: WCHAR szSize [MiscTextLen + 1] ;
984:
985: pLog = LogData (hWnd) ;
986:
987: DialogSetString (hWnd, IDD_LOGFILE, pLog->szFilePath) ;
988:
989: // position the cursor at the end of the text
990: EditSetTextEndPos (hWnd, IDD_LOGFILE) ;
991:
992:
993: DialogSetString (hWnd, IDD_LOGSTATUS, StatusText (pLog->iStatus)) ;
994:
995: LongToCommaString (pLog->lFileSize, szSize) ;
996: DialogSetString (hWnd, IDD_LOGSIZE, szSize) ;
997:
998: DialogSetInterval (hWnd, IDD_LOGINTERVAL, pLog->iIntervalMSecs) ;
999: } // UpdateLogDisplay
1000:
1001:
1002: BOOL LogInitializeApplication (void)
1003: {
1004: return (TRUE) ;
1005: } // LogInitializeApplication
1006:
1007:
1008: void SetLogTimer (HWND hWnd,
1009: int iIntervalMSecs)
1010: {
1011: PLOG pLog ;
1012:
1013: pLog = LogData (hWnd) ;
1014: pLog->iIntervalMSecs = iIntervalMSecs ;
1015:
1016: KillTimer (hWnd, LogTimerID) ;
1017: SetTimer (hWnd, LogTimerID, pLog->iIntervalMSecs, NULL) ;
1018: }
1019:
1020:
1021: void ClearLogTimer (HWND hWnd)
1022: {
1023: KillTimer (hWnd, LogTimerID) ;
1024: }
1025:
1026:
1027:
1028: BOOL CloseLogStopTimer (HWND hWnd, PLOG pLog)
1029: {
1030: CloseHandle (pLog->hFile) ;
1031:
1032: pLog->hFile = 0 ;
1033: pLog->iStatus = iPMStatusClosed ;
1034:
1035: ClearLogTimer (hWnd) ;
1036:
1037: return (TRUE) ;
1038: }
1039:
1040:
1041: BOOL CloseLog (HWND hWnd, PLOG pLog)
1042: { // CloseLog
1043: LogWriteIndexBlock (pLog) ;
1044: CloseLogStopTimer (hWnd, pLog) ;
1045: WindowInvalidate (hWndStatus) ;
1046: return (TRUE) ;
1047: } // CloseLog
1048:
1049: BOOL StartLog (HWND hWnd, PLOG pLog, BOOL bSameFile)
1050: {
1051: int RetCode ;
1052: SYSTEMTIME SystemTime ;
1053:
1054: if ((RetCode = CreateLogFile (pLog, TRUE, bSameFile)) == 0)
1055: {
1056: pLog->iStatus = iPMStatusCollecting ;
1057:
1058: GetLocalTime (&SystemTime) ;
1059:
1060: // write a dummy record.
1061: // this is needed because when playingback log
1062: // it will skip the first index from the first
1063: // index block.
1064: LogWriteIndex (pLog, 0, &SystemTime, 0, 0) ;
1065:
1066: if (!PlayingBackLog())
1067: {
1068: // write out a bookmark to indicate start of new data
1069: LogWriteStartBookmark (hWnd, &SystemTime) ;
1070: }
1071:
1072: if (!PlayingBackLog () && !(pLog->bManualRefresh))
1073: {
1074: SetLogTimer (hWnd, pLog->iIntervalMSecs) ;
1075: WindowInvalidate (hWndStatus) ;
1076: }
1077:
1078: // write counter names if needed
1079: LogWriteSystemCounterNames (hWnd, pLog) ;
1080:
1081: return (TRUE) ;
1082: }
1083:
1084: pLog->hFile = 0 ;
1085: CloseLogStopTimer(hWnd, pLog);
1086: PrepareMenu (GetMenu (hWndMain)) ;
1087: UpdateLogDisplay (hWnd) ;
1088: DlgErrorBox (hWnd, RetCode, pLog->szFilePath);
1089: return (FALSE) ;
1090: }
1091:
1092:
1093:
1094: DWORD LogFindEntry(LPTSTR lpszComputer, DWORD ObjectTitleIndex)
1095: /*
1096: Effect: Returns the index of the specified Computer/Object
1097: if it already exists in the Entries List Box,
1098: otherwise returns LOG_ENTRY_NOT_FOUND
1099: */
1100: {
1101: DWORD iLogEntry ;
1102: DWORD iLogNum ;
1103: PLOGENTRY pLogEntry ;
1104:
1105: iLogNum = (DWORD) LBNumItems(hWndLogEntries) ;
1106: for (iLogEntry = 0;
1107: iLogEntry < iLogNum ;
1108: iLogEntry++)
1109: {
1110: pLogEntry = (PLOGENTRY) LBData(hWndLogEntries, iLogEntry) ;
1111: if (pLogEntry->ObjectTitleIndex == ObjectTitleIndex &&
1112: strsamei(pLogEntry->szComputer, lpszComputer))
1113: {
1114: return iLogEntry ;
1115: }
1116: }
1117: return (DWORD) LOG_ENTRY_NOT_FOUND;
1118: }
1119:
1120:
1121:
1122: BOOL LogAddEntry (HWND hWndLog,
1123: LPTSTR lpszComputer,
1124: LPTSTR lpszObject,
1125: DWORD ObjectTitleIndex)
1126: /*
1127: Effect: Add an entry in the log structure for the computer and
1128: object to be logged.
1129:
1130: Returns: Whether the operation could be performed.
1131: */
1132: { // LogAddEntry
1133: PLOG pLog ;
1134: PLOGENTRY pLogEntry ;
1135: UINT iIndex ;
1136:
1137:
1138: pLog = LogData (hWndLog) ;
1139:
1140: SystemAdd (&(pLog->pSystemFirst), lpszComputer) ;
1141:
1142: pLogEntry = MemoryAllocate (sizeof (LOGENTRY)) ;
1143: if (!pLogEntry)
1144: return (FALSE) ;
1145:
1146: lstrcpy (pLogEntry->szComputer, lpszComputer) ;
1147: lstrcpy (pLogEntry->szObject, lpszObject) ;
1148: pLogEntry->ObjectTitleIndex = ObjectTitleIndex ;
1149:
1150: iIndex = LBAdd (hWndLogEntries, pLogEntry) ;
1151:
1152: if (iIndex == LB_ERR)
1153: {
1154: iIndex = 0 ;
1155: }
1156:
1157: LBSetSelection (hWndLogEntries, iIndex) ;
1158: LBSetVisible (hWndLogEntries, iIndex) ;
1159:
1160: LogEntriesChanged (hWndLogEntries) ;
1161:
1162: LogAddEntryToList (&(pLog->pLogEntryFirst), pLogEntry) ;
1163:
1164:
1165: } // LogAddEntry
1166:
1167:
1168:
1169:
1170: BOOL ToggleLogRefresh (HWND hWnd)
1171: { // ToggleLogRefresh
1172: PLOG pLog ;
1173:
1174: pLog = LogData (hWnd) ;
1175:
1176: if (pLog->bManualRefresh)
1177: SetLogTimer (hWnd, pLog->iIntervalMSecs) ;
1178: else
1179: ClearLogTimer (hWnd) ;
1180:
1181: pLog->bManualRefresh = !pLog->bManualRefresh ;
1182: return (pLog->bManualRefresh) ;
1183: } // ToggleLogRefresh
1184:
1185: BOOL LogRefresh (HWND hWnd)
1186: { // LogRefresh
1187: PLOG pLog ;
1188:
1189: pLog = LogData (hWnd) ;
1190:
1191: return (pLog->bManualRefresh) ;
1192: } // LogRefresh
1193:
1194:
1195: int SelectLogObjects(LPTSTR lpszComputer,
1196: PPERFDATA pPerfData,
1197: PPERFDATA *ppLogData)
1198: /*
1199: Effect: This routine copies the header from pPerfData
1200: to pLogData and initializes the byte length and the
1201: number of objects. It then copies the previously
1202: selected objects from pPerfData to pLogData. If
1203: pLogData must be enlarged to accomodate the new data,
1204: this routine will enlarge it.
1205:
1206: Returns: An updated pLogData, and TRUE if at least one object
1207: was copied.
1208:
1209: */
1210:
1211: {
1212: PLOGENTRY pLogEntry ;
1213: PPERF_OBJECT_TYPE
1214: pObject ;
1215: DWORD TotalBytes ;
1216: DWORD NumObjects ;
1217: PBYTE pNextObject ;
1218: DWORD MaxLogDataSize ;
1219: PLOG pLog ;
1220:
1221: if (!*ppLogData || !pPerfData)
1222: return -1 ;
1223:
1224: memcpy (*ppLogData, pPerfData, pPerfData->HeaderLength) ;
1225: TotalBytes = pPerfData->HeaderLength ;
1226: MaxLogDataSize = MemorySize(*ppLogData) ;
1227: NumObjects = 0;
1228:
1229:
1230: pLog = LogData (hWndLog) ;
1231:
1232: for (pLogEntry = pLog->pLogEntryFirst ;
1233: pLogEntry ;
1234: pLogEntry = pLogEntry->pNextLogEntry)
1235: { // for
1236: if (strsamei(pLogEntry->szComputer, lpszComputer))
1237: {
1238: pObject = GetObjectDefByTitleIndex(pPerfData,
1239: pLogEntry->ObjectTitleIndex) ;
1240:
1241: if (pObject)
1242: {
1243:
1244: if (MaxLogDataSize < TotalBytes + pObject->TotalByteLength)
1245: {
1246: *ppLogData = MemoryResize(*ppLogData,
1247: TotalBytes + pObject->TotalByteLength) ;
1248: if (!*ppLogData)
1249: return -1 ;
1250:
1251: }
1252:
1253: pNextObject = (PBYTE) *ppLogData + TotalBytes ;
1254: memcpy (pNextObject, pObject, pObject->TotalByteLength);
1255: TotalBytes += pObject->TotalByteLength ;
1256: NumObjects++;
1257: }
1258: else
1259: {
1260: }
1261: }
1262: } // for
1263:
1264: if (!NumObjects)
1265: return 1 ;
1266:
1267: (*ppLogData)->TotalByteLength = TotalBytes ;
1268: (*ppLogData)->NumObjectTypes = NumObjects ;
1269:
1270: return 0 ;
1271: }
1272:
1273:
1274: void LogTimer (HWND hWnd, BOOL bForce)
1275: /*
1276: Effect: Perform all actions necessary when the log window
1277: receives a timer tic. In particular, if we are
1278: collecting data, get a new perf_data_block and add a
1279: header entry. If the header block is full, write the
1280: data to disk.
1281:
1282: Called By: LogDisplayDlgProc, in response to a WM_TIMER message.
1283: */
1284: { // OnTimer
1285: PLOG pLog ;
1286: PPERFSYSTEM pSystem ;
1287: BOOL bWriteIndex ;
1288: DWORD iNumSystems ;
1289: SYSTEMTIME SystemTime ;
1290: int iNoUseSystemDetected = 0 ;
1291:
1292: pLog = LogData (hWnd) ;
1293:
1294: if (pLog->iStatus != iPMStatusCollecting)
1295: return ;
1296:
1297: if (bForce || !pLog->bManualRefresh)
1298: {
1299: iNumSystems = SystemCount(pLog->pSystemFirst) ;
1300: bWriteIndex = TRUE ;
1301: for (pSystem = pLog->pSystemFirst ;
1302: pSystem ;
1303: pSystem = pSystem->pSystemNext)
1304: { // for
1305: if (UpdateSystemData (pSystem, &pLog->pPerfData))
1306: {
1307: if (bWriteIndex)
1308: {
1309: GetLocalTime (&SystemTime) ;
1310: }
1311:
1312: if (SelectLogObjects(pSystem->sysName,
1313: pLog->pPerfData,
1314: &pLog->pLogData) == 0)
1315: {
1316: if ( !LogWritePerfData (hWnd, pLog, pLog->pLogData, &SystemTime,
1317: iNumSystems, bWriteIndex) )
1318: {
1319: CloseLogStopTimer(hWnd, pLog) ;
1320: return ;
1321: }
1322: // write an index for only the first system
1323: bWriteIndex = FALSE ;
1324: }
1325: else
1326: {
1327: if (!bAddLineInProgress)
1328: {
1329: pSystem->bSystemNoLongerNeeded = TRUE ;
1330: iNoUseSystemDetected ++ ;
1331: }
1332: }
1333: }
1334: } // for
1335:
1336: if (!bWriteIndex)
1337: {
1338: UpdateLogSize (hWnd) ;
1339: }
1340: } // if
1341:
1342: if (iNoUseSystemDetected)
1343: {
1344: DeleteUnusedSystems (&(pLog->pSystemFirst), iNoUseSystemDetected) ;
1345: }
1346: } // LogTimer
1347:
1348:
1349:
1350: BOOL NextIntervalIndexPosition (PLOG pLog, PLOGPOSITION pLP, int *pNumTics)
1351: {
1352: SYSTEMTIME SystemTime1 ;
1353: SYSTEMTIME SystemTime2 ;
1354: LOGPOSITION LP ;
1355: PLOGINDEX pIndex ;
1356: DWORD TimeDiff ;
1357:
1358: LogPositionSystemTime (pLP, &SystemTime1) ;
1359:
1360: LP = *pLP ;
1361:
1362: while (NextReLogIndexPosition (&LP))
1363: { // while
1364:
1365: *pNumTics = *pNumTics - 1 ;
1366:
1367: pIndex = IndexFromPosition (&LP) ;
1368: if (pIndex && IsBookmarkIndex (pIndex))
1369: {
1370: *pLP = LP ;
1371: return TRUE ;
1372: }
1373: LogPositionSystemTime (&LP, &SystemTime2) ;
1374: TimeDiff = (DWORD) SystemTimeDifference (&SystemTime1, &SystemTime2) ;
1375: if (TimeDiff * 1000 >= pLog->iIntervalMSecs)
1376: { // if
1377: *pLP = LP ;
1378: return (TRUE) ;
1379: } // if
1380: } // while
1381:
1382: return (FALSE) ;
1383: } // NextIntervalIndexPosition
1384:
1385:
1386:
1387: BOOL ReLogTimer (HWND hWnd,
1388: PLOG pLog,
1389: LOGPOSITION lp,
1390: BOOL *pWriteBookmark)
1391: { // ReLogTimer
1392: PPERFSYSTEM pSystem ;
1393: BOOL bWriteIndex ;
1394: DWORD iNumSystems ;
1395: SYSTEMTIME SystemTime ;
1396: PPERFDATA pPerfData ;
1397:
1398: bWriteIndex = TRUE ;
1399:
1400: // First count number of systems to be logged
1401:
1402: iNumSystems = 0;
1403:
1404: for (pSystem = pLog->pSystemFirst ;
1405: pSystem ;
1406: pSystem = pSystem->pSystemNext)
1407: { // for
1408: pPerfData = LogDataFromPosition (pSystem, &lp) ;
1409: if (pPerfData)
1410: {
1411: if (SelectLogObjects(pSystem->sysName,
1412: pPerfData,
1413: &pLog->pLogData) == 0)
1414: {
1415: iNumSystems++;
1416: }
1417: }
1418: } // for
1419:
1420: // Now we can log the data
1421:
1422: for (pSystem = pLog->pSystemFirst ;
1423: pSystem ;
1424: pSystem = pSystem->pSystemNext)
1425: { // for
1426: pPerfData = LogDataFromPosition (pSystem, &lp) ;
1427: if (pPerfData)
1428: {
1429: // write an index for only the first system
1430: LogPositionSystemTime (&lp, &SystemTime) ;
1431: if (SelectLogObjects(pSystem->sysName,
1432: pPerfData,
1433: &pLog->pLogData) == 0)
1434: {
1435: if (*pWriteBookmark)
1436: {
1437: // only need to write the start bookmark once.
1438: *pWriteBookmark = FALSE ;
1439: LogWriteStartBookmark (hWnd, &SystemTime) ;
1440: }
1441: if ( !LogWritePerfData (hWnd, pLog, pLog->pLogData, &SystemTime,
1442: iNumSystems, bWriteIndex) )
1443: {
1444: CloseLogStopTimer(hWnd, pLog) ;
1445: return FALSE ;
1446: }
1447: else
1448: {
1449: // write the index for only the first system logged
1450: bWriteIndex = FALSE ;
1451: }
1452: }
1453: }
1454: } // for
1455:
1456: return TRUE ;
1457: } // ReLogTimer
1458:
1459:
1460: void ReLog (HWND hWndLog, BOOL bSameFile)
1461: { // PlaybackLog
1462: PLOG pLog ;
1463: LOGPOSITION lp ;
1464: // SYSTEMTIME SystemTime ;
1465: PLOGINDEX pIndex ;
1466: PBOOKMARK pBookmark;
1467: int iDisplayTics ;
1468:
1469: // bWriteBookmark tell relogtimer to write start bookmark
1470: BOOL bWriteBookmark = TRUE ;
1471:
1472: pLog = LogData (hWndLog) ;
1473: StartLog (hWndLog, pLog, bSameFile) ;
1474:
1475: lp = PlaybackLog.StartIndexPos ;
1476: iDisplayTics = PlaybackLog.iSelectedTics;
1477:
1478: while (iDisplayTics > 0)
1479: {
1480: pIndex = IndexFromPosition (&lp) ;
1481: if (pIndex)
1482: {
1483: if (IsBookmarkIndex (pIndex))
1484: {
1485: pBookmark = (PBOOKMARK) PlaybackSeek (pIndex->lDataOffset) ;
1486: if (!LogWriteBookmarkData (hWndLog, pBookmark))
1487: break;
1488: }
1489: else if (!ReLogTimer (hWndLog, pLog, lp, &bWriteBookmark))
1490: break ;
1491: }
1492:
1493: if (!NextIntervalIndexPosition (pLog, &lp, &iDisplayTics))
1494: break ;
1495:
1496: } // while
1497: UpdateLogSize (hWndLog) ;
1498: CloseLog (hWndLog, pLog) ;
1499: } // ReLog
1500:
1501: // SaveLog is diff than other because we are not saving a "Line"
1502: // We are actually saving an entry in the hWndLogEntries listbox.
1503: // It only contains the system & object name.
1504: BOOL SaveLog (HWND hWndLog, HANDLE hInputFile, BOOL bGetFileName)
1505: {
1506: int iIndex, iIndexNum ;
1507: PLOG pLog ;
1508: PLOGENTRY pLogEntry ;
1509: LOGENTRY tempLogEntry ;
1510: HANDLE hFile ;
1511: DISKLOG DiskLog ;
1512: PERFFILEHEADER FileHeader ;
1513: TCHAR szFileName [256] ;
1514: BOOL newFileName = FALSE ;
1515:
1516: pLog = LogData (hWndLog) ;
1517: if (!pLog)
1518: {
1519: return (FALSE) ;
1520: }
1521:
1522: if (hInputFile)
1523: {
1524: // use the input file handle if it is available
1525: // this is the case for saving workspace data
1526: hFile = hInputFile ;
1527: }
1528: else
1529: {
1530: if (pLogFullFileName)
1531: {
1532: lstrcpy (szFileName, pLogFullFileName) ;
1533: }
1534: if (bGetFileName || pLogFullFileName == NULL)
1535: {
1536: // if (pLogFullFileName == NULL)
1537: // {
1538: // StringLoad (IDS_LOG_FNAME, szFileName) ;
1539: // }
1540:
1541: if (!FileGetName (hWndLog, IDS_LOGFILE, szFileName))
1542: {
1543: return (FALSE) ;
1544: }
1545: newFileName = TRUE ;
1546: }
1547:
1548: hFile = FileHandleCreate (szFileName) ;
1549:
1550: if (hFile && newFileName)
1551: {
1552: ChangeSaveFileName (szFileName, IDM_VIEWLOG) ;
1553: }
1554: else if (!hFile)
1555: {
1556: DlgErrorBox (hWndLog, ERR_CANT_OPEN, szFileName) ;
1557: }
1558: }
1559:
1560: if (!hFile)
1561: return (FALSE) ;
1562:
1563: iIndexNum = LBNumItems (hWndLogEntries) ;
1564:
1565: if (!hInputFile)
1566: {
1567: memset (&FileHeader, 0, sizeof (FileHeader)) ;
1568: lstrcpy (FileHeader.szSignature, szPerfLogSignature) ;
1569: FileHeader.dwMajorVersion = LogMajorVersion ;
1570: FileHeader.dwMinorVersion = LogMinorVersion ;
1571:
1572: if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
1573: {
1574: goto Exit0 ;
1575: }
1576: }
1577:
1578: DiskLog.dwIntervalSecs = pLog->iIntervalMSecs ;
1579: DiskLog.dwNumLines = iIndexNum ;
1580: DiskLog.bManualRefresh = pLog->bManualRefresh ;
1581: DiskLog.perfmonOptions = Options ;
1582:
1583: if (!FileWrite (hFile, &DiskLog, sizeof (DISKLOG)))
1584: {
1585: goto Exit0 ;
1586: }
1587:
1588: for (iIndex = 0 ;
1589: iIndex < iIndexNum ;
1590: iIndex++)
1591: { // for
1592: pLogEntry = LogEntryN (hWndLogEntries, iIndex) ;
1593: if (pstrsamei (pLogEntry->szComputer, LocalComputerName))
1594: {
1595: tempLogEntry = *pLogEntry ;
1596: lstrcpy (tempLogEntry.szComputer, LOCAL_SYS_CODE_NAME) ;
1597: if (!FileWrite (hFile,
1598: &tempLogEntry,
1599: sizeof(LOGENTRY)-sizeof(pLogEntry->pNextLogEntry)))
1600: {
1601: goto Exit0 ;
1602: }
1603: }
1604: else
1605: {
1606: if (!FileWrite (hFile,
1607: pLogEntry,
1608: sizeof(LOGENTRY)-sizeof(pLogEntry->pNextLogEntry)))
1609: {
1610: goto Exit0 ;
1611: }
1612: }
1613: } // for
1614:
1615: if (!hInputFile)
1616: {
1617: CloseHandle (hFile) ;
1618: }
1619:
1620: return (TRUE) ;
1621:
1622: Exit0:
1623: if (!hInputFile)
1624: {
1625: CloseHandle (hFile) ;
1626:
1627: // only need to report error if not workspace
1628: DlgErrorBox (hWndLog, ERR_SETTING_FILE, szFileName) ;
1629: }
1630: return (FALSE) ;
1631: }
1632:
1633: BOOL OpenLogVer1 (HWND hWndLog, HANDLE hFile, DISKLOG *pDiskLog, PLOG
1634: pLog, DWORD dwMinorVersion)
1635: {
1636: int iIndex, iIndexNum ;
1637: PLOGENTRY pLogEntry ;
1638: LOGENTRY LogEntry ;
1639: PPERFSYSTEM pSystem;
1640:
1641: pLog->iIntervalMSecs = pDiskLog->dwIntervalSecs ;
1642: if (dwMinorVersion < 3)
1643: {
1644: pLog->iIntervalMSecs *= 1000 ;
1645: }
1646:
1647: pLog->bManualRefresh = pDiskLog->bManualRefresh ;
1648: iIndexNum = pDiskLog->dwNumLines ;
1649:
1650: LBSetRedraw (hWndLogEntries, FALSE) ;
1651:
1652: for (iIndex = 0 ; iIndex < iIndexNum ; iIndex++)
1653: {
1654: if (!FileRead (hFile,
1655: &LogEntry,
1656: sizeof(LOGENTRY)-sizeof(LogEntry.pNextLogEntry)))
1657: {
1658: break ;
1659: }
1660:
1661: if (pstrsame (LogEntry.szComputer, LOCAL_SYS_CODE_NAME))
1662: {
1663: // convert it back to the local name
1664: lstrcpy (LogEntry.szComputer, LocalComputerName) ;
1665: }
1666:
1667: LogAddEntry (hWndLog,
1668: LogEntry.szComputer,
1669: LogEntry.szObject,
1670: LogEntry.ObjectTitleIndex) ;
1671: }
1672:
1673: LBSetRedraw (hWndLogEntries, TRUE) ;
1674:
1675: for (pSystem = pLog->pSystemFirst ;
1676: pSystem ;
1677: pSystem = pSystem->pSystemNext)
1678: {
1679: if (pSystem)
1680: {
1681: RemoveObjectsFromSystem (pSystem);
1682: }
1683: }
1684:
1685:
1686: for (iIndex = 0 ;
1687: iIndex < iIndexNum ;
1688: iIndex++)
1689: { // for all items in the list
1690: pLogEntry = LogEntryN (hWndLogEntries, iIndex) ;
1691:
1692: pSystem = SystemGet (pLog->pSystemFirst, pLogEntry->szComputer);
1693: if (pSystem) {
1694: AppendObjectToValueList (
1695: pLogEntry->ObjectTitleIndex,
1696: pSystem->lpszValue);
1697: }
1698: } // for
1699:
1700: return (TRUE) ;
1701: }
1702:
1703: BOOL OpenLog (HWND hWndLog,
1704: HANDLE hFile,
1705: DWORD dwMajorVersion,
1706: DWORD dwMinorVersion,
1707: BOOL bLogFile)
1708: {
1709: PLOG pLog ;
1710: DISKLOG DiskLog ;
1711: BOOL bSuccess = TRUE ;
1712:
1713: pLog = LogData (hWndLog) ;
1714: if (!pLog)
1715: {
1716: bSuccess = FALSE ;
1717: goto Exit0 ;
1718: }
1719:
1720: if (!FileRead (hFile, &DiskLog, sizeof (DISKLOG)))
1721: {
1722: bSuccess = FALSE ;
1723: goto Exit0 ;
1724: }
1725:
1726: switch (dwMajorVersion)
1727: {
1728: case (1):
1729:
1730: SetHourglassCursor() ;
1731:
1732: ResetLogView (hWndLog) ;
1733:
1734: OpenLogVer1 (hWndLog, hFile, &DiskLog, pLog, dwMinorVersion) ;
1735:
1736: // change to log view if we are opening a
1737: // log file
1738: if (bLogFile && iPerfmonView != IDM_VIEWLOG)
1739: {
1740: SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWLOG, 0L) ;
1741: }
1742:
1743: if (iPerfmonView == IDM_VIEWLOG)
1744: {
1745: SetPerfmonOptions (&DiskLog.perfmonOptions) ;
1746: }
1747:
1748: UpdateLogDisplay (hWndLog) ;
1749:
1750: SetArrowCursor() ;
1751:
1752: break ;
1753: }
1754:
1755: Exit0:
1756:
1757: if (bLogFile)
1758: {
1759: CloseHandle (hFile) ;
1760: }
1761:
1762: return (bSuccess) ;
1763: } // OpenLog
1764:
1765:
1766: BOOL LogCollecting (HWND hWndLog)
1767: /*
1768: Effect: Return whether the log associated with hWndLog is currently
1769: collecting data (writing performance values to disk).
1770: */
1771: { // LogCollecting
1772: PLOG pLog ;
1773:
1774: pLog = LogData (hWndLog) ;
1775:
1776: return (pLog->iStatus == iPMStatusCollecting) ;
1777: } // LogCollecting
1778:
1779:
1780: int LogFileSize (HWND hWndLog)
1781: {
1782: PLOG pLog ;
1783:
1784: pLog = LogData (hWndLog) ;
1785:
1786: return (pLog->lFileSize) ;
1787: }
1788:
1789: BOOL LogWriteStartBookmark (HWND hWnd, SYSTEMTIME *pSystemTime)
1790: {
1791: BOOKMARK Bookmark ;
1792: TCHAR NewDataBookmark [MiscTextLen] ;
1793:
1794: memset (&Bookmark, 0, sizeof (BOOKMARK)) ;
1795:
1796: NewDataBookmark [0] = TEXT('\0') ;
1797: StringLoad (IDS_NEWDATA_BOOKMARK, NewDataBookmark) ;
1798: Bookmark.SystemTime = *pSystemTime ;
1799: lstrcpy (Bookmark.szComment, NewDataBookmark) ;
1800:
1801: return (LogWriteBookmarkData (hWndLog, &Bookmark)) ;
1802: }
1803:
1804: BOOL LogWriteBookmarkData (HWND hWnd, PBOOKMARK pBookmark)
1805: {
1806: PLOG pLog ;
1807: LONG lDataOffset ;
1808: BOOL WriteOK ;
1809:
1810: pLog = LogData (hWndLog) ;
1811: if (!pLog)
1812: return (FALSE) ;
1813:
1814: lDataOffset = FileTell (pLog->hFile) ;
1815: WriteOK = FileWrite (pLog->hFile, pBookmark, sizeof (BOOKMARK)) ;
1816: if ( WriteOK )
1817: {
1818: pLog->lFileSize += sizeof (BOOKMARK) ;
1819: UpdateLogSize (hWndLog) ;
1820:
1821: WriteOK = LogWriteIndex (pLog, LogFileIndexBookmark,
1822: &(pBookmark->SystemTime),
1823: lDataOffset,
1824: 0) ;
1825: }
1826: if ( !WriteOK )
1827: {
1828: CloseLog (hWndLog, pLog) ;
1829: PrepareMenu (GetMenu (hWndMain)) ;
1830: UpdateLogDisplay (hWndLog) ;
1831: DlgErrorBox (hWndLog, ERR_LOG_FILE, pLog->szFilePath);
1832: }
1833: }
1834:
1835:
1836:
1837: BOOL LogWriteBookmark (HWND hWndLog,
1838: LPCTSTR lpszComment)
1839: { // LogWriteBookmark
1840: BOOKMARK Bookmark ;
1841:
1842: memset (&Bookmark, 0, sizeof (BOOKMARK)) ;
1843:
1844: GetLocalTime (&Bookmark.SystemTime) ;
1845: lstrcpy (Bookmark.szComment, lpszComment) ;
1846:
1847: return (LogWriteBookmarkData (hWndLog, &Bookmark)) ;
1848: } // LogWriteBookmark
1849:
1850:
1851: BOOL AnyLogLine (void)
1852: { // CurrentLogLine
1853: int iIndex ;
1854:
1855: iIndex = LBSelection (hWndLogEntries) ;
1856: if (iIndex == LB_ERR)
1857: {
1858: return (FALSE) ;
1859: }
1860: else
1861: {
1862: return (TRUE) ;
1863: }
1864: }
1865:
1866: void ResetLogView (HWND hWndLog)
1867: {
1868: PLOG pLog ;
1869:
1870: pLog = LogData (hWndLog) ;
1871:
1872: ChangeSaveFileName (NULL, IDM_VIEWLOG) ;
1873:
1874: if (pLog && pLog->pSystemFirst)
1875: {
1876: ResetLog (hWndLog) ;
1877: }
1878: } // ResetLogView
1879:
1880: BOOL ResetLog (HWND hWndLog)
1881: {
1882: int iIndex ;
1883: PLOG pLog ;
1884: int iEntriesNum ;
1885:
1886: pLog = LogData (hWndLog) ;
1887:
1888: if (LogCollecting (hWndLog))
1889: {
1890: CloseLog (hWndLog, pLog) ;
1891: }
1892:
1893: LBSetRedraw (hWndLogEntries, FALSE) ;
1894: iEntriesNum = LBNumItems (hWndLogEntries) ;
1895:
1896: // only need to zero out the list head
1897: // each item will be deleted by LogDeleteIndex via the listbox
1898: pLog->pLogEntryFirst = NULL ;
1899:
1900: // delete each line
1901: for (iIndex = iEntriesNum - 1 ;
1902: iIndex >= 0 ;
1903: iIndex-- )
1904: {
1905: LogDeleteIndex (hWndLogEntries, iIndex) ;
1906: }
1907:
1908: LBSetRedraw (hWndLogEntries, TRUE) ;
1909:
1910: if (pLog->pSystemFirst)
1911: {
1912: FreeSystems (pLog->pSystemFirst) ;
1913: pLog->pSystemFirst = NULL ;
1914: }
1915:
1916: MemoryFree (pLog->pPerfData) ;
1917: MemoryFree (pLog->pLogData) ;
1918:
1919: pLog->pPerfData = (PPERFDATA) MemoryAllocate (STARTING_SYSINFO_SIZE) ;
1920: pLog->pLogData = (PPERFDATA) MemoryAllocate (STARTING_SYSINFO_SIZE) ;
1921:
1922: LogEntriesChanged (hWndLogEntries) ;
1923:
1924: pLog->iStatus = iPMStatusClosed ;
1925: UpdateLogDisplay (hWndLog) ;
1926:
1927: return (TRUE) ;
1928: }
1929:
1930: BOOL LogDeleteEntry (HWND hWndLog)
1931: {
1932: int iIndex ;
1933: PLOG pLog ;
1934: BOOL retCode ;
1935: int iEntriesNum ;
1936:
1937: pLog = LogData (hWndLog) ;
1938:
1939: iIndex = LBSelection (hWndLogEntries) ;
1940:
1941: if (iIndex == LB_ERR)
1942: {
1943: retCode = FALSE ;
1944: }
1945: else
1946: {
1947: // remove the current selection
1948: LogDeleteIndex (hWndLogEntries, iIndex) ;
1949:
1950: iEntriesNum = LBNumItems (hWndLogEntries) ;
1951:
1952: if (iEntriesNum == 0 || iEntriesNum == LB_ERR)
1953: {
1954: // delete the last line or something bad happened,
1955: // then reset the window.
1956: ResetLog (hWndLog) ;
1957: }
1958: else
1959: {
1960: // set selection on the item above the deleted item.
1961: iIndex-- ;
1962: if (iIndex < 0)
1963: {
1964: iIndex = 0 ;
1965: }
1966: LBSetSelection (hWndLogEntries, iIndex) ;
1967: LBSetVisible (hWndLogEntries, iIndex) ;
1968: }
1969:
1970: LogEntriesChanged (hWndLogEntries) ;
1971: retCode = TRUE ;
1972: }
1973: return (retCode) ;
1974: }
1975:
1976:
1977: void ExportLog (void)
1978: {
1979: HANDLE hFile ;
1980: PLOG pLog ;
1981: PLOGENTRY pLogEntry ;
1982: int iIndex ;
1983: int iIndexNum ;
1984: CHAR TempBuff [LongTextLen] ;
1985: TCHAR UnicodeBuff [LongTextLen] ;
1986: TCHAR UnicodeBuff1 [MiscTextLen] ;
1987: int StringLen ;
1988: LPTSTR pFileName = NULL ;
1989: INT ErrCode = 0 ;
1990:
1991: if (!(pLog = LogData (hWndLog)))
1992: {
1993: return ;
1994: }
1995:
1996: // see if there is anything to export..
1997: iIndexNum = LBNumItems (hWndLogEntries) ;
1998: if (iIndexNum == 0 || iIndexNum == LB_ERR)
1999: {
2000: return ;
2001: }
2002:
2003: if (!FileGetName (hWndLog, IDS_EXPORTFILE, UnicodeBuff))
2004: {
2005: // user cancel
2006: return ;
2007: }
2008:
2009: pFileName = StringAllocate (UnicodeBuff) ;
2010:
2011: // open the file..
2012: if (!(hFile = FileHandleCreate (UnicodeBuff)))
2013: {
2014: // can't open the file
2015: ErrCode = ERR_CANT_OPEN ;
2016: return ;
2017: }
2018:
2019:
2020: SetHourglassCursor() ;
2021:
2022: // get header
2023: StringLoad (IDS_REPORT_HEADER, UnicodeBuff) ;
2024: ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
2025: StringLen = strlen (TempBuff) ;
2026: ConvertUnicodeStr (&TempBuff[StringLen], LocalComputerName) ;
2027: strcat (TempBuff, LineEndStr) ;
2028:
2029: if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
2030: {
2031: ErrCode = ERR_EXPORT_FILE ;
2032: goto Exit0 ;
2033: }
2034:
2035: if (!(strempty(pLog->szFilePath)))
2036: {
2037: // export filename is there is one
2038: StringLoad (IDS_REPORT_LOGFILE, UnicodeBuff) ;
2039: ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
2040: StringLen = strlen (TempBuff) ;
2041: ConvertUnicodeStr (&TempBuff[StringLen], pLog->szFilePath) ;
2042: strcat (TempBuff, LineEndStr) ;
2043:
2044: if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
2045: {
2046: ErrCode = ERR_EXPORT_FILE ;
2047: goto Exit0 ;
2048: }
2049: }
2050:
2051: // export interval
2052: StringLoad (IDS_CHARTINT_FORMAT, UnicodeBuff1) ;
2053: TSPRINTF (UnicodeBuff, UnicodeBuff1,
2054: (FLOAT) pLog->iIntervalMSecs / (FLOAT) 1000.0) ;
2055: ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
2056: strcat (TempBuff, LineEndStr) ;
2057: strcat (TempBuff, LineEndStr) ;
2058:
2059: if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
2060: {
2061: ErrCode = ERR_EXPORT_FILE ;
2062: goto Exit0 ;
2063: }
2064:
2065: // export Labels
2066: StringLoad (IDS_LABELOBJECT, UnicodeBuff) ;
2067: ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
2068: strcat (TempBuff, pDelimiter) ;
2069:
2070: if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
2071: {
2072: ErrCode = ERR_EXPORT_FILE ;
2073: goto Exit0 ;
2074: }
2075:
2076: StringLoad (IDS_LABELSYSTEM, UnicodeBuff) ;
2077: ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
2078: strcat (TempBuff, LineEndStr) ;
2079:
2080: if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
2081: {
2082: ErrCode = ERR_EXPORT_FILE ;
2083: goto Exit0 ;
2084: }
2085:
2086:
2087: // export each counter
2088: for (iIndex = 0 ; iIndex < iIndexNum ; iIndex++)
2089: { // for
2090:
2091: pLogEntry = LogEntryN (hWndLogEntries, iIndex) ;
2092:
2093: if (!pLogEntry || pLogEntry == (PLOGENTRY)LB_ERR)
2094: {
2095: continue ;
2096: }
2097:
2098: ConvertUnicodeStr (TempBuff, pLogEntry->szObject) ;
2099: strcat (TempBuff, pDelimiter) ;
2100:
2101: if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
2102: {
2103: ErrCode = ERR_EXPORT_FILE ;
2104: break ;
2105: }
2106:
2107: ConvertUnicodeStr (TempBuff, pLogEntry->szComputer) ;
2108: strcat (TempBuff, LineEndStr) ;
2109:
2110: if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
2111: {
2112: ErrCode = ERR_EXPORT_FILE ;
2113: break ;
2114: }
2115: }
2116:
2117: Exit0:
2118:
2119: SetArrowCursor() ;
2120: CloseHandle (hFile) ;
2121:
2122: if (pFileName)
2123: {
2124: if (ErrCode)
2125: {
2126: DlgErrorBox (hWndGraph, ErrCode, pFileName) ;
2127: }
2128: MemoryFree (pFileName) ;
2129: }
2130:
2131: } // ExportLog
2132:
2133:
2134: LPTSTR MatchSystemCounters (LPTSTR pBaseSysCounter,
2135: long lBaseSysSize,
2136: LPTSTR pSysCounter,
2137: long lSysSize,
2138: long *pMatchPortion)
2139: {
2140: LPTSTR pNotMatch = NULL ;
2141: long i, lSizeToCompare ;
2142:
2143: *pMatchPortion = 0 ;
2144: lSizeToCompare = min (lBaseSysSize, lSysSize) / sizeof (TCHAR) ;
2145:
2146: for (i = 0 ; i < lSizeToCompare ; i++, pBaseSysCounter++, pSysCounter++)
2147: {
2148: if (*pBaseSysCounter != *pSysCounter)
2149: {
2150: pNotMatch = pSysCounter ;
2151: break ;
2152: }
2153: }
2154:
2155: if (pNotMatch == NULL)
2156: {
2157: if (lBaseSysSize < lSysSize)
2158: {
2159: // the new system has longer counter names than base system
2160: // setup the extra portion.
2161: pNotMatch = pSysCounter ;
2162: }
2163: else
2164: {
2165: // new system counter name is shorter than or equal to
2166: // the base system counter names
2167: *pMatchPortion = lSysSize ;
2168: }
2169: }
2170:
2171: return (pNotMatch) ;
2172:
2173: }
2174:
2175: void LogWriteSystemCounterNames (HWND hWnd, PLOG pLog)
2176: {
2177: long dwArraySize ;
2178: PPERFSYSTEM pSystem = pLog->pSystemFirst ;
2179: LPTSTR pMatchLen ;
2180: LPTSTR pCounterName ;
2181: long lMatchLen, lMatchPortion ;
2182:
2183: for (pSystem = pLog->pSystemFirst ;
2184: pSystem ;
2185: pSystem = pSystem->pSystemNext)
2186: {
2187: if (pSystem->bSystemCounterNameSaved == TRUE)
2188: {
2189: // we have wrote out the counter name for
2190: // this system, skip it then.
2191: continue ;
2192: }
2193:
2194: dwArraySize = (pSystem->CounterInfo.dwLastId + 1 ) ;
2195:
2196: if (!pLog->lBaseCounterNameOffset)
2197: {
2198: LogWriteCounterName (hWnd, pSystem, pLog,
2199: (LPTSTR)(pSystem->CounterInfo.TextString + dwArraySize),
2200: 0,
2201: pSystem->CounterInfo.dwCounterSize,
2202: 0 ) ;
2203: }
2204: else
2205: {
2206: // check for matched characters between this system and the
2207: // base system
2208: pCounterName = (LPTSTR)(pSystem->CounterInfo.TextString + dwArraySize) ;
2209: pMatchLen = MatchSystemCounters (pLog->pBaseCounterName,
2210: pLog->lBaseCounterNameSize,
2211: pCounterName,
2212: pSystem->CounterInfo.dwCounterSize,
2213: &lMatchPortion) ;
2214:
2215: if (pMatchLen)
2216: {
2217: // This system matches part of the base system
2218: // (all if it has more names)
2219: lMatchLen = (long) (pMatchLen - pCounterName) * sizeof (TCHAR) ;
2220: LogWriteCounterName (hWnd, pSystem, pLog,
2221: pMatchLen,
2222: lMatchLen,
2223: pSystem->CounterInfo.dwCounterSize - lMatchLen,
2224: 0 ) ;
2225: }
2226: else
2227: {
2228: // This system matches the based system
2229: LogWriteCounterName (hWnd, pSystem, pLog,
2230: NULL,
2231: lMatchPortion,
2232: 0,
2233: 0 ) ;
2234: }
2235: }
2236: }
2237: } // LogWriteSystemCounterNames
2238:
2239:
2240: BOOL LogWriteCounterName (HWND hWnd,
2241: PPERFSYSTEM pSystem,
2242: PLOG pLog,
2243: LPTSTR pCounterName,
2244: long sizeMatched,
2245: long sizeOfData,
2246: BOOL bBaseCounterName)
2247: {
2248: BOOL ReadOK ;
2249: BOOL WriteOK ;
2250: SYSTEMTIME SystemTime ;
2251: LOGFILECOUNTERNAME CounterNameRecord ;
2252: LOGHEADER LogFileHeader ;
2253: long lDataOffset, lCurPosition ;
2254: TCHAR Dummy [sizeof(DWORD)] ;
2255: int PatchBytes ;
2256:
2257: if (pSystem->bSystemCounterNameSaved == TRUE)
2258: return FALSE ;
2259:
2260: GetLocalTime (&SystemTime) ;
2261:
2262: lCurPosition = FileTell (pLog->hFile) ;
2263:
2264: lstrcpy (CounterNameRecord.szComputer, pSystem->sysName) ;
2265: CounterNameRecord.lBaseCounterNameOffset = pLog->lBaseCounterNameOffset ;
2266: CounterNameRecord.lCurrentCounterNameOffset =
2267: lCurPosition + sizeof (LOGFILECOUNTERNAME) ;
2268: CounterNameRecord.lMatchLength = sizeMatched ;
2269: CounterNameRecord.lUnmatchCounterNames = sizeOfData ;
2270: CounterNameRecord.dwLastCounterId = pSystem->CounterInfo.dwLastId ;
2271: CounterNameRecord.dwLangId = pSystem->CounterInfo.dwLangId ;
2272: WriteOK = FileWrite (pLog->hFile, &CounterNameRecord,
2273: sizeof (CounterNameRecord)) ;
2274:
2275: if (WriteOK)
2276: {
2277: pLog->lFileSize += sizeof (LOGFILECOUNTERNAME) ;
2278:
2279: if (sizeOfData)
2280: {
2281:
2282: WriteOK = FileWrite (pLog->hFile, pCounterName, sizeOfData) ;
2283:
2284: if (WriteOK && (PatchBytes = sizeOfData % sizeof(DWORD)) > 0)
2285: {
2286: // ensure the file is in DWORD boundary.
2287: WriteOK = FileWrite (pLog->hFile, Dummy, PatchBytes) ;
2288: }
2289:
2290: if (WriteOK)
2291: {
2292: pLog->lFileSize += sizeOfData + PatchBytes ;
2293:
2294: if (!pLog->lBaseCounterNameOffset)
2295: {
2296: // this is the first counter name data block
2297: // then update the log file header
2298: lDataOffset = FileTell (pLog->hFile) ;
2299:
2300: FileSeekBegin (pLog->hFile, 0L) ;
2301:
2302: ReadOK = FileRead (pLog->hFile,
2303: &LogFileHeader,
2304: sizeof (LogFileHeader)) ;
2305:
2306: if (ReadOK)
2307: {
2308: LogFileHeader.lBaseCounterNameOffset = lCurPosition ;
2309: FileSeekBegin (pLog->hFile, 0L) ;
2310: WriteOK = FileWrite (pLog->hFile,
2311: &LogFileHeader,
2312: sizeof (LogFileHeader)) ;
2313: }
2314: else
2315: {
2316: // flag an error
2317: WriteOK = FALSE ;
2318: }
2319:
2320: // retore back to current file position
2321: FileSeekBegin (pLog->hFile, lDataOffset) ;
2322:
2323: if (ReadOK && WriteOK)
2324: {
2325: // allocate memory to save the base system counter names
2326: if (pLog->pBaseCounterName)
2327: {
2328: MemoryFree (pLog->pBaseCounterName) ;
2329: }
2330: if (pLog->pBaseCounterName = MemoryAllocate (sizeOfData))
2331: {
2332: memcpy (pLog->pBaseCounterName,
2333: pCounterName,
2334: sizeOfData) ;
2335: pLog->lBaseCounterNameOffset = lCurPosition ;
2336: pLog->lBaseCounterNameSize = sizeOfData ;
2337: }
2338: }
2339: } // if (!pLog->lBaseCounterNameOffset)
2340: }
2341: } // if (sizeOfData)
2342: }
2343:
2344: if ( WriteOK )
2345: {
2346: WriteOK = LogWriteIndex (pLog, LogFileIndexCounterName,
2347: &SystemTime,
2348: lCurPosition,
2349: 0) ;
2350: }
2351:
2352: if ( !WriteOK )
2353: {
2354: CloseLog (hWndLog, pLog) ;
2355: PrepareMenu (GetMenu (hWndMain)) ;
2356: UpdateLogDisplay (hWndLog) ;
2357: DlgErrorBox (hWndLog, ERR_LOG_FILE, pLog->szFilePath);
2358: }
2359: else
2360: {
2361: UpdateLogSize (hWnd) ;
2362: pSystem->bSystemCounterNameSaved = TRUE ;
2363: }
2364:
2365: return (TRUE) ;
2366: }
2367:
2368:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.