From bd52ea4ad8cc8d0cb0ba32cbc899d5afbbded2f1 Mon Sep 17 00:00:00 2001 From: wj32 Date: Sat, 14 Feb 2009 09:44:18 +0000 Subject: [PATCH] made a GetModules function for ProcessHandle - this means that we can now take advantage of KphOpenProcess git-svn-id: svn://svn.code.sf.net/p/processhacker/code@621 21ef857c-d57f-4fe0-8362-d861dc6d29cd --- trunk/ProcessHacker/Misc/Misc.cs | 2 +- .../ProcessHacker/Providers/ModuleProvider.cs | 42 +++++++------ trunk/ProcessHacker/Win32/API/Functions.cs | 16 ++++- trunk/ProcessHacker/Win32/API/Structs.cs | 12 +++- .../Win32/Handles/ProcessHandle.cs | 60 +++++++++++++++++++ 5 files changed, 110 insertions(+), 22 deletions(-) diff --git a/trunk/ProcessHacker/Misc/Misc.cs b/trunk/ProcessHacker/Misc/Misc.cs index 499337f2c..53b28079c 100644 --- a/trunk/ProcessHacker/Misc/Misc.cs +++ b/trunk/ProcessHacker/Misc/Misc.cs @@ -405,7 +405,7 @@ namespace ProcessHacker public static string GetRealPath(string path) { if (path.ToLower().StartsWith("\\systemroot")) - return Environment.SystemDirectory + "\\.." + path.Substring(11); + return (new System.IO.FileInfo(Environment.SystemDirectory + "\\.." + path.Substring(11))).FullName; else if (path.StartsWith("\\??\\")) return path.Substring(4); else diff --git a/trunk/ProcessHacker/Providers/ModuleProvider.cs b/trunk/ProcessHacker/Providers/ModuleProvider.cs index eca62cdc3..08ba86ff7 100644 --- a/trunk/ProcessHacker/Providers/ModuleProvider.cs +++ b/trunk/ProcessHacker/Providers/ModuleProvider.cs @@ -42,6 +42,7 @@ namespace ProcessHacker public class ModuleProvider : Provider { + private Win32.ProcessHandle _processHandle; private int _pid; public ModuleProvider(int PID) @@ -49,7 +50,17 @@ namespace ProcessHacker { _pid = PID; + try + { + _processHandle = new Win32.ProcessHandle(_pid, + Win32.PROCESS_RIGHTS.PROCESS_QUERY_INFORMATION | + Win32.PROCESS_RIGHTS.PROCESS_VM_READ); + } + catch + { } + this.ProviderUpdate += new ProviderUpdateOnce(UpdateOnce); + this.Killed += () => { if (_processHandle != null) _processHandle.Dispose(); }; } private void UpdateOnce() @@ -96,11 +107,11 @@ namespace ProcessHacker if (!Dictionary.ContainsKey(b)) { ModuleItem item = new ModuleItem(); - StringBuilder name = new StringBuilder(256); - StringBuilder filename = new StringBuilder(256); + StringBuilder name = new StringBuilder(0x400); + StringBuilder filename = new StringBuilder(0x400); - Win32.GetDeviceDriverBaseName(b, name, 255); - Win32.GetDeviceDriverFileName(b, filename, 255); + Win32.GetDeviceDriverBaseName(b, name, name.Capacity * 2); + Win32.GetDeviceDriverFileName(b, filename, filename.Capacity * 2); item.BaseAddress = b; item.Name = name.ToString(); @@ -129,12 +140,11 @@ namespace ProcessHacker private void UpdateModules() { - Process process = Process.GetProcessById(_pid); - ProcessModuleCollection modulesCollection = process.Modules; - Dictionary modules = new Dictionary(); - Dictionary newdictionary = new Dictionary(this.Dictionary); + var processModules = _processHandle.GetModules(); + var modules = new Dictionary(); + var newdictionary = new Dictionary(this.Dictionary); - foreach (ProcessModule m in modulesCollection) + foreach (var m in processModules) modules.Add(m.BaseAddress.ToInt32(), m); // look for unloaded modules @@ -152,17 +162,13 @@ namespace ProcessHacker { if (!Dictionary.ContainsKey(b)) { - ProcessModule m = modules[b]; + var m = modules[b]; ModuleItem item = new ModuleItem(); - item.Name = m.ModuleName; - - try { item.FileName = Misc.GetRealPath(m.FileName); } - catch { } - try { item.BaseAddress = b; } - catch { } - try { item.Size = m.ModuleMemorySize; } - catch { } + item.Name = m.BaseName; + item.FileName = Misc.GetRealPath(m.FileName); + item.BaseAddress = b; + item.Size = m.Size; try { diff --git a/trunk/ProcessHacker/Win32/API/Functions.cs b/trunk/ProcessHacker/Win32/API/Functions.cs index 0da9ae75d..1a2cfb31b 100644 --- a/trunk/ProcessHacker/Win32/API/Functions.cs +++ b/trunk/ProcessHacker/Win32/API/Functions.cs @@ -94,10 +94,10 @@ namespace ProcessHacker public static extern bool EnumDeviceDrivers(int[] ImageBases, int Size, out int Needed); [DllImport("psapi.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern bool GetDeviceDriverBaseName(int ImageBase, StringBuilder FileName, int Size); + public static extern int GetDeviceDriverBaseName(int ImageBase, StringBuilder FileName, int Size); [DllImport("psapi.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern bool GetDeviceDriverFileName(int ImageBase, StringBuilder FileName, int Size); + public static extern int GetDeviceDriverFileName(int ImageBase, StringBuilder FileName, int Size); #endregion @@ -330,6 +330,18 @@ namespace ProcessHacker [DllImport("kernel32.dll")] public static extern bool DebugActiveProcessStop(int PID); + [DllImport("psapi.dll")] + public static extern bool EnumProcessModules(int ProcessHandle, IntPtr[] ModuleHandles, int Size, out int RequiredSize); + + [DllImport("psapi.dll", CharSet = CharSet.Unicode)] + public static extern int GetModuleBaseName(int ProcessHandle, IntPtr ModuleHandle, StringBuilder BaseName, int Size); + + [DllImport("psapi.dll", CharSet = CharSet.Unicode)] + public static extern int GetModuleFileNameEx(int ProcessHandle, IntPtr ModuleHandle, StringBuilder FileName, int Size); + + [DllImport("psapi.dll")] + public static extern bool GetModuleInformation(int ProcessHandle, IntPtr ModuleHandle, ref MODULEINFO ModInfo, int Size); + #endregion #region Resources/Handles diff --git a/trunk/ProcessHacker/Win32/API/Structs.cs b/trunk/ProcessHacker/Win32/API/Structs.cs index daf9348b2..d86be32d1 100644 --- a/trunk/ProcessHacker/Win32/API/Structs.cs +++ b/trunk/ProcessHacker/Win32/API/Structs.cs @@ -383,8 +383,18 @@ namespace ProcessHacker [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szModule; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string szExePath; + + public int dwFlags; + } + + [StructLayout(LayoutKind.Sequential)] + public struct MODULEINFO + { + public IntPtr BaseOfDll; + public int SizeOfImage; + public IntPtr EntryPoint; } [StructLayout(LayoutKind.Sequential)] diff --git a/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs b/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs index d6a88bbb8..7c40c5719 100644 --- a/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs +++ b/trunk/ProcessHacker/Win32/Handles/ProcessHandle.cs @@ -21,7 +21,9 @@ */ using System; +using System.Collections.Generic; using System.Runtime.InteropServices; +using System.Text; namespace ProcessHacker { @@ -327,6 +329,46 @@ namespace ProcessHacker return Misc.GetRealPath(sb.ToString(0, len)); } + /// + /// Gets the modules loaded by the process. This requires the + /// PROCESS_QUERY_INFORMATION and PROCESS_VM_READ permissions. + /// + /// + public ProcessModule[] GetModules() + { + IntPtr[] moduleHandles; + int requiredSize; + + EnumProcessModules(this, null, 0, out requiredSize); + moduleHandles = new IntPtr[requiredSize / 4]; + + if (!EnumProcessModules(this, moduleHandles, requiredSize, out requiredSize)) + ThrowLastWin32Error(); + + ProcessModule[] moduleList = new ProcessModule[moduleHandles.Length]; + + for (int i = 0; i < moduleHandles.Length; i++) + { + MODULEINFO moduleInfo = new MODULEINFO(); + StringBuilder baseName = new StringBuilder(0x400); + StringBuilder fileName = new StringBuilder(0x400); + + if (!GetModuleInformation(this, moduleHandles[i], ref moduleInfo, Marshal.SizeOf(moduleInfo))) + ThrowLastWin32Error(); + if (GetModuleBaseName(this, moduleHandles[i], baseName, baseName.Capacity * 2) == 0) + ThrowLastWin32Error(); + if (GetModuleFileNameEx(this, moduleHandles[i], fileName, fileName.Capacity * 2) == 0) + ThrowLastWin32Error(); + + moduleList[i] = new ProcessModule( + moduleInfo.BaseOfDll, moduleInfo.SizeOfImage, moduleInfo.EntryPoint, + baseName.ToString(), Misc.GetRealPath(fileName.ToString()) + ); + } + + return moduleList; + } + /// /// Gets the file name of the process' image, in device name format. This /// requires the PROCESS_QUERY_LIMITED_INFORMATION permission. @@ -569,5 +611,23 @@ namespace ProcessHacker return new TokenHandle(this, access); } } + + public class ProcessModule + { + internal ProcessModule(IntPtr baseAddress, int size, IntPtr entryPoint, string baseName, string fileName) + { + this.BaseAddress = baseAddress; + this.Size = size; + this.EntryPoint = entryPoint; + this.BaseName = baseName; + this.FileName = fileName; + } + + public IntPtr BaseAddress { get; private set; } + public int Size { get; private set; } + public IntPtr EntryPoint { get; private set; } + public string BaseName { get; private set; } + public string FileName { get; private set; } + } } }