Click here to Skip to main content
15,896,457 members
Articles / Desktop Programming / MFC

MemSpyy

Rate me:
Please Sign up or sign in to vote.
4.95/5 (9 votes)
29 Oct 2007CPOL2 min read 34.7K   793   33  
Using OpenGL to map the virtual memory address space.
// OpenGLControl.cpp : implementation file
//

#include "stdafx.h"
#include "MemSpyy.h"
#include "OpenGLControl.h"
#include ".\openglcontrol.h"
#include "psapi.h"

// uggg i don't like this
#include "MemSpyyDlg.h"

#define ZOOM_FACTOR   800

// COpenGLControl

IMPLEMENT_DYNAMIC(COpenGLControl, CWnd)
COpenGLControl::COpenGLControl()
{
	dc = NULL;
	m_CurrentStartX = 0;
	m_CurrentStartY = 0;
	m_PID = 0;
	m_OpenGLInitialized = false;
	m_Red = 1.0;
	m_Blue = 1.0;

	m_OriginY = 0;
	m_OriginX = 0;

	m_CurrentlySelected = -1;

	RegisterWindowClass();
}

COpenGLControl::~COpenGLControl()
{
	if (dc) //Only delete dc when really allocated
	{
		delete dc;
	}
}


BEGIN_MESSAGE_MAP(COpenGLControl, CWnd)
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONDBLCLK()
END_MESSAGE_MAP()

void COpenGLControl::InitGL()
{
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	m_OpenGLInitialized = true;
}

void COpenGLControl::DrawMemory( SIZE_T blockSizeBytes )
{
	GLfloat sizeK = (GLfloat) (blockSizeBytes / 1024);
	GLfloat xcoord;
	GLfloat ycoord;

	if ( sizeK <= ( ZOOM_FACTOR - m_CurrentStartX ) )
	{
		xcoord = m_CurrentStartX / ZOOM_FACTOR;
		ycoord = m_CurrentStartY / ZOOM_FACTOR;
		glVertex3f( xcoord, ycoord, 0 );

		m_CurrentStartX += sizeK;
		xcoord = m_CurrentStartX / ZOOM_FACTOR;
		ycoord = m_CurrentStartY / ZOOM_FACTOR;
		glVertex3f( xcoord, ycoord, 0 );
	}
	else
	{
		int numLines = (int) sizeK / (ZOOM_FACTOR * 2);
		if ( 1 < numLines )
		{
			for ( int x = 0; x < numLines; x++ )
			{
				xcoord = m_CurrentStartX / ZOOM_FACTOR;
				ycoord = m_CurrentStartY / ZOOM_FACTOR;
				glVertex3f( xcoord, ycoord, 0 );

				xcoord = 1.0;
				ycoord = m_CurrentStartY / ZOOM_FACTOR;
				glVertex3f( xcoord, ycoord, 0 );

				m_CurrentStartY -= 1;
				xcoord = -1.0;
				ycoord = m_CurrentStartY / ZOOM_FACTOR;
				glVertex3f( xcoord, ycoord, 0 );

				xcoord = m_CurrentStartX / ZOOM_FACTOR;
				ycoord = m_CurrentStartY / ZOOM_FACTOR;
				glVertex3f( xcoord, ycoord, 0 );

				sizeK -= (ZOOM_FACTOR * 2);
			}
		}

		GLfloat nextLine = sizeK - (ZOOM_FACTOR - m_CurrentStartX);

		xcoord = m_CurrentStartX / ZOOM_FACTOR;
		ycoord = m_CurrentStartY / ZOOM_FACTOR;
		glVertex3f( xcoord, ycoord, 0 );

		xcoord = 1.0;
		ycoord = m_CurrentStartY / ZOOM_FACTOR;
		glVertex3f( xcoord, ycoord, 0 );

		m_CurrentStartY -= 1;

		xcoord = -1.0;
		ycoord = m_CurrentStartY / ZOOM_FACTOR;
		glVertex3f( xcoord, ycoord, 0 );

		m_CurrentStartX = -ZOOM_FACTOR + nextLine;

		xcoord = m_CurrentStartX / ZOOM_FACTOR;
		ycoord = m_CurrentStartY / ZOOM_FACTOR;
		glVertex3f( xcoord, ycoord, 0 );
	}
}

void COpenGLControl::DrawGLScene( bool inSelect )
{
	if ( m_PID == 0 )
		return;

	CheckInit();

	if ( inSelect )
		glInitNames();

	unsigned long largestFreeBlock = 0;
	unsigned long totalFree = 0;
	unsigned long totalDLL = 0;

	m_CurrentStartX = -ZOOM_FACTOR;
	m_CurrentStartY = ZOOM_FACTOR;


	glMatrixMode(GL_MODELVIEW);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Get a handle to the process.
	HANDLE process = OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,false, m_PID );

	PVOID baseAddress = 0;
	SIZE_T retVal = 1;
	unsigned long numBlocks = 0;
	while (retVal)
	{
		MEMORY_BASIC_INFORMATION memBlock;
		retVal = VirtualQueryEx(process, baseAddress,&memBlock,sizeof(memBlock));

		if ( inSelect )
		{
			glPushName( numBlocks );
			m_MemoryBlocks[numBlocks] = baseAddress;
		}

		glBegin(GL_LINES);
		if (retVal)
		{

			if (memBlock.State & MEM_FREE)
			{
				if (memBlock.RegionSize>largestFreeBlock)
					largestFreeBlock = (unsigned long) memBlock.RegionSize;

				totalFree += (unsigned long) memBlock.RegionSize;

				if ( numBlocks == m_CurrentlySelected )
					glColor3f( 1.0f, 1.0f, 1.0f );
				else
					glColor3f(m_Red,0.0f,0.0f);
				DrawMemory( memBlock.RegionSize );
			}
			else
			{
				char mappedFile[255];
				if ( GetMappedFileName( process, baseAddress, mappedFile, 255) )
				{
					totalDLL += (unsigned long) memBlock.RegionSize;

					if ( numBlocks == m_CurrentlySelected )
						glColor3f( 1.0f, 1.0f, 1.0f );
					else
						glColor3f(0.0f,1.0f,0.0f);
				}
				else
				{
					if ( numBlocks == m_CurrentlySelected )
						glColor3f( 1.0f, 1.0f, 1.0f );
					else
						glColor3f(0.0f,0.0f,m_Blue);
				}


				DrawMemory( memBlock.RegionSize );
			}

			baseAddress = (void *) (((char *) baseAddress) + memBlock.RegionSize);
		}

		glEnd();

		if ( inSelect )
			glPopName();

		numBlocks++;
	}

	CMemSpyyDlg* theParent = (CMemSpyyDlg*) GetParent();
	theParent->SetLargestFree( largestFreeBlock );
	theParent->SetTotalDLL( totalDLL );
	theParent->SetTotalFree( totalFree );

	SwapBuffers(dc->m_hDC);

}



// COpenGLControl message handlers


void COpenGLControl::OnSize(UINT nType, int cx, int cy)
{
	CWnd::OnSize(nType, cx, cy);


	// this isn't used (yet) since the dialog doesn't resize
	if (cy == 0)
	{
		cy = 1;
	}

	m_Width = cx;
	m_Height = cy;


	glViewport(0,0,cx,cy);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glOrtho(-1.0f,1.0f,-1.0f,1.0f,1.0f,-1.0f);

}



void COpenGLControl::OnPaint()
{

	CheckInit();

	ForceDraw();

	CWnd::OnPaint();
}
void COpenGLControl::ForceDraw()
{
	/** OpenGL section **/

	openGLDevice.makeCurrent();

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	DrawGLScene();
}

BOOL COpenGLControl::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

BOOL COpenGLControl::RegisterWindowClass()
{
	WNDCLASS wndcls;
	HINSTANCE hInst = AfxGetInstanceHandle();

	if (!(::GetClassInfo(hInst, _T("MFCOpenGLControl"), &wndcls)))
	{
		// otherwise we need to register a new class
		wndcls.style            = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
		wndcls.lpfnWndProc      = ::DefWindowProc;
		wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
		wndcls.hInstance        = hInst;
		wndcls.hIcon            = NULL;
		wndcls.hCursor          = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
		wndcls.hbrBackground    = (HBRUSH) (COLOR_3DFACE + 1);
		wndcls.lpszMenuName     = NULL;
		wndcls.lpszClassName    = _T("MFCOpenGLControl");

		if (!AfxRegisterClass(&wndcls))
		{
			AfxThrowResourceException();
			return FALSE;
		}
	}

	return TRUE;
}

void COpenGLControl::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_PrevLDownY = point.y;
	m_PrevLDownX = point.x;

	CWnd::OnLButtonDown(nFlags, point);
}

void COpenGLControl::OnMouseMove(UINT nFlags, CPoint point)
{
	if ( nFlags == MK_RBUTTON)
	{
		if ( m_PrevRDownY < point.y )
			m_Height -=  (3 * (point.y - m_PrevRDownY));
		else
			m_Height +=  (3 * (m_PrevRDownY - point.y));

		m_PrevRDownY = point.y;

		if ( m_PrevRDownX < point.x )
			m_Width +=  (3 * (point.x - m_PrevRDownX));
		else
			m_Width-=  (3 * (m_PrevRDownX - point.x));

		m_PrevRDownX = point.x;
	}
	else if ( nFlags == MK_LBUTTON)
	{
		if ( m_PrevLDownY < point.y )
			m_OriginY -=  point.y - m_PrevLDownY;
		else
			m_OriginY +=  m_PrevLDownY - point.y;

		m_PrevLDownY = point.y;

		if ( m_PrevLDownX < point.x )
			m_OriginX +=  point.x - m_PrevLDownX;
		else
			m_OriginX -=  m_PrevLDownX - point.x;

		m_PrevLDownX = point.x;

	}
	else
	{
		m_PrevX = point.x;
		m_PrevY = point.y;

		CMemSpyyDlg* theParent = (CMemSpyyDlg*) GetParent();


		//////// STATUS /////////////
		GLuint selectBuffer[100000];
		glSelectBuffer(100000, selectBuffer);

		glRenderMode(GL_SELECT);

		CRect rect;
		GetWindowRect(&rect);

		long halfWidth = rect.Width() / 2;
		long halfHeight = rect.Height() / 2;

		GLdouble xcoord = 0;
		if ( point.x < halfWidth )
			xcoord = -( (double) point.x / (double) halfWidth );
		else
			xcoord = ((double) (point.x - halfWidth)) / (double) halfWidth;

		GLdouble ycoord = 0;
		if ( point.y < halfHeight )
			ycoord = ((double) halfHeight - (double) point.y) / ((double) halfHeight);
		else
			ycoord = - ( (double) ( point.y - halfHeight ) / (double) halfHeight );

		GLint viewport[4];
		glGetIntegerv( GL_VIEWPORT, viewport );

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPickMatrix( point.x, rect.Height() - point.y - 1, 2, 2, viewport );

		DrawGLScene(true);
		glFlush();

		long hits = glRenderMode( GL_RENDER );

		if (hits > 0 )
		{
			int glItem = selectBuffer[3];

			theParent->UpdateStatus( m_MemoryBlocks[glItem] );
			m_CurrentlySelected = glItem;
		}
	}

	glViewport(m_OriginX,m_OriginY,m_Width,m_Height);
	ForceDraw();

	CWnd::OnMouseMove(nFlags, point);
}

void COpenGLControl::OnRButtonDown(UINT nFlags, CPoint point)
{
	m_PrevRDownY = point.y;
	m_PrevRDownX = point.x;


	CWnd::OnRButtonDown(nFlags, point);
}

void COpenGLControl::CheckInit()
{
	if ( !m_OpenGLInitialized )
	{
		CRect rect;
		GetWindowRect(&rect);

		m_Width = m_DefaultWidth = rect.Width();
		m_Height = m_DefaultHeight = rect.Height();

		dc = new CClientDC(this); //Get device context of window
		openGLDevice.create(dc->m_hDC); //Create opengl rendering context
		InitGL();
	}
}
void COpenGLControl::OnRButtonDblClk(UINT nFlags, CPoint point)
{
	m_OriginX = 0;
	m_OriginY = 0;
	m_Width = m_DefaultWidth;
	m_Height = m_DefaultHeight;

	glViewport(m_OriginX,m_OriginY,m_Width,m_Height);
	ForceDraw();

	CWnd::OnRButtonDblClk(nFlags, point);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
PJ currently works for Avid Technology, and lives in Cambridge, MA. When he isn't coding, you can find him collecting old dusty funk & soul records.

Comments and Discussions