reactos/dll/win32/iphlpapi/ipstats_reactos.c
Joachim Henze 8898f92574 [0.4.10][IPHLPAPI][TCPIP][IP][LWIP][SDK][PSDK] Port back groundworks for netstat
This fixes:
CORE-15363 'netstat TCP foreign address port is wrong'
CORE-5401 'Netstat returns ERROR_NO_DATA Pipe being closed'
CORE-5126 'UNIMPLEMENTED: iphlpapi: GetExtendedUdpTable'
even without touching the netstat binary yet.
And is mostly based on work done by Pierre Schweitzer during 0.4.11-dev'ing.

by porting back:
0.4.15-dev-6231-g a5360f542f [IPHLPAPI] Formatting only, no functional change
partially 0.4.14-dev-1425-g f540b2b20c [IPHLPAPI] GetAdaptersAddresses(): Add 1 free() in ERROR_NO_DATA case (#2526) (but leave out adding the comments in .h)
0.4.12-dev-686-g 22f60faf43 [IPHLPAPI] Remove dead code to fix CID 513306, 1442673, 1442697
0.4.11-dev-880-g bf052e120b [IPHLPAPI] Reduce code duplication and use a single function for TCP and UDP enumerations + fix corruption
0.4.11-dev-867-g 159f5b676a [IPHLPAPI] Fix broken size computation leading to buffer overrun
0.4.11-dev-861-g 05657bfcfd [SDK] Add a non documenter TOIID used to query modules information
0.4.11-dev-827-g ce7f9211a0 [TCPIP] In InfoTdiQueryGetConnectionTcpTable(), only return if there's a connection
0.4.11-dev-823-g 0ec92100bc [TCPIP] Properly display local information for established connections
0.4.11-dev-819-g fbdfe7bd40 [SDK] Add GetExtendedUdpTable()
0.4.11-dev-818-g 370b03b523 [IPHLPAPI] Reimplement GetUdpTable() using GetExtendedUdpTable()
0.4.11-dev-817-g 58cef01422 [IPHLPAPI] Implement GetExtendedUdpTable() CORE-5126
0.4.11-dev-816-g 6fb6c7b50b [IPHLPAPI] Implement getOwnerUdoTable(), to get UDP connections with owner PID
0.4.11-dev-815-g 13de7f08af [TCPIP] Implement enumerating UDP connections with owner PID
0.4.11-dev-813-g 73c87d5c14 [IPHLPAPI] Reimplement GetTcpTable() using GetExtendedTcpTable()
0.4.11-dev-812-g d76ac645e8 [IPHLPAPI] Don't leak memory
0.4.11-dev-811-g c949a12506 [IPHLPAPI] Implement the IPv4 TCP_TABLE_OWNER_PID_* cases in GetExtendedTcpTable()
0.4.11-dev-810-g dca7e5689f [IPHLPAPI] Implement getOwnerTcpTable(), to get TCP connections with owner PID
0.4.11-dev-809-g 411504b5f4 [TCPIP] Implement enumerating TCP connections with owner PID
0.4.11-dev-808-g 935978ee57 [TCPIP] Store creator PID in ADDRESS_FILE
0.4.11-dev-807-g 702d44c683 [IPHLPAPI] Implement the IPv4 TCP_TABLE_BASIC_* cases in GetExtendedTcpTable()
0.4.11-dev-804-g 91b013d387 [TCPIP] When enumerating sockets, retrieve their state and return it
0.4.11-dev-803-g 738f327668 [IP] Add a TCPGetSocketStatus() wrapper around LibTCPGetSocketStatus()
0.4.11-dev-802-g 29c1510423 [LWIP] Implement a LibTCPGetSocketStatus() function in our LwIP glue
0.4.11-dev-792-g 8a98c85c1f [IPHLPAPI] Fix checking entity when enumerating TCP/UDP connections
0.4.11-dev-784-g f29016dabe [TCPIP] Properly handle listening sockets
0.4.11-dev-782-g 007f43dd56 [TCPIP] Implement returning UDP connections CORE-5401
0.4.11-dev-781-g 77d5f04f22 [TCPIP] Implement returning TCP connections CORE-5401
0.4.11-dev-799-g 500a5151ea [TCPIP] Fix returned IP address when querying TCP connections CORE-15363
0.4.11-dev-783-g d18b1fe24b [IPHLPAPI] Properly count UDP entries CORE-5401
0.4.11-dev-780-g e3cb9697a4 [IPHLPAPI] Implement getNumUdpEntries() and getUdpTable() CORE-5401
0.4.11-dev-779-g 678204790c [IPHLPAPI] Implement getNumTcpEntries() and getTcpTable() CORE-5401
----------------
Strip some DPRINTs entirely in IPHLPAPI/TCPIP in releases/0.4.7 - 0.4.10 (instead of fixing them like we did on master). Many of them had x64 issues:
This was partially *inspired* by watching the following commits:
0.4.13-dev-14-g f9a967b2ae [IPHLPAPI] Fix misc 64 bit issues (only the parts in iphlpapi_main.c with the format strings)
0.4.10-dev-409-g 0f8439aa71 [IPHLPAPI] Fix 64 bit issue, just the one within [IPHLPAPI] ifenum_reactos.c
0.4.9-dev-856-g 6c9359221c [IPHLPAPI] ipstats_reactos: Review all TRACE/WARN calls
This does not only fix the x64 incompatibilities by superseding those 3 commits but also will keep the file-sizes under control for the backports.
2023-07-03 01:47:10 +02:00

717 lines
21 KiB
C

/* Copyright (C) 2003 Art Yerkes
* A reimplementation of ifenum.c by Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* This file is implemented on the IOCTL_TCP_QUERY_INFORMATION_EX ioctl on
* tcpip.sys
*/
#include "iphlpapi_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
#ifndef TCPS_ESTABLISHED
# define TCPS_ESTABLISHED TCP_ESTABLISHED
#endif
#ifndef TCPS_SYN_SENT
# define TCPS_SYN_SENT TCP_SYN_SENT
#endif
#ifndef TCPS_SYN_RECEIVED
# define TCPS_SYN_RECEIVED TCP_SYN_RECV
#endif
#ifndef TCPS_FIN_WAIT_1
# define TCPS_FIN_WAIT_1 TCP_FIN_WAIT1
#endif
#ifndef TCPS_FIN_WAIT_2
# define TCPS_FIN_WAIT_2 TCP_FIN_WAIT2
#endif
#ifndef TCPS_TIME_WAIT
# define TCPS_TIME_WAIT TCP_TIME_WAIT
#endif
#ifndef TCPS_CLOSED
# define TCPS_CLOSED TCP_CLOSE
#endif
#ifndef TCPS_CLOSE_WAIT
# define TCPS_CLOSE_WAIT TCP_CLOSE_WAIT
#endif
#ifndef TCPS_LAST_ACK
# define TCPS_LAST_ACK TCP_LAST_ACK
#endif
#ifndef TCPS_LISTEN
# define TCPS_LISTEN TCP_LISTEN
#endif
#ifndef TCPS_CLOSING
# define TCPS_CLOSING TCP_CLOSING
#endif
BOOL isIpEntity( HANDLE tcpFile, TDIEntityID *ent ) {
return (ent->tei_entity == CL_NL_ENTITY ||
ent->tei_entity == CO_NL_ENTITY);
}
NTSTATUS getNthIpEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) {
DWORD numEntities = 0;
DWORD numRoutes = 0;
TDIEntityID *entitySet = 0;
NTSTATUS status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
int i;
if( !NT_SUCCESS(status) )
return status;
for( i = 0; i < numEntities; i++ ) {
if( isIpEntity( tcpFile, &entitySet[i] ) ) {
if( numRoutes == index ) break;
else numRoutes++;
}
}
if( numRoutes == index && i < numEntities ) {
memcpy( ent, &entitySet[i], sizeof(*ent) );
tdiFreeThingSet( entitySet );
return STATUS_SUCCESS;
} else {
tdiFreeThingSet( entitySet );
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS tdiGetMibForIpEntity
( HANDLE tcpFile, TDIEntityID *ent, IPSNMPInfo *entry ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
NTSTATUS status = STATUS_SUCCESS;
DWORD returnSize;
memset( entry, 0, sizeof( *entry ) );
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = IP_MIB_STATS_ID;
req.ID.toi_entity = *ent;
status = DeviceIoControl(tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
entry,
sizeof(*entry),
&returnSize,
NULL);
return status;
}
NTSTATUS tdiGetRoutesForIpEntity
( HANDLE tcpFile, TDIEntityID *ent, IPRouteEntry **routes, PDWORD numRoutes ) {
NTSTATUS status = STATUS_SUCCESS;
status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
IP_MIB_ARPTABLE_ENTRY_ID,
CL_NL_ENTITY,
ent->tei_instance,
0,
sizeof(IPRouteEntry),
(PVOID *)routes,
numRoutes);
return status;
}
NTSTATUS tdiGetIpAddrsForIpEntity
( HANDLE tcpFile, TDIEntityID *ent, IPAddrEntry **addrs, PDWORD numAddrs ) {
NTSTATUS status;
status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
IP_MIB_ADDRTABLE_ENTRY_ID,
CL_NL_ENTITY,
ent->tei_instance,
0,
sizeof(IPAddrEntry),
(PVOID *)addrs,
numAddrs);
return status;
}
DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry)
{
if (!name)
return ERROR_INVALID_PARAMETER;
if (!entry)
return ERROR_INVALID_PARAMETER;
return NO_ERROR;
}
DWORD getInterfaceStatsByIndex(DWORD index, PMIB_IFROW entry)
{
return ERROR_INVALID_PARAMETER;
}
DWORD getICMPStats(MIB_ICMP *stats)
{
FILE *fp;
if (!stats)
return ERROR_INVALID_PARAMETER;
memset(stats, 0, sizeof(MIB_ICMP));
/* get most of these stats from /proc/net/snmp, no error if can't */
fp = fopen("/proc/net/snmp", "r");
if (fp) {
const char hdr[] = "Icmp:";
char buf[512] = { 0 }, *ptr;
do {
ptr = fgets(buf, sizeof(buf), fp);
} while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1));
if (ptr) {
/* last line was a header, get another */
ptr = fgets(buf, sizeof(buf), fp);
if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) {
char *endPtr;
ptr += sizeof(hdr);
if (ptr && *ptr) {
stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
if (ptr && *ptr) {
stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10);
ptr = endPtr;
}
}
}
fclose(fp);
}
return NO_ERROR;
}
DWORD getIPStats(PMIB_IPSTATS stats, DWORD family)
{
if (!stats)
return ERROR_INVALID_PARAMETER;
return NO_ERROR;
}
DWORD getTCPStats(MIB_TCPSTATS *stats, DWORD family)
{
if (!stats)
return ERROR_INVALID_PARAMETER;
return NO_ERROR;
}
DWORD getUDPStats(MIB_UDPSTATS *stats, DWORD family)
{
if (!stats)
return ERROR_INVALID_PARAMETER;
return NO_ERROR;
}
DWORD getNumRoutes(void)
{
DWORD numEntities, numRoutes = 0;
TDIEntityID *entitySet;
HANDLE tcpFile;
int i;
NTSTATUS status;
status = openTcpFile(&tcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(status))
return 0;
status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
if (!NT_SUCCESS(status)) {
closeTcpFile( tcpFile );
return 0;
}
for (i = 0; i < numEntities; i++) {
if (isIpEntity(tcpFile, &entitySet[i])) {
IPSNMPInfo isnmp;
memset(&isnmp, 0, sizeof(isnmp));
status = tdiGetMibForIpEntity(tcpFile, &entitySet[i], &isnmp);
if (!NT_SUCCESS(status)) {
numRoutes = 0;
break;
}
numRoutes += isnmp.ipsi_numroutes;
}
}
tdiFreeThingSet(entitySet);
closeTcpFile(tcpFile);
return numRoutes;
}
RouteTable *getRouteTable(void)
{
RouteTable *out_route_table;
DWORD numRoutes = getNumRoutes(), routesAdded = 0;
TDIEntityID ent;
HANDLE tcpFile;
NTSTATUS status = openTcpFile(&tcpFile, FILE_READ_DATA);
int i;
if (!NT_SUCCESS(status))
return 0;
out_route_table = HeapAlloc(GetProcessHeap(), 0,
sizeof(RouteTable) +
(sizeof(RouteEntry) * (numRoutes - 1)));
if (!out_route_table) {
closeTcpFile(tcpFile);
return NULL;
}
out_route_table->numRoutes = numRoutes;
for (i = 0; routesAdded < out_route_table->numRoutes; i++) {
int j;
IPRouteEntry *route_set;
getNthIpEntity(tcpFile, i, &ent);
tdiGetRoutesForIpEntity(tcpFile, &ent, &route_set, &numRoutes);
if (!route_set) {
closeTcpFile(tcpFile);
HeapFree(GetProcessHeap(), 0, out_route_table);
return 0;
}
for (j = 0; j < numRoutes; j++) {
int routeNum = j + routesAdded;
out_route_table->routes[routeNum].dest =
route_set[j].ire_dest;
out_route_table->routes[routeNum].mask =
route_set[j].ire_mask;
out_route_table->routes[routeNum].gateway =
route_set[j].ire_gw;
out_route_table->routes[routeNum].ifIndex =
route_set[j].ire_index;
out_route_table->routes[routeNum].metric =
route_set[j].ire_metric1;
}
if (route_set) tdiFreeThingSet(route_set);
routesAdded += numRoutes;
}
closeTcpFile(tcpFile);
return out_route_table;
}
DWORD getNumArpEntries(void)
{
DWORD numEntities;
TDIEntityID *entitySet = NULL;
HANDLE tcpFile;
int i, totalNumber = 0;
NTSTATUS status;
PMIB_IPNETROW IpArpTable = NULL;
DWORD returnSize;
status = openTcpFile(&tcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(status))
return 0;
status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
for (i = 0; i < numEntities; i++) {
if (isInterface(&entitySet[i]) && hasArp(tcpFile, &entitySet[i]))
{
status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
IP_MIB_ARPTABLE_ENTRY_ID,
AT_ENTITY,
entitySet[i].tei_instance,
0,
sizeof(MIB_IPNETROW),
(PVOID *)&IpArpTable,
&returnSize);
if (status == STATUS_SUCCESS) totalNumber += returnSize;
if (IpArpTable) {
tdiFreeThingSet(IpArpTable);
IpArpTable = NULL;
}
}
}
closeTcpFile(tcpFile);
if (entitySet) tdiFreeThingSet(entitySet);
return totalNumber;
}
PMIB_IPNETTABLE getArpTable(void)
{
DWORD numEntities, returnSize;
TDIEntityID *entitySet;
HANDLE tcpFile;
int i, totalNumber, TmpIdx, CurrIdx = 0;
NTSTATUS status;
PMIB_IPNETTABLE IpArpTable = NULL;
PMIB_IPNETROW AdapterArpTable = NULL;
totalNumber = getNumArpEntries();
status = openTcpFile(&tcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(status))
return 0;
IpArpTable = HeapAlloc(GetProcessHeap(), 0,
sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber));
if (!IpArpTable) {
closeTcpFile(tcpFile);
return NULL;
}
status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
for (i = 0; i < numEntities; i++) {
if (isInterface(&entitySet[i]) && hasArp(tcpFile, &entitySet[i]))
{
status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
IP_MIB_ARPTABLE_ENTRY_ID,
AT_ENTITY,
entitySet[i].tei_instance,
0,
sizeof(MIB_IPNETROW),
(PVOID *)&AdapterArpTable,
&returnSize);
if (status == STATUS_SUCCESS) {
for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
IpArpTable->table[CurrIdx] = AdapterArpTable[TmpIdx];
tdiFreeThingSet(AdapterArpTable);
}
}
}
closeTcpFile(tcpFile);
tdiFreeThingSet(entitySet);
IpArpTable->dwNumEntries = CurrIdx;
return IpArpTable;
}
struct _TABLE_CALL
{
DWORD TOIID;
SIZE_T UdpSize;
SIZE_T TcpSize;
SIZE_T UdpOffset;
SIZE_T TcpOffset;
} UdpTcpTableCall[] = {
{IP_MIB_ARPTABLE_ENTRY_ID, sizeof(MIB_UDPROW), sizeof(MIB_TCPROW), FIELD_OFFSET(MIB_UDPTABLE, table), FIELD_OFFSET(MIB_TCPTABLE, table)},
{IP_MIB_ADDRTABLE_ENTRY_ID, sizeof(MIB_UDPROW_OWNER_PID), sizeof(MIB_TCPROW_OWNER_PID), FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table), FIELD_OFFSET(MIB_TCPTABLE_OWNER_PID, table)},
{IP_SPECIFIC_MODULE_ENTRY_ID, sizeof(MIB_UDPROW_OWNER_MODULE), sizeof(MIB_TCPROW_OWNER_MODULE), FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table), FIELD_OFFSET(MIB_TCPTABLE_OWNER_MODULE, table)},
};
#define Add2Ptr(PTR, INC) (PVOID)((ULONG_PTR)(PTR) + (INC))
DWORD getNumUdpEntries(void)
{
DWORD numEntities;
TDIEntityID *entitySet = NULL;
HANDLE tcpFile;
int i, totalNumber = 0;
NTSTATUS status;
PMIB_UDPROW IpUdpTable = NULL;
DWORD returnSize;
status = openTcpFile(&tcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(status))
return 0;
status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
for (i = 0; i < numEntities; i++) {
if (entitySet[i].tei_entity == CL_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
{
status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
IP_MIB_ARPTABLE_ENTRY_ID,
CL_TL_ENTITY,
entitySet[i].tei_instance,
0,
sizeof(MIB_UDPROW),
(PVOID *)&IpUdpTable,
&returnSize);
if (status == STATUS_SUCCESS) totalNumber += returnSize;
if (IpUdpTable) {
tdiFreeThingSet(IpUdpTable);
IpUdpTable = NULL;
}
}
}
closeTcpFile(tcpFile);
if (entitySet) tdiFreeThingSet(entitySet);
return totalNumber;
}
PVOID getUdpTable(CLASS_TABLE Class)
{
DWORD numEntities, returnSize;
TDIEntityID *entitySet;
HANDLE tcpFile;
int i, totalNumber, TmpIdx, CurrIdx = 0;
NTSTATUS status;
PMIB_UDPTABLE IpUdpTable = NULL;
PVOID AdapterUdpTable = NULL;
totalNumber = getNumUdpEntries();
status = openTcpFile(&tcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(status))
return 0;
IpUdpTable = HeapAlloc(GetProcessHeap(), 0,
UdpTcpTableCall[Class].UdpOffset + (UdpTcpTableCall[Class].UdpSize * totalNumber));
if (!IpUdpTable) {
closeTcpFile(tcpFile);
return NULL;
}
status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
for (i = 0; i < numEntities; i++) {
if (entitySet[i].tei_entity == CL_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
{
status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
UdpTcpTableCall[Class].TOIID,
CL_TL_ENTITY,
entitySet[i].tei_instance,
0,
UdpTcpTableCall[Class].UdpSize,
&AdapterUdpTable,
&returnSize);
if (status == STATUS_SUCCESS) {
for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
CopyMemory(Add2Ptr(IpUdpTable, UdpTcpTableCall[Class].UdpOffset + UdpTcpTableCall[Class].UdpSize * CurrIdx),
Add2Ptr(AdapterUdpTable, UdpTcpTableCall[Class].UdpSize * TmpIdx),
UdpTcpTableCall[Class].UdpSize);
tdiFreeThingSet(AdapterUdpTable);
}
}
}
closeTcpFile(tcpFile);
tdiFreeThingSet(entitySet);
IpUdpTable->dwNumEntries = CurrIdx;
return IpUdpTable;
}
DWORD getNumTcpEntries(void)
{
DWORD numEntities;
TDIEntityID *entitySet = NULL;
HANDLE tcpFile;
int i, totalNumber = 0;
NTSTATUS status;
PMIB_TCPROW IpTcpTable = NULL;
DWORD returnSize;
status = openTcpFile(&tcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(status))
return 0;
status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
for (i = 0; i < numEntities; i++) {
if (entitySet[i].tei_entity == CO_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
{
status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
IP_MIB_ARPTABLE_ENTRY_ID,
CO_TL_ENTITY,
entitySet[i].tei_instance,
0,
sizeof(MIB_TCPROW),
(PVOID *)&IpTcpTable,
&returnSize);
if (status == STATUS_SUCCESS) totalNumber += returnSize;
if (IpTcpTable) {
tdiFreeThingSet(IpTcpTable);
IpTcpTable = NULL;
}
}
}
closeTcpFile(tcpFile);
if (entitySet) tdiFreeThingSet(entitySet);
return totalNumber;
}
PVOID getTcpTable(CLASS_TABLE Class)
{
DWORD numEntities, returnSize;
TDIEntityID *entitySet;
HANDLE tcpFile;
int i, totalNumber, TmpIdx, CurrIdx = 0;
NTSTATUS status;
PMIB_TCPTABLE IpTcpTable = NULL;
PVOID AdapterTcpTable = NULL;
totalNumber = getNumTcpEntries();
status = openTcpFile(&tcpFile, FILE_READ_DATA);
if (!NT_SUCCESS(status))
return 0;
IpTcpTable = HeapAlloc(GetProcessHeap(), 0,
UdpTcpTableCall[Class].TcpOffset + (UdpTcpTableCall[Class].TcpSize * totalNumber));
if (!IpTcpTable) {
closeTcpFile(tcpFile);
return NULL;
}
status = tdiGetEntityIDSet(tcpFile, &entitySet, &numEntities);
for (i = 0; i < numEntities; i++) {
if (entitySet[i].tei_entity == CO_TL_ENTITY && hasArp(tcpFile, &entitySet[i]))
{
status = tdiGetSetOfThings(tcpFile,
INFO_CLASS_PROTOCOL,
INFO_TYPE_PROVIDER,
UdpTcpTableCall[Class].TOIID,
CO_TL_ENTITY,
entitySet[i].tei_instance,
0,
UdpTcpTableCall[Class].TcpSize,
&AdapterTcpTable,
&returnSize);
if (status == STATUS_SUCCESS) {
for (TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++)
CopyMemory(Add2Ptr(IpTcpTable, UdpTcpTableCall[Class].TcpOffset + UdpTcpTableCall[Class].TcpSize * CurrIdx),
Add2Ptr(AdapterTcpTable, UdpTcpTableCall[Class].TcpSize * TmpIdx),
UdpTcpTableCall[Class].TcpSize);
tdiFreeThingSet(AdapterTcpTable);
}
}
}
closeTcpFile(tcpFile);
tdiFreeThingSet(entitySet);
IpTcpTable->dwNumEntries = CurrIdx;
return IpTcpTable;
}