Skip to content

Commit fb7a9ee

Browse files
committed
tmp
1 parent 1f1dc4f commit fb7a9ee

File tree

7 files changed

+386
-175
lines changed

7 files changed

+386
-175
lines changed

deadlock-dotnet-sdk/DeadLock.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ public DeadLock(bool rethrowExceptions)
4242
/// <returns>The FileLocker object that contains a List of Process objects that are locking a file</returns>
4343
public FileLocker FindLockingProcesses(string filePath)
4444
{
45-
FileLocker fileLocker = new(filePath,
45+
return new(filePath,
4646
NativeMethods.FindLockingProcesses(filePath, RethrowExceptions).ToList());
47-
return fileLocker;
4847
}
4948

5049
/// <summary>
@@ -315,7 +314,7 @@ public void UnlockEx(FileLockerEx fileLocker)
315314
if (h.IsClosed && h.IsInvalid) continue;
316315
try
317316
{
318-
h.UnlockSystemHandle();
317+
h.CloseSourceHandle();
319318
}
320319
catch (Exception) when (!RethrowExceptions) { }
321320
}
@@ -350,7 +349,7 @@ await Task.Run(() =>
350349
if (h.IsClosed && h.IsInvalid) continue;
351350
try
352351
{
353-
h.UnlockSystemHandle();
352+
h.CloseSourceHandle();
354353
}
355354
catch (Exception) when (!RethrowExceptions) { }
356355
}
@@ -372,7 +371,7 @@ await Task.Run(() =>
372371
if (h.IsClosed && h.IsInvalid) continue;
373372
try
374373
{
375-
h.UnlockSystemHandle();
374+
h.CloseSourceHandle();
376375
}
377376
catch (Exception) when (!RethrowExceptions) { }
378377
}

deadlock-dotnet-sdk/Domain/FileLockerEx.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ public FileLockerEx(string path, HandlesFilter filter, bool rethrowExceptions, o
7474
/// <summary>
7575
/// Filters for <see cref="NativeMethods.FindLockingHandles(string?, HandlesFilter)"/>
7676
/// </summary>
77-
/// TODO: rename to HandlesFilter
7877
[Flags]
7978
public enum HandlesFilter
8079
{

deadlock-dotnet-sdk/Domain/NativeMethods.SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX.cs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using Windows.Win32.Foundation;
66
using Windows.Win32.System.WindowsProgramming;
77
using static Windows.Win32.PInvoke;
8-
using NTSTATUS = PInvoke.NTSTATUS;
98

109
// Re: StructLayout
1110
// "C#, Visual Basic, and C++ compilers apply the Sequential layout value to structures by default."
@@ -20,8 +19,6 @@ namespace deadlock_dotnet_sdk.Domain;
2019

2120
internal static partial class NativeMethods
2221
{
23-
private static bool IsSuccessful(this NTSTATUS status) => status.Severity == NTSTATUS.SeverityCode.STATUS_SEVERITY_SUCCESS;
24-
private static bool NT_SUCCESS(this NTSTATUS status) => status.Severity == NTSTATUS.SeverityCode.STATUS_SEVERITY_SUCCESS;
2522
private const uint PH_LARGE_BUFFER_SIZE = int.MaxValue;
2623
private static List<ObjectTypeInformation>? objectTypes;
2724
private static List<ObjectTypeInformation> ObjectTypes => objectTypes ??= ObjectTypesInformationBuffer.PhEnumObjectTypes().ToList();
@@ -31,15 +28,13 @@ internal static partial class NativeMethods
3128
/// </summary>
3229
private static uint? GetObjectTypeNumber(string typeName)
3330
{
34-
Version WINDOWS_8_1 = new(6, 2);
35-
Version WindowsVersion = Environment.OSVersion.Version;
3631
uint objectIndex = uint.MaxValue;
3732

3833
for (int i = 0; i < ObjectTypes.Count; i++)
3934
{
4035
if (typeName.Equals(ObjectTypes[i].TypeName, StringComparison.OrdinalIgnoreCase))
4136
{
42-
if (WindowsVersion >= WINDOWS_8_1)
37+
if (OperatingSystem.IsWindowsVersionAtLeast(6, 3))
4338
objectIndex = ObjectTypes[i].TypeIndex;
4439
else
4540
objectIndex = (uint)(i + 2);
@@ -57,13 +52,11 @@ internal static partial class NativeMethods
5752
/// </summary>
5853
private static string GetObjectTypeName(int typeIndex)
5954
{
60-
Version WINDOWS_8_1 = new(6, 2);
61-
Version WindowsVersion = Environment.OSVersion.Version;
6255
string objectTypeName = "";
6356

6457
for (int i = 0; i < ObjectTypes.Count; i++)
6558
{
66-
if (WindowsVersion >= WINDOWS_8_1)
59+
if (OperatingSystem.IsWindowsVersionAtLeast(6, 3))
6760
{
6861
if (typeIndex == ObjectTypes[i].TypeIndex)
6962
objectTypeName = ObjectTypes[i].TypeName;
@@ -254,30 +247,28 @@ public unsafe void ReAllocate(uint lengthInBytes)
254247
/// <exception cref="NTStatusException"></exception>
255248
public static unsafe ObjectTypesInformationBuffer PhEnumObjectTypes()
256249
{
257-
NTSTATUS status;
258-
ObjectTypesInformationBuffer buffer;
250+
Windows.Win32.Foundation.NTSTATUS status;
251+
using ObjectTypesInformationBuffer buffer = new(0x1000);
259252
uint returnLength;
260253

261-
buffer = new(0x1000);
262-
263254
while ((status = NtQueryObject(
264255
null,
265256
OBJECT_INFORMATION_CLASS.ObjectTypesInformation,
266257
(void*)buffer.pointer,
267258
buffer.bytes,
268259
&returnLength
269-
)) == NTSTATUS.Code.STATUS_INFO_LENGTH_MISMATCH)
260+
)) == PInvoke.NTSTATUS.Code.STATUS_INFO_LENGTH_MISMATCH)
270261
{
271262
// Fail if we're resizing the buffer to something very large.
272263
if (returnLength * 1.5 > PH_LARGE_BUFFER_SIZE)
273-
throw new NTStatusException(NTSTATUS.Code.STATUS_INSUFFICIENT_RESOURCES);
264+
throw new NTStatusException(PInvoke.NTSTATUS.Code.STATUS_INSUFFICIENT_RESOURCES);
274265

275266
buffer.ReAllocate((uint)(returnLength * 1.5));
276267
}
277268

278-
if (!status.NT_SUCCESS())
269+
if (!status.IsSuccessful)
279270
{
280-
buffer.Dispose();
271+
// Dispose(or DisposeAsync) is called even if an exception occurs
281272
throw new NTStatusException(status);
282273
}
283274

@@ -300,7 +291,7 @@ public unsafe uint PhGetObjectTypeNumber(string typeName)
300291

301292
if (string.Equals(typeNameSr, typeName, StringComparison.OrdinalIgnoreCase))
302293
{
303-
if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version >= new Version(6, 3))
294+
if (OperatingSystem.IsWindowsVersionAtLeast(6, 3))
304295
{
305296
objectIndex = objectType->TypeIndex;
306297
break;
@@ -315,7 +306,6 @@ public unsafe uint PhGetObjectTypeNumber(string typeName)
315306
objectType = PH_NEXT_OBJECT_TYPE(objectType);
316307
}
317308
}
318-
319309
return objectIndex;
320310
}
321311

@@ -329,7 +319,7 @@ public unsafe uint PhGetObjectTypeNumber(string typeName)
329319

330320
for (i = 0; i < NumberOfTypes; i++)
331321
{
332-
if (OperatingSystem.IsWindowsVersionAtLeast(6, 2))
322+
if (OperatingSystem.IsWindowsVersionAtLeast(6, 3))
333323
{
334324
if (TypeIndex == objectType->TypeIndex)
335325
{

deadlock-dotnet-sdk/Domain/NativeMethods.cs

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Windows.Win32.System.RestartManager;
77
using Windows.Win32.System.WindowsProgramming;
88
using static deadlock_dotnet_sdk.Domain.FileLockerEx;
9+
using static deadlock_dotnet_sdk.Domain.NativeMethods;
910
using static Windows.Win32.PInvoke;
1011
using NTSTATUS = PInvoke.NTSTATUS;
1112
using Win32Exception = System.ComponentModel.Win32Exception;
@@ -40,85 +41,82 @@ internal static partial class NativeMethods
4041
/// <param name="path">Path to the file</param>
4142
/// <param name="rethrowExceptions">True if inner exceptions should be rethrown, otherwise false</param>
4243
/// <returns>A collection of processes that are locking a file</returns>
43-
internal static IEnumerable<Process> FindLockingProcesses(string path, bool rethrowExceptions)
44+
internal static unsafe IEnumerable<Process> FindLockingProcesses(string path, bool rethrowExceptions)
4445
{
45-
unsafe
46+
using (PWSTR key = new((char*)Marshal.StringToHGlobalUni(Guid.NewGuid().ToString())))
4647
{
47-
using (PWSTR key = new((char*)Marshal.StringToHGlobalUni(Guid.NewGuid().ToString())))
48+
List<Process> processes = new();
49+
50+
// todo: new RmStartSession overload in CsWin32_NativeMethods.cs which can throw a StartSessionException derived from System.ComponentModel.Win32Exception
51+
// Why? <c>new Win32Exception()</c> will get the last PInvoke error code in addition to the system's message for that Win32ErrorCode.
52+
uint res = RmStartSession(out var handle, 0, key);
53+
if (res != 0)
4854
{
49-
List<Process> processes = new();
55+
throw new StartSessionException();
56+
}
5057

51-
// todo: new RmStartSession overload in CsWin32_NativeMethods.cs which can throw a StartSessionException derived from System.ComponentModel.Win32Exception
52-
// Why? <c>new Win32Exception()</c> will get the last PInvoke error code in addition to the system's message for that Win32ErrorCode.
53-
uint res = RmStartSession(out var handle, 0, key);
54-
if (res != 0)
55-
{
56-
throw new StartSessionException();
57-
}
58+
try
59+
{
60+
const int errorMoreData = 234;
61+
uint pnProcInfo = 0;
62+
uint lpdwRebootReasons = RmRebootReasonNone;
63+
64+
string[] resources = { path };
5865

59-
try
66+
// "using" blocks have hidden "finally" blocks which are executed before exceptions leave this context.
67+
using (PWSTR pResources = (char*)Marshal.StringToHGlobalUni(path))
6068
{
61-
const int errorMoreData = 234;
62-
uint pnProcInfo = 0;
63-
uint lpdwRebootReasons = RmRebootReasonNone;
69+
res = RmRegisterResources(handle, new Span<PWSTR>(new PWSTR[] { pResources }), rgApplications: new(), new());
6470

65-
string[] resources = { path };
71+
if (res != 0)
72+
{
73+
throw new RegisterResourceException();
74+
}
75+
76+
res = RmGetList(handle, out var pnProcInfoNeeded, ref pnProcInfo, null, out lpdwRebootReasons);
6677

67-
// "using" blocks have hidden "finally" blocks which are executed before exceptions leave this context.
68-
using (PWSTR pResources = (char*)Marshal.StringToHGlobalUni(path))
78+
if (res == errorMoreData)
6979
{
70-
res = RmRegisterResources(handle, new Span<PWSTR>(new PWSTR[] { pResources }), rgApplications: new(), new());
80+
ReadOnlySpan<RM_PROCESS_INFO> processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
81+
pnProcInfo = pnProcInfoNeeded;
7182

72-
if (res != 0)
83+
fixed (RM_PROCESS_INFO* pProcessInfo = processInfo)
7384
{
74-
throw new RegisterResourceException();
85+
res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, pProcessInfo, out lpdwRebootReasons);
7586
}
76-
77-
res = RmGetList(handle, out var pnProcInfoNeeded, ref pnProcInfo, null, out lpdwRebootReasons);
78-
79-
if (res == errorMoreData)
87+
if (res == 0)
8088
{
81-
ReadOnlySpan<RM_PROCESS_INFO> processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
82-
pnProcInfo = pnProcInfoNeeded;
89+
processes = new List<Process>((int)pnProcInfo);
8390

84-
fixed (RM_PROCESS_INFO* pProcessInfo = processInfo)
85-
{
86-
res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, pProcessInfo, out lpdwRebootReasons);
87-
}
88-
if (res == 0)
91+
for (int i = 0; i < pnProcInfo; i++)
8992
{
90-
processes = new List<Process>((int)pnProcInfo);
91-
92-
for (int i = 0; i < pnProcInfo; i++)
93+
try
9394
{
94-
try
95-
{
96-
processes.Add(Process.GetProcessById((int)processInfo[i].Process.dwProcessId));
97-
}
98-
catch (ArgumentException)
99-
{
100-
if (rethrowExceptions) throw;
101-
}
95+
processes.Add(Process.GetProcessById((int)processInfo[i].Process.dwProcessId));
96+
}
97+
catch (ArgumentException)
98+
{
99+
if (rethrowExceptions) throw;
102100
}
103-
}
104-
else
105-
{
106-
throw new RmListException();
107101
}
108102
}
109-
else if (res != 0)
103+
else
110104
{
111-
throw new UnauthorizedAccessException();
105+
throw new RmListException();
112106
}
113107
}
108+
else if (res != 0)
109+
{
110+
throw new UnauthorizedAccessException();
111+
}
114112
}
115-
finally
116-
{
117-
_ = RmEndSession(handle);
118-
}
119-
120-
return processes;
121113
}
114+
finally
115+
{
116+
_ = RmEndSession(handle);
117+
}
118+
119+
return processes;
122120
}
123121
}
124122

0 commit comments

Comments
 (0)