785 lines
20 KiB
C
785 lines
20 KiB
C
//============================================================================
|
||
// 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
|
||
}
|
||
|
||
|
||
|