Category : Files from Magazines
Archive   : VOL11N15.ZIP
Filename : SYSMON.C
// Copyright (C) 1992 Ray Duncan
// PC Magazine * Ziff Davis Publishing
#define dim(x) (sizeof(x) / sizeof(x[0])) // returns no. of elements
#define MAXLINES 4096 // max lines to display
#include "stdlib.h"
#include "windows.h"
#include "toolhelp.h"
#include "dos.h"
#include "sysmon.h"
HANDLE hInst; // module instance handle
HWND hFrame; // handle for frame window
HFONT hFont; // handle for nonprop. font
int CharX, CharY; // character dimensions
int LinesPerPage; // lines per page
int CurLine = 0; // first line, current page
int TotLines = 0; // total lines to display
int TopLine = 0; // first line of last page
int DisplayType = IDM_MODULE; // type of info to display
char *LinePtr[MAXLINES]; // holds pointers to lines
char szFrameClass[] = "SysMon"; // classname for frame window
char szAppName[] = "System Monitor"; // long application name
char szMenuName[] = "SysMonMenu"; // name of menu resource
char szIcon[] = "SysMonIcon"; // name of icon resource
char szIni[] = "sysmon.ini"; // name of private INI file
WNDPROC lpTimerProc; // timer callback thunk
//
// Table of window messages supported by FrameWndProc()
// and the functions which correspond to each message.
//
struct decodeMsg frameMsgs[] = {
WM_PAINT, DoPaint,
WM_SIZE, DoSize,
WM_COMMAND, DoCommand,
WM_SETFOCUS, DoSetFocus,
WM_CLOSE, DoClose,
WM_DESTROY, DoDestroy,
WM_VSCROLL, DoVScroll, } ;
//
// Table of menubar item IDs and their corresponding functions.
//
struct decodeMsg menuitems[] = {
IDM_EXIT, DoMenuExit,
IDM_ABOUT, DoMenuAbout,
IDM_MODULE, DoDisplayType,
IDM_CLASS, DoDisplayType,
IDM_TASK, DoDisplayType,
IDM_GLOBHEAP, DoDisplayType,
IDM_SYSHEAP, DoDisplayType,
IDM_MEMMAN, DoDisplayType,
IDM_DISK, DoDisplayType,
IDM_REFRESH, DoRefresh, } ;
//
// Table of memory block types and descriptive strings
//
struct decodeUINT memType[] = {
GT_UNKNOWN, "Unknown",
GT_DGROUP, "DGROUP",
GT_DATA, "Program Data",
GT_CODE, "Program Code",
GT_TASK, "Task Database",
GT_RESOURCE, "Resource",
GT_MODULE, "Module Database",
GT_FREE, "Available",
GT_INTERNAL, "Internal",
GT_SENTINEL, "Sentinel",
GT_BURGERMASTER, "Arena Map", } ;
//
// WinMain -- entry point for this application from Windows.
//
int APIENTRY WinMain(HANDLE hInstance,
HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg; // scratch message storage
hInst = hInstance; // save this instance handle
if(!hPrevInstance) // if first instance,
if(!InitApp(hInstance)) // register window class
{
MessageBox(hFrame, "Can't initialize SysMon!", szAppName,
MB_ICONSTOP | MB_OK);
return(FALSE);
}
if(!InitInstance(hInstance, nCmdShow)) // create this instance's window
{
MessageBox(hFrame, "Can't initialize SysMon!", szAppName,
MB_ICONSTOP | MB_OK);
return(FALSE);
}
while(GetMessage(&msg, NULL, 0, 0)) // while message != WM_QUIT
{
TranslateMessage(&msg); // translate virtual key codes
DispatchMessage(&msg); // dispatch message to window
}
TermInstance(hInstance); // clean up for this instance
return(msg.wParam); // return code = WM_QUIT value
}
//
// InitApp --- global initialization code for this application.
//
BOOL InitApp(HANDLE hInstance)
{
WNDCLASS wc; // window class info
// set parameters for frame window class
wc.style = CS_HREDRAW|CS_VREDRAW; // class style
wc.lpfnWndProc = FrameWndProc; // class callback function
wc.cbClsExtra = 0; // extra per-class data
wc.cbWndExtra = 0; // extra per-window data
wc.hInstance = hInstance; // handle of class owner
wc.hIcon = LoadIcon(hInst, szIcon); // application icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // default cursor
wc.hbrBackground = GetStockObject(WHITE_BRUSH); // background color
wc.lpszMenuName = szMenuName; // name of menu resource
wc.lpszClassName = szFrameClass; // name of window class
return(RegisterClass(&wc)); // register frame window class
}
//
// InitInstance --- instance initialization code for this application.
//
BOOL InitInstance(HANDLE hInstance, int nCmdShow)
{
HDC hdc; // handle for device context
TEXTMETRIC tm; // info about font
RECT rect; // window position & size
int i; // scratch variable
for(i = 0; i < MAXLINES; i++) // initialize all line
LinePtr[i] = NULL; // pointers
hFrame = CreateWindow( // create frame window
szFrameClass, // window class name
szAppName, // text for title bar
WS_OVERLAPPEDWINDOW | WS_VSCROLL, // window style
CW_USEDEFAULT, CW_USEDEFAULT, // default position
CW_USEDEFAULT, CW_USEDEFAULT, // default size
NULL, // no parent window
NULL, // use class default menu
hInstance, // window owner
NULL); // unused pointer
if(!hFrame) return(FALSE); // error, can't create window
hdc = GetDC(hFrame); // get device context
hFont = GetStockObject(SYSTEM_FIXED_FONT); // handle for nonprop. font
SelectObject(hdc, hFont); // realize the font and get
GetTextMetrics(hdc, &tm); // the character dimensions
CharX = tm.tmAveCharWidth;
CharY = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hFrame, hdc); // release device context
GetWindowRect(hFrame, &rect); // current window pos & size
// read profile for frame window from previous invocation, if any
rect.left = GetPrivateProfileInt("Frame", "xul", rect.left, szIni);
rect.top = GetPrivateProfileInt("Frame", "yul", rect.top, szIni);
rect.right = GetPrivateProfileInt("Frame", "xlr", rect.right, szIni);
rect.bottom = GetPrivateProfileInt("Frame", "ylr", rect.bottom, szIni);
MoveWindow(hFrame, rect.left, rect.top, // force window size & position
rect.right-rect.left, rect.bottom-rect.top, TRUE);
// get display type from previous invocation, default to module list
DisplayType = GetPrivateProfileInt("Frame", "type", IDM_MODULE, szIni);
ShowWindow(hFrame, nCmdShow); // make frame window visible
UpdateWindow(hFrame); // force WM_PAINT message
// allocate thunk for timer callback routine
lpTimerProc = MakeProcInstance((WNDPROC) TimerProc, hInst);
// set up our 10 sec. (10,000 msec) timer callback
if (!SetTimer(hFrame, 1, 10000, lpTimerProc))
return(FALSE);
return(TRUE); // return success flag
}
//
// TermInstance -- instance termination code for this application.
// Does nothing in this case, included for symmetry with InitInstance.
//
BOOL TermInstance(HANDLE hinstance)
{
return(TRUE); // return success flag
}
//
// FrameWndProc --- callback function for application frame window.
// Searches frameMsgs[] for message match, runs corresponding function.
//
LONG FAR APIENTRY FrameWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
int i; // scratch variable
for(i = 0; i < dim(frameMsgs); i++) // decode window message and
{ // run corresponding function
if(wMsg == frameMsgs[i].Code)
return((*frameMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
}
return(DefWindowProc(hWnd, wMsg, wParam, lParam));
}
//
// DoCommand -- process WM_COMMAND message for frame window by
// decoding the menubar item with the menuitems[] array, then
// running the corresponding function to process the command.
//
LONG DoCommand(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
int i; // scratch variable
for(i = 0; i < dim(menuitems); i++) // decode menu command and
{ // run corresponding function
if(wParam == menuitems[i].Code)
return((*menuitems[i].Fxn)(hWnd, wMsg, wParam, lParam));
}
return(DefWindowProc(hWnd, wMsg, wParam, lParam));
}
//
// DoDestroy -- process WM_DESTROY message for frame window.
//
LONG DoDestroy(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
PostQuitMessage(0); // force WM_QUIT message to
return(0); // terminate the event loop
}
//
// DoClose -- process WM_CLOSE message for frame window.
//
LONG DoClose(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
UpdateProfile(); // save window size & position
DestroyWindow(hWnd); // then close down app
return(FALSE);
}
//
// DoVScroll -- process WM_VSCROLL message for frame window.
//
LONG DoVScroll(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
RECT rect;
switch(LOWORD(wParam)) // LOWORD vital for Win32
{
case SB_TOP: // go to top of output if
if(CurLine) // we aren't there already
{
SetCurLine(0);
Repaint();
}
break;
case SB_BOTTOM: // go to bottom of output if
if(CurLine < TopLine) // we aren't there already
{
SetCurLine(TopLine);
Repaint();
}
break;
case SB_LINEUP: // scroll up by one line if
if(CurLine) // we aren't already at top
{
SetCurLine(CurLine - 1);
ScrollWindow(hWnd, 0, CharY, NULL, NULL);
UpdateWindow(hWnd);
}
break;
case SB_LINEDOWN: // scroll down by one line if
if(CurLine < TopLine) // we aren't already at bottom
{
SetCurLine(CurLine + 1);
ScrollWindow(hWnd, 0, -CharY, NULL, NULL);
GetClientRect(hWnd, &rect);
rect.top = max(0, (LinesPerPage-1) * CharY);
InvalidateRect(hWnd, &rect, TRUE);
UpdateWindow(hWnd);
}
break;
case SB_PAGEUP: // scroll up by one page
SetCurLine(CurLine - LinesPerPage);
Repaint();
break;
case SB_PAGEDOWN: // scroll down by one page
SetCurLine(CurLine + LinesPerPage);
Repaint();
break;
case SB_THUMBPOSITION: // scroll display according
SetCurLine(THUMBPOS); // to new thumb position
Repaint();
break;
}
return(FALSE);
}
//
// DoPaint -- process WM_PAINT message for frame window.
//
LONG DoPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int i;
hdc = BeginPaint(hWnd, &ps); // get device context
SelectObject(hdc, hFont); // select non-prop. font
for(i = 0; i < LinesPerPage; i++) // paint lines of text
PaintLine(hdc, i); // in the window
EndPaint(hWnd, &ps); // release device context
return(FALSE);
}
//
// DoSize -- process WM_SIZE message for frame window. Recalculate
// lines per page, if window has grown and at end of file may need to
// change first line in window and refresh it.
//
LONG DoSize(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
LinesPerPage = HIWORD(lParam) / CharY; // window height / char height
ConfigWindow(); // calc display parameters
if(CurLine > TopLine) // make sure window refilled
SetCurLine(TopLine); // if window got bigger
return(FALSE);
}
//
// DoSetFocus -- process WM_SETFOCUS message for frame window.
// Refresh display in case something has changed since last timer event.
// This also gets called when app is launched after window is created.
//
LONG DoSetFocus(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
SendMessage(hFrame, WM_COMMAND, IDM_REFRESH, 0);
return(FALSE);
}
//
// DoMenuExit -- process File-Exit command from menu bar.
//
LONG DoMenuExit(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
SendMessage (hWnd, WM_CLOSE, 0, 0L); // send window close message
return(FALSE); // to shut down the app
}
//
// DoDisplayType -- process items on Display popup to select
// the type of information to display, then force window update
//
LONG DoDisplayType(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
HMENU hMenu; // scratch menu handle
hMenu = GetMenu(hWnd); // update popup checkmark
CheckMenuItem(hMenu, DisplayType, MF_UNCHECKED);
DisplayType = wParam;
CheckMenuItem(hMenu, DisplayType, MF_CHECKED);
SendMessage(hWnd, WM_COMMAND, IDM_REFRESH, 0); // update window
return(FALSE);
}
//
// DoRefresh -- rebuild the information for display according to
// the currently selected display type, then refresh the window.
//
LONG DoRefresh(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
EmptyLines(); // discard previous output
switch(DisplayType) // call the appropriate
{ // list walking routine
case IDM_MODULE: // according to display type
WalkModuleList();
SetWindowCaption("Modules");
break;
case IDM_CLASS:
WalkClassList();
SetWindowCaption("Window Classes");
break;
case IDM_TASK:
WalkTaskList();
SetWindowCaption("Active Tasks");
break;
case IDM_GLOBHEAP:
WalkGlobalHeap();
SetWindowCaption("Global Heap");
break;
case IDM_SYSHEAP:
ShowSystemHeap();
SetWindowCaption("System Heap");
break;
case IDM_MEMMAN:
ShowMemManInfo();
SetWindowCaption("Memory Available");
break;
case IDM_DISK:
ShowDiskSpace();
SetWindowCaption("Disk Space Available");
break;
}
ConfigWindow(); // configure scroll bar etc.
Repaint(); // refresh the window
return(FALSE);
}
//
// DoMenuAbout -- process File-About command from menu bar.
//
LONG DoMenuAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
WNDPROC lpAboutProc; // scratch far pointer
// allocate a thunk for the dialog callback, then display dialog
lpAboutProc = MakeProcInstance((WNDPROC)AboutDlgProc, hInst);
DialogBox(hInst, "AboutBox", hWnd, lpAboutProc);
FreeProcInstance(lpAboutProc);
return(FALSE);
}
//
// AboutDlgProc -- callback routine for About... dialog. Basically
// ignores all messages except for the OK button, which dismisses dialog.
//
BOOL FAR APIENTRY AboutDlgProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
{
if((msg == WM_COMMAND) && (wParam == IDOK))
EndDialog(hwnd, 0); // if OK button, destroy dialog
else return(FALSE); // otherwise ignore message
}
//
// WalkModuleList -- uses ToolHelp functions to walk through
// module list and build formatted output in LinePtr[] array.
//
VOID WalkModuleList(VOID)
{
MODULEENTRY me; // receives module info
char temp[256]; // scratch formatting buffer
memset(&me, 0, sizeof(MODULEENTRY)); // initialize structure for
me.dwSize = sizeof(MODULEENTRY); // return of module data
AddLine("Handle Usage Module Pathname"); // format title
ModuleFirst(&me); // initialize to 1st module
do { // format module information
wsprintf(temp, "%04Xh %4d %-8.8s %s", me.hModule, me.wcUsage,
(LPSTR) me.szModule, (LPSTR) me.szExePath);
AddLine(temp); // add to array for output
} while(ModuleNext(&me)); // get next module name
}
//
// WalkClassList -- uses ToolHelp functions to walk through
// window class list and build formatted output in LinePtr[] array.
//
VOID WalkClassList(VOID)
{
CLASSENTRY ce; // receives window class info
MODULEENTRY me; // receives module info
char temp[256]; // scratch formatting buffer
memset(&ce, 0, sizeof(CLASSENTRY)); // initialize structure for
ce.dwSize = sizeof(CLASSENTRY); // return of window class data
memset(&me, 0, sizeof(MODULEENTRY)); // initialize structure for
me.dwSize = sizeof(MODULEENTRY); // return of module data
AddLine("Class Name Owner Module"); // format title
ClassFirst(&ce); // initialize to 1st class
do { // format classname & owner
ModuleFindHandle(&me, ce.hInst); // get module name
wsprintf(temp, "%-16.16s %04Xh %s", (LPSTR) ce.szClassName,
ce.hInst, (LPSTR) me.szModule);
AddLine(temp); // add to array for output
} while(ClassNext(&ce)); // get next class name
}
//
// WalkTaskList -- uses ToolHelp functions to walk through
// task list and build formatted output in LinePtr[] array.
//
VOID WalkTaskList(VOID)
{
TASKENTRY te; // receives task info
MODULEENTRY me; // receives module info
char temp[256]; // scratch formatting buffer
memset(&te, 0, sizeof(TASKENTRY)); // initialize structure for
te.dwSize = sizeof(TASKENTRY); // return of task info
memset(&me, 0, sizeof(MODULEENTRY)); // initialize structure for
me.dwSize = sizeof(MODULEENTRY); // return of module data
AddLine("Task Parent Instance Module Module Module");
AddLine("Handle Task Handle Handle Name Pathname");
TaskFirst(&te); // initialize to 1st task
do { // format task information
ModuleFindHandle(&me, te.hModule); // get modulename & pathname
wsprintf(temp, "%04Xh %04Xh %04Xh %04Xh %-8.8s %s",
te.hTask, te.hTaskParent, te.hInst, te.hModule,
(LPSTR) me.szModule, (LPSTR) me.szExePath);
AddLine(temp); // add to array for output
} while(TaskNext(&te)); // get next task
}
//
// WalkGlobalHeap -- uses ToolHelp functions to walk through
// global heap and build formatted output in LinePtr[] array.
//
VOID WalkGlobalHeap(VOID)
{
GLOBALENTRY ge; // receives heap block info
TASKENTRY te; // receives task info
MODULEENTRY me; // receives module info
int i; // scratch variable
char *p; // scratch string pointer
char temp[256]; // scratch formatting buffer
memset(&ge, 0, sizeof(GLOBALENTRY)); // initialize structure for
ge.dwSize = sizeof(GLOBALENTRY); // return of heap block info
memset(&me, 0, sizeof(MODULEENTRY)); // initialize structure for
me.dwSize = sizeof(MODULEENTRY); // return of module data
memset(&te, 0, sizeof(TASKENTRY)); // initialize structure for
te.dwSize = sizeof(TASKENTRY); // return of task info
AddLine("Handle Linear Addr Size Type Owner");
GlobalFirst(&ge, GLOBAL_ALL); // initialize to 1st block
do {
if(TaskFindHandle(&te, ge.hOwner)) // get block owner's name
ModuleFindHandle(&me, te.hModule);
else if(!ModuleFindHandle(&me, ge.hOwner))
me.szModule[0] = '\0';
p = "Unknown"; // decode memory block type
for(i = 0; i < dim(memType); i++)
if(ge.wType == memType[i].Code)
p = memType[i].Name;
// format heap block info
wsprintf(temp, "%04Xh %08lXh %08lXh %-16.16s %04Xh %s",
ge.hBlock, ge.dwAddress, ge.dwBlockSize, (LPSTR) p, ge.hOwner,
(LPSTR) me.szModule);
AddLine(temp); // add to array for output
} while(GlobalNext(&ge, GLOBAL_ALL)); // get next class name
}
//
// ShowMemManInfo -- uses ToolHelp function to display various
// memory manager information.
//
VOID ShowMemManInfo(VOID)
{
MEMMANINFO mmi; // receives memory info
char temp[256]; // scratch formatting buffer
memset(&mmi, 0, sizeof(MEMMANINFO)); // initialize structure for
mmi.dwSize = sizeof(MEMMANINFO); // return of memory info
MemManInfo(&mmi); // now retrieve info
wsprintf(temp, "Page size: %d bytes",
mmi.wPageSize);
AddLine(temp);
wsprintf(temp, "Total pages: %ld",
mmi.dwTotalPages);
AddLine(temp);
wsprintf(temp, "Swap file pages: %ld",
mmi.dwSwapFilePages);
AddLine(temp);
wsprintf(temp, "Maximum pages available: %ld",
mmi.dwMaxPagesAvailable);
AddLine(temp);
wsprintf(temp, "Maximum pages lockable: %ld",
mmi.dwMaxPagesLockable);
AddLine(temp);
wsprintf(temp, "Total unlocked pages: %ld",
mmi.dwTotalUnlockedPages);
AddLine(temp);
wsprintf(temp, "Pages not in use: %ld",
mmi.dwFreePages);
AddLine(temp);
wsprintf(temp, "Total linear address space: %ld bytes",
mmi.dwTotalLinearSpace*mmi.wPageSize);
AddLine(temp);
wsprintf(temp, "Free linear address space: %ld bytes",
mmi.dwFreeLinearSpace * mmi.wPageSize);
AddLine(temp);
wsprintf(temp, "Largest free block: %ld bytes",
mmi.dwLargestFreeBlock);
AddLine(temp);
}
//
// ShowSystemHeap -- uses ToolHelp function to display various
// system heap information.
//
VOID ShowSystemHeap(VOID)
{
SYSHEAPINFO si; // receives system heap info
char temp[256]; // scratch formatting buffer
memset(&si, 0, sizeof(SYSHEAPINFO)); // initialize structure for
si.dwSize = sizeof(SYSHEAPINFO); // return of system heap info
SystemHeapInfo(&si); // now retrieve info
wsprintf(temp, "User Heap Space Free: %d%%", si.wUserFreePercent);
AddLine(temp);
wsprintf(temp, "GDI Heap Space Free: %d%%", si.wGDIFreePercent);
AddLine(temp);
AddLine(" ");
wsprintf(temp, "User Heap Handle: %04Xh", si.hUserSegment);
AddLine(temp);
wsprintf(temp, "GDI Heap Handle: %04Xh", si.hGDISegment);
AddLine(temp);
}
//
// ShowDiskSpace -- uses DOS Int 21H function to get & display free
// disk space for each valid drive.
//
VOID ShowDiskSpace(VOID)
{
union REGS regs; // int 21h register contents
int status; // receives int86 status
int drive = 3; // start with C drive
char temp[256]; // scratch formatting buffer
AddLine("Drive Total Bytes Free Bytes"); // format titles
while(TRUE)
{
regs.h.ah = 0x36; // function number
regs.h.dl = drive; // drive code (1=A, etc.)
status = intdos(®s, ®s); // perform int 21h
if(status == -1) break; // quit if this drive invalid
wsprintf(temp, " %c %10ld %10ld", // format drive info
drive + 'A' - 1,
(LONG) regs.x.ax * (LONG) regs.x.cx * (LONG) regs.x.dx,
(LONG) regs.x.ax * (LONG) regs.x.cx * (LONG) regs.x.bx);
AddLine(temp);
drive++; // go to next drive
}
}
//
// SetCurLine - called to set CurLine to valid value, clamped to
// the range (0...TopLine), and redraw thumb on scroll bar.
//
VOID SetCurLine(int NewLine)
{
CurLine = min(max(NewLine, 0), TopLine);
SetScrollPos(hFrame, SB_VERT, CurLine, TRUE);
}
//
// ConfigWindow -- Configures various display parameters and scrollbar
// according to total lines of output, current window size, and the
// number of lines that will fit into the window.
//
VOID ConfigWindow(VOID)
{
// calc line number of first line of last page
TopLine = max(TotLines - LinesPerPage,0);
// update scroll bar range and thumb position
SetScrollRange(hFrame, SB_VERT, 0, TopLine, FALSE);
SetScrollPos(hFrame, SB_VERT, CurLine, TRUE);
}
//
// AddLine -- called with a pointer to an ASCIIZ string, allocates
// memory from the heap to hold the string, puts the pointer
// to the heap block into the next position in the LinePtr[] array,
// and updates the total line count.
//
VOID AddLine(char * p)
{
char * q; // scratch pointer
if(TotLines == MAXLINES) // bail out if line pointer
return; // array is already full
q = malloc(strlen(p)+1); // allocate memory for line
if(q == 0) // bail out out if no
return; // heap space available
strcpy(q, p); // copy string to heap
LinePtr[TotLines] = q; // put heap pointer into array
TotLines++; // count lines of output
}
//
// EmptyLines - releases all heap blocks in LinePtr[] array,
// then zeros out the line pointers and the total line count
//
VOID EmptyLines(VOID)
{
int i; // scratch variable
for(i = 0; i < MAXLINES; i++)
{
if(LinePtr[i]) // if this position in
{ // the LinePtr array is
free(LinePtr[i]); // nonzero, release the
LinePtr[i] = NULL; // heap block, then zero
} // out the LinePtr slot
}
CurLine = 0; // initialize various
TotLines = 0; // other global variables
TopLine = 0;
}
//
// PaintLine -- paint a single line of text in the window.
// The passed line number is relative to the window, NOT to the
// total array of formatted output available to be painted.
//
VOID PaintLine(HDC hdc, INT RelLine)
{
int Line = RelLine + CurLine;
if(LinePtr[Line])
TextOut(hdc, CharX, RelLine*CharY, LinePtr[Line], strlen(LinePtr[Line]));
}
//
// Repaint - force repaint of all formatted output in main window
//
VOID Repaint(VOID)
{
InvalidateRect(hFrame, NULL, TRUE); // force repaint entire window
}
//
// SetWindowCaption -- concatenate the application name with the
// display type, then update the frame window's title bar.
//
VOID SetWindowCaption(char * szDisplayType)
{
char szTemp[256]; // scratch buffer
strcpy(szTemp, szAppName); // get application name
strcat(szTemp, " - "); // add separator
strcat(szTemp, szDisplayType); // add information type
SetWindowText(hFrame, szTemp); // put result into title bar
}
//
// UpdateProfile() -- saves the current window size and position
// and display type in the application's private INI file.
//
VOID UpdateProfile(VOID)
{
RECT rect;
char temp[20];
if(IsIconic(hFrame) || IsZoomed(hFrame)) return;
GetWindowRect(hFrame, &rect);
wsprintf(temp,"%d", rect.left);
WritePrivateProfileString("Frame", "xul", temp, szIni);
wsprintf(temp,"%d", rect.top);
WritePrivateProfileString("Frame", "yul", temp, szIni);
wsprintf(temp,"%d", rect.right);
WritePrivateProfileString("Frame", "xlr", temp, szIni);
wsprintf(temp,"%d", rect.bottom);
WritePrivateProfileString("Frame", "ylr", temp, szIni);
wsprintf(temp,"%d", DisplayType);
WritePrivateProfileString("Frame", "type", temp, szIni);
}
//
// TimerProc() -- Callback for 10 second timer. Refresh display
// if window is not minimized and does not have the focus.
//
WORD FAR APIENTRY TimerProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
{
if((!IsIconic(hFrame)) && (hFrame != GetFocus()))
SendMessage(hFrame, WM_COMMAND, IDM_REFRESH, 0);
return(FALSE);
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/