diff --git a/src/WinSW.Core/Native/Handle.cs b/src/WinSW.Core/Native/Handle.cs index 1a8ce60..cb14558 100644 --- a/src/WinSW.Core/Native/Handle.cs +++ b/src/WinSW.Core/Native/Handle.cs @@ -5,7 +5,7 @@ using static WinSW.Native.HandleApis; namespace WinSW.Native { [StructLayout(LayoutKind.Sequential)] - internal readonly ref struct Handle + internal readonly struct Handle : IDisposable { private readonly IntPtr handle; diff --git a/src/WinSW.Core/Native/ProcessApis.cs b/src/WinSW.Core/Native/ProcessApis.cs index e54fba5..00ea9e9 100644 --- a/src/WinSW.Core/Native/ProcessApis.cs +++ b/src/WinSW.Core/Native/ProcessApis.cs @@ -34,12 +34,20 @@ namespace WinSW.Native int processInformationLength, IntPtr returnLength = default); + [DllImport(Libraries.Kernel32)] + internal static extern Handle OpenProcess(ProcessAccess desiredAccess, bool inheritHandle, int processId); + [DllImport(Libraries.Advapi32, SetLastError = true)] internal static extern bool OpenProcessToken( IntPtr processHandle, TokenAccessLevels desiredAccess, out Handle tokenHandle); + internal enum ProcessAccess : uint + { + QueryInformation = 0x0400, + } + internal enum PROCESSINFOCLASS { ProcessBasicInformation = 0, diff --git a/src/WinSW.Core/Util/ProcessExtensions.cs b/src/WinSW.Core/Util/ProcessExtensions.cs index dec933e..fc8e751 100644 --- a/src/WinSW.Core/Util/ProcessExtensions.cs +++ b/src/WinSW.Core/Util/ProcessExtensions.cs @@ -20,9 +20,10 @@ namespace WinSW.Util foreach (var child in GetChildren(process)) { - using (child) + using (child.Process) + using (child.Handle) { - StopTree(child, millisecondsTimeout); + StopTree(child.Process, millisecondsTimeout); } } } @@ -31,54 +32,61 @@ namespace WinSW.Util { foreach (var child in GetChildren(process)) { - using (child) + using (child.Process) + using (child.Handle) { - StopTree(child, millisecondsTimeout); + StopTree(child.Process, millisecondsTimeout); } } } - internal static unsafe List GetChildren(this Process process) + // The handle is to keep a reference to the process. + internal static unsafe List<(Process Process, Handle Handle)> GetChildren(this Process process) { var startTime = process.StartTime; int processId = process.Id; - var children = new List(); + var children = new List<(Process Process, Handle Handle)>(); foreach (var other in Process.GetProcesses()) { + var handle = OpenProcess(ProcessAccess.QueryInformation, false, other.Id); + if (handle == IntPtr.Zero) + { + goto Next; + } + try { if (other.StartTime <= startTime) { goto Next; } - - var handle = other.Handle; - - if (NtQueryInformationProcess( - handle, - PROCESSINFOCLASS.ProcessBasicInformation, - out var information, - sizeof(PROCESS_BASIC_INFORMATION)) != 0) - { - goto Next; - } - - if ((int)information.InheritedFromUniqueProcessId == processId) - { - Log.Debug($"Found child process '{other.Format()}'."); - children.Add(other); - continue; - } - - Next: - other.Dispose(); } catch (Exception e) when (e is InvalidOperationException || e is Win32Exception) { - other.Dispose(); + goto Next; } + + if (NtQueryInformationProcess( + handle, + PROCESSINFOCLASS.ProcessBasicInformation, + out var information, + sizeof(PROCESS_BASIC_INFORMATION)) != 0) + { + goto Next; + } + + if ((int)information.InheritedFromUniqueProcessId == processId) + { + Log.Debug($"Found child process '{other.Format()}'."); + children.Add((other, handle)); + continue; + } + + Next: + other.Dispose(); + handle.Dispose(); } return children; @@ -94,7 +102,7 @@ namespace WinSW.Util return null; } - if (!(SendCtrlC(process) is bool sent)) + if (SendCtrlC(process) is not bool sent) { return null; } @@ -143,7 +151,7 @@ namespace WinSW.Util goto Exited; } - if (!(SendCtrlC(process) is bool sent)) + if (SendCtrlC(process) is not bool sent) { goto Exited; } diff --git a/src/WinSW/Program.cs b/src/WinSW/Program.cs index c395a78..b811d9f 100644 --- a/src/WinSW/Program.cs +++ b/src/WinSW/Program.cs @@ -880,8 +880,12 @@ namespace WinSW int count = children.Count; for (int i = 0; i < count; i++) { - using var child = children[i]; - Draw(child, indentation, i == count - 1); + var child = children[i]; + using (child.Process) + using (child.Handle) + { + Draw(child.Process, indentation, i == count - 1); + } } } }