2012-04-03 11 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 बिट विंडोज (64, मैं इटेनियम है, जो मुझे आशा है कि अलग नहीं है का परीक्षण नहीं किया। ..), संरचना इस प्रकार है के रूप में:

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

अब, मैं एक IntPtr को Object_Pointer बदलना चाहिए। मुझे एक पल की उम्मीद थी कि मैं ProcessId के साथ ऐसा ही कर सकता था, एक संदर्भ था कि यह वास्तव में HANDLE था जो वास्तव में 64-बिट मान है। हालांकि, Reserved हमेशा शून्य होता है, इसलिए मैं इसे IntPtr में उसी तरह मर्ज नहीं कर सकता।

शायद यह एकमात्र परिदृश्य नहीं है जहां यह होता है। मैं इस तरह के मतभेदों से निपटने का एक सबसे अच्छा अभ्यास रास्ता तलाश कर रहा हूँ:

  • #if WIN32 की तरह एक निरंतर (IntPtr के संदर्भ स्रोत में आंतरिक रूप से उपयोग) जब तक कि मैं अलग binaries बनाए रखना चाहते हैं यहाँ काम नहीं होगा का उपयोग करना।
  • मैं दो अलग-अलग फ़ंक्शन और दो अलग-अलग structs लिख सकता हूं, एक रैपर बना सकता हूं और कोड में if IntPtr.Size ==4 का उपयोग कर सकता हूं। यह बाहरी कार्यों के लिए काम करता है, लेकिन प्रकारों के साथ अच्छी तरह से काम नहीं करता है।
  • मैं GetType अधिभारित कर सकता हूं लेकिन मुझे यकीन नहीं है कि यह कहां जाता है (मार्शलिंग के साथ मदद कर सकता है?)।
  • और कुछ और? इनमें से

कोई भी आदर्श लगते हैं, लेकिन अब तक, केवल सरल तरीका if IsWin64() बयान के साथ अपने सिस्टम चरबी को हो रहा है। मुझे मेरी तुलना में बेहतर दृष्टिकोण सुनना अच्छा लगेगा।

+3

कोड इस तरह किशोर प्यार की तरह है, एक गलती और आप अपने जीवन के बाकी के लिए इसे समर्थन करेंगे। SysInternals 'Handle.exe उपयोगिता को चलाने के लिए प्रक्रिया वर्ग का उपयोग करें, कम से कम आप इसका समर्थन करने के लिए किसी और को प्राप्त कर सकते हैं। –

+0

@ हंसपैसेंट: एलओएल! हां, मैंने SysInternal की उपयोगिताओं में से किसी का भी उपयोग करने पर विचार किया है, लेकिन नहीं, मेरे परिदृश्य में फिट नहीं है। यद्यपि सूचक के लिए धन्यवाद। – Abel

उत्तर

2

IntPtr के आकार को देखते हुए अलग है, यही कारण है कि निम्नलिखित की कोशिश नहीं:

[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

हां, मैंने कोशिश की कि दो बार, लेकिन यह गलत प्रक्रिया आईडी उत्पन्न करता है। शायद यह एक अच्छा विचार है, फिर मुझे एक विधि 'GetProcessId()' के साथ संरचना का विस्तार करना चाहिए जो अनमास्किंग और प्रोसेस आईडी को चिह्नित करता है। – Abel

+0

@Abel: 64-बिट में, बस 32 बिट्स का अधिकार है।मैं एंडियन मुद्दों के बारे में निश्चित नहीं था :) – leppie

+0

यह प्रक्रिया आईडी 4 (सिस्टम) को '0x0000000400000000' के रूप में प्राप्त करता है, जो बाइट अनुक्रम '00 00 00 00 04 00 00 00' से' 17179869184' है। तो हाँ, अंतहीनता एक मुद्दा है (इस अर्थ में कि प्रमुख आरक्षित शून्य रास्ते में हैं)। '0x0000000400000000 >> 32' 64-बिट मामलों में काम करता है। – Abel

3

यही बात है - सिस्टमहैंडल इनफॉर्मेशन की संरचनाएं आपको केवल 16-बिट पीआईडी ​​देती हैं। आप XPE और उच्चतर पर SystemExtendedHandleInformation का उपयोग कर सकते हैं।

[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