GetExtendedTcpTable API Part 2

M

Michael M.

Hi all, I am trying to use the GetExtendedTcpTable API function and I having
some problems.

The program generates memory access errors, but not every time I run it
(about 1 n 3 times).

I first tried using StructureToPtr to read the TCP data, but then changed to
reading it 4 bytes at a time which did not make much diffrence in stability.

It does actualy return all the data correctly, but it crashes almost
randomly.

I think the problem might be something to do with the value returned in
dwTcpTableSize because when I check it's value it can be arround 380 when
there are only 4 TCP table records (each of which are 24 bytes long + 4
bytes for item count 96+4 ?).

I have included the whole function below followed by the API declaration. I
have used aliases for some types because it helps me convert the APIs from
MSDN so I have included my imports section.

Please help Thanks,
Michael.

<VB.Net 2005 on XP Pro SP2>

Imports
____________________________________
Imports System.Runtime.InteropServices

'** C++ Conversions Aliases. ***

Imports DWORD = System.UInt32

Imports BOOL = System.Boolean

'********************************


Function
____________________________________
Public Function GetExtendedTCPdata() As Integer

'* Use IP Version 4

Dim AF_INET As Integer = 2

'* Wlll store the TCP TABLE ROW Count.

Dim dwTcpTableSize As DWORD = 0

Dim RetVal As Integer

'* Get The Size of the TCP Table Data

RetVal = GetExtendedTcpTable(IntPtr.Zero, dwTcpTableSize, 1, AF_INET, 5, 0)

'* Create a Buffer

Dim iptrToTcpTableArray As IntPtr =
Marshal.AllocHGlobal(Marshal.SizeOf(dwTcpTableSize))

RetVal = GetExtendedTcpTable(iptrToTcpTableArray, dwTcpTableSize, 1,
AF_INET, 5, 0)

'* Create a List to hold the managed TCP ROWS after

Dim ListOfTcpRows As New List(Of MIB_TCPROW_OWNER_PID)

If RetVal = ERROR_SUCCESS Then

Dim dwTCPRowCount As DWORD



'* Get the total number / count of TCP ROWS.

dwTCPRowCount = Marshal.ReadInt32(iptrToTcpTableArray, 0)

'* Offset for walking through the unmanaged structures

Dim intOffset As Integer = 0

For I As DWORD = 0 To dwTCPRowCount - 1

Dim TCP_ROW As MIB_TCPROW_OWNER_PID ' * Structure 24 Bytes Long

'* Read a sngle data structure from unmanaged memory 4 bytes at a time then
increment offset and loop

With TCP_ROW

..dwState = Marshal.ReadInt32(iptrToTcpTableArray, intOffset + 4)

..dwLocalAddr = Marshal.ReadInt32(iptrToTcpTableArray, intOffset + 8)

..dwLocalPort = Marshal.ReadInt32(iptrToTcpTableArray, intOffset + 12)

..dwRemoteAddr = Marshal.ReadInt32(iptrToTcpTableArray, intOffset + 16)

..dwRemotePort = Marshal.ReadInt32(iptrToTcpTableArray, intOffset + 20)

..dwOwningPid = Marshal.ReadInt32(iptrToTcpTableArray, intOffset + 24)

End With

'* Add the filled TCP ROW into the List.

ListOfTcpRows.Add(TCP_ROW)

'* Increment the byte offset by 24 bytes (1 TCP ROW)

intOffset += 24

Next

End If

'* Free the allocated memory that holds the TCP DATA ROWS

Marshal.FreeHGlobal(iptrToTcpTableArray)

GC.Collect()

'TODO return the data in a generics list

Return 0 ' ListOfTcpRows

End Function

API DECLARATION
________________

Public Declare Unicode Function GetExtendedTcpTable Lib _

"IPHLPAPI.DLL" _

( _

ByVal pTcpTable As IntPtr, _

ByRef pDwSize As DWORD, _

ByVal bOrder As BOOL, _

ByVal ulAf As Integer, _

ByVal TCP_TABLE_CLASS As Integer, _

ByVal Reserved As Integer) As Integer
 
M

Michael M.

Changed dwTcpTableSize from DWORD to Integer, seems stable now, I will leave
it running a while and call that function in a Timer object as a quick test.
 
M

Mattias Sjögren

Dim iptrToTcpTableArray As IntPtr =
Marshal.AllocHGlobal(Marshal.SizeOf(dwTcpTableSize))

Here you're just allocating a 4 byte (= SizeOf(Integer)) buffer. What
you really want is

Dim iptrToTcpTableArray As IntPtr =
Marshal.AllocHGlobal(dwTcpTableSize)


Mattias
 
M

Michael M.

Thanks Mattias,

I Just realised I had made that change allready and that is what solved my
problem not changing it's type as I belive both would allocate 4 bytes. I
had changed it to this:


Dim iptrToTcpTableArray As IntPtr = Marshal.AllocHGlobal((dwTcpTableSize))

but it still important that you pointed it out because I kind of stumbled
upon the fix. Now I have the real reason the code is now stable.

I was confused; so the Marshal.SizeOf just returns the size of the
underlying data type, I guess it makes sense now you point it out. I
probably made the same mistake using StructureToPtr()

:0)

Michael.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top