Click here to Skip to main content
15,881,084 members
Please Sign up or sign in to vote.
5.00/5 (2 votes)
See more:
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

VB
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
VB
<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?
Posted
Comments
Sandeep Mewara 26-Jan-11 3:56am    
Nicely formed Q!

1 solution

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

VB
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.
 
Share this answer
 
Comments
uRLuVRJoNNeL 31-Mar-15 12:06pm    
im interested in your code , i'm having a problem about my app

i am currently developing a program that can backup files
but my problem now is whenever i try to copy those Handled/Locked Files
there is an error and it won't copied.

the solution for me is to unlock the file by Closing the Handle of the Process to the File.

I think it will work but i need to determine first what process(s) handled the file
then when i app found out that is locked by the target Process(s)
Those handles to the file will be forced closed by using win32 API
Idranel 25-May-17 5:37am    
I don't think Marshal.ReadInt64(lpBufferHandles) return the number of handles. In my case it was equal to 17179907089, that resulted in overflow.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900