You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
785 lines
21 KiB
785 lines
21 KiB
//============================================================================
|
|
// Copyright (c) 1994-95, Microsoft Corp.
|
|
//
|
|
// File: routetab.c
|
|
//
|
|
// History:
|
|
// t-abolag 6/20/95 Adapted from RIP code.
|
|
//
|
|
// Contains API entries for the Routing Table functions
|
|
//============================================================================
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <ctype.h>
|
|
|
|
#ifndef CHICAGO
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include <winsock.h>
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#include <io.h>
|
|
#include <winsvc.h>
|
|
#include "ipinfo.h"
|
|
#include "llinfo.h"
|
|
#include "ntddtcp.h"
|
|
#include "tdiinfo.h"
|
|
|
|
#include "routetab.h"
|
|
#include "rtdefs.h"
|
|
|
|
#include <assert.h>
|
|
|
|
#ifdef CHICAGO
|
|
|
|
#include <wscntl.h>
|
|
|
|
LPWSCONTROL pWsControl = NULL;
|
|
HANDLE hWsock = NULL;
|
|
|
|
#endif
|
|
|
|
|
|
GLOBAL_STRUCT g_rtCfg;
|
|
|
|
|
|
DWORD
|
|
APIENTRY
|
|
GetIfEntry(
|
|
IN DWORD dwIfIndex,
|
|
OUT LPIF_ENTRY lpIfEntry
|
|
)
|
|
{
|
|
DWORD dwErr;
|
|
LPIF_ENTRY lpIf, lpIfEnd;
|
|
|
|
if (lpIfEntry == NULL) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
RT_LOCK();
|
|
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
|
|
lpIfEnd = g_rtCfg.lpIfTable + g_rtCfg.dwIfCount;
|
|
for (lpIf = g_rtCfg.lpIfTable; lpIf < lpIfEnd; lpIf++) {
|
|
if (lpIf->ife_index == dwIfIndex) {
|
|
CopyMemory(lpIfEntry, lpIf, sizeof(IF_ENTRY));
|
|
dwErr = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
RT_UNLOCK();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
APIENTRY
|
|
GetIPAddressTable(
|
|
OUT LPIPADDRESS_ENTRY *lplpAddrTable,
|
|
OUT LPDWORD lpdwAddrCount
|
|
)
|
|
{
|
|
DWORD dwErr, dwCount;
|
|
LPIPADDRESS_ENTRY lpAddresses;
|
|
|
|
if (lpdwAddrCount == NULL || lplpAddrTable == NULL) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
RT_LOCK();
|
|
|
|
dwCount = g_rtCfg.dwIPAddressCount;
|
|
lpAddresses = (LPIPADDRESS_ENTRY)HeapAlloc(
|
|
GetProcessHeap(), 0,
|
|
dwCount * sizeof(IPADDRESS_ENTRY)
|
|
);
|
|
if (lpAddresses == NULL) {
|
|
*lpdwAddrCount = 0;
|
|
*lplpAddrTable = NULL;
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else {
|
|
CopyMemory(lpAddresses, g_rtCfg.lpIPAddressTable,
|
|
dwCount * sizeof(IPADDRESS_ENTRY));
|
|
|
|
*lpdwAddrCount = dwCount;
|
|
*lplpAddrTable = lpAddresses;
|
|
dwErr = 0;
|
|
}
|
|
|
|
RT_UNLOCK();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
APIENTRY
|
|
ReloadIPAddressTable(
|
|
OUT LPIPADDRESS_ENTRY *lplpAddrTable,
|
|
OUT LPDWORD lpdwAddrCount
|
|
)
|
|
{
|
|
|
|
DWORD dwErr, dwCount;
|
|
LPIPADDRESS_ENTRY lpAddresses;
|
|
|
|
|
|
if (lpdwAddrCount == NULL || lplpAddrTable == NULL) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
do
|
|
{
|
|
RT_LOCK();
|
|
|
|
if (g_rtCfg.lpIfTable != NULL) {
|
|
|
|
HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIfTable);
|
|
|
|
g_rtCfg.lpIfTable = NULL;
|
|
}
|
|
|
|
if (g_rtCfg.lpIPAddressTable != NULL) {
|
|
|
|
HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIPAddressTable);
|
|
|
|
g_rtCfg.lpIPAddressTable = NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// reload the tables
|
|
//
|
|
|
|
dwErr = RTGetTables(
|
|
&g_rtCfg.lpIfTable, &g_rtCfg.dwIfCount,
|
|
&g_rtCfg.lpIPAddressTable, &g_rtCfg.dwIPAddressCount
|
|
);
|
|
|
|
|
|
if (dwErr != 0) {
|
|
|
|
RT_UNLOCK();
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
dwCount = g_rtCfg.dwIPAddressCount;
|
|
lpAddresses = (LPIPADDRESS_ENTRY)HeapAlloc(
|
|
GetProcessHeap(), 0,
|
|
dwCount * sizeof(IPADDRESS_ENTRY)
|
|
);
|
|
if (lpAddresses == NULL) {
|
|
|
|
*lpdwAddrCount = 0;
|
|
*lplpAddrTable = NULL;
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
else {
|
|
|
|
CopyMemory(lpAddresses, g_rtCfg.lpIPAddressTable,
|
|
dwCount * sizeof(IPADDRESS_ENTRY));
|
|
|
|
*lpdwAddrCount = dwCount;
|
|
*lplpAddrTable = lpAddresses;
|
|
dwErr = 0;
|
|
}
|
|
|
|
RT_UNLOCK();
|
|
|
|
} while (FALSE);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
/*
|
|
*------------------------------------------------------------------
|
|
* Function: FreeIPAddressTable
|
|
*
|
|
* Parameters:
|
|
* LPIPADDRESS_ENTRY
|
|
* lpAddrTable the address table to be freed.
|
|
*
|
|
* This function frees the memory allocated for an address table.
|
|
* It returns 0 if successful and non-zero otherwise.
|
|
*------------------------------------------------------------------
|
|
*/
|
|
DWORD
|
|
APIENTRY
|
|
FreeIPAddressTable(
|
|
IN LPIPADDRESS_ENTRY lpAddrTable
|
|
)
|
|
{
|
|
if (lpAddrTable != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, lpAddrTable);
|
|
return 0;
|
|
}
|
|
else {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*------------------------------------------------------------------
|
|
* Function: GetRouteTable
|
|
*
|
|
* Parameters:
|
|
* LPIPROUTE_ENTRY
|
|
* *lplpRouteTable pointer to an LPIPROUTE_ENTRY
|
|
* which receives the routing table
|
|
* LPDWORD lpdwRouteCount pointer to a DWORD which receives
|
|
* the number of routing entries
|
|
*
|
|
* This function allocates and fills in an array of routing table
|
|
* entries from the Tcpip driver. It also sets the number of
|
|
* entries in the array in the DWORD pointed to by lpdwRouteCount.
|
|
*
|
|
* In the IPROUTE_ENTRY structure, the only metric used by
|
|
* the Tcpip stack is IPROUTE_ENTRY.ire_metric1; the other metric
|
|
* fields should be ignored.
|
|
*
|
|
* Call FreeRouteTable to free the memory allocated for the
|
|
* routing table.
|
|
*
|
|
* It returns 0 if successful and non-zero otherwise
|
|
*------------------------------------------------------------------
|
|
*/
|
|
DWORD
|
|
APIENTRY
|
|
GetRouteTable(
|
|
OUT LPIPROUTE_ENTRY *lplpRouteTable,
|
|
OUT LPDWORD lpdwRouteCount
|
|
)
|
|
{
|
|
ULONG_PTR *lpContext;
|
|
IPSNMPInfo ipsiInfo;
|
|
TDIObjectID *lpObject;
|
|
|
|
DWORD dwRouteCount;
|
|
LPIPROUTE_ENTRY lpRouteEntryTable;
|
|
|
|
DWORD dwErr, dwInSize, dwOutSize;
|
|
TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
|
|
|
|
|
|
// first get route count
|
|
dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
|
|
dwOutSize = sizeof(IPSNMPInfo);
|
|
|
|
lpContext = trqiBuffer.Context;
|
|
ZeroMemory(lpContext, CONTEXT_SIZE);
|
|
|
|
lpObject = &trqiBuffer.ID;
|
|
lpObject->toi_id = IP_MIB_STATS_ID;
|
|
lpObject->toi_type = INFO_TYPE_PROVIDER;
|
|
lpObject->toi_class = INFO_CLASS_PROTOCOL;
|
|
lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
|
|
lpObject->toi_entity.tei_instance = 0;
|
|
|
|
RT_LOCK();
|
|
dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize,
|
|
&ipsiInfo, &dwOutSize);
|
|
RT_UNLOCK();
|
|
if (dwErr != NO_ERROR || ipsiInfo.ipsi_numroutes == 0) {
|
|
return dwErr;
|
|
}
|
|
|
|
dwRouteCount = ipsiInfo.ipsi_numroutes;
|
|
|
|
// now get route table
|
|
dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
|
|
dwOutSize = dwRouteCount * sizeof(IPROUTE_ENTRY);
|
|
lpRouteEntryTable = HeapAlloc(GetProcessHeap(), 0, dwOutSize);
|
|
|
|
lpObject->toi_id = IP_MIB_RTTABLE_ENTRY_ID;
|
|
lpObject->toi_class = INFO_CLASS_PROTOCOL;
|
|
lpObject->toi_type = INFO_TYPE_PROVIDER;
|
|
lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
|
|
lpObject->toi_entity.tei_instance = 0;
|
|
|
|
RT_LOCK();
|
|
dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize,
|
|
lpRouteEntryTable, &dwOutSize);
|
|
RT_UNLOCK();
|
|
if (dwErr != NO_ERROR) {
|
|
HeapFree(GetProcessHeap(), 0, lpRouteEntryTable);
|
|
return dwErr;
|
|
}
|
|
|
|
*lpdwRouteCount = dwRouteCount;
|
|
*lplpRouteTable = lpRouteEntryTable;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*------------------------------------------------------------------
|
|
* Function: FreeRouteTable
|
|
*
|
|
* Parameters:
|
|
* LPIPROUTE_ENTRY
|
|
* lpRouteTable the routing table to be freed.
|
|
*
|
|
* This function frees the memory allocated for a routing table.
|
|
* It returns 0 if successful and non-zero otherwise.
|
|
*------------------------------------------------------------------
|
|
*/
|
|
DWORD
|
|
APIENTRY
|
|
FreeRouteTable(
|
|
IN LPIPROUTE_ENTRY lpRouteTable
|
|
)
|
|
{
|
|
if (lpRouteTable != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, lpRouteTable);
|
|
return 0;
|
|
}
|
|
else {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
*------------------------------------------------------------------
|
|
* Function: SetAddrChangeNotifyEvent
|
|
*
|
|
* Parameters:
|
|
* HANDLE hEvent the event to be signalled if the
|
|
* IP address of a local interface changes
|
|
*
|
|
* This function sets the event to be signalled if any IP address
|
|
* for any interfaces is changed either via DHCP client activity
|
|
* or manually in the Network Control Panel. This notification is
|
|
* optional.
|
|
*
|
|
* Returns 0 if successful, non-zero otherwise.
|
|
*------------------------------------------------------------------
|
|
*/
|
|
DWORD
|
|
APIENTRY
|
|
SetAddrChangeNotifyEvent(
|
|
HANDLE hEvent
|
|
)
|
|
{
|
|
RT_LOCK();
|
|
|
|
g_rtCfg.hUserNotifyEvent = hEvent;
|
|
|
|
RT_UNLOCK();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
DWORD UpdateRoute(DWORD dwProtocol, DWORD dwType, DWORD dwIndex,
|
|
DWORD dwDestVal, DWORD dwMaskVal, DWORD dwGateVal,
|
|
DWORD dwMetric, BOOL bAddRoute)
|
|
{
|
|
TDIObjectID *lpObject;
|
|
IPRouteEntry *lpentry;
|
|
|
|
DWORD dwErr, dwInSize, dwOutSize;
|
|
|
|
TCP_REQUEST_SET_INFORMATION_EX *lptrsiBuffer;
|
|
BYTE buffer[sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IPRouteEntry)];
|
|
|
|
lptrsiBuffer = (TCP_REQUEST_SET_INFORMATION_EX *)buffer;
|
|
|
|
lptrsiBuffer->BufferSize = sizeof(IPRouteEntry);
|
|
|
|
lpObject = &lptrsiBuffer->ID;
|
|
lpObject->toi_id = IP_MIB_RTTABLE_ENTRY_ID;
|
|
lpObject->toi_type = INFO_TYPE_PROVIDER;
|
|
lpObject->toi_class = INFO_CLASS_PROTOCOL;
|
|
lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
|
|
lpObject->toi_entity.tei_instance = 0;
|
|
|
|
lpentry = (IPRouteEntry *)lptrsiBuffer->Buffer;
|
|
lpentry->ire_dest = dwDestVal;
|
|
lpentry->ire_mask = dwMaskVal;
|
|
lpentry->ire_index = dwIndex;
|
|
lpentry->ire_metric1 = dwMetric;
|
|
lpentry->ire_metric2 =
|
|
lpentry->ire_metric3 =
|
|
lpentry->ire_metric4 =
|
|
lpentry->ire_metric5 = IRE_METRIC_UNUSED;
|
|
lpentry->ire_nexthop = dwGateVal;
|
|
lpentry->ire_type = (bAddRoute ? dwType : IRE_TYPE_INVALID);
|
|
lpentry->ire_proto = dwProtocol;
|
|
lpentry->ire_age = 0;
|
|
|
|
dwOutSize = 0;
|
|
dwInSize = sizeof(TCP_REQUEST_SET_INFORMATION_EX) +
|
|
sizeof(IPRouteEntry) - 1;
|
|
|
|
RT_LOCK();
|
|
|
|
dwErr = TCPSetInformationEx((LPVOID)lptrsiBuffer, &dwInSize,
|
|
NULL, &dwOutSize);
|
|
|
|
RT_UNLOCK();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
/*
|
|
*------------------------------------------------------------------
|
|
* Function: AddRoute
|
|
*
|
|
* Parameters:
|
|
* DWORD dwProtocol protocol of specified route
|
|
* DWORD dwType type of specified route
|
|
* DWORD dwDestVal destination IP addr (network order)
|
|
* DWORD dwMaskVal destination subnet mask, or zero
|
|
* if no subnet (network order)
|
|
* DWORD dwGateVal next hop IP addr (network order)
|
|
* DWORD dwMetric metric
|
|
*
|
|
* This function adds a new route (or updates an existing route)
|
|
* for the specified protocol, on the specified interface.
|
|
* (See above for values which can be used as protocol numbers,
|
|
* as well as values which can be used as route entry types.)
|
|
*
|
|
* Returns 0 if successful, non-zero otherwise.
|
|
*------------------------------------------------------------------
|
|
*/
|
|
|
|
DWORD
|
|
APIENTRY
|
|
AddRoute(
|
|
IN DWORD dwProtocol,
|
|
IN DWORD dwType,
|
|
IN DWORD dwIndex,
|
|
IN DWORD dwDestVal,
|
|
IN DWORD dwMaskVal,
|
|
IN DWORD dwGateVal,
|
|
IN DWORD dwMetric
|
|
)
|
|
{
|
|
return UpdateRoute(dwProtocol, dwType, dwIndex, dwDestVal,
|
|
dwMaskVal, dwGateVal, dwMetric, TRUE);
|
|
}
|
|
|
|
|
|
/*
|
|
*------------------------------------------------------------------
|
|
* Function: DeleteRoute
|
|
*
|
|
* Parameters:
|
|
* DWORD dwIndex index of interface to delete from
|
|
* DWORD dwDestVal destination IP addr (network order)
|
|
* DWORD dwMaskVal subnet mask (network order)
|
|
* DWORD dwGateVal next hop IP addr (network order)
|
|
*
|
|
* This function deletes a route for the specified protocol.
|
|
* See comments for AddRoute() for information on the use of
|
|
* the argument dwMaskVal.
|
|
*
|
|
* Returns 0 if successful, non-zero otherwise.
|
|
*------------------------------------------------------------------
|
|
*/
|
|
DWORD
|
|
APIENTRY
|
|
DeleteRoute(
|
|
IN DWORD dwIndex,
|
|
IN DWORD dwDestVal,
|
|
IN DWORD dwMaskVal,
|
|
IN DWORD dwGateVal
|
|
)
|
|
{
|
|
return UpdateRoute(IRE_PROTO_OTHER, IRE_TYPE_INVALID, dwIndex, dwDestVal,
|
|
dwMaskVal, dwGateVal, IRE_METRIC_UNUSED, FALSE);
|
|
}
|
|
|
|
/*
|
|
*------------------------------------------------------------------
|
|
* Function: RefreshAddresses
|
|
*
|
|
* Parameters:
|
|
*
|
|
* This function is added for RSVP
|
|
*
|
|
* This function prods this code into refreshing its address tables with
|
|
* the IP stack, just as if it had received a DHCP event notification.
|
|
* This is needed because address change notifications coming through winsock
|
|
* can arrive before the DHCP event has been set, which would normally cause
|
|
* routetab to refresh its addresses.s
|
|
*
|
|
* Returns 0 if successful, non-zero otherwise.
|
|
*------------------------------------------------------------------
|
|
*/
|
|
DWORD
|
|
APIENTRY
|
|
RefreshAddresses(
|
|
)
|
|
{
|
|
DWORD Error;
|
|
|
|
Error = RTGetTables( &g_rtCfg.lpIfTable, &g_rtCfg.dwIfCount,
|
|
&g_rtCfg.lpIPAddressTable, &g_rtCfg.dwIPAddressCount );
|
|
|
|
return( Error );
|
|
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
// Function: OpenTcp
|
|
//
|
|
// Parameters:
|
|
// none.
|
|
//
|
|
// Opens the handle to the Tcpip driver.
|
|
//------------------------------------------------------------------
|
|
|
|
DWORD OpenTcp()
|
|
{
|
|
#ifdef CHICAGO
|
|
|
|
WSADATA wsaData;
|
|
|
|
|
|
hWsock = LoadLibrary(TEXT("wsock32.dll"));
|
|
if(! hWsock ){
|
|
DEBUG_PRINT(("RTStartup: can't load wsock32.dll, %d\n",
|
|
GetLastError()));
|
|
DEBUG_PRINT(("OpenTcp: !hWsock\n"));
|
|
return 1;
|
|
}
|
|
|
|
pWsControl = (LPWSCONTROL) GetProcAddress(hWsock, "WsControl");
|
|
|
|
if (! pWsControl ){
|
|
DEBUG_PRINT((
|
|
"RTStartup: GetProcAddress(wsock32,WsControl) failed %d\n",
|
|
GetLastError()));
|
|
return 1;
|
|
}
|
|
|
|
if (WSAStartup(MAKEWORD(1, 1), &wsaData)) {
|
|
DEBUG_PRINT((
|
|
"RTStartup: error %d initializing Windows Sockets.",
|
|
WSAGetLastError()));
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
NTSTATUS status;
|
|
UNICODE_STRING nameString;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
|
|
// Open the ip stack for setting routes and parps later.
|
|
//
|
|
// Open a Handle to the TCP driver.
|
|
//
|
|
RtlInitUnicodeString(&nameString, DD_TCP_DEVICE_NAME);
|
|
|
|
InitializeObjectAttributes(&objectAttributes, &nameString,
|
|
OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
|
|
status = NtCreateFile(&g_rtCfg.hTCPHandle,
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&objectAttributes, &ioStatusBlock, NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF, 0, NULL, 0);
|
|
|
|
return (status == STATUS_SUCCESS ? 0 : ERROR_OPEN_FAILED);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// Function: TCPQueryInformationEx
|
|
//
|
|
// Parameters:
|
|
// TDIObjectID *ID The TDI Object ID to query
|
|
// void *Buffer buffer to contain the query results
|
|
// LPDWORD *BufferSize pointer to the size of the buffer
|
|
// filled in with the amount of data.
|
|
// UCHAR *Context context value for the query. should
|
|
// be zeroed for a new query. It will be
|
|
// filled with context information for
|
|
// linked enumeration queries.
|
|
//
|
|
// Returns:
|
|
// An NTSTATUS value.
|
|
//
|
|
// This routine provides the interface to the TDI QueryInformationEx
|
|
// facility of the TCP/IP stack on NT.
|
|
//---------------------------------------------------------------------
|
|
DWORD TCPQueryInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
|
|
LPVOID lpvOutBuffer, LPDWORD lpdwOutSize)
|
|
{
|
|
#ifdef CHICAGO
|
|
DWORD result;
|
|
|
|
if( ! pWsControl )
|
|
OpenTcp();
|
|
if( ! pWsControl ){
|
|
DEBUG_PRINT(("TCPQueryInformationEx: !pWsControl.\n"));
|
|
return 0;
|
|
}
|
|
|
|
assert( pWsControl );
|
|
result = (
|
|
(*pWsControl)(
|
|
IPPROTO_TCP,
|
|
WSCNTL_TCPIP_QUERY_INFO,
|
|
lpvInBuffer, // InBuf,
|
|
lpdwInSize , // InBufLen,
|
|
lpvOutBuffer, // OutBuf,
|
|
lpdwOutSize // OutBufLen
|
|
) );
|
|
return result;
|
|
#else
|
|
|
|
NTSTATUS status;
|
|
IO_STATUS_BLOCK isbStatusBlock;
|
|
|
|
if (g_rtCfg.hTCPHandle == NULL) {
|
|
OpenTcp();
|
|
}
|
|
|
|
status = NtDeviceIoControlFile(g_rtCfg.hTCPHandle, // Driver handle
|
|
NULL, // Event
|
|
NULL, // APC Routine
|
|
NULL, // APC context
|
|
&isbStatusBlock, // Status block
|
|
IOCTL_TCP_QUERY_INFORMATION_EX, // Control
|
|
lpvInBuffer, // Input buffer
|
|
*lpdwInSize, // Input buffer size
|
|
lpvOutBuffer, // Output buffer
|
|
*lpdwOutSize); // Output buffer size
|
|
|
|
if (status == STATUS_PENDING) {
|
|
status = NtWaitForSingleObject(g_rtCfg.hTCPHandle, TRUE, NULL);
|
|
status = isbStatusBlock.Status;
|
|
}
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
*lpdwOutSize = 0;
|
|
}
|
|
else {
|
|
*lpdwOutSize = (ULONG)isbStatusBlock.Information;
|
|
}
|
|
|
|
return status;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Function: TCPSetInformationEx
|
|
//
|
|
// Parameters:
|
|
//
|
|
// TDIObjectID *ID the TDI Object ID to set
|
|
// void *lpvBuffer data buffer containing the information
|
|
// to be set
|
|
// DWORD dwBufferSize the size of the data buffer.
|
|
//
|
|
// This routine provides the interface to the TDI SetInformationEx
|
|
// facility of the TCP/IP stack on NT.
|
|
//---------------------------------------------------------------------------
|
|
DWORD TCPSetInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
|
|
LPVOID lpvOutBuffer, LPDWORD lpdwOutSize)
|
|
{
|
|
#ifdef CHICAGO
|
|
DWORD result;
|
|
|
|
if( ! pWsControl )
|
|
OpenTcp();
|
|
if( ! pWsControl ){
|
|
DEBUG_PRINT(("TCPSetInformationEx: !pWsControl \n"));
|
|
return 0;
|
|
}
|
|
assert( pWsControl );
|
|
|
|
result = (
|
|
(*pWsControl)(
|
|
IPPROTO_TCP,
|
|
WSCNTL_TCPIP_SET_INFO,
|
|
lpvInBuffer, // InBuf,
|
|
lpdwInSize, // InBufLen,
|
|
lpvOutBuffer, // OutBuf,
|
|
lpdwOutSize // OutBufLen
|
|
) );
|
|
return result;
|
|
|
|
#else
|
|
|
|
NTSTATUS status;
|
|
IO_STATUS_BLOCK isbStatusBlock;
|
|
|
|
if (g_rtCfg.hTCPHandle == NULL) {
|
|
OpenTcp();
|
|
}
|
|
|
|
status = NtDeviceIoControlFile(g_rtCfg.hTCPHandle, // Driver handle
|
|
NULL, // Event
|
|
NULL, // APC Routine
|
|
NULL, // APC context
|
|
&isbStatusBlock, // Status block
|
|
IOCTL_TCP_SET_INFORMATION_EX, // Control
|
|
lpvInBuffer, // Input buffer
|
|
*lpdwInSize, // Input buffer size
|
|
lpvOutBuffer, // Output buffer
|
|
*lpdwOutSize); // Output buffer size
|
|
|
|
if (status == STATUS_PENDING) {
|
|
status = NtWaitForSingleObject(g_rtCfg.hTCPHandle, TRUE, NULL);
|
|
status = isbStatusBlock.Status;
|
|
}
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
*lpdwOutSize = 0;
|
|
}
|
|
else {
|
|
*lpdwOutSize = (ULONG)isbStatusBlock.Information;
|
|
}
|
|
|
|
return status;
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|