home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / memsz331.zip / Source.zip / SNAPSHOT.CPP < prev    next >
Text File  |  1996-11-29  |  26KB  |  731 lines

  1. /*************************************************************** SNAPSHOT.CPP
  2.  *                                                                          *
  3.  *           Standalone Text-mode Snapshot of System Resources              *
  4.  *                                                                          *
  5.  ****************************************************************************/
  6.  
  7. #define INCL_BASE
  8. #define INCL_DOSDEVIOCTL
  9. #define INCL_PM
  10. #include <os2.h>
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15.  
  16. #include "Config.h"
  17. #include "DQPS.h"
  18. #include "MemSize.h"
  19. #include "Module.h"
  20. #include "ReString.h"
  21. #include "Support.h"
  22. #include "SVDisk.h"
  23.  
  24.  
  25. /****************************************************************************
  26.  *                                                                          *
  27.  *                       Definitions & Declarations                         *
  28.  *                                                                          *
  29.  ****************************************************************************/
  30.  
  31. static void FormatValue ( ULONG Value, char Text[], COUNTRYINFO &CountryInfo, int ShowK=SHOWK_ABOVE512, int ShowTrueK=TRUE, int ShowM=TRUE, int Scale=1 ) ;
  32. extern PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) ;
  33. static char *CopyString ( char *Buffer, char *Original ) ;
  34. static int CheckDrive ( USHORT Drive, PBYTE FileSystem, PBYTE DiskLabel ) ;
  35.  
  36.  
  37. /****************************************************************************
  38.  *                                                                          *
  39.  *                              Mainline                                    *
  40.  *                                                                          *
  41.  ****************************************************************************/
  42.  
  43. extern int main ( int argc, char *argv[] ) {
  44.  
  45.    // Initialization
  46.  
  47.    Module Library ( PSZ(PROGRAM_NAME) ) ;
  48.  
  49.    COUNTRYCODE CountryCode ;
  50.    CountryCode.country = 0 ;
  51.    CountryCode.codepage = 0 ;
  52.  
  53.    COUNTRYINFO CountryInfo ;
  54.    ULONG Count ;
  55.    ULONG Status = DosGetCtryInfo ( sizeof(CountryInfo), &CountryCode, &CountryInfo, &Count ) ;
  56.    if ( Status ) {
  57.       CountryInfo.fsDateFmt = DATEFMT_MM_DD_YY ;
  58.       CountryInfo.fsTimeFmt = 0 ;
  59.       CountryInfo.szDateSeparator[0] = '/' ;
  60.       CountryInfo.szDateSeparator[1] = 0 ;
  61.       CountryInfo.szTimeSeparator[0] = ':' ;
  62.       CountryInfo.szTimeSeparator[1] = 0 ;
  63.       CountryInfo.szThousandsSeparator[0] = ',' ;
  64.       CountryInfo.szThousandsSeparator[1] = 0 ;
  65.    } /* endif */
  66.  
  67.    char Text [80] ;
  68.    ULONG Size = 2 ;
  69.    if ( PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("iDate"), Text, &Size ) ) 
  70.       CountryInfo.fsDateFmt = atoi ( Text ) ;
  71.  
  72.    Size = 2 ;
  73.    if ( PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("iTime"), Text, &Size ) ) 
  74.       CountryInfo.fsTimeFmt = UCHAR ( atoi ( Text ) ) ;
  75.  
  76.    Size = 2 ;
  77.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("sDate"), CountryInfo.szDateSeparator, &Size ) ;
  78.  
  79.    Size = 2 ;
  80.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("sTime"), CountryInfo.szTimeSeparator, &Size ) ;
  81.  
  82.    Size = 3 ;
  83.    char szAm [3] ;
  84.    strcpy ( szAm, "am" ) ;
  85.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("s1159"), szAm, &Size ) ;
  86.  
  87.    Size = 3 ;
  88.    char szPm [3] ;
  89.    strcpy ( szPm, "pm" ) ;
  90.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("s2359"), szPm, &Size ) ;
  91.  
  92.    Size = 2 ;
  93.    PrfQueryProfileData ( HINI_USERPROFILE, PSZ("PM_National"), PSZ("sThousand"), CountryInfo.szThousandsSeparator, &Size ) ;
  94.  
  95.    PSZ Swappath = ScanSystemConfig ( 0, PSZ("SWAPPATH") ) ;
  96.    if ( Swappath == NULL ) 
  97.       Swappath = PSZ("C:\\OS2\\SYSTEM 0") ;
  98.    char SwapPath [CCHMAXPATH] ;
  99.    char *p = CopyString ( SwapPath, PCHAR(Swappath) ) ;
  100.    ULONG MinFree ;
  101.    sscanf ( p, " %li", &MinFree ) ;
  102.  
  103.    PSZ SpoolPath = 0 ;
  104.    if ( PrfQueryProfileSize ( HINI_PROFILE, PSZ("PM_SPOOLER"), PSZ("DIR"), &Size ) ) {
  105.       SpoolPath = PSZ ( malloc ( (int)Size ) ) ;
  106.       if ( SpoolPath ) {
  107.          if ( PrfQueryProfileData ( HINI_PROFILE, PSZ("PM_SPOOLER"), PSZ("DIR"), SpoolPath, &Size ) ) {
  108.             PBYTE p = PBYTE( strchr ( PCHAR(SpoolPath), ';' ) ) ;
  109.             if ( p ) {
  110.                *p = 0 ;
  111.             } /* endif */
  112.          } else {
  113.             free ( SpoolPath ) ;
  114.             SpoolPath = 0 ;
  115.          } /* endif */
  116.       } /* endif */
  117.    } /* endif */
  118.    if ( SpoolPath == 0 )
  119.       SpoolPath = PSZ ( "C:\\SPOOL" ) ;
  120.  
  121.  
  122.    // Date and Time
  123.  
  124.    DATETIME DateTime ;
  125.    DosGetDateTime ( &DateTime ) ;
  126.  
  127.    ResourceString DaysOfWeek ( Library.QueryHandle(), IDS_DAYSOFWEEK ) ;
  128.  
  129.    switch ( CountryInfo.fsDateFmt ) {
  130.       case DATEFMT_DD_MM_YY:
  131.          sprintf ( Text, "%0.*s, %02lu%s%02lu ",
  132.             strlen(PCHAR(DaysOfWeek))/7, PSZ(DaysOfWeek) + DateTime.weekday*(strlen(PCHAR(DaysOfWeek))/7),
  133.             DateTime.day, CountryInfo.szDateSeparator, DateTime.month ) ;
  134.          break ;
  135.       case DATEFMT_YY_MM_DD:
  136.          sprintf ( Text, "%02lu%s%02lu %0.*s ",
  137.             DateTime.month, CountryInfo.szDateSeparator, DateTime.day,
  138.             strlen(PCHAR(DaysOfWeek))/7, PSZ(DaysOfWeek) + DateTime.weekday*(strlen(PCHAR(DaysOfWeek))/7) ) ;
  139.          break ;
  140.       case DATEFMT_MM_DD_YY:
  141.       default:
  142.          sprintf ( Text, "%0.*s, %02lu%s%02lu ",
  143.             strlen(PCHAR(DaysOfWeek))/7, PSZ(DaysOfWeek) + DateTime.weekday*(strlen(PCHAR(DaysOfWeek))/7),
  144.             DateTime.month, CountryInfo.szDateSeparator, DateTime.day ) ;
  145.          break ;
  146.    } /* endswitch */
  147.  
  148.    if ( CountryInfo.fsTimeFmt ) {
  149.       sprintf ( Text+strlen(Text), "%02lu%s%02lu", DateTime.hours, CountryInfo.szTimeSeparator, DateTime.minutes ) ;
  150.    } else {
  151.       PCHAR AmPm ;
  152.       if ( DateTime.hours ) {
  153.          if ( DateTime.hours < 12 ) {
  154.             AmPm = szAm ;
  155.          } else if ( DateTime.hours == 12 ) {
  156.             if ( DateTime.minutes )
  157.                AmPm = szPm ;
  158.             else
  159.                AmPm = szAm ;
  160.          } else if ( DateTime.hours > 12 ) {
  161.             DateTime.hours -= 12 ;
  162.             AmPm = szPm ;
  163.          } /* endif */
  164.       } else {
  165.          DateTime.hours = 12 ;
  166.          if ( DateTime.minutes )
  167.             AmPm = szAm ;
  168.          else
  169.             AmPm = szPm ;
  170.       } /* endif */
  171.       sprintf ( Text+strlen(Text), "%02lu%s%02lu%s", DateTime.hours, CountryInfo.szTimeSeparator, DateTime.minutes, AmPm ) ;
  172.    } /* endif */
  173.    printf ( "%*s%s", 40-strlen(Text)/2, "", Text ) ;
  174.    printf ( "\n" ) ;
  175.  
  176.  
  177.    // Elapsed Time
  178.  
  179.    ResourceString ElapsedLabel ( Library.QueryHandle(), IDS_ELAPSED ) ;
  180.    int Column = printf ( "%s", PSZ(ElapsedLabel) ) ;
  181.    strcpy ( Text, "" ) ;
  182.  
  183.    ULONG Milliseconds ;
  184.    DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &Milliseconds, sizeof(Milliseconds) ) ;
  185.  
  186.    ULONG Time = Milliseconds / 60000L ;
  187.  
  188.    ULONG NumberOfDays = Time / ( 60L * 24L ) ;
  189.  
  190.    if ( NumberOfDays ) {
  191.       ResourceString Day ( Library.QueryHandle(), IDS_DAY ) ;
  192.       ResourceString Days ( Library.QueryHandle(), IDS_DAYS ) ;
  193.       sprintf ( Text+strlen(Text), "%lu %s, ", NumberOfDays, NumberOfDays > 1 ? PSZ(Days) : PSZ(Day) ) ;
  194.    } /* endif */
  195.  
  196.    ULONG Minutes = Time % ( 60L * 24L ) ;
  197.    sprintf ( Text+strlen(Text), "%lu%s%02lu ", Minutes/60, CountryInfo.szTimeSeparator, Minutes%60 ) ;
  198.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  199.    printf ( "\n" ) ;
  200.  
  201.  
  202.    // Physical Memory Free
  203.  
  204.    ResourceString PhysicalMemoryFree ( Library.QueryHandle(), IDS_MEMORY ) ;
  205.    Column = printf ( "%s", PSZ(PhysicalMemoryFree) ) ;
  206.    APIRET16 APIENTRY16 Dos16MemAvail ( PULONG pulAvailMem ) ;
  207.    ULONG PhysMemFree ;
  208.    Dos16MemAvail ( &PhysMemFree ) ;
  209.    FormatValue ( PhysMemFree, Text, CountryInfo ) ;
  210.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  211.    printf ( "\n" ) ;
  212.  
  213.  
  214.    // Virtual Memory Free
  215.  
  216.    ResourceString VirtualMemoryFree ( Library.QueryHandle(), IDS_VIRTUAL ) ;
  217.    Column = printf ( "%s", PSZ(VirtualMemoryFree) ) ;
  218.    ULONG VirtMemFree ;
  219.    DosQuerySysInfo ( QSV_TOTAVAILMEM, QSV_TOTAVAILMEM, &VirtMemFree, sizeof(VirtMemFree) ) ;
  220.    FormatValue ( VirtMemFree, Text, CountryInfo ) ;
  221.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  222.    printf ( "\n" ) ;
  223.  
  224.  
  225.    // Swapfile Size
  226.  
  227.    ResourceString SwapfileSize ( Library.QueryHandle(), IDS_SWAPSIZE ) ;
  228.    Column = printf ( "%s", PSZ(SwapfileSize) ) ;
  229.    ULONG PathSize ;
  230.    DosQuerySysInfo ( QSV_MAX_PATH_LENGTH, QSV_MAX_PATH_LENGTH, &PathSize, sizeof(PathSize) ) ;
  231.    PBYTE Path = PBYTE ( malloc ( size_t(PathSize) ) ) ;
  232.    strcpy ( PCHAR(Path), PCHAR(SwapPath) ) ;
  233.    if ( Path[strlen(PCHAR(Path))-1] != '\\' ) {
  234.       strcat ( PCHAR(Path), "\\" ) ;
  235.    } /* endif */
  236.    strcat ( PCHAR(Path), "SWAPPER.DAT" ) ;
  237.    ULONG SwapSize = 0 ;
  238.    FILESTATUS3 FileStatus ;
  239.    if ( DosQueryPathInfo ( (PSZ)Path, FIL_STANDARD, &FileStatus, sizeof(FileStatus) ) == 0 ) {
  240.       SwapSize = FileStatus.cbFileAlloc ;
  241.    } /* endif */
  242.    free ( Path ) ;
  243.    FormatValue ( SwapSize, Text, CountryInfo ) ;
  244.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  245.    printf ( "\n" ) ;
  246.  
  247.  
  248.    // Available Swap Space
  249.  
  250.    ResourceString SwapspaceFree ( Library.QueryHandle(), IDS_SWAPFREE ) ;
  251.    Column = printf ( "%s", PSZ(SwapspaceFree) ) ;
  252.    Path = PBYTE ( malloc ( size_t(PathSize) ) ) ;
  253.    strcpy ( PCHAR(Path), (PCHAR)SwapPath ) ;
  254.    strcat ( PCHAR(Path), "\\SWAPPER.DAT" ) ;
  255.    ULONG SwapFree = 0 ;
  256.    if ( Path[0] ) {
  257.       DosError ( FERR_DISABLEHARDERR ) ;
  258.       FSALLOCATE Allocation ;
  259.       DosQueryFSInfo ( Path[0]-'A'+1, FSIL_ALLOC, (PBYTE)&Allocation, sizeof(Allocation) ) ;
  260.       DosError ( FERR_ENABLEHARDERR ) ;
  261.       SwapFree = Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ;
  262.    } /* endif */
  263.    if ( SwapFree < ULONG(MinFree*1024L) )
  264.       SwapFree = 0 ;
  265.    else
  266.       SwapFree = SwapFree - ULONG(MinFree*1024L) ;
  267.    free ( Path ) ;
  268.    FormatValue ( SwapFree, Text, CountryInfo ) ;
  269.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  270.    printf ( "\n" ) ;
  271.  
  272.  
  273.    // Swapfile Slack Space
  274.  
  275.    ResourceString SwapslackFree ( Library.QueryHandle(), IDS_SWAPSLACK ) ;
  276.    Column = printf ( "%s", PSZ(SwapslackFree) ) ;
  277.    LONG SwapSlack = VirtMemFree - SwapFree - PhysMemFree ;
  278.    SwapSlack = max ( 0, SwapSlack ) ;
  279.    FormatValue ( SwapSlack, Text, CountryInfo ) ;
  280.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  281.    printf ( "\n" ) ;
  282.  
  283.  
  284.    // Spoolfile Size
  285.  
  286.    ResourceString SpoolSize ( Library.QueryHandle(), IDS_SPOOLSIZE ) ;
  287.    Column = printf ( "%s", PSZ(SpoolSize) ) ;
  288.    Path = PBYTE ( malloc ( size_t(PathSize) ) ) ;
  289.    PFILEFINDBUF3 Found = PFILEFINDBUF3 ( malloc ( size_t(PathSize+sizeof(FILEFINDBUF3)) ) ) ;
  290.    strcpy ( (PCHAR)Path, (PCHAR)SpoolPath ) ;
  291.    strcat ( (PCHAR)Path, "\\*.*" ) ;
  292.    HDIR hDir = (HDIR) HDIR_CREATE ;
  293.    Count = 1 ;
  294.    ULONG TotalSize = 0 ;
  295.    if ( !DosFindFirst2 ( Path, &hDir,
  296.       FILE_NORMAL | FILE_READONLY | FILE_DIRECTORY | FILE_ARCHIVED,
  297.       Found, PathSize+sizeof(FILEFINDBUF3), &Count, FIL_STANDARD ) ) {
  298.       do {
  299.          if ( !strcmp ( (PCHAR)Found->achName, "." ) OR !strcmp ( (PCHAR)Found->achName, ".." ) ) {
  300.             continue ;
  301.          } /* endif */
  302.          if ( Found->attrFile & FILE_DIRECTORY ) {
  303.             HDIR hDir2 = (HDIR) HDIR_CREATE ;
  304.             strcpy ( (PCHAR)Path, (PCHAR)SpoolPath ) ;
  305.             strcat ( (PCHAR)Path, "\\" ) ;
  306.             strcat ( (PCHAR)Path, (PCHAR)Found->achName ) ;
  307.             strcat ( (PCHAR)Path, "\\*.*" ) ;
  308.             ULONG Count2 = 1 ;
  309.             if ( !DosFindFirst2 ( Path, &hDir2,
  310.                FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED,
  311.                Found, PathSize+sizeof(FILEFINDBUF3), &Count2, FIL_STANDARD ) ) {
  312.                do {
  313.                   TotalSize += Found->cbFileAlloc ;
  314.                } while ( !DosFindNext ( hDir2, Found, PathSize+sizeof(FILEFINDBUF3), &Count2 ) ) ;
  315.                DosFindClose ( hDir2 ) ;
  316.             } /* endif */
  317.          } else {
  318.             TotalSize += Found->cbFileAlloc ;
  319.          } /* endif */
  320.       } while ( !DosFindNext ( hDir, Found, PathSize+sizeof(FILEFINDBUF3), &Count ) ) ;
  321.       DosFindClose ( hDir ) ;
  322.    } /* endif */
  323.    free ( Path ) ;
  324.    free ( Found ) ;
  325.    FormatValue ( TotalSize, Text, CountryInfo ) ;
  326.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  327.    printf ( "\n" ) ;
  328.  
  329.  
  330.    // Battery Status
  331.    HFILE Handle ;  ULONG Action ;
  332.    if ( !DosOpen ( (PSZ) "APM$", &Handle, &Action, 0, FILE_NORMAL, FILE_OPEN,
  333.          OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) ) {
  334.  
  335.       ResourceString BatteryStatus ( Library.QueryHandle(), IDS_BATTERY ) ;
  336.       Column = printf ( "%s", PSZ(BatteryStatus) ) ;
  337.  
  338.       struct {
  339.          USHORT ParmLength ;
  340.          USHORT PowerFlags ;
  341.          UCHAR  ACStatus ;
  342.          UCHAR  BatteryStatus ;
  343.          UCHAR  BatteryLife ;
  344.       } Parm ;
  345.       Parm.ParmLength = sizeof(Parm) ;
  346.       ULONG ParmLen = sizeof(Parm) ;
  347.       USHORT Data ;
  348.       ULONG DataLen = sizeof(Data) ;
  349.       if ( !DosDevIOCtl ( Handle, IOCTL_POWER, POWER_GETPOWERSTATUS, &Parm, sizeof(Parm), &ParmLen, &Data, sizeof(Data), &DataLen ) ) {
  350.          if ( Parm.PowerFlags & 1 ) {                       
  351.             if ( Parm.BatteryStatus == 3 ) {                
  352.                if ( Parm.BatteryLife < 100 ) {               
  353.                   ResourceString Charging ( Library.QueryHandle(),IDS_APM_CHARGING ) ;
  354.                   sprintf ( Text, "%s ", PCHAR(Charging) ) ;
  355.                } else {                                        
  356.                   sprintf ( Text, "%lu%%", 100 ) ;
  357.                } /* endif */
  358.             } else if ( Parm.ACStatus == 1 ) {              
  359.                ResourceString AC ( Library.QueryHandle(),IDS_APM_AC ) ;
  360.                sprintf ( Text, "%s ", PCHAR(AC) ) ;
  361.             } else if ( Parm.BatteryLife <= 100 ) {         
  362.                sprintf ( Text, "%lu%%", Parm.BatteryLife ) ;
  363.             } else {                                        
  364.                ResourceString Error ( Library.QueryHandle(),IDS_APM_ERROR ) ;
  365.                sprintf ( Text, "%s ", PCHAR(Error) ) ;
  366.             } /* endif */                                   
  367.          } else {
  368.             ResourceString Error ( Library.QueryHandle(),IDS_APM_ERROR ) ;
  369.             sprintf ( Text, "%s ", PCHAR(Error) ) ;
  370.          } /* endif */
  371.       } else {
  372.          ResourceString Error ( Library.QueryHandle(),IDS_APM_ERROR ) ;
  373.          sprintf ( Text, "%s ", PCHAR(Error) ) ;
  374.       } /* endif */
  375.  
  376.       DosClose ( Handle ) ;
  377.  
  378.       printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  379.       printf ( "\n" ) ;
  380.  
  381.    } /* endif */
  382.  
  383.  
  384.    // Active Task Count
  385.  
  386.    ResourceString ActiveTaskCount ( Library.QueryHandle(), IDS_TASKCOUNT ) ;
  387.    Column = printf ( "%s", PSZ(ActiveTaskCount) ) ;
  388.    ULONG TaskCount = WinQuerySwitchList ( 0, 0, 0 ) ;
  389.    sprintf ( Text, "%i ", TaskCount ) ;
  390.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  391.    printf ( "\n" ) ;
  392.  
  393.  
  394.    // Process Count
  395.  
  396.    ResourceString ProcessCount ( Library.QueryHandle(), IDS_PROCESSCOUNT ) ;
  397.    Column = printf ( "%s", PSZ(ProcessCount) ) ;
  398.    int ProcCount = 0 ;
  399.    PULONG DQPS_Buffer ;
  400.    DosAllocMem ( (PPVOID)&DQPS_Buffer, 0x10000, PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE ) ;
  401.    if ( !DosQProcStatus ( DQPS_Buffer, 0xFFFF ) ) {
  402.       qsPrec_s *pProcRecord = ((qsPtrRec_s*)DQPS_Buffer)->pProcRec ;
  403.       while ( pProcRecord->RecType == 1 ) {
  404.          int Size = sizeof(qsPrec_s) ;
  405.          Size += pProcRecord->cTCB * sizeof(qsTrec_s) ;
  406.          Size += pProcRecord->c16Sem * sizeof(short) ;
  407.          Size += pProcRecord->cLib * sizeof(short) ;
  408.          Size += pProcRecord->cShrMem * sizeof(short) ;
  409.          pProcRecord = (qsPrec_s*) ( (char*)pProcRecord + Size ) ;
  410.          ProcCount ++ ;
  411.       } /* endwhile */
  412.    } /* endif */
  413.    DosFreeMem ( DQPS_Buffer ) ;
  414.    sprintf ( Text, "%i ", ProcCount ) ;
  415.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  416.    printf ( "\n" ) ;
  417.  
  418.  
  419.    // Thread Count
  420.  
  421.    ResourceString ThreadCount ( Library.QueryHandle(), IDS_THREADCOUNT ) ;
  422.    Column = printf ( "%s", PSZ(ThreadCount) ) ;
  423.    int ThrdCount = 0 ;
  424.    DosAllocMem ( (PPVOID)&DQPS_Buffer, 0x10000, PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE ) ;
  425.    if ( !DosQProcStatus ( DQPS_Buffer, 0xFFFF ) ) {
  426.       ThrdCount = int ( ((qsPtrRec_s*)DQPS_Buffer)->pGlobalRec->cThrds ) ;
  427.    } /* endif */
  428.    DosFreeMem ( DQPS_Buffer ) ;
  429.    sprintf ( Text, "%i ", ThrdCount ) ;
  430.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  431.    printf ( "\n" ) ;
  432.  
  433.  
  434.    // Total Free Space
  435.  
  436.    ResourceString TotalFree ( Library.QueryHandle(), IDS_TOTALFREE ) ;
  437.    Column = printf ( "%s", PSZ(TotalFree) ) ;
  438.    ULONG Drive, Drives ;
  439.    DosQueryCurrentDisk ( &Drive, &Drives ) ;
  440.    ULONG Free = 0 ;
  441.    ULONG Mask = Drives >> 2 ;
  442.    for ( Drive=3; Drive<=26; Drive++ ) {
  443.       if ( Mask & 1 ) {
  444.          BYTE FileSystem [80] = { 0 } ;
  445.          BYTE DiskLabel [12] = { 0 } ;
  446.          if ( CheckDrive ( USHORT(Drive), FileSystem, DiskLabel ) ) {
  447.             DosError ( FERR_DISABLEHARDERR ) ;
  448.             FSALLOCATE Allocation ;
  449.             APIRET Status = DosQueryFSInfo ( Drive, FSIL_ALLOC, (PBYTE)&Allocation, sizeof(Allocation) ) ;
  450.             DosError ( FERR_ENABLEHARDERR ) ;
  451.             if ( Status ) {
  452.                Drives &= ~ ( 1 << (Drive-1) ) ;
  453.             } else {
  454.                Free += Allocation.cUnitAvail*Allocation.cSectorUnit*(Allocation.cbSector/256) ;
  455.             } /* endif */
  456.          } else {
  457.             Drives &= ~ ( 1 << (Drive-1) ) ;
  458.          } /* endif */
  459.       } /* endif */
  460.       Mask >>= 1 ;
  461.    } /* endfor */
  462.    FormatValue ( Free, Text, CountryInfo, SHOWK_ABOVE512, TRUE, TRUE, 256 ) ;
  463.    printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  464.    printf ( "\n" ) ;
  465.  
  466.  
  467.    // Drive Space Free
  468.    ResourceString DriveFree ( Library.QueryHandle(), IDS_DRIVE_FREE ) ;
  469.    Mask = Drives >> 2 ;
  470.    for ( Drive=3; Drive<=26; Drive++ ) {
  471.       if ( Mask & 1 ) {
  472.          BYTE FileSystem [80] = { 0 } ;
  473.          BYTE DiskLabel [12] = { 0 } ;
  474.          if ( CheckDrive ( USHORT(Drive), FileSystem, DiskLabel ) ) {
  475.             DosError ( FERR_DISABLEHARDERR ) ;
  476.             FSALLOCATE Allocation ;
  477.             APIRET Status = DosQueryFSInfo ( Drive, FSIL_ALLOC, (PBYTE)&Allocation, sizeof(Allocation) ) ;
  478.             DosError ( FERR_ENABLEHARDERR ) ;
  479.             if ( Status ) {
  480.                Drives &= ~ ( 1 << (Drive-1) ) ;
  481.             } else {
  482.                char Label [80] ;
  483.                sprintf ( Label, PCHAR(DriveFree), Drive+'A'-1 ) ;
  484.                if ( *DiskLabel && *FileSystem ) {
  485.                   Column = printf ( "%s (%s,%s)", Label, DiskLabel, FileSystem ) ;
  486.                } else if ( *DiskLabel ) {
  487.                   Column = printf ( "%s (%s)", Label, DiskLabel ) ;
  488.                } else if ( *FileSystem ) {
  489.                   Column = printf ( "%s (%s)", Label, FileSystem ) ;
  490.                } else {
  491.                   Column = printf ( "%s", Label ) ;
  492.                } /* endif */
  493.                Free = Allocation.cUnitAvail*Allocation.cSectorUnit*Allocation.cbSector ;
  494.                FormatValue ( Free, Text, CountryInfo ) ;
  495.                printf ( "%*s%s", 79-Column-strlen(Text), "", Text ) ;
  496.                printf ( "\n" ) ;
  497.             } /* endif */
  498.          } else {
  499.             Drives &= ~ ( 1 << (Drive-1) ) ;
  500.          } /* endif */
  501.       } /* endif */
  502.       Mask >>= 1 ;
  503.    } /* endfor */
  504.  
  505.    return ( 0 ) ;
  506. }
  507.  
  508. inline ULONG KiloScale ( ULONG Value, int ShowTrueK=TRUE, int Scale=1 ) {
  509.    if ( ShowTrueK ) {
  510.       return ( (Value+(0x200/Scale))/(0x400/Scale) ) ;
  511.    } else {
  512.       return ( (Value+(500/Scale))/(1000/Scale) ) ;
  513.    } /* endif */
  514. }
  515.  
  516. inline ULONG MegaScale ( ULONG Value, int ShowTrueK=TRUE, int Scale=1 ) {
  517.    if ( ShowTrueK ) {
  518.       return ( (Value+(0x80000/Scale))/(0x100000/Scale) ) ;
  519.    } else {
  520.       return ( (Value+(500000/Scale))/(1000000/Scale) ) ;
  521.    } /* endif */
  522. }
  523.  
  524. static void FormatValue ( ULONG Value, char Text[], COUNTRYINFO &CountryInfo, int ShowK, int ShowTrueK, int ShowM, int Scale ) {
  525.  
  526.    int MegaBreak = ShowTrueK ? 0x800000/Scale : 8000000/Scale ;
  527.    int KiloBreak = ShowTrueK ? 0x80000/Scale : 500000/Scale ;
  528.  
  529.    switch ( ShowK ) {
  530.       case SHOWK_NEVER:
  531.          sprintf ( Text, "%lu", Value*Scale ) ;
  532.          break;
  533.       case SHOWK_ALWAYS:
  534.          if ( !ShowM || ( Value < MegaBreak ) )
  535.             sprintf ( Text, "%lu", KiloScale(Value,ShowTrueK,Scale) ) ;
  536.          else 
  537.             sprintf ( Text, "%lu", MegaScale(Value,ShowTrueK,Scale) ) ;
  538.          break;
  539.       case SHOWK_ABOVE512:
  540.       default:
  541.          if ( Value < KiloBreak )
  542.             sprintf ( Text, "%lu", Value*Scale ) ;
  543.          else if ( !ShowM || ( Value < MegaBreak ) )
  544.             sprintf ( Text, "%lu", KiloScale(Value,ShowTrueK,Scale) ) ;
  545.          else
  546.             sprintf ( Text, "%lu", MegaScale(Value,ShowTrueK,Scale) ) ;
  547.          break;
  548.    } /* endswitch */
  549.  
  550.    char Work[100] ;
  551.    char *p1 = Text ;
  552.    char *p2 = Work ;
  553.    while ( *p1 ) {
  554.       *p2 = *p1 ;
  555.       p1 ++ ;
  556.       p2 ++ ;
  557.       if ( *p1 ) {
  558.          if ( strlen(p1) % 3 == 0 ) {
  559.             *p2 = CountryInfo.szThousandsSeparator [0] ;
  560.             p2 ++ ;
  561.          } /* endif */
  562.       } /* endif */
  563.    } /* endwhile */
  564.    *p2 = 0 ;
  565.    strcpy ( Text, Work ) ;
  566.  
  567.    p2 = Text + strlen(Text) ;
  568.    *(p2+1) = 0 ;
  569.    switch ( ShowK ) {
  570.       case SHOWK_NEVER:
  571.          *p2 = ' ' ;
  572.          break;
  573.       case SHOWK_ALWAYS:
  574.          if ( !ShowM || ( Value < MegaBreak ) )
  575.             *p2 = (char) ( ShowTrueK ? 'K' : 'k' ) ;
  576.          else 
  577.             *p2 = (char) ( ShowTrueK ? 'M' : 'm' ) ;
  578.          break;
  579.       case SHOWK_ABOVE512:
  580.       default:
  581.          if ( Value < KiloBreak )
  582.             *p2 = ' ' ;
  583.          else if ( !ShowM || ( Value < MegaBreak ) )
  584.             *p2 = (char) ( ShowTrueK ? 'K' : 'k' ) ;
  585.          else 
  586.             *p2 = (char) ( ShowTrueK ? 'M' : 'm' ) ;
  587.          break;
  588.    } /* endswitch */
  589. }
  590.  
  591. extern PSZ ScanSystemConfig ( HAB Anchor, PSZ Keyword ) {
  592.  
  593.    ULONG BootDrive ;
  594.    DosQuerySysInfo ( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &BootDrive, sizeof(BootDrive) ) ;
  595.  
  596.    WinUpper ( Anchor, 0, 0, Keyword ) ;
  597.  
  598.    char Path [_MAX_PATH] ;
  599.    Path[0] = (char) ( BootDrive + 'A' - 1 ) ;
  600.    Path[1] = 0 ;
  601.    strcat ( Path, ":\\CONFIG.SYS" ) ;
  602.  
  603.    FILE *File = fopen ( Path, "r" ) ;
  604.    if ( NOT File ) {
  605.       return ( 0 ) ;
  606.    } /* endif */
  607.  
  608.    static char Buffer [500] ;
  609.    while ( fgets ( Buffer, sizeof(Buffer), File ) ) {
  610.  
  611.       if ( Buffer[strlen(Buffer)-1] == '\n' ) 
  612.          Buffer[strlen(Buffer)-1] = 0 ;
  613.  
  614.       WinUpper ( Anchor, 0, 0, PSZ(Buffer) ) ;
  615.  
  616.       char *p = Buffer ;
  617.       while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
  618.  
  619.       if ( strncmp ( p, PCHAR(Keyword), strlen(PCHAR(Keyword)) ) )
  620.          continue ;
  621.  
  622.       p += strlen(PCHAR(Keyword)) ;
  623.       while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
  624.  
  625.       if ( *p++ != '=' )
  626.          continue ;
  627.  
  628.       while ( *p AND ( ( *p == ' ' ) OR ( *p == '\t' ) ) ) p++ ;
  629.  
  630.       fclose ( File ) ;
  631.       return ( PSZ(p) ) ;
  632.  
  633.    } /* endwhile */
  634.  
  635.    fclose ( File ) ;
  636.  
  637.    return ( 0 ) ;
  638. }
  639.  
  640. static char *CopyString ( char *Buffer, char *Original ) {
  641.    char *p1 = PCHAR(Original), *p2 = Buffer ;
  642.    BOOL Quoted = FALSE ;
  643.    *p2 = 0 ;
  644.    while ( *p1 ) {
  645.       if ( Quoted ) {
  646.          if ( *p1 == '"' ) {
  647.             Quoted = FALSE ;
  648.          } else {
  649.             *p2++ = *p1 ;
  650.             *p2 = 0 ;
  651.          } /* endif */
  652.       } else {
  653.          if ( *p1 == '"' ) {
  654.             Quoted = TRUE ;
  655.          } else if ( ( *p1 == ' ' ) OR ( *p1 == '\t' ) ) {
  656.             break ;
  657.          } else {
  658.             *p2++ = *p1 ;
  659.             *p2 = 0 ;
  660.          } /* endif */
  661.       } /* endif */
  662.       p1 ++ ;
  663.    } /* endwhile */ 
  664.    return ( p1 ) ;
  665. }
  666.  
  667. static int CheckDrive ( USHORT Drive, PBYTE FileSystem, PBYTE DiskLabel ) {
  668.  
  669.    BYTE Path [3] ;
  670.    Path[0] = (BYTE) ( Drive + 'A' - 1 ) ;
  671.    Path[1] = ':' ;
  672.    Path[2] = 0 ;
  673.  
  674.    DosError ( FERR_DISABLEHARDERR ) ;
  675.  
  676.    BYTE Buffer [1024] ;
  677.    ULONG Size = sizeof(Buffer) ;
  678.    ULONG Status = DosQueryFSAttach ( Path, 0, FSAIL_QUERYNAME, (PFSQBUFFER2)Buffer, &Size ) ;
  679.    DosError ( FERR_ENABLEHARDERR ) ;
  680.  
  681.    if ( Status ) {
  682.       return ( 0 ) ;   // Don't monitor.
  683.    } /* endif */
  684.  
  685.    USHORT cbName = PFSQBUFFER2(Buffer)->cbName ;
  686.    strcpy ( PCHAR(FileSystem), PCHAR(PFSQBUFFER2(Buffer+cbName)->szFSDName) ) ;
  687.  
  688.    if ( PFSQBUFFER2(Buffer)->iType == FSAT_REMOTEDRV ) 
  689.       return ( -1 ) ;  // Monitor but don't include in the total over all drives.
  690.  
  691.    if ( strcmpi ( FileSystem, "CDFS" ) == 0 ) 
  692.       return ( 0 ) ;  // Reject CDs.
  693.  
  694.    ULONG Action ;
  695.    HFILE Handle ;
  696.    Status = DosOpen ( Path, &Handle, &Action, 0, 0, FILE_OPEN,
  697.       OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE |
  698.       OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR, 0 ) ;
  699.  
  700.    if ( Status ) {
  701.       return ( 0 ) ;   // Don't monitor.
  702.    } /* endif */
  703.  
  704.    BOOL Addit = FALSE ;
  705.    BYTE Command = 0 ;
  706.    BYTE NonRemovable ;
  707.  
  708.    ULONG LengthIn = sizeof(Command) ;
  709.    ULONG LengthOut = sizeof(NonRemovable);
  710.  
  711.    if ( NOT DosDevIOCtl ( Handle, 8, 0x20,
  712.       &Command, sizeof(Command), &LengthIn,
  713.       &NonRemovable, sizeof(NonRemovable), &LengthOut ) ) {
  714.  
  715.       Addit = NonRemovable ;
  716.  
  717.       if ( !NonRemovable && IsSVDisk((UCHAR)Drive) ) 
  718.          Addit = TRUE ;
  719.  
  720.    } /* endif */
  721.  
  722.    DosClose ( Handle ) ;
  723.  
  724.    FSINFO Info ;
  725.    if ( DosQueryFSInfo ( Drive, FSIL_VOLSER, PBYTE(&Info), sizeof(Info) ) == 0 )
  726.       strcpy ( PCHAR(DiskLabel), PCHAR(Info.vol.szVolLabel) ) ;
  727.  
  728.    return ( int(Addit) ) ;    // Monitor and include in overall total if not removable.
  729. }
  730.  
  731.