using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; namespace ISphereWinHelper { internal static class RuntimeProbe { [DllImport("kernel32.dll", SetLastError = true)] private static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process); public static Dictionary ProbeClientRuntime(Dictionary args) { var processNames = GetStringList(args, "process_names", new[] { "IMPlatformClient", "IMPP.ISphere", "iSphere", "importal" }); var moduleHints = GetStringList(args, "module_hints", new[] { "IMPlatformClient.exe", "smack.dll", "IMPP.Interface.dll", "IMPP.ServiceBase.dll", "IMPP.Service.dll", "IMPP.Common.dll", "IMPP.Helper.dll", "IMPP.Model.dll", "IMPP.Util.dll", "IMPP.UI.dll", "TcpFileTransfer.dll", "HYHC.IMPP.DAL.dll", "INetwork.dll", "IOClientNetwork.dll" }); bool includeModules = HelperProtocol.GetBool(args, "include_modules", true); int maxModules = HelperProtocol.GetInt(args, "max_modules", 120); if (maxModules < 0) { maxModules = 0; } var targets = new List>(); foreach (Process process in Process.GetProcesses()) { using (process) { string processName = SafeProcessName(process); if (!MatchesAny(processName, processNames)) { continue; } targets.Add(DescribeProcess(process, moduleHints, includeModules, maxModules)); } } targets.Sort(delegate(Dictionary left, Dictionary right) { int leftScore = Convert.ToInt32(left["score"]); int rightScore = Convert.ToInt32(right["score"]); int scoreCompare = rightScore.CompareTo(leftScore); if (scoreCompare != 0) { return scoreCompare; } return Convert.ToInt32(left["pid"]).CompareTo(Convert.ToInt32(right["pid"])); }); return new Dictionary { { "probe_mode", "read_only_process_module_inventory" }, { "host", new Dictionary { { "is_64_bit_os", Environment.Is64BitOperatingSystem }, { "is_64_bit_process", Environment.Is64BitProcess }, { "machine_name", Environment.MachineName } } }, { "process_names", processNames }, { "module_hints", moduleHints }, { "target_count", targets.Count }, { "targets", targets } }; } private static Dictionary DescribeProcess(Process process, List moduleHints, bool includeModules, int maxModules) { string executablePath = ""; string mainModuleName = ""; string mainModuleVersion = ""; string mainModuleError = ""; try { ProcessModule mainModule = process.MainModule; if (mainModule != null) { executablePath = mainModule.FileName ?? ""; mainModuleName = mainModule.ModuleName ?? ""; FileVersionInfo versionInfo = mainModule.FileVersionInfo; if (versionInfo != null) { mainModuleVersion = versionInfo.FileVersion ?? ""; } } } catch (Exception ex) { mainModuleError = ex.GetType().Name + ": " + ex.Message; } bool? isWow64 = GetIsWow64(process); string bitness = "unknown"; if (Environment.Is64BitOperatingSystem && isWow64.HasValue) { bitness = isWow64.Value ? "x86" : "x64"; } else if (!Environment.Is64BitOperatingSystem) { bitness = "x86"; } string moduleProbeError = ""; var modules = new List>(); var assemblyPresence = NewPresenceMap(moduleHints); if (includeModules) { try { int count = 0; foreach (ProcessModule module in process.Modules) { if (count >= maxModules) { break; } string moduleName = module.ModuleName ?? ""; string modulePath = module.FileName ?? ""; string matchedHint = FindMatchedHint(moduleName, modulePath, moduleHints); if (!string.IsNullOrEmpty(matchedHint)) { assemblyPresence[matchedHint] = true; } modules.Add(new Dictionary { { "name", moduleName }, { "path", modulePath }, { "matched_hint", matchedHint } }); count++; } } catch (Exception ex) { moduleProbeError = ex.GetType().Name + ": " + ex.Message; } } if (!string.IsNullOrEmpty(mainModuleName)) { string matchedMain = FindMatchedHint(mainModuleName, executablePath, moduleHints); if (!string.IsNullOrEmpty(matchedMain)) { assemblyPresence[matchedMain] = true; } } int score = Score(process.ProcessName, executablePath, assemblyPresence); return new Dictionary { { "pid", process.Id }, { "process_name", process.ProcessName }, { "main_window_title", SafeMainWindowTitle(process) }, { "main_window_handle", WindowScanner.FormatHwnd(process.MainWindowHandle) }, { "has_main_window", process.MainWindowHandle != IntPtr.Zero }, { "executable_path", executablePath }, { "main_module_name", mainModuleName }, { "main_module_version", mainModuleVersion }, { "main_module_error", mainModuleError }, { "bitness", bitness }, { "is_wow64", isWow64.HasValue ? (object)isWow64.Value : null }, { "module_probe_ok", string.IsNullOrEmpty(moduleProbeError) }, { "module_probe_error", moduleProbeError }, { "assembly_presence", assemblyPresence }, { "modules", modules }, { "score", score } }; } private static Dictionary NewPresenceMap(List moduleHints) { var presence = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (string hint in moduleHints) { if (!presence.ContainsKey(hint)) { presence.Add(hint, false); } } return presence; } private static int Score(string processName, string executablePath, Dictionary assemblyPresence) { int score = 0; string combined = ((processName ?? "") + " " + (executablePath ?? "")).ToLowerInvariant(); if (combined.Contains("implatformclient")) score += 80; if (combined.Contains("isphere")) score += 40; if (combined.Contains("impp")) score += 20; if (combined.Contains("importal")) score += 10; foreach (object value in assemblyPresence.Values) { if (value is bool && (bool)value) { score += 5; } } return score; } private static bool? GetIsWow64(Process process) { try { bool isWow64; if (IsWow64Process(process.Handle, out isWow64)) { return isWow64; } } catch { } return null; } private static string SafeProcessName(Process process) { try { return process.ProcessName ?? ""; } catch { return ""; } } private static string SafeMainWindowTitle(Process process) { try { return process.MainWindowTitle ?? ""; } catch { return ""; } } private static bool MatchesAny(string processName, List candidates) { foreach (string candidate in candidates) { if (string.Equals(processName, candidate, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static string FindMatchedHint(string moduleName, string modulePath, List hints) { foreach (string hint in hints) { if (string.Equals(moduleName, hint, StringComparison.OrdinalIgnoreCase)) { return hint; } if (!string.IsNullOrEmpty(modulePath) && modulePath.EndsWith("\\" + hint, StringComparison.OrdinalIgnoreCase)) { return hint; } } return ""; } private static List GetStringList(Dictionary source, string key, string[] defaults) { var values = new List(); object raw; if (source != null && source.TryGetValue(key, out raw) && raw != null) { object[] rawArray = raw as object[]; if (rawArray != null) { foreach (object item in rawArray) { string value = Convert.ToString(item); if (!string.IsNullOrWhiteSpace(value)) { values.Add(value.Trim()); } } } else { string single = Convert.ToString(raw); if (!string.IsNullOrWhiteSpace(single)) { foreach (string part in single.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { string value = part.Trim(); if (!string.IsNullOrWhiteSpace(value)) { values.Add(value); } } } } } if (values.Count == 0) { values.AddRange(defaults); } return values; } } }