Для определенной задачи мне требуется перечислить все дескрипторы в системе. Лучший подход, который я нашел до сих пор, — это использование недостаточно документированногоNtQuerySystemInformation
с флагом SystemHandleInformation
для параметра класса.
Пока все хорошо. Однако, если запустить его в 32-битном режиме на 64-битной Windows, необходимая структура выглядит следующим образом:
// 32-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
public uint ProcessID;
public byte ObjectTypeNumber;
public byte Flags;
public ushort Handle;
public uint Object_Pointer;
public UInt32 GrantedAccess;
}
И для 64-битной Windows (x64, я не тестировал Itanium, надеюсь, не отличается...), структура выглядит следующим образом:
// 64-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
public int Reserved; // unknown, no documentation found
public uint ProcessID;
public byte ObjectTypeNumber;
public byte Flags;
public ushort Handle;
public long Object_Pointer;
public UInt32 GrantedAccess;
}
Теперь я должен изменить Object_Pointer
на IntPtr
. На мгновение я надеялся, что смогу сделать то же самое с ProcessId
, там была ссылка, в которой говорилось, что это на самом деле HANDLE
, который на самом деле является 64-битным значением. Однако Reserved
всегда равен нулю, поэтому я не могу объединить его в IntPtr
таким же образом.
Вероятно, это не единственный сценарий, в котором это происходит. Я ищу наилучший способ справиться с такими различиями:
#if WIN32
(используется внутри исходного кода IntPtr) не будет работать здесь, если я не захочу поддерживать отдельные двоичные файлы., если IntPtr.Size ==4
в коде. Это работает для внешних функций, но плохо работает с типами.GetType
, но я не уверен, к чему это приведет (может помочь с маршаллингом?).Ни один из них не кажется идеальным, но до сих пор единственным надежным способом, кажется, является наполнение моей системы операторами if IsWin64()
. Я хотел бы услышать лучшие подходы, чем мои.