Terraria v1.4.4.9
Terraria source code documentation
All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Events Macros
NtProcessManager.cs
Go to the documentation of this file.
8
9namespace System.Diagnostics;
10
11internal static class NtProcessManager
12{
37
39 {
40 {
41 "Pool Paged Bytes",
42 ValueId.PoolPagedBytes
43 },
44 {
45 "Pool Nonpaged Bytes",
46 ValueId.PoolNonpagedBytes
47 },
48 {
49 "Elapsed Time",
50 ValueId.ElapsedTime
51 },
52 {
53 "Virtual Bytes Peak",
54 ValueId.VirtualBytesPeak
55 },
56 {
57 "Virtual Bytes",
58 ValueId.VirtualBytes
59 },
60 {
61 "Private Bytes",
62 ValueId.PrivateBytes
63 },
64 {
65 "Page File Bytes",
66 ValueId.PageFileBytes
67 },
68 {
69 "Page File Bytes Peak",
70 ValueId.PageFileBytesPeak
71 },
72 {
73 "Working Set Peak",
74 ValueId.WorkingSetPeak
75 },
76 {
77 "Working Set",
78 ValueId.WorkingSet
79 },
80 {
81 "ID Thread",
82 ValueId.ThreadId
83 },
84 {
85 "ID Process",
86 ValueId.ProcessId
87 },
88 {
89 "Priority Base",
90 ValueId.BasePriority
91 },
92 {
93 "Priority Current",
94 ValueId.CurrentPriority
95 },
96 {
97 "% User Time",
98 ValueId.UserTime
99 },
100 {
101 "% Privileged Time",
102 ValueId.PrivilegedTime
103 },
104 {
105 "Start Address",
106 ValueId.StartAddress
107 },
108 {
109 "Thread State",
110 ValueId.ThreadState
111 },
112 {
113 "Thread Wait Reason",
114 ValueId.ThreadWaitReason
115 }
116 };
117
118 internal static int SystemProcessID => 4;
119
120 public static int[] GetProcessIds(string machineName, bool isRemoteMachine)
121 {
123 int[] array = new int[processInfos.Length];
124 for (int i = 0; i < processInfos.Length; i++)
125 {
126 array[i] = processInfos[i].ProcessId;
127 }
128 return array;
129 }
130
131 public static int[] GetProcessIds()
132 {
133 int[] array = new int[256];
134 int needed;
135 while (true)
136 {
137 int num = array.Length * 4;
138 if (!global::Interop.Kernel32.EnumProcesses(array, num, out needed))
139 {
140 throw new Win32Exception();
141 }
142 if (needed != num)
143 {
144 break;
145 }
146 array = new int[array.Length * 2];
147 }
148 int[] array2 = new int[needed / 4];
149 Array.Copy(array, array2, array2.Length);
150 return array2;
151 }
152
154 {
155 return GetModules(processId, firstModuleOnly: false);
156 }
157
159 {
161 if (modules.Count != 0)
162 {
163 return modules[0];
164 }
165 return null;
166 }
167
168 public static int GetProcessIdFromHandle(SafeProcessHandle processHandle)
169 {
170 return global::Interop.Kernel32.GetProcessId(processHandle);
171 }
172
189
191 {
192 int num = 5;
194 do
195 {
196 try
197 {
198 byte[] performanceData = library.GetPerformanceData("230 232");
200 }
202 {
204 }
205 num--;
206 }
207 while (processInfos.Length == 0 && num != 0);
208 if (processInfos.Length == 0)
209 {
211 }
212 return processInfos;
213 }
214
216 {
219 ref readonly global::Interop.Advapi32.PERF_DATA_BLOCK reference = ref MemoryMarshal.AsRef<global::Interop.Advapi32.PERF_DATA_BLOCK>(data);
220 int num = reference.HeaderLength;
221 for (int i = 0; i < reference.NumObjectTypes; i++)
222 {
223 ref readonly global::Interop.Advapi32.PERF_OBJECT_TYPE reference2 = ref MemoryMarshal.AsRef<global::Interop.Advapi32.PERF_OBJECT_TYPE>(data.Slice(num));
224 global::Interop.Advapi32.PERF_COUNTER_DEFINITION[] array = new global::Interop.Advapi32.PERF_COUNTER_DEFINITION[reference2.NumCounters];
225 int num2 = num + reference2.HeaderLength;
226 for (int j = 0; j < reference2.NumCounters; j++)
227 {
228 ref readonly global::Interop.Advapi32.PERF_COUNTER_DEFINITION reference3 = ref MemoryMarshal.AsRef<global::Interop.Advapi32.PERF_COUNTER_DEFINITION>(data.Slice(num2));
229 string counterName = library.GetCounterName(reference3.CounterNameTitleIndex);
230 array[j] = reference3;
231 if (reference2.ObjectNameTitleIndex == processIndex)
232 {
233 array[j].CounterNameTitlePtr = (int)GetValueId(counterName);
234 }
235 else if (reference2.ObjectNameTitleIndex == threadIndex)
236 {
237 array[j].CounterNameTitlePtr = (int)GetValueId(counterName);
238 }
239 num2 += reference3.ByteLength;
240 }
241 int num3 = num + reference2.DefinitionLength;
242 for (int k = 0; k < reference2.NumInstances; k++)
243 {
244 ref readonly global::Interop.Advapi32.PERF_INSTANCE_DEFINITION reference4 = ref MemoryMarshal.AsRef<global::Interop.Advapi32.PERF_INSTANCE_DEFINITION>(data.Slice(num3));
245 ReadOnlySpan<char> span = global::Interop.Advapi32.PERF_INSTANCE_DEFINITION.GetName(in reference4, data.Slice(num3));
246 if (!MemoryExtensions.Equals(span, "_Total", StringComparison.Ordinal))
247 {
248 if (reference2.ObjectNameTitleIndex == processIndex)
249 {
250 ProcessInfo processInfo = GetProcessInfo(data.Slice(num3 + reference4.ByteLength), array);
251 if ((processInfo.ProcessId != 0 || MemoryExtensions.Equals(span, "Idle", StringComparison.OrdinalIgnoreCase)) && !dictionary.ContainsKey(processInfo.ProcessId))
252 {
253 if (span.Length == 15)
254 {
255 if (span.EndsWith(".", StringComparison.Ordinal))
256 {
257 span = span.Slice(0, 14);
258 }
259 else if (span.EndsWith(".e", StringComparison.Ordinal))
260 {
261 span = span.Slice(0, 13);
262 }
263 else if (span.EndsWith(".ex", StringComparison.Ordinal))
264 {
265 span = span.Slice(0, 12);
266 }
267 }
268 processInfo.ProcessName = span.ToString();
270 }
271 }
272 else if (reference2.ObjectNameTitleIndex == threadIndex)
273 {
274 ThreadInfo threadInfo = GetThreadInfo(data.Slice(num3 + reference4.ByteLength), array);
275 if (threadInfo._threadId != 0L)
276 {
277 list.Add(threadInfo);
278 }
279 }
280 }
281 num3 += reference4.ByteLength;
282 num3 += MemoryMarshal.AsRef<global::Interop.Advapi32.PERF_COUNTER_BLOCK>(data.Slice(num3)).ByteLength;
283 }
284 num += reference2.TotalByteLength;
285 }
286 for (int l = 0; l < list.Count; l++)
287 {
289 if (dictionary.TryGetValue(threadInfo2._processId, out var value))
290 {
291 value._threadInfoList.Add(threadInfo2);
292 }
293 }
294 ProcessInfo[] array2 = new ProcessInfo[dictionary.Values.Count];
295 dictionary.Values.CopyTo(array2, 0);
296 return array2;
297 }
298
299 private static ThreadInfo GetThreadInfo(ReadOnlySpan<byte> instanceData, global::Interop.Advapi32.PERF_COUNTER_DEFINITION[] counters)
300 {
302 for (int i = 0; i < counters.Length; i++)
303 {
304 global::Interop.Advapi32.PERF_COUNTER_DEFINITION pERF_COUNTER_DEFINITION = counters[i];
305 long num = ReadCounterValue(pERF_COUNTER_DEFINITION.CounterType, instanceData.Slice(pERF_COUNTER_DEFINITION.CounterOffset));
306 switch ((ValueId)pERF_COUNTER_DEFINITION.CounterNameTitlePtr)
307 {
308 case ValueId.ProcessId:
309 threadInfo._processId = (int)num;
310 break;
311 case ValueId.ThreadId:
312 threadInfo._threadId = (ulong)num;
313 break;
314 case ValueId.BasePriority:
315 threadInfo._basePriority = (int)num;
316 break;
317 case ValueId.CurrentPriority:
318 threadInfo._currentPriority = (int)num;
319 break;
320 case ValueId.StartAddress:
321 threadInfo._startAddress = (IntPtr)num;
322 break;
323 case ValueId.ThreadState:
324 threadInfo._threadState = (ThreadState)num;
325 break;
326 case ValueId.ThreadWaitReason:
327 threadInfo._threadWaitReason = GetThreadWaitReason((int)num);
328 break;
329 }
330 }
331 return threadInfo;
332 }
333
335 {
336 switch (value)
337 {
338 case 0:
339 case 7:
340 return ThreadWaitReason.Executive;
341 case 1:
342 case 8:
343 return ThreadWaitReason.FreePage;
344 case 2:
345 case 9:
346 return ThreadWaitReason.PageIn;
347 case 3:
348 case 10:
349 return ThreadWaitReason.SystemAllocation;
350 case 4:
351 case 11:
352 return ThreadWaitReason.ExecutionDelay;
353 case 5:
354 case 12:
355 return ThreadWaitReason.Suspended;
356 case 6:
357 case 13:
358 return ThreadWaitReason.UserRequest;
359 case 14:
360 return ThreadWaitReason.EventPairHigh;
361 case 15:
362 return ThreadWaitReason.EventPairLow;
363 case 16:
364 return ThreadWaitReason.LpcReceive;
365 case 17:
366 return ThreadWaitReason.LpcReply;
367 case 18:
368 return ThreadWaitReason.VirtualMemory;
369 case 19:
370 return ThreadWaitReason.PageOut;
371 default:
372 return ThreadWaitReason.Unknown;
373 }
374 }
375
376 private static ProcessInfo GetProcessInfo(ReadOnlySpan<byte> instanceData, global::Interop.Advapi32.PERF_COUNTER_DEFINITION[] counters)
377 {
379 for (int i = 0; i < counters.Length; i++)
380 {
381 global::Interop.Advapi32.PERF_COUNTER_DEFINITION pERF_COUNTER_DEFINITION = counters[i];
382 long num = ReadCounterValue(pERF_COUNTER_DEFINITION.CounterType, instanceData.Slice(pERF_COUNTER_DEFINITION.CounterOffset));
383 switch ((ValueId)pERF_COUNTER_DEFINITION.CounterNameTitlePtr)
384 {
385 case ValueId.ProcessId:
386 processInfo.ProcessId = (int)num;
387 break;
388 case ValueId.PoolPagedBytes:
389 processInfo.PoolPagedBytes = num;
390 break;
391 case ValueId.PoolNonpagedBytes:
392 processInfo.PoolNonPagedBytes = num;
393 break;
394 case ValueId.VirtualBytes:
395 processInfo.VirtualBytes = num;
396 break;
397 case ValueId.VirtualBytesPeak:
398 processInfo.VirtualBytesPeak = num;
399 break;
400 case ValueId.WorkingSetPeak:
401 processInfo.WorkingSetPeak = num;
402 break;
403 case ValueId.WorkingSet:
404 processInfo.WorkingSet = num;
405 break;
406 case ValueId.PageFileBytesPeak:
407 processInfo.PageFileBytesPeak = num;
408 break;
409 case ValueId.PageFileBytes:
410 processInfo.PageFileBytes = num;
411 break;
412 case ValueId.PrivateBytes:
413 processInfo.PrivateBytes = num;
414 break;
415 case ValueId.BasePriority:
416 processInfo.BasePriority = (int)num;
417 break;
418 case ValueId.HandleCount:
419 processInfo.HandleCount = (int)num;
420 break;
421 }
422 }
423 return processInfo;
424 }
425
426 private static ValueId GetValueId(string counterName)
427 {
428 if (counterName != null && s_valueIds.TryGetValue(counterName, out var value))
429 {
430 return value;
431 }
432 return ValueId.Unknown;
433 }
434
435 private static long ReadCounterValue(int counterType, ReadOnlySpan<byte> data)
436 {
437 if (((uint)counterType & 0x100u) != 0)
438 {
439 return MemoryMarshal.Read<long>(data);
440 }
441 return MemoryMarshal.Read<int>(data);
442 }
443
445 {
446 if (processId == SystemProcessID || processId == 0)
447 {
448 throw new Win32Exception(-2147467259, System.SR.EnumProcessModuleFailed);
449 }
451 try
452 {
454 if (!global::Interop.Kernel32.EnumProcessModules(safeProcessHandle, null, 0, out var needed))
455 {
456 if (!global::Interop.Kernel32.IsWow64Process(global::Interop.Kernel32.GetCurrentProcess(), out var Wow64Process))
457 {
458 throw new Win32Exception();
459 }
460 if (!global::Interop.Kernel32.IsWow64Process(safeProcessHandle, out var Wow64Process2))
461 {
462 throw new Win32Exception();
463 }
465 {
467 }
469 }
470 int num = needed / IntPtr.Size;
471 IntPtr[] array = new IntPtr[num];
472 while (true)
473 {
474 int num2 = needed;
476 if (num2 == needed)
477 {
478 break;
479 }
480 if (needed > num2 && needed / IntPtr.Size > num)
481 {
482 num = needed / IntPtr.Size;
483 array = new IntPtr[num];
484 }
485 }
487 char[] array2 = ArrayPool<char>.Shared.Rent(260);
488 try
489 {
490 for (int i = 0; i < num && (i <= 0 || !firstModuleOnly); i++)
491 {
493 if (!global::Interop.Kernel32.GetModuleInformation(safeProcessHandle, moduleHandle, out var ntModuleInfo))
494 {
496 continue;
497 }
499 {
500 ModuleMemorySize = ntModuleInfo.SizeOfImage,
501 EntryPointAddress = ntModuleInfo.EntryPoint,
502 BaseAddress = ntModuleInfo.BaseOfDll
503 };
504 int num3 = 0;
505 while ((num3 = global::Interop.Kernel32.GetModuleBaseName(safeProcessHandle, moduleHandle, array2, array2.Length)) == array2.Length)
506 {
507 char[] array3 = array2;
508 array2 = ArrayPool<char>.Shared.Rent(num3 * 2);
509 ArrayPool<char>.Shared.Return(array3);
510 }
511 if (num3 == 0)
512 {
513 processModule.Dispose();
515 continue;
516 }
517 processModule.ModuleName = new string(array2, 0, num3);
518 while ((num3 = global::Interop.Kernel32.GetModuleFileNameEx(safeProcessHandle, moduleHandle, array2, array2.Length)) == array2.Length)
519 {
520 char[] array4 = array2;
521 array2 = ArrayPool<char>.Shared.Rent(num3 * 2);
522 ArrayPool<char>.Shared.Return(array4);
523 }
524 if (num3 == 0)
525 {
526 processModule.Dispose();
528 continue;
529 }
530 ReadOnlySpan<char> span = array2.AsSpan(0, num3);
531 if (span.StartsWith("\\\\?\\"))
532 {
533 span = span.Slice("\\\\?\\".Length);
534 }
535 processModule.FileName = span.ToString();
537 }
538 }
539 finally
540 {
541 ArrayPool<char>.Shared.Return(array2);
542 }
544 }
545 finally
546 {
547 if (!safeProcessHandle.IsInvalid)
548 {
549 safeProcessHandle.Dispose();
550 }
551 }
552 }
553
554 private static void EnumProcessModulesUntilSuccess(SafeProcessHandle processHandle, IntPtr[] modules, int size, out int needed)
555 {
556 int num = 0;
557 while (true)
558 {
559 if (global::Interop.Kernel32.EnumProcessModules(processHandle, modules, size, out needed))
560 {
561 return;
562 }
563 if (num++ > 50)
564 {
565 break;
566 }
567 Thread.Sleep(1);
568 }
569 throw new Win32Exception();
570 }
571
572 private static void HandleLastWin32Error()
573 {
575 if (lastWin32Error != 6 && lastWin32Error != 299)
576 {
578 }
579 }
580}
static readonly SafeProcessHandle InvalidHandle
static unsafe void Copy(Array sourceArray, Array destinationArray, int length)
Definition Array.cs:624
void Add(TKey key, TValue value)
static ProcessInfo[] GetProcessInfos(PerformanceCounterLib library)
static long ReadCounterValue(int counterType, ReadOnlySpan< byte > data)
static ProcessModule GetFirstModule(int processId)
static ProcessInfo[] GetProcessInfos(string machineName, bool isRemoteMachine)
static ThreadInfo GetThreadInfo(ReadOnlySpan< byte > instanceData, global::Interop.Advapi32.PERF_COUNTER_DEFINITION[] counters)
static ProcessInfo[] GetProcessInfos(PerformanceCounterLib library, int processIndex, int threadIndex, ReadOnlySpan< byte > data)
static ThreadWaitReason GetThreadWaitReason(int value)
static readonly Dictionary< string, ValueId > s_valueIds
static ProcessInfo GetProcessInfo(ReadOnlySpan< byte > instanceData, global::Interop.Advapi32.PERF_COUNTER_DEFINITION[] counters)
static void EnumProcessModulesUntilSuccess(SafeProcessHandle processHandle, IntPtr[] modules, int size, out int needed)
static ProcessModuleCollection GetModules(int processId, bool firstModuleOnly)
static int[] GetProcessIds(string machineName, bool isRemoteMachine)
static ValueId GetValueId(string counterName)
static int GetProcessIdFromHandle(SafeProcessHandle processHandle)
static ProcessModuleCollection GetModules(int processId)
static PerformanceCounterLib GetPerformanceCounterLib(string machineName, CultureInfo culture)
static SafeProcessHandle OpenProcess(int processId, int access, bool throwIfExited)
static bool Equals(this ReadOnlySpan< char > span, ReadOnlySpan< char > other, StringComparison comparisonType)
static string EnumProcessModuleFailedDueToWow
Definition SR.cs:54
static string CouldntGetProcessInfos
Definition SR.cs:46
static string ProcessDisabled
Definition SR.cs:38
static string CouldntConnectToRemoteMachine
Definition SR.cs:44
static string EnumProcessModuleFailed
Definition SR.cs:52
Definition SR.cs:7
static void Sleep(int millisecondsTimeout)
Definition Thread.cs:658
static int Size
Definition IntPtr.cs:21