Skip to content

Commit 7d3ae8e

Browse files
committed
refactor: change Exception types, misc changes in GetSystemHandleInfoEx
1 parent 780275a commit 7d3ae8e

File tree

1 file changed

+18
-20
lines changed

1 file changed

+18
-20
lines changed

deadlock-dotnet-sdk/Domain/NativeMethods.cs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,14 @@ bool Discard(SafeFileHandleEx h)
178178
/// Get a Span of <see cref="SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX"/> via <see cref="NtQuerySystemInformation"/>
179179
/// </summary>
180180
/// <remarks>Heavily influenced by ProcessHacker/SystemInformer</remarks>
181-
private unsafe static Span<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> GetSystemHandleInfoEx()
181+
/// <exception cref="NTStatusException"></exception>
182+
/// <exception cref="Win32Exception"></exception>
183+
internal unsafe static ReadOnlySpan<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> GetSystemHandleInfoEx()
182184
{
183185
const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
184186
const uint PH_LARGE_BUFFER_SIZE = 256 * 1024 * 1024; // 256 Mebibytes
185-
const uint STATUS_INSUFFICIENT_RESOURCES = 0xC000009A;
186-
uint systemInformationLength = (uint)sizeof(SYSTEM_HANDLE_INFORMATION_EX);
187-
SYSTEM_HANDLE_INFORMATION_EX* pSysInfoBuffer = (SYSTEM_HANDLE_INFORMATION_EX*)Marshal.AllocHGlobal(sizeof(SYSTEM_HANDLE_INFORMATION_EX));
187+
uint systemInformationLength = (uint)Marshal.SizeOf<SYSTEM_HANDLE_INFORMATION_EX>();
188+
SYSTEM_HANDLE_INFORMATION_EX* pSysInfoBuffer = (SYSTEM_HANDLE_INFORMATION_EX*)Marshal.AllocHGlobal(Marshal.SizeOf<SYSTEM_HANDLE_INFORMATION_EX>());
188189
uint returnLength = 0;
189190

190191
NTSTATUS status = NtQuerySystemInformation(
@@ -194,9 +195,12 @@ private unsafe static Span<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> GetSystemHandleInf
194195
ReturnLength: ref returnLength
195196
);
196197

197-
for (uint attempts = 0; status == STATUS_INFO_LENGTH_MISMATCH && attempts < 10; attempts++)
198+
for (uint attempts = 0; status.Value == NTSTATUS.Code.STATUS_INFO_LENGTH_MISMATCH && attempts < 10; attempts++)
198199
{
199-
systemInformationLength = returnLength;
200+
/** The value of returnLength depends on how many handles are open.
201+
Handles may be opened or closed before, during, and after this operation, so the return length is rarely correct.
202+
*/
203+
systemInformationLength = (uint)(returnLength * 1.5);
200204
pSysInfoBuffer = (SYSTEM_HANDLE_INFORMATION_EX*)Marshal.ReAllocHGlobal((IntPtr)pSysInfoBuffer, (IntPtr)systemInformationLength);
201205

202206
status = NtQuerySystemInformation(
@@ -207,11 +211,11 @@ ref returnLength
207211
);
208212
}
209213

210-
if (!status.IsSuccessful)
214+
if (status != NTSTATUS.Code.STATUS_SUCCESS)
211215
{
212216
// Fall back to using the previous code that we've used since Windows XP (dmex)
213217
systemInformationLength = 0x10000;
214-
Marshal.FreeHGlobal((IntPtr)pSysInfoBuffer);
218+
//Marshal.FreeHGlobal((IntPtr)pSysInfoBuffer);
215219
pSysInfoBuffer = (SYSTEM_HANDLE_INFORMATION_EX*)Marshal.ReAllocHGlobal((IntPtr)pSysInfoBuffer, (IntPtr)systemInformationLength);
216220

217221
while ((status = NtQuerySystemInformation(
@@ -226,29 +230,23 @@ ref returnLength
226230

227231
// Fail if we're resizing the buffer to something very large.
228232
if (systemInformationLength > PH_LARGE_BUFFER_SIZE)
229-
{
230-
throw new Win32Exception(unchecked((int)STATUS_INSUFFICIENT_RESOURCES));
231-
}
233+
throw new NTStatusException(NTSTATUS.Code.STATUS_BUFFER_OVERFLOW);
232234

233-
pSysInfoBuffer = (SYSTEM_HANDLE_INFORMATION_EX*)Marshal.AllocHGlobal((int)systemInformationLength);
235+
pSysInfoBuffer = (SYSTEM_HANDLE_INFORMATION_EX*)Marshal.ReAllocHGlobal(pv: (IntPtr)pSysInfoBuffer, cb: (IntPtr)systemInformationLength);
234236
}
235237
}
236238

237-
if (!status.IsSuccessful)
239+
if (status != NTSTATUS.Code.STATUS_SUCCESS)
238240
{
239241
Marshal.FreeHGlobal((IntPtr)pSysInfoBuffer);
240-
Marshal.FreeHGlobal((IntPtr)returnLength);
241-
throw new Win32Exception((int)status);
242+
throw new NTStatusException(status);
242243
}
243244

244-
SYSTEM_HANDLE_INFORMATION_EX retVal = *pSysInfoBuffer;
245-
246-
retVal.CheckAccess();
245+
var retVal = (*pSysInfoBuffer).AsSpan();
247246

248247
Marshal.FreeHGlobal((IntPtr)pSysInfoBuffer);
249-
Marshal.FreeHGlobal((IntPtr)returnLength);
250248

251-
return retVal.AsSpan();
249+
return retVal;
252250
}
253251

254252
#endregion Methods

0 commit comments

Comments
 (0)