/* * Process Hacker - * run-time library debug buffer * * Copyright (C) 2009 wj32 * * This file is part of Process Hacker. * * Process Hacker is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Process Hacker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Process Hacker. If not, see . */ using System; using System.Collections.Generic; using ProcessHacker.Common.Objects; using ProcessHacker.Native.Api; using ProcessHacker.Native.Objects; namespace ProcessHacker.Native.Debugging { public delegate bool DebugEnumHeapsDelegate(HeapInformation heapInfo); public delegate bool DebugEnumLocksDelegate(LockInformation lockInfo); public delegate bool DebugEnumModulesDelegate(ModuleInformation moduleInfo); /// /// Represents a debug buffer managed by the run-time library. /// public sealed class DebugBuffer : BaseObject { private IntPtr _buffer; /// /// Creates a new debug buffer. /// public DebugBuffer() { _buffer = Win32.RtlCreateQueryDebugBuffer(0, false); if (_buffer == IntPtr.Zero) { this.DisableOwnership(false); throw new WindowsException(NtStatus.Unsuccessful); } } protected override void DisposeObject(bool disposing) { Win32.RtlDestroyQueryDebugBuffer(_buffer); } /// /// Enumerates heap information. /// /// The callback for the enumeration. public void EnumHeaps(DebugEnumHeapsDelegate callback) { var debugInfo = this.GetDebugInformation(); if (debugInfo.Heaps == IntPtr.Zero) throw new InvalidOperationException("Heap information does not exist."); MemoryRegion heapInfo = new MemoryRegion(debugInfo.Heaps); var heaps = heapInfo.ReadStruct(); for (int i = 0; i < heaps.NumberOfHeaps; i++) { var heap = heapInfo.ReadStruct(RtlProcessHeaps.HeapsOffset, i); if (!callback(new HeapInformation(heap))) break; } } /// /// Enumerates lock information. /// /// The callback for the enumeration. public void EnumLocks(DebugEnumLocksDelegate callback) { var debugInfo = this.GetDebugInformation(); if (debugInfo.Locks == IntPtr.Zero) throw new InvalidOperationException("Lock information does not exist."); MemoryRegion locksInfo = new MemoryRegion(debugInfo.Locks); var locks = locksInfo.ReadStruct(); for (int i = 0; i < locks.NumberOfLocks; i++) { var lock_ = locksInfo.ReadStruct(sizeof(int), i); if (!callback(new LockInformation(lock_))) break; } } /// /// Enumerates module information. /// /// The callback for the enumeration. public void EnumModules(DebugEnumModulesDelegate callback) { var debugInfo = this.GetDebugInformation(); if (debugInfo.Modules == IntPtr.Zero) throw new InvalidOperationException("Module information does not exist."); MemoryRegion modulesInfo = new MemoryRegion(debugInfo.Modules); var modules = modulesInfo.ReadStruct(); for (int i = 0; i < modules.NumberOfModules; i++) { var module = modulesInfo.ReadStruct(RtlProcessModules.ModulesOffset, i); if (!callback(new ModuleInformation(module))) break; } } /// /// Reads the debug information structure from the buffer. /// /// A RtlDebugInformation structure. private RtlDebugInformation GetDebugInformation() { MemoryRegion data = new MemoryRegion(_buffer); return data.ReadStruct(); } /// /// Gets heap information. /// /// An array of heap information objects. public HeapInformation[] GetHeaps() { List heaps = new List(); this.EnumHeaps((heap) => { heaps.Add(heap); return true; }); return heaps.ToArray(); } /// /// Gets lock information. /// /// An array of lock information objects. public LockInformation[] GetLocks() { List locks = new List(); this.EnumLocks((lock_) => { locks.Add(lock_); return true; }); return locks.ToArray(); } /// /// Gets module information. /// /// An array of module information objects. public ModuleInformation[] GetModules() { List modules = new List(); this.EnumModules((module) => { modules.Add(module); return true; }); return modules.ToArray(); } /// /// Queries debug information for the current process. /// /// The information to query. public void Query(RtlQueryProcessDebugFlags flags) { this.Query(ProcessHandle.GetCurrentId(), flags); } /// /// Queries debug information for the specified process. /// /// The PID of the process to query. /// The information to query. public void Query(int pid, RtlQueryProcessDebugFlags flags) { NtStatus status; if ((status = Win32.RtlQueryProcessDebugInformation( pid.ToIntPtr(), flags, _buffer )) >= NtStatus.Error) Win32.Throw(status); } /// /// Queries back trace information for the current process. /// public void QueryBackTraces() { NtStatus status; if ((status = Win32.RtlQueryProcessBackTraceInformation(_buffer)) >= NtStatus.Error) Win32.Throw(status); } /// /// Queries heap information for the current process. /// public void QueryHeaps() { NtStatus status; if ((status = Win32.RtlQueryProcessHeapInformation(_buffer)) >= NtStatus.Error) Win32.Throw(status); } /// /// Queries lock information for the current process. /// public void QueryLocks() { NtStatus status; if ((status = Win32.RtlQueryProcessLockInformation(_buffer)) >= NtStatus.Error) Win32.Throw(status); } //public void QueryModules() //{ // this.QueryModules(null, RtlQueryProcessDebugFlags.Modules); //} //public void QueryModules(ProcessHandle processHandle, RtlQueryProcessDebugFlags flags) //{ // NtStatus status; // if ((status = Win32.RtlQueryProcessModuleInformation( // processHandle ?? IntPtr.Zero, // flags, // _buffer // )) >= NtStatus.Error) // Win32.ThrowLastError(status); //} } }