Предпочтительный подход для условной компиляции для 32-битных версий типов по сравнению с 64-битными

Для определенной задачи мне требуется перечислить все дескрипторы в системе. Лучший подход, который я нашел до сих пор, — это использование недостаточно документированного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(). Я хотел бы услышать лучшие подходы, чем мои.

5
задан Jakub Konecki 3 April 2012 в 14:26
поделиться