home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / perfmon / perfmops.c < prev    next >
Text File  |  1994-11-01  |  40KB  |  1,505 lines

  1.  
  2. #include "perfmon.h"
  3. #include <lmcons.h>
  4. #include <lmerr.h>
  5. #include <lmapibuf.h>
  6. #include <lmwksta.h>
  7. #include "uiexprt.h"
  8. #include <stdio.h>         // for sprintf
  9. #include <locale.h>        // for setlocale
  10. #include "utils.h"
  11.  
  12. #include "perfdata.h"      // for OpenSystemPerfData
  13. #include "alert.h"         // for AlertInsertLine
  14. #include "report.h"        // for ReportInsertLine
  15. #include "grafdata.h"      // for GraphInsertLine
  16. #include "log.h"           // for OpenLog
  17. #include "fileopen.h"      // for FileGetName
  18. #include "fileutil.h"      // for FileRead etc
  19. #include "command.h"       // for PrepareMenu
  20. #include "playback.h"      // for PlayingBackLog & LogPositionSystemTime
  21. #include "system.h"
  22. #include "globals.h"
  23. #include "pmemory.h"       // for MemoryFree
  24. #include "status.h"        // for StatusLineReady
  25. #include "pmhelpid.h"
  26.  
  27. // test for delimiter, end of line and non-digit characters
  28. // used by IsNumberInUnicodeList routine
  29. //
  30. #define DIGIT       1
  31. #define DELIMITER   2
  32. #define INVALID     3
  33.  
  34. // globals used for International Date and Time formats
  35. enum DATE_STYLE
  36.    {
  37.    YEAR_FIRST,       // YYMMDD
  38.    DAY_FIRST,        // DDMMYY
  39.    MONTH_FIRST       // MMDDYY
  40.    } DateStyle ;
  41.  
  42. TCHAR szInternational[] = TEXT("Intl") ;
  43. TCHAR sz1159[6] ;       // AM String
  44. TCHAR sz2359[6] ;       // PM String
  45. int   iTime ;           // = 0 for 12-hour format,  <> 0 for 24-hour format
  46. int   YearCharCount ;   // = 4 for 1990, = 2 for 90
  47.  
  48. TCHAR szDateFormat[ResourceStringLen] ;
  49. TCHAR szTimeFormat[ResourceStringLen] ;   // time format including msec
  50. TCHAR szTimeFormat1[ResourceStringLen] ;  // time format without msec
  51.  
  52. TCHAR LeadingZeroStr [] = TEXT("%02d") ;
  53. TCHAR NoLeadingZeroStr [] = TEXT("%d") ;
  54.  
  55. TCHAR szDecimal [2] ;
  56. TCHAR szCurrentDecimal [2] ;
  57.  
  58. #define EvalThisChar(c,d) ( \
  59.      (c == d) ? DELIMITER : \
  60.      (c == 0) ? DELIMITER : \
  61.      (c < (WCHAR)'0') ? INVALID : \
  62.      (c > (WCHAR)'9') ? INVALID : \
  63.      DIGIT)
  64.  
  65. #define SIZE_OF_BIGGEST_INTEGER  16 
  66. // #define SIZE_OF_BIGGEST_INTEGER (16*sizeof(WCHAR)) 
  67.  
  68.  
  69. //==========================================================================//
  70. //                                  Typedefs                                //
  71. //==========================================================================//
  72.  
  73. BOOL AddObjectToSystem ( PLINE , PPERFSYSTEM );
  74. BOOL GetLogFileComputer (HWND hWndParent, LPTSTR lpComputerName, DWORD BufferSize) ;
  75.  
  76.  
  77. HWND PerfmonViewWindow (void)
  78. /*
  79.    Effect:        Return the current data window, i.e. the window currently
  80.                   visible as the client area of Perfmon.  This is either a
  81.                   chart, log, alert, or report window.
  82. */
  83.    {  // PerfmonDataWindow
  84.    switch (iPerfmonView)
  85.       {  // switch
  86.       case IDM_VIEWLOG:
  87.          return (hWndLog) ;
  88.  
  89.       case IDM_VIEWALERT:
  90.          return (hWndAlert) ;
  91.  
  92.       case IDM_VIEWREPORT:
  93.          return (hWndReport) ;
  94.  
  95. //      case IDM_VIEWCHART:
  96.       default:
  97.          return (hWndGraph) ;
  98.       }  // switch
  99.    }  // PerfmonViewWindow
  100.  
  101.  
  102.  
  103.  
  104. #define szChooseComputerLibrary     TEXT("ntlanman.dll")
  105. #define szChooseComputerFunction    "I_SystemFocusDialog"
  106.  
  107.  
  108. BOOL ChooseComputer (HWND hWndParent, LPTSTR lpszComputer)
  109. /*
  110.    Effect:        Display the choose Domain/Computer dialog provided by
  111.                   network services.  If the user selects a computer, 
  112.                   copy the computer name to lpszComputer and return
  113.                   nonnull. If the user cancels, return FALSE.
  114.  
  115.    Internals:     This dialog and code is currently not an exported 
  116.                   routine regularly found on any user's system. Right 
  117.                   now, we dynamically load and call the routine.
  118.  
  119.                   This is definitely temporary code that will be 
  120.                   rewritten when NT stabilizes. The callers of this
  121.                   routine, however, will not need to be modified.
  122.  
  123.                   Also, the Domain/Computer dialog currently allows
  124.                   a domain to be selected, which we cannot use. We
  125.                   therefore loop until the user cancels or selects
  126.                   a computer, putting up a message if the user selects
  127.                   a domain.
  128.  
  129.    Assert:        lpszComputer is at least MAX_SYSTEM_NAME_LENGTH + 1
  130.                   characters.
  131. */
  132.    {  // ChooseComputer
  133.    BOOL                     bSuccess ;
  134.    WCHAR                    wszWideComputer[MAX_COMPUTERNAME_LENGTH + 3] ;
  135.    HLIBRARY                 hLibrary ;
  136.    LPFNI_SYSTEMFOCUSDIALOG  lpfnChooseComputer ;
  137.    LONG                     lError ;
  138.  
  139.    if (!PlayingBackLog())
  140.       {
  141.  
  142.       // bring up the select network computer dialog
  143.       hLibrary = LoadLibrary (szChooseComputerLibrary) ;
  144.       if (!hLibrary || hLibrary == INVALID_HANDLE_VALUE)
  145.          {
  146.          return (FALSE) ;
  147.          }
  148.    
  149.       lpfnChooseComputer = (LPFNI_SYSTEMFOCUSDIALOG)
  150.          GetProcAddress (hLibrary, szChooseComputerFunction) ;
  151.  
  152.       if (!lpfnChooseComputer)
  153.          {
  154.          FreeLibrary (hLibrary) ;
  155.          return (FALSE) ;
  156.          }
  157.  
  158.       lError = (*lpfnChooseComputer) (hWndParent,
  159.          FOCUSDLG_SERVERS_ONLY | FOCUSDLG_BROWSE_ALL_DOMAINS,
  160.          wszWideComputer,
  161.          sizeof(wszWideComputer) / sizeof(WCHAR),
  162.          &bSuccess,
  163.          pszHelpFile,
  164.          HC_PM_idDlgSelectNetworkComputer) ;
  165.  
  166.       FreeLibrary (hLibrary) ;
  167.       }
  168.    else
  169.       {
  170.       // bring up the select Log Computer dialog
  171.       bSuccess = GetLogFileComputer (hWndParent,
  172.          wszWideComputer,
  173.          sizeof(wszWideComputer) / sizeof(WCHAR)) ;
  174.       }
  175.  
  176.    if (bSuccess)
  177.       {
  178.       lstrcpy (lpszComputer, wszWideComputer) ;
  179. //      wcstombs(lpszComputer, wszWideComputer, MAX_COMPUTERNAME_LENGTH + 3) ;
  180.       }
  181.  
  182.    return (bSuccess) ;
  183.    }  // ChooseComputer
  184.    
  185.  
  186. void SystemTimeDateString (SYSTEMTIME *pSystemTime,
  187.                            LPTSTR lpszDate)
  188.    {
  189.    int      wYear ;
  190.    
  191.    wYear = pSystemTime->wYear ;
  192.    if (YearCharCount == 2)
  193.       {
  194.       wYear %= 100 ;
  195.       }
  196.  
  197.    switch (DateStyle)
  198.       {
  199.       case YEAR_FIRST:
  200.          TSPRINTF (lpszDate, szDateFormat,
  201.              wYear, pSystemTime->wMonth, pSystemTime->wDay) ;
  202.          break ;
  203.  
  204.       case DAY_FIRST:
  205.          TSPRINTF (lpszDate, szDateFormat,
  206.              pSystemTime->wDay, pSystemTime->wMonth, wYear) ;
  207.          break ;
  208.  
  209.       case MONTH_FIRST:
  210.       default:
  211.          TSPRINTF (lpszDate, szDateFormat,
  212.              pSystemTime->wMonth, pSystemTime->wDay, wYear) ;
  213.          break ;
  214.       }
  215.    }
  216.  
  217.  
  218. void SystemTimeTimeString (SYSTEMTIME *pSystemTime,
  219.                            LPTSTR lpszTime,
  220.                            BOOL   bOutputMsec)
  221.    {
  222.    int            iHour ;
  223.    BOOL           bPM ;
  224.  
  225.    if (iTime)
  226.       {
  227.       // 24 hor format
  228.       if (bOutputMsec)
  229.          {
  230.          TSPRINTF (lpszTime, szTimeFormat,
  231.                 pSystemTime->wHour,
  232.                 pSystemTime->wMinute,
  233.                 (FLOAT)pSystemTime->wSecond +
  234.                 (FLOAT)pSystemTime->wMilliseconds / (FLOAT) 1000.0) ;
  235.          }
  236.       else
  237.          {
  238.          TSPRINTF (lpszTime, szTimeFormat1,
  239.                 pSystemTime->wHour,
  240.                 pSystemTime->wMinute,
  241.                 pSystemTime->wSecond) ;
  242.  
  243.          }
  244.       }
  245.    else
  246.       {
  247.       // 12 hour format
  248.       iHour = pSystemTime->wHour ;
  249.       bPM = (iHour >= 12) ;
  250.  
  251.       if (iHour > 12)
  252.          iHour -= 12 ;
  253.       else if (!iHour)
  254.          iHour = 12 ;
  255.  
  256.       if (bOutputMsec)
  257.          {
  258.          TSPRINTF (lpszTime, szTimeFormat,
  259.                 iHour, pSystemTime->wMinute,
  260.                 (FLOAT)pSystemTime->wSecond + 
  261.                 (FLOAT)pSystemTime->wMilliseconds / (FLOAT) 1000.0 ,
  262.                 bPM ? sz2359 : sz1159) ;
  263.          }
  264.       else
  265.          {
  266.          TSPRINTF (lpszTime, szTimeFormat1,
  267.                 iHour, pSystemTime->wMinute,
  268.                 pSystemTime->wSecond,
  269.                 bPM ? sz2359 : sz1159) ;
  270.          }
  271.       }
  272.    }
  273.             
  274. void ShowPerfmonWindowText ()
  275.    {
  276.    LPTSTR   *ppFileName ;
  277.    TCHAR    szApplication [MessageLen] ;
  278.  
  279.    switch (iPerfmonView)
  280.       {
  281.       case IDM_VIEWCHART:
  282.          ppFileName = &pChartFileName ;
  283.          break ;
  284.  
  285.       case IDM_VIEWALERT:
  286.          ppFileName = &pAlertFileName ;
  287.          break ;
  288.  
  289.       case IDM_VIEWREPORT:
  290.          ppFileName = &pReportFileName ;
  291.          break ;
  292.  
  293.       case IDM_VIEWLOG:
  294.          ppFileName = &pLogFileName ;
  295.          break ;
  296.  
  297.       default:
  298.          ppFileName = NULL ;
  299.          break ;
  300.       }
  301.  
  302.    if (ppFileName == NULL || *ppFileName == NULL)
  303.       {
  304.       ppFileName = &pWorkSpaceFileName ;
  305.       }
  306.  
  307.    // display the name file name on the Title bar.
  308.    StringLoad (IDS_APPNAME, szApplication) ;
  309.  
  310.    if (*ppFileName)
  311.       {
  312.       lstrcat (szApplication, TEXT(" - ")) ;
  313.       lstrcat (szApplication, *ppFileName) ;
  314.       }
  315.    SetWindowText (hWndMain, szApplication) ;
  316.    }
  317.  
  318. void ShowPerfmonMenu (BOOL bMenu)
  319.    {  // ShowPerfmonMenu
  320.    if (!bMenu)
  321.       {
  322.       WindowEnableTitle (hWndMain, FALSE) ;
  323. //      SetMenu(hWndMain, NULL) ;
  324.       }
  325.    else
  326.       {
  327.       WindowEnableTitle (hWndMain, TRUE) ;
  328.       switch (iPerfmonView)
  329.          {  // switch
  330.          case IDM_VIEWCHART:
  331.             SetMenu (hWndMain, hMenuChart) ;
  332.             break ;
  333.  
  334.          case IDM_VIEWALERT:
  335.             SetMenu (hWndMain, hMenuAlert) ;
  336.             break ;
  337.  
  338.          case IDM_VIEWLOG:
  339.             SetMenu (hWndMain, hMenuLog) ;
  340.             break ;
  341.  
  342.          case IDM_VIEWREPORT:
  343.             SetMenu (hWndMain, hMenuReport) ;
  344.             break ;
  345.          }  // switch
  346.       }  // else
  347.  
  348.    if (bMenu != Options.bMenubar)
  349.       {
  350.       PrepareMenu (GetMenu (hWndMain)) ;
  351.       }
  352.  
  353.    Options.bMenubar = bMenu ;
  354.  
  355.    // Show Window Text
  356.    if (bMenu)
  357.       {
  358.       ShowPerfmonWindowText () ;
  359.       }
  360.    }  // ShowPerfmonMenu
  361.  
  362.  
  363.  
  364. void SmallFileSizeString (int iFileSize,
  365.                           LPTSTR lpszFileText)
  366.    {  // SmallFileSizeString
  367.    if (iFileSize < 1000000)
  368.       TSPRINTF (lpszFileText, TEXT(" %1.1fK "), ((FLOAT) iFileSize) / 1000.0f) ;
  369.    else
  370.       TSPRINTF (lpszFileText, TEXT(" %1.1fM "), ((FLOAT) iFileSize) / 1000000.0f) ;
  371.    }  // SmallFileSizeString   
  372.  
  373.  
  374.  
  375. BOOL DoWindowDrag (HWND hWnd, LPARAM lParam)
  376.    {
  377.    POINT    lPoint ;
  378.  
  379.    if (!Options.bMenubar && !IsZoomed (hWndMain))
  380.       {
  381.       // convert lParam from client to screen
  382.       lPoint.x = LOWORD (lParam) ;
  383.       lPoint.y = HIWORD (lParam) ;
  384.       ClientToScreen (hWnd, &lPoint) ;
  385.       lParam = MAKELONG (lPoint.x, lPoint.y) ;
  386.       SendMessage (hWndMain, WM_NCLBUTTONDOWN, HTCAPTION, lParam) ;
  387.       return (TRUE) ;
  388.       }
  389.    else
  390.       return (FALSE) ;
  391.    }
  392.  
  393.  
  394.  
  395. // Filetimes are in 100NS units
  396. #define FILETIMES_PER_SECOND     10000000
  397.  
  398.  
  399. int SystemTimeDifference (SYSTEMTIME *pst1, SYSTEMTIME *pst2)
  400.    {
  401.    LONGLONG       li1, li2 ;
  402.    LONGLONG       liDifference, liDifferenceSeconds ;
  403.    int            RetInteger;
  404.    BOOL           bNegative;
  405.  
  406.    li1 = (LONGLONG) 0 ;
  407.    li2 = (LONGLONG) 0 ;
  408.  
  409.    SystemTimeToFileTime (pst1, (FILETIME *) &li1) ;
  410.    SystemTimeToFileTime (pst2, (FILETIME *) &li2) ;
  411.  
  412.    // check for special cases when the time can be 0
  413.    if (li2 == (LONGLONG)0)
  414.       {
  415.       if (li1 == (LONGLONG)0)
  416.          {
  417.          return 0 ;
  418.          }
  419.       else
  420.          {
  421.          return -INT_MAX ;
  422.          }
  423.       }
  424.    else if (li1 == (LONGLONG)0)
  425.       {
  426.       return INT_MAX ;
  427.       }
  428.  
  429.    liDifference = li2 - li1 ;
  430.    bNegative = liDifference <= (LONGLONG) 0 ;
  431.  
  432.    // add the round-off factor before doing the division
  433.    if (bNegative)
  434.       {
  435.       liDifferenceSeconds = (LONGLONG) (- FILETIMES_PER_SECOND / 2) ;
  436.       }
  437.    else
  438.       {
  439.       liDifferenceSeconds = (LONGLONG) (FILETIMES_PER_SECOND / 2) ;
  440.       }
  441.  
  442.  
  443.    liDifferenceSeconds = liDifferenceSeconds + liDifference ;
  444.  
  445.    liDifferenceSeconds =
  446.          liDifferenceSeconds / (LONGLONG) (FILETIMES_PER_SECOND) ; 
  447.  
  448.    RetInteger = (int) (liDifferenceSeconds & ((LONGLONG) 0x0ffffffff));
  449.  
  450.    if (bNegative)
  451.       {
  452.       return (-RetInteger) ;
  453.       }
  454.    else
  455.       {
  456.       return (RetInteger) ;
  457.       }
  458.    }
  459.  
  460.  
  461. BOOL InsertLine (PLINE pLine)
  462. {  // InsertLine
  463.  
  464.     BOOL bReturn;
  465.    
  466.     switch (pLine->iLineType) {  // switch
  467.         case LineTypeChart:
  468.             bReturn = ChartInsertLine (pGraphs, pLine) ;
  469.             break ;
  470.  
  471.         case LineTypeAlert:
  472.             bReturn = AlertInsertLine (hWndAlert, pLine) ;
  473.             break ;
  474.  
  475.         case LineTypeReport:
  476.             bReturn = ReportInsertLine (hWndReport, pLine) ;
  477.             break ;
  478.  
  479.     }  // switch
  480.  
  481.     return bReturn;
  482.  
  483. }  // InsertLine
  484.    
  485.  
  486. BOOL OpenWorkspace (HANDLE hFile, DWORD dwMajorVersion, DWORD dwMinorVersion)
  487.    {
  488.    DISKWORKSPACE  DiskWorkspace ;
  489.    
  490.    if (!FileRead (hFile, &DiskWorkspace, sizeof(DiskWorkspace)))
  491.       {
  492.       goto Exit0 ;
  493.       }
  494.  
  495.    if (DiskWorkspace.ChartOffset == 0 &&
  496.        DiskWorkspace.AlertOffset == 0 &&
  497.        DiskWorkspace.LogOffset == 0 &&
  498.        DiskWorkspace.ReportOffset == 0)
  499.       {
  500.       goto Exit0 ;
  501.       }
  502.  
  503.    switch (dwMajorVersion)
  504.       {  // switch
  505.       case (1):
  506.  
  507.          if (dwMinorVersion >= 1)
  508.             {
  509.             // setup the window position and size
  510.             DiskWorkspace.WindowPlacement.length = sizeof(WINDOWPLACEMENT);
  511.             DiskWorkspace.WindowPlacement.flags = WPF_SETMINPOSITION;
  512.             if (!SetWindowPlacement (hWndMain, &(DiskWorkspace.WindowPlacement)))
  513.                 {
  514.                 goto Exit0 ;
  515.                 }
  516.             }
  517.  
  518.          // change to the view as stored in the workspace file
  519.          SendMessage (hWndMain, WM_COMMAND,
  520.             (LONG)DiskWorkspace.iPerfmonView, 0L) ;
  521.          iPerfmonView = DiskWorkspace.iPerfmonView ;
  522.  
  523.          if (DiskWorkspace.ChartOffset)
  524.             {
  525.             if (FileSeekBegin(hFile, DiskWorkspace.ChartOffset) == 0xFFFFFFFF)
  526.                {
  527.                goto Exit0 ;
  528.                }
  529.  
  530.             if (!OpenChart (hWndGraph,
  531.                            hFile,
  532.                            dwMajorVersion,
  533.                            dwMinorVersion,
  534.                            FALSE))
  535.                {
  536.                goto Exit0 ;
  537.                }
  538.             }
  539.          if (DiskWorkspace.AlertOffset)
  540.             {
  541.             if (FileSeekBegin(hFile, DiskWorkspace.AlertOffset) == 0xffffffff)
  542.                {
  543.                goto Exit0 ;
  544.                }
  545.             if (!OpenAlert (hWndAlert,
  546.                        hFile,
  547.                        dwMajorVersion,
  548.                        dwMinorVersion,
  549.                        FALSE))
  550.                {
  551.                goto Exit0 ;
  552.                }
  553.             }
  554.          if (DiskWorkspace.LogOffset)
  555.             {
  556.             if (FileSeekBegin(hFile, DiskWorkspace.LogOffset) == 0xffffffff)
  557.                {
  558.                goto Exit0 ;
  559.                }
  560.             if (!OpenLog (hWndLog,
  561.                           hFile,
  562.                           dwMajorVersion,
  563.                           dwMinorVersion,
  564.                           FALSE))
  565.                {
  566.                goto Exit0 ;
  567.                }
  568.             }
  569.          if (DiskWorkspace.ReportOffset)
  570.             {
  571.             if (FileSeekBegin(hFile, DiskWorkspace.ReportOffset) == 0xffffffff)
  572.                {
  573.                goto Exit0 ;
  574.                }
  575.             if (!OpenReport (hWndReport,
  576.                         hFile,
  577.                         dwMajorVersion,
  578.                         dwMinorVersion,
  579.                         FALSE))
  580.                {
  581.                goto Exit0 ;
  582.                }
  583.             }
  584.          break ;
  585.  
  586.       default:
  587.          goto Exit0 ;
  588.          break ;
  589.       }
  590.  
  591.    CloseHandle (hFile) ;
  592.    return (TRUE) ;
  593.  
  594.  
  595. Exit0:
  596.    CloseHandle (hFile) ;
  597.    return (FALSE) ;
  598.  
  599.    }  // OpenWorkspace
  600.  
  601.  
  602. BOOL SaveWorkspace (void)
  603.    {
  604.    DISKWORKSPACE  DiskWorkspace ;
  605.    PERFFILEHEADER FileHeader ;
  606.    HANDLE         hFile ;
  607.    long           DiskWorkspacePosition ;
  608.    TCHAR          szFileName[FilePathLen] ;
  609.    BOOL           bWriteErr = TRUE ;
  610.  
  611.    if (!FileGetName (PerfmonViewWindow(), IDS_WORKSPACEFILE, szFileName))
  612.       {
  613.       return (FALSE) ;
  614.       }
  615.  
  616.    hFile = FileHandleCreate (szFileName) ;
  617.    if (!hFile)
  618.       {
  619.       DlgErrorBox (PerfmonViewWindow (), ERR_CANT_OPEN, szFileName) ;
  620.       return (FALSE) ;
  621.       }
  622.  
  623.    memset (&FileHeader, 0, sizeof (FileHeader)) ;
  624.    lstrcpy (FileHeader.szSignature, szPerfWorkspaceSignature) ;
  625.    FileHeader.dwMajorVersion = WorkspaceMajorVersion ;
  626.    FileHeader.dwMinorVersion = WorkspaceMinorVersion ;
  627.  
  628.    if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
  629.       {
  630.       goto Exit0 ;
  631.       }
  632.  
  633.    // reserve space in the file.  We will fill up info
  634.    // and write into this guy later.
  635.    memset (&DiskWorkspace, 0, sizeof(DiskWorkspace)) ;
  636.    DiskWorkspacePosition = FileTell (hFile) ;
  637.    DiskWorkspace.WindowPlacement.length = sizeof(WINDOWPLACEMENT);
  638.    if (!GetWindowPlacement (hWndMain, &(DiskWorkspace.WindowPlacement)))
  639.       {
  640.       goto Exit0 ;
  641.       }
  642.  
  643.    if (!FileWrite (hFile, &DiskWorkspace, sizeof (DISKWORKSPACE)))
  644.       {
  645.       goto Exit0 ;
  646.       }
  647.  
  648.    // put in chart data
  649.    DiskWorkspace.ChartOffset = FileTell (hFile) ;
  650.    if (!SaveChart (hWndGraph, hFile, 0))
  651.       {
  652.       goto Exit0 ;
  653.       }
  654.  
  655.    // put in alert data
  656.    DiskWorkspace.AlertOffset = FileTell (hFile) ;
  657.    if (!SaveAlert (hWndAlert, hFile, 0))
  658.       {
  659.       goto Exit0 ;
  660.       }
  661.  
  662.    // put in log data
  663.    DiskWorkspace.LogOffset = FileTell (hFile) ;
  664.    if (!SaveLog (hWndLog, hFile, 0))
  665.       {
  666.       goto Exit0 ;
  667.       }
  668.  
  669.    // put in report data
  670.    DiskWorkspace.ReportOffset = FileTell (hFile) ;
  671.    if (!SaveReport (hWndReport, hFile, 0))
  672.       {
  673.       goto Exit0 ;
  674.       }
  675.  
  676.    // put in the disk header info
  677.    DiskWorkspace.iPerfmonView = iPerfmonView ;
  678.    FileSeekBegin (hFile, DiskWorkspacePosition) ;
  679.    if (!FileWrite (hFile, &DiskWorkspace, sizeof (DISKWORKSPACE)))
  680.       {
  681.       goto Exit0 ;
  682.       }
  683.    bWriteErr = FALSE ;
  684.  
  685. Exit0:
  686.    if (bWriteErr)
  687.       {
  688.       DlgErrorBox (PerfmonViewWindow (), ERR_SETTING_FILE, szFileName) ;
  689.       }
  690.  
  691.    CloseHandle (hFile) ;
  692.  
  693.    }  // SaveWorkspace
  694.  
  695. void SetPerfmonOptions (OPTIONS *pOptions)
  696.    {
  697.    Options = *pOptions ;
  698.    ShowPerfmonMenu (Options.bMenubar) ;
  699.    SizePerfmonComponents () ;
  700.    WindowSetTopmost (hWndMain, Options.bAlwaysOnTop) ;
  701.    }  // SetPerfmonOptions
  702.  
  703. void ChangeSaveFileName (LPTSTR szFileName, int iPMView)
  704.    {
  705.    LPTSTR   *ppFullName ;
  706.    LPTSTR   *ppFileName ;
  707.    BOOL     errorInput = FALSE ;
  708.    TCHAR    szApplication [MessageLen] ;
  709.  
  710.  
  711.    switch (iPMView)
  712.       {
  713.       case IDM_VIEWCHART:
  714.          ppFileName = &pChartFileName ;
  715.          ppFullName = &pChartFullFileName ;
  716.          break ;
  717.  
  718.       case IDM_VIEWALERT:
  719.          ppFileName = &pAlertFileName ;
  720.          ppFullName = &pAlertFullFileName ;
  721.          break ;
  722.  
  723.       case IDM_VIEWREPORT:
  724.          ppFileName = &pReportFileName ;
  725.          ppFullName = &pReportFullFileName ;
  726.          break ;
  727.  
  728.       case IDM_VIEWLOG:
  729.          ppFileName = &pLogFileName ;
  730.          ppFullName = &pLogFullFileName ;
  731.          break ;
  732.  
  733.       case IDM_WORKSPACE:
  734.          // not a view but a define
  735.          ppFileName = &pWorkSpaceFileName ;
  736.          ppFullName = &pWorkSpaceFullFileName ;
  737.          break ;
  738.  
  739.       default:
  740.          errorInput = TRUE ;
  741.          break ;
  742.       }
  743.  
  744.    if (errorInput)
  745.       {
  746.       return ;
  747.       }
  748.  
  749.    // release last filename
  750.    if (*ppFullName)
  751.       {
  752.       MemoryFree (*ppFullName) ;
  753.       *ppFileName = NULL ;
  754.       *ppFullName = NULL ;
  755.       }
  756.  
  757.    // allocate new file name and display it
  758.    if (szFileName && (*ppFullName = StringAllocate (szFileName)))
  759.       {
  760.       *ppFileName = ExtractFileName (*ppFullName) ;
  761.       }
  762.  
  763.    if (iPerfmonView == iPMView || iPMView == IDM_WORKSPACE)
  764.       {
  765.       StatusLineReady (hWndStatus) ;
  766.  
  767.       if (Options.bMenubar)
  768.          {
  769.          // display the name file name on the Title bar.
  770.          StringLoad (IDS_APPNAME, szApplication) ;
  771.  
  772.          if (*ppFileName == NULL)
  773.             {
  774.             ppFileName = &pWorkSpaceFileName ;
  775.             }
  776.  
  777.          if (*ppFileName)
  778.             {
  779.             lstrcat (szApplication, TEXT(" - ")) ;
  780.             lstrcat (szApplication, *ppFileName) ;
  781.             }
  782.          SetWindowText (hWndMain, szApplication) ;
  783.          }
  784.       }
  785.    }     // ChangeSaveFileName
  786.  
  787. BOOL
  788. IsNumberInUnicodeList (
  789.     IN DWORD   dwNumber,
  790.     IN LPTSTR  lpwszUnicodeList
  791. )
  792. /*++
  793.  
  794. IsNumberInUnicodeList
  795.  
  796. Arguments:
  797.         
  798.     IN dwNumber
  799.         DWORD number to find in list
  800.  
  801.     IN lpwszUnicodeList
  802.         Null terminated, Space delimited list of decimal numbers
  803.  
  804. Return Value:
  805.  
  806.     TRUE:
  807.             dwNumber was found in the list of unicode number strings
  808.  
  809.     FALSE:
  810.             dwNumber was not found in the list.
  811.  
  812. --*/
  813. {
  814.     DWORD   dwThisNumber;
  815.     WCHAR   *pwcThisChar;
  816.     BOOL    bValidNumber;
  817.     BOOL    bNewItem;
  818.     WCHAR   wcDelimiter;    // could be an argument to be more flexible
  819.  
  820.     if (lpwszUnicodeList == 0) return FALSE;    // null pointer, # not founde
  821.  
  822.     pwcThisChar = lpwszUnicodeList;
  823.     dwThisNumber = 0;
  824.     wcDelimiter = (WCHAR)' ';
  825.     bValidNumber = FALSE;
  826.     bNewItem = TRUE;
  827.     
  828.     while (TRUE) {
  829.         switch (EvalThisChar (*pwcThisChar, wcDelimiter)) {
  830.             case DIGIT:
  831.                 // if this is the first digit after a delimiter, then 
  832.                 // set flags to start computing the new number
  833.                 if (bNewItem) {
  834.                     bNewItem = FALSE;
  835.                     bValidNumber = TRUE;
  836.                 }
  837.                 if (bValidNumber) {
  838.                     dwThisNumber *= 10;
  839.                     dwThisNumber += (*pwcThisChar - (WCHAR)'0');
  840.                 }
  841.                 break;
  842.             
  843.             case DELIMITER:
  844.                 // a delimter is either the delimiter character or the 
  845.                 // end of the string ('\0') if when the delimiter has been
  846.                 // reached a valid number was found, then compare it to the
  847.                 // number from the argument list. if this is the end of the
  848.                 // string and no match was found, then return.
  849.                 //
  850.                 if (bValidNumber) {
  851.                     if (dwThisNumber == dwNumber) return TRUE;
  852.                     bValidNumber = FALSE;
  853.                 }
  854.                 if (*pwcThisChar == 0) {
  855.                     return FALSE;
  856.                 } else {
  857.                     bNewItem = TRUE;
  858.                     dwThisNumber = 0;
  859.                 }
  860.                 break;
  861.  
  862.             case INVALID:
  863.                 // if an invalid character was encountered, ignore all
  864.                 // characters up to the next delimiter and then start fresh.
  865.                 // the invalid number is not compared.
  866.                 bValidNumber = FALSE;
  867.                 break;
  868.  
  869.             default:
  870.                 break;
  871.  
  872.         }
  873.         pwcThisChar++;
  874.     }
  875.  
  876. }   // IsNumberInUnicodeList
  877.  
  878. BOOL
  879. AppendObjectToValueList (
  880.     DWORD   dwObjectId,
  881.     PWSTR   pwszValueList
  882. )
  883. /*++
  884.  
  885. AppendObjectToValueList
  886.  
  887. Arguments:
  888.         
  889.     IN dwNumber
  890.         DWORD number to insert in list
  891.  
  892.     IN PUNICODE_STRING
  893.         pointer to unicode string structure that contains buffer that is
  894.         Null terminated, Space delimited list of decimal numbers that
  895.         may have this number appended to. 
  896.  
  897. Return Value:
  898.  
  899.     TRUE:
  900.             dwNumber was added to list
  901.  
  902.     FALSE:
  903.             dwNumber was not added. (because it's already there or
  904.                 an error occured)
  905.  
  906. --*/
  907. {
  908.     WCHAR           tempString [SIZE_OF_BIGGEST_INTEGER] ;
  909.     DWORD           dwStrLen, dwNewStrLen;
  910.  
  911.     if (!pwszValueList) {
  912.         return FALSE;
  913.     }
  914.  
  915.     if (IsNumberInUnicodeList(dwObjectId, pwszValueList)) {
  916.         return FALSE;   // object already in list
  917.     } else {
  918.         // append the new object id the  value list
  919.         TSPRINTF (tempString, TEXT("%d "), dwObjectId) ;
  920.  
  921.         // see if string will fit (compare in bytes)
  922.  
  923.         dwStrLen = MemorySize (pwszValueList) - sizeof (UNICODE_NULL);
  924.  
  925.         dwNewStrLen = (lstrlen (pwszValueList) + lstrlen (tempString)) *
  926.             sizeof (WCHAR);
  927.  
  928.         if (dwNewStrLen <= dwStrLen) {
  929.             lstrcat (pwszValueList, tempString);
  930.             return TRUE;
  931.         } else {
  932.             SetLastError (ERROR_OUTOFMEMORY); 
  933.             return FALSE;
  934.         }
  935.     }
  936. }
  937.  
  938. BOOL
  939. AddObjectToSystem (
  940.     PLINE pLine,
  941.     PPERFSYSTEM pFirstSystem
  942. )
  943. {
  944.     PPERFSYSTEM     pSystem;
  945.     
  946.     if ((ARGUMENT_PRESENT (pLine)) && (ARGUMENT_PRESENT(pFirstSystem))) {
  947.         pSystem = SystemGet (pFirstSystem, pLine->lnSystemName);
  948.  
  949.         if (pSystem) {
  950.             return AppendObjectToValueList (
  951.                 pLine->lnObject.ObjectNameTitleIndex,
  952.                 pSystem->lpszValue);
  953.         } else {
  954.             return FALSE;
  955.         }
  956.     } else {
  957.         return FALSE;
  958.     }
  959. }
  960.  
  961. BOOL
  962. RemoveObjectsFromSystem (
  963.     PPERFSYSTEM pSystem
  964. )
  965. {
  966.     DWORD   dwBufferSize = 0;
  967.  
  968.     if (ARGUMENT_PRESENT (pSystem)) {
  969.         // don't do foreign computers
  970.         if (pSystem->lpszValue && !strsame (pSystem->lpszValue, L"Foreign")){
  971.             dwBufferSize = MemorySize (pSystem->lpszValue);
  972.  
  973.             memset (pSystem->lpszValue, 0, dwBufferSize);
  974.             return TRUE;
  975.         } else {
  976.             return FALSE;
  977.         }
  978.     } else {
  979.         return FALSE;
  980.     }
  981.  
  982.  
  983. }    
  984.  
  985. BOOL
  986. BuildValueListForSystems (
  987.     PPERFSYSTEM pSystemListHead,
  988.     PLINE       pLineListHead
  989. )
  990. /*++
  991.  
  992. BuildValueListForSystem
  993.  
  994. Abstract:
  995.  
  996.     Walks down line list and builds the list of objects to query from
  997.     that system containing that line.
  998.  
  999. Arguments:
  1000.  
  1001.     pSystemListHead
  1002.  
  1003.         head of system linked list
  1004.         each system will have it's "Value Name" list appended
  1005.  
  1006.     pLineListHead
  1007.  
  1008.         head of line list that will be searched for creating the new
  1009.         valuelist.
  1010.  
  1011.  
  1012. Return Value:
  1013.  
  1014.  
  1015. --*/
  1016. {
  1017.  
  1018.     PPERFSYSTEM     pSystem;    // system that contains current line
  1019.     PLINE           pThisLine;  // current line
  1020.  
  1021.     if ((ARGUMENT_PRESENT (pLineListHead)) && (ARGUMENT_PRESENT(pSystemListHead))) {
  1022.         // clear system entries:
  1023.         for (pSystem = pSystemListHead; pSystem; pSystem = pSystem->pSystemNext) {
  1024.             if (pSystem && pSystem->FailureTime == 0) {
  1025.                 RemoveObjectsFromSystem (pSystem);
  1026.             }
  1027.         }
  1028.  
  1029.         // add new enties
  1030.  
  1031.         for (pThisLine = pLineListHead; pThisLine; pThisLine = pThisLine->pLineNext) {
  1032.  
  1033.             pSystem = SystemGet (pSystemListHead, pThisLine->lnSystemName);
  1034.             if (pSystem && pSystem->FailureTime == 0) {
  1035.                 AppendObjectToValueList (
  1036.                     pThisLine->lnObject.ObjectNameTitleIndex,
  1037.                     pSystem->lpszValue);
  1038.  
  1039.             }
  1040.         }
  1041.         return TRUE;
  1042.     } else {    // argument(s) missing
  1043.         return FALSE;
  1044.     }
  1045. }
  1046.  
  1047. // define in Addline.c
  1048. extern   PLINESTRUCT       pLineEdit ;
  1049. #define  bEditLine (pLineEdit != NULL)
  1050.  
  1051. BOOL
  1052. SetSystemValueNameToGlobal (
  1053.     PPERFSYSTEM pSystem
  1054. )
  1055. {
  1056.  
  1057.     if (!bEditLine && ARGUMENT_PRESENT(pSystem)) {
  1058.         if (pSystem->lpszValue && RemoveObjectsFromSystem(pSystem)) {
  1059.             lstrcpy (
  1060.                 pSystem->lpszValue,
  1061.                 TEXT("Global")) ;
  1062.             return TRUE;
  1063.         } else {
  1064.             return FALSE;
  1065.         }
  1066.     } else {
  1067.         return FALSE;
  1068.     }
  1069. }
  1070.  
  1071. BOOL
  1072. RemoveUnusedSystems (
  1073.     PPERFSYSTEM pSystemHead,
  1074.     PLINE       pLineHead
  1075. )
  1076. /*++
  1077.  
  1078.     walks system list and removes systems with no lines from list
  1079.  
  1080. --*/
  1081. {
  1082.     PPERFSYSTEM pSystem;
  1083.     PPERFSYSTEM pLastSystem;
  1084.     PLINE       pLine;
  1085.     BOOL        bSystemFound;
  1086.  
  1087.     pLastSystem = NULL;
  1088.  
  1089.     if ((ARGUMENT_PRESENT (pLineHead)) && (ARGUMENT_PRESENT(pSystemHead))) {
  1090.         for (pSystem = pSystemHead;
  1091.              pSystem;
  1092.              pLastSystem = pSystem, pSystem = pSystem->pSystemNext) {
  1093.             
  1094.             if (pSystem) {
  1095.                 bSystemFound = FALSE;
  1096.                 // walk lines to see if this system has a line
  1097.                 for (pLine = pLineHead; pLine; pLine = pLine->pLineNext) {
  1098.                     // if system in line is this system, then bailout
  1099.                     if (strsame (pLine->lnSystemName, pSystem->sysName)) {
  1100.                         bSystemFound = TRUE;
  1101.                         break;
  1102.                     }
  1103.                 }
  1104.                 
  1105.                 if (!bSystemFound) {    // delete this unused system
  1106.  
  1107.                     // fix pointers
  1108.                     pLastSystem->pSystemNext = pSystem->pSystemNext;
  1109.  
  1110.                     SystemFree (pSystem, TRUE);
  1111.  
  1112.                     // set pointer back to a valid structure
  1113.                     pSystem = pLastSystem; 
  1114.                 }
  1115.             }
  1116.         }
  1117.     }
  1118.     return TRUE;
  1119. }
  1120.  
  1121. void CreatePerfmonSystemObjects ()
  1122. {
  1123.    ColorBtnFace = GetSysColor (COLOR_BTNFACE) ;
  1124.    hBrushFace = CreateSolidBrush (ColorBtnFace) ;
  1125.    hPenHighlight = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNHIGHLIGHT)) ;
  1126.    hPenShadow = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNSHADOW)) ;
  1127. }
  1128.  
  1129. void DeletePerfmonSystemObjects ()
  1130. {
  1131.    if (hBrushFace)
  1132.       {
  1133.       DeleteBrush (hBrushFace) ;
  1134.       hBrushFace = 0 ;
  1135.       }
  1136.    if (hPenHighlight)
  1137.       {
  1138.       DeletePen (hPenHighlight) ;
  1139.       hPenHighlight = 0 ;
  1140.       }
  1141.    if (hPenShadow)
  1142.       {
  1143.       DeletePen (hPenShadow) ;
  1144.       hPenShadow = 0 ;
  1145.       }
  1146. }
  1147.  
  1148. // This routine count the number of the same charatcer in the input string
  1149. int  SameCharCount (LPTSTR pInputString)
  1150. {
  1151.    int      Count = 0 ;
  1152.    TCHAR    InputChar = *pInputString ;
  1153.  
  1154.    if (InputChar)
  1155.       {
  1156.       while (InputChar == *pInputString)
  1157.          {
  1158.          Count ++ ;
  1159.          pInputString ++ ;
  1160.          }
  1161.       }
  1162.    return (Count) ;
  1163. }
  1164.  
  1165. // create the format to be used in SystemTimeDateString()
  1166. BOOL CreateDateFormat (LPTSTR pShortDate)
  1167. {
  1168.    int   iIndex ;
  1169.    int   iDayCount ;
  1170.    int   iMonthCount ;
  1171.    int   DateSeparatorCount ;
  1172.    TCHAR szDateSeparator [10] ;
  1173.    BOOL  bFirstLeading, bSecondLeading, bThirdLeading ;
  1174.  
  1175.    // get the date format based on the first char
  1176.    if (*pShortDate == TEXT('M') || *pShortDate == TEXT('m'))
  1177.       {
  1178.       DateStyle = MONTH_FIRST ;
  1179.       }
  1180.    else if (*pShortDate == TEXT('D') || *pShortDate == TEXT('d'))
  1181.       {
  1182.       DateStyle = DAY_FIRST ;
  1183.       }
  1184.    else if (*pShortDate == TEXT('Y') || *pShortDate == TEXT('y'))
  1185.       {
  1186.       DateStyle = YEAR_FIRST ;
  1187.       }
  1188.    else
  1189.       {
  1190.       // bad format 
  1191.       return FALSE ;
  1192.       }
  1193.  
  1194.    bFirstLeading = bSecondLeading = bThirdLeading = FALSE ;
  1195.  
  1196.    switch (DateStyle)
  1197.       {
  1198.       case YEAR_FIRST:
  1199.          // YYYY-MM-DD
  1200.          YearCharCount = SameCharCount (pShortDate) ;
  1201.          pShortDate += YearCharCount ;
  1202.          DateSeparatorCount = SameCharCount (pShortDate) ;
  1203.  
  1204.          // get the separator string
  1205.          for (iIndex = 0; iIndex < DateSeparatorCount; iIndex ++)
  1206.             {
  1207.             szDateSeparator [iIndex] = *pShortDate++ ;
  1208.             }
  1209.          szDateSeparator [iIndex] = TEXT('\0') ;
  1210.  
  1211.          iMonthCount = SameCharCount (pShortDate) ;
  1212.          pShortDate += iMonthCount + DateSeparatorCount ;
  1213.          iDayCount = SameCharCount (pShortDate) ;
  1214.  
  1215.          if (YearCharCount == 2)
  1216.             {
  1217.             bFirstLeading = TRUE ;
  1218.             }
  1219.  
  1220.          if (iMonthCount == 2)
  1221.             {
  1222.             bSecondLeading = TRUE ;
  1223.             }
  1224.  
  1225.          if (iDayCount == 2)
  1226.             {
  1227.             bThirdLeading = TRUE ;
  1228.             }
  1229.  
  1230.          break ;
  1231.  
  1232.       case MONTH_FIRST:
  1233.          // MM-DD-YYYY
  1234.          iMonthCount = SameCharCount (pShortDate) ;
  1235.          pShortDate += iMonthCount ;
  1236.          DateSeparatorCount = SameCharCount (pShortDate) ;
  1237.  
  1238.          // get the separator string
  1239.          for (iIndex = 0; iIndex < DateSeparatorCount; iIndex ++)
  1240.             {
  1241.             szDateSeparator [iIndex] = *pShortDate++ ;
  1242.             }
  1243.          szDateSeparator [iIndex] = TEXT('\0') ;
  1244.          
  1245.          iDayCount = SameCharCount (pShortDate) ;
  1246.          pShortDate += iMonthCount + DateSeparatorCount ;
  1247.          YearCharCount = SameCharCount (pShortDate) ;
  1248.  
  1249.  
  1250.          if (iMonthCount == 2)
  1251.             {
  1252.             bFirstLeading = TRUE ;
  1253.             }
  1254.  
  1255.          if (iDayCount == 2)
  1256.             {
  1257.             bSecondLeading = TRUE ;
  1258.             }
  1259.  
  1260.          if (YearCharCount == 2)
  1261.             {
  1262.             bThirdLeading = TRUE ;
  1263.             }
  1264.  
  1265.          break ;
  1266.  
  1267.       case DAY_FIRST:
  1268.          // DD-MM-YYYY
  1269.          iDayCount = SameCharCount (pShortDate) ;
  1270.          pShortDate += iDayCount ;
  1271.          DateSeparatorCount = SameCharCount (pShortDate) ;
  1272.  
  1273.          // get the separator string
  1274.          for (iIndex = 0; iIndex < DateSeparatorCount; iIndex ++)
  1275.             {
  1276.             szDateSeparator [iIndex] = *pShortDate++ ;
  1277.             }
  1278.          szDateSeparator [iIndex] = TEXT('\0') ;
  1279.          
  1280.          iMonthCount = SameCharCount (pShortDate) ;
  1281.          pShortDate += iMonthCount + DateSeparatorCount ;
  1282.          YearCharCount = SameCharCount (pShortDate) ;
  1283.  
  1284.          if (iDayCount == 2)
  1285.             {
  1286.             bFirstLeading = TRUE ;
  1287.             }
  1288.  
  1289.          if (iMonthCount == 2)
  1290.             {
  1291.             bSecondLeading = TRUE ;
  1292.             }
  1293.  
  1294.          if (YearCharCount == 2)
  1295.             {
  1296.             bThirdLeading = TRUE ;
  1297.             }
  1298.  
  1299.          break ;
  1300.       }
  1301.  
  1302.    // now generate the date format
  1303.    lstrcpy (szDateFormat, bFirstLeading ? LeadingZeroStr : NoLeadingZeroStr) ;
  1304.    lstrcat (szDateFormat, szDateSeparator) ;
  1305.    lstrcat (szDateFormat, bSecondLeading ? LeadingZeroStr : NoLeadingZeroStr) ;
  1306.    lstrcat (szDateFormat, szDateSeparator) ;
  1307.    lstrcat (szDateFormat, bThirdLeading ? LeadingZeroStr : NoLeadingZeroStr) ;
  1308.  
  1309.    return TRUE ;
  1310. }
  1311.  
  1312. BOOL CreateTimeFormat (LPTSTR pTimeSeparator, int iLeadingZero)
  1313. {
  1314.    // create the format to be used in SystemTimeTimeString 
  1315.    if (iLeadingZero)
  1316.       {
  1317.       lstrcpy (szTimeFormat, LeadingZeroStr) ;
  1318.       }
  1319.    else
  1320.       {
  1321.       lstrcpy (szTimeFormat, NoLeadingZeroStr) ;
  1322.       }
  1323.  
  1324.    lstrcat (szTimeFormat, pTimeSeparator) ;
  1325.    lstrcat (szTimeFormat, LeadingZeroStr) ;
  1326.    lstrcat (szTimeFormat, pTimeSeparator) ;
  1327. //   lstrcat (szTimeFormat, LeadingZeroStr) ;
  1328.  
  1329.    // Duplicate the format without the msec field (for export use)
  1330.    lstrcpy (szTimeFormat1, szTimeFormat) ;
  1331.  
  1332.    // for the msec
  1333.    lstrcat (szTimeFormat, TEXT("%02.1f")) ;
  1334.  
  1335.    // for sec without msec
  1336.    lstrcat (szTimeFormat1, TEXT("%02d")) ;
  1337.  
  1338.    if (iTime == 0)
  1339.       {
  1340.       lstrcat (szTimeFormat, TEXT(" %s ")) ;
  1341.       lstrcat (szTimeFormat1, TEXT(" %s ")) ;
  1342.       }
  1343.  
  1344.    return TRUE ;
  1345. }  // CreateTimeFormats
  1346.  
  1347. BOOL GetInternational()
  1348. {
  1349.    TCHAR szShortDate[40] ;
  1350.    TCHAR szTime[40] ;   // time separator
  1351.    DWORD RetCode ;
  1352.    int   iTLZero = 0 ;      // = 0 for no leading zero, <> 0 for leading zero
  1353.    CHAR  aLanguageStr [2] ;
  1354.    LPSTR pRetStr ;
  1355.    LPTSTR lpStr ;
  1356.  
  1357.    // read the data from the win.ini (which i smapped to registry)
  1358.    RetCode = GetProfileString(szInternational,
  1359.       TEXT("sShortDate"), szShortDate, szShortDate, sizeof(szShortDate)/sizeof(TCHAR));
  1360.    
  1361.    if (RetCode)
  1362.       {
  1363.       RetCode = GetProfileString(szInternational,
  1364.          TEXT("sTime"), szTime, szTime, sizeof(szTime)/sizeof(TCHAR));
  1365.       }
  1366.  
  1367.  
  1368.    if (RetCode)
  1369.       {
  1370.       iTime   = GetProfileInt(szInternational, TEXT("iTime"), iTime);
  1371.       iTLZero = GetProfileInt(szInternational, TEXT("iTLZero"), iTLZero);
  1372.  
  1373.       GetProfileString(szInternational, TEXT("sDecimal"), szDecimal, szDecimal, sizeof(szDecimal)/sizeof(TCHAR));
  1374.  
  1375.       if (iTime == 0)
  1376.          {
  1377.          // get the AM PM strings for 12-hour format.
  1378.          // These two strings could be NULL.
  1379.          sz1159[0] = sz2359[0] = TEXT('\0') ;
  1380.          GetProfileString(szInternational,
  1381.             TEXT("s1159"), sz1159, sz1159, sizeof(sz1159)/sizeof(TCHAR));
  1382.  
  1383.          GetProfileString(szInternational,
  1384.             TEXT("s2359"), sz2359, sz2359, sizeof(sz2359)/sizeof(TCHAR));
  1385.          }
  1386.       }
  1387.  
  1388.    // create the two formats
  1389.    if (RetCode)
  1390.       {
  1391.       RetCode = (DWORD) CreateDateFormat (szShortDate) ;
  1392.       }
  1393.  
  1394.    if (RetCode)
  1395.       {
  1396.       RetCode = (DWORD) CreateTimeFormat (szTime, iTLZero) ;
  1397.       }
  1398.  
  1399.    // use the system default language numeric
  1400.    aLanguageStr[0] = '\0' ;
  1401.    pRetStr = setlocale(LC_NUMERIC, aLanguageStr);
  1402.  
  1403.    // get current decimal point used by C-runtime
  1404.    TSPRINTF (szShortDate, TEXT("%f"), (FLOAT)1.0) ;
  1405.    lpStr = szShortDate ;
  1406.  
  1407.    szCurrentDecimal [0] = TEXT('\0') ;
  1408.  
  1409.    while (*lpStr != TEXT('\0'))
  1410.       {
  1411.       if (*lpStr == TEXT('1'))
  1412.          {
  1413.          lpStr++ ;
  1414.          szCurrentDecimal [0] = *lpStr ;
  1415.          break ;
  1416.          }
  1417.       lpStr++ ;
  1418.       }
  1419.    
  1420.    if (szCurrentDecimal[0] == TEXT('\0'))
  1421.       {
  1422.       szCurrentDecimal [0] = TEXT('.') ;
  1423.       }
  1424.  
  1425.    return (RetCode != 0) ;
  1426. }  // GetInternational
  1427.  
  1428.  
  1429. // this routine is called to get the date/time formats either
  1430. // for the resource or from the registry.
  1431. void GetDateTimeFormats ()
  1432. {
  1433.    PALERT        pAlert ;
  1434.    PLOG          pLog ;
  1435.    if (!GetInternational())
  1436.       {
  1437.       // GetInternational failed, then get default formats from resource
  1438.       iTime = 0 ;
  1439.       DateStyle = MONTH_FIRST ;
  1440.       YearCharCount = 4 ;
  1441.       StringLoad (IDS_S1159, sz1159) ;
  1442.       StringLoad (IDS_S2359, sz2359) ;
  1443.       StringLoad (IDS_TIME_FORMAT, szTimeFormat) ;
  1444.       StringLoad (IDS_SHORT_DATE_FORMAT, szDateFormat) ;
  1445.       }
  1446.    WindowInvalidate (PerfmonViewWindow()) ;
  1447.  
  1448.    // reset all the field taht may be affected by the
  1449.    // language numberic changes
  1450.  
  1451.    pAlert = AlertData (hWndMain) ;
  1452.    pLog = LogData (hWndMain) ;
  1453.  
  1454.    if (pAlert)
  1455.       {
  1456.       DialogSetInterval (hWndAlert, IDD_ALERTINTERVAL, pAlert->iIntervalMSecs) ;
  1457.       }
  1458.  
  1459.    if (pLog)
  1460.       {
  1461.       DialogSetInterval (hWndLog, IDD_LOGINTERVAL, pLog->iIntervalMSecs) ;
  1462.       }
  1463. }  // GetDateTimeFormats
  1464.  
  1465. void ConvertDecimalPoint (LPTSTR lpFloatPointStr)
  1466. {
  1467.    if (szCurrentDecimal[0] == szDecimal[0])
  1468.       {
  1469.       // no need to convert anything
  1470.       return ;
  1471.       }
  1472.  
  1473.    while (*lpFloatPointStr)
  1474.       {
  1475.       if (*lpFloatPointStr == szCurrentDecimal[0])
  1476.          {
  1477.          *lpFloatPointStr = szDecimal[0] ;
  1478.          break ;
  1479.          }
  1480.       ++lpFloatPointStr ;
  1481.       }
  1482. }  // ConvertDecimalPoint
  1483.  
  1484. void ReconvertDecimalPoint (LPTSTR lpFloatPointStr)
  1485. {
  1486.    if (szCurrentDecimal[0] == szDecimal[0])
  1487.       {
  1488.       // no need to convert anything
  1489.       return ;
  1490.       }
  1491.  
  1492.    while (*lpFloatPointStr)
  1493.       {
  1494.       if (*lpFloatPointStr == szDecimal[0])
  1495.          {
  1496.          *lpFloatPointStr = szCurrentDecimal[0] ;
  1497.          break ;
  1498.          }
  1499.       ++lpFloatPointStr ;
  1500.       }
  1501. }  // ReconvertDecimalPoint
  1502.  
  1503.  
  1504. 
  1505.