2012-04-03 13 views
5

システム内のすべてのハンドルを列挙するためには、特定のタスクが必要です。これまでに私が見つけた最良のアプローチは、クラスパラメータにSystemHandleInformationというフラグを付けて、文書化されていないNtQuerySystemInformationを使用しています。32ビット版と64ビット版の条件付きコンパイルの優先アプローチ

これまでのところとても良いです。次のようにしかし、64ビットWindows上で32ビットモードでそれを実行し、必要な構造は、次のとおりです。

// 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;   
} 

、私はIntPtrObject_Pointerを変更する必要があります。私はProcessIdと同じことをすることができる瞬間を望んでいましたが、これは実際にはHANDLEであり、実際には64ビットの値であると言われました。しかし、Reservedは常にゼロですので、同じ方法でIntPtrにマージすることはできません。

これは、これが起こる唯一のシナリオではないでしょう。私は、このような違いに対処するベストプラクティスの方法を探しています:

  • 私は別のバイナリを維持する場合を除き、(のIntPtrの参照元に内部的に使用)#if WIN32のような定数を使用すると、ここでは動作しないでしょう。
  • 2つの異なる関数と2つの異なる構造体を記述し、ラッパーを作成してコード内にif IntPtr.Size ==4を使用することができます。これは外部関数では機能しますが、型ではうまく機能しません。
  • GetTypeをオーバーロードすることはできますが、どこがマーシャリングに役立つのでしょうか?
  • 他に何か?これらの

どれも理想的なようでいませんが、これまでのところ、唯一確実な方法はif IsWin64()文で私のシステムをラードするように思われます。私は私よりも良いアプローチを聞いてみたいと思う。 IntPtrの大きさを考えると

+3

この種のコードは、十代のセックスのような1つのミスであり、あなたがあなたの人生の残りのためにそれをサポートしています。 Processクラスを使用してSysInternalsのHandle.exeユーティリティを実行します。少なくとも、他の人にそれをサポートすることができます。 –

+0

@ HansPassant:LOL!はい、私はSysInternalのユーティリティの誰かを使用することを検討しましたが、いいえ、私のシナリオに合っていません。しかし、ポインタをありがとう。 – Abel

答えて

2

は異なり、次のことをしようとしない理由:

[StructLayout(LayoutKind.Sequential, Pack=1)] 
public struct SYSTEM_HANDLE_INFORMATION 
{ 
    public IntPtr ProcessID;    // mask with 0xffffffff 
    public byte ObjectTypeNumber;  
    public byte Flags;     
    public ushort Handle;    
    public IntPtr Object_Pointer;   // again good for 32/64bit 
    public UInt32 GrantedAccess;   
} 

これは、32ビットおよび64ビットの両方の未変更のために働く必要があります。

+0

はい、私は数回試みましたが、間違ったProcessIDが生成されます。たぶん良いアイデアかもしれませんが、私はunmaskingを行いProcessIDをprivateにマークするメソッド 'GetProcessId()'を使って構造体を拡張する必要があります。 – Abel

+0

@Abel:64ビットでは、32ビットだけ右にシフトします。私はエンディアンの問題については分かりませんでした:) – leppie

+0

バイトシーケンス '00 00 00 00 04 00 00 00'から、プロセスID 4(システム)が '0x0000000400000000'、つまり' 17179869184'になりました。そう、はい、エンディアンは問題です(先行予約されたゼロが途中にあるという意味で)。 '0x0000000400000000 >> 32'は64ビットの場合に機能します。 – Abel

3

SystemHandleInformationの構造は16ビットのPIDのみを提供します。 SystemExtendedHandleInformationは、XP以上で使用できます。

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
    public class SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX 
    { 
    public IntPtr Object; 
    public IntPtr UniqueProcessId; 
    public IntPtr HandleValue; 
    public uint GrantedAccess; 
    public ushort CreatorBackTraceIndex; 
    public ushort ObjectTypeIndex; 
    public uint HandleAttributes; 
    public uint Reserved; 
    } 

    internal enum SYSTEM_INFORMATION_CLASS 
    { 
    SystemBasicInformation = 0, 
    SystemPerformanceInformation = 2, 
    SystemTimeOfDayInformation = 3, 
    SystemProcessInformation = 5, 
    SystemProcessorPerformanceInformation = 8, 
    SystemHandleInformation = 16, 
    SystemInterruptInformation = 23, 
    SystemExceptionInformation = 33, 
    SystemRegistryQuotaInformation = 37, 
    SystemLookasideInformation = 45, 
    SystemExtendedHandleInformation = 64, 
    } 


[DllImport("ntdll.dll", CharSet=CharSet.Auto)] 
private static extern int NtQuerySystemInformation(int InfoType, IntPtr lpStructure, int StructSize, out int returnLength); 



    public static void Main(string[] args) 
    { 
    Console.WriteLine(Environment.Is64BitProcess ? "x64" : "x32"); 
    Console.WriteLine(); 

    var infoSize = Marshal.SizeOf(typeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX)); 

    Console.WriteLine("sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX): {0}", infoSize); 
    int allSize = 1000 * infoSize; 
    var buffer = Marshal.AllocHGlobal(allSize); 
    var status = NtQuerySystemInformation((int)SYSTEM_INFORMATION_CLASS.SystemExtendedHandleInformation, buffer, allSize, out allSize); 
    Console.WriteLine("status: {0:x}, return len: {1}", status, allSize); 

    if (status != 0) 
    { 
     allSize += 40 * infoSize; 
     Marshal.FreeHGlobal(buffer); 
     buffer = Marshal.AllocHGlobal(allSize); 
     status = NtQuerySystemInformation((int)SYSTEM_INFORMATION_CLASS.SystemExtendedHandleInformation, buffer, allSize, out allSize); 
     Console.WriteLine("status: {0:x}, return len: {1}", status, allSize); 
    } 

    Console.WriteLine(); 
    var info = new SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX(); 
    //for (var i = 0; i < allSize; i += infoSize) 
    for (var i = 0; i < Math.Min(allSize, 20 * infoSize); i+= infoSize) // for testing purpose only 20 
    { 
     Marshal.PtrToStructure(IntPtr.Add(buffer, i), info); 
     Console.WriteLine("{0,16:x}, {1,16:x}, {2,16:x}, {3,6:x}, {4,8:x}", info.Object.ToInt64(), info.UniqueProcessId.ToInt64(), info.HandleValue.ToInt64(), info.GrantedAccess, info.HandleAttributes); 
    } 
    Marshal.FreeHGlobal(buffer); 
    } 

出力:

x32 

sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX): 28 
status: c0000004, return len: 1850052 
status: 0, return len: 1850052 

      10219,    0,   6729b30,  4, 1fffff 
       0,    0,    dfa0,  4, 2001f 
       0,    0,    8eb0,  4, f000f 
       0,    0,    fca0,  4,  0 
       0,    0,   225b0,  4, 20019 
       0,    0,   98210,  4, f003f 
       0,    0,   6758e60,  4, 1f0001 
       0,    0,   98040,  4, 2001f 
       0,    0,   67534e0,  4, 1f0001 
       0,    0,   9c560,  4, 2001f 
       0,    0,   6834620,  4, 1fffff 
       0,    0,   99250,  4, f003f 
       0,    0,   9a7c0,  4, f003f 
       0,    0,   95380,  4, f003f 
       0,    0,   62d80,  4, f003f 
       0,    0,   15e580,  4, 20019 
       0,    0,   6f3b940,  4,  2a 
       0,    0,   20da30,  4,  e 
       0,    0,   7b07a0,  4,  10 
       0,    0,   9af83a0,  4, 20019 

x64 

sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX): 40 
status: c0000004, return len: 2647576 
status: 0, return len: 2647856 

      10294,    0, fffffa8006729b30,  4,  4 
    70000001fffff,    0, fffff8a00000dfa0,  4,  8 
    2300000002001f,    0, fffff8a000008eb0,  4,  c 
    30000000f000f,    0, fffff8a00000fca0,  4,  10 
    23000000000000,    0, fffff8a0000225b0,  4,  14 
    23000000020019,    0, fffff8a000098210,  4,  18 
    230000000f003f,    0, fffffa8006758e60,  4,  1c 
    240000001f0001,    0, fffff8a000098040,  4,  20 
    2300000002001f,    0, fffffa80067534e0,  4,  24 
    240000001f0001,    0, fffff8a00009c560,  4,  28 
    2300000002001f,    0, fffffa8006834620,  4,  2c 
    80000001fffff,    0, fffff8a000099250,  4,  30 
    230000000f003f,    0, fffff8a00009a7c0,  4,  34 
    230000000f003f,    0, fffff8a000095380,  4,  38 
    230000000f003f,    0, fffff8a000062d80,  4,  3c 
    230000000f003f,    0, fffff8a00015e580,  4,  40 
    23000000020019,    0, fffffa8006f3b940,  4,  44 
    700000000002a,    0, fffff8a00020da30,  4,  48 
    500000000000e,    0, fffff8a0007b07a0,  4,  4c 
    23000000000010,    0, fffff8a009af83a0,  4,  50 
+1

それは単に優れています。ビットネスを処理する一般的により良いアプローチについて質問していましたが、私のより具体的な質問に対する回答を受け取りました。私は、拡張バージョンを認識していなかった、ありがとう! – Abel

関連する問題