tgstation-server  4.3.2
The /tg/station 13 server suite
WindowsProcessFeatures.cs
Go to the documentation of this file.
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Diagnostics;
5 using System.Linq;
6 using System.Management;
7 using System.Threading;
8 using System.Threading.Tasks;
9 
10 namespace Tgstation.Server.Host.System
11 {
14  {
18  readonly ILogger<WindowsProcessFeatures> logger;
19 
24  public WindowsProcessFeatures(ILogger<WindowsProcessFeatures> logger)
25  {
26  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
27  }
28 
30  public void ResumeProcess(global::System.Diagnostics.Process process)
31  {
32  if (process == null)
33  throw new ArgumentNullException(nameof(process));
34 
35  try
36  {
37  foreach (ProcessThread thread in process.Threads)
38  {
39  var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, (uint)thread.Id);
40  if (pOpenThread == IntPtr.Zero)
41  continue;
42 
43  if (NativeMethods.ResumeThread(pOpenThread) == UInt32.MaxValue)
44  throw new Win32Exception();
45 
46  NativeMethods.CloseHandle(pOpenThread);
47  }
48 
49  logger.LogTrace("Resumed PID {0}", process.Id);
50  }
51  catch (Exception e)
52  {
53  logger.LogError(e, "Failed to resume PID {0}!", process.Id);
54  throw;
55  }
56  }
57 
59  public void SuspendProcess(global::System.Diagnostics.Process process)
60  {
61  if (process == null)
62  throw new ArgumentNullException(nameof(process));
63 
64  try
65  {
66  foreach (ProcessThread thread in process.Threads)
67  {
68  var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, (uint)thread.Id);
69  if (pOpenThread == IntPtr.Zero)
70  continue;
71 
72  if (NativeMethods.SuspendThread(pOpenThread) == UInt32.MaxValue)
73  throw new Win32Exception();
74 
75  NativeMethods.CloseHandle(pOpenThread);
76  }
77 
78  logger.LogTrace("Suspended PID {0}", process.Id);
79  }
80  catch (Exception e)
81  {
82  logger.LogError(e, "Failed to suspend PID {0}!", process.Id);
83  throw;
84  }
85  }
86 
88  public Task<string> GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
89  {
90  string query = $"SELECT * FROM Win32_Process WHERE ProcessId = {process?.Id ?? throw new ArgumentNullException(nameof(process))}";
91  using var searcher = new ManagementObjectSearcher(query);
92  foreach (ManagementObject obj in searcher.Get())
93  {
94  var argList = new string[] { String.Empty, String.Empty };
95  var returnString = obj.InvokeMethod(
96  "GetOwner",
97  argList)
98  ?.ToString();
99 
100  if (!Int32.TryParse(returnString, out var returnVal))
101  return Task.FromResult($"BAD RETURN PARSE: {returnString}");
102 
103  if (returnVal == 0)
104  {
105  // return DOMAIN\user
106  string owner = argList.Last() + "\\" + argList.First();
107  return Task.FromResult(owner);
108  }
109  }
110 
111  return Task.FromResult("NO OWNER");
112  }
113  }
114 }
static uint ResumeThread(IntPtr hThread)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms685086(v=vs.85).aspx ...
readonly ILogger< WindowsProcessFeatures > logger
The ILogger<TCategoryName> for the WindowsProcessFeatures.
void SuspendProcess(global::System.Diagnostics.Process process)
Suspend a given Process.
WindowsProcessFeatures(ILogger< WindowsProcessFeatures > logger)
Initializes a new instance of the WindowsProcessFeatures .
void ResumeProcess(global::System.Diagnostics.Process process)
Resume a given suspended Process.
Task< string > GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
Get the name of the user executing a given process .
static bool CloseHandle(IntPtr hObject)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx ...
Native Windows methods used by the code
ThreadAccess
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx ...
static uint SuspendThread(IntPtr hThread)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686345(v=vs.85).aspx ...
Abstraction for suspending and resuming processes.
static IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335(v=vs.85).aspx ...