Skip to content

Commit 4251f05

Browse files
committed
feat: add CloseSourceHandle(bool) overload
The parameterless overload now calls CloseSourceHandle(false) to increase perceived safety at the cost of reliability. When parameter removeCloseProtection is true, the method will attempt to remove the HANDLE_FLAG_PROTECT_FROM_CLOSE attribute from the handle before attempting to close it.
1 parent 4dd2396 commit 4251f05

File tree

2 files changed

+25
-4
lines changed

2 files changed

+25
-4
lines changed

deadlock-dotnet-sdk/DeadLock.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ public void UnlockEx(FileLockerEx fileLocker)
312312
if (h.IsClosed && h.IsInvalid) continue;
313313
try
314314
{
315-
h.CloseSourceHandle();
315+
h.CloseSourceHandle(true);
316316
}
317317
catch (Exception) when (!RethrowExceptions) { }
318318
}
@@ -347,7 +347,7 @@ await Task.Run(() =>
347347
if (h.IsClosed && h.IsInvalid) continue;
348348
try
349349
{
350-
h.CloseSourceHandle();
350+
h.CloseSourceHandle(true);
351351
}
352352
catch (Exception) when (!RethrowExceptions) { }
353353
}
@@ -369,7 +369,7 @@ await Task.Run(() =>
369369
if (h.IsClosed && h.IsInvalid) continue;
370370
try
371371
{
372-
h.CloseSourceHandle();
372+
h.CloseSourceHandle(true);
373373
}
374374
catch (Exception) when (!RethrowExceptions) { }
375375
}

deadlock-dotnet-sdk/Domain/SafeHandleEx.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Diagnostics;
2+
using System.Runtime.InteropServices;
23
using Microsoft.Win32.SafeHandles;
34
using PInvoke;
45
using Windows.Win32;
@@ -187,19 +188,39 @@ public unsafe (string? v, Exception? ex) ObjectName
187188

188189
#region Methods
189190

191+
/// <summary>
192+
/// Release the system handle. If the handle has the HANDLE_FLAG_PROTECT_FROM_CLOSE attribute, the operation fails.<br/>
193+
/// ! WARNING !<br/>
194+
/// If the handle or a duplicate is in use by a driver or other kernel-level software, a function that accesses the now-invalid handle will cause a stopcode (AKA Blue Screen Of Death).
195+
/// </summary>
196+
/// <remarks>
197+
/// See Raymond Chen's devblog article <see href="https://devblogs.microsoft.com/oldnewthing/20070829-00/?p=25363">"Kernel handles are not reference-counted"</see>.
198+
/// </remarks>
199+
/// <exception cref="Win32Exception">Failed to open process to duplicate and close object handle.</exception>
200+
public bool CloseSourceHandle() => CloseSourceHandle(false);
201+
190202
/// <summary>
191203
/// Release the system handle.<br/>
192204
/// ! WARNING !<br/>
193205
/// If the handle or a duplicate is in use by a driver or other kernel-level software, a function that accesses the now-invalid handle will cause a stopcode (AKA Blue Screen Of Death).
194206
/// </summary>
207+
/// <param name="removeCloseProtection">Some handles have the HANDLE_FLAG_PROTECT_FROM_CLOSE attribute. In this case, the attribute must be removed for the handle to be closed. Otherwise, the operation will fail. This parameter is made available to allow</param>
195208
/// <remarks>
196209
/// See Raymond Chen's devblog article <see href="https://devblogs.microsoft.com/oldnewthing/20070829-00/?p=25363">"Kernel handles are not reference-counted"</see>.
197210
/// </remarks>
198211
/// <exception cref="Win32Exception">Failed to open process to duplicate and close object handle.</exception>
199-
public bool CloseSourceHandle()
212+
public bool CloseSourceHandle(bool removeCloseProtection)
200213
{
201214
try
202215
{
216+
if (removeCloseProtection
217+
&& ((SysHandleEx.HandleAttributes & Kernel32.HandleFlags.HANDLE_FLAG_PROTECT_FROM_CLOSE) is not 0)
218+
&& !SetHandleInformation(this, (uint)HANDLE_FLAGS.HANDLE_FLAG_PROTECT_FROM_CLOSE, 0))
219+
{
220+
Win32ErrorCode err = (Win32ErrorCode)Marshal.GetLastPInvokeError();
221+
throw new PInvoke.Win32Exception(err, "Failed to remove HANDLE_FLAG_PROTECT_FROM_CLOSE attribute; " + err.GetMessage());
222+
}
223+
203224
HANDLE rawHProcess;
204225
using SafeProcessHandle hProcess = new(
205226
!(rawHProcess = OpenProcess(PROCESS_ACCESS_RIGHTS.PROCESS_DUP_HANDLE, true, ProcessId)).IsNull

0 commit comments

Comments
 (0)