using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Bds.Inject;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;
using System.IO;
namespace Bds.ObjectSpy
{
public partial class MainForm : Form
{
#region Win32 API Declarations
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
#region Helper methods
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
public static implicit operator System.Drawing.Point(POINT p)
{
return new System.Drawing.Point(p.X, p.Y);
}
public static implicit operator POINT(System.Drawing.Point p)
{
return new POINT(p.X, p.Y);
}
#endregion
}
const int DSTINVERT = 0x00550009;
[DllImport("gdi32.dll")]
static extern bool PatBlt(IntPtr hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, uint dwRop);
[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(POINT Point);
[DllImport("user32.dll")]
static extern int GetWindowText(int hWnd, StringBuilder text, int count);
[DllImport("user32.dll")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
static extern bool OffsetRect(ref RECT lprc, int dx, int dy);
[DllImport("user32.dll")]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
#endregion
bool _dragging;
IntPtr _hWndCurrent;
ContextMenuStrip _contextMenu;
ToolStripMenuItem _browse;
ToolStripMenuItem _cancel;
Image _imgAppCross;
Image _imgApp;
Cursor _curCross;
public MainForm()
{
InitializeComponent();
Assembly assembly = Assembly.GetExecutingAssembly();
_imgAppCross = Image.FromStream(assembly.GetManifestResourceStream("Bds.ObjectSpy.app_cross.bmp"));
_imgApp = Image.FromStream(assembly.GetManifestResourceStream("Bds.ObjectSpy.app.bmp"));
_curCross = new Cursor(assembly.GetManifestResourceStream("Bds.ObjectSpy.cross.cur"));
dragPictureBox.Image = _imgAppCross;
_browse = new ToolStripMenuItem("Inject Object Browser");
_cancel = new ToolStripMenuItem("Cancel");
_contextMenu = new ContextMenuStrip();
_contextMenu.Items.Add(_browse);
_contextMenu.Items.Add(_cancel);
_browse.Click += new EventHandler(Browse_Click);
_contextMenu.Closed += new ToolStripDropDownClosedEventHandler(ContextMenu_Closed);
}
private void DrawRevFrame(IntPtr hWnd)
{
if (hWnd == IntPtr.Zero)
return;
IntPtr hdc = GetWindowDC(hWnd);
RECT rect;
GetWindowRect(hWnd, out rect);
OffsetRect(ref rect, -rect.Left, -rect.Top);
const int frameWidth = 3;
PatBlt(hdc, rect.Left, rect.Top, rect.Right - rect.Left, frameWidth, DSTINVERT);
PatBlt(hdc, rect.Left, rect.Bottom - frameWidth, frameWidth,
-(rect.Bottom - rect.Top - 2 * frameWidth), DSTINVERT);
PatBlt(hdc, rect.Right - frameWidth, rect.Top + frameWidth, frameWidth,
rect.Bottom - rect.Top - 2 * frameWidth, DSTINVERT);
PatBlt(hdc, rect.Right, rect.Bottom - frameWidth, -(rect.Right - rect.Left),
frameWidth, DSTINVERT);
}
private string GetWindowText(IntPtr hWnd)
{
StringBuilder text = new StringBuilder(256);
if (GetWindowText(hWnd.ToInt32(), text, text.Capacity) > 0)
{
return text.ToString();
}
return String.Empty;
}
private string GetClassName(IntPtr hWnd)
{
StringBuilder className = new StringBuilder(100);
if (GetClassName(hWnd, className, className.Capacity) > 0)
{
return className.ToString();
}
return String.Empty;
}
/*private bool IsManaged(IntPtr hWnd)
{
int procId;
GetWindowThreadProcessId(hWnd, out procId);
Process proc = Process.GetProcessById(procId);
foreach (ProcessModule procModule in proc.Modules)
{
if (procModule.ModuleName == "mscorlib.dll" || procModule.ModuleName == "mscorlib.ni.dll")
{
return true;
}
}
return false;
}*/
private string GetApplication(IntPtr hWnd)
{
int procId;
GetWindowThreadProcessId(hWnd, out procId);
Process proc = Process.GetProcessById(procId);
return proc.MainModule.ModuleName;
}
private void dragPictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_dragging = true;
this.Cursor = _curCross;
dragPictureBox.Image = _imgApp;
}
}
private void dragPictureBox_MouseUp(object sender, MouseEventArgs e)
{
if (_dragging)
{
_dragging = false;
this.Cursor = Cursors.Default;
if (_hWndCurrent != IntPtr.Zero)
{
DrawRevFrame(_hWndCurrent);
_contextMenu.Show(MousePosition);
_hWndCurrent = IntPtr.Zero;
// The image in the dragPictureBox will be restored when the context menu is closed
}
else
{
dragPictureBox.Image = _imgAppCross;
}
}
}
private void dragPictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (_dragging)
{
IntPtr hWnd = WindowFromPoint(MousePosition);
if (hWnd == dragPictureBox.Handle)
{
// Drawing a border around the dragPictureBox (where we start
// dragging) doesn't look nice, so we ignore this window
hWnd = IntPtr.Zero;
}
if (hWnd != _hWndCurrent)
{
if (_hWndCurrent != null)
{
DrawRevFrame(_hWndCurrent);
}
DrawRevFrame(hWnd);
_hWndCurrent = hWnd;
}
if (hWnd != IntPtr.Zero)
{
txtWindowHandle.Text = hWnd.ToString();
txtWindowText.Text = GetWindowText(hWnd);
txtClassName.Text = GetClassName(hWnd);
txtApplication.Text = GetApplication(hWnd);
}
else
{
txtWindowHandle.Text = String.Empty;
txtWindowText.Text = String.Empty;
txtClassName.Text = String.Empty;
txtApplication.Text = String.Empty;
}
}
}
void ContextMenu_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
dragPictureBox.Image = _imgAppCross;
}
void Browse_Click(object sender, EventArgs e)
{
IntPtr hWnd = new IntPtr(UInt32.Parse(txtWindowHandle.Text));
Injector.InvokeRemote(hWnd, "ObjectSpyLib.dll", "Bds.ObjectSpy.ObjectSpyForm", "ShowBrowser", new object[] { hWnd });
}
private void aboutLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
MessageBox.Show(String.Format("{0}\nVersion {1}\n\nWritten by Bjarne Dam S�rensen", this.Text, Application.ProductVersion.ToString()),
"About " + this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}