mirror of https://github.com/tongzx/nt5src
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.
1412 lines
31 KiB
1412 lines
31 KiB
/*++
|
|
|
|
Copyright (c) 1998, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rmapi.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code for the part of the router-manager interface
|
|
which is common to all the protocols in this component.
|
|
|
|
Author:
|
|
|
|
Abolade Gbadegesin (aboladeg) 4-Mar-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include <ras.h>
|
|
#include <rasuip.h>
|
|
#include <raserror.h>
|
|
#include <ipinfo.h>
|
|
#include "beacon.h"
|
|
|
|
#include <atlbase.h>
|
|
CComModule _Module;
|
|
#include <atlcom.h>
|
|
#include "nathlp_i.c"
|
|
|
|
BEGIN_OBJECT_MAP(ObjectMap)
|
|
OBJECT_ENTRY(CLSID_SAUpdate, CSharedAccessUpdate)
|
|
END_OBJECT_MAP()
|
|
|
|
|
|
extern "C" {
|
|
#include <iphlpstk.h>
|
|
}
|
|
|
|
HANDLE NhpComponentEvent = NULL;
|
|
NH_COMPONENT_MODE NhComponentMode = NhUninitializedMode;
|
|
const WCHAR NhpDhcpDomainString[] = L"DhcpDomain";
|
|
const WCHAR NhpDomainString[] = L"Domain";
|
|
const WCHAR NhpEnableProxy[] = L"EnableProxy";
|
|
LONG NhpIsWinsProxyEnabled = -1;
|
|
CRITICAL_SECTION NhLock;
|
|
HMODULE NhpRtrmgrDll = NULL;
|
|
LIST_ENTRY NhApplicationSettingsList;
|
|
LIST_ENTRY NhDhcpReservationList;
|
|
DWORD NhDhcpScopeAddress = 0;
|
|
DWORD NhDhcpScopeMask = 0;
|
|
const WCHAR NhTcpipParametersString[] =
|
|
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services"
|
|
L"\\Tcpip\\Parameters";
|
|
|
|
//
|
|
// EXTERNAL DECLARATIONS
|
|
//
|
|
|
|
BOOL
|
|
APIENTRY
|
|
DllMain(
|
|
HINSTANCE Instance,
|
|
ULONG Reason,
|
|
PVOID Unused
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Standard DLL entry/exit routine.
|
|
Initializes/shuts-down the modules implemented in the DLL.
|
|
The initialization performed is sufficient that all the modules'
|
|
interface lists can be searched, whether or not the protocols are
|
|
installed or operational.
|
|
|
|
Arguments:
|
|
|
|
Instance - the instance of this DLL in this process
|
|
|
|
Reason - the reason for invocation
|
|
|
|
Unused - unused.
|
|
|
|
Return Value:
|
|
|
|
BOOL - indicates success or failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (Reason) {
|
|
case DLL_PROCESS_ATTACH: {
|
|
WSADATA wd;
|
|
DisableThreadLibraryCalls(Instance);
|
|
__try {
|
|
InitializeCriticalSection(&NhLock);
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
WSAStartup(MAKEWORD(2,2), &wd);
|
|
NhInitializeTraceManagement();
|
|
NhInitializeEventLogManagement();
|
|
InitializeListHead(&NhApplicationSettingsList);
|
|
InitializeListHead(&NhDhcpReservationList);
|
|
if (NhInitializeBufferManagement()) { return FALSE; }
|
|
if (NhInitializeTimerManagement()) { return FALSE; }
|
|
if (!NatInitializeModule()) { return FALSE; }
|
|
if (!DhcpInitializeModule()) { return FALSE; }
|
|
if (!DnsInitializeModule()) { return FALSE; }
|
|
#ifndef NO_FTP_PROXY
|
|
if (!FtpInitializeModule()) { return FALSE; }
|
|
#endif
|
|
if (!AlgInitializeModule()) { return FALSE; }
|
|
if (!H323InitializeModule()) { return FALSE; }
|
|
if(FAILED(InitializeBeaconSvr())) { return FALSE; }
|
|
|
|
_Module.Init(ObjectMap, Instance, &LIBID_IPNATHelperLib);
|
|
_Module.RegisterTypeLib();
|
|
break;
|
|
}
|
|
case DLL_PROCESS_DETACH: {
|
|
NhResetComponentMode();
|
|
TerminateBeaconSvr();
|
|
H323CleanupModule();
|
|
#ifndef NO_FTP_PROXY
|
|
FtpCleanupModule();
|
|
#endif
|
|
AlgCleanupModule();
|
|
DnsCleanupModule();
|
|
DhcpCleanupModule();
|
|
NatCleanupModule();
|
|
NhShutdownTimerManagement();
|
|
NhShutdownBufferManagement();
|
|
NhShutdownEventLogManagement();
|
|
NhShutdownTraceManagement();
|
|
WSACleanup();
|
|
if (NhpRtrmgrDll) {
|
|
FreeLibrary(NhpRtrmgrDll); NhpRtrmgrDll = NULL;
|
|
}
|
|
DeleteCriticalSection(&NhLock);
|
|
|
|
_Module.Term();
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} // DllMain
|
|
|
|
|
|
VOID
|
|
NhBuildDhcpReservations(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Builds the list of DHCP reservations
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Environment:
|
|
|
|
Invoked with NhLock held on a COM-initialized thread.
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr;
|
|
IHNetCfgMgr *pCfgMgr = NULL;
|
|
IEnumHNetPortMappingBindings *pEnumBindings;
|
|
IHNetIcsSettings *pIcsSettings;
|
|
PNAT_DHCP_RESERVATION pReservation;
|
|
ULONG ulCount;
|
|
|
|
hr = NhGetHNetCfgMgr(&pCfgMgr);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the ICS settings interface
|
|
//
|
|
|
|
hr = pCfgMgr->QueryInterface(
|
|
IID_PPV_ARG(IHNetIcsSettings, &pIcsSettings)
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get DHCP scope information
|
|
//
|
|
|
|
hr = pIcsSettings->GetDhcpScopeSettings(
|
|
&NhDhcpScopeAddress,
|
|
&NhDhcpScopeMask
|
|
);
|
|
|
|
//
|
|
// Get enumeration of DHCP reservered addresses
|
|
//
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIcsSettings->EnumDhcpReservedAddresses(&pEnumBindings);
|
|
}
|
|
|
|
pIcsSettings->Release();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Process the items in the enum
|
|
//
|
|
|
|
do
|
|
{
|
|
IHNetPortMappingBinding *pBinding;
|
|
|
|
hr = pEnumBindings->Next(1, &pBinding, &ulCount);
|
|
|
|
if (SUCCEEDED(hr) && 1 == ulCount)
|
|
{
|
|
//
|
|
// Allocate a new reservation entry
|
|
//
|
|
|
|
pReservation = reinterpret_cast<PNAT_DHCP_RESERVATION>(
|
|
NH_ALLOCATE(sizeof(*pReservation))
|
|
);
|
|
|
|
if (NULL != pReservation)
|
|
{
|
|
ZeroMemory(pReservation, sizeof(*pReservation));
|
|
|
|
//
|
|
// Get computer name
|
|
//
|
|
|
|
hr = pBinding->GetTargetComputerName(
|
|
&pReservation->Name
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get reserved address
|
|
//
|
|
|
|
hr = pBinding->GetTargetComputerAddress(
|
|
&pReservation->Address
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Add entry to list
|
|
//
|
|
|
|
InsertTailList(
|
|
&NhDhcpReservationList,
|
|
&pReservation->Link)
|
|
;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Free entry
|
|
//
|
|
|
|
NH_FREE(pReservation);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
pBinding->Release();
|
|
}
|
|
} while (SUCCEEDED(hr) && 1 == ulCount);
|
|
|
|
pEnumBindings->Release();
|
|
}
|
|
|
|
if (NULL != pCfgMgr)
|
|
{
|
|
pCfgMgr->Release();
|
|
}
|
|
} // NhBuildDhcpReservations
|
|
|
|
|
|
ULONG
|
|
NhDialSharedConnection(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to connect a home-router interface.
|
|
The connection is established by invoking the RAS autodial process
|
|
with the appropriate phonebook and entry-name in the security context
|
|
of the logged-on user.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
ULONG - Win32 status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
return RasAutoDialSharedConnection();
|
|
} // NhDialSharedConnection
|
|
|
|
|
|
VOID
|
|
NhFreeApplicationSettings(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Frees the list of application settings
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Environment:
|
|
|
|
Invoked with NhLock held.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLIST_ENTRY Link;
|
|
PNAT_APP_ENTRY pAppEntry;
|
|
|
|
PROFILE("NhFreeApplicationSettings");
|
|
|
|
while (!IsListEmpty(&NhApplicationSettingsList))
|
|
{
|
|
Link = RemoveHeadList(&NhApplicationSettingsList);
|
|
pAppEntry = CONTAINING_RECORD(Link, NAT_APP_ENTRY, Link);
|
|
|
|
CoTaskMemFree(pAppEntry->ResponseArray);
|
|
NH_FREE(pAppEntry);
|
|
}
|
|
} // NhFreeApplicationSettings
|
|
|
|
|
|
VOID
|
|
NhFreeDhcpReservations(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Frees the list of DHCP reservations
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
Environment:
|
|
|
|
Invoked with NhLock held.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLIST_ENTRY Link;
|
|
PNAT_DHCP_RESERVATION pReservation;
|
|
|
|
PROFILE("NhFreeDhcpReservations");
|
|
|
|
while (!IsListEmpty(&NhDhcpReservationList))
|
|
{
|
|
Link = RemoveHeadList(&NhDhcpReservationList);
|
|
pReservation = CONTAINING_RECORD(Link, NAT_DHCP_RESERVATION, Link);
|
|
|
|
CoTaskMemFree(pReservation->Name);
|
|
NH_FREE(pReservation);
|
|
}
|
|
} // NhFreeDhcpReservations
|
|
|
|
|
|
BOOLEAN
|
|
NhIsDnsProxyEnabled(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to discover whether the DNS proxy is enabled.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if DNS proxy is enabled, FALSE otherwise
|
|
|
|
Environment:
|
|
|
|
Invoked from an arbitrary context.
|
|
|
|
--*/
|
|
|
|
{
|
|
PROFILE("NhIsDnsProxyEnabled");
|
|
|
|
return DnsIsDnsEnabled();
|
|
|
|
} // NhIsDnsProxyEnabled
|
|
|
|
|
|
BOOLEAN
|
|
NhIsLocalAddress(
|
|
ULONG Address
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to determine whether the given IP address
|
|
is for a local interface.
|
|
|
|
Arguments:
|
|
|
|
Address - the IP address to find
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if the address is found, FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Error;
|
|
ULONG i;
|
|
PMIB_IPADDRTABLE Table;
|
|
|
|
Error =
|
|
AllocateAndGetIpAddrTableFromStack(
|
|
&Table, FALSE, GetProcessHeap(), 0
|
|
);
|
|
if (Error) {
|
|
NhTrace(
|
|
TRACE_FLAG_IF,
|
|
"NhIsLocalAddress: GetIpAddrTableFromStack=%d", Error
|
|
);
|
|
return FALSE;
|
|
}
|
|
for (i = 0; i < Table->dwNumEntries; i++) {
|
|
if (Table->table[i].dwAddr == Address) {
|
|
HeapFree(GetProcessHeap(), 0, Table);
|
|
return TRUE;
|
|
}
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, Table);
|
|
return FALSE;
|
|
|
|
} // NhIsLocalAddress
|
|
|
|
|
|
BOOLEAN
|
|
NhIsWinsProxyEnabled(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to discover whether the WINS proxy is enabled.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if WINS proxy is enabled, FALSE otherwise
|
|
|
|
Environment:
|
|
|
|
Invoked from an arbitrary context.
|
|
|
|
--*/
|
|
|
|
{
|
|
PROFILE("NhIsWinsProxyEnabled");
|
|
|
|
return DnsIsWinsEnabled();
|
|
|
|
} // NhIsWinsProxyEnabled
|
|
|
|
|
|
PIP_ADAPTER_BINDING_INFO
|
|
NhQueryBindingInformation(
|
|
ULONG AdapterIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to obtain the binding information
|
|
for the adapter with the given index.
|
|
It does this by obtaining a table of IP addresses from the stack,
|
|
and determining which addresses correspond to the given index.
|
|
|
|
Arguments:
|
|
|
|
AdapterIndex - the adapter for which binding information is required
|
|
|
|
Return Value:
|
|
|
|
PIP_ADAPTER_BINDING_INFO - the allocated binding information
|
|
|
|
--*/
|
|
|
|
{
|
|
PIP_ADAPTER_BINDING_INFO BindingInfo = NULL;
|
|
ULONG Count = 0;
|
|
ULONG i;
|
|
PMIB_IPADDRTABLE Table;
|
|
if (AllocateAndGetIpAddrTableFromStack(
|
|
&Table, FALSE, GetProcessHeap(), 0
|
|
) == NO_ERROR) {
|
|
//
|
|
// Count the adapter's addresses
|
|
//
|
|
for (i = 0; i < Table->dwNumEntries; i++) {
|
|
if (Table->table[i].dwIndex == AdapterIndex) { ++Count; }
|
|
}
|
|
//
|
|
// Allocate space for the binding info
|
|
//
|
|
BindingInfo = reinterpret_cast<PIP_ADAPTER_BINDING_INFO>(
|
|
NH_ALLOCATE(SIZEOF_IP_BINDING(Count))
|
|
);
|
|
if (BindingInfo) {
|
|
//
|
|
// Fill in the binding info
|
|
//
|
|
BindingInfo->AddressCount = Count;
|
|
BindingInfo->RemoteAddress = 0;
|
|
Count = 0;
|
|
for (i = 0; i < Table->dwNumEntries; i++) {
|
|
if (Table->table[i].dwIndex != AdapterIndex) { continue; }
|
|
BindingInfo->Address[Count].Address = Table->table[i].dwAddr;
|
|
BindingInfo->Address[Count].Mask = Table->table[i].dwMask;
|
|
++Count;
|
|
}
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, Table);
|
|
}
|
|
return BindingInfo;
|
|
} // NhQueryBindingInformation
|
|
|
|
|
|
NTSTATUS
|
|
NhQueryDomainName(
|
|
PCHAR* DomainName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to obtain the local domain name.
|
|
|
|
Arguments:
|
|
|
|
DomainName - receives the allocated string containing the domain name
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - NT status code.
|
|
|
|
Environment:
|
|
|
|
Invoked from an arbitrary context.
|
|
|
|
--*/
|
|
|
|
{
|
|
PKEY_VALUE_PARTIAL_INFORMATION Information;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
HANDLE Key;
|
|
ULONG Length;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
NTSTATUS status;
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
PROFILE("NhQueryDomainName");
|
|
|
|
*DomainName = NULL;
|
|
|
|
RtlInitUnicodeString(&UnicodeString, NhTcpipParametersString);
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Open the 'Tcpip' registry key
|
|
//
|
|
|
|
status =
|
|
NtOpenKey(
|
|
&Key,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
NhTrace(
|
|
TRACE_FLAG_REG,
|
|
"NhQueryDomainName: error %x opening registry key",
|
|
status
|
|
);
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Read the 'Domain' value
|
|
//
|
|
|
|
status =
|
|
NhQueryValueKey(
|
|
Key,
|
|
NhpDomainString,
|
|
&Information
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
status =
|
|
NhQueryValueKey(
|
|
Key,
|
|
NhpDhcpDomainString,
|
|
&Information
|
|
);
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
NhTrace(
|
|
TRACE_FLAG_REG,
|
|
"NhQueryDomainName: error %x querying domain name",
|
|
status
|
|
);
|
|
NtClose(Key);
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Copy the domain name
|
|
//
|
|
|
|
Length = lstrlenW((PWCHAR)Information->Data) + 1;
|
|
|
|
*DomainName = reinterpret_cast<PCHAR>(NH_ALLOCATE(Length));
|
|
|
|
if (!*DomainName) {
|
|
NH_FREE(Information);
|
|
NhTrace(
|
|
TRACE_FLAG_REG,
|
|
"NhQueryDomainName: error allocating domain name"
|
|
);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
RtlUnicodeToMultiByteN(
|
|
*DomainName,
|
|
Length,
|
|
NULL,
|
|
(PWCHAR)Information->Data,
|
|
Length * sizeof(WCHAR)
|
|
);
|
|
|
|
NH_FREE(Information);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} // NhQueryDomainName
|
|
|
|
|
|
NTSTATUS
|
|
NhQueryValueKey(
|
|
HANDLE Key,
|
|
const WCHAR ValueName[],
|
|
PKEY_VALUE_PARTIAL_INFORMATION* Information
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to obtain the value of a registry key.
|
|
|
|
Arguments:
|
|
|
|
Key - the key to be queried
|
|
|
|
ValueName - the value to be queried
|
|
|
|
Information - receives a pointer to the information read
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - NT status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
|
|
ULONG InformationLength;
|
|
NTSTATUS status;
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
PROFILE("NhQueryValueKey");
|
|
|
|
RtlInitUnicodeString(&UnicodeString, ValueName);
|
|
|
|
*Information = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
|
|
InformationLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
|
|
|
|
//
|
|
// Read the value's size
|
|
//
|
|
|
|
status =
|
|
NtQueryValueKey(
|
|
Key,
|
|
&UnicodeString,
|
|
KeyValuePartialInformation,
|
|
*Information,
|
|
InformationLength,
|
|
&InformationLength
|
|
);
|
|
|
|
if (!NT_SUCCESS(status) &&
|
|
status != STATUS_BUFFER_OVERFLOW &&
|
|
status != STATUS_BUFFER_TOO_SMALL
|
|
) {
|
|
NhTrace(
|
|
TRACE_FLAG_REG,
|
|
"NhQueryValueKey: status %08x obtaining value size",
|
|
status
|
|
);
|
|
*Information = NULL;
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Allocate space for the value's size
|
|
//
|
|
|
|
*Information =
|
|
(PKEY_VALUE_PARTIAL_INFORMATION)NH_ALLOCATE(InformationLength + 2);
|
|
|
|
if (!*Information) {
|
|
NhTrace(
|
|
TRACE_FLAG_REG,
|
|
"NhQueryValueKey: error allocating %d bytes",
|
|
InformationLength + 2
|
|
);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Read the value's data
|
|
//
|
|
|
|
status =
|
|
NtQueryValueKey(
|
|
Key,
|
|
&UnicodeString,
|
|
KeyValuePartialInformation,
|
|
*Information,
|
|
InformationLength,
|
|
&InformationLength
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
NhTrace(
|
|
TRACE_FLAG_REG,
|
|
"NhQueryValueKey: status %08x obtaining value data",
|
|
status
|
|
);
|
|
NH_FREE(*Information);
|
|
*Information = NULL;
|
|
}
|
|
|
|
return status;
|
|
|
|
} // NhQueryValueKey
|
|
|
|
|
|
ULONG
|
|
NhMapAddressToAdapter(
|
|
ULONG Address
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to map an IP address to an adapter index.
|
|
It does so by obtaining the stack's address-table, which contains
|
|
valid adapter-indices rather than IP router-manager indices.
|
|
This table is then used to obtain the IP address's adapter-index.
|
|
|
|
Arguments:
|
|
|
|
Address - the local address for which an adapter-index is required
|
|
|
|
Return Value:
|
|
|
|
ULONG - adapter index.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG AdapterIndex = (ULONG)-1;
|
|
ULONG i;
|
|
PMIB_IPADDRTABLE Table;
|
|
PROFILE("NhMapAddressToAdapter");
|
|
if (AllocateAndGetIpAddrTableFromStack(
|
|
&Table, FALSE, GetProcessHeap(), 0
|
|
) == NO_ERROR) {
|
|
for (i = 0; i < Table->dwNumEntries; i++) {
|
|
if (Table->table[i].dwAddr != Address) { continue; }
|
|
AdapterIndex = Table->table[i].dwIndex;
|
|
break;
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, Table);
|
|
}
|
|
return AdapterIndex;
|
|
} // NhMapAddressToAdapter
|
|
|
|
|
|
ULONG
|
|
NhMapInterfaceToAdapter(
|
|
ULONG Index
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to map an interface to an adapter index.
|
|
It does so by invoking the appropriate IP router-manager entry-point.
|
|
|
|
Arguments:
|
|
|
|
Index - the index of the interface to be mapped
|
|
|
|
Return Value:
|
|
|
|
ULONG - adapter index.
|
|
|
|
--*/
|
|
|
|
{
|
|
MAPINTERFACETOADAPTER FarProc;
|
|
PROFILE("NhMapInterfaceToAdapter");
|
|
EnterCriticalSection(&NhLock);
|
|
if (!NhpRtrmgrDll) { NhpRtrmgrDll = LoadLibraryA("IPRTRMGR.DLL"); }
|
|
LeaveCriticalSection(&NhLock);
|
|
if (!NhpRtrmgrDll) { return (ULONG)-1; }
|
|
FarProc = (MAPINTERFACETOADAPTER)GetProcAddress(NhpRtrmgrDll, "MapInterfaceToAdapter");
|
|
return (ULONG)(FarProc ? (*FarProc)(Index) : -1);
|
|
} // NhMapInterfaceToAdapter
|
|
|
|
|
|
VOID
|
|
NhResetComponentMode(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine relinquishes control of the kernel-mode translation module,
|
|
and returns this module to an uninitialized state.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
EnterCriticalSection(&NhLock);
|
|
if (NhpComponentEvent) {
|
|
CloseHandle(NhpComponentEvent); NhpComponentEvent = NULL;
|
|
}
|
|
NhComponentMode = NhUninitializedMode;
|
|
LeaveCriticalSection(&NhLock);
|
|
} // NhResetComponentMode
|
|
|
|
|
|
BOOLEAN
|
|
NhSetComponentMode(
|
|
NH_COMPONENT_MODE ComponentMode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to atomically set the module into a particular mode
|
|
in order to prevent conflict between shared-access and connection-sharing,
|
|
both of which are implemented in this module, and both of which run
|
|
in the 'netsvcs' instance of SVCHOST.EXE.
|
|
|
|
In setting either mode, the routine first determines whether it is already
|
|
executing in the alternate mode, in which case it fails.
|
|
Otherwise, it attempts to create a named event, to claim exclusive control
|
|
of the kernel-mode translation module. If the named event already exists,
|
|
then the routine again fails.
|
|
Otherwise, the kernel-mode translation module is claimed for this module
|
|
and the module is set into the required mode.
|
|
|
|
Arguments:
|
|
|
|
ComponentMode - the mode into which the module is to be set.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if successful, FALSE if the module could not be set
|
|
or if the kernel-mode translation module has already been claimed.
|
|
--*/
|
|
|
|
{
|
|
EnterCriticalSection(&NhLock);
|
|
if (NhpComponentEvent) {
|
|
if (NhComponentMode != ComponentMode) {
|
|
LeaveCriticalSection(&NhLock);
|
|
NhErrorLog(
|
|
(ComponentMode == NhRoutingProtocolMode)
|
|
? IP_NAT_LOG_ROUTING_PROTOCOL_CONFLICT
|
|
: IP_NAT_LOG_SHARED_ACCESS_CONFLICT,
|
|
0,
|
|
""
|
|
);
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
NhpComponentEvent =
|
|
CreateEventA(NULL, FALSE, FALSE, IP_NAT_SERVICE_NAME);
|
|
if (!NhpComponentEvent) {
|
|
LeaveCriticalSection(&NhLock);
|
|
return FALSE;
|
|
} else if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
|
CloseHandle(NhpComponentEvent); NhpComponentEvent = NULL;
|
|
LeaveCriticalSection(&NhLock);
|
|
NhErrorLog(
|
|
(ComponentMode == NhRoutingProtocolMode)
|
|
? IP_NAT_LOG_ROUTING_PROTOCOL_CONFLICT
|
|
: IP_NAT_LOG_SHARED_ACCESS_CONFLICT,
|
|
0,
|
|
""
|
|
);
|
|
return FALSE;
|
|
}
|
|
}
|
|
NhComponentMode = ComponentMode;
|
|
LeaveCriticalSection(&NhLock);
|
|
return TRUE;
|
|
} // NhSetComponentMode
|
|
|
|
|
|
VOID
|
|
NhSignalNatInterface(
|
|
ULONG Index,
|
|
BOOLEAN Boundary
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked upon reconfiguration of a NAT interface.
|
|
It invokes the reconfiguration for the DHCP allocator and DNS proxy,
|
|
neither of which are expected to operate on a NAT boundary interface.
|
|
This notification gives either (or both) an opportunity to deactivate
|
|
itself on NAT interfaces or reactivate itself on non-NAT interfaces.
|
|
|
|
Arguments:
|
|
|
|
Index - the interface whose configuration has changed
|
|
|
|
Boundary - indicates whether the interface is now a boundary interface
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
Environment:
|
|
|
|
Invoked from an arbitrary context.
|
|
|
|
--*/
|
|
|
|
{
|
|
PROFILE("NhSignalNatInterface");
|
|
|
|
//
|
|
// Attempt to obtain the corresponding DHCP and DNS interfaces.
|
|
// It is important that this works regardless of whether DHCP allocation,
|
|
// DNS proxying or DirectPlay transparent proxying is enabled;
|
|
// the interface lists are initialized minimally in 'DllMain' above.
|
|
//
|
|
|
|
DhcpSignalNatInterface(Index, Boundary);
|
|
DnsSignalNatInterface(Index, Boundary);
|
|
#ifndef NO_FTP_PROXY
|
|
FtpSignalNatInterface(Index, Boundary);
|
|
#endif
|
|
// AlgSignalNatInterface(Index, Boundary);
|
|
H323SignalNatInterface(Index, Boundary);
|
|
|
|
} // NhSignalNatInterface
|
|
|
|
|
|
VOID
|
|
NhUpdateApplicationSettings(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked to (re)load the advanced application settings.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
HRESULT hr;
|
|
PNAT_APP_ENTRY pAppEntry;
|
|
IHNetCfgMgr *pCfgMgr = NULL;
|
|
IHNetProtocolSettings *pProtocolSettings;
|
|
IEnumHNetApplicationProtocols *pEnumApps;
|
|
BOOLEAN ComInitialized = FALSE;
|
|
ULONG ulCount;
|
|
PROFILE("NhUpdateApplicationSettings");
|
|
|
|
EnterCriticalSection(&NhLock);
|
|
|
|
//
|
|
// Free old settings list
|
|
//
|
|
|
|
NhFreeApplicationSettings();
|
|
|
|
//
|
|
// Free DHCP reservation list
|
|
//
|
|
|
|
NhFreeDhcpReservations();
|
|
|
|
//
|
|
// Make sure COM is initialized on this thread
|
|
//
|
|
|
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ComInitialized = TRUE;
|
|
}
|
|
else if (RPC_E_CHANGED_MODE == hr)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the IHNetCfgMgr pointer out of the GIT
|
|
//
|
|
|
|
hr = NhGetHNetCfgMgr(&pCfgMgr);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the IHNetProtocolSettings interface
|
|
//
|
|
|
|
hr = pCfgMgr->QueryInterface(
|
|
IID_PPV_ARG(IHNetProtocolSettings, &pProtocolSettings)
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the enumeration of enabled application protocols
|
|
//
|
|
|
|
hr = pProtocolSettings->EnumApplicationProtocols(TRUE, &pEnumApps);
|
|
pProtocolSettings->Release();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Process the items in the enum
|
|
//
|
|
|
|
do
|
|
{
|
|
IHNetApplicationProtocol *pAppProtocol;
|
|
|
|
hr = pEnumApps->Next(1, &pAppProtocol, &ulCount);
|
|
|
|
if (SUCCEEDED(hr) && 1 == ulCount)
|
|
{
|
|
//
|
|
// Allocate a new app entry
|
|
//
|
|
|
|
pAppEntry = reinterpret_cast<PNAT_APP_ENTRY>(
|
|
NH_ALLOCATE(sizeof(*pAppEntry))
|
|
);
|
|
|
|
if (NULL != pAppEntry)
|
|
{
|
|
ZeroMemory(pAppEntry, sizeof(*pAppEntry));
|
|
|
|
//
|
|
// Get protocol
|
|
//
|
|
|
|
hr = pAppProtocol->GetOutgoingIPProtocol(
|
|
&pAppEntry->Protocol
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get port
|
|
//
|
|
|
|
hr = pAppProtocol->GetOutgoingPort(
|
|
&pAppEntry->Port
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get responses
|
|
//
|
|
|
|
hr = pAppProtocol->GetResponseRanges(
|
|
&pAppEntry->ResponseCount,
|
|
&pAppEntry->ResponseArray
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Add entry to list
|
|
//
|
|
|
|
InsertTailList(&NhApplicationSettingsList, &pAppEntry->Link);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Free entry
|
|
//
|
|
|
|
NH_FREE(pAppEntry);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
pAppProtocol->Release();
|
|
}
|
|
} while (SUCCEEDED(hr) && 1 == ulCount);
|
|
|
|
pEnumApps->Release();
|
|
}
|
|
|
|
//
|
|
// Build the DHCP reservation list
|
|
//
|
|
|
|
NhBuildDhcpReservations();
|
|
|
|
LeaveCriticalSection(&NhLock);
|
|
|
|
//
|
|
// Free config manager
|
|
//
|
|
|
|
if (NULL != pCfgMgr)
|
|
{
|
|
pCfgMgr->Release();
|
|
}
|
|
|
|
//
|
|
// Uninitialize COM
|
|
//
|
|
|
|
if (TRUE == ComInitialized)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
|
|
} // NhUpdateApplicationSettings
|
|
|
|
|
|
ULONG
|
|
APIENTRY
|
|
RegisterProtocol(
|
|
IN OUT PMPR_ROUTING_CHARACTERISTICS RoutingCharacteristics,
|
|
IN OUT PMPR_SERVICE_CHARACTERISTICS ServiceCharacteristics
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is invoked once for each protocol implemented in this module.
|
|
On each invocation, the supplied 'RoutingCharacteristics' indicates
|
|
the protocol to be registered in its 'dwProtocolId' field.
|
|
|
|
Arguments:
|
|
|
|
RoutingCharacteristics - on input, the protocol to be registered
|
|
and the router-manager's supported functionality.
|
|
|
|
ServiceCharacteristics - unused.
|
|
|
|
Return Value:
|
|
|
|
ULONG - status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (RoutingCharacteristics->dwVersion < MS_ROUTER_VERSION) {
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
if ((RoutingCharacteristics->fSupportedFunctionality &
|
|
(RF_ROUTING|RF_ADD_ALL_INTERFACES)) !=
|
|
(RF_ROUTING|RF_ADD_ALL_INTERFACES)) {
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
switch (RoutingCharacteristics->dwProtocolId) {
|
|
|
|
case MS_IP_NAT: {
|
|
//
|
|
// Attempt to set the component into 'Connection Sharing' mode.
|
|
// This module implements both shared-access and connection-sharing
|
|
// which are mutually exclusive, so we need to ensure that
|
|
// shared-access is not operational before proceeding.
|
|
//
|
|
if (!NhSetComponentMode(NhRoutingProtocolMode)) {
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
CopyMemory(
|
|
RoutingCharacteristics,
|
|
&NatRoutingCharacteristics,
|
|
sizeof(NatRoutingCharacteristics)
|
|
);
|
|
RoutingCharacteristics->fSupportedFunctionality = RF_ROUTING;
|
|
break;
|
|
}
|
|
|
|
case MS_IP_DNS_PROXY: {
|
|
CopyMemory(
|
|
RoutingCharacteristics,
|
|
&DnsRoutingCharacteristics,
|
|
sizeof(DnsRoutingCharacteristics)
|
|
);
|
|
RoutingCharacteristics->fSupportedFunctionality =
|
|
(RF_ROUTING|RF_ADD_ALL_INTERFACES);
|
|
break;
|
|
}
|
|
|
|
case MS_IP_DHCP_ALLOCATOR: {
|
|
CopyMemory(
|
|
RoutingCharacteristics,
|
|
&DhcpRoutingCharacteristics,
|
|
sizeof(DhcpRoutingCharacteristics)
|
|
);
|
|
RoutingCharacteristics->fSupportedFunctionality =
|
|
(RF_ROUTING|RF_ADD_ALL_INTERFACES);
|
|
break;
|
|
}
|
|
|
|
#ifndef NO_FTP_PROXY
|
|
case MS_IP_FTP: {
|
|
CopyMemory(
|
|
RoutingCharacteristics,
|
|
&FtpRoutingCharacteristics,
|
|
sizeof(FtpRoutingCharacteristics)
|
|
);
|
|
RoutingCharacteristics->fSupportedFunctionality =
|
|
(RF_ROUTING|RF_ADD_ALL_INTERFACES);
|
|
break;
|
|
}
|
|
#endif
|
|
case MS_IP_ALG: {
|
|
CopyMemory(
|
|
RoutingCharacteristics,
|
|
&AlgRoutingCharacteristics,
|
|
sizeof(AlgRoutingCharacteristics)
|
|
);
|
|
RoutingCharacteristics->fSupportedFunctionality =
|
|
(RF_ROUTING|RF_ADD_ALL_INTERFACES);
|
|
break;
|
|
}
|
|
|
|
case MS_IP_H323: {
|
|
CopyMemory(
|
|
RoutingCharacteristics,
|
|
&H323RoutingCharacteristics,
|
|
sizeof(H323RoutingCharacteristics)
|
|
);
|
|
RoutingCharacteristics->fSupportedFunctionality =
|
|
(RF_ROUTING|RF_ADD_ALL_INTERFACES);
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
ServiceCharacteristics->mscMpr40ServiceChars.fSupportedFunctionality = 0;
|
|
|
|
return NO_ERROR;
|
|
|
|
} // RegisterProtocol
|
|
|