home *** CD-ROM | disk | FTP | other *** search
- // MemWatch 1.1 is a small programmer utility that allows you to watch the memory usage of any
- // Windows application. If works by peeking into an applications memory at timed intervals. This
- // is initially set to .10 or 1/10 of a second. You can change this interval from the system pull
- // down menu. MemWatch is written in Microsoft Visual C++ 1.0 using the Microsoft Foundation Class
- // Library 2.0. By Todd Osborne - CompuServe ID 71431,2243
-
- #include <afxwin.h>
- #include <afxext.h>
- #include <dos.h>
- #include "resourc2.h"
-
- // The One and Only CWinApp
- class CMemwatchApp : public CWinApp
- {
- public:
- virtual BOOL InitInstance();
- };
-
- // CMainDlgWindow is a dialog box that is the main window
- class CMainDlgWindow : public CDialog
- {
- private:
- void dds_walk();
- float m_nTiming;
- public:
- //{{AFX_DATA(CMainDlgWindow)
- enum { IDD = IDD_MAIN };
- //}}AFX_DATA
- CMainDlgWindow();
- protected:
- //{{AFX_MSG(CMainDlgWindow)
- afx_msg void OnClose();
- afx_msg void OnOK();
- afx_msg void OnTimer(UINT nIDEvent);
- afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
- virtual BOOL OnInitDialog();
- virtual void OnCancel();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
- };
-
- // CTimingDlg is a dialog box that allow you to change the timing interval
- class CTimingDlg : public CDialog
- {
- public:
- CTimingDlg(CWnd* pParent, float* Timing);
- float* m_pTiming;
- // Dialog Data
- //{{AFX_DATA(CTimingDlg)
- enum { IDD = IDD_TIMING };
- float m_TB_TIMING;
- //}}AFX_DATA
- // Implementation
- protected:
- virtual void DoDataExchange(CDataExchange* pDX);
- // Generated message map functions
- //{{AFX_MSG(CTimingDlg)
- virtual BOOL OnInitDialog();
- afx_msg void OnClickOK();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
- };
-
- // About Box
- class CAboutDlg : public CDialog
- {
- public:
- CAboutDlg(CWnd* pParent = NULL);
- // Dialog Data
- //{{AFX_DATA(CAboutDlg)
- enum { IDD = IDD_ABOUT };
- // NOTE: the ClassWizard will add data members here
- //}}AFX_DATA
- protected:
- // Generated message map functions
- //{{AFX_MSG(CAboutDlg)
- virtual BOOL OnInitDialog();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
- };
-
- typedef struct tagDEFAULTDATASEGMENT
- {
- HANDLE hinstActive; // instance handle of active app
- HWND hwndActive; // window handle of active app
- WORD wSize, // size (bytes) of Data Segment.
- wStaticData, // size (bytes) of static data.
- wStackMax, // size (bytes) of stack size defined in .DEF
- wStackUsed, // size (bytes) of stack actually used.
- wHeapMoveable, // size (bytes) of heap allocation (moveable).
- wHeapFixed, // size (bytes) of heap allocation (fixed).
- wHeapFree, // size (bytes) of free space in heap.
- wOther, // size (bytes) of remaining allocated space in DS.
- wUnused; // size (bytes) of heap unused.
- } DEFAULTDATASEGMENT;
-
- static DEFAULTDATASEGMENT DDS ;
-
- // The one and only CWinApp object
- CMemwatchApp ThisApp;
-
- // Initialize this instance
- BOOL CMemwatchApp::InitInstance()
- {
- // Return pointer to main windows. In this case it is a dialog box
- m_pMainWnd = new CMainDlgWindow();
-
- // Use SetClassWord to attach an icon to a dialog box
- SetClassWord(m_pMainWnd->m_hWnd,GCW_HICON, (WORD)LoadIcon(AFX_IDI_STD_FRAME));
-
- return TRUE;
- }
-
- CMainDlgWindow::CMainDlgWindow()
- {
- // Call Create to create the main window dialog
- Create(IDD_MAIN);
-
- // Set initial timing to 1/10 of a second
- m_nTiming = .10;
- }
-
- void CMainDlgWindow::OnOK()
- {
- // Do nothing. Override default processing that closes window
- }
-
- void CMainDlgWindow::OnCancel()
- {
- // Do nothing. Override default processing that closes window
- }
-
- void CMainDlgWindow::OnClose()
- {
- // Clean up and end app
- KillTimer(1); // Remove the timer set in WM_INITDIALOG
- DestroyWindow(); // Destroy the dialog box window
- delete this; // Delete 'this' dialog box object
- PostQuitMessage(0); // End the application
- }
-
- BEGIN_MESSAGE_MAP(CMainDlgWindow, CDialog)
- //{{AFX_MSG_MAP(CMainDlgWindow)
- ON_WM_CLOSE()
- ON_WM_TIMER()
- ON_WM_SYSCOMMAND()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- BOOL CMainDlgWindow::OnInitDialog()
- {
- CDialog::OnInitDialog();
-
- CenterWindow();
-
- HMENU hMenu = ::GetSystemMenu (m_hWnd, FALSE);
-
- // Add Always On Top to System Menu
- ::AppendMenu (hMenu, MF_SEPARATOR, 0, "");
- ::AppendMenu (hMenu, MF_ENABLED, IDM_ALWAYSONTOP, "Always on &Top");
-
- // Add Exit Windows to System Menu
- ::AppendMenu (hMenu, MF_ENABLED, IDM_EXITWINDOWS, "E&xit Windows");
-
- // Add Restart Windows to System Menu
- ::AppendMenu (hMenu, MF_ENABLED, IDM_RESTARTWINDOWS, "&Restart Windows");
-
- // Add Timing to System Menu
- ::AppendMenu (hMenu, MF_ENABLED, IDM_TIMING, "Set T&iming...");
-
- // Add About to System Menu
- ::AppendMenu (hMenu, MF_ENABLED, IDM_ABOUT, "&About Memory Watcher...");
-
- // Set Timer to 1/10 second. NULL is used instead of callback function. CWnd object handles the WM_TIMER calls.
- if ( !SetTimer(1, m_nTiming * 1000, NULL) ) MessageBox ("Too many Timers or Clocks have been set.", "Memory Watcher", MB_ICONSTOP | MB_OK);
-
- return TRUE; // return TRUE unless you set the focus to a control
- }
-
-
- void CMainDlgWindow::OnTimer(UINT nIDEvent)
- {
- // Get Memory Information and Display if changed
- dds_walk();
-
- CDialog::OnTimer(nIDEvent);
- }
-
- void CMainDlgWindow::OnSysCommand(UINT nID, LPARAM lParam)
- {
- // Handle menu commands from the system menu
- switch (nID)
- {
- case IDM_ABOUT:
- {
- CAboutDlg dlg;
- dlg.DoModal();
- break;
- }
-
- case IDM_ALWAYSONTOP:
- {
- HMENU hMenu= ::GetSystemMenu (m_hWnd, FALSE);
- // Toggle State of Menu Item
- int CurVal = GetMenuState(hMenu, IDM_ALWAYSONTOP, MF_BYCOMMAND);
- if ( MF_CHECKED & CurVal )
- {
- ::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
- ::CheckMenuItem(hMenu, IDM_ALWAYSONTOP, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else
- {
- ::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
- ::CheckMenuItem(hMenu, IDM_ALWAYSONTOP, MF_BYCOMMAND | MF_CHECKED);
- }
- break;
- }
-
- case IDM_EXITWINDOWS:
- ExitWindows(0,0);
- break;
-
- case IDM_RESTARTWINDOWS:
- ExitWindows(EW_RESTARTWINDOWS,0);
- break;
-
- case IDM_TIMING:
- {
- CTimingDlg dlg(this, &m_nTiming);
- dlg.DoModal();
- KillTimer(1);
- SetTimer(1, m_nTiming * 1000, NULL);
- break;
- }
- }
-
- CDialog::OnSysCommand(nID, lParam);
- }
-
- void CMainDlgWindow::dds_walk ()
- {
- /* Original Code by: Chiverton Graphics, Inc. 1991
- Modified by Todd Osborne January 1994 to MFC 2.0 C++
- application with new features. CompuServe ID: 71431,2243
- */
-
- static DEFAULTDATASEGMENT OldDDS;
-
- WORD wRecordSize, // size in bytes of heap record.
- wStatus; // type of heap record.
-
- LPSTR lpInstance, // far pointer to Default Data Segment.
- lpHeapRecord, // far pointer to heap record.
- lpNextHeapRecord; // far pointer to next heap record.
-
- #define PREV_POINTER (*(WORD FAR*) lpHeapRecord) // Backward "pointer"
- #define NEXT_POINTER (*(WORD FAR*)(lpHeapRecord+2)) // Forward "pointer"
-
- #define PSTACKBOTTOM (*(WORD FAR*)(lpInstance+14))
- #define PSTACKMIN (*(WORD FAR*)(lpInstance+12))
- #define PSTACKTOP (*(WORD FAR*)(lpInstance+10))
- #define PLOCALHEAP (*(WORD FAR*)(lpInstance+ 6))
-
- // First, initialize the data segment values.
- DDS.wSize = 0;
- DDS.wStaticData = 0;
- DDS.wStackMax = 0;
- DDS.wStackUsed = 0;
- DDS.wHeapMoveable = 0;
- DDS.wHeapFixed = 0;
- DDS.wHeapFree = 0;
- DDS.wOther = 0;
- DDS.wUnused = 0;
-
- // Now, get the window that has the focus.
- DDS.hwndActive = ::GetActiveWindow ();
-
- // Is it a valid window?
- if ( !IsWindow (DDS.hwndActive) ) return;
-
- // If this is a different window than before, get a new instance handle.
- if (DDS.hwndActive != OldDDS.hwndActive)
- {
- DDS.hinstActive = (HANDLE) GetWindowWord (DDS.hwndActive, GWW_HINSTANCE);
- if (!DDS.hinstActive) return;
- }
-
- // Lock down the Data Segment
- if ( !(lpInstance = (LPSTR)GlobalLock (DDS.hinstActive))) return;
-
- /*
- * The Data Segment is a global memory object - created by WINDOWS
- * with a GlobalAlloc. It's comprised of 4 components: header,
- * Static, stack, and local heap. All 4 components are offset
- * into the segment, with the header at DS:0000.
- *
- *
- * The header occupies the first 16 bytes of a Default Data Segment.
- * Within the Header area are 3 pointers to the stack:
- *
- * pStackBottom - (highest physical address) beginning of stack.
- * pStackMin - High-Water mark of actual stack use.
- * pStackTop - (lowest physical address) end of stack.
- *
- * Remember, the stack grows "down" (higher to lower address), so
- * to compute the stack sizes, we use these equations:
- *
- * wStackMax = pStackBottom - pStackTop ;
- * wStackUsed = pStackBottom - pStackMin ;
- *
- *
- */
- DDS.wStackMax = PSTACKBOTTOM - PSTACKTOP ;
- DDS.wStackUsed = PSTACKBOTTOM - PSTACKMIN ;
- DDS.wStaticData = PSTACKTOP ;
-
- // First test for a heap. (It's possible there isn't one.)
- if (PLOCALHEAP == 0)
- {
- GlobalUnlock (DDS.hinstActive);
- return;
- }
-
- /*
- * The heap begins where the
- * stack ends. The offset that represents the
- * beginning of the heap is stored in the header area, 6 bytes from
- * DS:0000. Actually, the heap begins 4 bytes before this offset.
- *
- * Now we'll get a far pointer (lpHeapRecord) to the 1st record in the heap.
- *
- */
- lpHeapRecord = lpInstance + PLOCALHEAP - 4;
-
-
- /*
- * Traverse the local heap. The heap is implemented as a doubly-linked
- * list. The 1st WORD is a backward "pointer" (ie, offset) to the
- * previous record. The 2nd WORD is the forward pointer to the next record.
- * When the forward pointer points to itself we are done.
- *
- */
- DDS.wSize = (WORD)GlobalSize (DDS.hinstActive);
-
- while (FP_OFF(lpHeapRecord) < DDS.wSize)
- {
- lpNextHeapRecord = (lpInstance + NEXT_POINTER);
- if (lpNextHeapRecord == lpHeapRecord) break;
- wRecordSize = lpNextHeapRecord - lpHeapRecord; //includes ptr overhead
- wStatus = (PREV_POINTER & 0x0003);
-
- switch (wStatus)
- {
- case 0: DDS.wHeapFree += wRecordSize; break;
- case 1: DDS.wHeapFixed += wRecordSize; break;
- case 3: DDS.wHeapMoveable += wRecordSize; break;
- }
-
- lpHeapRecord = lpNextHeapRecord;
- }
-
- /*
- * At this point, heap traversal is done.
- * However, the heap can grow until the size of DS is 64K (0xFFFF).
- * Determine how many additional bytes the heap can grow.
- */
- DDS.wUnused = 0xFFFF - DDS.wSize;
-
- // Anything else we didn't account for?
- DDS.wOther = DDS.wSize - DDS.wStaticData
- - DDS.wStackMax
- - DDS.wHeapFixed
- - DDS.wHeapFree
- - DDS.wHeapMoveable ;
-
- GlobalUnlock (DDS.hinstActive);
-
- // If anything has changed since last walk, update client window.
- if (DDS.hwndActive != OldDDS.hwndActive ||
- DDS.wHeapFree != OldDDS.wHeapFree ||
- DDS.wHeapFixed != OldDDS.wHeapFixed ||
- DDS.wHeapMoveable != OldDDS.wHeapMoveable ||
- DDS.wOther != OldDDS.wOther ||
- DDS.wSize != OldDDS.wSize ||
- DDS.wStackUsed != OldDDS.wStackUsed)
- {
- // Update Dialog Box Values
- char sz[80];
-
- // Get Active Window Title
- char Title[80];
- ::GetWindowText(DDS.hwndActive, Title, 80);
- sprintf(sz, "Watching: %s", Title);
- SetDlgItemText(LBL_WATCHING, sz);
-
- // Fill in Memory Information
- sprintf(sz, "%u", DDS.wSize);
- SetDlgItemText(LBL_DATA0, sz);
-
- sprintf(sz, "%u", DDS.wStaticData);
- SetDlgItemText(LBL_DATA1, sz);
-
- sprintf(sz, "%u", DDS.wStackMax);
- SetDlgItemText(LBL_DATA2, sz);
-
- sprintf(sz, "%u", DDS.wStackUsed);
- SetDlgItemText(LBL_DATA3, sz);
-
- sprintf(sz, "%u", DDS.wHeapMoveable);
- SetDlgItemText(LBL_DATA4, sz);
-
- sprintf(sz, "%u", DDS.wHeapFixed);
- SetDlgItemText(LBL_DATA5, sz);
-
- sprintf(sz, "%u", DDS.wHeapFree);
- SetDlgItemText(LBL_DATA6, sz);
-
- sprintf(sz, "%u", DDS.wOther);
- SetDlgItemText(LBL_DATA7, sz);
-
- sprintf(sz, "%u", DDS.wUnused);
- SetDlgItemText(LBL_DATA8, sz);
-
- sprintf(sz, "%.3f", m_nTiming);
- SetDlgItemText(LBL_DATA9, sz);
-
- OldDDS = DDS;
- }
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CAboutDlg dialog
- CAboutDlg::CAboutDlg(CWnd* pParent /*=NULL*/)
- : CDialog(CAboutDlg::IDD, pParent)
- {
- }
-
- BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
- //{{AFX_MSG_MAP(CAboutDlg)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- BOOL CAboutDlg::OnInitDialog()
- {
- CDialog::OnInitDialog();
- CenterWindow();
-
- // Get and Display System Resources in LBL_SYS_RESOURCES ID
- UINT System = GetFreeSystemResources(GFSR_SYSTEMRESOURCES);
- UINT GDI = GetFreeSystemResources(GFSR_GDIRESOURCES);
- UINT User = GetFreeSystemResources(GFSR_USERRESOURCES);
-
- char str[256];
- sprintf(str, "System: %u%c GDI: %u%c User: %u%c", System, 37, GDI, 37, User, 37);
- SetDlgItemText(LBL_SYS_RESOURCES,str);
-
- return TRUE; // return TRUE unless you set the focus to a control
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // CTimingDlg dialog
- CTimingDlg::CTimingDlg(CWnd* pParent /*=NULL*/, float* Timing)
- : CDialog(CTimingDlg::IDD, pParent)
- {
- // The parent passed in a pointer to m_nTiming
- // Save this so that a new variable can be places at the same
- // memory location on exit of this dialog box
-
- //{{AFX_DATA_INIT(CTimingDlg)
- m_TB_TIMING = *Timing;
- m_pTiming = Timing;
- //}}AFX_DATA_INIT
- }
-
- void CTimingDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(CTimingDlg)
- DDX_Text(pDX, TB_TIMING, m_TB_TIMING);
- //}}AFX_DATA_MAP
- }
-
- BEGIN_MESSAGE_MAP(CTimingDlg, CDialog)
- //{{AFX_MSG_MAP(CTimingDlg)
- ON_BN_CLICKED(IDOK, OnClickOK)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // CTimingDlg message handlers
-
- BOOL CTimingDlg::OnInitDialog()
- {
- CDialog::OnInitDialog();
- this->CenterWindow();
- return TRUE; // return TRUE unless you set the focus to a control
- }
-
- void CTimingDlg::OnClickOK()
- {
- if ( this->UpdateData(TRUE) )
- {
- // Copy new timing info to address passed in constructor
- *m_pTiming = m_TB_TIMING;
- this->EndDialog(0);
- }
- else MessageBox("You must enter a decimal value.", "Error", MB_ICONSTOP | MB_OK);
- }
-