home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
SYSINFO.ZIP
/
SYSINFO.C
next >
Wrap
C/C++ Source or Header
|
1990-10-12
|
18KB
|
698 lines
/*----------------------------------
SysInfo.c - summary of system statistics
Largest free memory block, updated every .75 seconds
Displays Free CPU cycles, updated every .75 seconds
Time of day, updated every .75 seconds
swap file size, updated every 3 seconds
free disk space on 1 drv, updated every 3 seconds
Automatically positions itself at the top of the screen in a box 2.5
system characters high. Double clicking anywhere in the client window
will cause the the frame controls to be hidden, or restored if already
hidden. Keyboard accelerators will still work while the frame is hidden.
Program can also be minimized.
----------------------------------*/
#define INCL_WIN
#define INCL_GPI
#define INCL_DOS
#include <os2.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <process.h>
#define ID_TIMER 1
#define MAX_CHILDREN 10
#define CH_MEMTEXT 1
#define CH_MEMVAL 0
#define CH_SWAPTEXT 3
#define CH_SWAPVAL 2
#define CH_CLOCKTEXT 5
#define CH_CLOCKVAL 4
#define CH_CPUTEXT 7
#define CH_CPUVAL 6
#define CH_DISKTEXT 9
#define CH_DISKVAL 8
#define SWAPFILE "c:\\os2\\system\\swapper.dat"
MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ;
MRESULT EXPENTRY ChildProc (HWND, USHORT, MPARAM, MPARAM) ;
VOID SizeTheWindow( HWND );
void SwitchList( HWND hwndFrame, HPOINTER hptrIcon );
void far cdecl CountCyc( PVOID nl );
void GetFontInfo(HWND hwnd, PUSHORT cyChar, PUSHORT cxChar, PUSHORT cyDesc);
int ComputeFree(short DriveNum, float *fAvail );
SHORT CreateChildren( HWND hwndParent );
VOID ToggleFrameControls( HWND hwndFrame );
VOID UpdateLong( PHWND ahwndChild );
VOID UpdateShort( PHWND ahwndChild );
// window handles for hiding frame controls and creating children
HWND hwndFrame, hwndSys, hwndMin, hwndTitle;
HWND hwndChild[ MAX_CHILDREN ];
SHORT fHidden = 0;
// font info for sizing windows
SHORT cyChar, cxChar, cyDesc;
// raw data from CPU cycles count
ULONG uCalibVal = 0, uCurVal = 0, ulLast = 1;
// params for free disk space
USHORT usDriveNum = 3, fIsRed;
float fFreeSpace = 0.0;
// size of the swap file
ULONG ulSwapSize = 0;
// largest free block
ULONG ulFrSize = 0;
/*
Function: main
Description:
Entry point for system info program. Creates the client window and
starts the thread for the CPU monitor. Takes two command line params.
First param is the drive letter. If not present it defaults to C. This
is the drive on which the free space will be monitored.
If a second param is present and equal to /cal, the cpu counter will
be recalibrated. This should be done with no other programs running
to get a better idea of a true idle system.
Values Returned:
None.
Notes:
*/
int main ( int argc, char **argv )
{
static PSZ pszClientClass = "System Info" ;
static ULONG flFrameFlags = FCF_TITLEBAR | FCF_SYSMENU | FCF_ICON |
FCF_MINBUTTON | FCF_BORDER;
CHAR achBuf[12];
HPOINTER hwndIcon; /* handle to our programs icon */
HAB hab;
HMQ hmq;
HWND hwndClient;
QMSG qmsg;
usDriveNum = 3;
PrfQueryProfileString( HINI_USERPROFILE, "System Info",
"Calibration Value", "0", achBuf, 12L );
uCalibVal = atol( achBuf );
if ( argc >= 2 )
usDriveNum = toupper( *argv[1] ) - 'A' + 1; // pick up a drive letter.
if ( argc == 3 && !stricmp( argv[2], "/cal" ) )
uCalibVal = 0; // mark for recal
_beginthread( CountCyc, NULL, 8000, NULL );
hab = WinInitialize( 0 );
hmq = WinCreateMsgQueue( hab, 0 );
WinRegisterClass(hab, pszClientClass, ClientWndProc, CS_MOVENOTIFY, 0 );
WinRegisterClass(hab, "InfoChild", ChildProc, 0, 6 );
hwndFrame = WinCreateStdWindow( HWND_DESKTOP, WS_VISIBLE,
&flFrameFlags, pszClientClass, pszClientClass,
0L, 0, 1, &hwndClient );
/* Add our title to the task list maintained by Task Manager */
hwndIcon = WinLoadPointer( HWND_DESKTOP, 0, 1 );
SwitchList( hwndFrame, hwndIcon );
SizeTheWindow( hwndFrame );
CreateChildren( hwndClient );
ToggleFrameControls( hwndFrame );
WinStartTimer (hab, hwndClient, ID_TIMER, 750 );
while (WinGetMsg (hab, &qmsg, NULL, 0, 0 ) )
WinDispatchMsg (hab, &qmsg) ;
WinStopTimer (hab, hwndClient, ID_TIMER) ;
// store the calibration value on exit
sprintf( achBuf, "%lu", uCalibVal );
PrfWriteProfileString( HINI_USERPROFILE, "System Info",
"Calibration Value", achBuf );
WinDestroyWindow( hwndFrame );
WinDestroyMsgQueue( hmq );
WinDestroyPointer( hwndIcon );
WinTerminate( hab );
DosExit( EXIT_PROCESS, 0 );
}
/*
Function: SizeTheWindow
Description:
Set the initial size of the window at 2.5 character heights and for the
entire width of the display. Positions it at the top of the screen.
Values Returned:
None
Notes:
I stole this code from a petzold sample.
*/
VOID SizeTheWindow (HWND hwndFrame)
{
USHORT usCxScreen, usCyScreen, usCyBorder;
RECTL rcl;
usCxScreen = (USHORT)WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
usCyScreen = (USHORT)WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
usCyBorder = (USHORT)WinQuerySysValue( HWND_DESKTOP, SV_CYBORDER );
rcl.yBottom = 0 ;
rcl.yTop = 2 * cyChar;
rcl.xLeft = 0 ;
rcl.xRight = usCyScreen - 2 * usCyBorder;
/* now figure out the size of the frame rectangle */
WinCalcFrameRect( hwndFrame, &rcl, FALSE );
/* ... and shift to the top line of the screen */
rcl.yBottom = usCyScreen - (rcl.yTop - rcl.yBottom);
rcl.yTop = usCyScreen;
rcl.xRight = usCxScreen;
rcl.xLeft = 0;
WinSetWindowPos (hwndFrame, NULL, (SHORT) rcl.xLeft, (SHORT) rcl.yBottom,
(SHORT) (rcl.xRight - rcl.xLeft),
(SHORT) (rcl.yTop - rcl.yBottom), SWP_SIZE | SWP_MOVE) ;
}
/*
Function: ClientWndProc
Description:
Window procedure for the main window. Really does very little except
call other functions to do something useful.
Values Returned:
MRESULTS
Notes:
*/
MRESULT EXPENTRY ClientWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
{
static SHORT sTicks = 0;
switch (msg)
{
case WM_CREATE:
GetFontInfo( hwnd, &cyChar, &cxChar, &cyDesc );
return 0;
case WM_BUTTON1DOWN:
if ( fHidden )
return WinSendMsg( hwndFrame, WM_TRACKFRAME,
(MPARAM)( SHORT1FROMMP(mp2) | TF_MOVE ), NULL );
return 0;
case WM_BUTTON1DBLCLK:
ToggleFrameControls( hwndFrame );
return 0;
case WM_TIMER:
if ( (sTicks % 4) == 0 ) // every three seconds do the disk parms
UpdateLong( hwndChild );
UpdateShort( hwndChild );
sTicks++;
return 0;
case WM_ERASEBACKGROUND:
return MRFROMSHORT(TRUE);
}
return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
}
/*
Function: SwitchList
Description:
Add our program name to the switch list maintained by the system.
Values Returned:
None
Notes:
*/
void SwitchList( HWND hwndFrame, HPOINTER hptrIcon )
{
SWCNTRL swctl; /* switch list entry structure */
WinQueryWindowProcess( hwndFrame, &swctl.idProcess, NULL );
swctl.idSession = 0;
swctl.fReserved = 0;
swctl.hprog = NULL;
swctl.hwnd = hwndFrame;
swctl.hwndIcon = hptrIcon;
swctl.uchVisibility = SWL_VISIBLE;
swctl.fbJump = SWL_JUMPABLE;
strcpy( swctl.szSwtitle, "System Information" );
WinAddSwitchEntry( &swctl );
return;
}
/*
Function: CountCyc
Description:
Separate thread that runs at idle class, priority one. Since the system
provides an idle class, priority zero thread, setting it to one gives
a better value for idle time.
Simply counts iterations of a loop every 750 milliseconds. That value
is then compared to the number of iterations we were able to do when
the system was idle.
Values Returned:
None
Notes:
*/
void far cdecl CountCyc( PVOID nl )
{
SEL selGlobalSeg, /* selector num for global info seg */
selLocalSeg; /* selector num for local info seg */
GINFOSEG FAR *pgis; /* pointer to the global info seg */
ULONG lMils;
ULONG uBldVal;
DosGetInfoSeg(&selGlobalSeg, &selLocalSeg); /* get local & global info segs */
pgis = MAKEPGINFOSEG( selGlobalSeg ); /* get a pointer to the global */
if ( uCalibVal == 0L )
{
DosEnterCritSec();
DosSetPrty( PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0 );
lMils = pgis->msecs + 3750;
while( pgis->msecs < lMils )
uCalibVal++;
DosExitCritSec();
uCalibVal /= 5;
}
// set priority to idle, 1 so that we avoid conflict with system idle thread.
DosSetPrty( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MINIMUM, 0 );
DosSetPrty( PRTYS_THREAD, PRTYC_IDLETIME, 1, 0 );
while( 1 )
{
lMils = pgis->msecs + 750;
uBldVal = 0L;
while( pgis->msecs < lMils )
uBldVal++;
uCurVal = uBldVal;
}
}
/*
Function: ComputeFree
Description:
Compute free space on the specified drive. Set the free space as
a float point value representing free MB.
Values Returned:
0 - drive has more the 10% free
1 - drive is within 10% of being full
Notes:
*/
int ComputeFree( short DriveNum, float *fAvail )
{
FSALLOCATE fsaBuf;
float fTotFree;
DosQFSInfo( DriveNum, 1, (PCHAR)&fsaBuf, sizeof( fsaBuf ) );
fTotFree = (float)fsaBuf.cbSector * (float)fsaBuf.cSectorUnit *
(float)fsaBuf.cUnitAvail;
fTotFree /= (float)0x100000;
*fAvail = fTotFree;
if ( fsaBuf.cUnitAvail * 10 < fsaBuf.cUnit )
return( 1 ); /* less than 10% space free */
else
return( 0 );
}
/*
Function: GetFontInfo
Description:
Call WinQueryFontMetrics to determine information about the system font
Values Returned:
None.
Notes:
*/
void GetFontInfo( HWND hwnd, USHORT *cy, USHORT *cx, USHORT *cd )
{
HPS hps; /* need a ps before calling font metrics */
FONTMETRICS fm; /* info about the current font */
hps = WinGetPS( hwnd ); /* need a PS for query Font */
GpiQueryFontMetrics( hps, (LONG)sizeof(fm), &fm );
WinReleasePS( hps ); /* done with the ps now */
*cy = (SHORT)fm.lMaxBaselineExt; /* max height of one character */
*cx = (SHORT)fm.lAveCharWidth; /* average width of a character */
*cd = (SHORT)fm.lMaxDescender; /* max descender of a char */
return;
}
/*
Function: CreateChildren
Description:
Create the ten child windows in a double row. All windows are static
text. The leftmost windows are aligned on the left, the rightmost on the
right, all others are centered.
Values Returned:
0 - no error
1 - error
Notes:
*/
SHORT CreateChildren( HWND hwndParent )
{
short i, x, y, cx, cy;
SWP swp;
WinQueryWindowPos( hwndParent, &swp );
for( i = 0; i < 10; i+= 2 )
{
x = (swp.cx / 5) * (i/2);
y = 0;
cx = swp.cx / 5;
cy = swp.cy / 2;
hwndChild[i] = WinCreateWindow( hwndParent, "InfoChild", NULL,
WS_VISIBLE, x, y, cx, cy, NULL, HWND_TOP, i, NULL, NULL );
WinSetWindowPtr( hwndChild[i], 2, malloc( 100 ) );
y = swp.cy / 2;
hwndChild[i + 1] = WinCreateWindow( hwndParent, "InfoChild", NULL,
WS_VISIBLE, x, y, cx, cy, NULL, HWND_TOP, i + 1, NULL, NULL );
WinSetWindowPtr( hwndChild[i + 1], 2, malloc( 100 ) );
if ( hwndChild[ i ] == NULL || hwndChild[ i + 1 ] == NULL )
return 1;
}
strcpy( WinQueryWindowPtr( hwndChild[ CH_CPUTEXT ], 2 ), "CPU Usage" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_MEMTEXT ], 2 ), "Free Memory" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_SWAPTEXT ], 2 ), "Swap File Size" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_DISKTEXT ], 2 ), "Free Disk Space" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_CLOCKTEXT ], 2 ), "Time of day" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_CPUVAL ], 2 ), "" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_MEMVAL ], 2 ), "" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_SWAPVAL ], 2 ), "" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_DISKVAL ], 2 ), "" );
strcpy( WinQueryWindowPtr( hwndChild[ CH_CLOCKVAL ], 2 ), "" );
UpdateShort( hwndChild );
UpdateLong( hwndChild );
return 0;
}
/*
Function: ToggleFrameControls
Description:
if frame controls are hidden, restore them, if visible hide them.
Values Returned:
None
Notes:
I stole this code from an MS sample
*/
VOID ToggleFrameControls( HWND hwndFrame )
{
if ( !fHidden ) // hide the controls
{
hwndTitle = WinWindowFromID( hwndFrame, FID_TITLEBAR );
hwndSys = WinWindowFromID( hwndFrame, FID_SYSMENU );
hwndMin = WinWindowFromID( hwndFrame, FID_MINMAX );
WinSetParent( hwndTitle, HWND_OBJECT, FALSE );
WinSetParent( hwndSys, HWND_OBJECT, FALSE );
WinSetParent( hwndMin, HWND_OBJECT, FALSE );
WinSendMsg( hwndFrame, WM_UPDATEFRAME, (MPARAM)(FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON),
NULL ) ;
fHidden = TRUE;
SizeTheWindow( hwndFrame );
}
else
{
WinSetParent( hwndTitle, hwndFrame, FALSE );
WinSetParent( hwndSys, hwndFrame, FALSE );
WinSetParent( hwndMin, hwndFrame, FALSE );
WinSendMsg( hwndFrame, WM_UPDATEFRAME, (MPARAM)(FCF_TITLEBAR | FCF_SYSMENU | FCF_MINBUTTON),
NULL );
fHidden = FALSE;
SizeTheWindow( hwndFrame );
}
return;
}
/*
Function: UpdateLong
Description:
Update the parameters that are done every three seconds -- swap file,
disk space.
Values Returned:
None
Notes:
*/
VOID UpdateLong( PHWND ahwndChild )
{
float fTmp;
CHAR achSpace[20];
FILESTATUS fs;
fTmp = fFreeSpace;
fIsRed = ComputeFree( usDriveNum, &fFreeSpace );
if ( fFreeSpace != fTmp ) // drive space has changed
{
if ( fIsRed )
WinSetWindowUShort( ahwndChild[ CH_DISKVAL ], 0, 1 );
else
WinSetWindowUShort( ahwndChild[ CH_DISKVAL ], 0, 0 );
sprintf( achSpace, "%c: %3.1f MB", usDriveNum + 'A' - 1, fFreeSpace );
strcpy( WinQueryWindowPtr( ahwndChild[ CH_DISKVAL ], 2 ), achSpace );
WinInvalidateRect( ahwndChild[ CH_DISKVAL ], NULL, 0 );
}
DosQPathInfo( SWAPFILE, FIL_STANDARD, (PBYTE)&fs, sizeof(fs), 0L );
if ( ulSwapSize != fs.cbFile )
{
ulSwapSize = fs.cbFile;
sprintf( achSpace, "%4.0f KB", (float)ulSwapSize / 1024.0 );
strcpy( WinQueryWindowPtr( ahwndChild[ CH_SWAPVAL ], 2 ), achSpace );
WinInvalidateRect( ahwndChild[ CH_SWAPVAL ], NULL, 0 );
}
return;
}
/*
Function: UpdateShort
Description:
Updates the parameters that are done on a .75 second basis - free memory,
time of day, CPU usage
Values Returned:
None
Notes:
*/
VOID UpdateShort( PHWND ahwndChild )
{
ULONG ulCur;
CHAR achFmt[25];
struct tm *tml;
time_t timer;
while ( uCalibVal == 0L )
DosSleep( 100L );
ulCur = (uCurVal * 100L) / uCalibVal;
if ( ulLast != ulCur )
{
sprintf( achFmt, "%ld%%", 100L - ulCur );
strcpy( WinQueryWindowPtr( ahwndChild[ CH_CPUVAL ], 2 ), achFmt );
WinInvalidateRect( ahwndChild[ CH_CPUVAL ], NULL, 0 );
ulLast = ulCur;
}
time( &timer );
tml = localtime( &timer );
ctime( &timer );
if ( tml->tm_hour == 0 )
sprintf( achFmt, "12:%02d:%02d AM", tml->tm_min, tml->tm_sec );
else if ( tml->tm_hour < 12 )
sprintf( achFmt, "%02d:%02d:%02d AM", tml->tm_hour, tml->tm_min, tml->tm_sec );
else if ( tml->tm_hour == 12 )
sprintf( achFmt, "12:%02d:%02d PM", tml->tm_min, tml->tm_sec );
else
sprintf( achFmt, "%02d:%02d:%02d PM", tml->tm_hour - 12, tml->tm_min, tml->tm_sec );
strcpy( WinQueryWindowPtr( ahwndChild[ CH_CLOCKVAL ], 2 ), achFmt );
WinInvalidateRect( ahwndChild[ CH_CLOCKVAL ], NULL, 0 );
DosMemAvail( &ulCur );
if ( ulCur != ulFrSize )
{
sprintf( achFmt, "%4ld KB", (ulCur + 512) / 1024 );
strcpy( WinQueryWindowPtr( ahwndChild[ CH_MEMVAL ], 2 ), achFmt );
WinInvalidateRect( ahwndChild[ CH_MEMVAL ], NULL, 0 );
ulFrSize = ulCur;
}
return;
}
/*
Function: ChildProc
Description:
Child window that is extremely stupid -- knows how to display centered
text in its window
Values Returned:
MRESULTS
Notes:
*/
MRESULT EXPENTRY ChildProc( HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2 )
{
HPS hps;
RECTL rcl;
LONG lCol;
PCHAR pch;
switch( msg )
{
case WM_CREATE:
WinSetWindowUShort( hwnd, 0, 0 );
return 0;
case WM_BUTTON1DBLCLK:
case WM_BUTTON1DOWN:
WinSendMsg( WinQueryWindow( hwnd, QW_PARENT, 0 ), msg, mp1, mp2 );
return 0;
case WM_DESTROY:
free( WinQueryWindowPtr( hwnd, 2 ) );
return 0;
case WM_PAINT:
pch = WinQueryWindowPtr( hwnd, 2 );
WinQueryWindowRect( hwnd, &rcl );
hps = WinBeginPaint( hwnd, NULL, NULL );
if ( WinQueryWindowUShort( hwnd, 0 ) == 0 )
lCol = CLR_NEUTRAL;
else
lCol = CLR_RED;
WinDrawText( hps, -1, pch, &rcl, lCol, CLR_BACKGROUND,
DT_VCENTER | DT_CENTER | DT_ERASERECT );
WinEndPaint( hps );
return 0;
}
return WinDefWindowProc( hwnd, msg, mp1, mp2 );
}