Big merge in wine code. This merged version is far more complete than

the previous one.   See notes and comments by me and the original author
of iphlpapi_main.c, Juan Lang.

svn path=/trunk/; revision=8194
This commit is contained in:
Art Yerkes 2004-02-15 07:17:00 +00:00
parent d3a56d75eb
commit a3ac53db3d
17 changed files with 4129 additions and 39 deletions

117
reactos/lib/iphlpapi/icmp.c Normal file
View file

@ -0,0 +1,117 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#ifdef __REACTOS__
# include <windows.h>
# include <windef.h>
# include <winbase.h>
# include <net/miniport.h>
# include <winsock2.h>
# include <nspapi.h>
# include <iptypes.h>
# include "iphlpapiextra.h"
#else
# include "windef.h"
# include "winbase.h"
# include "winreg.h"
#endif
#include "iphlpapi.h"
#include "ifenum.h"
#include "ipstats.h"
#include "iphlp_res.h"
#include "wine/debug.h"
/*
* @unimplemented
*/
DWORD
STDCALL
IcmpParseReplies(
LPVOID ReplyBuffer,
DWORD ReplySize
)
{
UNIMPLEMENTED
return 0L;
}
/*
* @unimplemented
*/
HANDLE STDCALL IcmpCreateFile(
VOID
)
{
UNIMPLEMENTED
return 0L;
}
/*
* @unimplemented
*/
BOOL STDCALL IcmpCloseHandle(
HANDLE IcmpHandle
)
{
UNIMPLEMENTED
return 0L;
}
/*
* @unimplemented
*/
DWORD STDCALL IcmpSendEcho(
HANDLE IcmpHandle,
IPAddr DestinationAddress,
LPVOID RequestData,
WORD RequestSize,
PIP_OPTION_INFORMATION RequestOptions,
LPVOID ReplyBuffer,
DWORD ReplySize,
DWORD Timeout
)
{
UNIMPLEMENTED
return 0L;
}
/*
* @unimplemented
*/
DWORD
STDCALL
IcmpSendEcho2(
HANDLE IcmpHandle,
HANDLE Event,
FARPROC ApcRoutine,
PVOID ApcContext,
IPAddr DestinationAddress,
LPVOID RequestData,
WORD RequestSize,
PIP_OPTION_INFORMATION RequestOptions,
LPVOID ReplyBuffer,
DWORD ReplySize,
DWORD Timeout
)
{
UNIMPLEMENTED
return 0L;
}

View file

@ -0,0 +1,142 @@
/* ifenum.h
* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This module implements functions shared by DLLs that need to enumerate
* network interfaces and addresses. It's meant to hide some problematic
* defines like socket(), as well as provide only one file
* that needs to be ported to implement these functions on different platforms,
* since the Windows API provides multiple ways to get at this info.
*
* Like Windows, it uses a numeric index to identify an interface uniquely.
* As implemented, an interface represents a UNIX network interface, virtual
* or real, and thus can have 0 or 1 IP addresses associated with it. (This
* only supports IPv4.)
* The indexes returned are not guaranteed to be contiguous, so don't call
* getNumInterfaces() and assume the values [0,getNumInterfaces() - 1] will be
* valid indexes; use getInterfaceIndexTable() instead. Non-loopback
* interfaces have lower index values than loopback interfaces, in order to
* make the indexes somewhat reusable as Netbios LANA numbers. See ifenum.c
* for more detail on this.
*
* See also the companion file, ipstats.h, for functions related to getting
* statistics.
*/
#ifndef WINE_IFENUM_H_
#define WINE_IFENUM_H_
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "iprtrmib.h"
#define MAX_INTERFACE_PHYSADDR 8
#define MAX_INTERFACE_DESCRIPTION 256
/* Call before using the functions in this module */
void interfaceMapInit(void);
/* Call to free resources allocated in interfaceMapInit() */
void interfaceMapFree(void);
DWORD getNumInterfaces(void);
DWORD getNumNonLoopbackInterfaces(void);
/* A table of interface indexes, see get*InterfaceTable(). Ignore numAllocated,
* it's used during the creation of the table.
*/
typedef struct _InterfaceIndexTable {
DWORD numIndexes;
DWORD numAllocated;
DWORD indexes[1];
} InterfaceIndexTable;
/* Returns a table with all known interface indexes, or NULL if one could not
* be allocated. free() the returned table.
*/
InterfaceIndexTable *getInterfaceIndexTable(void);
/* Like getInterfaceIndexTable, but filters out loopback interfaces. */
InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void);
/* ByName/ByIndex versions of various getter functions. */
/* can be used as quick check to see if you've got a valid index, returns NULL
* if not. The buffer returned may have been allocated. It should be returned
* by calling consumeInterfaceNmae.
*/
const char *getInterfaceNameByIndex(DWORD index);
/* consume the interface name provided by getInterfaceName. */
void consumeInterfaceName( const char *ifname );
/* Fills index with the index of name, if found. Returns
* ERROR_INVALID_PARAMETER if name or index is NULL, ERROR_INVALID_DATA if name
* is not found, and NO_ERROR on success.
*/
DWORD getInterfaceIndexByName(const char *name, PDWORD index);
/* This bunch returns IP addresses, and INADDR_ANY or INADDR_NONE if not found,
* appropriately depending on the f/n.
*/
DWORD getInterfaceIPAddrByName(const char *name);
DWORD getInterfaceIPAddrByIndex(DWORD index);
DWORD getInterfaceMaskByName(const char *name);
DWORD getInterfaceMaskByIndex(DWORD index);
DWORD getInterfaceBCastAddrByName(const char *name);
DWORD getInterfaceBCastAddrByIndex(DWORD index);
/* Gets a few physical charactersistics of a device: MAC addr len, MAC addr,
* and type as one of the MIB_IF_TYPEs.
* len's in-out: on in, needs to say how many bytes are available in addr,
* which to be safe should be MAX_INTERFACE_PHYSADDR. On out, it's how many
* bytes were set, or how many were required if addr isn't big enough.
* Returns ERROR_INVALID_PARAMETER if name, len, addr, or type is NULL.
* Returns ERROR_INVALID_DATA if name/index isn't valid.
* Returns ERROR_INSUFFICIENT_BUFFER if addr isn't large enough for the
* physical address; *len will contain the required size.
* May return other errors, e.g. ERROR_OUTOFMEMORY or ERROR_NO_MORE_FILES,
* if internal errors occur.
* Returns NO_ERROR on success.
*/
DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
PDWORD type);
DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
PDWORD type);
/* Get the operational status as a (MIB_)IF_OPER_STATUS type.
*/
DWORD getInterfaceStatusByName(const char *name, PDWORD status);
DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status);
DWORD getInterfaceMtuByName(const char *name, PDWORD mtu);
DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu);
/* Fills in the MIB_IFROW by name/index. Doesn't fill in interface statistics,
* see ipstats.h for that.
* Returns ERROR_INVALID_PARAMETER if name or entry is NULL, ERROR_INVALID_DATA
* if name/index isn't valid, and NO_ERROR otherwise.
*/
DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry);
DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry);
/* Converts the network-order bytes in addr to a printable string. Returns
* string.
*/
char *toIPAddressString(unsigned int addr, char string[16]);
#endif /* ndef WINE_IFENUM_H_ */

View file

@ -0,0 +1,723 @@
/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Implementation notes
* - Our bretheren use IOCTL_TCP_QUERY_INFORMATION_EX to get information
* from tcpip.sys and IOCTL_TCP_SET_INFORMATION_EX to set info (such as
* the route table). These ioctls mirror WsControl exactly in usage.
* - This iphlpapi does not rely on any reactos-only features.
* - This implementation is meant to be largely correct. I am not, however,
* paying any attention to performance. It can be done faster, and
* someone should definately optimize this code when speed is more of a
* priority than it is now.
*
* Edited implementation notes from the original -- Basically edited to add
* information and prune things which are not accurate about this file.
* Interface index fun:
* - Windows may rely on an index being cleared in the topmost 8 bits in some
* APIs; see GetFriendlyIfIndex and the mention of "backward compatible"
* indexes. It isn't clear which APIs might fail with non-backward-compatible
* indexes, but I'll keep them bits clear just in case.
* FIXME:
* - We don't support IPv6 addresses here yet -- I moved the upper edge
* functions into iphlpv6.c (arty)
*/
#include "ipprivate.h"
#include "ifenum.h"
/* Globals */
const PWCHAR TcpFileName = L"\\Device\\Tcp";
/* Functions */
void interfaceMapInit(void)
{
/* For now, nothing */
}
void interfaceMapFree(void)
{
/* Ditto. */
}
NTSTATUS openTcpFile(PHANDLE tcpFile) {
UNICODE_STRING fileName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
NTSTATUS status;
TRACE("called.\n");
/* Shamelessly ripped from CreateFileW */
RtlInitUnicodeString( &fileName, TcpFileName );
InitializeObjectAttributes( &objectAttributes,
&fileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = NtCreateFile( tcpFile,
SYNCHRONIZE | GENERIC_EXECUTE,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
0,
0 );
/* String does not need to be freed: it points to the constant
* string we provided */
TRACE("returning %08x\n", (int)status);
return status;
}
void closeTcpFile( HANDLE h ) {
TRACE("called.\n");
NtClose( h );
}
/* A generic thing-getting function which interacts in the right way with
* TDI. This may seem oblique, but I'm using it to reduce code and hopefully
* make this thing easier to debug.
*
* The things returned can be any of:
* TDIEntityID
* TDIObjectID
* IFEntry
* IPSNMPInfo
* IPAddrEntry
* IPInterfaceInfo
*/
NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
DWORD toiClass,
DWORD toiType,
DWORD toiId,
DWORD teiEntity,
DWORD fixedPart,
DWORD entrySize,
PVOID *tdiEntitySet,
PDWORD numEntries ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
PVOID entitySet = 0;
NTSTATUS status = STATUS_SUCCESS;
DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES,
arraySize = entrySize * MAX_TDI_ENTITIES;
DPRINT("TdiGetSetOfThings(tcpFile %x,toiClass %x,toiType %x,toiId %x,"
"teiEntity %x,fixedPart %d,entrySize %d)\n",
(int)tcpFile,
(int)toiClass,
(int)toiType,
(int)toiId,
(int)teiEntity,
(int)fixedPart,
(int)entrySize );
req.ID.toi_class = toiClass;
req.ID.toi_type = toiType;
req.ID.toi_id = toiId;
req.ID.toi_entity.tei_entity = teiEntity;
/* There's a subtle problem here...
* If an interface is added at this exact instant, (as if by a PCMCIA
* card insertion), the array will still not have enough entries after
* have allocated it after the first DeviceIoControl call.
*
* We'll get around this by repeating until the number of interfaces
* stabilizes.
*/
do {
assert( !entitySet ); /* We must not have an entity set allocated */
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
0,
0,
&allocationSizeForEntityArray,
NULL );
if( !NT_SUCCESS(status) ) {
DPRINT("TdiGetSetOfThings() => %08x\n", (int)status);
return status;
}
arraySize = allocationSizeForEntityArray;
entitySet = HeapAlloc( GetProcessHeap(), 0, arraySize );
if( !entitySet ) {
status = STATUS_INSUFFICIENT_RESOURCES;
DPRINT("TdiGetSetOfThings() => %08x\n", (int)status);
return status;
}
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
entitySet,
arraySize,
&allocationSizeForEntityArray,
NULL );
/* This is why we have the loop -- we might have added an adapter */
if( arraySize == allocationSizeForEntityArray )
break;
HeapFree( GetProcessHeap(), 0, entitySet );
entitySet = 0;
if( !NT_SUCCESS(status) ) {
DPRINT("TdiGetSetOfThings() => %08x\n", (int)status);
return status;
}
DPRINT("TdiGetSetOfThings(): Array changed size: %d -> %d.\n",
arraySize, allocationSizeForEntityArray );
} while( TRUE ); /* We break if the array we received was the size we
* expected. Therefore, we got here because it wasn't */
*numEntries = (arraySize - fixedPart) / entrySize;
*tdiEntitySet = entitySet;
DPRINT("TdiGetSetOfThings() => Success: %d things @ %08x\n",
(int)*numEntries, (int)entitySet);
return STATUS_SUCCESS;
}
VOID tdiFreeThingSet( PVOID things ) {
HeapFree( GetProcessHeap(), 0, things );
}
NTSTATUS tdiGetMibForIfEntity
( HANDLE tcpFile, DWORD entityId, IFEntrySafelySized *entry ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
NTSTATUS status = STATUS_SUCCESS;
DWORD returnSize;
DPRINT("TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n",
(int)tcpFile, (int)entityId);
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = IF_MIB_STATS_ID;
req.ID.toi_entity.tei_entity = IF_ENTITY;
req.ID.toi_entity.tei_instance = entityId;
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
entry,
sizeof(*entry),
&returnSize,
NULL );
if( !NT_SUCCESS(status) ) {
TRACE("failure: %08x\n", status);
return status;
} else TRACE("Success.\n");
DPRINT("TdiGetMibForIfEntity() => {\n"
" if_index ....................... %x\n"
" if_type ........................ %x\n"
" if_mtu ......................... %d\n"
" if_speed ....................... %x\n"
" if_physaddrlen ................. %d\n"
" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n",
" if_descr ....................... %s\n"
"} status %08x\n",
(int)entry->offset.ent.if_index,
(int)entry->offset.ent.if_type,
(int)entry->offset.ent.if_mtu,
(int)entry->offset.ent.if_speed,
(int)entry->offset.ent.if_physaddrlen,
entry->offset.ent.if_physaddr[0] & 0xff,
entry->offset.ent.if_physaddr[1] & 0xff,
entry->offset.ent.if_physaddr[2] & 0xff,
entry->offset.ent.if_physaddr[3] & 0xff,
entry->offset.ent.if_physaddr[4] & 0xff,
entry->offset.ent.if_physaddr[5] & 0xff,
entry->offset.ent.if_descr,
(int)status);
return status;
}
NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile,
TDIEntityID **entitySet,
PDWORD numEntities ) {
NTSTATUS status = tdiGetSetOfThings( tcpFile,
INFO_CLASS_GENERIC,
INFO_TYPE_PROVIDER,
ENTITY_LIST_ID,
GENERIC_ENTITY,
0,
sizeof(TDIEntityID),
(PVOID *)entitySet,
numEntities );
if( NT_SUCCESS(status) ) {
int i;
for( i = 0; i < *numEntities; i++ ) {
DPRINT("%-4d: %04x:%08x\n",
i,
(*entitySet)[i].tei_entity,
(*entitySet)[i].tei_instance );
}
}
return status;
}
static BOOL isInterface( TDIEntityID *if_maybe ) {
return
if_maybe->tei_entity == IF_ENTITY;
}
static BOOL isLoopback( HANDLE tcpFile, TDIEntityID *loop_maybe ) {
IFEntrySafelySized entryInfo;
tdiGetMibForIfEntity( tcpFile,
loop_maybe->tei_instance,
&entryInfo );
return !entryInfo.offset.ent.if_type ||
entryInfo.offset.ent.if_type == IFENT_SOFTWARE_LOOPBACK;
}
NTSTATUS tdiGetEntityType( HANDLE tcpFile, TDIEntityID *ent, PULONG type ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
NTSTATUS status = STATUS_SUCCESS;
DWORD returnSize;
DPRINT("TdiGetEntityType(tcpFile %x,entityId %x)\n",
(DWORD)tcpFile, ent->tei_instance);
req.ID.toi_class = INFO_CLASS_GENERIC;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = ENTITY_TYPE_ID;
req.ID.toi_entity.tei_entity = ent->tei_entity;
req.ID.toi_entity.tei_instance = ent->tei_instance;
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
type,
sizeof(*type),
&returnSize,
NULL );
DPRINT("TdiGetEntityType() => %08x %08x\n", *type, status);
return status;
}
static DWORD getNumInterfacesInt(BOOL onlyLoopback)
{
DWORD numEntities, numInterfaces = 0;
TDIEntityID *entitySet;
HANDLE tcpFile;
NTSTATUS status;
int i;
status = openTcpFile( &tcpFile );
if( !NT_SUCCESS(status) ) {
DPRINT("getNumInterfaces: failed %08x\n", status );
return 0;
}
status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
if( !NT_SUCCESS(status) ) {
DPRINT("getNumInterfaces: failed %08x\n", status );
return 0;
}
closeTcpFile( tcpFile );
for( i = 0; i < numEntities; i++ ) {
if( isInterface( &entitySet[i] ) &&
(!onlyLoopback || isLoopback( tcpFile, &entitySet[i] )) )
numInterfaces++;
}
DPRINT("getNumInterfaces: success: %d %d %08x\n",
onlyLoopback, numInterfaces, status );
tdiFreeThingSet( entitySet );
return numInterfaces;
}
DWORD getNumInterfaces(void)
{
return getNumInterfacesInt( FALSE );
}
DWORD getNumNonLoopbackInterfaces(void)
{
return getNumInterfacesInt( TRUE );
}
DWORD getNthInterfaceEntity( HANDLE tcpFile, DWORD index, TDIEntityID *ent ) {
DWORD numEntities = 0;
DWORD numInterfaces = 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( isInterface( &entitySet[i] ) ) {
if( numInterfaces == index ) break;
else numInterfaces++;
}
}
DPRINT("Index %d is entity #%d - %04x:%08x\n", index, i,
entitySet[i].tei_entity, entitySet[i].tei_instance );
if( numInterfaces == index && i < numEntities ) {
memcpy( ent, &entitySet[i], sizeof(*ent) );
tdiFreeThingSet( entitySet );
return STATUS_SUCCESS;
} else {
tdiFreeThingSet( entitySet );
return STATUS_UNSUCCESSFUL;
}
}
/* Note that the result of this operation must be freed later */
const char *getInterfaceNameByIndex(DWORD index)
{
TDIEntityID ent;
IFEntrySafelySized entityInfo;
HANDLE tcpFile = INVALID_HANDLE_VALUE;
NTSTATUS status = STATUS_SUCCESS;
PCHAR interfaceName = 0;
char simple_name_buf[100];
char *adapter_name;
status = openTcpFile( &tcpFile );
if( !NT_SUCCESS(status) ) {
DPRINT("failed %08x\n", status );
return 0;
}
status = getNthInterfaceEntity( tcpFile, index, &ent );
if( !NT_SUCCESS(status) ) {
DPRINT("failed %08x\n", status );
return 0;
}
status = tdiGetMibForIfEntity( tcpFile,
ent.tei_instance,
&entityInfo );
if( NT_SUCCESS(status) ) {
adapter_name = entityInfo.offset.ent.if_descr;
} else {
sprintf( simple_name_buf, "eth%x",
(int)ent.tei_instance );
adapter_name = simple_name_buf;
}
interfaceName = HeapAlloc( GetProcessHeap(), 0,
strlen(adapter_name) + 1 );
strcpy( interfaceName, adapter_name );
closeTcpFile( tcpFile );
return interfaceName;
}
void consumeInterfaceName(const char *name) {
HeapFree( GetProcessHeap(), 0, (char *)name );
}
DWORD getInterfaceIndexByName(const char *name, PDWORD index)
{
DWORD ret = STATUS_SUCCESS;
int numInterfaces = getNumInterfaces();
const char *iname = 0;
int i;
HANDLE tcpFile;
ret = openTcpFile( &tcpFile );
if( !NT_SUCCESS(ret) ) {
DPRINT("Failure: %08x\n", ret);
return ret;
}
for( i = 0; i < numInterfaces; i++ ) {
iname = getInterfaceNameByIndex( i );
if( !strcmp(iname, name) ) {
*index = i;
}
HeapFree( GetProcessHeap(), 0, (char *)iname );
}
closeTcpFile( tcpFile );
return ret;
}
InterfaceIndexTable *getInterfaceIndexTableInt( BOOL nonLoopbackOnly ) {
HANDLE tcpFile;
DWORD numInterfaces, curInterface = 0;
int i;
InterfaceIndexTable *ret;
TDIEntityID *entitySet;
DWORD numEntities;
NTSTATUS status;
numInterfaces = getNumInterfaces();
TRACE("getInterfaceIndexTable: numInterfaces: %d\n", numInterfaces);
ret = (InterfaceIndexTable *)calloc(1,
sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD));
if (ret) {
ret->numAllocated = numInterfaces;
}
status = openTcpFile( &tcpFile );
tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
for( i = 0; i < numEntities; i++ ) {
if( isInterface( &entitySet[i] ) &&
(!nonLoopbackOnly || !isLoopback( tcpFile, &entitySet[i] )) ) {
ret->indexes[curInterface++] = entitySet[i].tei_instance;
}
}
tdiFreeThingSet( entitySet );
closeTcpFile( tcpFile );
ret->numIndexes = curInterface;
return ret;
}
InterfaceIndexTable *getInterfaceIndexTable(void) {
return getInterfaceIndexTableInt( FALSE );
}
InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void) {
return getInterfaceIndexTableInt( TRUE );
}
DWORD getInterfaceIPAddrByName(const char *name)
{
return INADDR_ANY;
}
DWORD getInterfaceIPAddrByIndex(DWORD index)
{
return INADDR_ANY;
}
DWORD getInterfaceBCastAddrByName(const char *name)
{
return INADDR_ANY;
}
DWORD getInterfaceBCastAddrByIndex(DWORD index)
{
return INADDR_ANY;
}
DWORD getInterfaceMaskByName(const char *name)
{
DWORD ret = INADDR_NONE;
return ret;
}
DWORD getInterfaceMaskByIndex(DWORD index)
{
DWORD ret = INADDR_NONE;
return ret;
}
DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
PDWORD type)
{
DWORD ret;
DWORD addrLen;
if (!name || !len || !addr || !type)
return ERROR_INVALID_PARAMETER;
if (addrLen > *len) {
ret = ERROR_INSUFFICIENT_BUFFER;
*len = addrLen;
}
else {
/* zero out remaining bytes for broken implementations */
memset(addr + addrLen, 0, *len - addrLen);
*len = addrLen;
ret = NO_ERROR;
}
ret = ERROR_NO_MORE_FILES;
return ret;
}
DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr,
PDWORD type)
{
const char *name = getInterfaceNameByIndex(index);
if (name)
return getInterfacePhysicalByName(name, len, addr, type);
else
return ERROR_INVALID_DATA;
}
DWORD getInterfaceMtuByName(const char *name, PDWORD mtu)
{
*mtu = 0;
return ERROR_SUCCESS;
}
DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu)
{
const char *name = getInterfaceNameByIndex(index);
if (name)
return getInterfaceMtuByName(name, mtu);
else
return ERROR_INVALID_DATA;
}
DWORD getInterfaceStatusByName(const char *name, PDWORD status)
{
DWORD ret;
if (!name)
return ERROR_INVALID_PARAMETER;
if (!status)
return ERROR_INVALID_PARAMETER;
ret = ERROR_NO_MORE_FILES;
return ret;
}
DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status)
{
const char *name = getInterfaceNameByIndex(index);
if (name)
return getInterfaceStatusByName(name, status);
else
return ERROR_INVALID_DATA;
}
DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry)
{
BYTE addr[MAX_INTERFACE_PHYSADDR];
DWORD ret, len = sizeof(addr), type;
if (!name)
return ERROR_INVALID_PARAMETER;
if (!entry)
return ERROR_INVALID_PARAMETER;
if (getInterfacePhysicalByName(name, &len, addr, &type) == NO_ERROR) {
WCHAR *assigner;
const char *walker;
memset(entry, 0, sizeof(MIB_IFROW));
for (assigner = entry->wszName, walker = name; *walker;
walker++, assigner++)
*assigner = *walker;
*assigner = 0;
getInterfaceIndexByName(name, &entry->dwIndex);
entry->dwPhysAddrLen = len;
memcpy(entry->bPhysAddr, addr, len);
memset(entry->bPhysAddr + len, 0, sizeof(entry->bPhysAddr) - len);
entry->dwType = type;
/* FIXME: how to calculate real speed? */
getInterfaceMtuByName(name, &entry->dwMtu);
/* lie, there's no "administratively down" here */
entry->dwAdminStatus = MIB_IF_ADMIN_STATUS_UP;
getInterfaceStatusByName(name, &entry->dwOperStatus);
/* punt on dwLastChange? */
entry->dwDescrLen = min(strlen(name), MAX_INTERFACE_DESCRIPTION - 1);
memcpy(entry->bDescr, name, entry->dwDescrLen);
entry->bDescr[entry->dwDescrLen] = '\0';
entry->dwDescrLen++;
ret = NO_ERROR;
}
else
ret = ERROR_INVALID_DATA;
return ret;
}
DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry)
{
HANDLE tcpFile;
NTSTATUS status = openTcpFile( &tcpFile );
TDIEntityID entity;
DPRINT("Called.\n");
if( !NT_SUCCESS(status) ) {
DPRINT("Failed: %08x\n", status);
return status;
}
status = getNthInterfaceEntity( tcpFile, index, &entity );
if( !NT_SUCCESS(status) ) {
DPRINT("Failed: %08x\n", status);
closeTcpFile( tcpFile );
return status;
}
status = tdiGetMibForIfEntity( tcpFile,
entity.tei_instance,
(IFEntrySafelySized *)
&entry->wszName[MAX_INTERFACE_NAME_LEN] );
closeTcpFile( tcpFile );
return status;
}
char *toIPAddressString(unsigned int addr, char string[16])
{
if (string) {
struct in_addr iAddr;
iAddr.s_addr = addr;
/* extra-anal, just to make auditors happy */
strncpy(string, inet_ntoa(iAddr), 16);
string[16] = '\0';
}
return string;
}

View file

@ -0,0 +1,12 @@
#ifndef _IPHLP_RES_H
#define _IPHLP_RES_H
typedef struct _IPHLP_RES_INFO {
DWORD riCount;
LPSOCKADDR riAddressList;
} IPHLP_RES_INFO, *PIPHLP_RES_INFO;
PIPHLP_RES_INFO getResInfo();
VOID disposeResInfo( PIPHLP_RES_INFO InfoPtr );
#endif/*_IPHLP_RES_H*/

View file

@ -19,14 +19,14 @@ GetUdpTable=GetUdpTable@12
FlushIpNetTable=FlushIpNetTable@4
;IpHlpDllEntry
;AllocateAndGetArpEntTableFromStack
AllocateAndGetIfTableFromStack@16
AllocateAndGetIpAddrTableFromStack@16
AllocateAndGetIpForwardTableFromStack@16
AllocateAndGetIpNetTableFromStack@16
AllocateAndGetIfTableFromStack=AllocateAndGetIfTableFromStack@16
AllocateAndGetIpAddrTableFromStack=AllocateAndGetIpAddrTableFromStack@16
AllocateAndGetIpForwardTableFromStack=AllocateAndGetIpForwardTableFromStack@16
AllocateAndGetIpNetTableFromStack=AllocateAndGetIpNetTableFromStack@16
;AllocateAndGetTcpExTableFromStack
AllocateAndGetTcpTableFromStack@16
AllocateAndGetTcpTableFromStack=AllocateAndGetTcpTableFromStack@16
;AllocateAndGetUdpExTableFromStack
AllocateAndGetUdpTableFromStack@16
AllocateAndGetUdpTableFromStack=AllocateAndGetUdpTableFromStack@16
CreateIpNetEntry=CreateIpNetEntry@4
CreateProxyArpEntry=CreateProxyArpEntry@12
DeleteIPAddress=DeleteIPAddress@4

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
#ifndef _IPHLPAPIEXTRA_H
#define _IPHLPAPIEXTRA_H
#include <w32api.h>
/* This is here until we switch to version 2.5 of the mingw headers */
#if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5)
BOOL WINAPI
GetComputerNameExA(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD);
#endif
#endif/*_IPHLPAPIEXTRA_H*/

View file

@ -0,0 +1,91 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#ifdef __REACTOS__
# include <windows.h>
# include <windef.h>
# include <winbase.h>
# include <net/miniport.h>
# include <winsock2.h>
# include <nspapi.h>
# include <iptypes.h>
# include <ws2tcpip.h>
# include "iphlpapiextra.h"
#else
# include "windef.h"
# include "winbase.h"
# include "winreg.h"
#endif
#include "iphlpapi.h"
#include "ifenum.h"
#include "ipstats.h"
#include "iphlp_res.h"
#include "wine/debug.h"
/*
* @unimplemented
*/
HANDLE STDCALL Icmp6CreateFile(
VOID
)
{
UNIMPLEMENTED
return 0L;
}
/*
* @unimplemented
*/
DWORD
STDCALL
Icmp6SendEcho2(
HANDLE IcmpHandle,
HANDLE Event,
FARPROC ApcRoutine,
PVOID ApcContext,
struct sockaddr_in6 *SourceAddress,
struct sockaddr_in6 *DestinationAddress,
LPVOID RequestData,
WORD RequestSize,
PIP_OPTION_INFORMATION RequestOptions,
LPVOID ReplyBuffer,
DWORD ReplySize,
DWORD Timeout
)
{
UNIMPLEMENTED
return 0L;
}
/*
* @unimplemented
*/
DWORD
STDCALL
Icmp6ParseReplies(
LPVOID ReplyBuffer,
DWORD ReplySize
)
{
UNIMPLEMENTED
return 0L;
}

View file

@ -1,15 +1,92 @@
#ifndef IPPRIVATE_H
#define IPPRIVATE_H
typedef void (*EnumInterfacesFunc)( HANDLE RegHandle, PWCHAR InterfaceName,
PVOID Data );
typedef void (*EnumNameServersFunc)( PWCHAR InterfaceName, PWCHAR Server,
PVOID Data );
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
typedef struct {
int NumServers;
int CurrentName;
PIP_ADDR_STRING AddrString;
} NAME_SERVER_LIST_PRIVATE, *PNAME_SERVER_LIST_PRIVATE;
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#define NTOS_MODE_USER
#include <ntos.h>
#include <ddk/ntddk.h>
#include <rosrtl/string.h>
#include <ntdll/rtl.h>
#include <windows.h>
#include <windef.h>
#include <winbase.h>
#include <net/miniport.h>
#include <winsock2.h>
#include <nspapi.h>
#include <iptypes.h>
#include "iphlpapiextra.h"
#include "ipregprivate.h"
#include "iphlpapi.h"
#include "ifenum.h"
#include "ipstats.h"
#include "iphlp_res.h"
#include "wine/debug.h"
#undef TRACE
#define TRACE(fmt,args...) DbgPrint("(%s:%d - %s) " fmt, __FILE__, __LINE__, __FUNCTION__, ## args)
#include "net/tdiinfo.h"
#include "tcpioctl.h"
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
#ifndef INADDR_NONE
#define INADDR_NONE (~0U)
#endif
#ifndef IFENT_SOFTWARE_LOOPBACK
#define IFENT_SOFTWARE_LOOPBACK 24 /* This is an SNMP constant from rfc1213 */
#endif/*IFENT_SOFTWARE_LOOPBACK*/
#define INDEX_IS_LOOPBACK 0x00800000
/* Type declarations */
#ifndef IFNAMSIZ
#define IFNAMSIZ 0x20
#endif/*IFNAMSIZ*/
#define TCP_REQUEST_QUERY_INFORMATION_INIT { { { 0 } } }
/* No caddr_t in reactos headers */
typedef char *caddr_t;
typedef union _IFEntrySafelySized {
PCHAR MaxSize[sizeof(DWORD) +
sizeof(IFEntry) +
MAX_ADAPTER_DESCRIPTION_LENGTH + 1];
struct {
DWORD ProperlyOffsetTheStructure;
IFEntry ent;
} offset;
} IFEntrySafelySized;
/** Prototypes **/
NTSTATUS openTcpFile(PHANDLE tcpFile);
VOID closeTcpFile(HANDLE tcpFile);
NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile, TDIEntityID **entitySet,
PDWORD numEntities );
VOID tdiFreeThingSet( PVOID things );
#endif/*IPPRIVATE_H*/

View file

@ -3,11 +3,11 @@
int GetLongestChildKeyName( HANDLE RegHandle );
LONG OpenChildKeyRead( HANDLE RegHandle,
PWCHAR ChildKeyName,
PCHAR ChildKeyName,
PHKEY ReturnHandle );
PWCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n );
void ConsumeChildKeyName( PWCHAR Name );
PWCHAR QueryRegistryValueString( HANDLE RegHandle, PWCHAR ValueName );
void ConsumeRegValueString( PWCHAR NameServer );
PCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n );
void ConsumeChildKeyName( PCHAR Name );
PCHAR QueryRegistryValueString( HANDLE RegHandle, PCHAR ValueName );
void ConsumeRegValueString( PCHAR NameServer );
#endif/*IPREGPRIVATE_H*/

View file

@ -0,0 +1,108 @@
/* ipstats.h
* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This module implements functions shared by DLLs that need to get network-
* related statistics. It's meant to hide some platform-specificisms, and
* share code that was previously duplicated.
*/
#ifndef WINE_IPSTATS_H_
#define WINE_IPSTATS_H_
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "iprtrmib.h"
/* Fills in entry's interface stats, using name to find them.
* Returns ERROR_INVALID_PARAMETER if name or entry is NULL, NO_ERROR otherwise.
*/
DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry);
/* Ditto above by index. */
DWORD getInterfaceStatsByIndex(DWORD index, PMIB_IFROW entry);
/* Gets ICMP statistics into stats. Returns ERROR_INVALID_PARAMETER if stats is
* NULL, NO_ERROR otherwise.
*/
DWORD getICMPStats(MIB_ICMP *stats);
/* Gets IP statistics into stats. Returns ERROR_INVALID_PARAMETER if stats is
* NULL, NO_ERROR otherwise.
*/
DWORD getIPStats(PMIB_IPSTATS stats, DWORD family);
/* Gets TCP statistics into stats. Returns ERROR_INVALID_PARAMETER if stats is
* NULL, NO_ERROR otherwise.
*/
DWORD getTCPStats(MIB_TCPSTATS *stats, DWORD family);
/* Gets UDP statistics into stats. Returns ERROR_INVALID_PARAMETER if stats is
* NULL, NO_ERROR otherwise.
*/
DWORD getUDPStats(MIB_UDPSTATS *stats, DWORD family);
/* Route table functions */
DWORD getNumRoutes(void);
/* Minimalist route entry, only has the fields I can actually fill in. How
* these map to the different windows route data structures is up to you.
*/
typedef struct _RouteEntry {
DWORD dest;
DWORD mask;
DWORD gateway;
DWORD ifIndex;
DWORD metric;
} RouteEntry;
typedef struct _RouteTable {
DWORD numRoutes;
RouteEntry routes[1];
} RouteTable;
/* Allocates and returns to you the route table, or NULL if it can't allocate
* enough memory. free() the returned table.
*/
RouteTable *getRouteTable(void);
/* Returns the number of entries in the arp table. */
DWORD getNumArpEntries(void);
/* Allocates and returns to you the arp table, or NULL if it can't allocate
* enough memory. free() the returned table.
*/
PMIB_IPNETTABLE getArpTable(void);
/* Returns the number of entries in the UDP state table. */
DWORD getNumUdpEntries(void);
/* Allocates and returns to you the UDP state table, or NULL if it can't
* allocate enough memory. free() the returned table.
*/
PMIB_UDPTABLE getUdpTable(void);
/* Returns the number of entries in the TCP state table. */
DWORD getNumTcpEntries(void);
/* Allocates and returns to you the TCP state table, or NULL if it can't
* allocate enough memory. free() the returned table.
*/
PMIB_TCPTABLE getTcpTable(void);
#endif /* ndef WINE_IPSTATS_H_ */

View file

@ -0,0 +1,558 @@
/* Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This file implements statistics getting using the /proc filesystem exported
* by Linux, and maybe other OSes.
*/
#include "ipprivate.h"
#include "ipstats.h"
#include "ifenum.h"
#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 ) {
DWORD entityType, returnedLen;
NTSTATUS status;
TCP_REQUEST_QUERY_INFORMATION_EX req;
req.ID.toi_class = INFO_CLASS_GENERIC;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = ENTITY_TYPE_ID;
req.ID.toi_entity = *ent;
status =
DeviceIoControl
( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
&entityType,
sizeof(entityType),
&returnedLen,
NULL );
DPRINT("Ent: %04x:d -> %04x\n",
ent->tei_entity, ent->tei_instance, entityType );
return NT_SUCCESS(status) && entityType == CL_NL_IP;
}
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] ) ) {
DPRINT("Entity %d is an IP Entity\n", i);
if( numRoutes == index ) break;
else numRoutes++;
}
}
DPRINT("Index %d is entity #%d - %04x:%08x\n", index, i,
entitySet[i].tei_entity, entitySet[i].tei_instance );
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 ) );
DPRINT("TdiGetMibForIpEntity(tcpFile %x,entityId %x)\n",
(DWORD)tcpFile, ent->tei_instance);
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 );
DPRINT("TdiGetMibForIpEntity() => {\n"
" ipsi_forwarding ............ %d\n"
" ipsi_defaultttl ............ %d\n"
" ipsi_inreceives ............ %d\n"
" ipsi_indelivers ............ %d\n"
" ipsi_outrequests ........... %d\n"
" ipsi_routingdiscards ....... %d\n"
" ipsi_outdiscards ........... %d\n"
" ipsi_outnoroutes ........... %d\n"
" ipsi_numif ................. %d\n"
" ipsi_numaddr ............... %d\n"
" ipsi_numroutes ............. %d\n"
"} status %08x\n",
entry->ipsi_forwarding,
entry->ipsi_defaultttl,
entry->ipsi_inreceives,
entry->ipsi_indelivers,
entry->ipsi_outrequests,
entry->ipsi_routingdiscards,
entry->ipsi_outdiscards,
entry->ipsi_outnoroutes,
entry->ipsi_numif,
entry->ipsi_numaddr,
entry->ipsi_numroutes,
status);
return status;
}
NTSTATUS tdiGetRoutesForIpEntity
( HANDLE tcpFile, TDIEntityID *ent, int numRoutes, IPRouteEntry *routes ) {
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
NTSTATUS status = STATUS_SUCCESS;
DWORD returnSize;
DPRINT("TdiGetRoutesForIpEntity(tcpFile %x,entityId %x)\n",
(DWORD)tcpFile, ent->tei_instance);
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = IP_MIB_ROUTETABLE_ENTRY_ID;
req.ID.toi_entity = *ent;
status = DeviceIoControl( tcpFile,
IOCTL_TCP_QUERY_INFORMATION_EX,
&req,
sizeof(req),
routes,
sizeof(*routes) * numRoutes,
&returnSize,
NULL );
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;
}
static DWORD getNumWithOneHeader(const char *filename)
{
return 0;
}
DWORD getNumRoutes(void)
{
DWORD numEntities, numRoutes = 0;
TDIEntityID *entitySet;
HANDLE tcpFile;
int i;
NTSTATUS status;
TRACE("called.\n");
status = openTcpFile( &tcpFile );
if( !NT_SUCCESS(status) ) {
TRACE("failure: %08x\n", (int)status );
return 0;
}
status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities );
if( !NT_SUCCESS(status) ) {
TRACE("failure: %08x\n", (int)status );
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) ) {
tdiFreeThingSet( entitySet );
return status;
}
numRoutes += isnmp.ipsi_numroutes;
}
}
TRACE("numRoutes: %d\n", (int)numRoutes);
closeTcpFile( tcpFile );
return numRoutes;
}
VOID HexDump( PCHAR Data, DWORD Len ) {
int i;
for( i = 0; i < Len; i++ ) {
if( !(i & 0xf) ) {
if( i ) fprintf(stderr,"\n");
fprintf(stderr,"%08x:", i);
}
fprintf( stderr, " %02x", Data[i] & 0xff );
}
fprintf(stderr,"\n");
}
RouteTable *getRouteTable(void)
{
RouteTable *out_route_table;
DWORD numRoutes = getNumRoutes(), routesAdded = 0;
IPSNMPInfo snmpInfo;
TDIEntityID ent;
HANDLE tcpFile;
NTSTATUS status = openTcpFile( &tcpFile );
int i;
if( !NT_SUCCESS(status) )
return 0;
out_route_table = HeapAlloc( GetProcessHeap(), 0,
sizeof(RouteTable) +
(sizeof(RouteEntry) * (numRoutes - 1)) );
out_route_table->numRoutes = numRoutes;
for( i = 0; routesAdded < numRoutes; i++ ) {
int j;
IPRouteEntry *route_set;
getNthIpEntity( tcpFile, i, &ent );
tdiGetMibForIpEntity( tcpFile, &ent, &snmpInfo );
route_set = HeapAlloc( GetProcessHeap(), 0,
sizeof( IPRouteEntry ) *
snmpInfo.ipsi_numroutes );
DPRINT( "%d routes in instance %d\n", snmpInfo.ipsi_numroutes, i );
if( !route_set ) {
closeTcpFile( tcpFile );
HeapFree( GetProcessHeap(), 0, out_route_table );
return 0;
}
tdiGetRoutesForIpEntity( tcpFile, &ent, numRoutes, route_set );
DPRINT("Route set returned\n");
#if 0
HexDump( route_set,
sizeof( IPRouteEntry ) *
snmpInfo.ipsi_numroutes );
#endif
for( j = 0; j < snmpInfo.ipsi_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_metric;
}
routesAdded += snmpInfo.ipsi_numroutes;
}
return out_route_table;
}
DWORD getNumArpEntries(void)
{
return getNumWithOneHeader("/proc/net/arp");
}
PMIB_IPNETTABLE getArpTable(void)
{
return 0;
}
DWORD getNumUdpEntries(void)
{
return getNumWithOneHeader("/proc/net/udp");
}
PMIB_UDPTABLE getUdpTable(void)
{
DWORD numEntries = getNumUdpEntries();
PMIB_UDPTABLE ret;
ret = (PMIB_UDPTABLE)calloc(1, sizeof(MIB_UDPTABLE) +
(numEntries - 1) * sizeof(MIB_UDPROW));
if (ret) {
FILE *fp;
/* get from /proc/net/udp, no error if can't */
fp = fopen("/proc/net/udp", "r");
if (fp) {
char buf[512] = { 0 }, *ptr;
/* skip header line */
ptr = fgets(buf, sizeof(buf), fp);
while (ptr && ret->dwNumEntries < numEntries) {
ptr = fgets(buf, sizeof(buf), fp);
if (ptr) {
char *endPtr;
if (ptr && *ptr) {
strtoul(ptr, &endPtr, 16); /* skip */
ptr = endPtr;
}
if (ptr && *ptr) {
ptr++;
ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr,
16);
ptr = endPtr;
}
if (ptr && *ptr) {
ptr++;
ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr,
16);
ptr = endPtr;
}
ret->dwNumEntries++;
}
}
fclose(fp);
}
}
return ret;
}
DWORD getNumTcpEntries(void)
{
return getNumWithOneHeader("/proc/net/tcp");
}
PMIB_TCPTABLE getTcpTable(void)
{
return 0;
}

View file

@ -8,11 +8,13 @@ TARGET_NAME = iphlpapi
TARGET_BASE = 0x777c0000
TARGET_CFLAGS = -DUNICODE -D_UNICODE -D__USE_W32API -Wall -Werror
TARGET_CFLAGS += -DYDEBUG -DUNICODE -D_UNICODE -D__USE_W32API -D__REACTOS__ -D_WIN32_WINNT=0x0500 -Wall
#-Werror
TARGET_SDKLIBS = ntdll.a kernel32.a
TARGET_SDKLIBS = ntdll.a kernel32.a ws2_32.a
TARGET_OBJECTS = $(TARGET_NAME).o registry.o
TARGET_OBJECTS = iphlpapi_main.o icmp.o iphlpv6.o media.o registry.o \
ifenum_reactos.o ipstats_reactos.o resinfo_reactos.o
DEP_OBJECTS = $(TARGET_OBJECTS)

View file

@ -0,0 +1,59 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#ifdef __REACTOS__
# include <windows.h>
# include <windef.h>
# include <winbase.h>
# include <net/miniport.h>
# include <winsock2.h>
# include <nspapi.h>
# include <iptypes.h>
# include "iphlpapiextra.h"
#else
# include "windef.h"
# include "winbase.h"
# include "winreg.h"
#endif
#include "iphlpapi.h"
#include "ifenum.h"
#include "ipstats.h"
#include "iphlp_res.h"
#include "wine/debug.h"
/*
* @unimplemented
*/
DWORD STDCALL DisableMediaSense(HANDLE *pHandle,OVERLAPPED *pOverLapped)
{
UNIMPLEMENTED
return 0L;
}
/*
* @unimplemented
*/
DWORD STDCALL RestoreMediaSense(OVERLAPPED* pOverlapped,LPDWORD lpdwEnableCount)
{
UNIMPLEMENTED
return 0L;
}

View file

@ -0,0 +1,36 @@
GetAdaptersInfo --
Wine uses: Software\\Wine\\Wine\\Config\\Network
-- Wins support is todo so this part isn't so important.
-- Overall, workable
Wine uses ansi functions
GetNetworkParams --
-- Make workable interface for _res
-- Wine based on real _res
-- Reactos based on my enumerator funcs
ROUTE PRINT:
iphlpapi_main.c:137 - ppIfTable 0104bd80, bOrder 1, heap 0xa0000000, flags 0x00000001
- AllocateAndGetIfTableFromStack
iphlpapi_main.c:898 - pIfTable 0104bd00, pdwSize 0104bd00, bOrder 1
- GetIfTable
(tcpip/main.c:168)(TiCreateFileObject) No EA information in IRP.
- We need a special case of no EA information to handle these ioctls in
tcpip.sys
iphlpapi_main.c:939 - returning 122
iphlpapi_main.c:898 - pIfTable 0104bd00, pdwSize 0104bd00, bOrder 1
- GetIfTable again
(tcpip/main.c:168)(TiCreateFileObject) No EA information in IRP.
(tcpip/main.c:168)(TiCreateFileObject) No EA information in IRP.
getInterfaceIndexTable: numInterfaces: 0
iphlpapi_main.c:939 - returning 0
iphlpapi_main.c:149 - returning 0
iphlpapi_main.c:213 - ppIpForwardTable 0104bd78, bOrder 1, heap 0xa0000000, flags 0x00000001
- AllocateAndGetIpForwardTableFromStack
iphlpapi_main.c:1151 - pIpForwardTable 00000000, pdwSize 0104bd00, bOrder 1
- GetIpForwardTable
iphlpapi_main.c:1214 - returning 122
iphlpapi_main.c:1151 - pIpForwardTable a0001d68, pdwSize 0104bd00, bOrder 1
- GetIpForwardTable again
iphlpapi_main.c:1214 - returning 122
iphlpapi_main.c:225 - returning 122

View file

@ -10,7 +10,7 @@ int GetLongestChildKeyName( HANDLE RegHandle ) {
LONG Status;
DWORD MaxAdapterName;
Status = RegQueryInfoKeyW(RegHandle,
Status = RegQueryInfoKeyA(RegHandle,
NULL,
NULL,
NULL,
@ -29,9 +29,9 @@ int GetLongestChildKeyName( HANDLE RegHandle ) {
}
LONG OpenChildKeyRead( HANDLE RegHandle,
PWCHAR ChildKeyName,
PCHAR ChildKeyName,
PHKEY ReturnHandle ) {
return RegOpenKeyExW( RegHandle,
return RegOpenKeyExA( RegHandle,
ChildKeyName,
0,
KEY_READ,
@ -42,10 +42,10 @@ LONG OpenChildKeyRead( HANDLE RegHandle,
* Yields a malloced value that must be freed.
*/
PWCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n ) {
PCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n ) {
LONG Status;
int MaxAdapterName = GetLongestChildKeyName( RegHandle );
PWCHAR Value;
PCHAR Value;
DWORD ValueLen;
if (MaxAdapterName == -1) {
@ -54,8 +54,8 @@ PWCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n ) {
}
ValueLen = MaxAdapterName;
Value = (PWCHAR)malloc( MaxAdapterName * sizeof(WCHAR) );
Status = RegEnumKeyExW( RegHandle, n, Value, &ValueLen,
Value = (PCHAR)HeapAlloc( GetProcessHeap(), 0, MaxAdapterName );
Status = RegEnumKeyExA( RegHandle, n, Value, &ValueLen,
NULL, NULL, NULL, NULL );
if (Status != ERROR_SUCCESS)
return 0;
@ -65,27 +65,27 @@ PWCHAR GetNthChildKeyName( HANDLE RegHandle, DWORD n ) {
}
}
void ConsumeChildKeyName( PWCHAR Name ) {
if (Name) free( Name );
void ConsumeChildKeyName( PCHAR Name ) {
if (Name) HeapFree( GetProcessHeap(), 0, Name );
}
PWCHAR QueryRegistryValueString( HANDLE RegHandle, PWCHAR ValueName ) {
PWCHAR Name;
PCHAR QueryRegistryValueString( HANDLE RegHandle, PCHAR ValueName ) {
PCHAR Name;
DWORD ReturnedSize = 0;
if (RegQueryValueExW( RegHandle, ValueName, NULL, NULL, NULL,
if (RegQueryValueExA( RegHandle, ValueName, NULL, NULL, NULL,
&ReturnedSize ) != 0)
return 0;
else {
Name = malloc( (ReturnedSize + 1) * sizeof(WCHAR) );
RegQueryValueExW( RegHandle, ValueName, NULL, NULL, (PVOID)Name,
RegQueryValueExA( RegHandle, ValueName, NULL, NULL, (PVOID)Name,
&ReturnedSize );
Name[ReturnedSize] = 0;
return Name;
}
}
void ConsumeRegValueString( PWCHAR Value ) {
void ConsumeRegValueString( PCHAR Value ) {
if (Value) free(Value);
}
@ -93,8 +93,8 @@ PWCHAR *QueryRegistryValueStringMulti( HANDLE RegHandle, PWCHAR ValueName ) {
return 0; /* FIXME if needed */
}
void ConsumeRegValueStringMulti( PWCHAR *Value ) {
PWCHAR *Orig = Value;
void ConsumeRegValueStringMulti( PCHAR *Value ) {
PCHAR *Orig = Value;
if (Value) {
while (*Value) {
free(*Value);

View file

@ -0,0 +1,52 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h>
#endif
#ifdef HAVE_RESOLV_H
# include <resolv.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#ifdef __REACTOS__
# include <net/miniport.h> /* ULONGLONG */
# include <winsock2.h> /* Enables NSPAPI */
# include <nspapi.h> /* SOCKET_ADDRESS */
# include <iptypes.h> /* IP_ADAPTER_ADDRESSES */
#endif
#include "iphlpapi.h"
#include "ifenum.h"
#include "ipstats.h"
#include "iphlp_res.h"
#include "wine/debug.h"
PIPHLP_RES_INFO getResInfo() {
PIPHLP_RES_INFO InfoPtr =
(PIPHLP_RES_INFO)HeapAlloc( GetProcessHeap(), 0,
sizeof(PIPHLP_RES_INFO) );
if( InfoPtr ) {
InfoPtr->riCount = 0;
InfoPtr->riAddressList = (LPSOCKADDR)0;
}
return InfoPtr;
}
VOID disposeResInfo( PIPHLP_RES_INFO InfoPtr ) {
HeapFree( GetProcessHeap(), 0, InfoPtr );
}