Last active
January 31, 2025 21:17
-
-
Save santisq/28b79c0ae6b9fc974772c04e41ba6c32 to your computer and use it in GitHub Desktop.
some thing about handles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Runtime.InteropServices; | |
namespace HandleStuff | |
{ | |
public class SystemHandle | |
{ | |
private readonly SYSTEM_HANDLE _handle; | |
private readonly string _type; | |
public string TypeName | |
{ | |
get { return _type; } | |
} | |
public IntPtr Object | |
{ | |
get { return _handle.Object; } | |
} | |
public IntPtr UniqueProcessId | |
{ | |
get { return _handle.UniqueProcessId; } | |
} | |
public IntPtr HandleValue | |
{ | |
get { return _handle.HandleValue; } | |
} | |
public uint GrantedAccess | |
{ | |
get { return _handle.GrantedAccess; } | |
} | |
public ushort ObjectTypeIndex | |
{ | |
get { return _handle.ObjectTypeIndex; } | |
} | |
public uint HandleAttributes | |
{ | |
get { return _handle.HandleAttributes; } | |
} | |
internal SystemHandle(string type, SYSTEM_HANDLE handle) | |
{ | |
_type = type; | |
_handle = handle; | |
} | |
} | |
internal enum OBJECT_INFORMATION_CLASS | |
{ | |
ObjectTypeInformation = 2 | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
internal struct PUBLIC_OBJECT_TYPE_INFORMATION | |
{ | |
internal UNICODE_STRING TypeName; | |
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)] | |
internal uint[] Reserved; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
internal struct UNICODE_STRING | |
{ | |
internal ushort Length; | |
internal ushort MaximumLength; | |
internal IntPtr Buffer; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
internal struct SYSTEM_HANDLE | |
{ | |
internal IntPtr Object; | |
internal IntPtr UniqueProcessId; | |
internal IntPtr HandleValue; | |
internal uint GrantedAccess; | |
internal ushort CreatorBackTraceIndex; | |
internal ushort ObjectTypeIndex; | |
internal uint HandleAttributes; | |
internal uint Reserved; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
internal struct SYSTEM_HANDLE_INFORMATION_EX | |
{ | |
internal UIntPtr HandleCount; | |
internal UIntPtr Reserved; | |
internal SYSTEM_HANDLE Handles; | |
} | |
internal enum SYSTEM_INFORMATION_CLASS | |
{ | |
SystemExtendedHandleInformation = 64 | |
} | |
public static class Native | |
{ | |
[DllImport("ntdll.dll")] | |
private static extern uint NtQuerySystemInformation( | |
[In] SYSTEM_INFORMATION_CLASS SystemInformationClass, | |
[Out] IntPtr SystemInformation, | |
[In] int SystemInformationLength, | |
[Out] out int ReturnLength); | |
[DllImport("ntdll.dll")] | |
private static extern uint RtlNtStatusToDosError( | |
[In] uint Status); | |
[DllImport("ntdll.dll")] | |
private static extern uint NtQueryObject( | |
[In] IntPtr Handle, | |
[In] OBJECT_INFORMATION_CLASS ObjectInformationClass, | |
[Out] IntPtr ObjectInformation, | |
[In] int ObjectInformationLength, | |
[Out] out int ReturnLength); | |
public static SystemHandle[] GetSystemHandles() | |
{ | |
List<SystemHandle> handles; | |
IntPtr sysInfo = IntPtr.Zero; | |
try | |
{ | |
sysInfo = GetSysHandleInfo(); | |
SYSTEM_HANDLE_INFORMATION_EX handleInfo = Marshal | |
.PtrToStructure<SYSTEM_HANDLE_INFORMATION_EX>(sysInfo); | |
IntPtr handlesPtr = IntPtr.Add( | |
sysInfo, | |
Marshal.OffsetOf<SYSTEM_HANDLE_INFORMATION_EX>("Handles").ToInt32()); | |
uint handleCount = handleInfo.HandleCount.ToUInt32(); | |
int handleSize = Marshal.SizeOf<SYSTEM_HANDLE>(); | |
handles = new List<SystemHandle>((int)handleCount); | |
for (int i = 0; i < handleCount; i++) | |
{ | |
IntPtr handlePtr = IntPtr.Add(handlesPtr, i * handleSize); | |
SYSTEM_HANDLE handle = Marshal.PtrToStructure<SYSTEM_HANDLE>(handlePtr); | |
handles.Add(new SystemHandle(GetHandleTypeName(handle.HandleValue), handle)); | |
} | |
} | |
finally | |
{ | |
if (sysInfo != IntPtr.Zero) | |
{ | |
Marshal.FreeHGlobal(sysInfo); | |
} | |
} | |
return handles.ToArray(); | |
} | |
private static IntPtr GetSysHandleInfo() | |
{ | |
int size = 512; | |
IntPtr sysInfo = IntPtr.Zero; | |
while (true) | |
{ | |
if (sysInfo != IntPtr.Zero) | |
{ | |
Marshal.FreeHGlobal(sysInfo); | |
} | |
sysInfo = Marshal.AllocHGlobal(size); | |
uint status = NtQuerySystemInformation( | |
SYSTEM_INFORMATION_CLASS.SystemExtendedHandleInformation, | |
sysInfo, | |
size, | |
out size); | |
if (status == 0) | |
{ | |
break; | |
} | |
if (status != 0xc0000004) | |
{ | |
throw new Win32Exception((int)RtlNtStatusToDosError(status)); | |
} | |
size *= 2; | |
} | |
return sysInfo; | |
} | |
private static string GetHandleTypeName(IntPtr handle) | |
{ | |
int size = 512; | |
IntPtr objectInfoBuffer = IntPtr.Zero; | |
try | |
{ | |
while (true) | |
{ | |
if (objectInfoBuffer != IntPtr.Zero) | |
{ | |
Marshal.FreeHGlobal(objectInfoBuffer); | |
} | |
objectInfoBuffer = Marshal.AllocHGlobal(size); | |
uint status = NtQueryObject( | |
handle, | |
OBJECT_INFORMATION_CLASS.ObjectTypeInformation, | |
objectInfoBuffer, | |
size, | |
out size); | |
if (status == 0) | |
{ | |
PUBLIC_OBJECT_TYPE_INFORMATION info = Marshal | |
.PtrToStructure<PUBLIC_OBJECT_TYPE_INFORMATION>(objectInfoBuffer); | |
if (info.TypeName.Buffer == IntPtr.Zero) | |
{ | |
return string.Empty; | |
} | |
return Marshal.PtrToStringUni(info.TypeName.Buffer, info.TypeName.Length / 2); | |
} | |
if (status != 0xc0000004) | |
{ | |
return string.Empty; | |
} | |
size *= 2; | |
} | |
} | |
finally | |
{ | |
if (objectInfoBuffer != IntPtr.Zero) | |
{ | |
Marshal.FreeHGlobal(objectInfoBuffer); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment