/***************************************************************************/
/*                                                                         */
/*    PROGRAM NAME: STATS32                                                */
/*    -------------                                                        */
/*    OS/2 Lan Server 3.0 API 32 bit sample program.                       */
/*    @Copyright International Business Machines Corp. 1984, 1992          */
/*    @Copyright Microsoft Corp. 1984, 1991                                */
/*                                                                         */
/*    What this program does:                                              */
/*                     It monitors server performance and loading at       */
/*                user-specified intervals.                                */
/*                     A server can be monitored both locally and          */
/*                remotely.                                                */
/*                     There are two types of monitoring that may be       */
/*                used. Monitoring of the server portion of a              */
/*                server's LAN code and monitoring of the requester        */
/*                portion of the server's LAN code.                        */
/*                     The LAN Requester must be running to execute        */
/*                this program. The userid must be defined as an           */
/*                administrator.                                           */
/*                                                                         */
/*    REQUIRED FILES:                                                      */
/*    ---------------                                                      */
/*    STATS32.MAK     - IBM C/Set2 MAKE File.                              */
/*    STATS32.C       - C source code for the main program.                */
/*    ERRMSG.C        - C source code for the Error_Message function.      */
/*                                                                         */
/*    REQUIRED LIBRARIES:                                                  */
/*    -------------------                                                  */
/*    NETAPI.LIB     -  Netapi library for OS/2                            */
/*                                                                         */
/*    NetAPI functions used in this program :                              */
/*    ---------------------------------------                              */
/*    NetStatisticsGet2                                                    */
/*                                                                         */
/*    HOW TO COMPILE THIS PROGRAM:                                         */
/*    ----------------------------                                         */
/*    ICC /c /Gt+ /DINCL_32 USERENUM.C                                     */
/*                                                                         */
/***************************************************************************/

/*--------------------- OS/2 Include definitions --------------------------*/

#define INCL_BASE
#define INCL_KBD
#include <os2.h>

/*----------- LAN Systems API Toolkit include definitions -----------------*/
#include <lanserv\netcons.h>
#include <lanserv\netstats.h>
#include <lanserv\neterr.h>

/*--------------------- C Include definitions -----------------------------*/
#include <stdio.h>
#include <stdlib.h>

/*--------------------------- Definitions ---------------------------------*/

#define SET_TO_CLEAR        0x1
#define NOT_SET_TO_CLEAR    0x0
#define NO                    0
#define YES                   1
#define ONE_SECOND         1000L
#define EXECUTE              'E'
#define PAUSE                'P'
#define lcPAUSE              'p'
#define QUIT                 'Q'
#define lcQUIT               'q'
#define RESUME               'R'
#define lcRESUME             'r'
#define REQUESTER            'R'
#define SERVER               'S'

/*------------------------ Global variables -------------------------------*/
typedef struct Parameters {
      CHAR     chProgramMode[1];              /* Program Mode              */
                                              /*  E - Execute              */
                                              /*  Q - Quit                 */
                                              /*  P - Pause                */
                                              /*  R - Resume               */
      PCHAR    pchServername;                 /* Server Machine Name       */
      PCHAR    pchServicename;                /* Service to be Viewed      */
                                              /*  - Server or Requester    */
      ULONG    ulPrintCycleTime;              /* Interval between          */
                                              /*  outputs.                 */
      USHORT   usInitialize;                  /* Flag - set during         */
                                              /* program initialization    */
      USHORT   usReset;                       /* Flag - to clear stats     */
                                              /*  at initialization        */
      USHORT   usClear;                       /* Flag - to clear stats     */
                                              /*  at each output           */
      USHORT   usDelta;                       /* Flag - print out delta    */
                                              /*  between the previous     */
                                              /*  output and the current   */
                                              /*  one.                     */
      ULONG    ulChangeFlag;                  /* Flag - set if any of      */
                                              /*  special condition        */
                                              /*  values have changed      */
                                              /*  since the last output    */
      HKBD     hkbd;                          /* Handle for Execution-     */
                                              /*  time keyboard            */
}       stParameters;

/***************************************************************************/
/*  Function declarations                                                  */
/*-------------------------------------------------------------------------*/

VOID Error_Message( USHORT, PSZ);

VOID Check_Kybd_Set_Pgm_Mode( struct Parameters *stParms);

stParameters *Init_Parms(SHORT, PCHAR *);    /* $32C */

struct stat_workstation_0 *Call_Wkstn_Stats( /* $32C */
                                           struct Parameters *stParms);

struct stat_server_0      *Call_Server_Stats( /* $32C */
                                           struct Parameters *stParms);

VOID Wkstn_Stats_Delta( struct stat_workstation_0 *statwkstn0Buf /* $32C */
                      , struct stat_workstation_0 *statwkstn0Old /* $32C */
                      , struct Parameters           *stParms);   /* $32C */

VOID Server_Stats_Delta( struct stat_server_0    *statsvr0Buf    /* $32C */
                       , struct stat_server_0    *statsvr0Old    /* $32C */
                       , struct Parameters       *stParms);      /* $32C */

VOID Print_Wkstn_Stats(  struct Parameters          *stParms         /* $32C */
                      ,  struct stat_workstation_0  *statwkstn0Buf); /* $32C */


VOID Print_Server_Stats( struct Parameters    *stParms       /* $32C */
                       , struct stat_server_0 *statsvr0Buf); /* $32C */

/***************************************************************************/
/* Main C Function                                                         */
/*-------------------------------------------------------------------------*/

VOID main(argc, argv)

  SHORT argc;
  PCHAR argv[];
{

  struct stat_server_0       *statsvr0Buf    ; /* Server stats buffer   $32C   */
  struct stat_workstation_0  *statwkstn0Buf  ; /* Workstation stats buf $32C */
  struct stat_server_0       *statsvr0Old    ; /* Old Server stats buf  $32C */
  struct stat_workstation_0  *statwkstn0Old  ; /* Old workstation stats $32C */

  struct Parameters          *stParms        ; /* Program environment   $32C */

  USHORT usRc = 0                               ; /* API Return code       */
  DATETIME                      DateTime        ; /* Date and time struct  */

  DosGetDateTime(&DateTime);

  printf("\nLAN Server Statistics Display Program \n");
  printf("-------------------------------------\n\n");

  printf("Start time : %d:%2d:%2d.%d\n"
         ,DateTime.hours
         ,DateTime.minutes
         ,DateTime.seconds
         ,DateTime.hundredths);

  printf("\n   Q - to Quit   P - to Pause   R - to Resume\n\n");

  stParms = Init_Parms(argc, argv); /* Set up initial program parameters */

  switch (*stParms->pchServicename) { /* Set up for Requester or Server    */
  case REQUESTER:                     /*  statistics collection.           */

      stParms->pchServicename = "REQUESTER";
      statwkstn0Buf = Call_Wkstn_Stats( stParms); /* Collect Statistics    */

      Print_Wkstn_Stats( stParms
                       , statwkstn0Buf); /* Print out initial statistics   */

      statwkstn0Old = statwkstn0Buf;

      break;
  case SERVER:

      stParms->pchServicename = "SERVER";
      statsvr0Buf = Call_Server_Stats( stParms);

      Print_Server_Stats( stParms
                        , statsvr0Buf);

      statsvr0Old = statsvr0Buf;

      break;
  default :

      printf("Server and Requester are the only valid values.\n");
      DosExit(EXIT_PROCESS, usRc);

      break;
  }

  /* Initialization is complete - Clear the Initialization Flag            */

  stParms->usInitialize = NO;

  /* Main Program Loop - Continue to gather and print out statistics       */
  /*                     until the user quits (by pressing 'Q' or 'q').    */

  while ( stParms->chProgramMode[0] != QUIT ) {

      DosSleep(stParms->ulPrintCycleTime); /* Wait for a user-specified    */
                                           /* period of time.              */

      Check_Kybd_Set_Pgm_Mode( stParms);   /* Check for user input         */

      if ( *stParms->chProgramMode == PAUSE) {
             printf("PAUSE ...");

             while ( stParms->chProgramMode[0] != QUIT &&
                 stParms->chProgramMode[0] != RESUME ) {

             DosSleep(ONE_SECOND);              /* Check the keyboard      */
             Check_Kybd_Set_Pgm_Mode( stParms); /* once a second when      */
            }                                   /* in Pause mode.          */

            printf("RESUME.\n");
      } /* endif */

      /* Collect Statistics on the requester portion of the Server's       */
      /* LAN code.                                                         */

      if (*stParms->pchServicename == REQUESTER) {

         statwkstn0Buf = Call_Wkstn_Stats( stParms);

         Wkstn_Stats_Delta( statwkstn0Buf/*Calculate the difference between*/
                          , statwkstn0Old/*  the previous set of statistics*/
                          , stParms);    /*  and the current set           */

         if (stParms->usDelta == YES)  /* Print out the difference between */
            Print_Wkstn_Stats( stParms        /* the previous set of stats */
                             , statwkstn0Old);/* and the current set.      */
         else
            Print_Wkstn_Stats( stParms        /* Print out the new stats   */
                             , statwkstn0Buf);

         statwkstn0Old = statwkstn0Buf;

      }

      /* Collect Statistics on the server portion of the Server's          */
      /*  LAN code                                                         */

      else {

         statsvr0Buf = Call_Server_Stats( stParms);

         Server_Stats_Delta( statsvr0Buf
                           , statsvr0Old
                           , stParms);

         if (stParms->usDelta == YES)
            Print_Server_Stats( stParms
                              , statsvr0Old);
         else
            Print_Server_Stats( stParms
                              , statsvr0Buf);

         statsvr0Old = statsvr0Buf;

      }
  }
  DosExit(EXIT_PROCESS, usRc); /* end the program */
}

/***************************************************************************/
/* Init_Parms Function                                                     */
/*     Create space for the program parameter buffer and set the           */
/*   parameter to either default or user-defined values (as appropriate).  */
/*-------------------------------------------------------------------------*/

stParameters *Init_Parms(SHORT sArgc, PCHAR pchArgv[])  /* $32C  */

{
  USHORT             usArgNum               ;
  USHORT             usRc           = 0     ;
  USHORT             usBuflen       = 0     ;
  SEL                selBuf                 ;

  struct Parameters         *stParms    ;

  if (( sArgc < 4 || (*pchArgv[1] != '\\' && *(pchArgv[1]+1) != '\\')) ||
       ((*pchArgv[3] == 'T' || *pchArgv[3] == 't') && sArgc < 5 )) {
     printf("Help for Server Statistics Display Program \n");
     printf("------------------------------------------\n\n");
     printf("\n   Q - to Quit   P - to Pause   R - to Resume\n\n");
     printf("%s \\\\<servername> <servicename> <option>\n\n", pchArgv[0]);
     printf("servername - The name of the server to be monitored.\n");
     printf("servicename- This must be SERVER or REQUESTER.\n\n");
     printf("              Choose which part of the server's LAN code\n");
     printf("              you wish to monitor.\n");
     printf("R          - Reset (clear) statistics at program startup.\n");
     printf("C          - Clear statistics at each display interval.\n");
     printf("D          - Display the difference between each set of\n");
     printf("              statistics without clearing the statistics.\n");
     printf("T <nn>     - Set the display interval to be nn seconds.\n");

     DosExit(EXIT_PROCESS, usRc);
  } /* endif */

  usBuflen = (sizeof(struct Parameters));
  /*  DosAllocSeg(usBuflen, &selBuf, SEG_NONSHARED);    $32D */
  /* stParms = (struct Parameters FAR *) MAKEP(selBuf, 0);   $32D */
                                               /* space for stParms buffer */
  DosAllocMem((PVOID)&stParms, (ULONG)usBuflen, fALLOC);   /*  $32A */

  stParms->pchServername  = pchArgv[1];   /* Positional                    */
  stParms->pchServicename = pchArgv[2];   /* Arguments                     */

  usArgNum = 2 ;

  stParms->chProgramMode[0] = EXECUTE      ; /* Set program parameters     */
  stParms->usInitialize        = YES       ; /* to default values          */
  stParms->usReset             = NO        ;
  stParms->usClear             = NO        ;
  stParms->usDelta             = NO        ;
  stParms->ulPrintCycleTime    = ONE_SECOND;

  while (( pchArgv[++usArgNum] != NULL ) && (usArgNum <= 3)){
                                          /* Set program parameters to     */
                                          /* user-defined values           */

      if ( *pchArgv[usArgNum]== 'R' || *pchArgv[usArgNum] == 'r')
         stParms->usReset = YES ;

      if ( *pchArgv[usArgNum]== 'C' || *pchArgv[usArgNum] == 'c')
         stParms->usClear = YES ;

      if ( *pchArgv[usArgNum]== 'D' || *pchArgv[usArgNum] == 'd')
         stParms->usDelta = YES ;

      if ( *pchArgv[usArgNum] == 'T' || *pchArgv[usArgNum] == 't') {
         ++usArgNum;
         stParms->ulPrintCycleTime = atol(pchArgv[usArgNum]) * ONE_SECOND;
      }
  }

  return (stParms);
}

/***************************************************************************/
/* Check_Kybd_Set_Pgm_Mode Function                                        */
/*     Open a virtual keyboard and read any characters out of its input    */
/*   buffer. Set or change the program mode if the buffer is not empty.    */
/*                                                                         */
/*-------------------------------------------------------------------------*/

VOID Check_Kybd_Set_Pgm_Mode( struct Parameters *stParms)   /*  $32C  */
{

  KBDKEYINFO       stKeyboardInfo ;

  if (stParms->usInitialize == YES) {  /* Initialize a virtual Keyboard    */

     KbdOpen(&stParms->hkbd);          /* Create a virtual keyboard        */

     KbdGetFocus( IO_WAIT
                 ,stParms->hkbd);      /* Set focus to the current session */

     KbdFlushBuffer(stParms->hkbd);    /* Clear the Keyboard buffer        */
  }
  else
     KbdGetFocus( IO_WAIT
                 ,stParms->hkbd);


  KbdCharIn( &stKeyboardInfo          /* Read in a character from the      */
            ,IO_NOWAIT                /* keyboard. Do not wait for a       */
            ,stParms->hkbd);          /* character if the buffer is empty  */

  switch (stKeyboardInfo.chChar) {          /* Set the program mode        */
  case QUIT:
  case lcQUIT:
     stParms->chProgramMode[0] = QUIT;      /* Set to Quit execution       */
     break;
  case PAUSE:
  case lcPAUSE:
     stParms->chProgramMode[0] = PAUSE;     /* Set to Pause execution      */
     break;
  case RESUME:
  case lcRESUME:
     stParms->chProgramMode[0] = RESUME;    /* Set to Resume execution     */
     break;                                 /* after a pause               */
  default:
     stParms->chProgramMode[0] = EXECUTE;   /* Continue normal execution   */
     break;
  } /* endswitch */

  KbdFreeFocus(stParms->hkbd); /* Let other sessions use the keyboard      */

}

/***************************************************************************/
/* Call_Wkstn_Stats Function                                               */
/*     Retrieve Workstation statistics using the NetStatisticsGet2 API     */
/*-------------------------------------------------------------------------*/

struct stat_workstation_0 *Call_Wkstn_Stats(            /*  $32C  */
                          struct Parameters *stParms)
{

  struct stat_workstation_0   *statwkstn0Buf;           /*  $32C  */
  ULONG              ulOptions         = NOT_SET_TO_CLEAR;
  ULONG              ulReserved        = 0      ;
  SHORT              sLevel            = 0      ;
  USHORT             usBuflen          = 0      ;
  USHORT             usTotalavail      = 0      ;
  USHORT             usRc              = 0      ;
  SEL                selBuf                        ;

  /* If Clear is set, set the flag to clear the workstation statistics     */
  /*   to clear the statistics on the server                               */

  if ( stParms->usClear == YES)
     ulOptions = SET_TO_CLEAR;

  /* If it is the initialization call, and Reset is set, clear the stats   */

  if (stParms->usInitialize == YES && stParms->usReset == YES)
     ulOptions = SET_TO_CLEAR;

  /* Get the statistics */

  usRc = NetStatisticsGet2( stParms->pchServername,
                            stParms->pchServicename,
                            ulReserved,
                            sLevel,
                            ulOptions,
                (PCHAR ) statwkstn0Buf,               /*  $32C */
                            usBuflen,
                           &usTotalavail);

  switch (usRc) {

  case NERR_BufTooSmall : /* Allocate space for the statistics buffer if   */
                          /*   space has not yet been allocated            */

/*   usBuflen = (sizeof(struct stat_workstation_0)*usTotalavail);*/
     usBuflen = usTotalavail;
     /* DosAllocSeg(usBuflen, &selBuf, SEG_NONSHARED);   $32D */
     /* statwkstn0Buf = (struct stat_workstation_0 FAR *) MAKEP(selBuf, 0); $32D */
     DosAllocMem((PVOID)&statwkstn0Buf, (ULONG)usBuflen, fALLOC);  /*  $32A */

     /* Now that space has been allocated, get the stats again             */

     usRc = NetStatisticsGet2( stParms->pchServername,
                               stParms->pchServicename,
                                ulReserved,
                               sLevel,
                               ulOptions,
                  (PCHAR ) statwkstn0Buf,       /*  $32C */
                               usBuflen,
                              &usTotalavail);

     Error_Message( usRc, "NetStatisticsGet2");
     break;

  default:
     Error_Message( usRc, "NetStatisticsGet2");
     break;
  } /* endswitch */

  return (statwkstn0Buf);
}

/***************************************************************************/
/* Call_Server_Stats Function                                              */
/*     Retrieve Server statistics using the NetStatisticsGet2 API          */
/*-------------------------------------------------------------------------*/

struct stat_server_0 *Call_Server_Stats(                 /*  $32C */
                          struct Parameters *stParms)    /*  $32C */
{

  struct stat_server_0     *statsvr0Buf     ;            /*  $32C */
  ULONG              ulOptions         = NOT_SET_TO_CLEAR ;
  ULONG              ulReserved        = 0      ;
  SHORT              sLevel            = 0      ;
  USHORT             usBuflen          = 0      ;
  USHORT             usTotalavail      = 0      ;
  USHORT             usRc              = 0      ;
  SEL                selBuf                        ;

  if ( stParms->usClear == YES)
     ulOptions = SET_TO_CLEAR;

  if (stParms->usInitialize == YES && stParms->usReset == YES)
     ulOptions = SET_TO_CLEAR;

  usRc = NetStatisticsGet2( stParms->pchServername,
                            stParms->pchServicename,
                            ulReserved,
                            sLevel,
                            ulOptions,
                (PCHAR ) statsvr0Buf,                 /*  $32C */
                            usBuflen,
                           &usTotalavail);

  switch (usRc) {

  case NERR_BufTooSmall :

/*   usBuflen = (sizeof(struct stat_server_0)*usTotalavail);*/
     usBuflen = usTotalavail;
     /*  DosAllocSeg(usBuflen, &selBuf, SEG_NONSHARED);  $32D */
     /*  statsvr0Buf = (struct stat_server_0 FAR *) MAKEP(selBuf, 0);  $32D */
     DosAllocMem((PVOID)&statsvr0Buf, (ULONG)usBuflen, fALLOC);   /* $32A */

     usRc = NetStatisticsGet2( stParms->pchServername,
                               stParms->pchServicename,
                               ulReserved,
                               sLevel,
                               ulOptions,
                   (PCHAR ) statsvr0Buf,           /*  $32C */
                               usBuflen,
                              &usTotalavail);

     Error_Message( usRc, "NetStatisticsGet2");
     break;
  default:
     Error_Message( usRc, "NetStatisticsGet2");
     break;
  } /* endswitch */

  return (statsvr0Buf);
}

/***************************************************************************/
/* Wkstn_Stats_Delta Function                                              */
/*     Calculates and returns the difference between two sets of           */
/*      workstation statistics.                                            */
/*-------------------------------------------------------------------------*/

VOID Wkstn_Stats_Delta( struct stat_workstation_0    *statwkstn0Buf  /* 32C */
                      , struct stat_workstation_0    *statwkstn0Old  /* 32C */
                      , struct Parameters            *stParms)       /* 32C */

{

/* Statistics that are printed at every interval                           */
/*  - Calculate the change between two samples only if the                 */
/*    change is to be printed.                                             */

  if (stParms->usDelta == YES) {
     statwkstn0Old->stw0_start          = statwkstn0Buf->stw0_start
                                        - statwkstn0Old->stw0_start;

     statwkstn0Old->stw0_numNCB_r       = statwkstn0Buf->stw0_numNCB_r
                                        - statwkstn0Old->stw0_numNCB_r;

     statwkstn0Old->stw0_numNCB_s       = statwkstn0Buf->stw0_numNCB_s
                                        - statwkstn0Old->stw0_numNCB_s;

     statwkstn0Old->stw0_numNCB_a       = statwkstn0Buf->stw0_numNCB_a
                                        - statwkstn0Old->stw0_numNCB_a;

     statwkstn0Old->stw0_sesstart       = statwkstn0Buf->stw0_sesstart
                                        - statwkstn0Old->stw0_sesstart;

     statwkstn0Old->stw0_uses           = statwkstn0Buf->stw0_uses
                                        - statwkstn0Old->stw0_uses;

     statwkstn0Old->stw0_bytessent_r_lo = statwkstn0Buf->stw0_bytessent_r_lo
                                        - statwkstn0Old->stw0_bytessent_r_lo;

     statwkstn0Old->stw0_bytesrcvd_r_lo = statwkstn0Buf->stw0_bytesrcvd_r_lo
                                        - statwkstn0Old->stw0_bytesrcvd_r_lo;

     statwkstn0Old->stw0_bytessent_s_lo = statwkstn0Buf->stw0_bytessent_s_lo
                                        - statwkstn0Old->stw0_bytessent_s_lo;

     statwkstn0Old->stw0_bytesrcvd_s_lo = statwkstn0Buf->stw0_bytesrcvd_s_lo
                                        - statwkstn0Old->stw0_bytesrcvd_s_lo;

     statwkstn0Old->stw0_bytessent_a_lo = statwkstn0Buf->stw0_bytessent_a_lo
                                        - statwkstn0Old->stw0_bytessent_a_lo;

     statwkstn0Old->stw0_bytessent_a_lo = statwkstn0Buf->stw0_bytessent_a_hi
                                        - statwkstn0Old->stw0_bytessent_a_hi;

     statwkstn0Old->stw0_bytesrcvd_a_lo = statwkstn0Buf->stw0_bytesrcvd_a_lo
                                        - statwkstn0Old->stw0_bytesrcvd_a_lo;
  } /* endif */

/* Statistics that are printed only if they change in a given interval.    */
/*  - calculate the change every iteration.                                */

  statwkstn0Old->stw0_fiNCB_r        = statwkstn0Buf->stw0_fiNCB_r
                                     - statwkstn0Old->stw0_fiNCB_r;

  statwkstn0Old->stw0_fiNCB_s        = statwkstn0Buf->stw0_fiNCB_s
                                     - statwkstn0Old->stw0_fiNCB_s;

  statwkstn0Old->stw0_fiNCB_a        = statwkstn0Buf->stw0_fiNCB_a
                                     - statwkstn0Old->stw0_fiNCB_a;

  statwkstn0Old->stw0_fcNCB_r        = statwkstn0Buf->stw0_fcNCB_r
                                     - statwkstn0Old->stw0_fcNCB_r;

  statwkstn0Old->stw0_fcNCB_s        = statwkstn0Buf->stw0_fcNCB_s
                                     - statwkstn0Old->stw0_fcNCB_s;

  statwkstn0Old->stw0_fcNCB_a        = statwkstn0Buf->stw0_fcNCB_a
                                     - statwkstn0Old->stw0_fcNCB_a;

  statwkstn0Old->stw0_sessfailcon    = statwkstn0Buf->stw0_sessfailcon
                                     - statwkstn0Old->stw0_sessfailcon;

  statwkstn0Old->stw0_sessbroke      = statwkstn0Buf->stw0_sessbroke
                                     - statwkstn0Old->stw0_sessbroke;

  statwkstn0Old->stw0_usefail        = statwkstn0Buf->stw0_usefail
                                     - statwkstn0Old->stw0_usefail;

  statwkstn0Old->stw0_autorec        = statwkstn0Buf->stw0_autorec
                                     - statwkstn0Old->stw0_autorec;

  statwkstn0Old->stw0_bytessent_r_hi = statwkstn0Buf->stw0_bytessent_r_hi
                                     - statwkstn0Old->stw0_bytessent_r_hi;

  statwkstn0Old->stw0_bytesrcvd_r_hi = statwkstn0Buf->stw0_bytesrcvd_r_hi
                                     - statwkstn0Old->stw0_bytesrcvd_r_hi;

  statwkstn0Old->stw0_bytessent_s_hi = statwkstn0Buf->stw0_bytessent_s_hi
                                     - statwkstn0Old->stw0_bytessent_s_hi;

  statwkstn0Old->stw0_bytesrcvd_s_hi = statwkstn0Buf->stw0_bytesrcvd_s_hi
                                     - statwkstn0Old->stw0_bytesrcvd_s_hi;

  statwkstn0Old->stw0_bytessent_a_hi = statwkstn0Buf->stw0_bytessent_a_hi
                                     - statwkstn0Old->stw0_bytessent_a_hi;

  statwkstn0Old->stw0_bytesrcvd_a_hi = statwkstn0Buf->stw0_bytesrcvd_a_hi
                                     - statwkstn0Old->stw0_bytesrcvd_a_hi;

  statwkstn0Old->stw0_reqbufneed     = statwkstn0Buf->stw0_reqbufneed
                                     - statwkstn0Old->stw0_reqbufneed;

  statwkstn0Old->stw0_bigbufneed     = statwkstn0Buf->stw0_bigbufneed
                                     - statwkstn0Old->stw0_bigbufneed;

  if (stParms->usInitialize ==YES)
     stParms->ulChangeFlag = 1;    /* Print stats that are non-zero        */
                                   /*  at initialization                   */
  else {

     stParms->ulChangeFlag = 0 ;
     stParms->ulChangeFlag = statwkstn0Old->stw0_fiNCB_r   /* ulChangeFlag */
                           + statwkstn0Old->stw0_fiNCB_s   /* will be zero */
                           + statwkstn0Old->stw0_fiNCB_a   /* when all     */
                           + statwkstn0Old->stw0_fcNCB_r   /* fields are   */
                           + statwkstn0Old->stw0_fcNCB_s   /* unchanged    */
                           + statwkstn0Old->stw0_fcNCB_a
                           + statwkstn0Old->stw0_sessfailcon
                           + statwkstn0Old->stw0_sessbroke
                           + statwkstn0Old->stw0_usefail
                           + statwkstn0Old->stw0_autorec
                           + statwkstn0Old->stw0_bytessent_r_hi
                           + statwkstn0Old->stw0_bytesrcvd_r_hi
                           + statwkstn0Old->stw0_bytessent_s_hi
                           + statwkstn0Old->stw0_bytesrcvd_s_hi
                           + statwkstn0Buf->stw0_bytessent_a_hi
                           + statwkstn0Old->stw0_bytesrcvd_a_hi
                           + statwkstn0Old->stw0_reqbufneed
                           + statwkstn0Old->stw0_bigbufneed;
  }
}

/***************************************************************************/
/* Server_Stats_Delta Function                                             */
/*     Calculates and returns the difference between two sets of           */
/*      server statistics.                                                 */
/*-------------------------------------------------------------------------*/

VOID Server_Stats_Delta( struct stat_server_0    *statsvr0Buf   /*  $32C */
                       , struct stat_server_0    *statsvr0Old   /*  $32C */
                       , struct Parameters       *stParms)      /*  $32C */

{

/* Statistics that are printed at every interval                           */

  statsvr0Old->sts0_start          = statsvr0Buf->sts0_start
                                   - statsvr0Old->sts0_start;

  statsvr0Old->sts0_fopens         = statsvr0Buf->sts0_fopens
                                   - statsvr0Old->sts0_fopens;

  statsvr0Old->sts0_devopens       = statsvr0Buf->sts0_devopens
                                   - statsvr0Old->sts0_devopens;

  statsvr0Old->sts0_jobsqueued     = statsvr0Buf->sts0_jobsqueued
                                   - statsvr0Old->sts0_jobsqueued;

  statsvr0Old->sts0_sopens         = statsvr0Buf->sts0_sopens
                                   - statsvr0Old->sts0_sopens;

  statsvr0Old->sts0_bytessent_low  = statsvr0Buf->sts0_bytessent_low
                                   - statsvr0Old->sts0_bytessent_low;

  statsvr0Old->sts0_bytessent_high = statsvr0Buf->sts0_bytessent_high
                                   - statsvr0Old->sts0_bytessent_high;

  statsvr0Old->sts0_bytesrcvd_low  = statsvr0Buf->sts0_bytesrcvd_low
                                   - statsvr0Old->sts0_bytesrcvd_low;

  statsvr0Old->sts0_bytesrcvd_high = statsvr0Buf->sts0_bytesrcvd_high
                                   - statsvr0Old->sts0_bytesrcvd_high;

  statsvr0Old->sts0_avresponse     = statsvr0Buf->sts0_avresponse;


/* Statistics that are printed only if they change                         */
/*  in a given interval.                                                   */

  statsvr0Old->sts0_stimedout      = statsvr0Buf->sts0_stimedout
                                   - statsvr0Old->sts0_stimedout;

  statsvr0Old->sts0_serrorout      = statsvr0Buf->sts0_serrorout
                                   - statsvr0Old->sts0_serrorout;

  statsvr0Old->sts0_pwerrors       = statsvr0Buf->sts0_pwerrors
                                   - statsvr0Old->sts0_pwerrors;

  statsvr0Old->sts0_permerrors     = statsvr0Buf->sts0_permerrors
                                   - statsvr0Old->sts0_permerrors;

  statsvr0Old->sts0_syserrors      = statsvr0Buf->sts0_syserrors
                                   - statsvr0Old->sts0_syserrors;

  statsvr0Old->sts0_reqbufneed     = statsvr0Buf->sts0_reqbufneed
                                   - statsvr0Old->sts0_reqbufneed;

  statsvr0Old->sts0_bigbufneed     = statsvr0Buf->sts0_bigbufneed
                                   - statsvr0Old->sts0_bigbufneed;

  if (stParms->usInitialize ==YES)
     stParms->ulChangeFlag = 1;

  else {

     stParms->ulChangeFlag = 0 ;
     stParms->ulChangeFlag = statsvr0Old->sts0_stimedout
                           + statsvr0Old->sts0_serrorout
                           + statsvr0Old->sts0_pwerrors
                           + statsvr0Old->sts0_permerrors
                           + statsvr0Old->sts0_syserrors
                           + statsvr0Old->sts0_reqbufneed
                           + statsvr0Old->sts0_bigbufneed;
  } /* endif */
}

/***************************************************************************/
/* Print_Wkstn_Stats Function                                              */
/*     Prints out the statistics from a stat_workstation_0 structure       */
/*-------------------------------------------------------------------------*/

VOID Print_Wkstn_Stats( struct Parameters          *stParms         /* $32C */
                      , struct stat_workstation_0  *statwkstn0Buf)  /* $32C */

{
  DATETIME                  DateTime ;

  if ( stParms->usInitialize == YES) { /* Print out the workstation stats  */
                                       /*  header.                         */
     printf(" Machine name = %s\n",stParms->pchServername);
     printf(" Service Name = %s\n",stParms->pchServicename);
     printf("\n        NCBs Issued   Req. -----Bytes Sent-----");
     printf(" -----Bytes Rcvd-----\n");
     printf("Time   Req  Svr  App  S  U   Req    Svr    App   ");
     printf(" Req    Svr    App\n");
  }

  DosGetDateTime(&DateTime);

  printf("%02d:%02d %4ld %4ld %4ld"
         ,DateTime.minutes
         ,DateTime.seconds
         ,statwkstn0Buf->stw0_numNCB_r
         ,statwkstn0Buf->stw0_numNCB_s
         ,statwkstn0Buf->stw0_numNCB_a);

  /* Statistics that are printed out every iteration                       */

  printf(" %2ld %2ld"
         ,statwkstn0Buf->stw0_sesstart
         ,statwkstn0Buf->stw0_uses);

  printf(" %6ld %6ld %6ld"
         ,statwkstn0Buf->stw0_bytessent_r_lo
         ,statwkstn0Buf->stw0_bytessent_s_lo
         ,statwkstn0Buf->stw0_bytessent_a_lo);

  printf(" %6ld %6ld %6ld"
         ,statwkstn0Buf->stw0_bytesrcvd_r_lo
         ,statwkstn0Buf->stw0_bytesrcvd_s_lo
         ,statwkstn0Buf->stw0_bytesrcvd_a_lo);

  if( stParms->usInitialize == YES) { /* Note when initialization is taking*/
     printf(" *Init");                /*  place, and if the statistics are */
     if( stParms->usReset == YES)     /*  being cleared.                   */
        printf(" & Clear");
  }

  if( stParms->usClear == SET_TO_CLEAR)
     printf(" *Clear");

  printf("\n");

 if( stParms->ulChangeFlag != 0) {    /* Print out any changes in the      */
                                      /*  'special' statistics.            */

    if ( statwkstn0Buf->stw0_fiNCB_r        != 0 )
       printf("     ****** Redirector NCBs failed issue : %ld\n"
             ,statwkstn0Buf->stw0_fiNCB_r);

    if ( statwkstn0Buf->stw0_fiNCB_s        != 0 )
       printf("     ****** Server NCBs failed issue : %ld\n"
             ,statwkstn0Buf->stw0_fiNCB_s);

    if ( statwkstn0Buf->stw0_fiNCB_a        != 0 )
       printf("     ****** Application NCBs failed issue : %ld\n"
             ,statwkstn0Buf->stw0_fiNCB_a);

    if ( statwkstn0Buf->stw0_fcNCB_r        != 0 )
       printf("     ****** Redirector NCBs failed completion : %ld\n"
             ,statwkstn0Buf->stw0_fcNCB_r);

    if ( statwkstn0Buf->stw0_fcNCB_s        != 0 )
       printf("     ****** Server NCBs failed completion : %ld\n"
             ,statwkstn0Buf->stw0_fcNCB_s);

    if ( statwkstn0Buf->stw0_fcNCB_a        != 0 )
       printf("     ****** Application NCBs failed completion : %ld\n"
             ,statwkstn0Buf->stw0_fcNCB_a);

    if ( statwkstn0Buf->stw0_sessfailcon    != 0 )
       printf("     ****** Requester sessions failed to connect : %ld\n"
             ,statwkstn0Buf->stw0_sessfailcon);

    if ( statwkstn0Buf->stw0_sessbroke      != 0 )
       printf("     ****** Broken requester sessions            : %ld\n"
             ,statwkstn0Buf->stw0_sessbroke);

    if ( statwkstn0Buf->stw0_usefail        != 0 )
       printf("     ****** Requester use failures               : %ld\n"
             ,statwkstn0Buf->stw0_usefail);

    if ( statwkstn0Buf->stw0_autorec        != 0 )
       printf("     ****** Requester auto-connects              : %ld\n"
             ,statwkstn0Buf->stw0_autorec);

    if ( statwkstn0Buf->stw0_bytessent_r_hi != 0 )
       printf("     ****** Requester bytes sent /2^32           : %ld\n"
             ,statwkstn0Buf->stw0_bytessent_r_hi);

    if ( statwkstn0Buf->stw0_bytesrcvd_r_hi != 0 )
       printf("     ****** Requester bytes received / 2^32      : %ld\n"
             ,statwkstn0Buf->stw0_bytesrcvd_r_hi);

    if ( statwkstn0Buf->stw0_bytessent_s_hi != 0 )
       printf("     ****** Server bytes sent /2^32              : %ld\n"
             ,statwkstn0Buf->stw0_bytessent_s_hi);

    if ( statwkstn0Buf->stw0_bytesrcvd_s_hi != 0 )
       printf("     ****** Server bytes received / 2^32         : %ld\n"
             ,statwkstn0Buf->stw0_bytesrcvd_s_hi);

    if ( statwkstn0Buf->stw0_bytessent_a_hi != 0 )
       printf("     ****** Application bytes sent /2^32         : %ld\n"
             ,statwkstn0Buf->stw0_bytessent_a_hi);

    if ( statwkstn0Buf->stw0_bytesrcvd_a_hi != 0 )
       printf("     ****** Application bytes received /2^32     : %ld\n"
             ,statwkstn0Buf->stw0_bytesrcvd_a_hi);

    if ( statwkstn0Buf->stw0_reqbufneed     != 0 )
       printf("     ****** Requester buffers failed allocation  : %ld\n"
             ,statwkstn0Buf->stw0_reqbufneed);

    if ( statwkstn0Buf->stw0_bigbufneed     != 0 )
       printf("     ****** Big buffers failed allocation       : %ld\n"
             ,statwkstn0Buf->stw0_bigbufneed);

 } /* endif */

}

/***************************************************************************/
/* Print_Server_Stats Function                                             */
/*     Prints out the statistics from a stat_server_0 structure            */
/*-------------------------------------------------------------------------*/

VOID Print_Server_Stats( struct Parameters    *stParms        /* $32C */
                       , struct stat_server_0 *statsvr0Buf)   /* $32C */
{

  DATETIME             DateTime  ;

  if ( stParms->usInitialize == YES) {
      printf(" Machine name = %s\n",stParms->pchServername);
      printf(" Service Name = %s\n",stParms->pchServicename);
      printf("\n                         ");
      printf("-------------------Server------------------ Avg \n");
      printf("      File  Dev Prt  Ses ");
      printf("------Bytes Sent----- ---Bytes Received---- Resp\n");
      printf("Time  Opens Opn Jobs Opn ");
      printf("bytes*2^32    bytes   bytes*2^32    bytes   Time\n");
      printf("\n");
  }

  DosGetDateTime(&DateTime);

  printf("%02d:%02d"
         ,DateTime.minutes
         ,DateTime.seconds);
  printf(" %4ld  %3ld %3ld  %3ld %10ld %10ld %10ld %10ld %3ld\n"
         ,statsvr0Buf->sts0_fopens
         ,statsvr0Buf->sts0_devopens
         ,statsvr0Buf->sts0_jobsqueued
         ,statsvr0Buf->sts0_sopens
         ,statsvr0Buf->sts0_bytessent_high
         ,statsvr0Buf->sts0_bytessent_low
         ,statsvr0Buf->sts0_bytesrcvd_high
         ,statsvr0Buf->sts0_bytesrcvd_low
         ,statsvr0Buf->sts0_avresponse);

  if( stParms->usInitialize == YES) {
     printf("                                               ");
     printf("                         *Init\n");
     if( stParms->usReset == YES) {
        printf("                                            ");
        printf("                      *Clear\n");
     }
  }
  else
     if (stParms->usClear ==SET_TO_CLEAR) {
     printf("                                               ");
     printf("                         *Clear\n");
  };

 if( stParms->ulChangeFlag != 0) {

    if ( statsvr0Buf->sts0_stimedout  != 0 )
       printf("     ****** Server sessions auto-disconnected         : %ld\n"
             ,statsvr0Buf->sts0_stimedout);

    if ( statsvr0Buf->sts0_serrorout  != 0 )
       printf("     ****** Server sessions errored out               : %ld\n"
             ,statsvr0Buf->sts0_serrorout);

    if ( statsvr0Buf->sts0_pwerrors   != 0 )
       printf("     ****** Server password violations                : %ld\n"
             ,statsvr0Buf->sts0_pwerrors);

    if ( statsvr0Buf->sts0_permerrors != 0 )
       printf("     ****** Server access permission errors           : %ld\n"
             ,statsvr0Buf->sts0_permerrors);

    if ( statsvr0Buf->sts0_syserrors  != 0 )
       printf("     ****** Server system errors                      : %ld\n"
             ,statsvr0Buf->sts0_syserrors);

    if ( statsvr0Buf->sts0_reqbufneed != 0 )
       printf("     ****** Server failures to allocate req. buffers  : %ld\n"
             ,statsvr0Buf->sts0_reqbufneed);

    if ( statsvr0Buf->sts0_bigbufneed != 0 )
       printf("     ****** Server failures to allocate big buffers   : %ld\n"
             ,statsvr0Buf->sts0_bigbufneed);
  } /* endif */
}
