NtQuerySystemInformation API适用于32位但不适用于64位? [英] NtQuerySystemInformation API Works on 32bit but not on 64bits?

查看:199
本文介绍了NtQuerySystemInformation API适用于32位但不适用于64位?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用API​​ NtQuerySystemInformation来检索SystemHandleInformation。

到目前为止,当我在32位操作系统中运行代码时,它的工作正常,但是当我在64位操作系统中运行代码时,我会发现无效数据在目的地指针中



 公共 声明自动功能 NtQuerySystemInformation  Lib     ntdll.dll ByVal  SystemInformationClass 正如 整数 ByVal  SystemInformation  As   IntPtr  ByVal  SystemInformationLength  As  < span class =code-keyword>整数, ByRef  returnLength 作为 整数正如  UInteger  

' 初始长度和缓冲区
Dim retLength As 整数 = 512
Dim lpBufferHandles As IntPtr
' 句柄指针
Dim 句柄作为 SYSTEM_HANDLE_INFORMATION()

' 分配初始值512字节并调用...
lpBufferHandles = Marsha l.AllocHGlobal(retLength)
NtQuerySystemInformation(SystemHandleInformation,lpBufferHandles,retLength,retLength)

' 释放缓冲区并调整大小,然后再次调用函数。
Marshal.FreeHGlobal(lpBufferHandles)
lpBufferHandles = Marshal.AllocHGlobal(retLength)
NtQuerySystemInformation(SystemHandleInformation,lpBufferHandles,retLength ,retLength

Dim totalHandles as 整数 = Marshal.ReadInt32(lpBufferHandles)

对于 X As 整数 = 0 m_totalHandles - 1
句柄= DirectCast (Marshal.PtrToStructure( IntPtr (lpBufferHandles.ToInt32 + 4 +( 16 * X)),句柄。[ GetType ]()),SYSTEM_HANDLE_INFORMATION)
Debug.WriteLine( 找到PID {1}的句柄类型{0}。,Handle.ObjectTypeNumber,Handle.ProcessID)
下一步





这里是SYSTEM_HANDLE_INFORMATION结构

< StructLayout(LayoutKind.Sequential)GT; 结构 SYSTEM_HANDLE_INFORMATION 
公共 ProcessID As 整数
公共 ObjectTypeNumber As 字节
公开标志 As 字节
公开句柄 As UShort
公共 Object_Pointer As 整数
公开 GrantedAccess As 整数
结束 结构





我目前正在运行Windows 7 64位,所以我通常做的是将CPU设置为AnyCPU,无论如何,当我为x86编译这段代码时它正确运行并返回正确的数据,但是当我编译它为x64它返回所有类型的无效细节(错误的数据)。



到目前为止我无法理解什么是错误,任何人都可以帮助我吗?

作为一个补充信息,如果我查询Handle的结构大小,它们是相同的,在两种情况下,但是buffersize,在这种情况下lpBufferHandles非常不同,在x86和58k中大约37k在x64 ...所以,看起来它的返回细节是一些其他结构左右?

解决方案

好吧,我要回答自己,因为这可能不是完美的解决方案,似乎在32位和64位上工作。



 公开 功能 GetAllHandles(可选  ByVal  PID  As  整数 =  0 作为列表(  HandleInfo)
Dim nCurrentLength 作为 整数 = 0
Dim nHandleInfoSize As 整数 =& H10000
Dim lpHandle 作为 IntPtr = IntPtr .Zero
Dim lpBufferHandles As IntPtr = Marshal.AllocHGlobal(nHandleInfoSize)

NtQuerySystemInformation(SystemHandleInformation,lpBufferHandles,nHandleInfoSize,nCurrentLength)= STATUS_INFO_LENGTH_MISMATCH
nHandleInfoSize = nCurrentLength
Marshal.FreeHGlobal(lpBufferHandles)
lpBufferHandles = Marshal.AllocHGlobal(nCurrentLength)
结束

Dim lHandleCount As Long = 0
如果 Is64Bits()那么
lHandleCount = Marshal.ReadInt64( lpBufferHandles)
lpHandle = IntPtr (lpBufferHandles.ToInt64()+ 8
其他
lHandleCount = Marshal.ReadInt32(lpBufferHandles)
lpHandle = IntPtr (lpBufferHandles.ToInt32()+ 4
结束 如果

Dim shHandle 作为 SYSTEM_HANDLE_INFORMATION
Dim HandlesInfos 作为 列表( HandleInfo)

对于 lIndex 作为 = 0 lHandleCount - 1
shHandle = SYSTEM_HANDLE_INFORMATION()
如果 Is64Bits()然后
lpHandle = IntPtr (lpHandle.ToInt64()+ Marshal.SizeOf(shHandle)+ 8
shHandle = DirectCast (Marshal.PtrToStructure(lpHandle,shHandle。[ GetType ]()),SYSTEM_HANDLE_INFORMATION)
否则
lpHandle = IntPtr (lpHandle.ToInt32()+ Marshal.SizeOf(shHandle))
shHandle = DirectCast (Marshal.PtrToStructure(lHHandle,shHandle。[ GetType ]()),SYSTEM_HANDLE_INFORMATION)
End 如果
如果 PID = 0 OrElse PID = shHandle.ProcessID 然后
HandlesInfos.Add(RetrieveObject(shHandle))
结束 如果
下一步

CloseProcessForHandle()
Marshal.FreeHGlobal(lpBufferHandles)
返回 HandlesInfos
结束 功能





正如您在上面的代码中所注意到的,它使用了一个is64Bits函数,它充当一个标志,然后根据它移动指针,因为它似乎IntPtr的大小不同,32位是4字节,64位是8字节。



希望这对其他用途也有帮助。


im using the API NtQuerySystemInformation to retrieve SystemHandleInformation.
So far, its working perfectly when i run the code in a 32bit OS, but when i run the code in a 64bit OS i eget invalid data in the destination pointer

Public Declare Auto Function NtQuerySystemInformation Lib "ntdll.dll" (ByVal SystemInformationClass As Integer, ByVal SystemInformation As IntPtr, ByVal SystemInformationLength As Integer, ByRef returnLength As Integer) As UInteger

'Initial Length and buffer
Dim retLength As Integer = 512
Dim lpBufferHandles As IntPtr
'Handle Pointer
Dim Handle As New SYSTEM_HANDLE_INFORMATION()

'Allocate initial 512 bytes and call...
lpBufferHandles = Marshal.AllocHGlobal(retLength)
NtQuerySystemInformation(SystemHandleInformation, lpBufferHandles, retLength, retLength)

'Free buffer and resize, then call function again.
Marshal.FreeHGlobal(lpBufferHandles)
lpBufferHandles = Marshal.AllocHGlobal(retLength)
NtQuerySystemInformation(SystemHandleInformation, lpBufferHandles, retLength, retLength

Dim totalHandles as integer = Marshal.ReadInt32(lpBufferHandles)

For X As Integer = 0 To m_totalHandles - 1
  Handle = DirectCast(Marshal.PtrToStructure(New IntPtr(lpBufferHandles.ToInt32 + 4 + (16 * X)), Handle.[GetType]()), SYSTEM_HANDLE_INFORMATION)
  Debug.WriteLine("Found handle type {0} for PID {1}.", Handle.ObjectTypeNumber, Handle.ProcessID)
Next



and here is the SYSTEM_HANDLE_INFORMATION structure

<StructLayout(LayoutKind.Sequential)> Structure SYSTEM_HANDLE_INFORMATION
  Public ProcessID As Integer
  Public ObjectTypeNumber As Byte
  Public Flags As Byte
  Public Handle As UShort
  Public Object_Pointer As Integer
  Public GrantedAccess As Integer
End Structure



Im currently running Windows 7 64 bit, so what i usually do is set CPU to AnyCPU, regardless of this, when i compile this piece of code for x86 it runs correctly and returns correct data, but when i compile it for x64 it returns all sort of invalid details (wrong data).

So far i wasn't able to understand what is wrong, could anyone help me?
As an added information, if i query the struct size of "Handle" they are the same, in both cases, but the buffersize, in this case lpBufferHandles is very different, around 37k in x86 and 58k in x64 ... so, it looks like its returning details is some other structure or so?

解决方案

Well, im gonna answer myself, as this might not be the "perfect" solution, it seems to be working both on 32 and 64 bits.

Public Function GetAllHandles(Optional ByVal PID As Integer = 0) As List(Of HandleInfo)
  Dim nCurrentLength As Integer = 0
  Dim nHandleInfoSize As Integer = &H10000
  Dim lpHandle As IntPtr = IntPtr.Zero
  Dim lpBufferHandles As IntPtr = Marshal.AllocHGlobal(nHandleInfoSize)

  While NtQuerySystemInformation(SystemHandleInformation, lpBufferHandles, nHandleInfoSize, nCurrentLength) = STATUS_INFO_LENGTH_MISMATCH
    nHandleInfoSize = nCurrentLength
    Marshal.FreeHGlobal(lpBufferHandles)
    lpBufferHandles = Marshal.AllocHGlobal(nCurrentLength)
  End While

  Dim lHandleCount As Long = 0
  If Is64Bits() Then
    lHandleCount = Marshal.ReadInt64(lpBufferHandles)
    lpHandle = New IntPtr(lpBufferHandles.ToInt64() + 8)
  Else
    lHandleCount = Marshal.ReadInt32(lpBufferHandles)
    lpHandle = New IntPtr(lpBufferHandles.ToInt32() + 4)
  End If

  Dim shHandle As SYSTEM_HANDLE_INFORMATION
  Dim HandlesInfos As New List(Of HandleInfo)

  For lIndex As Long = 0 To lHandleCount - 1
    shHandle = New SYSTEM_HANDLE_INFORMATION()
    If Is64Bits() Then
      lpHandle = New IntPtr(lpHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8)
      shHandle = DirectCast(Marshal.PtrToStructure(lpHandle, shHandle.[GetType]()), SYSTEM_HANDLE_INFORMATION)
    Else
      lpHandle = New IntPtr(lpHandle.ToInt32() + Marshal.SizeOf(shHandle))
      shHandle = DirectCast(Marshal.PtrToStructure(lpHandle, shHandle.[GetType]()), SYSTEM_HANDLE_INFORMATION)
    End If
    If PID = 0 OrElse PID = shHandle.ProcessID Then
      HandlesInfos.Add(RetrieveObject(shHandle))
    End If
  Next

  CloseProcessForHandle()
  Marshal.FreeHGlobal(lpBufferHandles)
  Return HandlesInfos
End Function



As you can notice in the above code, it uses a is64Bits function, which act as a flag and then move the pointers according, as it seems that the IntPtr has not the same size, in 32bits its 4 bytes and in 64bits its 8 bytes long.

Hope this does help other uses as well.


这篇关于NtQuerySystemInformation API适用于32位但不适用于64位?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆