@@ -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