tgstation-server 5.12.7
The /tg/station 13 server suite
Loading...
Searching...
No Matches
WindowsProcessFeatures.cs
Go to the documentation of this file.
1using System;
2using System.Diagnostics;
3using System.IO;
4using System.Linq;
5using System.Management;
6using System.Runtime.Versioning;
7using System.Threading;
8using System.Threading.Tasks;
9
10using BetterWin32Errors;
11using Microsoft.Extensions.Logging;
12
16
18{
20 [SupportedOSPlatform("windows")]
22 {
26 readonly ILogger<WindowsProcessFeatures> logger;
27
32 public WindowsProcessFeatures(ILogger<WindowsProcessFeatures> logger)
33 {
34 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
35 }
36
38 public void ResumeProcess(global::System.Diagnostics.Process process)
39 {
40 ArgumentNullException.ThrowIfNull(process);
41
42 process.Refresh();
43 foreach (ProcessThread thread in process.Threads)
44 {
45 var threadId = (uint)thread.Id;
46 logger.LogTrace("Resuming thread {threadId}...", threadId);
47 var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, threadId);
48 if (pOpenThread == IntPtr.Zero)
49 {
50 logger.LogDebug(new Win32Exception(), "Failed to open thread {threadId}!", threadId);
51 continue;
52 }
53
54 try
55 {
56 if (NativeMethods.ResumeThread(pOpenThread) == UInt32.MaxValue)
57 throw new Win32Exception();
58 }
59 finally
60 {
61 NativeMethods.CloseHandle(pOpenThread);
62 }
63 }
64 }
65
67 public void SuspendProcess(global::System.Diagnostics.Process process)
68 {
69 ArgumentNullException.ThrowIfNull(process);
70
71 process.Refresh();
72 foreach (ProcessThread thread in process.Threads)
73 {
74 var threadId = (uint)thread.Id;
75 logger.LogTrace("Suspending thread {threadId}...", threadId);
76 var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, threadId);
77 if (pOpenThread == IntPtr.Zero)
78 {
79 logger.LogDebug(new Win32Exception(), "Failed to open thread {threadId}!", threadId);
80 continue;
81 }
82
83 try
84 {
85 if (NativeMethods.SuspendThread(pOpenThread) == UInt32.MaxValue)
86 throw new Win32Exception();
87 }
88 finally
89 {
90 NativeMethods.CloseHandle(pOpenThread);
91 }
92 }
93 }
94
96 public Task<string> GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
97 {
98 string query = $"SELECT * FROM Win32_Process WHERE ProcessId = {process?.Id ?? throw new ArgumentNullException(nameof(process))}";
99 using var searcher = new ManagementObjectSearcher(query);
100 foreach (var obj in searcher.Get().Cast<ManagementObject>())
101 {
102 var argList = new string[] { String.Empty, String.Empty };
103 var returnString = obj.InvokeMethod(
104 "GetOwner",
105 argList)
106 ?.ToString();
107
108 if (!Int32.TryParse(returnString, out var returnVal))
109 return Task.FromResult($"BAD RETURN PARSE: {returnString}");
110
111 if (returnVal == 0)
112 {
113 // return DOMAIN\user
114 string owner = argList.Last() + "\\" + argList.First();
115 return Task.FromResult(owner);
116 }
117 }
118
119 return Task.FromResult("NO OWNER");
120 }
121
123 public async Task CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken)
124 {
125 try
126 {
127 if (process.HasExited)
128 throw new JobException(ErrorCode.DreamDaemonOffline);
129 }
130 catch (InvalidOperationException ex)
131 {
132 throw new JobException(ErrorCode.DreamDaemonOffline, ex);
133 }
134
135 await using var fileStream = new FileStream(outputFile, FileMode.CreateNew);
136
137 await Task.Factory.StartNew(
138 () =>
139 {
141 process.Handle,
142 (uint)process.Id,
143 fileStream.SafeFileHandle,
144 NativeMethods.MiniDumpType.WithDataSegs
145 | NativeMethods.MiniDumpType.WithFullMemory
146 | NativeMethods.MiniDumpType.WithHandleData
147 | NativeMethods.MiniDumpType.WithThreadInfo
148 | NativeMethods.MiniDumpType.WithUnloadedModules,
149 IntPtr.Zero,
150 IntPtr.Zero,
151 IntPtr.Zero))
152 throw new Win32Exception();
153 },
154 cancellationToken,
156 TaskScheduler.Current);
157 }
158 }
159}
IIOManager that resolves paths to Environment.CurrentDirectory.
const TaskCreationOptions BlockingTaskCreationOptions
The TaskCreationOptions used to spawn Tasks for potentially long running, blocking operations.
Operation exceptions thrown from the context of a Models.Job.
Definition: JobException.cs:11
Native Windows methods used by the code.
MiniDumpType
See https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ne-minidumpapiset-minidump_type...
static IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335(v=vs.85).aspx.
static uint ResumeThread(IntPtr hThread)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms685086(v=vs.85).aspx.
static uint SuspendThread(IntPtr hThread)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686345(v=vs.85).aspx.
static bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, MiniDumpType dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam)
See https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwrite...
static bool CloseHandle(IntPtr hObject)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx.
ThreadAccess
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx.
void SuspendProcess(global::System.Diagnostics.Process process)
Suspend a given process .
void ResumeProcess(global::System.Diagnostics.Process process)
Resume a given suspended Process.
WindowsProcessFeatures(ILogger< WindowsProcessFeatures > logger)
Initializes a new instance of the WindowsProcessFeatures class.
async Task CreateDump(global::System.Diagnostics.Process process, string outputFile, CancellationToken cancellationToken)
Create a dump file for a given process . A Task representing the running operation.
Task< string > GetExecutingUsername(global::System.Diagnostics.Process process, CancellationToken cancellationToken)
Get the name of the user executing a given process . The name of the user executing process .
readonly ILogger< WindowsProcessFeatures > logger
The ILogger for the WindowsProcessFeatures.
Abstraction for suspending and resuming processes.
ErrorCode
Types of Response.ErrorMessageResponses that the API may return.
Definition: ErrorCode.cs:11